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