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