00001
00007 #include "system.h"
00008
00009 #define MYALLPERMS 07777
00010
00011 #include <regex.h>
00012 #include <signal.h>
00013
00014 #include <rpmio_internal.h>
00015 #include <rpmbuild.h>
00016
00017 #include "cpio.h"
00018
00019 #define _RPMFI_INTERNAL
00020 #include "rpmfi.h"
00021
00022 #define _RPMTE_INTERNAL
00023 #include "rpmte.h"
00024
00025 #include "buildio.h"
00026
00027 #include "myftw.h"
00028 #include "legacy.h"
00029 #include "misc.h"
00030 #include "debug.h"
00031
00032
00033
00034
00035
00036
00037
00038 #define SKIPWHITE(_x) {while(*(_x) && (xisspace(*_x) || *(_x) == ',')) (_x)++;}
00039 #define SKIPNONWHITE(_x){while(*(_x) &&!(xisspace(*_x) || *(_x) == ',')) (_x)++;}
00040
00041 #define MAXDOCDIR 1024
00042
00045 typedef enum specdFlags_e {
00046 SPECD_DEFFILEMODE = (1 << 0),
00047 SPECD_DEFDIRMODE = (1 << 1),
00048 SPECD_DEFUID = (1 << 2),
00049 SPECD_DEFGID = (1 << 3),
00050 SPECD_DEFVERIFY = (1 << 4),
00051
00052 SPECD_FILEMODE = (1 << 8),
00053 SPECD_DIRMODE = (1 << 9),
00054 SPECD_UID = (1 << 10),
00055 SPECD_GID = (1 << 11),
00056 SPECD_VERIFY = (1 << 12)
00057 } specdFlags;
00058
00061 typedef struct FileListRec_s {
00062 struct stat fl_st;
00063 #define fl_dev fl_st.st_dev
00064 #define fl_ino fl_st.st_ino
00065 #define fl_mode fl_st.st_mode
00066 #define fl_nlink fl_st.st_nlink
00067 #define fl_uid fl_st.st_uid
00068 #define fl_gid fl_st.st_gid
00069 #define fl_rdev fl_st.st_rdev
00070 #define fl_size fl_st.st_size
00071 #define fl_mtime fl_st.st_mtime
00072
00073 const char * diskURL;
00074 const char * fileURL;
00075 const char * uname;
00076 const char * gname;
00077 unsigned flags;
00078 specdFlags specdFlags;
00079 unsigned verifyFlags;
00080 const char *langs;
00081 } * FileListRec;
00082
00085 typedef struct AttrRec_s {
00086 const char * ar_fmodestr;
00087 const char * ar_dmodestr;
00088 const char * ar_user;
00089 const char * ar_group;
00090 mode_t ar_fmode;
00091 mode_t ar_dmode;
00092 } * AttrRec;
00093
00096
00097 static int multiLib = 0;
00098
00099
00100
00101 static StringBuf check_fileList = NULL;
00102
00103 static int check_fileListLen = 0;
00104
00108 typedef struct FileList_s {
00109 const char * buildRootURL;
00110 const char * prefix;
00111
00112 int fileCount;
00113 int totalFileSize;
00114 int processingFailed;
00115
00116 int passedSpecialDoc;
00117 int isSpecialDoc;
00118
00119 int noGlob;
00120 unsigned devtype;
00121 unsigned devmajor;
00122 int devminor;
00123
00124 int isDir;
00125 int inFtw;
00126 int currentFlags;
00127 specdFlags currentSpecdFlags;
00128 int currentVerifyFlags;
00129 struct AttrRec_s cur_ar;
00130 struct AttrRec_s def_ar;
00131 specdFlags defSpecdFlags;
00132 int defVerifyFlags;
00133 int nLangs;
00134 const char ** currentLangs;
00135
00136
00137
00138 const char * docDirs[MAXDOCDIR];
00139 int docDirCount;
00140
00141 FileListRec fileList;
00142 int fileListRecsAlloced;
00143 int fileListRecsUsed;
00144 } * FileList;
00145
00148 static void nullAttrRec( AttrRec ar)
00149 {
00150 ar->ar_fmodestr = NULL;
00151 ar->ar_dmodestr = NULL;
00152 ar->ar_user = NULL;
00153 ar->ar_group = NULL;
00154 ar->ar_fmode = 0;
00155 ar->ar_dmode = 0;
00156 }
00157
00160 static void freeAttrRec(AttrRec ar)
00161 {
00162 ar->ar_fmodestr = _free(ar->ar_fmodestr);
00163 ar->ar_dmodestr = _free(ar->ar_dmodestr);
00164 ar->ar_user = _free(ar->ar_user);
00165 ar->ar_group = _free(ar->ar_group);
00166
00167
00168 return;
00169
00170 }
00171
00174 static void dupAttrRec(const AttrRec oar, AttrRec nar)
00175
00176 {
00177 if (oar == nar)
00178 return;
00179 freeAttrRec(nar);
00180 nar->ar_fmodestr = (oar->ar_fmodestr ? xstrdup(oar->ar_fmodestr) : NULL);
00181 nar->ar_dmodestr = (oar->ar_dmodestr ? xstrdup(oar->ar_dmodestr) : NULL);
00182 nar->ar_user = (oar->ar_user ? xstrdup(oar->ar_user) : NULL);
00183 nar->ar_group = (oar->ar_group ? xstrdup(oar->ar_group) : NULL);
00184 nar->ar_fmode = oar->ar_fmode;
00185 nar->ar_dmode = oar->ar_dmode;
00186 }
00187
00188 #if 0
00189
00191 static void dumpAttrRec(const char * msg, AttrRec ar)
00192
00193
00194 {
00195 if (msg)
00196 fprintf(stderr, "%s:\t", msg);
00197 fprintf(stderr, "(%s, %s, %s, %s)\n",
00198 ar->ar_fmodestr,
00199 ar->ar_user,
00200 ar->ar_group,
00201 ar->ar_dmodestr);
00202 }
00203 #endif
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00226
00227 static char *strtokWithQuotes(char *s, char *delim)
00228
00229 {
00230 static char *olds = NULL;
00231 char *token;
00232
00233 if (s == NULL) {
00234 s = olds;
00235 }
00236
00237
00238 s += strspn(s, delim);
00239 if (*s == '\0') {
00240 return NULL;
00241 }
00242
00243
00244 token = s;
00245 if (*token == '"') {
00246 token++;
00247
00248 s = strchr(token, '"');
00249 } else {
00250 s = strpbrk(token, delim);
00251 }
00252
00253
00254 if (s == NULL) {
00255
00256 olds = strchr(token, '\0');
00257 } else {
00258
00259 *s = '\0';
00260 olds = s+1;
00261 }
00262
00263
00264 return token;
00265
00266 }
00267
00268
00271 static void timeCheck(int tc, Header h)
00272
00273
00274 {
00275 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00276 HFD_t hfd = headerFreeData;
00277 int * mtime;
00278 const char ** files;
00279 rpmTagType fnt;
00280 int count, x;
00281 time_t currentTime = time(NULL);
00282
00283 x = hge(h, RPMTAG_OLDFILENAMES, &fnt, (void **) &files, &count);
00284 x = hge(h, RPMTAG_FILEMTIMES, NULL, (void **) &mtime, NULL);
00285
00286
00287 for (x = 0; x < count; x++) {
00288 if ((currentTime - mtime[x]) > tc)
00289 rpmMessage(RPMMESS_WARNING, _("TIMECHECK failure: %s\n"), files[x]);
00290 }
00291 files = hfd(files, fnt);
00292
00293 }
00294
00297 typedef struct VFA {
00298 const char * attribute;
00299 int flag;
00300 } VFA_t;
00301
00304
00305
00306 VFA_t verifyAttrs[] = {
00307 { "md5", RPMVERIFY_MD5 },
00308 { "size", RPMVERIFY_FILESIZE },
00309 { "link", RPMVERIFY_LINKTO },
00310 { "user", RPMVERIFY_USER },
00311 { "group", RPMVERIFY_GROUP },
00312 { "mtime", RPMVERIFY_MTIME },
00313 { "mode", RPMVERIFY_MODE },
00314 { "rdev", RPMVERIFY_RDEV },
00315 { NULL, 0 }
00316 };
00317
00318
00325
00326 static int parseForVerify(char * buf, FileList fl)
00327
00328
00329
00330 {
00331 char *p, *pe, *q;
00332 const char *name;
00333 int *resultVerify;
00334 int negated;
00335 int verifyFlags;
00336 specdFlags * specdFlags;
00337
00338 if ((p = strstr(buf, (name = "%verify"))) != NULL) {
00339 resultVerify = &(fl->currentVerifyFlags);
00340 specdFlags = &fl->currentSpecdFlags;
00341 } else if ((p = strstr(buf, (name = "%defverify"))) != NULL) {
00342 resultVerify = &(fl->defVerifyFlags);
00343 specdFlags = &fl->defSpecdFlags;
00344 } else
00345 return 0;
00346
00347 for (pe = p; (pe-p) < strlen(name); pe++)
00348 *pe = ' ';
00349
00350 SKIPSPACE(pe);
00351
00352 if (*pe != '(') {
00353 rpmError(RPMERR_BADSPEC, _("Missing '(' in %s %s\n"), name, pe);
00354 fl->processingFailed = 1;
00355 return RPMERR_BADSPEC;
00356 }
00357
00358
00359 *pe++ = ' ';
00360 for (p = pe; *pe && *pe != ')'; pe++)
00361 {};
00362
00363 if (*pe == '\0') {
00364 rpmError(RPMERR_BADSPEC, _("Missing ')' in %s(%s\n"), name, p);
00365 fl->processingFailed = 1;
00366 return RPMERR_BADSPEC;
00367 }
00368
00369
00370 q = alloca((pe-p) + 1);
00371 strncpy(q, p, pe-p);
00372 q[pe-p] = '\0';
00373 while (p <= pe)
00374 *p++ = ' ';
00375
00376 negated = 0;
00377 verifyFlags = RPMVERIFY_NONE;
00378
00379 for (p = q; *p != '\0'; p = pe) {
00380 SKIPWHITE(p);
00381 if (*p == '\0')
00382 break;
00383 pe = p;
00384 SKIPNONWHITE(pe);
00385 if (*pe != '\0')
00386 *pe++ = '\0';
00387
00388 { VFA_t *vfa;
00389 for (vfa = verifyAttrs; vfa->attribute != NULL; vfa++) {
00390 if (strcmp(p, vfa->attribute))
00391 continue;
00392 verifyFlags |= vfa->flag;
00393 break;
00394 }
00395 if (vfa->attribute)
00396 continue;
00397 }
00398
00399 if (!strcmp(p, "not")) {
00400 negated ^= 1;
00401 } else {
00402 rpmError(RPMERR_BADSPEC, _("Invalid %s token: %s\n"), name, p);
00403 fl->processingFailed = 1;
00404 return RPMERR_BADSPEC;
00405 }
00406 }
00407
00408 *resultVerify = negated ? ~(verifyFlags) : verifyFlags;
00409 *specdFlags |= SPECD_VERIFY;
00410
00411 return 0;
00412 }
00413
00414
00415 #define isAttrDefault(_ars) ((_ars)[0] == '-' && (_ars)[1] == '\0')
00416
00423
00424 static int parseForDev(char * buf, FileList fl)
00425
00426
00427 {
00428 const char * name;
00429 const char * errstr = NULL;
00430 char *p, *pe, *q;
00431 int rc = RPMERR_BADSPEC;
00432
00433 if ((p = strstr(buf, (name = "%dev"))) == NULL)
00434 return 0;
00435
00436 for (pe = p; (pe-p) < strlen(name); pe++)
00437 *pe = ' ';
00438 SKIPSPACE(pe);
00439
00440 if (*pe != '(') {
00441 errstr = "'('";
00442 goto exit;
00443 }
00444
00445
00446 *pe++ = ' ';
00447 for (p = pe; *pe && *pe != ')'; pe++)
00448 {};
00449 if (*pe != ')') {
00450 errstr = "')'";
00451 goto exit;
00452 }
00453
00454
00455 q = alloca((pe-p) + 1);
00456 strncpy(q, p, pe-p);
00457 q[pe-p] = '\0';
00458 while (p <= pe)
00459 *p++ = ' ';
00460
00461 p = q; SKIPWHITE(p);
00462 pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
00463 if (*p == 'b')
00464 fl->devtype = 'b';
00465 else if (*p == 'c')
00466 fl->devtype = 'c';
00467 else {
00468 errstr = "devtype";
00469 goto exit;
00470 }
00471
00472 p = pe; SKIPWHITE(p);
00473 pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
00474 for (pe = p; *pe && xisdigit(*pe); pe++)
00475 {} ;
00476 if (*pe == '\0') {
00477 fl->devmajor = atoi(p);
00478
00479 if (!(fl->devmajor >= 0 && fl->devmajor < 256)) {
00480 errstr = "devmajor";
00481 goto exit;
00482 }
00483
00484 pe++;
00485 } else {
00486 errstr = "devmajor";
00487 goto exit;
00488 }
00489
00490 p = pe; SKIPWHITE(p);
00491 pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
00492 for (pe = p; *pe && xisdigit(*pe); pe++)
00493 {} ;
00494 if (*pe == '\0') {
00495 fl->devminor = atoi(p);
00496 if (!(fl->devminor >= 0 && fl->devminor < 256)) {
00497 errstr = "devminor";
00498 goto exit;
00499 }
00500 pe++;
00501 } else {
00502 errstr = "devminor";
00503 goto exit;
00504 }
00505
00506 fl->noGlob = 1;
00507
00508 rc = 0;
00509
00510 exit:
00511 if (rc) {
00512 rpmError(RPMERR_BADSPEC, _("Missing %s in %s %s\n"), errstr, name, p);
00513 fl->processingFailed = 1;
00514 }
00515 return rc;
00516 }
00517
00518
00525
00526 static int parseForAttr(char * buf, FileList fl)
00527
00528
00529
00530 {
00531 const char *name;
00532 char *p, *pe, *q;
00533 int x;
00534 struct AttrRec_s arbuf;
00535 AttrRec ar = &arbuf, ret_ar;
00536 specdFlags * specdFlags;
00537
00538 if ((p = strstr(buf, (name = "%attr"))) != NULL) {
00539 ret_ar = &(fl->cur_ar);
00540 specdFlags = &fl->currentSpecdFlags;
00541 } else if ((p = strstr(buf, (name = "%defattr"))) != NULL) {
00542 ret_ar = &(fl->def_ar);
00543 specdFlags = &fl->defSpecdFlags;
00544 } else
00545 return 0;
00546
00547 for (pe = p; (pe-p) < strlen(name); pe++)
00548 *pe = ' ';
00549
00550 SKIPSPACE(pe);
00551
00552 if (*pe != '(') {
00553 rpmError(RPMERR_BADSPEC, _("Missing '(' in %s %s\n"), name, pe);
00554 fl->processingFailed = 1;
00555 return RPMERR_BADSPEC;
00556 }
00557
00558
00559 *pe++ = ' ';
00560 for (p = pe; *pe && *pe != ')'; pe++)
00561 {};
00562
00563 if (ret_ar == &(fl->def_ar)) {
00564 q = pe;
00565 q++;
00566 SKIPSPACE(q);
00567 if (*q != '\0') {
00568 rpmError(RPMERR_BADSPEC,
00569 _("Non-white space follows %s(): %s\n"), name, q);
00570 fl->processingFailed = 1;
00571 return RPMERR_BADSPEC;
00572 }
00573 }
00574
00575
00576 q = alloca((pe-p) + 1);
00577 strncpy(q, p, pe-p);
00578 q[pe-p] = '\0';
00579 while (p <= pe)
00580 *p++ = ' ';
00581
00582 nullAttrRec(ar);
00583
00584 p = q; SKIPWHITE(p);
00585 if (*p != '\0') {
00586 pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
00587 ar->ar_fmodestr = p;
00588 p = pe; SKIPWHITE(p);
00589 }
00590 if (*p != '\0') {
00591 pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
00592 ar->ar_user = p;
00593 p = pe; SKIPWHITE(p);
00594 }
00595 if (*p != '\0') {
00596 pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
00597 ar->ar_group = p;
00598 p = pe; SKIPWHITE(p);
00599 }
00600 if (*p != '\0' && ret_ar == &(fl->def_ar)) {
00601 pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
00602 ar->ar_dmodestr = p;
00603 p = pe; SKIPWHITE(p);
00604 }
00605
00606 if (!(ar->ar_fmodestr && ar->ar_user && ar->ar_group) || *p != '\0') {
00607 rpmError(RPMERR_BADSPEC, _("Bad syntax: %s(%s)\n"), name, q);
00608 fl->processingFailed = 1;
00609 return RPMERR_BADSPEC;
00610 }
00611
00612
00613 if (ar->ar_fmodestr && !isAttrDefault(ar->ar_fmodestr)) {
00614 unsigned int ui;
00615 x = sscanf(ar->ar_fmodestr, "%o", &ui);
00616 if ((x == 0) || (ar->ar_fmode & ~MYALLPERMS)) {
00617 rpmError(RPMERR_BADSPEC, _("Bad mode spec: %s(%s)\n"), name, q);
00618 fl->processingFailed = 1;
00619 return RPMERR_BADSPEC;
00620 }
00621 ar->ar_fmode = ui;
00622 } else
00623 ar->ar_fmodestr = NULL;
00624
00625 if (ar->ar_dmodestr && !isAttrDefault(ar->ar_dmodestr)) {
00626 unsigned int ui;
00627 x = sscanf(ar->ar_dmodestr, "%o", &ui);
00628 if ((x == 0) || (ar->ar_dmode & ~MYALLPERMS)) {
00629 rpmError(RPMERR_BADSPEC, _("Bad dirmode spec: %s(%s)\n"), name, q);
00630 fl->processingFailed = 1;
00631 return RPMERR_BADSPEC;
00632 }
00633 ar->ar_dmode = ui;
00634 } else
00635 ar->ar_dmodestr = NULL;
00636
00637 if (!(ar->ar_user && !isAttrDefault(ar->ar_user)))
00638 ar->ar_user = NULL;
00639
00640 if (!(ar->ar_group && !isAttrDefault(ar->ar_group)))
00641 ar->ar_group = NULL;
00642
00643 dupAttrRec(ar, ret_ar);
00644
00645
00646 *specdFlags |= SPECD_UID | SPECD_GID | SPECD_FILEMODE | SPECD_DIRMODE;
00647
00648 return 0;
00649 }
00650
00651
00658
00659 static int parseForConfig(char * buf, FileList fl)
00660
00661
00662 {
00663 char *p, *pe, *q;
00664 const char *name;
00665
00666 if ((p = strstr(buf, (name = "%config"))) == NULL)
00667 return 0;
00668
00669 fl->currentFlags = RPMFILE_CONFIG;
00670
00671 for (pe = p; (pe-p) < strlen(name); pe++)
00672 *pe = ' ';
00673 SKIPSPACE(pe);
00674 if (*pe != '(')
00675 return 0;
00676
00677
00678 *pe++ = ' ';
00679 for (p = pe; *pe && *pe != ')'; pe++)
00680 {};
00681
00682 if (*pe == '\0') {
00683 rpmError(RPMERR_BADSPEC, _("Missing ')' in %s(%s\n"), name, p);
00684 fl->processingFailed = 1;
00685 return RPMERR_BADSPEC;
00686 }
00687
00688
00689 q = alloca((pe-p) + 1);
00690 strncpy(q, p, pe-p);
00691 q[pe-p] = '\0';
00692 while (p <= pe)
00693 *p++ = ' ';
00694
00695 for (p = q; *p != '\0'; p = pe) {
00696 SKIPWHITE(p);
00697 if (*p == '\0')
00698 break;
00699 pe = p;
00700 SKIPNONWHITE(pe);
00701 if (*pe != '\0')
00702 *pe++ = '\0';
00703 if (!strcmp(p, "missingok")) {
00704 fl->currentFlags |= RPMFILE_MISSINGOK;
00705 } else if (!strcmp(p, "noreplace")) {
00706 fl->currentFlags |= RPMFILE_NOREPLACE;
00707 } else {
00708 rpmError(RPMERR_BADSPEC, _("Invalid %s token: %s\n"), name, p);
00709 fl->processingFailed = 1;
00710 return RPMERR_BADSPEC;
00711 }
00712 }
00713
00714 return 0;
00715 }
00716
00717
00720 static int langCmp(const void * ap, const void * bp)
00721
00722 {
00723
00724 return strcmp(*(const char **)ap, *(const char **)bp);
00725
00726 }
00727
00734
00735 static int parseForLang(char * buf, FileList fl)
00736
00737
00738 {
00739 char *p, *pe, *q;
00740 const char *name;
00741
00742 while ((p = strstr(buf, (name = "%lang"))) != NULL) {
00743
00744 for (pe = p; (pe-p) < strlen(name); pe++)
00745 *pe = ' ';
00746 SKIPSPACE(pe);
00747
00748 if (*pe != '(') {
00749 rpmError(RPMERR_BADSPEC, _("Missing '(' in %s %s\n"), name, pe);
00750 fl->processingFailed = 1;
00751 return RPMERR_BADSPEC;
00752 }
00753
00754
00755 *pe++ = ' ';
00756 for (pe = p; *pe && *pe != ')'; pe++)
00757 {};
00758
00759 if (*pe == '\0') {
00760 rpmError(RPMERR_BADSPEC, _("Missing ')' in %s(%s\n"), name, p);
00761 fl->processingFailed = 1;
00762 return RPMERR_BADSPEC;
00763 }
00764
00765
00766 q = alloca((pe-p) + 1);
00767 strncpy(q, p, pe-p);
00768 q[pe-p] = '\0';
00769 while (p <= pe)
00770 *p++ = ' ';
00771
00772
00773 for (p = q; *p != '\0'; p = pe) {
00774 char *newp;
00775 size_t np;
00776 int i;
00777
00778 SKIPWHITE(p);
00779 pe = p;
00780 SKIPNONWHITE(pe);
00781
00782 np = pe - p;
00783
00784
00785 if (np < 1 || (np == 1 && *p != 'C') || np >= 32) {
00786 rpmError(RPMERR_BADSPEC,
00787 _("Unusual locale length: \"%.*s\" in %%lang(%s)\n"),
00788 (int)np, p, q);
00789 fl->processingFailed = 1;
00790 return RPMERR_BADSPEC;
00791 }
00792
00793
00794 if (fl->currentLangs != NULL)
00795 for (i = 0; i < fl->nLangs; i++) {
00796 if (strncmp(fl->currentLangs[i], p, np))
00797 continue;
00798 rpmError(RPMERR_BADSPEC, _("Duplicate locale %.*s in %%lang(%s)\n"),
00799 (int)np, p, q);
00800 fl->processingFailed = 1;
00801 return RPMERR_BADSPEC;
00802 }
00803
00804
00805 fl->currentLangs = xrealloc(fl->currentLangs,
00806 (fl->nLangs + 1) * sizeof(*fl->currentLangs));
00807 newp = xmalloc( np+1 );
00808 strncpy(newp, p, np);
00809 newp[np] = '\0';
00810 fl->currentLangs[fl->nLangs++] = newp;
00811 if (*pe == ',') pe++;
00812 }
00813 }
00814
00815
00816 if (fl->currentLangs)
00817 qsort(fl->currentLangs, fl->nLangs, sizeof(*fl->currentLangs), langCmp);
00818
00819 return 0;
00820 }
00821
00822
00825
00826 static int parseForRegexLang(const char * fileName, char ** lang)
00827
00828
00829 {
00830 static int initialized = 0;
00831 static int hasRegex = 0;
00832 static regex_t compiledPatt;
00833 static char buf[BUFSIZ];
00834 int x;
00835 regmatch_t matches[2];
00836 const char *s;
00837
00838 if (! initialized) {
00839 const char *patt = rpmExpand("%{_langpatt}", NULL);
00840 int rc = 0;
00841 if (!(patt && *patt != '%'))
00842 rc = 1;
00843 else if (regcomp(&compiledPatt, patt, REG_EXTENDED))
00844 rc = -1;
00845 patt = _free(patt);
00846 if (rc)
00847 return rc;
00848 hasRegex = 1;
00849 initialized = 1;
00850 }
00851
00852 memset(matches, 0, sizeof(matches));
00853 if (! hasRegex || regexec(&compiledPatt, fileName, 2, matches, REG_NOTEOL))
00854 return 1;
00855
00856
00857 s = fileName + matches[1].rm_eo - 1;
00858 x = matches[1].rm_eo - matches[1].rm_so;
00859 buf[x] = '\0';
00860 while (x) {
00861 buf[--x] = *s--;
00862 }
00863 if (lang)
00864 *lang = buf;
00865 return 0;
00866 }
00867
00868
00871
00872 static int parseForRegexMultiLib(const char *fileName)
00873
00874
00875 {
00876 static int initialized = 0;
00877 static int hasRegex = 0;
00878 static regex_t compiledPatt;
00879
00880 if (! initialized) {
00881 const char *patt;
00882 int rc = 0;
00883
00884 initialized = 1;
00885 patt = rpmExpand("%{_multilibpatt}", NULL);
00886 if (!(patt && *patt != '%'))
00887 rc = 1;
00888 else if (regcomp(&compiledPatt, patt, REG_EXTENDED | REG_NOSUB))
00889 rc = -1;
00890 patt = _free(patt);
00891 if (rc)
00892 return rc;
00893 hasRegex = 1;
00894 }
00895
00896 if (! hasRegex || regexec(&compiledPatt, fileName, 0, NULL, 0))
00897 return 1;
00898
00899 return 0;
00900 }
00901
00902
00905
00906
00907 VFA_t virtualFileAttributes[] = {
00908 { "%dir", 0 },
00909 { "%doc", RPMFILE_DOC },
00910 { "%ghost", RPMFILE_GHOST },
00911 { "%exclude", RPMFILE_EXCLUDE },
00912 { "%readme", RPMFILE_README },
00913 { "%license", RPMFILE_LICENSE },
00914 { "%multilib", 0 },
00915
00916 #if WHY_NOT
00917 { "%spec", RPMFILE_SPEC },
00918 { "%config", RPMFILE_CONFIG },
00919 { "%donotuse", RPMFILE_DONOTUSE },
00920 { "%missingok", RPMFILE_CONFIG|RPMFILE_MISSINGOK },
00921 { "%noreplace", RPMFILE_CONFIG|RPMFILE_NOREPLACE },
00922 #endif
00923
00924 { NULL, 0 }
00925 };
00926
00927
00937
00938 static int parseForSimple(Spec spec, Package pkg, char * buf,
00939 FileList fl, const char ** fileName)
00940
00941
00942
00943
00944
00945
00946 {
00947 char *s, *t;
00948 int res, specialDoc = 0;
00949 char specialDocBuf[BUFSIZ];
00950
00951 specialDocBuf[0] = '\0';
00952 *fileName = NULL;
00953 res = 0;
00954
00955 t = buf;
00956 while ((s = strtokWithQuotes(t, " \t\n")) != NULL) {
00957 t = NULL;
00958 if (!strcmp(s, "%docdir")) {
00959 s = strtokWithQuotes(NULL, " \t\n");
00960 if (fl->docDirCount == MAXDOCDIR) {
00961 rpmError(RPMERR_INTERNAL, _("Hit limit for %%docdir\n"));
00962 fl->processingFailed = 1;
00963 res = 1;
00964 }
00965 fl->docDirs[fl->docDirCount++] = xstrdup(s);
00966 if (strtokWithQuotes(NULL, " \t\n")) {
00967 rpmError(RPMERR_INTERNAL, _("Only one arg for %%docdir\n"));
00968 fl->processingFailed = 1;
00969 res = 1;
00970 }
00971 break;
00972 }
00973
00974
00975 { VFA_t *vfa;
00976 for (vfa = virtualFileAttributes; vfa->attribute != NULL; vfa++) {
00977 if (strcmp(s, vfa->attribute))
00978 continue;
00979 if (!vfa->flag) {
00980 if (!strcmp(s, "%dir"))
00981 fl->isDir = 1;
00982 else if (!strcmp(s, "%multilib"))
00983 fl->currentFlags |= multiLib;
00984 } else
00985 fl->currentFlags |= vfa->flag;
00986 break;
00987 }
00988
00989 if (vfa->attribute != NULL)
00990 continue;
00991 }
00992
00993 if (*fileName) {
00994
00995 rpmError(RPMERR_BADSPEC, _("Two files on one line: %s\n"),
00996 *fileName);
00997 fl->processingFailed = 1;
00998 res = 1;
00999 }
01000
01001
01002 if (*s != '/') {
01003 if (fl->currentFlags & RPMFILE_DOC) {
01004 specialDoc = 1;
01005 strcat(specialDocBuf, " ");
01006 strcat(specialDocBuf, s);
01007 } else {
01008
01009 rpmError(RPMERR_BADSPEC,
01010 _("File must begin with \"/\": %s\n"), s);
01011 fl->processingFailed = 1;
01012 res = 1;
01013 }
01014 } else {
01015 *fileName = s;
01016 }
01017
01018 }
01019
01020 if (specialDoc) {
01021 if (*fileName || (fl->currentFlags & ~(RPMFILE_DOC))) {
01022 rpmError(RPMERR_BADSPEC,
01023 _("Can't mix special %%doc with other forms: %s\n"),
01024 (*fileName ? *fileName : ""));
01025 fl->processingFailed = 1;
01026 res = 1;
01027 } else {
01028
01029 { const char *ddir, *n, *v;
01030
01031 (void) headerNVR(pkg->header, &n, &v, NULL);
01032
01033 ddir = rpmGetPath("%{_docdir}/", n, "-", v, NULL);
01034 strcpy(buf, ddir);
01035 ddir = _free(ddir);
01036 }
01037
01038
01039
01040 if (! fl->passedSpecialDoc) {
01041 pkg->specialDoc = newStringBuf();
01042 appendStringBuf(pkg->specialDoc, "DOCDIR=$RPM_BUILD_ROOT");
01043 appendLineStringBuf(pkg->specialDoc, buf);
01044 appendLineStringBuf(pkg->specialDoc, "export DOCDIR");
01045 appendLineStringBuf(pkg->specialDoc, "rm -rf $DOCDIR");
01046 appendLineStringBuf(pkg->specialDoc, MKDIR_P " $DOCDIR");
01047
01048
01049 *fileName = buf;
01050
01051 fl->passedSpecialDoc = 1;
01052 fl->isSpecialDoc = 1;
01053 }
01054
01055 appendStringBuf(pkg->specialDoc, "cp -pr ");
01056 appendStringBuf(pkg->specialDoc, specialDocBuf);
01057 appendLineStringBuf(pkg->specialDoc, " $DOCDIR");
01058 }
01059 }
01060
01061 return res;
01062 }
01063
01064
01067 static int compareFileListRecs(const void * ap, const void * bp)
01068 {
01069 const char *a = ((FileListRec)ap)->fileURL;
01070 const char *b = ((FileListRec)bp)->fileURL;
01071 return strcmp(a, b);
01072 }
01073
01081 static int isDoc(FileList fl, const char * fileName)
01082 {
01083 int x = fl->docDirCount;
01084
01085 while (x--) {
01086 if (strstr(fileName, fl->docDirs[x]) == fileName)
01087 return 1;
01088 }
01089 return 0;
01090 }
01091
01098 static int checkHardLinks(FileList fl)
01099
01100 {
01101 FileListRec ilp, jlp;
01102 int i, j;
01103
01104 for (i = 0; i < fl->fileListRecsUsed; i++) {
01105 ilp = fl->fileList + i;
01106 if (!(S_ISREG(ilp->fl_mode) && ilp->fl_nlink > 1))
01107 continue;
01108
01109 for (j = i + 1; j < fl->fileListRecsUsed; j++) {
01110 jlp = fl->fileList + j;
01111 if (!S_ISREG(jlp->fl_mode))
01112 continue;
01113 if (ilp->fl_nlink != jlp->fl_nlink)
01114 continue;
01115 if (ilp->fl_ino != jlp->fl_ino)
01116 continue;
01117 if (ilp->fl_dev != jlp->fl_dev)
01118 continue;
01119 return 1;
01120 }
01121 }
01122 return 0;
01123 }
01124
01134
01135 static void genCpioListAndHeader( FileList fl,
01136 rpmfi * cpioList, Header h, int isSrc)
01137
01138
01139
01140 {
01141 int _addDotSlash = !(isSrc || rpmExpandNumeric("%{_noPayloadPrefix}"));
01142 uint_32 multiLibMask = 0;
01143 int apathlen = 0;
01144 int dpathlen = 0;
01145 int skipLen = 0;
01146 FileListRec flp;
01147 char buf[BUFSIZ];
01148 int i;
01149
01150
01151 qsort(fl->fileList, fl->fileListRecsUsed,
01152 sizeof(*(fl->fileList)), compareFileListRecs);
01153
01154
01155 if (! isSrc) {
01156 skipLen = 1;
01157 if (fl->prefix)
01158 skipLen += strlen(fl->prefix);
01159 }
01160
01161 for (i = 0, flp = fl->fileList; i < fl->fileListRecsUsed; i++, flp++) {
01162 char *s;
01163
01164
01165 while (i < (fl->fileListRecsUsed - 1) &&
01166 !strcmp(flp->fileURL, flp[1].fileURL)) {
01167
01168
01169
01170
01171
01172 flp[1].flags |= flp->flags;
01173
01174 if (!(flp[1].flags & RPMFILE_EXCLUDE))
01175 rpmMessage(RPMMESS_WARNING, _("File listed twice: %s\n"),
01176 flp->fileURL);
01177
01178
01179 if (S_ISDIR(flp->fl_mode)) {
01180 if ((flp[1].specdFlags & (SPECD_DIRMODE | SPECD_DEFDIRMODE)) <
01181 (flp->specdFlags & (SPECD_DIRMODE | SPECD_DEFDIRMODE)))
01182 flp[1].fl_mode = flp->fl_mode;
01183 } else {
01184 if ((flp[1].specdFlags & (SPECD_FILEMODE | SPECD_DEFFILEMODE)) <
01185 (flp->specdFlags & (SPECD_FILEMODE | SPECD_DEFFILEMODE)))
01186 flp[1].fl_mode = flp->fl_mode;
01187 }
01188
01189
01190 if ((flp[1].specdFlags & (SPECD_UID | SPECD_DEFUID)) <
01191 (flp->specdFlags & (SPECD_UID | SPECD_DEFUID)))
01192 {
01193 flp[1].fl_uid = flp->fl_uid;
01194 flp[1].uname = flp->uname;
01195 }
01196
01197
01198 if ((flp[1].specdFlags & (SPECD_GID | SPECD_DEFGID)) <
01199 (flp->specdFlags & (SPECD_GID | SPECD_DEFGID)))
01200 {
01201 flp[1].fl_gid = flp->fl_gid;
01202 flp[1].gname = flp->gname;
01203 }
01204
01205
01206 if ((flp[1].specdFlags & (SPECD_VERIFY | SPECD_DEFVERIFY)) <
01207 (flp->specdFlags & (SPECD_VERIFY | SPECD_DEFVERIFY)))
01208 flp[1].verifyFlags = flp->verifyFlags;
01209
01210
01211
01212 flp++; i++;
01213 }
01214
01215
01216 if (flp->flags & RPMFILE_EXCLUDE) continue;
01217
01218
01219 apathlen += (strlen(flp->fileURL) - skipLen + (_addDotSlash ? 3 : 1));
01220
01221
01222 dpathlen += (strlen(flp->diskURL) + 2);
01223
01224 if (flp->flags & RPMFILE_MULTILIB_MASK)
01225 multiLibMask |=
01226 (1u << ((flp->flags & RPMFILE_MULTILIB_MASK))
01227 >> RPMFILE_MULTILIB_SHIFT);
01228
01229
01230
01231
01232
01233
01234 (void) headerAddOrAppendEntry(h, RPMTAG_OLDFILENAMES, RPM_STRING_ARRAY_TYPE,
01235 &(flp->fileURL), 1);
01236
01237
01238 if (sizeof(flp->fl_size) != sizeof(uint_32)) {
01239 uint_32 psize = (uint_32)flp->fl_size;
01240 (void) headerAddOrAppendEntry(h, RPMTAG_FILESIZES, RPM_INT32_TYPE,
01241 &(psize), 1);
01242 } else {
01243 (void) headerAddOrAppendEntry(h, RPMTAG_FILESIZES, RPM_INT32_TYPE,
01244 &(flp->fl_size), 1);
01245 }
01246 (void) headerAddOrAppendEntry(h, RPMTAG_FILEUSERNAME, RPM_STRING_ARRAY_TYPE,
01247 &(flp->uname), 1);
01248 (void) headerAddOrAppendEntry(h, RPMTAG_FILEGROUPNAME, RPM_STRING_ARRAY_TYPE,
01249 &(flp->gname), 1);
01250 if (sizeof(flp->fl_mtime) != sizeof(uint_32)) {
01251 uint_32 mtime = (uint_32)flp->fl_mtime;
01252 (void) headerAddOrAppendEntry(h, RPMTAG_FILEMTIMES, RPM_INT32_TYPE,
01253 &(mtime), 1);
01254 } else {
01255 (void) headerAddOrAppendEntry(h, RPMTAG_FILEMTIMES, RPM_INT32_TYPE,
01256 &(flp->fl_mtime), 1);
01257 }
01258 if (sizeof(flp->fl_mode) != sizeof(uint_16)) {
01259 uint_16 pmode = (uint_16)flp->fl_mode;
01260 (void) headerAddOrAppendEntry(h, RPMTAG_FILEMODES, RPM_INT16_TYPE,
01261 &(pmode), 1);
01262 } else {
01263 (void) headerAddOrAppendEntry(h, RPMTAG_FILEMODES, RPM_INT16_TYPE,
01264 &(flp->fl_mode), 1);
01265 }
01266 if (sizeof(flp->fl_rdev) != sizeof(uint_16)) {
01267 uint_16 prdev = (uint_16)flp->fl_rdev;
01268 (void) headerAddOrAppendEntry(h, RPMTAG_FILERDEVS, RPM_INT16_TYPE,
01269 &(prdev), 1);
01270 } else {
01271 (void) headerAddOrAppendEntry(h, RPMTAG_FILERDEVS, RPM_INT16_TYPE,
01272 &(flp->fl_rdev), 1);
01273 }
01274 if (sizeof(flp->fl_dev) != sizeof(uint_32)) {
01275 uint_32 pdevice = (uint_32)flp->fl_dev;
01276 (void) headerAddOrAppendEntry(h, RPMTAG_FILEDEVICES, RPM_INT32_TYPE,
01277 &(pdevice), 1);
01278 } else {
01279 (void) headerAddOrAppendEntry(h, RPMTAG_FILEDEVICES, RPM_INT32_TYPE,
01280 &(flp->fl_dev), 1);
01281 }
01282 if (sizeof(flp->fl_ino) != sizeof(uint_32)) {
01283 uint_32 ino = (uint_32)flp->fl_ino;
01284 (void) headerAddOrAppendEntry(h, RPMTAG_FILEINODES, RPM_INT32_TYPE,
01285 &(ino), 1);
01286 } else {
01287 (void) headerAddOrAppendEntry(h, RPMTAG_FILEINODES, RPM_INT32_TYPE,
01288 &(flp->fl_ino), 1);
01289 }
01290
01291
01292 (void) headerAddOrAppendEntry(h, RPMTAG_FILELANGS, RPM_STRING_ARRAY_TYPE,
01293 &(flp->langs), 1);
01294
01295
01296
01297
01298
01299
01300
01301
01302 buf[0] = '\0';
01303 if (S_ISREG(flp->fl_mode))
01304 (void) domd5(flp->diskURL, buf, 1, NULL);
01305 s = buf;
01306 (void) headerAddOrAppendEntry(h, RPMTAG_FILEMD5S, RPM_STRING_ARRAY_TYPE,
01307 &s, 1);
01308
01309 buf[0] = '\0';
01310 if (S_ISLNK(flp->fl_mode)) {
01311 buf[Readlink(flp->diskURL, buf, BUFSIZ)] = '\0';
01312 if (fl->buildRootURL) {
01313 const char * buildRoot;
01314 (void) urlPath(fl->buildRootURL, &buildRoot);
01315
01316 if (buf[0] == '/' && strcmp(buildRoot, "/") &&
01317 !strncmp(buf, buildRoot, strlen(buildRoot))) {
01318 rpmError(RPMERR_BADSPEC,
01319 _("Symlink points to BuildRoot: %s -> %s\n"),
01320 flp->fileURL, buf);
01321 fl->processingFailed = 1;
01322 }
01323 }
01324 }
01325 s = buf;
01326 (void) headerAddOrAppendEntry(h, RPMTAG_FILELINKTOS, RPM_STRING_ARRAY_TYPE,
01327 &s, 1);
01328
01329 if (flp->flags & RPMFILE_GHOST) {
01330 flp->verifyFlags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE |
01331 RPMVERIFY_LINKTO | RPMVERIFY_MTIME);
01332 }
01333 (void) headerAddOrAppendEntry(h, RPMTAG_FILEVERIFYFLAGS, RPM_INT32_TYPE,
01334 &(flp->verifyFlags), 1);
01335
01336 if (!isSrc && isDoc(fl, flp->fileURL))
01337 flp->flags |= RPMFILE_DOC;
01338
01339 if (S_ISDIR(flp->fl_mode))
01340 flp->flags &= ~(RPMFILE_CONFIG|RPMFILE_DOC);
01341
01342 (void) headerAddOrAppendEntry(h, RPMTAG_FILEFLAGS, RPM_INT32_TYPE,
01343 &(flp->flags), 1);
01344
01345 }
01346 (void) headerAddEntry(h, RPMTAG_SIZE, RPM_INT32_TYPE,
01347 &(fl->totalFileSize), 1);
01348
01349
01350
01351
01352
01353 if (multiLibMask)
01354 (void) headerAddEntry(h, RPMTAG_MULTILIBS, RPM_INT32_TYPE,
01355 &multiLibMask, 1);
01356
01357 if (_addDotSlash)
01358 (void) rpmlibNeedsFeature(h, "PayloadFilesHavePrefix", "4.0-1");
01359
01360
01361 if (_noDirTokens)
01362 expandFilelist(h);
01363 else {
01364 compressFilelist(h);
01365
01366 (void) rpmlibNeedsFeature(h, "CompressedFileNames", "3.0.4-1");
01367 }
01368
01369 { int scareMem = 1;
01370 rpmts ts = NULL;
01371 rpmfi fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem);
01372 char * a, * d;
01373
01374 if (fi == NULL) return;
01375
01376
01377 fi->te = xcalloc(1, sizeof(*fi->te));
01378
01379 fi->te->type = TR_ADDED;
01380
01381 fi->dnl = _free(fi->dnl);
01382 fi->bnl = _free(fi->bnl);
01383
01384 fi->dnl = xmalloc(fi->fc * sizeof(*fi->dnl) + dpathlen);
01385 d = (char *)(fi->dnl + fi->fc);
01386 *d = '\0';
01387
01388 fi->bnl = xmalloc(fi->fc * (sizeof(*fi->bnl) + sizeof(*fi->dil)));
01389
01390 fi->dil = (int *)(fi->bnl + fi->fc);
01391
01392
01393 fi->apath = xmalloc(fi->fc * sizeof(*fi->apath) + apathlen);
01394 a = (char *)(fi->apath + fi->fc);
01395 *a = '\0';
01396
01397 fi->actions = xcalloc(sizeof(*fi->actions), fi->fc);
01398 fi->fmapflags = xcalloc(sizeof(*fi->fmapflags), fi->fc);
01399 fi->astriplen = 0;
01400 if (fl->buildRootURL)
01401 fi->astriplen = strlen(fl->buildRootURL);
01402 fi->striplen = 0;
01403 fi->fuser = NULL;
01404 fi->fuids = xcalloc(sizeof(*fi->fuids), fi->fc);
01405 fi->fgroup = NULL;
01406 fi->fgids = xcalloc(sizeof(*fi->fgids), fi->fc);
01407
01408
01409 for (i = 0, flp = fl->fileList; i < fi->fc; i++, flp++) {
01410 char * b;
01411
01412
01413 while (((flp - fl->fileList) < (fl->fileListRecsUsed - 1)) &&
01414 !strcmp(flp->fileURL, flp[1].fileURL))
01415 flp++;
01416
01417 if (flp->flags & RPMFILE_EXCLUDE) {
01418 i--;
01419 continue;
01420 }
01421
01422
01423 fi->dil[i] = i;
01424
01425 fi->dnl[fi->dil[i]] = d;
01426
01427 #ifdef IA64_SUCKS_ROCKS
01428 (void) stpcpy(d, flp->diskURL);
01429 d += strlen(d);
01430 #else
01431 d = stpcpy(d, flp->diskURL);
01432 #endif
01433
01434
01435 for (b = d; b > fi->dnl[fi->dil[i]] && *b != '/'; b--)
01436 b[1] = b[0];
01437 b++;
01438 *b++ = '\0';
01439 fi->bnl[i] = b;
01440 d += 2;
01441
01442
01443
01444 fi->apath[i] = a;
01445
01446 if (_addDotSlash) {
01447 #ifdef IA64_SUCKS_ROCKS
01448 (void) stpcpy(a, "./");
01449 a += strlen(a);
01450 #else
01451 a = stpcpy(a, "./");
01452 #endif
01453 }
01454 #ifdef IA64_SUCKS_ROCKS
01455 (void) stpcpy(a, (flp->fileURL + skipLen));
01456 a += strlen(a);
01457 #else
01458 a = stpcpy(a, (flp->fileURL + skipLen));
01459 #endif
01460 a++;
01461
01462 if (flp->flags & RPMFILE_GHOST) {
01463 fi->actions[i] = FA_SKIP;
01464 continue;
01465 }
01466 fi->actions[i] = FA_COPYOUT;
01467 fi->fuids[i] = getUidS(flp->uname);
01468 fi->fgids[i] = getGidS(flp->gname);
01469 if (fi->fuids[i] == (uid_t)-1) fi->fuids[i] = 0;
01470 if (fi->fgids[i] == (gid_t)-1) fi->fgids[i] = 0;
01471 fi->fmapflags[i] = CPIO_MAP_PATH |
01472 CPIO_MAP_TYPE | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
01473 if (isSrc)
01474 fi->fmapflags[i] |= CPIO_FOLLOW_SYMLINKS;
01475 if (flp->flags & RPMFILE_MULTILIB_MASK)
01476 fi->fmapflags[i] |= CPIO_MULTILIB;
01477
01478 }
01479
01480 if (cpioList)
01481 *cpioList = fi;
01482 else
01483 fi = _free(fi);
01484
01485 }
01486 }
01487
01488
01491
01492 static FileListRec freeFileList( FileListRec fileList,
01493 int count)
01494
01495 {
01496 while (count--) {
01497 fileList[count].diskURL = _free(fileList[count].diskURL);
01498 fileList[count].fileURL = _free(fileList[count].fileURL);
01499 fileList[count].langs = _free(fileList[count].langs);
01500 }
01501 fileList = _free(fileList);
01502 return NULL;
01503 }
01504
01505
01513
01514 static int addFile(FileList fl, const char * diskURL,
01515 struct stat * statp)
01516
01517
01518
01519
01520
01521
01522
01523 {
01524 const char *fileURL = diskURL;
01525 struct stat statbuf;
01526 mode_t fileMode;
01527 uid_t fileUid;
01528 gid_t fileGid;
01529 const char *fileUname;
01530 const char *fileGname;
01531 char *lang;
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544 { const char *fileName;
01545 (void) urlPath(fileURL, &fileName);
01546 if (fl->buildRootURL && strcmp(fl->buildRootURL, "/"))
01547 fileURL += strlen(fl->buildRootURL);
01548 }
01549
01550
01551
01552 if (*fileURL == '\0')
01553 fileURL = "/";
01554
01555
01556
01557 if (!fl->inFtw && fl->prefix) {
01558 const char *prefixTest;
01559 const char *prefixPtr = fl->prefix;
01560
01561 (void) urlPath(fileURL, &prefixTest);
01562 while (*prefixPtr && *prefixTest && (*prefixTest == *prefixPtr)) {
01563 prefixPtr++;
01564 prefixTest++;
01565 }
01566 if (*prefixPtr || (*prefixTest && *prefixTest != '/')) {
01567 rpmError(RPMERR_BADSPEC, _("File doesn't match prefix (%s): %s\n"),
01568 fl->prefix, fileURL);
01569 fl->processingFailed = 1;
01570 return RPMERR_BADSPEC;
01571 }
01572 }
01573
01574 if (statp == NULL) {
01575 statp = &statbuf;
01576 memset(statp, 0, sizeof(*statp));
01577 if (fl->devtype) {
01578 time_t now = time(NULL);
01579
01580
01581 statp->st_nlink = 1;
01582 statp->st_rdev =
01583 ((fl->devmajor & 0xff) << 8) | (fl->devminor & 0xff);
01584 statp->st_dev = statp->st_rdev;
01585 statp->st_mode = (fl->devtype == 'b' ? S_IFBLK : S_IFCHR);
01586 statp->st_mode |= (fl->cur_ar.ar_fmode & 0777);
01587 statp->st_atime = now;
01588 statp->st_mtime = now;
01589 statp->st_ctime = now;
01590 } else if (Lstat(diskURL, statp)) {
01591 rpmError(RPMERR_BADSPEC, _("File not found: %s\n"), diskURL);
01592 fl->processingFailed = 1;
01593 return RPMERR_BADSPEC;
01594 }
01595 }
01596
01597 if ((! fl->isDir) && S_ISDIR(statp->st_mode)) {
01598
01599
01600
01601
01602 fl->inFtw = 1;
01603 fl->isDir = 1;
01604 (void) myftw(diskURL, 16, (myftwFunc) addFile, fl);
01605 fl->isDir = 0;
01606 fl->inFtw = 0;
01607 return 0;
01608 }
01609
01610 fileMode = statp->st_mode;
01611 fileUid = statp->st_uid;
01612 fileGid = statp->st_gid;
01613
01614 if (S_ISDIR(fileMode) && fl->cur_ar.ar_dmodestr) {
01615 fileMode &= S_IFMT;
01616 fileMode |= fl->cur_ar.ar_dmode;
01617 } else if (fl->cur_ar.ar_fmodestr != NULL) {
01618 fileMode &= S_IFMT;
01619 fileMode |= fl->cur_ar.ar_fmode;
01620 }
01621 if (fl->cur_ar.ar_user) {
01622 fileUname = getUnameS(fl->cur_ar.ar_user);
01623 } else {
01624 fileUname = getUname(fileUid);
01625 }
01626 if (fl->cur_ar.ar_group) {
01627 fileGname = getGnameS(fl->cur_ar.ar_group);
01628 } else {
01629 fileGname = getGname(fileGid);
01630 }
01631
01632 #if 0
01633 if (! (fileUname && fileGname)) {
01634 rpmError(RPMERR_BADSPEC, _("Bad owner/group: %s\n"), diskName);
01635 fl->processingFailed = 1;
01636 return RPMERR_BADSPEC;
01637 }
01638 #else
01639
01640 if (fileUname == NULL)
01641 fileUname = getUname(getuid());
01642 if (fileGname == NULL)
01643 fileGname = getGname(getgid());
01644 #endif
01645
01646 #ifdef DYING
01647 rpmMessage(RPMMESS_DEBUG, _("File%5d: %07o %s.%s\t %s\n"), fl->fileCount,
01648 (unsigned)fileMode, fileUname, fileGname, fileURL);
01649 #endif
01650
01651
01652 if (check_fileList && S_ISREG(fileMode)) {
01653 appendStringBuf(check_fileList, diskURL);
01654 appendStringBuf(check_fileList, "\n");
01655 check_fileListLen += strlen(diskURL) + 1;
01656 }
01657
01658
01659 if (fl->fileListRecsUsed == fl->fileListRecsAlloced) {
01660 fl->fileListRecsAlloced += 128;
01661 fl->fileList = xrealloc(fl->fileList,
01662 fl->fileListRecsAlloced * sizeof(*(fl->fileList)));
01663 }
01664
01665 { FileListRec flp = &fl->fileList[fl->fileListRecsUsed];
01666 int i;
01667
01668 flp->fl_st = *statp;
01669 flp->fl_mode = fileMode;
01670 flp->fl_uid = fileUid;
01671 flp->fl_gid = fileGid;
01672
01673 flp->fileURL = xstrdup(fileURL);
01674 flp->diskURL = xstrdup(diskURL);
01675 flp->uname = fileUname;
01676 flp->gname = fileGname;
01677
01678 if (fl->currentLangs && fl->nLangs > 0) {
01679 char * ncl;
01680 size_t nl = 0;
01681
01682 for (i = 0; i < fl->nLangs; i++)
01683 nl += strlen(fl->currentLangs[i]) + 1;
01684
01685 flp->langs = ncl = xmalloc(nl);
01686 for (i = 0; i < fl->nLangs; i++) {
01687 const char *ocl;
01688 if (i) *ncl++ = '|';
01689 for (ocl = fl->currentLangs[i]; *ocl != '\0'; ocl++)
01690 *ncl++ = *ocl;
01691 *ncl = '\0';
01692 }
01693 } else if (! parseForRegexLang(fileURL, &lang)) {
01694 flp->langs = xstrdup(lang);
01695 } else {
01696 flp->langs = xstrdup("");
01697 }
01698
01699 flp->flags = fl->currentFlags;
01700 flp->specdFlags = fl->currentSpecdFlags;
01701 flp->verifyFlags = fl->currentVerifyFlags;
01702
01703 if (multiLib
01704 && !(flp->flags & RPMFILE_MULTILIB_MASK)
01705 && !parseForRegexMultiLib(fileURL))
01706 flp->flags |= multiLib;
01707
01708
01709
01710 if (S_ISREG(flp->fl_mode) && flp->fl_nlink > 1) {
01711 FileListRec ilp;
01712 for (i = 0; i < fl->fileListRecsUsed; i++) {
01713 ilp = fl->fileList + i;
01714 if (!S_ISREG(ilp->fl_mode))
01715 continue;
01716 if (flp->fl_nlink != ilp->fl_nlink)
01717 continue;
01718 if (flp->fl_ino != ilp->fl_ino)
01719 continue;
01720 if (flp->fl_dev != ilp->fl_dev)
01721 continue;
01722 break;
01723 }
01724 } else
01725 i = fl->fileListRecsUsed;
01726
01727 if (S_ISREG(flp->fl_mode) && i >= fl->fileListRecsUsed)
01728 fl->totalFileSize += flp->fl_size;
01729 }
01730
01731 fl->fileListRecsUsed++;
01732 fl->fileCount++;
01733
01734 return 0;
01735 }
01736
01737
01745
01746 static int processBinaryFile( Package pkg, FileList fl,
01747 const char * fileURL)
01748
01749
01750
01751
01752
01753 {
01754 int doGlob;
01755 const char *diskURL = NULL;
01756 int rc = 0;
01757
01758 doGlob = myGlobPatternP(fileURL);
01759
01760
01761 { const char * fileName;
01762 (void) urlPath(fileURL, &fileName);
01763 if (*fileName != '/') {
01764 rpmError(RPMERR_BADSPEC, _("File needs leading \"/\": %s\n"),
01765 fileName);
01766 rc = 1;
01767 goto exit;
01768 }
01769 }
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779 diskURL = rpmGenPath(fl->buildRootURL, NULL, fileURL);
01780
01781 if (doGlob) {
01782 const char ** argv = NULL;
01783 int argc = 0;
01784 int i;
01785
01786 if (fl->noGlob) {
01787 rpmError(RPMERR_BADSPEC, _("Glob not permitted: %s\n"),
01788 diskURL);
01789 rc = 1;
01790 goto exit;
01791 }
01792
01793
01794 rc = rpmGlob(diskURL, &argc, &argv);
01795 if (rc == 0 && argc >= 1 && !myGlobPatternP(argv[0])) {
01796 for (i = 0; i < argc; i++) {
01797 rc = addFile(fl, argv[i], NULL);
01798 argv[i] = _free(argv[i]);
01799 }
01800 argv = _free(argv);
01801 } else {
01802 rpmError(RPMERR_BADSPEC, _("File not found by glob: %s\n"),
01803 diskURL);
01804 rc = 1;
01805 }
01806
01807 } else {
01808 rc = addFile(fl, diskURL, NULL);
01809 }
01810
01811 exit:
01812 diskURL = _free(diskURL);
01813 if (rc)
01814 fl->processingFailed = 1;
01815 return rc;
01816 }
01817
01818
01821
01822 static int processPackageFiles(Spec spec, Package pkg,
01823 int installSpecialDoc, int test)
01824
01825
01826
01827
01828
01829 {
01830 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
01831 struct FileList_s fl;
01832 char *s, **files, **fp;
01833 const char *fileName;
01834 char buf[BUFSIZ];
01835 struct AttrRec_s arbuf;
01836 AttrRec specialDocAttrRec = &arbuf;
01837 char *specialDoc = NULL;
01838
01839 #ifdef MULTILIB
01840 multiLib = rpmExpandNumeric("%{_multilibno}");
01841 if (multiLib)
01842 multiLib = RPMFILE_MULTILIB(multiLib);
01843 #endif
01844
01845 nullAttrRec(specialDocAttrRec);
01846 pkg->cpioList = NULL;
01847
01848 if (pkg->fileFile) {
01849 const char *ffn;
01850 FILE * f;
01851 FD_t fd;
01852
01853
01854 if (*pkg->fileFile == '/') {
01855 ffn = rpmGetPath(pkg->fileFile, NULL);
01856 } else {
01857
01858 ffn = rpmGetPath("%{_builddir}/",
01859 (spec->buildSubdir ? spec->buildSubdir : "") ,
01860 "/", pkg->fileFile, NULL);
01861 }
01862 fd = Fopen(ffn, "r.fpio");
01863
01864 if (fd == NULL || Ferror(fd)) {
01865 rpmError(RPMERR_BADFILENAME,
01866 _("Could not open %%files file %s: %s\n"),
01867 ffn, Fstrerror(fd));
01868 return RPMERR_BADFILENAME;
01869 }
01870 ffn = _free(ffn);
01871
01872 f = fdGetFp(fd);
01873 if (f != NULL)
01874 while (fgets(buf, sizeof(buf), f)) {
01875 handleComments(buf);
01876 if (expandMacros(spec, spec->macros, buf, sizeof(buf))) {
01877 rpmError(RPMERR_BADSPEC, _("line: %s\n"), buf);
01878 return RPMERR_BADSPEC;
01879 }
01880 appendStringBuf(pkg->fileList, buf);
01881 }
01882 (void) Fclose(fd);
01883 }
01884
01885
01886 memset(&fl, 0, sizeof(fl));
01887
01888
01889 fl.buildRootURL = rpmGenPath(spec->rootURL, spec->buildRootURL, NULL);
01890
01891 if (hge(pkg->header, RPMTAG_DEFAULTPREFIX, NULL, (void **)&fl.prefix, NULL))
01892 fl.prefix = xstrdup(fl.prefix);
01893 else
01894 fl.prefix = NULL;
01895
01896 fl.fileCount = 0;
01897 fl.totalFileSize = 0;
01898 fl.processingFailed = 0;
01899
01900 fl.passedSpecialDoc = 0;
01901 fl.isSpecialDoc = 0;
01902
01903 fl.isDir = 0;
01904 fl.inFtw = 0;
01905 fl.currentFlags = 0;
01906 fl.currentVerifyFlags = 0;
01907
01908 fl.noGlob = 0;
01909 fl.devtype = 0;
01910 fl.devmajor = 0;
01911 fl.devminor = 0;
01912
01913 nullAttrRec(&fl.cur_ar);
01914 nullAttrRec(&fl.def_ar);
01915
01916 fl.defVerifyFlags = RPMVERIFY_ALL;
01917 fl.nLangs = 0;
01918 fl.currentLangs = NULL;
01919
01920 fl.currentSpecdFlags = 0;
01921 fl.defSpecdFlags = 0;
01922
01923 fl.docDirCount = 0;
01924 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/doc");
01925 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/man");
01926 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/info");
01927 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/X11R6/man");
01928 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/share/doc");
01929 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/share/man");
01930 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/share/info");
01931 fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_docdir}", NULL);
01932 fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_mandir}", NULL);
01933 fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_infodir}", NULL);
01934
01935 fl.fileList = NULL;
01936 fl.fileListRecsAlloced = 0;
01937 fl.fileListRecsUsed = 0;
01938
01939 s = getStringBuf(pkg->fileList);
01940 files = splitString(s, strlen(s), '\n');
01941
01942 for (fp = files; *fp != NULL; fp++) {
01943 s = *fp;
01944 SKIPSPACE(s);
01945 if (*s == '\0')
01946 continue;
01947 fileName = NULL;
01948
01949 strcpy(buf, s);
01950
01951
01952
01953 fl.isDir = 0;
01954 fl.inFtw = 0;
01955 fl.currentFlags = 0;
01956
01957 fl.currentSpecdFlags = ((unsigned)fl.defSpecdFlags) >> 8;
01958 fl.currentVerifyFlags = fl.defVerifyFlags;
01959 fl.isSpecialDoc = 0;
01960
01961 fl.noGlob = 0;
01962 fl.devtype = 0;
01963 fl.devmajor = 0;
01964 fl.devminor = 0;
01965
01966
01967 if (fl.currentLangs) {
01968 int i;
01969 for (i = 0; i < fl.nLangs; i++)
01970
01971 fl.currentLangs[i] = _free(fl.currentLangs[i]);
01972
01973 fl.currentLangs = _free(fl.currentLangs);
01974 }
01975 fl.nLangs = 0;
01976
01977 dupAttrRec(&fl.def_ar, &fl.cur_ar);
01978
01979
01980 if (parseForVerify(buf, &fl))
01981 continue;
01982 if (parseForAttr(buf, &fl))
01983 continue;
01984 if (parseForDev(buf, &fl))
01985 continue;
01986 if (parseForConfig(buf, &fl))
01987 continue;
01988 if (parseForLang(buf, &fl))
01989 continue;
01990
01991 if (parseForSimple(spec, pkg, buf, &fl, &fileName))
01992
01993 continue;
01994
01995 if (fileName == NULL)
01996 continue;
01997
01998
01999 if (fl.isSpecialDoc) {
02000
02001 specialDoc = _free(specialDoc);
02002 specialDoc = xstrdup(fileName);
02003 dupAttrRec(&fl.cur_ar, specialDocAttrRec);
02004 } else {
02005
02006 (void) processBinaryFile(pkg, &fl, fileName);
02007
02008 }
02009
02010 }
02011
02012
02013 if (specialDoc) {
02014 if (installSpecialDoc) {
02015 static int _missing_doc_files_terminate_build = 0;
02016 static int oneshot = 0;
02017 int rc;
02018
02019 if (!oneshot) {
02020 _missing_doc_files_terminate_build =
02021 rpmExpandNumeric("%{?_missing_doc_files_terminate_build}");
02022 oneshot = 1;
02023 }
02024 rc = doScript(spec, RPMBUILD_STRINGBUF, "%doc", pkg->specialDoc, test);
02025 if (rc && _missing_doc_files_terminate_build)
02026 fl.processingFailed = rc;
02027 }
02028
02029
02030 fl.isDir = 0;
02031 fl.inFtw = 0;
02032 fl.currentFlags = 0;
02033 fl.currentVerifyFlags = 0;
02034
02035 fl.noGlob = 0;
02036 fl.devtype = 0;
02037 fl.devmajor = 0;
02038 fl.devminor = 0;
02039
02040
02041 if (fl.currentLangs) {
02042 int i;
02043 for (i = 0; i < fl.nLangs; i++)
02044
02045 fl.currentLangs[i] = _free(fl.currentLangs[i]);
02046
02047 fl.currentLangs = _free(fl.currentLangs);
02048 }
02049 fl.nLangs = 0;
02050
02051 dupAttrRec(specialDocAttrRec, &fl.cur_ar);
02052 freeAttrRec(specialDocAttrRec);
02053
02054
02055 (void) processBinaryFile(pkg, &fl, specialDoc);
02056
02057
02058 specialDoc = _free(specialDoc);
02059 }
02060
02061 freeSplitString(files);
02062
02063 if (fl.processingFailed)
02064 goto exit;
02065
02066
02067 if (checkHardLinks(&fl))
02068 (void) rpmlibNeedsFeature(pkg->header,
02069 "PartialHardlinkSets", "4.0.4-1");
02070
02071 genCpioListAndHeader(&fl, (rpmfi *)&pkg->cpioList, pkg->header, 0);
02072
02073 if (spec->timeCheck)
02074 timeCheck(spec->timeCheck, pkg->header);
02075
02076 exit:
02077 fl.buildRootURL = _free(fl.buildRootURL);
02078 fl.prefix = _free(fl.prefix);
02079
02080 freeAttrRec(&fl.cur_ar);
02081 freeAttrRec(&fl.def_ar);
02082
02083 if (fl.currentLangs) {
02084 int i;
02085 for (i = 0; i < fl.nLangs; i++)
02086
02087 fl.currentLangs[i] = _free(fl.currentLangs[i]);
02088
02089 fl.currentLangs = _free(fl.currentLangs);
02090 }
02091
02092 fl.fileList = freeFileList(fl.fileList, fl.fileListRecsUsed);
02093 while (fl.docDirCount--)
02094 fl.docDirs[fl.docDirCount] = _free(fl.docDirs[fl.docDirCount]);
02095 return fl.processingFailed;
02096 }
02097
02098
02099 void initSourceHeader(Spec spec)
02100 {
02101 HeaderIterator hi;
02102 int_32 tag, type, count;
02103 const void * ptr;
02104
02105 spec->sourceHeader = headerNew();
02106
02107
02108 for (hi = headerInitIterator(spec->packages->header);
02109 headerNextIterator(hi, &tag, &type, &ptr, &count);
02110 ptr = headerFreeData(ptr, type))
02111 {
02112 switch (tag) {
02113 case RPMTAG_NAME:
02114 case RPMTAG_VERSION:
02115 case RPMTAG_RELEASE:
02116 case RPMTAG_EPOCH:
02117 case RPMTAG_SUMMARY:
02118 case RPMTAG_DESCRIPTION:
02119 case RPMTAG_PACKAGER:
02120 case RPMTAG_DISTRIBUTION:
02121 case RPMTAG_DISTURL:
02122 case RPMTAG_VENDOR:
02123 case RPMTAG_LICENSE:
02124 case RPMTAG_GROUP:
02125 case RPMTAG_OS:
02126 case RPMTAG_ARCH:
02127 case RPMTAG_CHANGELOGTIME:
02128 case RPMTAG_CHANGELOGNAME:
02129 case RPMTAG_CHANGELOGTEXT:
02130 case RPMTAG_URL:
02131 case HEADER_I18NTABLE:
02132 if (ptr)
02133 (void)headerAddEntry(spec->sourceHeader, tag, type, ptr, count);
02134 break;
02135 default:
02136
02137 break;
02138 }
02139 }
02140 hi = headerFreeIterator(hi);
02141
02142
02143
02144
02145 for (hi = headerInitIterator(spec->buildRestrictions);
02146 headerNextIterator(hi, &tag, &type, &ptr, &count);
02147 ptr = headerFreeData(ptr, type))
02148 {
02149 if (ptr)
02150 (void) headerAddEntry(spec->sourceHeader, tag, type, ptr, count);
02151 }
02152 hi = headerFreeIterator(hi);
02153
02154
02155 if (spec->BANames && spec->BACount > 0) {
02156 (void) headerAddEntry(spec->sourceHeader, RPMTAG_BUILDARCHS,
02157 RPM_STRING_ARRAY_TYPE,
02158 spec->BANames, spec->BACount);
02159 }
02160 }
02161
02162 int processSourceFiles(Spec spec)
02163 {
02164 struct Source *srcPtr;
02165 StringBuf sourceFiles;
02166 int x, isSpec = 1;
02167 struct FileList_s fl;
02168 char *s, **files, **fp;
02169 Package pkg;
02170
02171 sourceFiles = newStringBuf();
02172
02173
02174
02175
02176
02177 if (spec->sourceHeader == NULL)
02178 initSourceHeader(spec);
02179
02180
02181 appendLineStringBuf(sourceFiles, spec->specFile);
02182 if (spec->sourceHeader != NULL)
02183 for (srcPtr = spec->sources; srcPtr != NULL; srcPtr = srcPtr->next) {
02184 if (srcPtr->flags & RPMBUILD_ISSOURCE) {
02185 (void) headerAddOrAppendEntry(spec->sourceHeader, RPMTAG_SOURCE,
02186 RPM_STRING_ARRAY_TYPE, &srcPtr->source, 1);
02187 if (srcPtr->flags & RPMBUILD_ISNO) {
02188 (void) headerAddOrAppendEntry(spec->sourceHeader, RPMTAG_NOSOURCE,
02189 RPM_INT32_TYPE, &srcPtr->num, 1);
02190 }
02191 }
02192 if (srcPtr->flags & RPMBUILD_ISPATCH) {
02193 (void) headerAddOrAppendEntry(spec->sourceHeader, RPMTAG_PATCH,
02194 RPM_STRING_ARRAY_TYPE, &srcPtr->source, 1);
02195 if (srcPtr->flags & RPMBUILD_ISNO) {
02196 (void) headerAddOrAppendEntry(spec->sourceHeader, RPMTAG_NOPATCH,
02197 RPM_INT32_TYPE, &srcPtr->num, 1);
02198 }
02199 }
02200
02201 { const char * sfn;
02202 sfn = rpmGetPath( ((srcPtr->flags & RPMBUILD_ISNO) ? "!" : ""),
02203 "%{_sourcedir}/", srcPtr->source, NULL);
02204 appendLineStringBuf(sourceFiles, sfn);
02205 sfn = _free(sfn);
02206 }
02207 }
02208
02209 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
02210 for (srcPtr = pkg->icon; srcPtr != NULL; srcPtr = srcPtr->next) {
02211 const char * sfn;
02212 sfn = rpmGetPath( ((srcPtr->flags & RPMBUILD_ISNO) ? "!" : ""),
02213 "%{_sourcedir}/", srcPtr->source, NULL);
02214 appendLineStringBuf(sourceFiles, sfn);
02215 sfn = _free(sfn);
02216 }
02217 }
02218
02219 spec->sourceCpioList = NULL;
02220
02221 fl.fileList = xcalloc((spec->numSources + 1), sizeof(*fl.fileList));
02222 fl.processingFailed = 0;
02223 fl.fileListRecsUsed = 0;
02224 fl.totalFileSize = 0;
02225 fl.prefix = NULL;
02226 fl.buildRootURL = NULL;
02227
02228 s = getStringBuf(sourceFiles);
02229 files = splitString(s, strlen(s), '\n');
02230
02231
02232 x = 0;
02233 for (fp = files; *fp != NULL; fp++) {
02234 const char * diskURL, *diskPath;
02235 FileListRec flp;
02236
02237 diskURL = *fp;
02238 SKIPSPACE(diskURL);
02239 if (! *diskURL)
02240 continue;
02241
02242 flp = &fl.fileList[x];
02243
02244 flp->flags = isSpec ? RPMFILE_SPECFILE : 0;
02245
02246 if (*diskURL == '!') {
02247 flp->flags |= RPMFILE_GHOST;
02248 diskURL++;
02249 }
02250
02251 (void) urlPath(diskURL, &diskPath);
02252
02253 flp->diskURL = xstrdup(diskURL);
02254 diskPath = strrchr(diskPath, '/');
02255 if (diskPath)
02256 diskPath++;
02257 else
02258 diskPath = diskURL;
02259
02260 flp->fileURL = xstrdup(diskPath);
02261 flp->verifyFlags = RPMVERIFY_ALL;
02262
02263 if (Stat(diskURL, &flp->fl_st)) {
02264 rpmError(RPMERR_BADSPEC, _("Bad file: %s: %s\n"),
02265 diskURL, strerror(errno));
02266 fl.processingFailed = 1;
02267 }
02268
02269 flp->uname = getUname(flp->fl_uid);
02270 flp->gname = getGname(flp->fl_gid);
02271 flp->langs = xstrdup("");
02272
02273 fl.totalFileSize += flp->fl_size;
02274
02275 if (! (flp->uname && flp->gname)) {
02276 rpmError(RPMERR_BADSPEC, _("Bad owner/group: %s\n"), diskURL);
02277 fl.processingFailed = 1;
02278 }
02279
02280 isSpec = 0;
02281 x++;
02282 }
02283 fl.fileListRecsUsed = x;
02284 freeSplitString(files);
02285
02286 if (! fl.processingFailed) {
02287 if (spec->sourceHeader != NULL)
02288 genCpioListAndHeader(&fl, (rpmfi *)&spec->sourceCpioList,
02289 spec->sourceHeader, 1);
02290 }
02291
02292 sourceFiles = freeStringBuf(sourceFiles);
02293 fl.fileList = freeFileList(fl.fileList, fl.fileListRecsUsed);
02294 return fl.processingFailed;
02295 }
02296
02299
02300 static StringBuf getOutputFrom(char * dir, char * argv[],
02301 const char * writePtr, int writeBytesLeft,
02302 int failNonZero)
02303
02304
02305 {
02306 int progPID;
02307 int toProg[2];
02308 int fromProg[2];
02309 int status;
02310 void *oldhandler;
02311 StringBuf readBuff;
02312 int done;
02313
02314
02315 oldhandler = signal(SIGPIPE, SIG_IGN);
02316
02317
02318 toProg[0] = toProg[1] = 0;
02319 (void) pipe(toProg);
02320 fromProg[0] = fromProg[1] = 0;
02321 (void) pipe(fromProg);
02322
02323 if (!(progPID = fork())) {
02324 (void) close(toProg[1]);
02325 (void) close(fromProg[0]);
02326
02327 (void) dup2(toProg[0], STDIN_FILENO);
02328 (void) dup2(fromProg[1], STDOUT_FILENO);
02329
02330 (void) close(toProg[0]);
02331 (void) close(fromProg[1]);
02332
02333 if (dir) {
02334 (void) chdir(dir);
02335 }
02336
02337 unsetenv("MALLOC_CHECK_");
02338 (void) execvp(argv[0], argv);
02339
02340 rpmError(RPMERR_EXEC, _("Couldn't exec %s: %s\n"),
02341 argv[0], strerror(errno));
02342 _exit(RPMERR_EXEC);
02343 }
02344 if (progPID < 0) {
02345 rpmError(RPMERR_FORK, _("Couldn't fork %s: %s\n"),
02346 argv[0], strerror(errno));
02347 return NULL;
02348 }
02349
02350 (void) close(toProg[0]);
02351 (void) close(fromProg[1]);
02352
02353
02354 (void) fcntl(fromProg[0], F_SETFL, O_NONBLOCK);
02355 (void) fcntl(toProg[1], F_SETFL, O_NONBLOCK);
02356
02357 readBuff = newStringBuf();
02358
02359 do {
02360 fd_set ibits, obits;
02361 struct timeval tv;
02362 int nfd, nbw, nbr;
02363 int rc;
02364
02365 done = 0;
02366 top:
02367
02368 FD_ZERO(&ibits);
02369 FD_ZERO(&obits);
02370 if (fromProg[0] >= 0) {
02371 FD_SET(fromProg[0], &ibits);
02372 }
02373 if (toProg[1] >= 0) {
02374 FD_SET(toProg[1], &obits);
02375 }
02376 tv.tv_sec = 1;
02377 tv.tv_usec = 0;
02378 nfd = ((fromProg[0] > toProg[1]) ? fromProg[0] : toProg[1]);
02379 if ((rc = select(nfd, &ibits, &obits, NULL, &tv)) < 0) {
02380 if (errno == EINTR)
02381 goto top;
02382 break;
02383 }
02384
02385
02386 if (toProg[1] >= 0 && FD_ISSET(toProg[1], &obits)) {
02387 if (writeBytesLeft) {
02388 if ((nbw = write(toProg[1], writePtr,
02389 (1024<writeBytesLeft) ? 1024 : writeBytesLeft)) < 0) {
02390 if (errno != EAGAIN) {
02391 perror("getOutputFrom()");
02392 exit(EXIT_FAILURE);
02393 }
02394 nbw = 0;
02395 }
02396 writeBytesLeft -= nbw;
02397 writePtr += nbw;
02398 } else if (toProg[1] >= 0) {
02399 (void) close(toProg[1]);
02400 toProg[1] = -1;
02401 }
02402 }
02403
02404
02405 { char buf[BUFSIZ+1];
02406 while ((nbr = read(fromProg[0], buf, sizeof(buf)-1)) > 0) {
02407 buf[nbr] = '\0';
02408 appendStringBuf(readBuff, buf);
02409 }
02410 }
02411
02412
02413 done = (nbr == 0 || (nbr < 0 && errno != EAGAIN));
02414
02415 } while (!done);
02416
02417
02418 if (toProg[1] >= 0)
02419 (void) close(toProg[1]);
02420 if (fromProg[0] >= 0)
02421 (void) close(fromProg[0]);
02422
02423 (void) signal(SIGPIPE, oldhandler);
02424
02425
02426
02427 (void)waitpid(progPID, &status, 0);
02428 if (failNonZero && (!WIFEXITED(status) || WEXITSTATUS(status))) {
02429 rpmError(RPMERR_EXEC, _("%s failed\n"), argv[0]);
02430 return NULL;
02431 }
02432 if (writeBytesLeft) {
02433 rpmError(RPMERR_EXEC, _("failed to write all data to %s\n"), argv[0]);
02434 return NULL;
02435 }
02436 return readBuff;
02437 }
02438
02439
02442 typedef struct {
02443 const char * msg;
02444 const char * argv[4];
02445 rpmTag ntag;
02446 rpmTag vtag;
02447 rpmTag ftag;
02448 int mask;
02449 int xor;
02450 } DepMsg_t;
02451
02454
02455
02456 DepMsg_t depMsgs[] = {
02457 { "Provides", { "%{__find_provides}", NULL, NULL, NULL },
02458 RPMTAG_PROVIDENAME, RPMTAG_PROVIDEVERSION, RPMTAG_PROVIDEFLAGS,
02459 0, -1 },
02460 { "PreReq", { NULL, NULL, NULL, NULL },
02461 RPMTAG_REQUIRENAME, RPMTAG_REQUIREVERSION, RPMTAG_REQUIREFLAGS,
02462 RPMSENSE_PREREQ, 0 },
02463 { "Requires(interp)", { NULL, "interp", NULL, NULL },
02464 -1, -1, RPMTAG_REQUIREFLAGS,
02465 _notpre(RPMSENSE_INTERP), 0 },
02466 { "Requires(rpmlib)", { NULL, "rpmlib", NULL, NULL },
02467 -1, -1, RPMTAG_REQUIREFLAGS,
02468 _notpre(RPMSENSE_RPMLIB), 0 },
02469 { "Requires(verify)", { NULL, "verify", NULL, NULL },
02470 -1, -1, RPMTAG_REQUIREFLAGS,
02471 RPMSENSE_SCRIPT_VERIFY, 0 },
02472 { "Requires(pre)", { NULL, "pre", NULL, NULL },
02473 -1, -1, RPMTAG_REQUIREFLAGS,
02474 _notpre(RPMSENSE_SCRIPT_PRE), 0 },
02475 { "Requires(post)", { NULL, "post", NULL, NULL },
02476 -1, -1, RPMTAG_REQUIREFLAGS,
02477 _notpre(RPMSENSE_SCRIPT_POST), 0 },
02478 { "Requires(preun)", { NULL, "preun", NULL, NULL },
02479 -1, -1, RPMTAG_REQUIREFLAGS,
02480 _notpre(RPMSENSE_SCRIPT_PREUN), 0 },
02481 { "Requires(postun)", { NULL, "postun", NULL, NULL },
02482 -1, -1, RPMTAG_REQUIREFLAGS,
02483 _notpre(RPMSENSE_SCRIPT_POSTUN), 0 },
02484 { "Requires", { "%{__find_requires}", NULL, NULL, NULL },
02485 -1, -1, RPMTAG_REQUIREFLAGS,
02486 RPMSENSE_PREREQ, RPMSENSE_PREREQ },
02487 { "Conflicts", { "%{__find_conflicts}", NULL, NULL, NULL },
02488 RPMTAG_CONFLICTNAME, RPMTAG_CONFLICTVERSION, RPMTAG_CONFLICTFLAGS,
02489 0, -1 },
02490 { "Obsoletes", { "%{__find_obsoletes}", NULL, NULL, NULL },
02491 RPMTAG_OBSOLETENAME, RPMTAG_OBSOLETEVERSION, RPMTAG_OBSOLETEFLAGS,
02492 0, -1 },
02493 { NULL, { NULL, NULL, NULL, NULL }, 0, 0, 0, 0, 0 }
02494 };
02495
02496
02499
02500 static int generateDepends(Spec spec, Package pkg, rpmfi cpioList, int multiLib)
02501
02502
02503
02504
02505 {
02506 rpmfi fi = cpioList;
02507 StringBuf writeBuf;
02508 int writeBytes;
02509 StringBuf readBuf;
02510 DepMsg_t *dm;
02511 char ** myargv;
02512 int failnonzero = 0;
02513 int rc = 0;
02514 int ac;
02515 int i;
02516
02517 myargv = xcalloc(5, sizeof(*myargv));
02518
02519 if (!(fi && fi->fc > 0))
02520 return 0;
02521
02522 if (! (pkg->autoReq || pkg->autoProv))
02523 return 0;
02524
02525 writeBuf = newStringBuf();
02526 for (i = 0, writeBytes = 0; i < fi->fc; i++) {
02527
02528 if (fi->fmapflags && multiLib == 2) {
02529 if (!(fi->fmapflags[i] & CPIO_MULTILIB))
02530 continue;
02531 fi->fmapflags[i] &= ~CPIO_MULTILIB;
02532 }
02533
02534 appendStringBuf(writeBuf, fi->dnl[fi->dil[i]]);
02535 writeBytes += strlen(fi->dnl[fi->dil[i]]);
02536 appendLineStringBuf(writeBuf, fi->bnl[i]);
02537 writeBytes += strlen(fi->bnl[i]) + 1;
02538 }
02539
02540 for (dm = depMsgs; dm->msg != NULL; dm++) {
02541 int tag, tagflags;
02542 char * s;
02543
02544 tag = (dm->ftag > 0) ? dm->ftag : dm->ntag;
02545 tagflags = 0;
02546 s = NULL;
02547
02548 switch(tag) {
02549 case RPMTAG_PROVIDEFLAGS:
02550 if (!pkg->autoProv)
02551 continue;
02552 failnonzero = 1;
02553 tagflags = RPMSENSE_FIND_PROVIDES;
02554 break;
02555 case RPMTAG_REQUIREFLAGS:
02556 if (!pkg->autoReq)
02557 continue;
02558 failnonzero = 0;
02559 tagflags = RPMSENSE_FIND_REQUIRES;
02560 break;
02561 default:
02562 continue;
02563 break;
02564 }
02565
02566
02567
02568 if (dm->argv[0] != NULL) {
02569 const char ** av;
02570
02571
02572 s = rpmExpand(dm->argv[0], NULL);
02573
02574 if (!(s != NULL && *s != '%' && *s != '\0')) {
02575 s = _free(s);
02576 continue;
02577 }
02578
02579 if (!(i = poptParseArgvString(s, &ac, (const char ***)&av))
02580 && ac > 0 && av != NULL)
02581 {
02582 myargv = xrealloc(myargv, (ac + 5) * sizeof(*myargv));
02583 for (i = 0; i < ac; i++)
02584 myargv[i] = xstrdup(av[i]);
02585 }
02586 av = _free(av);
02587 }
02588
02589
02590 if (myargv[0] == NULL)
02591 continue;
02592
02593 rpmMessage(RPMMESS_NORMAL, _("Finding %s: %s\n"), dm->msg,
02594 (s ? s : ""));
02595 s = _free(s);
02596
02597 #if 0
02598 if (*myargv[0] != '/') {
02599 myargv[0] = _free(myargv[0]);
02600 continue;
02601 }
02602 #endif
02603
02604
02605 for (i = 1; i < 4; i++) {
02606 if (dm->argv[i] == NULL)
02607 break;
02608
02609 myargv[ac++] = rpmExpand(dm->argv[i], NULL);
02610
02611 }
02612
02613 myargv[ac] = NULL;
02614 readBuf = getOutputFrom(NULL, myargv,
02615 getStringBuf(writeBuf), writeBytes, failnonzero);
02616
02617
02618 for (i = 0; i < ac; i++)
02619 myargv[i] = _free(myargv[i]);
02620
02621 if (readBuf == NULL) {
02622 rc = RPMERR_EXEC;
02623 rpmError(rc, _("Failed to find %s:\n"), dm->msg);
02624 break;
02625 }
02626
02627
02628 tagflags &= ~RPMSENSE_MULTILIB;
02629 if (multiLib > 1)
02630 tagflags |= RPMSENSE_MULTILIB;
02631 else
02632 tagflags &= ~RPMSENSE_MULTILIB;
02633 rc = parseRCPOT(spec, pkg, getStringBuf(readBuf), tag, 0, tagflags);
02634 readBuf = freeStringBuf(readBuf);
02635
02636 if (rc) {
02637 rpmError(rc, _("Failed to find %s:\n"), dm->msg);
02638 break;
02639 }
02640 }
02641
02642 writeBuf = freeStringBuf(writeBuf);
02643 myargv = _free(myargv);
02644 return rc;
02645 }
02646
02647
02650 static void printDepMsg(DepMsg_t * dm, int count, const char ** names,
02651 const char ** versions, int *flags)
02652
02653 {
02654 int hasVersions = (versions != NULL);
02655 int hasFlags = (flags != NULL);
02656 int bingo = 0;
02657 int i;
02658
02659 for (i = 0; i < count; i++, names++, versions++, flags++) {
02660 if (hasFlags && !((*flags & dm->mask) ^ dm->xor))
02661 continue;
02662 if (bingo == 0) {
02663 rpmMessage(RPMMESS_NORMAL, "%s:", (dm->msg ? dm->msg : ""));
02664 bingo = 1;
02665 }
02666 rpmMessage(RPMMESS_NORMAL, " %s", *names);
02667
02668 if (hasFlags && isDependsMULTILIB(*flags))
02669 rpmMessage(RPMMESS_NORMAL, " (multilib)");
02670
02671 if (hasVersions && !(*versions != NULL && **versions != '\0'))
02672 continue;
02673 if (!(hasFlags && (*flags && RPMSENSE_SENSEMASK)))
02674 continue;
02675
02676 rpmMessage(RPMMESS_NORMAL, " ");
02677 if (*flags & RPMSENSE_LESS)
02678 rpmMessage(RPMMESS_NORMAL, "<");
02679 if (*flags & RPMSENSE_GREATER)
02680 rpmMessage(RPMMESS_NORMAL, ">");
02681 if (*flags & RPMSENSE_EQUAL)
02682 rpmMessage(RPMMESS_NORMAL, "=");
02683
02684 rpmMessage(RPMMESS_NORMAL, " %s", *versions);
02685 }
02686 if (bingo)
02687 rpmMessage(RPMMESS_NORMAL, "\n");
02688 }
02689
02692 static void printDeps(Header h)
02693
02694 {
02695 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
02696 HFD_t hfd = headerFreeData;
02697 const char ** names = NULL;
02698 rpmTagType dnt = -1;
02699 const char ** versions = NULL;
02700 rpmTagType dvt = -1;
02701 int * flags = NULL;
02702 DepMsg_t * dm;
02703 int count, xx;
02704
02705 for (dm = depMsgs; dm->msg != NULL; dm++) {
02706 switch (dm->ntag) {
02707 case 0:
02708 names = hfd(names, dnt);
02709 break;
02710 case -1:
02711 break;
02712 default:
02713 names = hfd(names, dnt);
02714 if (!hge(h, dm->ntag, &dnt, (void **) &names, &count))
02715 continue;
02716 break;
02717 }
02718 switch (dm->vtag) {
02719 case 0:
02720 versions = hfd(versions, dvt);
02721 break;
02722 case -1:
02723 break;
02724 default:
02725 versions = hfd(versions, dvt);
02726 xx = hge(h, dm->vtag, &dvt, (void **) &versions, NULL);
02727 break;
02728 }
02729 switch (dm->ftag) {
02730 case 0:
02731 flags = NULL;
02732 break;
02733 case -1:
02734 break;
02735 default:
02736 xx = hge(h, dm->ftag, NULL, (void **) &flags, NULL);
02737 break;
02738 }
02739
02740 printDepMsg(dm, count, names, versions, flags);
02741
02742 }
02743 names = hfd(names, dnt);
02744 versions = hfd(versions, dvt);
02745 }
02746
02753 static int checkFiles(StringBuf fileList, int fileListLen)
02754
02755
02756 {
02757 StringBuf readBuf = NULL;
02758 const char * s = NULL;
02759 char ** av = NULL;
02760 int ac = 0;
02761 int rc = 0;
02762 char *buf;
02763
02764 s = rpmExpand("%{?__check_files}", NULL);
02765 if (!(s && *s)) {
02766 rc = -1;
02767 goto exit;
02768 }
02769 if (!((rc = poptParseArgvString(s, &ac, (const char ***)&av)) == 0
02770 && ac > 0 && av != NULL))
02771 {
02772 goto exit;
02773 }
02774
02775 rpmMessage(RPMMESS_NORMAL, _("Checking for unpackaged file(s): %s\n"), s);
02776
02777 readBuf = getOutputFrom(NULL, av, getStringBuf(fileList), fileListLen, 0);
02778
02779 if (readBuf) {
02780 static int _unpackaged_files_terminate_build = 0;
02781 static int oneshot = 0;
02782
02783 if (!oneshot) {
02784 _unpackaged_files_terminate_build =
02785 rpmExpandNumeric("%{?_unpackaged_files_terminate_build}");
02786 oneshot = 1;
02787 }
02788
02789 buf = getStringBuf(readBuf);
02790 if ((*buf != '\0') && (*buf != '\n')) {
02791 rc = (_unpackaged_files_terminate_build) ? 1 : 0;
02792 rpmMessage((rc ? RPMMESS_ERROR : RPMMESS_WARNING),
02793 _("Installed (but unpackaged) file(s) found:\n%s"), buf);
02794 }
02795 }
02796
02797 exit:
02798 readBuf = freeStringBuf(readBuf);
02799 s = _free(s);
02800 av = _free(av);
02801 return rc;
02802 }
02803
02804
02805 int processBinaryFiles(Spec spec, int installSpecialDoc, int test)
02806
02807
02808 {
02809 Package pkg;
02810 int res = 0;
02811
02812 check_fileList = newStringBuf();
02813 check_fileListLen = 0;
02814
02815 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
02816 const char *n, *v, *r;
02817 int rc;
02818
02819 if (pkg->fileList == NULL)
02820 continue;
02821
02822 (void) headerNVR(pkg->header, &n, &v, &r);
02823 rpmMessage(RPMMESS_NORMAL, _("Processing files: %s-%s-%s\n"), n, v, r);
02824
02825 if ((rc = processPackageFiles(spec, pkg, installSpecialDoc, test)))
02826 res = rc;
02827
02828
02829
02830
02831
02832 if (headerIsEntry(pkg->header, RPMTAG_MULTILIBS)) {
02833 (void) generateDepends(spec, pkg, pkg->cpioList, 1);
02834 (void) generateDepends(spec, pkg, pkg->cpioList, 2);
02835 } else
02836 (void) generateDepends(spec, pkg, pkg->cpioList, 0);
02837
02838 printDeps(pkg->header);
02839
02840 }
02841
02842
02843
02844
02845
02846
02847 if (res == 0) {
02848 if (checkFiles(check_fileList, check_fileListLen) > 0)
02849 res = 1;
02850 }
02851
02852 check_fileList = freeStringBuf(check_fileList);
02853
02854 return res;
02855 }
02856