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