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 static int _debug = 0;
00008 
00009 /* just to put a marker in librpm.a */
00010 const char * RPMVERSION = VERSION;
00011 
00012 #include "rpmio_internal.h"
00013 #include <rpmlib.h>
00014 #include <rpmurl.h>
00015 #include <rpmmacro.h>   /* XXX for rpmGetPath */
00016 
00017 #include "misc.h"
00018 #include "debug.h"
00019 
00020 /*@access Header@*/             /* XXX compared with NULL */
00021 /*@access FD_t@*/               /* XXX compared with NULL */
00022 
00023 char ** splitString(const char * str, int length, char sep)
00024 {
00025     const char * source;
00026     char * s, * dest;
00027     char ** list;
00028     int i;
00029     int fields;
00030 
00031     s = xmalloc(length + 1);
00032 
00033     fields = 1;
00034     for (source = str, dest = s, i = 0; i < length; i++, source++, dest++) {
00035         *dest = *source;
00036         if (*dest == sep) fields++;
00037     }
00038 
00039     *dest = '\0';
00040 
00041     list = xmalloc(sizeof(*list) * (fields + 1));
00042 
00043     dest = s;
00044     list[0] = dest;
00045     i = 1;
00046     while (i < fields) {
00047         if (*dest == sep) {
00048             list[i++] = dest + 1;
00049             *dest = 0;
00050         }
00051         dest++;
00052     }
00053 
00054     list[i] = NULL;
00055 
00056     return list;
00057 }
00058 
00059 void freeSplitString(char ** list)
00060 {
00061     /*@-unqualifiedtrans@*/
00062     list[0] = _free(list[0]);
00063     /*@=unqualifiedtrans@*/
00064     list = _free(list);
00065 }
00066 
00067 #ifdef  DYING
00068 int rpmfileexists(const char * urlfn)
00069 {
00070     const char *fn;
00071     int urltype = urlPath(urlfn, &fn);
00072     struct stat buf;
00073 
00074     if (*fn == '\0') fn = "/";
00075     switch (urltype) {
00076     case URL_IS_FTP:    /* XXX WRONG WRONG WRONG */
00077     case URL_IS_HTTP:   /* XXX WRONG WRONG WRONG */
00078     case URL_IS_PATH:
00079     case URL_IS_UNKNOWN:
00080         if (Stat(fn, &buf)) {
00081             switch(errno) {
00082             case ENOENT:
00083             case EINVAL:
00084                 return 0;
00085             }
00086         }
00087         break;
00088     case URL_IS_DASH:
00089     default:
00090         return 0;
00091         /*@notreached@*/ break;
00092     }
00093 
00094     return 1;
00095 }
00096 #endif
00097 
00098 int doputenv(const char *str)
00099 {
00100     char * a;
00101 
00102     /* FIXME: this leaks memory! */
00103     a = xmalloc(strlen(str) + 1);
00104     strcpy(a, str);
00105     return putenv(a);
00106 }
00107 
00108 int dosetenv(const char * name, const char * value, int overwrite)
00109 {
00110     char * a;
00111 
00112     if (!overwrite && getenv(name)) return 0;
00113 
00114     /* FIXME: this leaks memory! */
00115     a = xmalloc(strlen(name) + strlen(value) + sizeof("="));
00116     (void) stpcpy( stpcpy( stpcpy( a, name), "="), value);
00117     return putenv(a);
00118 }
00119 
00120 static int rpmMkpath(const char * path, mode_t mode, uid_t uid, gid_t gid)
00121         /*@globals fileSystem @*/
00122         /*@modifies fileSystem @*/
00123 {
00124     char * d, * de;
00125     int created = 0;
00126     int rc;
00127 
00128     if (path == NULL)
00129         return -1;
00130     d = alloca(strlen(path)+2);
00131     de = stpcpy(d, path);
00132     de[1] = '\0';
00133     for (de = d; *de != '\0'; de++) {
00134         struct stat st;
00135         char savec;
00136 
00137         while (*de && *de != '/') de++;
00138         savec = de[1];
00139         de[1] = '\0';
00140 
00141         rc = stat(d, &st);
00142         if (rc) {
00143             switch(errno) {
00144             default:
00145                 return errno;
00146                 /*@notreached@*/ /*@switchbreak@*/ break;
00147             case ENOENT:
00148                 /*@switchbreak@*/ break;
00149             }
00150             rc = mkdir(d, mode);
00151             if (rc)
00152                 return errno;
00153             created = 1;
00154             if (!(uid == (uid_t) -1 && gid == (gid_t) -1)) {
00155                 rc = chown(d, uid, gid);
00156                 if (rc)
00157                     return errno;
00158             }
00159         } else if (!S_ISDIR(st.st_mode)) {
00160             return ENOTDIR;
00161         }
00162         de[1] = savec;
00163     }
00164     rc = 0;
00165     if (created)
00166         rpmMessage(RPMMESS_WARNING, "created %%_tmppath directory %s\n", path);
00167     return rc;
00168 }
00169 
00170 int makeTempFile(const char * prefix, const char ** fnptr, FD_t * fdptr)
00171 {
00172     const char * tpmacro = "%{?_tmppath:%{_tmppath}}%{!?_tmppath:/var/tmp}";
00173     const char * tempfn = NULL;
00174     const char * tfn = NULL;
00175     static int _initialized = 0;
00176     int temput;
00177     FD_t fd = NULL;
00178     int ran;
00179 
00180     /*@-branchstate@*/
00181     if (!prefix) prefix = "";
00182     /*@=branchstate@*/
00183 
00184     /* Create the temp directory if it doesn't already exist. */
00185     /*@-branchstate@*/
00186     if (!_initialized) {
00187         _initialized = 1;
00188         tempfn = rpmGenPath(prefix, tpmacro, NULL);
00189         if (rpmMkpath(tempfn, 0755, (uid_t) -1, (gid_t) -1))
00190             goto errxit;
00191     }
00192     /*@=branchstate@*/
00193 
00194     /* XXX should probably use mkstemp here */
00195     srand(time(NULL));
00196     ran = rand() % 100000;
00197 
00198     /* maybe this should use link/stat? */
00199 
00200     do {
00201         char tfnbuf[64];
00202 #ifndef NOTYET
00203         sprintf(tfnbuf, "rpm-tmp.%d", ran++);
00204         tempfn = _free(tempfn);
00205         tempfn = rpmGenPath(prefix, tpmacro, tfnbuf);
00206 #else
00207         strcpy(tfnbuf, "rpm-tmp.XXXXXX");
00208         tempfn = _free(tempfn);
00209         tempfn = rpmGenPath(prefix, tpmacro, mktemp(tfnbuf));
00210 #endif
00211 
00212         temput = urlPath(tempfn, &tfn);
00213         if (*tfn == '\0') goto errxit;
00214 
00215         switch (temput) {
00216         case URL_IS_HTTP:
00217         case URL_IS_DASH:
00218             goto errxit;
00219             /*@notreached@*/ /*@switchbreak@*/ break;
00220         default:
00221             /*@switchbreak@*/ break;
00222         }
00223 
00224         fd = Fopen(tempfn, "w+x.ufdio");
00225         /* XXX FIXME: errno may not be correct for ufdio */
00226     } while ((fd == NULL || Ferror(fd)) && errno == EEXIST);
00227 
00228     if (fd == NULL || Ferror(fd))
00229         goto errxit;
00230 
00231     switch(temput) {
00232     case URL_IS_PATH:
00233     case URL_IS_UNKNOWN:
00234       { struct stat sb, sb2;
00235         if (!stat(tfn, &sb) && S_ISLNK(sb.st_mode)) {
00236             rpmError(RPMERR_SCRIPT, _("error creating temporary file %s\n"), tfn);
00237             goto errxit;
00238         }
00239 
00240         if (sb.st_nlink != 1) {
00241             rpmError(RPMERR_SCRIPT, _("error creating temporary file %s\n"), tfn);
00242             goto errxit;
00243         }
00244 
00245         if (fstat(Fileno(fd), &sb2) == 0) {
00246             if (sb2.st_ino != sb.st_ino || sb2.st_dev != sb.st_dev) {
00247                 rpmError(RPMERR_SCRIPT, _("error creating temporary file %s\n"), tfn);
00248                 goto errxit;
00249             }
00250         }
00251       } break;
00252     default:
00253         break;
00254     }
00255 
00256     /*@-branchstate@*/
00257     if (fnptr)
00258         *fnptr = tempfn;
00259     else 
00260         tempfn = _free(tempfn);
00261     /*@=branchstate@*/
00262     *fdptr = fd;
00263 
00264     return 0;
00265 
00266 errxit:
00267     tempfn = _free(tempfn);
00268     /*@-usereleased@*/
00269     if (fd) (void) Fclose(fd);
00270     /*@=usereleased@*/
00271     return 1;
00272 }
00273 
00274 char * currentDirectory(void)
00275 {
00276     int currDirLen;
00277     char * currDir;
00278 
00279     currDirLen = 50;
00280     currDir = xmalloc(currDirLen);
00281     while (!getcwd(currDir, currDirLen) && errno == ERANGE) {
00282         currDirLen += 50;
00283         currDir = xrealloc(currDir, currDirLen);
00284     }
00285 
00286     return currDir;
00287 }
00288 
00289 int _noDirTokens = 0;
00290 
00291 static int dncmp(const void * a, const void * b)
00292 {
00293     const char *const * first = a;
00294     const char *const * second = b;
00295     return strcmp(*first, *second);
00296 }
00297 
00298 void compressFilelist(Header h)
00299 {
00300     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00301     HAE_t hae = (HAE_t)headerAddEntry;
00302     HRE_t hre = (HRE_t)headerRemoveEntry;
00303     HFD_t hfd = headerFreeData;
00304     char ** fileNames;
00305     const char ** dirNames;
00306     const char ** baseNames;
00307     int_32 * dirIndexes;
00308     rpmTagType fnt;
00309     int count;
00310     int i;
00311     int dirIndex = -1;
00312 
00313     /*
00314      * This assumes the file list is already sorted, and begins with a
00315      * single '/'. That assumption isn't critical, but it makes things go
00316      * a bit faster.
00317      */
00318 
00319     if (headerIsEntry(h, RPMTAG_DIRNAMES)) {
00320         (void) hre(h, RPMTAG_OLDFILENAMES);
00321         return;         /* Already converted. */
00322     }
00323 
00324     if (!hge(h, RPMTAG_OLDFILENAMES, &fnt, (void **) &fileNames, &count))
00325         return;         /* no file list */
00326     if (fileNames == NULL || count <= 0)
00327         return;
00328 
00329     dirNames = alloca(sizeof(*dirNames) * count);       /* worst case */
00330     baseNames = alloca(sizeof(*dirNames) * count);
00331     dirIndexes = alloca(sizeof(*dirIndexes) * count);
00332 
00333     if (fileNames[0][0] != '/') {
00334         /* HACK. Source RPM, so just do things differently */
00335         dirIndex = 0;
00336         dirNames[dirIndex] = "";
00337         for (i = 0; i < count; i++) {
00338             dirIndexes[i] = dirIndex;
00339             baseNames[i] = fileNames[i];
00340         }
00341         goto exit;
00342     }
00343 
00344     for (i = 0; i < count; i++) {
00345         const char ** needle;
00346         char savechar;
00347         char * baseName;
00348         int len;
00349 
00350         if (fileNames[i] == NULL)       /* XXX can't happen */
00351             continue;
00352         baseName = strrchr(fileNames[i], '/') + 1;
00353         len = baseName - fileNames[i];
00354         needle = dirNames;
00355         savechar = *baseName;
00356         *baseName = '\0';
00357         if (dirIndex < 0 ||
00358             (needle = bsearch(&fileNames[i], dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) {
00359             char *s = alloca(len + 1);
00360             memcpy(s, fileNames[i], len + 1);
00361             s[len] = '\0';
00362             dirIndexes[i] = ++dirIndex;
00363             dirNames[dirIndex] = s;
00364         } else
00365             dirIndexes[i] = needle - dirNames;
00366 
00367         *baseName = savechar;
00368         baseNames[i] = baseName;
00369     }
00370 
00371 exit:
00372     if (count > 0) {
00373         (void) hae(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, dirIndexes, count);
00374         (void) hae(h, RPMTAG_BASENAMES, RPM_STRING_ARRAY_TYPE,
00375                         baseNames, count);
00376         (void) hae(h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE,
00377                         dirNames, dirIndex + 1);
00378     }
00379 
00380     fileNames = hfd(fileNames, fnt);
00381 
00382     (void) hre(h, RPMTAG_OLDFILENAMES);
00383 }
00384 
00385 /*
00386  * This is pretty straight-forward. The only thing that even resembles a trick
00387  * is getting all of this into a single xmalloc'd block.
00388  */
00389 static void doBuildFileList(Header h, /*@out@*/ const char *** fileListPtr,
00390                             /*@out@*/ int * fileCountPtr, rpmTag baseNameTag,
00391                             rpmTag dirNameTag, rpmTag dirIndexesTag)
00392         /*@modifies *fileListPtr, *fileCountPtr @*/
00393 {
00394     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00395     HFD_t hfd = headerFreeData;
00396     const char ** baseNames;
00397     const char ** dirNames;
00398     int * dirIndexes;
00399     int count;
00400     const char ** fileNames;
00401     int size;
00402     rpmTagType bnt, dnt;
00403     char * data;
00404     int i;
00405 
00406     if (!hge(h, baseNameTag, &bnt, (void **) &baseNames, &count)) {
00407         if (fileListPtr) *fileListPtr = NULL;
00408         if (fileCountPtr) *fileCountPtr = 0;
00409         return;         /* no file list */
00410     }
00411 
00412     (void) hge(h, dirNameTag, &dnt, (void **) &dirNames, NULL);
00413     (void) hge(h, dirIndexesTag, NULL, (void **) &dirIndexes, &count);
00414 
00415     size = sizeof(*fileNames) * count;
00416     for (i = 0; i < count; i++)
00417         size += strlen(baseNames[i]) + strlen(dirNames[dirIndexes[i]]) + 1;
00418 
00419     fileNames = xmalloc(size);
00420     data = ((char *) fileNames) + (sizeof(*fileNames) * count);
00421     for (i = 0; i < count; i++) {
00422         fileNames[i] = data;
00423         data = stpcpy( stpcpy(data, dirNames[dirIndexes[i]]), baseNames[i]);
00424         *data++ = '\0';
00425     }
00426     baseNames = hfd(baseNames, bnt);
00427     dirNames = hfd(dirNames, dnt);
00428 
00429     if (fileListPtr)
00430         *fileListPtr = fileNames;
00431     else
00432         fileNames = _free(fileNames);
00433     if (fileCountPtr) *fileCountPtr = count;
00434 }
00435 
00436 void expandFilelist(Header h)
00437 {
00438     HAE_t hae = (HAE_t)headerAddEntry;
00439     HRE_t hre = (HRE_t)headerRemoveEntry;
00440     const char ** fileNames = NULL;
00441     int count = 0;
00442 
00443     if (!headerIsEntry(h, RPMTAG_OLDFILENAMES)) {
00444         doBuildFileList(h, &fileNames, &count, RPMTAG_BASENAMES,
00445                         RPMTAG_DIRNAMES, RPMTAG_DIRINDEXES);
00446         if (fileNames == NULL || count <= 0)
00447             return;
00448         (void) hae(h, RPMTAG_OLDFILENAMES, RPM_STRING_ARRAY_TYPE,
00449                         fileNames, count);
00450         fileNames = _free(fileNames);
00451     }
00452 
00453     (void) hre(h, RPMTAG_DIRNAMES);
00454     (void) hre(h, RPMTAG_BASENAMES);
00455     (void) hre(h, RPMTAG_DIRINDEXES);
00456 }
00457 
00458 
00459 void rpmBuildFileList(Header h, const char *** fileListPtr, int * fileCountPtr)
00460 {
00461     doBuildFileList(h, fileListPtr, fileCountPtr, RPMTAG_BASENAMES,
00462                         RPMTAG_DIRNAMES, RPMTAG_DIRINDEXES);
00463 }
00464 
00465 void buildOrigFileList(Header h, const char *** fileListPtr, int * fileCountPtr)
00466 {
00467     doBuildFileList(h, fileListPtr, fileCountPtr, RPMTAG_ORIGBASENAMES,
00468                         RPMTAG_ORIGDIRNAMES, RPMTAG_ORIGDIRINDEXES);
00469 }
00470 
00471 /* glob_pattern_p() taken from bash
00472  * Copyright (C) 1985, 1988, 1989 Free Software Foundation, Inc.
00473  *
00474  * Return nonzero if PATTERN has any special globbing chars in it.
00475  */
00476 int myGlobPatternP (const char *patternURL)
00477 {
00478     const char *p;
00479     char c;
00480     int open = 0;
00481   
00482     (void) urlPath(patternURL, &p);
00483     while ((c = *p++) != '\0')
00484         switch (c) {
00485         case '?':
00486         case '*':
00487             return (1);
00488         case '[':      /* Only accept an open brace if there is a close */
00489             open++;    /* brace to match it.  Bracket expressions must be */
00490             continue;  /* complete, according to Posix.2 */
00491         case ']':
00492             if (open)
00493                 return (1);
00494             continue;      
00495         case '\\':
00496             if (*p++ == '\0')
00497                 return (0);
00498         }
00499 
00500     return (0);
00501 }
00502 
00503 static int glob_error(/*@unused@*/const char *foo, /*@unused@*/int bar)
00504 {
00505     return 1;
00506 }
00507 
00508 int rpmGlob(const char * patterns, int * argcPtr, const char *** argvPtr)
00509 {
00510     int ac = 0;
00511     const char ** av = NULL;
00512     int argc = 0;
00513     const char ** argv = NULL;
00514     const char * path;
00515     const char * globURL;
00516     char * globRoot = NULL;
00517     size_t maxb, nb;
00518     glob_t gl;
00519     int ut;
00520     int i, j;
00521     int rc;
00522 
00523     rc = poptParseArgvString(patterns, &ac, &av);
00524     if (rc)
00525         return rc;
00526 
00527     for (j = 0; j < ac; j++) {
00528         if (!myGlobPatternP(av[j])) {
00529             if (argc == 0)
00530                 argv = xmalloc((argc+2) * sizeof(*argv));
00531             else
00532                 argv = xrealloc(argv, (argc+2) * sizeof(*argv));
00533             argv[argc] = xstrdup(av[j]);
00534 /*@-modfilesys@*/
00535 if (_debug)
00536 fprintf(stderr, "*** rpmGlob argv[%d] \"%s\"\n", argc, argv[argc]);
00537 /*@=modfilesys@*/
00538             argc++;
00539             continue;
00540         }
00541         
00542         gl.gl_pathc = 0;
00543         gl.gl_pathv = NULL;
00544         rc = Glob(av[j], 0, glob_error, &gl);
00545         if (rc)
00546             goto exit;
00547 
00548         /* XXX Prepend the URL leader for globs that have stripped it off */
00549         maxb = 0;
00550         for (i = 0; i < gl.gl_pathc; i++) {
00551             if ((nb = strlen(&(gl.gl_pathv[i][0]))) > maxb)
00552                 maxb = nb;
00553         }
00554         
00555         ut = urlPath(av[j], &path);
00556         nb = ((ut > URL_IS_DASH) ? (path - av[j]) : 0);
00557         maxb += nb;
00558         maxb += 1;
00559         globURL = globRoot = xmalloc(maxb);
00560 
00561         switch (ut) {
00562         case URL_IS_HTTP:
00563         case URL_IS_FTP:
00564         case URL_IS_PATH:
00565         case URL_IS_DASH:
00566             strncpy(globRoot, av[j], nb);
00567             /*@switchbreak@*/ break;
00568         case URL_IS_UNKNOWN:
00569             /*@switchbreak@*/ break;
00570         }
00571         globRoot += nb;
00572         *globRoot = '\0';
00573 /*@-modfilesys@*/
00574 if (_debug)
00575 fprintf(stderr, "*** GLOB maxb %d diskURL %d %*s globURL %p %s\n", (int)maxb, (int)nb, (int)nb, av[j], globURL, globURL);
00576 /*@=modfilesys@*/
00577         
00578         /*@-branchstate@*/
00579         if (argc == 0)
00580             argv = xmalloc((gl.gl_pathc+1) * sizeof(*argv));
00581         else if (gl.gl_pathc > 0)
00582             argv = xrealloc(argv, (argc+gl.gl_pathc+1) * sizeof(*argv));
00583         /*@=branchstate@*/
00584         for (i = 0; i < gl.gl_pathc; i++) {
00585             const char * globFile = &(gl.gl_pathv[i][0]);
00586             if (globRoot > globURL && globRoot[-1] == '/')
00587                 while (*globFile == '/') globFile++;
00588             strcpy(globRoot, globFile);
00589 /*@-modfilesys@*/
00590 if (_debug)
00591 fprintf(stderr, "*** rpmGlob argv[%d] \"%s\"\n", argc, globURL);
00592 /*@=modfilesys@*/
00593             argv[argc++] = xstrdup(globURL);
00594         }
00595         /*@-immediatetrans@*/
00596         Globfree(&gl);
00597         /*@=immediatetrans@*/
00598         globURL = _free(globURL);
00599     }
00600     if (argv != NULL && argc > 0) {
00601         argv[argc] = NULL;
00602         if (argvPtr)
00603             *argvPtr = argv;
00604         if (argcPtr)
00605             *argcPtr = argc;
00606         rc = 0;
00607     } else
00608         rc = 1;
00609 
00610 
00611 exit:
00612     av = _free(av);
00613     if (rc || argvPtr == NULL) {
00614         if (argv != NULL)
00615         for (i = 0; i < argc; i++)
00616             argv[i] = _free(argv[i]);
00617         argv = _free(argv);
00618     }
00619     return rc;
00620 }
00621 
00622 /*
00623  * XXX This is a "dressed" entry to headerGetEntry to do:
00624  *      1) DIRNAME/BASENAME/DIRINDICES -> FILENAMES tag conversions.
00625  *      2) i18n lookaside (if enabled).
00626  */
00627 int rpmHeaderGetEntry(Header h, int_32 tag, int_32 *type,
00628         void **p, int_32 *c)
00629 {
00630     switch (tag) {
00631     case RPMTAG_OLDFILENAMES:
00632     {   const char ** fl = NULL;
00633         int count;
00634         rpmBuildFileList(h, &fl, &count);
00635         if (count > 0) {
00636             *p = fl;
00637             if (c)      *c = count;
00638             if (type)   *type = RPM_STRING_ARRAY_TYPE;
00639             return 1;
00640         }
00641         if (c)  *c = 0;
00642         return 0;
00643     }   /*@notreached@*/ break;
00644 
00645     case RPMTAG_GROUP:
00646     case RPMTAG_DESCRIPTION:
00647     case RPMTAG_SUMMARY:
00648     {   char fmt[128];
00649         const char * msgstr;
00650         const char * errstr;
00651 
00652         fmt[0] = '\0';
00653         (void) stpcpy( stpcpy( stpcpy( fmt, "%{"), tagName(tag)), "}\n");
00654 
00655         /* XXX FIXME: memory leak. */
00656         msgstr = headerSprintf(h, fmt, rpmTagTable, rpmHeaderFormats, &errstr);
00657         if (msgstr) {
00658             *p = (void *) msgstr;
00659             if (type)   *type = RPM_STRING_TYPE;
00660             if (c)      *c = 1;
00661             return 1;
00662         } else {
00663             if (c)      *c = 0;
00664             return 0;
00665         }
00666     }   /*@notreached@*/ break;
00667 
00668     default:
00669         return headerGetEntry(h, tag, type, p, c);
00670         /*@notreached@*/ break;
00671     }
00672     /*@notreached@*/
00673 }
00674 
00675 /*
00676  * XXX Yet Another dressed entry to unify signature/header tag retrieval.
00677  */
00678 int rpmPackageGetEntry( /*@unused@*/ void *leadp, Header sigs, Header h,
00679         int_32 tag, int_32 *type, void **p, int_32 *c)
00680 {
00681     int_32 sigtag;
00682 
00683     switch (tag) {
00684     case RPMTAG_SIGSIZE:        sigtag = RPMSIGTAG_SIZE;        break;
00685     case RPMTAG_SIGLEMD5_1:     sigtag = RPMSIGTAG_LEMD5_1;     break;
00686     case RPMTAG_SIGPGP:         sigtag = RPMSIGTAG_PGP;         break;
00687     case RPMTAG_SIGLEMD5_2:     sigtag = RPMSIGTAG_LEMD5_2;     break;
00688     case RPMTAG_SIGMD5:         sigtag = RPMSIGTAG_MD5;         break;
00689     case RPMTAG_SIGGPG:         sigtag = RPMSIGTAG_GPG;         break;
00690     case RPMTAG_SIGPGP5:        sigtag = RPMSIGTAG_GPG;         break;
00691         
00692     default:
00693         return rpmHeaderGetEntry(h, tag, type, p, c);
00694         /*@notreached@*/ break;
00695     }
00696 
00697     if (headerIsEntry(h, tag))
00698         return rpmHeaderGetEntry(h, tag, type, p, c);
00699 
00700     if (sigs == NULL) {
00701         if (c)  *c = 0;
00702         return 0;
00703     }
00704 
00705     return headerGetEntry(sigs, sigtag, type, p, c);
00706 }
00707 
00708 /*
00709  * Up to rpm 3.0.4, packages implicitly provided their own name-version-release.
00710  * Retrofit an explicit "Provides: name = epoch:version-release.
00711  */
00712 void providePackageNVR(Header h)
00713 {
00714     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00715     HFD_t hfd = headerFreeData;
00716     const char *name, *version, *release;
00717     int_32 * epoch;
00718     const char *pEVR;
00719     char *p;
00720     int_32 pFlags = RPMSENSE_EQUAL;
00721     const char ** provides = NULL;
00722     const char ** providesEVR = NULL;
00723     rpmTagType pnt, pvt;
00724     int_32 * provideFlags = NULL;
00725     int providesCount;
00726     int i;
00727     int bingo = 1;
00728 
00729     /* Generate provides for this package name-version-release. */
00730     (void) headerNVR(h, &name, &version, &release);
00731     if (!(name && version && release))
00732         return;
00733     pEVR = p = alloca(21 + strlen(version) + 1 + strlen(release) + 1);
00734     *p = '\0';
00735     if (hge(h, RPMTAG_EPOCH, NULL, (void **) &epoch, NULL)) {
00736         sprintf(p, "%d:", *epoch);
00737         while (*p != '\0')
00738             p++;
00739     }
00740     (void) stpcpy( stpcpy( stpcpy(p, version) , "-") , release);
00741 
00742     /*
00743      * Rpm prior to 3.0.3 does not have versioned provides.
00744      * If no provides at all are available, we can just add.
00745      */
00746     if (!hge(h, RPMTAG_PROVIDENAME, &pnt, (void **) &provides, &providesCount))
00747         goto exit;
00748 
00749     /*
00750      * Otherwise, fill in entries on legacy packages.
00751      */
00752     if (!hge(h, RPMTAG_PROVIDEVERSION, &pvt, (void **) &providesEVR, NULL)) {
00753         for (i = 0; i < providesCount; i++) {
00754             char * vdummy = "";
00755             int_32 fdummy = RPMSENSE_ANY;
00756             (void) headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
00757                         &vdummy, 1);
00758             (void) headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
00759                         &fdummy, 1);
00760         }
00761         goto exit;
00762     }
00763 
00764     (void) hge(h, RPMTAG_PROVIDEFLAGS, NULL, (void **) &provideFlags, NULL);
00765 
00766     if (provides && providesEVR && provideFlags)
00767     for (i = 0; i < providesCount; i++) {
00768         if (!(provides[i] && providesEVR[i]))
00769             continue;
00770         if (!(provideFlags[i] == RPMSENSE_EQUAL &&
00771             !strcmp(name, provides[i]) && !strcmp(pEVR, providesEVR[i])))
00772             continue;
00773         bingo = 0;
00774         break;
00775     }
00776 
00777 exit:
00778     provides = hfd(provides, pnt);
00779     providesEVR = hfd(providesEVR, pvt);
00780 
00781     if (bingo) {
00782         (void) headerAddOrAppendEntry(h, RPMTAG_PROVIDENAME, RPM_STRING_ARRAY_TYPE,
00783                 &name, 1);
00784         (void) headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
00785                 &pFlags, 1);
00786         (void) headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
00787                 &pEVR, 1);
00788     }
00789 }
00790 
00791 int domd5(const char * fn, /*@out@*/ unsigned char * digest, int asAscii)
00792         /*@modifies digest, fileSystem @*/
00793 {
00794     int rc;
00795     FD_t fd = Fopen(fn, "r.ufdio");
00796     unsigned char buf[BUFSIZ];
00797     unsigned char * md5sum = NULL;
00798     size_t md5len;
00799 
00800     if (fd == NULL || Ferror(fd)) {
00801         if (fd)
00802             (void) Fclose(fd);
00803         return 1;
00804     }
00805 
00806     fdInitDigest(fd, PGPHASHALGO_MD5, 0);
00807     while ((rc = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
00808         {};
00809     fdFiniDigest(fd, PGPHASHALGO_MD5, (void **)&md5sum, &md5len, asAscii);
00810 
00811     if (Ferror(fd))
00812         rc = 1;
00813     (void) Fclose(fd);
00814 
00815     if (!rc)
00816         memcpy(digest, md5sum, md5len);
00817     md5sum = _free(md5sum);
00818 
00819     return rc;
00820 }

Generated at Fri Feb 15 10:30:35 2002 for rpm by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001