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