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 #include <rpmmacro.h>
00017
00018 #include "buildio.h"
00019
00020 #include "myftw.h"
00021 #include "md5.h"
00022 #include "debug.h"
00023
00024
00025
00026
00027
00028
00029 #define SKIPWHITE(_x) {while(*(_x) && (isspace(*_x) || *(_x) == ',')) (_x)++;}
00030 #define SKIPNONWHITE(_x){while(*(_x) &&!(isspace(*_x) || *(_x) == ',')) (_x)++;}
00031
00032 #define MAXDOCDIR 1024
00033
00034 extern int _noDirTokens;
00035
00036 #define SPECD_DEFFILEMODE (1<<0)
00037 #define SPECD_DEFDIRMODE (1<<1)
00038 #define SPECD_DEFUID (1<<2)
00039 #define SPECD_DEFGID (1<<3)
00040 #define SPECD_DEFVERIFY (1<<4)
00041
00042 #define SPECD_FILEMODE (1<<8)
00043 #define SPECD_DIRMODE (1<<9)
00044 #define SPECD_UID (1<<10)
00045 #define SPECD_GID (1<<11)
00046 #define SPECD_VERIFY (1<<12)
00047
00050 typedef struct {
00051 struct stat fl_st;
00052 #define fl_dev fl_st.st_dev
00053 #define fl_ino fl_st.st_ino
00054 #define fl_mode fl_st.st_mode
00055 #define fl_nlink fl_st.st_nlink
00056 #define fl_uid fl_st.st_uid
00057 #define fl_gid fl_st.st_gid
00058 #define fl_rdev fl_st.st_rdev
00059 #define fl_size fl_st.st_size
00060 #define fl_mtime fl_st.st_mtime
00061
00062 const char *diskURL;
00063 const char *fileURL;
00064 const char *uname;
00065 const char *gname;
00066 int flags;
00067 int specdFlags;
00068 int verifyFlags;
00069 const char *langs;
00070 } FileListRec;
00071
00074 typedef struct {
00075 const char *ar_fmodestr;
00076 const char *ar_dmodestr;
00077 const char *ar_user;
00078 const char *ar_group;
00079 mode_t ar_fmode;
00080 mode_t ar_dmode;
00081 } AttrRec;
00082
00085 static int multiLib = 0;
00086
00090 struct FileList {
00091 const char *buildRootURL;
00092 const char *prefix;
00093
00094 int fileCount;
00095 int totalFileSize;
00096 int processingFailed;
00097
00098 int passedSpecialDoc;
00099 int isSpecialDoc;
00100
00101 int isDir;
00102 int inFtw;
00103 int currentFlags;
00104 int currentSpecdFlags;
00105 int currentVerifyFlags;
00106 AttrRec cur_ar;
00107 AttrRec def_ar;
00108 int defSpecdFlags;
00109 int defVerifyFlags;
00110 int nLangs;
00111 const char **currentLangs;
00112
00113
00114
00115 const char *docDirs[MAXDOCDIR];
00116 int docDirCount;
00117
00118 FileListRec *fileList;
00119 int fileListRecsAlloced;
00120 int fileListRecsUsed;
00121 };
00122
00125 static void nullAttrRec(AttrRec *ar)
00126 {
00127 ar->ar_fmodestr = NULL;
00128 ar->ar_dmodestr = NULL;
00129 ar->ar_user = NULL;
00130 ar->ar_group = NULL;
00131 ar->ar_fmode = 0;
00132 ar->ar_dmode = 0;
00133 }
00134
00137 static void freeAttrRec(AttrRec *ar)
00138 {
00139 FREE(ar->ar_fmodestr);
00140 FREE(ar->ar_dmodestr);
00141 FREE(ar->ar_user);
00142 FREE(ar->ar_group);
00143
00144 }
00145
00148 static void dupAttrRec(AttrRec *oar, AttrRec *nar)
00149 {
00150 if (oar == nar)
00151 return;
00152 freeAttrRec(nar);
00153 nar->ar_fmodestr = (oar->ar_fmodestr ? xstrdup(oar->ar_fmodestr) : NULL);
00154 nar->ar_dmodestr = (oar->ar_dmodestr ? xstrdup(oar->ar_dmodestr) : NULL);
00155 nar->ar_user = (oar->ar_user ? xstrdup(oar->ar_user) : NULL);
00156 nar->ar_group = (oar->ar_group ? xstrdup(oar->ar_group) : NULL);
00157 nar->ar_fmode = oar->ar_fmode;
00158 nar->ar_dmode = oar->ar_dmode;
00159 }
00160
00161 #if 0
00162
00164 static void dumpAttrRec(const char *msg, AttrRec *ar) {
00165 if (msg)
00166 fprintf(stderr, "%s:\t", msg);
00167 fprintf(stderr, "(%s, %s, %s, %s)\n",
00168 ar->ar_fmodestr,
00169 ar->ar_user,
00170 ar->ar_group,
00171 ar->ar_dmodestr);
00172 }
00173 #endif
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00196 static char *strtokWithQuotes(char *s, char *delim)
00197 {
00198 static char *olds = NULL;
00199 char *token;
00200
00201 if (s == NULL) {
00202 s = olds;
00203 }
00204
00205
00206 s += strspn(s, delim);
00207 if (*s == '\0') {
00208 return NULL;
00209 }
00210
00211
00212 token = s;
00213 if (*token == '"') {
00214 token++;
00215
00216 s = strchr(token, '"');
00217 } else {
00218 s = strpbrk(token, delim);
00219 }
00220
00221
00222 if (s == NULL) {
00223
00224 olds = strchr(token, '\0');
00225 } else {
00226
00227 *s = '\0';
00228 olds = s+1;
00229 }
00230
00231 return token;
00232 }
00233
00236 static void timeCheck(int tc, Header h)
00237 {
00238 int *mtime;
00239 char **files;
00240 int count, x, currentTime;
00241
00242 headerGetEntry(h, RPMTAG_OLDFILENAMES, NULL, (void **) &files, &count);
00243 headerGetEntry(h, RPMTAG_FILEMTIMES, NULL, (void **) &mtime, NULL);
00244
00245 currentTime = time(NULL);
00246
00247 for (x = 0; x < count; x++) {
00248 if (currentTime - mtime[x] > tc) {
00249 rpmMessage(RPMMESS_WARNING, _("TIMECHECK failure: %s\n"), files[x]);
00250 }
00251 }
00252 FREE(files);
00253 }
00254
00257 typedef struct VFA {
00258 char * attribute;
00259 int flag;
00260 } VFA_t;
00261
00264 VFA_t verifyAttrs[] = {
00265 { "md5", RPMVERIFY_MD5 },
00266 { "size", RPMVERIFY_FILESIZE },
00267 { "link", RPMVERIFY_LINKTO },
00268 { "user", RPMVERIFY_USER },
00269 { "group", RPMVERIFY_GROUP },
00270 { "mtime", RPMVERIFY_MTIME },
00271 { "mode", RPMVERIFY_MODE },
00272 { "rdev", RPMVERIFY_RDEV },
00273 { NULL, 0 }
00274 };
00275
00279 static int parseForVerify(char *buf, struct FileList *fl)
00280 {
00281 char *p, *pe, *q;
00282 const char *name;
00283 int *resultVerify;
00284 int not;
00285 int verifyFlags;
00286 int *specdFlags;
00287
00288 if ((p = strstr(buf, (name = "%verify"))) != NULL) {
00289 resultVerify = &(fl->currentVerifyFlags);
00290 specdFlags = &fl->currentSpecdFlags;
00291 } else if ((p = strstr(buf, (name = "%defverify"))) != NULL) {
00292 resultVerify = &(fl->defVerifyFlags);
00293 specdFlags = &fl->defSpecdFlags;
00294 } else
00295 return 0;
00296
00297 for (pe = p; (pe-p) < strlen(name); pe++)
00298 *pe = ' ';
00299
00300 SKIPSPACE(pe);
00301
00302 if (*pe != '(') {
00303 rpmError(RPMERR_BADSPEC, _("Missing '(' in %s %s\n"), name, pe);
00304 fl->processingFailed = 1;
00305 return RPMERR_BADSPEC;
00306 }
00307
00308
00309 *pe++ = ' ';
00310 for (p = pe; *pe && *pe != ')'; pe++)
00311 ;
00312
00313 if (*pe == '\0') {
00314 rpmError(RPMERR_BADSPEC, _("Missing ')' in %s(%s\n"), name, p);
00315 fl->processingFailed = 1;
00316 return RPMERR_BADSPEC;
00317 }
00318
00319
00320 q = alloca((pe-p) + 1);
00321 strncpy(q, p, pe-p);
00322 q[pe-p] = '\0';
00323 while (p <= pe)
00324 *p++ = ' ';
00325
00326 not = 0;
00327 verifyFlags = RPMVERIFY_NONE;
00328
00329 for (p = q; *p; p = pe) {
00330 SKIPWHITE(p);
00331 if (*p == '\0')
00332 break;
00333 pe = p;
00334 SKIPNONWHITE(pe);
00335 if (*pe)
00336 *pe++ = '\0';
00337
00338 { VFA_t *vfa;
00339 for (vfa = verifyAttrs; vfa->attribute != NULL; vfa++) {
00340 if (strcmp(p, vfa->attribute))
00341 continue;
00342 verifyFlags |= vfa->flag;
00343 break;
00344 }
00345 if (vfa->attribute)
00346 continue;
00347 }
00348
00349 if (!strcmp(p, "not")) {
00350 not ^= 1;
00351 } else {
00352 rpmError(RPMERR_BADSPEC, _("Invalid %s token: %s\n"), name, p);
00353 fl->processingFailed = 1;
00354 return RPMERR_BADSPEC;
00355 }
00356 }
00357
00358 *resultVerify = not ? ~(verifyFlags) : verifyFlags;
00359 *specdFlags |= SPECD_VERIFY;
00360
00361 return 0;
00362 }
00363
00364 #define isAttrDefault(_ars) ((_ars)[0] == '-' && (_ars)[1] == '\0')
00365
00369 static int parseForAttr(char *buf, struct FileList *fl)
00370 {
00371 char *p, *pe, *q;
00372 const char *name;
00373 int x;
00374 AttrRec arbuf, *ar = &arbuf, *ret_ar;
00375 int *specdFlags = NULL;
00376
00377 if ((p = strstr(buf, (name = "%attr"))) != NULL) {
00378 ret_ar = &(fl->cur_ar);
00379 specdFlags = &fl->currentSpecdFlags;
00380 } else if ((p = strstr(buf, (name = "%defattr"))) != NULL) {
00381 ret_ar = &(fl->def_ar);
00382 specdFlags = &fl->defSpecdFlags;
00383 } else
00384 return 0;
00385
00386 for (pe = p; (pe-p) < strlen(name); pe++)
00387 *pe = ' ';
00388
00389 SKIPSPACE(pe);
00390
00391 if (*pe != '(') {
00392 rpmError(RPMERR_BADSPEC, _("Missing '(' in %s %s\n"), name, pe);
00393 fl->processingFailed = 1;
00394 return RPMERR_BADSPEC;
00395 }
00396
00397
00398 *pe++ = ' ';
00399 for (p = pe; *pe && *pe != ')'; pe++)
00400 ;
00401
00402 if (ret_ar == &(fl->def_ar)) {
00403 q = pe;
00404 q++;
00405 SKIPSPACE(q);
00406 if (*q) {
00407 rpmError(RPMERR_BADSPEC,
00408 _("Non-white space follows %s(): %s\n"), name, q);
00409 fl->processingFailed = 1;
00410 return RPMERR_BADSPEC;
00411 }
00412 }
00413
00414
00415 q = alloca((pe-p) + 1);
00416 strncpy(q, p, pe-p);
00417 q[pe-p] = '\0';
00418 while (p <= pe)
00419 *p++ = ' ';
00420
00421 nullAttrRec(ar);
00422
00423 p = q; SKIPWHITE(p);
00424 if (*p) {
00425 pe = p; SKIPNONWHITE(pe); if (*pe) *pe++ = '\0';
00426 ar->ar_fmodestr = p;
00427 p = pe; SKIPWHITE(p);
00428 }
00429 if (*p) {
00430 pe = p; SKIPNONWHITE(pe); if (*pe) *pe++ = '\0';
00431 ar->ar_user = p;
00432 p = pe; SKIPWHITE(p);
00433 }
00434 if (*p) {
00435 pe = p; SKIPNONWHITE(pe); if (*pe) *pe++ = '\0';
00436 ar->ar_group = p;
00437 p = pe; SKIPWHITE(p);
00438 }
00439 if (*p && ret_ar == &(fl->def_ar)) {
00440 pe = p; SKIPNONWHITE(pe); if (*pe) *pe++ = '\0';
00441 ar->ar_dmodestr = p;
00442 p = pe; SKIPWHITE(p);
00443 }
00444
00445 if (!(ar->ar_fmodestr && ar->ar_user && ar->ar_group) || *p != '\0') {
00446 rpmError(RPMERR_BADSPEC, _("Bad syntax: %s(%s)\n"), name, q);
00447 fl->processingFailed = 1;
00448 return RPMERR_BADSPEC;
00449 }
00450
00451
00452 if (ar->ar_fmodestr && !isAttrDefault(ar->ar_fmodestr)) {
00453 unsigned int ui;
00454 x = sscanf(ar->ar_fmodestr, "%o", &ui);
00455 if ((x == 0) || (ar->ar_fmode & ~MYALLPERMS)) {
00456 rpmError(RPMERR_BADSPEC, _("Bad mode spec: %s(%s)\n"), name, q);
00457 fl->processingFailed = 1;
00458 return RPMERR_BADSPEC;
00459 }
00460 ar->ar_fmode = ui;
00461 } else
00462 ar->ar_fmodestr = NULL;
00463
00464 if (ar->ar_dmodestr && !isAttrDefault(ar->ar_dmodestr)) {
00465 unsigned int ui;
00466 x = sscanf(ar->ar_dmodestr, "%o", &ui);
00467 if ((x == 0) || (ar->ar_dmode & ~MYALLPERMS)) {
00468 rpmError(RPMERR_BADSPEC, _("Bad dirmode spec: %s(%s)\n"), name, q);
00469 fl->processingFailed = 1;
00470 return RPMERR_BADSPEC;
00471 }
00472 ar->ar_dmode = ui;
00473 } else
00474 ar->ar_dmodestr = NULL;
00475
00476 if (!(ar->ar_user && !isAttrDefault(ar->ar_user)))
00477 ar->ar_user = NULL;
00478
00479 if (!(ar->ar_group && !isAttrDefault(ar->ar_group)))
00480 ar->ar_group = NULL;
00481
00482 dupAttrRec(ar, ret_ar);
00483
00484
00485 *specdFlags |= SPECD_UID | SPECD_GID | SPECD_FILEMODE | SPECD_DIRMODE;
00486
00487 return 0;
00488 }
00489
00493 static int parseForConfig(char *buf, struct FileList *fl)
00494 {
00495 char *p, *pe, *q;
00496 const char *name;
00497
00498 if ((p = strstr(buf, (name = "%config"))) == NULL)
00499 return 0;
00500
00501 fl->currentFlags = RPMFILE_CONFIG;
00502
00503 for (pe = p; (pe-p) < strlen(name); pe++)
00504 *pe = ' ';
00505 SKIPSPACE(pe);
00506 if (*pe != '(')
00507 return 0;
00508
00509
00510 *pe++ = ' ';
00511 for (p = pe; *pe && *pe != ')'; pe++)
00512 ;
00513
00514 if (*pe == '\0') {
00515 rpmError(RPMERR_BADSPEC, _("Missing ')' in %s(%s\n"), name, p);
00516 fl->processingFailed = 1;
00517 return RPMERR_BADSPEC;
00518 }
00519
00520
00521 q = alloca((pe-p) + 1);
00522 strncpy(q, p, pe-p);
00523 q[pe-p] = '\0';
00524 while (p <= pe)
00525 *p++ = ' ';
00526
00527 for (p = q; *p; p = pe) {
00528 SKIPWHITE(p);
00529 if (*p == '\0')
00530 break;
00531 pe = p;
00532 SKIPNONWHITE(pe);
00533 if (*pe)
00534 *pe++ = '\0';
00535 if (!strcmp(p, "missingok")) {
00536 fl->currentFlags |= RPMFILE_MISSINGOK;
00537 } else if (!strcmp(p, "noreplace")) {
00538 fl->currentFlags |= RPMFILE_NOREPLACE;
00539 } else {
00540 rpmError(RPMERR_BADSPEC, _("Invalid %s token: %s\n"), name, p);
00541 fl->processingFailed = 1;
00542 return RPMERR_BADSPEC;
00543 }
00544 }
00545
00546 return 0;
00547 }
00548
00551 static int langCmp(const void * ap, const void *bp) {
00552 return strcmp(*(const char **)ap, *(const char **)bp);
00553 }
00554
00558 static int parseForLang(char *buf, struct FileList *fl)
00559 {
00560 char *p, *pe, *q;
00561 const char *name;
00562
00563 while ((p = strstr(buf, (name = "%lang"))) != NULL) {
00564
00565 for (pe = p; (pe-p) < strlen(name); pe++)
00566 *pe = ' ';
00567 SKIPSPACE(pe);
00568
00569 if (*pe != '(') {
00570 rpmError(RPMERR_BADSPEC, _("Missing '(' in %s %s\n"), name, pe);
00571 fl->processingFailed = 1;
00572 return RPMERR_BADSPEC;
00573 }
00574
00575
00576 *pe++ = ' ';
00577 for (pe = p; *pe && *pe != ')'; pe++)
00578 ;
00579
00580 if (*pe == '\0') {
00581 rpmError(RPMERR_BADSPEC, _("Missing ')' in %s(%s\n"), name, p);
00582 fl->processingFailed = 1;
00583 return RPMERR_BADSPEC;
00584 }
00585
00586
00587 q = alloca((pe-p) + 1);
00588 strncpy(q, p, pe-p);
00589 q[pe-p] = '\0';
00590 while (p <= pe)
00591 *p++ = ' ';
00592
00593
00594 for (p = q; *p; p = pe) {
00595 char *newp;
00596 size_t np;
00597 int i;
00598
00599 SKIPWHITE(p);
00600 pe = p;
00601 SKIPNONWHITE(pe);
00602
00603 np = pe - p;
00604
00605
00606 if (np < 1 || (np == 1 && *p != 'C') || np >= 32) {
00607 rpmError(RPMERR_BADSPEC,
00608 _("Unusual locale length: \"%.*s\" in %%lang(%s)\n"),
00609 (int)np, p, q);
00610 fl->processingFailed = 1;
00611 return RPMERR_BADSPEC;
00612 }
00613
00614
00615 for (i = 0; i < fl->nLangs; i++) {
00616 if (strncmp(fl->currentLangs[i], p, np))
00617 continue;
00618 rpmError(RPMERR_BADSPEC, _("Duplicate locale %.*s in %%lang(%s)\n"),
00619 (int)np, p, q);
00620 fl->processingFailed = 1;
00621 return RPMERR_BADSPEC;
00622 }
00623
00624
00625 fl->currentLangs = (const char **) ((fl->currentLangs == NULL)
00626 ? xmalloc(sizeof(*fl->currentLangs))
00627 : xrealloc(fl->currentLangs,((fl->nLangs+1)*sizeof(*fl->currentLangs))));
00628 newp = xmalloc( np+1 );
00629 strncpy(newp, p, np);
00630 newp[np] = '\0';
00631 fl->currentLangs[fl->nLangs++] = newp;
00632 if (*pe == ',') pe++;
00633 }
00634 }
00635
00636
00637 if (fl->currentLangs)
00638 qsort(fl->currentLangs, fl->nLangs, sizeof(*fl->currentLangs), langCmp);
00639
00640 return 0;
00641 }
00642
00645 static int parseForRegexLang(const char *fileName, char **lang)
00646 {
00647 static int initialized = 0;
00648 static int hasRegex = 0;
00649 static regex_t compiledPatt;
00650 static char buf[BUFSIZ];
00651 int x;
00652 regmatch_t matches[2];
00653 const char *s;
00654
00655 if (! initialized) {
00656 const char *patt = rpmExpand("%{_langpatt}", NULL);
00657 int rc = 0;
00658 if (!(patt && *patt != '%'))
00659 rc = 1;
00660 else if (regcomp(&compiledPatt, patt, REG_EXTENDED))
00661 rc = -1;
00662 free((void *)patt);
00663 if (rc)
00664 return rc;
00665 hasRegex = 1;
00666 initialized = 1;
00667 }
00668
00669 if (! hasRegex || regexec(&compiledPatt, fileName, 2, matches, REG_NOTEOL))
00670 return 1;
00671
00672
00673 s = fileName + matches[1].rm_eo - 1;
00674 x = matches[1].rm_eo - matches[1].rm_so;
00675 buf[x] = '\0';
00676 while (x) {
00677 buf[--x] = *s--;
00678 }
00679 if (lang)
00680 *lang = buf;
00681 return 0;
00682 }
00683
00686 static int parseForRegexMultiLib(const char *fileName)
00687 {
00688 static int initialized = 0;
00689 static int hasRegex = 0;
00690 static regex_t compiledPatt;
00691
00692 if (! initialized) {
00693 const char *patt;
00694 int rc = 0;
00695
00696 initialized = 1;
00697 patt = rpmExpand("%{_multilibpatt}", NULL);
00698 if (!(patt && *patt != '%'))
00699 rc = 1;
00700 else if (regcomp(&compiledPatt, patt, REG_EXTENDED | REG_NOSUB))
00701 rc = -1;
00702 free((void *)patt);
00703 if (rc)
00704 return rc;
00705 hasRegex = 1;
00706 }
00707
00708 if (! hasRegex || regexec(&compiledPatt, fileName, 0, NULL, 0))
00709 return 1;
00710
00711 return 0;
00712 }
00713
00716 VFA_t virtualFileAttributes[] = {
00717 { "%dir", 0 },
00718 { "%doc", RPMFILE_DOC },
00719 { "%ghost", RPMFILE_GHOST },
00720 { "%exclude", RPMFILE_EXCLUDE },
00721 { "%readme", RPMFILE_README },
00722 { "%license", RPMFILE_LICENSE },
00723 { "%multilib", 0 },
00724
00725 #if WHY_NOT
00726 { "%spec", RPMFILE_SPEC },
00727 { "%config", RPMFILE_CONFIG },
00728 { "%donotuse", RPMFILE_DONOTUSE },
00729 { "%missingok", RPMFILE_CONFIG|RPMFILE_MISSINGOK },
00730 { "%noreplace", RPMFILE_CONFIG|RPMFILE_NOREPLACE },
00731 #endif
00732
00733 { NULL, 0 }
00734 };
00735
00739 static int parseForSimple(Spec spec, Package pkg, char *buf,
00740 struct FileList *fl, const char **fileName)
00741 {
00742 char *s, *t;
00743 int res, specialDoc = 0;
00744 char specialDocBuf[BUFSIZ];
00745
00746 specialDocBuf[0] = '\0';
00747 *fileName = NULL;
00748 res = 0;
00749
00750 t = buf;
00751 while ((s = strtokWithQuotes(t, " \t\n")) != NULL) {
00752 t = NULL;
00753 if (!strcmp(s, "%docdir")) {
00754 s = strtokWithQuotes(NULL, " \t\n");
00755 if (fl->docDirCount == MAXDOCDIR) {
00756 rpmError(RPMERR_INTERNAL, _("Hit limit for %%docdir\n"));
00757 fl->processingFailed = 1;
00758 res = 1;
00759 }
00760 fl->docDirs[fl->docDirCount++] = xstrdup(s);
00761 if (strtokWithQuotes(NULL, " \t\n")) {
00762 rpmError(RPMERR_INTERNAL, _("Only one arg for %%docdir\n"));
00763 fl->processingFailed = 1;
00764 res = 1;
00765 }
00766 break;
00767 }
00768
00769
00770 { VFA_t *vfa;
00771 for (vfa = virtualFileAttributes; vfa->attribute != NULL; vfa++) {
00772 if (strcmp(s, vfa->attribute))
00773 continue;
00774 if (!vfa->flag) {
00775 if (!strcmp(s, "%dir"))
00776 fl->isDir = 1;
00777 else if (!strcmp(s, "%multilib"))
00778 fl->currentFlags |= multiLib;
00779 } else
00780 fl->currentFlags |= vfa->flag;
00781 break;
00782 }
00783
00784 if (vfa->attribute != NULL)
00785 continue;
00786 }
00787
00788 if (*fileName) {
00789
00790 rpmError(RPMERR_BADSPEC, _("Two files on one line: %s\n"),
00791 *fileName);
00792 fl->processingFailed = 1;
00793 res = 1;
00794 }
00795
00796 if (*s != '/') {
00797 if (fl->currentFlags & RPMFILE_DOC) {
00798 specialDoc = 1;
00799 strcat(specialDocBuf, " ");
00800 strcat(specialDocBuf, s);
00801 } else {
00802
00803 rpmError(RPMERR_BADSPEC,
00804 _("File must begin with \"/\": %s\n"), s);
00805 fl->processingFailed = 1;
00806 res = 1;
00807 }
00808 } else {
00809 *fileName = s;
00810 }
00811 }
00812
00813 if (specialDoc) {
00814 if (*fileName || (fl->currentFlags & ~(RPMFILE_DOC))) {
00815 rpmError(RPMERR_BADSPEC,
00816 _("Can't mix special %%doc with other forms: %s\n"),
00817 *fileName);
00818 fl->processingFailed = 1;
00819 res = 1;
00820 } else {
00821
00822 { const char *ddir, *n, *v;
00823
00824 headerNVR(pkg->header, &n, &v, NULL);
00825
00826 ddir = rpmGetPath("%{_docdir}/", n, "-", v, NULL);
00827 strcpy(buf, ddir);
00828 free((void *)ddir);
00829 }
00830
00831
00832
00833 if (! fl->passedSpecialDoc) {
00834 pkg->specialDoc = newStringBuf();
00835 appendStringBuf(pkg->specialDoc, "DOCDIR=$RPM_BUILD_ROOT");
00836 appendLineStringBuf(pkg->specialDoc, buf);
00837 appendLineStringBuf(pkg->specialDoc, "export DOCDIR");
00838 appendLineStringBuf(pkg->specialDoc, "rm -rf $DOCDIR");
00839 appendLineStringBuf(pkg->specialDoc, MKDIR_P " $DOCDIR");
00840
00841 *fileName = buf;
00842 fl->passedSpecialDoc = 1;
00843 fl->isSpecialDoc = 1;
00844 }
00845
00846 appendStringBuf(pkg->specialDoc, "cp -pr ");
00847 appendStringBuf(pkg->specialDoc, specialDocBuf);
00848 appendLineStringBuf(pkg->specialDoc, " $DOCDIR");
00849 }
00850 }
00851
00852 return res;
00853 }
00854
00857 static int compareFileListRecs(const void *ap, const void *bp)
00858 {
00859 const char *a = ((FileListRec *)ap)->fileURL;
00860 const char *b = ((FileListRec *)bp)->fileURL;
00861 return strcmp(a, b);
00862 }
00863
00867 static int isDoc(struct FileList *fl, const char *fileName)
00868 {
00869 int x = fl->docDirCount;
00870
00871 while (x--) {
00872 if (strstr(fileName, fl->docDirs[x]) == fileName)
00873 return 1;
00874 }
00875 return 0;
00876 }
00877
00883 static void checkHardLinks(struct FileList *fl)
00884 {
00885 char nlangs[BUFSIZ];
00886 FileListRec *ilp, *jlp;
00887 int i, j;
00888
00889 for (i = 0; i < fl->fileListRecsUsed; i++) {
00890 char *te;
00891
00892 ilp = fl->fileList + i;
00893 if (!(S_ISREG(ilp->fl_mode) && ilp->fl_nlink > 1))
00894 continue;
00895 if (ilp->flags & RPMFILE_SPECFILE)
00896 continue;
00897
00898 te = nlangs;
00899 *te = '\0';
00900 for (j = i + 1; j < fl->fileListRecsUsed; j++) {
00901 jlp = fl->fileList + j;
00902 if (!S_ISREG(jlp->fl_mode))
00903 continue;
00904 if (ilp->fl_nlink != jlp->fl_nlink)
00905 continue;
00906 if (ilp->fl_ino != jlp->fl_ino)
00907 continue;
00908 if (ilp->fl_dev != jlp->fl_dev)
00909 continue;
00910 if (!strcmp(ilp->langs, jlp->langs)) {
00911 jlp->flags |= RPMFILE_SPECFILE;
00912 continue;
00913 }
00914 if (te == nlangs)
00915 te = stpcpy(te, ilp->langs);
00916 *te++ = '|';
00917 te = stpcpy(te, jlp->langs);
00918 }
00919
00920
00921 if (te == nlangs)
00922 continue;
00923
00924 free((void *)ilp->langs);
00925 ilp->langs = xstrdup(nlangs);
00926 for (j = i + 1; j < fl->fileListRecsUsed; j++) {
00927 jlp = fl->fileList + j;
00928 if (!S_ISREG(jlp->fl_mode))
00929 continue;
00930 if (ilp->fl_nlink != jlp->fl_nlink)
00931 continue;
00932 if (ilp->fl_ino != jlp->fl_ino)
00933 continue;
00934 if (ilp->fl_dev != jlp->fl_dev)
00935 continue;
00936 jlp->flags |= RPMFILE_SPECFILE;
00937 free((void *)jlp->langs);
00938 jlp->langs = xstrdup(nlangs);
00939 }
00940 }
00941
00942 for (i = 0; i < fl->fileListRecsUsed; i++) {
00943 ilp = fl->fileList + i;
00944 ilp->flags &= ~RPMFILE_SPECFILE;
00945 }
00946 }
00947
00953 static void genCpioListAndHeader(struct FileList *fl, TFI_t *cpioList,
00954 Header h, int isSrc)
00955 {
00956 int _addDotSlash = !(isSrc || rpmExpandNumeric("%{_noPayloadPrefix}"));
00957 uint_32 multiLibMask = 0;
00958 int apathlen = 0;
00959 int dpathlen = 0;
00960 int skipLen = 0;
00961 FileListRec *flp;
00962 char buf[BUFSIZ];
00963 int i;
00964
00965
00966 qsort(fl->fileList, fl->fileListRecsUsed,
00967 sizeof(*(fl->fileList)), compareFileListRecs);
00968
00969
00970 if (! isSrc) {
00971 skipLen = 1;
00972 if (fl->prefix)
00973 skipLen += strlen(fl->prefix);
00974 }
00975
00976 for (i = 0, flp = fl->fileList; i < fl->fileListRecsUsed; i++, flp++) {
00977 char *s;
00978
00979 #ifdef DYING
00980 if (i < (fl->fileListRecsUsed - 1) &&
00981 !strcmp(flp->fileURL, flp[1].fileURL))
00982 {
00983 rpmError(RPMERR_BADSPEC, _("File listed twice: %s\n"),
00984 flp->fileURL);
00985 fl->processingFailed = 1;
00986 }
00987 #endif
00988
00989
00990 while (i < (fl->fileListRecsUsed - 1) &&
00991 !strcmp(flp->fileURL, flp[1].fileURL)) {
00992
00993
00994
00995
00996 flp[1].flags |= flp->flags;
00997
00998
00999 if (S_ISDIR(flp->fl_mode)) {
01000 if ((flp[1].specdFlags & (SPECD_DIRMODE | SPECD_DEFDIRMODE)) <
01001 (flp->specdFlags & (SPECD_DIRMODE | SPECD_DEFDIRMODE)))
01002 flp[1].fl_mode = flp->fl_mode;
01003 } else {
01004 if ((flp[1].specdFlags & (SPECD_FILEMODE | SPECD_DEFFILEMODE)) <
01005 (flp->specdFlags & (SPECD_FILEMODE | SPECD_DEFFILEMODE)))
01006 flp[1].fl_mode = flp->fl_mode;
01007 }
01008
01009
01010 if ((flp[1].specdFlags & (SPECD_UID | SPECD_DEFUID)) <
01011 (flp->specdFlags & (SPECD_UID | SPECD_DEFUID)))
01012 {
01013 flp[1].fl_uid = flp->fl_uid;
01014 flp[1].uname = flp->uname;
01015 }
01016
01017
01018 if ((flp[1].specdFlags & (SPECD_GID | SPECD_DEFGID)) <
01019 (flp->specdFlags & (SPECD_GID | SPECD_DEFGID)))
01020 {
01021 flp[1].fl_gid = flp->fl_gid;
01022 flp[1].gname = flp->gname;
01023 }
01024
01025
01026 if ((flp[1].specdFlags & (SPECD_VERIFY | SPECD_DEFVERIFY)) <
01027 (flp->specdFlags & (SPECD_VERIFY | SPECD_DEFVERIFY)))
01028 flp[1].verifyFlags = flp->verifyFlags;
01029
01030
01031
01032 flp++; i++;
01033 }
01034
01035
01036 if (flp->flags & RPMFILE_EXCLUDE) continue;
01037
01038
01039 apathlen += (strlen(flp->fileURL) - skipLen + (_addDotSlash ? 3 : 1));
01040
01041
01042 dpathlen += (strlen(flp->diskURL) + 2);
01043
01044 if (flp->flags & RPMFILE_MULTILIB_MASK)
01045 multiLibMask |=
01046 (1 << ((flp->flags & RPMFILE_MULTILIB_MASK))
01047 >> RPMFILE_MULTILIB_SHIFT);
01048
01049
01050
01051
01052
01053
01054 headerAddOrAppendEntry(h, RPMTAG_OLDFILENAMES, RPM_STRING_ARRAY_TYPE,
01055 &(flp->fileURL), 1);
01056
01057 if (sizeof(flp->fl_size) != sizeof(uint_32)) {
01058 uint_32 psize = (uint_32)flp->fl_size;
01059 headerAddOrAppendEntry(h, RPMTAG_FILESIZES, RPM_INT32_TYPE,
01060 &(psize), 1);
01061 } else {
01062 headerAddOrAppendEntry(h, RPMTAG_FILESIZES, RPM_INT32_TYPE,
01063 &(flp->fl_size), 1);
01064 }
01065 headerAddOrAppendEntry(h, RPMTAG_FILEUSERNAME, RPM_STRING_ARRAY_TYPE,
01066 &(flp->uname), 1);
01067 headerAddOrAppendEntry(h, RPMTAG_FILEGROUPNAME, RPM_STRING_ARRAY_TYPE,
01068 &(flp->gname), 1);
01069 headerAddOrAppendEntry(h, RPMTAG_FILEMTIMES, RPM_INT32_TYPE,
01070 &(flp->fl_mtime), 1);
01071 if (sizeof(flp->fl_mode) != sizeof(uint_16)) {
01072 uint_16 pmode = (uint_16)flp->fl_mode;
01073 headerAddOrAppendEntry(h, RPMTAG_FILEMODES, RPM_INT16_TYPE,
01074 &(pmode), 1);
01075 } else {
01076 headerAddOrAppendEntry(h, RPMTAG_FILEMODES, RPM_INT16_TYPE,
01077 &(flp->fl_mode), 1);
01078 }
01079 if (sizeof(flp->fl_rdev) != sizeof(uint_16)) {
01080 uint_16 prdev = (uint_16)flp->fl_rdev;
01081 headerAddOrAppendEntry(h, RPMTAG_FILERDEVS, RPM_INT16_TYPE,
01082 &(prdev), 1);
01083 } else {
01084 headerAddOrAppendEntry(h, RPMTAG_FILERDEVS, RPM_INT16_TYPE,
01085 &(flp->fl_rdev), 1);
01086 }
01087 if (sizeof(flp->fl_dev) != sizeof(uint_32)) {
01088 uint_32 pdevice = (uint_32)flp->fl_dev;
01089 headerAddOrAppendEntry(h, RPMTAG_FILEDEVICES, RPM_INT32_TYPE,
01090 &(pdevice), 1);
01091 } else {
01092 headerAddOrAppendEntry(h, RPMTAG_FILEDEVICES, RPM_INT32_TYPE,
01093 &(flp->fl_dev), 1);
01094 }
01095 headerAddOrAppendEntry(h, RPMTAG_FILEINODES, RPM_INT32_TYPE,
01096 &(flp->fl_ino), 1);
01097
01098 headerAddOrAppendEntry(h, RPMTAG_FILELANGS, RPM_STRING_ARRAY_TYPE,
01099 &(flp->langs), 1);
01100
01101
01102
01103
01104
01105
01106
01107
01108 buf[0] = '\0';
01109 if (S_ISREG(flp->fl_mode))
01110 mdfile(flp->diskURL, buf);
01111 s = buf;
01112 headerAddOrAppendEntry(h, RPMTAG_FILEMD5S, RPM_STRING_ARRAY_TYPE,
01113 &s, 1);
01114
01115 buf[0] = '\0';
01116 if (S_ISLNK(flp->fl_mode)) {
01117 buf[Readlink(flp->diskURL, buf, BUFSIZ)] = '\0';
01118 if (fl->buildRootURL) {
01119 const char * buildRoot;
01120 (void) urlPath(fl->buildRootURL, &buildRoot);
01121
01122 if (buf[0] == '/' && strcmp(buildRoot, "/") &&
01123 !strncmp(buf, buildRoot, strlen(buildRoot))) {
01124 rpmError(RPMERR_BADSPEC,
01125 _("Symlink points to BuildRoot: %s -> %s\n"),
01126 flp->fileURL, buf);
01127 fl->processingFailed = 1;
01128 }
01129 }
01130 }
01131 s = buf;
01132 headerAddOrAppendEntry(h, RPMTAG_FILELINKTOS, RPM_STRING_ARRAY_TYPE,
01133 &s, 1);
01134
01135 if (flp->flags & RPMFILE_GHOST) {
01136 flp->verifyFlags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE |
01137 RPMVERIFY_LINKTO | RPMVERIFY_MTIME);
01138 }
01139 headerAddOrAppendEntry(h, RPMTAG_FILEVERIFYFLAGS, RPM_INT32_TYPE,
01140 &(flp->verifyFlags), 1);
01141
01142 if (!isSrc && isDoc(fl, flp->fileURL))
01143 flp->flags |= RPMFILE_DOC;
01144
01145 if (S_ISDIR(flp->fl_mode))
01146 flp->flags &= ~(RPMFILE_CONFIG|RPMFILE_DOC);
01147
01148 headerAddOrAppendEntry(h, RPMTAG_FILEFLAGS, RPM_INT32_TYPE,
01149 &(flp->flags), 1);
01150
01151 }
01152 headerAddEntry(h, RPMTAG_SIZE, RPM_INT32_TYPE,
01153 &(fl->totalFileSize), 1);
01154
01155
01156
01157
01158
01159 if (multiLibMask)
01160 headerAddEntry(h, RPMTAG_MULTILIBS, RPM_INT32_TYPE,
01161 &multiLibMask, 1);
01162
01163 if (_addDotSlash)
01164 rpmlibNeedsFeature(h, "PayloadFilesHavePrefix", "4.0-1");
01165
01166
01167 if (_noDirTokens)
01168 expandFilelist(h);
01169 else {
01170 compressFilelist(h);
01171
01172 rpmlibNeedsFeature(h, "CompressedFileNames", "3.0.4-1");
01173 }
01174
01175 { TFI_t fi = xcalloc(sizeof(*fi), 1);
01176 char * a, * d;
01177
01178 fi->type = TR_ADDED;
01179 loadFi(h, fi);
01180 if (fi->dnl) {
01181 free((void *)fi->dnl); fi->dnl = NULL;
01182 }
01183 if (fi->bnl) {
01184 free((void *)fi->bnl); fi->bnl = NULL;
01185 }
01186
01187 fi->dnl = xmalloc(fi->fc * sizeof(*fi->dnl) + dpathlen);
01188 d = (char *)(fi->dnl + fi->fc);
01189 *d = '\0';
01190
01191 fi->bnl = xmalloc(fi->fc * (sizeof(*fi->bnl) + sizeof(*fi->dil)));
01192 fi->dil = (int *)(fi->bnl + fi->fc);
01193
01194 fi->apath = xmalloc(fi->fc * sizeof(*fi->apath) + apathlen);
01195 a = (char *)(fi->apath + fi->fc);
01196 *a = '\0';
01197
01198 fi->actions = xcalloc(sizeof(*fi->actions), fi->fc);
01199 fi->fmapflags = xcalloc(sizeof(*fi->fmapflags), fi->fc);
01200 fi->astriplen = 0;
01201 if (fl->buildRootURL)
01202 fi->astriplen = strlen(fl->buildRootURL);
01203 fi->striplen = 0;
01204 fi->fuser = NULL;
01205 fi->fuids = xcalloc(sizeof(*fi->fuids), fi->fc);
01206 fi->fgroup = NULL;
01207 fi->fgids = xcalloc(sizeof(*fi->fgids), fi->fc);
01208
01209
01210 for (i = 0, flp = fl->fileList; i < fi->fc; i++, flp++) {
01211 char * b;
01212
01213
01214 fi->dil[i] = i;
01215 fi->dnl[fi->dil[i]] = d;
01216 d = stpcpy(d, flp->diskURL);
01217
01218
01219 for (b = d; b > fi->dnl[fi->dil[i]] && *b != '/'; b--)
01220 b[1] = b[0];
01221 b++;
01222 *b++ = '\0';
01223 fi->bnl[i] = b;
01224 d += 2;
01225
01226
01227 fi->apath[i] = a;
01228 if (_addDotSlash) a = stpcpy(a, "./");
01229 a = stpcpy(a, (flp->fileURL + skipLen));
01230 a++;
01231
01232 if (flp->flags & RPMFILE_GHOST) {
01233 fi->actions[i] = FA_SKIP;
01234 continue;
01235 }
01236 fi->actions[i] = FA_COPYOUT;
01237 fi->fuids[i] = flp->fl_uid;
01238 fi->fgids[i] = flp->fl_gid;
01239 fi->fmapflags[i] =
01240 CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
01241 if (isSrc)
01242 fi->fmapflags[i] |= CPIO_FOLLOW_SYMLINKS;
01243 if (flp->flags & RPMFILE_MULTILIB_MASK)
01244 fi->fmapflags[i] |= CPIO_MULTILIB;
01245
01246 }
01247 if (cpioList)
01248 *cpioList = fi;
01249 else
01250 free(fi);
01251 }
01252 }
01253
01256 static void freeFileList(FileListRec *fileList, int count)
01257 {
01258 while (count--) {
01259 FREE(fileList[count].diskURL);
01260 FREE(fileList[count].fileURL);
01261 FREE(fileList[count].langs);
01262 }
01263 FREE(fileList);
01264 }
01265
01269 static int addFile(struct FileList *fl, const char * diskURL, struct stat *statp)
01270 {
01271 const char *fileURL = diskURL;
01272 struct stat statbuf;
01273 mode_t fileMode;
01274 uid_t fileUid;
01275 gid_t fileGid;
01276 const char *fileUname;
01277 const char *fileGname;
01278 char *lang;
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291 { const char *fileName;
01292 (void) urlPath(fileURL, &fileName);
01293 if (fl->buildRootURL && strcmp(fl->buildRootURL, "/"))
01294 fileURL += strlen(fl->buildRootURL);
01295 }
01296
01297
01298 if (*fileURL == '\0')
01299 fileURL = "/";
01300
01301
01302 if (!fl->inFtw && fl->prefix) {
01303 const char *prefixTest;
01304 const char *prefixPtr = fl->prefix;
01305
01306 (void) urlPath(fileURL, &prefixTest);
01307 while (*prefixPtr && *prefixTest && (*prefixTest == *prefixPtr)) {
01308 prefixPtr++;
01309 prefixTest++;
01310 }
01311 if (*prefixPtr || (*prefixTest && *prefixTest != '/')) {
01312 rpmError(RPMERR_BADSPEC, _("File doesn't match prefix (%s): %s\n"),
01313 fl->prefix, fileURL);
01314 fl->processingFailed = 1;
01315 return RPMERR_BADSPEC;
01316 }
01317 }
01318
01319 if (statp == NULL) {
01320 statp = &statbuf;
01321 if (Lstat(diskURL, statp)) {
01322 rpmError(RPMERR_BADSPEC, _("File not found: %s\n"), diskURL);
01323 fl->processingFailed = 1;
01324 return RPMERR_BADSPEC;
01325 }
01326 }
01327
01328 if ((! fl->isDir) && S_ISDIR(statp->st_mode)) {
01329
01330
01331
01332
01333 fl->inFtw = 1;
01334 fl->isDir = 1;
01335 myftw(diskURL, 16, (myftwFunc) addFile, fl);
01336 fl->isDir = 0;
01337 fl->inFtw = 0;
01338 return 0;
01339 }
01340
01341 fileMode = statp->st_mode;
01342 fileUid = statp->st_uid;
01343 fileGid = statp->st_gid;
01344
01345 if (S_ISDIR(fileMode) && fl->cur_ar.ar_dmodestr) {
01346 fileMode &= S_IFMT;
01347 fileMode |= fl->cur_ar.ar_dmode;
01348 } else if (fl->cur_ar.ar_fmodestr != NULL) {
01349 fileMode &= S_IFMT;
01350 fileMode |= fl->cur_ar.ar_fmode;
01351 }
01352 if (fl->cur_ar.ar_user) {
01353 fileUname = getUnameS(fl->cur_ar.ar_user);
01354 } else {
01355 fileUname = getUname(fileUid);
01356 }
01357 if (fl->cur_ar.ar_group) {
01358 fileGname = getGnameS(fl->cur_ar.ar_group);
01359 } else {
01360 fileGname = getGname(fileGid);
01361 }
01362
01363 #if 0
01364 if (! (fileUname && fileGname)) {
01365 rpmError(RPMERR_BADSPEC, _("Bad owner/group: %s\n"), diskName);
01366 fl->processingFailed = 1;
01367 return RPMERR_BADSPEC;
01368 }
01369 #else
01370
01371 if (fileUname == NULL)
01372 fileUname = getUname(getuid());
01373 if (fileGname == NULL)
01374 fileGname = getGname(getgid());
01375 #endif
01376
01377 rpmMessage(RPMMESS_DEBUG, _("File %4d: %07o %s.%s\t %s\n"), fl->fileCount,
01378 fileMode, fileUname, fileGname, fileURL);
01379
01380
01381 if (fl->fileListRecsUsed == fl->fileListRecsAlloced) {
01382 fl->fileListRecsAlloced += 128;
01383 fl->fileList = xrealloc(fl->fileList,
01384 fl->fileListRecsAlloced * sizeof(*(fl->fileList)));
01385 }
01386
01387 { FileListRec * flp = &fl->fileList[fl->fileListRecsUsed];
01388
01389 flp->fl_st = *statp;
01390 flp->fl_mode = fileMode;
01391 flp->fl_uid = fileUid;
01392 flp->fl_gid = fileGid;
01393
01394 flp->fileURL = xstrdup(fileURL);
01395 flp->diskURL = xstrdup(diskURL);
01396 flp->uname = fileUname;
01397 flp->gname = fileGname;
01398
01399 if (fl->currentLangs && fl->nLangs > 0) {
01400 char *ncl;
01401 size_t nl = 0;
01402 int i;
01403
01404 for (i = 0; i < fl->nLangs; i++)
01405 nl += strlen(fl->currentLangs[i]) + 1;
01406
01407 flp->langs = ncl = xmalloc(nl);
01408 for (i = 0; i < fl->nLangs; i++) {
01409 const char *ocl;
01410 if (i) *ncl++ = '|';
01411 for (ocl = fl->currentLangs[i]; *ocl; ocl++)
01412 *ncl++ = *ocl;
01413 *ncl = '\0';
01414 }
01415 } else if (! parseForRegexLang(fileURL, &lang)) {
01416 flp->langs = xstrdup(lang);
01417 } else {
01418 flp->langs = xstrdup("");
01419 }
01420
01421 flp->flags = fl->currentFlags;
01422 flp->specdFlags = fl->currentSpecdFlags;
01423 flp->verifyFlags = fl->currentVerifyFlags;
01424
01425 if (multiLib
01426 && !(flp->flags & RPMFILE_MULTILIB_MASK)
01427 && !parseForRegexMultiLib(fileURL))
01428 flp->flags |= multiLib;
01429
01430 fl->totalFileSize += flp->fl_size;
01431 }
01432
01433 fl->fileListRecsUsed++;
01434 fl->fileCount++;
01435
01436 return 0;
01437 }
01438
01442 static int processBinaryFile(Package pkg, struct FileList *fl,
01443 const char *fileURL)
01444 {
01445 int doGlob;
01446 const char *diskURL = NULL;
01447 int rc = 0;
01448
01449 doGlob = myGlobPatternP(fileURL);
01450
01451
01452 { const char * fileName;
01453 (void) urlPath(fileURL, &fileName);
01454 if (*fileName != '/') {
01455 rpmError(RPMERR_BADSPEC, _("File needs leading \"/\": %s\n"),
01456 fileName);
01457 rc = 1;
01458 goto exit;
01459 }
01460 }
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470 diskURL = rpmGenPath(fl->buildRootURL, NULL, fileURL);
01471
01472 if (doGlob) {
01473 const char ** argv = NULL;
01474 int argc = 0;
01475 int i;
01476
01477 rc = rpmGlob(diskURL, &argc, &argv);
01478 if (rc == 0 && argc >= 1 && !myGlobPatternP(argv[0])) {
01479 for (i = 0; i < argc; i++) {
01480 rc = addFile(fl, argv[i], NULL);
01481 free((void *)argv[i]);
01482 }
01483 free((void *)argv);
01484 } else {
01485 rpmError(RPMERR_BADSPEC, _("File not found by glob: %s\n"),
01486 diskURL);
01487 rc = 1;
01488 }
01489 } else {
01490 rc = addFile(fl, diskURL, NULL);
01491 }
01492
01493 exit:
01494 if (diskURL)
01495 free((void *)diskURL);
01496 if (rc)
01497 fl->processingFailed = 1;
01498 return rc;
01499 }
01500
01503 static int processPackageFiles(Spec spec, Package pkg,
01504 int installSpecialDoc, int test)
01505 {
01506 struct FileList fl;
01507 char *s, **files, **fp;
01508 const char *fileName;
01509 char buf[BUFSIZ];
01510 AttrRec specialDocAttrRec;
01511 char *specialDoc = NULL;
01512
01513 #ifdef MULTILIB
01514 multiLib = rpmExpandNumeric("%{_multilibno}");
01515 if (multiLib)
01516 multiLib = RPMFILE_MULTILIB(multiLib);
01517 #endif
01518
01519 nullAttrRec(&specialDocAttrRec);
01520 pkg->cpioList = NULL;
01521
01522 if (pkg->fileFile) {
01523 const char *ffn;
01524 FD_t fd;
01525
01526
01527 if (*pkg->fileFile == '/') {
01528 ffn = rpmGetPath(pkg->fileFile, NULL);
01529 } else {
01530
01531 ffn = rpmGetPath("%{_builddir}/",
01532 (spec->buildSubdir ? spec->buildSubdir : "") ,
01533 "/", pkg->fileFile, NULL);
01534 }
01535 fd = Fopen(ffn, "r.fpio");
01536
01537 if (fd == NULL || Ferror(fd)) {
01538 rpmError(RPMERR_BADFILENAME,
01539 _("Could not open %%files file %s: %s\n"),
01540 ffn, Fstrerror(fd));
01541 return RPMERR_BADFILENAME;
01542 }
01543 free((void *)ffn);
01544
01545 while (fgets(buf, sizeof(buf), (FILE *)fdGetFp(fd))) {
01546 handleComments(buf);
01547 if (expandMacros(spec, spec->macros, buf, sizeof(buf))) {
01548 rpmError(RPMERR_BADSPEC, _("line: %s\n"), buf);
01549 return RPMERR_BADSPEC;
01550 }
01551 appendStringBuf(pkg->fileList, buf);
01552 }
01553 Fclose(fd);
01554 }
01555
01556
01557
01558
01559 fl.buildRootURL = rpmGenPath(spec->rootURL, spec->buildRootURL, NULL);
01560
01561 if (headerGetEntry(pkg->header, RPMTAG_DEFAULTPREFIX,
01562 NULL, (void **)&fl.prefix, NULL)) {
01563 fl.prefix = xstrdup(fl.prefix);
01564 } else {
01565 fl.prefix = NULL;
01566 }
01567
01568 fl.fileCount = 0;
01569 fl.totalFileSize = 0;
01570 fl.processingFailed = 0;
01571
01572 fl.passedSpecialDoc = 0;
01573 fl.isSpecialDoc = 0;
01574
01575 fl.isDir = 0;
01576 fl.inFtw = 0;
01577 fl.currentFlags = 0;
01578 fl.currentVerifyFlags = 0;
01579
01580 nullAttrRec(&fl.cur_ar);
01581 nullAttrRec(&fl.def_ar);
01582
01583 fl.defVerifyFlags = RPMVERIFY_ALL;
01584 fl.nLangs = 0;
01585 fl.currentLangs = NULL;
01586
01587 fl.currentSpecdFlags = 0;
01588 fl.defSpecdFlags = 0;
01589
01590 fl.docDirCount = 0;
01591 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/doc");
01592 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/man");
01593 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/info");
01594 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/X11R6/man");
01595 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/share/doc");
01596 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/share/man");
01597 fl.docDirs[fl.docDirCount++] = xstrdup("/usr/share/info");
01598 fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_docdir}", NULL);
01599 fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_mandir}", NULL);
01600 fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_infodir}", NULL);
01601
01602 fl.fileList = NULL;
01603 fl.fileListRecsAlloced = 0;
01604 fl.fileListRecsUsed = 0;
01605
01606 s = getStringBuf(pkg->fileList);
01607 files = splitString(s, strlen(s), '\n');
01608
01609 for (fp = files; *fp != NULL; fp++) {
01610 s = *fp;
01611 SKIPSPACE(s);
01612 if (*s == '\0')
01613 continue;
01614 fileName = NULL;
01615 strcpy(buf, s);
01616
01617
01618 fl.isDir = 0;
01619 fl.inFtw = 0;
01620 fl.currentFlags = 0;
01621
01622 fl.currentSpecdFlags = fl.defSpecdFlags>>8;
01623 fl.currentVerifyFlags = fl.defVerifyFlags;
01624 fl.isSpecialDoc = 0;
01625
01626
01627 if (fl.currentLangs) {
01628 int i;
01629 for (i = 0; i < fl.nLangs; i++)
01630 free((void *)fl.currentLangs[i]);
01631 FREE(fl.currentLangs);
01632 }
01633 fl.nLangs = 0;
01634
01635 dupAttrRec(&fl.def_ar, &fl.cur_ar);
01636
01637 if (parseForVerify(buf, &fl))
01638 continue;
01639 if (parseForAttr(buf, &fl))
01640 continue;
01641 if (parseForConfig(buf, &fl))
01642 continue;
01643 if (parseForLang(buf, &fl))
01644 continue;
01645 if (parseForSimple(spec, pkg, buf, &fl, &fileName))
01646 continue;
01647 if (fileName == NULL)
01648 continue;
01649
01650 if (fl.isSpecialDoc) {
01651
01652 FREE(specialDoc);
01653 specialDoc = xstrdup(fileName);
01654 dupAttrRec(&fl.cur_ar, &specialDocAttrRec);
01655 } else {
01656 processBinaryFile(pkg, &fl, fileName);
01657 }
01658 }
01659
01660
01661 if (specialDoc) {
01662 if (installSpecialDoc) {
01663 doScript(spec, RPMBUILD_STRINGBUF, "%doc", pkg->specialDoc, test);
01664 }
01665
01666
01667 fl.isDir = 0;
01668 fl.inFtw = 0;
01669 fl.currentFlags = 0;
01670 fl.currentVerifyFlags = 0;
01671
01672
01673 if (fl.currentLangs) {
01674 int i;
01675 for (i = 0; i < fl.nLangs; i++)
01676 free((void *)fl.currentLangs[i]);
01677 FREE(fl.currentLangs);
01678 }
01679 fl.nLangs = 0;
01680
01681 dupAttrRec(&specialDocAttrRec, &fl.cur_ar);
01682 freeAttrRec(&specialDocAttrRec);
01683
01684 processBinaryFile(pkg, &fl, specialDoc);
01685
01686 FREE(specialDoc);
01687 }
01688
01689 freeSplitString(files);
01690
01691 if (fl.processingFailed)
01692 goto exit;
01693
01694
01695 checkHardLinks(&fl);
01696
01697 genCpioListAndHeader(&fl, (TFI_t *)&pkg->cpioList, pkg->header, 0);
01698
01699 if (spec->timeCheck)
01700 timeCheck(spec->timeCheck, pkg->header);
01701
01702 exit:
01703 FREE(fl.buildRootURL);
01704 FREE(fl.prefix);
01705
01706 freeAttrRec(&fl.cur_ar);
01707 freeAttrRec(&fl.def_ar);
01708
01709 if (fl.currentLangs) {
01710 int i;
01711 for (i = 0; i < fl.nLangs; i++)
01712 free((void *)fl.currentLangs[i]);
01713 FREE(fl.currentLangs);
01714 }
01715
01716 freeFileList(fl.fileList, fl.fileListRecsUsed);
01717 while (fl.docDirCount--) {
01718 FREE(fl.docDirs[fl.docDirCount]);
01719 }
01720 return fl.processingFailed;
01721 }
01722
01723 void initSourceHeader(Spec spec)
01724 {
01725 HeaderIterator hi;
01726 int_32 tag, type, count;
01727 const void * ptr;
01728
01729 spec->sourceHeader = headerNew();
01730
01731 for (hi = headerInitIterator(spec->packages->header);
01732 headerNextIterator(hi, &tag, &type, &ptr, &count);
01733 ptr = headerFreeData(ptr, type))
01734 {
01735 switch (tag) {
01736 case RPMTAG_NAME:
01737 case RPMTAG_VERSION:
01738 case RPMTAG_RELEASE:
01739 case RPMTAG_EPOCH:
01740 case RPMTAG_SUMMARY:
01741 case RPMTAG_DESCRIPTION:
01742 case RPMTAG_PACKAGER:
01743 case RPMTAG_DISTRIBUTION:
01744 case RPMTAG_DISTURL:
01745 case RPMTAG_VENDOR:
01746 case RPMTAG_LICENSE:
01747 case RPMTAG_GROUP:
01748 case RPMTAG_OS:
01749 case RPMTAG_ARCH:
01750 case RPMTAG_CHANGELOGTIME:
01751 case RPMTAG_CHANGELOGNAME:
01752 case RPMTAG_CHANGELOGTEXT:
01753 case RPMTAG_URL:
01754 case HEADER_I18NTABLE:
01755 headerAddEntry(spec->sourceHeader, tag, type, ptr, count);
01756 break;
01757 default:
01758
01759 break;
01760 }
01761 }
01762 headerFreeIterator(hi);
01763
01764
01765 for (hi = headerInitIterator(spec->buildRestrictions);
01766 headerNextIterator(hi, &tag, &type, &ptr, &count);
01767 ptr = headerFreeData(ptr, type))
01768 {
01769 headerAddEntry(spec->sourceHeader, tag, type, ptr, count);
01770 }
01771 headerFreeIterator(hi);
01772
01773 if (spec->buildArchitectureCount) {
01774 headerAddEntry(spec->sourceHeader, RPMTAG_BUILDARCHS,
01775 RPM_STRING_ARRAY_TYPE,
01776 spec->buildArchitectures, spec->buildArchitectureCount);
01777 }
01778 }
01779
01780 int processSourceFiles(Spec spec)
01781 {
01782 struct Source *srcPtr;
01783 StringBuf sourceFiles;
01784 int x, isSpec = 1;
01785 struct FileList fl;
01786 char *s, **files, **fp;
01787 Package pkg;
01788
01789 sourceFiles = newStringBuf();
01790
01791
01792
01793
01794
01795 if (spec->sourceHeader == NULL)
01796 initSourceHeader(spec);
01797
01798
01799 appendLineStringBuf(sourceFiles, spec->specFile);
01800 for (srcPtr = spec->sources; srcPtr != NULL; srcPtr = srcPtr->next) {
01801 if (srcPtr->flags & RPMBUILD_ISSOURCE) {
01802 headerAddOrAppendEntry(spec->sourceHeader, RPMTAG_SOURCE,
01803 RPM_STRING_ARRAY_TYPE, &srcPtr->source, 1);
01804 if (srcPtr->flags & RPMBUILD_ISNO) {
01805 headerAddOrAppendEntry(spec->sourceHeader, RPMTAG_NOSOURCE,
01806 RPM_INT32_TYPE, &srcPtr->num, 1);
01807 }
01808 }
01809 if (srcPtr->flags & RPMBUILD_ISPATCH) {
01810 headerAddOrAppendEntry(spec->sourceHeader, RPMTAG_PATCH,
01811 RPM_STRING_ARRAY_TYPE, &srcPtr->source, 1);
01812 if (srcPtr->flags & RPMBUILD_ISNO) {
01813 headerAddOrAppendEntry(spec->sourceHeader, RPMTAG_NOPATCH,
01814 RPM_INT32_TYPE, &srcPtr->num, 1);
01815 }
01816 }
01817
01818 { const char *s;
01819 s = rpmGetPath( ((srcPtr->flags & RPMBUILD_ISNO) ? "!" : ""),
01820 "%{_sourcedir}/", srcPtr->source, NULL);
01821 appendLineStringBuf(sourceFiles, s);
01822 free((void *)s);
01823 }
01824 }
01825
01826 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
01827 for (srcPtr = pkg->icon; srcPtr != NULL; srcPtr = srcPtr->next) {
01828 const char *s;
01829 s = rpmGetPath( ((srcPtr->flags & RPMBUILD_ISNO) ? "!" : ""),
01830 "%{_sourcedir}/", srcPtr->source, NULL);
01831 appendLineStringBuf(sourceFiles, s);
01832 free((void *)s);
01833 }
01834 }
01835
01836 spec->sourceCpioList = NULL;
01837
01838 fl.fileList = xmalloc((spec->numSources + 1) * sizeof(FileListRec));
01839 fl.processingFailed = 0;
01840 fl.fileListRecsUsed = 0;
01841 fl.totalFileSize = 0;
01842 fl.prefix = NULL;
01843
01844 s = getStringBuf(sourceFiles);
01845 files = splitString(s, strlen(s), '\n');
01846
01847
01848 x = 0;
01849 for (fp = files; *fp != NULL; fp++) {
01850 const char * diskURL, *diskPath;
01851 FileListRec *flp;
01852
01853 diskURL = *fp;
01854 SKIPSPACE(diskURL);
01855 if (! *diskURL)
01856 continue;
01857
01858 flp = &fl.fileList[x];
01859
01860 flp->flags = isSpec ? RPMFILE_SPECFILE : 0;
01861
01862 if (*diskURL == '!') {
01863 flp->flags |= RPMFILE_GHOST;
01864 diskURL++;
01865 }
01866
01867 urlPath(diskURL, &diskPath);
01868
01869 flp->diskURL = xstrdup(diskURL);
01870 diskPath = strrchr(diskPath, '/');
01871 if (diskPath)
01872 diskPath++;
01873 else
01874 diskPath = diskURL;
01875
01876 flp->fileURL = xstrdup(diskPath);
01877 flp->verifyFlags = RPMVERIFY_ALL;
01878
01879 if (Stat(diskURL, &flp->fl_st)) {
01880 rpmError(RPMERR_BADSPEC, _("Bad file: %s: %s\n"),
01881 diskURL, strerror(errno));
01882 fl.processingFailed = 1;
01883 }
01884
01885 flp->uname = getUname(flp->fl_uid);
01886 flp->gname = getGname(flp->fl_gid);
01887 flp->langs = xstrdup("");
01888
01889 fl.totalFileSize += flp->fl_size;
01890
01891 if (! (flp->uname && flp->gname)) {
01892 rpmError(RPMERR_BADSPEC, _("Bad owner/group: %s\n"), diskURL);
01893 fl.processingFailed = 1;
01894 }
01895
01896 isSpec = 0;
01897 x++;
01898 }
01899 fl.fileListRecsUsed = x;
01900 freeSplitString(files);
01901
01902 if (! fl.processingFailed) {
01903 genCpioListAndHeader