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