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