00001
00007 #include "system.h"
00008
00009 #define MYALLPERMS 07777
00010
00011 #include <regex.h>
00012 #include <signal.h>
00013
00014 #include <rpmio_internal.h>
00015 #include <rpmbuild.h>
00016 #include <rpmmacro.h>
00017
00018 #include "buildio.h"
00019
00020 #include "myftw.h"
00021 #include "md5.h"
00022 #include "debug.h"
00023
00024 #define SKIPWHITE(_x) {while(*(_x) && (isspace(*_x) || *(_x) == ',')) (_x)++;}
00025 #define SKIPNONWHITE(_x){while(*(_x) &&!(isspace(*_x) || *(_x) == ',')) (_x)++;}
00026
00027 #define MAXDOCDIR 1024
00028
00031 typedef struct {
00032 struct stat fl_st;
00033 #define fl_dev fl_st.st_dev
00034 #define fl_ino fl_st.st_ino
00035 #define fl_mode fl_st.st_mode
00036 #define fl_nlink fl_st.st_nlink
00037 #define fl_uid fl_st.st_uid
00038 #define fl_gid fl_st.st_gid
00039 #define fl_rdev fl_st.st_rdev
00040 #define fl_size fl_st.st_size
00041 #define fl_mtime fl_st.st_mtime
00042
00043 const char *diskURL;
00044 const char *fileURL;
00045 const char *uname;
00046 const char *gname;
00047 int flags;
00048 int verifyFlags;
00049 const char *langs;
00050 } FileListRec;
00051
00054 typedef struct {
00055 const char *ar_fmodestr;
00056 const char *ar_dmodestr;
00057 const char *ar_user;
00058 const char *ar_group;
00059 mode_t ar_fmode;
00060 mode_t ar_dmode;
00061 } AttrRec;
00062
00065 static int multiLib = 0;
00066
00070 struct FileList {
00071 const char *buildRootURL;
00072 const char *prefix;
00073
00074 int fileCount;
00075 int totalFileSize;
00076 int processingFailed;
00077
00078 int passedSpecialDoc;
00079 int isSpecialDoc;
00080
00081 int isDir;
00082 int inFtw;
00083 int currentFlags;
00084 int currentVerifyFlags;
00085 AttrRec cur_ar;
00086 AttrRec def_ar;
00087 int defVerifyFlags;
00088 int nLangs;
00089 const char **currentLangs;
00090
00091
00092
00093 const char *docDirs[MAXDOCDIR];
00094 int docDirCount;
00095
00096 FileListRec *fileList;
00097 int fileListRecsAlloced;
00098 int fileListRecsUsed;
00099 };
00100
00103 static void nullAttrRec(AttrRec *ar)
00104 {
00105 ar->ar_fmodestr = NULL;
00106 ar->ar_dmodestr = NULL;
00107 ar->ar_user = NULL;
00108 ar->ar_group = NULL;
00109 ar->ar_fmode = 0;
00110 ar->ar_dmode = 0;
00111 }
00112
00115 static void freeAttrRec(AttrRec *ar)
00116 {
00117 FREE(ar->ar_fmodestr);
00118 FREE(ar->ar_dmodestr);
00119 FREE(ar->ar_user);
00120 FREE(ar->ar_group);
00121
00122 }
00123
00126 static void dupAttrRec(AttrRec *oar, AttrRec *nar)
00127 {
00128 if (oar == nar)
00129 return;
00130 freeAttrRec(nar);
00131 nar->ar_fmodestr = (oar->ar_fmodestr ? xstrdup(oar->ar_fmodestr) : NULL);
00132 nar->ar_dmodestr = (oar->ar_dmodestr ? xstrdup(oar->ar_dmodestr) : NULL);
00133 nar->ar_user = (oar->ar_user ? xstrdup(oar->ar_user) : NULL);
00134 nar->ar_group = (oar->ar_group ? xstrdup(oar->ar_group) : NULL);
00135 nar->ar_fmode = oar->ar_fmode;
00136 nar->ar_dmode = oar->ar_dmode;
00137 }
00138
00139 #if 0
00140
00142 static void dumpAttrRec(const char *msg, AttrRec *ar) {
00143 if (msg)
00144 fprintf(stderr, "%s:\t", msg);
00145 fprintf(stderr, "(%s, %s, %s, %s)\n",
00146 ar->ar_fmodestr,
00147 ar->ar_user,
00148 ar->ar_group,
00149 ar->ar_dmodestr);
00150 }
00151 #endif
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00174 static char *strtokWithQuotes(char *s, char *delim)
00175 {
00176 static char *olds = NULL;
00177 char *token;
00178
00179 if (s == NULL) {
00180 s = olds;
00181 }
00182
00183
00184 s += strspn(s, delim);
00185 if (*s == '\0') {
00186 return NULL;
00187 }
00188
00189
00190 token = s;
00191 if (*token == '"') {
00192 token++;
00193
00194 s = strchr(token, '"');
00195 } else {
00196 s = strpbrk(token, delim);
00197 }
00198
00199
00200 if (s == NULL) {
00201
00202 olds = strchr(token, '\0');
00203 } else {
00204
00205 *s = '\0';
00206 olds = s+1;
00207 }
00208
00209 return token;
00210 }
00211
00214 static void timeCheck(int tc, Header h)
00215 {
00216 int *mtime;
00217 char **files;
00218 int count, x, currentTime;
00219
00220 headerGetEntry(h, RPMTAG_OLDFILENAMES, NULL, (void **) &files, &count);
00221 headerGetEntry(h, RPMTAG_FILEMTIMES, NULL, (void **) &mtime, NULL);
00222
00223 currentTime = time(NULL);
00224
00225 for (x = 0; x < count; x++) {
00226 if (currentTime - mtime[x] > tc) {
00227 rpmMessage(RPMMESS_WARNING, _("TIMECHECK failure: %s\n"), files[x]);
00228 }
00229 }
00230 FREE(files);
00231 }
00232
00235 typedef struct VFA {
00236 char * attribute;
00237 int flag;
00238 } VFA_t;
00239
00242 VFA_t verifyAttrs[] = {
00243 { "md5", RPMVERIFY_MD5 },
00244 { "size", RPMVERIFY_FILESIZE },
00245 { "link", RPMVERIFY_LINKTO },
00246 { "user", RPMVERIFY_USER },
00247 { "group", RPMVERIFY_GROUP },
00248 { "mtime", RPMVERIFY_MTIME },
00249 { "mode", RPMVERIFY_MODE },
00250 { "rdev", RPMVERIFY_RDEV },
00251 { NULL, 0 }
00252 };
00253
00257 static int parseForVerify(char *buf, struct FileList *fl)
00258 {
00259 char *p, *pe, *q;
00260 const char *name;
00261 int *resultVerify;
00262 int not;
00263 int verifyFlags;
00264
00265 if ((p = strstr(buf, (name = "%verify"))) != NULL) {
00266 resultVerify = &(fl->currentVerifyFlags);
00267 } else if ((p = strstr(buf, (name = "%defverify"))) != NULL) {
00268 resultVerify = &(fl->defVerifyFlags);
00269 } else
00270 return 0;
00271
00272 for (pe = p; (pe-p) < strlen(name); pe++)
00273 *pe = ' ';
00274
00275 SKIPSPACE(pe);
00276
00277 if (*pe != '(') {
00278 rpmError(RPMERR_BADSPEC, _("Missing '(' in %s %s\n"), name, pe);
00279 fl->processingFailed = 1;
00280 return RPMERR_BADSPEC;
00281 }
00282
00283
00284 *pe++ = ' ';
00285 for (p = pe; *pe && *pe != ')'; pe++)
00286 ;
00287
00288 if (*pe == '\0') {
00289 rpmError(RPMERR_BADSPEC, _("Missing ')' in %s(%s\n"), name, p);
00290 fl->processingFailed = 1;
00291 return RPMERR_BADSPEC;
00292 }
00293
00294
00295 q = alloca((pe-p) + 1);
00296 strncpy(q, p, pe-p);
00297 q[pe-p] = '\0';
00298 while (p <= pe)
00299 *p++ = ' ';
00300
00301 not = 0;
00302 verifyFlags = RPMVERIFY_NONE;
00303
00304 for (p = q; *p; p = pe) {
00305 SKIPWHITE(p);
00306 if (*p == '\0')
00307 break;
00308 pe = p;
00309 SKIPNONWHITE(pe);
00310 if (*pe)
00311 *pe++ = '\0';
00312
00313 { VFA_t *vfa;
00314 for (vfa = verifyAttrs; vfa->attribute != NULL; vfa++) {
00315 if (strcmp(p, vfa->attribute))
00316 continue;
00317 verifyFlags |= vfa->flag;
00318 break;
00319 }
00320 if (vfa->attribute)
00321 continue;
00322 }
00323
00324 if (!strcmp(p, "not")) {
00325 not ^= 1;
00326 } else {
00327 rpmError(RPMERR_BADSPEC, _("Invalid %s token: %s\n"), name, p);
00328 fl->processingFailed = 1;
00329 return RPMERR_BADSPEC;
00330 }
00331 }
00332
00333 *resultVerify = not ? ~(verifyFlags) : verifyFlags;
00334
00335 return 0;
00336 }
00337
00338 #define isAttrDefault(_ars) ((_ars)[0] == '-' && (_ars)[1] == '\0')
00339
00343 static int parseForAttr(char *buf, struct FileList *fl)
00344 {
00345 char *p, *pe, *q;
00346 const char *name;
00347 int x;
00348 AttrRec arbuf, *ar = &arbuf, *ret_ar;
00349
00350 if ((p = strstr(buf, (name = "%attr"))) != NULL) {
00351 ret_ar = &(fl->cur_ar);
00352 } else if ((p = strstr(buf, (name = "%defattr"))) != NULL) {
00353 ret_ar = &(fl->def_ar);
00354 } else
00355 return 0;
00356
00357 for (pe = p; (pe-p) < strlen(name); pe++)
00358 *pe = ' ';
00359
00360 SKIPSPACE(pe);
00361
00362 if (*pe != '(') {
00363 rpmError(RPMERR_BADSPEC, _("Missing '(' in %s %s\n"), name, pe);
00364 fl->processingFailed = 1;
00365 return RPMERR_BADSPEC;
00366 }
00367
00368
00369 *pe++ = ' ';
00370 for (p = pe; *pe && *pe != ')'; pe++)
00371 ;
00372
00373 if (ret_ar == &(fl->def_ar)) {
00374 q = pe;
00375 q++;
00376 SKIPSPACE(q);
00377 if (*q) {
00378 rpmError(RPMERR_BADSPEC,
00379 _("Non-white space follows %s(): %s\n"), name, q);
00380 fl->processingFailed = 1;
00381 return RPMERR_BADSPEC;
00382 }
00383 }
00384
00385
00386 q = alloca((pe-p) + 1);
00387 strncpy(q, p, pe-p);
00388 q[pe-p] = '\0';
00389 while (p <= pe)
00390 *p++ = ' ';
00391
00392 nullAttrRec(ar);
00393
00394 p = q; SKIPWHITE(p);
00395 if (*p) {
00396 pe = p; SKIPNONWHITE(pe); if (*pe) *pe++ = '\0';
00397 ar->ar_fmodestr = p;
00398 p = pe; SKIPWHITE(p);
00399 }
00400 if (*p) {
00401 pe = p; SKIPNONWHITE(pe); if (*pe) *pe++ = '\0';
00402 ar->ar_user = p;
00403 p = pe; SKIPWHITE(p);
00404 }
00405 if (*p) {
00406 pe = p; SKIPNONWHITE(pe); if (*pe) *pe++ = '\0';
00407 ar->ar_group = p;
00408 p = pe; SKIPWHITE(p);
00409 }
00410 if (*p && ret_ar == &(fl->def_ar)) {
00411 pe = p; SKIPNONWHITE(pe); if (*pe) *pe++ = '\0';
00412 ar->ar_dmodestr = p;
00413 p = pe; SKIPWHITE(p);
00414 }
00415
00416 if (!(ar->ar_fmodestr && ar->ar_user && ar->ar_group) || *p != '\0') {
00417 rpmError(RPMERR_BADSPEC, _("Bad syntax: %s(%s)\n"), name, q);
00418 fl->processingFailed = 1;
00419 return RPMERR_BADSPEC;
00420 }
00421
00422
00423 if (ar->ar_fmodestr && !isAttrDefault(ar->ar_fmodestr)) {
00424 unsigned int ui;
00425 x = sscanf(ar->ar_fmodestr, "%o", &ui);
00426 if ((x == 0) || (ar->ar_fmode & ~MYALLPERMS)) {
00427 rpmError(RPMERR_BADSPEC, _("Bad mode spec: %s(%s)\n"), name, q);
00428 fl->processingFailed = 1;
00429 return RPMERR_BADSPEC;
00430 }
00431 ar->ar_fmode = ui;
00432 } else
00433 ar->ar_fmodestr = NULL;
00434
00435 if (ar->ar_dmodestr && !isAttrDefault(ar->ar_dmodestr)) {
00436 unsigned int ui;
00437 x = sscanf(ar->ar_dmodestr, "%o", &ui);
00438 if ((x == 0) || (ar->ar_dmode & ~MYALLPERMS)) {
00439 rpmError(RPMERR_BADSPEC, _("Bad dirmode spec: %s(%s)\n"), name, q);
00440 fl->processingFailed = 1;
00441 return RPMERR_BADSPEC;
00442 }
00443 ar->ar_dmode = ui;
00444 } else
00445 ar->ar_dmodestr = NULL;
00446
00447 if (!(ar->ar_user && !isAttrDefault(ar->ar_user)))
00448 ar->ar_user = NULL;
00449
00450 if (!(ar->ar_group && !isAttrDefault(ar->ar_group)))
00451 ar->ar_group = NULL;
00452
00453 dupAttrRec(ar, ret_ar);
00454
00455 return 0;
00456 }
00457
00461 static int parseForConfig(char *buf, struct FileList *fl)
00462 {
00463 char *p, *pe, *q;
00464 const char *name;
00465
00466 if ((p = strstr(buf, (name = "%config"))) == NULL)
00467 return 0;
00468
00469 fl->currentFlags = RPMFILE_CONFIG;
00470
00471 for (pe = p; (pe-p) < strlen(name); pe++)
00472 *pe = ' ';
00473 SKIPSPACE(pe);
00474 if (*pe != '(')
00475 return 0;
00476
00477
00478 *pe++ = ' ';
00479 for (p = pe; *pe && *pe != ')'; pe++)
00480 ;
00481
00482 if (*pe == '\0') {
00483 rpmError(RPMERR_BADSPEC, _("Missing ')' in %s(%s\n"), name, p);
00484 fl->processingFailed = 1;
00485 return RPMERR_BADSPEC;
00486 }
00487
00488
00489 q = alloca((pe-p) + 1);
00490 strncpy(q, p, pe-p);
00491 q[pe-p] = '\0';
00492 while (p <= pe)
00493 *p++ = ' ';
00494
00495 for (p = q; *p; p = pe) {
00496 SKIPWHITE(p);
00497 if (*p == '\0')
00498 break;
00499 pe = p;
00500 SKIPNONWHITE(pe);
00501 if (*pe)
00502 *pe++ = '\0';
00503 if (!strcmp(p, "missingok")) {
00504 fl->currentFlags |= RPMFILE_MISSINGOK;
00505 } else if (!strcmp(p, "noreplace")) {
00506 fl->currentFlags |= RPMFILE_NOREPLACE;
00507 } else {
00508 rpmError(RPMERR_BADSPEC, _("Invalid %s token: %s\n"), name, p);
00509 fl->processingFailed = 1;
00510 return RPMERR_BADSPEC;
00511 }
00512 }
00513
00514 return 0;
00515 }
00516
00519 static int langCmp(const void * ap, const void *bp) {
00520 return strcmp(*(const char **)ap, *(const char **)bp);
00521 }
00522
00526 static int parseForLang(char *buf, struct FileList *fl)
00527 {
00528 char *p, *pe, *q;
00529 const char *name;
00530
00531 while ((p = strstr(buf, (name = "%lang"))) != NULL) {
00532
00533 for (pe = p; (pe-p) < strlen(name); pe++)
00534 *pe = ' ';
00535 SKIPSPACE(pe);
00536
00537 if (*pe != '(') {
00538 rpmError(RPMERR_BADSPEC, _("Missing '(' in %s %s\n"), name, pe);
00539 fl->processingFailed = 1;
00540 return RPMERR_BADSPEC;
00541 }
00542
00543
00544 *pe++ = ' ';
00545 for (pe = p; *pe && *pe != ')'; pe++)
00546 ;
00547
00548 if (*pe == '\0') {
00549 rpmError(RPMERR_BADSPEC, _("Missing ')' in %s(%s\n"), name, p);
00550 fl->processingFailed = 1;
00551 return RPMERR_BADSPEC;
00552 }
00553
00554
00555 q = alloca((pe-p) + 1);
00556 strncpy(q, p, pe-p);
00557 q[pe-p] = '\0';
00558 while (p <= pe)
00559 *p++ = ' ';
00560
00561
00562 for (p = q; *p; p = pe) {
00563 char *newp;
00564 size_t np;
00565 int i;
00566
00567 SKIPWHITE(p);
00568 pe = p;
00569 SKIPNONWHITE(pe);
00570
00571 np = pe - p;
00572
00573
00574 if (np < 1 || (np == 1 && *p != 'C') || np >= 32) {
00575 rpmError(RPMERR_BADSPEC,
00576 _("Unusual locale length: \"%.*s\" in %%lang(%s)\n"),
00577 (int)np, p, q);
00578 fl->processingFailed = 1;
00579 return RPMERR_BADSPEC;
00580 }
00581
00582
00583 for (i = 0; i < fl->nLangs; i++) {
00584 if (strncmp(fl->currentLangs[i], p, np))
00585 continue;
00586 rpmError(RPMERR_BADSPEC, _("Duplicate locale %.*s in %%lang(%s)\n"),
00587 (int)np, p, q);
00588 fl->processingFailed = 1;
00589 return RPMERR_BADSPEC;
00590 }
00591
00592
00593 fl->currentLangs = (const char **) ((fl->currentLangs == NULL)
00594 ? xmalloc(sizeof(*fl->currentLangs))
00595 : xrealloc(fl->currentLangs,((fl->nLangs+1)*sizeof(*fl->currentLangs))));
00596 newp = xmalloc( np+1 );
00597 strncpy(newp, p, np);
00598 newp[np] = '\0';
00599 fl->currentLangs[fl->nLangs++] = newp;
00600 if (*pe == ',') pe++;
00601 }
00602 }
00603
00604
00605 if (fl->currentLangs)
00606 qsort(fl->currentLangs, fl->nLangs, sizeof(*fl->currentLangs), langCmp);
00607
00608 return 0;
00609 }
00610
00613 static int parseForRegexLang(const char *fileName, char **lang)
00614 {
00615 static int initialized = 0;
00616 static int hasRegex = 0;
00617 static regex_t compiledPatt;
00618 static char buf[BUFSIZ];
00619 int x;
00620 regmatch_t matches[2];
00621 const char *s;
00622
00623 if (! initialized) {
00624 const char *patt = rpmExpand("%{_langpatt}", NULL);
00625 int rc = 0;
00626 if (!(patt && *patt != '%'))
00627 rc = 1;
00628 else if (regcomp(&compiledPatt, patt, REG_EXTENDED))
00629 rc = -1;
00630 free((void *)patt);
00631 if (rc)
00632 return rc;
00633 hasRegex = 1;
00634 initialized = 1;
00635 }
00636
00637 if (! hasRegex || regexec(&compiledPatt, fileName, 2, matches, REG_NOTEOL))
00638 return 1;
00639
00640
00641 s = fileName + matches[1].rm_eo - 1;
00642 x = matches[1].rm_eo - matches[1].rm_so;
00643 buf[x] = '\0';
00644 while (x) {
00645 buf[--x] = *s--;
00646 }
00647 if (lang)
00648 *lang = buf;
00649 return 0;
00650 }
00651
00654 static int parseForRegexMultiLib(const char *fileName)
00655 {
00656 static int initialized = 0;
00657 static int hasRegex = 0;
00658 static regex_t compiledPatt;
00659
00660 if (! initialized) {
00661 const char *patt;
00662 int rc = 0;
00663
00664 initialized = 1;
00665 patt = rpmExpand("%{_multilibpatt}", NULL);
00666 if (!(patt && *patt != '%'))
00667 rc = 1;
00668 else if (regcomp(&compiledPatt, patt, REG_EXTENDED | REG_NOSUB))
00669 rc = -1;
00670 free((void *)patt);
00671 if (rc)
00672 return rc;
00673 hasRegex = 1;
00674 }
00675
00676 if (! hasRegex || regexec(&compiledPatt, fileName, 0, NULL, 0))
00677 return 1;
00678
00679 return 0;
00680 }
00681
00684 VFA_t virtualFileAttributes[] = {
00685 { "%dir", 0 },
00686 { "%doc", RPMFILE_DOC },
00687 { "%ghost", RPMFILE_GHOST },
00688 { "%readme", RPMFILE_README },
00689 { "%license", RPMFILE_LICENSE },
00690 { "%multilib", 0 },
00691
00692 #if WHY_NOT
00693 { "%spec", RPMFILE_SPEC },
00694 { "%config", RPMFILE_CONFIG },
00695 { "%donotuse", RPMFILE_DONOTUSE },
00696 { "%missingok", RPMFILE_CONFIG|RPMFILE_MISSINGOK },
00697 { "%noreplace", RPMFILE_CONFIG|RPMFILE_NOREPLACE },
00698 #endif
00699
00700 { NULL, 0 }
00701 };
00702
00706 static int parseForSimple(Spec spec, Package pkg, char *buf,
00707 struct FileList *fl, const char **fileName)
00708 {
00709 char *s, *t;
00710 int res, specialDoc = 0;
00711 char specialDocBuf[BUFSIZ];
00712
00713 specialDocBuf[0] = '\0';
00714 *fileName = NULL;
00715 res = 0;
00716
00717 t = buf;
00718 while ((s = strtokWithQuotes(t, " \t\n")) != NULL) {
00719 t = NULL;
00720 if (!strcmp(s, "%docdir")) {
00721 s = strtokWithQuotes(NULL, " \t\n");
00722 if (fl->docDirCount == MAXDOCDIR) {
00723 rpmError(RPMERR_INTERNAL, _("Hit limit for %%docdir\n"));
00724 fl->processingFailed = 1;
00725 res = 1;
00726 }
00727 fl->docDirs[fl->docDirCount++] = xstrdup(s);
00728 if (strtokWithQuotes(NULL, " \t\n")) {
00729 rpmError(RPMERR_INTERNAL, _("Only one arg for %%docdir\n"));
00730 fl->processingFailed = 1;
00731 res = 1;
00732 }
00733 break;
00734 }
00735
00736
00737 { VFA_t *vfa;
00738 for (vfa = virtualFileAttributes; vfa->attribute != NULL; vfa++) {
00739 if (strcmp(s, vfa->attribute))
00740 continue;
00741 if (!vfa->flag) {
00742 if (!strcmp(s, "%dir"))
00743 fl->isDir = 1;
00744 else if (!strcmp(s, "%multilib"))
00745 fl->currentFlags |= multiLib;
00746 } else
00747 fl->currentFlags |= vfa->flag;
00748 break;
00749 }
00750
00751 if (vfa->attribute != NULL)
00752 continue;
00753 }
00754
00755 if (*fileName) {
00756
00757 rpmError(RPMERR_BADSPEC, _("Two files on one line: %s\n"),
00758 *fileName);
00759 fl->processingFailed = 1;
00760 res = 1;
00761 }
00762
00763 if (*s != '/') {
00764 if (fl->currentFlags & RPMFILE_DOC) {
00765 specialDoc = 1;
00766 strcat(specialDocBuf, " ");
00767 strcat(specialDocBuf, s);
00768 } else {
00769
00770 rpmError(RPMERR_BADSPEC,
00771 _("File must begin with \"/\": %s\n"), s);
00772 fl->processingFailed = 1;
00773 res = 1;
00774 }
00775 } else {
00776 *fileName = s;
00777 }
00778 }
00779
00780 if (specialDoc) {
00781 if (*fileName || (fl->currentFlags & ~(RPMFILE_DOC))) {
00782 rpmError(RPMERR_BADSPEC,
00783 _("Can't mix special %%doc with other forms: %s\n"),
00784 *fileName);
00785 fl->processingFailed = 1;
00786 res = 1;
00787 } else {
00788
00789 { const char *ddir, *n, *v;
00790
00791 headerNVR(pkg->header, &n, &v, NULL);
00792
00793 ddir = rpmGetPath("%{_docdir}/", n, "-", v, NULL);
00794 strcpy(buf, ddir);
00795 free((void *)ddir);
00796 }
00797
00798
00799
00800 if (! fl->passedSpecialDoc) {
00801 pkg->specialDoc = newStringBuf();
00802 appendStringBuf(pkg->specialDoc, "DOCDIR=$RPM_BUILD_ROOT");
00803 appendLineStringBuf(pkg->specialDoc, buf);
00804 appendLineStringBuf(pkg->specialDoc, "export DOCDIR");
00805 appendLineStringBuf(pkg->specialDoc, "rm -rf $DOCDIR");
00806 appendLineStringBuf(pkg->specialDoc, MKDIR_P " $DOCDIR");
00807
00808 *fileName = buf;
00809 fl->passedSpecialDoc = 1;
00810 fl->isSpecialDoc = 1;
00811 }
00812
00813 appendStringBuf(pkg->specialDoc, "cp -pr ");
00814 appendStringBuf(pkg->specialDoc, specialDocBuf);
00815 appendLineStringBuf(pkg->specialDoc, " $DOCDIR");
00816 }
00817 }
00818
00819 return res;
00820 }
00821
00824 static int compareFileListRecs(const void *ap, const void *bp)
00825 {
00826 const char *a = ((FileListRec *)ap)->fileURL;
00827 const char *b = ((FileListRec *)bp)->fileURL;
00828 return strcmp(a, b);
00829 }
00830
00834 static int isDoc(struct FileList *fl, const char *fileName)
00835 {
00836 int x = fl->docDirCount;
00837
00838 while (x--) {
00839 if (strstr(fileName, fl->docDirs[x]) == fileName) {
00840 return 1;
00841 }
00842 }
00843 return 0;
00844 }
00845
00851 static void checkHardLinks(struct FileList *fl)
00852 {
00853 char nlangs[BUFSIZ];
00854 FileListRec *ilp, *jlp;
00855 int i, j;
00856
00857 for (i = 0; i < fl->fileListRecsUsed; i++) {
00858 char *te;
00859
00860 ilp = fl->fileList + i;
00861 if (!(S_ISREG(ilp->fl_mode) && ilp->fl_nlink > 1))
00862 continue;
00863 if (ilp->flags & RPMFILE_SPECFILE)
00864 continue;
00865
00866 te = nlangs;
00867 *te = '\0';
00868 for (j = i + 1; j < fl->fileListRecsUsed; j++) {
00869 jlp = fl->fileList + j;
00870 if (!S_ISREG(jlp->fl_mode))
00871 continue;
00872 if (ilp->fl_nlink != jlp->fl_nlink)
00873 continue;
00874 if (ilp->fl_ino != jlp->fl_ino)
00875 continue;
00876 if (ilp->fl_dev != jlp->fl_dev)
00877 continue;
00878 if (!strcmp(ilp->langs, jlp->langs)) {
00879 jlp->flags |= RPMFILE_SPECFILE;
00880 continue;
00881 }
00882 if (te == nlangs)
00883 te = stpcpy(te, ilp->langs);
00884 *te++ = '|';
00885 te = stpcpy(te, jlp->langs);
00886 }
00887
00888
00889 if (te == nlangs)
00890 continue;
00891
00892 free((void *)ilp->langs);
00893 ilp->langs = xstrdup(nlangs);
00894 for (j = i + 1; j < fl->fileListRecsUsed; j++) {
00895 jlp = fl->fileList + j;
00896 if (!S_ISREG(jlp->fl_mode))
00897 continue;
00898 if (ilp->fl_nlink != jlp->fl_nlink)
00899 continue;
00900 if (ilp->fl_ino != jlp->fl_ino)
00901 continue;
00902 if (ilp->fl_dev != jlp->fl_dev)
00903 continue;
00904 jlp->flags |= RPMFILE_SPECFILE;
00905 free((void *)jlp->langs);
00906 jlp->langs = xstrdup(nlangs);
00907 }
00908 }
00909
00910 for (i = 0; i < fl->fileListRecsUsed; i++) {
00911 ilp = fl->fileList + i;
00912 ilp->flags &= ~RPMFILE_SPECFILE;
00913 }
00914 }
00915
00920 static void genCpioListAndHeader(struct FileList *fl,
00921 struct cpioFileMapping **cpioList,
00922 int *cpioCount, Header h, int isSrc)
00923 {
00924 int skipLen;
00925 int count;
00926 FileListRec *flp;
00927 struct cpioFileMapping *clp;
00928 char *s;
00929 char buf[BUFSIZ];
00930 uint_32 multiLibMask = 0;
00931
00932
00933 qsort(fl->fileList, fl->fileListRecsUsed,
00934 sizeof(*(fl->fileList)), compareFileListRecs);
00935
00936
00937 skipLen = 0;
00938 if (! isSrc) {
00939 skipLen = 1;
00940 if (fl->prefix)
00941 skipLen += strlen(fl->prefix);
00942 }
00943
00944 *cpioCount = 0;
00945 clp = *cpioList = xmalloc(sizeof(**cpioList) * fl->fileListRecsUsed);
00946
00947 for (flp = fl->fileList, count = fl->fileListRecsUsed; count > 0; flp++, count--) {
00948 if ((count > 1) && !strcmp(flp->fileURL, flp[1].fileURL)) {
00949 rpmError(RPMERR_BADSPEC, _("File listed twice: %s\n"),
00950 flp->fileURL);
00951 fl->processingFailed = 1;
00952 }
00953
00954 if (flp->flags & RPMFILE_MULTILIB_MASK)
00955 multiLibMask |=
00956 (1 << ((flp->flags & RPMFILE_MULTILIB_MASK))
00957 >> RPMFILE_MULTILIB_SHIFT);
00958
00959
00960 if (! (flp->flags & RPMFILE_GHOST)) {
00961 clp->fsPath = xstrdup(flp->diskURL);
00962
00963 { char * t = buf;
00964 if (!isSrc && !rpmExpandNumeric("%{_noPayloadPrefix}")) {
00965 t = stpcpy(t, "./");
00966 rpmlibNeedsFeature(h, "PayloadFilesHavePrefix", "4.0-1");
00967 }
00968 t = stpcpy(t, (flp->fileURL + skipLen));
00969 clp->archivePath = xstrdup(buf);
00970 }
00971 clp->finalMode = flp->fl_mode;
00972 clp->finalUid = flp->fl_uid;
00973 clp->finalGid = flp->fl_gid;
00974 clp->mapFlags = CPIO_MAP_PATH | CPIO_MAP_MODE |
00975 CPIO_MAP_UID | CPIO_MAP_GID;
00976
00977 if (isSrc)
00978 clp->mapFlags |= CPIO_FOLLOW_SYMLINKS;
00979 if (flp->flags & RPMFILE_MULTILIB_MASK)
00980 clp->mapFlags |= CPIO_MULTILIB;
00981
00982 clp++;
00983 (*cpioCount)++;
00984 }
00985
00986
00987
00988
00989 headerAddOrAppendEntry(h, RPMTAG_OLDFILENAMES, RPM_STRING_ARRAY_TYPE,
00990 &(flp->fileURL), 1);
00991
00992 if (sizeof(flp->fl_size) != sizeof(uint_32)) {
00993 uint_32 psize = (uint_32)flp->fl_size;
00994 headerAddOrAppendEntry(h, RPMTAG_FILESIZES, RPM_INT32_TYPE,
00995 &(psize), 1);
00996 } else {
00997 headerAddOrAppendEntry(h, RPMTAG_FILESIZES, RPM_INT32_TYPE,
00998 &(flp->fl_size), 1);
00999 }
01000 headerAddOrAppendEntry(h, RPMTAG_FILEUSERNAME, RPM_STRING_ARRAY_TYPE,
01001 &(flp->uname), 1);
01002 headerAddOrAppendEntry(h, RPMTAG_FILEGROUPNAME, RPM_STRING_ARRAY_TYPE,
01003 &(flp->gname), 1);
01004 headerAddOrAppendEntry(h, RPMTAG_FILEMTIMES, RPM_INT32_TYPE,
01005 &(flp->fl_mtime), 1);
01006 if (sizeof(flp->fl_mode) != sizeof(uint_16)) {
01007 uint_16 pmode = (uint_16)flp->fl_mode;
01008 headerAddOrAppendEntry(h, RPMTAG_FILEMODES, RPM_INT16_TYPE,
01009 &(pmode), 1);
01010 } else {
01011 headerAddOrAppendEntry(h, RPMTAG_FILEMODES, RPM_INT16_TYPE,
01012 &(flp->fl_mode), 1);
01013 }
01014 if (sizeof(flp->fl_rdev) != sizeof(uint_16)) {
01015 uint_16 prdev = (uint_16)flp->fl_rdev;
01016 headerAddOrAppendEntry(h, RPMTAG_FILERDEVS, RPM_INT16_TYPE,
01017 &(prdev), 1);
01018 } else {
01019 headerAddOrAppendEntry(h, RPMTAG_FILERDEVS, RPM_INT16_TYPE,
01020 &(flp->fl_rdev), 1);
01021 }
01022 if (sizeof(flp->fl_dev) != sizeof(uint_32)) {
01023 uint_32 pdevice = (uint_32)flp->fl_dev;
01024 headerAddOrAppendEntry(h, RPMTAG_FILEDEVICES, RPM_INT32_TYPE,
01025 &(pdevice), 1);
01026 } else {
01027 headerAddOrAppendEntry(h, RPMTAG_FILEDEVICES, RPM_INT32_TYPE,
01028 &(flp->fl_dev), 1);
01029 }
01030 headerAddOrAppendEntry(h, RPMTAG_FILEINODES, RPM_INT32_TYPE,
01031 &(flp->fl_ino), 1);
01032
01033 headerAddOrAppendEntry(h, RPMTAG_FILELANGS, RPM_STRING_ARRAY_TYPE,
01034 &(flp->langs), 1);
01035
01036
01037
01038
01039
01040
01041
01042
01043 buf[0] = '\0';
01044 if (S_ISREG(flp->fl_mode))
01045 mdfile(flp->diskURL, buf);
01046 s = buf;
01047 headerAddOrAppendEntry(h, RPMTAG_FILEMD5S, RPM_STRING_ARRAY_TYPE,
01048 &s, 1);
01049
01050 buf[0] = '\0';
01051 if (S_ISLNK(flp->fl_mode)) {
01052 buf[Readlink(flp->diskURL, buf, BUFSIZ)] = '\0';
01053 if (fl->buildRootURL) {
01054 const char * buildRoot;
01055 (void) urlPath(fl->buildRootURL, &buildRoot);
01056
01057 if (buf[0] == '/' && strcmp(buildRoot, "/") &&
01058 !strncmp(buf, buildRoot, strlen(buildRoot))) {
01059 rpmError(RPMERR_BADSPEC,
01060 _("Symlink points to BuildRoot: %s -> %s\n"),
01061 flp->fileURL, buf);
01062 fl->processingFailed = 1;
01063 }
01064 }
01065 }
01066 s = buf;
01067 headerAddOrAppendEntry(h, RPMTAG_FILELINKTOS, RPM_STRING_ARRAY_TYPE,
01068 &s, 1);
01069
01070 if (flp->flags & RPMFILE_GHOST) {
01071 flp->verifyFlags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE |
01072 RPMVERIFY_LINKTO | RPMVERIFY_MTIME);
01073 }
01074 headerAddOrAppendEntry(h, RPMTAG_FILEVERIFYFLAGS, RPM_INT32_TYPE,
01075 &(flp->verifyFlags), 1);
01076
01077 if (!isSrc && isDoc(fl, flp->fileURL))
01078 flp->flags |= RPMFILE_DOC;
01079
01080 if (S_ISDIR(flp->fl_mode))
01081 flp->flags &= ~(RPMFILE_CONFIG|RPMFILE_DOC);
01082
01083 headerAddOrAppendEntry(h, RPMTAG_FILEFLAGS, RPM_INT32_TYPE,
01084 &(flp->flags), 1);
01085 }
01086 headerAddEntry(h, RPMTAG_SIZE, RPM_INT32_TYPE,
01087 &(fl->totalFileSize), 1);
01088
01089
01090
01091
01092 if (multiLibMask)
01093 headerAddEntry(h, RPMTAG_MULTILIBS, RPM_INT32_TYPE,
01094 &multiLibMask, 1);
01095 }
01096
01099 static void freeFileList(FileListRec *fileList, int count)
01100 {
01101 while (count--) {
01102 FREE(fileList[count].diskURL);
01103 FREE(fileList[count].fileURL);
01104 FREE(fileList[count].langs);
01105 }
01106 FREE(fileList);
01107 }
01108
01112 static int addFile(struct FileList *fl, const char * diskURL, struct stat *statp)
01113 {
01114 const char *fileURL = diskURL;
01115 struct stat statbuf;
01116 mode_t fileMode;
01117 uid_t fileUid;
01118 gid_t fileGid;
01119 const char *fileUname;
01120 const char *fileGname;
01121 char *lang;
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134 { const char *fileName;
01135 (void) urlPath(fileURL, &fileName);
01136 if (fl->buildRootURL && strcmp(fl->buildRootURL, "/"))
01137 fileURL += strlen(fl->buildRootURL);
01138 }
01139
01140
01141 if (*fileURL == '\0')
01142 fileURL = "/";
01143
01144
01145 if (!fl->inFtw && fl->prefix) {
01146 const char *prefixTest;
01147 const char *prefixPtr = fl->prefix;
01148
01149 (void) urlPath(fileURL, &prefixTest);
01150 while (*prefixPtr && *prefixTest && (*prefixTest == *prefixPtr)) {
01151 prefixPtr++;
01152 prefixTest++;
01153 }
01154 if (*prefixPtr || (*prefixTest && *prefixTest != '/')) {
01155 rpmError(RPMERR_BADSPEC, _("File doesn't match prefix (%s): %s\n"),
01156 fl->prefix, fileURL);
01157 fl->processingFailed = 1;
01158 return RPMERR_BADSPEC;
01159 }
01160 }
01161
01162 if (statp == NULL) {
01163 statp = &statbuf;
01164 if (Lstat(diskURL, statp)) {
01165 rpmError(RPMERR_BADSPEC, _("File not found: %s\n"), diskURL);
01166 fl->processingFailed = 1;
01167 return RPMERR_BADSPEC;
01168 }
01169 }
01170
01171 if ((! fl->isDir) && S_ISDIR(statp->st_mode)) {
01172
01173
01174
01175
01176 fl->inFtw = 1;
01177 fl->isDir = 1;
01178 myftw(diskURL, 16, (myftwFunc) addFile, fl);
01179 fl->isDir = 0;
01180 fl->inFtw = 0;
01181 return 0;
01182 }
01183
01184 fileMode = statp->st_mode;
01185 fileUid = statp->st_uid;
01186 fileGid = statp->st_gid;
01187
01188 if (S_ISDIR(fileMode) && fl->cur_ar.ar_dmodestr) {
01189 fileMode &= S_IFMT;
01190 fileMode |= fl->cur_ar.ar_dmode;
01191 } else if (fl->cur_ar.ar_fmodestr != NULL) {
01192 fileMode &= S_IFMT;
01193 fileMode |= fl->cur_ar.ar_fmode;
01194 }
01195 if (fl->cur_ar.ar_user) {
01196 fileUname = getUnameS(fl->cur_ar.ar_user);
01197 } else {
01198 fileUname = getUname(fileUid);
01199 }
01200 if (fl->cur_ar.ar_group) {
01201 fileGname = getGnameS(fl->cur_ar.ar_group);
01202 } else {
01203 fileGname = getGname(fileGid);
01204 }
01205
01206 #if 0
01207 if (! (fileUname && fileGname)) {
01208 rpmError(RPMERR_BADSPEC, _("Bad owner/group: %s\n"), diskName);
01209 fl->processingFailed = 1;
01210 return RPMERR_BADSPEC;
01211 }
01212 #else
01213
01214 if (fileUname == NULL)
01215 fileUname = getUname(getuid());
01216 if (fileGname == NULL)
01217 fileGname = getGname(getgid());
01218 #endif
01219
01220 rpmMessage(RPMMESS_DEBUG, _("File %4d: %07o %s.%s\t %s\n"), fl->fileCount,
01221 fileMode, fileUname, fileGname, fileURL);
01222
01223
01224 if (fl->fileListRecsUsed == fl->fileListRecsAlloced) {
01225 fl->fileListRecsAlloced += 128;
01226 fl->fileList = xrealloc(fl->fileList,
01227 fl->fileListRecsAlloced * sizeof(*(fl->fileList)));
01228 }
01229
01230 { FileListRec * flp = &fl->fileList[fl->fileListRecsUsed];
01231
01232 flp->fl_st = *statp;
01233 flp->fl_mode = fileMode;
01234 flp->fl_uid = fileUid;
01235 flp->fl_gid = fileGid;
01236
01237 flp->fileURL = xstrdup(fileURL);
01238 flp->diskURL = xstrdup(diskURL);
01239 flp->uname = fileUname;
01240 flp->gname = fileGname;
01241
01242 if (fl->currentLangs && fl->nLangs > 0) {
01243 char *ncl;
01244 size_t nl = 0;
01245 int i;
01246
01247 for (i = 0; i < fl->nLangs; i++)
01248 nl += strlen(fl->currentLangs[i]) + 1;
01249
01250 flp->langs = ncl = xmalloc(nl);
01251 for (i = 0; i < fl->nLangs; i++) {
01252 const char *ocl;
01253 if (i) *ncl++ = '|';
01254 for (ocl = fl->currentLangs[i]; *ocl; ocl++)
01255 *ncl++ = *ocl;
01256 *ncl = '\0';
01257 }
01258 } else if (! parseForRegexLang(fileURL, &lang)) {
01259 flp->langs = xstrdup(lang);
01260 } else {
01261 flp->langs = xstrdup("");
01262 }
01263
01264 flp->flags = fl->currentFlags;
01265 flp->verifyFlags = fl->currentVerifyFlags;
01266
01267 if (multiLib
01268 && !(flp->flags & RPMFILE_MULTILIB_MASK)
01269 && !parseForRegexMultiLib(fileURL))
01270 flp->flags |= multiLib;
01271
01272 fl->totalFileSize += flp->fl_size;
01273 }
01274
01275 fl->fileListRecsUsed++;
01276 fl->fileCount++;
01277
01278 return 0;
01279 }
01280
01284 static int processBinaryFile(Package pkg, struct FileList *fl,
01285 const char *fileURL)
01286 {
01287 int doGlob;
01288 const char *diskURL = NULL;
01289 int rc = 0;
01290
01291 doGlob = myGlobPatternP(fileURL);
01292
01293
01294 { const char * fileName;
01295 (void) urlPath(fileURL, &fileName);
01296 if (*fileName != '/') {
01297 rpmError(RPMERR_BADSPEC, _("File needs leading \"/\": %s\n"),
01298 fileName);
01299 rc = 1;
01300 goto exit;
01301 }
01302 }
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312 diskURL = rpmGenPath(fl->buildRootURL, NULL, fileURL);
01313
01314 if (doGlob) {
01315 const char ** argv = NULL;
01316 int argc = 0;
01317 int i;
01318
01319 rc = rpmGlob(diskURL, &argc, &argv);
01320 if (rc == 0 && argc >= 1 && !myGlobPatternP(argv[0])) {
01321 for (i = 0; i < argc; i++) {
01322 rc = addFile(fl, argv[i], NULL);
01323 free((void *)argv[i]);
01324 }
01325 free((void *)argv);
01326 } else {
01327 rpmError(RPMERR_BADSPEC, _("File not found by glob: %s\n"),
01328 diskURL);
01329 rc = 1;
01330 }
01331 } else {
01332 rc = addFile(fl, diskURL, NULL);
01333 }
01334
01335 exit:
01336 if (diskURL)
01337 free((void *)diskURL);
01338 if (rc)
01339 fl->processingFailed = 1;
01340 return rc;
01341 }
01342
01345 static int processPackageFiles(Spec spec, Package pkg,
01346 int installSpecialDoc, int test)
01347 {
01348 struct FileList fl;
01349 char *s, **files, **fp;
01350 const char *fileName;
01351 char buf[BUFSIZ];
01352 AttrRec specialDocAttrRec;
01353 char *specialDoc = NULL;
01354
01355 #ifdef MULTILIB
01356 multiLib = rpmExpandNumeric("%{_multilibno}");
01357 if (multiLib)
01358 multiLib = RPMFILE_MULTILIB(multiLib);
01359 #endif
01360
01361 nullAttrRec(&specialDocAttrRec);
01362 pkg->cpioList = NULL;
01363 pkg->cpioCount = 0;
01364
01365 if (pkg->fileFile) {
01366 const char *ffn;
01367 FD_t fd;
01368
01369
01370 if (*pkg->fileFile == '/') {
01371 ffn = rpmGetPath(pkg->fileFile, NULL);
01372 } else {
01373
01374 ffn = rpmGetPath("%{_builddir}/",
01375 (spec->buildSubdir ? spec->buildSubdir : "") ,
01376 "/", pkg->fileFile, NULL);
01377 }
01378 fd = Fopen(ffn, "r.fpio");
01379
01380 if (fd == NULL || Ferror(fd)) {
01381 rpmError(RPMERR_BADFILENAME,
01382 _("Could not open %%files file %s: %s\n"),
01383 ffn, Fstrerror(fd));
01384 return RPMERR_BADFILENAME;
01385 }
01386 free((void *)ffn);
01387
01388 while (fgets(buf, sizeof(buf), (FILE *)fdGetFp(fd))) {
01389 handleComments(buf);
01390 if (expandMacros(spec, spec->macros, buf, sizeof(buf))) {
01391 rpmError(RPMERR_BADSPEC, _("line: %s\n"), buf);
01392 return RPMERR_BADSPEC;
01393 }
01394 appendStringBuf(pkg->fileList, buf);
01395 }
01396 Fclose(fd);
01397 }
01398
01399
01400
01401
01402 fl.buildRootURL = rpmGenPath(spec->rootURL, spec->buildRootURL, NULL);
01403
01404 if (headerGetEntry(pkg->header, RPMTAG_DEFAULTPREFIX,
01405 NULL, (void **)&fl.prefix, NULL)) {
01406 fl.prefix = xstrdup(fl.prefix);
01407 } else {
01408 fl.prefix = NULL;
01409 }
01410
01411 fl.fileCount = 0;
01412 fl.totalFileSize = 0;
01413 fl.processingFailed = 0;
01414
01415 fl.passedSpecialDoc = 0;
01416 fl.isSpecialDoc = 0;
01417
01418 fl.isDir = 0;
01419 fl.inFtw = 0;
01420 fl.currentFlags = 0;
01421 fl.currentVerifyFlags = 0;
01422
01423 nullAttrRec(&fl.cur_ar);
01424 nullAttrRec(&fl.def_ar);
01425
01426 fl.defVerifyFlags = RPMVERIFY_ALL;
01427 fl.nLangs = 0;
01428 fl.currentLangs = NULL;
01429
01430 fl.docDirCount = 0;
01431 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/doc");
01432 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/man");
01433 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/info");
01434 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/X11R6/man");
01435 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/share/doc");
01436 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/share/man");
01437 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/share/info");
01438 fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_docdir}", NULL);
01439 fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_mandir}", NULL);
01440 fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_infodir}", NULL);
01441
01442 fl.fileList = NULL;
01443 fl.fileListRecsAlloced = 0;
01444 fl.fileListRecsUsed = 0;
01445
01446 s = getStringBuf(pkg->fileList);
01447 files = splitString(s, strlen(s), '\n');
01448
01449 for (fp = files; *fp != NULL; fp++) {
01450 s = *fp;
01451 SKIPSPACE(s);
01452 if (*s == '\0')
01453 continue;
01454 fileName = NULL;
01455 strcpy(buf, s);
01456
01457
01458 fl.isDir = 0;
01459 fl.inFtw = 0;
01460 fl.currentFlags = 0;
01461 fl.currentVerifyFlags = fl.defVerifyFlags;
01462 fl.isSpecialDoc = 0;
01463
01464
01465 if (fl.currentLangs) {
01466 int i;
01467 for (i = 0; i < fl.nLangs; i++)
01468 free((void *)fl.currentLangs[i]);
01469 FREE(fl.currentLangs);
01470 }
01471 fl.nLangs = 0;
01472
01473 dupAttrRec(&fl.def_ar, &fl.cur_ar);
01474
01475 if (parseForVerify(buf, &fl))
01476 continue;
01477 if (parseForAttr(buf, &fl))
01478 continue;
01479 if (parseForConfig(buf, &fl))
01480 continue;
01481 if (parseForLang(buf, &fl))
01482 continue;
01483 if (parseForSimple(spec, pkg, buf, &fl, &fileName))
01484 continue;
01485 if (fileName == NULL)
01486 continue;
01487
01488 if (fl.isSpecialDoc) {
01489
01490 FREE(specialDoc);
01491 specialDoc = xstrdup(fileName);
01492 dupAttrRec(&fl.cur_ar, &specialDocAttrRec);
01493 } else {
01494 processBinaryFile(pkg, &fl, fileName);
01495 }
01496 }
01497
01498
01499 if (specialDoc) {
01500 if (installSpecialDoc) {
01501 doScript(spec, RPMBUILD_STRINGBUF, "%doc", pkg->specialDoc, test);
01502 }
01503
01504
01505 fl.isDir = 0;
01506 fl.inFtw = 0;
01507 fl.currentFlags = 0;
01508 fl.currentVerifyFlags = 0;
01509
01510
01511 if (fl.currentLangs) {
01512 int i;
01513 for (i = 0; i < fl.nLangs; i++)
01514 free((void *)fl.currentLangs[i]);
01515 FREE(fl.currentLangs);
01516 }
01517 fl.nLangs = 0;
01518
01519 dupAttrRec(&specialDocAttrRec, &fl.cur_ar);
01520 freeAttrRec(&specialDocAttrRec);
01521
01522 processBinaryFile(pkg, &fl, specialDoc);
01523
01524 FREE(specialDoc);
01525 }
01526
01527 freeSplitString(files);
01528
01529 if (fl.processingFailed)
01530 goto exit;
01531
01532
01533 checkHardLinks(&fl);
01534
01535 genCpioListAndHeader(&fl, &(pkg->cpioList), &(pkg->cpioCount),
01536 pkg->header, 0);
01537
01538 if (spec->timeCheck)
01539 timeCheck(spec->timeCheck, pkg->header);
01540
01541 exit:
01542 FREE(fl.buildRootURL);
01543 FREE(fl.prefix);
01544
01545 freeAttrRec(&fl.cur_ar);
01546 freeAttrRec(&fl.def_ar);
01547
01548 if (fl.currentLangs) {
01549 int i;
01550 for (i = 0; i < fl.nLangs; i++)
01551 free((void *)fl.currentLangs[i]);
01552 FREE(fl.currentLangs);
01553 }
01554
01555 freeFileList(fl.fileList, fl.fileListRecsUsed);
01556 while (fl.docDirCount--) {
01557 FREE(fl.docDirs[fl.docDirCount]);
01558 }
01559 return fl.processingFailed;
01560 }
01561
01562 void initSourceHeader(Spec spec)
01563 {
01564 HeaderIterator hi;
01565 int_32 tag, type, count;
01566 const void * ptr;
01567
01568 spec->sourceHeader = headerNew();
01569
01570 for (hi = headerInitIterator(spec->packages->header);
01571 headerNextIterator(hi, &tag, &type, &ptr, &count);
01572 ptr = headerFreeData(ptr, type))
01573 {
01574 switch (tag) {
01575 case RPMTAG_NAME:
01576 case RPMTAG_VERSION:
01577 case RPMTAG_RELEASE:
01578 case RPMTAG_EPOCH:
01579 case RPMTAG_SUMMARY:
01580 case RPMTAG_DESCRIPTION:
01581 case RPMTAG_PACKAGER:
01582 case RPMTAG_DISTRIBUTION:
01583 case RPMTAG_DISTURL:
01584 case RPMTAG_VENDOR:
01585 case RPMTAG_LICENSE:
01586 case RPMTAG_GROUP:
01587 case RPMTAG_OS:
01588 case RPMTAG_ARCH:
01589 case RPMTAG_CHANGELOGTIME:
01590 case RPMTAG_CHANGELOGNAME:
01591 case RPMTAG_CHANGELOGTEXT:
01592 case RPMTAG_URL:
01593 case HEADER_I18NTABLE:
01594 headerAddEntry(spec->sourceHeader, tag, type, ptr, count);
01595 break;
01596 default:
01597
01598 break;
01599 }
01600 }
01601 headerFreeIterator(hi);
01602
01603
01604 for (hi = headerInitIterator(spec->buildRestrictions);
01605 headerNextIterator(hi, &tag, &type, &ptr, &count);
01606 ptr = headerFreeData(ptr, type))
01607 {
01608 headerAddEntry(spec->sourceHeader, tag, type, ptr, count);
01609 }
01610 headerFreeIterator(hi);
01611
01612 if (spec->buildArchitectureCount) {
01613 headerAddEntry(spec->sourceHeader, RPMTAG_BUILDARCHS,
01614 RPM_STRING_ARRAY_TYPE,
01615 spec->buildArchitectures, spec->buildArchitectureCount);
01616 }
01617 }
01618
01619 int processSourceFiles(Spec spec)
01620 {
01621 struct Source *srcPtr;
01622 StringBuf sourceFiles;
01623 int x, isSpec = 1;
01624 struct FileList fl;
01625 char *s, **files, **fp;
01626 Package pkg;
01627
01628 sourceFiles = newStringBuf();
01629
01630
01631
01632
01633
01634 if (spec->sourceHeader == NULL)
01635 initSourceHeader(spec);
01636
01637
01638 appendLineStringBuf(sourceFiles, spec->specFile);
01639 for (srcPtr = spec->sources; srcPtr != NULL; srcPtr = srcPtr->next) {
01640 if (srcPtr->flags & RPMBUILD_ISSOURCE) {
01641 headerAddOrAppendEntry(spec->sourceHeader, RPMTAG_SOURCE,
01642 RPM_STRING_ARRAY_TYPE, &srcPtr->source, 1);
01643 if (srcPtr->flags & RPMBUILD_ISNO) {
01644 headerAddOrAppendEntry(spec->sourceHeader, RPMTAG_NOSOURCE,
01645 RPM_INT32_TYPE, &srcPtr->num, 1);
01646 }
01647 }
01648 if (srcPtr->flags & RPMBUILD_ISPATCH) {
01649 headerAddOrAppendEntry(spec->sourceHeader, RPMTAG_PATCH,
01650 RPM_STRING_ARRAY_TYPE, &srcPtr->source, 1);
01651 if (srcPtr->flags & RPMBUILD_ISNO) {
01652 headerAddOrAppendEntry(spec->sourceHeader, RPMTAG_NOPATCH,
01653 RPM_INT32_TYPE, &srcPtr->num, 1);
01654 }
01655 }
01656
01657 { const char *s;
01658 s = rpmGetPath( ((srcPtr->flags & RPMBUILD_ISNO) ? "!" : ""),
01659 "%{_sourcedir}/", srcPtr->source, NULL);
01660 appendLineStringBuf(sourceFiles, s);
01661 free((void *)s);
01662 }
01663 }
01664
01665 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
01666 for (srcPtr = pkg->icon; srcPtr != NULL; srcPtr = srcPtr->next) {
01667 const char *s;
01668 s = rpmGetPath( ((srcPtr->flags & RPMBUILD_ISNO) ? "!" : ""),
01669 "%{_sourcedir}/", srcPtr->source, NULL);
01670 appendLineStringBuf(sourceFiles, s);
01671 free((void *)s);
01672 }
01673 }
01674
01675 spec->sourceCpioList = NULL;
01676 spec->sourceCpioCount = 0;
01677
01678 fl.fileList = xmalloc((spec->numSources + 1) * sizeof(FileListRec));
01679 fl.processingFailed = 0;
01680 fl.fileListRecsUsed = 0;
01681 fl.totalFileSize = 0;
01682 fl.prefix = NULL;
01683
01684 s = getStringBuf(sourceFiles);
01685 files = splitString(s, strlen(s), '\n');
01686
01687
01688 x = 0;
01689 for (fp = files; *fp != NULL; fp++) {
01690 const char * diskURL, *diskPath;
01691 FileListRec *flp;
01692
01693 diskURL = *fp;
01694 SKIPSPACE(diskURL);
01695 if (! *diskURL)
01696 continue;
01697
01698 flp = &fl.fileList[x];
01699
01700 flp->flags = isSpec ? RPMFILE_SPECFILE : 0;
01701
01702 if (*diskURL == '!') {
01703 flp->flags |= RPMFILE_GHOST;
01704 diskURL++;
01705 }
01706
01707 urlPath(diskURL, &diskPath);
01708
01709 flp->diskURL = xstrdup(diskURL);
01710 diskPath = strrchr(diskPath, '/');
01711 if (diskPath)
01712 diskPath++;
01713 else
01714 diskPath = diskURL;
01715
01716 flp->fileURL = xstrdup(diskPath);
01717 flp->verifyFlags = RPMVERIFY_ALL;
01718
01719 if (Stat(diskURL, &flp->fl_st)) {
01720 rpmError(RPMERR_BADSPEC, _("Bad file: %s: %s\n"),
01721 diskURL, strerror(errno));
01722 fl.processingFailed = 1;
01723 }
01724
01725 flp->uname = getUname(flp->fl_uid);
01726 flp->gname = getGname(flp->fl_gid);
01727 flp->langs = xstrdup("");
01728
01729 fl.totalFileSize += flp->fl_size;
01730
01731 if (! (flp->uname && flp->gname)) {
01732 rpmError(RPMERR_BADSPEC, _("Bad owner/group: %s\n"), diskURL);
01733 fl.processingFailed = 1;
01734 }
01735
01736 isSpec = 0;
01737 x++;
01738 }
01739 fl.fileListRecsUsed = x;
01740 freeSplitString(files);
01741
01742 if (! fl.processingFailed) {
01743 genCpioListAndHeader(&fl, &(spec->sourceCpioList),
01744 &(spec->sourceCpioCount), spec->sourceHeader, 1);
01745 }
01746
01747 freeStringBuf(sourceFiles);
01748 freeFileList(fl.fileList, fl.fileListRecsUsed);
01749 return fl.processingFailed;
01750 }
01751
01754 static StringBuf getOutputFrom(char *dir, char *argv[],
01755 const char *writePtr, int writeBytesLeft,
01756 int failNonZero)
01757 {
01758 int progPID;
01759 int toProg[2];
01760 int fromProg[2];
01761 int status;
01762 void *oldhandler;
01763 StringBuf readBuff;
01764 int done;
01765
01766 oldhandler = signal(SIGPIPE, SIG_IGN);
01767
01768 toProg[0] = toProg[1] = 0;
01769 pipe(toProg);
01770 fromProg[0] = fromProg[1] = 0;
01771 pipe(fromProg);
01772
01773 if (!(progPID = fork())) {
01774 close(toProg[1]);
01775 close(fromProg[0]);
01776
01777 dup2(toProg[0], STDIN_FILENO);
01778 dup2(fromProg[1], STDOUT_FILENO);
01779
01780 close(toProg[0]);
01781 close(fromProg[1]);
01782
01783 if (dir) {
01784 chdir(dir);
01785 }
01786
01787 execvp(argv[0], argv);
01788
01789 rpmError(RPMERR_EXEC, _("Couldn't exec %s: %s\n"),
01790 argv[0], strerror(errno));
01791 _exit(RPMERR_EXEC);
01792 }
01793 if (progPID < 0) {
01794 rpmError(RPMERR_FORK, _("Couldn't fork %s: %s\n"),
01795 argv[0], strerror(errno));
01796 return NULL;
01797 }
01798
01799 close(toProg[0]);
01800 close(fromProg[1]);
01801
01802
01803 fcntl(fromProg[0], F_SETFL, O_NONBLOCK);
01804 fcntl(toProg[1], F_SETFL, O_NONBLOCK);
01805
01806 readBuff = newStringBuf();
01807
01808 do {
01809 fd_set ibits, obits;
01810 struct timeval tv;
01811 int nfd, nbw, nbr;
01812 int rc;
01813
01814 done = 0;
01815 top:
01816
01817 FD_ZERO(&ibits);
01818 FD_ZERO(&obits);
01819 if (fromProg[0] >= 0) {
01820 FD_SET(fromProg[0], &ibits);
01821 }
01822 if (toProg[1] >= 0) {
01823 FD_SET(toProg[1], &obits);
01824 }
01825 tv.tv_sec = 1;
01826 tv.tv_usec = 0;
01827 nfd = ((fromProg[0] > toProg[1]) ? fromProg[0] : toProg[1]);
01828 if ((rc = select(nfd, &ibits, &obits, NULL, &tv)) < 0) {
01829 if (errno == EINTR)
01830 goto top;
01831 break;
01832 }
01833
01834
01835 if (toProg[1] >= 0 && FD_ISSET(toProg[1], &obits)) {
01836 if (writeBytesLeft) {
01837 if ((nbw = write(toProg[1], writePtr,
01838 (1024<writeBytesLeft) ? 1024 : writeBytesLeft)) < 0) {
01839 if (errno != EAGAIN) {
01840 perror("getOutputFrom()");
01841 exit(EXIT_FAILURE);
01842 }
01843 nbw = 0;
01844 }
01845 writeBytesLeft -= nbw;
01846 writePtr += nbw;
01847 } else if (toProg[1] >= 0) {
01848 close(toProg[1]);
01849 toProg[1] = -1;
01850 }
01851 }
01852
01853
01854 { char buf[BUFSIZ+1];
01855 while ((nbr = read(fromProg[0], buf, sizeof(buf)-1)) > 0) {
01856 buf[nbr] = '\0';
01857 appendStringBuf(readBuff, buf);
01858 }
01859 }
01860
01861
01862 done = (nbr == 0 || (nbr < 0 && errno != EAGAIN));
01863
01864 } while (!done);
01865
01866
01867 if (toProg[1] >= 0)
01868 close(toProg[1]);
01869 if (fromProg[0] >= 0)
01870 close(fromProg[0]);
01871 (void)signal(SIGPIPE, oldhandler);
01872
01873
01874 (void)waitpid(progPID, &status, 0);
01875 if (failNonZero && (!WIFEXITED(status) || WEXITSTATUS(status))) {
01876 rpmError(RPMERR_EXEC, _("%s failed\n"), argv[0]);
01877 return NULL;
01878 }
01879 if (writeBytesLeft) {
01880 rpmError(RPMERR_EXEC, _("failed to write all data to %s\n"), argv[0]);
01881 return NULL;
01882 }
01883 return readBuff;
01884 }
01885
01888 typedef struct {
01889 const char *msg;
01890 const char *argv[4];
01891 int ntag;
01892 int vtag;
01893 int ftag;
01894 int mask;
01895 int xor;
01896 } DepMsg_t;
01897
01900 DepMsg_t depMsgs[] = {
01901 { "Provides", { "%{__find_provides}", NULL, NULL, NULL },
01902 RPMTAG_PROVIDENAME, RPMTAG_PROVIDEVERSION, RPMTAG_PROVIDEFLAGS,
01903 0, -1 },
01904 { "PreReq", { NULL, NULL, NULL, NULL },
01905 RPMTAG_REQUIRENAME, RPMTAG_REQUIREVERSION, RPMTAG_REQUIREFLAGS,
01906 RPMSENSE_PREREQ, 0 },
01907 { "Requires(interp)", { NULL, "interp", NULL, NULL },
01908 -1, -1, RPMTAG_REQUIREFLAGS,
01909 _notpre(RPMSENSE_INTERP), 0 },
01910 { "Requires(rpmlib)", { NULL, "rpmlib", NULL, NULL },
01911 -1, -1, RPMTAG_REQUIREFLAGS,
01912 _notpre(RPMSENSE_RPMLIB), 0 },
01913 { "Requires(verify)", { NULL, "verify", NULL, NULL },
01914 -1, -1, RPMTAG_REQUIREFLAGS,
01915 RPMSENSE_SCRIPT_VERIFY, 0 },
01916 { "Requires(pre)", { NULL, "pre", NULL, NULL },
01917 -1, -1, RPMTAG_REQUIREFLAGS,
01918 _notpre(RPMSENSE_SCRIPT_PRE), 0 },
01919 { "Requires(post)", { NULL, "post", NULL, NULL },
01920 -1, -1, RPMTAG_REQUIREFLAGS,
01921 _notpre(RPMSENSE_SCRIPT_POST), 0 },
01922 { "Requires(preun)", { NULL, "preun", NULL, NULL },
01923 -1, -1, RPMTAG_REQUIREFLAGS,
01924 _notpre(RPMSENSE_SCRIPT_PREUN), 0 },
01925 { "Requires(postun)", { NULL, "postun", NULL, NULL },
01926 -1, -1, RPMTAG_REQUIREFLAGS,
01927 _notpre(RPMSENSE_SCRIPT_POSTUN), 0 },
01928 { "Requires", { "%{__find_requires}", NULL, NULL, NULL },
01929 -1, -1, RPMTAG_REQUIREFLAGS,
01930 RPMSENSE_PREREQ, RPMSENSE_PREREQ },
01931 { "Conflicts", { "%{__find_conflicts}", NULL, NULL, NULL },
01932 RPMTAG_CONFLICTNAME, RPMTAG_CONFLICTVERSION, RPMTAG_CONFLICTFLAGS,
01933 0, -1 },
01934 { "Obsoletes", { "%{__find_obsoletes}", NULL, NULL, NULL },
01935 RPMTAG_OBSOLETENAME, RPMTAG_OBSOLETEVERSION, RPMTAG_OBSOLETEFLAGS,
01936 0, -1 },
01937 { NULL, { NULL, NULL, NULL, NULL }, 0, 0, 0, 0, 0 }
01938 };
01939
01942 static int generateDepends(Spec spec, Package pkg,
01943 struct cpioFileMapping *cpioList, int cpioCount,
01944 int multiLib)
01945 {
01946 StringBuf writeBuf;
01947 int writeBytes;
01948 StringBuf readBuf;
01949 DepMsg_t *dm;
01950 char *myargv[4];
01951 int failnonzero = 0;
01952 int rc = 0;
01953
01954 if (cpioCount <= 0)
01955 return 0;
01956
01957 if (! (pkg->autoReq || pkg->autoProv))
01958 return 0;
01959
01960 writeBuf = newStringBuf();
01961 for (writeBytes = 0; cpioCount--; cpioList++) {
01962
01963 if (multiLib == 2) {
01964 if (!(cpioList->mapFlags & CPIO_MULTILIB))
01965 continue;
01966 cpioList->mapFlags &= ~CPIO_MULTILIB;
01967 }
01968
01969 writeBytes += strlen(cpioList->fsPath) + 1;
01970 appendLineStringBuf(writeBuf, cpioList->fsPath);
01971 }
01972
01973 for (dm = depMsgs; dm->msg != NULL; dm++) {
01974 int i, tag, tagflags;
01975
01976 tag = (dm->ftag > 0) ? dm->ftag : dm->ntag;
01977 tagflags = 0;
01978
01979 switch(tag) {
01980 case RPMTAG_PROVIDEFLAGS:
01981 if (!pkg->autoProv)
01982 continue;
01983 failnonzero = 1;
01984 tagflags = RPMSENSE_FIND_PROVIDES;
01985 break;
01986 case RPMTAG_REQUIREFLAGS:
01987 if (!pkg->autoReq)
01988 continue;
01989 failnonzero = 0;
01990 tagflags = RPMSENSE_FIND_REQUIRES;
01991 break;
01992 default:
01993 continue;
01994 break;
01995 }
01996
01997
01998 myargv[0] = (dm->argv[0] ? rpmExpand(dm->argv[0], NULL) : NULL);
01999
02000 if (!(myargv[0] && *myargv[0] != '%')) {
02001 free(myargv[0]);
02002 continue;
02003 }
02004
02005 rpmMessage(RPMMESS_NORMAL, _("Finding %s: (using %s)...\n"),
02006 dm->msg, myargv[0]);
02007
02008 #if 0
02009 if (*myargv[0] != '/') {
02010 free(myargv[0]);
02011 myargv[0] = NULL;
02012 continue;
02013 }
02014 #endif
02015
02016
02017 for (i = 1; i < 4; i++) {
02018 myargv[i] = dm->argv[i] ? rpmExpand(dm->argv[i], NULL) : NULL;
02019 }
02020
02021 readBuf = getOutputFrom(NULL, myargv,
02022 getStringBuf(writeBuf), writeBytes, failnonzero);
02023
02024
02025 for (i = 0; i < 4; i++) {
02026 if (myargv[i] == NULL) continue;
02027 free(myargv[i]);
02028 myargv[i] = NULL;
02029 }
02030
02031 if (readBuf == NULL) {
02032 rc = RPMERR_EXEC;
02033 rpmError(rc, _("Failed to find %s:\n"), dm->msg);
02034 break;
02035 }
02036
02037
02038 tagflags &= ~RPMSENSE_MULTILIB;
02039 if (multiLib > 1)
02040 tagflags |= RPMSENSE_MULTILIB;
02041 else
02042 tagflags &= ~RPMSENSE_MULTILIB;
02043 rc = parseRCPOT(spec, pkg, getStringBuf(readBuf), tag, 0, tagflags);
02044 freeStringBuf(readBuf);
02045
02046 if (rc) {
02047 rpmError(rc, _("Failed to find %s:\n"), dm->msg);
02048 break;
02049 }
02050 }
02051
02052 freeStringBuf(writeBuf);
02053 return rc;
02054 }
02055
02058 static void printDepMsg(DepMsg_t *dm, int count, const char **names,
02059 const char **versions, int *flags)
02060 {
02061 int hasVersions = (versions != NULL);
02062 int hasFlags = (flags != NULL);
02063 int bingo = 0;
02064 int i;
02065
02066 for (i = 0; i < count; i++, names++, versions++, flags++) {
02067 if (hasFlags && !((*flags & dm->mask) ^ dm->xor))
02068 continue;
02069 if (bingo == 0) {
02070 rpmMessage(RPMMESS_NORMAL, "%s:", dm->msg);
02071 bingo = 1;
02072 }
02073 rpmMessage(RPMMESS_NORMAL, " %s", *names);
02074
02075 if (hasFlags && isDependsMULTILIB(*flags))
02076 rpmMessage(RPMMESS_NORMAL, " (multilib)");
02077
02078 if (hasVersions && !(*versions != NULL && **versions != '\0'))
02079 continue;
02080 if (!(hasFlags && (*flags && RPMSENSE_SENSEMASK)))
02081 continue;
02082
02083 rpmMessage(RPMMESS_NORMAL, " ");
02084 if (*flags & RPMSENSE_LESS)
02085 rpmMessage(RPMMESS_NORMAL, "<");
02086 if (*flags & RPMSENSE_GREATER)
02087 rpmMessage(RPMMESS_NORMAL, ">");
02088 if (*flags & RPMSENSE_EQUAL)
02089 rpmMessage(RPMMESS_NORMAL, "=");
02090
02091 rpmMessage(RPMMESS_NORMAL, " %s", *versions);
02092 }
02093 if (bingo)
02094 rpmMessage(RPMMESS_NORMAL, "\n");
02095 }
02096
02099 static void printDeps(Header h)
02100 {
02101 const char **names = NULL;
02102 const char **versions = NULL;
02103 int *flags = NULL;
02104 DepMsg_t *dm;
02105 int type, count;
02106
02107 for (dm = depMsgs; dm->msg != NULL; dm++) {
02108 switch (dm->ntag) {
02109 case 0:
02110 FREE(names);
02111 break;
02112 case -1:
02113 break;
02114 default:
02115 FREE(names);
02116 if (!headerGetEntry(h, dm->ntag, &type, (void **) &names, &count))
02117 continue;
02118 break;
02119 }
02120 switch (dm->vtag) {
02121 case 0:
02122 FREE(versions);
02123 break;
02124 case -1:
02125 break;
02126 default:
02127 FREE(versions);
02128 headerGetEntry(h, dm->vtag, NULL, (void **) &versions, NULL);
02129 break;
02130 }
02131 switch (dm->ftag) {
02132 case 0:
02133 flags = NULL;
02134 break;
02135 case -1:
02136 break;
02137 default:
02138 headerGetEntry(h, dm->ftag, NULL, (void **) &flags, NULL);
02139 break;
02140 }
02141 printDepMsg(dm, count, names, versions, flags);
02142 }
02143 FREE(names);
02144 FREE(versions);
02145 }
02146
02147 int processBinaryFiles(Spec spec, int installSpecialDoc, int test)
02148 {
02149 Package pkg;
02150 int res = 0;
02151
02152 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
02153 const char *n, *v, *r;
02154 int rc;
02155
02156 if (pkg->fileList == NULL)
02157 continue;
02158
02159 headerNVR(pkg->header, &n, &v, &r);
02160 rpmMessage(RPMMESS_NORMAL, _("Processing files: %s-%s-%s\n"), n, v, r);
02161
02162 if ((rc = processPackageFiles(spec, pkg, installSpecialDoc, test)))
02163 res = rc;
02164
02165
02166
02167
02168
02169 if (headerGetEntry(pkg->header, RPMTAG_MULTILIBS, NULL, NULL, NULL)) {
02170 generateDepends(spec, pkg, pkg->cpioList, pkg->cpioCount, 1);
02171 generateDepends(spec, pkg, pkg->cpioList, pkg->cpioCount, 2);
02172 } else
02173 generateDepends(spec, pkg, pkg->cpioList, pkg->cpioCount, 0);
02174 printDeps(pkg->header);
02175
02176 }
02177
02178 return res;
02179 }