Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages  

lib/misc.c

Go to the documentation of this file.
00001 
00005 #include "system.h"
00006 
00007 /*@unchecked@*/
00008 static int _debug = 0;
00009 
00010 /* just to put a marker in librpm.a */
00011 const char * RPMVERSION = VERSION;
00012 
00013 #include "rpmio_internal.h"
00014 #include <rpmurl.h>
00015 #include <rpmmacro.h>   /* XXX for rpmGetPath */
00016 #include <rpmlib.h>
00017 
00018 #include "misc.h"
00019 #include "debug.h"
00020 
00021 /*@access Header@*/             /* XXX compared with NULL */
00022 /*@access FD_t@*/               /* XXX compared with NULL */
00023 
00024 rpmRC rpmMkdirPath (const char * dpath, const char * dname)
00025 {
00026     struct stat st;
00027     int rc;
00028 
00029     if ((rc = Stat(dpath, &st)) < 0) {
00030         int ut = urlPath(dpath, NULL);
00031         switch (ut) {
00032         case URL_IS_PATH:
00033         case URL_IS_UNKNOWN:
00034             if (errno != ENOENT)
00035                 break;
00036             /*@fallthrough@*/
00037         case URL_IS_FTP:
00038         case URL_IS_HTTP:
00039             rc = Mkdir(dpath, 0755);
00040             break;
00041         case URL_IS_DASH:
00042             break;
00043         }
00044         if (rc < 0) {
00045             rpmError(RPMERR_CREATE, _("cannot create %%%s %s\n"), dname, dpath);
00046             return RPMRC_FAIL;
00047         }
00048     }
00049     if ((rc = Access(dpath, W_OK))) {
00050         rpmError(RPMERR_CREATE, _("cannot write to %%%s %s\n"), dname, dpath);
00051         return RPMRC_FAIL;
00052     }
00053     return RPMRC_OK;
00054 }
00055 
00056 /*@-bounds@*/
00057 char ** splitString(const char * str, int length, char sep)
00058 {
00059     const char * source;
00060     char * s, * dest;
00061     char ** list;
00062     int i;
00063     int fields;
00064 
00065     s = xmalloc(length + 1);
00066 
00067     fields = 1;
00068     for (source = str, dest = s, i = 0; i < length; i++, source++, dest++) {
00069         *dest = *source;
00070         if (*dest == sep) fields++;
00071     }
00072 
00073     *dest = '\0';
00074 
00075     list = xmalloc(sizeof(*list) * (fields + 1));
00076 
00077     dest = s;
00078     list[0] = dest;
00079     i = 1;
00080     while (i < fields) {
00081         if (*dest == sep) {
00082             list[i++] = dest + 1;
00083             *dest = 0;
00084         }
00085         dest++;
00086     }
00087 
00088     list[i] = NULL;
00089 
00090     return list;
00091 }
00092 /*@=bounds@*/
00093 
00094 void freeSplitString(char ** list)
00095 {
00096     /*@-unqualifiedtrans@*/
00097     list[0] = _free(list[0]);
00098     /*@=unqualifiedtrans@*/
00099     list = _free(list);
00100 }
00101 
00102 int doputenv(const char *str)
00103 {
00104     char * a;
00105 
00106     /* FIXME: this leaks memory! */
00107     a = xmalloc(strlen(str) + 1);
00108     strcpy(a, str);
00109     return putenv(a);
00110 }
00111 
00112 int dosetenv(const char * name, const char * value, int overwrite)
00113 {
00114     char * a;
00115 
00116     if (!overwrite && getenv(name)) return 0;
00117 
00118     /* FIXME: this leaks memory! */
00119     a = xmalloc(strlen(name) + strlen(value) + sizeof("="));
00120     (void) stpcpy( stpcpy( stpcpy( a, name), "="), value);
00121     return putenv(a);
00122 }
00123 
00124 int makeTempFile(const char * prefix, const char ** fnptr, FD_t * fdptr)
00125 {
00126     const char * tpmacro = "%{?_tmppath:%{_tmppath}}%{!?_tmppath:/var/tmp}";
00127     const char * tempfn = NULL;
00128     const char * tfn = NULL;
00129     static int _initialized = 0;
00130     int temput;
00131     FD_t fd = NULL;
00132     int ran;
00133 
00134     /*@-branchstate@*/
00135     if (!prefix) prefix = "";
00136     /*@=branchstate@*/
00137 
00138     /* Create the temp directory if it doesn't already exist. */
00139     /*@-branchstate@*/
00140     if (!_initialized) {
00141         _initialized = 1;
00142         tempfn = rpmGenPath(prefix, tpmacro, NULL);
00143         if (rpmioMkpath(tempfn, 0755, (uid_t) -1, (gid_t) -1))
00144             goto errxit;
00145     }
00146     /*@=branchstate@*/
00147 
00148     /* XXX should probably use mkstemp here */
00149     srand(time(NULL));
00150     ran = rand() % 100000;
00151 
00152     /* maybe this should use link/stat? */
00153 
00154     do {
00155         char tfnbuf[64];
00156 #ifndef NOTYET
00157         sprintf(tfnbuf, "rpm-tmp.%d", ran++);
00158         tempfn = _free(tempfn);
00159         tempfn = rpmGenPath(prefix, tpmacro, tfnbuf);
00160 #else
00161         strcpy(tfnbuf, "rpm-tmp.XXXXXX");
00162         tempfn = _free(tempfn);
00163         tempfn = rpmGenPath(prefix, tpmacro, mktemp(tfnbuf));
00164 #endif
00165 
00166         temput = urlPath(tempfn, &tfn);
00167         if (*tfn == '\0') goto errxit;
00168 
00169         switch (temput) {
00170         case URL_IS_HTTP:
00171         case URL_IS_DASH:
00172             goto errxit;
00173             /*@notreached@*/ /*@switchbreak@*/ break;
00174         default:
00175             /*@switchbreak@*/ break;
00176         }
00177 
00178         fd = Fopen(tempfn, "w+x.ufdio");
00179         /* XXX FIXME: errno may not be correct for ufdio */
00180     } while ((fd == NULL || Ferror(fd)) && errno == EEXIST);
00181 
00182     if (fd == NULL || Ferror(fd))
00183         goto errxit;
00184 
00185     switch(temput) {
00186     case URL_IS_PATH:
00187     case URL_IS_UNKNOWN:
00188       { struct stat sb, sb2;
00189         if (!stat(tfn, &sb) && S_ISLNK(sb.st_mode)) {
00190             rpmError(RPMERR_SCRIPT, _("error creating temporary file %s\n"), tfn);
00191             goto errxit;
00192         }
00193 
00194         if (sb.st_nlink != 1) {
00195             rpmError(RPMERR_SCRIPT, _("error creating temporary file %s\n"), tfn);
00196             goto errxit;
00197         }
00198 
00199         if (fstat(Fileno(fd), &sb2) == 0) {
00200             if (sb2.st_ino != sb.st_ino || sb2.st_dev != sb.st_dev) {
00201                 rpmError(RPMERR_SCRIPT, _("error creating temporary file %s\n"), tfn);
00202                 goto errxit;
00203             }
00204         }
00205       } break;
00206     default:
00207         break;
00208     }
00209 
00210     /*@-branchstate@*/
00211     if (fnptr)
00212         *fnptr = tempfn;
00213     else 
00214         tempfn = _free(tempfn);
00215     /*@=branchstate@*/
00216     *fdptr = fd;
00217 
00218     return 0;
00219 
00220 errxit:
00221     tempfn = _free(tempfn);
00222     /*@-usereleased@*/
00223     if (fd) (void) Fclose(fd);
00224     /*@=usereleased@*/
00225     return 1;
00226 }
00227 
00228 char * currentDirectory(void)
00229 {
00230     int currDirLen;
00231     char * currDir;
00232 
00233     currDirLen = 50;
00234     currDir = xmalloc(currDirLen);
00235     while (!getcwd(currDir, currDirLen) && errno == ERANGE) {
00236         currDirLen += 50;
00237         currDir = xrealloc(currDir, currDirLen);
00238     }
00239 
00240     return currDir;
00241 }
00242 
00243 /* glob_pattern_p() taken from bash
00244  * Copyright (C) 1985, 1988, 1989 Free Software Foundation, Inc.
00245  *
00246  * Return nonzero if PATTERN has any special globbing chars in it.
00247  */
00248 int myGlobPatternP (const char *patternURL)
00249 {
00250     const char *p;
00251     char c;
00252     int open = 0;
00253   
00254     (void) urlPath(patternURL, &p);
00255     while ((c = *p++) != '\0')
00256         switch (c) {
00257         case '+':
00258         case '@':
00259         case '!':
00260             if (*p == '(')
00261                 return (1);
00262             continue;
00263         case '?':
00264         case '*':
00265             return (1);
00266         case '[':      /* Only accept an open brace if there is a close */
00267             open++;    /* brace to match it.  Bracket expressions must be */
00268             continue;  /* complete, according to Posix.2 */
00269         case ']':
00270             if (open)
00271                 return (1);
00272             continue;      
00273         case '\\':
00274             if (*p++ == '\0')
00275                 return (0);
00276         }
00277 
00278     return (0);
00279 }
00280 
00281 static int glob_error(/*@unused@*/const char *foo, /*@unused@*/int bar)
00282 {
00283     return 1;
00284 }
00285 
00286 int rpmGlob(const char * patterns, int * argcPtr, const char *** argvPtr)
00287 {
00288     int ac = 0;
00289     const char ** av = NULL;
00290     int argc = 0;
00291     const char ** argv = NULL;
00292     const char * path;
00293     const char * globURL;
00294     char * globRoot = NULL;
00295     size_t maxb, nb;
00296     glob_t gl;
00297     int ut;
00298     int i, j;
00299     int rc;
00300 
00301     rc = poptParseArgvString(patterns, &ac, &av);
00302     if (rc)
00303         return rc;
00304 
00305     for (j = 0; j < ac; j++) {
00306         if (!myGlobPatternP(av[j])) {
00307             if (argc == 0)
00308                 argv = xmalloc((argc+2) * sizeof(*argv));
00309             else
00310                 argv = xrealloc(argv, (argc+2) * sizeof(*argv));
00311             argv[argc] = xstrdup(av[j]);
00312 if (_debug)
00313 fprintf(stderr, "*** rpmGlob argv[%d] \"%s\"\n", argc, argv[argc]);
00314             argc++;
00315             continue;
00316         }
00317         
00318         gl.gl_pathc = 0;
00319         gl.gl_pathv = NULL;
00320         rc = Glob(av[j], 0, glob_error, &gl);
00321         if (rc)
00322             goto exit;
00323 
00324         /* XXX Prepend the URL leader for globs that have stripped it off */
00325         maxb = 0;
00326         for (i = 0; i < gl.gl_pathc; i++) {
00327             if ((nb = strlen(&(gl.gl_pathv[i][0]))) > maxb)
00328                 maxb = nb;
00329         }
00330         
00331         ut = urlPath(av[j], &path);
00332         nb = ((ut > URL_IS_DASH && ut != URL_IS_FTP) ? (path - av[j]) : 0);
00333         maxb += nb;
00334         maxb += 1;
00335         globURL = globRoot = xmalloc(maxb);
00336 
00337         switch (ut) {
00338         case URL_IS_HTTP:
00339         case URL_IS_PATH:
00340         case URL_IS_DASH:
00341             strncpy(globRoot, av[j], nb);
00342             /*@switchbreak@*/ break;
00343         case URL_IS_FTP:
00344         case URL_IS_UNKNOWN:
00345             /*@switchbreak@*/ break;
00346         }
00347         globRoot += nb;
00348         *globRoot = '\0';
00349 if (_debug)
00350 fprintf(stderr, "*** GLOB maxb %d diskURL %d %*s globURL %p %s\n", (int)maxb, (int)nb, (int)nb, av[j], globURL, globURL);
00351         
00352         /*@-branchstate@*/
00353         if (argc == 0)
00354             argv = xmalloc((gl.gl_pathc+1) * sizeof(*argv));
00355         else if (gl.gl_pathc > 0)
00356             argv = xrealloc(argv, (argc+gl.gl_pathc+1) * sizeof(*argv));
00357         /*@=branchstate@*/
00358         for (i = 0; i < gl.gl_pathc; i++) {
00359             const char * globFile = &(gl.gl_pathv[i][0]);
00360             if (globRoot > globURL && globRoot[-1] == '/')
00361                 while (*globFile == '/') globFile++;
00362             strcpy(globRoot, globFile);
00363 if (_debug)
00364 fprintf(stderr, "*** rpmGlob argv[%d] \"%s\"\n", argc, globURL);
00365             argv[argc++] = xstrdup(globURL);
00366         }
00367         /*@-immediatetrans@*/
00368         Globfree(&gl);
00369         /*@=immediatetrans@*/
00370         globURL = _free(globURL);
00371     }
00372     if (argv != NULL && argc > 0) {
00373         argv[argc] = NULL;
00374         if (argvPtr)
00375             *argvPtr = argv;
00376         if (argcPtr)
00377             *argcPtr = argc;
00378         rc = 0;
00379     } else
00380         rc = 1;
00381 
00382 
00383 exit:
00384     av = _free(av);
00385     if (rc || argvPtr == NULL) {
00386         if (argv != NULL)
00387         for (i = 0; i < argc; i++)
00388             argv[i] = _free(argv[i]);
00389         argv = _free(argv);
00390     }
00391     return rc;
00392 }
00393 
00394 /*
00395  * XXX This is a "dressed" entry to headerGetEntry to do:
00396  *      1) DIRNAME/BASENAME/DIRINDICES -> FILENAMES tag conversions.
00397  *      2) i18n lookaside (if enabled).
00398  */
00399 int rpmHeaderGetEntry(Header h, int_32 tag, int_32 *type,
00400         void **p, int_32 *c)
00401 {
00402     switch (tag) {
00403     case RPMTAG_OLDFILENAMES:
00404     {   const char ** fl = NULL;
00405         int count;
00406         rpmBuildFileList(h, &fl, &count);
00407         if (count > 0) {
00408             *p = fl;
00409             if (c)      *c = count;
00410             if (type)   *type = RPM_STRING_ARRAY_TYPE;
00411             return 1;
00412         }
00413         if (c)  *c = 0;
00414         return 0;
00415     }   /*@notreached@*/ break;
00416 
00417     case RPMTAG_GROUP:
00418     case RPMTAG_DESCRIPTION:
00419     case RPMTAG_SUMMARY:
00420     {   char fmt[128];
00421         const char * msgstr;
00422         const char * errstr;
00423 
00424         fmt[0] = '\0';
00425         (void) stpcpy( stpcpy( stpcpy( fmt, "%{"), tagName(tag)), "}\n");
00426 
00427         /* XXX FIXME: memory leak. */
00428         msgstr = headerSprintf(h, fmt, rpmTagTable, rpmHeaderFormats, &errstr);
00429         if (msgstr) {
00430             *p = (void *) msgstr;
00431             if (type)   *type = RPM_STRING_TYPE;
00432             if (c)      *c = 1;
00433             return 1;
00434         } else {
00435             if (c)      *c = 0;
00436             return 0;
00437         }
00438     }   /*@notreached@*/ break;
00439 
00440     default:
00441         return headerGetEntry(h, tag, type, p, c);
00442         /*@notreached@*/ break;
00443     }
00444     /*@notreached@*/
00445 }

Generated on Tue Sep 17 15:56:38 2002 for rpm by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002