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