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

Generated on Sun Oct 26 13:01:56 2003 for rpm by doxygen1.2.18