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