rpm  5.4.15
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;
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  { "owner", 0, RPMVERIFY_USER },
314  { "group", 0, RPMVERIFY_GROUP },
315  { "mtime", 0, RPMVERIFY_MTIME },
316  { "mode", 0, RPMVERIFY_MODE },
317  { "rdev", 0, RPMVERIFY_RDEV },
318  { "digest", 0, RPMVERIFY_FDIGEST },
319  { "hmac", 0, RPMVERIFY_HMAC },
320  { NULL, 0, 0 }
321 };
322 /*@=exportlocal =exportheadervar@*/
323 
330 static rpmRC parseForVerify(char * buf, FileList fl)
331  /*@modifies buf, fl->processingFailed,
332  fl->currentVerifyFlags, fl->defVerifyFlags,
333  fl->currentSpecdFlags, fl->defSpecdFlags @*/
334 {
335  char *p, *pe, *q;
336  const char *name;
337  unsigned *resultVerify;
338  int negated;
339  unsigned verifyFlags;
341 
342  if ((p = strstr(buf, (name = "%verify"))) != NULL) {
343  resultVerify = &(fl->currentVerifyFlags);
344  specdFlags = &fl->currentSpecdFlags;
345  } else if ((p = strstr(buf, (name = "%defverify"))) != NULL) {
346  resultVerify = &(fl->defVerifyFlags);
347  specdFlags = &fl->defSpecdFlags;
348  } else
349  return RPMRC_OK;
350 
351  for (pe = p; (size_t)(pe-p) < strlen(name); pe++)
352  *pe = ' ';
353 
354  SKIPSPACE(pe);
355 
356  if (*pe != '(') {
357  rpmlog(RPMLOG_ERR, _("Missing '(' in %s %s\n"), name, pe);
358  fl->processingFailed = 1;
359  return RPMRC_FAIL;
360  }
361 
362  /* Bracket %*verify args */
363  *pe++ = ' ';
364  for (p = pe; *pe && *pe != ')'; pe++)
365  {};
366 
367  if (*pe == '\0') {
368  rpmlog(RPMLOG_ERR, _("Missing ')' in %s(%s\n"), name, p);
369  fl->processingFailed = 1;
370  return RPMRC_FAIL;
371  }
372 
373  /* Localize. Erase parsed string */
374  q = alloca((pe-p) + 1);
375  strncpy(q, p, pe-p);
376  q[pe-p] = '\0';
377  while (p <= pe)
378  *p++ = ' ';
379 
380  negated = 0;
381  verifyFlags = RPMVERIFY_NONE;
382 
383  for (p = q; *p != '\0'; p = pe) {
384  SKIPWHITE(p);
385  if (*p == '\0')
386  break;
387  pe = p;
388  SKIPNONWHITE(pe);
389  if (*pe != '\0')
390  *pe++ = '\0';
391 
392  { VFA_t *vfa;
393  for (vfa = verifyAttrs; vfa->attribute != NULL; vfa++) {
394  if (strcmp(p, vfa->attribute))
395  /*@innercontinue@*/ continue;
396  verifyFlags |= vfa->flag;
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  goto exit;
934  }
935 
936  if (s != NULL)
937  fl->docDirs[fl->docDirCount++] = xstrdup(s);
938  if (s == NULL || strtokWithQuotes(NULL, " \t\n")) {
939  rpmlog(RPMLOG_CRIT, _("Only one arg for %%docdir\n"));
940  fl->processingFailed = 1;
941  res = RPMRC_FAIL;
942  goto exit;
943  }
944  break;
945  }
946 #if defined(__LCLINT__)
947  assert(s != NULL);
948 #endif
949 
950  /* Set flags for virtual file attributes */
951  { VFA_t *vfa;
952  for (vfa = virtualFileAttributes; vfa->attribute != NULL; vfa++) {
953  if (strcmp(s, vfa->attribute))
954  /*@innercontinue@*/ continue;
955  if (!vfa->flag) {
956  if (!strcmp(s, "%dir"))
957  fl->isDir = 1; /* XXX why not RPMFILE_DIR? */
958  } else {
959  if (vfa->not)
960  fl->currentFlags &= ~vfa->flag;
961  else
962  fl->currentFlags |= vfa->flag;
963  }
964 
965  /*@innerbreak@*/ break;
966  }
967  /* if we got an attribute, continue with next token */
968  if (vfa->attribute != NULL)
969  continue;
970  }
971 
972  if (*fileName) {
973  /* We already got a file -- error */
974  rpmlog(RPMLOG_ERR, _("Two files on one line: %s\n"),
975  *fileName);
976  fl->processingFailed = 1;
977  res = RPMRC_FAIL;
978  goto exit;
979  }
980 
981  if (*s != '/') {
982  if (fl->currentFlags & RPMFILE_DOC) {
983  specialDoc = 1;
984  strcat(specialDocBuf, " ");
985  strcat(specialDocBuf, s);
986  } else
988  {
989  *fileName = s;
990  } else {
991  const char * sfn = NULL;
992  int urltype = urlPath(s, &sfn);
993  switch (urltype) {
994  default: /* relative path, not in %doc and not a URL */
996  _("File must begin with \"/\": %s\n"), s);
997  fl->processingFailed = 1;
998  res = RPMRC_FAIL;
999  goto exit;
1000  /*@switchbreak@*/ break;
1001  case URL_IS_PATH:
1002  *fileName = s;
1003  /*@switchbreak@*/ break;
1004  }
1005  }
1006  } else {
1007  *fileName = s;
1008  }
1009  }
1010 
1011  if (specialDoc) {
1012  if (*fileName || (fl->currentFlags & ~(RPMFILE_DOC))) {
1014  _("Can't mix special %%doc with other forms: %s\n"),
1015  (*fileName ? *fileName : ""));
1016  fl->processingFailed = 1;
1017  res = RPMRC_FAIL;
1018  goto exit;
1019  } else {
1020  /* XXX WATCHOUT: buf is an arg */
1021  {
1022  /*@only@*/
1023  static char *_docdir_fmt = NULL; /* XXX memleak */
1024  static int oneshot = 0;
1025  const char *ddir, *fmt, *errstr;
1026  if (!oneshot) {
1027  _docdir_fmt = rpmExpand("%{?_docdir_fmt}", NULL);
1028  if (!(_docdir_fmt && *_docdir_fmt))
1029  _docdir_fmt = _free(_docdir_fmt);
1030  oneshot = 1;
1031  }
1032  if (_docdir_fmt == NULL)
1033  _docdir_fmt = xstrdup("%{NAME}-%{VERSION}");
1034  fmt = headerSprintf(pkg->header, _docdir_fmt, NULL, rpmHeaderFormats, &errstr);
1035  if (fmt == NULL) {
1036  rpmlog(RPMLOG_ERR, _("illegal _docdir_fmt: %s\n"), errstr);
1037  fl->processingFailed = 1;
1038  res = RPMRC_FAIL;
1039  goto exit;
1040  } else {
1041  ddir = rpmGetPath("%{_docdir}/", fmt, NULL);
1042  strcpy(buf, ddir);
1043  ddir = _free(ddir);
1044  fmt = _free(fmt);
1045  }
1046  }
1047 
1048  /* XXX FIXME: this is easy to do as macro expansion */
1049 
1050  if (! fl->passedSpecialDoc) {
1051  char *mkdir_p;
1052 
1053  pkg->specialDoc = rpmiobNew(0);
1054  pkg->specialDoc = rpmiobAppend(pkg->specialDoc, "DOCDIR=\"$RPM_BUILD_ROOT\"", 0);
1055  pkg->specialDoc = rpmiobAppend(pkg->specialDoc, buf, 1);
1056  pkg->specialDoc = rpmiobAppend(pkg->specialDoc, "export DOCDIR", 1);
1057  pkg->specialDoc = rpmiobAppend(pkg->specialDoc, "if test -d \"$DOCDIR\" ; then rmdir \"$DOCDIR\" ; fi", 1);
1058  mkdir_p = rpmExpand("%{?__mkdir_p}%{!?__mkdir_p:mkdir -p}", NULL);
1059  if (!mkdir_p)
1060  mkdir_p = xstrdup("mkdir -p");
1061  pkg->specialDoc = rpmiobAppend(pkg->specialDoc, mkdir_p, 0);
1062  mkdir_p = _free(mkdir_p);
1063  pkg->specialDoc = rpmiobAppend(pkg->specialDoc, " \"$DOCDIR\"", 1);
1064 
1065  /*@-temptrans@*/
1066  *fileName = buf;
1067  /*@=temptrans@*/
1068  fl->passedSpecialDoc = 1;
1069  fl->isSpecialDoc = 1;
1070  }
1071 
1072  pkg->specialDoc = rpmiobAppend(pkg->specialDoc, "cp -pr ", 0);
1073  pkg->specialDoc = rpmiobAppend(pkg->specialDoc, specialDocBuf, 0);
1074  pkg->specialDoc = rpmiobAppend(pkg->specialDoc, " \"$DOCDIR\"", 1);
1075 
1076  {
1077  char *compress_doc;
1078 
1079  compress_doc = rpmExpand("%{__compress_doc}", NULL);
1080  if (compress_doc && *compress_doc != '%')
1081  pkg->specialDoc = rpmiobAppend(pkg->specialDoc, compress_doc, 1);
1082  compress_doc = _free(compress_doc);
1083  }
1084  }
1085  }
1086 
1087 exit:
1088  return res;
1089 }
1090 
1093 static int compareFileListRecs(const void * ap, const void * bp) /*@*/
1094 {
1095  const char *aurl = ((FileListRec)ap)->fileURL;
1096  const char *a = NULL;
1097  const char *burl = ((FileListRec)bp)->fileURL;
1098  const char *b = NULL;
1099  (void) urlPath(aurl, &a);
1100  (void) urlPath(burl, &b);
1101  return strcmp(a, b);
1102 }
1103 
1110 static int isDoc(FileList fl, const char * fileName) /*@*/
1111 {
1112  int x = fl->docDirCount;
1113  size_t k, l;
1114 
1115  k = strlen(fileName);
1116  while (x--) {
1117  l = strlen(fl->docDirs[x]);
1118  if (l < k && strncmp(fileName, fl->docDirs[x], l) == 0 && fileName[l] == '/')
1119  return 1;
1120  }
1121  return 0;
1122 }
1123 
1130 static int checkHardLinks(FileList fl)
1131  /*@*/
1132 {
1133  FileListRec ilp, jlp;
1134  int i, j;
1135 
1136  for (i = 0; i < fl->fileListRecsUsed; i++) {
1137  ilp = fl->fileList + i;
1138  if (!(S_ISREG(ilp->fl_mode) && ilp->fl_nlink > 1))
1139  continue;
1140  if (ilp->flags & (RPMFILE_EXCLUDE | RPMFILE_GHOST))
1141  continue;
1142 
1143  for (j = i + 1; j < fl->fileListRecsUsed; j++) {
1144  jlp = fl->fileList + j;
1145  if (!S_ISREG(jlp->fl_mode))
1146  /*@innercontinue@*/ continue;
1147  if (ilp->fl_nlink != jlp->fl_nlink)
1148  /*@innercontinue@*/ continue;
1149  if (ilp->fl_ino != jlp->fl_ino)
1150  /*@innercontinue@*/ continue;
1151  if (ilp->fl_dev != jlp->fl_dev)
1152  /*@innercontinue@*/ continue;
1153  if (jlp->flags & (RPMFILE_EXCLUDE | RPMFILE_GHOST))
1154  /*@innercontinue@*/ continue;
1155  return 1;
1156  }
1157  }
1158  return 0;
1159 }
1160 
1161 static int dncmp(const void * a, const void * b)
1162  /*@*/
1163 {
1164  const char ** aurlp = (const char **)a;
1165  const char ** burlp = (const char **)b;
1166  const char * adn;
1167  const char * bdn;
1168  (void) urlPath(*aurlp, &adn);
1169  (void) urlPath(*burlp, &bdn);
1170  return strcmp(adn, bdn);
1171 }
1172 
1177 static void compressFilelist(Header h)
1178  /*@globals internalState @*/
1179  /*@modifies h, internalState @*/
1180 {
1181  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
1182  const char ** fileNames;
1183  const char * fn;
1184  const char ** dirNames;
1185  const char ** baseNames;
1186  rpmuint32_t * dirIndexes;
1187  int count;
1188  int dirIndex = -1;
1189  int xx;
1190  int i;
1191 
1192  /*
1193  * This assumes the file list is already sorted, and begins with a
1194  * single '/'. That assumption isn't critical, but it makes things go
1195  * a bit faster.
1196  */
1197 
1198  if (headerIsEntry(h, RPMTAG_DIRNAMES)) {
1199  he->tag = RPMTAG_OLDFILENAMES;
1200  xx = headerDel(h, he, 0);
1201  return; /* Already converted. */
1202  }
1203 
1204  he->tag = RPMTAG_OLDFILENAMES;
1205  xx = headerGet(h, he, 0);
1206  fileNames = he->p.argv;
1207  count = he->c;
1208  if (!xx || fileNames == NULL || count <= 0)
1209  return; /* no file list */
1210 
1211  dirNames = alloca(sizeof(*dirNames) * count); /* worst case */
1212  baseNames = alloca(sizeof(*dirNames) * count);
1213  dirIndexes = alloca(sizeof(*dirIndexes) * count);
1214 
1215  (void) urlPath(fileNames[0], &fn);
1216  if (fn[0] != '/') {
1217  /* HACK. Source RPM, so just do things differently */
1218  dirIndex = 0;
1219  dirNames[dirIndex] = "";
1220  for (i = 0; i < count; i++) {
1221  dirIndexes[i] = dirIndex;
1222  baseNames[i] = fileNames[i];
1223  }
1224  goto exit;
1225  }
1226 
1227  for (i = 0; i < count; i++) {
1228  const char ** needle;
1229  char savechar;
1230  char * baseName;
1231  size_t len;
1232 
1233  if (fileNames[i] == NULL) /* XXX can't happen */
1234  continue;
1235  baseName = strrchr(fileNames[i], '/') + 1;
1236  len = baseName - fileNames[i];
1237  needle = dirNames;
1238  savechar = *baseName;
1239  *baseName = '\0';
1240 /*@-compdef@*/
1241  if (dirIndex < 0 ||
1242  (needle = bsearch(&fileNames[i], dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) {
1243  char *s = alloca(len + 1);
1244  memcpy(s, fileNames[i], len + 1);
1245  s[len] = '\0';
1246  dirIndexes[i] = ++dirIndex;
1247  dirNames[dirIndex] = s;
1248  } else
1249  dirIndexes[i] = needle - dirNames;
1250 /*@=compdef@*/
1251 
1252  *baseName = savechar;
1253  baseNames[i] = baseName;
1254  }
1255 
1256 exit:
1257  if (count > 0) {
1258  he->tag = RPMTAG_DIRINDEXES;
1259  he->t = RPM_UINT32_TYPE;
1260  he->p.ui32p = dirIndexes;
1261  he->c = count;
1262  xx = headerPut(h, he, 0);
1263 
1264  he->tag = RPMTAG_BASENAMES;
1265  he->t = RPM_STRING_ARRAY_TYPE;
1266  he->p.argv = baseNames;
1267  he->c = count;
1268  xx = headerPut(h, he, 0);
1269 
1270  he->tag = RPMTAG_DIRNAMES;
1271  he->t = RPM_STRING_ARRAY_TYPE;
1272  he->p.argv = dirNames;
1273  he->c = dirIndex + 1;
1274  xx = headerPut(h, he, 0);
1275  }
1276 
1277  fileNames = _free(fileNames);
1278 
1279  he->tag = RPMTAG_OLDFILENAMES;
1280  xx = headerDel(h, he, 0);
1281 }
1282 
1283 static rpmuint32_t getDigestAlgo(Header h, int isSrc)
1284  /*@modifies h @*/
1285 {
1286  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
1287  static rpmuint32_t source_file_dalgo = 0;
1288  static rpmuint32_t binary_file_dalgo = 0;
1289  static int oneshot = 0;
1290  rpmuint32_t dalgo = 0;
1291  int xx;
1292 
1293  if (!oneshot) {
1294  source_file_dalgo =
1295  rpmExpandNumeric("%{?_build_source_file_digest_algo}");
1296  binary_file_dalgo =
1297  rpmExpandNumeric("%{?_build_binary_file_digest_algo}");
1298  oneshot++;
1299  }
1300 
1301  dalgo = (isSrc ? source_file_dalgo : binary_file_dalgo);
1302  switch (dalgo) {
1303  case PGPHASHALGO_SHA1:
1304  case PGPHASHALGO_MD2:
1305  case PGPHASHALGO_SHA256:
1306  case PGPHASHALGO_SHA384:
1307  case PGPHASHALGO_SHA512:
1308  (void) rpmlibNeedsFeature(h, "FileDigests", "4.6.0-1");
1309  he->tag = RPMTAG_FILEDIGESTALGO;
1310  he->t = RPM_UINT32_TYPE;
1311  he->p.ui32p = &dalgo;
1312  he->c = 1;
1313  xx = headerPut(h, he, 0);
1314  /*@fallthgrough@*/
1315  case PGPHASHALGO_RIPEMD160:
1316  case PGPHASHALGO_TIGER192:
1317  case PGPHASHALGO_MD4:
1318  case PGPHASHALGO_RIPEMD128:
1319  case PGPHASHALGO_CRC32:
1320  case PGPHASHALGO_ADLER32:
1321  case PGPHASHALGO_CRC64:
1322  (void) rpmlibNeedsFeature(h, "FileDigestParameterized", "4.4.6-1");
1323  /*@switchbreak@*/ break;
1324  case PGPHASHALGO_MD5:
1325  case PGPHASHALGO_HAVAL_5_160: /* XXX unimplemented */
1326  default:
1327  dalgo = PGPHASHALGO_MD5;
1328  /*@switchbreak@*/ break;
1329  }
1330 
1331  return dalgo;
1332 }
1333 
1334 static int isHardLink(FileListRec flp, FileListRec tlp)
1335 {
1336  return ((S_ISREG(flp->fl_mode) && S_ISREG(tlp->fl_mode)) &&
1337  ((flp->fl_nlink > 1) && (flp->fl_nlink == tlp->fl_nlink)) &&
1338  (flp->fl_ino == tlp->fl_ino) &&
1339  (flp->fl_dev == tlp->fl_dev));
1340 }
1341 
1342 static int seenHardLink(FileList fl, FileListRec flp, ino_t *fileid)
1343 {
1344  FileListRec ilp;
1345  for (ilp = fl->fileList; ilp < flp; ilp++) {
1346  if (isHardLink(flp, ilp)) {
1347  *fileid = ilp - fl->fileList;
1348  return 1;
1349  }
1350  }
1351  return 0;
1352 }
1353 
1363 static rpmRC genCpioListAndHeader(/*@partial@*/ FileList fl,
1364  rpmfi * fip, Header h, int isSrc)
1365  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1366  /*@modifies h, *fip, fl->processingFailed, fl->fileList,
1367  fl->totalFileSize,
1368  rpmGlobalMacroContext, fileSystem, internalState @*/
1369 {
1370  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
1371  const char * apath;
1372  rpmuint16_t ui16;
1373  rpmuint32_t ui32;
1374  int _addDotSlash = !isSrc;
1375  int apathlen = 0;
1376  int dpathlen = 0;
1377  int skipLen = 0;
1378  rpmsx sx = rpmsxNew("%{?_build_file_context_path}", 0);
1379  FileListRec flp;
1380  rpmuint32_t dalgo = getDigestAlgo(h, isSrc);
1381  char buf[BUFSIZ];
1382  int i, xx;
1383  rpmRC rc = RPMRC_OK;
1384 
1385 memset(buf, 0, sizeof(buf)); /* XXX valgrind on rhel6 beta pickier */
1386 
1387  /* Sort the big list */
1388  if (fl->fileListRecsUsed > 1)
1389  qsort(fl->fileList, fl->fileListRecsUsed,
1390  sizeof(*(fl->fileList)), compareFileListRecs);
1391 
1392  /* Generate the header. */
1393  if (! isSrc) {
1394  skipLen = 1;
1395  if (fl->prefix)
1396  skipLen += strlen(fl->prefix);
1397  }
1398 
1399  for (i = 0, flp = fl->fileList; i < fl->fileListRecsUsed; i++, flp++) {
1400  const char *s;
1401  ino_t fileid = flp - fl->fileList;
1402 
1403  /* Merge duplicate entries. */
1404  while (i < (fl->fileListRecsUsed - 1) &&
1405  !strcmp(flp->fileURL, flp[1].fileURL)) {
1406 
1407  /* Two entries for the same file found, merge the entries. */
1408  /* Note that an %exclude is a duplication of a file reference */
1409 
1410  /* file flags */
1411  flp[1].flags |= flp->flags;
1412 
1413  if (!(flp[1].flags & RPMFILE_EXCLUDE)) {
1414  int terminate = rpmExpandNumeric("%{?_files_listed_twice_terminate_build}");
1415 
1416  rpmlog(terminate ? RPMLOG_ERR : RPMLOG_WARNING, _("File listed twice: %s\n"),
1417  flp->fileURL);
1418  if (terminate)
1419  rc = RPMRC_FAIL;
1420  }
1421 
1422  /* file mode */
1423  if (S_ISDIR(flp->fl_mode)) {
1424  if ((flp[1].specdFlags & (SPECD_DIRMODE | SPECD_DEFDIRMODE)) <
1426  flp[1].fl_mode = flp->fl_mode;
1427  } else {
1428  if ((flp[1].specdFlags & (SPECD_FILEMODE | SPECD_DEFFILEMODE)) <
1430  flp[1].fl_mode = flp->fl_mode;
1431  }
1432 
1433  /* uid */
1434  if ((flp[1].specdFlags & (SPECD_UID | SPECD_DEFUID)) <
1435  (flp->specdFlags & (SPECD_UID | SPECD_DEFUID)))
1436  {
1437  flp[1].fl_uid = flp->fl_uid;
1438  flp[1].uname = flp->uname;
1439  }
1440 
1441  /* gid */
1442  if ((flp[1].specdFlags & (SPECD_GID | SPECD_DEFGID)) <
1443  (flp->specdFlags & (SPECD_GID | SPECD_DEFGID)))
1444  {
1445  flp[1].fl_gid = flp->fl_gid;
1446  flp[1].gname = flp->gname;
1447  }
1448 
1449  /* verify flags */
1450  if ((flp[1].specdFlags & (SPECD_VERIFY | SPECD_DEFVERIFY)) <
1452  flp[1].verifyFlags = flp->verifyFlags;
1453 
1454  /* XXX to-do: language */
1455 
1456  flp++; i++;
1457  }
1458 
1459  /* Skip files that were marked with %exclude. */
1460  if (flp->flags & RPMFILE_EXCLUDE) continue;
1461 
1462  /* Omit '/' and/or URL prefix, leave room for "./" prefix */
1463  (void) urlPath(flp->fileURL, &apath);
1464  apathlen += (strlen(apath) - skipLen + (_addDotSlash ? 3 : 1));
1465 
1466  /* Leave room for both dirname and basename NUL's */
1467  dpathlen += (strlen(flp->diskURL) + 2);
1468 
1469  /* Excludes and dupes have been filtered out by now. */
1470  if (S_ISREG(flp->fl_mode)) {
1471  if (flp->fl_nlink == 1 || !seenHardLink(fl, flp, &fileid)) {
1472  fl->totalFileSize += flp->fl_size;
1473  }
1474  }
1475 
1476  /*
1477  * Make the header, the OLDFILENAMES will get converted to a
1478  * compressed file list write before we write the actual package to
1479  * disk.
1480  */
1481  he->tag = RPMTAG_OLDFILENAMES;
1482  he->t = RPM_STRING_ARRAY_TYPE;
1483  he->p.argv = &flp->fileURL;
1484  he->c = 1;
1485  he->append = 1;
1486  xx = headerPut(h, he, 0);
1487  he->append = 0;
1488 
1489 /*@-sizeoftype@*/
1490  ui32 = (rpmuint32_t) flp->fl_size;
1491  he->tag = RPMTAG_FILESIZES;
1492  he->t = RPM_UINT32_TYPE;
1493  he->p.ui32p = &ui32;
1494  he->c = 1;
1495  he->append = 1;
1496  xx = headerPut(h, he, 0);
1497  he->append = 0;
1498 
1499  he->tag = RPMTAG_FILEUSERNAME;
1500  he->t = RPM_STRING_ARRAY_TYPE;
1501  he->p.argv = &flp->uname;
1502  he->c = 1;
1503  he->append = 1;
1504  xx = headerPut(h, he, 0);
1505  he->append = 0;
1506 
1507  he->tag = RPMTAG_FILEGROUPNAME;
1508  he->t = RPM_STRING_ARRAY_TYPE;
1509  he->p.argv = &flp->gname;
1510  he->c = 1;
1511  he->append = 1;
1512  xx = headerPut(h, he, 0);
1513  he->append = 0;
1514 
1515  ui32 = (rpmuint32_t) flp->fl_mtime;
1516  he->tag = RPMTAG_FILEMTIMES;
1517  he->t = RPM_UINT32_TYPE;
1518  he->p.ui32p = &ui32;
1519  he->c = 1;
1520  he->append = 1;
1521  xx = headerPut(h, he, 0);
1522  he->append = 0;
1523 
1524  ui16 = (rpmuint16_t)flp->fl_mode;
1525  he->tag = RPMTAG_FILEMODES;
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  { dev_t _dev = flp->fl_rdev;
1534  ui16 = _dev;
1535  }
1536  he->tag = RPMTAG_FILERDEVS;
1537  he->t = RPM_UINT16_TYPE;
1538  he->p.ui16p = &ui16;
1539  he->c = 1;
1540  he->append = 1;
1541  xx = headerPut(h, he, 0);
1542  he->append = 0;
1543 
1544  /* XXX Hash instead of 64b->32b truncate to prevent aliasing. */
1545  { dev_t _dev = flp->fl_dev;
1546  ui32 = hashFunctionString(0, &_dev, sizeof(_dev));
1547  }
1548  he->tag = RPMTAG_FILEDEVICES;
1549  he->t = RPM_UINT32_TYPE;
1550  he->p.ui32p = &ui32;
1551  he->c = 1;
1552  he->append = 1;
1553  xx = headerPut(h, he, 0);
1554  he->append = 0;
1555 
1556  /* XXX Hash instead of 64b->32b truncate to prevent aliasing. */
1557  { ino_t _ino = flp->fl_ino;
1558  /* don't use hash here, as hash collisions which happen on large packages
1559  cause bus errors in rpmbuild
1560  ui32 = hashFunctionString(0, &_ino, sizeof(_ino));
1561  */
1562  ui32 = fileid + 1;
1563  }
1564  he->tag = RPMTAG_FILEINODES;
1565  he->t = RPM_UINT32_TYPE;
1566  he->p.ui32p = &ui32;
1567  he->c = 1;
1568  he->append = 1;
1569  xx = headerPut(h, he, 0);
1570  he->append = 0;
1571 
1572 /*@=sizeoftype@*/
1573 
1574  he->tag = RPMTAG_FILELANGS;
1575  he->t = RPM_STRING_ARRAY_TYPE;
1576  he->p.argv = &flp->langs;
1577  he->c = 1;
1578  he->append = 1;
1579  xx = headerPut(h, he, 0);
1580  he->append = 0;
1581 
1582  buf[0] = '\0';
1583  if (S_ISREG(flp->fl_mode)) {
1584  unsigned dflags = 0x01; /* asAscii */
1585 #define _mask (RPMVERIFY_FDIGEST|RPMVERIFY_HMAC)
1586  if ((flp->verifyFlags & _mask) == RPMVERIFY_HMAC)
1587  dflags |= 0x02; /* doHmac */
1588 #undef _mask
1589  (void) dodigest(dalgo, flp->diskURL, (unsigned char *)buf,
1590  dflags, NULL);
1591  }
1592  s = buf;
1593 
1594  he->tag = RPMTAG_FILEDIGESTS;
1595  he->t = RPM_STRING_ARRAY_TYPE;
1596  he->p.argv = &s;
1597  he->c = 1;
1598  he->append = 1;
1599  xx = headerPut(h, he, 0);
1600  he->append = 0;
1601 
1602 if (!(_rpmbuildFlags & 4)) {
1603  ui32 = dalgo;
1605  he->t = RPM_UINT32_TYPE;
1606  he->p.ui32p = &ui32;
1607  he->c = 1;
1608  he->append = 1;
1609  xx = headerPut(h, he, 0);
1610  he->append = 0;
1611 }
1612 
1613  buf[0] = '\0';
1614  if (S_ISLNK(flp->fl_mode)) {
1615  xx = Readlink(flp->diskURL, buf, BUFSIZ);
1616  if (xx >= 0)
1617  buf[xx] = '\0';
1618  if (fl->buildRootURL) {
1619  const char * buildRoot;
1620  (void) urlPath(fl->buildRootURL, &buildRoot);
1621 
1622  if (buf[0] == '/' && strcmp(buildRoot, "/") &&
1623  !strncmp(buf, buildRoot, strlen(buildRoot))) {
1625  _("Symlink points to BuildRoot: %s -> %s\n"),
1626  flp->fileURL, buf);
1627  fl->processingFailed = 1;
1628  }
1629  }
1630  }
1631  s = buf;
1632  he->tag = RPMTAG_FILELINKTOS;
1633  he->t = RPM_STRING_ARRAY_TYPE;
1634  he->p.argv = &s;
1635  he->c = 1;
1636  he->append = 1;
1637  xx = headerPut(h, he, 0);
1638  he->append = 0;
1639 
1640  if (flp->flags & RPMFILE_GHOST) {
1643  }
1644  ui32 = flp->verifyFlags;
1646  he->t = RPM_UINT32_TYPE;
1647  he->p.ui32p = &ui32;
1648  he->c = 1;
1649  he->append = 1;
1650  xx = headerPut(h, he, 0);
1651  he->append = 0;
1652 
1653  if (!isSrc && isDoc(fl, flp->fileURL))
1654  flp->flags |= RPMFILE_DOC;
1655  /* XXX Should directories have %doc/%config attributes? (#14531) */
1656  if (S_ISDIR(flp->fl_mode))
1657  flp->flags &= ~(RPMFILE_CONFIG|RPMFILE_DOC);
1658 
1659  ui32 = flp->flags;
1660  he->tag = RPMTAG_FILEFLAGS;
1661  he->t = RPM_UINT32_TYPE;
1662  he->p.ui32p = &ui32;
1663  he->c = 1;
1664  he->append = 1;
1665  xx = headerPut(h, he, 0);
1666  he->append = 0;
1667 
1668  /* Add file security context to package. */
1669  if (sx && sx->fn && *sx->fn && !(_rpmbuildFlags & 4)) {
1670  const char * scon = rpmsxMatch(sx, flp->fileURL, flp->fl_mode);
1671  if (scon) {
1672  he->tag = RPMTAG_FILECONTEXTS;
1673  he->t = RPM_STRING_ARRAY_TYPE;
1674  he->p.argv = &scon;
1675  he->c = 1;
1676  he->append = 1;
1677  xx = headerPut(h, he, 0);
1678  he->append = 0;
1679  }
1680  scon = _free(scon); /* XXX freecon(scon) instead()? */
1681  }
1682  }
1683 
1684  sx = rpmsxFree(sx);
1685 
1686 if (_rpmbuildFlags & 4) {
1687 (void) rpmlibNeedsFeature(h, "PayloadFilesHavePrefix", "4.0-1");
1688 (void) rpmlibNeedsFeature(h, "CompressedFileNames", "3.0.4-1");
1689 }
1690 
1691  compressFilelist(h);
1692 
1693  { static int scareMem = 0;
1694  void * ts = NULL; /* XXX FIXME drill rpmts ts all the way down here */
1695  rpmfi fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem);
1696  char * a, * d;
1697 
1698  if (fi == NULL) return; /* XXX can't happen */
1699 
1700 /*@-onlytrans@*/
1701  fi->te = xcalloc(1, sizeof(*((rpmte)fi->te)));
1702 /*@=onlytrans@*/
1703  ((rpmte)fi->te)->type = TR_ADDED;
1704 
1705  fi->dnl = _free(fi->dnl);
1706  fi->bnl = _free(fi->bnl);
1707  if (!scareMem) fi->dil = _free(fi->dil);
1708 
1709  /* XXX Insure at least 1 byte is always allocated. */
1710  fi->dnl = xmalloc(fi->fc * sizeof(*fi->dnl) + dpathlen + 1);
1711  d = (char *)(fi->dnl + fi->fc);
1712  *d = '\0';
1713 
1714  fi->bnl = xmalloc(fi->fc * (sizeof(*fi->bnl) + sizeof(*fi->dil)));
1715 /*@-dependenttrans@*/ /* FIX: artifact of spoofing header tag store */
1716  fi->dil = (!scareMem)
1717  ? xcalloc(sizeof(*fi->dil), fi->fc)
1718  : (rpmuint32_t *)(fi->bnl + fi->fc);
1719 /*@=dependenttrans@*/
1720 
1721  /* XXX Insure at least 1 byte is always allocated. */
1722  fi->apath = xmalloc(fi->fc * sizeof(*fi->apath) + apathlen + 1);
1723  a = (char *)(fi->apath + fi->fc);
1724  *a = '\0';
1725 
1726  fi->actions = _free(fi->actions); /* XXX memory leak */
1727  fi->actions = xcalloc(sizeof(*fi->actions), fi->fc);
1728  fi->fmapflags = xcalloc(sizeof(*fi->fmapflags), fi->fc);
1729  fi->astriplen = 0;
1730  if (fl->buildRootURL)
1731  fi->astriplen = strlen(fl->buildRootURL);
1732  fi->striplen = 0;
1733  fi->fuser = _free(fi->fuser);
1734  fi->fgroup = _free(fi->fgroup);
1735 
1736  /* Make the cpio list */
1737  if (fi->dil != NULL) /* XXX can't happen */
1738  for (i = 0, flp = fl->fileList; (unsigned)i < fi->fc; i++, flp++) {
1739  char * b;
1740 
1741  /* Skip (possible) duplicate file entries, use last entry info. */
1742  while (((flp - fl->fileList) < (fl->fileListRecsUsed - 1)) &&
1743  !strcmp(flp->fileURL, flp[1].fileURL))
1744  flp++;
1745 
1746  if (flp->flags & RPMFILE_EXCLUDE) {
1747  i--;
1748  continue;
1749  }
1750 
1751  {
1752  /* this fi uses diskURL (with buildroot), not fileURL */
1753  size_t fnlen = strlen(flp->diskURL);
1754  if (fnlen > fi->fnlen) {
1755  /* fnlen-sized buffer must not be allocated yet */
1756  assert(fi->fn == NULL);
1757  fi->fnlen = fnlen;
1758  }
1759  }
1760 
1761  /* Create disk directory and base name. */
1762  fi->dil[i] = i;
1763 /*@-dependenttrans@*/ /* FIX: artifact of spoofing header tag store */
1764  fi->dnl[fi->dil[i]] = d;
1765 /*@=dependenttrans@*/
1766  d = stpcpy(d, flp->diskURL);
1767 
1768  /* Make room for the dirName NUL, find start of baseName. */
1769  for (b = d; b > fi->dnl[fi->dil[i]] && *b != '/'; b--)
1770  b[1] = b[0];
1771  b++; /* dirname's end in '/' */
1772  *b++ = '\0'; /* terminate dirname, b points to basename */
1773  fi->bnl[i] = b;
1774  d += 2; /* skip both dirname and basename NUL's */
1775 
1776  /* Create archive path, normally adding "./" */
1777  /*@-dependenttrans@*/ /* FIX: xstrdup? nah ... */
1778  fi->apath[i] = a;
1779  /*@=dependenttrans@*/
1780  if (_addDotSlash)
1781  a = stpcpy(a, "./");
1782  (void) urlPath(flp->fileURL, &apath);
1783  a = stpcpy(a, (apath + skipLen));
1784  a++; /* skip apath NUL */
1785 
1786  if (flp->flags & RPMFILE_GHOST) {
1787  fi->actions[i] = FA_SKIP;
1788  continue;
1789  }
1790  fi->actions[i] = FA_COPYOUT;
1791  fi->fmapflags[i] = IOSM_MAP_PATH |
1793  if (isSrc)
1794  fi->fmapflags[i] |= IOSM_FOLLOW_SYMLINKS;
1795  }
1796 
1797  ui32 = fl->totalFileSize;
1798  he->tag = RPMTAG_SIZE;
1799  he->t = RPM_UINT32_TYPE;
1800  he->p.ui32p = &ui32;
1801  he->c = 1;
1802  xx = headerPut(h, he, 0);
1803 
1804  /*@-compdef@*/
1805  if (fip)
1806  *fip = fi;
1807  else
1808  fi = rpmfiFree(fi);
1809  /*@=compdef@*/
1810  }
1811 
1812  return rc;
1813 }
1814 
1817 static /*@null@*/ FileListRec freeFileList(/*@only@*/ FileListRec fileList,
1818  int count)
1819  /*@*/
1820 {
1821  while (count--) {
1822  fileList[count].diskURL = _free(fileList[count].diskURL);
1823  fileList[count].fileURL = _free(fileList[count].fileURL);
1824  fileList[count].langs = _free(fileList[count].langs);
1825  }
1826  fileList = _free(fileList);
1827  return NULL;
1828 }
1829 
1830 /* forward ref */
1831 static rpmRC recurseDir(FileList fl, const char * diskURL)
1832  /*@globals rpmGlobalMacroContext, h_errno,
1833  fileSystem, internalState @*/
1834  /*@modifies *fl, fl->processingFailed,
1835  fl->fileList, fl->fileListRecsAlloced, fl->fileListRecsUsed,
1836  fl->totalFileSize, fl->fileCount, fl->inFtw, fl->isDir,
1837  rpmGlobalMacroContext,
1838  fileSystem, internalState @*/;
1839 
1847 static int addFile(FileList fl, const char * diskURL,
1848  /*@null@*/ struct stat * statp)
1849  /*@globals rpmGlobalMacroContext, h_errno,
1850  fileSystem, internalState @*/
1851  /*@modifies *statp, *fl, fl->processingFailed,
1852  fl->fileList, fl->fileListRecsAlloced, fl->fileListRecsUsed,
1853  fl->totalFileSize, fl->fileCount,
1854  rpmGlobalMacroContext,
1855  fileSystem, internalState @*/
1856 {
1857  const char *fn = xstrdup(diskURL);
1858  const char *fileURL = fn;
1859  struct stat statbuf;
1860  mode_t fileMode;
1861  uid_t fileUid;
1862  gid_t fileGid;
1863  const char *fileUname;
1864  const char *fileGname;
1865  char *lang;
1866  rpmRC rc = RPMRC_OK;
1867 
1868  /* Path may have prepended buildRootURL, so locate the original filename. */
1869  /*
1870  * XXX There are 3 types of entry into addFile:
1871  *
1872  * From diskUrl statp
1873  * =====================================================
1874  * processBinaryFile path NULL
1875  * processBinaryFile glob result path NULL
1876  * recurseDir path stat
1877  *
1878  */
1879  { const char *fileName;
1880  int urltype = urlPath(fileURL, &fileName);
1881  switch (urltype) {
1882  case URL_IS_PATH:
1883  fileURL += (fileName - fileURL);
1884  if (fl->buildRootURL && strcmp(fl->buildRootURL, "/")) {
1885  size_t nb = strlen(fl->buildRootURL);
1886  const char * s = fileURL + nb;
1887  char * t = (char *) fileURL;
1888  (void) memmove(t, s, nb);
1889  }
1890  fileURL = fn;
1891  break;
1892  default:
1893  if (fl->buildRootURL && strcmp(fl->buildRootURL, "/"))
1894  fileURL += strlen(fl->buildRootURL);
1895  break;
1896  }
1897  }
1898 
1899  /* XXX make sure '/' can be packaged also */
1900  if (*fileURL == '\0')
1901  fileURL = "/";
1902 
1903  /* If we are using a prefix, validate the file */
1904  if (!fl->inFtw && fl->prefix) {
1905  const char *prefixTest;
1906  const char *prefixPtr = fl->prefix;
1907 
1908  (void) urlPath(fileURL, &prefixTest);
1909  while (*prefixPtr && *prefixTest && (*prefixTest == *prefixPtr)) {
1910  prefixPtr++;
1911  prefixTest++;
1912  }
1913  if (*prefixPtr || (*prefixTest && *prefixTest != '/')) {
1914  rpmlog(RPMLOG_ERR, _("File doesn't match prefix (%s): %s\n"),
1915  fl->prefix, fileURL);
1916  fl->processingFailed = 1;
1917  rc = RPMRC_FAIL;
1918  goto exit;
1919  }
1920  }
1921 
1922  if (statp == NULL) {
1923  statp = &statbuf;
1924  memset(statp, 0, sizeof(*statp));
1925  if (fl->devtype) {
1926  time_t now = time(NULL);
1927 
1928  /* XXX hack up a stat structure for a %dev(...) directive. */
1929  statp->st_nlink = 1;
1930  statp->st_rdev =
1931  ((fl->devmajor & 0xff) << 8) | (fl->devminor & 0xff);
1932  statp->st_dev = statp->st_rdev;
1933  statp->st_mode = (fl->devtype == 'b' ? S_IFBLK : S_IFCHR);
1934  statp->st_mode |= (fl->cur_ar.ar_fmode & 0777);
1935  statp->st_atime = now;
1936  statp->st_mtime = now;
1937  statp->st_ctime = now;
1938  } else if (Lstat(diskURL, statp)) {
1939  if (fl->currentFlags & RPMFILE_OPTIONAL) {
1940  rpmlog(RPMLOG_WARNING, _("Optional file not found: %s\n"), diskURL);
1941  rc = RPMRC_OK;
1942  } else {
1943  rpmlog(RPMLOG_ERR, _("File not found: %s\n"), diskURL);
1944  fl->processingFailed = 1;
1945  rc = RPMRC_FAIL;
1946  }
1947  goto exit;
1948  }
1949  }
1950 
1951  if ((! fl->isDir) && S_ISDIR(statp->st_mode)) {
1952 /*@-nullstate@*/ /* FIX: fl->buildRootURL may be NULL */
1953  rc = recurseDir(fl, diskURL);
1954  goto exit;
1955 /*@=nullstate@*/
1956  }
1957 
1958  fileMode = statp->st_mode;
1959  fileUid = statp->st_uid;
1960  fileGid = statp->st_gid;
1961 
1962  if (S_ISDIR(fileMode) && fl->cur_ar.ar_dmodestr) {
1963  fileMode &= S_IFMT;
1964  fileMode |= fl->cur_ar.ar_dmode;
1965  } else if (fl->cur_ar.ar_fmodestr != NULL) {
1966  fileMode &= S_IFMT;
1967  fileMode |= fl->cur_ar.ar_fmode;
1968  }
1969  if (fl->cur_ar.ar_user) {
1970  fileUname = getUnameS(fl->cur_ar.ar_user);
1971  } else {
1972  fileUname = getUname(fileUid);
1973  }
1974  if (fl->cur_ar.ar_group) {
1975  fileGname = getGnameS(fl->cur_ar.ar_group);
1976  } else {
1977  fileGname = getGname(fileGid);
1978  }
1979 
1980  /* Default user/group to builder's user/group */
1981  if (fileUname == NULL)
1982  fileUname = getUname(getuid());
1983  if (fileGname == NULL)
1984  fileGname = getGname(getgid());
1985 
1986  /* Add to the file list */
1987  if (fl->fileListRecsUsed == fl->fileListRecsAlloced) {
1988  fl->fileListRecsAlloced += 128;
1989  fl->fileList = xrealloc(fl->fileList,
1990  fl->fileListRecsAlloced * sizeof(*(fl->fileList)));
1991  }
1992 
1993  { FileListRec flp = &fl->fileList[fl->fileListRecsUsed];
1994  int i;
1995 
1996  flp->fl_st = *statp; /* structure assignment */
1997  flp->fl_mode = fileMode;
1998  flp->fl_uid = fileUid;
1999  flp->fl_gid = fileGid;
2000 
2001  flp->fileURL = xstrdup(fileURL);
2002  flp->diskURL = xstrdup(diskURL);
2003  flp->uname = fileUname;
2004  flp->gname = fileGname;
2005 
2006  if (fl->currentLangs && fl->nLangs > 0) {
2007  char * ncl;
2008  size_t nl = 0;
2009 
2010  for (i = 0; i < fl->nLangs; i++)
2011  nl += strlen(fl->currentLangs[i]) + 1;
2012 
2013  flp->langs = ncl = xmalloc(nl);
2014  for (i = 0; i < fl->nLangs; i++) {
2015  const char *ocl;
2016  if (i) *ncl++ = '|';
2017  for (ocl = fl->currentLangs[i]; *ocl != '\0'; ocl++)
2018  *ncl++ = *ocl;
2019  *ncl = '\0';
2020  }
2021  } else if (! parseForRegexLang(fileURL, &lang)) {
2022  flp->langs = xstrdup(lang);
2023  } else {
2024  flp->langs = xstrdup("");
2025  }
2026 
2027  flp->flags = fl->currentFlags;
2028  flp->specdFlags = fl->currentSpecdFlags;
2029  flp->verifyFlags = fl->currentVerifyFlags;
2030  }
2031 
2032  fl->fileListRecsUsed++;
2033  fl->fileCount++;
2034 
2035 exit:
2036 /*@i@*/ fn = _free(fn);
2037  return rc;
2038 }
2039 
2046 static rpmRC recurseDir(FileList fl, const char * diskURL)
2047 {
2048  char * ftsSet[2];
2049  FTS * ftsp;
2050  FTSENT * fts;
2051  int myFtsOpts = (FTS_COMFOLLOW | FTS_NOCHDIR | FTS_PHYSICAL);
2052  rpmRC rc = RPMRC_FAIL;
2053 
2054  fl->inFtw = 1; /* Flag to indicate file has buildRootURL prefixed */
2055  fl->isDir = 1; /* Keep it from following myftw() again */
2056 
2057  ftsSet[0] = (char *) diskURL;
2058  ftsSet[1] = NULL;
2059  ftsp = Fts_open(ftsSet, myFtsOpts, NULL);
2060  while ((fts = Fts_read(ftsp)) != NULL) {
2061  switch (fts->fts_info) {
2062  case FTS_D: /* preorder directory */
2063  case FTS_F: /* regular file */
2064  case FTS_SL: /* symbolic link */
2065  case FTS_SLNONE: /* symbolic link without target */
2066  case FTS_DEFAULT: /* none of the above */
2067  rc = addFile(fl, fts->fts_accpath, fts->fts_statp);
2068  /*@switchbreak@*/ break;
2069  case FTS_DOT: /* dot or dot-dot */
2070  case FTS_DP: /* postorder directory */
2071  rc = RPMRC_OK;
2072  /*@switchbreak@*/ break;
2073  case FTS_NS: /* stat(2) failed */
2074  case FTS_DNR: /* unreadable directory */
2075  case FTS_ERR: /* error; errno is set */
2076  case FTS_DC: /* directory that causes cycles */
2077  case FTS_NSOK: /* no stat(2) requested */
2078  case FTS_INIT: /* initialized only */
2079  case FTS_W: /* whiteout object */
2080  default:
2081  rc = RPMRC_FAIL;
2082  /*@switchbreak@*/ break;
2083  }
2084  if (rc != RPMRC_OK)
2085  break;
2086  }
2087  (void) Fts_close(ftsp);
2088 
2089  fl->isDir = 0;
2090  fl->inFtw = 0;
2091 
2092  return rc;
2093 }
2094 
2103 static rpmRC processMetadataFile(Package pkg, FileList fl, const char * fileURL,
2104  rpmTag tag)
2105  /*@globals rpmGlobalMacroContext, h_errno,
2106  fileSystem, internalState @*/
2107  /*@modifies pkg->header, *fl, fl->processingFailed,
2108  fl->fileList, fl->fileListRecsAlloced, fl->fileListRecsUsed,
2109  fl->totalFileSize, fl->fileCount,
2110  rpmGlobalMacroContext,
2111  fileSystem, internalState @*/
2112 {
2113  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
2114  const char * buildURL = "%{_builddir}/%{?buildsubdir}/";
2115  const char * fn = NULL;
2116  const char * apkt = NULL;
2117  rpmiob iob = NULL;
2118  rpmuint8_t * pkt = NULL;
2119  ssize_t pktlen = 0;
2120  int absolute = 0;
2121  rpmRC rc = RPMRC_FAIL;
2122  int xx;
2123 
2124  (void) urlPath(fileURL, &fn);
2125  if (*fn == '/') {
2126  fn = rpmGenPath(fl->buildRootURL, NULL, fn);
2127  absolute = 1;
2128  } else
2129  fn = rpmGenPath(buildURL, NULL, fn);
2130 
2131  switch (tag) {
2132  default:
2133  rpmlog(RPMLOG_ERR, _("%s: can't load unknown tag (%d).\n"),
2134  fn, tag);
2135  goto exit;
2136  /*@notreached@*/ break;
2137  case RPMTAG_PUBKEYS:
2138  if ((xx = pgpReadPkts(fn, &pkt, (size_t *)&pktlen)) <= 0) {
2139  rpmlog(RPMLOG_ERR, _("%s: public key read failed.\n"), fn);
2140  goto exit;
2141  }
2142  if (xx != PGPARMOR_PUBKEY) {
2143  rpmlog(RPMLOG_ERR, _("%s: not an armored public key.\n"), fn);
2144  goto exit;
2145  }
2146  apkt = pgpArmorWrap(PGPARMOR_PUBKEY, pkt, pktlen);
2147  break;
2148  case RPMTAG_POLICIES:
2149  xx = rpmiobSlurp(fn, &iob);
2150  if (!(xx == 0 && iob != NULL)) {
2151  rpmlog(RPMLOG_ERR, _("%s: *.te policy read failed.\n"), fn);
2152  goto exit;
2153  }
2154  apkt = (const char *) iob->b; /* XXX unsigned char */
2155  /* XXX steal the I/O buffer */
2156  iob->b = (rpmuint8_t *)xcalloc(1, sizeof(*iob->b));
2157  iob->blen = 0;
2158  break;
2159  }
2160 
2161  he->tag = tag;
2162  he->t = RPM_STRING_ARRAY_TYPE;
2163  he->p.argv = &apkt;
2164  he->c = 1;
2165  he->append = 1;
2166  xx = headerPut(pkg->header, he, 0);
2167  he->append = 0;
2168 
2169  rc = RPMRC_OK;
2170  if (absolute)
2171  rc = addFile(fl, fn, NULL);
2172 
2173 exit:
2174  apkt = _free(apkt);
2175  pkt = _free(pkt);
2176  iob = rpmiobFree(iob);
2177  fn = _free(fn);
2178  if (rc != RPMRC_OK)
2179  fl->processingFailed = 1;
2180  return rc;
2181 }
2182 
2190 static rpmRC processBinaryFile(/*@unused@*/ Package pkg, FileList fl,
2191  const char * fileURL)
2192  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
2193  /*@modifies *fl, fl->processingFailed,
2194  fl->fileList, fl->fileListRecsAlloced, fl->fileListRecsUsed,
2195  fl->totalFileSize, fl->fileCount,
2196  rpmGlobalMacroContext, fileSystem, internalState @*/
2197 {
2198  int quote = 1; /* XXX permit quoted glob characters. */
2199  int doGlob;
2200  const char *diskURL = NULL;
2201  rpmRC rc = RPMRC_OK;
2202  int xx;
2203 
2204  doGlob = Glob_pattern_p(fileURL, quote);
2205 
2206  /* Check that file starts with leading "/" */
2207  { const char * fileName;
2208  (void) urlPath(fileURL, &fileName);
2209  if (*fileName != '/') {
2210  rpmlog(RPMLOG_ERR, _("File needs leading \"/\": %s\n"),
2211  fileName);
2212  rc = RPMRC_FAIL;
2213  goto exit;
2214  }
2215  }
2216 
2217  /* Copy file name or glob pattern removing multiple "/" chars. */
2218  /*
2219  * Note: rpmGetPath should guarantee a "canonical" path. That means
2220  * that the following pathologies should be weeded out:
2221  * //bin//sh
2222  * //usr//bin/
2223  * /.././../usr/../bin//./sh
2224  */
2225  diskURL = rpmGenPath(fl->buildRootURL, NULL, fileURL);
2226 
2227  if (doGlob) {
2228  const char ** argv = NULL;
2229  int argc = 0;
2230  int i;
2231 
2232  /* XXX for %dev marker in file manifest only */
2233  if (fl->noGlob) {
2234  rpmlog(RPMLOG_ERR, _("Glob not permitted: %s\n"),
2235  diskURL);
2236  rc = RPMRC_FAIL;
2237  goto exit;
2238  }
2239 
2240  xx = rpmGlob(diskURL, &argc, &argv);
2241  if (xx == 0 && argc >= 1) {
2242  for (i = 0; i < argc; i++) {
2243  rc = addFile(fl, argv[i], NULL);
2244  argv[i] = _free(argv[i]);
2245  }
2246  argv = _free(argv);
2247  } else {
2248  if (fl->currentFlags & RPMFILE_OPTIONAL) {
2249  rpmlog(RPMLOG_WARNING, _("Optional file not found by glob: %s\n"),
2250  diskURL);
2251  rc = RPMRC_OK;
2252  } else {
2253  rpmlog(RPMLOG_ERR, _("File not found by glob: %s\n"),
2254  diskURL);
2255  rc = RPMRC_FAIL;
2256  }
2257  goto exit;
2258  }
2259  } else
2260  rc = addFile(fl, diskURL, NULL);
2261 
2262 exit:
2263  diskURL = _free(diskURL);
2264  if (rc != RPMRC_OK)
2265  fl->processingFailed = 1;
2266  return rc;
2267 }
2268 
2272  int installSpecialDoc, int test)
2273  /*@globals rpmGlobalMacroContext, h_errno,
2274  fileSystem, internalState@*/
2275  /*@modifies spec->macros,
2276  pkg->fi, pkg->fileList, pkg->specialDoc, pkg->header,
2277  rpmGlobalMacroContext, fileSystem, internalState @*/
2278 {
2279  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
2280  struct FileList_s fl;
2281  ARGV_t files = NULL;
2282  ARGV_t fp;
2283  const char *fileName;
2284  char buf[BUFSIZ];
2285  struct AttrRec_s arbuf;
2286  AttrRec specialDocAttrRec = &arbuf;
2287  char *specialDoc = NULL;
2288  int xx;
2289 
2290  nullAttrRec(specialDocAttrRec);
2291  pkg->fi = NULL;
2292 
2293  if (pkg->fileFile) {
2294  char *saveptr = NULL;
2295  char *filesFiles = xstrdup(pkg->fileFile);
2296 /*@-unrecog@*/
2297  char *token = strtok_r(filesFiles, ",", &saveptr);
2298 /*@=unrecog@*/
2299  do {
2300  const char *ffn;
2301  FILE * f;
2302  FD_t fd;
2303 
2304  /* XXX W2DO? urlPath might be useful here. */
2305  if (*token == '/') {
2306  ffn = rpmGetPath(token, NULL);
2307  } else {
2308  /* XXX FIXME: add %{buildsubdir} */
2309  ffn = rpmGetPath("%{_builddir}/",
2310  (spec->buildSubdir ? spec->buildSubdir : "") ,
2311  "/", token, NULL);
2312  }
2313 
2314  fd = Fopen(ffn, "r.fpio");
2315 
2316  if (fd == NULL || Ferror(fd)) {
2318  _("Could not open %%files file %s: %s\n"),
2319  ffn, Fstrerror(fd));
2320  ffn = _free(ffn);
2321  filesFiles = _free(filesFiles);
2322  return RPMRC_FAIL;
2323  }
2324  ffn = _free(ffn);
2325 
2326  /*@+voidabstract@*/ f = fdGetFp(fd); /*@=voidabstract@*/
2327  if (f != NULL) {
2328  while (fgets(buf, (int)sizeof(buf), f)) {
2329  handleComments(buf);
2330  if (expandMacros(spec, spec->macros, buf, sizeof(buf))) {
2331  rpmlog(RPMLOG_ERR, _("line: %s\n"), buf);
2332  filesFiles = _free(filesFiles);
2333  return RPMRC_FAIL;
2334  }
2335  pkg->fileList = rpmiobAppend(pkg->fileList, buf, 0);
2336  }
2337  }
2338  (void) Fclose(fd);
2339  } while((token = strtok_r(NULL, ",", &saveptr)) != NULL);
2340  filesFiles = _free(filesFiles);
2341  }
2342 
2343  /* Init the file list structure */
2344  memset(&fl, 0, sizeof(fl));
2345 
2346  fl.buildRootURL = rpmGenPath(spec->rootURL, "%{?buildroot}", NULL);
2347 
2348  he->tag = RPMTAG_DEFAULTPREFIX;
2349  xx = headerGet(pkg->header, he, 0);
2350  fl.prefix = he->p.str;
2351 
2352  fl.fileCount = 0;
2353  fl.totalFileSize = 0;
2354  fl.processingFailed = 0;
2355 
2356  fl.passedSpecialDoc = 0;
2357  fl.isSpecialDoc = 0;
2358 
2359  fl.isDir = 0;
2360  fl.inFtw = 0;
2361  fl.currentFlags = 0;
2362  fl.currentVerifyFlags = 0;
2363 
2364  fl.noGlob = 0;
2365  fl.devtype = 0;
2366  fl.devmajor = 0;
2367  fl.devminor = 0;
2368 
2369  nullAttrRec(&fl.cur_ar);
2370  nullAttrRec(&fl.def_ar);
2371  dupAttrRec(&root_ar, &fl.def_ar); /* XXX assume %defattr(-,root,root) */
2372 
2374  fl.nLangs = 0;
2375  fl.currentLangs = NULL;
2376 
2377  fl.currentSpecdFlags = 0;
2378  fl.defSpecdFlags = 0;
2379 
2380  fl.docDirCount = 0;
2381 #if defined(RPM_VENDOR_OPENPKG) /* no-default-doc-files */
2382  /* do not declare any files as %doc files by default. */
2383 #else
2384  fl.docDirs[fl.docDirCount++] = xstrdup("/usr/doc");
2385  fl.docDirs[fl.docDirCount++] = xstrdup("/usr/man");
2386  fl.docDirs[fl.docDirCount++] = xstrdup("/usr/info");
2387  fl.docDirs[fl.docDirCount++] = xstrdup("/usr/X11R6/man");
2388  fl.docDirs[fl.docDirCount++] = xstrdup("/usr/share/doc");
2389  fl.docDirs[fl.docDirCount++] = xstrdup("/usr/share/man");
2390  fl.docDirs[fl.docDirCount++] = xstrdup("/usr/share/info");
2391  fl.docDirs[fl.docDirCount++] = xstrdup("/usr/src/examples");
2392  fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_docdir}", NULL);
2393  fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_mandir}", NULL);
2394  fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_infodir}", NULL);
2395  fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_javadocdir}", NULL);
2396  fl.docDirs[fl.docDirCount++] = rpmGetPath("%{_examplesdir}", NULL);
2397 #endif
2398 
2399  fl.fileList = NULL;
2400  fl.fileListRecsAlloced = 0;
2401  fl.fileListRecsUsed = 0;
2402 
2403  xx = argvSplit(&files, rpmiobStr(pkg->fileList), "\n");
2404 
2405  for (fp = files; *fp != NULL; fp++) {
2406  const char * s;
2407  s = *fp;
2408  SKIPSPACE(s);
2409  if (*s == '\0')
2410  continue;
2411  fileName = NULL;
2412  /*@-nullpass@*/ /* LCL: buf is NULL ?!? */
2413  strncpy(buf, s, sizeof(buf)-1);
2414  buf[sizeof(buf)-1] = '\0';
2415  /*@=nullpass@*/
2416 
2417  /* Reset for a new line in %files */
2418  fl.isDir = 0;
2419  fl.inFtw = 0;
2420  fl.currentFlags = 0;
2421  /* turn explicit flags into %def'd ones (gosh this is hacky...) */
2422  fl.currentSpecdFlags = ((unsigned)fl.defSpecdFlags) >> 8;
2424  fl.isSpecialDoc = 0;
2425 
2426  fl.noGlob = 0;
2427  fl.devtype = 0;
2428  fl.devmajor = 0;
2429  fl.devminor = 0;
2430 
2431  /* XXX should reset to %deflang value */
2432  if (fl.currentLangs) {
2433  int i;
2434  for (i = 0; i < fl.nLangs; i++)
2435  /*@-unqualifiedtrans@*/
2436  fl.currentLangs[i] = _free(fl.currentLangs[i]);
2437  /*@=unqualifiedtrans@*/
2438  fl.currentLangs = _free(fl.currentLangs);
2439  }
2440  fl.nLangs = 0;
2441 
2442  dupAttrRec(&fl.def_ar, &fl.cur_ar);
2443 
2444  /*@-nullpass@*/ /* LCL: buf is NULL ?!? */
2445  if (parseForVerify(buf, &fl) != RPMRC_OK)
2446  continue;
2447  if (parseForAttr(buf, &fl) != RPMRC_OK)
2448  continue;
2449  if (parseForDev(buf, &fl) != RPMRC_OK)
2450  continue;
2451  if (parseForConfig(buf, &fl) != RPMRC_OK)
2452  continue;
2453  if (parseForLang(buf, &fl) != RPMRC_OK)
2454  continue;
2455  /*@-nullstate@*/ /* FIX: pkg->fileFile might be NULL */
2456  if (parseForSimple(spec, pkg, buf, &fl, &fileName) != RPMRC_OK)
2457  /*@=nullstate@*/
2458  continue;
2459  /*@=nullpass@*/
2460  if (fileName == NULL)
2461  continue;
2462 
2463  if (fl.isSpecialDoc) {
2464  /* Save this stuff for last */
2465  specialDoc = _free(specialDoc);
2466  specialDoc = xstrdup(fileName);
2467  dupAttrRec(&fl.cur_ar, specialDocAttrRec);
2468  } else if (fl.currentFlags & RPMFILE_PUBKEY) {
2469 /*@-nullstate@*/ /* FIX: pkg->fileFile might be NULL */
2470  (void) processMetadataFile(pkg, &fl, fileName, RPMTAG_PUBKEYS);
2471 /*@=nullstate@*/
2472  } else if (fl.currentFlags & RPMFILE_POLICY) {
2473 /*@-nullstate@*/ /* FIX: pkg->fileFile might be NULL */
2474  (void) processMetadataFile(pkg, &fl, fileName, RPMTAG_POLICIES);
2475 /*@=nullstate@*/
2476  } else {
2477 /*@-nullstate@*/ /* FIX: pkg->fileFile might be NULL */
2478  (void) processBinaryFile(pkg, &fl, fileName);
2479 /*@=nullstate@*/
2480  }
2481  }
2482 
2483  /* Now process special doc, if there is one */
2484  if (specialDoc) {
2485  if (installSpecialDoc) {
2486  int _missing_doc_files_terminate_build =
2487  rpmExpandNumeric("%{?_missing_doc_files_terminate_build}");
2488  rpmRC rc;
2489 
2490  rc = doScript(spec, RPMBUILD_STRINGBUF, "%doc", pkg->specialDoc, test);
2491  if (rc != RPMRC_OK && _missing_doc_files_terminate_build)
2492  fl.processingFailed = 1;
2493  }
2494 
2495  /* Reset for %doc */
2496  fl.isDir = 0;
2497  fl.inFtw = 0;
2498  fl.currentFlags = 0;
2500 
2501  fl.noGlob = 0;
2502  fl.devtype = 0;
2503  fl.devmajor = 0;
2504  fl.devminor = 0;
2505 
2506  /* XXX should reset to %deflang value */
2507  if (fl.currentLangs) {
2508  int i;
2509  for (i = 0; i < fl.nLangs; i++)
2510  /*@-unqualifiedtrans@*/
2511  fl.currentLangs[i] = _free(fl.currentLangs[i]);
2512  /*@=unqualifiedtrans@*/
2513  fl.currentLangs = _free(fl.currentLangs);
2514  }
2515  fl.nLangs = 0;
2516 
2517  dupAttrRec(specialDocAttrRec, &fl.cur_ar);
2518  freeAttrRec(specialDocAttrRec);
2519 
2520  /*@-nullstate@*/ /* FIX: pkg->fileFile might be NULL */
2521  (void) processBinaryFile(pkg, &fl, specialDoc);
2522  /*@=nullstate@*/
2523 
2524  specialDoc = _free(specialDoc);
2525  }
2526 
2527  files = argvFree(files);
2528 
2529  if (fl.processingFailed)
2530  goto exit;
2531 
2532  /* Verify that file attributes scope over hardlinks correctly. */
2533  if (checkHardLinks(&fl) && !rpmExpandNumeric("%{_hack_dontneed_PartialHardlinkSets}"))
2534  (void) rpmlibNeedsFeature(pkg->header,
2535  "PartialHardlinkSets", "4.0.4-1");
2536 
2537  /* XXX should tags be added if filelist is empty? */
2538  if (genCpioListAndHeader(&fl, &pkg->fi, pkg->header, 0) != RPMRC_OK)
2539  fl.processingFailed = 1;
2540 
2541  if (spec->timeCheck)
2542  timeCheck(spec->timeCheck, pkg->header);
2543 
2544 exit:
2545  fl.buildRootURL = _free(fl.buildRootURL);
2546  fl.prefix = _free(fl.prefix);
2547 
2548  freeAttrRec(&fl.cur_ar);
2549  freeAttrRec(&fl.def_ar);
2550 
2551  if (fl.currentLangs) {
2552  int i;
2553  for (i = 0; i < fl.nLangs; i++)
2554  /*@-unqualifiedtrans@*/
2555  fl.currentLangs[i] = _free(fl.currentLangs[i]);
2556  /*@=unqualifiedtrans@*/
2557  fl.currentLangs = _free(fl.currentLangs);
2558  }
2559 
2561  while (fl.docDirCount--)
2562  fl.docDirs[fl.docDirCount] = _free(fl.docDirs[fl.docDirCount]);
2563  return (fl.processingFailed ? RPMRC_FAIL : RPMRC_OK);
2564 }
2565 
2567 {
2568  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
2569  HeaderIterator hi;
2570  rpmiob sourceFiles;
2571  struct Source *srcPtr;
2572  static rpmTag classTag = 0xffffffff;
2573  int xx;
2574  size_t i;
2575 
2576  if (classTag == 0xffffffff)
2577  classTag = tagValue("Class");
2578 
2579  /* Only specific tags are added to the source package header */
2580  if (spec->packages && !spec->sourceHdrInit) {
2581  for (hi = headerInit(spec->packages->header);
2582  headerNext(hi, he, 0);
2583  he->p.ptr = _free(he->p.ptr))
2584  {
2585  switch (he->tag) {
2586  case RPMTAG_NAME:
2587  case RPMTAG_VERSION:
2588  case RPMTAG_RELEASE:
2589  case RPMTAG_DISTEPOCH:
2590  case RPMTAG_EPOCH:
2591  case RPMTAG_SUMMARY:
2592  case RPMTAG_DESCRIPTION:
2593  case RPMTAG_PACKAGER:
2594  case RPMTAG_DISTRIBUTION:
2595  case RPMTAG_DISTURL:
2596  case RPMTAG_VENDOR:
2597  case RPMTAG_LICENSE:
2598  case RPMTAG_GROUP:
2599  case RPMTAG_OS:
2600  case RPMTAG_ARCH:
2601  case RPMTAG_CHANGELOGTIME:
2602  case RPMTAG_CHANGELOGNAME:
2603  case RPMTAG_CHANGELOGTEXT:
2604  case RPMTAG_URL:
2605  case RPMTAG_BUGURL:
2606  case RPMTAG_ICON:
2607  case RPMTAG_GIF:
2608  case RPMTAG_XPM:
2609  case HEADER_I18NTABLE:
2610 #if defined(RPM_VENDOR_OPENPKG) /* propagate-provides-to-srpms */
2611  /* make sure the "Provides" headers are available for querying from the .src.rpm files. */
2612  case RPMTAG_PROVIDENAME:
2613  case RPMTAG_PROVIDEVERSION:
2614  case RPMTAG_PROVIDEFLAGS:
2615 #endif
2616  if (he->p.ptr)
2617  xx = headerPut(spec->sourceHeader, he, 0);
2618  /*@switchbreak@*/ break;
2619  default:
2620  if (classTag == he->tag && he->p.ptr != NULL)
2621  xx = headerPut(spec->sourceHeader, he, 0);
2622  /*@switchbreak@*/ break;
2623  }
2624  }
2625  hi = headerFini(hi);
2626 
2627  if (spec->BANames && spec->BACount > 0) {
2628  he->tag = RPMTAG_BUILDARCHS;
2629  he->t = RPM_STRING_ARRAY_TYPE;
2630  he->p.argv = spec->BANames;
2631  he->c = spec->BACount;
2632  xx = headerPut(spec->sourceHeader, he, 0);
2633  }
2634 
2635  /* Load arbitrary tags into srpm header. */
2636  if (spec->foo)
2637  for (i = 0; i < spec->nfoo; i++) {
2638  const char * str = spec->foo[i].str;
2639  rpmTag tag = spec->foo[i].tag;
2640  rpmiob iob = spec->foo[i].iob;
2641  char * s;
2642 
2643  if (str == NULL || iob == NULL)
2644  continue;
2645 
2646  /* XXX Special case %track interpreter for now. */
2647  if (!xstrcasecmp(str, "track")) {
2648  he->p.str = rpmExpand("%{?__vcheck}", NULL);
2649  if (!(he->p.str != NULL && he->p.str[0] != '\0')) {
2650  he->p.str = _free(he->p.str);
2651  continue;
2652  }
2653  he->tag = tagValue("Trackprog");
2654  he->t = RPM_STRING_TYPE;
2655  he->c = 1;
2656  xx = headerPut(spec->sourceHeader, he, 0);
2657  he->p.str = _free(he->p.str);
2658  }
2659 
2660  s = rpmiobStr(iob);
2661  he->tag = tag;
2662  he->append = headerIsEntry(spec->sourceHeader, tag);
2663  if (he->append) {
2664  he->t = RPM_STRING_ARRAY_TYPE;
2665  he->p.argv = (const char **) &s;
2666  he->c = 1;
2667  } else {
2668  he->t = RPM_STRING_TYPE;
2669  he->p.str = s;
2670  he->c = 1;
2671  }
2672  xx = headerPut(spec->sourceHeader, he, 0);
2673  he->append = 0;
2674  }
2675  }
2676 
2677  if (sfp != NULL && *sfp != NULL)
2678  sourceFiles = *sfp;
2679  else
2680  sourceFiles = rpmiobNew(0);
2681 
2682  /* Construct the source/patch tag entries */
2683  if (spec->specFile != NULL) /* XXX segfault avoidance */
2684  sourceFiles = rpmiobAppend(sourceFiles, spec->specFile, 1);
2685  if (spec->sourceHeader != NULL)
2686  for (srcPtr = spec->sources; srcPtr != NULL; srcPtr = srcPtr->next) {
2687  { const char * sfn;
2688 /*@-nullpass@*/ /* XXX getSourceDir returns NULL with bad flags. */
2689  sfn = rpmGetPath( ((srcPtr->flags & RPMFILE_GHOST) ? "!" : ""),
2690 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
2691  getSourceDir(srcPtr->flags, srcPtr->source), srcPtr->source, NULL);
2692 #else
2693  getSourceDir(srcPtr->flags), srcPtr->source, NULL);
2694 #endif
2695 /*@=nullpass@*/
2696  sourceFiles = rpmiobAppend(sourceFiles, sfn, 1);
2697  sfn = _free(sfn);
2698  }
2699 
2700  if (spec->sourceHdrInit)
2701  continue;
2702 
2703  if (srcPtr->flags & RPMFILE_SOURCE) {
2704  he->tag = RPMTAG_SOURCE;
2705  he->t = RPM_STRING_ARRAY_TYPE;
2706  he->p.argv = &srcPtr->source;
2707  he->c = 1;
2708  he->append = 1;
2709  xx = headerPut(spec->sourceHeader, he, 0);
2710  he->append = 0;
2711  if (srcPtr->flags & RPMFILE_GHOST) {
2712  he->tag = RPMTAG_NOSOURCE;
2713  he->t = RPM_UINT32_TYPE;
2714  he->p.ui32p = &srcPtr->num;
2715  he->c = 1;
2716  he->append = 1;
2717  xx = headerPut(spec->sourceHeader, he, 0);
2718  he->append = 0;
2719  }
2720  }
2721  if (srcPtr->flags & RPMFILE_PATCH) {
2722  he->tag = RPMTAG_PATCH;
2723  he->t = RPM_STRING_ARRAY_TYPE;
2724  he->p.argv = &srcPtr->source;
2725  he->c = 1;
2726  he->append = 1;
2727  xx = headerPut(spec->sourceHeader, he, 0);
2728  he->append = 0;
2729  if (srcPtr->flags & RPMFILE_GHOST) {
2730  he->tag = RPMTAG_NOPATCH;
2731  he->t = RPM_UINT32_TYPE;
2732  he->p.ui32p = &srcPtr->num;
2733  he->c = 1;
2734  he->append = 1;
2735  xx = headerPut(spec->sourceHeader, he, 0);
2736  he->append = 0;
2737  }
2738  }
2739  }
2740 
2741  if (sfp == NULL)
2742  sourceFiles = rpmiobFree(sourceFiles);
2743 
2744  spec->sourceHdrInit = 1;
2745 
2746 /*@-usereleased@*/
2747  return 0;
2748 /*@=usereleased@*/
2749 }
2750 
2752 {
2753  rpmiob sourceFiles, *sfp = &sourceFiles;
2754  int x, isSpec = 1;
2755  struct FileList_s fl;
2756  ARGV_t files = NULL;
2757  ARGV_t fp;
2758  int rc;
2759  /* srcdefattr: needed variables */
2760  char _srcdefattr_buf[BUFSIZ];
2761  char * _srcdefattr = rpmExpand("%{?_srcdefattr}", NULL);
2762  int xx;
2763 
2764  *sfp = rpmiobNew(0);
2765  x = initSourceHeader(spec, sfp);
2766 
2767  /* srcdefattr: initialize file list structure */
2768  memset(&fl, 0, sizeof(fl));
2769  if (_srcdefattr && *_srcdefattr) {
2770  xx = snprintf(_srcdefattr_buf, sizeof(_srcdefattr_buf), "%%defattr %s", _srcdefattr);
2771  _srcdefattr_buf[sizeof(_srcdefattr_buf)-1] = '\0';
2772  xx = parseForAttr(_srcdefattr_buf, &fl);
2773  }
2774 
2775  /* Construct the SRPM file list. */
2776  fl.fileList = xcalloc((spec->numSources + 1), sizeof(*fl.fileList));
2777  rc = fl.processingFailed = 0;
2778  fl.fileListRecsUsed = 0;
2779  fl.totalFileSize = 0;
2780  fl.prefix = NULL;
2781  fl.buildRootURL = NULL;
2782 
2783  xx = argvSplit(&files, rpmiobStr(*sfp), "\n");
2784 
2785  /* The first source file is the spec file */
2786  x = 0;
2787  for (fp = files; *fp != NULL; fp++) {
2788  const char * diskURL, *diskPath;
2789  FileListRec flp;
2790 
2791  diskURL = *fp;
2792  SKIPSPACE(diskURL);
2793  if (! *diskURL)
2794  continue;
2795 
2796  flp = &fl.fileList[x];
2797 
2798  flp->flags = isSpec ? RPMFILE_SPECFILE : 0;
2799  /* files with leading ! are no source files */
2800  if (*diskURL == '!') {
2801  flp->flags |= RPMFILE_GHOST;
2802  diskURL++;
2803  }
2804 
2805  (void) urlPath(diskURL, &diskPath);
2806 
2807  flp->diskURL = xstrdup(diskURL);
2808  diskPath = strrchr(diskPath, '/');
2809  if (diskPath)
2810  diskPath++;
2811  else
2812  diskPath = diskURL;
2813 
2814  flp->fileURL = xstrdup(diskPath);
2815  flp->verifyFlags = RPMVERIFY_ALL;
2816 
2817  if (Stat(diskURL, &flp->fl_st)) {
2818  rpmlog(RPMLOG_ERR, _("Bad file: %s: %s\n"),
2819  diskURL, strerror(errno));
2820  rc = fl.processingFailed = 1;
2821  }
2822 
2823 #if defined(RPM_VENDOR_OPENPKG) || defined(RPM_VENDOR_MANDRIVA) /* support-srcdefattr */
2824  /* srcdefattr: allow to set SRPM file attributes via %{_srcdefattr} macro */
2825  if (fl.def_ar.ar_fmodestr) {
2826  flp->fl_mode &= S_IFMT;
2827  flp->fl_mode |= fl.def_ar.ar_fmode;
2828  }
2829  flp->uname = fl.def_ar.ar_user ? getUnameS(fl.def_ar.ar_user) : getUname(flp->fl_uid);
2830  flp->gname = fl.def_ar.ar_group ? getGnameS(fl.def_ar.ar_group) : getGname(flp->fl_gid);
2831 #else
2832  flp->uname = getUname(flp->fl_uid);
2833  flp->gname = getGname(flp->fl_gid);
2834 #endif
2835  flp->langs = xstrdup("");
2836 
2837  if (! (flp->uname && flp->gname)) {
2838  rpmlog(RPMLOG_ERR, _("Bad owner/group: %s\n"), diskURL);
2839  rc = fl.processingFailed = 1;
2840  }
2841 
2842  isSpec = 0;
2843  x++;
2844  }
2845  fl.fileListRecsUsed = x;
2846  files = argvFree(files);
2847 
2848  if (rc)
2849  goto exit;
2850 
2851  /* XXX should tags be added if filelist is empty? */
2852  spec->fi = NULL;
2853  rc = genCpioListAndHeader(&fl, &spec->fi, spec->sourceHeader, 1);
2854 
2855 exit:
2856  *sfp = rpmiobFree(*sfp);
2858  _srcdefattr = _free(_srcdefattr);
2859  return rc;
2860 }
2861 
2867 static int checkUnpackagedFiles(Spec spec)
2868  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
2869  /*@modifies *spec->packages,
2870  rpmGlobalMacroContext, fileSystem, internalState @*/
2871 {
2872 /*@-readonlytrans@*/
2873  static const char * av_ckfile[] = { "%{?__check_files}", NULL };
2874 /*@=readonlytrans@*/
2875  rpmiob iob_stdout = NULL;
2876  const char * s;
2877  int rc;
2878  rpmiob fileList = NULL;
2879  Package pkg;
2880  int n = 0;
2881 
2882  s = rpmExpand(av_ckfile[0], NULL);
2883  if (!(s && *s)) {
2884  rc = -1;
2885  goto exit;
2886  }
2887  rc = 0;
2888 
2889  /* initialize fileList */
2890  fileList = rpmiobNew(0);
2891  for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
2892  int i;
2893 #ifndef DYING /* XXX rpmfiNew is necessary here. why?!? */
2894  rpmfi fi = rpmfiNew(NULL, pkg->header, RPMTAG_BASENAMES, 0);
2895 #else
2896  rpmfi fi = rpmfiLink(pkg->fi, __FUNCTION__);
2897 #endif
2898  fi = rpmfiInit(fi, 0);
2899  while ((i = rpmfiNext(fi)) >= 0) {
2900  const char *fn = rpmfiFN(fi);
2901  fileList = rpmiobAppend(fileList, fn, 1);
2902  n++;
2903  }
2904  fi = rpmfiFree(fi);
2905  }
2906 
2907  if (n == 0) {
2908  /* no packaged files, and buildroot may not exist -
2909  * no need to run check */
2910  rc = -1;
2911  goto exit;
2912  }
2913 
2914  rpmlog(RPMLOG_NOTICE, _("Checking for unpackaged file(s): %s\n"), s);
2915 
2916  rc = rpmfcExec(av_ckfile, fileList, &iob_stdout, 0);
2917  if (rc < 0)
2918  goto exit;
2919 
2920  if (iob_stdout) {
2921  int _unpackaged_files_terminate_build =
2922  rpmExpandNumeric("%{?_unpackaged_files_terminate_build}");
2923  const char * t;
2924 
2925  t = rpmiobStr(iob_stdout);
2926  if ((*t != '\0') && (*t != '\n')) {
2927  rc = (_unpackaged_files_terminate_build) ? 1 : 0;
2928  rpmlog((rc ? RPMLOG_ERR : RPMLOG_WARNING),
2929  _("Installed (but unpackaged) file(s) found:\n%s"), t);
2930  }
2931  }
2932 
2933 exit:
2934  fileList = rpmiobFree(fileList);
2935  iob_stdout = rpmiobFree(iob_stdout);
2936  s = _free(s);
2937  return rc;
2938 }
2939 
2940 /* auxiliary function for checkDuplicateFiles() */
2941 /* XXX need to pass Header because fi->h is NULL */
2942 static int fiIntersect(/*@null@*/ rpmfi fi1, /*@null@*/ rpmfi fi2,
2943  size_t buildrootL, int _duplicate_files_terminate_build)
2944  /*@globals internalState @*/
2945  /*@modifies fi1, fi2, internalState @*/
2946 {
2947  int n = 0;
2948  int i1, i2;
2949  const char *fn1, *fn2;
2950  rpmiob dups = NULL;
2951 
2952  if ((fi1 = rpmfiInit(fi1, 0)) != NULL)
2953  while ((i1 = rpmfiNext(fi1)) >= 0) {
2954  if (S_ISDIR(rpmfiFMode(fi1)))
2955  continue;
2956  fn1 = rpmfiFN(fi1);
2957  if ((fi2 = rpmfiInit(fi2, 0)) != NULL)
2958  while ((i2 = rpmfiNext(fi2)) >= 0) {
2959  if (S_ISDIR(rpmfiFMode(fi2)))
2960  /*@innercontinue@*/ continue;
2961  fn2 = rpmfiFN(fi2);
2962  if (strcmp(fn1, fn2))
2963  /*@innercontinue@*/ continue;
2964  if (!dups)
2965  dups = rpmiobNew(0);
2966  dups = rpmiobAppend(dups, "\t", 0);
2967  dups = rpmiobAppend(dups, fn1+buildrootL, 1);
2968  n++;
2969  }
2970  }
2971 
2972  if (n > 0) {
2973  const char *N1, *N2;
2974  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
2975 
2976  he->tag = RPMTAG_NVRA;
2977  N1 = (headerGet(fi1->h, he, 0) ? he->p.str : NULL);
2978  he->tag = RPMTAG_NVRA;
2979  N2 = (headerGet(fi2->h, he, 0) ? he->p.str : NULL);
2980 
2981  rpmlog(_duplicate_files_terminate_build ? RPMLOG_ERR : RPMLOG_WARNING,
2982  _("File(s) packaged into both %s and %s:\n%s"),
2983  N1, N2, rpmiobStr(dups));
2984 
2985  N1 = _free(N1);
2986  N2 = _free(N2);
2987  dups = rpmiobFree(dups);
2988  }
2989 
2990  return n;
2991 }
2992 
2998 static int checkDuplicateFiles(Spec spec, size_t buildrootL,
2999  int _duplicate_files_terminate_build)
3000  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
3001  /*@modifies *spec->packages,
3002  rpmGlobalMacroContext, fileSystem, internalState @*/
3003 {
3004  int n = 0;
3005  Package pkg1, pkg2;
3006 
3007  if (spec->packages) /* XXX segfault avoidance */
3008  for (pkg1 = spec->packages; pkg1->next; pkg1 = pkg1->next) {
3009 #ifdef DYING
3010  rpmfi fi1 = rpmfiNew(NULL, pkg1->header, RPMTAG_BASENAMES, 0);
3011 #else
3012  rpmfi fi1 = rpmfiLink(pkg1->fi, __FUNCTION__);
3013 #endif
3014  if (fi1 == NULL) continue;
3015  (void) rpmfiSetHeader(fi1, pkg1->header);
3016  for (pkg2 = pkg1->next; pkg2; pkg2 = pkg2->next) {
3017 #ifdef DYING
3018  rpmfi fi2 = rpmfiNew(NULL, pkg2->header, RPMTAG_BASENAMES, 0);
3019 #else
3020  rpmfi fi2 = rpmfiLink(pkg2->fi, __FUNCTION__);
3021 #endif
3022  if (fi2 == NULL) continue;
3023  (void) rpmfiSetHeader(fi2, pkg2->header);
3024  n += fiIntersect(fi1, fi2, buildrootL, _duplicate_files_terminate_build);
3025  (void) rpmfiSetHeader(fi2, NULL);
3026  fi2 = rpmfiFree(fi2);
3027  }
3028  (void) rpmfiSetHeader(fi1, NULL);
3029  fi1 = rpmfiFree(fi1);
3030  }
3031  return n;
3032 }
3033 
3034 /* auxiliary function: check if directory d is packaged */
3035 static int packagedDir(Package pkg, const char *d)
3036  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
3037  /*@modifies pkg->header,
3038  rpmGlobalMacroContext, fileSystem, internalState @*/
3039 {
3040  if(!rpmbfChk(rpmfiFNBF(pkg->fi), d, strlen(d)))
3041  return 0;
3042  char * fifn = (char *) xmalloc(pkg->fi->fnlen + 1);
3043  rpmuint32_t j;
3044  for(j = 0; j < pkg->fi->fc; j++) {
3045  const char * dn = NULL;
3046  (void) urlPath(pkg->fi->dnl[pkg->fi->dil[j]], &dn);
3047  strcpy(stpcpy(fifn, dn), pkg->fi->bnl[j]);
3048  if (!strcmp(d, fifn)) {
3049  free(fifn);
3050  return 1;
3051  }
3052  }
3053  free(fifn);
3054  return 0;
3055 }
3056 
3057 /* auxiliary function: find unpackaged subdirectories
3058  *
3059  * E.g. consider this %files section:
3060  * %dir /A
3061  * /A/B/C/D
3062  * Now directories "/A/B" and "/A/B/C" should also be packaged.
3063  */
3064 static int pkgUnpackagedSubdirs(Package pkg, size_t buildrootL, int _unpackaged_subdirs_terminate_build)
3065  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
3066  /*@modifies pkg->header,
3067  rpmGlobalMacroContext, fileSystem, internalState @*/
3068 {
3069  int n = 0;
3070  int i, j;
3071  char **unpackaged = NULL;
3072  char *fn;
3073 #ifdef DYING
3074  rpmfi fi = rpmfiNew(NULL, pkg->header, RPMTAG_BASENAMES, 0);
3075 #else
3076  rpmfi fi = rpmfiLink(pkg->fi, __FUNCTION__);
3077 #endif
3078 
3079  if (rpmfiFC(fi) <= 1) {
3080  fi = rpmfiFree(fi);
3081  return 0;
3082  }
3083  fn = alloca(rpmfiFNMaxLen(fi) + 1);
3084 
3085  fi = rpmfiInit(fi, 0);
3086  while ((i = rpmfiNext(fi)) >= 0) {
3087  int found = 0;
3088  /* make local copy of file name */
3089  char *p = fn;
3090  strcpy(fn, rpmfiFN(fi));
3091  /* find the first path component that is packaged */
3092  while ((p = strchr(p + 1, '/'))) {
3093  if (p - fn < buildrootL)
3094  continue; /* don't try to check components over buildroot */
3095  *p = '\0';
3096  found = packagedDir(pkg, fn);
3097  *p = '/';
3098  if (found)
3099  /*@innerbreak@*/ break;
3100  }
3101  if (!found)
3102  continue;
3103  /* other path components should be packaged, too */
3104  if (p != NULL)
3105  while ((p = strchr(p + 1, '/'))) {
3106  *p = '\0';
3107  if (packagedDir(pkg, fn)) {
3108  *p = '/';
3109  /*@innercontinue@*/ continue;
3110  }
3111  /* might be already added */
3112  found = 0;
3113  for (j = 0; j < n; j++)
3114  if (strcmp(fn, unpackaged[j]) == 0) {
3115  found = 1;
3116  /*@innerbreak@*/ break;
3117  }
3118  if (found) {
3119  *p = '/';
3120  /*@innercontinue@*/ continue;
3121  }
3122  unpackaged = xrealloc(unpackaged, sizeof(*unpackaged) * (n + 1));
3123  unpackaged[n++] = xstrdup(fn);
3124  *p = '/';
3125  }
3126  }
3127  fi = rpmfiFree(fi);
3128 
3129  if (n > 0) {
3130  const char *N;
3131  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
3132  rpmiob list = rpmiobNew(0);
3133 
3134  he->tag = RPMTAG_NVRA;
3135  N = (headerGet(pkg->header, he, 0) ? he->p.str : NULL);
3136 
3137  for (i = 0; i < n; i++) {
3138  list = rpmiobAppend(list, "\t", 0);
3139  list = rpmiobAppend(list, unpackaged[i]+buildrootL, 1);
3140  unpackaged[i] = _free(unpackaged[i]);
3141  }
3142  unpackaged = _free(unpackaged);
3143 
3144  rpmlog(_unpackaged_subdirs_terminate_build ? RPMLOG_ERR : RPMLOG_WARNING,
3145  _("Unpackaged subdir(s) in %s:\n%s"),
3146  N, rpmiobStr(list));
3147 
3148  N = _free(N);
3149  list = rpmiobFree(list);
3150  }
3151 
3152  return n;
3153 }
3154 
3160 static int checkUnpackagedSubdirs(Spec spec, size_t buildrootL, int _unpackaged_subdirs_terminate_build)
3161  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
3162  /*@modifies *spec->packages,
3163  rpmGlobalMacroContext, fileSystem, internalState @*/
3164 {
3165  int n = 0;
3166  Package pkg;
3167 
3168  for (pkg = spec->packages; pkg; pkg = pkg->next)
3169  n += pkgUnpackagedSubdirs(pkg, buildrootL, _unpackaged_subdirs_terminate_build);
3170  return n;
3171 }
3172 
3173 /*@-incondefs@*/
3174 rpmRC processBinaryFiles(Spec spec, int installSpecialDoc, int test)
3175 {
3176  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
3177  Package pkg;
3178  rpmRC res = RPMRC_OK;
3179 
3180  char *buildroot = rpmExpand("%{?buildroot}", NULL);
3181  size_t buildrootL = strlen(buildroot);
3182 
3183  buildroot = _free(buildroot);
3184 
3185  for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
3186  int rc;
3187 
3188  if (pkg->fileList == NULL)
3189  continue;
3190 
3191  (void) headerMacrosLoad(pkg->header);
3192 
3193  he->tag = RPMTAG_NVRA;
3194  rc = headerGet(pkg->header, he, 0);
3195  rpmlog(RPMLOG_NOTICE, _("Processing files: %s\n"), he->p.str);
3196  he->p.ptr = _free(he->p.ptr);
3197 
3198  if ((rc = processPackageFiles(spec, pkg, installSpecialDoc, test))) {
3199  res = RPMRC_FAIL;
3200  (void) headerMacrosUnload(pkg->header);
3201  break;
3202  }
3203 
3204  /* Finalize package scriptlets before extracting dependencies. */
3205  if ((rc = processScriptFiles(spec, pkg))) {
3206  res = rc;
3207  (void) headerMacrosUnload(pkg->header);
3208  break;
3209  }
3210 
3211  if ((rc = rpmfcGenerateDepends(spec, pkg))) {
3212  res = RPMRC_FAIL;
3213  (void) headerMacrosUnload(pkg->header);
3214  break;
3215  }
3216 
3217  /* XXX this should be earlier for deps to be entirely sorted. */
3218  providePackageNVR(pkg->header);
3219 
3220  (void) headerMacrosUnload(pkg->header);
3221  }
3222 
3223  if (res == RPMRC_OK) {
3224  int _duplicate_files_terminate_build =
3225  rpmExpandNumeric("%{?_duplicate_files_terminate_build}");
3226  int _unpackaged_subdirs_terminate_build =
3227  rpmExpandNumeric("%{?_unpackaged_subdirs_terminate_build}");
3228  if (checkUnpackagedFiles(spec) > 0)
3229  res = RPMRC_FAIL;
3230  if (checkDuplicateFiles(spec, buildrootL, _duplicate_files_terminate_build) > 0 &&
3231  _duplicate_files_terminate_build)
3232  res = RPMRC_FAIL;
3233  if (checkUnpackagedSubdirs(spec, buildrootL, _unpackaged_subdirs_terminate_build) > 0 &&
3234  _unpackaged_subdirs_terminate_build)
3235  res = RPMRC_FAIL;
3236  }
3237 
3238  return res;
3239 }
3240 /*@=incondefs@*/
int sourceHdrInit
Definition: rpmspec.h:174
int docDirCount
Definition: files.c:154
int headerMacrosUnload(Header h)
Define per-header macros.
Definition: hdrNVR.c:111
const bson * b
Definition: bson.h:280
rpmTagType t
Definition: rpmtag.h:504
Definition: iosm.h:34
#define FTS_SLNONE
Definition: fts.h:141
const char const double d
Definition: bson.h:800
static rpmRC processMetadataFile(Package pkg, FileList fl, const char *fileURL, rpmTag tag)
Add a pubkey/policy/icon to a binary package.
Definition: files.c:2103
const char * str
Definition: rpmtag.h:73
rpmTag tag
Definition: rpmtag.h:503
struct stat fl_st
Definition: files.c:71
const char ** argv
Definition: rpmtag.h:75
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
mongo_error_t const char * errstr
Definition: mongo.h:922
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:1439
const char const char size_t len
Definition: bson.h:823
unsigned devtype
Definition: files.c:134
const char bson_timestamp_t * ts
Definition: bson.h:1004
Package next
Definition: rpmspec.h:255
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:253
rpmRC processBinaryFiles(Spec spec, int installSpecialDoc, int test)
Post-build processing for binary package(s).
Definition: files.c:3174
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:321
rpmuint32_t * ui32p
Definition: rpmtag.h:70
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:120
char * rpmGetPath(const char *path,...)
Return (malloc'ed) expanded, canonicalized, file path.
Definition: macro.c:3431
const char * specFile
Definition: rpmspec.h:116
int headerGet(Header h, HE_t he, unsigned int flags)
Retrieve extension or tag value from a header.
Definition: header.c:2231
int headerPut(Header h, HE_t he, unsigned int flags)
Add or append tag container to header.
Definition: header.c:2294
Package file tree walk data.
Definition: files.c:120
#define FTS_W
Definition: fts.h:142
const char int time
Definition: bson.h:1005
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:251
HeaderIterator headerFini(HeaderIterator hi)
Destroy header tag container iterator.
Definition: header.c:2134
headerSprintfExtension rpmHeaderFormats
Table of query format extensions.
Definition: formats.c:305
rpmuint16_t * ui16p
Definition: rpmtag.h:69
#define FTS_SL
Definition: fts.h:140
HeaderIterator headerInit(Header h)
Create header tag iterator.
Definition: header.c:2144
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:1363
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:50
#define S_ISLNK(mode)
Definition: system.h:651
char * pgpArmorWrap(rpmuint8_t atype, const unsigned char *s, size_t ns)
Wrap a OpenPGP packets in ascii armor for transport.
Definition: rpmpgp.c:1749
int errno
Header sourceHeader
Definition: rpmspec.h:171
#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:2313
const char * rpmfiFN(rpmfi fi)
Return current file name from file info set.
Definition: rpmfi.c:163
unsigned short rpmuint16_t
Definition: rpmiotypes.h:27
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:162
Header tag iterator data structure.
Definition: header.c:2129
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:3064
struct AttrRec_s def_ar
Definition: files.c:144
const char ** BANames
Definition: rpmspec.h:147
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:2998
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:77
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:2158
int flag
Definition: files.c:301
struct Source * next
Definition: rpmspec.h:52
static rpmRC recurseDir(FileList fl, const char *diskURL)
Add directory (and all of its files) to the package manifest.
Definition: files.c:2046
char * headerSprintf(Header h, const char *fmt, headerTagTableEntry tags, headerSprintfExtension exts, errmsg_t *errmsg)
Return formatted output string from header tags.
Definition: hdrfmt.c:6730
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:2271
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:129
static int seenHardLink(FileList fl, FileListRec flp, ino_t *fileid)
Definition: files.c:1342
const char * source
Definition: rpmspec.h:48
static int dncmp(const void *a, const void *b)
Definition: files.c:1161
Definition: rpmspec.h:44
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:2942
const char * str
Definition: bson.h:593
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:1739
Header header
Definition: rpmspec.h:217
int rpmGlob(const char *patterns, int *argcPtr, const char ***argvPtr)
Return URL path(s) from a (URL prefixed) pattern glob.
Definition: macro.c:2607
unsigned int rpmuint32_t
Definition: rpmiotypes.h:28
struct _HE_s * HE_t
Definition: rpmtag.h:59
#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:2190
const char * Fstrerror(FD_t fd)
strerror(3) clone.
Definition: rpmio.c:2401
void * xcalloc(size_t nmemb, size_t size)
Definition: rpmmalloc.c:300
void * ptr
Definition: rpmtag.h:67
int fileListRecsAlloced
Definition: files.c:158
static int isHardLink(FileListRec flp, FileListRec tlp)
Definition: files.c:1334
int isDir
Definition: files.c:138
#define RPMVERIFY_ALL
Definition: rpmcli.h:162
unsigned devmajor
Definition: files.c:135
static rpmuint32_t getDigestAlgo(Header h, int isSrc)
Definition: files.c:1283
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:26
struct rpmfi_s * rpmfi
File info tag sets from a header, so that a header can be discarded early.
Definition: rpmfi.h:83
mode_t ar_fmode
Definition: files.c:108
rpmiob specialDoc
Definition: rpmspec.h:245
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:3035
rpmTagData p
Definition: rpmtag.h:506
MacroContext macros
Definition: rpmspec.h:177
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:1177
#define FTS_DOT
Definition: fts.h:133
#define HEADER_I18NTABLE
Definition: rpmtag.h:120
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:3477
const char * fileURL
Definition: files.c:85
unsigned verifyFlags
Definition: files.c:92
rpmTagCount c
Definition: rpmtag.h:507
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:330
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:113
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'ed) concatenated macro expansion(s).
Definition: macro.c:3238
const char * buildSubdir
Definition: rpmspec.h:118
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:198
int numSources
Definition: rpmspec.h:163
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
const char const bson int mongo_write_concern int flags
Definition: mongo.h:485
#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:3160
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:1093
int processSourceFiles(Spec spec)
Post-build processing for source package.
Definition: files.c:2751
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:1110
int BACount
Definition: rpmspec.h:148
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:112
#define MAXDOCDIR
Definition: files.c:50
Package packages
Definition: rpmspec.h:204
Definition: rpmtag.h:502
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:37
int noGlob
Definition: files.c:133
const char const int i
Definition: bson.h:778
static int xisdigit(int c)
Definition: rpmiotypes.h:546
const char * docDirs[1024]
Definition: files.c:153
urltype urlPath(const char *url, const char **pathp)
Return path component of URL.
Definition: url.c:430
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:157
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:756
struct rpmiob_s * rpmiob
Definition: rpmiotypes.h:60
rpmfi fi
Definition: filetriggers.h:15
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:1817
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:214
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:173
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:2747
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's.
#define FTS_F
Definition: fts.h:136
#define _(Text)
Definition: system.h:29
The structure used to store values for a package.
Definition: rpmspec.h:214
#define xmalloc
Definition: system.h:32
unsigned flags
Definition: files.c:90
#define SKIPNONWHITE(_x)
Definition: files.c:48
static int checkUnpackagedFiles(Spec spec)
Check for unpackaged files against what's in the build root.
Definition: files.c:2867
#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:1883
ARGstr_t * ARGV_t
Definition: argv.h:12
rpmfi fi
Definition: rpmspec.h:221
enum rpmTag_e rpmTag
Definition: rpmtag.h:470
#define SKIPSPACE(s)
Definition: rpmbuild.h:46
unsigned currentVerifyFlags
Definition: files.c:142
static int checkHardLinks(FileList fl)
Verify that file attributes scope over hardlinks correctly.
Definition: files.c:1130
tagStore_t foo
Definition: rpmspec.h:200
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:142
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:2566
void providePackageNVR(Header h)
Retrofit an explicit Provides: N = E:V-R dependency into package headers.
Definition: pack.c:454
int inFtw
Definition: files.c:139
int rpmExpandNumeric(const char *arg)
Return macro expansion as a numeric value.
Definition: macro.c:3312
int isSpecialDoc
Definition: files.c:131
#define FTS_ERR
Definition: fts.h:135
int flags
Definition: rpmspec.h:49
#define xrealloc
Definition: system.h:35
Definition: files.c:298
specdFlags_e
Definition: files.c:54
int j
Definition: mongo.h:438
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:1847
int rpmbfChk(rpmbf bf, const void *_s, size_t ns)
Check for item in a Bloom filter.
Definition: rpmbf.c:90
int rpmlibNeedsFeature(Header h, const char *feature, const char *featureEVR)
Add rpmlib feature dependency.
Definition: reqprov.c:212
unsigned int append
Definition: rpmtag.h:511