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