36 "@(#) Copyright (c) 1989, 1990, 1993\n\
37 The Regents of the University of California. All rights reserved.\n";
46 #if defined(__QNXNTO__)
47 #define st_mtimespec st_mtime
55 #undef _RPMFI_INTERNAL
56 #if defined(_RPMFI_INTERNAL)
57 #define _RPMAV_INTERNAL
66 #define RPM_LIST_HEAD(name, type) \
67 struct name { struct type *lh_first; }
68 #define RPM_LIST_ENTRY(type) \
69 struct { struct type *le_next;struct type **le_prev; }
70 #define RPM_LIST_EMPTY(head) \
71 ((head)->lh_first == NULL)
72 #define RPM_LIST_FIRST(head) \
74 #define RPM_LIST_NEXT(elm, field) \
75 ((elm)->field.le_next)
76 #define RPM_LIST_INIT(head) \
77 do { RPM_LIST_FIRST((head)) = NULL; } while (0)
78 #define RPM_LIST_INSERT_HEAD(head, elm, field) \
79 do { if ((RPM_LIST_NEXT((elm), field) = RPM_LIST_FIRST((head))) != NULL) \
80 RPM_LIST_FIRST((head))->field.le_prev = &RPM_LIST_NEXT((elm), field);\
81 RPM_LIST_FIRST((head)) = (elm); \
82 (elm)->field.le_prev = &RPM_LIST_FIRST((head)); } while (0)
83 #define RPM_LIST_FOREACH(var, head, field) \
84 for ((var) = RPM_LIST_FIRST((head)); (var); (var) = RPM_LIST_NEXT((var), field))
86 #define _MTREE_INTERNAL
89 #define _KFB(n) (1U << (n))
90 #define _MFB(n) (_KFB(n) | 0x40000000)
117 #if defined(_MTREE_INTERNAL)
158 #define F_BLOCK 0x001
195 #if defined(HAVE_STRUCT_STAT_ST_FLAGS)
210 #if defined(_RPMFI_INTERNAL)
260 #define MF_ISSET(_FLAG) ((mtreeFlags & ((MTREE_FLAGS_##_FLAG) & ~0x40000000)) != MTREE_FLAGS_NONE)
263 (MTREE_KEYS_GID | MTREE_KEYS_MODE | MTREE_KEYS_NLINK | MTREE_KEYS_SIZE | \
264 MTREE_KEYS_SLINK | MTREE_KEYS_TIME | MTREE_KEYS_UID)
266 #define MISMATCHEXIT 2
268 #define MBITS (S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO)
303 __attribute__ ((
format (printf, 1, 2)))
316 (
void) vfprintf(stderr, fmt, ap);
320 (
void)
fprintf(stderr,
_(
"%s: failed at line %d of the specification\n"),
330 #define NEEDVALUE 0xffffffff
375 keycompare(
const void * a,
const void *
b)
389 if (needvaluep !=
NULL)
395 sizeof(
keylist[0]), keycompare);
399 if (needvaluep !=
NULL)
400 *needvaluep = k->flags;
405 algo2tagname(uint32_t algo)
431 default: tagname =
NULL;
break;
436 #if defined(HAVE_STRUCT_STAT_ST_FLAGS)
438 flags_to_string(u_long fflags)
441 char *
string = fflagstostr(fflags);
442 if (
string !=
NULL && *
string ==
'\0') {
455 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
456 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
457 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
458 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
459 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
460 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
461 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
462 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
463 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
464 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
465 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
466 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
467 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
468 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
469 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
470 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
471 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
472 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
473 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
474 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
475 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
476 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
477 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
478 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
479 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
480 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
481 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
482 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
483 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
484 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
485 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
486 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
487 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
488 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
489 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
490 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
491 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
492 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
493 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
494 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
495 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
496 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
497 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
498 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
499 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
500 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
501 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
502 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
503 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
504 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
505 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
522 #define COMPUTE(var, ch) (var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)]
528 while ((nr =
Fread(buf,
sizeof(buf[0]),
sizeof(buf), fd)) != 0) {
530 for (len += nr, p = buf; nr--; ++
p) {
542 for (; len != 0; len >>= 8) {
547 *cval = (crc ^ 0xffffffff);
557 #define VIS_OCTAL 0x01
558 #define VIS_CSTYLE 0x02
567 #define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL)
568 #define VIS_SAFE 0x20
573 #define VIS_NOSLASH 0x40
578 #define UNVIS_VALID 1
579 #define UNVIS_VALIDPUSH 2
580 #define UNVIS_NOCHAR 3
581 #define UNVIS_SYNBAD -1
582 #define UNVIS_ERROR -2
589 static char *
vis(
char *dst,
int c,
int flag,
int nextc)
591 static int strvis(
char *dst,
const char *src,
int flag)
594 static int strnvis(
char *dst,
const char *src,
size_t siz,
int flag)
596 static int strvisx(
char *dst,
const char *src,
size_t len,
int flag)
599 static int strunvis(
char *dst,
const char *src)
601 static int unvis(
char *cp,
char c,
int *astate,
int flag)
604 #define isoctal(c) (((unsigned char)(c)) >= '0' && ((unsigned char)(c)) <= '7')
605 #define isvisible(c) \
606 (((unsigned)(c) <= (unsigned)UCHAR_MAX && isascii((unsigned char)(c)) && \
607 isgraph((unsigned char)(c))) \
608 || ((flag & VIS_SP) == 0 && (c) == (int)' ') \
609 || ((flag & VIS_TAB) == 0 && (c) == (int)'\t') \
610 || ((flag & VIS_NL) == 0 && (c) == (int)'\n') \
611 || ((flag & VIS_SAFE) \
612 && ((c) == (int)'\b' || (c) == (int)'\007' || (c) == (int)'\r')))
618 vis(
char * dst,
int c,
int flag,
int nextc)
674 *dst++ = ((
unsigned char)c >> 6 & 07) +
'0';
675 *dst++ = ((
unsigned char)c >> 3 & 07) +
'0';
676 *dst++ = ((
unsigned char)c & 07) +
'0';
690 *dst++ = (char)(c + (
int)
'@');
715 strvis(
char * dst,
const char * src,
int flag)
720 for (start = dst; (c = *src) !=
'\0';)
721 dst =
vis(dst, (
int)
c, flag, (
int)*++src);
723 return (dst - start);
728 strnvis(
char * dst,
const char * src,
size_t siz,
int flag)
733 for (start = dst, end = start + siz - 1; (c = *src) && dst < end; ) {
749 dst =
vis(dst, (
int)c, flag, (
int)*++src);
759 while ((c = *src) !=
'\0')
760 dst +=
vis(tbuf, (
int)c, flag, (
int)*++src) -
tbuf;
762 return (dst - start);
768 strvisx(
char * dst,
const char * src,
size_t len,
int flag)
773 for (start = dst; len > 1; len--) {
775 dst =
vis(dst, (
int)c, flag, (
int)*++src);
778 dst =
vis(dst, (
int)*src, flag, (
int)
'\0');
780 return (dst - start);
795 #if !defined(isoctal)
796 #define isoctal(c) (((unsigned char)(c)) >= '0' && ((unsigned char)(c)) <= '7')
803 unvis(
char *cp,
char c,
int *astate,
int flag)
831 case '0':
case '1':
case '2':
case '3':
832 case '4':
case '5':
case '6':
case '7':
918 *cp = (*cp << 3) + (c -
'0');
931 *cp = (*cp << 3) + (c -
'0');
962 while ((c = *src++) !=
'\0') {
964 switch (
unvis(dst, c, &state, 0)) {
981 return (dst - start);
987 #if defined(__linux__) || defined(__sun) || defined(__LCLINT__) || defined(__QNXNTO__)
988 #if !defined(HAVE_GETMODE) || !defined(HAVE_SETMODE)
991 #define SET_LEN_INCR 4
993 typedef struct bitcmd {
999 #define CMD2_CLR 0x01
1000 #define CMD2_SET 0x02
1001 #define CMD2_GBITS 0x04
1002 #define CMD2_OBITS 0x08
1003 #define CMD2_UBITS 0x10
1005 #if !defined(HAVE_GETMODE)
1013 getmode(
const void * bbox, mode_t omode)
1017 mode_t clrval, newmode,
value;
1019 set = (
const BITCMD *)bbox;
1021 for (value = 0;; set++)
1030 value = (newmode & S_IRWXU) >> 6;
1034 value = (newmode & S_IRWXG) >> 3;
1038 value = newmode & S_IRWXO;
1039 common:
if ((set->cmd2 & CMD2_CLR) !=
'\0') {
1040 clrval = (set->cmd2 & CMD2_SET) !=
'\0' ? S_IRWXO : value;
1041 if ((set->cmd2 & CMD2_UBITS) !=
'\0')
1042 newmode &= ~((clrval<<6) & set->bits);
1043 if ((set->cmd2 & CMD2_GBITS) !=
'\0')
1044 newmode &= ~((clrval<<3) & set->bits);
1045 if ((set->cmd2 & CMD2_OBITS) !=
'\0')
1046 newmode &= ~(clrval & set->bits);
1048 if ((set->cmd2 & CMD2_SET) !=
'\0') {
1049 if ((set->cmd2 & CMD2_UBITS) !=
'\0')
1050 newmode |= (value<<6) & set->bits;
1051 if ((set->cmd2 & CMD2_GBITS) !=
'\0')
1052 newmode |= (value<<3) & set->bits;
1053 if ((set->cmd2 & CMD2_OBITS) !=
'\0')
1054 newmode |= value & set->bits;
1059 newmode |= set->bits;
1063 newmode &= ~set->bits;
1067 if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH))
1068 newmode |= set->bits;
1073 #ifdef SETMODE_DEBUG
1074 (
void) printf(
"getmode:%04o -> %04o\n", omode, newmode);
1081 #if !defined(HAVE_SETMODE)
1082 #ifdef SETMODE_DEBUG
1084 dumpmode(BITCMD *set)
1086 for (; set->cmd; ++set)
1087 (
void) printf(
"cmd: '%c' bits %04o%s%s%s%s%s%s\n",
1088 set->cmd, set->bits, set->cmd2 ?
" cmd2:" :
"",
1089 set->cmd2 & CMD2_CLR ?
" CLR" :
"",
1090 set->cmd2 & CMD2_SET ?
" SET" :
"",
1091 set->cmd2 & CMD2_UBITS ?
" UBITS" :
"",
1092 set->cmd2 & CMD2_GBITS ?
" GBITS" :
"",
1093 set->cmd2 & CMD2_OBITS ?
" OBITS" :
"");
1097 #define ADDCMD(a, b, c, d) \
1098 if (set >= endset) { \
1100 setlen += SET_LEN_INCR; \
1101 newset = realloc(saveset, sizeof(*newset) * setlen); \
1102 if (newset == NULL) { \
1103 if (saveset != NULL) \
1108 set = newset + (set - saveset); \
1110 endset = newset + (setlen - 2); \
1112 set = addcmd(set, (a), (b), (c), (d))
1114 #define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
1117 addcmd( BITCMD *set,
int op,
int who,
int oparg,
unsigned mask)
1123 set->bits = who ? who : (
int) STANDARD_BITS;
1131 set->cmd = (char)op;
1132 set->bits = (who ? (
unsigned)who : mask) & oparg;
1138 set->cmd = (char)op;
1140 set->cmd2 = (char)( ((who & S_IRUSR) ? CMD2_UBITS : 0) |
1141 ((who & S_IRGRP) ? CMD2_GBITS : 0) |
1142 ((who & S_IROTH) ? CMD2_OBITS : 0));
1143 set->bits = (mode_t)~0;
1145 set->cmd2 =(char)(CMD2_UBITS | CMD2_GBITS | CMD2_OBITS);
1149 if (oparg == (
int)
'+')
1150 set->cmd2 |= CMD2_SET;
1151 else if (oparg == (
int)
'-')
1152 set->cmd2 |= CMD2_CLR;
1153 else if (oparg == (
int)
'=')
1154 set->cmd2 |= CMD2_SET|CMD2_CLR;
1167 compress_mode( BITCMD *set)
1171 int setbits, clrbits, Xbits,
op;
1173 for (nset = set;;) {
1175 while ((op = (
int)nset->cmd) != (
int)
'+' && op != (
int)
'-' && op != (
int)
'X') {
1181 for (setbits = clrbits = Xbits = 0;; nset++) {
1182 if ((op = (
int)nset->cmd) == (
int)
'-') {
1183 clrbits |= nset->bits;
1184 setbits &= ~nset->bits;
1185 Xbits &= ~nset->bits;
1186 }
else if (op == (
int)
'+') {
1187 setbits |= nset->bits;
1188 clrbits &= ~nset->bits;
1189 Xbits &= ~nset->bits;
1190 }
else if (op == (
int)
'X')
1191 Xbits |= nset->bits & ~setbits;
1198 set->bits = clrbits;
1204 set->bits = setbits;
1219 setmode(
const char *
p)
1225 BITCMD *set, *saveset, *endset;
1226 sigset_t sigset, sigoset;
1228 int equalopdone = 0;
1229 int permXbits, setlen;
1241 (
void) sigfillset(&sigset);
1242 (
void) sigprocmask(SIG_BLOCK, &sigset, &sigoset);
1243 (
void) umask(mask = umask(0));
1245 (
void) sigprocmask(SIG_SETMASK, &sigoset,
NULL);
1247 setlen = SET_LEN + 2;
1249 if ((set = malloc((
unsigned)(
sizeof(*set) * setlen))) ==
NULL)
1252 endset = set + (setlen - 2);
1259 perml = strtol(p,
NULL, 8);
1261 if (perml < 0 || (perml & ~(STANDARD_BITS|S_ISTXT)))
1267 perm = (
int)(mode_t)perml;
1268 while (*++p !=
'\0')
1269 if (*p < '0' || *p >
'7') {
1273 ADDCMD((
int)
'=', (
int)(STANDARD_BITS|S_ISTXT), perm, (
unsigned)mask);
1283 for (who = 0;; ++
p) {
1286 who |= STANDARD_BITS;
1289 who |= S_ISUID|S_IRWXU;
1292 who |= S_ISGID|S_IRWXG;
1302 getop:
if ((op = *p++) !=
'+' && op !=
'-' && op !=
'=') {
1310 for (perm = 0, permXbits = 0;; ++
p) {
1313 perm |= S_IRUSR|S_IRGRP|S_IROTH;
1320 if (who == 0 || (who & ~S_IRWXO))
1321 perm |= S_ISUID|S_ISGID;
1328 if (who == 0 || (who & ~S_IRWXO)) {
1334 perm |= S_IWUSR|S_IWGRP|S_IWOTH;
1337 permXbits = (
int)(S_IXUSR|S_IXGRP|S_IXOTH);
1340 perm |= S_IXUSR|S_IXGRP|S_IXOTH;
1351 ADDCMD((
int)op, who, perm, (
unsigned)mask);
1356 if (op ==
'+' && permXbits) {
1357 ADDCMD((
int)
'X', who, permXbits, (
unsigned)mask);
1360 ADDCMD((
int)*p, who, (
int)op, (
unsigned)mask);
1368 if (perm || (op ==
'=' && !equalopdone)) {
1371 ADDCMD((
int)op, who, perm, (
unsigned)mask);
1375 ADDCMD((
int)
'X', who, permXbits, (
unsigned)mask);
1389 #ifdef SETMODE_DEBUG
1390 (
void) printf(
"Before compress_mode()\n");
1393 compress_mode(saveset);
1394 #ifdef SETMODE_DEBUG
1395 (
void) printf(
"After compress_mode()\n");
1408 set(
char *
t,
NODE * ip)
1420 if (needvalue && (val = strtok(
NULL,
" \t\n")) ==
NULL)
1425 ip->
cksum = strtoul(val, &ep, 10);
1430 #if defined(HAVE_STRUCT_STAT_ST_FLAGS)
1431 if (!
strcmp(val,
"none")) {
1432 ip->
sb.st_flags = 0;
1435 {
unsigned long fset, fclr;
1436 if (strtofflags(&val, &fset, &fclr))
1438 ip->
sb.st_flags = fset;
1443 ip->
sb.st_gid = strtoul(val, &ep, 10);
1456 if ((m = setmode(val)) ==
NULL)
1458 ip->
sb.st_mode = getmode(m, 0);
1462 ip->
sb.st_nlink = strtoul(val, &ep, 10);
1472 ip->
sb.st_size = strtoul(val, &ep, 10);
1480 fprintf(stderr,
_(
"%s: filename (%s) encoded incorrectly\n"),
1483 strcpy(ip->
slink, val);
1487 #if defined(TIMEVAL_TO_TIMESPEC)
1488 ip->
sb.st_mtimespec.tv_sec = strtoul(val, &ep, 10);
1492 ip->
sb.st_mtimespec.tv_nsec = strtoul(val, &ep, 10);
1496 ip->
sb.st_mtime = strtoul(val, &ep, 10);
1500 (
void) strtoul(val, &ep, 10);
1508 if (!
strcmp(val,
"block"))
1512 if (!
strcmp(val,
"char"))
1520 if (!
strcmp(val,
"file"))
1522 if (!
strcmp(val,
"fifo"))
1526 if (!
strcmp(val,
"link"))
1530 if (!
strcmp(val,
"socket"))
1538 ip->
sb.st_uid = strtoul(val, &ep, 10);
1559 unset(
char * t,
NODE * ip)
1565 while ((p = strtok(t,
"\n\t ")) !=
NULL)
1569 #define KF_ISSET(_keys, _KEY) ((_keys) & (MTREE_KEYS_##_KEY))
1588 memset(&ginfo, 0,
sizeof(ginfo));
1589 for (fts->
lineno = 1; fgets(buf, (
int)
sizeof(buf), fp) !=
NULL;
1590 ++fts->
lineno, c_cur = c_next, c_next = 0)
1597 if ((p = strchr(buf,
'\n')) ==
NULL)
1601 if (p[-1] ==
'\\') {
1610 for (p = buf; *p && isspace(*p); ++
p);
1613 if (*p ==
'\0' || *p ==
'#')
1626 if ((p = strtok(p,
"\n\t ")) ==
NULL)
1632 if (
strcmp(p + 1,
"set"))
1637 if (
strcmp(p + 1,
"unset"))
1639 unset(
NULL, &ginfo);
1643 #if !defined(_RPMFI_INTERNAL)
1644 if (strchr(p,
'/') !=
NULL)
1664 centry =
xcalloc(1,
sizeof(*centry) + strlen(p));
1670 fprintf(stderr,
_(
"%s: filename (%s) encoded incorrectly\n"),
1672 strcpy(centry->
name, p);
1677 last = root = centry;
1681 }
else if (centry->
name[0] ==
'.' && centry->
name[1] ==
'\0') {
1682 centry->
prev = root;
1683 last = root = root->
next = centry;
1687 last = last->
child = centry;
1690 centry->
prev = last;
1691 last = last->
next = centry;
1701 ftype(
unsigned type)
1706 case F_CHAR:
return "char";
1707 case F_DIR:
return "dir";
1708 case F_FIFO:
return "fifo";
1709 case F_FILE:
return "file";
1710 case F_LINK:
return "link";
1711 case F_SOCK:
return "socket";
1712 default:
return "unknown";
1719 inotype(mode_t
mode)
1722 switch(mode & S_IFMT) {
1723 case S_IFBLK:
return "block";
1724 case S_IFCHR:
return "char";
1725 case S_IFDIR:
return "dir";
1726 case S_IFIFO:
return "fifo";
1727 case S_IFREG:
return "file";
1728 case S_IFLNK:
return "link";
1732 default:
return "unknown";
1763 #define FF(a, b, c, d) \
1764 (((a)->flags & (c)) && ((b)->flags & (c)) && ((a)->d) != ((b)->d))
1765 #define FS(a, b, c, d) \
1766 (((a)->flags & (c)) && ((b)->flags & (c)) && strcmp((a)->d,(b)->d))
1767 #define FM(a, b, c, d) \
1768 (((a)->flags & (c)) && ((b)->flags & (c)) && memcmp(&(a)->d,&(b)->d, sizeof (a)->d))
1775 printf(
"%s%s %s", path, n->
name, ftype((
unsigned)n->
type));
1777 printf(
" cksum=%lu", (
unsigned long) n->
cksum);
1779 printf(
" gid=%lu", (
unsigned long) n->
sb.st_gid);
1783 printf(
" gname=%s", gname);
1785 printf(
" gid=%lu", (
unsigned long) n->
sb.st_gid);
1788 printf(
" mode=%o", (
unsigned) n->
sb.st_mode);
1790 printf(
" nlink=%lu", (
unsigned long) n->
sb.st_nlink);
1793 printf(
" size=%llu", (
unsigned long long)n->
sb.st_size);
1796 printf(
" uid=%lu", (
unsigned long) n->
sb.st_uid);
1800 printf(
" uname=%s", uname);
1802 printf(
" uid=%lu", (
unsigned long) n->
sb.st_uid);
1812 const char * tagname = algo2tagname(algo);
1813 if (tagname !=
NULL)
1814 printf(
" %s=%s", tagname, n->
digests[i]);
1818 #if defined(HAVE_STRUCT_STAT_ST_FLAGS)
1821 const char * fflags = flags_to_string(n->
sb.st_flags);
1822 printf(
" flags=%s", fflags);
1823 fflags =
_free(fflags);
1837 shownode(n1, differ, path);
1842 shownode(n2, differ, path);
1845 if (!(differ & keys))
1848 shownode(n1, differ, path);
1850 shownode(n2, differ, path);
1855 compare_nodes(
NODE *n1,
NODE *n2,
const char *path)
1867 differs = n2->
flags;
1868 xx = mismatch(n1, n2, differs, path);
1872 differs = n1->
flags;
1873 xx = mismatch(n1, n2, differs, path);
1878 xx = mismatch(n1, n2, differs, path);
1925 #if defined(HAVE_STRUCT_STAT_ST_FLAGS)
1931 xx = mismatch(n1, n2, differs, path);
1938 mtreeSWalk(
NODE *t1,
NODE *t2,
const char *path)
1973 if (asprintf(&np,
"%s%s/", path, c2->
name)) {
1976 i = mtreeSWalk(c1, c2, np);
1978 i += compare_nodes(c1, c2, path);
1980 if (asprintf(&np,
"%s%s/", path, c1->
name)) {
1983 i = mtreeSWalk(c1, c2, np);
1985 i += compare_nodes(c1, c2, path);
1986 }
else if (c1 ==
NULL || c2 ==
NULL) {
1987 i = compare_nodes(c1, c2, path);
1989 if (asprintf(&np,
"%s%s/", path, c1->
name)) {
1992 i = mtreeSWalk(c1, c2, np);
1994 i += compare_nodes(c1, c2, path);
1996 i = compare_nodes(c1, c2, path);
2013 rval = mtreeSWalk(root1, root2,
"");
2014 rval += compare_nodes(root1, root2,
"");
2022 rlink(
const char * name)
2030 if ((len =
Readlink(name, lbuf,
sizeof(lbuf)-1)) == -1)
2036 #define SKIPDOTSLASH(_f) ((_f)[0] == '.' && (_f)[1] == '/' ? (_f) + 2 : (_f))
2038 #define COMPAREINDENTNAMELEN 8
2041 (void) printf(_("%s changed\n"), SKIPDOTSLASH(p->fts_path)); \
2046 static const char * algo2name(uint32_t algo)
2072 default:
return "Unknown";
2083 const char * name = s->
name;
2090 const char *tab =
"";
2094 if (!S_ISBLK(st->st_mode))
2098 if (!S_ISCHR(st->st_mode))
2102 if (!S_ISDIR(st->st_mode))
2106 if (!S_ISFIFO(st->st_mode))
2110 if (!S_ISREG(st->st_mode))
2121 (
void) printf(
_(
"\ttype expected %s found %s)\n"),
2122 ftype((
unsigned)s->
type), inotype(st->st_mode));
2131 (
void) printf(
_(
"%s%s expected %lu found %lu"), tab,
"user",
2132 (
unsigned long)s->
sb.st_uid, (
unsigned long)st->st_uid);
2134 if (
Chown(fts_accpath, s->
sb.st_uid, -1))
2135 (
void) printf(
_(
" not modified: %s)\n"), strerror(
errno));
2137 (
void) printf(
_(
" modified)\n"));
2139 (
void) printf(
"\n");
2144 (
void) printf(
_(
"%s%s expected %lu found %lu"), tab,
"gid",
2145 (
unsigned long)s->
sb.st_gid, (
unsigned long)st->st_gid);
2147 if (
Chown(fts_accpath, -1, s->
sb.st_gid))
2148 (
void) printf(
_(
" not modified: %s)\n"), strerror(
errno));
2150 (
void) printf(
_(
" modified)\n"));
2152 (
void) printf(
"\n");
2157 mode_t tmode = s->
sb.st_mode;
2158 mode_t mode = (st->st_mode &
MBITS);
2165 if (!((tmode & ~(S_IRWXU|S_IRWXG|S_IRWXO))
2166 || (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO))))
2167 if ((mode | tmode) == tmode)
2171 (
void) printf(
_(
"%s%s expected %#o found %#o"), tab,
"permissions",
2174 if (
Chmod(fts_accpath, s->
sb.st_mode))
2175 (
void) printf(
_(
" not modified: %s)\n"), strerror(
errno));
2177 (
void) printf(
_(
" modified)\n"));
2179 (
void) printf(
"\n");
2185 s->
sb.st_nlink != st->st_nlink)
2188 (
void) printf(
_(
"%s%s expected %lu found %lu)\n"), tab,
"link_count",
2189 (
unsigned long)s->
sb.st_nlink, (
unsigned long)st->st_nlink);
2192 if (
KF_ISSET(keys, SIZE) && s->
sb.st_size != st->st_size) {
2195 (
void) printf(
_(
"%s%s expected %llu found %llu\n"), tab,
"size",
2196 (
unsigned long long)s->
sb.st_size,
2197 (
unsigned long long)st->st_size);
2210 struct timeval tv[2];
2213 #if defined(TIMESPEC_TO_TIMEVAL)
2217 tv[0].tv_sec = (long)s->
sb.st_mtime;
2219 tv[1].tv_sec = (
long)st->st_mtime;
2223 if (tv[0].tv_sec != tv[1].tv_sec
2225 || tv[0].tv_usec != tv[1].tv_usec
2228 time_t t1 = (time_t)tv[0].tv_sec;
2229 time_t t2 = (time_t)tv[1].tv_sec;
2231 (
void) printf(
_(
"%s%s expected %.24s "), tab,
"modification time", ctime(&t1));
2232 (
void) printf(
_(
"found %.24s"), ctime(&t2));
2235 if (
Utimes(fts_accpath, tv))
2236 (
void) printf(
_(
" not modified: %s)\n"), strerror(
errno));
2238 (
void) printf(
_(
" modified\n"));
2240 (
void) printf(
"\n");
2247 FD_t fd =
Fopen(fts_accpath,
"r.ufdio");
2253 (
void) printf(
"%scksum: %s: %s\n", tab, fts_accpath,
Fstrerror(fd));
2264 i = crc(fd, &val, &vlen);
2266 char buffer[16 * 1024];
2267 while (
Fread(buffer,
sizeof(buffer[0]),
sizeof(buffer), fd) > 0)
2269 i = (
Ferror(fd) ? 1 : 0);
2273 (
void) printf(
"%scksum: %s: %s\n", tab, fts_accpath,
Fstrerror(fd));
2279 if (s->
cksum != val) {
2281 (
void) printf(
_(
"%s%s expected %lu found %lu\n"), tab,
"cksum",
2282 (
unsigned long) s->
cksum, (
unsigned long)
val);
2290 static int asAscii = 1;
2293 size_t digestlen = 0;
2299 printf(
_(
"%s%s expected %s found %s\n"), tab, algo2name(algo),
2303 digest =
_free(digest);
2319 (
void) printf(
_(
"%s%s expected %s found %s\n"), tab,
"link_ref",
2322 #if defined(HAVE_STRUCT_STAT_ST_FLAGS)
2323 if (
KF_ISSET(keys, FLAGS) && s->
sb.st_flags != st->st_flags) {
2327 fflags = fflagstostr(s->
sb.st_flags);
2328 (
void) printf(
_(
"%s%s expected \"%s\""), tab,
"flags", fflags);
2329 fflags =
_free(fflags);
2331 fflags = fflagstostr(st->st_flags);
2332 (
void) printf(
_(
" found \"%s\""), fflags);
2333 fflags =
_free(fflags);
2336 if (chflags(fts_accpath, s->
sb.st_flags))
2337 (
void) printf(
" not modified: %s)\n", strerror(
errno));
2339 (
void) printf(
" modified)\n");
2342 (
void) printf(
"\n");
2351 #define _FTSCALLOC(_p, _n) \
2353 (_p) = _free(_p); (_p) = xcalloc((_n), sizeof(*(_p))); \
2357 mtreeVisitD(rpmfts fts)
2362 const FTSENT *
const parent = fts->
p;
2368 #if defined(HAVE_STRUCT_STAT_ST_FLAGS)
2369 unsigned long maxflags = 0;
2384 #if defined(HAVE_STRUCT_STAT_ST_FLAGS)
2392 if (
MF_ISSET(DIRSONLY) || !S_ISDIR(st->st_mode))
2396 { mode_t st_mode = st->st_mode &
MBITS;
2397 if (st_mode < fts->
maxm && ++fts->
m[st_mode] > maxmode) {
2398 sb.st_mode = st_mode;
2399 maxmode = fts->
m[st_mode];
2403 if (st->st_gid < fts->
maxg && ++fts->
g[st->st_gid] > maxgid) {
2404 sb.st_gid = st->st_gid;
2405 maxgid = fts->
g[st->st_gid];
2408 if (st->st_uid < fts->
maxu && ++fts->
u[st->st_uid] > maxuid) {
2409 sb.st_uid = st->st_uid;
2410 maxuid = fts->
u[st->st_uid];
2412 #if defined(HAVE_STRUCT_STAT_ST_FLAGS)
2419 #define FLAGS2IDX(f) ((f & 0xf) | ((f >> 12) & 0xf0))
2421 {
unsigned long st_flags = FLAGS2IDX(st->st_flags);
2422 if (st_flags < fts->maxf && ++fts->f[st_flags] > maxflags) {
2424 sb.st_flags = st->st_flags;
2425 maxflags = fts->f[st_flags];
2436 if (((
KF_ISSET(keys, UNAME) ||
KF_ISSET(keys, UID)) && (fts->
sb.st_uid != sb.st_uid))
2438 || (
KF_ISSET(keys, MODE) && (fts->
sb.st_mode != sb.st_mode))
2439 #
if defined(HAVE_STRUCT_STAT_ST_FLAGS)
2440 || (
KF_ISSET(keys, FLAGS) && (fts->
sb.st_flags != sb.st_flags))
2446 (
void) printf(
"/set type=dir");
2448 (
void) printf(
"/set type=file");
2452 (
void) printf(
" uname=%s", uname);
2454 fprintf(stderr,
_(
"%s: Could not get uname for uid=%lu\n"),
2458 (
unsigned long)sb.st_uid);
2461 (
void) printf(
" uid=%lu", (
unsigned long)sb.st_uid);
2465 (
void) printf(
" gname=%s", gname);
2467 fprintf(stderr,
_(
"%s: Could not get gname for gid=%lu\n"),
2471 (
unsigned long) sb.st_gid);
2474 (
void) printf(
" gid=%lu", (
unsigned long)sb.st_gid);
2476 (
void) printf(
" mode=%#o", (
unsigned)sb.st_mode);
2478 (
void) printf(
" nlink=1");
2479 #if defined(HAVE_STRUCT_STAT_ST_FLAGS)
2481 const char * fflags = flags_to_string(sb.st_flags);
2482 (
void) printf(
" flags=%s", fflags);
2483 fflags =
_free(fflags);
2486 (
void) printf(
"\n");
2492 #define CWALKINDENTNAMELEN 15
2493 #define MAXLINELEN 80
2497 output(
int indent,
int *
offset,
const char * fmt, ...)
2508 if (*offset + strlen(buf) >
MAXLINELEN - 3) {
2512 *offset += printf(
" %s", buf) + 1;
2516 mtreeVisitF(rpmfts fts)
2522 unsigned short fts_info = fts->
p->
fts_info;
2527 {
const char * fts_name = fts->
p->
fts_name;
2532 if (fts->
p->
fts_level == 0 && fts_namelen == 0) {
2534 fts_namelen =
sizeof(
".") - 1;
2537 escname =
xmalloc(fts_namelen * 4 + 1);
2541 if (
MF_ISSET(INDENT) || S_ISDIR(st->st_mode))
2542 offset = printf(
"%*s%s", indent,
"", escname);
2544 offset = printf(
"%*s %s", indent,
"", escname);
2545 escname =
_free(escname);
2553 if (!S_ISREG(st->st_mode) && !
MF_ISSET(DIRSONLY))
2554 output(indent, &offset,
"type=%s", inotype(st->st_mode));
2555 if (st->st_uid != fts->
sb.st_uid) {
2559 output(indent, &offset,
"uname=%s", uname);
2561 fprintf(stderr,
_(
"%s: Could not get uname for uid=%lu\n"),
2565 (
unsigned long)st->st_uid);
2568 output(indent, &offset,
"uid=%u", st->st_uid);
2570 if (st->st_gid != fts->
sb.st_gid) {
2574 output(indent, &offset,
"gname=%s", gname);
2576 fprintf(stderr,
_(
"%s: Could not get gname for gid=%lu\n"),
2580 (
unsigned long) st->st_gid);
2583 output(indent, &offset,
"gid=%lu", (
unsigned long)st->st_gid);
2586 output(indent, &offset,
"mode=%#o", (st->st_mode &
MBITS));
2587 if (
KF_ISSET(keys, NLINK) && st->st_nlink != 1)
2588 output(indent, &offset,
"nlink=%lu", (
unsigned long)st->st_nlink);
2589 if (
KF_ISSET(keys, SIZE) && S_ISREG(st->st_mode))
2590 output(indent, &offset,
"size=%llu", (
unsigned long long)st->st_size);
2593 #if defined(TIMESPEC_TO_TIMEVAL)
2596 tv.tv_sec = (long)st->st_mtime;
2599 output(indent, &offset,
"time=%lu.%lu",
2600 (
unsigned long) tv.tv_sec,
2601 (
unsigned long) tv.tv_usec);
2605 if (S_ISREG(st->st_mode)) {
2609 FD_t fd =
Fopen(fts_accpath,
"r.ufdio");
2631 i = crc(fd, &val, &len);
2633 char buffer[16 * 1024];
2634 while (
Fread(buffer,
sizeof(buffer[0]),
sizeof(buffer), fd) > 0)
2636 i = (
Ferror(fd) ? 1 : 0);
2651 output(indent, &offset,
"cksum=%lu", (
unsigned long)val);
2657 static int asAscii = 1;
2658 const char * digest =
NULL;
2659 size_t digestlen = 0;
2670 {
const char * tagname = algo2tagname(algo);
2671 if (tagname !=
NULL)
2672 output(indent, &offset,
"%s=%s", tagname, digest);
2674 digest =
_free(digest);
2690 const char * name = rlink(fts_accpath);
2691 char * escname =
xmalloc(strlen(name) * 4 + 1);
2693 output(indent, &offset,
"link=%s", escname);
2694 escname =
_free(escname);
2698 #if defined(HAVE_STRUCT_STAT_ST_FLAGS)
2699 char * fflags = fflagstostr(st->st_flags);
2701 if (fflags !=
NULL && fflags[0] !=
'\0')
2702 output(indent, &offset,
"flags=%s", fflags);
2704 output(indent, &offset,
"flags=none");
2707 output(indent, &offset,
"flags=none");
2710 (
void) putchar(
'\n');
2751 mtreeReadExcludes(
const char *
fn)
2757 char buffer[16 * 1024];
2766 while (fgets(buffer, (
int)
sizeof(buffer), fp) !=
NULL) {
2771 buffer[
sizeof(buffer)-1] =
'\0';
2772 for (line = buffer; *line !=
'\0'; line++)
2773 if (strchr(
" \t\n\r", line[1]) ==
NULL)
break;
2774 if (*line ==
'\0' || *line ==
'#')
2776 for (len = strlen(line); len > 0; len--)
2777 if (strchr(
" \t\n\r", line[len-1]) ==
NULL)
break;
2796 mtreeCheckExcludes(
const char *fname,
const char *path)
2802 #define MATCH(g, n) (fnmatch((g), (n), FNM_PATHNAME) == 0)
2819 if (S_ISDIR((*a)->fts_statp->st_mode)) {
2820 if (!S_ISDIR((*b)->fts_statp->st_mode))
2822 }
else if (S_ISDIR((*b)->fts_statp->st_mode))
2824 return strcmp((*a)->fts_name, (*b)->fts_name);
2827 #if defined(_RPMFI_INTERNAL)
2837 size_t flen = strlen(fn);
2838 size_t slen = strlen(suffix);
2839 return (flen > slen && !
strcmp(fn + flen - slen, suffix));
2842 static int _rpmfiStat(
const char * path,
struct stat * st)
2848 size_t len = strlen(fts->
paths[0]);
2854 fprintf(stderr,
"*** _rpmfiStat(%s, %p) fi %p rc %d\n", path+len, st, fi, rc);
2859 static int _rpmfiClosedir( DIR * dir)
2863 rpmfi fi = _rpmfts->fi;
2866 fprintf(stderr,
"*** _rpmfiClosedir(%p) fi %p\n", dir, fi);
2868 return avClosedir(dir);
2871 static struct dirent * _rpmfiReaddir(DIR * dir)
2875 rpmfi fi = _rpmfts->fi;
2879 fprintf(stderr,
"*** _rpmfiReaddir(%p) fi %p %p \"%s\"\n", dir, fi, dp, (dp !=
NULL ? dp->d_name :
""));
2887 uint8_t * rpmfiParentDirNotWithin(
rpmfi fi)
2890 size_t * dnlens =
xmalloc(fi->dc *
sizeof(*dnlens));
2894 for (i = 0; i < (
int)fi->dc; i++)
2895 dnlens[
i] = strlen(fi->dnl[i]);
2898 for (i = 0; i < (
int)fi->fc; i++) {
2899 size_t dnlen, bnlen;
2901 if (!S_ISDIR(fi->fmodes[i]))
2904 dnlen = dnlens[fi->dil[
i]];
2905 bnlen = strlen(fi->bnl[i]);
2907 for (j = 0; j < (
int)fi->dc; j++) {
2909 if (!noparent[j] || j == (
int)fi->dil[
i])
2911 if (dnlens[j] != (dnlen+bnlen+1))
2913 if (strncmp(fi->dnl[j], fi->dnl[fi->dil[i]], dnlen))
2915 if (strncmp(fi->dnl[j]+dnlen, fi->bnl[i], bnlen))
2917 if (fi->dnl[j][dnlen+bnlen] !=
'/' || fi->dnl[j][dnlen+bnlen+1] !=
'\0')
2921 noparent[
j] = (uint8_t)0;
2925 dnlens =
_free(dnlens);
2929 static Header rpmftsReadHeader(rpmfts fts,
const char * path)
2959 static rpmfi rpmftsLoadFileInfo(rpmfts fts,
const char * path)
2964 size_t nb = strlen(fn);
2968 h = rpmftsReadHeader(fts, fn);
2979 static DIR * _rpmfiOpendir(
const char * path)
2988 if (fts->ts ==
NULL)
2991 if (fts->fi ==
NULL) {
2992 rpmfi fi = rpmftsLoadFileInfo(fts, path);
2993 uint8_t * noparent = rpmfiParentDirNotWithin(fi);
2995 const char ** fnames =
NULL;
3003 if (!S_ISDIR(fi->fmodes[i]) && !noparent[fi->dil[i]])
3006 fmodes[ac++] = fi->fmodes[
i];
3009 dir = (DIR *) avOpendir(path, fnames, fmodes);
3012 fmodes =
_free(fmodes);
3013 noparent =
_free(noparent);
3016 const char * dn = path + strlen(fts->
paths[0]);
3022 fprintf(stderr,
"*** _rpmfiOpendir(%s) dir %p\n", path, dir);
3027 #define ALIGNBYTES (__alignof__ (long double) - 1)
3028 #define ALIGN(p) (((unsigned long int) (p) + ALIGNBYTES) & ~ALIGNBYTES)
3045 len =
sizeof(*p) + namelen;
3053 memmove(p->
fts_name, name, namelen);
3070 static void _rpmfiSetFts(rpmfts fts)
3074 char *
const *
argv = (
char *
const *) fts->
paths;
3079 register FTSENT *p, *root;
3086 fprintf(stderr,
"*** _rpmfiSetFts(%p)\n", fts);
3097 if (*argv !=
NULL) {
3104 len = strlen(*argv);
3108 p->fts_parent = parent;
3115 p->fts_info =
FTS_D;
3118 p->fts_name[len-1] =
'\0';
3119 {
struct stat * st = p->fts_statp;
3120 int xx =
Stat(p->fts_accpath, st);
3122 st->st_mode &= ~S_IFMT;
3123 st->st_mode |= S_IFDIR;
3124 p->fts_dev = st->st_dev;
3125 p->fts_ino = st->st_ino;
3126 p->fts_nlink = st->st_nlink;
3128 p->fts_name[len-1] =
'/';
3129 p->fts_info =
FTS_D;
3154 if (compar &&
nitems > 1)
3175 #if defined(_RPMFI_INTERNAL)
3180 const char * empty =
NULL;
3181 char *
const *
paths = (
char *
const *) (isrpm ? &empty : fts->
paths);
3185 fts->
t =
Fts_open(paths, ftsoptions, dsort);
3189 #if defined(_RPMFI_INTERNAL)
3207 (
void) printf(
"\n");
3210 (
void) mtreeVisitD(fts);
3216 (
void) printf(
"%*s..\n", indent,
"");
3218 (
void) printf(
"\n");
3262 (
void) printf(
_(
"missing: %s"), fts->
path);
3265 (
void) putchar(
'\n');
3270 type = (p->
type ==
F_LINK ?
"symlink" :
"directory");
3273 (
void) printf(
_(
" (%s not created: user not specified)"), type);
3275 (
void) printf(
_(
" (%s not created: group not specified))"),
type);
3278 (
void) printf(
_(
" (%s not created: %s)\n"), type,
3281 (
void) printf(
_(
" (%s created)\n"), type);
3286 if (p->
sb.st_uid == (uid_t)-1)
3288 else if (
lchown(fts->
path, (uid_t)-1, p->
sb.st_gid) == -1)
3289 what =
"user & group";
3294 (
void) printf(
_(
"%s: %s not modified: %s\n"),
3299 (
void) printf(
_(
" (%s not created: mode not specified)"), type);
3304 (
void) printf(
_(
" (%s created)"),
type);
3309 (
void) putchar(
'\n');
3311 for (tp = tail; *tp !=
'\0'; ++tp);
3322 if (p->
sb.st_uid == (uid_t)-1)
3324 else if (
Chown(fts->
path, (uid_t)-1, p->
sb.st_gid) == -1)
3325 what =
"user & group";
3330 (
void) printf(
_(
"%s: %s not modified: %s\n"),
3335 (
void) printf(
_(
"%s: permissions not set: %s\n"),
3337 #if defined(HAVE_STRUCT_STAT_ST_FLAGS)
3339 chflags(fts->
path, p->
sb.st_flags))
3340 (
void) printf(
_(
"%s: file flags not set: %s\n"),
3349 #if defined(_RPMFI_INTERNAL)
3354 const char * empty =
NULL;
3355 char *
const * paths = (
char *
const *) (isrpm ? &empty : fts->
paths);
3366 #if defined(_RPMFI_INTERNAL)
3374 const char * fts_name = fts->
p->
fts_name;
3381 if (fts->
p->
fts_level == 0 && fts_namelen == 0) {
3383 fts_namelen =
sizeof(
".") - 1;
3386 if (mtreeCheckExcludes(fts_name, fts->
p->
fts_path)) {
3396 level = root = fts->
root;
3398 level = root = root->
next;
3422 for (ep = level; ep !=
NULL; ep = ep->
next)
3452 (
void) printf(
_(
", not removed: %s"), strerror(
errno));
3454 (
void) printf(
_(
", removed"));
3456 (
void) putchar(
'\n');
3471 enum poptCallbackReason reason,
3472 const struct poptOption * opt,
const char * arg,
3480 if (opt->arg ==
NULL)
3485 if ((_rpmfts->
spec1 = fopen(arg,
"r")) !=
NULL)
3488 if ((_rpmfts->
spec2 = fopen(arg,
"r")) !=
NULL)
3492 poptPrintUsage(con, stderr, 0);
3503 while ((p = strsep((
char **)&arg,
" \t,")) !=
NULL) {
3529 mtreeReadExcludes(arg);
3535 poptPrintUsage(con, stderr, 0);
3544 {
NULL,
'\0', POPT_ARG_CALLBACK | POPT_CBFLAG_INC_DATA | POPT_CBFLAG_CONTINUE,
3545 mtreeArgCallback, 0,
NULL, NULL },
3550 N_(
"Follow symlinks"), NULL },
3553 N_(
"Don't follow symlinks"), NULL },
3555 N_(
"Read fnmatch(3) exclude patterns from <file>"),
N_(
"<file>") },
3558 N_(
"Print file tree specification to stdout"), NULL },
3560 N_(
"Directories only"), NULL },
3562 N_(
"Don't complain about files not in the specification"), NULL },
3563 {
"file",
'f', POPT_ARG_STRING,
NULL, (
int)
'f',
3564 N_(
"Read file tree <spec>"),
N_(
"<spec>") },
3566 N_(
"Indent sub-directories"), NULL },
3567 {
"add",
'K', POPT_ARG_STRING,
NULL, (
int)
'K',
3568 N_(
"Add <key> to specification"),
N_(
"<key>") },
3569 {
"key",
'k', POPT_ARG_STRING,
NULL, (
int)
'k',
3570 N_(
"Use \"type\" keywords instead"),
N_(
"<key>") },
3572 N_(
"Loose permissions check"), NULL },
3574 N_(
"Don't include sub-directory comments"), NULL },
3576 N_(
"Use <path> rather than current directory"),
N_(
"<path>") },
3579 N_(
"Quiet mode"), NULL },
3581 N_(
"Remove files not in specification"), NULL },
3583 N_(
"Display crc for file(s) with <seed>"),
N_(
"<seed>") },
3585 N_(
"Touch files iff timestamp differs"), NULL },
3587 N_(
"Update owner/group/permissions to match specification"), NULL },
3589 N_(
"Same as -u, but ignore match status on exit"), NULL },
3591 N_(
"Treat missing uid/gid as warning"), NULL },
3594 N_(
"Don't cross mount points"), NULL },
3597 N_(
"Fts(3) traversal options:"), NULL },
3600 N_(
"Available digests:"), NULL },
3603 N_(
"Common options for all rpmio executables:"),
3609 {
NULL, (char)-1, POPT_ARG_INCLUDE_TABLE, NULL, 0,
3611 Usage: mtree [-cdeilnqrtUux] [-f spec] [-K key] [-k key] [-p path] [-s seed]\n\
3617 #if defined(__linux__)
3619 static const char *my_getlogin(
void)
3623 const char *s = getlogin();
3628 struct passwd *pw = getpwuid(geteuid());
3631 if (pw != NULL && pw->pw_name != NULL && pw->pw_name[0] !=
'\0') {
3632 if (asprintf(&ss,
_(
"(no controlling terminal) %s"), pw->pw_name) < 0) {
3637 if (asprintf(&ss,
_(
"(no controlling terminal) #%d"), geteuid()) < 0) {
3646 #define __getlogin my_getlogin
3648 #define __getlogin getlogin
3652 main(
int argc,
char *argv[])
3670 #if defined(HAVE_STRUCT_STAT_ST_FLAGS)
3672 fts->
sb.st_flags = 0xffffffff;
3679 argv = (
char **) poptGetArgs(optCon);
3680 if (!(argv == NULL || argv[0] == NULL)) {
3681 poptPrintUsage(optCon, stderr, 0);
3686 mtree_error(
"-l and -u flags are mutually exclusive");
3695 mtree_error(
"-L and -P flags are mutually exclusive");
3712 const char * lpath =
NULL;
3714 size_t nb = (size_t)(lpath - fts->
paths[i]);
3715 int isdir = (lpath[strlen(lpath)-1] ==
'/');
3718 if (lpath[0] !=
'/') {
3726 if (rpath != fullpath)
3727 rpath =
_free(rpath);
3741 fullpath[
nb] =
'\0';
3743 lpath =
_free(lpath);
3748 lpath = (isdir || (!
Stat(rpath, &sb) && S_ISDIR(sb.st_mode))
3753 rpath =
_free(rpath);
3766 char host[MAXHOSTNAMELEN];
3768 (
void) time(&clock);
3769 (
void) gethostname(host,
sizeof(host));
3771 (
void) printf(
"#\tmachine: %s\n", host);
3773 (
void) printf(
"#\t tree: %s\n", fts->
paths[i]);
3774 (
void) printf(
"#\t date: %s", ctime(&clock));
3782 if (fts->
spec2 != NULL) {
3808 #if defined(_RPMFI_INTERNAL)
3814 if (fts->
spec1 != NULL && fileno(fts->
spec1) > 2) {
3823 #if defined(HAVE_STRUCT_STAT_ST_FLAGS)
3824 fts->f =
_free(fts->f);
static void fdInitDigest(FD_t fd, pgpHashAlgo hashalgo, int _flags)
Attach digest to fd.
static const char * suffix[]
poptContext rpmioInit(int argc, char *const argv[], struct poptOption *optionsTable)
#define CWALKINDENTNAMELEN
static FTSENT * fts_sort(FTS *sp, FTSENT *head, int nitems)
struct poptOption rpmioDigestPoptTable[]
Digest options using popt.
FTS * Fts_open(char *const *argv, int options, int(*compar)(const FTSENT **, const FTSENT **))
Create a handle for file hierarchy traversal.
rpmtime_t rpmswAdd(rpmop to, rpmop from)
Sum statistic counters.
static PyObject *int type
static struct rpmfts_s __rpmfts
#define KF_ISSET(_keys, _KEY)
int Symlink(const char *oldpath, const char *newpath)
symlink(3) clone.
char * xstrdup(const char *str)
FTSENT * Fts_children(FTS *sp, int instr)
Return list of children of the current node.
FD_t Fopen(const char *path, const char *_fmode)
fopen(3) clone.
#define RPM_LIST_INIT(head)
char * rpmGetPath(const char *path,...)
Return (malloc'ed) expanded, canonicalized, file path.
int Utimes(const char *path, const struct timeval *times)
utimes(2) clone.
Structure(s) used for file info tag sets.
static char *size_t nb
fgets(3) analogue that reads \ continuations.
struct rpmts_s * rpmts
The RPM Transaction Set.
static struct poptOption optionsTable[]
static const char copyright[]
rpmts rpmtsFree(rpmts ts)
Destroy transaction set, closing the database as well.
int main(int argc, const char **argv, char **envp)
char * gidToGname(gid_t gid)
int(* fts_stat)(const char *path, struct stat *st)
struct poptOption rpmioFtsPoptTable[]
static void mtreeMiss(rpmfts fts, NODE *p, char *tail)
DIR *(* fts_opendir)(const char *path)
int Stat(const char *path, struct stat *st)
stat(2) clone.
static const uint32_t crctab[]
static FTSENT * fts_alloc(FTS *sp, const char *name, int namelen)
static struct rpmop_s dc_readops
rpmfi rpmfiFree(rpmfi fi)
Destroy a file info set.
const char * rpmfiFN(rpmfi fi)
Return current file name from file info set.
rpmfi rpmfiNew(const void *_ts, Header h, rpmTag tagN, int flags)
Create and load a file info set.
int(* fts_closedir)(DIR *dir)
static u_short fts_stat(FTS *sp, FTSENT *p, int follow)
int rpmfiFC(rpmfi fi)
Return file count from file info set.
static PyObject *char * mode
static struct rpmop_s dc_digestops
int Chown(const char *path, uid_t owner, gid_t group)
chown(2) clone.
enum rpmRC_e rpmRC
RPM return codes.
static int mtreeCWalk(rpmfts fts)
memset(_r, 0, sizeof(*_r))
rpmts rpmtsCreate(void)
Create an empty transaction set.
const char * Fstrerror(FD_t fd)
strerror(3) clone.
void * xcalloc(size_t nmemb, size_t size)
assert(key->size==sizeof(hdrNum))
int Rmdir(const char *path)
rmdir(2) clone.
void mtree_error(const char *fmt,...)
fprintf(stderr,"--> %s(%p,%p,%p) sig %p sigp %p\n", __FUNCTION__, dig, t, rsactx, sig, sigp)
void rpmswPrint(const char *name, rpmop op, FILE *fp)
Print operation statistics.
int gnameToGid(const char *thisGname, gid_t *gid)
static int strvis(char *dst, const char *src, int flag)
int Mkdir(const char *path, mode_t mode)
mkdir(2) clone.
ARGV_t argvFree(ARGV_t argv)
Destroy an argv array.
static NODE * mtreeSpec(rpmfts fts, FILE *fp)
rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char *fn, Header *hdrp)
Return package header from file handle, verifying digests/signatures.
static struct @9 excludes
static int mtreeVWalk(rpmfts fts)
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.
int argvAdd(ARGV_t *argvp, ARGstr_t val)
Add a string to an argv array.
static int unvis(char *cp, char c, int *astate, int flag)
FTSENT * Fts_read(FTS *sp)
Return next node in the file hierarchy traversal.
char * rpmExpand(const char *arg,...)
Return (malloc'ed) concatenated macro expansion(s).
size_t Fread(void *buf, size_t size, size_t nmemb, FD_t fd)
fread(3) clone.
static int strunvis(char *dst, const char *src)
#define RPM_LIST_INSERT_HEAD(head, elm, field)
int Fclose(FD_t fd)
fclose(3) clone.
#define TIMESPEC_TO_TIMEVAL(tv, ts)
#define RPM_LIST_ENTRY(type)
Cumulative statistics for an operation.
static struct rpmop_s dc_totalops
int rpmfiNext(rpmfi fi)
Return next file iterator index.
int Fts_set(FTS *sp, FTSENT *p, int instr)
Modify the traversal for a file set member.
int fnmatch(char *__pattern, char *__name, int __flags)
static const char *char c
Return text between pl and matching pr characters.
int Readlink(const char *path, char *buf, size_t bufsiz)
readlink(2) clone.
void * rpmfiOpendir(rpmfi fi, const char *name)
Return directory stream onto file info set.
int Ferror(FD_t fd)
ferror(3) clone.
rpmfi rpmfiInit(rpmfi fi, int fx)
Initialize file iterator index.
return strcmp(ame->name, bme->name)
urltype urlPath(const char *url, const char **pathp)
Return path component of URL.
static int vsnprintf(char *buf, int nb, const char *fmt, va_list ap)
static enum mtreeFlags_e mtreeFlags
int(* fts_lstat)(const char *path, struct stat *st)
char * uidToUname(uid_t uid)
Structures and prototypes used for an "rpmts" transaction set.
#define RPM_LIST_FOREACH(var, head, field)
static int chkSuffix(const char *fn, const char *suffix)
Check string for a suffix.
struct dirent *(* fts_readdir)(DIR *dir)
int argiAdd(ARGI_t *argip, int ix, int val)
Add an int to an argi array.
static char * vis(char *dst, int c, int flag, int nextc)
#define _FTSCALLOC(_p, _n)
int Fts_close(FTS *sp)
Destroy a file hierarchy traversal handle.
#define RPM_LIST_HEAD(name, type)
static int mtreeVSpec(rpmfts fts)
int Chmod(const char *path, mode_t mode)
chmod(2) clone.
static void fdFiniDigest(FD_t fd, pgpHashAlgo hashalgo, void *datap, size_t *lenp, int asAscii)
char * buf
Parse (and execute) macro undefinition.
mtreeKeys_e
Bit field enum for mtree keys.
static rpmop fdstat_op(FD_t fd, fdOpX opx)
int
Save source and expand field into target.
struct rpmfi_s * rpmfi
File info tag sets from a header, so that a header can be discarded early.
mtreeFlags_e
Bit field enum for mtree CLI options.
struct poptOption rpmioAllPoptTable[]
int rpmfiStat(rpmfi fi, const char *path, struct stat *st)
Return lstat(2) data of path from file info set.
int unameToUid(const char *thisUname, uid_t *uid)
poptContext rpmioFini(poptContext optCon)
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
In Memoriam: Steve Taylor staylor@redhat.com was here, now he's not.
char * Realpath(const char *path, char *resolved_path)
realpath(3) clone.
struct _ftsent * fts_link
#define FTS_ROOTPARENTLEVEL
const unsigned char * digest
int Unlink(const char *path)
unlink(2) clone.