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 }