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