rpm  5.4.10
files.c
Go to the documentation of this file.
1 
7 #include "system.h"
8 
9 #define MYALLPERMS 07777
10 
11 #if defined(WITH_PCRE) && defined(WITH_PCRE_POSIX)
12 #include <pcreposix.h>
13 #else
14 #include <regex.h>
15 #endif
16 
17 #define _RPMIOB_INTERNAL
18 #include <rpmiotypes.h>
19 #include <rpmio_internal.h> /* XXX fdGetFp */
20 #include <rpmbf.h>
21 #include <rpmcb.h>
22 #define _RPMSX_INTERNAL /* XXX permit disabling. */
23 #include <rpmsx.h>
24 #include <fts.h>
25 #include <argv.h>
26 
27 #include "iosm.h"
28 #define _RPMTAG_INTERNAL /* XXX rpmTags->aTags */
29 #define _RPMFI_INTERNAL
30 #include <rpmbuild.h>
31 
32 #define _RPMTE_INTERNAL
33 #include <rpmte.h>
34 
35 #include "rpmfc.h"
36 
37 #include "buildio.h"
38 
39 #include "legacy.h" /* XXX dodigest */
40 #include "debug.h"
41 
42 /*@access Header @*/
43 /*@access rpmfi @*/
44 /*@access rpmte @*/
45 /*@access FD_t @*/
46 
47 #define SKIPWHITE(_x) {while(*(_x) && (xisspace(*_x) || *(_x) == ',')) (_x)++;}
48 #define SKIPNONWHITE(_x){while(*(_x) &&!(xisspace(*_x) || *(_x) == ',')) (_x)++;}
49 
50 #define MAXDOCDIR 1024
51 
54 typedef enum specdFlags_e {
55  SPECD_DEFFILEMODE = (1 << 0),
56  SPECD_DEFDIRMODE = (1 << 1),
57  SPECD_DEFUID = (1 << 2),
58  SPECD_DEFGID = (1 << 3),
59  SPECD_DEFVERIFY = (1 << 4),
60 
61  SPECD_FILEMODE = (1 << 8),
62  SPECD_DIRMODE = (1 << 9),
63  SPECD_UID = (1 << 10),
64  SPECD_GID = (1 << 11),
65  SPECD_VERIFY = (1 << 12)
66 } specdFlags;
67 
70 typedef struct FileListRec_s {
71  struct stat fl_st;
72 #define fl_dev fl_st.st_dev
73 #define fl_ino fl_st.st_ino
74 #define fl_mode fl_st.st_mode
75 #define fl_nlink fl_st.st_nlink
76 #define fl_uid fl_st.st_uid
77 #define fl_gid fl_st.st_gid
78 #define fl_rdev fl_st.st_rdev
79 #define fl_size fl_st.st_size
80 #define fl_mtime fl_st.st_mtime
81 
82 /*@only@*/
83  const char *diskURL; /* get file from here */
84 /*@only@*/
85  const char *fileURL; /* filename in cpio archive */
86 /*@observer@*/
87  const char *uname;
88 /*@observer@*/
89  const char *gname;
90  unsigned flags;
91  specdFlags specdFlags; /* which attributes have been explicitly specified. */
92  unsigned verifyFlags;
93 /*@only@*/
94  const char *langs; /* XXX locales separated with | */
95 } * FileListRec;
96 
99 typedef struct AttrRec_s {
100 /*@null@*/
101  const char *ar_fmodestr;
102 /*@null@*/
103  const char *ar_dmodestr;
104 /*@null@*/
105  const char *ar_user;
106 /*@null@*/
107  const char *ar_group;
108  mode_t ar_fmode;
109  mode_t ar_dmode;
110 } * AttrRec;
111 
112 /*@-readonlytrans@*/
113 /*@unchecked@*/ /*@observer@*/
114 static struct AttrRec_s root_ar = { NULL, NULL, "root", "root", 0, 0 };
115 /*@=readonlytrans@*/
116 
120 typedef struct FileList_s {
121 /*@only@*/
122  const char * buildRootURL;
123 /*@only@*/
124  const char * prefix;
125 
129 
132 
133  int noGlob;
134  unsigned devtype;
135  unsigned devmajor;
136  int devminor;
137 
138  int isDir;
139  int inFtw;
143  struct AttrRec_s cur_ar;
144  struct AttrRec_s def_ar;
146  unsigned defVerifyFlags;
147  int nLangs;
148 /*@only@*/ /*@null@*/
149  const char ** currentLangs;
150 
151  /* Hard coded limit of MAXDOCDIR docdirs. */
152  /* If you break it you are doing something wrong. */
153  const char * docDirs[MAXDOCDIR];
155 
156 /*@only@*/
160 } * FileList;
161 
164 static void nullAttrRec(/*@out@*/ AttrRec ar) /*@modifies ar @*/
165 {
166  ar->ar_fmodestr = NULL;
167  ar->ar_dmodestr = NULL;
168  ar->ar_user = NULL;
169  ar->ar_group = NULL;
170  ar->ar_fmode = 0;
171  ar->ar_dmode = 0;
172 }
173 
176 static void freeAttrRec(AttrRec ar) /*@modifies ar @*/
177 {
178  ar->ar_fmodestr = _free(ar->ar_fmodestr);
179  ar->ar_dmodestr = _free(ar->ar_dmodestr);
180  ar->ar_user = _free(ar->ar_user);
181  ar->ar_group = _free(ar->ar_group);
182  /* XXX doesn't free ar (yet) */
183  /*@-nullstate@*/
184  return;
185  /*@=nullstate@*/
186 }
187 
190 static void dupAttrRec(const AttrRec oar, /*@in@*/ /*@out@*/ AttrRec nar)
191  /*@modifies nar @*/
192 {
193  if (oar == nar)
194  return;
195  freeAttrRec(nar);
196  nar->ar_fmodestr = (oar->ar_fmodestr ? xstrdup(oar->ar_fmodestr) : NULL);
197  nar->ar_dmodestr = (oar->ar_dmodestr ? xstrdup(oar->ar_dmodestr) : NULL);
198  nar->ar_user = (oar->ar_user ? xstrdup(oar->ar_user) : NULL);
199  nar->ar_group = (oar->ar_group ? xstrdup(oar->ar_group) : NULL);
200  nar->ar_fmode = oar->ar_fmode;
201  nar->ar_dmode = oar->ar_dmode;
202 }
203 
204 #if 0
205 
207 static void dumpAttrRec(const char * msg, AttrRec ar)
208  /*@globals fileSystem@*/
209  /*@modifies fileSystem @*/
210 {
211  if (msg)
212  fprintf(stderr, "%s:\t", msg);
213  fprintf(stderr, "(%s, %s, %s, %s)\n",
214  ar->ar_fmodestr,
215  ar->ar_user,
216  ar->ar_group,
217  ar->ar_dmodestr);
218 }
219 #endif
220 
226 /*@null@*/
227 static char *strtokWithQuotes(/*@null@*/ char *s, const char *delim)
228  /*@modifies *s @*/
229 {
230  static char *olds = NULL;
231  char *token;
232 
233  if (s == NULL)
234  s = olds;
235  if (s == NULL)
236  return NULL;
237 
238  /* Skip leading delimiters */
239  s += strspn(s, delim);
240  if (*s == '\0')
241  return NULL;
242 
243  /* Find the end of the token. */
244  token = s;
245  if (*token == '"') {
246  token++;
247  /* Find next " char */
248  s = strchr(token, '"');
249  } else {
250  s = strpbrk(token, delim);
251  }
252 
253  /* Terminate it */
254  if (s == NULL) {
255  /* This token finishes the string */
256  olds = strchr(token, '\0');
257  } else {
258  /* Terminate the token and make olds point past it */
259  *s = '\0';
260  olds = s+1;
261  }
262 
263  /*@-retalias -temptrans @*/
264  return token;
265  /*@=retalias =temptrans @*/
266 }
267 
270 static void timeCheck(int tc, Header h)
271  /*@globals internalState @*/
272  /*@modifies internalState @*/
273 {
274  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
275  rpmuint32_t currentTime = (rpmuint32_t) time(NULL);
276  rpmuint32_t * mtime;
277  int xx;
278  size_t i;
279 
280  he->tag = RPMTAG_FILEMTIMES;
281  xx = headerGet(h, he, 0);
282  mtime = he->p.ui32p;
283  he->tag = RPMTAG_OLDFILENAMES;
284  xx = headerGet(h, he, 0);
285 
286  for (i = 0; i < he->c; i++) {
287  xx = currentTime - mtime[i];
288  if (xx < 0) xx = -xx;
289  if (xx > tc)
290  rpmlog(RPMLOG_WARNING, _("TIMECHECK failure: %s\n"), he->p.argv[i]);
291  }
292  he->p.ptr = _free(he->p.ptr);
293  mtime = _free(mtime);
294 }
295 
298 typedef struct VFA {
299 /*@observer@*/ /*@null@*/ const char * attribute;
300  int not;
301  int flag;
302 } VFA_t;
303 
306 /*@-exportlocal -exportheadervar@*/
307 /*@unchecked@*/
308 static VFA_t verifyAttrs[] = {
309  { "md5", 0, RPMVERIFY_FDIGEST }, /* XXX legacy syntax */
310  { "size", 0, RPMVERIFY_FILESIZE },
311  { "link", 0, RPMVERIFY_LINKTO },
312  { "user", 0, RPMVERIFY_USER },
313  { "group", 0, RPMVERIFY_GROUP },
314  { "mtime", 0, RPMVERIFY_MTIME },
315  { "mode", 0, RPMVERIFY_MODE },
316  { "rdev", 0, RPMVERIFY_RDEV },
317  { "digest", 0, RPMVERIFY_FDIGEST },
318  { "hmac", 0, RPMVERIFY_HMAC },
319  { NULL, 0, 0 }
320 };
321 /*@=exportlocal =exportheadervar@*/
322 
329 static rpmRC parseForVerify(char * buf, FileList fl)
330  /*@modifies buf, fl->processingFailed,
331  fl->currentVerifyFlags, fl->defVerifyFlags,
332  fl->currentSpecdFlags, fl->defSpecdFlags @*/
333 {
334  char *p, *pe, *q;
335  const char *name;
336  unsigned *resultVerify;
337  int negated;
338  unsigned verifyFlags;
340 
341  if ((p = strstr(buf, (name = "%verify"))) != NULL) {
342  resultVerify = &(fl->currentVerifyFlags);
343  specdFlags = &fl->currentSpecdFlags;
344  } else if ((p = strstr(buf, (name = "%defverify"))) != NULL) {
345  resultVerify = &(fl->defVerifyFlags);
346  specdFlags = &fl->defSpecdFlags;
347  } else
348  return RPMRC_OK;
349 
350  for (pe = p; (size_t)(pe-p) < strlen(name); pe++)
351  *pe = ' ';
352 
353  SKIPSPACE(pe);
354 
355  if (*pe != '(') {
356  rpmlog(RPMLOG_ERR, _("Missing '(' in %s %s\n"), name, pe);
357  fl->processingFailed = 1;
358  return RPMRC_FAIL;
359  }
360 
361  /* Bracket %*verify args */
362  *pe++ = ' ';
363  for (p = pe; *pe && *pe != ')'; pe++)
364  {};
365 
366  if (*pe == '\0') {
367  rpmlog(RPMLOG_ERR, _("Missing ')' in %s(%s\n"), name, p);
368  fl->processingFailed = 1;
369  return RPMRC_FAIL;
370  }
371 
372  /* Localize. Erase parsed string */
373  q = alloca((pe-p) + 1);
374  strncpy(q, p, pe-p);
375  q[pe-p] = '\0';
376  while (p <= pe)
377  *p++ = ' ';
378 
379  negated = 0;
380  verifyFlags = RPMVERIFY_NONE;
381 
382  for (p = q; *p != '\0'; p = pe) {
383  SKIPWHITE(p);
384  if (*p == '\0')
385  break;
386  pe = p;
387  SKIPNONWHITE(pe);
388  if (*pe != '\0')
389  *pe++ = '\0';
390 
391  { VFA_t *vfa;
392  for (vfa = verifyAttrs; vfa->attribute != NULL; vfa++) {
393  if (strcmp(p, vfa->attribute))
394  /*@innercontinue@*/ continue;
395  verifyFlags |= vfa->flag;
396  verifyFlags &= ~RPMVERIFY_FDIGEST;
397  /*@innerbreak@*/ break;
398  }
399  if (vfa->attribute)
400  continue;
401  }
402 
403  if (!strcmp(p, "not")) {
404  negated ^= 1;
405  } else {
406  rpmlog(RPMLOG_ERR, _("Invalid %s token: %s\n"), name, p);
407  fl->processingFailed = 1;
408  return RPMRC_FAIL;
409  }
410  }
411 
412  *resultVerify = negated ? ~(verifyFlags) : verifyFlags;
413  if (negated) {
414  /* Make sure "no digest" implies "no hmac" */
415  if (!(*resultVerify & RPMVERIFY_FDIGEST))
416  *resultVerify &= ~RPMVERIFY_HMAC;
417  } else {
418  /* Make sure "hmac" implies "no digest" */
419  if (*resultVerify & RPMVERIFY_HMAC)
420  *resultVerify &= ~RPMVERIFY_FDIGEST;
421  }
422  *specdFlags |= SPECD_VERIFY;
423 
424  return RPMRC_OK;
425 }
426 
427 #define isAttrDefault(_ars) ((_ars)[0] == '-' && (_ars)[1] == '\0')
428 
435 static rpmRC parseForDev(char * buf, FileList fl)
436  /*@modifies buf, fl->processingFailed,
437  fl->noGlob, fl->devtype, fl->devmajor, fl->devminor @*/
438 {
439  const char * name;
440  const char * errstr = NULL;
441  char *p, *pe, *q;
442  rpmRC rc = RPMRC_FAIL; /* assume error */
443 
444  if ((p = strstr(buf, (name = "%dev"))) == NULL)
445  return RPMRC_OK;
446 
447  for (pe = p; (size_t)(pe-p) < strlen(name); pe++)
448  *pe = ' ';
449  SKIPSPACE(pe);
450 
451  if (*pe != '(') {
452  errstr = "'('";
453  goto exit;
454  }
455 
456  /* Bracket %dev args */
457  *pe++ = ' ';
458  for (p = pe; *pe && *pe != ')'; pe++)
459  {};
460  if (*pe != ')') {
461  errstr = "')'";
462  goto exit;
463  }
464 
465  /* Localize. Erase parsed string */
466  q = alloca((pe-p) + 1);
467  strncpy(q, p, pe-p);
468  q[pe-p] = '\0';
469  while (p <= pe)
470  *p++ = ' ';
471 
472  p = q; SKIPWHITE(p);
473  pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
474  if (*p == 'b')
475  fl->devtype = 'b';
476  else if (*p == 'c')
477  fl->devtype = 'c';
478  else {
479  errstr = "devtype";
480  goto exit;
481  }
482 
483  p = pe; SKIPWHITE(p);
484  pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
485  for (pe = p; *pe && xisdigit(*pe); pe++)
486  {} ;
487  if (*pe == '\0') {
488  fl->devmajor = atoi(p);
489  /*@-unsignedcompare @*/ /* LCL: ge is ok */
490  if (!((int)fl->devmajor >= 0 && (int)fl->devmajor < 256)) {
491  errstr = "devmajor";
492  goto exit;
493  }
494  /*@=unsignedcompare @*/
495  pe++;
496  } else {
497  errstr = "devmajor";
498  goto exit;
499  }
500 
501  p = pe; SKIPWHITE(p);
502  pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
503  for (pe = p; *pe && xisdigit(*pe); pe++)
504  {} ;
505  if (*pe == '\0') {
506  fl->devminor = atoi(p);
507  if (!(fl->devminor >= 0 && fl->devminor < 256)) {
508  errstr = "devminor";
509  goto exit;
510  }
511  pe++;
512  } else {
513  errstr = "devminor";
514  goto exit;
515  }
516 
517  fl->noGlob = 1;
518 
519  rc = 0;
520 
521 exit:
522  if (rc) {
523  rpmlog(RPMLOG_ERR, _("Missing %s in %s %s\n"), errstr, name, p);
524  fl->processingFailed = 1;
525  }
526  return rc;
527 }
528 
535 static rpmRC parseForAttr(char * buf, FileList fl)
536  /*@modifies buf, fl->processingFailed,
537  fl->cur_ar, fl->def_ar,
538  fl->currentSpecdFlags, fl->defSpecdFlags @*/
539 {
540  const char *name;
541  char *p, *pe, *q;
542  int x;
543  struct AttrRec_s arbuf;
544  AttrRec ar = &arbuf, ret_ar;
546 
547  if ((p = strstr(buf, (name = "%attr"))) != NULL) {
548  ret_ar = &(fl->cur_ar);
549  specdFlags = &fl->currentSpecdFlags;
550  } else if ((p = strstr(buf, (name = "%defattr"))) != NULL) {
551  ret_ar = &(fl->def_ar);
552  specdFlags = &fl->defSpecdFlags;
553  } else
554  return RPMRC_OK;
555 
556  for (pe = p; (size_t)(pe-p) < strlen(name); pe++)
557  *pe = ' ';
558 
559  SKIPSPACE(pe);
560 
561  if (*pe != '(') {
562  rpmlog(RPMLOG_ERR, _("Missing '(' in %s %s\n"), name, pe);
563  fl->processingFailed = 1;
564  return RPMRC_FAIL;
565  }
566 
567  /* Bracket %*attr args */
568  *pe++ = ' ';
569  for (p = pe; *pe && *pe != ')'; pe++)
570  {};
571 
572  if (ret_ar == &(fl->def_ar)) { /* %defattr */
573  q = pe;
574  q++;
575  SKIPSPACE(q);
576  if (*q != '\0') {
578  _("Non-white space follows %s(): %s\n"), name, q);
579  fl->processingFailed = 1;
580  return RPMRC_FAIL;
581  }
582  }
583 
584  /* Localize. Erase parsed string */
585  q = alloca((pe-p) + 1);
586  strncpy(q, p, pe-p);
587  q[pe-p] = '\0';
588  while (p <= pe)
589  *p++ = ' ';
590 
591  nullAttrRec(ar);
592 
593  p = q; SKIPWHITE(p);
594  if (*p != '\0') {
595  pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
596  ar->ar_fmodestr = p;
597  p = pe; SKIPWHITE(p);
598  }
599  if (*p != '\0') {
600  pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
601  ar->ar_user = p;
602  p = pe; SKIPWHITE(p);
603  }
604  if (*p != '\0') {
605  pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
606  ar->ar_group = p;
607  p = pe; SKIPWHITE(p);
608  }
609  if (*p != '\0' && ret_ar == &(fl->def_ar)) { /* %defattr */
610  pe = p; SKIPNONWHITE(pe); if (*pe != '\0') *pe++ = '\0';
611  ar->ar_dmodestr = p;
612  p = pe; SKIPWHITE(p);
613  }
614 
615  if (!(ar->ar_fmodestr && ar->ar_user && ar->ar_group) || *p != '\0') {
616  rpmlog(RPMLOG_ERR, _("Bad syntax: %s(%s)\n"), name, q);
617  fl->processingFailed = 1;
618  return RPMRC_FAIL;
619  }
620 
621  /* Do a quick test on the mode argument and adjust for "-" */
622  if (ar->ar_fmodestr && !isAttrDefault(ar->ar_fmodestr)) {
623  unsigned int ui;
624  x = sscanf(ar->ar_fmodestr, "%o", &ui);
625  if ((x == 0) || (ar->ar_fmode & ~MYALLPERMS)) {
626  rpmlog(RPMLOG_ERR, _("Bad mode spec: %s(%s)\n"), name, q);
627  fl->processingFailed = 1;
628  return RPMRC_FAIL;
629  }
630  ar->ar_fmode = ui;
631  } else
632  ar->ar_fmodestr = NULL;
633 
634  if (ar->ar_dmodestr && !isAttrDefault(ar->ar_dmodestr)) {
635  unsigned int ui;
636  x = sscanf(ar->ar_dmodestr, "%o", &ui);
637  if ((x == 0) || (ar->ar_dmode & ~MYALLPERMS)) {
638  rpmlog(RPMLOG_ERR, _("Bad dirmode spec: %s(%s)\n"), name, q);
639  fl->processingFailed = 1;
640  return RPMRC_FAIL;
641  }
642  ar->ar_dmode = ui;
643  } else
644  ar->ar_dmodestr = NULL;
645 
646  if (!(ar->ar_user && !isAttrDefault(ar->ar_user)))
647  ar->ar_user = NULL;
648 
649  if (!(ar->ar_group && !isAttrDefault(ar->ar_group)))
650  ar->ar_group = NULL;
651 
652  dupAttrRec(ar, ret_ar);
653 
654  /* XXX fix all this */
655  *specdFlags |= SPECD_UID | SPECD_GID | SPECD_FILEMODE | SPECD_DIRMODE;
656 
657  return RPMRC_OK;
658 }
659 
666 static rpmRC parseForConfig(char * buf, FileList fl)
667  /*@modifies buf, fl->processingFailed, fl->currentFlags @*/
668 {
669  char *p, *pe, *q;
670  const char *name;
671 
672  if ((p = strstr(buf, (name = "%config"))) == NULL)
673  return RPMRC_OK;
674 
676 
677  /* Erase "%config" token. */
678  for (pe = p; (size_t)(pe-p) < strlen(name); pe++)
679  *pe = ' ';
680  SKIPSPACE(pe);
681  if (*pe != '(')
682  return RPMRC_OK;
683 
684  /* Bracket %config args */
685  *pe++ = ' ';
686  for (p = pe; *pe && *pe != ')'; pe++)
687  {};
688 
689  if (*pe == '\0') {
690  rpmlog(RPMLOG_ERR, _("Missing ')' in %s(%s\n"), name, p);
691  fl->processingFailed = 1;
692  return RPMRC_FAIL;
693  }
694 
695  /* Localize. Erase parsed string. */
696  q = alloca((pe-p) + 1);
697  strncpy(q, p, pe-p);
698  q[pe-p] = '\0';
699  while (p <= pe)
700  *p++ = ' ';
701 
702  for (p = q; *p != '\0'; p = pe) {
703  SKIPWHITE(p);
704  if (*p == '\0')
705  break;
706  pe = p;
707  SKIPNONWHITE(pe);
708  if (*pe != '\0')
709  *pe++ = '\0';
710  if (!strcmp(p, "missingok")) {
712  } else if (!strcmp(p, "noreplace")) {
714  } else {
715  rpmlog(RPMLOG_ERR, _("Invalid %s token: %s\n"), name, p);
716  fl->processingFailed = 1;
717  return RPMRC_FAIL;
718  }
719  }
720 
721  return RPMRC_OK;
722 }
723 
726 static int langCmp(const void * ap, const void * bp)
727  /*@*/
728 {
729  return strcmp(*(const char **)ap, *(const char **)bp);
730 }
731 
738 static rpmRC parseForLang(char * buf, FileList fl)
739  /*@modifies buf, fl->processingFailed,
740  fl->currentLangs, fl->nLangs @*/
741 {
742  char *p, *pe, *q;
743  const char *name;
744 
745  while ((p = strstr(buf, (name = "%lang"))) != NULL) {
746 
747  for (pe = p; (size_t)(pe-p) < strlen(name); pe++)
748  *pe = ' ';
749  SKIPSPACE(pe);
750 
751  if (*pe != '(') {
752  rpmlog(RPMLOG_ERR, _("Missing '(' in %s %s\n"), name, pe);
753  fl->processingFailed = 1;
754  return RPMRC_FAIL;
755  }
756 
757  /* Bracket %lang args */
758  *pe++ = ' ';
759  for (pe = p; *pe && *pe != ')'; pe++)
760  {};
761 
762  if (*pe == '\0') {
763  rpmlog(RPMLOG_ERR, _("Missing ')' in %s(%s\n"), name, p);
764  fl->processingFailed = 1;
765  return RPMRC_FAIL;
766  }
767 
768  /* Localize. Erase parsed string. */
769  q = alloca((pe-p) + 1);
770  strncpy(q, p, pe-p);
771  q[pe-p] = '\0';
772  while (p <= pe)
773  *p++ = ' ';
774 
775  /* Parse multiple arguments from %lang */
776  for (p = q; *p != '\0'; p = pe) {
777  char *newp;
778  size_t np;
779  int i;
780 
781  SKIPWHITE(p);
782  pe = p;
783  SKIPNONWHITE(pe);
784 
785  np = pe - p;
786 
787  /* Sanity check on locale lengths */
788  if (np < 1 || (np == 1 && *p != 'C') || np >= 32) {
790  _("Unusual locale length: \"%.*s\" in %%lang(%s)\n"),
791  (int)np, p, q);
792  fl->processingFailed = 1;
793  return RPMRC_FAIL;
794  }
795 
796  /* Check for duplicate locales */
797  if (fl->currentLangs != NULL)
798  for (i = 0; i < fl->nLangs; i++) {
799  if (strncmp(fl->currentLangs[i], p, np))
800  /*@innercontinue@*/ continue;
801  rpmlog(RPMLOG_ERR, _("Duplicate locale %.*s in %%lang(%s)\n"),
802  (int)np, p, q);
803  fl->processingFailed = 1;
804  return RPMRC_FAIL;
805  }
806 
807  /* Add new locale */
809  (fl->nLangs + 1) * sizeof(*fl->currentLangs));
810  newp = xmalloc( np+1 );
811  strncpy(newp, p, np);
812  newp[np] = '\0';
813  fl->currentLangs[fl->nLangs++] = newp;
814  if (*pe == ',') pe++; /* skip , if present */
815  }
816  }
817 
818  /* Insure that locales are sorted. */
819  if (fl->currentLangs)
820  qsort(fl->currentLangs, fl->nLangs, sizeof(*fl->currentLangs), langCmp);
821 
822  return RPMRC_OK;
823 }
824 
827 static int parseForRegexLang(const char * fileName, /*@out@*/ char ** lang)
828  /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
829  /*@modifies *lang, rpmGlobalMacroContext, internalState @*/
830 {
831  static int initialized = 0;
832  static int hasRegex = 0;
833  static regex_t compiledPatt;
834  static char buf[BUFSIZ];
835  int x;
836  regmatch_t matches[2];
837  const char *s;
838 
839  if (! initialized) {
840  const char *patt = rpmExpand("%{?_langpatt}", NULL);
841  int rc = 0;
842  if (!(patt && *patt != '\0'))
843  rc = 1;
844  else if (regcomp(&compiledPatt, patt, REG_EXTENDED))
845  rc = -1;
846  patt = _free(patt);
847  if (rc)
848  return rc;
849  hasRegex = 1;
850  initialized = 1;
851  }
852 
853  memset(matches, 0, sizeof(matches));
854  if (! hasRegex || regexec(&compiledPatt, fileName, 2, matches, REG_NOTEOL))
855  return 1;
856 
857  /* Got match */
858  s = fileName + matches[1].rm_eo - 1;
859  x = (int)matches[1].rm_eo - (int)matches[1].rm_so;
860  buf[x] = '\0';
861  while (x) {
862  buf[--x] = *s--;
863  }
864  if (lang)
865  *lang = buf;
866  return 0;
867 }
868 
871 /*@-exportlocal -exportheadervar@*/
872 /*@unchecked@*/
874  { "%dir", 0, 0 }, /* XXX why not RPMFILE_DIR? */
875  { "%doc", 0, RPMFILE_DOC },
876  { "%ghost", 0, RPMFILE_GHOST },
877  { "%exclude", 0, RPMFILE_EXCLUDE },
878  { "%readme", 0, RPMFILE_README },
879  { "%license", 0, RPMFILE_LICENSE },
880  { "%pubkey", 0, RPMFILE_PUBKEY },
881  { "%policy", 0, RPMFILE_POLICY },
882  { "%optional", 0, RPMFILE_OPTIONAL },
883  { "%remove", 0, RPMFILE_REMOVE },
884 
885 #if WHY_NOT
886  { "%icon", 0, RPMFILE_ICON },
887  { "%spec", 0, RPMFILE_SPEC },
888  { "%config", 0, RPMFILE_CONFIG },
889  { "%missingok", 0, RPMFILE_CONFIG|RPMFILE_MISSINGOK },
890  { "%noreplace", 0, RPMFILE_CONFIG|RPMFILE_NOREPLACE },
891 #endif
892 
893  { NULL, 0, 0 }
894 };
895 /*@=exportlocal =exportheadervar@*/
896 
906 static rpmRC parseForSimple(/*@unused@*/ Spec spec, Package pkg,
907  char * buf, FileList fl, /*@out@*/ const char ** fileName)
908  /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
909  /*@modifies buf, fl->processingFailed, *fileName,
910  fl->currentFlags,
911  fl->docDirs, fl->docDirCount, fl->isDir,
912  fl->passedSpecialDoc, fl->isSpecialDoc,
913  pkg->header, pkg->specialDoc,
914  rpmGlobalMacroContext, internalState @*/
915 {
916  char *s, *t;
917  int specialDoc = 0;
918  char specialDocBuf[BUFSIZ];
919  rpmRC res = RPMRC_OK; /* assume success */
920 
921  specialDocBuf[0] = '\0';
922  *fileName = NULL;
923 
924  t = buf;
925  while ((s = strtokWithQuotes(t, " \t\n")) != NULL) {
926  t = NULL;
927  if (!strcmp(s, "%docdir")) {
928  s = strtokWithQuotes(NULL, " \t\n");
929  if (fl->docDirCount == MAXDOCDIR) {
930  rpmlog(RPMLOG_CRIT, _("Hit limit for %%docdir\n"));
931  fl->processingFailed = 1;
932  res = RPMRC_FAIL;
933  }
934 
935  if (s != NULL)
936  fl->docDirs[fl->docDirCount++] = xstrdup(s);
937  if (s == NULL || strtokWithQuotes(NULL, " \t\n")) {
938  rpmlog(RPMLOG_CRIT, _("Only one arg for %%docdir\n"));
939  fl->processingFailed = 1;
940  res = RPMRC_FAIL;
941  }
942  break;
943  }
944 #if defined(__LCLINT__)
945  assert(s != NULL);
946 #endif
947 
948  /* Set flags for virtual file attributes */
949  { VFA_t *vfa;
950  for (vfa = virtualFileAttributes; vfa->attribute != NULL; vfa++) {
951  if (strcmp(s, vfa->attribute))
952  /*@innercontinue@*/ continue;
953  if (!vfa->flag) {
954  if (!strcmp(s, "%dir"))
955  fl->isDir = 1; /* XXX why not RPMFILE_DIR? */
956  } else {
957  if (vfa->not)
958  fl->currentFlags &= ~vfa->flag;
959  else
960  fl->currentFlags |= vfa->flag;
961  }
962 
963  /*@innerbreak@*/ break;
964  }
965  /* if we got an attribute, continue with next token */
966  if (vfa->attribute != NULL)
967  continue;
968  }
969 
970  if (*fileName) {
971  /* We already got a file -- error */
972  rpmlog(RPMLOG_ERR, _("Two files on one line: %s\n"),
973  *fileName);
974  fl->processingFailed = 1;
975  res = RPMRC_FAIL;
976  }
977 
978  if (*s != '/') {
979  if (fl->currentFlags & RPMFILE_DOC) {
980  specialDoc = 1;
981  strcat(specialDocBuf, " ");
982  strcat(specialDocBuf, s);
983  } else
985  {
986  *fileName = s;
987  } else {
988  const char * sfn = NULL;
989  int urltype = urlPath(s, &sfn);
990  switch (urltype) {
991  default: /* relative path, not in %doc and not a URL */
993  _("File must begin with \"/\": %s\n"), s);
994  fl->processingFailed = 1;
995  res = RPMRC_FAIL;
996  /*@switchbreak@*/ break;
997  case URL_IS_PATH:
998  *fileName = s;
999  /*@switchbreak@*/ break;
1000  }
1001  }
1002  } else {
1003  *fileName = s;
1004  }
1005  }
1006 
1007  if (specialDoc) {
1008  if (*fileName || (fl->currentFlags & ~(RPMFILE_DOC))) {
1010  _("Can't mix special %%doc with other forms: %s\n"),
1011  (*fileName ? *fileName : ""));
1012  fl->processingFailed = 1;
1013  res = RPMRC_FAIL;
1014  } else {
1015  /* XXX WATCHOUT: buf is an arg */
1016  {
1017  /*@only@*/
1018  static char *_docdir_fmt = NULL; /* XXX memleak */
1019  static int oneshot = 0;
1020  const char *ddir, *fmt, *errstr;
1021  if (!oneshot) {
1022  _docdir_fmt = rpmExpand("%{?_docdir_fmt}", NULL);
1023  if (!(_docdir_fmt && *_docdir_fmt))
1024  _docdir_fmt = _free(_docdir_fmt);
1025  oneshot = 1;
1026  }
1027  if (_docdir_fmt == NULL)
1028  _docdir_fmt = xstrdup("%{NAME}-%{VERSION}");
1029  fmt = headerSprintf(pkg->header, _docdir_fmt, NULL, rpmHeaderFormats, &errstr);
1030  if (fmt == NULL) {
1031  rpmlog(RPMLOG_ERR, _("illegal _docdir_fmt: %s\n"), errstr);
1032  fl->processingFailed = 1;
1033  res = RPMRC_FAIL;
1034  } else {
1035  ddir = rpmGetPath("%{_docdir}/", fmt, NULL);
1036  strcpy(buf, ddir);
1037  ddir = _free(ddir);
1038  fmt = _free(fmt);
1039  }
1040  }
1041 
1042  /* XXX FIXME: this is easy to do as macro expansion */
1043 
1044  if (! fl->passedSpecialDoc) {
1045  char *compress_doc;
1046  char *mkdir_p;
1047 
1048  pkg->specialDoc = rpmiobNew(0);
1049  pkg->specialDoc = rpmiobAppend(pkg->specialDoc, "DOCDIR=\"$RPM_BUILD_ROOT\"", 0);
1050  pkg->specialDoc = rpmiobAppend(pkg->specialDoc, buf, 1);
1051  pkg->specialDoc = rpmiobAppend(pkg->specialDoc, "export DOCDIR", 1);
1052  mkdir_p = rpmExpand("%{?__mkdir_p}%{!?__mkdir_p:mkdir -p}", NULL);
1053  if (!mkdir_p)
1054  mkdir_p = xstrdup("mkdir -p");
1055  pkg->specialDoc = rpmiobAppend(pkg->specialDoc, mkdir_p, 0);
1056  mkdir_p = _free(mkdir_p);
1057  pkg->specialDoc = rpmiobAppend(pkg->specialDoc, " \"$DOCDIR\"", 1);
1058 
1059  compress_doc = rpmExpand("%{__compress_doc}", NULL);
1060  if (compress_doc && *compress_doc != '%')
1061  pkg->specialDoc = rpmiobAppend(pkg->specialDoc, compress_doc, 1);
1062  compress_doc = _free(compress_doc);
1063 
1064  /*@-temptrans@*/
1065  *fileName = buf;
1066  /*@=temptrans@*/
1067  fl->passedSpecialDoc = 1;
1068  fl->isSpecialDoc = 1;
1069  }
1070 
1071  pkg->specialDoc = rpmiobAppend(pkg->specialDoc, "cp -pr ", 0);
1072  pkg->specialDoc = rpmiobAppend(pkg->specialDoc, specialDocBuf, 0);
1073  pkg->specialDoc = rpmiobAppend(pkg->specialDoc, " \"$DOCDIR\"", 1);
1074  }
1075  }
1076 
1077  return res;
1078 }
1079 
1082 static int compareFileListRecs(const void * ap, const void * bp) /*@*/
1083 {
1084  const char *aurl = ((FileListRec)ap)->fileURL;
1085  const char *a = NULL;
1086  const char *burl = ((FileListRec)bp)->fileURL;
1087  const char *b = NULL;
1088  (void) urlPath(aurl, &a);
1089  (void) urlPath(burl, &b);
1090  return strcmp(a, b);
1091 }
1092 
1099 static int isDoc(FileList fl, const char * fileName) /*@*/
1100 {
1101  int x = fl->docDirCount;
1102  size_t k, l;
1103 
1104  k = strlen(fileName);
1105  while (x--) {
1106  l = strlen(fl->docDirs[x]);
1107  if (l < k && strncmp(fileName, fl->docDirs[x], l) == 0 && fileName[l] == '/')
1108  return 1;
1109  }
1110  return 0;
1111 }
1112 
1119 static int checkHardLinks(FileList fl)
1120  /*@*/
1121 {
1122  FileListRec ilp, jlp;
1123  int i, j;
1124 
1125  for (i = 0; i < fl->fileListRecsUsed; i++) {
1126  ilp = fl->fileList + i;
1127  if (!(S_ISREG(ilp->fl_mode) && ilp->fl_nlink > 1))
1128  continue;
1129  if (ilp->flags & (RPMFILE_EXCLUDE | RPMFILE_GHOST))
1130  continue;
1131 
1132  for (j = i + 1; j < fl->fileListRecsUsed; j++) {
1133  jlp = fl->fileList + j;
1134  if (!S_ISREG(jlp->fl_mode))
1135  /*@innercontinue@*/ continue;
1136  if (ilp->fl_nlink != jlp->fl_nlink)
1137  /*@innercontinue@*/ continue;
1138  if (ilp->fl_ino != jlp->fl_ino)
1139  /*@innercontinue@*/ continue;
1140  if (ilp->fl_dev != jlp->fl_dev)
1141  /*@innercontinue@*/ continue;
1142  if (jlp->flags & (RPMFILE_EXCLUDE | RPMFILE_GHOST))
1143  /*@innercontinue@*/ continue;
1144  return 1;
1145  }
1146  }
1147  return 0;
1148 }
1149 
1150 static int dncmp(const void * a, const void * b)
1151  /*@*/
1152 {
1153  const char ** aurlp = (const char **)a;
1154  const char ** burlp = (const char **)b;
1155  const char * adn;
1156  const char * bdn;
1157  (void) urlPath(*aurlp, &adn);
1158  (void) urlPath(*burlp, &bdn);
1159  return strcmp(adn, bdn);
1160 }
1161 
1166 static void compressFilelist(Header h)
1167  /*@globals internalState @*/
1168  /*@modifies h, internalState @*/
1169 {
1170  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
1171  const char ** fileNames;
1172  const char * fn;
1173  const char ** dirNames;
1174  const char ** baseNames;
1175  rpmuint32_t * dirIndexes;
1176  int count;
1177  int dirIndex = -1;
1178  int xx;
1179  int i;
1180 
1181  /*
1182  * This assumes the file list is already sorted, and begins with a
1183  * single '/'. That assumption isn't critical, but it makes things go
1184  * a bit faster.
1185  */
1186 
1187  if (headerIsEntry(h, RPMTAG_DIRNAMES)) {
1188  he->tag = RPMTAG_OLDFILENAMES;
1189  xx = headerDel(h, he, 0);
1190  return; /* Already converted. */
1191  }
1192 
1193  he->tag = RPMTAG_OLDFILENAMES;
1194  xx = headerGet(h, he, 0);
1195  fileNames = he->p.argv;
1196  count = he->c;
1197  if (!xx || fileNames == NULL || count <= 0)
1198  return; /* no file list */
1199 
1200  dirNames = alloca(sizeof(*dirNames) * count); /* worst case */
1201  baseNames = alloca(sizeof(*dirNames) * count);
1202  dirIndexes = alloca(sizeof(*dirIndexes) * count);
1203 
1204  (void) urlPath(fileNames[0], &fn);
1205  if (fn[0] != '/') {
1206  /* HACK. Source RPM, so just do things differently */
1207  dirIndex = 0;
1208  dirNames[dirIndex] = "";
1209  for (i = 0; i < count; i++) {
1210  dirIndexes[i] = dirIndex;
1211  baseNames[i] = fileNames[i];
1212  }
1213  goto exit;
1214  }
1215 
1216  for (i = 0; i < count; i++) {
1217  const char ** needle;
1218  char savechar;
1219  char * baseName;
1220  size_t len;
1221 
1222  if (fileNames[i] == NULL) /* XXX can't happen */
1223  continue;
1224  baseName = strrchr(fileNames[i], '/') + 1;
1225  len = baseName - fileNames[i];
1226  needle = dirNames;
1227  savechar = *baseName;
1228  *baseName = '\0';
1229 /*@-compdef@*/
1230  if (dirIndex < 0 ||
1231  (needle = bsearch(&fileNames[i], dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) {
1232  char *s = alloca(len + 1);
1233  memcpy(s, fileNames[i], len + 1);
1234  s[len] = '\0';
1235  dirIndexes[i] = ++dirIndex;
1236  dirNames[dirIndex] = s;
1237  } else
1238  dirIndexes[i] = needle - dirNames;
1239 /*@=compdef@*/
1240 
1241  *baseName = savechar;
1242  baseNames[i] = baseName;
1243  }
1244 
1245 exit:
1246  if (count > 0) {
1247  he->tag = RPMTAG_DIRINDEXES;
1248  he->t = RPM_UINT32_TYPE;
1249  he->p.ui32p = dirIndexes;
1250  he->c = count;
1251  xx = headerPut(h, he, 0);
1252 
1253  he->tag = RPMTAG_BASENAMES;
1254  he->t = RPM_STRING_ARRAY_TYPE;
1255  he->p.argv = baseNames;
1256  he->c = count;
1257  xx = headerPut(h, he, 0);
1258 
1259  he->tag = RPMTAG_DIRNAMES;
1260  he->t = RPM_STRING_ARRAY_TYPE;
1261  he->p.argv = dirNames;
1262  he->c = dirIndex + 1;
1263  xx = headerPut(h, he, 0);
1264  }
1265 
1266  fileNames = _free(fileNames);
1267 
1268  he->tag = RPMTAG_OLDFILENAMES;
1269  xx = headerDel(h, he, 0);
1270 }
1271 
1272 static rpmuint32_t getDigestAlgo(Header h, int isSrc)
1273  /*@modifies h @*/
1274 {
1275  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
1276  static rpmuint32_t source_file_dalgo = 0;
1277  static rpmuint32_t binary_file_dalgo = 0;
1278  static int oneshot = 0;
1279  rpmuint32_t dalgo = 0;
1280  int xx;
1281 
1282  if (!oneshot) {
1283  source_file_dalgo =
1284  rpmExpandNumeric("%{?_build_source_file_digest_algo}");
1285  binary_file_dalgo =
1286  rpmExpandNumeric("%{?_build_binary_file_digest_algo}");
1287  oneshot++;
1288  }
1289 
1290  dalgo = (isSrc ? source_file_dalgo : binary_file_dalgo);
1291  switch (dalgo) {
1292  case PGPHASHALGO_SHA1:
1293  case PGPHASHALGO_MD2:
1294  case PGPHASHALGO_SHA256:
1295  case PGPHASHALGO_SHA384:
1296  case PGPHASHALGO_SHA512:
1297  (void) rpmlibNeedsFeature(h, "FileDigests", "4.6.0-1");
1298  he->tag = RPMTAG_FILEDIGESTALGO;
1299  he->t = RPM_UINT32_TYPE;
1300  he->p.ui32p = &dalgo;
1301  he->c = 1;
1302  xx = headerPut(h, he, 0);
1303  /*@fallthgrough@*/
1304  case PGPHASHALGO_RIPEMD160:
1305  case PGPHASHALGO_TIGER192:
1306  case PGPHASHALGO_MD4:
1307  case PGPHASHALGO_RIPEMD128:
1308  case PGPHASHALGO_CRC32:
1309  case PGPHASHALGO_ADLER32:
1310  case PGPHASHALGO_CRC64:
1311  (void) rpmlibNeedsFeature(h, "FileDigestParameterized", "4.4.6-1");
1312  /*@switchbreak@*/ break;
1313  case PGPHASHALGO_MD5:
1314  case PGPHASHALGO_HAVAL_5_160: /* XXX unimplemented */
1315  default:
1316  dalgo = PGPHASHALGO_MD5;
1317  /*@switchbreak@*/ break;
1318  }
1319 
1320  return dalgo;
1321 }
1322 
1323 static int isHardLink(FileListRec flp, FileListRec tlp)
1324 {
1325  return ((S_ISREG(flp->fl_mode) && S_ISREG(tlp->fl_mode)) &&
1326  ((flp->fl_nlink > 1) && (flp->fl_nlink == tlp->fl_nlink)) &&
1327  (flp->fl_ino == tlp->fl_ino) &&
1328  (flp->fl_dev == tlp->fl_dev));
1329 }
1330 
1331 static int seenHardLink(FileList fl, FileListRec flp, ino_t *fileid)
1332 {
1333  FileListRec ilp;
1334  for (ilp = fl->fileList; ilp < flp; ilp++) {
1335  if (isHardLink(flp, ilp)) {
1336  *fileid = ilp - fl->fileList;
1337  return 1;
1338  }
1339  }
1340  return 0;
1341 }
1342 
1352 static rpmRC genCpioListAndHeader(/*@partial@*/ FileList fl,
1353  rpmfi * fip, Header h, int isSrc)
1354  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1355  /*@modifies h, *fip, fl->processingFailed, fl->fileList,
1356  fl->totalFileSize,
1357  rpmGlobalMacroContext, fileSystem, internalState @*/
1358 {
1359  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
1360  const char * apath;
1361  rpmuint16_t ui16;
1362  rpmuint32_t ui32;
1363  int _addDotSlash = !isSrc;
1364  int apathlen = 0;
1365  int dpathlen = 0;
1366  int skipLen = 0;
1367  rpmsx sx = rpmsxNew("%{?_build_file_context_path}", 0);
1368  FileListRec flp;
1369  rpmuint32_t dalgo = getDigestAlgo(h, isSrc);
1370  char buf[BUFSIZ];
1371  int i, xx;
1372  rpmRC rc = RPMRC_OK;
1373 
1374 memset(buf, 0, sizeof(buf)); /* XXX valgrind on rhel6 beta pickier */
1375 
1376  /* Sort the big list */
1377  if (fl->fileListRecsUsed > 1)
1378  qsort(fl->fileList, fl->fileListRecsUsed,
1379  sizeof(*(fl->fileList)), compareFileListRecs);
1380 
1381  /* Generate the header. */
1382  if (! isSrc) {
1383  skipLen = 1;
1384  if (fl->prefix)
1385  skipLen += strlen(fl->prefix);
1386  }
1387 
1388  for (i = 0, flp = fl->fileList; i < fl->fileListRecsUsed; i++, flp++) {
1389  const char *s;
1390  ino_t fileid = flp - fl->fileList;
1391 
1392  /* Merge duplicate entries. */
1393  while (i < (fl->fileListRecsUsed - 1) &&
1394  !strcmp(flp->fileURL, flp[1].fileURL)) {
1395 
1396  /* Two entries for the same file found, merge the entries. */
1397  /* Note that an %exclude is a duplication of a file reference */
1398 
1399  /* file flags */
1400  flp[1].flags |= flp->flags;
1401 
1402  if (!(flp[1].flags & RPMFILE_EXCLUDE)) {
1403  int terminate = rpmExpandNumeric("%{?_files_listed_twice_terminate_build}");
1404 
1405  rpmlog(terminate ? RPMLOG_ERR : RPMLOG_WARNING, _("File listed twice: %s\n"),
1406  flp->fileURL);
1407  if (terminate)
1408  rc = RPMRC_FAIL;
1409  }
1410 
1411  /* file mode */
1412  if (S_ISDIR(flp->fl_mode)) {
1413  if ((flp[1].specdFlags & (SPECD_DIRMODE | SPECD_DEFDIRMODE)) <
1415  flp[1].fl_mode = flp->fl_mode;
1416  } else {
1417  if ((flp[1].specdFlags & (SPECD_FILEMODE | SPECD_DEFFILEMODE)) <
1419  flp[1].fl_mode = flp->fl_mode;
1420  }
1421 
1422  /* uid */
1423  if ((flp[1].specdFlags & (SPECD_UID | SPECD_DEFUID)) <
1424  (flp->specdFlags & (SPECD_UID | SPECD_DEFUID)))
1425  {
1426  flp[1].fl_uid = flp->fl_uid;
1427  flp[1].uname = flp->uname;
1428  }
1429 
1430  /* gid */
1431  if ((flp[1].specdFlags & (SPECD_GID | SPECD_DEFGID)) <
1432  (flp->specdFlags & (SPECD_GID | SPECD_DEFGID)))
1433  {
1434  flp[1].fl_gid = flp->fl_gid;
1435  flp[1].gname = flp->gname;
1436  }
1437 
1438  /* verify flags */
1439  if ((flp[1].specdFlags & (SPECD_VERIFY | SPECD_DEFVERIFY)) <
1441  flp[1].verifyFlags = flp->verifyFlags;
1442 
1443  /* XXX to-do: language */
1444 
1445  flp++; i++;
1446  }
1447 
1448  /* Skip files that were marked with %exclude. */
1449  if (flp->flags & RPMFILE_EXCLUDE) continue;
1450 
1451  /* Omit '/' and/or URL prefix, leave room for "./" prefix */
1452  (void) urlPath(flp->fileURL, &apath);
1453  apathlen += (strlen(apath) - skipLen + (_addDotSlash ? 3 : 1));
1454 
1455  /* Leave room for both dirname and basename NUL's */
1456  dpathlen += (strlen(flp->diskURL) + 2);
1457 
1458  /* Excludes and dupes have been filtered out by now. */
1459  if (S_ISREG(flp->fl_mode)) {
1460  if (flp->fl_nlink == 1 || !seenHardLink(fl, flp, &fileid)) {
1461  fl->totalFileSize += flp->fl_size;
1462  }
1463  }
1464 
1465  /*
1466  * Make the header, the OLDFILENAMES will get converted to a
1467  * compressed file list write before we write the actual package to
1468  * disk.
1469  */
1470  he->tag = RPMTAG_OLDFILENAMES;
1471  he->t = RPM_STRING_ARRAY_TYPE;
1472  he->p.argv = &flp->fileURL;
1473  he->c = 1;
1474  he->append = 1;
1475  xx = headerPut(h, he, 0);
1476  he->append = 0;
1477 
1478 /*@-sizeoftype@*/
1479  ui32 = (rpmuint32_t) flp->fl_size;
1480  he->tag = RPMTAG_FILESIZES;
1481  he->t = RPM_UINT32_TYPE;
1482  he->p.ui32p = &ui32;
1483  he->c = 1;
1484  he->append = 1;
1485  xx = headerPut(h, he, 0);
1486  he->append = 0;
1487 
1488  he->tag = RPMTAG_FILEUSERNAME;
1489  he->t = RPM_STRING_ARRAY_TYPE;
1490  he->p.argv = &flp->uname;
1491  he->c = 1;
1492  he->append = 1;
1493  xx = headerPut(h, he, 0);
1494  he->append = 0;
1495 
1496  he->tag = RPMTAG_FILEGROUPNAME;
1497  he->t = RPM_STRING_ARRAY_TYPE;
1498  he->p.argv = &flp->gname;
1499  he->c = 1;
1500  he->append = 1;
1501  xx = headerPut(h, he, 0);
1502  he->append = 0;
1503 
1504  ui32 = (rpmuint32_t) flp->fl_mtime;
1505  he->tag = RPMTAG_FILEMTIMES;
1506  he->t = RPM_UINT32_TYPE;
1507  he->p.ui32p = &ui32;
1508  he->c = 1;
1509  he->append = 1;
1510  xx = headerPut(h, he, 0);
1511  he->append = 0;
1512 
1513  ui16 = (rpmuint16_t)flp->fl_mode;
1514  he->tag = RPMTAG_FILEMODES;
1515  he->t = RPM_UINT16_TYPE;
1516  he->p.ui16p = &ui16;
1517  he->c = 1;
1518  he->append = 1;
1519  xx = headerPut(h, he, 0);
1520  he->append = 0;
1521 
1522  { dev_t _dev = flp->fl_rdev;
1523  ui16 = _dev;
1524  }
1525  he->tag = RPMTAG_FILERDEVS;
1526  he->t = RPM_UINT16_TYPE;
1527  he->p.ui16p = &ui16;
1528  he->c = 1;
1529  he->append = 1;
1530  xx = headerPut(h, he, 0);
1531  he->append = 0;
1532 
1533  /* XXX Hash instead of 64b->32b truncate to prevent aliasing. */
1534  { dev_t _dev = flp->fl_dev;
1535  ui32 = hashFunctionString(0, &_dev, sizeof(_dev));
1536  }
1537  he->tag = RPMTAG_FILEDEVICES;
1538  he->t = RPM_UINT32_TYPE;
1539  he->p.ui32p = &ui32;
1540  he->c = 1;
1541  he->append = 1;
1542  xx = headerPut(h, he, 0);
1543  he->append = 0;
1544 
1545  /* XXX Hash instead of 64b->32b truncate to prevent aliasing. */
1546  { ino_t _ino = flp->fl_ino;
1547  /* don't use hash here, as hash collisions which happen on large packages
1548  cause bus errors in rpmbuild
1549  ui32 = hashFunctionString(0, &_ino, sizeof(_ino));
1550  */
1551  ui32 = fileid + 1;
1552  }
1553  he->tag = RPMTAG_FILEINODES;
1554  he->t = RPM_UINT32_TYPE;
1555  he->p.ui32p = &ui32;
1556  he->c = 1;
1557  he->append = 1;
1558  xx = headerPut(h, he, 0);
1559  he->append = 0;
1560 
1561 /*@=sizeoftype@*/
1562 
1563  he->tag = RPMTAG_FILELANGS;
1564  he->t = RPM_STRING_ARRAY_TYPE;
1565  he->p.argv = &flp->langs;
1566  he->c = 1;
1567  he->append = 1;
1568  xx = headerPut(h, he, 0);
1569  he->append = 0;
1570 
1571  buf[0] = '\0';
1572  if (S_ISREG(flp->fl_mode)) {
1573  unsigned dflags = 0x01; /* asAscii */
1574 #define _mask (RPMVERIFY_FDIGEST|RPMVERIFY_HMAC)
1575  if ((flp->verifyFlags & _mask) == RPMVERIFY_HMAC)
1576  dflags |= 0x02; /* doHmac */
1577 #undef _mask
1578  (void) dodigest(dalgo, flp->diskURL, (unsigned char *)buf,
1579  dflags, NULL);
1580  }
1581  s = buf;
1582 
1583  he->tag = RPMTAG_FILEDIGESTS;
1584  he->t = RPM_STRING_ARRAY_TYPE;
1585  he->p.argv = &s;
1586  he->c = 1;
1587  he->append = 1;
1588  xx = headerPut(h, he, 0);
1589  he->append = 0;
1590 
1591 if (!(_rpmbuildFlags & 4)) {
1592  ui32 = dalgo;
1594  he->t = RPM_UINT32_TYPE;
1595  he->p.ui32p = &ui32;
1596  he->c = 1;
1597  he->append = 1;
1598  xx = headerPut(h, he, 0);
1599  he->append = 0;
1600 }
1601 
1602  buf[0] = '\0';
1603  if (S_ISLNK(flp->fl_mode)) {
1604  xx = Readlink(flp->diskURL, buf, BUFSIZ);
1605  if (xx >= 0)
1606  buf[xx] = '\0';
1607  if (fl->buildRootURL) {
1608  const char * buildRoot;
1609  (void) urlPath(fl->buildRootURL, &buildRoot);
1610 
1611  if (buf[0] == '/' && strcmp(buildRoot, "/") &&
1612  !strncmp(buf, buildRoot, strlen(buildRoot))) {
1614  _("Symlink points to BuildRoot: %s -> %s\n"),
1615  flp->fileURL, buf);
1616  fl->processingFailed = 1;
1617  }
1618  }
1619  }
1620  s = buf;
1621  he->tag = RPMTAG_FILELINKTOS;
1622  he->t = RPM_STRING_ARRAY_TYPE;
1623  he->p.argv = &s;
1624  he->c = 1;
1625  he->append = 1;
1626  xx = headerPut(h, he, 0);
1627  he->append = 0;
1628 
1629  if (flp->flags & RPMFILE_GHOST) {
1632  }
1633  ui32 = flp->verifyFlags;
1635  he->t = RPM_UINT32_TYPE;
1636  he->p.ui32p = &ui32;
1637  he->c = 1;
1638  he->append = 1;
1639  xx = headerPut(h, he, 0);
1640  he->append = 0;
1641 
1642  if (!isSrc && isDoc(fl, flp->fileURL))
1643  flp->flags |= RPMFILE_DOC;
1644  /* XXX Should directories have %doc/%config attributes? (#14531) */
1645  if (S_ISDIR(flp->fl_mode))
1646  flp->flags &= ~(RPMFILE_CONFIG|RPMFILE_DOC);
1647 
1648  ui32 = flp->flags;
1649  he->tag = RPMTAG_FILEFLAGS;
1650  he->t = RPM_UINT32_TYPE;
1651  he->p.ui32p = &ui32;
1652  he->c = 1;
1653  he->append = 1;
1654  xx = headerPut(h, he, 0);
1655  he->append = 0;
1656 
1657  /* Add file security context to package. */
1658  if (sx && sx->fn && *sx->fn && !(_rpmbuildFlags & 4)) {
1659  const char * scon = rpmsxMatch(sx, flp->fileURL, flp->fl_mode);
1660  if (scon) {
1661  he->tag = RPMTAG_FILECONTEXTS;
1662  he->t = RPM_STRING_ARRAY_TYPE;
1663  he->p.argv = &scon;
1664  he->c = 1;
1665  he->append = 1;
1666  xx = headerPut(h, he, 0);
1667  he->append = 0;
1668  }
1669  scon = _free(scon); /* XXX freecon(scon) instead()? */
1670  }
1671  }
1672 
1673  sx = rpmsxFree(sx);
1674 
1675 if (_rpmbuildFlags & 4) {
1676 (void) rpmlibNeedsFeature(h, "PayloadFilesHavePrefix", "4.0-1");
1677 (void) rpmlibNeedsFeature(h, "CompressedFileNames", "3.0.4-1");
1678 }
1679 
1680  compressFilelist(h);
1681 
1682  { static int scareMem = 0;
1683  void * ts = NULL; /* XXX FIXME drill rpmts ts all the way down here */
1684  rpmfi fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem);
1685  char * a, * d;
1686 
1687  if (fi == NULL) return; /* XXX can't happen */
1688 
1689 /*@-onlytrans@*/
1690  fi->te = xcalloc(1, sizeof(*((rpmte)fi->te)));
1691 /*@=onlytrans@*/
1692  ((rpmte)fi->te)->type = TR_ADDED;
1693 
1694  fi->dnl = _free(fi->dnl);
1695  fi->bnl = _free(fi->bnl);
1696  if (!scareMem) fi->dil = _free(fi->dil);
1697 
1698  /* XXX Insure at least 1 byte is always allocated. */
1699  fi->dnl = xmalloc(fi->fc * sizeof(*fi->dnl) + dpathlen + 1);
1700  d = (char *)(fi->dnl + fi->fc);
1701  *d = '\0';
1702 
1703  fi->bnl = xmalloc(fi->fc * (sizeof(*fi->bnl) + sizeof(*fi->dil)));
1704 /*@-dependenttrans@*/ /* FIX: artifact of spoofing header tag store */
1705  fi->dil = (!scareMem)
1706  ? xcalloc(sizeof(*fi->dil), fi->fc)
1707  : (rpmuint32_t *)(fi->bnl + fi->fc);
1708 /*@=dependenttrans@*/
1709 
1710  /* XXX Insure at least 1 byte is always allocated. */
1711  fi->apath = xmalloc(fi->fc * sizeof(*fi->apath) + apathlen + 1);
1712  a = (char *)(fi->apath + fi->fc);
1713  *a = '\0';
1714 
1715  fi->actions = _free(fi->actions); /* XXX memory leak */
1716  fi->actions = xcalloc(sizeof(*fi->actions), fi->fc);
1717  fi->fmapflags = xcalloc(sizeof(*fi->fmapflags), fi->fc);
1718  fi->astriplen = 0;
1719  if (fl->buildRootURL)
1720  fi->astriplen = strlen(fl->buildRootURL);
1721  fi->striplen = 0;
1722  fi->fuser = _free(fi->fuser);
1723  fi->fgroup = _free(fi->fgroup);
1724 
1725  /* Make the cpio list */
1726  if (fi->dil != NULL) /* XXX can't happen */
1727  for (i = 0, flp = fl->fileList; (unsigned)i < fi->fc; i++, flp++) {
1728  char * b;
1729 
1730  /* Skip (possible) duplicate file entries, use last entry info. */
1731  while (((flp - fl->fileList) < (fl->fileListRecsUsed - 1)) &&
1732  !strcmp(flp->fileURL, flp[1].fileURL))
1733  flp++;
1734 
1735  if (flp->flags & RPMFILE_EXCLUDE) {
1736  i--;
1737  continue;
1738  }
1739 
1740  {
1741  /* this fi uses diskURL (with buildroot), not fileURL */
1742  size_t fnlen = strlen(flp->diskURL);
1743  if (fnlen > fi->fnlen) {
1744  /* fnlen-sized buffer must not be allocated yet */
1745  assert(fi->fn == NULL);
1746  fi->fnlen = fnlen;
1747  }
1748  }
1749 
1750  /* Create disk directory and base name. */
1751  fi->dil[i] = i;
1752 /*@-dependenttrans@*/ /* FIX: artifact of spoofing header tag store */
1753  fi->dnl[fi->dil[i]] = d;
1754 /*@=dependenttrans@*/
1755  d = stpcpy(d, flp->diskURL);
1756 
1757  /* Make room for the dirName NUL, find start of baseName. */
1758  for (b = d; b > fi->dnl[fi->dil[i]] && *b != '/'; b--)
1759  b[1] = b[0];
1760  b++; /* dirname's end in '/' */
1761  *b++ = '\0'; /* terminate dirname, b points to basename */
1762  fi->bnl[i] = b;
1763  d += 2; /* skip both dirname and basename NUL's */
1764 
1765  /* Create archive path, normally adding "./" */
1766  /*@-dependenttrans@*/ /* FIX: xstrdup? nah ... */
1767  fi->apath[i] = a;
1768  /*@=dependenttrans@*/
1769  if (_addDotSlash)
1770  a = stpcpy(a, "./");
1771  (void) urlPath(flp->fileURL, &apath);
1772  a = stpcpy(a, (apath + skipLen));
1773  a++; /* skip apath NUL */
1774 
1775  if (flp->flags & RPMFILE_GHOST) {
1776  fi->actions[i] = FA_SKIP;
1777  continue;
1778  }
1779  fi->actions[i] = FA_COPYOUT;
1780  fi->fmapflags[i] = IOSM_MAP_PATH |
1782  if (isSrc)
1783  fi->fmapflags[i] |= IOSM_FOLLOW_SYMLINKS;
1784  }
1785 
1786  ui32 = fl->totalFileSize;
1787  he->tag = RPMTAG_SIZE;
1788  he->t = RPM_UINT32_TYPE;
1789  he->p.ui32p = &ui32;
1790  he->c = 1;
1791  xx = headerPut(h, he, 0);
1792 
1793  /*@-compdef@*/
1794  if (fip)
1795  *fip = fi;
1796  else
1797  fi = rpmfiFree(fi);
1798  /*@=compdef@*/
1799  }
1800 
1801  return rc;
1802 }
1803 
1806 static /*@null@*/ FileListRec freeFileList(/*@only@*/ FileListRec fileList,
1807  int count)
1808  /*@*/
1809 {
1810  while (count--) {
1811  fileList[count].diskURL = _free(fileList[count].diskURL);
1812  fileList[count].fileURL = _free(fileList[count].fileURL);
1813  fileList[count].langs = _free(fileList[count].langs);
1814  }
1815  fileList = _free(fileList);
1816  return NULL;
1817 }
1818 
1819 /* forward ref */
1820 static rpmRC recurseDir(FileList fl, const char * diskURL)
1821  /*@globals rpmGlobalMacroContext, h_errno,
1822  fileSystem, internalState @*/
1823  /*@modifies *fl, fl->processingFailed,
1824  fl->fileList, fl->fileListRecsAlloced, fl->fileListRecsUsed,
1825  fl->totalFileSize, fl->fileCount, fl->inFtw, fl->isDir,
1826  rpmGlobalMacroContext,
1827  fileSystem, internalState @*/;
1828 
1836 static int addFile(FileList fl, const char * diskURL,
1837  /*@null@*/ struct stat * statp)
1838  /*@globals rpmGlobalMacroContext, h_errno,
1839  fileSystem, internalState @*/
1840  /*@modifies *statp, *fl, fl->processingFailed,
1841  fl->fileList, fl->fileListRecsAlloced, fl->fileListRecsUsed,
1842  fl->totalFileSize, fl->fileCount,
1843  rpmGlobalMacroContext,
1844  fileSystem, internalState @*/
1845 {
1846  const char *fn = xstrdup(diskURL);
1847  const char *fileURL = fn;
1848  struct stat statbuf;
1849  mode_t fileMode;
1850  uid_t fileUid;
1851  gid_t fileGid;
1852  const char *fileUname;
1853  const char *fileGname;
1854  char *lang;
1855  rpmRC rc = RPMRC_OK;
1856 
1857  /* Path may have prepended buildRootURL, so locate the original filename. */
1858  /*
1859  * XXX There are 3 types of entry into addFile:
1860  *
1861  * From diskUrl statp
1862  * =====================================================
1863  * processBinaryFile path NULL
1864  * processBinaryFile glob result path NULL
1865  * recurseDir path stat
1866  *
1867  */
1868  { const char *fileName;
1869  int urltype = urlPath(fileURL, &fileName);
1870  switch (urltype) {
1871  case URL_IS_PATH:
1872  fileURL += (fileName - fileURL);
1873  if (fl->buildRootURL && strcmp(fl->buildRootURL, "/")) {
1874  size_t nb = strlen(fl->buildRootURL);
1875  const char * s = fileURL + nb;
1876  char * t = (char *) fileURL;
1877  (void) memmove(t, s, nb);
1878  }
1879  fileURL = fn;
1880  break;
1881  default:
1882  if (fl->buildRootURL && strcmp(fl->buildRootURL, "/"))
1883  fileURL += strlen(fl->buildRootURL);
1884  break;
1885  }
1886  }
1887 
1888  /* XXX make sure '/' can be packaged also */
1889  if (*fileURL == '\0')
1890  fileURL = "/";
1891 
1892  /* If we are using a prefix, validate the file */
1893  if (!fl->inFtw && fl->prefix) {
1894  const char *prefixTest;
1895  const char *prefixPtr = fl->prefix;
1896 
1897  (void) urlPath(fileURL, &prefixTest);
1898  while (*prefixPtr && *prefixTest && (*prefixTest == *prefixPtr)) {
1899  prefixPtr++;
1900  prefixTest++;
1901  }
1902  if (*prefixPtr || (*prefixTest && *prefixTest != '/')) {
1903  rpmlog(RPMLOG_ERR, _("File doesn't match prefix (%s): %s\n"),
1904  fl->prefix, fileURL);
1905  fl->processingFailed = 1;
1906  rc = RPMRC_FAIL;
1907  goto exit;
1908  }
1909  }
1910 
1911  if (statp == NULL) {
1912  statp = &statbuf;
1913  memset(statp, 0, sizeof(*statp));
1914  if (fl->devtype) {
1915  time_t now = time(NULL);
1916 
1917  /* XXX hack up a stat structure for a %dev(...) directive. */
1918  statp->st_nlink = 1;
1919  statp->st_rdev =
1920  ((fl->devmajor & 0xff) << 8) | (fl->devminor & 0xff);
1921  statp->st_dev = statp->st_rdev;
1922  statp->st_mode = (fl->devtype == 'b' ? S_IFBLK : S_IFCHR);
1923  statp->st_mode |= (fl->cur_ar.ar_fmode & 0777);
1924  statp->st_atime = now;
1925  statp->st_mtime = now;
1926  statp->st_ctime = now;
1927  } else if (Lstat(diskURL, statp)) {
1928  if (fl->currentFlags & RPMFILE_OPTIONAL) {
1929  rpmlog(RPMLOG_WARNING, _("Optional file not found: %s\n"), diskURL);
1930  rc = RPMRC_OK;
1931  } else {
1932  rpmlog(RPMLOG_ERR, _("File not found: %s\n"), diskURL);
1933  fl->processingFailed = 1;
1934  rc = RPMRC_FAIL;
1935  }
1936  goto exit;
1937  }
1938  }
1939 
1940  if ((! fl->isDir) && S_ISDIR(statp->st_mode)) {
1941 /*@-nullstate@*/ /* FIX: fl->buildRootURL may be NULL */
1942  rc = recurseDir(fl, diskURL);
1943  goto exit;
1944 /*@=nullstate@*/
1945  }
1946 
1947  fileMode = statp->st_mode;
1948  fileUid = statp->st_uid;
1949  fileGid = statp->st_gid;
1950 
1951  if (S_ISDIR(fileMode) && fl->cur_ar.ar_dmodestr) {
1952  fileMode &= S_IFMT;
1953  fileMode |= fl->cur_ar.ar_dmode;
1954  } else if (fl->cur_ar.ar_fmodestr != NULL) {
1955  fileMode &= S_IFMT;
1956  fileMode |= fl->cur_ar.ar_fmode;
1957  }
1958  if (fl->cur_ar.ar_user) {
1959  fileUname = getUnameS(fl->cur_ar.ar_user);
1960  } else {
1961  fileUname = getUname(fileUid);
1962  }
1963  if (fl->cur_ar.ar_group) {
1964  fileGname = getGnameS(fl->cur_ar.ar_group);
1965  } else {
1966  fileGname = getGname(fileGid);
1967  }
1968 
1969  /* Default user/group to builder's user/group */
1970  if (fileUname == NULL)
1971  fileUname = getUname(getuid());
1972  if (fileGname == NULL)
1973  fileGname = getGname(getgid());
1974 
1975  /* Add to the file list */
1976  if (fl->fileListRecsUsed == fl->fileListRecsAlloced) {
1977  fl->fileListRecsAlloced += 128;
1978  fl->fileList = xrealloc(fl->fileList,
1979  fl->fileListRecsAlloced * sizeof(*(fl->fileList)));
1980  }
1981 
1982  { FileListRec flp = &fl->fileList[fl->fileListRecsUsed];
1983  int i;
1984 
1985  flp->fl_st = *statp; /* structure assignment */
1986  flp->fl_mode = fileMode;
1987  flp->fl_uid = fileUid;
1988  flp->fl_gid = fileGid;
1989 
1990  flp->fileURL = xstrdup(fileURL);
1991  flp->diskURL = xstrdup(diskURL);
1992  flp->uname = fileUname;
1993  flp->gname = fileGname;
1994 
1995  if (fl->currentLangs && fl->nLangs > 0) {
1996  char * ncl;
1997  size_t nl = 0;
1998 
1999  for (i = 0; i < fl->nLangs; i++)
2000  nl += strlen(fl->currentLangs[i]) + 1;
2001 
2002  flp->langs = ncl = xmalloc(nl);
2003  for (i = 0; i < fl->nLangs; i++) {
2004  const char *ocl;
2005  if (i) *ncl++ = '|';
2006  for (ocl = fl->currentLangs[i]; *ocl != '\0'; ocl++)
2007  *ncl++ = *ocl;
2008  *ncl = '\0';
2009  }
2010  } else if (! parseForRegexLang(fileURL, &lang)) {
2011  flp->langs = xstrdup(lang);
2012  } else {
2013  flp->langs = xstrdup("");
2014  }
2015 
2016  flp->flags = fl->currentFlags;
2017  flp->specdFlags = fl->currentSpecdFlags;
2018  flp->verifyFlags = fl->currentVerifyFlags;
2019  }
2020 
2021  fl->fileListRecsUsed++;
2022  fl->fileCount++;
2023 
2024 exit:
2025 /*@i@*/ fn = _free(fn);
2026  return rc;
2027 }
2028 
2035 static rpmRC recurseDir(FileList fl, const char * diskURL)
2036 {
2037  char * ftsSet[2];
2038  FTS * ftsp;
2039  FTSENT * fts;
2040  int myFtsOpts = (FTS_COMFOLLOW | FTS_NOCHDIR | FTS_PHYSICAL);
2041  rpmRC rc = RPMRC_FAIL;
2042 
2043  fl->inFtw = 1; /* Flag to indicate file has buildRootURL prefixed */
2044  fl->isDir = 1; /* Keep it from following myftw() again */
2045 
2046  ftsSet[0] = (char *) diskURL;
2047  ftsSet[1] = NULL;
2048  ftsp = Fts_open(ftsSet, myFtsOpts, NULL);
2049  while ((fts = Fts_read(ftsp)) != NULL) {
2050  switch (fts->fts_info) {
2051  case FTS_D: /* preorder directory */
2052  case FTS_F: /* regular file */
2053  case FTS_SL: /* symbolic link */
2054  case FTS_SLNONE: /* symbolic link without target */
2055  case FTS_DEFAULT: /* none of the above */
2056  rc = addFile(fl, fts->fts_accpath, fts->fts_statp);
2057  /*@switchbreak@*/ break;
2058  case FTS_DOT: /* dot or dot-dot */
2059  case FTS_DP: /* postorder directory */
2060  rc = RPMRC_OK;
2061  /*@switchbreak@*/ break;
2062  case FTS_NS: /* stat(2) failed */
2063  case FTS_DNR: /* unreadable directory */
2064  case FTS_ERR: /* error; errno is set */
2065  case FTS_DC: /* directory that causes cycles */
2066  case FTS_NSOK: /* no stat(2) requested */
2067  case FTS_INIT: /* initialized only */
2068  case FTS_W: /* whiteout object */
2069  default:
2070  rc = RPMRC_FAIL;
2071  /*@switchbreak@*/ break;
2072  }
2073  if (rc != RPMRC_OK)
2074  break;
2075  }
2076  (void) Fts_close(ftsp);
2077 
2078  fl->isDir = 0;
2079  fl->inFtw = 0;
2080 
2081  return rc;
2082 }
2083 
2092 static rpmRC processMetadataFile(Package pkg, FileList fl, const char * fileURL,
2093  rpmTag tag)
2094  /*@globals rpmGlobalMacroContext, h_errno,
2095  fileSystem, internalState @*/
2096  /*@modifies pkg->header, *fl, fl->processingFailed,
2097  fl->fileList, fl->fileListRecsAlloced, fl->fileListRecsUsed,
2098  fl->totalFileSize, fl->fileCount,
2099  rpmGlobalMacroContext,
2100  fileSystem, internalState @*/
2101 {
2102  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
2103  const char * buildURL = "%{_builddir}/%{?buildsubdir}/";
2104  const char * fn = NULL;
2105  const char * apkt = NULL;
2106  rpmiob iob = NULL;
2107  rpmuint8_t * pkt = NULL;
2108  ssize_t pktlen = 0;
2109  int absolute = 0;
2110  rpmRC rc = RPMRC_FAIL;
2111  int xx;
2112 
2113  (void) urlPath(fileURL, &fn);
2114  if (*fn == '/') {
2115  fn = rpmGenPath(fl->buildRootURL, NULL, fn);
2116  absolute = 1;
2117  } else
2118  fn = rpmGenPath(buildURL, NULL, fn);
2119 
2120  switch (tag) {
2121  default:
2122  rpmlog(RPMLOG_ERR, _("%s: can't load unknown tag (%d).\n"),
2123  fn, tag);
2124  goto exit;
2125  /*@notreached@*/ break;
2126  case RPMTAG_PUBKEYS:
2127  if ((xx = pgpReadPkts(fn, &pkt, (size_t *)&pktlen)) <= 0) {
2128  rpmlog(RPMLOG_ERR, _("%s: public key read failed.\n"), fn);
2129  goto exit;
2130  }
2131  if (xx != PGPARMOR_PUBKEY) {
2132  rpmlog(RPMLOG_ERR, _("%s: not an armored public key.\n"), fn);
2133  goto exit;
2134  }
2135  apkt = pgpArmorWrap(PGPARMOR_PUBKEY, pkt, pktlen);
2136  break;
2137  case RPMTAG_POLICIES:
2138  xx = rpmiobSlurp(fn, &iob);
2139  if (!(xx == 0 && iob != NULL)) {
2140  rpmlog(RPMLOG_ERR, _("%s: *.te policy read failed.\n"), fn);
2141  goto exit;
2142  }
2143  apkt = (const char *) iob->b; /* XXX unsigned char */
2144  /* XXX steal the I/O buffer */
2145  iob->b = (rpmuint8_t *)xcalloc(1, sizeof(*iob->b));
2146  iob->blen = 0;
2147  break;
2148  }
2149 
2150  he->tag = tag;
2151  he->t = RPM_STRING_ARRAY_TYPE;
2152  he->p.argv = &apkt;
2153  he->c = 1;
2154  he->append = 1;
2155  xx = headerPut(pkg->header, he, 0);
2156  he->append = 0;
2157 
2158  rc = RPMRC_OK;
2159  if (absolute)
2160  rc = addFile(fl, fn, NULL);
2161 
2162 exit:
2163  apkt = _free(apkt);
2164  pkt = _free(pkt);
2165  iob = rpmiobFree(iob);
2166  fn = _free(fn);
2167  if (rc != RPMRC_OK)
2168  fl->processingFailed = 1;
2169  return rc;
2170 }
2171 
2179 static rpmRC processBinaryFile(/*@unused@*/ Package pkg, FileList fl,
2180  const char * fileURL)
2181  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
2182  /*@modifies *fl, fl->processingFailed,
2183  fl->fileList, fl->fileListRecsAlloced, fl->fileListRecsUsed,
2184  fl->totalFileSize, fl->fileCount,
2185  rpmGlobalMacroContext, fileSystem, internalState @*/
2186 {
2187  int quote = 1; /* XXX permit quoted glob characters. */
2188  int doGlob;
2189  const char *diskURL = NULL;
2190  rpmRC rc = RPMRC_OK;
2191  int xx;
2192 
2193  doGlob = Glob_pattern_p(fileURL, quote);
2194 
2195  /* Check that file starts with leading "/" */
2196  { const char * fileName;
2197  (void) urlPath(fileURL, &fileName);
2198  if (*fileName != '/') {
2199  rpmlog(RPMLOG_ERR, _("File needs leading \"/\": %s\n"),
2200  fileName);
2201  rc = RPMRC_FAIL;
2202  goto exit;
2203  }
2204  }
2205 
2206  /* Copy file name or glob pattern removing multiple "/" chars. */
2207  /*
2208  * Note: rpmGetPath should guarantee a "canonical" path. That means
2209  * that the following pathologies should be weeded out:
2210  * //bin//sh
2211  * //usr//bin/
2212  * /.././../usr/../bin//./sh
2213  */
2214  diskURL = rpmGenPath(fl->buildRootURL, NULL, fileURL);
2215 
2216  if (doGlob) {
2217  const char ** argv = NULL;
2218  int argc = 0;
2219  int i;
2220 
2221  /* XXX for %dev marker in file manifest only */
2222  if (fl->noGlob) {
2223  rpmlog(RPMLOG_ERR, _("Glob not permitted: %s\n"),
2224  diskURL);
2225  rc = RPMRC_FAIL;
2226  goto exit;
2227  }
2228 
2229  xx = rpmGlob(diskURL, &argc, &argv);
2230  if (xx == 0 && argc >= 1) {
2231  for (i = 0; i < argc; i++) {
2232  rc = addFile(fl, argv[i], NULL);
2233  argv[i] = _free(argv[i]);
2234  }
2235  argv = _free(argv);
2236  } else {
2237  if (fl->currentFlags & RPMFILE_OPTIONAL) {
2238  rpmlog(RPMLOG_WARNING, _("Optional file not found by glob: %s\n"),
2239  diskURL);
2240  rc = RPMRC_OK;
2241  } else {
2242  rpmlog(RPMLOG_ERR, _("File not found by glob: %s\n"),
2243  diskURL);
2244  rc = RPMRC_FAIL;
2245  }
2246  goto exit;
2247  }
2248  } else
2249  rc = addFile(fl, diskURL, NULL);
2250 
2251 exit:
2252  diskURL = _free(diskURL);
2253  if (rc != RPMRC_OK)
2254  fl->processingFailed = 1;
2255  return rc;
2256 }
2257 
2261  int installSpecialDoc, int test)
2262  /*@globals rpmGlobalMacroContext, h_errno,
2263  fileSystem, internalState@*/
2264  /*@modifies spec->macros,
2265  pkg->fi, pkg->fileList, pkg->specialDoc, pkg->header,
2266  rpmGlobalMacroContext, fileSystem, internalState @*/
2267 {
2268  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
2269  struct FileList_s fl;
2270  ARGV_t files = NULL;
2271  ARGV_t fp;
2272  const char *fileName;
2273  char buf[BUFSIZ];
2274  struct AttrRec_s arbuf;
2275  AttrRec specialDocAttrRec = &arbuf;
2276  char *specialDoc = NULL;
2277  int xx;
2278 
2279  nullAttrRec(specialDocAttrRec);
2280  pkg->fi = NULL;
2281 
2282  if (pkg->fileFile) {
2283  char *saveptr = NULL;
2284  char *filesFiles = xstrdup(pkg->fileFile);
2285 /*@-unrecog@*/
2286  char *token = strtok_r(filesFiles, ",", &saveptr);
2287 /*@=unrecog@*/
2288  do {
2289  const char *ffn;
2290  FILE * f;
2291  FD_t fd;
2292 
2293  /* XXX W2DO? urlPath might be useful here. */
2294  if (*token == '/') {
2295  ffn = rpmGetPath(token, NULL);
2296  } else {
2297  /* XXX FIXME: add %{buildsubdir} */
2298  ffn = rpmGetPath("%{_builddir}/",
2299  (spec->buildSubdir ? spec->buildSubdir : "") ,
2300  "/", token, NULL);
2301  }
2302 
2303  fd = Fopen(ffn, "r.fpio");
2304 
2305  if (fd == NULL || Ferror(fd)) {
2307  _("Could not open %%files file %s: %s\n"),
2308  ffn, Fstrerror(fd));
2309  return RPMRC_FAIL;
2310  }
2311  ffn = _free(ffn);
2312 
2313  /*@+voidabstract@*/ f = fdGetFp(fd); /*@=voidabstract@*/
2314  if (f != NULL) {
2315  while (fgets(buf, (int)sizeof(buf), f)) {
2316  handleComments(buf);
2317  if (expandMacros(spec, spec->macros, buf, sizeof(buf))) {
2318  rpmlog(RPMLOG_ERR, _("line: %s\n"), buf);
2319  return RPMRC_FAIL;
2320  }
2321  pkg->fileList = rpmiobAppend(pkg->fileList, buf, 0);
2322  }
2323  }
2324  (void) Fclose(fd);
2325  } while((token = strtok_r(NULL, ",", &saveptr)) != NULL);
2326  filesFiles = _free(filesFiles);
2327  }
2328 
2329  /* Init the file list structure */
2330  memset(&fl, 0, sizeof(fl));
2331 
2332  fl.buildRootURL = rpmGenPath(spec->rootURL, "%{?buildroot}", NULL);
2333 
2334  he->tag = RPMTAG_DEFAULTPREFIX;
2335  xx = headerGet(pkg->header, he, 0);
2336  fl.prefix = he->p.str;
2337 
2338  fl.fileCount = 0;
2339  fl.totalFileSize = 0;
2340  fl.processingFailed = 0;
2341 
2342  fl.passedSpecialDoc = 0;
2343  fl.isSpecialDoc = 0;
2344 
2345  fl.isDir = 0;
2346  fl.inFtw = 0;
2347  fl.currentFlags = 0;
2348  fl.currentVerifyFlags = 0;
2349 
2350  fl.noGlob = 0;
2351  fl.devtype = 0;
2352  fl.devmajor = 0;
2353  fl.devminor = 0;
2354 
2355  nullAttrRec(&fl.cur_ar);
2356  nullAttrRec(&fl.def_ar);
2357  dupAttrRec(&root_ar, &fl.def_ar); /* XXX assume %defattr(-,root,root) */
2358 
2360  fl.nLangs = 0;
2361  fl.currentLangs = NULL;
2362 
2363  fl.currentSpecdFlags = 0;
2364  fl.defSpecdFlags = 0;
2365 
2366  fl.docDirCount = 0;
2367 #if defined(RPM_VENDOR_OPENPKG) /* no-default-doc-files */
2368  /* do not declare any files as %doc files by default. */
2369 #else
2370  fl.docDirs[fl.docDirCount++] = xstrdup("/usr/doc");
2371  fl.docDirs[fl.docDirCount++] = xstrdup("/usr/man");
2372  fl.docDirs[fl.docDirCount++] = xstrdup("/usr/info");
2373  fl.docDirs[fl.docDirCount++] = xstrdup("/usr/X11R6/man");
2374  fl.docDirs[fl.docDirCount++] = xstrdup("/usr/share/doc");
2375  fl.docDirs[fl.docDirCount++] = xstrdup("/usr/share/man");
2376  fl.docDirs[fl.docDirCount++] = xstrdup("/usr/share/info");
2377  fl.docDirs[fl.docDirCount++] = xstrdup("/usr/src/examples");
2378  fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_docdir}", NULL);
2379  fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_mandir}", NULL);
2380  fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_infodir}", NULL);
2381  fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_javadocdir}", NULL);
2382  fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_examplesdir}", NULL);
2383 #endif
2384 
2385  fl.fileList = NULL;
2386  fl.fileListRecsAlloced = 0;
2387  fl.fileListRecsUsed = 0;
2388 
2389  xx = argvSplit(&files, rpmiobStr(pkg->fileList), "\n");
2390 
2391  for (fp = files; *fp != NULL; fp++) {
2392  const char * s;
2393  s = *fp;
2394  SKIPSPACE(s);
2395  if (*s == '\0')
2396  continue;
2397  fileName = NULL;
2398  /*@-nullpass@*/ /* LCL: buf is NULL ?!? */
2399  strncpy(buf, s, sizeof(buf)-1);
2400  buf[sizeof(buf)-1] = '\0';
2401  /*@=nullpass@*/
2402 
2403  /* Reset for a new line in %files */
2404  fl.isDir = 0;
2405  fl.inFtw = 0;
2406  fl.currentFlags = 0;
2407  /* turn explicit flags into %def'd ones (gosh this is hacky...) */
2408  fl.currentSpecdFlags = ((unsigned)fl.defSpecdFlags) >> 8;
2410  fl.isSpecialDoc = 0;
2411 
2412  fl.noGlob = 0;
2413  fl.devtype = 0;
2414  fl.devmajor = 0;
2415  fl.devminor = 0;
2416 
2417  /* XXX should reset to %deflang value */
2418  if (fl.currentLangs) {
2419  int i;
2420  for (i = 0; i < fl.nLangs; i++)
2421  /*@-unqualifiedtrans@*/
2422  fl.currentLangs[i] = _free(fl.currentLangs[i]);
2423  /*@=unqualifiedtrans@*/
2424  fl.currentLangs = _free(fl.currentLangs);
2425  }
2426  fl.nLangs = 0;
2427 
2428  dupAttrRec(&fl.def_ar, &fl.cur_ar);
2429 
2430  /*@-nullpass@*/ /* LCL: buf is NULL ?!? */
2431  if (parseForVerify(buf, &fl) != RPMRC_OK)
2432  continue;
2433  if (parseForAttr(buf, &fl) != RPMRC_OK)
2434  continue;
2435  if (parseForDev(buf, &fl) != RPMRC_OK)
2436  continue;
2437  if (parseForConfig(buf, &fl) != RPMRC_OK)
2438  continue;
2439  if (parseForLang(buf, &fl) != RPMRC_OK)
2440  continue;
2441  /*@-nullstate@*/ /* FIX: pkg->fileFile might be NULL */
2442  if (parseForSimple(spec, pkg, buf, &fl, &fileName) != RPMRC_OK)
2443  /*@=nullstate@*/
2444  continue;
2445  /*@=nullpass@*/
2446  if (fileName == NULL)
2447  continue;
2448 
2449  if (fl.isSpecialDoc) {
2450  /* Save this stuff for last */
2451  specialDoc = _free(specialDoc);
2452  specialDoc = xstrdup(fileName);
2453  dupAttrRec(&fl.cur_ar, specialDocAttrRec);
2454  } else if (fl.currentFlags & RPMFILE_PUBKEY) {
2455 /*@-nullstate@*/ /* FIX: pkg->fileFile might be NULL */
2456  (void) processMetadataFile(pkg, &fl, fileName, RPMTAG_PUBKEYS);
2457 /*@=nullstate@*/
2458  } else if (fl.currentFlags & RPMFILE_POLICY) {
2459 /*@-nullstate@*/ /* FIX: pkg->fileFile might be NULL */
2460  (void) processMetadataFile(pkg, &fl, fileName, RPMTAG_POLICIES);
2461 /*@=nullstate@*/
2462  } else {
2463 /*@-nullstate@*/ /* FIX: pkg->fileFile might be NULL */
2464  (void) processBinaryFile(pkg, &fl, fileName);
2465 /*@=nullstate@*/
2466  }
2467  }
2468 
2469  /* Now process special doc, if there is one */
2470  if (specialDoc) {
2471  if (installSpecialDoc) {
2472  int _missing_doc_files_terminate_build =
2473  rpmExpandNumeric("%{?_missing_doc_files_terminate_build}");
2474  rpmRC rc;
2475 
2476  rc = doScript(spec, RPMBUILD_STRINGBUF, "%doc", pkg->specialDoc, test);
2477  if (rc != RPMRC_OK && _missing_doc_files_terminate_build)
2478  fl.processingFailed = 1;
2479  }
2480 
2481  /* Reset for %doc */
2482  fl.isDir = 0;
2483  fl.inFtw = 0;
2484  fl.currentFlags = 0;
2486 
2487  fl.noGlob = 0;
2488  fl.devtype = 0;
2489  fl.devmajor = 0;
2490  fl.devminor = 0;
2491 
2492  /* XXX should reset to %deflang value */
2493  if (fl.currentLangs) {
2494  int i;
2495  for (i = 0; i < fl.nLangs; i++)
2496  /*@-unqualifiedtrans@*/
2497  fl.currentLangs[i] = _free(fl.currentLangs[i]);
2498  /*@=unqualifiedtrans@*/
2499  fl.currentLangs = _free(fl.currentLangs);
2500  }
2501  fl.nLangs = 0;
2502 
2503  dupAttrRec(specialDocAttrRec, &fl.cur_ar);
2504  freeAttrRec(specialDocAttrRec);
2505 
2506  /*@-nullstate@*/ /* FIX: pkg->fileFile might be NULL */
2507  (void) processBinaryFile(pkg, &fl, specialDoc);
2508  /*@=nullstate@*/
2509 
2510  specialDoc = _free(specialDoc);
2511  }
2512 
2513  files = argvFree(files);
2514 
2515 /* if (fl.processingFailed)
2516  goto exit;*/
2517 
2518  /* Verify that file attributes scope over hardlinks correctly. */
2519  if (checkHardLinks(&fl))
2520  (void) rpmlibNeedsFeature(pkg->header,
2521  "PartialHardlinkSets", "4.0.4-1");
2522 
2523  /* XXX should tags be added if filelist is empty? */
2524  if (genCpioListAndHeader(&fl, &pkg->fi, pkg->header, 0) != RPMRC_OK)
2525  fl.processingFailed = 1;
2526 
2527  if (spec->timeCheck)
2528  timeCheck(spec->timeCheck, pkg->header);
2529 
2530 exit:
2531  fl.buildRootURL = _free(fl.buildRootURL);
2532  fl.prefix = _free(fl.prefix);
2533 
2534  freeAttrRec(&fl.cur_ar);
2535  freeAttrRec(&fl.def_ar);
2536 
2537  if (fl.currentLangs) {
2538  int i;
2539  for (i = 0; i < fl.nLangs; i++)
2540  /*@-unqualifiedtrans@*/
2541  fl.currentLangs[i] = _free(fl.currentLangs[i]);
2542  /*@=unqualifiedtrans@*/
2543  fl.currentLangs = _free(fl.currentLangs);
2544  }
2545 
2547  while (fl.docDirCount--)
2548  fl.docDirs[fl.docDirCount] = _free(fl.docDirs[fl.docDirCount]);
2549  return (fl.processingFailed ? RPMRC_FAIL : RPMRC_OK);
2550 }
2551 
2553 {
2554  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
2555  HeaderIterator hi;
2556  rpmiob sourceFiles;
2557  struct Source *srcPtr;
2558  static rpmTag classTag = 0xffffffff;
2559  int xx;
2560  size_t i;
2561 
2562  if (classTag == 0xffffffff)
2563  classTag = tagValue("Class");
2564 
2565  /* Only specific tags are added to the source package header */
2566  if (spec->packages && !spec->sourceHdrInit) {
2567  for (hi = headerInit(spec->packages->header);
2568  headerNext(hi, he, 0);
2569  he->p.ptr = _free(he->p.ptr))
2570  {
2571  switch (he->tag) {
2572  case RPMTAG_NAME:
2573  case RPMTAG_VERSION:
2574  case RPMTAG_RELEASE:
2575  case RPMTAG_DISTEPOCH:
2576  case RPMTAG_EPOCH:
2577  case RPMTAG_SUMMARY:
2578  case RPMTAG_DESCRIPTION:
2579  case RPMTAG_PACKAGER:
2580  case RPMTAG_DISTRIBUTION:
2581  case RPMTAG_DISTURL:
2582  case RPMTAG_VENDOR:
2583  case RPMTAG_LICENSE:
2584  case RPMTAG_GROUP:
2585  case RPMTAG_OS:
2586  case RPMTAG_ARCH:
2587  case RPMTAG_CHANGELOGTIME:
2588  case RPMTAG_CHANGELOGNAME:
2589  case RPMTAG_CHANGELOGTEXT:
2590  case RPMTAG_URL:
2591  case RPMTAG_BUGURL:
2592  case RPMTAG_ICON:
2593  case RPMTAG_GIF:
2594  case RPMTAG_XPM:
2595  case HEADER_I18NTABLE:
2596 #if defined(RPM_VENDOR_OPENPKG) /* propagate-provides-to-srpms */
2597  /* make sure the "Provides" headers are available for querying from the .src.rpm files. */
2598  case RPMTAG_PROVIDENAME:
2599  case RPMTAG_PROVIDEVERSION:
2600  case RPMTAG_PROVIDEFLAGS:
2601 #endif
2602  if (he->p.ptr)
2603  xx = headerPut(spec->sourceHeader, he, 0);
2604  /*@switchbreak@*/ break;
2605  default:
2606  if (classTag == he->tag && he->p.ptr != NULL)
2607  xx = headerPut(spec->sourceHeader, he, 0);
2608  /*@switchbreak@*/ break;
2609  }
2610  }
2611  hi = headerFini(hi);
2612 
2613  if (spec->BANames && spec->BACount > 0) {
2614  he->tag = RPMTAG_BUILDARCHS;
2615  he->t = RPM_STRING_ARRAY_TYPE;
2616  he->p.argv = spec->BANames;
2617  he->c = spec->BACount;
2618  xx = headerPut(spec->sourceHeader, he, 0);
2619  }
2620 
2621  /* Load arbitrary tags into srpm header. */
2622  if (spec->foo)
2623  for (i = 0; i < spec->nfoo; i++) {
2624  const char * str = spec->foo[i].str;
2625  rpmTag tag = spec->foo[i].tag;
2626  rpmiob iob = spec->foo[i].iob;
2627  char * s;
2628 
2629  if (str == NULL || iob == NULL)
2630  continue;
2631 
2632  /* XXX Special case %track interpreter for now. */
2633  if (!xstrcasecmp(str, "track")) {
2634  he->p.str = rpmExpand("%{?__vcheck}", NULL);
2635  if (!(he->p.str != NULL && he->p.str[0] != '\0')) {
2636  he->p.str = _free(he->p.str);
2637  continue;
2638  }
2639  he->tag = tagValue("Trackprog");
2640  he->t = RPM_STRING_TYPE;
2641  he->c = 1;
2642  xx = headerPut(spec->sourceHeader, he, 0);
2643  he->p.str = _free(he->p.str);
2644  }
2645 
2646  s = rpmiobStr(iob);
2647  he->tag = tag;
2648  he->append = headerIsEntry(spec->sourceHeader, tag);
2649  if (he->append) {
2650  he->t = RPM_STRING_ARRAY_TYPE;
2651  he->p.argv = (const char **) &s;
2652  he->c = 1;
2653  } else {
2654  he->t = RPM_STRING_TYPE;
2655  he->p.str = s;
2656  he->c = 1;
2657  }
2658  xx = headerPut(spec->sourceHeader, he, 0);
2659  he->append = 0;
2660  }
2661  }
2662 
2663  if (sfp != NULL && *sfp != NULL)
2664  sourceFiles = *sfp;
2665  else
2666  sourceFiles = rpmiobNew(0);
2667 
2668  /* Construct the source/patch tag entries */
2669  if (spec->specFile != NULL) /* XXX segfault avoidance */
2670  sourceFiles = rpmiobAppend(sourceFiles, spec->specFile, 1);
2671  if (spec->sourceHeader != NULL)
2672  for (srcPtr = spec->sources; srcPtr != NULL; srcPtr = srcPtr->next) {
2673  { const char * sfn;
2674 /*@-nullpass@*/ /* XXX getSourceDir returns NULL with bad flags. */
2675  sfn = rpmGetPath( ((srcPtr->flags & RPMFILE_GHOST) ? "!" : ""),
2676 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
2677  getSourceDir(srcPtr->flags, srcPtr->source), srcPtr->source, NULL);
2678 #else
2679  getSourceDir(srcPtr->flags), srcPtr->source, NULL);
2680 #endif
2681 /*@=nullpass@*/
2682  sourceFiles = rpmiobAppend(sourceFiles, sfn, 1);
2683  sfn = _free(sfn);
2684  }
2685 
2686  if (spec->sourceHdrInit)
2687  continue;
2688 
2689  if (srcPtr->flags & RPMFILE_SOURCE) {
2690  he->tag = RPMTAG_SOURCE;
2691  he->t = RPM_STRING_ARRAY_TYPE;
2692  he->p.argv = &srcPtr->source;
2693  he->c = 1;
2694  he->append = 1;
2695  xx = headerPut(spec->sourceHeader, he, 0);
2696  he->append = 0;
2697  if (srcPtr->flags & RPMFILE_GHOST) {
2698  he->tag = RPMTAG_NOSOURCE;
2699  he->t = RPM_UINT32_TYPE;
2700  he->p.ui32p = &srcPtr->num;
2701  he->c = 1;
2702  he->append = 1;
2703  xx = headerPut(spec->sourceHeader, he, 0);
2704  he->append = 0;
2705  }
2706  }
2707  if (srcPtr->flags & RPMFILE_PATCH) {
2708  he->tag = RPMTAG_PATCH;
2709  he->t = RPM_STRING_ARRAY_TYPE;
2710  he->p.argv = &srcPtr->source;
2711  he->c = 1;
2712  he->append = 1;
2713  xx = headerPut(spec->sourceHeader, he, 0);
2714  he->append = 0;
2715  if (srcPtr->flags & RPMFILE_GHOST) {
2716  he->tag = RPMTAG_NOPATCH;
2717  he->t = RPM_UINT32_TYPE;
2718  he->p.ui32p = &srcPtr->num;
2719  he->c = 1;
2720  he->append = 1;
2721  xx = headerPut(spec->sourceHeader, he, 0);
2722  he->append = 0;
2723  }
2724  }
2725  }
2726 
2727  if (sfp == NULL)
2728  sourceFiles = rpmiobFree(sourceFiles);
2729 
2730  spec->sourceHdrInit = 1;
2731 
2732 /*@-usereleased@*/
2733  return 0;
2734 /*@=usereleased@*/
2735 }
2736 
2738 {
2739  rpmiob sourceFiles, *sfp = &sourceFiles;
2740  int x, isSpec = 1;
2741  struct FileList_s fl;
2742  ARGV_t files = NULL;
2743  ARGV_t fp;
2744  int rc;
2745  /* srcdefattr: needed variables */
2746  char _srcdefattr_buf[BUFSIZ];
2747  char * _srcdefattr = rpmExpand("%{?_srcdefattr}", NULL);
2748  int xx;
2749 
2750  *sfp = rpmiobNew(0);
2751  x = initSourceHeader(spec, sfp);
2752 
2753  /* srcdefattr: initialize file list structure */
2754  memset(&fl, 0, sizeof(fl));
2755  if (_srcdefattr && *_srcdefattr) {
2756  xx = snprintf(_srcdefattr_buf, sizeof(_srcdefattr_buf), "%%defattr %s", _srcdefattr);
2757  _srcdefattr_buf[sizeof(_srcdefattr_buf)-1] = '\0';
2758  xx = parseForAttr(_srcdefattr_buf, &fl);
2759  }
2760 
2761  /* Construct the SRPM file list. */
2762  fl.fileList = xcalloc((spec->numSources + 1), sizeof(*fl.fileList));
2763  rc = fl.processingFailed = 0;
2764  fl.fileListRecsUsed = 0;
2765  fl.totalFileSize = 0;
2766  fl.prefix = NULL;
2767  fl.buildRootURL = NULL;
2768 
2769  xx = argvSplit(&files, rpmiobStr(*sfp), "\n");
2770 
2771  /* The first source file is the spec file */
2772  x = 0;
2773  for (fp = files; *fp != NULL; fp++) {
2774  const char * diskURL, *diskPath;
2775  FileListRec flp;
2776 
2777  diskURL = *fp;
2778  SKIPSPACE(diskURL);
2779  if (! *diskURL)
2780  continue;
2781 
2782  flp = &fl.fileList[x];
2783 
2784  flp->flags = isSpec ? RPMFILE_SPECFILE : 0;
2785  /* files with leading ! are no source files */
2786  if (*diskURL == '!') {
2787  flp->flags |= RPMFILE_GHOST;
2788  diskURL++;
2789  }
2790 
2791  (void) urlPath(diskURL, &diskPath);
2792 
2793  flp->diskURL = xstrdup(diskURL);
2794  diskPath = strrchr(diskPath, '/');
2795  if (diskPath)
2796  diskPath++;
2797  else
2798  diskPath = diskURL;
2799 
2800  flp->fileURL = xstrdup(diskPath);
2801  flp->verifyFlags = RPMVERIFY_ALL;
2802 
2803  if (Stat(diskURL, &flp->fl_st)) {
2804  rpmlog(RPMLOG_ERR, _("Bad file: %s: %s\n"),
2805  diskURL, strerror(errno));
2806  rc = fl.processingFailed = 1;
2807  }
2808 
2809 #if defined(RPM_VENDOR_OPENPKG) || defined(RPM_VENDOR_MANDRIVA) /* support-srcdefattr */
2810  /* srcdefattr: allow to set SRPM file attributes via %{_srcdefattr} macro */
2811  if (fl.def_ar.ar_fmodestr) {
2812  flp->fl_mode &= S_IFMT;
2813  flp->fl_mode |= fl.def_ar.ar_fmode;
2814  }
2815  flp->uname = fl.def_ar.ar_user ? getUnameS(fl.def_ar.ar_user) : getUname(flp->fl_uid);
2816  flp->gname = fl.def_ar.ar_group ? getGnameS(fl.def_ar.ar_group) : getGname(flp->fl_gid);
2817 #else
2818  flp->uname = getUname(flp->fl_uid);
2819  flp->gname = getGname(flp->fl_gid);
2820 #endif
2821  flp->langs = xstrdup("");
2822 
2823  if (! (flp->uname && flp->gname)) {
2824  rpmlog(RPMLOG_ERR, _("Bad owner/group: %s\n"), diskURL);
2825  rc = fl.processingFailed = 1;
2826  }
2827 
2828  isSpec = 0;
2829  x++;
2830  }
2831  fl.fileListRecsUsed = x;
2832  files = argvFree(files);
2833 
2834  if (rc)
2835  goto exit;
2836 
2837  /* XXX should tags be added if filelist is empty? */
2838  spec->fi = NULL;
2839  rc = genCpioListAndHeader(&fl, &spec->fi, spec->sourceHeader, 1);
2840 
2841 exit:
2842  *sfp = rpmiobFree(*sfp);
2844  _srcdefattr = _free(_srcdefattr);
2845  return rc;
2846 }
2847 
2853 static int checkUnpackagedFiles(Spec spec)
2854  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
2855  /*@modifies *spec->packages,
2856  rpmGlobalMacroContext, fileSystem, internalState @*/
2857 {
2858 /*@-readonlytrans@*/
2859  static const char * av_ckfile[] = { "%{?__check_files}", NULL };
2860 /*@=readonlytrans@*/
2861  rpmiob iob_stdout = NULL;
2862  const char * s;
2863  int rc;
2864  rpmiob fileList = NULL;
2865  Package pkg;
2866  int n = 0;
2867 
2868  s = rpmExpand(av_ckfile[0], NULL);
2869  if (!(s && *s)) {
2870  rc = -1;
2871  goto exit;
2872  }
2873  rc = 0;
2874 
2875  /* initialize fileList */
2876  fileList = rpmiobNew(0);
2877  for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
2878  int i;
2879 #ifndef DYING /* XXX rpmfiNew is necessary here. why?!? */
2880  rpmfi fi = rpmfiNew(NULL, pkg->header, RPMTAG_BASENAMES, 0);
2881 #else
2882  rpmfi fi = rpmfiLink(pkg->fi, __FUNCTION__);
2883 #endif
2884  fi = rpmfiInit(fi, 0);
2885  while ((i = rpmfiNext(fi)) >= 0) {
2886  const char *fn = rpmfiFN(fi);
2887  fileList = rpmiobAppend(fileList, fn, 1);
2888  n++;
2889  }
2890  fi = rpmfiFree(fi);
2891  }
2892 
2893  if (n == 0) {
2894  /* no packaged files, and buildroot may not exist -
2895  * no need to run check */
2896  rc = -1;
2897  goto exit;
2898  }
2899 
2900  rpmlog(RPMLOG_NOTICE, _("Checking for unpackaged file(s): %s\n"), s);
2901 
2902  rc = rpmfcExec(av_ckfile, fileList, &iob_stdout, 0);
2903  if (rc < 0)
2904  goto exit;
2905 
2906  if (iob_stdout) {
2907  int _unpackaged_files_terminate_build =
2908  rpmExpandNumeric("%{?_unpackaged_files_terminate_build}");
2909  const char * t;
2910 
2911  t = rpmiobStr(iob_stdout);
2912  if ((*t != '\0') && (*t != '\n')) {
2913  rc = (_unpackaged_files_terminate_build) ? 1 : 0;
2914  rpmlog((rc ? RPMLOG_ERR : RPMLOG_WARNING),
2915  _("Installed (but unpackaged) file(s) found:\n%s"), t);
2916  }
2917  }
2918 
2919 exit:
2920  fileList = rpmiobFree(fileList);
2921  iob_stdout = rpmiobFree(iob_stdout);
2922  s = _free(s);
2923  return rc;
2924 }
2925 
2926 /* auxiliary function for checkDuplicateFiles() */
2927 /* XXX need to pass Header because fi->h is NULL */
2928 static int fiIntersect(/*@null@*/ rpmfi fi1, /*@null@*/ rpmfi fi2,
2929  size_t buildrootL, int _duplicate_files_terminate_build)
2930  /*@globals internalState @*/
2931  /*@modifies fi1, fi2, internalState @*/
2932 {
2933  int n = 0;
2934  int i1, i2;
2935  const char *fn1, *fn2;
2936  rpmiob dups = NULL;
2937 
2938  if ((fi1 = rpmfiInit(fi1, 0)) != NULL)
2939  while ((i1 = rpmfiNext(fi1)) >= 0) {
2940  if (S_ISDIR(rpmfiFMode(fi1)))
2941  continue;
2942  fn1 = rpmfiFN(fi1);
2943  if ((fi2 = rpmfiInit(fi2, 0)) != NULL)
2944  while ((i2 = rpmfiNext(fi2)) >= 0) {
2945  if (S_ISDIR(rpmfiFMode(fi2)))
2946  /*@innercontinue@*/ continue;
2947  fn2 = rpmfiFN(fi2);
2948  if (strcmp(fn1, fn2))
2949  /*@innercontinue@*/ continue;
2950  if (!dups)
2951  dups = rpmiobNew(0);
2952  dups = rpmiobAppend(dups, "\t", 0);
2953  dups = rpmiobAppend(dups, fn1+buildrootL, 1);
2954  n++;
2955  }
2956  }
2957 
2958  if (n > 0) {
2959  const char *N1, *N2;
2960  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
2961 
2962  he->tag = RPMTAG_NVRA;
2963  N1 = (headerGet(fi1->h, he, 0) ? he->p.str : NULL);
2964  he->tag = RPMTAG_NVRA;
2965  N2 = (headerGet(fi2->h, he, 0) ? he->p.str : NULL);
2966 
2967  rpmlog(_duplicate_files_terminate_build ? RPMLOG_ERR : RPMLOG_WARNING,
2968  _("File(s) packaged into both %s and %s:\n%s"),
2969  N1, N2, rpmiobStr(dups));
2970 
2971  N1 = _free(N1);
2972  N2 = _free(N2);
2973  dups = rpmiobFree(dups);
2974  }
2975 
2976  return n;
2977 }
2978 
2984 static int checkDuplicateFiles(Spec spec, size_t buildrootL,
2985  int _duplicate_files_terminate_build)
2986  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
2987  /*@modifies *spec->packages,
2988  rpmGlobalMacroContext, fileSystem, internalState @*/
2989 {
2990  int n = 0;
2991  Package pkg1, pkg2;
2992 
2993  if (spec->packages) /* XXX segfault avoidance */
2994  for (pkg1 = spec->packages; pkg1->next; pkg1 = pkg1->next) {
2995 #ifdef DYING
2996  rpmfi fi1 = rpmfiNew(NULL, pkg1->header, RPMTAG_BASENAMES, 0);
2997 #else
2998  rpmfi fi1 = rpmfiLink(pkg1->fi, __FUNCTION__);
2999 #endif
3000  if (fi1 == NULL) continue;
3001  (void) rpmfiSetHeader(fi1, pkg1->header);
3002  for (pkg2 = pkg1->next; pkg2; pkg2 = pkg2->next) {
3003 #ifdef DYING
3004  rpmfi fi2 = rpmfiNew(NULL, pkg2->header, RPMTAG_BASENAMES, 0);
3005 #else
3006  rpmfi fi2 = rpmfiLink(pkg2->fi, __FUNCTION__);
3007 #endif
3008  if (fi2 == NULL) continue;
3009  (void) rpmfiSetHeader(fi2, pkg2->header);
3010  n += fiIntersect(fi1, fi2, buildrootL, _duplicate_files_terminate_build);
3011  (void) rpmfiSetHeader(fi2, NULL);
3012  fi2 = rpmfiFree(fi2);
3013  }
3014  (void) rpmfiSetHeader(fi1, NULL);
3015  fi1 = rpmfiFree(fi1);
3016  }
3017  return n;
3018 }
3019 
3020 /* auxiliary function: check if directory d is packaged */
3021 static inline int packagedDir(Package pkg, const char *d)
3022  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
3023  /*@modifies pkg->header,
3024  rpmGlobalMacroContext, fileSystem, internalState @*/
3025 {
3026  return rpmbfChk(rpmfiFNBF(pkg->fi), d, strlen(d));
3027 }
3028 
3029 /* auxiliary function: find unpackaged subdirectories
3030  *
3031  * E.g. consider this %files section:
3032  * %dir /A
3033  * /A/B/C/D
3034  * Now directories "/A/B" and "/A/B/C" should also be packaged.
3035  */
3036 static int pkgUnpackagedSubdirs(Package pkg, size_t buildrootL, int _unpackaged_subdirs_terminate_build)
3037  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
3038  /*@modifies pkg->header,
3039  rpmGlobalMacroContext, fileSystem, internalState @*/
3040 {
3041  int n = 0;
3042  int i, j;
3043  char **unpackaged = NULL;
3044  char *fn;
3045 #ifdef DYING
3046  rpmfi fi = rpmfiNew(NULL, pkg->header, RPMTAG_BASENAMES, 0);
3047 #else
3048  rpmfi fi = rpmfiLink(pkg->fi, __FUNCTION__);
3049 #endif
3050 
3051  if (rpmfiFC(fi) <= 1) {
3052  fi = rpmfiFree(fi);
3053  return 0;
3054  }
3055  fn = alloca(rpmfiFNMaxLen(fi) + 1);
3056 
3057  fi = rpmfiInit(fi, 0);
3058  while ((i = rpmfiNext(fi)) >= 0) {
3059  int found = 0;
3060  /* make local copy of file name */
3061  char *p = fn;
3062  strcpy(fn, rpmfiFN(fi));
3063  /* find the first path component that is packaged */
3064  while ((p = strchr(p + 1, '/'))) {
3065  *p = '\0';
3066  found = packagedDir(pkg, fn);
3067  *p = '/';
3068  if (found)
3069  /*@innerbreak@*/ break;
3070  }
3071  if (!found)
3072  continue;
3073  /* other path components should be packaged, too */
3074  if (p != NULL)
3075  while ((p = strchr(p + 1, '/'))) {
3076  *p = '\0';
3077  if (packagedDir(pkg, fn)) {
3078  *p = '/';
3079  /*@innercontinue@*/ continue;
3080  }
3081  /* might be already added */
3082  found = 0;
3083  for (j = 0; j < n; j++)
3084  if (strcmp(fn, unpackaged[j]) == 0) {
3085  found = 1;
3086  /*@innerbreak@*/ break;
3087  }
3088  if (found) {
3089  *p = '/';
3090  /*@innercontinue@*/ continue;
3091  }
3092  unpackaged = xrealloc(unpackaged, sizeof(*unpackaged) * (n + 1));
3093  unpackaged[n++] = xstrdup(fn);
3094  *p = '/';
3095  }
3096  }
3097  fi = rpmfiFree(fi);
3098 
3099  if (n > 0) {
3100  const char *N;
3101  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
3102  rpmiob list = rpmiobNew(0);
3103 
3104  he->tag = RPMTAG_NVRA;
3105  N = (headerGet(pkg->header, he, 0) ? he->p.str : NULL);
3106 
3107  for (i = 0; i < n; i++) {
3108  list = rpmiobAppend(list, "\t", 0);
3109  list = rpmiobAppend(list, unpackaged[i]+buildrootL, 1);
3110  unpackaged[i] = _free(unpackaged[i]);
3111  }
3112  unpackaged = _free(unpackaged);
3113 
3114  rpmlog(_unpackaged_subdirs_terminate_build ? RPMLOG_ERR : RPMLOG_WARNING,
3115  _("Unpackaged subdir(s) in %s:\n%s"),
3116  N, rpmiobStr(list));
3117 
3118  N = _free(N);
3119  list = rpmiobFree(list);
3120  }
3121 
3122  return n;
3123 }
3124 
3130 static int checkUnpackagedSubdirs(Spec spec, size_t buildrootL, int _unpackaged_subdirs_terminate_build)
3131  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
3132  /*@modifies *spec->packages,
3133  rpmGlobalMacroContext, fileSystem, internalState @*/
3134 {
3135  int n = 0;
3136  Package pkg;
3137 
3138  for (pkg = spec->packages; pkg; pkg = pkg->next)
3139  n += pkgUnpackagedSubdirs(pkg, buildrootL, _unpackaged_subdirs_terminate_build);
3140  return n;
3141 }
3142 
3143 /*@-incondefs@*/
3144 rpmRC processBinaryFiles(Spec spec, int installSpecialDoc, int test)
3145 {
3146  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
3147  Package pkg;
3148  rpmRC res = RPMRC_OK;
3149  short failed_once = 0;
3150 
3151  char *buildroot = rpmExpand("%{?buildroot}", NULL);
3152  size_t buildrootL = strlen(buildroot);
3153 
3154  buildroot = _free(buildroot);
3155 
3156  for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
3157  int rc;
3158 
3159  if (pkg->fileList == NULL)
3160  continue;
3161 
3162  (void) headerMacrosLoad(pkg->header);
3163 
3164  he->tag = RPMTAG_NVRA;
3165  rc = headerGet(pkg->header, he, 0);
3166  rpmlog(RPMLOG_NOTICE, _("Processing files: %s\n"), he->p.str);
3167  he->p.ptr = _free(he->p.ptr);
3168 
3169  if ((rc = processPackageFiles(spec, pkg, installSpecialDoc, test))) {
3170  failed_once = 1;
3171  }
3172 
3173  /* Finalize package scriptlets before extracting dependencies. */
3174  if ((rc = processScriptFiles(spec, pkg))) {
3175  res = rc;
3176  (void) headerMacrosUnload(pkg->header);
3177  if (res == RPMRC_FAIL) {
3178  failed_once = 1;
3179  }
3180  else {
3181  break;
3182  }
3183  }
3184 
3185  if ((rc = rpmfcGenerateDepends(spec, pkg))) {
3186  failed_once = 1;
3187  }
3188 
3189  /* XXX this should be earlier for deps to be entirely sorted. */
3190  providePackageNVR(pkg->header);
3191 
3192  (void) headerMacrosUnload(pkg->header);
3193  }
3194 
3195  if (failed_once == 1)
3196  res = RPMRC_FAIL;
3197 
3198 /* if (res == RPMRC_OK) {*/
3199  int _duplicate_files_terminate_build =
3200  rpmExpandNumeric("%{?_duplicate_files_terminate_build}");
3201  int _unpackaged_subdirs_terminate_build =
3202  rpmExpandNumeric("%{?_unpackaged_subdirs_terminate_build}");
3203  if (checkUnpackagedFiles(spec) > 0)
3204  res = RPMRC_FAIL;
3205  if (checkDuplicateFiles(spec, buildrootL, _duplicate_files_terminate_build) > 0 &&
3206  _duplicate_files_terminate_build)
3207  res = RPMRC_FAIL;
3208  if (checkUnpackagedSubdirs(spec, buildrootL, _unpackaged_subdirs_terminate_build) > 0 &&
3209  _unpackaged_subdirs_terminate_build)
3210  res = RPMRC_FAIL;
3211 /* }*/
3212 
3213  return res;
3214 }
3215 /*@=incondefs@*/
int sourceHdrInit
Definition: rpmspec.h:169
int docDirCount
Definition: files.c:154
int headerMacrosUnload(Header h)
Define per-header macros.
Definition: hdrNVR.c:111
rpmTagType t
Definition: rpmtag.h:505
Definition: iosm.h:34
#define FTS_SLNONE
Definition: fts.h:141
static rpmRC processMetadataFile(Package pkg, FileList fl, const char *fileURL, rpmTag tag)
Add a pubkey/policy/icon to a binary package.
Definition: files.c:2092
const char * str
Definition: rpmtag.h:72
rpmTag tag
Definition: rpmtag.h:504
struct stat fl_st
Definition: files.c:71
const char ** argv
Definition: rpmtag.h:74
int rpmfiSetHeader(rpmfi fi, Header h)
Link a header to a file info set.
Definition: rpmfi.c:1275
static rpmRC parseForAttr(char *buf, FileList fl)
Parse attr and defattr from file manifest.
Definition: files.c:535
FTS * Fts_open(char *const *argv, int options, int(*compar)(const FTSENT **, const FTSENT **))
Create a handle for file hierarchy traversal.
Definition: fts.c:207
int headerIsEntry(Header h, rpmTag tag)
Check if tag is in header.
Definition: header.c:1431
unsigned devtype
Definition: files.c:134
Package next
Definition: rpmspec.h:248
static char * strtokWithQuotes(char *s, const char *delim)
Strip quotes from strtok(3) string.
Definition: files.c:227
static void * fdGetFp(FD_t fd)
enum urltype_e urltype
Supported URL types.
#define SKIPWHITE(_x)
Definition: files.c:47
int currentFlags
Definition: files.c:140
rpmiob fileList
Definition: rpmspec.h:246
rpmRC processBinaryFiles(Spec spec, int installSpecialDoc, int test)
Post-build processing for binary package(s).
Definition: files.c:3144
int _rpmbuildFlags
Definition: poptBT.c:53
enum specdFlags_e specdFlags
Structures used for an "rpmte" transaction element.
char * xstrdup(const char *str)
Definition: rpmmalloc.c:322
rpmuint32_t * ui32p
Definition: rpmtag.h:69
FD_t Fopen(const char *path, const char *_fmode)
fopen(3) clone.
Definition: rpmio.c:2833
struct VFA VFA_t
int nLangs
Definition: files.c:147
const char * rootURL
Definition: rpmspec.h:115
char * rpmGetPath(const char *path,...)
Return (malloc&#39;ed) expanded, canonicalized, file path.
Definition: macro.c:3310
const char * specFile
Definition: rpmspec.h:111
int headerGet(Header h, HE_t he, unsigned int flags)
Retrieve extension or tag value from a header.
Definition: header.c:2222
int headerPut(Header h, HE_t he, unsigned int flags)
Add or append tag container to header.
Definition: header.c:2285
Package file tree walk data.
Definition: files.c:120
#define FTS_W
Definition: fts.h:142
const char * ar_user
Definition: files.c:105
rpmsx rpmsxFree(rpmsx sx)
Destroy a SELinux wrapper.
The Header data structure.
const char * fileFile
Definition: rpmspec.h:244
HeaderIterator headerFini(HeaderIterator hi)
Destroy header tag container iterator.
Definition: header.c:2125
headerSprintfExtension rpmHeaderFormats
Table of query format extensions.
Definition: formats.c:305
rpmuint16_t * ui16p
Definition: rpmtag.h:68
#define FTS_SL
Definition: fts.h:140
HeaderIterator headerInit(Header h)
Create header tag iterator.
Definition: header.c:2135
int Stat(const char *path, struct stat *st)
stat(2) clone.
Definition: rpmrpc.c:1361
static rpmRC genCpioListAndHeader(FileList fl, rpmfi *fip, Header h, int isSrc)
Add file entries to header.
Definition: files.c:1352
size_t rpmfiFNMaxLen(rpmfi fi)
Return maximum file name length from file info set.
Definition: rpmfi.c:212
void * rpmfiFNBF(rpmfi fi)
Return FN Bloom filter from file info set.
Definition: rpmfi.c:181
mode_t ar_dmode
Definition: files.c:109
rpmuint32_t num
Definition: rpmspec.h:45
#define S_ISLNK(mode)
Definition: system.h:610
char * pgpArmorWrap(rpmuint8_t atype, const unsigned char *s, size_t ns)
Wrap a OpenPGP packets in ascii armor for transport.
Definition: rpmpgp.c:1574
int errno
Header sourceHeader
Definition: rpmspec.h:166
#define FTS_NS
Definition: fts.h:138
unsigned defVerifyFlags
Definition: files.c:146
rpmfi rpmfiFree(rpmfi fi)
Destroy a file info set.
int headerDel(Header h, HE_t he, unsigned int flags)
Remove tag container from header.
Definition: header.c:2304
const char * rpmfiFN(rpmfi fi)
Return current file name from file info set.
Definition: rpmfi.c:163
unsigned short rpmuint16_t
Definition: rpmiotypes.h:24
rpmiob rpmiobFree(rpmiob iob)
Destroy a I/O buffer instance.
int dodigest(int dalgo, const char *fn, unsigned char *digest, unsigned dflags, size_t *fsizep)
Return digest and size of a file.
Definition: legacy.c:178
struct Source * sources
Definition: rpmspec.h:157
Header tag iterator data structure.
Definition: header.c:2120
static void rpmlog(int code, const char *fmt,...)
Definition: rpmlog.h:299
const char * prefix
Definition: files.c:124
static int pkgUnpackagedSubdirs(Package pkg, size_t buildrootL, int _unpackaged_subdirs_terminate_build)
Definition: files.c:3036
struct AttrRec_s def_ar
Definition: files.c:144
const char ** BANames
Definition: rpmspec.h:142
const char * getUnameS(const char *uname)
Return cached user name.
Definition: names.c:65
static int checkDuplicateFiles(Spec spec, size_t buildrootL, int _duplicate_files_terminate_build)
Check if the same files are packaged into a few sub-packages.
Definition: files.c:2984
rpmfi rpmfiNew(const void *_ts, Header h, rpmTag tagN, int flags)
Create and load a file info set.
Definition: rpmfi.c:1403
const char * ar_dmodestr
Definition: files.c:103
rpmiob rpmiobAppend(rpmiob iob, const char *s, size_t nl)
Append string to I/O buffer.
Definition: rpmiob.c:78
struct FileList_s * FileList
Package file tree walk data.
int headerNext(HeaderIterator hi, HE_t he, unsigned int flags)
Return next tag from header.
Definition: header.c:2149
int flag
Definition: files.c:301
struct Source * next
Definition: rpmspec.h:47
static rpmRC recurseDir(FileList fl, const char *diskURL)
Add directory (and all of its files) to the package manifest.
Definition: files.c:2035
char * headerSprintf(Header h, const char *fmt, headerTagTableEntry tags, headerSprintfExtension exts, errmsg_t *errmsg)
Return formatted output string from header tags.
Definition: hdrfmt.c:6700
const char * getUname(uid_t uid)
Return cached user name from user id.
Definition: names.c:41
const char * getSourceDir(rpmfileAttrs attr)
Return the macro directory location from source file flags.
Definition: build.c:24
int rpmfiFC(rpmfi fi)
Return file count from file info set.
Definition: rpmfi.c:87
static rpmRC processPackageFiles(Spec spec, Package pkg, int installSpecialDoc, int test)
Definition: files.c:2260
struct rpmte_s * rpmte
An element of a transaction set, i.e.
Definition: rpmtypes.h:38
rpmTag tagValue(const char *tagstr)
Return tag value from name.
Definition: tagname.c:446
int rpmiobSlurp(const char *fn, rpmiob *iobp)
Definition: rpmiob.c:130
static int seenHardLink(FileList fl, FileListRec flp, ino_t *fileid)
Definition: files.c:1331
const char * source
Definition: rpmspec.h:43
static int dncmp(const void *a, const void *b)
Definition: files.c:1150
Definition: rpmspec.h:39
char * alloca()
specdFlags currentSpecdFlags
Definition: files.c:141
static int fiIntersect(rpmfi fi1, rpmfi fi2, size_t buildrootL, int _duplicate_files_terminate_build)
Definition: files.c:2928
u_short fts_info
Definition: fts.h:143
#define _mask
pgpArmor pgpReadPkts(const char *fn, rpmuint8_t **pkt, size_t *pktlen)
Parse armored OpenPGP packets from a file.
Definition: rpmpgp.c:1564
Header header
Definition: rpmspec.h:210
int rpmGlob(const char *patterns, int *argcPtr, const char ***argvPtr)
Return URL path(s) from a (URL prefixed) pattern glob.
Definition: macro.c:2509
unsigned int rpmuint32_t
Definition: rpmiotypes.h:25
struct _HE_s * HE_t
Definition: rpmtag.h:58
#define FTS_D
Definition: fts.h:129
static rpmRC processBinaryFile(Package pkg, FileList fl, const char *fileURL)
Add a file to a binary package.
Definition: files.c:2179
const char * Fstrerror(FD_t fd)
strerror(3) clone.
Definition: rpmio.c:2401
void * xcalloc(size_t nmemb, size_t size)
Definition: rpmmalloc.c:301
void * ptr
Definition: rpmtag.h:66
int fileListRecsAlloced
Definition: files.c:158
static int isHardLink(FileListRec flp, FileListRec tlp)
Definition: files.c:1323
int isDir
Definition: files.c:138
#define RPMVERIFY_ALL
Definition: rpmcli.h:161
unsigned devmajor
Definition: files.c:135
static rpmuint32_t getDigestAlgo(Header h, int isSrc)
Definition: files.c:1272
int passedSpecialDoc
Definition: files.c:130
const char * uname
Definition: files.c:87
int devminor
Definition: files.c:136
#define FTS_NSOK
Definition: fts.h:139
struct AttrRec_s * AttrRec
unsigned char rpmuint8_t
Private int typedefs to avoid C99 portability issues.
Definition: rpmiotypes.h:23
struct rpmfi_s * rpmfi
File info tag sets from a header, so that a header can be discarded early.
Definition: rpmfi.h:78
mode_t ar_fmode
Definition: files.c:108
rpmiob specialDoc
Definition: rpmspec.h:238
int not
Definition: files.c:300
rpmuint16_t rpmfiFMode(rpmfi fi)
Return current file mode from file info set.
Definition: rpmfi.c:265
#define FTS_COMFOLLOW
Definition: fts.h:87
int Lstat(const char *path, struct stat *st)
lstat(2) clone.
Definition: rpmrpc.c:1401
static int packagedDir(Package pkg, const char *d)
Definition: files.c:3021
rpmTagData p
Definition: rpmtag.h:507
MacroContext macros
Definition: rpmspec.h:172
const char ** currentLangs
Definition: files.c:149
const char * getGname(gid_t gid)
Return cached group name from group id.
Definition: names.c:119
ARGV_t argvFree(ARGV_t argv)
Destroy an argv array.
Definition: argv.c:44
int rpmfcExec(ARGV_t av, rpmiob iob_stdin, rpmiob *iob_stdoutp, int failnonzero)
Definition: rpmfc.c:229
#define FTS_DEFAULT
Definition: fts.h:131
#define FTS_DC
Definition: fts.h:130
static VFA_t verifyAttrs[]
Definition: files.c:308
int Glob_pattern_p(const char *pattern, int quote)
glob_pattern_p(3) clone.
Definition: rpmrpc.c:2231
int headerMacrosLoad(Header h)
Define per-header macros.
Definition: hdrNVR.c:36
static void compressFilelist(Header h)
Convert absolute path tag to (dirname,basename,dirindex) tags.
Definition: files.c:1166
#define FTS_DOT
Definition: fts.h:133
#define HEADER_I18NTABLE
Definition: rpmtag.h:119
The FD_t File Handle data structure.
const char * rpmGenPath(const char *urlroot, const char *urlmdir, const char *urlfile)
Merge 3 args into path, any or all of which may be a url.
Definition: macro.c:3356
const char * fileURL
Definition: files.c:85
unsigned verifyFlags
Definition: files.c:92
rpmTagCount c
Definition: rpmtag.h:508
static const char * lang
Definition: fts.h:54
static rpmRC parseForVerify(char *buf, FileList fl)
Parse verify and defverify from file manifest.
Definition: files.c:329
int xstrcasecmp(const char *s1, const char *s2)
Locale insensitive strcasecmp(3).
Definition: strcasecmp.c:9
The structure used to store values parsed from a spec file.
Definition: rpmspec.h:108
FTSENT * Fts_read(FTS *sp)
Return next node in the file hierarchy traversal.
Definition: fts.c:467
const char * diskURL
Definition: files.c:83
char * rpmExpand(const char *arg,...)
Return (malloc&#39;ed) concatenated macro expansion(s).
Definition: macro.c:3117
const char * buildSubdir
Definition: rpmspec.h:113
const char * gname
Definition: files.c:89
static VFA_t virtualFileAttributes[]
Definition: files.c:873
FileListRec fileList
Definition: files.c:157
size_t nfoo
Definition: rpmspec.h:191
int numSources
Definition: rpmspec.h:158
int Fclose(FD_t fd)
fclose(3) clone.
Definition: rpmio.c:2534
static rpmRC parseForSimple(Spec spec, Package pkg, char *buf, FileList fl, const char **fileName)
Parse simple attributes (e.g.
Definition: files.c:906
static rpmRC parseForConfig(char *buf, FileList fl)
Parse config from file manifest.
Definition: files.c:666
struct rpmsx_s * rpmsx
Definition: rpmsx.h:11
rpmiob rpmiobNew(size_t len)
Create an I/O buffer.
Definition: rpmiob.c:44
#define FTS_DNR
Definition: fts.h:132
static int checkUnpackagedSubdirs(Spec spec, size_t buildrootL, int _unpackaged_subdirs_terminate_build)
Check for unpackaged subdirectories.
Definition: files.c:3130
char * fts_accpath
Definition: fts.h:113
#define MYALLPERMS
Definition: files.c:9
int rpmfiNext(rpmfi fi)
Return next file iterator index.
Definition: rpmfi.c:526
static int compareFileListRecs(const void *ap, const void *bp)
Definition: files.c:1082
int processSourceFiles(Spec spec)
Post-build processing for source package.
Definition: files.c:2737
Routines to read and write packages.
static int isDoc(FileList fl, const char *fileName)
Test if file is located in a docdir.
Definition: files.c:1099
int BACount
Definition: rpmspec.h:143
static rpmRC parseForLang(char *buf, FileList fl)
Parse lang from file manifest.
Definition: files.c:738
const char * getGnameS(const char *gname)
Return cached group name.
Definition: names.c:143
int Readlink(const char *path, char *buf, size_t bufsiz)
readlink(2) clone.
Definition: rpmrpc.c:2154
#define FTS_INIT
Definition: fts.h:137
static void nullAttrRec(AttrRec ar)
Definition: files.c:164
#define isAttrDefault(_ars)
Definition: files.c:427
enum rpmRC_e rpmRC
RPM return codes.
static int langCmp(const void *ap, const void *bp)
Definition: files.c:726
int Ferror(FD_t fd)
ferror(3) clone.
Definition: rpmio.c:2944
char * rpmiobStr(rpmiob iob)
Return I/O buffer (as string).
Definition: rpmiob.c:113
#define MAXDOCDIR
Definition: files.c:50
Package packages
Definition: rpmspec.h:197
Definition: rpmtag.h:503
rpmfi rpmfiInit(rpmfi fi, int fx)
Initialize file iterator index.
Definition: rpmfi.c:548
const char * ar_group
Definition: files.c:107
Definition: rpmte.h:31
int noGlob
Definition: files.c:133
static int xisdigit(int c)
Definition: rpmiotypes.h:437
const char * docDirs[1024]
Definition: files.c:153
urltype urlPath(const char *url, const char **pathp)
Return path component of URL.
Definition: url.c:429
static int snprintf(char *buf, int nb, const char *fmt,...)
Definition: rpmps.c:220
static ARGV_t ftsSet
Definition: rpmcache.c:56
This is the only module users of librpmbuild should need to include.
#define FTS_NOCHDIR
Definition: fts.h:89
Definition: fts.h:102
rpmfi rpmfiLink(rpmfi fi, const char *msg)
Reference a file info set instance.
int timeCheck
Definition: rpmspec.h:152
struct FileListRec_s * FileListRec
rpmRC doScript(Spec spec, int what, const char *name, rpmiob iob, int test)
Run a build script, assembled from spec file scriptlet section.
Definition: build.c:89
specdFlags specdFlags
Definition: files.c:91
struct stat * fts_statp
Definition: fts.h:156
char * stpcpy(char *dest, const char *src)
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:647
struct rpmiob_s * rpmiob
Definition: rpmiotypes.h:57
specdFlags defSpecdFlags
Definition: files.c:145
static void timeCheck(int tc, Header h)
Definition: files.c:270
struct AttrRec_s cur_ar
Definition: files.c:143
static FileListRec freeFileList(FileListRec fileList, int count)
Definition: files.c:1806
static void freeAttrRec(AttrRec ar)
Definition: files.c:176
int totalFileSize
Definition: files.c:127
rpmRC processScriptFiles(Spec spec, Package pkg)
Append files (if any) to scriptlet tags.
Definition: pack.c:212
static void dupAttrRec(const AttrRec oar, AttrRec nar)
Definition: files.c:190
rpmsx rpmsxNew(const char *fn, unsigned int flags)
Create and load a SELinux wrapper.
Definition: rpmsx.c:97
#define FTS_PHYSICAL
Definition: fts.h:91
int argvSplit(ARGV_t *argvp, const char *str, const char *seps)
Split a string into an argv array.
Definition: argv.c:233
int Fts_close(FTS *sp)
Destroy a file hierarchy traversal handle.
Definition: fts.c:380
rpmfi fi
Definition: rpmspec.h:168
const char * langs
Definition: files.c:94
const char * ar_fmodestr
Definition: files.c:101
int expandMacros(void *spec, MacroContext mc, char *sbuf, size_t slen)
Expand macro into buffer.
Definition: macro.c:2649
rpmuint32_t hashFunctionString(rpmuint32_t h, const void *data, size_t size)
Return hash value of a string.
Definition: rpmhash.c:83
static const char * name
const char * attribute
Definition: files.c:299
File state machine to handle archive I/O and system call&#39;s.
#define FTS_F
Definition: fts.h:136
#define _(Text)
Definition: system.h:30
The structure used to store values for a package.
Definition: rpmspec.h:207
#define xmalloc
Definition: system.h:33
unsigned flags
Definition: files.c:90
#define SKIPNONWHITE(_x)
Definition: files.c:48
static int checkUnpackagedFiles(Spec spec)
Check for unpackaged files against what&#39;s in the build root.
Definition: files.c:2853
#define FTS_DP
Definition: fts.h:134
int fileListRecsUsed
Definition: files.c:159
rpmRC rpmfcGenerateDepends(void *_spec, void *_pkg)
Generate package dependencies.
Definition: rpmfc.c:1992
ARGstr_t * ARGV_t
Definition: argv.h:9
rpmfi fi
Definition: rpmspec.h:214
enum rpmTag_e rpmTag
Definition: rpmtag.h:471
#define SKIPSPACE(s)
Definition: rpmbuild.h:45
unsigned currentVerifyFlags
Definition: files.c:142
static int checkHardLinks(FileList fl)
Verify that file attributes scope over hardlinks correctly.
Definition: files.c:1119
tagStore_t foo
Definition: rpmspec.h:193
static rpmRC parseForDev(char *buf, FileList fl)
Parse dev from file manifest.
Definition: files.c:435
const char * rpmsxMatch(rpmsx sx, const char *fn, mode_t mode)
Return security context for a file.
Definition: rpmsx.c:151
void handleComments(char *s)
Truncate comment lines.
Definition: parseSpec.c:144
static int parseForRegexLang(const char *fileName, char **lang)
Definition: files.c:827
int processingFailed
Definition: files.c:128
static struct AttrRec_s root_ar
Definition: files.c:114
const char * buildRootURL
Definition: files.c:122
int initSourceHeader(Spec spec, rpmiob *sfp)
Create and initialize header for source package.
Definition: files.c:2552
void providePackageNVR(Header h)
Retrofit an explicit Provides: N = E:V-R dependency into package headers.
Definition: pack.c:452
int inFtw
Definition: files.c:139
int rpmExpandNumeric(const char *arg)
Return macro expansion as a numeric value.
Definition: macro.c:3191
int isSpecialDoc
Definition: files.c:131
#define FTS_ERR
Definition: fts.h:135
int flags
Definition: rpmspec.h:44
#define xrealloc
Definition: system.h:36
Definition: files.c:298
specdFlags_e
Definition: files.c:54
int fileCount
Definition: files.c:126
static int addFile(FileList fl, const char *diskURL, struct stat *statp)
Add a file to the package manifest.
Definition: files.c:1836
int rpmlibNeedsFeature(Header h, const char *feature, const char *featureEVR)
Add rpmlib feature dependency.
Definition: reqprov.c:258
unsigned int append
Definition: rpmtag.h:512