├── CHANGES ├── CVS ├── Entries ├── Repository └── Root ├── Makefile.am ├── README ├── autogen.sh ├── compare.c ├── configure.ac ├── crc.c ├── create.c ├── excludes.c ├── extern.h ├── getid.c ├── misc.c ├── mtree.5 ├── mtree.8 ├── mtree.c ├── mtree.h ├── pack_dev.c ├── pack_dev.h ├── spec.c ├── stat_flags.c ├── stat_flags.h └── verify.c /CHANGES: -------------------------------------------------------------------------------- 1 | Version Next 2 | 3 | - Fix bug with timestamps after 2038. 4 | 5 | Version 1.0.0 released August 28, 2020 6 | 7 | - Initial release 8 | -------------------------------------------------------------------------------- /CVS/Entries: -------------------------------------------------------------------------------- 1 | /Makefile.in/1.9/Thu Mar 8 01:11:21 2012// 2 | /compare.c/1.7/Sun Sep 8 16:20:10 2013// 3 | /config.guess/1.3/Mon Mar 12 00:48:29 2007// 4 | /config.h.in/1.10/Sun Sep 8 16:20:10 2013// 5 | /config.sub/1.3/Mon Mar 12 00:48:29 2007// 6 | /configure/1.10/Sun Sep 8 16:20:10 2013// 7 | /configure.ac/1.11/Sun Sep 8 16:20:10 2013// 8 | /crc.c/1.5/Sun Mar 21 16:30:17 2010// 9 | /create.c/1.9/Sun Sep 8 16:20:10 2013// 10 | /excludes.c/1.4/Sat Aug 21 04:10:45 2004// 11 | /extern.h/1.5/Wed Jul 27 15:31:00 2011// 12 | /getid.c/1.4/Thu Nov 6 02:14:52 2008// 13 | /install-sh/1.1.1.1/Mon Mar 31 08:51:16 2003// 14 | /misc.c/1.3/Thu Nov 6 02:14:52 2008// 15 | /mtree.8/1.4/Thu Nov 6 02:14:52 2008// 16 | /mtree.c/1.3/Sat Aug 21 04:10:45 2004// 17 | /mtree.cat8/1.4/Thu Nov 6 02:14:52 2008// 18 | /mtree.h/1.3/Thu Nov 6 02:14:52 2008// 19 | /mtree2nbcompat/1.3/Wed Aug 22 20:48:38 2018// 20 | /pack_dev.c/1.5/Thu Nov 6 02:14:52 2008// 21 | /pack_dev.h/1.4/Thu Nov 6 02:14:52 2008// 22 | /spec.c/1.5/Thu Nov 6 02:14:52 2008// 23 | /stat_flags.c/1.5/Wed Jul 27 15:31:00 2011// 24 | /stat_flags.h/1.1/Fri Sep 5 18:39:00 2003// 25 | /verify.c/1.6/Sun Mar 21 16:30:17 2010// 26 | D 27 | -------------------------------------------------------------------------------- /CVS/Repository: -------------------------------------------------------------------------------- 1 | pkgsrc/pkgtools/mtree/files 2 | -------------------------------------------------------------------------------- /CVS/Root: -------------------------------------------------------------------------------- 1 | :pserver:anoncvs@anoncvs.NetBSD.org:/cvsroot 2 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | # vim: noet:sw=8:ts=8: 2 | 3 | bin_PROGRAMS= mtree 4 | 5 | mtree_SOURCES= compare.c \ 6 | crc.c \ 7 | create.c \ 8 | excludes.c \ 9 | getid.c \ 10 | misc.c \ 11 | mtree.c \ 12 | pack_dev.c \ 13 | spec.c \ 14 | stat_flags.c \ 15 | verify.c 16 | 17 | noinst_HEADERS= extern.h \ 18 | mtree.h \ 19 | pack_dev.h \ 20 | stat_flags.h 21 | 22 | man_MANS= mtree.5 mtree.8 23 | 24 | docdir= $(datadir)/doc/packages/$(PACKAGE) 25 | 26 | doc_DATA= README 27 | 28 | EXTRA_DIST= $(man_MANS) 29 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This project is a port of NetBSD's mtree utility to Linux. 2 | 3 | Notes: 4 | 5 | - Information about the original NetBSD version: 6 | https://cdn.netbsd.org/pub/pkgsrc/current/pkgsrc/pkgtools/mtree/README.html 7 | 8 | - This build requires the "libnbcompat" library, available here: 9 | https://github.com/archiecobbs/libnbcompat 10 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Bail on error 4 | set -e 5 | 6 | # Clean up 7 | echo ">>> cleaning up..." 1>&2 8 | if test -d mtree-[0-9].[0-9].[0-9]; then 9 | chmod -R u+w mtree-[0-9].[0-9].[0-9] 10 | fi 11 | find . -type d -name .deps -print0 | xargs -0 rm -fr 12 | rm -rf \ 13 | aclocal.m4 \ 14 | autom4te.cache \ 15 | config/* \ 16 | config.guess \ 17 | config.log \ 18 | config.status \ 19 | config.sub \ 20 | configure \ 21 | mtree \ 22 | mtree-[0-9].[0-9].[0-9] \ 23 | mtree-[0-9].[0-9].[0-9].tar.gz \ 24 | Makefile \ 25 | Makefile.in \ 26 | config.h* \ 27 | stamp-h1 \ 28 | *.o 29 | 30 | if [ "$1" = '-n' ]; then 31 | exit 0 32 | fi 33 | 34 | # Regnenerate 35 | echo ">>> applying autotools..." 1>&2 36 | autoreconf -vfi -I . 37 | 38 | if [ "$1" != '-c' ]; then 39 | exit 0 40 | fi 41 | 42 | # Reconfigure 43 | echo ">>> running ./configure script..." 1>&2 44 | ./configure 45 | -------------------------------------------------------------------------------- /compare.c: -------------------------------------------------------------------------------- 1 | /* $NetBSD: compare.c,v 1.7 2013/09/08 16:20:10 ryoon Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 1989, 1993 5 | * The Regents of the University of California. All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. Neither the name of the University nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 | * SUCH DAMAGE. 30 | */ 31 | 32 | #if HAVE_CONFIG_H 33 | #include "config.h" 34 | #endif 35 | #if HAVE_NBTOOL_CONFIG_H 36 | #include "nbtool_config.h" 37 | #endif 38 | 39 | #include 40 | #if HAVE_SYS_CDEFS_H 41 | #include 42 | #endif 43 | #if defined(__RCSID) && !defined(lint) 44 | #if 0 45 | static char sccsid[] = "@(#)compare.c 8.1 (Berkeley) 6/6/93"; 46 | #else 47 | __RCSID("$NetBSD: compare.c,v 1.7 2013/09/08 16:20:10 ryoon Exp $"); 48 | #endif 49 | #endif /* not lint */ 50 | 51 | #if HAVE_SYS_PARAM_H 52 | #include 53 | #endif 54 | 55 | #if HAVE_ERRNO_H 56 | #include 57 | #endif 58 | #if HAVE_FCNTL_H 59 | #include 60 | #endif 61 | #if HAVE_STDIO_H 62 | #include 63 | #endif 64 | #if HAVE_STRING_H 65 | #include 66 | #endif 67 | #if HAVE_TIME_H 68 | #include 69 | #endif 70 | #if HAVE_UNISTD_H 71 | #include 72 | #endif 73 | 74 | #ifndef NO_MD5 75 | #if HAVE_MD5_H 76 | #include 77 | #elif HAVE_NBCOMPAT_MD5_H 78 | #include 79 | #endif 80 | #endif 81 | #ifndef NO_RMD160 82 | #if HAVE_RMD160_H 83 | #include 84 | #elif HAVE_NBCOMPAT_RMD160_H 85 | #include 86 | #endif 87 | #endif 88 | #ifndef NO_SHA1 89 | #if HAVE_SHA1_H 90 | #include 91 | #elif HAVE_NBCOMPAT_SHA1_H 92 | #include 93 | #endif 94 | #endif 95 | #ifndef NO_SHA2 96 | #if HAVE_SHA2_H && HAVE_SHA512_FILE 97 | #include 98 | #elif HAVE_NBCOMPAT_SHA2_H 99 | #include 100 | #endif 101 | #endif 102 | 103 | 104 | #include "extern.h" 105 | 106 | #define INDENTNAMELEN 8 107 | #define MARK \ 108 | do { \ 109 | len = printf("%s: ", RP(p)); \ 110 | if (len > INDENTNAMELEN) { \ 111 | tab = "\t"; \ 112 | printf("\n"); \ 113 | } else { \ 114 | tab = ""; \ 115 | printf("%*s", INDENTNAMELEN - (int)len, ""); \ 116 | } \ 117 | } while (0) 118 | #define LABEL if (!label++) MARK 119 | 120 | #if HAVE_STRUCT_STAT_ST_FLAGS 121 | 122 | 123 | #define CHANGEFLAGS \ 124 | if (flags != p->fts_statp->st_flags) { \ 125 | if (!label) { \ 126 | MARK; \ 127 | printf("%sflags (\"%s\"", tab, \ 128 | flags_to_string(p->fts_statp->st_flags, "none")); \ 129 | } \ 130 | if (lchflags(p->fts_accpath, flags)) { \ 131 | label++; \ 132 | printf(", not modified: %s)\n", \ 133 | strerror(errno)); \ 134 | } else \ 135 | printf(", modified to \"%s\")\n", \ 136 | flags_to_string(flags, "none")); \ 137 | } 138 | 139 | /* SETFLAGS: 140 | * given pflags, additionally set those flags specified in s->st_flags and 141 | * selected by mask (the other flags are left unchanged). 142 | */ 143 | #define SETFLAGS(pflags, mask) \ 144 | do { \ 145 | flags = (s->st_flags & (mask)) | (pflags); \ 146 | CHANGEFLAGS; \ 147 | } while (0) 148 | 149 | /* CLEARFLAGS: 150 | * given pflags, reset the flags specified in s->st_flags and selected by mask 151 | * (the other flags are left unchanged). 152 | */ 153 | #define CLEARFLAGS(pflags, mask) \ 154 | do { \ 155 | flags = (~(s->st_flags & (mask)) & CH_MASK) & (pflags); \ 156 | CHANGEFLAGS; \ 157 | } while (0) 158 | #endif /* HAVE_STRUCT_STAT_ST_FLAGS */ 159 | 160 | int 161 | compare(NODE *s, FTSENT *p) 162 | { 163 | uint32_t len, val; 164 | #if HAVE_STRUCT_STAT_ST_FLAGS 165 | uint32_t flags; 166 | #endif 167 | int fd, label; 168 | const char *cp, *tab; 169 | #if !defined(NO_MD5) || !defined(NO_RMD160) || !defined(NO_SHA1) || !defined(NO_SHA2) 170 | char digestbuf[MAXHASHLEN + 1]; 171 | #endif 172 | 173 | tab = NULL; 174 | label = 0; 175 | switch(s->type) { 176 | case F_BLOCK: 177 | if (!S_ISBLK(p->fts_statp->st_mode)) 178 | goto typeerr; 179 | break; 180 | case F_CHAR: 181 | if (!S_ISCHR(p->fts_statp->st_mode)) 182 | goto typeerr; 183 | break; 184 | case F_DIR: 185 | if (!S_ISDIR(p->fts_statp->st_mode)) 186 | goto typeerr; 187 | break; 188 | case F_FIFO: 189 | if (!S_ISFIFO(p->fts_statp->st_mode)) 190 | goto typeerr; 191 | break; 192 | case F_FILE: 193 | if (!S_ISREG(p->fts_statp->st_mode)) 194 | goto typeerr; 195 | break; 196 | case F_LINK: 197 | if (!S_ISLNK(p->fts_statp->st_mode)) 198 | goto typeerr; 199 | break; 200 | #ifdef S_ISSOCK 201 | case F_SOCK: 202 | if (!S_ISSOCK(p->fts_statp->st_mode)) 203 | goto typeerr; 204 | break; 205 | #endif 206 | typeerr: LABEL; 207 | printf("\ttype (%s, %s)\n", 208 | nodetype(s->type), inotype(p->fts_statp->st_mode)); 209 | return (label); 210 | } 211 | if (mtree_Wflag) 212 | goto afterpermwhack; 213 | #if HAVE_STRUCT_STAT_ST_FLAGS 214 | if (iflag && !uflag) { 215 | if (s->flags & F_FLAGS) 216 | SETFLAGS(p->fts_statp->st_flags, SP_FLGS); 217 | return (label); 218 | } 219 | if (mflag && !uflag) { 220 | if (s->flags & F_FLAGS) 221 | CLEARFLAGS(p->fts_statp->st_flags, SP_FLGS); 222 | return (label); 223 | } 224 | #endif 225 | if (s->flags & F_DEV && 226 | (s->type == F_BLOCK || s->type == F_CHAR) && 227 | s->st_rdev != p->fts_statp->st_rdev) { 228 | LABEL; 229 | printf("%sdevice (%#lx, %#lx", 230 | tab, (unsigned long)s->st_rdev, (unsigned long)p->fts_statp->st_rdev); 231 | if (uflag) { 232 | if ((unlink(p->fts_accpath) == -1) || 233 | (mknod(p->fts_accpath, 234 | s->st_mode | nodetoino(s->type), 235 | s->st_rdev) == -1) || 236 | (lchown(p->fts_accpath, p->fts_statp->st_uid, 237 | p->fts_statp->st_gid) == -1) ) 238 | printf(", not modified: %s)\n", 239 | strerror(errno)); 240 | else 241 | printf(", modified)\n"); 242 | } else 243 | printf(")\n"); 244 | tab = "\t"; 245 | } 246 | /* Set the uid/gid first, then set the mode. */ 247 | if (s->flags & (F_UID | F_UNAME) && s->st_uid != p->fts_statp->st_uid) { 248 | LABEL; 249 | printf("%suser (%lu, %lu", 250 | tab, (u_long)s->st_uid, (u_long)p->fts_statp->st_uid); 251 | if (uflag) { 252 | if (lchown(p->fts_accpath, s->st_uid, -1)) 253 | printf(", not modified: %s)\n", 254 | strerror(errno)); 255 | else 256 | printf(", modified)\n"); 257 | } else 258 | printf(")\n"); 259 | tab = "\t"; 260 | } 261 | if (s->flags & (F_GID | F_GNAME) && s->st_gid != p->fts_statp->st_gid) { 262 | LABEL; 263 | printf("%sgid (%lu, %lu", 264 | tab, (u_long)s->st_gid, (u_long)p->fts_statp->st_gid); 265 | if (uflag) { 266 | if (lchown(p->fts_accpath, -1, s->st_gid)) 267 | printf(", not modified: %s)\n", 268 | strerror(errno)); 269 | else 270 | printf(", modified)\n"); 271 | } 272 | else 273 | printf(")\n"); 274 | tab = "\t"; 275 | } 276 | if (s->flags & F_MODE && 277 | s->st_mode != (p->fts_statp->st_mode & MBITS)) { 278 | if (lflag) { 279 | mode_t tmode, mode; 280 | 281 | tmode = s->st_mode; 282 | mode = p->fts_statp->st_mode & MBITS; 283 | /* 284 | * if none of the suid/sgid/etc bits are set, 285 | * then if the mode is a subset of the target, 286 | * skip. 287 | */ 288 | if (!((tmode & ~(S_IRWXU|S_IRWXG|S_IRWXO)) || 289 | (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO)))) 290 | if ((mode | tmode) == tmode) 291 | goto skip; 292 | } 293 | 294 | LABEL; 295 | printf("%spermissions (%#lo, %#lo", 296 | tab, (u_long)s->st_mode, 297 | (u_long)p->fts_statp->st_mode & MBITS); 298 | if (uflag) { 299 | if (lchmod(p->fts_accpath, s->st_mode)) 300 | printf(", not modified: %s)\n", 301 | strerror(errno)); 302 | else 303 | printf(", modified)\n"); 304 | } 305 | else 306 | printf(")\n"); 307 | tab = "\t"; 308 | skip: ; 309 | } 310 | if (s->flags & F_NLINK && s->type != F_DIR && 311 | s->st_nlink != p->fts_statp->st_nlink) { 312 | LABEL; 313 | printf("%slink count (%lu, %lu)\n", 314 | tab, (u_long)s->st_nlink, (u_long)p->fts_statp->st_nlink); 315 | tab = "\t"; 316 | } 317 | if (s->flags & F_SIZE && s->st_size != p->fts_statp->st_size) { 318 | LABEL; 319 | printf("%ssize (%lld, %lld)\n", 320 | tab, (long long)s->st_size, 321 | (long long)p->fts_statp->st_size); 322 | tab = "\t"; 323 | } 324 | /* 325 | * XXX 326 | * Since utimes(2) only takes a timeval, there's no point in 327 | * comparing the low bits of the timespec nanosecond field. This 328 | * will only result in mismatches that we can never fix. 329 | * 330 | * Doesn't display microsecond differences. 331 | */ 332 | if (s->flags & F_TIME) { 333 | struct timeval tv[2]; 334 | struct stat *ps = p->fts_statp; 335 | time_t smtime = s->st_mtimespec.tv_sec; 336 | time_t pmtime = ps->st_mtim.tv_sec; 337 | 338 | TIMESPEC_TO_TIMEVAL(&tv[0], &s->st_mtimespec); 339 | TIMESPEC_TO_TIMEVAL(&tv[1], &ps->st_mtim); 340 | 341 | if (tv[0].tv_sec != tv[1].tv_sec || 342 | tv[0].tv_usec != tv[1].tv_usec) { 343 | LABEL; 344 | printf("%smodification time (%.24s, ", 345 | tab, ctime(&smtime)); 346 | printf("%.24s", ctime(&pmtime)); 347 | if (tflag) { 348 | tv[1] = tv[0]; 349 | if (utimes(p->fts_accpath, tv)) 350 | printf(", not modified: %s)\n", 351 | strerror(errno)); 352 | else 353 | printf(", modified)\n"); 354 | } else 355 | printf(")\n"); 356 | tab = "\t"; 357 | } 358 | } 359 | #if HAVE_STRUCT_STAT_ST_FLAGS 360 | /* 361 | * XXX 362 | * since lchflags(2) will reset file times, the utimes() above 363 | * may have been useless! oh well, we'd rather have correct 364 | * flags, rather than times? 365 | */ 366 | if ((s->flags & F_FLAGS) && ((s->st_flags != p->fts_statp->st_flags) 367 | || mflag || iflag)) { 368 | if (s->st_flags != p->fts_statp->st_flags) { 369 | LABEL; 370 | printf("%sflags (\"%s\" is not ", tab, 371 | flags_to_string(s->st_flags, "none")); 372 | printf("\"%s\"", 373 | flags_to_string(p->fts_statp->st_flags, "none")); 374 | } 375 | if (uflag) { 376 | if (iflag) 377 | SETFLAGS(0, CH_MASK); 378 | else if (mflag) 379 | CLEARFLAGS(0, SP_FLGS); 380 | else 381 | SETFLAGS(0, (~SP_FLGS & CH_MASK)); 382 | } else 383 | printf(")\n"); 384 | tab = "\t"; 385 | } 386 | #endif /* HAVE_STRUCT_STAT_ST_FLAGS */ 387 | 388 | /* 389 | * from this point, no more permission checking or whacking 390 | * occurs, only checking of stuff like checksums and symlinks. 391 | */ 392 | afterpermwhack: 393 | if (s->flags & F_CKSUM) { 394 | if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0) { 395 | LABEL; 396 | printf("%scksum: %s: %s\n", 397 | tab, p->fts_accpath, strerror(errno)); 398 | tab = "\t"; 399 | } else if (crc(fd, &val, &len)) { 400 | close(fd); 401 | LABEL; 402 | printf("%scksum: %s: %s\n", 403 | tab, p->fts_accpath, strerror(errno)); 404 | tab = "\t"; 405 | } else { 406 | close(fd); 407 | if (s->cksum != val) { 408 | LABEL; 409 | printf("%scksum (%lu, %lu)\n", 410 | tab, s->cksum, (unsigned long)val); 411 | } 412 | tab = "\t"; 413 | } 414 | } 415 | #ifndef NO_MD5 416 | if (s->flags & F_MD5) { 417 | if (MD5File(p->fts_accpath, digestbuf) == NULL) { 418 | LABEL; 419 | printf("%smd5: %s: %s\n", 420 | tab, p->fts_accpath, strerror(errno)); 421 | tab = "\t"; 422 | } else { 423 | if (strcmp(s->md5digest, digestbuf)) { 424 | LABEL; 425 | printf("%smd5 (0x%s, 0x%s)\n", 426 | tab, s->md5digest, digestbuf); 427 | } 428 | tab = "\t"; 429 | } 430 | } 431 | #endif /* ! NO_MD5 */ 432 | #ifndef NO_RMD160 433 | if (s->flags & F_RMD160) { 434 | if (RMD160File(p->fts_accpath, digestbuf) == NULL) { 435 | LABEL; 436 | printf("%srmd160: %s: %s\n", 437 | tab, p->fts_accpath, strerror(errno)); 438 | tab = "\t"; 439 | } else { 440 | if (strcmp(s->rmd160digest, digestbuf)) { 441 | LABEL; 442 | printf("%srmd160 (0x%s, 0x%s)\n", 443 | tab, s->rmd160digest, digestbuf); 444 | } 445 | tab = "\t"; 446 | } 447 | } 448 | #endif /* ! NO_RMD160 */ 449 | #ifndef NO_SHA1 450 | if (s->flags & F_SHA1) { 451 | if (SHA1File(p->fts_accpath, digestbuf) == NULL) { 452 | LABEL; 453 | printf("%ssha1: %s: %s\n", 454 | tab, p->fts_accpath, strerror(errno)); 455 | tab = "\t"; 456 | } else { 457 | if (strcmp(s->sha1digest, digestbuf)) { 458 | LABEL; 459 | printf("%ssha1 (0x%s, 0x%s)\n", 460 | tab, s->sha1digest, digestbuf); 461 | } 462 | tab = "\t"; 463 | } 464 | } 465 | #endif /* ! NO_SHA1 */ 466 | #ifndef NO_SHA2 467 | if (s->flags & F_SHA256) { 468 | if (SHA256_File(p->fts_accpath, digestbuf) == NULL) { 469 | LABEL; 470 | printf("%ssha256: %s: %s\n", 471 | tab, p->fts_accpath, strerror(errno)); 472 | tab = "\t"; 473 | } else { 474 | if (strcmp(s->sha256digest, digestbuf)) { 475 | LABEL; 476 | printf("%ssha256 (0x%s, 0x%s)\n", 477 | tab, s->sha256digest, digestbuf); 478 | } 479 | tab = "\t"; 480 | } 481 | } 482 | if (s->flags & F_SHA384) { 483 | if (SHA384_File(p->fts_accpath, digestbuf) == NULL) { 484 | LABEL; 485 | printf("%ssha384: %s: %s\n", 486 | tab, p->fts_accpath, strerror(errno)); 487 | tab = "\t"; 488 | } else { 489 | if (strcmp(s->sha384digest, digestbuf)) { 490 | LABEL; 491 | printf("%ssha384 (0x%s, 0x%s)\n", 492 | tab, s->sha384digest, digestbuf); 493 | } 494 | tab = "\t"; 495 | } 496 | } 497 | if (s->flags & F_SHA512) { 498 | if (SHA512_File(p->fts_accpath, digestbuf) == NULL) { 499 | LABEL; 500 | printf("%ssha512: %s: %s\n", 501 | tab, p->fts_accpath, strerror(errno)); 502 | tab = "\t"; 503 | } else { 504 | if (strcmp(s->sha512digest, digestbuf)) { 505 | LABEL; 506 | printf("%ssha512 (0x%s, 0x%s)\n", 507 | tab, s->sha512digest, digestbuf); 508 | } 509 | tab = "\t"; 510 | } 511 | } 512 | #endif /* ! NO_SHA2 */ 513 | if (s->flags & F_SLINK && 514 | strcmp(cp = rlink(p->fts_accpath), s->slink)) { 515 | LABEL; 516 | printf("%slink ref (%s, %s", tab, cp, s->slink); 517 | if (uflag) { 518 | if ((unlink(p->fts_accpath) == -1) || 519 | (symlink(s->slink, p->fts_accpath) == -1) ) 520 | printf(", not modified: %s)\n", 521 | strerror(errno)); 522 | else 523 | printf(", modified)\n"); 524 | } else 525 | printf(")\n"); 526 | } 527 | return (label); 528 | } 529 | 530 | const char * 531 | rlink(const char *name) 532 | { 533 | static char lbuf[MAXPATHLEN]; 534 | int len; 535 | 536 | if ((len = readlink(name, lbuf, sizeof(lbuf) - 1)) == -1) 537 | mtree_err("%s: %s", name, strerror(errno)); 538 | lbuf[len] = '\0'; 539 | return (lbuf); 540 | } 541 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_PREREQ(2.59) 2 | AC_INIT([mtree], [1.0.0], [https://github.com/archiecobbs/nmtree/issues]) 3 | AC_CONFIG_AUX_DIR([config]) 4 | AC_CONFIG_SRCDIR([mtree.c]) 5 | AC_CONFIG_HEADER([config.h]) 6 | AM_INIT_AUTOMAKE([1.9 foreign]) 7 | 8 | # Allow changing program name 9 | AC_ARG_PROGRAM 10 | 11 | # Checks for programs. 12 | AC_PROG_CC 13 | AC_PROG_INSTALL 14 | 15 | # Checks for libraries. 16 | AC_CHECK_LIB(nbcompat, fparseln) 17 | 18 | # Checks for header files. 19 | AC_HEADER_STDC 20 | AC_CHECK_HEADERS([ctype.h dirent.h err.h errno.h fcntl.h fnmatch.h fts.h \ 21 | grp.h limits.h netdb.h pwd.h \ 22 | stdarg.h stddef.h stdio.h stdlib.h string.h time.h unistd.h \ 23 | util.h vis.h]) 24 | AC_CHECK_HEADERS([sys/cdefs.h sys/param.h sys/queue.h sys/stat.h sys/types.h]) 25 | AC_CHECK_HEADERS([nbcompat/md5.h nbcompat/rmd160.h nbcompat/sha1.h nbcompat/sha2.h]) 26 | 27 | # Checks for typedefs, structures, and compiler characteristics. 28 | AC_C_CONST 29 | AC_TYPE_UID_T 30 | AC_TYPE_MODE_T 31 | AC_TYPE_OFF_T 32 | AC_TYPE_SIZE_T 33 | AC_CHECK_MEMBERS([struct stat.st_rdev]) 34 | AC_CHECK_MEMBERS([struct stat.st_flags]) 35 | AC_CHECK_DECLS([UF_SETTABLE, SF_SETTABLE]) 36 | AH_BOTTOM([/* Define to 1 if the user- and root-changeable masks were detected */ 37 | #if HAVE_STRUCT_STAT_ST_FLAGS && HAVE_DECL_UF_SETTABLE && HAVE_DECL_SF_SETTABLE 38 | #define HAVE_FILE_FLAGS 1 39 | #endif 40 | ]) 41 | AC_HEADER_TIME 42 | 43 | # Checks for library functions. 44 | AC_REPLACE_FNMATCH 45 | AC_CHECK_FUNCS([endgrent endpwent getcwd gethostname mkdir SHA256_File strchr strpbrk strstr strtol strtoul]) 46 | 47 | AC_CONFIG_FILES([Makefile]) 48 | AC_OUTPUT 49 | -------------------------------------------------------------------------------- /crc.c: -------------------------------------------------------------------------------- 1 | /* $NetBSD: crc.c,v 1.5 2010/03/21 16:30:17 joerg Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 1991, 1993 5 | * The Regents of the University of California. All rights reserved. 6 | * 7 | * This code is derived from software contributed to Berkeley by 8 | * James W. Williams of NASA Goddard Space Flight Center. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the University nor the names of its contributors 19 | * may be used to endorse or promote products derived from this software 20 | * without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 | * SUCH DAMAGE. 33 | */ 34 | 35 | #if HAVE_CONFIG_H 36 | #include "config.h" 37 | #endif 38 | #if HAVE_NBTOOL_CONFIG_H 39 | #include "nbtool_config.h" 40 | #endif 41 | 42 | #include 43 | #if HAVE_SYS_CDEFS_H 44 | #include 45 | #endif 46 | #if defined(__RCSID) && !defined(lint) 47 | #if 0 48 | static char sccsid[] = "@(#)crc.c 8.1 (Berkeley) 6/17/93"; 49 | #else 50 | __RCSID("$NetBSD: crc.c,v 1.5 2010/03/21 16:30:17 joerg Exp $"); 51 | #endif 52 | #endif /* not lint */ 53 | 54 | #if HAVE_SYS_TYPES_H 55 | #include 56 | #endif 57 | 58 | #if HAVE_STDIO_H 59 | #include 60 | #endif 61 | #if HAVE_TIME_H 62 | #include 63 | #endif 64 | #if HAVE_UNISTD_H 65 | #include 66 | #endif 67 | 68 | #include "extern.h" 69 | 70 | static const uint32_t crctab[] = { 71 | 0x0, 72 | 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 73 | 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 74 | 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 75 | 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 76 | 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f, 77 | 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 78 | 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 79 | 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 80 | 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 81 | 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe, 82 | 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, 83 | 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 84 | 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, 85 | 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 86 | 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 87 | 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 88 | 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 89 | 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 90 | 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, 91 | 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 92 | 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 93 | 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 94 | 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 95 | 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f, 96 | 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 97 | 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 98 | 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 99 | 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 100 | 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629, 101 | 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 102 | 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 103 | 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 104 | 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 105 | 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 106 | 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, 107 | 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 108 | 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, 109 | 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 110 | 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 111 | 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 112 | 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 113 | 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087, 114 | 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, 115 | 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 116 | 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 117 | 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 118 | 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 119 | 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09, 120 | 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 121 | 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 122 | 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 123 | }; 124 | 125 | /* 126 | * Compute a POSIX 1003.2 checksum. This routine has been broken out so that 127 | * other programs can use it. It takes a file descriptor to read from and 128 | * locations to store the crc and the number of bytes read. It returns 0 on 129 | * success and 1 on failure. Errno is set on failure. 130 | */ 131 | extern int sflag; 132 | uint32_t crc_total = ~0; /* The crc over a number of files. */ 133 | 134 | int 135 | crc(int fd, uint32_t *cval, uint32_t *clen) 136 | { 137 | u_char *p; 138 | int nr; 139 | uint32_t thecrc, len; 140 | uint32_t crctot; 141 | u_char buf[16 * 1024]; 142 | 143 | #define COMPUTE(var, ch) (var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)] 144 | 145 | thecrc = len = crctot = 0; 146 | if (sflag) 147 | crctot = ~crc_total; 148 | while ((nr = read(fd, buf, sizeof(buf))) > 0) 149 | if (sflag) { 150 | for (len += nr, p = buf; nr--; ++p) { 151 | COMPUTE(thecrc, *p); 152 | COMPUTE(crctot, *p); 153 | } 154 | } else { 155 | for (len += nr, p = buf; nr--; ++p) 156 | COMPUTE(thecrc, *p); 157 | } 158 | if (nr < 0) 159 | return 1; 160 | 161 | *clen = len; 162 | 163 | /* Include the length of the file. */ 164 | if (sflag) { 165 | for (; len != 0; len >>= 8) { 166 | COMPUTE(thecrc, len & 0xff); 167 | COMPUTE(crctot, len & 0xff); 168 | } 169 | } else { 170 | for (; len != 0; len >>= 8) 171 | COMPUTE(thecrc, len & 0xff); 172 | } 173 | 174 | *cval = ~thecrc; 175 | if (sflag) 176 | crc_total = ~crctot; 177 | return 0; 178 | } 179 | -------------------------------------------------------------------------------- /create.c: -------------------------------------------------------------------------------- 1 | /* $NetBSD: create.c,v 1.9 2013/09/08 16:20:10 ryoon Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 1989, 1993 5 | * The Regents of the University of California. All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. Neither the name of the University nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 | * SUCH DAMAGE. 30 | */ 31 | 32 | #if HAVE_CONFIG_H 33 | #include "config.h" 34 | #endif 35 | #if HAVE_NBTOOL_CONFIG_H 36 | #include "nbtool_config.h" 37 | #endif 38 | 39 | #include 40 | #if HAVE_SYS_CDEFS_H 41 | #include 42 | #endif 43 | #if defined(__RCSID) && !defined(lint) 44 | #if 0 45 | static char sccsid[] = "@(#)create.c 8.1 (Berkeley) 6/6/93"; 46 | #else 47 | __RCSID("$NetBSD: create.c,v 1.9 2013/09/08 16:20:10 ryoon Exp $"); 48 | #endif 49 | #endif /* not lint */ 50 | 51 | #if HAVE_SYS_PARAM_H 52 | #include 53 | #endif 54 | #if HAVE_SYS_STAT_H 55 | #include 56 | #endif 57 | 58 | #if ! HAVE_NBTOOL_CONFIG_H 59 | #if HAVE_DIRENT_H 60 | #include 61 | #endif 62 | #endif 63 | 64 | #if HAVE_ERRNO_H 65 | #include 66 | #endif 67 | #if HAVE_FCNTL_H 68 | #include 69 | #endif 70 | #if HAVE_GRP_H 71 | #include 72 | #endif 73 | #if HAVE_PWD_H 74 | #include 75 | #endif 76 | #if HAVE_STDIO_H 77 | #include 78 | #endif 79 | #if HAVE_STDARG_H 80 | #include 81 | #endif 82 | #if HAVE_STDLIB_H 83 | #include 84 | #endif 85 | #if HAVE_STRING_H 86 | #include 87 | #endif 88 | #if HAVE_TIME_H 89 | #include 90 | #endif 91 | #if HAVE_UNISTD_H 92 | #include 93 | #endif 94 | 95 | #ifndef NO_MD5 96 | #if HAVE_MD5_H 97 | #include 98 | #else 99 | #include 100 | #endif 101 | #endif 102 | #ifndef NO_RMD160 103 | #if HAVE_RMD160_H 104 | #include 105 | #else 106 | #include 107 | #endif 108 | #endif 109 | #ifndef NO_SHA1 110 | #if HAVE_SHA1_H 111 | #include 112 | #else 113 | #include 114 | #endif 115 | #endif 116 | #ifndef NO_SHA2 117 | #if HAVE_SHA2_H && HAVE_SHA512_FILE 118 | #include 119 | #else 120 | #include 121 | #endif 122 | #endif 123 | 124 | #include "extern.h" 125 | 126 | #define INDENTNAMELEN 15 127 | #define MAXLINELEN 80 128 | 129 | static gid_t gid; 130 | static uid_t uid; 131 | static mode_t mode; 132 | static u_long flags; 133 | 134 | static int dsort(const FTSENT **, const FTSENT **); 135 | static void output(int *, const char *, ...) 136 | __attribute__((__format__(__printf__, 2, 3))); 137 | static int statd(FTS *, FTSENT *, uid_t *, gid_t *, mode_t *, u_long *); 138 | static void statf(FTSENT *); 139 | 140 | void 141 | cwalk(void) 142 | { 143 | FTS *t; 144 | FTSENT *p; 145 | time_t clocktime; 146 | char host[MAXHOSTNAMELEN + 1]; 147 | char *argv[2]; 148 | char dot[] = "."; 149 | argv[0] = dot; 150 | argv[1] = NULL; 151 | 152 | time(&clocktime); 153 | gethostname(host, sizeof(host)); 154 | host[sizeof(host) - 1] = '\0'; 155 | printf( 156 | "#\t user: %s\n#\tmachine: %s\n#\t tree: %s\n#\t date: %s", 157 | getlogin(), host, fullpath, ctime(&clocktime)); 158 | 159 | if ((t = fts_open(argv, ftsoptions, dsort)) == NULL) 160 | mtree_err("fts_open: %s", strerror(errno)); 161 | while ((p = fts_read(t)) != NULL) { 162 | if (check_excludes(p->fts_name, p->fts_path)) { 163 | fts_set(t, p, FTS_SKIP); 164 | continue; 165 | } 166 | switch(p->fts_info) { 167 | case FTS_D: 168 | printf("\n# %s\n", p->fts_path); 169 | statd(t, p, &uid, &gid, &mode, &flags); 170 | statf(p); 171 | break; 172 | case FTS_DP: 173 | if (p->fts_level > 0) 174 | printf("# %s\n..\n\n", p->fts_path); 175 | break; 176 | case FTS_DNR: 177 | case FTS_ERR: 178 | case FTS_NS: 179 | mtree_err("%s: %s", 180 | p->fts_path, strerror(p->fts_errno)); 181 | break; 182 | default: 183 | if (!dflag) 184 | statf(p); 185 | break; 186 | 187 | } 188 | } 189 | fts_close(t); 190 | if (sflag && keys & F_CKSUM) 191 | mtree_err("%s checksum: %u", fullpath, crc_total); 192 | } 193 | 194 | static void 195 | statf(FTSENT *p) 196 | { 197 | uint32_t len, val; 198 | int fd, indent; 199 | const char *name; 200 | #if !defined(NO_MD5) || !defined(NO_RMD160) || !defined(NO_SHA1) || !defined(NO_SHA2) 201 | char digestbuf[MAXHASHLEN + 1]; 202 | #endif 203 | 204 | indent = printf("%s%s", 205 | S_ISDIR(p->fts_statp->st_mode) ? "" : " ", vispath(p->fts_name)); 206 | 207 | if (indent > INDENTNAMELEN) 208 | indent = MAXLINELEN; 209 | else 210 | indent += printf("%*s", INDENTNAMELEN - indent, ""); 211 | 212 | if (!S_ISREG(p->fts_statp->st_mode)) 213 | output(&indent, "type=%s", inotype(p->fts_statp->st_mode)); 214 | if (keys & (F_UID | F_UNAME) && p->fts_statp->st_uid != uid) { 215 | if (keys & F_UNAME && 216 | (name = user_from_uid(p->fts_statp->st_uid, 1)) != NULL) 217 | output(&indent, "uname=%s", name); 218 | else /* if (keys & F_UID) */ 219 | output(&indent, "uid=%u", p->fts_statp->st_uid); 220 | } 221 | if (keys & (F_GID | F_GNAME) && p->fts_statp->st_gid != gid) { 222 | if (keys & F_GNAME && 223 | (name = group_from_gid(p->fts_statp->st_gid, 1)) != NULL) 224 | output(&indent, "gname=%s", name); 225 | else /* if (keys & F_GID) */ 226 | output(&indent, "gid=%u", p->fts_statp->st_gid); 227 | } 228 | if (keys & F_MODE && (p->fts_statp->st_mode & MBITS) != mode) 229 | output(&indent, "mode=%#o", p->fts_statp->st_mode & MBITS); 230 | if (keys & F_DEV && 231 | (S_ISBLK(p->fts_statp->st_mode) || S_ISCHR(p->fts_statp->st_mode))) 232 | output(&indent, "device=%#lx", (unsigned long)p->fts_statp->st_rdev); 233 | if (keys & F_NLINK && p->fts_statp->st_nlink != 1) 234 | output(&indent, "nlink=%lu", (unsigned long)p->fts_statp->st_nlink); 235 | if (keys & F_SIZE && S_ISREG(p->fts_statp->st_mode)) 236 | output(&indent, "size=%lld", (long long)p->fts_statp->st_size); 237 | if (keys & F_TIME) 238 | output(&indent, "time=%ju.%09ld", 239 | (uintmax_t)p->fts_statp->st_mtim.tv_sec, 240 | (long)p->fts_statp->st_mtim.tv_nsec); 241 | if (keys & F_CKSUM && S_ISREG(p->fts_statp->st_mode)) { 242 | if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0 || 243 | crc(fd, &val, &len)) 244 | mtree_err("%s: %s", p->fts_accpath, strerror(errno)); 245 | close(fd); 246 | output(&indent, "cksum=%lu", (long)val); 247 | } 248 | #ifndef NO_MD5 249 | if (keys & F_MD5 && S_ISREG(p->fts_statp->st_mode)) { 250 | if (MD5File(p->fts_accpath, digestbuf) == NULL) 251 | mtree_err("%s: %s", p->fts_accpath, "MD5File"); 252 | output(&indent, "md5=%s", digestbuf); 253 | } 254 | #endif /* ! NO_MD5 */ 255 | #ifndef NO_RMD160 256 | if (keys & F_RMD160 && S_ISREG(p->fts_statp->st_mode)) { 257 | if (RMD160File(p->fts_accpath, digestbuf) == NULL) 258 | mtree_err("%s: %s", p->fts_accpath, "RMD160File"); 259 | output(&indent, "rmd160=%s", digestbuf); 260 | } 261 | #endif /* ! NO_RMD160 */ 262 | #ifndef NO_SHA1 263 | if (keys & F_SHA1 && S_ISREG(p->fts_statp->st_mode)) { 264 | if (SHA1File(p->fts_accpath, digestbuf) == NULL) 265 | mtree_err("%s: %s", p->fts_accpath, "SHA1File"); 266 | output(&indent, "sha1=%s", digestbuf); 267 | } 268 | #endif /* ! NO_SHA1 */ 269 | #ifndef NO_SHA2 270 | if (keys & F_SHA256 && S_ISREG(p->fts_statp->st_mode)) { 271 | if (SHA256_File(p->fts_accpath, digestbuf) == NULL) 272 | mtree_err("%s: %s", p->fts_accpath, "SHA256_File"); 273 | output(&indent, "sha256=%s", digestbuf); 274 | } 275 | if (keys & F_SHA384 && S_ISREG(p->fts_statp->st_mode)) { 276 | if (SHA384_File(p->fts_accpath, digestbuf) == NULL) 277 | mtree_err("%s: %s", p->fts_accpath, "SHA384_File"); 278 | output(&indent, "sha384=%s", digestbuf); 279 | } 280 | if (keys & F_SHA512 && S_ISREG(p->fts_statp->st_mode)) { 281 | if (SHA512_File(p->fts_accpath, digestbuf) == NULL) 282 | mtree_err("%s: %s", p->fts_accpath, "SHA512_File"); 283 | output(&indent, "sha512=%s", digestbuf); 284 | } 285 | #endif /* ! NO_SHA2 */ 286 | if (keys & F_SLINK && 287 | (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) 288 | output(&indent, "link=%s", vispath(rlink(p->fts_accpath))); 289 | #if HAVE_STRUCT_STAT_ST_FLAGS 290 | if (keys & F_FLAGS && p->fts_statp->st_flags != flags) 291 | output(&indent, "flags=%s", 292 | flags_to_string(p->fts_statp->st_flags, "none")); 293 | #endif 294 | putchar('\n'); 295 | } 296 | 297 | /* XXX 298 | * FLAGS2INDEX will fail once the user and system settable bits need more 299 | * than one byte, respectively. 300 | */ 301 | #define FLAGS2INDEX(x) (((x >> 8) & 0x0000ff00) | (x & 0x000000ff)) 302 | 303 | #define MTREE_MAXGID 5000 304 | #define MTREE_MAXUID 5000 305 | #define MTREE_MAXMODE (MBITS + 1) 306 | #if HAVE_STRUCT_STAT_ST_FLAGS 307 | #define MTREE_MAXFLAGS (FLAGS2INDEX(CH_MASK) + 1) /* 1808 */ 308 | #else 309 | #define MTREE_MAXFLAGS 1 310 | #endif 311 | #define MTREE_MAXS 16 312 | 313 | static int 314 | statd(FTS *t, FTSENT *parent, uid_t *puid, gid_t *pgid, mode_t *pmode, 315 | u_long *pflags) 316 | { 317 | FTSENT *p; 318 | gid_t sgid; 319 | uid_t suid; 320 | mode_t smode; 321 | #if HAVE_STRUCT_STAT_ST_FLAGS 322 | u_long sflags = 0; 323 | #endif 324 | const char *name; 325 | gid_t savegid; 326 | uid_t saveuid; 327 | mode_t savemode; 328 | u_long saveflags; 329 | u_short maxgid, maxuid, maxmode, maxflags; 330 | u_short g[MTREE_MAXGID], u[MTREE_MAXUID], 331 | m[MTREE_MAXMODE], f[MTREE_MAXFLAGS]; 332 | static int first = 1; 333 | 334 | savegid = *pgid; 335 | saveuid = *puid; 336 | savemode = *pmode; 337 | saveflags = *pflags; 338 | if ((p = fts_children(t, 0)) == NULL) { 339 | if (errno) 340 | mtree_err("%s: %s", RP(parent), strerror(errno)); 341 | return (1); 342 | } 343 | 344 | memset(g, 0, sizeof(g)); 345 | memset(u, 0, sizeof(u)); 346 | memset(m, 0, sizeof(m)); 347 | memset(f, 0, sizeof(f)); 348 | 349 | maxuid = maxgid = maxmode = maxflags = 0; 350 | for (; p; p = p->fts_link) { 351 | smode = p->fts_statp->st_mode & MBITS; 352 | if (smode < MTREE_MAXMODE && ++m[smode] > maxmode) { 353 | savemode = smode; 354 | maxmode = m[smode]; 355 | } 356 | sgid = p->fts_statp->st_gid; 357 | if (sgid < MTREE_MAXGID && ++g[sgid] > maxgid) { 358 | savegid = sgid; 359 | maxgid = g[sgid]; 360 | } 361 | suid = p->fts_statp->st_uid; 362 | if (suid < MTREE_MAXUID && ++u[suid] > maxuid) { 363 | saveuid = suid; 364 | maxuid = u[suid]; 365 | } 366 | 367 | #if HAVE_STRUCT_STAT_ST_FLAGS 368 | sflags = FLAGS2INDEX(p->fts_statp->st_flags); 369 | if (sflags < MTREE_MAXFLAGS && ++f[sflags] > maxflags) { 370 | saveflags = p->fts_statp->st_flags; 371 | maxflags = f[sflags]; 372 | } 373 | #endif 374 | } 375 | /* 376 | * If the /set record is the same as the last one we do not need to 377 | * output a new one. So first we check to see if anything changed. 378 | * Note that we always output a /set record for the first directory. 379 | */ 380 | if (((keys & (F_UNAME | F_UID)) && (*puid != saveuid)) || 381 | ((keys & (F_GNAME | F_GID)) && (*pgid != savegid)) || 382 | ((keys & F_MODE) && (*pmode != savemode)) || 383 | ((keys & F_FLAGS) && (*pflags != saveflags)) || 384 | first) { 385 | first = 0; 386 | printf("/set type=file"); 387 | if (keys & (F_UID | F_UNAME)) { 388 | if (keys & F_UNAME && 389 | (name = user_from_uid(saveuid, 1)) != NULL) 390 | printf(" uname=%s", name); 391 | else /* if (keys & F_UID) */ 392 | printf(" uid=%lu", (u_long)saveuid); 393 | } 394 | if (keys & (F_GID | F_GNAME)) { 395 | if (keys & F_GNAME && 396 | (name = group_from_gid(savegid, 1)) != NULL) 397 | printf(" gname=%s", name); 398 | else /* if (keys & F_UID) */ 399 | printf(" gid=%lu", (u_long)savegid); 400 | } 401 | if (keys & F_MODE) 402 | printf(" mode=%#lo", (u_long)savemode); 403 | if (keys & F_NLINK) 404 | printf(" nlink=1"); 405 | if (keys & F_FLAGS) 406 | printf(" flags=%s", 407 | flags_to_string(saveflags, "none")); 408 | printf("\n"); 409 | *puid = saveuid; 410 | *pgid = savegid; 411 | *pmode = savemode; 412 | *pflags = saveflags; 413 | } 414 | return (0); 415 | } 416 | 417 | static int 418 | dsort(const FTSENT **a, const FTSENT **b) 419 | { 420 | 421 | if (S_ISDIR((*a)->fts_statp->st_mode)) { 422 | if (!S_ISDIR((*b)->fts_statp->st_mode)) 423 | return (1); 424 | } else if (S_ISDIR((*b)->fts_statp->st_mode)) 425 | return (-1); 426 | return (strcmp((*a)->fts_name, (*b)->fts_name)); 427 | } 428 | 429 | static void 430 | output(int *offset, const char *fmt, ...) 431 | { 432 | va_list ap; 433 | char buf[1024]; 434 | 435 | va_start(ap, fmt); 436 | vsnprintf(buf, sizeof(buf), fmt, ap); 437 | va_end(ap); 438 | 439 | if (*offset + strlen(buf) > MAXLINELEN - 3) { 440 | printf(" \\\n%*s", INDENTNAMELEN, ""); 441 | *offset = INDENTNAMELEN; 442 | } 443 | *offset += printf(" %s", buf) + 1; 444 | } 445 | -------------------------------------------------------------------------------- /excludes.c: -------------------------------------------------------------------------------- 1 | /* $NetBSD: excludes.c,v 1.4 2004/08/21 04:10:45 jlam Exp $ */ 2 | 3 | /* 4 | * Copyright 2000 Massachusetts Institute of Technology 5 | * 6 | * Permission to use, copy, modify, and distribute this software and 7 | * its documentation for any purpose and without fee is hereby 8 | * granted, provided that both the above copyright notice and this 9 | * permission notice appear in all copies, that both the above 10 | * copyright notice and this permission notice appear in all 11 | * supporting documentation, and that the name of M.I.T. not be used 12 | * in advertising or publicity pertaining to distribution of the 13 | * software without specific, written prior permission. M.I.T. makes 14 | * no representations about the suitability of this software for any 15 | * purpose. It is provided "as is" without express or implied 16 | * warranty. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS 19 | * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, 20 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT 22 | * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 25 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 28 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 | * SUCH DAMAGE. 30 | */ 31 | 32 | #if HAVE_CONFIG_H 33 | #include "config.h" 34 | #endif 35 | #if HAVE_NBTOOL_CONFIG_H 36 | #include "nbtool_config.h" 37 | #endif 38 | 39 | #include 40 | #if HAVE_SYS_CDEFS_H 41 | #include 42 | #endif 43 | 44 | #if defined(__RCSID) && !defined(lint) 45 | __RCSID("$NetBSD: excludes.c,v 1.4 2004/08/21 04:10:45 jlam Exp $"); 46 | #endif 47 | 48 | #if HAVE_SYS_TYPES_H 49 | #include 50 | #endif 51 | #if HAVE_SYS_QUEUE_H 52 | #include 53 | #endif 54 | 55 | #if HAVE_FNMATCH_H 56 | #include 57 | #endif 58 | #if HAVE_STDIO_H 59 | #include 60 | #endif 61 | #if HAVE_STDLIB_H 62 | #include 63 | #endif 64 | #if HAVE_STRING_H 65 | #include 66 | #endif 67 | #if HAVE_TIME_H 68 | #include 69 | #endif 70 | #if HAVE_UTIL_H 71 | #include 72 | #endif 73 | 74 | #include "extern.h" 75 | 76 | 77 | /* 78 | * We're assuming that there won't be a whole lot of excludes, 79 | * so it's OK to use a stupid algorithm. 80 | */ 81 | struct exclude { 82 | LIST_ENTRY(exclude) link; 83 | const char *glob; 84 | int pathname; 85 | }; 86 | static LIST_HEAD(, exclude) excludes; 87 | 88 | 89 | void 90 | init_excludes(void) 91 | { 92 | 93 | LIST_INIT(&excludes); 94 | } 95 | 96 | void 97 | read_excludes_file(const char *name) 98 | { 99 | FILE *fp; 100 | char *line; 101 | struct exclude *e; 102 | 103 | fp = fopen(name, "r"); 104 | if (fp == 0) 105 | err(1, "%s", name); 106 | 107 | while ((line = fparseln(fp, NULL, NULL, NULL, 108 | FPARSELN_UNESCCOMM | FPARSELN_UNESCCONT | FPARSELN_UNESCESC)) 109 | != NULL) { 110 | if (line[0] == '\0') 111 | continue; 112 | 113 | if ((e = malloc(sizeof *e)) == NULL) 114 | mtree_err("memory allocation error"); 115 | 116 | e->glob = line; 117 | if (strchr(e->glob, '/') != NULL) 118 | e->pathname = 1; 119 | else 120 | e->pathname = 0; 121 | LIST_INSERT_HEAD(&excludes, e, link); 122 | } 123 | fclose(fp); 124 | } 125 | 126 | int 127 | check_excludes(const char *fname, const char *path) 128 | { 129 | struct exclude *e; 130 | 131 | /* fnmatch(3) has a funny return value convention... */ 132 | #define MATCH(g, n) (fnmatch((g), (n), FNM_PATHNAME) == 0) 133 | 134 | e = LIST_FIRST(&excludes); 135 | while (e) { 136 | if ((e->pathname && MATCH(e->glob, path)) 137 | || MATCH(e->glob, fname)) { 138 | return (1); 139 | } 140 | e = LIST_NEXT(e, link); 141 | } 142 | return (0); 143 | } 144 | -------------------------------------------------------------------------------- /extern.h: -------------------------------------------------------------------------------- 1 | /* $NetBSD: extern.h,v 1.5 2011/07/27 15:31:00 seb Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 1991, 1993 5 | * The Regents of the University of California. All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. Neither the name of the University nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 | * SUCH DAMAGE. 30 | * 31 | * @(#)extern.h 8.1 (Berkeley) 6/6/93 32 | */ 33 | 34 | #if HAVE_CONFIG_H 35 | #include "config.h" 36 | #endif 37 | #include "mtree.h" 38 | 39 | #if 0 40 | #if HAVE_NBTOOL_CONFIG_H 41 | #include "nbtool_config.h" 42 | #else 43 | #define HAVE_STRUCT_STAT_ST_FLAGS 1 44 | #endif 45 | #endif 46 | 47 | #include 48 | #if HAVE_ERR_H 49 | #include 50 | #endif 51 | #if HAVE_FTS_H 52 | #include 53 | #endif 54 | 55 | #if HAVE_NETDB_H 56 | /* For MAXHOSTNAMELEN on some platforms. */ 57 | #if HAVE_NETDB_H 58 | #include 59 | #endif 60 | #endif 61 | 62 | #ifndef MAXHOSTNAMELEN 63 | #define MAXHOSTNAMELEN 256 64 | #endif 65 | 66 | void addtag(slist_t *, char *); 67 | int check_excludes(const char *, const char *); 68 | int compare(NODE *, FTSENT *); 69 | int crc(int, uint32_t *, uint32_t *); 70 | void cwalk(void); 71 | void dump_nodes(const char *, NODE *, int); 72 | void init_excludes(void); 73 | int matchtags(NODE *); 74 | void mtree_err(const char *, ...) 75 | __attribute__((__format__(__printf__, 1, 2))); 76 | const char *nodetype(u_int); 77 | u_int parsekey(const char *, int *); 78 | void parsetags(slist_t *, char *); 79 | u_int parsetype(const char *); 80 | void read_excludes_file(const char *); 81 | const char *rlink(const char *); 82 | int verify(void); 83 | 84 | extern int dflag, eflag, gflag, iflag, lflag, mflag, rflag, sflag, tflag, uflag; 85 | extern int mtree_Mflag, mtree_Wflag; 86 | extern size_t mtree_lineno; 87 | extern uint32_t crc_total; 88 | extern int ftsoptions, keys; 89 | extern char fullpath[]; 90 | extern slist_t includetags, excludetags; 91 | 92 | 93 | #include "stat_flags.h" 94 | -------------------------------------------------------------------------------- /getid.c: -------------------------------------------------------------------------------- 1 | /* $NetBSD: getid.c,v 1.4 2008/11/06 02:14:52 jschauma Exp $ */ 2 | /* from: NetBSD: getpwent.c,v 1.48 2000/10/03 03:22:26 enami Exp */ 3 | /* from: NetBSD: getgrent.c,v 1.41 2002/01/12 23:51:30 lukem Exp */ 4 | 5 | /* 6 | * Copyright (c) 1987, 1988, 1989, 1993, 1994, 1995 7 | * The Regents of the University of California. All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 1. Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * 2. Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in the 16 | * documentation and/or other materials provided with the distribution. 17 | * 3. Neither the name of the University nor the names of its contributors 18 | * may be used to endorse or promote products derived from this software 19 | * without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 | * SUCH DAMAGE. 32 | */ 33 | 34 | /*- 35 | * Copyright (c) 2002 The NetBSD Foundation, Inc. 36 | * All rights reserved. 37 | * 38 | * This code is derived from software contributed to The NetBSD Foundation 39 | * by Luke Mewburn of Wasabi Systems. 40 | * 41 | * Redistribution and use in source and binary forms, with or without 42 | * modification, are permitted provided that the following conditions 43 | * are met: 44 | * 1. Redistributions of source code must retain the above copyright 45 | * notice, this list of conditions and the following disclaimer. 46 | * 2. Redistributions in binary form must reproduce the above copyright 47 | * notice, this list of conditions and the following disclaimer in the 48 | * documentation and/or other materials provided with the distribution. 49 | * 3. All advertising materials mentioning features or use of this software 50 | * must display the following acknowledgement: 51 | * This product includes software developed by the NetBSD 52 | * Foundation, Inc. and its contributors. 53 | * 4. Neither the name of The NetBSD Foundation nor the names of its 54 | * contributors may be used to endorse or promote products derived 55 | * from this software without specific prior written permission. 56 | * 57 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 58 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 59 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 60 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 61 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 62 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 63 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 64 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 65 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 66 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 67 | * POSSIBILITY OF SUCH DAMAGE. 68 | */ 69 | 70 | #if HAVE_CONFIG_H 71 | #include "config.h" 72 | #endif 73 | #if HAVE_NBTOOL_CONFIG_H 74 | #include "nbtool_config.h" 75 | #endif 76 | 77 | #include 78 | #if HAVE_SYS_PARAM_H 79 | #include 80 | #endif 81 | 82 | #if HAVE_GRP_H 83 | #include 84 | #endif 85 | #if HAVE_LIMITS_H 86 | #include 87 | #endif 88 | #if HAVE_PWD_H 89 | #include 90 | #endif 91 | #if HAVE_STDLIB_H 92 | #include 93 | #endif 94 | #if HAVE_STDIO_H 95 | #include 96 | #endif 97 | #if HAVE_STRING_H 98 | #include 99 | #endif 100 | #if HAVE_TIME_H 101 | #include 102 | #endif 103 | #if HAVE_UNISTD_H 104 | #include 105 | #endif 106 | 107 | #include "extern.h" 108 | 109 | static struct group * gi_getgrnam(const char *); 110 | static struct group * gi_getgrgid(gid_t); 111 | static int gi_setgroupent(int); 112 | static void gi_endgrent(void); 113 | static int grstart(void); 114 | static int grscan(int, gid_t, const char *); 115 | static int grmatchline(int, gid_t, const char *); 116 | 117 | static struct passwd * gi_getpwnam(const char *); 118 | static struct passwd * gi_getpwuid(uid_t); 119 | static int gi_setpassent(int); 120 | static void gi_endpwent(void); 121 | static int pwstart(void); 122 | static int pwscan(int, uid_t, const char *); 123 | static int pwmatchline(int, uid_t, const char *); 124 | 125 | #define MAXGRP 200 126 | #define MAXLINELENGTH 1024 127 | 128 | static FILE *_gr_fp; 129 | static struct group _gr_group; 130 | static int _gr_stayopen; 131 | static int _gr_filesdone; 132 | static FILE *_pw_fp; 133 | static struct passwd _pw_passwd; /* password structure */ 134 | static int _pw_stayopen; /* keep fd's open */ 135 | static int _pw_filesdone; 136 | 137 | static char grfile[MAXPATHLEN]; 138 | static char pwfile[MAXPATHLEN]; 139 | 140 | static char *members[MAXGRP]; 141 | static char grline[MAXLINELENGTH]; 142 | static char pwline[MAXLINELENGTH]; 143 | 144 | int 145 | setup_getid(const char *dir) 146 | { 147 | if (dir == NULL) 148 | return (0); 149 | 150 | /* close existing databases */ 151 | gi_endgrent(); 152 | gi_endpwent(); 153 | 154 | /* build paths to new databases */ 155 | snprintf(grfile, sizeof(grfile), "%s/group", dir); 156 | snprintf(pwfile, sizeof(pwfile), "%s/master.passwd", dir); 157 | 158 | /* try to open new databases */ 159 | if (!grstart() || !pwstart()) 160 | return (0); 161 | 162 | /* switch pwcache(3) lookup functions */ 163 | if (pwcache_groupdb(gi_setgroupent, gi_endgrent, 164 | gi_getgrnam, gi_getgrgid) == -1 165 | || pwcache_userdb(gi_setpassent, gi_endpwent, 166 | gi_getpwnam, gi_getpwuid) == -1) 167 | return (0); 168 | 169 | return (1); 170 | } 171 | 172 | 173 | /* 174 | * group lookup functions 175 | */ 176 | 177 | static struct group * 178 | gi_getgrnam(const char *name) 179 | { 180 | int rval; 181 | 182 | if (!grstart()) 183 | return NULL; 184 | rval = grscan(1, 0, name); 185 | if (!_gr_stayopen) 186 | endgrent(); 187 | return (rval) ? &_gr_group : NULL; 188 | } 189 | 190 | static struct group * 191 | gi_getgrgid(gid_t gid) 192 | { 193 | int rval; 194 | 195 | if (!grstart()) 196 | return NULL; 197 | rval = grscan(1, gid, NULL); 198 | if (!_gr_stayopen) 199 | endgrent(); 200 | return (rval) ? &_gr_group : NULL; 201 | } 202 | 203 | static int 204 | gi_setgroupent(int stayopen) 205 | { 206 | 207 | if (!grstart()) 208 | return 0; 209 | _gr_stayopen = stayopen; 210 | return 1; 211 | } 212 | 213 | static void 214 | gi_endgrent(void) 215 | { 216 | 217 | _gr_filesdone = 0; 218 | if (_gr_fp) { 219 | (void)fclose(_gr_fp); 220 | _gr_fp = NULL; 221 | } 222 | } 223 | 224 | static int 225 | grstart(void) 226 | { 227 | 228 | _gr_filesdone = 0; 229 | if (_gr_fp) { 230 | rewind(_gr_fp); 231 | return 1; 232 | } 233 | if (grfile[0] == '\0') /* sanity check */ 234 | return 0; 235 | return (_gr_fp = fopen(grfile, "r")) ? 1 : 0; 236 | } 237 | 238 | 239 | static int 240 | grscan(int search, gid_t gid, const char *name) 241 | { 242 | 243 | if (_gr_filesdone) 244 | return 0; 245 | for (;;) { 246 | if (!fgets(grline, sizeof(grline), _gr_fp)) { 247 | if (!search) 248 | _gr_filesdone = 1; 249 | return 0; 250 | } 251 | /* skip lines that are too big */ 252 | if (!strchr(grline, '\n')) { 253 | int ch; 254 | 255 | while ((ch = getc(_gr_fp)) != '\n' && ch != EOF) 256 | ; 257 | continue; 258 | } 259 | if (grmatchline(search, gid, name)) 260 | return 1; 261 | } 262 | /* NOTREACHED */ 263 | } 264 | 265 | static int 266 | grmatchline(int search, gid_t gid, const char *name) 267 | { 268 | unsigned long id; 269 | char **m; 270 | char *cp, *bp, *ep; 271 | 272 | /* name may be NULL if search is nonzero */ 273 | 274 | bp = grline; 275 | memset(&_gr_group, 0, sizeof(_gr_group)); 276 | _gr_group.gr_name = strsep(&bp, ":\n"); 277 | if (search && name && strcmp(_gr_group.gr_name, name)) 278 | return 0; 279 | _gr_group.gr_passwd = strsep(&bp, ":\n"); 280 | if (!(cp = strsep(&bp, ":\n"))) 281 | return 0; 282 | id = strtoul(cp, &ep, 10); 283 | if (id > GID_MAX || *ep != '\0') 284 | return 0; 285 | _gr_group.gr_gid = (gid_t)id; 286 | if (search && name == NULL && _gr_group.gr_gid != gid) 287 | return 0; 288 | cp = NULL; 289 | if (bp == NULL) 290 | return 0; 291 | for (_gr_group.gr_mem = m = members;; bp++) { 292 | if (m == &members[MAXGRP - 1]) 293 | break; 294 | if (*bp == ',') { 295 | if (cp) { 296 | *bp = '\0'; 297 | *m++ = cp; 298 | cp = NULL; 299 | } 300 | } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') { 301 | if (cp) { 302 | *bp = '\0'; 303 | *m++ = cp; 304 | } 305 | break; 306 | } else if (cp == NULL) 307 | cp = bp; 308 | } 309 | *m = NULL; 310 | return 1; 311 | } 312 | 313 | 314 | /* 315 | * user lookup functions 316 | */ 317 | 318 | static struct passwd * 319 | gi_getpwnam(const char *name) 320 | { 321 | int rval; 322 | 323 | if (!pwstart()) 324 | return NULL; 325 | rval = pwscan(1, 0, name); 326 | if (!_pw_stayopen) 327 | endpwent(); 328 | return (rval) ? &_pw_passwd : NULL; 329 | } 330 | 331 | static struct passwd * 332 | gi_getpwuid(uid_t uid) 333 | { 334 | int rval; 335 | 336 | if (!pwstart()) 337 | return NULL; 338 | rval = pwscan(1, uid, NULL); 339 | if (!_pw_stayopen) 340 | endpwent(); 341 | return (rval) ? &_pw_passwd : NULL; 342 | } 343 | 344 | static int 345 | gi_setpassent(int stayopen) 346 | { 347 | 348 | if (!pwstart()) 349 | return 0; 350 | _pw_stayopen = stayopen; 351 | return 1; 352 | } 353 | 354 | static void 355 | gi_endpwent(void) 356 | { 357 | 358 | _pw_filesdone = 0; 359 | if (_pw_fp) { 360 | (void)fclose(_pw_fp); 361 | _pw_fp = NULL; 362 | } 363 | } 364 | 365 | static int 366 | pwstart(void) 367 | { 368 | 369 | _pw_filesdone = 0; 370 | if (_pw_fp) { 371 | rewind(_pw_fp); 372 | return 1; 373 | } 374 | if (pwfile[0] == '\0') /* sanity check */ 375 | return 0; 376 | return (_pw_fp = fopen(pwfile, "r")) ? 1 : 0; 377 | } 378 | 379 | 380 | static int 381 | pwscan(int search, uid_t uid, const char *name) 382 | { 383 | 384 | if (_pw_filesdone) 385 | return 0; 386 | for (;;) { 387 | if (!fgets(pwline, sizeof(pwline), _pw_fp)) { 388 | if (!search) 389 | _pw_filesdone = 1; 390 | return 0; 391 | } 392 | /* skip lines that are too big */ 393 | if (!strchr(pwline, '\n')) { 394 | int ch; 395 | 396 | while ((ch = getc(_pw_fp)) != '\n' && ch != EOF) 397 | ; 398 | continue; 399 | } 400 | if (pwmatchline(search, uid, name)) 401 | return 1; 402 | } 403 | /* NOTREACHED */ 404 | } 405 | 406 | static int 407 | pwmatchline(int search, uid_t uid, const char *name) 408 | { 409 | unsigned long id; 410 | char *cp, *bp, *ep; 411 | 412 | /* name may be NULL if search is nonzero */ 413 | 414 | bp = pwline; 415 | memset(&_pw_passwd, 0, sizeof(_pw_passwd)); 416 | _pw_passwd.pw_name = strsep(&bp, ":\n"); /* name */ 417 | if (search && name && strcmp(_pw_passwd.pw_name, name)) 418 | return 0; 419 | 420 | _pw_passwd.pw_passwd = strsep(&bp, ":\n"); /* passwd */ 421 | 422 | if (!(cp = strsep(&bp, ":\n"))) /* uid */ 423 | return 0; 424 | id = strtoul(cp, &ep, 10); 425 | if (id > UID_MAX || *ep != '\0') 426 | return 0; 427 | _pw_passwd.pw_uid = (uid_t)id; 428 | if (search && name == NULL && _pw_passwd.pw_uid != uid) 429 | return 0; 430 | 431 | if (!(cp = strsep(&bp, ":\n"))) /* gid */ 432 | return 0; 433 | id = strtoul(cp, &ep, 10); 434 | if (id > GID_MAX || *ep != '\0') 435 | return 0; 436 | _pw_passwd.pw_gid = (gid_t)id; 437 | 438 | if (!(ep = strsep(&bp, ":"))) /* class */ 439 | return 0; 440 | if (!(ep = strsep(&bp, ":"))) /* change */ 441 | return 0; 442 | if (!(ep = strsep(&bp, ":"))) /* expire */ 443 | return 0; 444 | 445 | if (!(_pw_passwd.pw_gecos = strsep(&bp, ":\n"))) /* gecos */ 446 | return 0; 447 | if (!(_pw_passwd.pw_dir = strsep(&bp, ":\n"))) /* directory */ 448 | return 0; 449 | if (!(_pw_passwd.pw_shell = strsep(&bp, ":\n"))) /* shell */ 450 | return 0; 451 | 452 | if (strchr(bp, ':') != NULL) 453 | return 0; 454 | 455 | return 1; 456 | } 457 | 458 | -------------------------------------------------------------------------------- /misc.c: -------------------------------------------------------------------------------- 1 | /* $NetBSD: misc.c,v 1.3 2008/11/06 02:14:52 jschauma Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 1991, 1993 5 | * The Regents of the University of California. All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. Neither the name of the University nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 | * SUCH DAMAGE. 30 | * 31 | * @(#)misc.c 8.1 (Berkeley) 6/6/93 32 | */ 33 | 34 | #if HAVE_CONFIG_H 35 | #include "config.h" 36 | #endif 37 | #if HAVE_NBTOOL_CONFIG_H 38 | #include "nbtool_config.h" 39 | #endif 40 | 41 | #include 42 | #if HAVE_SYS_CDEFS_H 43 | #include 44 | #endif 45 | #if defined(__RCSID) && !defined(lint) 46 | __RCSID("$NetBSD: misc.c,v 1.3 2008/11/06 02:14:52 jschauma Exp $"); 47 | #endif /* not lint */ 48 | 49 | #if HAVE_SYS_TYPES_H 50 | #include 51 | #endif 52 | #if HAVE_SYS_STAT_H 53 | #include 54 | #endif 55 | 56 | #if HAVE_STDARG_H 57 | #include 58 | #endif 59 | #if HAVE_STDIO_H 60 | #include 61 | #endif 62 | #if HAVE_STDLIB_H 63 | #include 64 | #endif 65 | #if HAVE_STRING_H 66 | #include 67 | #endif 68 | 69 | #include "extern.h" 70 | 71 | typedef struct _key { 72 | const char *name; /* key name */ 73 | u_int val; /* value */ 74 | 75 | #define NEEDVALUE 0x01 76 | u_int flags; 77 | } KEY; 78 | 79 | /* NB: the following tables must be sorted lexically. */ 80 | static KEY keylist[] = { 81 | {"cksum", F_CKSUM, NEEDVALUE}, 82 | {"device", F_DEV, NEEDVALUE}, 83 | {"flags", F_FLAGS, NEEDVALUE}, 84 | {"gid", F_GID, NEEDVALUE}, 85 | {"gname", F_GNAME, NEEDVALUE}, 86 | {"ignore", F_IGN, 0}, 87 | {"link", F_SLINK, NEEDVALUE}, 88 | {"md5", F_MD5, NEEDVALUE}, 89 | {"md5digest", F_MD5, NEEDVALUE}, 90 | {"mode", F_MODE, NEEDVALUE}, 91 | {"nlink", F_NLINK, NEEDVALUE}, 92 | {"optional", F_OPT, 0}, 93 | {"rmd160", F_RMD160, NEEDVALUE}, 94 | {"rmd160digest",F_RMD160, NEEDVALUE}, 95 | {"sha1", F_SHA1, NEEDVALUE}, 96 | {"sha1digest", F_SHA1, NEEDVALUE}, 97 | {"sha256", F_SHA256, NEEDVALUE}, 98 | {"sha256digest",F_SHA256, NEEDVALUE}, 99 | {"sha384", F_SHA384, NEEDVALUE}, 100 | {"sha384digest",F_SHA384, NEEDVALUE}, 101 | {"sha512", F_SHA512, NEEDVALUE}, 102 | {"sha512digest",F_SHA512, NEEDVALUE}, 103 | {"size", F_SIZE, NEEDVALUE}, 104 | {"tags", F_TAGS, NEEDVALUE}, 105 | {"time", F_TIME, NEEDVALUE}, 106 | {"type", F_TYPE, NEEDVALUE}, 107 | {"uid", F_UID, NEEDVALUE}, 108 | {"uname", F_UNAME, NEEDVALUE} 109 | }; 110 | 111 | static KEY typelist[] = { 112 | {"block", F_BLOCK, 0}, 113 | {"char", F_CHAR, 0}, 114 | {"dir", F_DIR, 0}, 115 | #ifdef S_IFDOOR 116 | {"door", F_DOOR, 0}, 117 | #endif 118 | {"fifo", F_FIFO, 0}, 119 | {"file", F_FILE, 0}, 120 | {"link", F_LINK, 0}, 121 | {"socket", F_SOCK, 0}, 122 | }; 123 | 124 | slist_t excludetags, includetags; 125 | int keys = KEYDEFAULT; 126 | 127 | 128 | int keycompare(const void *, const void *); 129 | 130 | u_int 131 | parsekey(const char *name, int *needvaluep) 132 | { 133 | static int allbits; 134 | KEY *k, tmp; 135 | 136 | if (allbits == 0) { 137 | int i; 138 | 139 | for (i = 0; i < sizeof(keylist) / sizeof(KEY); i++) 140 | allbits |= keylist[i].val; 141 | } 142 | tmp.name = name; 143 | if (strcmp(name, "all") == 0) 144 | return (allbits); 145 | k = (KEY *)bsearch(&tmp, keylist, sizeof(keylist) / sizeof(KEY), 146 | sizeof(KEY), keycompare); 147 | if (k == NULL) 148 | mtree_err("unknown keyword `%s'", name); 149 | 150 | if (needvaluep) 151 | *needvaluep = k->flags & NEEDVALUE ? 1 : 0; 152 | 153 | return (k->val); 154 | } 155 | 156 | u_int 157 | parsetype(const char *name) 158 | { 159 | KEY *k, tmp; 160 | 161 | tmp.name = name; 162 | k = (KEY *)bsearch(&tmp, typelist, sizeof(typelist) / sizeof(KEY), 163 | sizeof(KEY), keycompare); 164 | if (k == NULL) 165 | mtree_err("unknown file type `%s'", name); 166 | 167 | return (k->val); 168 | } 169 | 170 | int 171 | keycompare(const void *a, const void *b) 172 | { 173 | 174 | return (strcmp(((const KEY *)a)->name, ((const KEY *)b)->name)); 175 | } 176 | 177 | void 178 | mtree_err(const char *fmt, ...) 179 | { 180 | va_list ap; 181 | 182 | va_start(ap, fmt); 183 | vwarnx(fmt, ap); 184 | va_end(ap); 185 | if (mtree_lineno) 186 | warnx("failed at line %lu of the specification", 187 | (u_long) mtree_lineno); 188 | exit(1); 189 | /* NOTREACHED */ 190 | } 191 | 192 | void 193 | addtag(slist_t *list, char *elem) 194 | { 195 | 196 | #define TAG_CHUNK 20 197 | 198 | if ((list->count % TAG_CHUNK) == 0) { 199 | char **new; 200 | 201 | new = (char **)realloc(list->list, (list->count + TAG_CHUNK) 202 | * sizeof(char *)); 203 | if (new == NULL) 204 | mtree_err("memory allocation error"); 205 | list->list = new; 206 | } 207 | list->list[list->count] = elem; 208 | list->count++; 209 | } 210 | 211 | void 212 | parsetags(slist_t *list, char *args) 213 | { 214 | char *p, *e; 215 | int len; 216 | 217 | if (args == NULL) { 218 | addtag(list, NULL); 219 | return; 220 | } 221 | while ((p = strsep(&args, ",")) != NULL) { 222 | if (*p == '\0') 223 | continue; 224 | len = strlen(p) + 3; /* "," + p + ",\0" */ 225 | if ((e = malloc(len)) == NULL) 226 | mtree_err("memory allocation error"); 227 | snprintf(e, len, ",%s,", p); 228 | addtag(list, e); 229 | } 230 | } 231 | 232 | /* 233 | * matchtags 234 | * returns 0 if there's a match from the exclude list in the node's tags, 235 | * or there's an include list and no match. 236 | * return 1 otherwise. 237 | */ 238 | int 239 | matchtags(NODE *node) 240 | { 241 | int i; 242 | 243 | if (node->tags) { 244 | for (i = 0; i < excludetags.count; i++) 245 | if (strstr(node->tags, excludetags.list[i])) 246 | break; 247 | if (i < excludetags.count) 248 | return (0); 249 | 250 | for (i = 0; i < includetags.count; i++) 251 | if (strstr(node->tags, includetags.list[i])) 252 | break; 253 | if (i > 0 && i == includetags.count) 254 | return (0); 255 | } else if (includetags.count > 0) { 256 | return (0); 257 | } 258 | return (1); 259 | } 260 | 261 | u_int 262 | nodetoino(u_int type) 263 | { 264 | 265 | switch (type) { 266 | case F_BLOCK: 267 | return S_IFBLK; 268 | case F_CHAR: 269 | return S_IFCHR; 270 | case F_DIR: 271 | return S_IFDIR; 272 | case F_FIFO: 273 | return S_IFIFO; 274 | case F_FILE: 275 | return S_IFREG; 276 | case F_LINK: 277 | return S_IFLNK; 278 | #ifdef S_IFSOCK 279 | case F_SOCK: 280 | return S_IFSOCK; 281 | #endif 282 | default: 283 | printf("unknown type %d", type); 284 | abort(); 285 | } 286 | /* NOTREACHED */ 287 | } 288 | 289 | const char * 290 | nodetype(u_int type) 291 | { 292 | 293 | return (inotype(nodetoino(type))); 294 | } 295 | 296 | 297 | const char * 298 | inotype(u_int type) 299 | { 300 | 301 | switch (type & S_IFMT) { 302 | case S_IFBLK: 303 | return ("block"); 304 | case S_IFCHR: 305 | return ("char"); 306 | case S_IFDIR: 307 | return ("dir"); 308 | case S_IFIFO: 309 | return ("fifo"); 310 | case S_IFREG: 311 | return ("file"); 312 | case S_IFLNK: 313 | return ("link"); 314 | #ifdef S_IFSOCK 315 | case S_IFSOCK: 316 | return ("socket"); 317 | #endif 318 | #ifdef S_IFDOOR 319 | case S_IFDOOR: 320 | return ("door"); 321 | #endif 322 | default: 323 | return ("unknown"); 324 | } 325 | /* NOTREACHED */ 326 | } 327 | -------------------------------------------------------------------------------- /mtree.5: -------------------------------------------------------------------------------- 1 | .\" Copyright (c) 1989, 1990, 1993 2 | .\" The Regents of the University of California. All rights reserved. 3 | .\" 4 | .\" Redistribution and use in source and binary forms, with or without 5 | .\" modification, are permitted provided that the following conditions 6 | .\" are met: 7 | .\" 1. Redistributions of source code must retain the above copyright 8 | .\" notice, this list of conditions and the following disclaimer. 9 | .\" 2. Redistributions in binary form must reproduce the above copyright 10 | .\" notice, this list of conditions and the following disclaimer in the 11 | .\" documentation and/or other materials provided with the distribution. 12 | .\" 4. Neither the name of the University nor the names of its contributors 13 | .\" may be used to endorse or promote products derived from this software 14 | .\" without specific prior written permission. 15 | .\" 16 | .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 17 | .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 | .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | .\" SUCH DAMAGE. 27 | .\" 28 | .\" From: @(#)mtree.8 8.2 (Berkeley) 12/11/93 29 | .\" $FreeBSD$ 30 | .\" 31 | .Dd September 4, 2013 32 | .Dt MTREE 5 33 | .Os 34 | .Sh NAME 35 | .Nm mtree 36 | .Nd format of mtree dir hierarchy files 37 | .Sh DESCRIPTION 38 | The 39 | .Nm 40 | format is a textual format that describes a collection of filesystem objects. 41 | Such files are typically used to create or verify directory hierarchies. 42 | .Ss General Format 43 | An 44 | .Nm 45 | file consists of a series of lines, each providing information 46 | about a single filesystem object. 47 | Leading whitespace is always ignored. 48 | .Pp 49 | When encoding file or pathnames, any backslash character or 50 | character outside of the 95 printable ASCII characters must be 51 | encoded as a backslash followed by three 52 | octal digits. 53 | When reading mtree files, any appearance of a backslash 54 | followed by three octal digits should be converted into the 55 | corresponding character. 56 | .Pp 57 | Each line is interpreted independently as one of the following types: 58 | .Bl -tag -width Cm 59 | .It Blank 60 | Blank lines are ignored. 61 | .It Comment 62 | Lines beginning with 63 | .Cm # 64 | are ignored. 65 | .It Special 66 | Lines beginning with 67 | .Cm / 68 | are special commands that influence 69 | the interpretation of later lines. 70 | .It Relative 71 | If the first whitespace-delimited word has no 72 | .Cm / 73 | characters, 74 | it is the name of a file in the current directory. 75 | Any relative entry that describes a directory changes the 76 | current directory. 77 | .It dot-dot 78 | As a special case, a relative entry with the filename 79 | .Pa .. 80 | changes the current directory to the parent directory. 81 | Options on dot-dot entries are always ignored. 82 | .It Full 83 | If the first whitespace-delimited word has a 84 | .Cm / 85 | character after 86 | the first character, it is the pathname of a file relative to the 87 | starting directory. 88 | There can be multiple full entries describing the same file. 89 | .El 90 | .Pp 91 | Some tools that process 92 | .Nm 93 | files may require that multiple lines describing the same file 94 | occur consecutively. 95 | It is not permitted for the same file to be mentioned using 96 | both a relative and a full file specification. 97 | .Ss Special commands 98 | Two special commands are currently defined: 99 | .Bl -tag -width Cm 100 | .It Cm /set 101 | This command defines default values for one or more keywords. 102 | It is followed on the same line by one or more whitespace-separated 103 | keyword definitions. 104 | These definitions apply to all following files that do not specify 105 | a value for that keyword. 106 | .It Cm /unset 107 | This command removes any default value set by a previous 108 | .Cm /set 109 | command. 110 | It is followed on the same line by one or more keywords 111 | separated by whitespace. 112 | .El 113 | .Ss Keywords 114 | After the filename, a full or relative entry consists of zero 115 | or more whitespace-separated keyword definitions. 116 | Each such definition consists of a key from the following 117 | list immediately followed by an '=' sign 118 | and a value. 119 | Software programs reading mtree files should warn about 120 | unrecognized keywords. 121 | .Pp 122 | Currently supported keywords are as follows: 123 | .Bl -tag -width Cm 124 | .It Cm cksum 125 | The checksum of the file using the default algorithm specified by 126 | the 127 | .Xr cksum 1 128 | utility. 129 | .It Cm device 130 | The device number for 131 | .Sy block 132 | or 133 | .Sy char 134 | file types. 135 | The value must be one of the following forms: 136 | .Pp 137 | .Bl -tag -width 4n 138 | .It Ar format , Ns Ar major , Ns Ar minor Ns Bo , Ns Ar subunit Bc 139 | A device with 140 | .Ar major , minor 141 | and optional 142 | .Ar subunit 143 | fields. 144 | Their meaning is specified by the operating's system 145 | .Ar format . 146 | See below for valid formats. 147 | .It Ar number 148 | Opaque number (as stored on the file system). 149 | .El 150 | .Pp 151 | The following values for 152 | .Ar format 153 | are recognized: 154 | .Sy native , 155 | .Sy 386bsd , 156 | .Sy 4bsd , 157 | .Sy bsdos , 158 | .Sy freebsd , 159 | .Sy hpux , 160 | .Sy isc , 161 | .Sy linux , 162 | .Sy netbsd , 163 | .Sy osf1 , 164 | .Sy sco , 165 | .Sy solaris , 166 | .Sy sunos , 167 | .Sy svr3 , 168 | .Sy svr4 , 169 | and 170 | .Sy ultrix . 171 | .Pp 172 | See 173 | .Xr mknod 8 174 | for more details. 175 | .It Cm contents 176 | The full pathname of a file that holds the contents of this file. 177 | .It Cm flags 178 | The file flags as a symbolic name. 179 | See 180 | .Xr chflags 1 181 | for information on these names. 182 | If no flags are to be set the string 183 | .Dq none 184 | may be used to override the current default. 185 | .It Cm gid 186 | The file group as a numeric value. 187 | .It Cm gname 188 | The file group as a symbolic name. 189 | .It Cm ignore 190 | Ignore any file hierarchy below this file. 191 | .It Cm inode 192 | The inode number. 193 | .It Cm link 194 | The target of the symbolic link when type=link. 195 | .It Cm md5 196 | The MD5 message digest of the file. 197 | .It Cm md5digest 198 | A synonym for 199 | .Cm md5 . 200 | .It Cm mode 201 | The current file's permissions as a numeric (octal) or symbolic 202 | value. 203 | .It Cm nlink 204 | The number of hard links the file is expected to have. 205 | .It Cm nochange 206 | Make sure this file or directory exists but otherwise ignore all attributes. 207 | .It Cm optional 208 | The file is optional; do not complain about the file if it is not in 209 | the file hierarchy. 210 | .It Cm resdevice 211 | The 212 | .Dq resident 213 | device number of the file, e.g. the ID of the device that 214 | contains the file. 215 | Its format is the same as the one for 216 | .Cm device . 217 | .It Cm ripemd160digest 218 | The 219 | .Tn RIPEMD160 220 | message digest of the file. 221 | .It Cm rmd160 222 | A synonym for 223 | .Cm ripemd160digest . 224 | .It Cm rmd160digest 225 | A synonym for 226 | .Cm ripemd160digest . 227 | .It Cm sha1 228 | The 229 | .Tn FIPS 230 | 160-1 231 | .Pq Dq Tn SHA-1 232 | message digest of the file. 233 | .It Cm sha1digest 234 | A synonym for 235 | .Cm sha1 . 236 | .It Cm sha256 237 | The 238 | .Tn FIPS 239 | 180-2 240 | .Pq Dq Tn SHA-256 241 | message digest of the file. 242 | .It Cm sha256digest 243 | A synonym for 244 | .Cm sha256 . 245 | .It Cm sha384 246 | The 247 | .Tn FIPS 248 | 180-2 249 | .Pq Dq Tn SHA-384 250 | message digest of the file. 251 | .It Cm sha384digest 252 | A synonym for 253 | .Cm sha384 . 254 | .It Cm sha512 255 | The 256 | .Tn FIPS 257 | 180-2 258 | .Pq Dq Tn SHA-512 259 | message digest of the file. 260 | .It Cm sha512digest 261 | A synonym for 262 | .Cm sha512 . 263 | .It Cm size 264 | The size, in bytes, of the file. 265 | .It Cm time 266 | The last modification time of the file. 267 | .It Cm type 268 | The type of the file; may be set to any one of the following: 269 | .Pp 270 | .Bl -tag -width Cm -compact 271 | .It Cm block 272 | block special device 273 | .It Cm char 274 | character special device 275 | .It Cm dir 276 | directory 277 | .It Cm fifo 278 | fifo 279 | .It Cm file 280 | regular file 281 | .It Cm link 282 | symbolic link 283 | .It Cm socket 284 | socket 285 | .El 286 | .It Cm uid 287 | The file owner as a numeric value. 288 | .It Cm uname 289 | The file owner as a symbolic name. 290 | .El 291 | .Pp 292 | .Sh SEE ALSO 293 | .Xr cksum 1 , 294 | .Xr find 1 , 295 | .Xr mtree 8 296 | .Sh BUGS 297 | .Sh HISTORY 298 | The 299 | .Nm 300 | utility appeared in 301 | .Bx 4.3 Reno . 302 | The 303 | .Tn MD5 304 | digest capability was added in 305 | .Fx 2.1 , 306 | in response to the widespread use of programs which can spoof 307 | .Xr cksum 1 . 308 | The 309 | .Tn SHA-1 310 | and 311 | .Tn RIPEMD160 312 | digests were added in 313 | .Fx 4.0 , 314 | as new attacks have demonstrated weaknesses in 315 | .Tn MD5 . 316 | The 317 | .Tn SHA-256 318 | digest was added in 319 | .Fx 6.0 . 320 | Support for file flags was added in 321 | .Fx 4.0 , 322 | and mostly comes from 323 | .Nx . 324 | The 325 | .Dq full 326 | entry format was added by 327 | .Nx . 328 | -------------------------------------------------------------------------------- /mtree.8: -------------------------------------------------------------------------------- 1 | .\" $NetBSD: mtree.8,v 1.4 2008/11/06 02:14:52 jschauma Exp $ 2 | .\" 3 | .\" Copyright (c) 1989, 1990, 1993 4 | .\" The Regents of the University of California. All rights reserved. 5 | .\" 6 | .\" Redistribution and use in source and binary forms, with or without 7 | .\" modification, are permitted provided that the following conditions 8 | .\" are met: 9 | .\" 1. Redistributions of source code must retain the above copyright 10 | .\" notice, this list of conditions and the following disclaimer. 11 | .\" 2. Redistributions in binary form must reproduce the above copyright 12 | .\" notice, this list of conditions and the following disclaimer in the 13 | .\" documentation and/or other materials provided with the distribution. 14 | .\" 3. Neither the name of the University nor the names of its contributors 15 | .\" may be used to endorse or promote products derived from this software 16 | .\" without specific prior written permission. 17 | .\" 18 | .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 | .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 | .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 | .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 | .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 | .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 | .\" SUCH DAMAGE. 29 | .\" 30 | .\" Copyright (c) 2001-2004 The NetBSD Foundation, Inc. 31 | .\" All rights reserved. 32 | .\" 33 | .\" This code is derived from software contributed to The NetBSD Foundation 34 | .\" by Luke Mewburn of Wasabi Systems. 35 | .\" 36 | .\" Redistribution and use in source and binary forms, with or without 37 | .\" modification, are permitted provided that the following conditions 38 | .\" are met: 39 | .\" 1. Redistributions of source code must retain the above copyright 40 | .\" notice, this list of conditions and the following disclaimer. 41 | .\" 2. Redistributions in binary form must reproduce the above copyright 42 | .\" notice, this list of conditions and the following disclaimer in the 43 | .\" documentation and/or other materials provided with the distribution. 44 | .\" 3. All advertising materials mentioning features or use of this software 45 | .\" must display the following acknowledgement: 46 | .\" This product includes software developed by the NetBSD 47 | .\" Foundation, Inc. and its contributors. 48 | .\" 4. Neither the name of The NetBSD Foundation nor the names of its 49 | .\" contributors may be used to endorse or promote products derived 50 | .\" from this software without specific prior written permission. 51 | .\" 52 | .\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 53 | .\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 54 | .\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 55 | .\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 56 | .\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 57 | .\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 58 | .\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 59 | .\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 60 | .\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 61 | .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 62 | .\" POSSIBILITY OF SUCH DAMAGE. 63 | .\" 64 | .\" @(#)mtree.8 8.2 (Berkeley) 12/11/93 65 | .\" 66 | .Dd September 12, 2006 67 | .Dt MTREE 8 68 | .Os 69 | .Sh NAME 70 | .Nm mtree 71 | .Nd map a directory hierarchy 72 | .Sh SYNOPSIS 73 | .Nm 74 | .Op Fl cCdDelLMPruUWx 75 | .Bk -words 76 | .Op Fl i | Fl m 77 | .Ek 78 | .Bk -words 79 | .Op Fl f Ar spec 80 | .Ek 81 | .Bk -words 82 | .Op Fl p Ar path 83 | .Ek 84 | .Bk -words 85 | .Op Fl k Ar keywords 86 | .Ek 87 | .Bk -words 88 | .Op Fl K Ar keywords 89 | .Ek 90 | .Bk -words 91 | .Op Fl R Ar keywords 92 | .Ek 93 | .Bk -words 94 | .Op Fl E Ar tags 95 | .Ek 96 | .Bk -words 97 | .Op Fl I Ar tags 98 | .Ek 99 | .Bk -words 100 | .Op Fl N Ar dbdir 101 | .Ek 102 | .Bk -words 103 | .Op Fl s Ar seed 104 | .Ek 105 | .Bk -words 106 | .Op Fl X Ar exclude-file 107 | .Ek 108 | .Sh DESCRIPTION 109 | The 110 | .Nm 111 | utility compares the file hierarchy rooted in the current directory 112 | against a specification read from the standard input. 113 | Messages are written to the standard output for any files whose 114 | characteristics do not match the specification, or which are 115 | missing from either the file hierarchy or the specification. 116 | .Pp 117 | The options are as follows: 118 | .Bl -tag -width flag 119 | .It Fl c 120 | Print a specification for the file hierarchy to the standard output. 121 | .It Fl d 122 | Ignore everything except directory type files. 123 | .It Fl C 124 | Print 125 | .Pq Sq dump 126 | the specification as provided by 127 | .Fl f Ar spec 128 | in a format that's easier to parse with various tools. 129 | The full path name is always printed as the first field, and 130 | .Fl k , 131 | .Fl K , 132 | and 133 | .Fl R 134 | can be used to control which other keywords are printed, 135 | and 136 | .Fl E 137 | and 138 | .Fl I 139 | can be used to control which files are printed. 140 | .It Fl D 141 | As per 142 | .Fl C , 143 | except that the path name is always printed as the last field instead of 144 | the first. 145 | .It Fl E Ar tags 146 | Add the comma separated tags to the 147 | .Dq exclusion 148 | list. 149 | Non-directories with tags which are in the exclusion list are not printed with 150 | .Fl D . 151 | .It Fl e 152 | Don't complain about files that are in the file hierarchy, but not in the 153 | specification. 154 | .It Fl f Ar spec 155 | Read the specification from 156 | .Ar file , 157 | instead of from the standard input. 158 | .It Fl I Ar tags 159 | Add the comma separated tags to the 160 | .Dq inclusion 161 | list. 162 | Non-directories with tags which are in the inclusion list are printed with 163 | .Fl D . 164 | If no inclusion list is provided, the default is to display all files. 165 | .It Fl g 166 | Earlier versions contained undocumented behavior whereby input filenames containing 167 | .Xr glob 7 168 | characters would be matched using 169 | .Xr fnmatch 3 170 | pattern matching. 171 | This behavior is now disabled by default, but can be re-enabled using this flag. 172 | .It Fl i 173 | If specified, set the schg and/or sappnd flags. 174 | .It Fl K Ar keywords 175 | Add the specified (whitespace or comma separated) keywords to the current 176 | set of keywords. 177 | If 178 | .Ql all 179 | is specified, add all of the other keywords. 180 | .It Fl k Ar keywords 181 | Use the 182 | .Sy type 183 | keyword plus the specified (whitespace or comma separated) 184 | keywords instead of the current set of keywords. 185 | If 186 | .Ql all 187 | is specified, use all of the other keywords. 188 | If the 189 | .Sy type 190 | keyword is not desired, suppress it with 191 | .Fl R Ar type . 192 | .It Fl l 193 | Do 194 | .Dq loose 195 | permissions checks, in which more stringent permissions 196 | will match less stringent ones. For example, a file marked mode 0444 197 | will pass a check for mode 0644. 198 | .Dq Loose 199 | checks apply only to read, write and execute permissions -- in 200 | particular, if other bits like the sticky bit or suid/sgid bits are 201 | set either in the specification or the file, exact checking will be 202 | performed. This flag may not be set at the same time as the 203 | .Fl u 204 | or 205 | .Fl U 206 | flags. 207 | .It Fl L 208 | Follow all symbolic links in the file hierarchy. 209 | .It Fl m 210 | If the schg and/or sappnd flags are specified, reset these flags. Note that 211 | this is only possible with securelevel less than 1 (i.e. in single user mode 212 | or while the system is running in insecure mode). See 213 | .Xr init 8 214 | for information on security levels. 215 | .It Fl M 216 | Permit merging of specification entries with different types, 217 | with the last entry take precedence. 218 | .It Fl N Ar dbdir 219 | Use the user database text file 220 | .Pa master.passwd 221 | and group database text file 222 | .Pa group 223 | from 224 | .Ar dbdir , 225 | rather than using the results from the system's 226 | .Xr getpwnam 3 227 | and 228 | .Xr getgrnam 3 229 | (and related) library calls. 230 | .It Fl p Ar path 231 | Use the file hierarchy rooted in 232 | .Ar path , 233 | instead of the current directory. 234 | .It Fl P 235 | Don't follow symbolic links in the file hierarchy, instead consider 236 | the symbolic link itself in any comparisons. 237 | This is the default. 238 | .It Fl r 239 | Remove any files in the file hierarchy that are not described in the 240 | specification. 241 | .It Fl R Ar keywords 242 | Remove the specified (whitespace or comma separated) keywords from the current 243 | set of keywords. 244 | If 245 | .Ql all 246 | is specified, remove all of the other keywords. 247 | .It Fl s Ar seed 248 | Display a single checksum to the standard error output that represents all 249 | of the files for which the keyword 250 | .Sy cksum 251 | was specified. 252 | The checksum is seeded with the specified value. 253 | .It Fl u 254 | Modify the owner, group, permissions, and flags of existing files, 255 | the device type of devices, and symbolic link targets, 256 | to match the specification. 257 | Create any missing directories, devices or symbolic links. 258 | User, group, and permissions must all be specified for missing directories 259 | to be created. 260 | Note that unless the 261 | .Fl i 262 | option is given, the schg and sappnd flags will not be set, even if 263 | specified. If 264 | .Fl m 265 | is given, these flags will be reset. 266 | Exit with a status of 0 on success, 267 | 2 if the file hierarchy did not match the specification, and 268 | 1 if any other error occurred. 269 | .It Fl U 270 | Same as 271 | .Fl u 272 | except that a mismatch is not considered to be an error if it was corrected. 273 | .It Fl W 274 | Don't attempt to set various file attributes such as the 275 | ownership, mode, flags, or time 276 | when creating new directories or changing existing entries. 277 | This option will be most useful when used in conjunction with 278 | .Fl u 279 | or 280 | .Fl U . 281 | .It Fl x 282 | Don't descend below mount points in the file hierarchy. 283 | .It Fl X Ar exclude-file 284 | The specified file contains 285 | .Xr fnmatch 3 286 | patterns matching files to be excluded from 287 | the specification, one to a line. 288 | If the pattern contains a 289 | .Ql \&/ 290 | character, it will be matched against entire pathnames (relative to 291 | the starting directory); otherwise, 292 | it will be matched against basenames only. 293 | Comments are permitted in 294 | the 295 | .Ar exclude-list 296 | file. 297 | .El 298 | .Pp 299 | Specifications are mostly composed of 300 | .Dq keywords , 301 | i.e. strings that 302 | that specify values relating to files. 303 | No keywords have default values, and if a keyword has no value set, no 304 | checks based on it are performed. 305 | .Pp 306 | Currently supported keywords are as follows: 307 | .Bl -tag -width Sy 308 | .It Sy cksum 309 | The checksum of the file using the default algorithm specified by 310 | the 311 | .Xr cksum 1 312 | utility. 313 | .It Sy device 314 | The device number to use for 315 | .Sy block 316 | or 317 | .Sy char 318 | file types. 319 | The argument must be one of the following forms: 320 | .Pp 321 | .Bl -tag -width 4n 322 | .It Xo 323 | .Sm off 324 | .Ar format , 325 | .Ar major , 326 | .Ar minor 327 | .Sm on 328 | .Xc 329 | A device with 330 | .Ar major 331 | and 332 | .Ar minor 333 | fields, for an operating system specified with 334 | .Ar format . 335 | See below for valid formats. 336 | .It Xo 337 | .Sm off 338 | .Ar format , 339 | .Ar major , 340 | .Ar unit , 341 | .Ar subunit 342 | .Sm on 343 | .Xc 344 | A device with 345 | .Ar major , 346 | .Ar unit , 347 | and 348 | .Ar subunit 349 | fields, for an operating system specified with 350 | .Ar format . 351 | (Currently this is only supported by the 352 | .Sy bsdos 353 | format.) 354 | .It Ar number 355 | Opaque number (as stored on the file system). 356 | .El 357 | .Pp 358 | The following values for 359 | .Ar format 360 | are recognized: 361 | .Sy native , 362 | .Sy 386bsd , 363 | .Sy 4bsd , 364 | .Sy bsdos , 365 | .Sy freebsd , 366 | .Sy hpux , 367 | .Sy isc , 368 | .Sy linux , 369 | .Sy netbsd , 370 | .Sy osf1 , 371 | .Sy sco , 372 | .Sy solaris , 373 | .Sy sunos , 374 | .Sy svr3 , 375 | .Sy svr4 , 376 | and 377 | .Sy ultrix . 378 | .Pp 379 | See 380 | .Xr mknod 8 381 | for more details. 382 | .It Sy flags 383 | The file flags as a symbolic name. See 384 | .Xr chflags 1 385 | for information on these names. If no flags are to be set the string 386 | .Ql none 387 | may be used to override the current default. 388 | Note that the schg and sappnd flags are treated specially (see the 389 | .Fl i 390 | and 391 | .Fl m 392 | options). 393 | .It Sy ignore 394 | Ignore any file hierarchy below this file. 395 | .It Sy gid 396 | The file group as a numeric value. 397 | .It Sy gname 398 | The file group as a symbolic name. 399 | .It Sy link 400 | The file the symbolic link is expected to reference. 401 | .It Sy md5 402 | The 403 | .Tn MD5 404 | cryptographic message digest of the file. 405 | .It Sy md5digest 406 | Synonym for 407 | .Sy md5 . 408 | .It Sy mode 409 | The current file's permissions as a numeric (octal) or symbolic 410 | value. 411 | .It Sy nlink 412 | The number of hard links the file is expected to have. 413 | .It Sy optional 414 | The file is optional; don't complain about the file if it's 415 | not in the file hierarchy. 416 | .It Sy rmd160 417 | The 418 | .Tn RMD-160 419 | cryptographic message digest of the file. 420 | .It Sy rmd160digest 421 | Synonym for 422 | .Sy rmd160 . 423 | .It Sy sha1 424 | The 425 | .Tn SHA-1 426 | cryptographic message digest of the file. 427 | .It Sy sha1digest 428 | Synonym for 429 | .Sy sha1 . 430 | .It Sy sha256 431 | The 256-bits 432 | .Tn SHA-2 433 | cryptographic message digest of the file. 434 | .It Sy sha256digest 435 | Synonym for 436 | .Sy sha256 . 437 | .It Sy sha384 438 | The 384-bits 439 | .Tn SHA-2 440 | cryptographic message digest of the file. 441 | .It Sy sha384digest 442 | Synonym for 443 | .Sy sha384 . 444 | .It Sy sha512 445 | The 512-bits 446 | .Tn SHA-2 447 | cryptographic message digest of the file. 448 | .It Sy sha512digest 449 | Synonym for 450 | .Sy sha512 . 451 | .It Sy size 452 | The size, in bytes, of the file. 453 | .It Sy tags 454 | Comma delimited tags to be matched with 455 | .Fl E 456 | and 457 | .Fl I . 458 | These may be specified without leading or trailing commas, but will be 459 | stored internally with them. 460 | .It Sy time 461 | The last modification time of the file. 462 | .It Sy type 463 | The type of the file; may be set to any one of the following: 464 | .Pp 465 | .Bl -tag -width Sy -compact 466 | .It Sy block 467 | block special device 468 | .It Sy char 469 | character special device 470 | .It Sy dir 471 | directory 472 | .It Sy fifo 473 | fifo 474 | .It Sy file 475 | regular file 476 | .It Sy link 477 | symbolic link 478 | .It Sy socket 479 | socket 480 | .El 481 | .It Sy uid 482 | The file owner as a numeric value. 483 | .It Sy uname 484 | The file owner as a symbolic name. 485 | .El 486 | .Pp 487 | The default set of keywords are 488 | .Sy flags , 489 | .Sy gid , 490 | .Sy link , 491 | .Sy mode , 492 | .Sy nlink , 493 | .Sy size , 494 | .Sy time , 495 | .Sy type , 496 | and 497 | .Sy uid . 498 | .Pp 499 | There are four types of lines in a specification: 500 | .Pp 501 | .Bl -enum 502 | .It 503 | Set global values for a keyword. 504 | This consists of the string 505 | .Ql /set 506 | followed by whitespace, followed by sets of keyword/value 507 | pairs, separated by whitespace. 508 | Keyword/value pairs consist of a keyword, followed by an equals sign 509 | .Pq Ql = , 510 | followed by a value, without whitespace characters. 511 | Once a keyword has been set, its value remains unchanged until either 512 | reset or unset. 513 | .It 514 | Unset global values for a keyword. 515 | This consists of the string 516 | .Ql /unset , 517 | followed by whitespace, followed by one or more keywords, 518 | separated by whitespace. 519 | If 520 | .Ql all 521 | is specified, unset all of the keywords. 522 | .It 523 | A file specification, consisting of a path name, followed by whitespace, 524 | followed by zero or more whitespace separated keyword/value pairs. 525 | .Pp 526 | The path name may be preceded by whitespace characters. 527 | The path name may contain any of the standard path name matching 528 | characters 529 | .Po 530 | .Ql \&[ , 531 | .Ql \&] , 532 | .Ql \&? 533 | or 534 | .Ql * 535 | .Pc , 536 | in which case files 537 | in the hierarchy will be associated with the first pattern that 538 | they match. 539 | .Nm 540 | uses 541 | .Xr strsvis 3 542 | (in VIS_CSTYLE format) to encode path names containing 543 | non-printable characters. Whitespace characters are encoded as 544 | .Ql \es 545 | (space), 546 | .Ql \et 547 | (tab), and 548 | .Ql \en 549 | (new line). 550 | .Ql # 551 | characters in path names are escaped by a preceding backslash 552 | .Ql \e 553 | to distinguish them from comments. 554 | .Pp 555 | Each of the keyword/value pairs consist of a keyword, followed by an 556 | equals sign 557 | .Pq Ql = , 558 | followed by the keyword's value, without 559 | whitespace characters. 560 | These values override, without changing, the global value of the 561 | corresponding keyword. 562 | .Pp 563 | The first path name entry listed must be a directory named 564 | .Ql \&. , 565 | as this ensures that intermixing full and relative path names will 566 | work consistently and correctly. 567 | Multiple entries for a directory named 568 | .Ql \&. 569 | are permitted; the settings for the last such entry override those 570 | of the existing entry. 571 | .Pp 572 | A path name that contains a slash 573 | .Pq Ql / 574 | that is not the first character will be treated as a full path 575 | (relative to the root of the tree). 576 | All parent directories referenced in the path name must exist. 577 | The current directory path used by relative path names will be updated 578 | appropriately. 579 | Multiple entries for the same full path are permitted if the types 580 | are the same (unless 581 | .Fl M 582 | is given, and then the types may differ); 583 | in this case the settings for the last entry take precedence. 584 | .Pp 585 | A path name that does not contain a slash will be treated as a relative path. 586 | Specifying a directory will cause subsequent files to be searched 587 | for in that directory hierarchy. 588 | .It 589 | A line containing only the string 590 | .Ql \&.. 591 | which causes the current directory path (used by relative paths) 592 | to ascend one level. 593 | .El 594 | .Pp 595 | Empty lines and lines whose first non-whitespace character is a hash 596 | mark 597 | .Pq Ql # 598 | are ignored. 599 | .Pp 600 | The 601 | .Nm 602 | utility exits with a status of 0 on success, 1 if any error occurred, 603 | and 2 if the file hierarchy did not match the specification. 604 | .Sh FILES 605 | .Bl -tag -width /etc/mtree -compact 606 | .It Pa /etc/mtree 607 | system specification directory 608 | .El 609 | .Sh EXAMPLES 610 | To detect system binaries that have been 611 | .Dq trojan horsed , 612 | it is recommended that 613 | .Nm 614 | be run on the file systems, and a copy of the results stored on a different 615 | machine, or, at least, in encrypted form. 616 | The seed for the 617 | .Fl s 618 | option should not be an obvious value and the final checksum should not be 619 | stored on-line under any circumstances! 620 | Then, periodically, 621 | .Nm 622 | should be run against the on-line specifications and the final checksum 623 | compared with the previous value. 624 | While it is possible for the bad guys to change the on-line specifications 625 | to conform to their modified binaries, it shouldn't be possible for them 626 | to make it produce the same final checksum value. 627 | If the final checksum value changes, the off-line copies of the specification 628 | can be used to detect which of the binaries have actually been modified. 629 | .Pp 630 | The 631 | .Fl d 632 | and 633 | .Fl u 634 | options can be used in combination to create directory hierarchies 635 | for distributions and other such things. 636 | .Sh SEE ALSO 637 | .Xr chflags 1 , 638 | .Xr chgrp 1 , 639 | .Xr chmod 1 , 640 | .Xr cksum 1 , 641 | .Xr stat 2 , 642 | .Xr fnmatch 3 , 643 | .Xr fts 3 , 644 | .Xr strsvis 3 , 645 | .Xr chown 8 , 646 | .Xr mknod 8 647 | .Sh HISTORY 648 | The 649 | .Nm 650 | utility appeared in 651 | .Bx 4.3 Reno . 652 | The 653 | .Sy optional 654 | keyword appeared in 655 | .Nx 1.2 . 656 | The 657 | .Fl U 658 | flag appeared in 659 | .Nx 1.3 . 660 | The 661 | .Sy flags 662 | and 663 | .Sy md5 664 | keywords, and 665 | .Fl i 666 | and 667 | .Fl m 668 | flags 669 | appeared in 670 | .Nx 1.4 . 671 | The 672 | .Sy device , 673 | .Sy rmd160 , 674 | .Sy sha1 , 675 | .Sy tags , 676 | and 677 | .Sy all 678 | keywords, 679 | .Fl D , 680 | .Fl E , 681 | .Fl I , 682 | .Fl l , 683 | .Fl L , 684 | .Fl N , 685 | .Fl P , 686 | .Fl R , 687 | .Fl W , 688 | and 689 | .Fl X 690 | flags, and support for full paths appeared in 691 | .Nx 1.6 . 692 | The 693 | .Sy sha256 , 694 | .Sy sha384 , 695 | and 696 | .Sy sha512 697 | keywords appeared in 698 | .Nx 3.0 . 699 | -------------------------------------------------------------------------------- /mtree.c: -------------------------------------------------------------------------------- 1 | /* $NetBSD: mtree.c,v 1.3 2004/08/21 04:10:45 jlam Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 1989, 1990, 1993 5 | * The Regents of the University of California. All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. Neither the name of the University nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 | * SUCH DAMAGE. 30 | */ 31 | 32 | #if HAVE_CONFIG_H 33 | #include "config.h" 34 | #endif 35 | #if HAVE_NBTOOL_CONFIG_H 36 | #include "nbtool_config.h" 37 | #endif 38 | 39 | #include 40 | #if HAVE_SYS_CDEFS_H 41 | #include 42 | #endif 43 | #if defined(__COPYRIGHT) && !defined(lint) 44 | __COPYRIGHT("@(#) Copyright (c) 1989, 1990, 1993\n\ 45 | The Regents of the University of California. All rights reserved.\n"); 46 | #endif /* not lint */ 47 | 48 | #if defined(__RCSID) && !defined(lint) 49 | #if 0 50 | static char sccsid[] = "@(#)mtree.c 8.1 (Berkeley) 6/6/93"; 51 | #else 52 | __RCSID("$NetBSD: mtree.c,v 1.3 2004/08/21 04:10:45 jlam Exp $"); 53 | #endif 54 | #endif /* not lint */ 55 | 56 | #if HAVE_SYS_PARAM_H 57 | #include 58 | #endif 59 | #if HAVE_SYS_STAT_H 60 | #include 61 | #endif 62 | 63 | #if HAVE_ERRNO_H 64 | #include 65 | #endif 66 | #if HAVE_STDIO_H 67 | #include 68 | #endif 69 | #if HAVE_STDLIB_H 70 | #include 71 | #endif 72 | #if HAVE_STRING_H 73 | #include 74 | #endif 75 | #if HAVE_UNISTD_H 76 | #include 77 | #endif 78 | 79 | #include "extern.h" 80 | 81 | int ftsoptions = FTS_PHYSICAL; 82 | int cflag, Cflag, dflag, Dflag, eflag, gflag, iflag, lflag, mflag, 83 | rflag, sflag, tflag, uflag, Uflag; 84 | char fullpath[MAXPATHLEN]; 85 | 86 | int main(int, char **); 87 | static void usage(void); 88 | 89 | int 90 | main(int argc, char **argv) 91 | { 92 | int ch, status; 93 | char *dir, *p; 94 | 95 | setprogname(argv[0]); 96 | 97 | dir = NULL; 98 | init_excludes(); 99 | 100 | while ((ch = getopt(argc, argv, "cCdDeE:f:I:igk:K:lLmMN:p:PrR:s:tuUWxX:")) 101 | != -1) { 102 | switch((char)ch) { 103 | case 'c': 104 | cflag = 1; 105 | break; 106 | case 'C': 107 | Cflag = 1; 108 | break; 109 | case 'd': 110 | dflag = 1; 111 | break; 112 | case 'D': 113 | Dflag = 1; 114 | break; 115 | case 'E': 116 | parsetags(&excludetags, optarg); 117 | break; 118 | case 'e': 119 | eflag = 1; 120 | break; 121 | case 'f': 122 | if (!(freopen(optarg, "r", stdin))) 123 | mtree_err("%s: %s", optarg, strerror(errno)); 124 | break; 125 | case 'g': 126 | gflag = 1; 127 | break; 128 | case 'i': 129 | iflag = 1; 130 | break; 131 | case 'I': 132 | parsetags(&includetags, optarg); 133 | break; 134 | case 'k': 135 | keys = F_TYPE; 136 | while ((p = strsep(&optarg, " \t,")) != NULL) 137 | if (*p != '\0') 138 | keys |= parsekey(p, NULL); 139 | break; 140 | case 'K': 141 | while ((p = strsep(&optarg, " \t,")) != NULL) 142 | if (*p != '\0') 143 | keys |= parsekey(p, NULL); 144 | break; 145 | case 'l': 146 | lflag = 1; 147 | break; 148 | case 'L': 149 | ftsoptions &= ~FTS_PHYSICAL; 150 | ftsoptions |= FTS_LOGICAL; 151 | break; 152 | case 'm': 153 | mflag = 1; 154 | break; 155 | case 'M': 156 | mtree_Mflag = 1; 157 | break; 158 | case 'N': 159 | if (! setup_getid(optarg)) 160 | mtree_err( 161 | "Unable to use user and group databases in `%s'", 162 | optarg); 163 | break; 164 | case 'p': 165 | dir = optarg; 166 | break; 167 | case 'P': 168 | ftsoptions &= ~FTS_LOGICAL; 169 | ftsoptions |= FTS_PHYSICAL; 170 | break; 171 | case 'r': 172 | rflag = 1; 173 | break; 174 | case 'R': 175 | while ((p = strsep(&optarg, " \t,")) != NULL) 176 | if (*p != '\0') 177 | keys &= ~parsekey(p, NULL); 178 | break; 179 | case 's': 180 | sflag = 1; 181 | crc_total = ~strtol(optarg, &p, 0); 182 | if (*p) 183 | mtree_err("illegal seed value -- %s", optarg); 184 | break; 185 | case 't': 186 | tflag = 1; 187 | break; 188 | case 'u': 189 | uflag = 1; 190 | break; 191 | case 'U': 192 | Uflag = uflag = 1; 193 | break; 194 | case 'W': 195 | mtree_Wflag = 1; 196 | break; 197 | case 'x': 198 | ftsoptions |= FTS_XDEV; 199 | break; 200 | case 'X': 201 | read_excludes_file(optarg); 202 | break; 203 | case '?': 204 | default: 205 | usage(); 206 | } 207 | } 208 | argc -= optind; 209 | argv += optind; 210 | 211 | if (argc) 212 | usage(); 213 | 214 | if (dir && chdir(dir)) 215 | mtree_err("%s: %s", dir, strerror(errno)); 216 | 217 | if ((cflag || sflag) && !getcwd(fullpath, sizeof(fullpath))) 218 | mtree_err("%s", strerror(errno)); 219 | 220 | if ((cflag && Cflag) || (cflag && Dflag) || (Cflag && Dflag)) 221 | mtree_err("-c, -C and -D flags are mutually exclusive"); 222 | 223 | if (iflag && mflag) 224 | mtree_err("-i and -m flags are mutually exclusive"); 225 | 226 | if (lflag && uflag) 227 | mtree_err("-l and -u flags are mutually exclusive"); 228 | 229 | if (cflag) { 230 | cwalk(); 231 | exit(0); 232 | } 233 | if (Cflag || Dflag) { 234 | dump_nodes("", spec(stdin), Dflag); 235 | exit(0); 236 | } 237 | status = verify(); 238 | if (Uflag & (status == MISMATCHEXIT)) 239 | status = 0; 240 | exit(status); 241 | } 242 | 243 | static void 244 | usage(void) 245 | { 246 | 247 | fprintf(stderr, 248 | "usage: %s [-cCdDeglLMPruUWx] [-i|-m] [-f spec] [-k key]\n" 249 | "\t\t[-K addkey] [-R removekey] [-I inctags] [-E exctags]\n" 250 | "\t\t[-N userdbdir] [-X exclude-file] [-p path] [-s seed]\n", 251 | getprogname()); 252 | exit(1); 253 | } 254 | -------------------------------------------------------------------------------- /mtree.h: -------------------------------------------------------------------------------- 1 | /* $NetBSD: mtree.h,v 1.3 2008/11/06 02:14:52 jschauma Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 1990, 1993 5 | * The Regents of the University of California. All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. Neither the name of the University nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 | * SUCH DAMAGE. 30 | * 31 | * @(#)mtree.h 8.1 (Berkeley) 6/6/93 32 | */ 33 | 34 | #ifndef _MTREE_H_ 35 | #define _MTREE_H_ 36 | 37 | #define KEYDEFAULT (F_GID | F_MODE | F_NLINK | F_SIZE | F_SLINK | \ 38 | F_TIME | F_TYPE | F_UID | F_FLAGS) 39 | 40 | #define MISMATCHEXIT 2 41 | 42 | /* Max. length of hash -- update this if needed when adding a new algorithm. */ 43 | #define MAXHASHLEN 128 /* SHA512 */ 44 | 45 | typedef struct _node { 46 | struct _node *parent, *child; /* up, down */ 47 | struct _node *prev, *next; /* left, right */ 48 | off_t st_size; /* size */ 49 | struct timespec st_mtimespec; /* last modification time */ 50 | char *slink; /* symbolic link reference */ 51 | uid_t st_uid; /* uid */ 52 | gid_t st_gid; /* gid */ 53 | #define MBITS (S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO) 54 | mode_t st_mode; /* mode */ 55 | dev_t st_rdev; /* device type */ 56 | u_long st_flags; /* flags */ 57 | nlink_t st_nlink; /* link count */ 58 | u_long cksum; /* check sum */ 59 | char *md5digest; /* MD5 digest */ 60 | char *rmd160digest; /* RMD-160 digest */ 61 | char *sha1digest; /* SHA1 digest */ 62 | char *sha256digest; /* SHA256 digest */ 63 | char *sha384digest; /* SHA384 digest */ 64 | char *sha512digest; /* SHA512 digest */ 65 | char *tags; /* tags, comma delimited */ 66 | size_t lineno; /* line # entry came from */ 67 | 68 | #define F_CKSUM 0x00000001 /* cksum(1) check sum */ 69 | #define F_DEV 0x00000002 /* device type */ 70 | #define F_DONE 0x00000004 /* directory done */ 71 | #define F_FLAGS 0x00000008 /* file flags */ 72 | #define F_GID 0x00000010 /* gid */ 73 | #define F_GNAME 0x00000020 /* group name */ 74 | #define F_IGN 0x00000040 /* ignore */ 75 | #define F_MAGIC 0x00000080 /* name has magic chars */ 76 | #define F_MD5 0x00000100 /* MD5 digest */ 77 | #define F_MODE 0x00000200 /* mode */ 78 | #define F_NLINK 0x00000400 /* number of links */ 79 | #define F_OPT 0x00000800 /* existence optional */ 80 | #define F_RMD160 0x00001000 /* RMD-160 digest */ 81 | #define F_SHA1 0x00002000 /* SHA1 digest */ 82 | #define F_SIZE 0x00004000 /* size */ 83 | #define F_SLINK 0x00008000 /* symbolic link */ 84 | #define F_TAGS 0x00010000 /* tags */ 85 | #define F_TIME 0x00020000 /* modification time */ 86 | #define F_TYPE 0x00040000 /* file type */ 87 | #define F_UID 0x00080000 /* uid */ 88 | #define F_UNAME 0x00100000 /* user name */ 89 | #define F_VISIT 0x00200000 /* file visited */ 90 | #define F_SHA256 0x00800000 /* SHA256 digest */ 91 | #define F_SHA384 0x01000000 /* SHA384 digest */ 92 | #define F_SHA512 0x02000000 /* SHA512 digest */ 93 | 94 | int flags; /* items set */ 95 | 96 | #define F_BLOCK 0x001 /* block special */ 97 | #define F_CHAR 0x002 /* char special */ 98 | #define F_DIR 0x004 /* directory */ 99 | #define F_FIFO 0x008 /* fifo */ 100 | #define F_FILE 0x010 /* regular file */ 101 | #define F_LINK 0x020 /* symbolic link */ 102 | #define F_SOCK 0x040 /* socket */ 103 | #define F_DOOR 0x080 /* door */ 104 | int type; /* file type */ 105 | 106 | char name[1]; /* file name (must be last) */ 107 | } NODE; 108 | 109 | 110 | typedef struct { 111 | char **list; 112 | int count; 113 | } slist_t; 114 | 115 | 116 | /* 117 | * prototypes for functions published to other programs which want to use 118 | * the specfile parser but don't want to pull in all of "extern.h" 119 | */ 120 | const char *inotype(u_int); 121 | u_int nodetoino(u_int); 122 | int setup_getid(const char *); 123 | NODE *spec(FILE *); 124 | void free_nodes(NODE *); 125 | char *vispath(const char *); 126 | 127 | 128 | #define RP(p) \ 129 | ((p)->fts_path[0] == '.' && (p)->fts_path[1] == '/' ? \ 130 | (p)->fts_path + 2 : (p)->fts_path) 131 | 132 | #define UF_MASK ((UF_NODUMP | UF_IMMUTABLE | \ 133 | UF_APPEND | UF_OPAQUE) \ 134 | & UF_SETTABLE) /* user settable flags */ 135 | #define SF_MASK ((SF_ARCHIVED | SF_IMMUTABLE | \ 136 | SF_APPEND) & SF_SETTABLE) /* root settable flags */ 137 | #define CH_MASK (UF_MASK | SF_MASK) /* all settable flags */ 138 | #define SP_FLGS (SF_IMMUTABLE | SF_APPEND) /* special flags */ 139 | 140 | #endif /* _MTREE_H_ */ 141 | -------------------------------------------------------------------------------- /pack_dev.c: -------------------------------------------------------------------------------- 1 | /* $NetBSD: pack_dev.c,v 1.5 2008/11/06 02:14:52 jschauma Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc. 5 | * All rights reserved. 6 | * 7 | * This code is derived from software contributed to The NetBSD Foundation 8 | * by Charles M. Hannum. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. All advertising materials mentioning features or use of this software 19 | * must display the following acknowledgement: 20 | * This product includes software developed by the NetBSD 21 | * Foundation, Inc. and its contributors. 22 | * 4. Neither the name of The NetBSD Foundation nor the names of its 23 | * contributors may be used to endorse or promote products derived 24 | * from this software without specific prior written permission. 25 | * 26 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 | * POSSIBILITY OF SUCH DAMAGE. 37 | */ 38 | 39 | #if HAVE_CONFIG_H 40 | #include "config.h" 41 | #endif 42 | #if HAVE_NBTOOL_CONFIG_H 43 | #include "nbtool_config.h" 44 | #endif 45 | 46 | #include 47 | #if HAVE_SYS_CDEFS_H 48 | #include 49 | #endif 50 | #if !defined(lint) 51 | __RCSID("$NetBSD: pack_dev.c,v 1.5 2008/11/06 02:14:52 jschauma Exp $"); 52 | #endif /* not lint */ 53 | 54 | #include 55 | 56 | #if HAVE_SYS_TYPES_H 57 | #include 58 | #endif 59 | #if HAVE_SYS_STAT_H 60 | #include 61 | #endif 62 | 63 | #if HAVE_LIMITS_H 64 | #include 65 | #endif 66 | #if HAVE_STDIO_H 67 | #include 68 | #endif 69 | #if HAVE_STDLIB_H 70 | #include 71 | #endif 72 | #if HAVE_STRING_H 73 | #include 74 | #endif 75 | #if HAVE_UNISTD_H 76 | #include 77 | #endif 78 | 79 | #include "pack_dev.h" 80 | 81 | static pack_t pack_netbsd; 82 | static pack_t pack_freebsd; 83 | static pack_t pack_8_8; 84 | static pack_t pack_12_20; 85 | static pack_t pack_14_18; 86 | static pack_t pack_8_24; 87 | static pack_t pack_bsdos; 88 | static int compare_format(const void *, const void *); 89 | 90 | static const char iMajorError[] = "invalid major number"; 91 | static const char iMinorError[] = "invalid minor number"; 92 | static const char tooManyFields[] = "too many fields for format"; 93 | 94 | /* exported */ 95 | portdev_t 96 | pack_native(int n, u_long numbers[], const char **error) 97 | { 98 | portdev_t dev = 0; 99 | 100 | if (n == 2) { 101 | dev = makedev(numbers[0], numbers[1]); 102 | if (major(dev) != numbers[0]) 103 | *error = iMajorError; 104 | else if (minor(dev) != numbers[1]) 105 | *error = iMinorError; 106 | } else 107 | *error = tooManyFields; 108 | return (dev); 109 | } 110 | 111 | 112 | static portdev_t 113 | pack_netbsd(int n, u_long numbers[], const char **error) 114 | { 115 | portdev_t dev = 0; 116 | 117 | if (n == 2) { 118 | dev = makedev_netbsd(numbers[0], numbers[1]); 119 | if (major_netbsd(dev) != numbers[0]) 120 | *error = iMajorError; 121 | else if (minor_netbsd(dev) != numbers[1]) 122 | *error = iMinorError; 123 | } else 124 | *error = tooManyFields; 125 | return (dev); 126 | } 127 | 128 | 129 | #define major_freebsd(x) ((int32_t)(((x) & 0x0000ff00) >> 8)) 130 | #define minor_freebsd(x) ((int32_t)(((x) & 0xffff00ff) >> 0)) 131 | #define makedev_freebsd(x,y) ((portdev_t)((((x) << 8) & 0x0000ff00) | \ 132 | (((y) << 0) & 0xffff00ff))) 133 | 134 | static portdev_t 135 | pack_freebsd(int n, u_long numbers[], const char **error) 136 | { 137 | portdev_t dev = 0; 138 | 139 | if (n == 2) { 140 | dev = makedev_freebsd(numbers[0], numbers[1]); 141 | if (major_freebsd(dev) != numbers[0]) 142 | *error = iMajorError; 143 | if (minor_freebsd(dev) != numbers[1]) 144 | *error = iMinorError; 145 | } else 146 | *error = tooManyFields; 147 | return (dev); 148 | } 149 | 150 | 151 | #define major_8_8(x) ((int32_t)(((x) & 0x0000ff00) >> 8)) 152 | #define minor_8_8(x) ((int32_t)(((x) & 0x000000ff) >> 0)) 153 | #define makedev_8_8(x,y) ((portdev_t)((((x) << 8) & 0x0000ff00) | \ 154 | (((y) << 0) & 0x000000ff))) 155 | 156 | static portdev_t 157 | pack_8_8(int n, u_long numbers[], const char **error) 158 | { 159 | portdev_t dev = 0; 160 | 161 | if (n == 2) { 162 | dev = makedev_8_8(numbers[0], numbers[1]); 163 | if (major_8_8(dev) != numbers[0]) 164 | *error = iMajorError; 165 | if (minor_8_8(dev) != numbers[1]) 166 | *error = iMinorError; 167 | } else 168 | *error = tooManyFields; 169 | return (dev); 170 | } 171 | 172 | 173 | #define major_12_20(x) ((int32_t)(((x) & 0xfff00000) >> 20)) 174 | #define minor_12_20(x) ((int32_t)(((x) & 0x000fffff) >> 0)) 175 | #define makedev_12_20(x,y) ((portdev_t)((((x) << 20) & 0xfff00000) | \ 176 | (((y) << 0) & 0x000fffff))) 177 | 178 | static portdev_t 179 | pack_12_20(int n, u_long numbers[], const char **error) 180 | { 181 | portdev_t dev = 0; 182 | 183 | if (n == 2) { 184 | dev = makedev_12_20(numbers[0], numbers[1]); 185 | if (major_12_20(dev) != numbers[0]) 186 | *error = iMajorError; 187 | if (minor_12_20(dev) != numbers[1]) 188 | *error = iMinorError; 189 | } else 190 | *error = tooManyFields; 191 | return (dev); 192 | } 193 | 194 | 195 | #define major_14_18(x) ((int32_t)(((x) & 0xfffc0000) >> 18)) 196 | #define minor_14_18(x) ((int32_t)(((x) & 0x0003ffff) >> 0)) 197 | #define makedev_14_18(x,y) ((portdev_t)((((x) << 18) & 0xfffc0000) | \ 198 | (((y) << 0) & 0x0003ffff))) 199 | 200 | static portdev_t 201 | pack_14_18(int n, u_long numbers[], const char **error) 202 | { 203 | portdev_t dev = 0; 204 | 205 | if (n == 2) { 206 | dev = makedev_14_18(numbers[0], numbers[1]); 207 | if (major_14_18(dev) != numbers[0]) 208 | *error = iMajorError; 209 | if (minor_14_18(dev) != numbers[1]) 210 | *error = iMinorError; 211 | } else 212 | *error = tooManyFields; 213 | return (dev); 214 | } 215 | 216 | 217 | #define major_8_24(x) ((int32_t)(((x) & 0xff000000) >> 24)) 218 | #define minor_8_24(x) ((int32_t)(((x) & 0x00ffffff) >> 0)) 219 | #define makedev_8_24(x,y) ((portdev_t)((((x) << 24) & 0xff000000) | \ 220 | (((y) << 0) & 0x00ffffff))) 221 | 222 | static portdev_t 223 | pack_8_24(int n, u_long numbers[], const char **error) 224 | { 225 | portdev_t dev = 0; 226 | 227 | if (n == 2) { 228 | dev = makedev_8_24(numbers[0], numbers[1]); 229 | if (major_8_24(dev) != numbers[0]) 230 | *error = iMajorError; 231 | if (minor_8_24(dev) != numbers[1]) 232 | *error = iMinorError; 233 | } else 234 | *error = tooManyFields; 235 | return (dev); 236 | } 237 | 238 | 239 | #define major_12_12_8(x) ((int32_t)(((x) & 0xfff00000) >> 20)) 240 | #define unit_12_12_8(x) ((int32_t)(((x) & 0x000fff00) >> 8)) 241 | #define subunit_12_12_8(x) ((int32_t)(((x) & 0x000000ff) >> 0)) 242 | #define makedev_12_12_8(x,y,z) ((portdev_t)((((x) << 20) & 0xfff00000) | \ 243 | (((y) << 8) & 0x000fff00) | \ 244 | (((z) << 0) & 0x000000ff))) 245 | 246 | static portdev_t 247 | pack_bsdos(int n, u_long numbers[], const char **error) 248 | { 249 | portdev_t dev = 0; 250 | 251 | if (n == 2) { 252 | dev = makedev_12_20(numbers[0], numbers[1]); 253 | if (major_12_20(dev) != numbers[0]) 254 | *error = iMajorError; 255 | if (minor_12_20(dev) != numbers[1]) 256 | *error = iMinorError; 257 | } else if (n == 3) { 258 | dev = makedev_12_12_8(numbers[0], numbers[1], numbers[2]); 259 | if (major_12_12_8(dev) != numbers[0]) 260 | *error = iMajorError; 261 | if (unit_12_12_8(dev) != numbers[1]) 262 | *error = "invalid unit number"; 263 | if (subunit_12_12_8(dev) != numbers[2]) 264 | *error = "invalid subunit number"; 265 | } else 266 | *error = tooManyFields; 267 | return (dev); 268 | } 269 | 270 | 271 | /* list of formats and pack functions */ 272 | /* this list must be sorted lexically */ 273 | struct format { 274 | const char *name; 275 | pack_t *pack; 276 | } formats[] = { 277 | {"386bsd", pack_8_8}, 278 | {"4bsd", pack_8_8}, 279 | {"bsdos", pack_bsdos}, 280 | {"freebsd", pack_freebsd}, 281 | {"hpux", pack_8_24}, 282 | {"isc", pack_8_8}, 283 | {"linux", pack_8_8}, 284 | {"native", pack_native}, 285 | {"netbsd", pack_netbsd}, 286 | {"osf1", pack_12_20}, 287 | {"sco", pack_8_8}, 288 | {"solaris", pack_14_18}, 289 | {"sunos", pack_8_8}, 290 | {"svr3", pack_8_8}, 291 | {"svr4", pack_14_18}, 292 | {"ultrix", pack_8_8}, 293 | }; 294 | 295 | static int 296 | compare_format(const void *key, const void *element) 297 | { 298 | const char *name; 299 | const struct format *format; 300 | 301 | name = key; 302 | format = element; 303 | 304 | return (strcmp(name, format->name)); 305 | } 306 | 307 | 308 | pack_t * 309 | pack_find(const char *name) 310 | { 311 | struct format *format; 312 | 313 | format = bsearch(name, formats, 314 | sizeof(formats)/sizeof(formats[0]), 315 | sizeof(formats[0]), compare_format); 316 | if (format == 0) 317 | return (NULL); 318 | return (format->pack); 319 | } 320 | -------------------------------------------------------------------------------- /pack_dev.h: -------------------------------------------------------------------------------- 1 | /* $NetBSD: pack_dev.h,v 1.4 2008/11/06 02:14:52 jschauma Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc. 5 | * All rights reserved. 6 | * 7 | * This code is derived from software contributed to The NetBSD Foundation 8 | * by Charles M. Hannum. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. All advertising materials mentioning features or use of this software 19 | * must display the following acknowledgement: 20 | * This product includes software developed by the NetBSD 21 | * Foundation, Inc. and its contributors. 22 | * 4. Neither the name of The NetBSD Foundation nor the names of its 23 | * contributors may be used to endorse or promote products derived 24 | * from this software without specific prior written permission. 25 | * 26 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 | * POSSIBILITY OF SUCH DAMAGE. 37 | */ 38 | 39 | #ifndef _PACK_DEV_H 40 | #define _PACK_DEV_H 41 | 42 | #ifdef __CYGWIN__ 43 | typedef __dev32_t portdev_t; 44 | #else 45 | typedef dev_t portdev_t; 46 | #endif 47 | typedef portdev_t pack_t(int, u_long [], const char **); 48 | 49 | pack_t *pack_find(const char *); 50 | pack_t pack_native; 51 | 52 | #define major_netbsd(x) ((int32_t)((((x) & 0x000fff00) >> 8))) 53 | #define minor_netbsd(x) ((int32_t)((((x) & 0xfff00000) >> 12) | \ 54 | (((x) & 0x000000ff) >> 0))) 55 | #define makedev_netbsd(x,y) ((dev_t)((((x) << 8) & 0x000fff00) | \ 56 | (((y) << 12) & 0xfff00000) | \ 57 | (((y) << 0) & 0x000000ff))) 58 | 59 | #endif /* _PACK_DEV_H */ 60 | -------------------------------------------------------------------------------- /spec.c: -------------------------------------------------------------------------------- 1 | /* $NetBSD: spec.c,v 1.5 2008/11/06 02:14:52 jschauma Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 1989, 1993 5 | * The Regents of the University of California. All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. Neither the name of the University nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 | * SUCH DAMAGE. 30 | */ 31 | 32 | /*- 33 | * Copyright (c) 2001-2004 The NetBSD Foundation, Inc. 34 | * All rights reserved. 35 | * 36 | * This code is derived from software contributed to The NetBSD Foundation 37 | * by Luke Mewburn of Wasabi Systems. 38 | * 39 | * Redistribution and use in source and binary forms, with or without 40 | * modification, are permitted provided that the following conditions 41 | * are met: 42 | * 1. Redistributions of source code must retain the above copyright 43 | * notice, this list of conditions and the following disclaimer. 44 | * 2. Redistributions in binary form must reproduce the above copyright 45 | * notice, this list of conditions and the following disclaimer in the 46 | * documentation and/or other materials provided with the distribution. 47 | * 3. All advertising materials mentioning features or use of this software 48 | * must display the following acknowledgement: 49 | * This product includes software developed by the NetBSD 50 | * Foundation, Inc. and its contributors. 51 | * 4. Neither the name of The NetBSD Foundation nor the names of its 52 | * contributors may be used to endorse or promote products derived 53 | * from this software without specific prior written permission. 54 | * 55 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 56 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 57 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 58 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 59 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 60 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 61 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 62 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 63 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 64 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 65 | * POSSIBILITY OF SUCH DAMAGE. 66 | */ 67 | 68 | #if HAVE_CONFIG_H 69 | #include "config.h" 70 | #endif 71 | #if HAVE_NBTOOL_CONFIG_H 72 | #include "nbtool_config.h" 73 | #endif 74 | 75 | #include 76 | #if HAVE_SYS_CDEFS_H 77 | #include 78 | #endif 79 | #if defined(__RCSID) && !defined(lint) 80 | #if 0 81 | static char sccsid[] = "@(#)spec.c 8.2 (Berkeley) 4/28/95"; 82 | #else 83 | __RCSID("$NetBSD: spec.c,v 1.5 2008/11/06 02:14:52 jschauma Exp $"); 84 | #endif 85 | #endif /* not lint */ 86 | 87 | #if HAVE_SYS_PARAM_H 88 | #include 89 | #endif 90 | #if HAVE_SYS_STAT_H 91 | #include 92 | #endif 93 | 94 | #if HAVE_CTYPE_H 95 | #include 96 | #endif 97 | #if HAVE_ERRNO_H 98 | #include 99 | #endif 100 | #if HAVE_GRP_H 101 | #include 102 | #endif 103 | #if HAVE_PWD_H 104 | #include 105 | #endif 106 | #if HAVE_STDIO_H 107 | #include 108 | #endif 109 | #if HAVE_STDLIB_H 110 | #include 111 | #endif 112 | #if HAVE_STRING_H 113 | #include 114 | #endif 115 | #if HAVE_UNISTD_H 116 | #include 117 | #endif 118 | #if HAVE_VIS_H 119 | #include 120 | #endif 121 | #if HAVE_UTIL_H 122 | #include 123 | #endif 124 | 125 | #include "extern.h" 126 | #include "pack_dev.h" 127 | 128 | size_t mtree_lineno; /* Current spec line number */ 129 | int mtree_Mflag; /* Merge duplicate entries */ 130 | int mtree_Wflag; /* Don't "whack" permissions */ 131 | 132 | static dev_t parsedev(char *); 133 | static void replacenode(NODE *, NODE *); 134 | static void set(char *, NODE *); 135 | static void unset(char *, NODE *); 136 | 137 | #define REPLACEPTR(x,v) do { if ((x)) free((x)); (x) = (v); } while (0) 138 | 139 | NODE * 140 | spec(FILE *fp) 141 | { 142 | NODE *centry, *last, *pathparent, *cur; 143 | char *p, *e, *next; 144 | NODE ginfo, *root; 145 | char *buf, *tname, *ntname; 146 | size_t tnamelen, plen; 147 | 148 | root = NULL; 149 | centry = last = NULL; 150 | tname = NULL; 151 | tnamelen = 0; 152 | memset(&ginfo, 0, sizeof(ginfo)); 153 | for (mtree_lineno = 0; 154 | (buf = fparseln(fp, NULL, &mtree_lineno, NULL, 155 | FPARSELN_UNESCCOMM)); 156 | free(buf)) { 157 | /* Skip leading whitespace. */ 158 | for (p = buf; *p && isspace((unsigned char)*p); ++p) 159 | continue; 160 | 161 | /* If nothing but whitespace, continue. */ 162 | if (!*p) 163 | continue; 164 | 165 | #ifdef DEBUG 166 | fprintf(stderr, "line %lu: {%s}\n", 167 | (u_long)mtree_lineno, p); 168 | #endif 169 | /* Grab file name, "$", "set", or "unset". */ 170 | next = buf; 171 | while ((p = strsep(&next, " \t")) != NULL && *p == '\0') 172 | continue; 173 | if (p == NULL) 174 | mtree_err("missing field"); 175 | 176 | if (p[0] == '/') { 177 | if (strcmp(p + 1, "set") == 0) 178 | set(next, &ginfo); 179 | else if (strcmp(p + 1, "unset") == 0) 180 | unset(next, &ginfo); 181 | else 182 | mtree_err("invalid specification `%s'", p); 183 | continue; 184 | } 185 | 186 | if (strcmp(p, "..") == 0) { 187 | /* Don't go up, if haven't gone down. */ 188 | if (root == NULL) 189 | goto noparent; 190 | if (last->type != F_DIR || last->flags & F_DONE) { 191 | if (last == root) 192 | goto noparent; 193 | last = last->parent; 194 | } 195 | last->flags |= F_DONE; 196 | continue; 197 | 198 | noparent: mtree_err("no parent node"); 199 | } 200 | 201 | plen = strlen(p) + 1; 202 | if (plen > tnamelen) { 203 | if ((ntname = realloc(tname, plen)) == NULL) 204 | mtree_err("realloc: %s", strerror(errno)); 205 | tname = ntname; 206 | tnamelen = plen; 207 | } 208 | if (strunvis(tname, p) == -1) 209 | mtree_err("strunvis failed on `%s'", p); 210 | p = tname; 211 | 212 | pathparent = NULL; 213 | if (strchr(p, '/') != NULL) { 214 | cur = root; 215 | for (; (e = strchr(p, '/')) != NULL; p = e+1) { 216 | if (p == e) 217 | continue; /* handle // */ 218 | *e = '\0'; 219 | if (strcmp(p, ".") != 0) { 220 | while (cur && 221 | strcmp(cur->name, p) != 0) { 222 | cur = cur->next; 223 | } 224 | } 225 | if (cur == NULL || cur->type != F_DIR) { 226 | mtree_err("%s: %s", tname, 227 | strerror(ENOENT)); 228 | } 229 | *e = '/'; 230 | pathparent = cur; 231 | cur = cur->child; 232 | } 233 | if (*p == '\0') 234 | mtree_err("%s: empty leaf element", tname); 235 | } 236 | 237 | if ((centry = calloc(1, sizeof(NODE) + strlen(p))) == NULL) 238 | mtree_err("%s", strerror(errno)); 239 | *centry = ginfo; 240 | centry->lineno = mtree_lineno; 241 | strcpy(centry->name, p); 242 | #define MAGIC "?*[" 243 | if (strpbrk(p, MAGIC)) 244 | centry->flags |= F_MAGIC; 245 | set(next, centry); 246 | 247 | if (root == NULL) { 248 | /* 249 | * empty tree 250 | */ 251 | if (strcmp(centry->name, ".") != 0 || 252 | centry->type != F_DIR) 253 | mtree_err( 254 | "root node must be the directory `.'"); 255 | last = root = centry; 256 | root->parent = root; 257 | } else if (pathparent != NULL) { 258 | /* 259 | * full path entry 260 | */ 261 | centry->parent = pathparent; 262 | cur = pathparent->child; 263 | if (cur == NULL) { 264 | pathparent->child = centry; 265 | last = centry; 266 | } else { 267 | for (; cur != NULL; cur = cur->next) { 268 | if (strcmp(cur->name, centry->name) 269 | == 0) { 270 | /* existing entry; replace */ 271 | replacenode(cur, centry); 272 | break; 273 | } 274 | if (cur->next == NULL) { 275 | /* last entry; add new */ 276 | cur->next = centry; 277 | centry->prev = cur; 278 | break; 279 | } 280 | } 281 | last = cur; 282 | while (last->next != NULL) 283 | last = last->next; 284 | } 285 | } else if (strcmp(centry->name, ".") == 0) { 286 | /* 287 | * duplicate "." entry; always replace 288 | */ 289 | replacenode(root, centry); 290 | } else if (last->type == F_DIR && !(last->flags & F_DONE)) { 291 | /* 292 | * new relative child 293 | * (no duplicate check) 294 | */ 295 | centry->parent = last; 296 | last = last->child = centry; 297 | } else { 298 | /* 299 | * relative entry, up one directory 300 | * (no duplicate check) 301 | */ 302 | centry->parent = last->parent; 303 | centry->prev = last; 304 | last = last->next = centry; 305 | } 306 | } 307 | return (root); 308 | } 309 | 310 | void 311 | free_nodes(NODE *root) 312 | { 313 | NODE *cur, *next; 314 | 315 | if (root == NULL) 316 | return; 317 | 318 | next = NULL; 319 | for (cur = root; cur != NULL; cur = next) { 320 | next = cur->next; 321 | free_nodes(cur->child); 322 | REPLACEPTR(cur->slink, NULL); 323 | REPLACEPTR(cur->md5digest, NULL); 324 | REPLACEPTR(cur->rmd160digest, NULL); 325 | REPLACEPTR(cur->sha1digest, NULL); 326 | REPLACEPTR(cur->sha256digest, NULL); 327 | REPLACEPTR(cur->sha384digest, NULL); 328 | REPLACEPTR(cur->sha512digest, NULL); 329 | REPLACEPTR(cur->tags, NULL); 330 | REPLACEPTR(cur, NULL); 331 | } 332 | } 333 | 334 | /* 335 | * dump_nodes -- 336 | * dump the NODEs from `cur', based in the directory `dir'. 337 | * if pathlast is none zero, print the path last, otherwise print 338 | * it first. 339 | */ 340 | void 341 | dump_nodes(const char *dir, NODE *root, int pathlast) 342 | { 343 | NODE *cur; 344 | char path[MAXPATHLEN]; 345 | const char *name; 346 | 347 | for (cur = root; cur != NULL; cur = cur->next) { 348 | if (cur->type != F_DIR && !matchtags(cur)) 349 | continue; 350 | 351 | if (snprintf(path, sizeof(path), "%s%s%s", 352 | dir, *dir ? "/" : "", cur->name) 353 | >= sizeof(path)) 354 | mtree_err("Pathname too long."); 355 | 356 | if (!pathlast) 357 | printf("%s ", vispath(path)); 358 | 359 | #define MATCHFLAG(f) ((keys & (f)) && (cur->flags & (f))) 360 | if (MATCHFLAG(F_TYPE)) 361 | printf("type=%s ", nodetype(cur->type)); 362 | if (MATCHFLAG(F_UID | F_UNAME)) { 363 | if (keys & F_UNAME && 364 | (name = user_from_uid(cur->st_uid, 1)) != NULL) 365 | printf("uname=%s ", name); 366 | else 367 | printf("uid=%u ", cur->st_uid); 368 | } 369 | if (MATCHFLAG(F_GID | F_GNAME)) { 370 | if (keys & F_GNAME && 371 | (name = group_from_gid(cur->st_gid, 1)) != NULL) 372 | printf("gname=%s ", name); 373 | else 374 | printf("gid=%u ", cur->st_gid); 375 | } 376 | if (MATCHFLAG(F_MODE)) 377 | printf("mode=%#o ", cur->st_mode); 378 | if (MATCHFLAG(F_DEV) && 379 | (cur->type == F_BLOCK || cur->type == F_CHAR)) 380 | printf("device=%#lx ", (unsigned long)cur->st_rdev); 381 | if (MATCHFLAG(F_NLINK)) 382 | printf("nlink=%ld ", (unsigned long)cur->st_nlink); 383 | if (MATCHFLAG(F_SLINK)) 384 | printf("link=%s ", vispath(cur->slink)); 385 | if (MATCHFLAG(F_SIZE)) 386 | printf("size=%lld ", (long long)cur->st_size); 387 | if (MATCHFLAG(F_TIME)) 388 | printf("time=%ju.%09ld ", (uintmax_t)cur->st_mtimespec.tv_sec, (long)cur->st_mtimespec.tv_nsec); 389 | if (MATCHFLAG(F_CKSUM)) 390 | printf("cksum=%lu ", cur->cksum); 391 | if (MATCHFLAG(F_MD5)) 392 | printf("md5=%s ", cur->md5digest); 393 | if (MATCHFLAG(F_RMD160)) 394 | printf("rmd160=%s ", cur->rmd160digest); 395 | if (MATCHFLAG(F_SHA1)) 396 | printf("sha1=%s ", cur->sha1digest); 397 | if (MATCHFLAG(F_SHA256)) 398 | printf("sha256=%s ", cur->sha256digest); 399 | if (MATCHFLAG(F_SHA384)) 400 | printf("sha384=%s ", cur->sha384digest); 401 | if (MATCHFLAG(F_SHA512)) 402 | printf("sha512=%s ", cur->sha512digest); 403 | if (MATCHFLAG(F_FLAGS)) 404 | printf("flags=%s ", 405 | flags_to_string(cur->st_flags, "none")); 406 | if (MATCHFLAG(F_IGN)) 407 | printf("ignore "); 408 | if (MATCHFLAG(F_OPT)) 409 | printf("optional "); 410 | if (MATCHFLAG(F_TAGS)) 411 | printf("tags=%s ", cur->tags); 412 | puts(pathlast ? vispath(path) : ""); 413 | 414 | if (cur->child) 415 | dump_nodes(path, cur->child, pathlast); 416 | } 417 | } 418 | 419 | /* 420 | * vispath -- 421 | * strsvis(3) encodes path, which must not be longer than MAXPATHLEN 422 | * characters long, and returns a pointer to a static buffer containing 423 | * the result. 424 | */ 425 | char * 426 | vispath(const char *path) 427 | { 428 | const char extra[] = { ' ', '\t', '\n', '\\', '#', '\0' }; 429 | static char pathbuf[4*MAXPATHLEN + 1]; 430 | 431 | strsvis(pathbuf, path, VIS_CSTYLE, extra); 432 | return(pathbuf); 433 | } 434 | 435 | 436 | static dev_t 437 | parsedev(char *arg) 438 | { 439 | #define MAX_PACK_ARGS 3 440 | u_long numbers[MAX_PACK_ARGS]; 441 | char *p, *ep, *dev; 442 | int argc; 443 | pack_t *pack; 444 | dev_t result; 445 | const char *error = NULL; 446 | 447 | if ((dev = strchr(arg, ',')) != NULL) { 448 | *dev++='\0'; 449 | if ((pack = pack_find(arg)) == NULL) 450 | mtree_err("unknown format `%s'", arg); 451 | argc = 0; 452 | while ((p = strsep(&dev, ",")) != NULL) { 453 | if (*p == '\0') 454 | mtree_err("missing number"); 455 | numbers[argc++] = strtoul(p, &ep, 0); 456 | if (*ep != '\0') 457 | mtree_err("invalid number `%s'", 458 | p); 459 | if (argc > MAX_PACK_ARGS) 460 | mtree_err("too many arguments"); 461 | } 462 | if (argc < 2) 463 | mtree_err("not enough arguments"); 464 | result = (*pack)(argc, numbers, &error); 465 | if (error != NULL) 466 | mtree_err(error); 467 | } else { 468 | result = (dev_t)strtoul(arg, &ep, 0); 469 | if (*ep != '\0') 470 | mtree_err("invalid device `%s'", arg); 471 | } 472 | return (result); 473 | } 474 | 475 | static void 476 | replacenode(NODE *cur, NODE *new) 477 | { 478 | 479 | #define REPLACE(x) cur->x = new->x 480 | #define REPLACESTR(x) REPLACEPTR(cur->x,new->x) 481 | 482 | if (cur->type != new->type) { 483 | if (mtree_Mflag) { 484 | /* 485 | * merge entries with different types; we 486 | * don't want children retained in this case. 487 | */ 488 | REPLACE(type); 489 | free_nodes(cur->child); 490 | cur->child = NULL; 491 | } else { 492 | mtree_err( 493 | "existing entry for `%s', type `%s'" 494 | " does not match type `%s'", 495 | cur->name, nodetype(cur->type), 496 | nodetype(new->type)); 497 | } 498 | } 499 | 500 | REPLACE(st_size); 501 | REPLACE(st_mtimespec); 502 | REPLACESTR(slink); 503 | if (cur->slink != NULL) { 504 | if ((cur->slink = strdup(new->slink)) == NULL) 505 | mtree_err("memory allocation error"); 506 | if (strunvis(cur->slink, new->slink) == -1) 507 | mtree_err("strunvis failed on `%s'", new->slink); 508 | free(new->slink); 509 | } 510 | REPLACE(st_uid); 511 | REPLACE(st_gid); 512 | REPLACE(st_mode); 513 | REPLACE(st_rdev); 514 | REPLACE(st_flags); 515 | REPLACE(st_nlink); 516 | REPLACE(cksum); 517 | REPLACESTR(md5digest); 518 | REPLACESTR(rmd160digest); 519 | REPLACESTR(sha1digest); 520 | REPLACESTR(sha256digest); 521 | REPLACESTR(sha384digest); 522 | REPLACESTR(sha512digest); 523 | REPLACESTR(tags); 524 | REPLACE(lineno); 525 | REPLACE(flags); 526 | free(new); 527 | } 528 | 529 | static void 530 | set(char *t, NODE *ip) 531 | { 532 | int type, value, len; 533 | gid_t gid; 534 | uid_t uid; 535 | char *kw, *val, *md, *ep; 536 | void *m; 537 | 538 | while ((kw = strsep(&t, "= \t")) != NULL) { 539 | if (*kw == '\0') 540 | continue; 541 | if (strcmp(kw, "all") == 0) 542 | mtree_err("invalid keyword `all'"); 543 | ip->flags |= type = parsekey(kw, &value); 544 | if (!value) 545 | /* Just set flag bit (F_IGN and F_OPT) */ 546 | continue; 547 | while ((val = strsep(&t, " \t")) != NULL && *val == '\0') 548 | continue; 549 | if (val == NULL) 550 | mtree_err("missing value"); 551 | switch (type) { 552 | case F_CKSUM: 553 | ip->cksum = strtoul(val, &ep, 10); 554 | if (*ep) 555 | mtree_err("invalid checksum `%s'", val); 556 | break; 557 | case F_DEV: 558 | ip->st_rdev = parsedev(val); 559 | break; 560 | case F_FLAGS: 561 | if (strcmp("none", val) == 0) 562 | ip->st_flags = 0; 563 | else if (string_to_flags(&val, &ip->st_flags, NULL) 564 | != 0) 565 | mtree_err("invalid flag `%s'", val); 566 | break; 567 | case F_GID: 568 | ip->st_gid = (gid_t)strtoul(val, &ep, 10); 569 | if (*ep) 570 | mtree_err("invalid gid `%s'", val); 571 | break; 572 | case F_GNAME: 573 | if (mtree_Wflag) /* don't parse if whacking */ 574 | break; 575 | if (gid_from_group(val, &gid) == -1) 576 | mtree_err("unknown group `%s'", val); 577 | ip->st_gid = gid; 578 | break; 579 | case F_MD5: 580 | if (val[0]=='0' && val[1]=='x') 581 | md=&val[2]; 582 | else 583 | md=val; 584 | if ((ip->md5digest = strdup(md)) == NULL) 585 | mtree_err("memory allocation error"); 586 | break; 587 | case F_MODE: 588 | if ((m = setmode(val)) == NULL) 589 | mtree_err("cannot set file mode `%s' (%s)", 590 | val, strerror(errno)); 591 | ip->st_mode = getmode(m, 0); 592 | free(m); 593 | break; 594 | case F_NLINK: 595 | ip->st_nlink = (nlink_t)strtoul(val, &ep, 10); 596 | if (*ep) 597 | mtree_err("invalid link count `%s'", val); 598 | break; 599 | case F_RMD160: 600 | if (val[0]=='0' && val[1]=='x') 601 | md=&val[2]; 602 | else 603 | md=val; 604 | if ((ip->rmd160digest = strdup(md)) == NULL) 605 | mtree_err("memory allocation error"); 606 | break; 607 | case F_SHA1: 608 | if (val[0]=='0' && val[1]=='x') 609 | md=&val[2]; 610 | else 611 | md=val; 612 | if ((ip->sha1digest = strdup(md)) == NULL) 613 | mtree_err("memory allocation error"); 614 | break; 615 | case F_SIZE: 616 | ip->st_size = (off_t)strtoll(val, &ep, 10); 617 | if (*ep) 618 | mtree_err("invalid size `%s'", val); 619 | break; 620 | case F_SLINK: 621 | if ((ip->slink = strdup(val)) == NULL) 622 | mtree_err("memory allocation error"); 623 | if (strunvis(ip->slink, val) == -1) 624 | mtree_err("strunvis failed on `%s'", val); 625 | break; 626 | case F_TAGS: 627 | len = strlen(val) + 3; /* "," + str + ",\0" */ 628 | if ((ip->tags = malloc(len)) == NULL) 629 | mtree_err("memory allocation error"); 630 | snprintf(ip->tags, len, ",%s,", val); 631 | break; 632 | case F_TIME: 633 | ip->st_mtimespec.tv_sec = 634 | (time_t)strtoull(val, &ep, 10); 635 | if (*ep != '.') 636 | mtree_err("invalid time `%s'", val); 637 | val = ep + 1; 638 | ip->st_mtimespec.tv_nsec = strtoul(val, &ep, 10); 639 | if (*ep) 640 | mtree_err("invalid time `%s'", val); 641 | break; 642 | case F_TYPE: 643 | ip->type = parsetype(val); 644 | break; 645 | case F_UID: 646 | ip->st_uid = (uid_t)strtoul(val, &ep, 10); 647 | if (*ep) 648 | mtree_err("invalid uid `%s'", val); 649 | break; 650 | case F_UNAME: 651 | if (mtree_Wflag) /* don't parse if whacking */ 652 | break; 653 | if (uid_from_user(val, &uid) == -1) 654 | mtree_err("unknown user `%s'", val); 655 | ip->st_uid = uid; 656 | break; 657 | case F_SHA256: 658 | if (val[0]=='0' && val[1]=='x') 659 | md=&val[2]; 660 | else 661 | md=val; 662 | if ((ip->sha256digest = strdup(md)) == NULL) 663 | mtree_err("memory allocation error"); 664 | break; 665 | case F_SHA384: 666 | if (val[0]=='0' && val[1]=='x') 667 | md=&val[2]; 668 | else 669 | md=val; 670 | if ((ip->sha384digest = strdup(md)) == NULL) 671 | mtree_err("memory allocation error"); 672 | break; 673 | case F_SHA512: 674 | if (val[0]=='0' && val[1]=='x') 675 | md=&val[2]; 676 | else 677 | md=val; 678 | if ((ip->sha512digest = strdup(md)) == NULL) 679 | mtree_err("memory allocation error"); 680 | break; 681 | default: 682 | mtree_err( 683 | "set(): unsupported key type 0x%x (INTERNAL ERROR)", 684 | type); 685 | /* NOTREACHED */ 686 | } 687 | } 688 | } 689 | 690 | static void 691 | unset(char *t, NODE *ip) 692 | { 693 | char *p; 694 | 695 | while ((p = strsep(&t, " \t")) != NULL) { 696 | if (*p == '\0') 697 | continue; 698 | ip->flags &= ~parsekey(p, NULL); 699 | } 700 | } 701 | -------------------------------------------------------------------------------- /stat_flags.c: -------------------------------------------------------------------------------- 1 | /* $NetBSD: stat_flags.c,v 1.5 2011/07/27 15:31:00 seb Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 1993 5 | * The Regents of the University of California. All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. Neither the name of the University nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 | * SUCH DAMAGE. 30 | */ 31 | 32 | #if HAVE_CONFIG_H 33 | #include "config.h" 34 | #endif 35 | #if 0 36 | #if HAVE_NBTOOL_CONFIG_H 37 | #include "nbtool_config.h" 38 | #else 39 | #define HAVE_STRUCT_STAT_ST_FLAGS 1 40 | #endif 41 | #endif 42 | 43 | #include 44 | #if HAVE_SYS_CDEFS_H 45 | #include 46 | #endif 47 | #if !defined(lint) 48 | #if 0 49 | static char sccsid[] = "@(#)stat_flags.c 8.2 (Berkeley) 7/28/94"; 50 | #else 51 | __RCSID("$NetBSD: stat_flags.c,v 1.5 2011/07/27 15:31:00 seb Exp $"); 52 | #endif 53 | #endif /* not lint */ 54 | 55 | #if HAVE_SYS_TYPES_H 56 | #include 57 | #endif 58 | #if HAVE_SYS_STAT_H 59 | #include 60 | #endif 61 | #if HAVE_FTS_H 62 | #include 63 | #endif 64 | #if HAVE_STDDEF_H 65 | #include 66 | #endif 67 | #if HAVE_STRING_H 68 | #include 69 | #endif 70 | 71 | #include "stat_flags.h" 72 | 73 | #define SAPPEND(s) do { \ 74 | if (prefix != NULL) \ 75 | (void)strlcat(string, prefix, sizeof(string)); \ 76 | (void)strlcat(string, s, sizeof(string)); \ 77 | prefix = ","; \ 78 | } while (/* CONSTCOND */ 0) 79 | 80 | /* 81 | * flags_to_string -- 82 | * Convert stat flags to a comma-separated string. If no flags 83 | * are set, return the default string. 84 | */ 85 | char * 86 | flags_to_string(u_long flags, const char *def) 87 | { 88 | static char string[128]; 89 | const char *prefix; 90 | 91 | string[0] = '\0'; 92 | prefix = NULL; 93 | #if HAVE_STRUCT_STAT_ST_FLAGS 94 | if (flags & UF_APPEND) 95 | SAPPEND("uappnd"); 96 | if (flags & UF_IMMUTABLE) 97 | SAPPEND("uchg"); 98 | if (flags & UF_NODUMP) 99 | SAPPEND("nodump"); 100 | if (flags & UF_OPAQUE) 101 | SAPPEND("opaque"); 102 | if (flags & SF_APPEND) 103 | SAPPEND("sappnd"); 104 | if (flags & SF_ARCHIVED) 105 | SAPPEND("arch"); 106 | if (flags & SF_IMMUTABLE) 107 | SAPPEND("schg"); 108 | #ifdef SF_SNAPSHOT 109 | if (flags & SF_SNAPSHOT) 110 | SAPPEND("snap"); 111 | #endif 112 | #endif 113 | if (prefix == NULL) 114 | strlcpy(string, def, sizeof(string)); 115 | return (string); 116 | } 117 | 118 | #define TEST(a, b, f) { \ 119 | if (!strcmp(a, b)) { \ 120 | if (clear) { \ 121 | if (clrp) \ 122 | *clrp |= (f); \ 123 | if (setp) \ 124 | *setp &= ~(f); \ 125 | } else { \ 126 | if (setp) \ 127 | *setp |= (f); \ 128 | if (clrp) \ 129 | *clrp &= ~(f); \ 130 | } \ 131 | break; \ 132 | } \ 133 | } 134 | 135 | /* 136 | * string_to_flags -- 137 | * Take string of arguments and return stat flags. Return 0 on 138 | * success, 1 on failure. On failure, stringp is set to point 139 | * to the offending token. 140 | */ 141 | int 142 | string_to_flags(char **stringp, u_long *setp, u_long *clrp) 143 | { 144 | #if HAVE_STRUCT_STAT_ST_FLAGS 145 | int clear; 146 | char *string, *p; 147 | #endif 148 | 149 | if (setp) 150 | *setp = 0; 151 | if (clrp) 152 | *clrp = 0; 153 | 154 | #if HAVE_STRUCT_STAT_ST_FLAGS 155 | string = *stringp; 156 | while ((p = strsep(&string, "\t ,")) != NULL) { 157 | clear = 0; 158 | *stringp = p; 159 | if (*p == '\0') 160 | continue; 161 | if (p[0] == 'n' && p[1] == 'o') { 162 | clear = 1; 163 | p += 2; 164 | } 165 | switch (p[0]) { 166 | case 'a': 167 | TEST(p, "arch", SF_ARCHIVED); 168 | TEST(p, "archived", SF_ARCHIVED); 169 | return (1); 170 | case 'd': 171 | clear = !clear; 172 | TEST(p, "dump", UF_NODUMP); 173 | return (1); 174 | case 'n': 175 | /* 176 | * Support `nonodump'. Note that 177 | * the state of clear is not changed. 178 | */ 179 | TEST(p, "nodump", UF_NODUMP); 180 | return (1); 181 | case 'o': 182 | TEST(p, "opaque", UF_OPAQUE); 183 | return (1); 184 | case 's': 185 | TEST(p, "sappnd", SF_APPEND); 186 | TEST(p, "sappend", SF_APPEND); 187 | TEST(p, "schg", SF_IMMUTABLE); 188 | TEST(p, "schange", SF_IMMUTABLE); 189 | TEST(p, "simmutable", SF_IMMUTABLE); 190 | return (1); 191 | case 'u': 192 | TEST(p, "uappnd", UF_APPEND); 193 | TEST(p, "uappend", UF_APPEND); 194 | TEST(p, "uchg", UF_IMMUTABLE); 195 | TEST(p, "uchange", UF_IMMUTABLE); 196 | TEST(p, "uimmutable", UF_IMMUTABLE); 197 | return (1); 198 | default: 199 | return (1); 200 | } 201 | } 202 | #endif 203 | 204 | return (0); 205 | } 206 | -------------------------------------------------------------------------------- /stat_flags.h: -------------------------------------------------------------------------------- 1 | /* $NetBSD: stat_flags.h,v 1.1 2003/09/05 18:39:00 jlam Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 1991, 1993 5 | * The Regents of the University of California. All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. Neither the name of the University nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 | * SUCH DAMAGE. 30 | * 31 | * @(#)extern.h 8.1 (Berkeley) 5/31/93 32 | */ 33 | 34 | char *flags_to_string(u_long, const char *); 35 | int string_to_flags(char **, u_long *, u_long *); 36 | -------------------------------------------------------------------------------- /verify.c: -------------------------------------------------------------------------------- 1 | /* $NetBSD: verify.c,v 1.6 2010/03/21 16:30:17 joerg Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 1990, 1993 5 | * The Regents of the University of California. All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. Neither the name of the University nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 | * SUCH DAMAGE. 30 | */ 31 | 32 | #if HAVE_CONFIG_H 33 | #include "config.h" 34 | #endif 35 | #if HAVE_NBTOOL_CONFIG_H 36 | #include "nbtool_config.h" 37 | #endif 38 | 39 | #include 40 | #if HAVE_SYS_CDEFS_H 41 | #include 42 | #endif 43 | #if defined(__RCSID) && !defined(lint) 44 | #if 0 45 | static char sccsid[] = "@(#)verify.c 8.1 (Berkeley) 6/6/93"; 46 | #else 47 | __RCSID("$NetBSD: verify.c,v 1.6 2010/03/21 16:30:17 joerg Exp $"); 48 | #endif 49 | #endif /* not lint */ 50 | 51 | #if HAVE_SYS_PARAM_H 52 | #include 53 | #endif 54 | #if HAVE_SYS_STAT_H 55 | #include 56 | #endif 57 | 58 | #if ! HAVE_NBTOOL_CONFIG_H 59 | #if HAVE_DIRENT_H 60 | #include 61 | #endif 62 | #endif 63 | 64 | #if HAVE_ERRNO_H 65 | #include 66 | #endif 67 | #if HAVE_FNMATCH_H 68 | #include 69 | #endif 70 | #if HAVE_STDIO_H 71 | #include 72 | #endif 73 | #if HAVE_STRING_H 74 | #include 75 | #endif 76 | #if HAVE_UNISTD_H 77 | #include 78 | #endif 79 | 80 | #include "extern.h" 81 | 82 | static NODE *root; 83 | static char path[MAXPATHLEN]; 84 | 85 | static void miss(NODE *, char *); 86 | static int vwalk(void); 87 | 88 | int 89 | verify(void) 90 | { 91 | int rval; 92 | 93 | root = spec(stdin); 94 | rval = vwalk(); 95 | miss(root, path); 96 | return (rval); 97 | } 98 | 99 | static int 100 | vwalk(void) 101 | { 102 | FTS *t; 103 | FTSENT *p; 104 | NODE *ep, *level; 105 | int specdepth, rval; 106 | char *argv[2]; 107 | char dot[] = "."; 108 | argv[0] = dot; 109 | argv[1] = NULL; 110 | 111 | if ((t = fts_open(argv, ftsoptions, NULL)) == NULL) 112 | mtree_err("fts_open: %s", strerror(errno)); 113 | level = root; 114 | specdepth = rval = 0; 115 | while ((p = fts_read(t)) != NULL) { 116 | if (check_excludes(p->fts_name, p->fts_path)) { 117 | fts_set(t, p, FTS_SKIP); 118 | continue; 119 | } 120 | switch(p->fts_info) { 121 | case FTS_D: 122 | case FTS_SL: 123 | break; 124 | case FTS_DP: 125 | if (specdepth > p->fts_level) { 126 | for (level = level->parent; level->prev; 127 | level = level->prev) 128 | continue; 129 | --specdepth; 130 | } 131 | continue; 132 | case FTS_DNR: 133 | case FTS_ERR: 134 | case FTS_NS: 135 | warnx("%s: %s", RP(p), strerror(p->fts_errno)); 136 | continue; 137 | default: 138 | if (dflag) 139 | continue; 140 | } 141 | 142 | if (specdepth != p->fts_level) 143 | goto extra; 144 | for (ep = level; ep; ep = ep->next) 145 | if ((gflag && (ep->flags & F_MAGIC) != 0 && 146 | !fnmatch(ep->name, p->fts_name, FNM_PATHNAME)) || 147 | !strcmp(ep->name, p->fts_name)) { 148 | ep->flags |= F_VISIT; 149 | if (compare(ep, p)) 150 | rval = MISMATCHEXIT; 151 | if (!(ep->flags & F_IGN) && 152 | ep->type == F_DIR && 153 | p->fts_info == FTS_D) { 154 | if (ep->child) { 155 | level = ep->child; 156 | ++specdepth; 157 | } 158 | } else 159 | fts_set(t, p, FTS_SKIP); 160 | break; 161 | } 162 | 163 | if (ep) 164 | continue; 165 | extra: 166 | if (!eflag) { 167 | printf("extra: %s", RP(p)); 168 | if (rflag) { 169 | if ((S_ISDIR(p->fts_statp->st_mode) 170 | ? rmdir : unlink)(p->fts_accpath)) { 171 | printf(", not removed: %s", 172 | strerror(errno)); 173 | } else 174 | printf(", removed"); 175 | } 176 | putchar('\n'); 177 | } 178 | fts_set(t, p, FTS_SKIP); 179 | } 180 | fts_close(t); 181 | if (sflag) 182 | warnx("%s checksum: %u", fullpath, crc_total); 183 | return (rval); 184 | } 185 | 186 | static void 187 | miss(NODE *p, char *tail) 188 | { 189 | int create; 190 | char *tp; 191 | const char *type; 192 | #if HAVE_STRUCT_STAT_ST_FLAGS 193 | uint32_t flags; 194 | #endif 195 | 196 | for (; p; p = p->next) { 197 | if (p->flags & F_OPT && !(p->flags & F_VISIT)) 198 | continue; 199 | if (p->type != F_DIR && (dflag || p->flags & F_VISIT)) 200 | continue; 201 | strcpy(tail, p->name); 202 | if (!(p->flags & F_VISIT)) 203 | printf("missing: %s", path); 204 | switch (p->type) { 205 | case F_BLOCK: 206 | case F_CHAR: 207 | type = "device"; 208 | break; 209 | case F_DIR: 210 | type = "directory"; 211 | break; 212 | case F_LINK: 213 | type = "symlink"; 214 | break; 215 | default: 216 | putchar('\n'); 217 | continue; 218 | } 219 | 220 | create = 0; 221 | if (!(p->flags & F_VISIT) && uflag) { 222 | if (mtree_Wflag || p->type == F_LINK) 223 | goto createit; 224 | if (!(p->flags & (F_UID | F_UNAME))) 225 | printf( 226 | " (%s not created: user not specified)", type); 227 | else if (!(p->flags & (F_GID | F_GNAME))) 228 | printf( 229 | " (%s not created: group not specified)", type); 230 | else if (!(p->flags & F_MODE)) 231 | printf( 232 | " (%s not created: mode not specified)", type); 233 | else 234 | createit: 235 | switch (p->type) { 236 | case F_BLOCK: 237 | case F_CHAR: 238 | if (mtree_Wflag) 239 | continue; 240 | if (!(p->flags & F_DEV)) 241 | printf( 242 | " (%s not created: device not specified)", 243 | type); 244 | else if (mknod(path, 245 | p->st_mode | nodetoino(p->type), 246 | p->st_rdev) == -1) 247 | printf(" (%s not created: %s)\n", 248 | type, strerror(errno)); 249 | else 250 | create = 1; 251 | break; 252 | case F_LINK: 253 | if (!(p->flags & F_SLINK)) 254 | printf( 255 | " (%s not created: link not specified)\n", 256 | type); 257 | else if (symlink(p->slink, path)) 258 | printf( 259 | " (%s not created: %s)\n", 260 | type, strerror(errno)); 261 | else 262 | create = 1; 263 | break; 264 | case F_DIR: 265 | if (mkdir(path, S_IRWXU|S_IRWXG|S_IRWXO)) 266 | printf(" (not created: %s)", 267 | strerror(errno)); 268 | else 269 | create = 1; 270 | break; 271 | default: 272 | mtree_err("can't create create %s", 273 | nodetype(p->type)); 274 | } 275 | } 276 | if (create) 277 | printf(" (created)"); 278 | if (p->type == F_DIR) { 279 | if (!(p->flags & F_VISIT)) 280 | putchar('\n'); 281 | for (tp = tail; *tp; ++tp) 282 | continue; 283 | *tp = '/'; 284 | miss(p->child, tp + 1); 285 | *tp = '\0'; 286 | } else 287 | putchar('\n'); 288 | 289 | if (!create || mtree_Wflag) 290 | continue; 291 | if ((p->flags & (F_UID | F_UNAME)) && 292 | (p->flags & (F_GID | F_GNAME)) && 293 | (lchown(path, p->st_uid, p->st_gid))) { 294 | printf("%s: user/group/mode not modified: %s\n", 295 | path, strerror(errno)); 296 | printf("%s: warning: file mode %snot set\n", path, 297 | (p->flags & F_FLAGS) ? "and file flags " : ""); 298 | continue; 299 | } 300 | if (p->flags & F_MODE) { 301 | if (lchmod(path, p->st_mode)) 302 | printf("%s: permissions not set: %s\n", 303 | path, strerror(errno)); 304 | } 305 | #if HAVE_STRUCT_STAT_ST_FLAGS 306 | if ((p->flags & F_FLAGS) && p->st_flags) { 307 | if (iflag) 308 | flags = p->st_flags; 309 | else 310 | flags = p->st_flags & ~SP_FLGS; 311 | if (lchflags(path, flags)) 312 | printf("%s: file flags not set: %s\n", 313 | path, strerror(errno)); 314 | } 315 | #endif /* HAVE_STRUCT_STAT_ST_FLAGS */ 316 | } 317 | } 318 | --------------------------------------------------------------------------------