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