00001
00007 #include "system.h"
00008
00009 #define MYALLPERMS 07777
00010
00011 #if defined(WITH_PCRE) && defined(WITH_PCRE_POSIX)
00012 #include <pcreposix.h>
00013 #else
00014 #include <regex.h>
00015 #endif
00016
00017 #define _RPMIOB_INTERNAL
00018 #include <rpmiotypes.h>
00019 #include <rpmio_internal.h>
00020 #include <rpmcb.h>
00021 #include <fts.h>
00022 #include <argv.h>
00023
00024 #include "iosm.h"
00025 #define _RPMTAG_INTERNAL
00026 #define _RPMFI_INTERNAL
00027 #include <rpmbuild.h>
00028
00029 #define _RPMTE_INTERNAL
00030 #include <rpmte.h>
00031
00032 #include "rpmfc.h"
00033
00034 #include "buildio.h"
00035
00036 #include "legacy.h"
00037 #include "debug.h"
00038
00039
00040
00041
00042
00043
00044 #define SKIPWHITE(_x) {while(*(_x) && (xisspace(*_x) || *(_x) == ',')) (_x)++;}
00045 #define SKIPNONWHITE(_x){while(*(_x) &&!(xisspace(*_x) || *(_x) == ',')) (_x)++;}
00046
00047 #define MAXDOCDIR 1024
00048
00051 typedef enum specdFlags_e {
00052 SPECD_DEFFILEMODE = (1 << 0),
00053 SPECD_DEFDIRMODE = (1 << 1),
00054 SPECD_DEFUID = (1 << 2),
00055 SPECD_DEFGID = (1 << 3),
00056 SPECD_DEFVERIFY = (1 << 4),
00057
00058 SPECD_FILEMODE = (1 << 8),
00059 SPECD_DIRMODE = (1 << 9),
00060 SPECD_UID = (1 << 10),
00061 SPECD_GID = (1 << 11),
00062 SPECD_VERIFY = (1 << 12)
00063 } specdFlags;
00064
00067 typedef struct FileListRec_s {
00068 struct stat fl_st;
00069 #define fl_dev fl_st.st_dev
00070 #define fl_ino fl_st.st_ino
00071 #define fl_mode fl_st.st_mode
00072 #define fl_nlink fl_st.st_nlink
00073 #define fl_uid fl_st.st_uid
00074 #define fl_gid fl_st.st_gid
00075 #define fl_rdev fl_st.st_rdev
00076 #define fl_size fl_st.st_size
00077 #define fl_mtime fl_st.st_mtime
00078
00079
00080 const char *diskURL;
00081
00082 const char *fileURL;
00083
00084 const char *uname;
00085
00086 const char *gname;
00087 unsigned flags;
00088 specdFlags specdFlags;
00089 unsigned verifyFlags;
00090
00091 const char *langs;
00092 } * FileListRec;
00093
00096 typedef struct AttrRec_s {
00097
00098 const char *ar_fmodestr;
00099
00100 const char *ar_dmodestr;
00101
00102 const char *ar_user;
00103
00104 const char *ar_group;
00105 mode_t ar_fmode;
00106 mode_t ar_dmode;
00107 } * AttrRec;
00108
00109
00110
00111 static struct AttrRec_s root_ar = { NULL, NULL, "root", "root", 0, 0 };
00112
00113
00117 typedef struct FileList_s {
00118
00119 const char * buildRootURL;
00120
00121 const char * prefix;
00122
00123 int fileCount;
00124 int totalFileSize;
00125 int processingFailed;
00126
00127 int passedSpecialDoc;
00128 int isSpecialDoc;
00129
00130 int noGlob;
00131 unsigned devtype;
00132 unsigned devmajor;
00133 int devminor;
00134
00135 int isDir;
00136 int inFtw;
00137 int currentFlags;
00138 specdFlags currentSpecdFlags;
00139 int currentVerifyFlags;
00140 struct AttrRec_s cur_ar;
00141 struct AttrRec_s def_ar;
00142 specdFlags defSpecdFlags;
00143 int defVerifyFlags;
00144 int nLangs;
00145
00146 const char ** currentLangs;
00147
00148
00149
00150 const char * docDirs[MAXDOCDIR];
00151 int docDirCount;
00152
00153
00154 FileListRec fileList;
00155 int fileListRecsAlloced;
00156 int fileListRecsUsed;
00157 } * FileList;
00158
00161 static void nullAttrRec( AttrRec ar)
00162 {
00163 ar->ar_fmodestr = NULL;
00164 ar->ar_dmodestr = NULL;
00165 ar->ar_user = NULL;
00166 ar->ar_group = NULL;
00167 ar->ar_fmode = 0;
00168 ar->ar_dmode = 0;
00169 }
00170
00173 static void freeAttrRec(AttrRec ar)
00174 {
00175 ar->ar_fmodestr = _free(ar->ar_fmodestr);
00176 ar->ar_dmodestr = _free(ar->ar_dmodestr);
00177 ar->ar_user = _free(ar->ar_user);
00178 ar->ar_group = _free(ar->ar_group);
00179
00180
00181 return;
00182
00183 }
00184
00187 static void dupAttrRec(const AttrRec oar, AttrRec nar)
00188
00189 {
00190 if (oar == nar)
00191 return;
00192 freeAttrRec(nar);
00193 nar->ar_fmodestr = (oar->ar_fmodestr ? xstrdup(oar->ar_fmodestr) : NULL);
00194 nar->ar_dmodestr = (oar->ar_dmodestr ? xstrdup(oar->ar_dmodestr) : NULL);
00195 nar->ar_user = (oar->ar_user ? xstrdup(oar->ar_user) : NULL);
00196 nar->ar_group = (oar->ar_group ? xstrdup(oar->ar_group) : NULL);
00197 nar->ar_fmode = oar->ar_fmode;
00198 nar->ar_dmode = oar->ar_dmode;
00199 }
00200
00201 #if 0
00202
00204 static void dumpAttrRec(const char * msg, AttrRec ar)
00205
00206
00207 {
00208 if (msg)
00209 fprintf(stderr, "%s:\t", msg);
00210 fprintf(stderr, "(%s, %s, %s, %s)\n",
00211 ar->ar_fmodestr,
00212 ar->ar_user,
00213 ar->ar_group,
00214 ar->ar_dmodestr);
00215 }
00216 #endif
00217
00223
00224 static char *strtokWithQuotes( char *s, const char *delim)
00225
00226 {
00227 static char *olds = NULL;
00228 char *token;
00229
00230 if (s == NULL)
00231 s = olds;
00232 if (s == NULL)
00233 return NULL;
00234
00235
00236 s += strspn(s, delim);
00237 if (*s == '\0')
00238 return NULL;
00239
00240
00241 token = s;
00242 if (*token == '"') {
00243 token++;
00244
00245 s = strchr(token, '"');
00246 } else {
00247 s = strpbrk(token, delim);
00248 }
00249
00250
00251 if (s == NULL) {
00252
00253 olds = strchr(token, '\0');
00254 } else {
00255
00256 *s = '\0';
00257 olds = s+1;
00258 }
00259
00260
00261 return token;
00262
00263 }
00264
00267 static void timeCheck(int tc, Header h)
00268
00269
00270 {
00271 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00272 rpmuint32_t currentTime = (rpmuint32_t) time(NULL);
00273 rpmuint32_t * mtime;
00274 int xx;
00275 size_t i;
00276
00277 he->tag = RPMTAG_FILEMTIMES;
00278 xx = headerGet(h, he, 0);
00279 mtime = he->p.ui32p;
00280 he->tag = RPMTAG_OLDFILENAMES;
00281 xx = headerGet(h, he, 0);
00282
00283 for (i = 0; i < he->c; i++) {
00284 xx = currentTime - mtime[i];
00285 if (xx < 0) xx = -xx;
00286 if (xx > tc)
00287 rpmlog(RPMLOG_WARNING, _("TIMECHECK failure: %s\n"), he->p.argv[i]);
00288 }
00289 he->p.ptr = _free(he->p.ptr);
00290 mtime = _free(mtime);
00291 }
00292
00295 typedef struct VFA {
00296 const char * attribute;
00297 int not;
00298 int flag;
00299 } VFA_t;
00300
00303
00304
00305 static 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 static rpmRC parseForVerify(char * buf, FileList fl)
00325
00326
00327
00328 {
00329 char *p, *pe, *q;
00330 const char *name;
00331 int *resultVerify;
00332 int negated;
00333 int verifyFlags;
00334 specdFlags * specdFlags;
00335
00336 if ((p = strstr(buf, (name = "%verify"))) != NULL) {
00337 resultVerify = &(fl->currentVerifyFlags);
00338 specdFlags = &fl->currentSpecdFlags;
00339 } else if ((p = strstr(buf, (name = "%defverify"))) != NULL) {
00340 resultVerify = &(fl->defVerifyFlags);
00341 specdFlags = &fl->defSpecdFlags;
00342 } else
00343 return RPMRC_OK;
00344
00345 for (pe = p; (size_t)(pe-p) < strlen(name); pe++)
00346 *pe = ' ';
00347
00348 SKIPSPACE(pe);
00349
00350 if (*pe != '(') {
00351 rpmlog(RPMLOG_ERR, _("Missing '(' in %s %s\n"), name, pe);
00352 fl->processingFailed = 1;
00353 return RPMRC_FAIL;
00354 }
00355
00356
00357 *pe++ = ' ';
00358 for (p = pe; *pe && *pe != ')'; pe++)
00359 {};
00360
00361 if (*pe == '\0') {
00362 rpmlog(RPMLOG_ERR, _("Missing ')' in %s(%s\n"), name, p);
00363 fl->processingFailed = 1;
00364 return RPMRC_FAIL;
00365 }
00366
00367
00368 q = alloca((pe-p) + 1);
00369 strncpy(q, p, pe-p);
00370 q[pe-p] = '\0';
00371 while (p <= pe)
00372 *p++ = ' ';
00373
00374 negated = 0;
00375 verifyFlags = RPMVERIFY_NONE;
00376
00377 for (p = q; *p != '\0'; p = pe) {
00378 SKIPWHITE(p);
00379 if (*p == '\0')
00380 break;
00381 pe = p;
00382 SKIPNONWHITE(pe);
00383 if (*pe != '\0')
00384 *pe++ = '\0';
00385
00386 { VFA_t *vfa;
00387 for (vfa = verifyAttrs; vfa->attribute != NULL; vfa++) {
00388 if (strcmp(p, vfa->attribute))
00389 continue;
00390 verifyFlags |= vfa->flag;
00391 break;
00392 }
00393 if (vfa->attribute)
00394 continue;
00395 }
00396
00397 if (!strcmp(p, "not")) {
00398 negated ^= 1;
00399 } else {
00400 rpmlog(RPMLOG_ERR, _("Invalid %s token: %s\n"), name, p);
00401 fl->processingFailed = 1;
00402 return RPMRC_FAIL;
00403 }
00404 }
00405
00406 *resultVerify = negated ? ~(verifyFlags) : verifyFlags;
00407 *specdFlags |= SPECD_VERIFY;
00408
00409 return RPMRC_OK;
00410 }
00411
00412 #define isAttrDefault(_ars) ((_ars)[0] == '-' && (_ars)[1] == '\0')
00413
00420 static rpmRC parseForDev(char * buf, FileList fl)
00421
00422
00423 {
00424 const char * name;
00425 const char * errstr = NULL;
00426 char *p, *pe, *q;
00427 rpmRC rc = RPMRC_FAIL;
00428
00429 if ((p = strstr(buf, (name = "%dev"))) == NULL)
00430 return RPMRC_OK;
00431
00432 for (pe = p; (size_t)(pe-p) < strlen(name); pe++)
00433 *pe = ' ';
00434 SKIPSPACE(pe);
00435
00436 if (*pe != '(') {
00437 errstr = "'('";
00438 goto exit;
00439 }
00440
00441
00442 *pe++ = ' ';
00443 for (p = pe; *pe && *pe != ')'; pe++)
00444 {};
00445 if (*pe != ')') {
00446 errstr = "')'";
00447 goto exit;
00448 }
00449
00450
00451 q = alloca((pe-p) + 1);
00452 strncpy(q, p, pe-p);
00453 q[pe-p] = '\0';
00454 while (p <= pe)
00455 *p++ = ' ';
00456
00457 p = q; SKIPWHITE(p);
00458 pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
00459 if (*p == 'b')
00460 fl->devtype = 'b';
00461 else if (*p == 'c')
00462 fl->devtype = 'c';
00463 else {
00464 errstr = "devtype";
00465 goto exit;
00466 }
00467
00468 p = pe; SKIPWHITE(p);
00469 pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
00470 for (pe = p; *pe && xisdigit(*pe); pe++)
00471 {} ;
00472 if (*pe == '\0') {
00473 fl->devmajor = atoi(p);
00474
00475 if (!((int)fl->devmajor >= 0 && (int)fl->devmajor < 256)) {
00476 errstr = "devmajor";
00477 goto exit;
00478 }
00479
00480 pe++;
00481 } else {
00482 errstr = "devmajor";
00483 goto exit;
00484 }
00485
00486 p = pe; SKIPWHITE(p);
00487 pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
00488 for (pe = p; *pe && xisdigit(*pe); pe++)
00489 {} ;
00490 if (*pe == '\0') {
00491 fl->devminor = atoi(p);
00492 if (!(fl->devminor >= 0 && fl->devminor < 256)) {
00493 errstr = "devminor";
00494 goto exit;
00495 }
00496 pe++;
00497 } else {
00498 errstr = "devminor";
00499 goto exit;
00500 }
00501
00502 fl->noGlob = 1;
00503
00504 rc = 0;
00505
00506 exit:
00507 if (rc) {
00508 rpmlog(RPMLOG_ERR, _("Missing %s in %s %s\n"), errstr, name, p);
00509 fl->processingFailed = 1;
00510 }
00511 return rc;
00512 }
00513
00520 static rpmRC parseForAttr(char * buf, FileList fl)
00521
00522
00523
00524 {
00525 const char *name;
00526 char *p, *pe, *q;
00527 int x;
00528 struct AttrRec_s arbuf;
00529 AttrRec ar = &arbuf, ret_ar;
00530 specdFlags * specdFlags;
00531
00532 if ((p = strstr(buf, (name = "%attr"))) != NULL) {
00533 ret_ar = &(fl->cur_ar);
00534 specdFlags = &fl->currentSpecdFlags;
00535 } else if ((p = strstr(buf, (name = "%defattr"))) != NULL) {
00536 ret_ar = &(fl->def_ar);
00537 specdFlags = &fl->defSpecdFlags;
00538 } else
00539 return RPMRC_OK;
00540
00541 for (pe = p; (size_t)(pe-p) < strlen(name); pe++)
00542 *pe = ' ';
00543
00544 SKIPSPACE(pe);
00545
00546 if (*pe != '(') {
00547 rpmlog(RPMLOG_ERR, _("Missing '(' in %s %s\n"), name, pe);
00548 fl->processingFailed = 1;
00549 return RPMRC_FAIL;
00550 }
00551
00552
00553 *pe++ = ' ';
00554 for (p = pe; *pe && *pe != ')'; pe++)
00555 {};
00556
00557 if (ret_ar == &(fl->def_ar)) {
00558 q = pe;
00559 q++;
00560 SKIPSPACE(q);
00561 if (*q != '\0') {
00562 rpmlog(RPMLOG_ERR,
00563 _("Non-white space follows %s(): %s\n"), name, q);
00564 fl->processingFailed = 1;
00565 return RPMRC_FAIL;
00566 }
00567 }
00568
00569
00570 q = alloca((pe-p) + 1);
00571 strncpy(q, p, pe-p);
00572 q[pe-p] = '\0';
00573 while (p <= pe)
00574 *p++ = ' ';
00575
00576 nullAttrRec(ar);
00577
00578 p = q; SKIPWHITE(p);
00579 if (*p != '\0') {
00580 pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
00581 ar->ar_fmodestr = p;
00582 p = pe; SKIPWHITE(p);
00583 }
00584 if (*p != '\0') {
00585 pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
00586 ar->ar_user = p;
00587 p = pe; SKIPWHITE(p);
00588 }
00589 if (*p != '\0') {
00590 pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
00591 ar->ar_group = p;
00592 p = pe; SKIPWHITE(p);
00593 }
00594 if (*p != '\0' && ret_ar == &(fl->def_ar)) {
00595 pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
00596 ar->ar_dmodestr = p;
00597 p = pe; SKIPWHITE(p);
00598 }
00599
00600 if (!(ar->ar_fmodestr && ar->ar_user && ar->ar_group) || *p != '\0') {
00601 rpmlog(RPMLOG_ERR, _("Bad syntax: %s(%s)\n"), name, q);
00602 fl->processingFailed = 1;
00603 return RPMRC_FAIL;
00604 }
00605
00606
00607 if (ar->ar_fmodestr && !isAttrDefault(ar->ar_fmodestr)) {
00608 unsigned int ui;
00609 x = sscanf(ar->ar_fmodestr, "%o", &ui);
00610 if ((x == 0) || (ar->ar_fmode & ~MYALLPERMS)) {
00611 rpmlog(RPMLOG_ERR, _("Bad mode spec: %s(%s)\n"), name, q);
00612 fl->processingFailed = 1;
00613 return RPMRC_FAIL;
00614 }
00615 ar->ar_fmode = ui;
00616 } else
00617 ar->ar_fmodestr = NULL;
00618
00619 if (ar->ar_dmodestr && !isAttrDefault(ar->ar_dmodestr)) {
00620 unsigned int ui;
00621 x = sscanf(ar->ar_dmodestr, "%o", &ui);
00622 if ((x == 0) || (ar->ar_dmode & ~MYALLPERMS)) {
00623 rpmlog(RPMLOG_ERR, _("Bad dirmode spec: %s(%s)\n"), name, q);
00624 fl->processingFailed = 1;
00625 return RPMRC_FAIL;
00626 }
00627 ar->ar_dmode = ui;
00628 } else
00629 ar->ar_dmodestr = NULL;
00630
00631 if (!(ar->ar_user && !isAttrDefault(ar->ar_user)))
00632 ar->ar_user = NULL;
00633
00634 if (!(ar->ar_group && !isAttrDefault(ar->ar_group)))
00635 ar->ar_group = NULL;
00636
00637 dupAttrRec(ar, ret_ar);
00638
00639
00640 *specdFlags |= SPECD_UID | SPECD_GID | SPECD_FILEMODE | SPECD_DIRMODE;
00641
00642 return RPMRC_OK;
00643 }
00644
00651 static rpmRC parseForConfig(char * buf, FileList fl)
00652
00653 {
00654 char *p, *pe, *q;
00655 const char *name;
00656
00657 if ((p = strstr(buf, (name = "%config"))) == NULL)
00658 return RPMRC_OK;
00659
00660 fl->currentFlags |= RPMFILE_CONFIG;
00661
00662
00663 for (pe = p; (size_t)(pe-p) < strlen(name); pe++)
00664 *pe = ' ';
00665 SKIPSPACE(pe);
00666 if (*pe != '(')
00667 return RPMRC_OK;
00668
00669
00670 *pe++ = ' ';
00671 for (p = pe; *pe && *pe != ')'; pe++)
00672 {};
00673
00674 if (*pe == '\0') {
00675 rpmlog(RPMLOG_ERR, _("Missing ')' in %s(%s\n"), name, p);
00676 fl->processingFailed = 1;
00677 return RPMRC_FAIL;
00678 }
00679
00680
00681 q = alloca((pe-p) + 1);
00682 strncpy(q, p, pe-p);
00683 q[pe-p] = '\0';
00684 while (p <= pe)
00685 *p++ = ' ';
00686
00687 for (p = q; *p != '\0'; p = pe) {
00688 SKIPWHITE(p);
00689 if (*p == '\0')
00690 break;
00691 pe = p;
00692 SKIPNONWHITE(pe);
00693 if (*pe != '\0')
00694 *pe++ = '\0';
00695 if (!strcmp(p, "missingok")) {
00696 fl->currentFlags |= RPMFILE_MISSINGOK;
00697 } else if (!strcmp(p, "noreplace")) {
00698 fl->currentFlags |= RPMFILE_NOREPLACE;
00699 } else {
00700 rpmlog(RPMLOG_ERR, _("Invalid %s token: %s\n"), name, p);
00701 fl->processingFailed = 1;
00702 return RPMRC_FAIL;
00703 }
00704 }
00705
00706 return RPMRC_OK;
00707 }
00708
00711 static int langCmp(const void * ap, const void * bp)
00712
00713 {
00714 return strcmp(*(const char **)ap, *(const char **)bp);
00715 }
00716
00723 static rpmRC parseForLang(char * buf, FileList fl)
00724
00725
00726 {
00727 char *p, *pe, *q;
00728 const char *name;
00729
00730 while ((p = strstr(buf, (name = "%lang"))) != NULL) {
00731
00732 for (pe = p; (size_t)(pe-p) < strlen(name); pe++)
00733 *pe = ' ';
00734 SKIPSPACE(pe);
00735
00736 if (*pe != '(') {
00737 rpmlog(RPMLOG_ERR, _("Missing '(' in %s %s\n"), name, pe);
00738 fl->processingFailed = 1;
00739 return RPMRC_FAIL;
00740 }
00741
00742
00743 *pe++ = ' ';
00744 for (pe = p; *pe && *pe != ')'; pe++)
00745 {};
00746
00747 if (*pe == '\0') {
00748 rpmlog(RPMLOG_ERR, _("Missing ')' in %s(%s\n"), name, p);
00749 fl->processingFailed = 1;
00750 return RPMRC_FAIL;
00751 }
00752
00753
00754 q = alloca((pe-p) + 1);
00755 strncpy(q, p, pe-p);
00756 q[pe-p] = '\0';
00757 while (p <= pe)
00758 *p++ = ' ';
00759
00760
00761 for (p = q; *p != '\0'; p = pe) {
00762 char *newp;
00763 size_t np;
00764 int i;
00765
00766 SKIPWHITE(p);
00767 pe = p;
00768 SKIPNONWHITE(pe);
00769
00770 np = pe - p;
00771
00772
00773 if (np < 1 || (np == 1 && *p != 'C') || np >= 32) {
00774 rpmlog(RPMLOG_ERR,
00775 _("Unusual locale length: \"%.*s\" in %%lang(%s)\n"),
00776 (int)np, p, q);
00777 fl->processingFailed = 1;
00778 return RPMRC_FAIL;
00779 }
00780
00781
00782 if (fl->currentLangs != NULL)
00783 for (i = 0; i < fl->nLangs; i++) {
00784 if (strncmp(fl->currentLangs[i], p, np))
00785 continue;
00786 rpmlog(RPMLOG_ERR, _("Duplicate locale %.*s in %%lang(%s)\n"),
00787 (int)np, p, q);
00788 fl->processingFailed = 1;
00789 return RPMRC_FAIL;
00790 }
00791
00792
00793 fl->currentLangs = xrealloc(fl->currentLangs,
00794 (fl->nLangs + 1) * sizeof(*fl->currentLangs));
00795 newp = xmalloc( np+1 );
00796 strncpy(newp, p, np);
00797 newp[np] = '\0';
00798 fl->currentLangs[fl->nLangs++] = newp;
00799 if (*pe == ',') pe++;
00800 }
00801 }
00802
00803
00804 if (fl->currentLangs)
00805 qsort(fl->currentLangs, fl->nLangs, sizeof(*fl->currentLangs), langCmp);
00806
00807 return RPMRC_OK;
00808 }
00809
00812 static int parseForRegexLang(const char * fileName, char ** lang)
00813
00814
00815 {
00816 static int initialized = 0;
00817 static int hasRegex = 0;
00818 static regex_t compiledPatt;
00819 static char buf[BUFSIZ];
00820 int x;
00821 regmatch_t matches[2];
00822 const char *s;
00823
00824 if (! initialized) {
00825 const char *patt = rpmExpand("%{?_langpatt}", NULL);
00826 int rc = 0;
00827 if (!(patt && *patt != '\0'))
00828 rc = 1;
00829 else if (regcomp(&compiledPatt, patt, REG_EXTENDED))
00830 rc = -1;
00831 patt = _free(patt);
00832 if (rc)
00833 return rc;
00834 hasRegex = 1;
00835 initialized = 1;
00836 }
00837
00838 memset(matches, 0, sizeof(matches));
00839 if (! hasRegex || regexec(&compiledPatt, fileName, 2, matches, REG_NOTEOL))
00840 return 1;
00841
00842
00843 s = fileName + matches[1].rm_eo - 1;
00844 x = (int)matches[1].rm_eo - (int)matches[1].rm_so;
00845 buf[x] = '\0';
00846 while (x) {
00847 buf[--x] = *s--;
00848 }
00849 if (lang)
00850 *lang = buf;
00851 return 0;
00852 }
00853
00856
00857
00858 static VFA_t virtualFileAttributes[] = {
00859 { "%dir", 0, 0 },
00860 { "%doc", 0, RPMFILE_DOC },
00861 { "%ghost", 0, RPMFILE_GHOST },
00862 { "%exclude", 0, RPMFILE_EXCLUDE },
00863 { "%readme", 0, RPMFILE_README },
00864 { "%license", 0, RPMFILE_LICENSE },
00865 { "%pubkey", 0, RPMFILE_PUBKEY },
00866 { "%policy", 0, RPMFILE_POLICY },
00867 { "%optional", 0, RPMFILE_OPTIONAL },
00868 { "%remove", 0, RPMFILE_REMOVE },
00869
00870 #if WHY_NOT
00871 { "%icon", 0, RPMFILE_ICON },
00872 { "%spec", 0, RPMFILE_SPEC },
00873 { "%config", 0, RPMFILE_CONFIG },
00874 { "%missingok", 0, RPMFILE_CONFIG|RPMFILE_MISSINGOK },
00875 { "%noreplace", 0, RPMFILE_CONFIG|RPMFILE_NOREPLACE },
00876 #endif
00877
00878 { NULL, 0, 0 }
00879 };
00880
00881
00891 static rpmRC parseForSimple( Spec spec, Package pkg,
00892 char * buf, FileList fl, const char ** fileName)
00893
00894
00895
00896
00897
00898
00899
00900 {
00901 char *s, *t;
00902 int specialDoc = 0;
00903 char specialDocBuf[BUFSIZ];
00904 rpmRC res = RPMRC_OK;
00905
00906 specialDocBuf[0] = '\0';
00907 *fileName = NULL;
00908
00909 t = buf;
00910 while ((s = strtokWithQuotes(t, " \t\n")) != NULL) {
00911 t = NULL;
00912 if (!strcmp(s, "%docdir")) {
00913 s = strtokWithQuotes(NULL, " \t\n");
00914 if (fl->docDirCount == MAXDOCDIR) {
00915 rpmlog(RPMLOG_CRIT, _("Hit limit for %%docdir\n"));
00916 fl->processingFailed = 1;
00917 res = RPMRC_FAIL;
00918 }
00919
00920 if (s != NULL)
00921 fl->docDirs[fl->docDirCount++] = xstrdup(s);
00922 if (s == NULL || strtokWithQuotes(NULL, " \t\n")) {
00923 rpmlog(RPMLOG_CRIT, _("Only one arg for %%docdir\n"));
00924 fl->processingFailed = 1;
00925 res = RPMRC_FAIL;
00926 }
00927 break;
00928 }
00929 #if defined(__LCLINT__)
00930 assert(s != NULL);
00931 #endif
00932
00933
00934 { VFA_t *vfa;
00935 for (vfa = virtualFileAttributes; vfa->attribute != NULL; vfa++) {
00936 if (strcmp(s, vfa->attribute))
00937 continue;
00938 if (!vfa->flag) {
00939 if (!strcmp(s, "%dir"))
00940 fl->isDir = 1;
00941 } else {
00942 if (vfa->not)
00943 fl->currentFlags &= ~vfa->flag;
00944 else
00945 fl->currentFlags |= vfa->flag;
00946 }
00947
00948 break;
00949 }
00950
00951 if (vfa->attribute != NULL)
00952 continue;
00953 }
00954
00955 if (*fileName) {
00956
00957 rpmlog(RPMLOG_ERR, _("Two files on one line: %s\n"),
00958 *fileName);
00959 fl->processingFailed = 1;
00960 res = RPMRC_FAIL;
00961 }
00962
00963 if (*s != '/') {
00964 if (fl->currentFlags & RPMFILE_DOC) {
00965 specialDoc = 1;
00966 strcat(specialDocBuf, " ");
00967 strcat(specialDocBuf, s);
00968 } else
00969 if (fl->currentFlags & (RPMFILE_POLICY|RPMFILE_PUBKEY|RPMFILE_ICON))
00970 {
00971 *fileName = s;
00972 } else {
00973 const char * sfn = NULL;
00974 int urltype = urlPath(s, &sfn);
00975 switch (urltype) {
00976 default:
00977 rpmlog(RPMLOG_ERR,
00978 _("File must begin with \"/\": %s\n"), s);
00979 fl->processingFailed = 1;
00980 res = RPMRC_FAIL;
00981 break;
00982 case URL_IS_PATH:
00983 *fileName = s;
00984 break;
00985 }
00986 }
00987 } else {
00988 *fileName = s;
00989 }
00990 }
00991
00992 if (specialDoc) {
00993 if (*fileName || (fl->currentFlags & ~(RPMFILE_DOC))) {
00994 rpmlog(RPMLOG_ERR,
00995 _("Can't mix special %%doc with other forms: %s\n"),
00996 (*fileName ? *fileName : ""));
00997 fl->processingFailed = 1;
00998 res = RPMRC_FAIL;
00999 } else {
01000
01001 {
01002
01003 static char *_docdir_fmt = NULL;
01004 static int oneshot = 0;
01005 const char *ddir, *fmt, *errstr;
01006 if (!oneshot) {
01007 _docdir_fmt = rpmExpand("%{?_docdir_fmt}", NULL);
01008 if (!(_docdir_fmt && *_docdir_fmt))
01009 _docdir_fmt = _free(_docdir_fmt);
01010 oneshot = 1;
01011 }
01012 if (_docdir_fmt == NULL)
01013 _docdir_fmt = xstrdup("%{NAME}-%{VERSION}");
01014 fmt = headerSprintf(pkg->header, _docdir_fmt, NULL, rpmHeaderFormats, &errstr);
01015 if (fmt == NULL) {
01016 rpmlog(RPMLOG_ERR, _("illegal _docdir_fmt: %s\n"), errstr);
01017 fl->processingFailed = 1;
01018 res = RPMRC_FAIL;
01019 } else {
01020 ddir = rpmGetPath("%{_docdir}/", fmt, NULL);
01021 strcpy(buf, ddir);
01022 ddir = _free(ddir);
01023 fmt = _free(fmt);
01024 }
01025 }
01026
01027
01028
01029 if (! fl->passedSpecialDoc) {
01030 char *compress_doc;
01031 char *mkdir_p;
01032
01033 pkg->specialDoc = rpmiobNew(0);
01034 pkg->specialDoc = rpmiobAppend(pkg->specialDoc, "DOCDIR=\"$RPM_BUILD_ROOT\"", 0);
01035 pkg->specialDoc = rpmiobAppend(pkg->specialDoc, buf, 1);
01036 pkg->specialDoc = rpmiobAppend(pkg->specialDoc, "export DOCDIR", 1);
01037 mkdir_p = rpmExpand("%{?__mkdir_p}%{!?__mkdir_p:mkdir -p}", NULL);
01038 if (!mkdir_p)
01039 mkdir_p = xstrdup("mkdir -p");
01040 pkg->specialDoc = rpmiobAppend(pkg->specialDoc, mkdir_p, 0);
01041 mkdir_p = _free(mkdir_p);
01042 pkg->specialDoc = rpmiobAppend(pkg->specialDoc, " \"$DOCDIR\"", 1);
01043
01044 compress_doc = rpmExpand("%{__compress_doc}", NULL);
01045 if (compress_doc && *compress_doc != '%')
01046 pkg->specialDoc = rpmiobAppend(pkg->specialDoc, compress_doc, 1);
01047 compress_doc = _free(compress_doc);
01048
01049
01050 *fileName = buf;
01051
01052 fl->passedSpecialDoc = 1;
01053 fl->isSpecialDoc = 1;
01054 }
01055
01056 pkg->specialDoc = rpmiobAppend(pkg->specialDoc, "cp -pr ", 0);
01057 pkg->specialDoc = rpmiobAppend(pkg->specialDoc, specialDocBuf, 0);
01058 pkg->specialDoc = rpmiobAppend(pkg->specialDoc, " \"$DOCDIR\"", 1);
01059 }
01060 }
01061
01062 return res;
01063 }
01064
01067 static int compareFileListRecs(const void * ap, const void * bp)
01068 {
01069 const char *aurl = ((FileListRec)ap)->fileURL;
01070 const char *a = NULL;
01071 const char *burl = ((FileListRec)bp)->fileURL;
01072 const char *b = NULL;
01073 (void) urlPath(aurl, &a);
01074 (void) urlPath(burl, &b);
01075 return strcmp(a, b);
01076 }
01077
01084 static int isDoc(FileList fl, const char * fileName)
01085 {
01086 int x = fl->docDirCount;
01087 size_t k, l;
01088
01089 k = strlen(fileName);
01090 while (x--) {
01091 l = strlen(fl->docDirs[x]);
01092 if (l < k && strncmp(fileName, fl->docDirs[x], l) == 0 && fileName[l] == '/')
01093 return 1;
01094 }
01095 return 0;
01096 }
01097
01104 static int checkHardLinks(FileList fl)
01105
01106 {
01107 FileListRec ilp, jlp;
01108 int i, j;
01109
01110 for (i = 0; i < fl->fileListRecsUsed; i++) {
01111 ilp = fl->fileList + i;
01112 if (!(S_ISREG(ilp->fl_mode) && ilp->fl_nlink > 1))
01113 continue;
01114 if (ilp->flags & (RPMFILE_EXCLUDE | RPMFILE_GHOST))
01115 continue;
01116
01117 for (j = i + 1; j < fl->fileListRecsUsed; j++) {
01118 jlp = fl->fileList + j;
01119 if (!S_ISREG(jlp->fl_mode))
01120 continue;
01121 if (ilp->fl_nlink != jlp->fl_nlink)
01122 continue;
01123 if (ilp->fl_ino != jlp->fl_ino)
01124 continue;
01125 if (ilp->fl_dev != jlp->fl_dev)
01126 continue;
01127 if (jlp->flags & (RPMFILE_EXCLUDE | RPMFILE_GHOST))
01128 continue;
01129 return 1;
01130 }
01131 }
01132 return 0;
01133 }
01134
01135 static int dncmp(const void * a, const void * b)
01136
01137 {
01138 const char ** aurlp = (const char **)a;
01139 const char ** burlp = (const char **)b;
01140 const char * adn;
01141 const char * bdn;
01142 (void) urlPath(*aurlp, &adn);
01143 (void) urlPath(*burlp, &bdn);
01144 return strcmp(adn, bdn);
01145 }
01146
01151 static void compressFilelist(Header h)
01152
01153
01154 {
01155 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
01156 const char ** fileNames;
01157 const char * fn;
01158 const char ** dirNames;
01159 const char ** baseNames;
01160 rpmuint32_t * dirIndexes;
01161 int count;
01162 int dirIndex = -1;
01163 int xx;
01164 int i;
01165
01166
01167
01168
01169
01170
01171
01172 if (headerIsEntry(h, RPMTAG_DIRNAMES)) {
01173 he->tag = RPMTAG_OLDFILENAMES;
01174 xx = headerDel(h, he, 0);
01175 return;
01176 }
01177
01178 he->tag = RPMTAG_OLDFILENAMES;
01179 xx = headerGet(h, he, 0);
01180 fileNames = he->p.argv;
01181 count = he->c;
01182 if (!xx || fileNames == NULL || count <= 0)
01183 return;
01184
01185 dirNames = alloca(sizeof(*dirNames) * count);
01186 baseNames = alloca(sizeof(*dirNames) * count);
01187 dirIndexes = alloca(sizeof(*dirIndexes) * count);
01188
01189 (void) urlPath(fileNames[0], &fn);
01190 if (fn[0] != '/') {
01191
01192 dirIndex = 0;
01193 dirNames[dirIndex] = "";
01194 for (i = 0; i < count; i++) {
01195 dirIndexes[i] = dirIndex;
01196 baseNames[i] = fileNames[i];
01197 }
01198 goto exit;
01199 }
01200
01201 for (i = 0; i < count; i++) {
01202 const char ** needle;
01203 char savechar;
01204 char * baseName;
01205 size_t len;
01206
01207 if (fileNames[i] == NULL)
01208 continue;
01209 baseName = strrchr(fileNames[i], '/') + 1;
01210 len = baseName - fileNames[i];
01211 needle = dirNames;
01212 savechar = *baseName;
01213 *baseName = '\0';
01214
01215 if (dirIndex < 0 ||
01216 (needle = bsearch(&fileNames[i], dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) {
01217 char *s = alloca(len + 1);
01218 memcpy(s, fileNames[i], len + 1);
01219 s[len] = '\0';
01220 dirIndexes[i] = ++dirIndex;
01221 dirNames[dirIndex] = s;
01222 } else
01223 dirIndexes[i] = needle - dirNames;
01224
01225
01226 *baseName = savechar;
01227 baseNames[i] = baseName;
01228 }
01229
01230 exit:
01231 if (count > 0) {
01232 he->tag = RPMTAG_DIRINDEXES;
01233 he->t = RPM_UINT32_TYPE;
01234 he->p.ui32p = dirIndexes;
01235 he->c = count;
01236 xx = headerPut(h, he, 0);
01237
01238 he->tag = RPMTAG_BASENAMES;
01239 he->t = RPM_STRING_ARRAY_TYPE;
01240 he->p.argv = baseNames;
01241 he->c = count;
01242 xx = headerPut(h, he, 0);
01243
01244 he->tag = RPMTAG_DIRNAMES;
01245 he->t = RPM_STRING_ARRAY_TYPE;
01246 he->p.argv = dirNames;
01247 he->c = dirIndex + 1;
01248 xx = headerPut(h, he, 0);
01249 }
01250
01251 fileNames = _free(fileNames);
01252
01253 he->tag = RPMTAG_OLDFILENAMES;
01254 xx = headerDel(h, he, 0);
01255 }
01256
01257 static rpmuint32_t getDigestAlgo(Header h, int isSrc)
01258
01259 {
01260 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
01261 static rpmuint32_t source_file_dalgo = 0;
01262 static rpmuint32_t binary_file_dalgo = 0;
01263 static int oneshot = 0;
01264 rpmuint32_t dalgo = 0;
01265 int xx;
01266
01267 if (!oneshot) {
01268 source_file_dalgo =
01269 rpmExpandNumeric("%{?_build_source_file_digest_algo}");
01270 binary_file_dalgo =
01271 rpmExpandNumeric("%{?_build_binary_file_digest_algo}");
01272 oneshot++;
01273 }
01274
01275 dalgo = (isSrc ? source_file_dalgo : binary_file_dalgo);
01276 switch (dalgo) {
01277 case PGPHASHALGO_SHA1:
01278 case PGPHASHALGO_MD2:
01279 case PGPHASHALGO_SHA256:
01280 case PGPHASHALGO_SHA384:
01281 case PGPHASHALGO_SHA512:
01282 (void) rpmlibNeedsFeature(h, "FileDigests", "4.6.0-1");
01283 he->tag = RPMTAG_FILEDIGESTALGO;
01284 he->t = RPM_UINT32_TYPE;
01285 he->p.ui32p = &dalgo;
01286 he->c = 1;
01287 xx = headerPut(h, he, 0);
01288
01289 case PGPHASHALGO_RIPEMD160:
01290 case PGPHASHALGO_TIGER192:
01291 case PGPHASHALGO_MD4:
01292 case PGPHASHALGO_RIPEMD128:
01293 case PGPHASHALGO_CRC32:
01294 case PGPHASHALGO_ADLER32:
01295 case PGPHASHALGO_CRC64:
01296 (void) rpmlibNeedsFeature(h, "FileDigestParameterized", "4.4.6-1");
01297 break;
01298 case PGPHASHALGO_MD5:
01299 case PGPHASHALGO_HAVAL_5_160:
01300 default:
01301 dalgo = PGPHASHALGO_MD5;
01302 break;
01303 }
01304
01305 return dalgo;
01306 }
01307
01317 static void genCpioListAndHeader( FileList fl,
01318 rpmfi * fip, Header h, int isSrc)
01319
01320
01321
01322
01323 {
01324 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
01325 const char * apath;
01326 rpmuint16_t ui16;
01327 rpmuint32_t ui32;
01328 int _addDotSlash = !isSrc;
01329 int apathlen = 0;
01330 int dpathlen = 0;
01331 int skipLen = 0;
01332 security_context_t scon = NULL;
01333 const char * sxfn;
01334 FileListRec flp;
01335 rpmuint32_t dalgo = getDigestAlgo(h, isSrc);
01336 char buf[BUFSIZ];
01337 int i, xx;
01338
01339
01340 qsort(fl->fileList, fl->fileListRecsUsed,
01341 sizeof(*(fl->fileList)), compareFileListRecs);
01342
01343
01344 if (! isSrc) {
01345 skipLen = 1;
01346 if (fl->prefix)
01347 skipLen += strlen(fl->prefix);
01348 }
01349
01350 sxfn = rpmGetPath("%{?_build_file_context_path}", NULL);
01351
01352 if (sxfn != NULL && *sxfn != '\0')
01353 xx = matchpathcon_init(sxfn);
01354
01355
01356 for (i = 0, flp = fl->fileList; i < fl->fileListRecsUsed; i++, flp++) {
01357 const char *s;
01358
01359
01360 while (i < (fl->fileListRecsUsed - 1) &&
01361 !strcmp(flp->fileURL, flp[1].fileURL)) {
01362
01363
01364
01365
01366
01367 flp[1].flags |= flp->flags;
01368
01369 if (!(flp[1].flags & RPMFILE_EXCLUDE))
01370 rpmlog(RPMLOG_WARNING, _("File listed twice: %s\n"),
01371 flp->fileURL);
01372
01373
01374 if (S_ISDIR(flp->fl_mode)) {
01375 if ((flp[1].specdFlags & (SPECD_DIRMODE | SPECD_DEFDIRMODE)) <
01376 (flp->specdFlags & (SPECD_DIRMODE | SPECD_DEFDIRMODE)))
01377 flp[1].fl_mode = flp->fl_mode;
01378 } else {
01379 if ((flp[1].specdFlags & (SPECD_FILEMODE | SPECD_DEFFILEMODE)) <
01380 (flp->specdFlags & (SPECD_FILEMODE | SPECD_DEFFILEMODE)))
01381 flp[1].fl_mode = flp->fl_mode;
01382 }
01383
01384
01385 if ((flp[1].specdFlags & (SPECD_UID | SPECD_DEFUID)) <
01386 (flp->specdFlags & (SPECD_UID | SPECD_DEFUID)))
01387 {
01388 flp[1].fl_uid = flp->fl_uid;
01389 flp[1].uname = flp->uname;
01390 }
01391
01392
01393 if ((flp[1].specdFlags & (SPECD_GID | SPECD_DEFGID)) <
01394 (flp->specdFlags & (SPECD_GID | SPECD_DEFGID)))
01395 {
01396 flp[1].fl_gid = flp->fl_gid;
01397 flp[1].gname = flp->gname;
01398 }
01399
01400
01401 if ((flp[1].specdFlags & (SPECD_VERIFY | SPECD_DEFVERIFY)) <
01402 (flp->specdFlags & (SPECD_VERIFY | SPECD_DEFVERIFY)))
01403 flp[1].verifyFlags = flp->verifyFlags;
01404
01405
01406
01407 flp++; i++;
01408 }
01409
01410
01411 if (flp->flags & RPMFILE_EXCLUDE) continue;
01412
01413
01414 (void) urlPath(flp->fileURL, &apath);
01415 apathlen += (strlen(apath) - skipLen + (_addDotSlash ? 3 : 1));
01416
01417
01418 dpathlen += (strlen(flp->diskURL) + 2);
01419
01420
01421
01422
01423
01424
01425 he->tag = RPMTAG_OLDFILENAMES;
01426 he->t = RPM_STRING_ARRAY_TYPE;
01427 he->p.argv = &flp->fileURL;
01428 he->c = 1;
01429 he->append = 1;
01430 xx = headerPut(h, he, 0);
01431 he->append = 0;
01432
01433
01434 ui32 = (rpmuint32_t) flp->fl_size;
01435 he->tag = RPMTAG_FILESIZES;
01436 he->t = RPM_UINT32_TYPE;
01437 he->p.ui32p = &ui32;
01438 he->c = 1;
01439 he->append = 1;
01440 xx = headerPut(h, he, 0);
01441 he->append = 0;
01442
01443 he->tag = RPMTAG_FILEUSERNAME;
01444 he->t = RPM_STRING_ARRAY_TYPE;
01445 he->p.argv = &flp->uname;
01446 he->c = 1;
01447 he->append = 1;
01448 xx = headerPut(h, he, 0);
01449 he->append = 0;
01450
01451 he->tag = RPMTAG_FILEGROUPNAME;
01452 he->t = RPM_STRING_ARRAY_TYPE;
01453 he->p.argv = &flp->gname;
01454 he->c = 1;
01455 he->append = 1;
01456 xx = headerPut(h, he, 0);
01457 he->append = 0;
01458
01459 ui32 = (rpmuint32_t) flp->fl_mtime;
01460 he->tag = RPMTAG_FILEMTIMES;
01461 he->t = RPM_UINT32_TYPE;
01462 he->p.ui32p = &ui32;
01463 he->c = 1;
01464 he->append = 1;
01465 xx = headerPut(h, he, 0);
01466 he->append = 0;
01467
01468 ui16 = (rpmuint16_t)flp->fl_mode;
01469 he->tag = RPMTAG_FILEMODES;
01470 he->t = RPM_UINT16_TYPE;
01471 he->p.ui16p = &ui16;
01472 he->c = 1;
01473 he->append = 1;
01474 xx = headerPut(h, he, 0);
01475 he->append = 0;
01476
01477 ui16 = (rpmuint16_t) flp->fl_rdev;
01478 he->tag = RPMTAG_FILERDEVS;
01479 he->t = RPM_UINT16_TYPE;
01480 he->p.ui16p = &ui16;
01481 he->c = 1;
01482 he->append = 1;
01483 xx = headerPut(h, he, 0);
01484 he->append = 0;
01485
01486 ui32 = (rpmuint32_t) flp->fl_dev;
01487 he->tag = RPMTAG_FILEDEVICES;
01488 he->t = RPM_UINT32_TYPE;
01489 he->p.ui32p = &ui32;
01490 he->c = 1;
01491 he->append = 1;
01492 xx = headerPut(h, he, 0);
01493 he->append = 0;
01494
01495 ui32 = (rpmuint32_t) flp->fl_ino;
01496 he->tag = RPMTAG_FILEINODES;
01497 he->t = RPM_UINT32_TYPE;
01498 he->p.ui32p = &ui32;
01499 he->c = 1;
01500 he->append = 1;
01501 xx = headerPut(h, he, 0);
01502 he->append = 0;
01503
01504
01505
01506 he->tag = RPMTAG_FILELANGS;
01507 he->t = RPM_STRING_ARRAY_TYPE;
01508 he->p.argv = &flp->langs;
01509 he->c = 1;
01510 he->append = 1;
01511 xx = headerPut(h, he, 0);
01512 he->append = 0;
01513
01514 buf[0] = '\0';
01515 if (S_ISREG(flp->fl_mode))
01516 (void) dodigest(dalgo, flp->diskURL, (unsigned char *)buf, 1, NULL);
01517 s = buf;
01518
01519 he->tag = RPMTAG_FILEDIGESTS;
01520 he->t = RPM_STRING_ARRAY_TYPE;
01521 he->p.argv = &s;
01522 he->c = 1;
01523 he->append = 1;
01524 xx = headerPut(h, he, 0);
01525 he->append = 0;
01526
01527 if (!(_rpmbuildFlags & 4)) {
01528 ui32 = dalgo;
01529 he->tag = RPMTAG_FILEDIGESTALGOS;
01530 he->t = RPM_UINT32_TYPE;
01531 he->p.ui32p = &ui32;
01532 he->c = 1;
01533 he->append = 1;
01534 xx = headerPut(h, he, 0);
01535 he->append = 0;
01536 }
01537
01538 buf[0] = '\0';
01539 if (S_ISLNK(flp->fl_mode)) {
01540 xx = Readlink(flp->diskURL, buf, BUFSIZ);
01541 if (xx >= 0)
01542 buf[xx] = '\0';
01543 if (fl->buildRootURL) {
01544 const char * buildRoot;
01545 (void) urlPath(fl->buildRootURL, &buildRoot);
01546
01547 if (buf[0] == '/' && strcmp(buildRoot, "/") &&
01548 !strncmp(buf, buildRoot, strlen(buildRoot))) {
01549 rpmlog(RPMLOG_ERR,
01550 _("Symlink points to BuildRoot: %s -> %s\n"),
01551 flp->fileURL, buf);
01552 fl->processingFailed = 1;
01553 }
01554 }
01555 }
01556 s = buf;
01557 he->tag = RPMTAG_FILELINKTOS;
01558 he->t = RPM_STRING_ARRAY_TYPE;
01559 he->p.argv = &s;
01560 he->c = 1;
01561 he->append = 1;
01562 xx = headerPut(h, he, 0);
01563 he->append = 0;
01564
01565 if (flp->flags & RPMFILE_GHOST) {
01566 flp->verifyFlags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE |
01567 RPMVERIFY_LINKTO | RPMVERIFY_MTIME);
01568 }
01569 ui32 = flp->verifyFlags;
01570 he->tag = RPMTAG_FILEVERIFYFLAGS;
01571 he->t = RPM_UINT32_TYPE;
01572 he->p.ui32p = &ui32;
01573 he->c = 1;
01574 he->append = 1;
01575 xx = headerPut(h, he, 0);
01576 he->append = 0;
01577
01578 if (!isSrc && isDoc(fl, flp->fileURL))
01579 flp->flags |= RPMFILE_DOC;
01580
01581 if (S_ISDIR(flp->fl_mode))
01582 flp->flags &= ~(RPMFILE_CONFIG|RPMFILE_DOC);
01583
01584 ui32 = flp->flags;
01585 he->tag = RPMTAG_FILEFLAGS;
01586 he->t = RPM_UINT32_TYPE;
01587 he->p.ui32p = &ui32;
01588 he->c = 1;
01589 he->append = 1;
01590 xx = headerPut(h, he, 0);
01591 he->append = 0;
01592
01593
01594 if (!(_rpmbuildFlags & 4) && sxfn != NULL && *sxfn != '\0')
01595 {
01596 static char *nocon = "";
01597
01598 if (matchpathcon(flp->fileURL, flp->fl_mode, &scon) || scon == NULL)
01599 scon = nocon;
01600
01601
01602 he->tag = RPMTAG_FILECONTEXTS;
01603 he->t = RPM_STRING_ARRAY_TYPE;
01604 he->p.argv = (const char **)&scon;
01605 he->c = 1;
01606 he->append = 1;
01607 xx = headerPut(h, he, 0);
01608 he->append = 0;
01609
01610
01611 if (scon != nocon) {
01612 freecon(scon);
01613 }
01614
01615 }
01616 }
01617
01618 if (sxfn != NULL && *sxfn != '\0') {
01619 matchpathcon_fini();
01620 }
01621
01622 sxfn = _free(sxfn);
01623
01624 if (_rpmbuildFlags & 4) {
01625 (void) rpmlibNeedsFeature(h, "PayloadFilesHavePrefix", "4.0-1");
01626 (void) rpmlibNeedsFeature(h, "CompressedFileNames", "3.0.4-1");
01627 }
01628
01629 compressFilelist(h);
01630
01631 { int scareMem = 0;
01632 void * ts = NULL;
01633 rpmfi fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem);
01634 char * a, * d;
01635
01636 if (fi == NULL) return;
01637
01638
01639 fi->te = xcalloc(1, sizeof(*((rpmte)fi->te)));
01640
01641 ((rpmte)fi->te)->type = TR_ADDED;
01642
01643 fi->dnl = _free(fi->dnl);
01644 fi->bnl = _free(fi->bnl);
01645 if (!scareMem) fi->dil = _free(fi->dil);
01646
01647
01648 fi->dnl = xmalloc(fi->fc * sizeof(*fi->dnl) + dpathlen + 1);
01649 d = (char *)(fi->dnl + fi->fc);
01650 *d = '\0';
01651
01652 fi->bnl = xmalloc(fi->fc * (sizeof(*fi->bnl) + sizeof(*fi->dil)));
01653
01654 fi->dil = (!scareMem)
01655 ? xcalloc(sizeof(*fi->dil), fi->fc)
01656 : (rpmuint32_t *)(fi->bnl + fi->fc);
01657
01658
01659
01660 fi->apath = xmalloc(fi->fc * sizeof(*fi->apath) + apathlen + 1);
01661 a = (char *)(fi->apath + fi->fc);
01662 *a = '\0';
01663
01664 fi->actions = _free(fi->actions);
01665 fi->actions = xcalloc(sizeof(*fi->actions), fi->fc);
01666 fi->fmapflags = xcalloc(sizeof(*fi->fmapflags), fi->fc);
01667 fi->astriplen = 0;
01668 if (fl->buildRootURL)
01669 fi->astriplen = strlen(fl->buildRootURL);
01670 fi->striplen = 0;
01671 fi->fuser = _free(fi->fuser);
01672 fi->fgroup = _free(fi->fgroup);
01673
01674
01675 if (fi->dil != NULL)
01676 for (i = 0, flp = fl->fileList; (unsigned)i < fi->fc; i++, flp++) {
01677 char * b;
01678
01679
01680 while (((flp - fl->fileList) < (fl->fileListRecsUsed - 1)) &&
01681 !strcmp(flp->fileURL, flp[1].fileURL))
01682 flp++;
01683
01684 if (flp->flags & RPMFILE_EXCLUDE) {
01685 i--;
01686 continue;
01687 }
01688
01689 {
01690
01691 size_t fnlen = strlen(flp->diskURL);
01692 if (fnlen > fi->fnlen) {
01693
01694 assert(fi->fn == NULL);
01695 fi->fnlen = fnlen;
01696 }
01697 }
01698
01699
01700
01701 fi->dil[i] = i;
01702
01703 fi->dnl[fi->dil[i]] = d;
01704
01705 d = stpcpy(d, flp->diskURL);
01706
01707
01708 for (b = d; b > fi->dnl[fi->dil[i]] && *b != '/'; b--)
01709 b[1] = b[0];
01710 b++;
01711 *b++ = '\0';
01712 fi->bnl[i] = b;
01713 d += 2;
01714
01715
01716
01717 fi->apath[i] = a;
01718
01719 if (_addDotSlash)
01720 a = stpcpy(a, "./");
01721 (void) urlPath(flp->fileURL, &apath);
01722 a = stpcpy(a, (apath + skipLen));
01723 a++;
01724
01725 if (flp->flags & RPMFILE_GHOST) {
01726 fi->actions[i] = FA_SKIP;
01727 continue;
01728 }
01729 fi->actions[i] = FA_COPYOUT;
01730 fi->fmapflags[i] = IOSM_MAP_PATH |
01731 IOSM_MAP_TYPE | IOSM_MAP_MODE | IOSM_MAP_UID | IOSM_MAP_GID;
01732 if (isSrc)
01733 fi->fmapflags[i] |= IOSM_FOLLOW_SYMLINKS;
01734
01735 if (S_ISREG(flp->fl_mode)) {
01736 int bingo = 1;
01737
01738 if (flp->fl_nlink > 1) {
01739 FileListRec jlp = flp + 1;
01740 int j = i + 1;
01741 for (; (unsigned)j < fi->fc; j++, jlp++) {
01742
01743 while (((jlp - fl->fileList) < (fl->fileListRecsUsed - 1)) &&
01744 !strcmp(jlp->fileURL, jlp[1].fileURL))
01745 jlp++;
01746 if (jlp->flags & RPMFILE_EXCLUDE) {
01747 j--;
01748 continue;
01749 }
01750 if (jlp->flags & RPMFILE_GHOST)
01751 continue;
01752 if (!S_ISREG(jlp->fl_mode))
01753 continue;
01754 if (flp->fl_nlink != jlp->fl_nlink)
01755 continue;
01756 if (flp->fl_ino != jlp->fl_ino)
01757 continue;
01758 if (flp->fl_dev != jlp->fl_dev)
01759 continue;
01760 bingo = 0;
01761 break;
01762 }
01763 }
01764 if (bingo)
01765 fl->totalFileSize += flp->fl_size;
01766 }
01767 }
01768
01769 ui32 = fl->totalFileSize;
01770 he->tag = RPMTAG_SIZE;
01771 he->t = RPM_UINT32_TYPE;
01772 he->p.ui32p = &ui32;
01773 he->c = 1;
01774 xx = headerPut(h, he, 0);
01775
01776
01777 if (fip)
01778 *fip = fi;
01779 else
01780 fi = rpmfiFree(fi);
01781
01782 }
01783 }
01784
01787 static FileListRec freeFileList( FileListRec fileList,
01788 int count)
01789
01790 {
01791 while (count--) {
01792 fileList[count].diskURL = _free(fileList[count].diskURL);
01793 fileList[count].fileURL = _free(fileList[count].fileURL);
01794 fileList[count].langs = _free(fileList[count].langs);
01795 }
01796 fileList = _free(fileList);
01797 return NULL;
01798 }
01799
01800
01801 static rpmRC recurseDir(FileList fl, const char * diskURL)
01802
01803
01804
01805
01806
01807
01808 ;
01809
01817 static int addFile(FileList fl, const char * diskURL,
01818 struct stat * statp)
01819
01820
01821
01822
01823
01824
01825
01826 {
01827 const char *fn = xstrdup(diskURL);
01828 const char *fileURL = fn;
01829 struct stat statbuf;
01830 mode_t fileMode;
01831 uid_t fileUid;
01832 gid_t fileGid;
01833 const char *fileUname;
01834 const char *fileGname;
01835 char *lang;
01836 rpmRC rc = RPMRC_OK;
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849 { const char *fileName;
01850 int urltype = urlPath(fileURL, &fileName);
01851 switch (urltype) {
01852 case URL_IS_PATH:
01853 fileURL += (fileName - fileURL);
01854 if (fl->buildRootURL && strcmp(fl->buildRootURL, "/")) {
01855 size_t nb = strlen(fl->buildRootURL);
01856 const char * s = fileURL + nb;
01857 char * t = (char *) fileURL;
01858 (void) memmove(t, s, nb);
01859 }
01860 fileURL = fn;
01861 break;
01862 default:
01863 if (fl->buildRootURL && strcmp(fl->buildRootURL, "/"))
01864 fileURL += strlen(fl->buildRootURL);
01865 break;
01866 }
01867 }
01868
01869
01870 if (*fileURL == '\0')
01871 fileURL = "/";
01872
01873
01874 if (!fl->inFtw && fl->prefix) {
01875 const char *prefixTest;
01876 const char *prefixPtr = fl->prefix;
01877
01878 (void) urlPath(fileURL, &prefixTest);
01879 while (*prefixPtr && *prefixTest && (*prefixTest == *prefixPtr)) {
01880 prefixPtr++;
01881 prefixTest++;
01882 }
01883 if (*prefixPtr || (*prefixTest && *prefixTest != '/')) {
01884 rpmlog(RPMLOG_ERR, _("File doesn't match prefix (%s): %s\n"),
01885 fl->prefix, fileURL);
01886 fl->processingFailed = 1;
01887 rc = RPMRC_FAIL;
01888 goto exit;
01889 }
01890 }
01891
01892 if (statp == NULL) {
01893 statp = &statbuf;
01894 memset(statp, 0, sizeof(*statp));
01895 if (fl->devtype) {
01896 time_t now = time(NULL);
01897
01898
01899 statp->st_nlink = 1;
01900 statp->st_rdev =
01901 ((fl->devmajor & 0xff) << 8) | (fl->devminor & 0xff);
01902 statp->st_dev = statp->st_rdev;
01903 statp->st_mode = (fl->devtype == 'b' ? S_IFBLK : S_IFCHR);
01904 statp->st_mode |= (fl->cur_ar.ar_fmode & 0777);
01905 statp->st_atime = now;
01906 statp->st_mtime = now;
01907 statp->st_ctime = now;
01908 } else if (Lstat(diskURL, statp)) {
01909 if (fl->currentFlags & RPMFILE_OPTIONAL) {
01910 rpmlog(RPMLOG_WARNING, _("Optional file not found: %s\n"), diskURL);
01911 rc = RPMRC_OK;
01912 } else {
01913 rpmlog(RPMLOG_ERR, _("File not found: %s\n"), diskURL);
01914 fl->processingFailed = 1;
01915 rc = RPMRC_FAIL;
01916 }
01917 goto exit;
01918 }
01919 }
01920
01921 if ((! fl->isDir) && S_ISDIR(statp->st_mode)) {
01922
01923 rc = recurseDir(fl, diskURL);
01924 goto exit;
01925
01926 }
01927
01928 fileMode = statp->st_mode;
01929 fileUid = statp->st_uid;
01930 fileGid = statp->st_gid;
01931
01932 if (S_ISDIR(fileMode) && fl->cur_ar.ar_dmodestr) {
01933 fileMode &= S_IFMT;
01934 fileMode |= fl->cur_ar.ar_dmode;
01935 } else if (fl->cur_ar.ar_fmodestr != NULL) {
01936 fileMode &= S_IFMT;
01937 fileMode |= fl->cur_ar.ar_fmode;
01938 }
01939 if (fl->cur_ar.ar_user) {
01940 fileUname = getUnameS(fl->cur_ar.ar_user);
01941 } else {
01942 fileUname = getUname(fileUid);
01943 }
01944 if (fl->cur_ar.ar_group) {
01945 fileGname = getGnameS(fl->cur_ar.ar_group);
01946 } else {
01947 fileGname = getGname(fileGid);
01948 }
01949
01950
01951 if (fileUname == NULL)
01952 fileUname = getUname(getuid());
01953 if (fileGname == NULL)
01954 fileGname = getGname(getgid());
01955
01956
01957 if (fl->fileListRecsUsed == fl->fileListRecsAlloced) {
01958 fl->fileListRecsAlloced += 128;
01959 fl->fileList = xrealloc(fl->fileList,
01960 fl->fileListRecsAlloced * sizeof(*(fl->fileList)));
01961 }
01962
01963 { FileListRec flp = &fl->fileList[fl->fileListRecsUsed];
01964 int i;
01965
01966 flp->fl_st = *statp;
01967 flp->fl_mode = fileMode;
01968 flp->fl_uid = fileUid;
01969 flp->fl_gid = fileGid;
01970
01971 flp->fileURL = xstrdup(fileURL);
01972 flp->diskURL = xstrdup(diskURL);
01973 flp->uname = fileUname;
01974 flp->gname = fileGname;
01975
01976 if (fl->currentLangs && fl->nLangs > 0) {
01977 char * ncl;
01978 size_t nl = 0;
01979
01980 for (i = 0; i < fl->nLangs; i++)
01981 nl += strlen(fl->currentLangs[i]) + 1;
01982
01983 flp->langs = ncl = xmalloc(nl);
01984 for (i = 0; i < fl->nLangs; i++) {
01985 const char *ocl;
01986 if (i) *ncl++ = '|';
01987 for (ocl = fl->currentLangs[i]; *ocl != '\0'; ocl++)
01988 *ncl++ = *ocl;
01989 *ncl = '\0';
01990 }
01991 } else if (! parseForRegexLang(fileURL, &lang)) {
01992 flp->langs = xstrdup(lang);
01993 } else {
01994 flp->langs = xstrdup("");
01995 }
01996
01997 flp->flags = fl->currentFlags;
01998 flp->specdFlags = fl->currentSpecdFlags;
01999 flp->verifyFlags = fl->currentVerifyFlags;
02000 }
02001
02002 fl->fileListRecsUsed++;
02003 fl->fileCount++;
02004
02005 exit:
02006 fn = _free(fn);
02007 return rc;
02008 }
02009
02016 static rpmRC recurseDir(FileList fl, const char * diskURL)
02017 {
02018 char * ftsSet[2];
02019 FTS * ftsp;
02020 FTSENT * fts;
02021 int myFtsOpts = (FTS_COMFOLLOW | FTS_NOCHDIR | FTS_PHYSICAL);
02022 rpmRC rc = RPMRC_FAIL;
02023
02024 fl->inFtw = 1;
02025 fl->isDir = 1;
02026
02027 ftsSet[0] = (char *) diskURL;
02028 ftsSet[1] = NULL;
02029 ftsp = Fts_open(ftsSet, myFtsOpts, NULL);
02030 while ((fts = Fts_read(ftsp)) != NULL) {
02031 switch (fts->fts_info) {
02032 case FTS_D:
02033 case FTS_F:
02034 case FTS_SL:
02035 case FTS_SLNONE:
02036 case FTS_DEFAULT:
02037 rc = addFile(fl, fts->fts_accpath, fts->fts_statp);
02038 break;
02039 case FTS_DOT:
02040 case FTS_DP:
02041 rc = 0;
02042 break;
02043 case FTS_NS:
02044 case FTS_DNR:
02045 case FTS_ERR:
02046 case FTS_DC:
02047 case FTS_NSOK:
02048 case FTS_INIT:
02049 case FTS_W:
02050 default:
02051 rc = RPMRC_FAIL;
02052 break;
02053 }
02054 if (rc != RPMRC_OK)
02055 break;
02056 }
02057 (void) Fts_close(ftsp);
02058
02059 fl->isDir = 0;
02060 fl->inFtw = 0;
02061
02062 return rc;
02063 }
02064
02073 static rpmRC processMetadataFile(Package pkg, FileList fl, const char * fileURL,
02074 rpmTag tag)
02075
02076
02077
02078
02079
02080
02081
02082 {
02083 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
02084 const char * buildURL = "%{_builddir}/%{?buildsubdir}/";
02085 const char * fn = NULL;
02086 const char * apkt = NULL;
02087 rpmiob iob = NULL;
02088 rpmuint8_t * pkt = NULL;
02089 ssize_t pktlen = 0;
02090 int absolute = 0;
02091 rpmRC rc = RPMRC_FAIL;
02092 int xx;
02093
02094 (void) urlPath(fileURL, &fn);
02095 if (*fn == '/') {
02096 fn = rpmGenPath(fl->buildRootURL, NULL, fn);
02097 absolute = 1;
02098 } else
02099 fn = rpmGenPath(buildURL, NULL, fn);
02100
02101 switch (tag) {
02102 default:
02103 rpmlog(RPMLOG_ERR, _("%s: can't load unknown tag (%d).\n"),
02104 fn, tag);
02105 goto exit;
02106 break;
02107 case RPMTAG_PUBKEYS:
02108 if ((xx = pgpReadPkts(fn, &pkt, (size_t *)&pktlen)) <= 0) {
02109 rpmlog(RPMLOG_ERR, _("%s: public key read failed.\n"), fn);
02110 goto exit;
02111 }
02112 if (xx != PGPARMOR_PUBKEY) {
02113 rpmlog(RPMLOG_ERR, _("%s: not an armored public key.\n"), fn);
02114 goto exit;
02115 }
02116 apkt = pgpArmorWrap(PGPARMOR_PUBKEY, pkt, pktlen);
02117 break;
02118 case RPMTAG_POLICIES:
02119 xx = rpmiobSlurp(fn, &iob);
02120 if (!(xx == 0 && iob != NULL)) {
02121 rpmlog(RPMLOG_ERR, _("%s: *.te policy read failed.\n"), fn);
02122 goto exit;
02123 }
02124 apkt = (const char *) iob->b;
02125
02126 iob->b = (rpmuint8_t *)xcalloc(1, sizeof(*iob->b));
02127 iob->blen = 0;
02128 break;
02129 }
02130
02131 he->tag = tag;
02132 he->t = RPM_STRING_ARRAY_TYPE;
02133 he->p.argv = &apkt;
02134 he->c = 1;
02135 he->append = 1;
02136 xx = headerPut(pkg->header, he, 0);
02137 he->append = 0;
02138
02139 rc = RPMRC_OK;
02140 if (absolute)
02141 rc = addFile(fl, fn, NULL);
02142
02143 exit:
02144 apkt = _free(apkt);
02145 pkt = _free(pkt);
02146 iob = rpmiobFree(iob);
02147 fn = _free(fn);
02148 if (rc != RPMRC_OK)
02149 fl->processingFailed = 1;
02150 return rc;
02151 }
02152
02160 static rpmRC processBinaryFile( Package pkg, FileList fl,
02161 const char * fileURL)
02162
02163
02164
02165
02166
02167 {
02168 int quote = 1;
02169 int doGlob;
02170 const char *diskURL = NULL;
02171 rpmRC rc = RPMRC_OK;
02172 int xx;
02173
02174 doGlob = Glob_pattern_p(fileURL, quote);
02175
02176
02177 { const char * fileName;
02178 (void) urlPath(fileURL, &fileName);
02179 if (*fileName != '/') {
02180 rpmlog(RPMLOG_ERR, _("File needs leading \"/\": %s\n"),
02181 fileName);
02182 rc = RPMRC_FAIL;
02183 goto exit;
02184 }
02185 }
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195 diskURL = rpmGenPath(fl->buildRootURL, NULL, fileURL);
02196
02197 if (doGlob) {
02198 const char ** argv = NULL;
02199 int argc = 0;
02200 int i;
02201
02202
02203 if (fl->noGlob) {
02204 rpmlog(RPMLOG_ERR, _("Glob not permitted: %s\n"),
02205 diskURL);
02206 rc = RPMRC_FAIL;
02207 goto exit;
02208 }
02209
02210 xx = rpmGlob(diskURL, &argc, &argv);
02211 if (xx == 0 && argc >= 1) {
02212 for (i = 0; i < argc; i++) {
02213 rc = addFile(fl, argv[i], NULL);
02214 argv[i] = _free(argv[i]);
02215 }
02216 argv = _free(argv);
02217 } else {
02218 if (fl->currentFlags & RPMFILE_OPTIONAL) {
02219 rpmlog(RPMLOG_WARNING, _("Optional file not found by glob: %s\n"),
02220 diskURL);
02221 rc = RPMRC_OK;
02222 } else {
02223 rpmlog(RPMLOG_ERR, _("File not found by glob: %s\n"),
02224 diskURL);
02225 rc = RPMRC_FAIL;
02226 }
02227 goto exit;
02228 }
02229 } else
02230 rc = addFile(fl, diskURL, NULL);
02231
02232 exit:
02233 diskURL = _free(diskURL);
02234 if (rc != RPMRC_OK)
02235 fl->processingFailed = 1;
02236 return rc;
02237 }
02238
02241 static rpmRC processPackageFiles(Spec spec, Package pkg,
02242 int installSpecialDoc, int test)
02243
02244
02245
02246
02247
02248 {
02249 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
02250 struct FileList_s fl;
02251 ARGV_t files = NULL;
02252 ARGV_t fp;
02253 const char *fileName;
02254 char buf[BUFSIZ];
02255 struct AttrRec_s arbuf;
02256 AttrRec specialDocAttrRec = &arbuf;
02257 char *specialDoc = NULL;
02258 int xx;
02259
02260 nullAttrRec(specialDocAttrRec);
02261 pkg->cpioList = NULL;
02262
02263 if (pkg->fileFile) {
02264 char *saveptr = NULL;
02265 char *filesFiles = xstrdup(pkg->fileFile);
02266
02267 char *token = strtok_r(filesFiles, ",", &saveptr);
02268
02269 do {
02270 const char *ffn;
02271 FILE * f;
02272 FD_t fd;
02273
02274
02275 if (*token == '/') {
02276 ffn = rpmGetPath(token, NULL);
02277 } else {
02278
02279 ffn = rpmGetPath("%{_builddir}/",
02280 (spec->buildSubdir ? spec->buildSubdir : "") ,
02281 "/", token, NULL);
02282 }
02283
02284 fd = Fopen(ffn, "r.fpio");
02285
02286 if (fd == NULL || Ferror(fd)) {
02287 rpmlog(RPMLOG_ERR,
02288 _("Could not open %%files file %s: %s\n"),
02289 ffn, Fstrerror(fd));
02290 return RPMRC_FAIL;
02291 }
02292 ffn = _free(ffn);
02293
02294 f = fdGetFp(fd);
02295 if (f != NULL) {
02296 while (fgets(buf, (int)sizeof(buf), f)) {
02297 handleComments(buf);
02298 if (expandMacros(spec, spec->macros, buf, sizeof(buf))) {
02299 rpmlog(RPMLOG_ERR, _("line: %s\n"), buf);
02300 return RPMRC_FAIL;
02301 }
02302 pkg->fileList = rpmiobAppend(pkg->fileList, buf, 0);
02303 }
02304 }
02305 (void) Fclose(fd);
02306 } while((token = strtok_r(NULL, ",", &saveptr)) != NULL);
02307 filesFiles = _free(filesFiles);
02308 }
02309
02310
02311 memset(&fl, 0, sizeof(fl));
02312
02313 fl.buildRootURL = rpmGenPath(spec->rootURL, "%{?buildroot}", NULL);
02314
02315 he->tag = RPMTAG_DEFAULTPREFIX;
02316 xx = headerGet(pkg->header, he, 0);
02317 fl.prefix = he->p.str;
02318
02319 fl.fileCount = 0;
02320 fl.totalFileSize = 0;
02321 fl.processingFailed = 0;
02322
02323 fl.passedSpecialDoc = 0;
02324 fl.isSpecialDoc = 0;
02325
02326 fl.isDir = 0;
02327 fl.inFtw = 0;
02328 fl.currentFlags = 0;
02329 fl.currentVerifyFlags = 0;
02330
02331 fl.noGlob = 0;
02332 fl.devtype = 0;
02333 fl.devmajor = 0;
02334 fl.devminor = 0;
02335
02336 nullAttrRec(&fl.cur_ar);
02337 nullAttrRec(&fl.def_ar);
02338 dupAttrRec(&root_ar, &fl.def_ar);
02339
02340 fl.defVerifyFlags = RPMVERIFY_ALL;
02341 fl.nLangs = 0;
02342 fl.currentLangs = NULL;
02343
02344 fl.currentSpecdFlags = 0;
02345 fl.defSpecdFlags = 0;
02346
02347 fl.docDirCount = 0;
02348 #if defined(RPM_VENDOR_OPENPKG)
02349
02350 #else
02351 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/doc");
02352 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/man");
02353 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/info");
02354 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/X11R6/man");
02355 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/share/doc");
02356 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/share/man");
02357 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/share/info");
02358 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/src/examples");
02359 fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_docdir}", NULL);
02360 fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_mandir}", NULL);
02361 fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_infodir}", NULL);
02362 fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_javadocdir}", NULL);
02363 fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_examplesdir}", NULL);
02364 #endif
02365
02366 fl.fileList = NULL;
02367 fl.fileListRecsAlloced = 0;
02368 fl.fileListRecsUsed = 0;
02369
02370 xx = argvSplit(&files, rpmiobStr(pkg->fileList), "\n");
02371
02372 for (fp = files; *fp != NULL; fp++) {
02373 const char * s;
02374 s = *fp;
02375 SKIPSPACE(s);
02376 if (*s == '\0')
02377 continue;
02378 fileName = NULL;
02379
02380 strncpy(buf, s, sizeof(buf)-1);
02381 buf[sizeof(buf)-1] = '\0';
02382
02383
02384
02385 fl.isDir = 0;
02386 fl.inFtw = 0;
02387 fl.currentFlags = 0;
02388
02389 fl.currentSpecdFlags = ((unsigned)fl.defSpecdFlags) >> 8;
02390 fl.currentVerifyFlags = fl.defVerifyFlags;
02391 fl.isSpecialDoc = 0;
02392
02393 fl.noGlob = 0;
02394 fl.devtype = 0;
02395 fl.devmajor = 0;
02396 fl.devminor = 0;
02397
02398
02399 if (fl.currentLangs) {
02400 int i;
02401 for (i = 0; i < fl.nLangs; i++)
02402
02403 fl.currentLangs[i] = _free(fl.currentLangs[i]);
02404
02405 fl.currentLangs = _free(fl.currentLangs);
02406 }
02407 fl.nLangs = 0;
02408
02409 dupAttrRec(&fl.def_ar, &fl.cur_ar);
02410
02411
02412 if (parseForVerify(buf, &fl) != RPMRC_OK)
02413 continue;
02414 if (parseForAttr(buf, &fl) != RPMRC_OK)
02415 continue;
02416 if (parseForDev(buf, &fl) != RPMRC_OK)
02417 continue;
02418 if (parseForConfig(buf, &fl) != RPMRC_OK)
02419 continue;
02420 if (parseForLang(buf, &fl) != RPMRC_OK)
02421 continue;
02422
02423 if (parseForSimple(spec, pkg, buf, &fl, &fileName) != RPMRC_OK)
02424
02425 continue;
02426
02427 if (fileName == NULL)
02428 continue;
02429
02430 if (fl.isSpecialDoc) {
02431
02432 specialDoc = _free(specialDoc);
02433 specialDoc = xstrdup(fileName);
02434 dupAttrRec(&fl.cur_ar, specialDocAttrRec);
02435 } else if (fl.currentFlags & RPMFILE_PUBKEY) {
02436
02437 (void) processMetadataFile(pkg, &fl, fileName, RPMTAG_PUBKEYS);
02438
02439 } else if (fl.currentFlags & RPMFILE_POLICY) {
02440
02441 (void) processMetadataFile(pkg, &fl, fileName, RPMTAG_POLICIES);
02442
02443 } else {
02444
02445 (void) processBinaryFile(pkg, &fl, fileName);
02446
02447 }
02448 }
02449
02450
02451 if (specialDoc) {
02452 if (installSpecialDoc) {
02453 int _missing_doc_files_terminate_build =
02454 rpmExpandNumeric("%{?_missing_doc_files_terminate_build}");
02455 rpmRC rc;
02456
02457 rc = doScript(spec, RPMBUILD_STRINGBUF, "%doc", pkg->specialDoc, test);
02458 if (rc != RPMRC_OK && _missing_doc_files_terminate_build)
02459 fl.processingFailed = 1;
02460 }
02461
02462
02463 fl.isDir = 0;
02464 fl.inFtw = 0;
02465 fl.currentFlags = 0;
02466 fl.currentVerifyFlags = fl.defVerifyFlags;
02467
02468 fl.noGlob = 0;
02469 fl.devtype = 0;
02470 fl.devmajor = 0;
02471 fl.devminor = 0;
02472
02473
02474 if (fl.currentLangs) {
02475 int i;
02476 for (i = 0; i < fl.nLangs; i++)
02477
02478 fl.currentLangs[i] = _free(fl.currentLangs[i]);
02479
02480 fl.currentLangs = _free(fl.currentLangs);
02481 }
02482 fl.nLangs = 0;
02483
02484 dupAttrRec(specialDocAttrRec, &fl.cur_ar);
02485 freeAttrRec(specialDocAttrRec);
02486
02487
02488 (void) processBinaryFile(pkg, &fl, specialDoc);
02489
02490
02491 specialDoc = _free(specialDoc);
02492 }
02493
02494 files = argvFree(files);
02495
02496 if (fl.processingFailed)
02497 goto exit;
02498
02499
02500 if (checkHardLinks(&fl))
02501 (void) rpmlibNeedsFeature(pkg->header,
02502 "PartialHardlinkSets", "4.0.4-1");
02503
02504 genCpioListAndHeader(&fl, &pkg->cpioList, pkg->header, 0);
02505
02506 if (spec->timeCheck)
02507 timeCheck(spec->timeCheck, pkg->header);
02508
02509 exit:
02510 fl.buildRootURL = _free(fl.buildRootURL);
02511 fl.prefix = _free(fl.prefix);
02512
02513 freeAttrRec(&fl.cur_ar);
02514 freeAttrRec(&fl.def_ar);
02515
02516 if (fl.currentLangs) {
02517 int i;
02518 for (i = 0; i < fl.nLangs; i++)
02519
02520 fl.currentLangs[i] = _free(fl.currentLangs[i]);
02521
02522 fl.currentLangs = _free(fl.currentLangs);
02523 }
02524
02525 fl.fileList = freeFileList(fl.fileList, fl.fileListRecsUsed);
02526 while (fl.docDirCount--)
02527 fl.docDirs[fl.docDirCount] = _free(fl.docDirs[fl.docDirCount]);
02528 return (fl.processingFailed ? RPMRC_FAIL : RPMRC_OK);
02529 }
02530
02531 int initSourceHeader(Spec spec, rpmiob *sfp)
02532 {
02533 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
02534 HeaderIterator hi;
02535 rpmiob sourceFiles;
02536 struct Source *srcPtr;
02537 static rpmTag classTag = 0xffffffff;
02538 int xx;
02539 size_t i;
02540
02541 if (classTag == 0xffffffff)
02542 classTag = tagValue("Class");
02543
02544
02545 if (!spec->sourceHdrInit) {
02546 for (hi = headerInit(spec->packages->header);
02547 headerNext(hi, he, 0);
02548 he->p.ptr = _free(he->p.ptr))
02549 {
02550 switch (he->tag) {
02551 case RPMTAG_NAME:
02552 case RPMTAG_VERSION:
02553 case RPMTAG_RELEASE:
02554 case RPMTAG_DISTEPOCH:
02555 case RPMTAG_EPOCH:
02556 case RPMTAG_SUMMARY:
02557 case RPMTAG_DESCRIPTION:
02558 case RPMTAG_PACKAGER:
02559 case RPMTAG_DISTRIBUTION:
02560 case RPMTAG_DISTURL:
02561 case RPMTAG_VENDOR:
02562 case RPMTAG_LICENSE:
02563 case RPMTAG_GROUP:
02564 case RPMTAG_OS:
02565 case RPMTAG_ARCH:
02566 case RPMTAG_CHANGELOGTIME:
02567 case RPMTAG_CHANGELOGNAME:
02568 case RPMTAG_CHANGELOGTEXT:
02569 case RPMTAG_URL:
02570 case RPMTAG_ICON:
02571 case RPMTAG_GIF:
02572 case RPMTAG_XPM:
02573 case HEADER_I18NTABLE:
02574 #if defined(RPM_VENDOR_OPENPKG)
02575
02576 case RPMTAG_PROVIDENAME:
02577 case RPMTAG_PROVIDEVERSION:
02578 case RPMTAG_PROVIDEFLAGS:
02579 #endif
02580 if (he->p.ptr)
02581 xx = headerPut(spec->sourceHeader, he, 0);
02582 break;
02583 default:
02584 if (classTag == he->tag && he->p.ptr != NULL)
02585 xx = headerPut(spec->sourceHeader, he, 0);
02586 break;
02587 }
02588 }
02589 hi = headerFini(hi);
02590
02591 if (spec->BANames && spec->BACount > 0) {
02592 he->tag = RPMTAG_BUILDARCHS;
02593 he->t = RPM_STRING_ARRAY_TYPE;
02594 he->p.argv = spec->BANames;
02595 he->c = spec->BACount;
02596 xx = headerPut(spec->sourceHeader, he, 0);
02597 }
02598
02599
02600 if (spec->foo)
02601 for (i = 0; i < spec->nfoo; i++) {
02602 const char * str = spec->foo[i].str;
02603 rpmTag tag = spec->foo[i].tag;
02604 rpmiob iob = spec->foo[i].iob;
02605 char * s;
02606
02607 if (str == NULL || iob == NULL)
02608 continue;
02609
02610
02611 if (!xstrcasecmp(str, "track")) {
02612 he->p.str = rpmExpand("%{?__vcheck}", NULL);
02613 if (!(he->p.str != NULL && he->p.str[0] != '\0')) {
02614 he->p.str = _free(he->p.str);
02615 continue;
02616 }
02617 he->tag = tagValue("Trackprog");
02618 he->t = RPM_STRING_TYPE;
02619 he->c = 1;
02620 xx = headerPut(spec->sourceHeader, he, 0);
02621 he->p.str = _free(he->p.str);
02622 }
02623
02624 s = rpmiobStr(iob);
02625 he->tag = tag;
02626 he->append = headerIsEntry(spec->sourceHeader, tag);
02627 if (he->append) {
02628 he->t = RPM_STRING_ARRAY_TYPE;
02629 he->p.argv = (const char **) &s;
02630 he->c = 1;
02631 } else {
02632 he->t = RPM_STRING_TYPE;
02633 he->p.str = s;
02634 he->c = 1;
02635 }
02636 xx = headerPut(spec->sourceHeader, he, 0);
02637 he->append = 0;
02638 }
02639 }
02640
02641 if (sfp != NULL && *sfp != NULL)
02642 sourceFiles = *sfp;
02643 else
02644 sourceFiles = rpmiobNew(0);
02645
02646
02647 sourceFiles = rpmiobAppend(sourceFiles, spec->specFile, 1);
02648 if (spec->sourceHeader != NULL)
02649 for (srcPtr = spec->sources; srcPtr != NULL; srcPtr = srcPtr->next) {
02650 { const char * sfn;
02651
02652 sfn = rpmGetPath( ((srcPtr->flags & RPMFILE_GHOST) ? "!" : ""),
02653 #if defined(RPM_VENDOR_OPENPKG)
02654 getSourceDir(srcPtr->flags, srcPtr->source), srcPtr->source, NULL);
02655 #else
02656 getSourceDir(srcPtr->flags), srcPtr->source, NULL);
02657 #endif
02658
02659 sourceFiles = rpmiobAppend(sourceFiles, sfn, 1);
02660 sfn = _free(sfn);
02661 }
02662
02663 if (spec->sourceHdrInit)
02664 continue;
02665
02666 if (srcPtr->flags & RPMFILE_SOURCE) {
02667 he->tag = RPMTAG_SOURCE;
02668 he->t = RPM_STRING_ARRAY_TYPE;
02669 he->p.argv = &srcPtr->source;
02670 he->c = 1;
02671 he->append = 1;
02672 xx = headerPut(spec->sourceHeader, he, 0);
02673 he->append = 0;
02674 if (srcPtr->flags & RPMFILE_GHOST) {
02675 he->tag = RPMTAG_NOSOURCE;
02676 he->t = RPM_UINT32_TYPE;
02677 he->p.ui32p = &srcPtr->num;
02678 he->c = 1;
02679 he->append = 1;
02680 xx = headerPut(spec->sourceHeader, he, 0);
02681 he->append = 0;
02682 }
02683 }
02684 if (srcPtr->flags & RPMFILE_PATCH) {
02685 he->tag = RPMTAG_PATCH;
02686 he->t = RPM_STRING_ARRAY_TYPE;
02687 he->p.argv = &srcPtr->source;
02688 he->c = 1;
02689 he->append = 1;
02690 xx = headerPut(spec->sourceHeader, he, 0);
02691 he->append = 0;
02692 if (srcPtr->flags & RPMFILE_GHOST) {
02693 he->tag = RPMTAG_NOPATCH;
02694 he->t = RPM_UINT32_TYPE;
02695 he->p.ui32p = &srcPtr->num;
02696 he->c = 1;
02697 he->append = 1;
02698 xx = headerPut(spec->sourceHeader, he, 0);
02699 he->append = 0;
02700 }
02701 }
02702 }
02703
02704 if (sfp == NULL)
02705 sourceFiles = rpmiobFree(sourceFiles);
02706
02707 spec->sourceHdrInit = 1;
02708
02709
02710 return 0;
02711
02712 }
02713
02714 int processSourceFiles(Spec spec)
02715 {
02716 rpmiob sourceFiles, *sfp = &sourceFiles;
02717 int x, isSpec = 1;
02718 struct FileList_s fl;
02719 ARGV_t files = NULL;
02720 ARGV_t fp;
02721 int rc;
02722
02723 char _srcdefattr_buf[BUFSIZ];
02724 char *_srcdefattr;
02725 int xx;
02726
02727 _srcdefattr = rpmExpand("%{?_srcdefattr}", NULL);
02728
02729 *sfp = rpmiobNew(0);
02730 x = initSourceHeader(spec, sfp);
02731
02732
02733 memset(&fl, 0, sizeof(fl));
02734 if (_srcdefattr && *_srcdefattr) {
02735 xx = snprintf(_srcdefattr_buf, sizeof(_srcdefattr_buf), "%%defattr %s", _srcdefattr);
02736 _srcdefattr_buf[sizeof(_srcdefattr_buf)-1] = '\0';
02737 xx = parseForAttr(_srcdefattr_buf, &fl);
02738 }
02739
02740
02741 fl.fileList = xcalloc((spec->numSources + 1), sizeof(*fl.fileList));
02742 rc = fl.processingFailed = 0;
02743 fl.fileListRecsUsed = 0;
02744 fl.totalFileSize = 0;
02745 fl.prefix = NULL;
02746 fl.buildRootURL = NULL;
02747
02748 xx = argvSplit(&files, rpmiobStr(*sfp), "\n");
02749
02750
02751 x = 0;
02752 for (fp = files; *fp != NULL; fp++) {
02753 const char * diskURL, *diskPath;
02754 FileListRec flp;
02755
02756 diskURL = *fp;
02757 SKIPSPACE(diskURL);
02758 if (! *diskURL)
02759 continue;
02760
02761 flp = &fl.fileList[x];
02762
02763 flp->flags = isSpec ? RPMFILE_SPECFILE : 0;
02764
02765 if (*diskURL == '!') {
02766 flp->flags |= RPMFILE_GHOST;
02767 diskURL++;
02768 }
02769
02770 (void) urlPath(diskURL, &diskPath);
02771
02772 flp->diskURL = xstrdup(diskURL);
02773 diskPath = strrchr(diskPath, '/');
02774 if (diskPath)
02775 diskPath++;
02776 else
02777 diskPath = diskURL;
02778
02779 flp->fileURL = xstrdup(diskPath);
02780 flp->verifyFlags = RPMVERIFY_ALL;
02781
02782 if (Stat(diskURL, &flp->fl_st)) {
02783 rpmlog(RPMLOG_ERR, _("Bad file: %s: %s\n"),
02784 diskURL, strerror(errno));
02785 rc = fl.processingFailed = 1;
02786 }
02787
02788 #if defined(RPM_VENDOR_OPENPKG)
02789
02790 if (fl.def_ar.ar_fmodestr) {
02791 flp->fl_mode &= S_IFMT;
02792 flp->fl_mode |= fl.def_ar.ar_fmode;
02793 }
02794 flp->uname = fl.def_ar.ar_user ? getUnameS(fl.def_ar.ar_user) : getUname(flp->fl_uid);
02795 flp->gname = fl.def_ar.ar_group ? getGnameS(fl.def_ar.ar_group) : getGname(flp->fl_gid);
02796 #else
02797 flp->uname = getUname(flp->fl_uid);
02798 flp->gname = getGname(flp->fl_gid);
02799 #endif
02800 flp->langs = xstrdup("");
02801
02802 if (! (flp->uname && flp->gname)) {
02803 rpmlog(RPMLOG_ERR, _("Bad owner/group: %s\n"), diskURL);
02804 rc = fl.processingFailed = 1;
02805 }
02806
02807 isSpec = 0;
02808 x++;
02809 }
02810 fl.fileListRecsUsed = x;
02811 files = argvFree(files);
02812
02813 if (rc)
02814 goto exit;
02815
02816 spec->sourceCpioList = NULL;
02817 genCpioListAndHeader(&fl, &spec->sourceCpioList, spec->sourceHeader, 1);
02818
02819 exit:
02820 *sfp = rpmiobFree(*sfp);
02821 fl.fileList = freeFileList(fl.fileList, fl.fileListRecsUsed);
02822 return rc;
02823 }
02824
02830 static int checkUnpackagedFiles(Spec spec)
02831
02832
02833
02834 {
02835
02836 static const char * av_ckfile[] = { "%{?__check_files}", NULL };
02837
02838 rpmiob iob_stdout = NULL;
02839 const char * s;
02840 int rc;
02841 rpmiob fileList = NULL;
02842 Package pkg;
02843 int n = 0;
02844
02845 s = rpmExpand(av_ckfile[0], NULL);
02846 if (!(s && *s)) {
02847 rc = -1;
02848 goto exit;
02849 }
02850 rc = 0;
02851
02852
02853 fileList = rpmiobNew(0);
02854 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
02855 int i;
02856 rpmfi fi = rpmfiNew(NULL, pkg->header, RPMTAG_BASENAMES, 0);
02857 fi = rpmfiInit(fi, 0);
02858 while ((i = rpmfiNext(fi)) >= 0) {
02859 const char *fn = rpmfiFN(fi);
02860 fileList = rpmiobAppend(fileList, fn, 1);
02861 n++;
02862 }
02863 fi = rpmfiFree(fi);
02864 }
02865 if (n == 0) {
02866
02867
02868 rc = -1;
02869 goto exit;
02870 }
02871
02872 rpmlog(RPMLOG_NOTICE, _("Checking for unpackaged file(s): %s\n"), s);
02873
02874 rc = rpmfcExec(av_ckfile, fileList, &iob_stdout, 0);
02875 if (rc < 0)
02876 goto exit;
02877
02878 if (iob_stdout) {
02879 int _unpackaged_files_terminate_build =
02880 rpmExpandNumeric("%{?_unpackaged_files_terminate_build}");
02881 const char * t;
02882
02883 t = rpmiobStr(iob_stdout);
02884 if ((*t != '\0') && (*t != '\n')) {
02885 rc = (_unpackaged_files_terminate_build) ? 1 : 0;
02886 rpmlog((rc ? RPMLOG_ERR : RPMLOG_WARNING),
02887 _("Installed (but unpackaged) file(s) found:\n%s"), t);
02888 }
02889 }
02890
02891 exit:
02892 fileList = rpmiobFree(fileList);
02893 iob_stdout = rpmiobFree(iob_stdout);
02894 s = _free(s);
02895 return rc;
02896 }
02897
02898
02899
02900 static int fiIntersect( rpmfi fi1, rpmfi fi2, Header h1, Header h2)
02901
02902
02903 {
02904 int n = 0;
02905 int i1, i2;
02906 const char *fn1, *fn2;
02907 rpmiob dups = NULL;
02908
02909 if ((fi1 = rpmfiInit(fi1, 0)) != NULL)
02910 while ((i1 = rpmfiNext(fi1)) >= 0) {
02911 if (S_ISDIR(rpmfiFMode(fi1)))
02912 continue;
02913 fn1 = rpmfiFN(fi1);
02914 if ((fi2 = rpmfiInit(fi2, 0)) != NULL)
02915 while ((i2 = rpmfiNext(fi2)) >= 0) {
02916 if (S_ISDIR(rpmfiFMode(fi2)))
02917 continue;
02918 fn2 = rpmfiFN(fi2);
02919 if (strcmp(fn1, fn2))
02920 continue;
02921 if (!dups)
02922 dups = rpmiobNew(0);
02923 dups = rpmiobAppend(dups, "\t", 0);
02924 dups = rpmiobAppend(dups, fn1, 1);
02925 n++;
02926 }
02927 }
02928
02929 if (n > 0) {
02930 const char *N1, *N2;
02931 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
02932
02933 he->tag = RPMTAG_NVRA;
02934 N1 = (headerGet(h1, he, 0) ? he->p.str : NULL);
02935 he->tag = RPMTAG_NVRA;
02936 N2 = (headerGet(h2, he, 0) ? he->p.str : NULL);
02937
02938 rpmlog(RPMLOG_WARNING,
02939 _("File(s) packaged into both %s and %s:\n%s"),
02940 N1, N2, rpmiobStr(dups));
02941
02942 N1 = _free(N1);
02943 N2 = _free(N2);
02944 dups = rpmiobFree(dups);
02945 }
02946
02947 return n;
02948 }
02949
02955 static int checkDuplicateFiles(Spec spec)
02956
02957
02958
02959 {
02960 int n = 0;
02961 Package pkg1, pkg2;
02962
02963 for (pkg1 = spec->packages; pkg1->next; pkg1 = pkg1->next) {
02964 rpmfi fi1 = rpmfiNew(NULL, pkg1->header, RPMTAG_BASENAMES, 0);
02965 for (pkg2 = pkg1->next; pkg2; pkg2 = pkg2->next) {
02966 rpmfi fi2 = rpmfiNew(NULL, pkg2->header, RPMTAG_BASENAMES, 0);
02967 n += fiIntersect(fi1, fi2, pkg1->header, pkg2->header);
02968 fi2 = rpmfiFree(fi2);
02969 }
02970 fi1 = rpmfiFree(fi1);
02971 }
02972 return n;
02973 }
02974
02975
02976 static int packagedDir(Package pkg, const char *d)
02977
02978
02979
02980 {
02981 int i;
02982 int found = 0;
02983 const char *fn;
02984 rpmfi fi = rpmfiNew(NULL, pkg->header, RPMTAG_BASENAMES, 0);
02985
02986 fi = rpmfiInit(fi, 0);
02987 while ((i = rpmfiNext(fi)) >= 0) {
02988 if (!S_ISDIR(rpmfiFMode(fi)))
02989 continue;
02990 fn = rpmfiFN(fi);
02991 if (strcmp(fn, d) == 0) {
02992 found = 1;
02993 break;
02994 }
02995 }
02996 fi = rpmfiFree(fi);
02997 return found;
02998 }
02999
03000
03001
03002
03003
03004
03005
03006
03007 static int pkgUnpackagedSubdirs(Package pkg)
03008
03009
03010
03011 {
03012 int n = 0;
03013 int i, j;
03014 char **unpackaged = NULL;
03015 char *fn;
03016 rpmfi fi = rpmfiNew(NULL, pkg->header, RPMTAG_BASENAMES, 0);
03017
03018 if (rpmfiFC(fi) <= 1) {
03019 fi = rpmfiFree(fi);
03020 return 0;
03021 }
03022 fn = alloca(rpmfiFNMaxLen(fi) + 1);
03023
03024 fi = rpmfiInit(fi, 0);
03025 while ((i = rpmfiNext(fi)) >= 0) {
03026 int found = 0;
03027
03028 char *p = fn;
03029 strcpy(fn, rpmfiFN(fi));
03030
03031 while ((p = strchr(p + 1, '/'))) {
03032 *p = '\0';
03033 found = packagedDir(pkg, fn);
03034 *p = '/';
03035 if (found)
03036 break;
03037 }
03038 if (!found)
03039 continue;
03040
03041 if (p != NULL)
03042 while ((p = strchr(p + 1, '/'))) {
03043 *p = '\0';
03044 if (packagedDir(pkg, fn)) {
03045 *p = '/';
03046 continue;
03047 }
03048
03049 found = 0;
03050 for (j = 0; j < n; j++)
03051 if (strcmp(fn, unpackaged[j]) == 0) {
03052 found = 1;
03053 break;
03054 }
03055 if (found) {
03056 *p = '/';
03057 continue;
03058 }
03059 unpackaged = xrealloc(unpackaged, sizeof(*unpackaged) * (n + 1));
03060 unpackaged[n++] = xstrdup(fn);
03061 *p = '/';
03062 }
03063 }
03064 fi = rpmfiFree(fi);
03065
03066 if (n > 0) {
03067 const char *N;
03068 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
03069 rpmiob list = rpmiobNew(0);
03070
03071 he->tag = RPMTAG_NVRA;
03072 N = (headerGet(pkg->header, he, 0) ? he->p.str : NULL);
03073
03074 for (i = 0; i < n; i++) {
03075 list = rpmiobAppend(list, "\t", 0);
03076 list = rpmiobAppend(list, unpackaged[i], 1);
03077 unpackaged[i] = _free(unpackaged[i]);
03078 }
03079 unpackaged = _free(unpackaged);
03080
03081 rpmlog(RPMLOG_WARNING,
03082 _("Unpackaged subdir(s) in %s:\n%s"),
03083 N, rpmiobStr(list));
03084
03085 N = _free(N);
03086 list = rpmiobFree(list);
03087 }
03088
03089 return n;
03090 }
03091
03097 static int checkUnpackagedSubdirs(Spec spec)
03098
03099
03100
03101 {
03102 int n = 0;
03103 Package pkg;
03104
03105 for (pkg = spec->packages; pkg; pkg = pkg->next)
03106 n += pkgUnpackagedSubdirs(pkg);
03107 return n;
03108 }
03109
03110
03111 rpmRC processBinaryFiles(Spec spec, int installSpecialDoc, int test)
03112 {
03113 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
03114 Package pkg;
03115 rpmRC res = RPMRC_OK;
03116
03117 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
03118 int rc;
03119
03120 if (pkg->fileList == NULL)
03121 continue;
03122
03123 (void) headerMacrosLoad(pkg->header);
03124
03125 he->tag = RPMTAG_NVRA;
03126 rc = headerGet(pkg->header, he, 0);
03127 rpmlog(RPMLOG_NOTICE, _("Processing files: %s\n"), he->p.str);
03128 he->p.ptr = _free(he->p.ptr);
03129
03130 if ((rc = processPackageFiles(spec, pkg, installSpecialDoc, test))) {
03131 res = RPMRC_FAIL;
03132 (void) headerMacrosUnload(pkg->header);
03133 break;
03134 }
03135
03136
03137 if ((rc = processScriptFiles(spec, pkg))) {
03138 res = rc;
03139 (void) headerMacrosUnload(pkg->header);
03140 break;
03141 }
03142
03143 if ((rc = rpmfcGenerateDepends(spec, pkg))) {
03144 res = RPMRC_FAIL;
03145 (void) headerMacrosUnload(pkg->header);
03146 break;
03147 }
03148
03149
03150 providePackageNVR(pkg->header);
03151
03152 (void) headerMacrosUnload(pkg->header);
03153 }
03154
03155 if (res == RPMRC_OK) {
03156 if (checkUnpackagedFiles(spec) > 0)
03157 res = RPMRC_FAIL;
03158 (void) checkDuplicateFiles(spec);
03159 (void) checkUnpackagedSubdirs(spec);
03160 }
03161
03162 return res;
03163 }
03164