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
00025
00026
00027
00028
00029 #define SKIPWHITE(_x) {while(*(_x) && (xisspace(*_x) || *(_x) == ',')) (_x)++;}
00030 #define SKIPNONWHITE(_x){while(*(_x) &&!(xisspace(*_x) || *(_x) == ',')) (_x)++;}
00031
00032 #define MAXDOCDIR 1024
00033
00034
00035 extern int _noDirTokens;
00036
00037
00040 typedef enum specdFlags_e {
00041 SPECD_DEFFILEMODE = (1 << 0),
00042 SPECD_DEFDIRMODE = (1 << 1),
00043 SPECD_DEFUID = (1 << 2),
00044 SPECD_DEFGID = (1 << 3),
00045 SPECD_DEFVERIFY = (1 << 4),
00046
00047 SPECD_FILEMODE = (1 << 8),
00048 SPECD_DIRMODE = (1 << 9),
00049 SPECD_UID = (1 << 10),
00050 SPECD_GID = (1 << 11),
00051 SPECD_VERIFY = (1 << 12)
00052 } specdFlags;
00053
00056 typedef struct FileListRec_s {
00057 struct stat fl_st;
00058 #define fl_dev fl_st.st_dev
00059 #define fl_ino fl_st.st_ino
00060 #define fl_mode fl_st.st_mode
00061 #define fl_nlink fl_st.st_nlink
00062 #define fl_uid fl_st.st_uid
00063 #define fl_gid fl_st.st_gid
00064 #define fl_rdev fl_st.st_rdev
00065 #define fl_size fl_st.st_size
00066 #define fl_mtime fl_st.st_mtime
00067
00068 const char * diskURL;
00069 const char * fileURL;
00070 const char * uname;
00071 const char * gname;
00072 int flags;
00073 specdFlags specdFlags;
00074 int verifyFlags;
00075 const char *langs;
00076 } * FileListRec;
00077
00080 typedef struct AttrRec_s {
00081 const char * ar_fmodestr;
00082 const char * ar_dmodestr;
00083 const char * ar_user;
00084 const char * ar_group;
00085 mode_t ar_fmode;
00086 mode_t ar_dmode;
00087 } * AttrRec;
00088
00091 static int multiLib = 0;
00092
00096 typedef struct FileList_s {
00097 const char * buildRootURL;
00098 const char * prefix;
00099
00100 int fileCount;
00101 int totalFileSize;
00102 int processingFailed;
00103
00104 int passedSpecialDoc;
00105 int isSpecialDoc;
00106
00107 int noGlob;
00108 unsigned devtype;
00109 unsigned devmajor;
00110 int devminor;
00111
00112 int isDir;
00113 int inFtw;
00114 int currentFlags;
00115 specdFlags currentSpecdFlags;
00116 int currentVerifyFlags;
00117 struct AttrRec_s cur_ar;
00118 struct AttrRec_s def_ar;
00119 specdFlags defSpecdFlags;
00120 int defVerifyFlags;
00121 int nLangs;
00122 const char ** currentLangs;
00123
00124
00125
00126 const char * docDirs[MAXDOCDIR];
00127 int docDirCount;
00128
00129 FileListRec fileList;
00130 int fileListRecsAlloced;
00131 int fileListRecsUsed;
00132 } * FileList;
00133
00136 static void nullAttrRec( AttrRec ar)
00137 {
00138 ar->ar_fmodestr = NULL;
00139 ar->ar_dmodestr = NULL;
00140 ar->ar_user = NULL;
00141 ar->ar_group = NULL;
00142 ar->ar_fmode = 0;
00143 ar->ar_dmode = 0;
00144 }
00145
00148 static void freeAttrRec(AttrRec ar)
00149 {
00150 ar->ar_fmodestr = _free(ar->ar_fmodestr);
00151 ar->ar_dmodestr = _free(ar->ar_dmodestr);
00152 ar->ar_user = _free(ar->ar_user);
00153 ar->ar_group = _free(ar->ar_group);
00154
00155
00156 return;
00157
00158 }
00159
00162 static void dupAttrRec(const AttrRec oar, AttrRec nar)
00163
00164 {
00165 if (oar == nar)
00166 return;
00167 freeAttrRec(nar);
00168 nar->ar_fmodestr = (oar->ar_fmodestr ? xstrdup(oar->ar_fmodestr) : NULL);
00169 nar->ar_dmodestr = (oar->ar_dmodestr ? xstrdup(oar->ar_dmodestr) : NULL);
00170 nar->ar_user = (oar->ar_user ? xstrdup(oar->ar_user) : NULL);
00171 nar->ar_group = (oar->ar_group ? xstrdup(oar->ar_group) : NULL);
00172 nar->ar_fmode = oar->ar_fmode;
00173 nar->ar_dmode = oar->ar_dmode;
00174 }
00175
00176 #if 0
00177
00179 static void dumpAttrRec(const char * msg, AttrRec ar)
00180
00181 {
00182 if (msg)
00183 fprintf(stderr, "%s:\t", msg);
00184 fprintf(stderr, "(%s, %s, %s, %s)\n",
00185 ar->ar_fmodestr,
00186 ar->ar_user,
00187 ar->ar_group,
00188 ar->ar_dmodestr);
00189 }
00190 #endif
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00213 static char *strtokWithQuotes(char *s, char *delim)
00214 {
00215 static char *olds = NULL;
00216 char *token;
00217
00218 if (s == NULL) {
00219 s = olds;
00220 }
00221
00222
00223 s += strspn(s, delim);
00224 if (*s == '\0') {
00225 return NULL;
00226 }
00227
00228
00229 token = s;
00230 if (*token == '"') {
00231 token++;
00232
00233 s = strchr(token, '"');
00234 } else {
00235 s = strpbrk(token, delim);
00236 }
00237
00238
00239 if (s == NULL) {
00240
00241 olds = strchr(token, '\0');
00242 } else {
00243
00244 *s = '\0';
00245 olds = s+1;
00246 }
00247
00248 return token;
00249 }
00250
00253 static void timeCheck(int tc, Header h)
00254 {
00255 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00256 HFD_t hfd = headerFreeData;
00257 int * mtime;
00258 const char ** files;
00259 rpmTagType fnt;
00260 int count, x;
00261 time_t currentTime = time(NULL);
00262
00263 (void) hge(h, RPMTAG_OLDFILENAMES, &fnt, (void **) &files, &count);
00264 (void) hge(h, RPMTAG_FILEMTIMES, NULL, (void **) &mtime, NULL);
00265
00266 for (x = 0; x < count; x++) {
00267 if ((currentTime - mtime[x]) > tc)
00268 rpmMessage(RPMMESS_WARNING, _("TIMECHECK failure: %s\n"), files[x]);
00269 }
00270 files = hfd(files, fnt);
00271 }
00272
00275 typedef struct VFA {
00276 const char * attribute;
00277 int flag;
00278 } VFA_t;
00279
00282
00283 VFA_t verifyAttrs[] = {
00284 { "md5", RPMVERIFY_MD5 },
00285 { "size", RPMVERIFY_FILESIZE },
00286 { "link", RPMVERIFY_LINKTO },
00287 { "user", RPMVERIFY_USER },
00288 { "group", RPMVERIFY_GROUP },
00289 { "mtime", RPMVERIFY_MTIME },
00290 { "mode", RPMVERIFY_MODE },
00291 { "rdev", RPMVERIFY_RDEV },
00292 { NULL, 0 }
00293 };
00294
00295
00299 static int parseForVerify(char * buf, FileList fl)
00300
00301
00302
00303 {
00304 char *p, *pe, *q;
00305 const char *name;
00306 int *resultVerify;
00307 int negated;
00308 int verifyFlags;
00309 specdFlags * specdFlags;
00310
00311 if ((p = strstr(buf, (name = "%verify"))) != NULL) {
00312 resultVerify = &(fl->currentVerifyFlags);
00313 specdFlags = &fl->currentSpecdFlags;
00314 } else if ((p = strstr(buf, (name = "%defverify"))) != NULL) {
00315 resultVerify = &(fl->defVerifyFlags);
00316 specdFlags = &fl->defSpecdFlags;
00317 } else
00318 return 0;
00319
00320 for (pe = p; (pe-p) < strlen(name); pe++)
00321 *pe = ' ';
00322
00323 SKIPSPACE(pe);
00324
00325 if (*pe != '(') {
00326 rpmError(RPMERR_BADSPEC, _("Missing '(' in %s %s\n"), name, pe);
00327 fl->processingFailed = 1;
00328 return RPMERR_BADSPEC;
00329 }
00330
00331
00332 *pe++ = ' ';
00333 for (p = pe; *pe && *pe != ')'; pe++)
00334 {};
00335
00336 if (*pe == '\0') {
00337 rpmError(RPMERR_BADSPEC, _("Missing ')' in %s(%s\n"), name, p);
00338 fl->processingFailed = 1;
00339 return RPMERR_BADSPEC;
00340 }
00341
00342
00343 q = alloca((pe-p) + 1);
00344 strncpy(q, p, pe-p);
00345 q[pe-p] = '\0';
00346 while (p <= pe)
00347 *p++ = ' ';
00348
00349 negated = 0;
00350 verifyFlags = RPMVERIFY_NONE;
00351
00352 for (p = q; *p != '\0'; p = pe) {
00353 SKIPWHITE(p);
00354 if (*p == '\0')
00355 break;
00356 pe = p;
00357 SKIPNONWHITE(pe);
00358 if (*pe != '\0')
00359 *pe++ = '\0';
00360
00361 { VFA_t *vfa;
00362 for (vfa = verifyAttrs; vfa->attribute != NULL; vfa++) {
00363 if (strcmp(p, vfa->attribute))
00364 continue;
00365 verifyFlags |= vfa->flag;
00366 break;
00367 }
00368 if (vfa->attribute)
00369 continue;
00370 }
00371
00372 if (!strcmp(p, "not")) {
00373 negated ^= 1;
00374 } else {
00375 rpmError(RPMERR_BADSPEC, _("Invalid %s token: %s\n"), name, p);
00376 fl->processingFailed = 1;
00377 return RPMERR_BADSPEC;
00378 }
00379 }
00380
00381 *resultVerify = negated ? ~(verifyFlags) : verifyFlags;
00382 *specdFlags |= SPECD_VERIFY;
00383
00384 return 0;
00385 }
00386
00387 #define isAttrDefault(_ars) ((_ars)[0] == '-' && (_ars)[1] == '\0')
00388
00393 static int parseForDev(char * buf, FileList fl)
00394
00395
00396 {
00397 const char * name;
00398 const char * errstr = NULL;
00399 char *p, *pe, *q;
00400 int rc = RPMERR_BADSPEC;
00401
00402 if ((p = strstr(buf, (name = "%dev"))) == NULL)
00403 return 0;
00404
00405 for (pe = p; (pe-p) < strlen(name); pe++)
00406 *pe = ' ';
00407 SKIPSPACE(pe);
00408
00409 if (*pe != '(') {
00410 errstr = "'('";
00411 goto exit;
00412 }
00413
00414
00415 *pe++ = ' ';
00416 for (p = pe; *pe && *pe != ')'; pe++)
00417 {};
00418 if (*pe != ')') {
00419 errstr = "')'";
00420 goto exit;
00421 }
00422
00423
00424 q = alloca((pe-p) + 1);
00425 strncpy(q, p, pe-p);
00426 q[pe-p] = '\0';
00427 while (p <= pe)
00428 *p++ = ' ';
00429
00430 p = q; SKIPWHITE(p);
00431 pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
00432 if (*p == 'b')
00433 fl->devtype = 'b';
00434 else if (*p == 'c')
00435 fl->devtype = 'c';
00436 else {
00437 errstr = "devtype";
00438 goto exit;
00439 }
00440
00441 p = pe; SKIPWHITE(p);
00442 pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
00443 for (pe = p; *pe && xisdigit(*pe); pe++)
00444 {} ;
00445 if (*pe == '\0') {
00446 fl->devmajor = atoi(p);
00447
00448 if (!(fl->devmajor >= 0 && fl->devmajor < 256)) {
00449 errstr = "devmajor";
00450 goto exit;
00451 }
00452
00453 pe++;
00454 } else {
00455 errstr = "devmajor";
00456 goto exit;
00457 }
00458
00459 p = pe; SKIPWHITE(p);
00460 pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
00461 for (pe = p; *pe && xisdigit(*pe); pe++)
00462 {} ;
00463 if (*pe == '\0') {
00464 fl->devminor = atoi(p);
00465 if (!(fl->devminor >= 0 && fl->devminor < 256)) {
00466 errstr = "devminor";
00467 goto exit;
00468 }
00469 pe++;
00470 } else {
00471 errstr = "devminor";
00472 goto exit;
00473 }
00474
00475 fl->noGlob = 1;
00476
00477 rc = 0;
00478
00479 exit:
00480 if (rc) {
00481 rpmError(RPMERR_BADSPEC, _("Missing %s in %s %s\n"), errstr, name, p);
00482 fl->processingFailed = 1;
00483 }
00484 return rc;
00485 }
00486
00491 static int parseForAttr(char * buf, FileList fl)
00492
00493
00494
00495 {
00496 const char *name;
00497 char *p, *pe, *q;
00498 int x;
00499 struct AttrRec_s arbuf;
00500 AttrRec ar = &arbuf, ret_ar;
00501 specdFlags * specdFlags;
00502
00503 if ((p = strstr(buf, (name = "%attr"))) != NULL) {
00504 ret_ar = &(fl->cur_ar);
00505 specdFlags = &fl->currentSpecdFlags;
00506 } else if ((p = strstr(buf, (name = "%defattr"))) != NULL) {
00507 ret_ar = &(fl->def_ar);
00508 specdFlags = &fl->defSpecdFlags;
00509 } else
00510 return 0;
00511
00512 for (pe = p; (pe-p) < strlen(name); pe++)
00513 *pe = ' ';
00514
00515 SKIPSPACE(pe);
00516
00517 if (*pe != '(') {
00518 rpmError(RPMERR_BADSPEC, _("Missing '(' in %s %s\n"), name, pe);
00519 fl->processingFailed = 1;
00520 return RPMERR_BADSPEC;
00521 }
00522
00523
00524 *pe++ = ' ';
00525 for (p = pe; *pe && *pe != ')'; pe++)
00526 {};
00527
00528 if (ret_ar == &(fl->def_ar)) {
00529 q = pe;
00530 q++;
00531 SKIPSPACE(q);
00532 if (*q != '\0') {
00533 rpmError(RPMERR_BADSPEC,
00534 _("Non-white space follows %s(): %s\n"), name, q);
00535 fl->processingFailed = 1;
00536 return RPMERR_BADSPEC;
00537 }
00538 }
00539
00540
00541 q = alloca((pe-p) + 1);
00542 strncpy(q, p, pe-p);
00543 q[pe-p] = '\0';
00544 while (p <= pe)
00545 *p++ = ' ';
00546
00547 nullAttrRec(ar);
00548
00549 p = q; SKIPWHITE(p);
00550 if (*p != '\0') {
00551 pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
00552 ar->ar_fmodestr = p;
00553 p = pe; SKIPWHITE(p);
00554 }
00555 if (*p != '\0') {
00556 pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
00557 ar->ar_user = p;
00558 p = pe; SKIPWHITE(p);
00559 }
00560 if (*p != '\0') {
00561 pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
00562 ar->ar_group = p;
00563 p = pe; SKIPWHITE(p);
00564 }
00565 if (*p != '\0' && ret_ar == &(fl->def_ar)) {
00566 pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
00567 ar->ar_dmodestr = p;
00568 p = pe; SKIPWHITE(p);
00569 }
00570
00571 if (!(ar->ar_fmodestr && ar->ar_user && ar->ar_group) || *p != '\0') {
00572 rpmError(RPMERR_BADSPEC, _("Bad syntax: %s(%s)\n"), name, q);
00573 fl->processingFailed = 1;
00574 return RPMERR_BADSPEC;
00575 }
00576
00577
00578 if (ar->ar_fmodestr && !isAttrDefault(ar->ar_fmodestr)) {
00579 unsigned int ui;
00580 x = sscanf(ar->ar_fmodestr, "%o", &ui);
00581 if ((x == 0) || (ar->ar_fmode & ~MYALLPERMS)) {
00582 rpmError(RPMERR_BADSPEC, _("Bad mode spec: %s(%s)\n"), name, q);
00583 fl->processingFailed = 1;
00584 return RPMERR_BADSPEC;
00585 }
00586 ar->ar_fmode = ui;
00587 } else
00588 ar->ar_fmodestr = NULL;
00589
00590 if (ar->ar_dmodestr && !isAttrDefault(ar->ar_dmodestr)) {
00591 unsigned int ui;
00592 x = sscanf(ar->ar_dmodestr, "%o", &ui);
00593 if ((x == 0) || (ar->ar_dmode & ~MYALLPERMS)) {
00594 rpmError(RPMERR_BADSPEC, _("Bad dirmode spec: %s(%s)\n"), name, q);
00595 fl->processingFailed = 1;
00596 return RPMERR_BADSPEC;
00597 }
00598 ar->ar_dmode = ui;
00599 } else
00600 ar->ar_dmodestr = NULL;
00601
00602 if (!(ar->ar_user && !isAttrDefault(ar->ar_user)))
00603 ar->ar_user = NULL;
00604
00605 if (!(ar->ar_group && !isAttrDefault(ar->ar_group)))
00606 ar->ar_group = NULL;
00607
00608 dupAttrRec(ar, ret_ar);
00609
00610
00611 *specdFlags |= SPECD_UID | SPECD_GID | SPECD_FILEMODE | SPECD_DIRMODE;
00612
00613 return 0;
00614 }
00615
00619 static int parseForConfig(char * buf, FileList fl)
00620
00621
00622 {
00623 char *p, *pe, *q;
00624 const char *name;
00625
00626 if ((p = strstr(buf, (name = "%config"))) == NULL)
00627 return 0;
00628
00629 fl->currentFlags = RPMFILE_CONFIG;
00630
00631 for (pe = p; (pe-p) < strlen(name); pe++)
00632 *pe = ' ';
00633 SKIPSPACE(pe);
00634 if (*pe != '(')
00635 return 0;
00636
00637
00638 *pe++ = ' ';
00639 for (p = pe; *pe && *pe != ')'; pe++)
00640 {};
00641
00642 if (*pe == '\0') {
00643 rpmError(RPMERR_BADSPEC, _("Missing ')' in %s(%s\n"), name, p);
00644 fl->processingFailed = 1;
00645 return RPMERR_BADSPEC;
00646 }
00647
00648
00649 q = alloca((pe-p) + 1);
00650 strncpy(q, p, pe-p);
00651 q[pe-p] = '\0';
00652 while (p <= pe)
00653 *p++ = ' ';
00654
00655 for (p = q; *p != '\0'; p = pe) {
00656 SKIPWHITE(p);
00657 if (*p == '\0')
00658 break;
00659 pe = p;
00660 SKIPNONWHITE(pe);
00661 if (*pe != '\0')
00662 *pe++ = '\0';
00663 if (!strcmp(p, "missingok")) {
00664 fl->currentFlags |= RPMFILE_MISSINGOK;
00665 } else if (!strcmp(p, "noreplace")) {
00666 fl->currentFlags |= RPMFILE_NOREPLACE;
00667 } else {
00668 rpmError(RPMERR_BADSPEC, _("Invalid %s token: %s\n"), name, p);
00669 fl->processingFailed = 1;
00670 return RPMERR_BADSPEC;
00671 }
00672 }
00673
00674 return 0;
00675 }
00676
00679 static int langCmp(const void * ap, const void * bp)
00680 {
00681 return strcmp(*(const char **)ap, *(const char **)bp);
00682 }
00683
00687 static int parseForLang(char * buf, FileList fl)
00688
00689
00690 {
00691 char *p, *pe, *q;
00692 const char *name;
00693
00694 while ((p = strstr(buf, (name = "%lang"))) != NULL) {
00695
00696 for (pe = p; (pe-p) < strlen(name); pe++)
00697 *pe = ' ';
00698 SKIPSPACE(pe);
00699
00700 if (*pe != '(') {
00701 rpmError(RPMERR_BADSPEC, _("Missing '(' in %s %s\n"), name, pe);
00702 fl->processingFailed = 1;
00703 return RPMERR_BADSPEC;
00704 }
00705
00706
00707 *pe++ = ' ';
00708 for (pe = p; *pe && *pe != ')'; pe++)
00709 {};
00710
00711 if (*pe == '\0') {
00712 rpmError(RPMERR_BADSPEC, _("Missing ')' in %s(%s\n"), name, p);
00713 fl->processingFailed = 1;
00714 return RPMERR_BADSPEC;
00715 }
00716
00717
00718 q = alloca((pe-p) + 1);
00719 strncpy(q, p, pe-p);
00720 q[pe-p] = '\0';
00721 while (p <= pe)
00722 *p++ = ' ';
00723
00724
00725 for (p = q; *p != '\0'; p = pe) {
00726 char *newp;
00727 size_t np;
00728 int i;
00729
00730 SKIPWHITE(p);
00731 pe = p;
00732 SKIPNONWHITE(pe);
00733
00734 np = pe - p;
00735
00736
00737 if (np < 1 || (np == 1 && *p != 'C') || np >= 32) {
00738 rpmError(RPMERR_BADSPEC,
00739 _("Unusual locale length: \"%.*s\" in %%lang(%s)\n"),
00740 (int)np, p, q);
00741 fl->processingFailed = 1;
00742 return RPMERR_BADSPEC;
00743 }
00744
00745
00746 if (fl->currentLangs != NULL)
00747 for (i = 0; i < fl->nLangs; i++) {
00748 if (strncmp(fl->currentLangs[i], p, np))
00749 continue;
00750 rpmError(RPMERR_BADSPEC, _("Duplicate locale %.*s in %%lang(%s)\n"),
00751 (int)np, p, q);
00752 fl->processingFailed = 1;
00753 return RPMERR_BADSPEC;
00754 }
00755
00756
00757 fl->currentLangs = xrealloc(fl->currentLangs,
00758 (fl->nLangs + 1) * sizeof(*fl->currentLangs));
00759 newp = xmalloc( np+1 );
00760 strncpy(newp, p, np);
00761 newp[np] = '\0';
00762 fl->currentLangs[fl->nLangs++] = newp;
00763 if (*pe == ',') pe++;
00764 }
00765 }
00766
00767
00768 if (fl->currentLangs)
00769 qsort(fl->currentLangs, fl->nLangs, sizeof(*fl->currentLangs), langCmp);
00770
00771 return 0;
00772 }
00773
00776 static int parseForRegexLang(const char * fileName, char ** lang)
00777
00778 {
00779 static int initialized = 0;
00780 static int hasRegex = 0;
00781 static regex_t compiledPatt;
00782 static char buf[BUFSIZ];
00783 int x;
00784 regmatch_t matches[2];
00785 const char *s;
00786
00787 if (! initialized) {
00788 const char *patt = rpmExpand("%{_langpatt}", NULL);
00789 int rc = 0;
00790 if (!(patt && *patt != '%'))
00791 rc = 1;
00792 else if (regcomp(&compiledPatt, patt, REG_EXTENDED))
00793 rc = -1;
00794 patt = _free(patt);
00795 if (rc)
00796 return rc;
00797 hasRegex = 1;
00798 initialized = 1;
00799 }
00800
00801 memset(matches, 0, sizeof(matches));
00802 if (! hasRegex || regexec(&compiledPatt, fileName, 2, matches, REG_NOTEOL))
00803 return 1;
00804
00805
00806 s = fileName + matches[1].rm_eo - 1;
00807 x = matches[1].rm_eo - matches[1].rm_so;
00808 buf[x] = '\0';
00809 while (x) {
00810 buf[--x] = *s--;
00811 }
00812 if (lang)
00813 *lang = buf;
00814 return 0;
00815 }
00816
00819 static int parseForRegexMultiLib(const char *fileName)
00820 {
00821 static int initialized = 0;
00822 static int hasRegex = 0;
00823 static regex_t compiledPatt;
00824
00825 if (! initialized) {
00826 const char *patt;
00827 int rc = 0;
00828
00829 initialized = 1;
00830 patt = rpmExpand("%{_multilibpatt}", NULL);
00831 if (!(patt && *patt != '%'))
00832 rc = 1;
00833 else if (regcomp(&compiledPatt, patt, REG_EXTENDED | REG_NOSUB))
00834 rc = -1;
00835 patt = _free(patt);
00836 if (rc)
00837 return rc;
00838 hasRegex = 1;
00839 }
00840
00841 if (! hasRegex || regexec(&compiledPatt, fileName, 0, NULL, 0))
00842 return 1;
00843
00844 return 0;
00845 }
00846
00849
00850 VFA_t virtualFileAttributes[] = {
00851 { "%dir", 0 },
00852 { "%doc", RPMFILE_DOC },
00853 { "%ghost", RPMFILE_GHOST },
00854 { "%exclude", RPMFILE_EXCLUDE },
00855 { "%readme", RPMFILE_README },
00856 { "%license", RPMFILE_LICENSE },
00857 { "%multilib", 0 },
00858
00859 #if WHY_NOT
00860 { "%spec", RPMFILE_SPEC },
00861 { "%config", RPMFILE_CONFIG },
00862 { "%donotuse", RPMFILE_DONOTUSE },
00863 { "%missingok", RPMFILE_CONFIG|RPMFILE_MISSINGOK },
00864 { "%noreplace", RPMFILE_CONFIG|RPMFILE_NOREPLACE },
00865 #endif
00866
00867 { NULL, 0 }
00868 };
00869
00870
00874 static int parseForSimple(Spec spec, Package pkg, char * buf,
00875 FileList fl, const char ** fileName)
00876
00877
00878
00879
00880
00881 {
00882 char *s, *t;
00883 int res, specialDoc = 0;
00884 char specialDocBuf[BUFSIZ];
00885
00886 specialDocBuf[0] = '\0';
00887 *fileName = NULL;
00888 res = 0;
00889
00890 t = buf;
00891 while ((s = strtokWithQuotes(t, " \t\n")) != NULL) {
00892 t = NULL;
00893 if (!strcmp(s, "%docdir")) {
00894 s = strtokWithQuotes(NULL, " \t\n");
00895 if (fl->docDirCount == MAXDOCDIR) {
00896 rpmError(RPMERR_INTERNAL, _("Hit limit for %%docdir\n"));
00897 fl->processingFailed = 1;
00898 res = 1;
00899 }
00900 fl->docDirs[fl->docDirCount++] = xstrdup(s);
00901 if (strtokWithQuotes(NULL, " \t\n")) {
00902 rpmError(RPMERR_INTERNAL, _("Only one arg for %%docdir\n"));
00903 fl->processingFailed = 1;
00904 res = 1;
00905 }
00906 break;
00907 }
00908
00909
00910 { VFA_t *vfa;
00911 for (vfa = virtualFileAttributes; vfa->attribute != NULL; vfa++) {
00912 if (strcmp(s, vfa->attribute))
00913 continue;
00914 if (!vfa->flag) {
00915 if (!strcmp(s, "%dir"))
00916 fl->isDir = 1;
00917 else if (!strcmp(s, "%multilib"))
00918 fl->currentFlags |= multiLib;
00919 } else
00920 fl->currentFlags |= vfa->flag;
00921 break;
00922 }
00923
00924 if (vfa->attribute != NULL)
00925 continue;
00926 }
00927
00928 if (*fileName) {
00929
00930 rpmError(RPMERR_BADSPEC, _("Two files on one line: %s\n"),
00931 *fileName);
00932 fl->processingFailed = 1;
00933 res = 1;
00934 }
00935
00936 if (*s != '/') {
00937 if (fl->currentFlags & RPMFILE_DOC) {
00938 specialDoc = 1;
00939 strcat(specialDocBuf, " ");
00940 strcat(specialDocBuf, s);
00941 } else {
00942
00943 rpmError(RPMERR_BADSPEC,
00944 _("File must begin with \"/\": %s\n"), s);
00945 fl->processingFailed = 1;
00946 res = 1;
00947 }
00948 } else {
00949 *fileName = s;
00950 }
00951 }
00952
00953 if (specialDoc) {
00954 if (*fileName || (fl->currentFlags & ~(RPMFILE_DOC))) {
00955 rpmError(RPMERR_BADSPEC,
00956 _("Can't mix special %%doc with other forms: %s\n"),
00957 (*fileName ? *fileName : ""));
00958 fl->processingFailed = 1;
00959 res = 1;
00960 } else {
00961
00962 { const char *ddir, *n, *v;
00963
00964 (void) headerNVR(pkg->header, &n, &v, NULL);
00965
00966 ddir = rpmGetPath("%{_docdir}/", n, "-", v, NULL);
00967 strcpy(buf, ddir);
00968 ddir = _free(ddir);
00969 }
00970
00971
00972
00973 if (! fl->passedSpecialDoc) {
00974 pkg->specialDoc = newStringBuf();
00975 appendStringBuf(pkg->specialDoc, "DOCDIR=$RPM_BUILD_ROOT");
00976 appendLineStringBuf(pkg->specialDoc, buf);
00977 appendLineStringBuf(pkg->specialDoc, "export DOCDIR");
00978 appendLineStringBuf(pkg->specialDoc, "rm -rf $DOCDIR");
00979 appendLineStringBuf(pkg->specialDoc, MKDIR_P " $DOCDIR");
00980
00981
00982 *fileName = buf;
00983
00984 fl->passedSpecialDoc = 1;
00985 fl->isSpecialDoc = 1;
00986 }
00987
00988 appendStringBuf(pkg->specialDoc, "cp -pr ");
00989 appendStringBuf(pkg->specialDoc, specialDocBuf);
00990 appendLineStringBuf(pkg->specialDoc, " $DOCDIR");
00991 }
00992 }
00993
00994 return res;
00995 }
00996
00999 static int compareFileListRecs(const void * ap, const void * bp)
01000 {
01001 const char *a = ((FileListRec)ap)->fileURL;
01002 const char *b = ((FileListRec)bp)->fileURL;
01003 return strcmp(a, b);
01004 }
01005
01009 static int isDoc(FileList fl, const char * fileName)
01010 {
01011 int x = fl->docDirCount;
01012
01013 while (x--) {
01014 if (strstr(fileName, fl->docDirs[x]) == fileName)
01015 return 1;
01016 }
01017 return 0;
01018 }
01019
01025 static void checkHardLinks(FileList fl)
01026
01027 {
01028 char nlangs[BUFSIZ];
01029 FileListRec ilp, jlp;
01030 int i, j;
01031
01032 nlangs[0] = '\0';
01033 for (i = 0; i < fl->fileListRecsUsed; i++) {
01034 char *te;
01035
01036 ilp = fl->fileList + i;
01037 if (!(S_ISREG(ilp->fl_mode) && ilp->fl_nlink > 1))
01038 continue;
01039 if (ilp->flags & RPMFILE_SPECFILE)
01040 continue;
01041
01042 te = nlangs;
01043 *te = '\0';
01044 for (j = i + 1; j < fl->fileListRecsUsed; j++) {
01045 jlp = fl->fileList + j;
01046 if (!S_ISREG(jlp->fl_mode))
01047 continue;
01048 if (ilp->fl_nlink != jlp->fl_nlink)
01049 continue;
01050 if (ilp->fl_ino != jlp->fl_ino)
01051 continue;
01052 if (ilp->fl_dev != jlp->fl_dev)
01053 continue;
01054 if (!strcmp(ilp->langs, jlp->langs)) {
01055 jlp->flags |= RPMFILE_SPECFILE;
01056 continue;
01057 }
01058 if (te == nlangs)
01059 te = stpcpy(te, ilp->langs);
01060 *te++ = '|';
01061 te = stpcpy(te, jlp->langs);
01062 }
01063
01064
01065 if (te == nlangs)
01066 continue;
01067
01068 ilp->langs = _free(ilp->langs);
01069 ilp->langs = xstrdup(nlangs);
01070 for (j = i + 1; j < fl->fileListRecsUsed; j++) {
01071 jlp = fl->fileList + j;
01072 if (!S_ISREG(jlp->fl_mode))
01073 continue;
01074 if (ilp->fl_nlink != jlp->fl_nlink)
01075 continue;
01076 if (ilp->fl_ino != jlp->fl_ino)
01077 continue;
01078 if (ilp->fl_dev != jlp->fl_dev)
01079 continue;
01080 jlp->flags |= RPMFILE_SPECFILE;
01081 jlp->langs = _free(jlp->langs);
01082 jlp->langs = xstrdup(nlangs);
01083 }
01084 }
01085
01086 for (i = 0; i < fl->fileListRecsUsed; i++) {
01087 ilp = fl->fileList + i;
01088 ilp->flags &= ~RPMFILE_SPECFILE;
01089 }
01090 }
01091
01097 static void genCpioListAndHeader( FileList fl,
01098 TFI_t * cpioList, Header h, int isSrc)
01099
01100 {
01101 int _addDotSlash = !(isSrc || rpmExpandNumeric("%{_noPayloadPrefix}"));
01102 uint_32 multiLibMask = 0;
01103 int apathlen = 0;
01104 int dpathlen = 0;
01105 int skipLen = 0;
01106 FileListRec flp;
01107 char buf[BUFSIZ];
01108 int i;
01109
01110
01111 qsort(fl->fileList, fl->fileListRecsUsed,
01112 sizeof(*(fl->fileList)), compareFileListRecs);
01113
01114
01115 if (! isSrc) {
01116 skipLen = 1;
01117 if (fl->prefix)
01118 skipLen += strlen(fl->prefix);
01119 }
01120
01121 for (i = 0, flp = fl->fileList; i < fl->fileListRecsUsed; i++, flp++) {
01122 char *s;
01123
01124
01125 while (i < (fl->fileListRecsUsed - 1) &&
01126 !strcmp(flp->fileURL, flp[1].fileURL)) {
01127
01128
01129
01130 rpmMessage(RPMMESS_WARNING, _("File listed twice: %s\n"),
01131 flp->fileURL);
01132
01133
01134 flp[1].flags |= flp->flags;
01135
01136
01137 if (S_ISDIR(flp->fl_mode)) {
01138 if ((flp[1].specdFlags & (SPECD_DIRMODE | SPECD_DEFDIRMODE)) <
01139 (flp->specdFlags & (SPECD_DIRMODE | SPECD_DEFDIRMODE)))
01140 flp[1].fl_mode = flp->fl_mode;
01141 } else {
01142 if ((flp[1].specdFlags & (SPECD_FILEMODE | SPECD_DEFFILEMODE)) <
01143 (flp->specdFlags & (SPECD_FILEMODE | SPECD_DEFFILEMODE)))
01144 flp[1].fl_mode = flp->fl_mode;
01145 }
01146
01147
01148 if ((flp[1].specdFlags & (SPECD_UID | SPECD_DEFUID)) <
01149 (flp->specdFlags & (SPECD_UID | SPECD_DEFUID)))
01150 {
01151 flp[1].fl_uid = flp->fl_uid;
01152 flp[1].uname = flp->uname;
01153 }
01154
01155
01156 if ((flp[1].specdFlags & (SPECD_GID | SPECD_DEFGID)) <
01157 (flp->specdFlags & (SPECD_GID | SPECD_DEFGID)))
01158 {
01159 flp[1].fl_gid = flp->fl_gid;
01160 flp[1].gname = flp->gname;
01161 }
01162
01163
01164 if ((flp[1].specdFlags & (SPECD_VERIFY | SPECD_DEFVERIFY)) <
01165 (flp->specdFlags & (SPECD_VERIFY | SPECD_DEFVERIFY)))
01166 flp[1].verifyFlags = flp->verifyFlags;
01167
01168
01169
01170 flp++; i++;
01171 }
01172
01173
01174 if (flp->flags & RPMFILE_EXCLUDE) continue;
01175
01176
01177 apathlen += (strlen(flp->fileURL) - skipLen + (_addDotSlash ? 3 : 1));
01178
01179
01180 dpathlen += (strlen(flp->diskURL) + 2);
01181
01182 if (flp->flags & RPMFILE_MULTILIB_MASK)
01183 multiLibMask |=
01184 (1u << ((flp->flags & RPMFILE_MULTILIB_MASK))
01185 >> RPMFILE_MULTILIB_SHIFT);
01186
01187
01188
01189
01190
01191
01192 (void) headerAddOrAppendEntry(h, RPMTAG_OLDFILENAMES, RPM_STRING_ARRAY_TYPE,
01193 &(flp->fileURL), 1);
01194
01195 if (sizeof(flp->fl_size) != sizeof(uint_32)) {
01196 uint_32 psize = (uint_32)flp->fl_size;
01197 (void) headerAddOrAppendEntry(h, RPMTAG_FILESIZES, RPM_INT32_TYPE,
01198 &(psize), 1);
01199 } else {
01200 (void) headerAddOrAppendEntry(h, RPMTAG_FILESIZES, RPM_INT32_TYPE,
01201 &(flp->fl_size), 1);
01202 }
01203 (void) headerAddOrAppendEntry(h, RPMTAG_FILEUSERNAME, RPM_STRING_ARRAY_TYPE,
01204 &(flp->uname), 1);
01205 (void) headerAddOrAppendEntry(h, RPMTAG_FILEGROUPNAME, RPM_STRING_ARRAY_TYPE,
01206 &(flp->gname), 1);
01207 if (sizeof(flp->fl_mtime) != sizeof(uint_32)) {
01208 uint_32 mtime = (uint_32)flp->fl_mtime;
01209 (void) headerAddOrAppendEntry(h, RPMTAG_FILEMTIMES, RPM_INT32_TYPE,
01210 &(mtime), 1);
01211 } else {
01212 (void) headerAddOrAppendEntry(h, RPMTAG_FILEMTIMES, RPM_INT32_TYPE,
01213 &(flp->fl_mtime), 1);
01214 }
01215 if (sizeof(flp->fl_mode) != sizeof(uint_16)) {
01216 uint_16 pmode = (uint_16)flp->fl_mode;
01217 (void) headerAddOrAppendEntry(h, RPMTAG_FILEMODES, RPM_INT16_TYPE,
01218 &(pmode), 1);
01219 } else {
01220 (void) headerAddOrAppendEntry(h, RPMTAG_FILEMODES, RPM_INT16_TYPE,
01221 &(flp->fl_mode), 1);
01222 }
01223 if (sizeof(flp->fl_rdev) != sizeof(uint_16)) {
01224 uint_16 prdev = (uint_16)flp->fl_rdev;
01225 (void) headerAddOrAppendEntry(h, RPMTAG_FILERDEVS, RPM_INT16_TYPE,
01226 &(prdev), 1);
01227 } else {
01228 (void) headerAddOrAppendEntry(h, RPMTAG_FILERDEVS, RPM_INT16_TYPE,
01229 &(flp->fl_rdev), 1);
01230 }
01231 if (sizeof(flp->fl_dev) != sizeof(uint_32)) {
01232 uint_32 pdevice = (uint_32)flp->fl_dev;
01233 (void) headerAddOrAppendEntry(h, RPMTAG_FILEDEVICES, RPM_INT32_TYPE,
01234 &(pdevice), 1);
01235 } else {
01236 (void) headerAddOrAppendEntry(h, RPMTAG_FILEDEVICES, RPM_INT32_TYPE,
01237 &(flp->fl_dev), 1);
01238 }
01239
01240 if (sizeof(flp->fl_ino) != sizeof(uint_32)) {
01241 uint_32 ino = (uint_32)flp->fl_ino;
01242 (void) headerAddOrAppendEntry(h, RPMTAG_FILEINODES, RPM_INT32_TYPE,
01243 &(ino), 1);
01244 } else {
01245 (void) headerAddOrAppendEntry(h, RPMTAG_FILEINODES, RPM_INT32_TYPE,
01246 &(flp->fl_ino), 1);
01247 }
01248
01249 (void) headerAddOrAppendEntry(h, RPMTAG_FILELANGS, RPM_STRING_ARRAY_TYPE,
01250 &(flp->langs), 1);
01251
01252
01253
01254
01255
01256
01257
01258
01259 buf[0] = '\0';
01260 if (S_ISREG(flp->fl_mode))
01261 (void) mdfile(flp->diskURL, buf);
01262 s = buf;
01263 (void) headerAddOrAppendEntry(h, RPMTAG_FILEMD5S, RPM_STRING_ARRAY_TYPE,
01264 &s, 1);
01265
01266 buf[0] = '\0';
01267 if (S_ISLNK(flp->fl_mode)) {
01268 buf[Readlink(flp->diskURL, buf, BUFSIZ)] = '\0';
01269 if (fl->buildRootURL) {
01270 const char * buildRoot;
01271 (void) urlPath(fl->buildRootURL, &buildRoot);
01272
01273 if (buf[0] == '/' && strcmp(buildRoot, "/") &&
01274 !strncmp(buf, buildRoot, strlen(buildRoot))) {
01275 rpmError(RPMERR_BADSPEC,
01276 _("Symlink points to BuildRoot: %s -> %s\n"),
01277 flp->fileURL, buf);
01278 fl->processingFailed = 1;
01279 }
01280 }
01281 }
01282 s = buf;
01283 (void) headerAddOrAppendEntry(h, RPMTAG_FILELINKTOS, RPM_STRING_ARRAY_TYPE,
01284 &s, 1);
01285
01286 if (flp->flags & RPMFILE_GHOST) {
01287 flp->verifyFlags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE |
01288 RPMVERIFY_LINKTO | RPMVERIFY_MTIME);
01289 }
01290 (void) headerAddOrAppendEntry(h, RPMTAG_FILEVERIFYFLAGS, RPM_INT32_TYPE,
01291 &(flp->verifyFlags), 1);
01292
01293 if (!isSrc && isDoc(fl, flp->fileURL))
01294 flp->flags |= RPMFILE_DOC;
01295
01296 if (S_ISDIR(flp->fl_mode))
01297 flp->flags &= ~(RPMFILE_CONFIG|RPMFILE_DOC);
01298
01299 (void) headerAddOrAppendEntry(h, RPMTAG_FILEFLAGS, RPM_INT32_TYPE,
01300 &(flp->flags), 1);
01301
01302 }
01303 (void) headerAddEntry(h, RPMTAG_SIZE, RPM_INT32_TYPE,
01304 &(fl->totalFileSize), 1);
01305
01306
01307
01308
01309
01310 if (multiLibMask)
01311 (void) headerAddEntry(h, RPMTAG_MULTILIBS, RPM_INT32_TYPE,
01312 &multiLibMask, 1);
01313
01314 if (_addDotSlash)
01315 (void) rpmlibNeedsFeature(h, "PayloadFilesHavePrefix", "4.0-1");
01316
01317
01318 if (_noDirTokens)
01319 expandFilelist(h);
01320 else {
01321 compressFilelist(h);
01322
01323 (void) rpmlibNeedsFeature(h, "CompressedFileNames", "3.0.4-1");
01324 }
01325
01326 { TFI_t fi = xcalloc(sizeof(*fi), 1);
01327 char * a, * d;
01328
01329 fi->type = TR_ADDED;
01330 loadFi(h, fi);
01331 fi->dnl = _free(fi->dnl);
01332 fi->bnl = _free(fi->bnl);
01333
01334 fi->dnl = xmalloc(fi->fc * sizeof(*fi->dnl) + dpathlen);
01335 d = (char *)(fi->dnl + fi->fc);
01336 *d = '\0';
01337
01338 fi->bnl = xmalloc(fi->fc * (sizeof(*fi->bnl) + sizeof(*fi->dil)));
01339 fi->dil = (int *)(fi->bnl + fi->fc);
01340
01341 fi->apath = xmalloc(fi->fc * sizeof(*fi->apath) + apathlen);
01342 a = (char *)(fi->apath + fi->fc);
01343 *a = '\0';
01344
01345 fi->actions = xcalloc(sizeof(*fi->actions), fi->fc);
01346 fi->fmapflags = xcalloc(sizeof(*fi->fmapflags), fi->fc);
01347 fi->astriplen = 0;
01348 if (fl->buildRootURL)
01349 fi->astriplen = strlen(fl->buildRootURL);
01350 fi->striplen = 0;
01351 fi->fuser = NULL;
01352 fi->fuids = xcalloc(sizeof(*fi->fuids), fi->fc);
01353 fi->fgroup = NULL;
01354 fi->fgids = xcalloc(sizeof(*fi->fgids), fi->fc);
01355
01356
01357 for (i = 0, flp = fl->fileList; i < fi->fc; i++, flp++) {
01358 char * b;
01359
01360
01361 while (((flp - fl->fileList) < (fl->fileListRecsUsed - 1)) &&
01362 !strcmp(flp->fileURL, flp[1].fileURL))
01363 flp++;
01364
01365
01366 fi->dil[i] = i;
01367 fi->dnl[fi->dil[i]] = d;
01368 d = stpcpy(d, flp->diskURL);
01369
01370
01371 for (b = d; b > fi->dnl[fi->dil[i]] && *b != '/'; b--)
01372 b[1] = b[0];
01373 b++;
01374 *b++ = '\0';
01375 fi->bnl[i] = b;
01376 d += 2;
01377
01378
01379
01380 fi->apath[i] = a;
01381
01382 if (_addDotSlash) a = stpcpy(a, "./");
01383 a = stpcpy(a, (flp->fileURL + skipLen));
01384 a++;
01385
01386 if (flp->flags & RPMFILE_GHOST) {
01387 fi->actions[i] = FA_SKIP;
01388 continue;
01389 }
01390 fi->actions[i] = FA_COPYOUT;
01391 fi->fuids[i] = getUidS(flp->uname);
01392 fi->fgids[i] = getGidS(flp->gname);
01393 if (fi->fuids[i] == (uid_t)-1) fi->fuids[i] = 0;
01394 if (fi->fgids[i] == (gid_t)-1) fi->fgids[i] = 0;
01395 fi->fmapflags[i] = CPIO_MAP_PATH |
01396 CPIO_MAP_TYPE | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
01397 if (isSrc)
01398 fi->fmapflags[i] |= CPIO_FOLLOW_SYMLINKS;
01399 if (flp->flags & RPMFILE_MULTILIB_MASK)
01400 fi->fmapflags[i] |= CPIO_MULTILIB;
01401
01402 }
01403 if (cpioList)
01404 *cpioList = fi;
01405 else
01406 fi = _free(fi);
01407 }
01408 }
01409
01412 static FileListRec freeFileList( FileListRec fileList,
01413 int count)
01414
01415 {
01416 while (count--) {
01417 fileList[count].diskURL = _free(fileList[count].diskURL);
01418 fileList[count].fileURL = _free(fileList[count].fileURL);
01419 fileList[count].langs = _free(fileList[count].langs);
01420 }
01421 fileList = _free(fileList);
01422 return NULL;
01423 }
01424
01428 static int addFile(FileList fl, const char * diskURL, struct stat * statp)
01429
01430
01431
01432 {
01433 const char *fileURL = diskURL;
01434 struct stat statbuf;
01435 mode_t fileMode;
01436 uid_t fileUid;
01437 gid_t fileGid;
01438 const char *fileUname;
01439 const char *fileGname;
01440 char *lang;
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453 { const char *fileName;
01454 (void) urlPath(fileURL, &fileName);
01455 if (fl->buildRootURL && strcmp(fl->buildRootURL, "/"))
01456 fileURL += strlen(fl->buildRootURL);
01457 }
01458
01459
01460 if (*fileURL == '\0')
01461 fileURL = "/";
01462
01463
01464 if (!fl->inFtw && fl->prefix) {
01465 const char *prefixTest;
01466 const char *prefixPtr = fl->prefix;
01467
01468 (void) urlPath(fileURL, &prefixTest);
01469 while (*prefixPtr && *prefixTest && (*prefixTest == *prefixPtr)) {
01470 prefixPtr++;
01471 prefixTest++;
01472 }
01473 if (*prefixPtr || (*prefixTest && *prefixTest != '/')) {
01474 rpmError(RPMERR_BADSPEC, _("File doesn't match prefix (%s): %s\n"),
01475 fl->prefix, fileURL);
01476 fl->processingFailed = 1;
01477 return RPMERR_BADSPEC;
01478 }
01479 }
01480
01481 if (statp == NULL) {
01482 statp = &statbuf;
01483 memset(statp, 0, sizeof(*statp));
01484 if (fl->devtype) {
01485 time_t now = time(NULL);
01486
01487
01488 statp->st_nlink = 1;
01489 statp->st_rdev =
01490 ((fl->devmajor & 0xff) << 8) | (fl->devminor & 0xff);
01491 statp->st_dev = statp->st_rdev;
01492 statp->st_mode = (fl->devtype == 'b' ? S_IFBLK : S_IFCHR);
01493 statp->st_mode |= (fl->cur_ar.ar_fmode & 0777);
01494 statp->st_atime = now;
01495 statp->st_mtime = now;
01496 statp->st_ctime = now;
01497 } else if (Lstat(diskURL, statp)) {
01498 rpmError(RPMERR_BADSPEC, _("File not found: %s\n"), diskURL);
01499 fl->processingFailed = 1;
01500 return RPMERR_BADSPEC;
01501 }
01502 }
01503
01504 if ((! fl->isDir) && S_ISDIR(statp->st_mode)) {
01505
01506
01507
01508
01509 fl->inFtw = 1;
01510 fl->isDir = 1;
01511 (void) myftw(diskURL, 16, (myftwFunc) addFile, fl);
01512 fl->isDir = 0;
01513 fl->inFtw = 0;
01514 return 0;
01515 }
01516
01517 fileMode = statp->st_mode;
01518 fileUid = statp->st_uid;
01519 fileGid = statp->st_gid;
01520
01521 if (S_ISDIR(fileMode) && fl->cur_ar.ar_dmodestr) {
01522 fileMode &= S_IFMT;
01523 fileMode |= fl->cur_ar.ar_dmode;
01524 } else if (fl->cur_ar.ar_fmodestr != NULL) {
01525 fileMode &= S_IFMT;
01526 fileMode |= fl->cur_ar.ar_fmode;
01527 }
01528 if (fl->cur_ar.ar_user) {
01529 fileUname = getUnameS(fl->cur_ar.ar_user);
01530 } else {
01531 fileUname = getUname(fileUid);
01532 }
01533 if (fl->cur_ar.ar_group) {
01534 fileGname = getGnameS(fl->cur_ar.ar_group);
01535 } else {
01536 fileGname = getGname(fileGid);
01537 }
01538
01539 #if 0
01540 if (! (fileUname && fileGname)) {
01541 rpmError(RPMERR_BADSPEC, _("Bad owner/group: %s\n"), diskName);
01542 fl->processingFailed = 1;
01543 return RPMERR_BADSPEC;
01544 }
01545 #else
01546
01547 if (fileUname == NULL)
01548 fileUname = getUname(getuid());
01549 if (fileGname == NULL)
01550 fileGname = getGname(getgid());
01551 #endif
01552
01553 rpmMessage(RPMMESS_DEBUG, _("File %4d: %07o %s.%s\t %s\n"), fl->fileCount,
01554 (unsigned)fileMode, fileUname, fileGname, fileURL);
01555
01556
01557 if (fl->fileListRecsUsed == fl->fileListRecsAlloced) {
01558 fl->fileListRecsAlloced += 128;
01559 fl->fileList = xrealloc(fl->fileList,
01560 fl->fileListRecsAlloced * sizeof(*(fl->fileList)));
01561 }
01562
01563 { FileListRec flp = &fl->fileList[fl->fileListRecsUsed];
01564 int i;
01565
01566 flp->fl_st = *statp;
01567 flp->fl_mode = fileMode;
01568 flp->fl_uid = fileUid;
01569 flp->fl_gid = fileGid;
01570
01571 flp->fileURL = xstrdup(fileURL);
01572 flp->diskURL = xstrdup(diskURL);
01573 flp->uname = fileUname;
01574 flp->gname = fileGname;
01575
01576 if (fl->currentLangs && fl->nLangs > 0) {
01577 char * ncl;
01578 size_t nl = 0;
01579
01580 for (i = 0; i < fl->nLangs; i++)
01581 nl += strlen(fl->currentLangs[i]) + 1;
01582
01583 flp->langs = ncl = xmalloc(nl);
01584 for (i = 0; i < fl->nLangs; i++) {
01585 const char *ocl;
01586 if (i) *ncl++ = '|';
01587 for (ocl = fl->currentLangs[i]; *ocl != '\0'; ocl++)
01588 *ncl++ = *ocl;
01589 *ncl = '\0';
01590 }
01591 } else if (! parseForRegexLang(fileURL, &lang)) {
01592 flp->langs = xstrdup(lang);
01593 } else {
01594 flp->langs = xstrdup("");
01595 }
01596
01597 flp->flags = fl->currentFlags;
01598 flp->specdFlags = fl->currentSpecdFlags;
01599 flp->verifyFlags = fl->currentVerifyFlags;
01600
01601 if (multiLib
01602 && !(flp->flags & RPMFILE_MULTILIB_MASK)
01603 && !parseForRegexMultiLib(fileURL))
01604 flp->flags |= multiLib;
01605
01606
01607
01608 if (S_ISREG(flp->fl_mode) && flp->fl_nlink > 1) {
01609 FileListRec ilp;
01610 for (i = 0; i < fl->fileListRecsUsed; i++) {
01611 ilp = fl->fileList + i;
01612 if (!S_ISREG(ilp->fl_mode))
01613 continue;
01614 if (flp->fl_nlink != ilp->fl_nlink)
01615 continue;
01616 if (flp->fl_ino != ilp->fl_ino)
01617 continue;
01618 if (flp->fl_dev != ilp->fl_dev)
01619 continue;
01620 break;
01621 }
01622 } else
01623 i = fl->fileListRecsUsed;
01624
01625 if (S_ISREG(flp->fl_mode) && i >= fl->fileListRecsUsed)
01626 fl->totalFileSize += flp->fl_size;
01627 }
01628
01629 fl->fileListRecsUsed++;
01630 fl->fileCount++;
01631
01632 return 0;
01633 }
01634
01638 static int processBinaryFile( Package pkg, FileList fl,
01639 const char * fileURL)
01640
01641
01642
01643 {
01644 int doGlob;
01645 const char *diskURL = NULL;
01646 int rc = 0;
01647
01648 doGlob = myGlobPatternP(fileURL);
01649
01650
01651 { const char * fileName;
01652 (void) urlPath(fileURL, &fileName);
01653 if (*fileName != '/') {
01654 rpmError(RPMERR_BADSPEC, _("File needs leading \"/\": %s\n"),
01655 fileName);
01656 rc = 1;
01657 goto exit;
01658 }
01659 }
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669 diskURL = rpmGenPath(fl->buildRootURL, NULL, fileURL);
01670
01671 if (doGlob) {
01672 const char ** argv = NULL;
01673 int argc = 0;
01674 int i;
01675
01676 if (fl->noGlob) {
01677 rpmError(RPMERR_BADSPEC, _("Glob not permitted: %s\n"),
01678 diskURL);
01679 rc = 1;
01680 goto exit;
01681 }
01682
01683 rc = rpmGlob(diskURL, &argc, &argv);
01684 if (rc == 0 && argc >= 1 && !myGlobPatternP(argv[0])) {
01685 for (i = 0; i < argc; i++) {
01686 rc = addFile(fl, argv[i], NULL);
01687 argv[i] = _free(argv[i]);
01688 }
01689 argv = _free(argv);
01690 } else {
01691 rpmError(RPMERR_BADSPEC, _("File not found by glob: %s\n"),
01692 diskURL);
01693 rc = 1;
01694 }
01695 } else {
01696 rc = addFile(fl, diskURL, NULL);
01697 }
01698
01699 exit:
01700 diskURL = _free(diskURL);
01701 if (rc)
01702 fl->processingFailed = 1;
01703 return rc;
01704 }
01705
01708 static int processPackageFiles(Spec spec, Package pkg,
01709 int installSpecialDoc, int test)
01710
01711
01712 {
01713 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
01714 struct FileList_s fl;
01715 char *s, **files, **fp;
01716 const char *fileName;
01717 char buf[BUFSIZ];
01718 struct AttrRec_s arbuf;
01719 AttrRec specialDocAttrRec = &arbuf;
01720 char *specialDoc = NULL;
01721
01722 #ifdef MULTILIB
01723 multiLib = rpmExpandNumeric("%{_multilibno}");
01724 if (multiLib)
01725 multiLib = RPMFILE_MULTILIB(multiLib);
01726 #endif
01727
01728 nullAttrRec(specialDocAttrRec);
01729 pkg->cpioList = NULL;
01730
01731 if (pkg->fileFile) {
01732 const char *ffn;
01733 FILE * f;
01734 FD_t fd;
01735
01736
01737 if (*pkg->fileFile == '/') {
01738 ffn = rpmGetPath(pkg->fileFile, NULL);
01739 } else {
01740
01741 ffn = rpmGetPath("%{_builddir}/",
01742 (spec->buildSubdir ? spec->buildSubdir : "") ,
01743 "/", pkg->fileFile, NULL);
01744 }
01745 fd = Fopen(ffn, "r.fpio");
01746
01747 if (fd == NULL || Ferror(fd)) {
01748 rpmError(RPMERR_BADFILENAME,
01749 _("Could not open %%files file %s: %s\n"),
01750 ffn, Fstrerror(fd));
01751 return RPMERR_BADFILENAME;
01752 }
01753 ffn = _free(ffn);
01754
01755 f = fdGetFp(fd);
01756 if (f != NULL)
01757 while (fgets(buf, sizeof(buf), f)) {
01758 handleComments(buf);
01759 if (expandMacros(spec, spec->macros, buf, sizeof(buf))) {
01760 rpmError(RPMERR_BADSPEC, _("line: %s\n"), buf);
01761 return RPMERR_BADSPEC;
01762 }
01763 appendStringBuf(pkg->fileList, buf);
01764 }
01765 (void) Fclose(fd);
01766 }
01767
01768
01769 memset(&fl, 0, sizeof(fl));
01770
01771
01772 fl.buildRootURL = rpmGenPath(spec->rootURL, spec->buildRootURL, NULL);
01773
01774 if (hge(pkg->header, RPMTAG_DEFAULTPREFIX, NULL, (void **)&fl.prefix, NULL))
01775 fl.prefix = xstrdup(fl.prefix);
01776 else
01777 fl.prefix = NULL;
01778
01779 fl.fileCount = 0;
01780 fl.totalFileSize = 0;
01781 fl.processingFailed = 0;
01782
01783 fl.passedSpecialDoc = 0;
01784 fl.isSpecialDoc = 0;
01785
01786 fl.isDir = 0;
01787 fl.inFtw = 0;
01788 fl.currentFlags = 0;
01789 fl.currentVerifyFlags = 0;
01790
01791 fl.noGlob = 0;
01792 fl.devtype = 0;
01793 fl.devmajor = 0;
01794 fl.devminor = 0;
01795
01796 nullAttrRec(&fl.cur_ar);
01797 nullAttrRec(&fl.def_ar);
01798
01799 fl.defVerifyFlags = RPMVERIFY_ALL;
01800 fl.nLangs = 0;
01801 fl.currentLangs = NULL;
01802
01803 fl.currentSpecdFlags = 0;
01804 fl.defSpecdFlags = 0;
01805
01806 fl.docDirCount = 0;
01807 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/doc");
01808 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/man");
01809 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/info");
01810 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/X11R6/man");
01811 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/share/doc");
01812 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/share/man");
01813 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/share/info");
01814 fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_docdir}", NULL);
01815 fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_mandir}", NULL);
01816 fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_infodir}", NULL);
01817
01818 fl.fileList = NULL;
01819 fl.fileListRecsAlloced = 0;
01820 fl.fileListRecsUsed = 0;
01821
01822 s = getStringBuf(pkg->fileList);
01823 files = splitString(s, strlen(s), '\n');
01824
01825 for (fp = files; *fp != NULL; fp++) {
01826 s = *fp;
01827 SKIPSPACE(s);
01828 if (*s == '\0')
01829 continue;
01830 fileName = NULL;
01831
01832 strcpy(buf, s);
01833
01834
01835
01836 fl.isDir = 0;
01837 fl.inFtw = 0;
01838 fl.currentFlags = 0;
01839
01840 fl.currentSpecdFlags = ((unsigned)fl.defSpecdFlags) >> 8;
01841 fl.currentVerifyFlags = fl.defVerifyFlags;
01842 fl.isSpecialDoc = 0;
01843
01844 fl.noGlob = 0;
01845 fl.devtype = 0;
01846 fl.devmajor = 0;
01847 fl.devminor = 0;
01848
01849
01850 if (fl.currentLangs) {
01851 int i;
01852 for (i = 0; i < fl.nLangs; i++)
01853
01854 fl.currentLangs[i] = _free(fl.currentLangs[i]);
01855
01856 fl.currentLangs = _free(fl.currentLangs);
01857 }
01858 fl.nLangs = 0;
01859
01860 dupAttrRec(&fl.def_ar, &fl.cur_ar);
01861
01862
01863 if (parseForVerify(buf, &fl))
01864 continue;
01865 if (parseForAttr(buf, &fl))
01866 continue;
01867 if (parseForDev(buf, &fl))
01868 continue;
01869 if (parseForConfig(buf, &fl))
01870 continue;
01871 if (parseForLang(buf, &fl))
01872 continue;
01873
01874 if (parseForSimple(spec, pkg, buf, &fl, &fileName))
01875
01876 continue;
01877
01878 if (fileName == NULL)
01879 continue;
01880
01881 if (fl.isSpecialDoc) {
01882
01883 specialDoc = _free(specialDoc);
01884 specialDoc = xstrdup(fileName);
01885 dupAttrRec(&fl.cur_ar, specialDocAttrRec);
01886 } else {
01887
01888 (void) processBinaryFile(pkg, &fl, fileName);
01889
01890 }
01891 }
01892
01893
01894 if (specialDoc) {
01895 if (installSpecialDoc) {
01896 (void) doScript(spec, RPMBUILD_STRINGBUF, "%doc", pkg->specialDoc, test);
01897 }
01898
01899
01900 fl.isDir = 0;
01901 fl.inFtw = 0;
01902 fl.currentFlags = 0;
01903 fl.currentVerifyFlags = 0;
01904
01905 fl.noGlob = 0;
01906 fl.devtype = 0;
01907 fl.devmajor = 0;
01908 fl.devminor = 0;
01909
01910
01911 if (fl.currentLangs) {
01912 int i;
01913 for (i = 0; i < fl.nLangs; i++)
01914
01915 fl.currentLangs[i] = _free(fl.currentLangs[i]);
01916
01917 fl.currentLangs = _free(fl.currentLangs);
01918 }
01919 fl.nLangs = 0;
01920
01921 dupAttrRec(specialDocAttrRec, &fl.cur_ar);
01922 freeAttrRec(specialDocAttrRec);
01923
01924
01925 (void) processBinaryFile(pkg, &fl, specialDoc);
01926
01927
01928 specialDoc = _free(specialDoc);
01929 }
01930
01931 freeSplitString(files);
01932
01933 if (fl.processingFailed)
01934 goto exit;
01935
01936
01937 checkHardLinks(&fl);
01938
01939 genCpioListAndHeader(&fl, (TFI_t *)&pkg->cpioList, pkg->header, 0);
01940
01941 if (spec->timeCheck)
01942 timeCheck(spec->timeCheck, pkg->header);
01943
01944 exit:
01945 fl.buildRootURL = _free(fl.buildRootURL);
01946 fl.prefix = _free(fl.prefix);
01947
01948 freeAttrRec(&fl.cur_ar);
01949 freeAttrRec(&fl.def_ar);
01950
01951 if (fl.currentLangs) {
01952 int i;
01953 for (i = 0; i < fl.nLangs; i++)
01954
01955 fl.currentLangs[i] = _free(fl.currentLangs[i]);
01956
01957 fl.currentLangs = _free(fl.currentLangs);
01958 }
01959
01960 fl.fileList = freeFileList(fl.fileList, fl.fileListRecsUsed);
01961 while (fl.docDirCount--)
01962 fl.docDirs[fl.docDirCount] = _free(fl.docDirs[fl.docDirCount]);
01963 return fl.processingFailed;
01964 }
01965
01966 void initSourceHeader(Spec spec)
01967 {
01968 HeaderIterator hi;
01969 int_32 tag, type, count;
01970 const void * ptr;
01971
01972 spec->sourceHeader = headerNew();
01973
01974 for (hi = headerInitIterator(spec->packages->header);
01975 headerNextIterator(hi, &tag, &type, &ptr, &count);
01976 ptr = headerFreeData(ptr, type))
01977 {
01978 switch (tag) {
01979 case RPMTAG_NAME:
01980 case RPMTAG_VERSION:
01981 case RPMTAG_RELEASE:
01982 case RPMTAG_EPOCH:
01983 case RPMTAG_SUMMARY:
01984 case RPMTAG_DESCRIPTION:
01985 case RPMTAG_PACKAGER:
01986 case RPMTAG_DISTRIBUTION:
01987 case RPMTAG_DISTURL:
01988 case RPMTAG_VENDOR:
01989 case RPMTAG_LICENSE:
01990 case RPMTAG_GROUP:
01991 case RPMTAG_OS:
01992 case RPMTAG_ARCH:
01993 case RPMTAG_CHANGELOGTIME:
01994 case RPMTAG_CHANGELOGNAME:
01995 case RPMTAG_CHANGELOGTEXT:
01996 case RPMTAG_URL:
01997 case HEADER_I18NTABLE:
01998 if (ptr)
01999 (void)headerAddEntry(spec->sourceHeader, tag, type, ptr, count);
02000 break;
02001 default:
02002
02003 break;
02004 }
02005 }
02006 hi = headerFreeIterator(hi);
02007
02008
02009 for (hi = headerInitIterator(spec->buildRestrictions);
02010 headerNextIterator(hi, &tag, &type, &ptr, &count);
02011 ptr = headerFreeData(ptr, type))
02012 {
02013 if (ptr)
02014 (void) headerAddEntry(spec->sourceHeader, tag, type, ptr, count);
02015 }
02016 hi = headerFreeIterator(hi);
02017
02018 if (spec->BANames && spec->BACount > 0) {
02019 (void) headerAddEntry(spec->sourceHeader, RPMTAG_BUILDARCHS,
02020 RPM_STRING_ARRAY_TYPE,
02021 spec->BANames, spec->BACount);
02022 }
02023 }
02024
02025 int processSourceFiles(Spec spec)
02026 {
02027 struct Source *srcPtr;
02028 StringBuf sourceFiles;
02029 int x, isSpec = 1;
02030 struct FileList_s fl;
02031 char *s, **files, **fp;
02032 Package pkg;
02033
02034 sourceFiles = newStringBuf();
02035
02036
02037
02038
02039
02040 if (spec->sourceHeader == NULL)
02041 initSourceHeader(spec);
02042
02043
02044 appendLineStringBuf(sourceFiles, spec->specFile);
02045 if (spec->sourceHeader != NULL)
02046 for (srcPtr = spec->sources; srcPtr != NULL; srcPtr = srcPtr->next) {
02047 if (srcPtr->flags & RPMBUILD_ISSOURCE) {
02048 (void) headerAddOrAppendEntry(spec->sourceHeader, RPMTAG_SOURCE,
02049 RPM_STRING_ARRAY_TYPE, &srcPtr->source, 1);
02050 if (srcPtr->flags & RPMBUILD_ISNO) {
02051 (void) headerAddOrAppendEntry(spec->sourceHeader, RPMTAG_NOSOURCE,
02052 RPM_INT32_TYPE, &srcPtr->num, 1);
02053 }
02054 }
02055 if (srcPtr->flags & RPMBUILD_ISPATCH) {
02056 (void) headerAddOrAppendEntry(spec->sourceHeader, RPMTAG_PATCH,
02057 RPM_STRING_ARRAY_TYPE, &srcPtr->source, 1);
02058 if (srcPtr->flags & RPMBUILD_ISNO) {
02059 (void) headerAddOrAppendEntry(spec->sourceHeader, RPMTAG_NOPATCH,
02060 RPM_INT32_TYPE, &srcPtr->num, 1);
02061 }
02062 }
02063
02064 { const char * sfn;
02065 sfn = rpmGetPath( ((srcPtr->flags & RPMBUILD_ISNO) ? "!" : ""),
02066 "%{_sourcedir}/", srcPtr->source, NULL);
02067 appendLineStringBuf(sourceFiles, sfn);
02068 sfn = _free(sfn);
02069 }
02070 }
02071
02072 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
02073 for (srcPtr = pkg->icon; srcPtr != NULL; srcPtr = srcPtr->next) {
02074 const char * sfn;
02075 sfn = rpmGetPath( ((srcPtr->flags & RPMBUILD_ISNO) ? "!" : ""),
02076 "%{_sourcedir}/", srcPtr->source, NULL);
02077 appendLineStringBuf(sourceFiles, sfn);
02078 sfn = _free(sfn);
02079 }
02080 }
02081
02082 spec->sourceCpioList = NULL;
02083
02084 fl.fileList = xcalloc((spec->numSources + 1), sizeof(*fl.fileList));
02085 fl.processingFailed = 0;
02086 fl.fileListRecsUsed = 0;
02087 fl.totalFileSize = 0;
02088 fl.prefix = NULL;
02089 fl.buildRootURL = NULL;
02090
02091 s = getStringBuf(sourceFiles);
02092 files = splitString(s, strlen(s), '\n');
02093
02094
02095 x = 0;
02096 for (fp = files; *fp != NULL; fp++) {
02097 const char * diskURL, *diskPath;
02098 FileListRec flp;
02099
02100 diskURL = *fp;
02101 SKIPSPACE(diskURL);
02102 if (! *diskURL)
02103 continue;
02104
02105 flp = &fl.fileList[x];
02106
02107 flp->flags = isSpec ? RPMFILE_SPECFILE : 0;
02108
02109 if (*diskURL == '!') {
02110 flp->flags |= RPMFILE_GHOST;
02111 diskURL++;
02112 }
02113
02114 (void) urlPath(diskURL, &diskPath);
02115
02116 flp->diskURL = xstrdup(diskURL);
02117 diskPath = strrchr(diskPath, '/');
02118 if (diskPath)
02119 diskPath++;
02120 else
02121 diskPath = diskURL;
02122
02123 flp->fileURL = xstrdup(diskPath);
02124 flp->verifyFlags = RPMVERIFY_ALL;
02125
02126 if (Stat(diskURL, &flp->fl_st)) {
02127 rpmError(RPMERR_BADSPEC, _("Bad file: %s: %s\n"),
02128 diskURL, strerror(errno));
02129 fl.processingFailed = 1;
02130 }
02131
02132 flp->uname = getUname(flp->fl_uid);
02133 flp->gname = getGname(flp->fl_gid);
02134 flp->langs = xstrdup("");
02135
02136 fl.totalFileSize += flp->fl_size;
02137
02138 if (! (flp->uname && flp->gname)) {
02139 rpmError(RPMERR_BADSPEC, _("Bad owner/group: %s\n"), diskURL);
02140 fl.processingFailed = 1;
02141 }
02142
02143 isSpec = 0;
02144 x++;
02145 }
02146 fl.fileListRecsUsed = x;
02147 freeSplitString(files);
02148
02149 if (! fl.processingFailed) {
02150 if (spec->sourceHeader != NULL)
02151 genCpioListAndHeader(&fl, (TFI_t *)&spec->sourceCpioList,
02152 spec->sourceHeader, 1);
02153 }
02154
02155 sourceFiles = freeStringBuf(sourceFiles);
02156 fl.fileList = freeFileList(fl.fileList, fl.fileListRecsUsed);
02157 return fl.processingFailed;
02158 }
02159
02162 static StringBuf getOutputFrom(char * dir, char * argv[],
02163 const char * writePtr, int writeBytesLeft,
02164 int failNonZero)
02165
02166 {
02167 int progPID;
02168 int toProg[2];
02169 int fromProg[2];
02170 int status;
02171 void *oldhandler;
02172 StringBuf readBuff;
02173 int done;
02174
02175 oldhandler = signal(SIGPIPE, SIG_IGN);
02176
02177 toProg[0] = toProg[1] = 0;
02178 (void) pipe(toProg);
02179 fromProg[0] = fromProg[1] = 0;
02180 (void) pipe(fromProg);
02181
02182 if (!(progPID = fork())) {
02183 (void) close(toProg[1]);
02184 (void) close(fromProg[0]);
02185
02186 (void) dup2(toProg[0], STDIN_FILENO);
02187 (void) dup2(fromProg[1], STDOUT_FILENO);
02188
02189 (void) close(toProg[0]);
02190 (void) close(fromProg[1]);
02191
02192 if (dir) {
02193 (void) chdir(dir);
02194 }
02195
02196 (void) execvp(argv[0], argv);
02197
02198 rpmError(RPMERR_EXEC, _("Couldn't exec %s: %s\n"),
02199 argv[0], strerror(errno));
02200 _exit(RPMERR_EXEC);
02201 }
02202 if (progPID < 0) {
02203 rpmError(RPMERR_FORK, _("Couldn't fork %s: %s\n"),
02204 argv[0], strerror(errno));
02205 return NULL;
02206 }
02207
02208 (void) close(toProg[0]);
02209 (void) close(fromProg[1]);
02210
02211
02212 (void) fcntl(fromProg[0], F_SETFL, O_NONBLOCK);
02213 (void) fcntl(toProg[1], F_SETFL, O_NONBLOCK);
02214
02215 readBuff = newStringBuf();
02216
02217 do {
02218 fd_set ibits, obits;
02219 struct timeval tv;
02220 int nfd, nbw, nbr;
02221 int rc;
02222
02223 done = 0;
02224 top:
02225
02226 FD_ZERO(&ibits);
02227 FD_ZERO(&obits);
02228 if (fromProg[0] >= 0) {
02229 FD_SET(fromProg[0], &ibits);
02230 }
02231 if (toProg[1] >= 0) {
02232 FD_SET(toProg[1], &obits);
02233 }
02234 tv.tv_sec = 1;
02235 tv.tv_usec = 0;
02236 nfd = ((fromProg[0] > toProg[1]) ? fromProg[0] : toProg[1]);
02237 if ((rc = select(nfd, &ibits, &obits, NULL, &tv)) < 0) {
02238 if (errno == EINTR)
02239 goto top;
02240 break;
02241 }
02242
02243
02244 if (toProg[1] >= 0 && FD_ISSET(toProg[1], &obits)) {
02245 if (writeBytesLeft) {
02246 if ((nbw = write(toProg[1], writePtr,
02247 (1024<writeBytesLeft) ? 1024 : writeBytesLeft)) < 0) {
02248 if (errno != EAGAIN) {
02249 perror("getOutputFrom()");
02250 exit(EXIT_FAILURE);
02251 }
02252 nbw = 0;
02253 }
02254 writeBytesLeft -= nbw;
02255 writePtr += nbw;
02256 } else if (toProg[1] >= 0) {
02257 (void) close(toProg[1]);
02258 toProg[1] = -1;
02259 }
02260 }
02261
02262
02263 { char buf[BUFSIZ+1];
02264 while ((nbr = read(fromProg[0], buf, sizeof(buf)-1)) > 0) {
02265 buf[nbr] = '\0';
02266 appendStringBuf(readBuff, buf);
02267 }
02268 }
02269
02270
02271 done = (nbr == 0 || (nbr < 0 && errno != EAGAIN));
02272
02273 } while (!done);
02274
02275
02276 if (toProg[1] >= 0)
02277 (void) close(toProg[1]);
02278 if (fromProg[0] >= 0)
02279 (void) close(fromProg[0]);
02280 (void) signal(SIGPIPE, oldhandler);
02281
02282
02283 (void)waitpid(progPID, &status, 0);
02284 if (failNonZero && (!WIFEXITED(status) || WEXITSTATUS(status))) {
02285 rpmError(RPMERR_EXEC, _("%s failed\n"), argv[0]);
02286 return NULL;
02287 }
02288 if (writeBytesLeft) {
02289 rpmError(RPMERR_EXEC, _("failed to write all data to %s\n"), argv[0]);
02290 return NULL;
02291 }
02292 return readBuff;
02293 }
02294
02297 typedef struct {
02298 const char * msg;
02299 const char * argv[4];
02300 rpmTag ntag;
02301 rpmTag vtag;
02302 rpmTag ftag;
02303 int mask;
02304 int xor;
02305 } DepMsg_t;
02306
02309
02310 DepMsg_t depMsgs[] = {
02311 { "Provides", { "%{__find_provides}", NULL, NULL, NULL },
02312 RPMTAG_PROVIDENAME, RPMTAG_PROVIDEVERSION, RPMTAG_PROVIDEFLAGS,
02313 0, -1 },
02314 { "PreReq", { NULL, NULL, NULL, NULL },
02315 RPMTAG_REQUIRENAME, RPMTAG_REQUIREVERSION, RPMTAG_REQUIREFLAGS,
02316 RPMSENSE_PREREQ, 0 },
02317 { "Requires(interp)", { NULL, "interp", NULL, NULL },
02318 -1, -1, RPMTAG_REQUIREFLAGS,
02319 _notpre(RPMSENSE_INTERP), 0 },
02320 { "Requires(rpmlib)", { NULL, "rpmlib", NULL, NULL },
02321 -1, -1, RPMTAG_REQUIREFLAGS,
02322 _notpre(RPMSENSE_RPMLIB), 0 },
02323 { "Requires(verify)", { NULL, "verify", NULL, NULL },
02324 -1, -1, RPMTAG_REQUIREFLAGS,
02325 RPMSENSE_SCRIPT_VERIFY, 0 },
02326 { "Requires(pre)", { NULL, "pre", NULL, NULL },
02327 -1, -1, RPMTAG_REQUIREFLAGS,
02328 _notpre(RPMSENSE_SCRIPT_PRE), 0 },
02329 { "Requires(post)", { NULL, "post", NULL, NULL },
02330 -1, -1, RPMTAG_REQUIREFLAGS,
02331 _notpre(RPMSENSE_SCRIPT_POST), 0 },
02332 { "Requires(preun)", { NULL, "preun", NULL, NULL },
02333 -1, -1, RPMTAG_REQUIREFLAGS,
02334 _notpre(RPMSENSE_SCRIPT_PREUN), 0 },
02335 { "Requires(postun)", { NULL, "postun", NULL, NULL },
02336 -1, -1, RPMTAG_REQUIREFLAGS,
02337 _notpre(RPMSENSE_SCRIPT_POSTUN), 0 },
02338 { "Requires", { "%{__find_requires}", NULL, NULL, NULL },
02339 -1, -1, RPMTAG_REQUIREFLAGS,
02340 RPMSENSE_PREREQ, RPMSENSE_PREREQ },
02341 { "Conflicts", { "%{__find_conflicts}", NULL, NULL, NULL },
02342 RPMTAG_CONFLICTNAME, RPMTAG_CONFLICTVERSION, RPMTAG_CONFLICTFLAGS,
02343 0, -1 },
02344 { "Obsoletes", { "%{__find_obsoletes}", NULL, NULL, NULL },
02345 RPMTAG_OBSOLETENAME, RPMTAG_OBSOLETEVERSION, RPMTAG_OBSOLETEFLAGS,
02346 0, -1 },
02347 { NULL, { NULL, NULL, NULL, NULL }, 0, 0, 0, 0, 0 }
02348 };
02349
02350
02353 static int generateDepends(Spec spec, Package pkg, TFI_t cpioList, int multiLib)
02354
02355 {
02356 TFI_t fi = cpioList;
02357 StringBuf writeBuf;
02358 int writeBytes;
02359 StringBuf readBuf;
02360 DepMsg_t *dm;
02361 char ** myargv;
02362 int failnonzero = 0;
02363 int rc = 0;
02364 int ac;
02365 int i;
02366
02367 myargv = xcalloc(5, sizeof(*myargv));
02368
02369 if (!(fi && fi->fc > 0))
02370 return 0;
02371
02372 if (! (pkg->autoReq || pkg->autoProv))
02373 return 0;
02374
02375 writeBuf = newStringBuf();
02376 for (i = 0, writeBytes = 0; i < fi->fc; i++) {
02377
02378 if (fi->fmapflags && multiLib == 2) {
02379 if (!(fi->fmapflags[i] & CPIO_MULTILIB))
02380 continue;
02381 fi->fmapflags[i] &= ~CPIO_MULTILIB;
02382 }
02383
02384 appendStringBuf(writeBuf, fi->dnl[fi->dil[i]]);
02385 writeBytes += strlen(fi->dnl[fi->dil[i]]);
02386 appendLineStringBuf(writeBuf, fi->bnl[i]);
02387 writeBytes += strlen(fi->bnl[i]) + 1;
02388 }
02389
02390 for (dm = depMsgs; dm->msg != NULL; dm++) {
02391 int tag, tagflags;
02392
02393 tag = (dm->ftag > 0) ? dm->ftag : dm->ntag;
02394 tagflags = 0;
02395
02396 switch(tag) {
02397 case RPMTAG_PROVIDEFLAGS:
02398 if (!pkg->autoProv)
02399 continue;
02400 failnonzero = 1;
02401 tagflags = RPMSENSE_FIND_PROVIDES;
02402 break;
02403 case RPMTAG_REQUIREFLAGS:
02404 if (!pkg->autoReq)
02405 continue;
02406 failnonzero = 0;
02407 tagflags = RPMSENSE_FIND_REQUIRES;
02408 break;
02409 default:
02410 continue;
02411 break;
02412 }
02413
02414
02415 if (dm->argv[0] != NULL) {
02416 const char ** av;
02417 char * s;
02418
02419
02420 s = rpmExpand(dm->argv[0], NULL);
02421
02422 if (!(s != NULL && *s != '%' && *s != '\0')) {
02423 s = _free(s);
02424 continue;
02425 }
02426
02427 if (!(i = poptParseArgvString(s, &ac, (const char ***)&av))
02428 && ac > 0 && av != NULL)
02429 {
02430 myargv = xrealloc(myargv, (ac + 5) * sizeof(*myargv));
02431 for (i = 0; i < ac; i++)
02432 myargv[i] = xstrdup(av[i]);
02433 }
02434 av = _free(av);
02435 s = _free(s);
02436 }
02437
02438 if (myargv[0] == NULL)
02439 continue;
02440
02441 rpmMessage(RPMMESS_NORMAL, _("Finding %s: (using %s)...\n"),
02442 dm->msg, myargv[0]);
02443
02444 #if 0
02445 if (*myargv[0] != '/') {
02446 myargv[0] = _free(myargv[0]);
02447 continue;
02448 }
02449 #endif
02450
02451
02452 for (i = 1; i < 4; i++) {
02453 if (dm->argv[i] == NULL)
02454 break;
02455
02456 myargv[ac++] = rpmExpand(dm->argv[i], NULL);
02457
02458 }
02459
02460 myargv[ac] = NULL;
02461 readBuf = getOutputFrom(NULL, myargv,
02462 getStringBuf(writeBuf), writeBytes, failnonzero);
02463
02464
02465 for (i = 0; i < ac; i++)
02466 myargv[i] = _free(myargv[i]);
02467
02468 if (readBuf == NULL) {
02469 rc = RPMERR_EXEC;
02470 rpmError(rc, _("Failed to find %s:\n"), dm->msg);
02471 break;
02472 }
02473
02474
02475 tagflags &= ~RPMSENSE_MULTILIB;
02476 if (multiLib > 1)
02477 tagflags |= RPMSENSE_MULTILIB;
02478 else
02479 tagflags &= ~RPMSENSE_MULTILIB;
02480 rc = parseRCPOT(spec, pkg, getStringBuf(readBuf), tag, 0, tagflags);
02481 readBuf = freeStringBuf(readBuf);
02482
02483 if (rc) {
02484 rpmError(rc, _("Failed to find %s:\n"), dm->msg);
02485 break;
02486 }
02487 }
02488
02489 writeBuf = freeStringBuf(writeBuf);
02490 myargv = _free(myargv);
02491 return rc;
02492 }
02493
02496 static void printDepMsg(DepMsg_t * dm, int count, const char ** names,
02497 const char ** versions, int *flags)
02498
02499 {
02500 int hasVersions = (versions != NULL);
02501 int hasFlags = (flags != NULL);
02502 int bingo = 0;
02503 int i;
02504
02505 for (i = 0; i < count; i++, names++, versions++, flags++) {
02506 if (hasFlags && !((*flags & dm->mask) ^ dm->xor))
02507 continue;
02508 if (bingo == 0) {
02509 rpmMessage(RPMMESS_NORMAL, "%s:", (dm->msg ? dm->msg : ""));
02510 bingo = 1;
02511 }
02512 rpmMessage(RPMMESS_NORMAL, " %s", *names);
02513
02514 if (hasFlags && isDependsMULTILIB(*flags))
02515 rpmMessage(RPMMESS_NORMAL, " (multilib)");
02516
02517 if (hasVersions && !(*versions != NULL && **versions != '\0'))
02518 continue;
02519 if (!(hasFlags && (*flags && RPMSENSE_SENSEMASK)))
02520 continue;
02521
02522 rpmMessage(RPMMESS_NORMAL, " ");
02523 if (*flags & RPMSENSE_LESS)
02524 rpmMessage(RPMMESS_NORMAL, "<");
02525 if (*flags & RPMSENSE_GREATER)
02526 rpmMessage(RPMMESS_NORMAL, ">");
02527 if (*flags & RPMSENSE_EQUAL)
02528 rpmMessage(RPMMESS_NORMAL, "=");
02529
02530 rpmMessage(RPMMESS_NORMAL, " %s", *versions);
02531 }
02532 if (bingo)
02533 rpmMessage(RPMMESS_NORMAL, "\n");
02534 }
02535
02538 static void printDeps(Header h)
02539
02540 {
02541 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
02542 HFD_t hfd = headerFreeData;
02543 const char ** names = NULL;
02544 rpmTagType dnt = -1;
02545 const char ** versions = NULL;
02546 rpmTagType dvt = -1;
02547 int * flags = NULL;
02548 DepMsg_t * dm;
02549 int count;
02550
02551 for (dm = depMsgs; dm->msg != NULL; dm++) {
02552 switch (dm->ntag) {
02553 case 0:
02554 names = hfd(names, dnt);
02555 break;
02556 case -1:
02557 break;
02558 default:
02559 names = hfd(names, dnt);
02560 if (!hge(h, dm->ntag, &dnt, (void **) &names, &count))
02561 continue;
02562 break;
02563 }
02564 switch (dm->vtag) {
02565 case 0:
02566 versions = hfd(versions, dvt);
02567 break;
02568 case -1:
02569 break;
02570 default:
02571 versions = hfd(versions, dvt);
02572 (void) hge(h, dm->vtag, &dvt, (void **) &versions, NULL);
02573 break;
02574 }
02575 switch (dm->ftag) {
02576 case 0:
02577 flags = NULL;
02578 break;
02579 case -1:
02580 break;
02581 default:
02582 (void) hge(h, dm->ftag, NULL, (void **) &flags, NULL);
02583 break;
02584 }
02585 printDepMsg(dm, count, names, versions, flags);
02586 }
02587 names = hfd(names, dnt);
02588 versions = hfd(versions, dvt);
02589 }
02590
02591 int processBinaryFiles(Spec spec, int installSpecialDoc, int test)
02592 {
02593 Package pkg;
02594 int res = 0;
02595
02596 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
02597 const char *n, *v, *r;
02598 int rc;
02599
02600 if (pkg->fileList == NULL)
02601 continue;
02602
02603 (void) headerNVR(pkg->header, &n, &v, &r);
02604 rpmMessage(RPMMESS_NORMAL, _("Processing files: %s-%s-%s\n"), n, v, r);
02605
02606 if ((rc = processPackageFiles(spec, pkg, installSpecialDoc, test)))
02607 res = rc;
02608
02609
02610
02611
02612
02613 if (headerIsEntry(pkg->header, RPMTAG_MULTILIBS)) {
02614 (void) generateDepends(spec, pkg, pkg->cpioList, 1);
02615 (void) generateDepends(spec, pkg, pkg->cpioList, 2);
02616 } else
02617 (void) generateDepends(spec, pkg, pkg->cpioList, 0);
02618 printDeps(pkg->header);
02619 }
02620
02621 return res;
02622 }