Remove fmtree(8)
fmtree(8) deprecation was announced on February 12, 2021, and no longer built by default as of that date. The deprecation notice was merged back to stable/12 and stable/13 + releng/13.0. Continue with the plan by finishing the removal. Relnotes: yes
This commit is contained in:
parent
ca4e1ea19f
commit
e4d63c5d5f
@ -36,6 +36,10 @@
|
||||
# xargs -n1 | sort | uniq -d;
|
||||
# done
|
||||
|
||||
# 20210302: fmtree removed
|
||||
OLD_FILES+=usr/sbin/fmtree
|
||||
OLD_FILES+=usr/share/man/man8/fmtree.8.gz
|
||||
|
||||
# 20210201: bump shared libraries which link against ncurses
|
||||
OLD_LIBS+=lib/libedit.so.7
|
||||
OLD_LIBS+=usr/lib/libdialog.so.8
|
||||
|
@ -201,7 +201,6 @@ __DEFAULT_NO_OPTIONS = \
|
||||
CLANG_FORMAT \
|
||||
DTRACE_TESTS \
|
||||
EXPERIMENTAL \
|
||||
FMTREE \
|
||||
HESIOD \
|
||||
LIBSOFT \
|
||||
LOADER_FIREWIRE \
|
||||
|
@ -1684,11 +1684,6 @@ OLD_FILES+=usr/sbin/uefisign
|
||||
OLD_FILES+=usr/share/examples/uefisign/uefikeys
|
||||
.endif
|
||||
|
||||
.if ${MK_FMTREE} == no
|
||||
OLD_FILES+=usr/sbin/fmtree
|
||||
OLD_FILES+=usr/share/man/man8/fmtree.8.gz
|
||||
.endif
|
||||
|
||||
.if ${MK_FTP} == no
|
||||
OLD_FILES+=etc/ftpusers
|
||||
OLD_FILES+=etc/newsyslog.conf.d/ftp.conf
|
||||
|
@ -1,3 +0,0 @@
|
||||
.\" $FreeBSD$
|
||||
Set to not build and install
|
||||
.Pa /usr/sbin/fmtree .
|
@ -1,5 +0,0 @@
|
||||
.\" $FreeBSD$
|
||||
Set to build and install
|
||||
.Pa /usr/sbin/fmtree .
|
||||
This option is deprecated, and will be gone in
|
||||
.Fx 14.0 .
|
@ -137,7 +137,6 @@ SUBDIR.${MK_FLOPPY}+= fdcontrol
|
||||
SUBDIR.${MK_FLOPPY}+= fdformat
|
||||
SUBDIR.${MK_FLOPPY}+= fdread
|
||||
SUBDIR.${MK_FLOPPY}+= fdwrite
|
||||
SUBDIR.${MK_FMTREE}+= fmtree
|
||||
SUBDIR.${MK_FREEBSD_UPDATE}+= freebsd-update
|
||||
SUBDIR.${MK_GSSAPI}+= gssd
|
||||
SUBDIR.${MK_GPIO}+= gpioctl
|
||||
|
@ -1,21 +0,0 @@
|
||||
# From: @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
# $FreeBSD$
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
.PATH: ${SRCTOP}/usr.bin/cksum
|
||||
|
||||
PROG= fmtree
|
||||
MAN= fmtree.8
|
||||
SRCS= compare.c crc.c create.c excludes.c misc.c mtree.c spec.c verify.c
|
||||
SRCS+= specspec.c
|
||||
|
||||
CFLAGS+= -DWITH_MD5 -DWITH_SHA1 -DWITH_RMD160 -DWITH_SHA256
|
||||
LIBADD= md
|
||||
|
||||
CLEANFILES+= fmtree.8
|
||||
|
||||
fmtree.8: mtree.8
|
||||
${CP} ${.ALLSRC} ${.TARGET}
|
||||
|
||||
.include <bsd.prog.mk>
|
@ -1,18 +0,0 @@
|
||||
# $FreeBSD$
|
||||
# Autogenerated - do NOT edit!
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
lib/libc \
|
||||
lib/libcompiler_rt \
|
||||
lib/libmd \
|
||||
|
||||
|
||||
.include <dirdeps.mk>
|
||||
|
||||
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
|
||||
# local dependencies - needed for -jN in clean tree
|
||||
.endif
|
@ -1,389 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)compare.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <fts.h>
|
||||
#ifdef WITH_MD5
|
||||
#include <md5.h>
|
||||
#endif
|
||||
#ifdef WITH_RMD160
|
||||
#include <ripemd.h>
|
||||
#endif
|
||||
#ifdef WITH_SHA1
|
||||
#include <sha.h>
|
||||
#endif
|
||||
#ifdef WITH_SHA256
|
||||
#include <sha256.h>
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <vis.h>
|
||||
|
||||
#include "mtree.h"
|
||||
#include "extern.h"
|
||||
|
||||
#define INDENTNAMELEN 8
|
||||
#define LABEL \
|
||||
if (!label++) { \
|
||||
len = printf("%s changed\n", RP(p)); \
|
||||
tab = "\t"; \
|
||||
}
|
||||
|
||||
int
|
||||
compare(char *name __unused, NODE *s, FTSENT *p)
|
||||
{
|
||||
struct timeval tv[2];
|
||||
uint32_t val;
|
||||
int fd, label;
|
||||
off_t len;
|
||||
char *cp;
|
||||
const char *tab = "";
|
||||
char *fflags;
|
||||
|
||||
label = 0;
|
||||
switch(s->type) {
|
||||
case F_BLOCK:
|
||||
if (!S_ISBLK(p->fts_statp->st_mode))
|
||||
goto typeerr;
|
||||
break;
|
||||
case F_CHAR:
|
||||
if (!S_ISCHR(p->fts_statp->st_mode))
|
||||
goto typeerr;
|
||||
break;
|
||||
case F_DIR:
|
||||
if (!S_ISDIR(p->fts_statp->st_mode))
|
||||
goto typeerr;
|
||||
break;
|
||||
case F_FIFO:
|
||||
if (!S_ISFIFO(p->fts_statp->st_mode))
|
||||
goto typeerr;
|
||||
break;
|
||||
case F_FILE:
|
||||
if (!S_ISREG(p->fts_statp->st_mode))
|
||||
goto typeerr;
|
||||
break;
|
||||
case F_LINK:
|
||||
if (!S_ISLNK(p->fts_statp->st_mode))
|
||||
goto typeerr;
|
||||
break;
|
||||
case F_SOCK:
|
||||
if (!S_ISSOCK(p->fts_statp->st_mode)) {
|
||||
typeerr: LABEL;
|
||||
(void)printf("\ttype expected %s found %s\n",
|
||||
ftype(s->type), inotype(p->fts_statp->st_mode));
|
||||
return (label);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Set the uid/gid first, then set the mode. */
|
||||
if (s->flags & (F_UID | F_UNAME) && s->st_uid != p->fts_statp->st_uid) {
|
||||
LABEL;
|
||||
(void)printf("%suser expected %lu found %lu",
|
||||
tab, (u_long)s->st_uid, (u_long)p->fts_statp->st_uid);
|
||||
if (uflag)
|
||||
if (chown(p->fts_accpath, s->st_uid, -1))
|
||||
(void)printf(" not modified: %s\n",
|
||||
strerror(errno));
|
||||
else
|
||||
(void)printf(" modified\n");
|
||||
else
|
||||
(void)printf("\n");
|
||||
tab = "\t";
|
||||
}
|
||||
if (s->flags & (F_GID | F_GNAME) && s->st_gid != p->fts_statp->st_gid) {
|
||||
LABEL;
|
||||
(void)printf("%sgid expected %lu found %lu",
|
||||
tab, (u_long)s->st_gid, (u_long)p->fts_statp->st_gid);
|
||||
if (uflag)
|
||||
if (chown(p->fts_accpath, -1, s->st_gid))
|
||||
(void)printf(" not modified: %s\n",
|
||||
strerror(errno));
|
||||
else
|
||||
(void)printf(" modified\n");
|
||||
else
|
||||
(void)printf("\n");
|
||||
tab = "\t";
|
||||
}
|
||||
if (s->flags & F_MODE &&
|
||||
!S_ISLNK(p->fts_statp->st_mode) &&
|
||||
s->st_mode != (p->fts_statp->st_mode & MBITS)) {
|
||||
LABEL;
|
||||
(void)printf("%spermissions expected %#o found %#o",
|
||||
tab, s->st_mode, p->fts_statp->st_mode & MBITS);
|
||||
if (uflag)
|
||||
if (chmod(p->fts_accpath, s->st_mode))
|
||||
(void)printf(" not modified: %s\n",
|
||||
strerror(errno));
|
||||
else
|
||||
(void)printf(" modified\n");
|
||||
else
|
||||
(void)printf("\n");
|
||||
tab = "\t";
|
||||
}
|
||||
if (s->flags & F_NLINK && s->type != F_DIR &&
|
||||
s->st_nlink != p->fts_statp->st_nlink) {
|
||||
LABEL;
|
||||
(void)printf("%slink_count expected %ju found %ju\n",
|
||||
tab, (uintmax_t)s->st_nlink,
|
||||
(uintmax_t)p->fts_statp->st_nlink);
|
||||
tab = "\t";
|
||||
}
|
||||
if (s->flags & F_SIZE && s->st_size != p->fts_statp->st_size &&
|
||||
!S_ISDIR(p->fts_statp->st_mode)) {
|
||||
LABEL;
|
||||
(void)printf("%ssize expected %jd found %jd\n", tab,
|
||||
(intmax_t)s->st_size, (intmax_t)p->fts_statp->st_size);
|
||||
tab = "\t";
|
||||
}
|
||||
/*
|
||||
* XXX
|
||||
* Catches nano-second differences, but doesn't display them.
|
||||
*/
|
||||
if ((s->flags & F_TIME) &&
|
||||
((s->st_mtimespec.tv_sec != p->fts_statp->st_mtim.tv_sec) ||
|
||||
(s->st_mtimespec.tv_nsec != p->fts_statp->st_mtim.tv_nsec))) {
|
||||
LABEL;
|
||||
(void)printf("%smodification time expected %.24s ",
|
||||
tab, ctime(&s->st_mtimespec.tv_sec));
|
||||
(void)printf("found %.24s",
|
||||
ctime(&p->fts_statp->st_mtim.tv_sec));
|
||||
if (uflag) {
|
||||
tv[0].tv_sec = s->st_mtimespec.tv_sec;
|
||||
tv[0].tv_usec = s->st_mtimespec.tv_nsec / 1000;
|
||||
tv[1] = tv[0];
|
||||
if (utimes(p->fts_accpath, tv))
|
||||
(void)printf(" not modified: %s\n",
|
||||
strerror(errno));
|
||||
else
|
||||
(void)printf(" modified\n");
|
||||
} else
|
||||
(void)printf("\n");
|
||||
tab = "\t";
|
||||
}
|
||||
if (s->flags & F_CKSUM) {
|
||||
if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0) {
|
||||
LABEL;
|
||||
(void)printf("%scksum: %s: %s\n",
|
||||
tab, p->fts_accpath, strerror(errno));
|
||||
tab = "\t";
|
||||
} else if (crc(fd, &val, &len)) {
|
||||
(void)close(fd);
|
||||
LABEL;
|
||||
(void)printf("%scksum: %s: %s\n",
|
||||
tab, p->fts_accpath, strerror(errno));
|
||||
tab = "\t";
|
||||
} else {
|
||||
(void)close(fd);
|
||||
if (s->cksum != val) {
|
||||
LABEL;
|
||||
(void)printf("%scksum expected %lu found %lu\n",
|
||||
tab, s->cksum, (unsigned long)val);
|
||||
tab = "\t";
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((s->flags & F_FLAGS) && s->st_flags != p->fts_statp->st_flags) {
|
||||
LABEL;
|
||||
fflags = flags_to_string(s->st_flags);
|
||||
(void)printf("%sflags expected \"%s\"", tab, fflags);
|
||||
free(fflags);
|
||||
|
||||
fflags = flags_to_string(p->fts_statp->st_flags);
|
||||
(void)printf(" found \"%s\"", fflags);
|
||||
free(fflags);
|
||||
|
||||
if (uflag)
|
||||
if (chflags(p->fts_accpath, s->st_flags))
|
||||
(void)printf(" not modified: %s\n",
|
||||
strerror(errno));
|
||||
else
|
||||
(void)printf(" modified\n");
|
||||
else
|
||||
(void)printf("\n");
|
||||
tab = "\t";
|
||||
}
|
||||
#ifdef WITH_MD5
|
||||
if (s->flags & F_MD5) {
|
||||
char *new_digest, buf[33];
|
||||
|
||||
new_digest = MD5File(p->fts_accpath, buf);
|
||||
if (!new_digest) {
|
||||
LABEL;
|
||||
printf("%sMD5: %s: %s\n", tab, p->fts_accpath,
|
||||
strerror(errno));
|
||||
tab = "\t";
|
||||
} else if (strcmp(new_digest, s->md5digest)) {
|
||||
LABEL;
|
||||
printf("%sMD5 expected %s found %s\n", tab, s->md5digest,
|
||||
new_digest);
|
||||
tab = "\t";
|
||||
}
|
||||
}
|
||||
#endif /* MD5 */
|
||||
#ifdef WITH_SHA1
|
||||
if (s->flags & F_SHA1) {
|
||||
char *new_digest, buf[41];
|
||||
|
||||
new_digest = SHA1_File(p->fts_accpath, buf);
|
||||
if (!new_digest) {
|
||||
LABEL;
|
||||
printf("%sSHA-1: %s: %s\n", tab, p->fts_accpath,
|
||||
strerror(errno));
|
||||
tab = "\t";
|
||||
} else if (strcmp(new_digest, s->sha1digest)) {
|
||||
LABEL;
|
||||
printf("%sSHA-1 expected %s found %s\n",
|
||||
tab, s->sha1digest, new_digest);
|
||||
tab = "\t";
|
||||
}
|
||||
}
|
||||
#endif /* SHA1 */
|
||||
#ifdef WITH_RMD160
|
||||
if (s->flags & F_RMD160) {
|
||||
char *new_digest, buf[41];
|
||||
|
||||
new_digest = RIPEMD160_File(p->fts_accpath, buf);
|
||||
if (!new_digest) {
|
||||
LABEL;
|
||||
printf("%sRIPEMD160: %s: %s\n", tab,
|
||||
p->fts_accpath, strerror(errno));
|
||||
tab = "\t";
|
||||
} else if (strcmp(new_digest, s->rmd160digest)) {
|
||||
LABEL;
|
||||
printf("%sRIPEMD160 expected %s found %s\n",
|
||||
tab, s->rmd160digest, new_digest);
|
||||
tab = "\t";
|
||||
}
|
||||
}
|
||||
#endif /* RMD160 */
|
||||
#ifdef WITH_SHA256
|
||||
if (s->flags & F_SHA256) {
|
||||
char *new_digest, buf[65];
|
||||
|
||||
new_digest = SHA256_File(p->fts_accpath, buf);
|
||||
if (!new_digest) {
|
||||
LABEL;
|
||||
printf("%sSHA-256: %s: %s\n", tab, p->fts_accpath,
|
||||
strerror(errno));
|
||||
tab = "\t";
|
||||
} else if (strcmp(new_digest, s->sha256digest)) {
|
||||
LABEL;
|
||||
printf("%sSHA-256 expected %s found %s\n",
|
||||
tab, s->sha256digest, new_digest);
|
||||
tab = "\t";
|
||||
}
|
||||
}
|
||||
#endif /* SHA256 */
|
||||
|
||||
if (s->flags & F_SLINK &&
|
||||
strcmp(cp = rlink(p->fts_accpath), s->slink)) {
|
||||
LABEL;
|
||||
(void)printf("%slink_ref expected %s found %s\n",
|
||||
tab, s->slink, cp);
|
||||
}
|
||||
return (label);
|
||||
}
|
||||
|
||||
const char *
|
||||
inotype(u_int type)
|
||||
{
|
||||
switch(type & S_IFMT) {
|
||||
case S_IFBLK:
|
||||
return ("block");
|
||||
case S_IFCHR:
|
||||
return ("char");
|
||||
case S_IFDIR:
|
||||
return ("dir");
|
||||
case S_IFIFO:
|
||||
return ("fifo");
|
||||
case S_IFREG:
|
||||
return ("file");
|
||||
case S_IFLNK:
|
||||
return ("link");
|
||||
case S_IFSOCK:
|
||||
return ("socket");
|
||||
default:
|
||||
return ("unknown");
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
const char *
|
||||
ftype(u_int type)
|
||||
{
|
||||
switch(type) {
|
||||
case F_BLOCK:
|
||||
return ("block");
|
||||
case F_CHAR:
|
||||
return ("char");
|
||||
case F_DIR:
|
||||
return ("dir");
|
||||
case F_FIFO:
|
||||
return ("fifo");
|
||||
case F_FILE:
|
||||
return ("file");
|
||||
case F_LINK:
|
||||
return ("link");
|
||||
case F_SOCK:
|
||||
return ("socket");
|
||||
default:
|
||||
return ("unknown");
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
char *
|
||||
rlink(char *name)
|
||||
{
|
||||
static char lbuf[MAXPATHLEN * 4];
|
||||
int len;
|
||||
char tbuf[MAXPATHLEN];
|
||||
|
||||
if ((len = readlink(name, tbuf, sizeof(tbuf) - 1)) == -1)
|
||||
err(1, "line %d: %s", lineno, name);
|
||||
tbuf[len] = '\0';
|
||||
strvis(lbuf, tbuf, VIS_WHITE | VIS_OCTAL);
|
||||
return (lbuf);
|
||||
}
|
@ -1,431 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)create.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <fts.h>
|
||||
#include <grp.h>
|
||||
#ifdef MD5
|
||||
#include <md5.h>
|
||||
#endif
|
||||
#ifdef SHA1
|
||||
#include <sha.h>
|
||||
#endif
|
||||
#ifdef RMD160
|
||||
#include <ripemd.h>
|
||||
#endif
|
||||
#ifdef SHA256
|
||||
#include <sha256.h>
|
||||
#endif
|
||||
#include <pwd.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <vis.h>
|
||||
#include "mtree.h"
|
||||
#include "extern.h"
|
||||
|
||||
#define INDENTNAMELEN 15
|
||||
#define MAXLINELEN 80
|
||||
|
||||
static gid_t gid;
|
||||
static uid_t uid;
|
||||
static mode_t mode;
|
||||
static u_long flags = 0xffffffff;
|
||||
|
||||
static int dsort(const FTSENT * const *, const FTSENT * const *);
|
||||
static void output(int, int *, const char *, ...) __printflike(3, 4);
|
||||
static int statd(FTS *, FTSENT *, uid_t *, gid_t *, mode_t *, u_long *);
|
||||
static void statf(int, FTSENT *);
|
||||
|
||||
void
|
||||
cwalk(void)
|
||||
{
|
||||
FTS *t;
|
||||
FTSENT *p;
|
||||
time_t cl;
|
||||
char *argv[2], host[MAXHOSTNAMELEN];
|
||||
char dot[] = ".";
|
||||
int indent = 0;
|
||||
|
||||
if (!nflag) {
|
||||
(void)time(&cl);
|
||||
(void)gethostname(host, sizeof(host));
|
||||
(void)printf(
|
||||
"#\t user: %s\n#\tmachine: %s\n",
|
||||
getlogin(), host);
|
||||
(void)printf(
|
||||
"#\t tree: %s\n#\t date: %s",
|
||||
fullpath, ctime(&cl));
|
||||
}
|
||||
|
||||
argv[0] = dot;
|
||||
argv[1] = NULL;
|
||||
if ((t = fts_open(argv, ftsoptions, dsort)) == NULL)
|
||||
err(1, "fts_open()");
|
||||
while (errno = 0, (p = fts_read(t))) {
|
||||
if (iflag)
|
||||
indent = p->fts_level * 4;
|
||||
if (check_excludes(p->fts_name, p->fts_path)) {
|
||||
fts_set(t, p, FTS_SKIP);
|
||||
continue;
|
||||
}
|
||||
switch(p->fts_info) {
|
||||
case FTS_D:
|
||||
if (!dflag)
|
||||
(void)printf("\n");
|
||||
if (!nflag)
|
||||
(void)printf("# %s\n", p->fts_path);
|
||||
statd(t, p, &uid, &gid, &mode, &flags);
|
||||
statf(indent, p);
|
||||
break;
|
||||
case FTS_DP:
|
||||
if (!nflag && (p->fts_level > 0))
|
||||
(void)printf("%*s# %s\n", indent, "", p->fts_path);
|
||||
(void)printf("%*s..\n", indent, "");
|
||||
if (!dflag)
|
||||
(void)printf("\n");
|
||||
break;
|
||||
case FTS_DNR:
|
||||
case FTS_ERR:
|
||||
case FTS_NS:
|
||||
warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
|
||||
break;
|
||||
default:
|
||||
if (!dflag)
|
||||
statf(indent, p);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
if (errno != 0)
|
||||
err(1, "fts_read()");
|
||||
(void)fts_close(t);
|
||||
if (sflag && keys & F_CKSUM)
|
||||
warnx("%s checksum: %lu", fullpath, (unsigned long)crc_total);
|
||||
}
|
||||
|
||||
static void
|
||||
statf(int indent, FTSENT *p)
|
||||
{
|
||||
struct group *gr;
|
||||
struct passwd *pw;
|
||||
uint32_t val;
|
||||
off_t len;
|
||||
int fd, offset;
|
||||
char *fflags;
|
||||
char *escaped_name;
|
||||
|
||||
escaped_name = calloc(1, p->fts_namelen * 4 + 1);
|
||||
if (escaped_name == NULL)
|
||||
errx(1, "statf(): calloc() failed");
|
||||
strvis(escaped_name, p->fts_name, VIS_WHITE | VIS_OCTAL | VIS_GLOB);
|
||||
|
||||
if (iflag || S_ISDIR(p->fts_statp->st_mode))
|
||||
offset = printf("%*s%s", indent, "", escaped_name);
|
||||
else
|
||||
offset = printf("%*s %s", indent, "", escaped_name);
|
||||
|
||||
free(escaped_name);
|
||||
|
||||
if (offset > (INDENTNAMELEN + indent))
|
||||
offset = MAXLINELEN;
|
||||
else
|
||||
offset += printf("%*s", (INDENTNAMELEN + indent) - offset, "");
|
||||
|
||||
if (!S_ISREG(p->fts_statp->st_mode) && !dflag)
|
||||
output(indent, &offset, "type=%s", inotype(p->fts_statp->st_mode));
|
||||
if (p->fts_statp->st_uid != uid) {
|
||||
if (keys & F_UNAME) {
|
||||
pw = getpwuid(p->fts_statp->st_uid);
|
||||
if (pw != NULL)
|
||||
output(indent, &offset, "uname=%s", pw->pw_name);
|
||||
else if (wflag)
|
||||
warnx("Could not get uname for uid=%u",
|
||||
p->fts_statp->st_uid);
|
||||
else
|
||||
errx(1,
|
||||
"Could not get uname for uid=%u",
|
||||
p->fts_statp->st_uid);
|
||||
}
|
||||
if (keys & F_UID)
|
||||
output(indent, &offset, "uid=%u", p->fts_statp->st_uid);
|
||||
}
|
||||
if (p->fts_statp->st_gid != gid) {
|
||||
if (keys & F_GNAME) {
|
||||
gr = getgrgid(p->fts_statp->st_gid);
|
||||
if (gr != NULL)
|
||||
output(indent, &offset, "gname=%s", gr->gr_name);
|
||||
else if (wflag)
|
||||
warnx("Could not get gname for gid=%u",
|
||||
p->fts_statp->st_gid);
|
||||
else
|
||||
errx(1,
|
||||
"Could not get gname for gid=%u",
|
||||
p->fts_statp->st_gid);
|
||||
}
|
||||
if (keys & F_GID)
|
||||
output(indent, &offset, "gid=%u", p->fts_statp->st_gid);
|
||||
}
|
||||
if (keys & F_MODE && (p->fts_statp->st_mode & MBITS) != mode)
|
||||
output(indent, &offset, "mode=%#o", p->fts_statp->st_mode & MBITS);
|
||||
if (keys & F_NLINK && p->fts_statp->st_nlink != 1)
|
||||
output(indent, &offset, "nlink=%ju",
|
||||
(uintmax_t)p->fts_statp->st_nlink);
|
||||
if (keys & F_SIZE && S_ISREG(p->fts_statp->st_mode))
|
||||
output(indent, &offset, "size=%jd",
|
||||
(intmax_t)p->fts_statp->st_size);
|
||||
if (keys & F_TIME)
|
||||
output(indent, &offset, "time=%ld.%09ld",
|
||||
(long)p->fts_statp->st_mtim.tv_sec,
|
||||
p->fts_statp->st_mtim.tv_nsec);
|
||||
if (keys & F_CKSUM && S_ISREG(p->fts_statp->st_mode)) {
|
||||
if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0 ||
|
||||
crc(fd, &val, &len))
|
||||
err(1, "%s", p->fts_accpath);
|
||||
(void)close(fd);
|
||||
output(indent, &offset, "cksum=%lu", (unsigned long)val);
|
||||
}
|
||||
#ifdef MD5
|
||||
if (keys & F_MD5 && S_ISREG(p->fts_statp->st_mode)) {
|
||||
char *digest, buf[33];
|
||||
|
||||
digest = MD5File(p->fts_accpath, buf);
|
||||
if (!digest)
|
||||
err(1, "%s", p->fts_accpath);
|
||||
output(indent, &offset, "md5digest=%s", digest);
|
||||
}
|
||||
#endif /* MD5 */
|
||||
#ifdef SHA1
|
||||
if (keys & F_SHA1 && S_ISREG(p->fts_statp->st_mode)) {
|
||||
char *digest, buf[41];
|
||||
|
||||
digest = SHA1_File(p->fts_accpath, buf);
|
||||
if (!digest)
|
||||
err(1, "%s", p->fts_accpath);
|
||||
output(indent, &offset, "sha1digest=%s", digest);
|
||||
}
|
||||
#endif /* SHA1 */
|
||||
#ifdef RMD160
|
||||
if (keys & F_RMD160 && S_ISREG(p->fts_statp->st_mode)) {
|
||||
char *digest, buf[41];
|
||||
|
||||
digest = RIPEMD160_File(p->fts_accpath, buf);
|
||||
if (!digest)
|
||||
err(1, "%s", p->fts_accpath);
|
||||
output(indent, &offset, "ripemd160digest=%s", digest);
|
||||
}
|
||||
#endif /* RMD160 */
|
||||
#ifdef SHA256
|
||||
if (keys & F_SHA256 && S_ISREG(p->fts_statp->st_mode)) {
|
||||
char *digest, buf[65];
|
||||
|
||||
digest = SHA256_File(p->fts_accpath, buf);
|
||||
if (!digest)
|
||||
err(1, "%s", p->fts_accpath);
|
||||
output(indent, &offset, "sha256digest=%s", digest);
|
||||
}
|
||||
#endif /* SHA256 */
|
||||
if (keys & F_SLINK &&
|
||||
(p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE))
|
||||
output(indent, &offset, "link=%s", rlink(p->fts_accpath));
|
||||
if (keys & F_FLAGS && p->fts_statp->st_flags != flags) {
|
||||
fflags = flags_to_string(p->fts_statp->st_flags);
|
||||
output(indent, &offset, "flags=%s", fflags);
|
||||
free(fflags);
|
||||
}
|
||||
(void)putchar('\n');
|
||||
}
|
||||
|
||||
#define MAXGID 5000
|
||||
#define MAXUID 5000
|
||||
#define MAXMODE MBITS + 1
|
||||
#define MAXFLAGS 256
|
||||
#define MAXS 16
|
||||
|
||||
static int
|
||||
statd(FTS *t, FTSENT *parent, uid_t *puid, gid_t *pgid, mode_t *pmode, u_long *pflags)
|
||||
{
|
||||
FTSENT *p;
|
||||
gid_t sgid;
|
||||
uid_t suid;
|
||||
mode_t smode;
|
||||
u_long sflags;
|
||||
struct group *gr;
|
||||
struct passwd *pw;
|
||||
gid_t savegid = *pgid;
|
||||
uid_t saveuid = *puid;
|
||||
mode_t savemode = *pmode;
|
||||
u_long saveflags = *pflags;
|
||||
u_short maxgid, maxuid, maxmode, maxflags;
|
||||
u_short g[MAXGID], u[MAXUID], m[MAXMODE], f[MAXFLAGS];
|
||||
char *fflags;
|
||||
static int first = 1;
|
||||
|
||||
if ((p = fts_children(t, 0)) == NULL) {
|
||||
if (errno)
|
||||
err(1, "%s", RP(parent));
|
||||
return (1);
|
||||
}
|
||||
|
||||
bzero(g, sizeof(g));
|
||||
bzero(u, sizeof(u));
|
||||
bzero(m, sizeof(m));
|
||||
bzero(f, sizeof(f));
|
||||
|
||||
maxuid = maxgid = maxmode = maxflags = 0;
|
||||
for (; p; p = p->fts_link) {
|
||||
if (!dflag || (dflag && S_ISDIR(p->fts_statp->st_mode))) {
|
||||
smode = p->fts_statp->st_mode & MBITS;
|
||||
if (smode < MAXMODE && ++m[smode] > maxmode) {
|
||||
savemode = smode;
|
||||
maxmode = m[smode];
|
||||
}
|
||||
sgid = p->fts_statp->st_gid;
|
||||
if (sgid < MAXGID && ++g[sgid] > maxgid) {
|
||||
savegid = sgid;
|
||||
maxgid = g[sgid];
|
||||
}
|
||||
suid = p->fts_statp->st_uid;
|
||||
if (suid < MAXUID && ++u[suid] > maxuid) {
|
||||
saveuid = suid;
|
||||
maxuid = u[suid];
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* note that the below will break when file flags
|
||||
* are extended beyond the first 4 bytes of each
|
||||
* half word of the flags
|
||||
*/
|
||||
#define FLAGS2IDX(f) ((f & 0xf) | ((f >> 12) & 0xf0))
|
||||
sflags = p->fts_statp->st_flags;
|
||||
if (FLAGS2IDX(sflags) < MAXFLAGS &&
|
||||
++f[FLAGS2IDX(sflags)] > maxflags) {
|
||||
saveflags = sflags;
|
||||
maxflags = f[FLAGS2IDX(sflags)];
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If the /set record is the same as the last one we do not need to output
|
||||
* a new one. So first we check to see if anything changed. Note that we
|
||||
* always output a /set record for the first directory.
|
||||
*/
|
||||
if ((((keys & F_UNAME) | (keys & F_UID)) && (*puid != saveuid)) ||
|
||||
(((keys & F_GNAME) | (keys & F_GID)) && (*pgid != savegid)) ||
|
||||
((keys & F_MODE) && (*pmode != savemode)) ||
|
||||
((keys & F_FLAGS) && (*pflags != saveflags)) ||
|
||||
(first)) {
|
||||
first = 0;
|
||||
if (dflag)
|
||||
(void)printf("/set type=dir");
|
||||
else
|
||||
(void)printf("/set type=file");
|
||||
if (keys & F_UNAME) {
|
||||
pw = getpwuid(saveuid);
|
||||
if (pw != NULL)
|
||||
(void)printf(" uname=%s", pw->pw_name);
|
||||
else if (wflag)
|
||||
warnx( "Could not get uname for uid=%u", saveuid);
|
||||
else
|
||||
errx(1, "Could not get uname for uid=%u", saveuid);
|
||||
}
|
||||
if (keys & F_UID)
|
||||
(void)printf(" uid=%lu", (u_long)saveuid);
|
||||
if (keys & F_GNAME) {
|
||||
gr = getgrgid(savegid);
|
||||
if (gr != NULL)
|
||||
(void)printf(" gname=%s", gr->gr_name);
|
||||
else if (wflag)
|
||||
warnx("Could not get gname for gid=%u", savegid);
|
||||
else
|
||||
errx(1, "Could not get gname for gid=%u", savegid);
|
||||
}
|
||||
if (keys & F_GID)
|
||||
(void)printf(" gid=%lu", (u_long)savegid);
|
||||
if (keys & F_MODE)
|
||||
(void)printf(" mode=%#o", savemode);
|
||||
if (keys & F_NLINK)
|
||||
(void)printf(" nlink=1");
|
||||
if (keys & F_FLAGS) {
|
||||
fflags = flags_to_string(saveflags);
|
||||
(void)printf(" flags=%s", fflags);
|
||||
free(fflags);
|
||||
}
|
||||
(void)printf("\n");
|
||||
*puid = saveuid;
|
||||
*pgid = savegid;
|
||||
*pmode = savemode;
|
||||
*pflags = saveflags;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
dsort(const FTSENT * const *a, const FTSENT * const *b)
|
||||
{
|
||||
if (S_ISDIR((*a)->fts_statp->st_mode)) {
|
||||
if (!S_ISDIR((*b)->fts_statp->st_mode))
|
||||
return (1);
|
||||
} else if (S_ISDIR((*b)->fts_statp->st_mode))
|
||||
return (-1);
|
||||
return (strcmp((*a)->fts_name, (*b)->fts_name));
|
||||
}
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
void
|
||||
output(int indent, int *offset, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[1024];
|
||||
va_start(ap, fmt);
|
||||
(void)vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (*offset + strlen(buf) > MAXLINELEN - 3) {
|
||||
(void)printf(" \\\n%*s", INDENTNAMELEN + indent, "");
|
||||
*offset = INDENTNAMELEN + indent;
|
||||
}
|
||||
*offset += printf(" %s", buf) + 1;
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000 Massachusetts Institute of Technology
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby
|
||||
* granted, provided that both the above copyright notice and this
|
||||
* permission notice appear in all copies, that both the above
|
||||
* copyright notice and this permission notice appear in all
|
||||
* supporting documentation, and that the name of M.I.T. not be used
|
||||
* in advertising or publicity pertaining to distribution of the
|
||||
* software without specific, written prior permission. M.I.T. makes
|
||||
* no representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied
|
||||
* warranty.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
|
||||
* ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
|
||||
* SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h> /* XXX for mtree.h */
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <fnmatch.h>
|
||||
#include <fts.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mtree.h" /* XXX for extern.h */
|
||||
#include "extern.h"
|
||||
|
||||
/*
|
||||
* We're assuming that there won't be a whole lot of excludes,
|
||||
* so it's OK to use a stupid algorithm.
|
||||
*/
|
||||
struct exclude {
|
||||
LIST_ENTRY(exclude) link;
|
||||
const char *glob;
|
||||
int pathname;
|
||||
};
|
||||
static LIST_HEAD(, exclude) excludes;
|
||||
|
||||
void
|
||||
init_excludes(void)
|
||||
{
|
||||
LIST_INIT(&excludes);
|
||||
}
|
||||
|
||||
void
|
||||
read_excludes_file(const char *name)
|
||||
{
|
||||
FILE *fp;
|
||||
char *line, *str;
|
||||
struct exclude *e;
|
||||
size_t len;
|
||||
|
||||
fp = fopen(name, "r");
|
||||
if (fp == NULL)
|
||||
err(1, "%s", name);
|
||||
|
||||
while ((line = fgetln(fp, &len)) != NULL) {
|
||||
if (line[len - 1] == '\n')
|
||||
len--;
|
||||
if (len == 0)
|
||||
continue;
|
||||
|
||||
str = malloc(len + 1);
|
||||
e = malloc(sizeof *e);
|
||||
if (str == NULL || e == NULL)
|
||||
errx(1, "memory allocation error");
|
||||
e->glob = str;
|
||||
memcpy(str, line, len);
|
||||
str[len] = '\0';
|
||||
if (strchr(str, '/'))
|
||||
e->pathname = 1;
|
||||
else
|
||||
e->pathname = 0;
|
||||
LIST_INSERT_HEAD(&excludes, e, link);
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
int
|
||||
check_excludes(const char *fname, const char *path)
|
||||
{
|
||||
struct exclude *e;
|
||||
|
||||
/* fnmatch(3) has a funny return value convention... */
|
||||
#define MATCH(g, n) (fnmatch((g), (n), FNM_PATHNAME) == 0)
|
||||
|
||||
LIST_FOREACH(e, &excludes, link) {
|
||||
if ((e->pathname && MATCH(e->glob, path))
|
||||
|| MATCH(e->glob, fname))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)extern.h 8.1 (Berkeley) 6/6/93
|
||||
* $FreeBSD$
|
||||
*/
|
||||
extern uint32_t crc_total;
|
||||
|
||||
#ifdef _FTS_H_
|
||||
int compare(char *, NODE *, FTSENT *);
|
||||
#endif
|
||||
int crc(int, uint32_t *, off_t *);
|
||||
void cwalk(void);
|
||||
char *flags_to_string(u_long);
|
||||
|
||||
const char *inotype(u_int);
|
||||
u_int parsekey(char *, int *);
|
||||
char *rlink(char *);
|
||||
NODE *mtree_readspec(FILE *fi);
|
||||
int mtree_verifyspec(FILE *fi);
|
||||
int mtree_specspec(FILE *fi, FILE *fj);
|
||||
|
||||
int check_excludes(const char *, const char *);
|
||||
void init_excludes(void);
|
||||
void read_excludes_file(const char *);
|
||||
const char * ftype(u_int type);
|
||||
|
||||
extern int ftsoptions;
|
||||
extern u_int keys;
|
||||
extern int lineno;
|
||||
extern int dflag, eflag, iflag, nflag, qflag, rflag, sflag, uflag, wflag;
|
||||
#ifdef MAXPATHLEN
|
||||
extern char fullpath[MAXPATHLEN];
|
||||
#endif
|
@ -1,124 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /*not lint */
|
||||
#endif
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <err.h>
|
||||
#include <fts.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include "mtree.h"
|
||||
#include "extern.h"
|
||||
|
||||
typedef struct _key {
|
||||
const char *name; /* key name */
|
||||
u_int val; /* value */
|
||||
|
||||
#define NEEDVALUE 0x01
|
||||
u_int flags;
|
||||
} KEY;
|
||||
|
||||
/* NB: the following table must be sorted lexically. */
|
||||
static KEY keylist[] = {
|
||||
{"cksum", F_CKSUM, NEEDVALUE},
|
||||
{"flags", F_FLAGS, NEEDVALUE},
|
||||
{"gid", F_GID, NEEDVALUE},
|
||||
{"gname", F_GNAME, NEEDVALUE},
|
||||
{"ignore", F_IGN, 0},
|
||||
{"link", F_SLINK, NEEDVALUE},
|
||||
#ifdef MD5
|
||||
{"md5digest", F_MD5, NEEDVALUE},
|
||||
#endif
|
||||
{"mode", F_MODE, NEEDVALUE},
|
||||
{"nlink", F_NLINK, NEEDVALUE},
|
||||
{"nochange", F_NOCHANGE, 0},
|
||||
{"optional", F_OPT, 0},
|
||||
#ifdef RMD160
|
||||
{"ripemd160digest", F_RMD160, NEEDVALUE},
|
||||
#endif
|
||||
#ifdef SHA1
|
||||
{"sha1digest", F_SHA1, NEEDVALUE},
|
||||
#endif
|
||||
#ifdef SHA256
|
||||
{"sha256digest", F_SHA256, NEEDVALUE},
|
||||
#endif
|
||||
{"size", F_SIZE, NEEDVALUE},
|
||||
{"time", F_TIME, NEEDVALUE},
|
||||
{"type", F_TYPE, NEEDVALUE},
|
||||
{"uid", F_UID, NEEDVALUE},
|
||||
{"uname", F_UNAME, NEEDVALUE},
|
||||
};
|
||||
|
||||
int keycompare(const void *, const void *);
|
||||
|
||||
u_int
|
||||
parsekey(char *name, int *needvaluep)
|
||||
{
|
||||
KEY *k, tmp;
|
||||
|
||||
tmp.name = name;
|
||||
k = (KEY *)bsearch(&tmp, keylist, sizeof(keylist) / sizeof(KEY),
|
||||
sizeof(KEY), keycompare);
|
||||
if (k == NULL)
|
||||
errx(1, "line %d: unknown keyword %s", lineno, name);
|
||||
|
||||
if (needvaluep)
|
||||
*needvaluep = k->flags & NEEDVALUE ? 1 : 0;
|
||||
return (k->val);
|
||||
}
|
||||
|
||||
int
|
||||
keycompare(const void *a, const void *b)
|
||||
{
|
||||
return (strcmp(((const KEY *)a)->name, ((const KEY *)b)->name));
|
||||
}
|
||||
|
||||
char *
|
||||
flags_to_string(u_long fflags)
|
||||
{
|
||||
char *string;
|
||||
|
||||
string = fflagstostr(fflags);
|
||||
if (string != NULL && *string == '\0') {
|
||||
free(string);
|
||||
string = strdup("none");
|
||||
}
|
||||
if (string == NULL)
|
||||
err(1, NULL);
|
||||
|
||||
return string;
|
||||
}
|
@ -1,408 +0,0 @@
|
||||
.\" Copyright (c) 1989, 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" From: @(#)mtree.8 8.2 (Berkeley) 12/11/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd February 13, 2021
|
||||
.Dt MTREE 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm mtree
|
||||
.Nd map a directory hierarchy
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl LPUcdeinqruxw
|
||||
.Bk -words
|
||||
.Op Fl f Ar spec
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl K Ar keywords
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl k Ar keywords
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl p Ar path
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl s Ar seed
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl X Ar exclude-list
|
||||
.Ek
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility compares the file hierarchy rooted in the current directory against a
|
||||
specification read from the standard input.
|
||||
Messages are written to the standard output for any files whose
|
||||
characteristics do not match the specifications, or which are
|
||||
missing from either the file hierarchy or the specification.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width flag
|
||||
.It Fl L
|
||||
Follow all symbolic links in the file hierarchy.
|
||||
.It Fl P
|
||||
Do not follow symbolic links in the file hierarchy, instead consider
|
||||
the symbolic link itself in any comparisons.
|
||||
This is the default.
|
||||
.It Fl U
|
||||
Modify the owner, group, permissions, and modification time of existing
|
||||
files to match the specification and create any missing directories or
|
||||
symbolic links.
|
||||
User, group and permissions must all be specified for missing directories
|
||||
to be created.
|
||||
Corrected mismatches are not considered errors.
|
||||
.It Fl c
|
||||
Print a specification for the file hierarchy to the standard output.
|
||||
.It Fl d
|
||||
Ignore everything except directory type files.
|
||||
.It Fl e
|
||||
Do not complain about files that are in the file hierarchy, but not in the
|
||||
specification.
|
||||
.It Fl i
|
||||
Indent the output 4 spaces each time a directory level is descended when
|
||||
creating a specification with the
|
||||
.Fl c
|
||||
option.
|
||||
This does not affect either the /set statements or the comment before each
|
||||
directory.
|
||||
It does however affect the comment before the close of each directory.
|
||||
.It Fl n
|
||||
Do not emit pathname comments when creating a specification.
|
||||
Normally
|
||||
a comment is emitted before each directory and before the close of that
|
||||
directory when using the
|
||||
.Fl c
|
||||
option.
|
||||
.It Fl q
|
||||
Quiet mode.
|
||||
Do not complain when a
|
||||
.Dq missing
|
||||
directory cannot be created because it already exists.
|
||||
This occurs when the directory is a symbolic link.
|
||||
.It Fl r
|
||||
Remove any files in the file hierarchy that are not described in the
|
||||
specification.
|
||||
.It Fl u
|
||||
Same as
|
||||
.Fl U
|
||||
except a status of 2 is returned if the file hierarchy did not match
|
||||
the specification.
|
||||
.It Fl w
|
||||
Make some errors non-fatal warnings.
|
||||
.It Fl x
|
||||
Do not descend below mount points in the file hierarchy.
|
||||
.It Fl f Ar file
|
||||
Read the specification from
|
||||
.Ar file ,
|
||||
instead of from the standard input.
|
||||
.Pp
|
||||
If this option is specified twice, the two specifications are compared
|
||||
to each other rather than to the file hierarchy.
|
||||
The specifications will be sorted like output generated using
|
||||
.Fl c .
|
||||
The output format in this case is somewhat remniscent of
|
||||
.Xr comm 1 ,
|
||||
having "in first spec only", "in second spec only", and "different"
|
||||
columns, prefixed by zero, one and two TAB characters respectively.
|
||||
Each entry in the "different" column occupies two lines, one from each specification.
|
||||
.It Fl K Ar keywords
|
||||
Add the specified (whitespace or comma separated)
|
||||
.Ar keywords
|
||||
to the current set of keywords.
|
||||
.It Fl k Ar keywords
|
||||
Use the ``type'' keyword plus the specified (whitespace or comma separated)
|
||||
.Ar keywords
|
||||
instead of the current set of keywords.
|
||||
.It Fl p Ar path
|
||||
Use the file hierarchy rooted in
|
||||
.Ar path ,
|
||||
instead of the current directory.
|
||||
.It Fl s Ar seed
|
||||
Display a single checksum to the standard error output that represents all
|
||||
of the files for which the keyword
|
||||
.Cm cksum
|
||||
was specified.
|
||||
The checksum is seeded with the specified value.
|
||||
.It Fl X Ar exclude-list
|
||||
The specified file contains
|
||||
.Xr fnmatch 3
|
||||
patterns matching files to be excluded from
|
||||
the specification, one to a line.
|
||||
If the pattern contains a
|
||||
.Ql \&/
|
||||
character, it will be matched against entire pathnames (relative to
|
||||
the starting directory); otherwise,
|
||||
it will be matched against basenames only.
|
||||
No comments are allowed in
|
||||
the
|
||||
.Ar exclude-list
|
||||
file.
|
||||
.El
|
||||
.Pp
|
||||
Specifications are mostly composed of ``keywords'', i.e., strings
|
||||
that specify values relating to files.
|
||||
No keywords have default values, and if a keyword has no value set, no
|
||||
checks based on it are performed.
|
||||
.Pp
|
||||
Currently supported keywords are as follows:
|
||||
.Bl -tag -width Cm
|
||||
.It Cm cksum
|
||||
The checksum of the file using the default algorithm specified by
|
||||
the
|
||||
.Xr cksum 1
|
||||
utility.
|
||||
.It Cm flags
|
||||
The file flags as a symbolic name.
|
||||
See
|
||||
.Xr chflags 1
|
||||
for information on these names.
|
||||
If no flags are to be set the string
|
||||
.Dq none
|
||||
may be used to override the current default.
|
||||
.It Cm ignore
|
||||
Ignore any file hierarchy below this file.
|
||||
.It Cm gid
|
||||
The file group as a numeric value.
|
||||
.It Cm gname
|
||||
The file group as a symbolic name.
|
||||
.It Cm md5digest
|
||||
The MD5 message digest of the file.
|
||||
.It Cm sha1digest
|
||||
The
|
||||
.Tn FIPS
|
||||
160-1
|
||||
.Pq Dq Tn SHA-1
|
||||
message digest of the file.
|
||||
.It Cm sha256digest
|
||||
The
|
||||
.Tn FIPS
|
||||
180-2
|
||||
.Pq Dq Tn SHA-256
|
||||
message digest of the file.
|
||||
.It Cm ripemd160digest
|
||||
The
|
||||
.Tn RIPEMD160
|
||||
message digest of the file.
|
||||
.It Cm mode
|
||||
The current file's permissions as a numeric (octal) or symbolic
|
||||
value.
|
||||
.It Cm nlink
|
||||
The number of hard links the file is expected to have.
|
||||
.It Cm nochange
|
||||
Make sure this file or directory exists but otherwise ignore all attributes.
|
||||
.It Cm optional
|
||||
The file is optional; do not complain about the file if it is
|
||||
not in the file hierarchy.
|
||||
.It Cm uid
|
||||
The file owner as a numeric value.
|
||||
.It Cm uname
|
||||
The file owner as a symbolic name.
|
||||
.It Cm size
|
||||
The size, in bytes, of the file.
|
||||
.It Cm link
|
||||
The file the symbolic link is expected to reference.
|
||||
.It Cm time
|
||||
The last modification time of the file, in seconds and nanoseconds.
|
||||
The value should include a period character and exactly nine digits
|
||||
after the period.
|
||||
.It Cm type
|
||||
The type of the file; may be set to any one of the following:
|
||||
.Pp
|
||||
.Bl -tag -width Cm -compact
|
||||
.It Cm block
|
||||
block special device
|
||||
.It Cm char
|
||||
character special device
|
||||
.It Cm dir
|
||||
directory
|
||||
.It Cm fifo
|
||||
fifo
|
||||
.It Cm file
|
||||
regular file
|
||||
.It Cm link
|
||||
symbolic link
|
||||
.It Cm socket
|
||||
socket
|
||||
.El
|
||||
.El
|
||||
.Pp
|
||||
The default set of keywords are
|
||||
.Cm flags ,
|
||||
.Cm gid ,
|
||||
.Cm link ,
|
||||
.Cm mode ,
|
||||
.Cm nlink ,
|
||||
.Cm size ,
|
||||
.Cm time ,
|
||||
and
|
||||
.Cm uid .
|
||||
.Pp
|
||||
There are four types of lines in a specification.
|
||||
.Pp
|
||||
The first type of line sets a global value for a keyword, and consists of
|
||||
the string ``/set'' followed by whitespace, followed by sets of keyword/value
|
||||
pairs, separated by whitespace.
|
||||
Keyword/value pairs consist of a keyword, followed by an equals sign
|
||||
(``=''), followed by a value, without whitespace characters.
|
||||
Once a keyword has been set, its value remains unchanged until either
|
||||
reset or unset.
|
||||
.Pp
|
||||
The second type of line unsets keywords and consists of the string
|
||||
``/unset'', followed by whitespace, followed by one or more keywords,
|
||||
separated by whitespace.
|
||||
.Pp
|
||||
The third type of line is a file specification and consists of a file
|
||||
name, followed by whitespace, followed by zero or more whitespace
|
||||
separated keyword/value pairs.
|
||||
The file name may be preceded by whitespace characters.
|
||||
The file name may contain any of the standard file name matching
|
||||
characters (``['', ``]'', ``?'' or ``*''), in which case files
|
||||
in the hierarchy will be associated with the first pattern that
|
||||
they match.
|
||||
.Pp
|
||||
Each of the keyword/value pairs consist of a keyword, followed by an
|
||||
equals sign (``=''), followed by the keyword's value, without
|
||||
whitespace characters.
|
||||
These values override, without changing, the global value of the
|
||||
corresponding keyword.
|
||||
.Pp
|
||||
All paths are relative.
|
||||
Specifying a directory will cause subsequent files to be searched
|
||||
for in that directory hierarchy.
|
||||
Which brings us to the last type of line in a specification: a line
|
||||
containing only the string
|
||||
.Dq Pa ..\&
|
||||
causes the current directory
|
||||
path to ascend one level.
|
||||
.Pp
|
||||
Empty lines and lines whose first non-whitespace character is a hash
|
||||
mark (``#'') are ignored.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility exits with a status of 0 on success, 1 if any error occurred,
|
||||
and 2 if the file hierarchy did not match the specification.
|
||||
A status of 2 is converted to a status of 0 if the
|
||||
.Fl U
|
||||
option is used.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /etc/mtree -compact
|
||||
.It Pa /etc/mtree
|
||||
system specification directory
|
||||
.El
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Sh EXAMPLES
|
||||
To detect system binaries that have been ``trojan horsed'', it is recommended
|
||||
that
|
||||
.Nm
|
||||
.Fl K
|
||||
.Cm sha256digest
|
||||
be run on the file systems, and a copy of the results stored on a different
|
||||
machine, or, at least, in encrypted form.
|
||||
The output file itself should be digested using the
|
||||
.Xr sha256 1
|
||||
utility.
|
||||
Then, periodically,
|
||||
.Nm
|
||||
and
|
||||
.Xr sha256 1
|
||||
should be run against the on-line specifications.
|
||||
While it is possible for the bad guys to change the on-line specifications
|
||||
to conform to their modified binaries, it is believed to be
|
||||
impractical for them to create a modified specification which has
|
||||
the same SHA-256 digest as the original.
|
||||
.Pp
|
||||
The
|
||||
.Fl d
|
||||
and
|
||||
.Fl u
|
||||
options can be used in combination to create directory hierarchies
|
||||
for distributions and other such things; the files in
|
||||
.Pa /etc/mtree
|
||||
were used to create almost all directories in this
|
||||
.Fx
|
||||
distribution.
|
||||
.Pp
|
||||
To create an
|
||||
.Pa /etc/mtree
|
||||
style BSD.*.dist file, use
|
||||
.Nm
|
||||
.Fl c
|
||||
.Fl d
|
||||
.Fl i
|
||||
.Fl n
|
||||
.Fl k
|
||||
.Cm uname,gname,mode,nochange.
|
||||
.Sh DEPRECATION NOTICE
|
||||
.Nm fmtree
|
||||
is deprecated, and will be gone in
|
||||
.Fx 14.0 .
|
||||
.Xr mtree 8
|
||||
should be used instead.
|
||||
.Sh SEE ALSO
|
||||
.Xr chflags 1 ,
|
||||
.Xr chgrp 1 ,
|
||||
.Xr chmod 1 ,
|
||||
.Xr cksum 1 ,
|
||||
.Xr md5 1 ,
|
||||
.Xr stat 2 ,
|
||||
.Xr fts 3 ,
|
||||
.Xr md5 3 ,
|
||||
.Xr chown 8 ,
|
||||
.Xr mtree 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility appeared in
|
||||
.Bx 4.3 Reno .
|
||||
The
|
||||
.Tn MD5
|
||||
digest capability was added in
|
||||
.Fx 2.1 ,
|
||||
in response to the widespread use of programs which can spoof
|
||||
.Xr cksum 1 .
|
||||
The
|
||||
.Tn SHA-1
|
||||
and
|
||||
.Tn RIPEMD160
|
||||
digests were added in
|
||||
.Fx 4.0 ,
|
||||
as new attacks have demonstrated weaknesses in
|
||||
.Tn MD5 .
|
||||
The
|
||||
.Tn SHA-256
|
||||
digest was added in
|
||||
.Fx 6.0 .
|
||||
Support for file flags was added in
|
||||
.Fx 4.0 ,
|
||||
and mostly comes from
|
||||
.Nx .
|
@ -1,191 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1989, 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static const char copyright[] =
|
||||
"@(#) Copyright (c) 1989, 1990, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)mtree.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fts.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include "mtree.h"
|
||||
#include "extern.h"
|
||||
|
||||
int ftsoptions = FTS_PHYSICAL;
|
||||
int dflag, eflag, iflag, nflag, qflag, rflag, sflag, uflag, wflag;
|
||||
static int cflag, Uflag;
|
||||
u_int keys;
|
||||
char fullpath[MAXPATHLEN];
|
||||
|
||||
static void usage(void);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int ch;
|
||||
char *dir, *p;
|
||||
int status;
|
||||
FILE *spec1, *spec2;
|
||||
|
||||
dir = NULL;
|
||||
keys = KEYDEFAULT;
|
||||
init_excludes();
|
||||
spec1 = stdin;
|
||||
spec2 = NULL;
|
||||
|
||||
while ((ch = getopt(argc, argv, "cdef:iK:k:LnPp:qrs:UuwxX:")) != -1)
|
||||
switch((char)ch) {
|
||||
case 'c':
|
||||
cflag = 1;
|
||||
break;
|
||||
case 'd':
|
||||
dflag = 1;
|
||||
break;
|
||||
case 'e':
|
||||
eflag = 1;
|
||||
break;
|
||||
case 'f':
|
||||
if (spec1 == stdin) {
|
||||
spec1 = fopen(optarg, "r");
|
||||
if (spec1 == NULL)
|
||||
err(1, "%s", optarg);
|
||||
} else if (spec2 == NULL) {
|
||||
spec2 = fopen(optarg, "r");
|
||||
if (spec2 == NULL)
|
||||
err(1, "%s", optarg);
|
||||
} else
|
||||
usage();
|
||||
break;
|
||||
case 'i':
|
||||
iflag = 1;
|
||||
break;
|
||||
case 'K':
|
||||
while ((p = strsep(&optarg, " \t,")) != NULL)
|
||||
if (*p != '\0')
|
||||
keys |= parsekey(p, NULL);
|
||||
break;
|
||||
case 'k':
|
||||
keys = F_TYPE;
|
||||
while ((p = strsep(&optarg, " \t,")) != NULL)
|
||||
if (*p != '\0')
|
||||
keys |= parsekey(p, NULL);
|
||||
break;
|
||||
case 'L':
|
||||
ftsoptions &= ~FTS_PHYSICAL;
|
||||
ftsoptions |= FTS_LOGICAL;
|
||||
break;
|
||||
case 'n':
|
||||
nflag = 1;
|
||||
break;
|
||||
case 'P':
|
||||
ftsoptions &= ~FTS_LOGICAL;
|
||||
ftsoptions |= FTS_PHYSICAL;
|
||||
break;
|
||||
case 'p':
|
||||
dir = optarg;
|
||||
break;
|
||||
case 'q':
|
||||
qflag = 1;
|
||||
break;
|
||||
case 'r':
|
||||
rflag = 1;
|
||||
break;
|
||||
case 's':
|
||||
sflag = 1;
|
||||
crc_total = ~strtoul(optarg, &p, 0);
|
||||
if (*p)
|
||||
errx(1, "illegal seed value -- %s", optarg);
|
||||
break;
|
||||
case 'U':
|
||||
Uflag = 1;
|
||||
uflag = 1;
|
||||
break;
|
||||
case 'u':
|
||||
uflag = 1;
|
||||
break;
|
||||
case 'w':
|
||||
wflag = 1;
|
||||
break;
|
||||
case 'x':
|
||||
ftsoptions |= FTS_XDEV;
|
||||
break;
|
||||
case 'X':
|
||||
read_excludes_file(optarg);
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc)
|
||||
usage();
|
||||
|
||||
if (dir && chdir(dir))
|
||||
err(1, "%s", dir);
|
||||
|
||||
if ((cflag || sflag) && !getcwd(fullpath, sizeof(fullpath)))
|
||||
errx(1, "%s", fullpath);
|
||||
|
||||
if (cflag) {
|
||||
cwalk();
|
||||
exit(0);
|
||||
}
|
||||
if (spec2 != NULL)
|
||||
status = mtree_specspec(spec1, spec2);
|
||||
else
|
||||
status = mtree_verifyspec(spec1);
|
||||
if (Uflag & (status == MISMATCHEXIT))
|
||||
status = 0;
|
||||
exit(status);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"usage: mtree [-LPUcdeinqruxw] [-f spec] [-f spec] [-K key] [-k key] [-p path] [-s seed]\n"
|
||||
"\t[-X excludes]\n");
|
||||
exit(1);
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)mtree.h 8.1 (Berkeley) 6/6/93
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define KEYDEFAULT \
|
||||
(F_GID | F_MODE | F_NLINK | F_SIZE | F_SLINK | F_TIME | F_UID | F_FLAGS)
|
||||
|
||||
#define MISMATCHEXIT 2
|
||||
|
||||
typedef struct _node {
|
||||
struct _node *parent, *child; /* up, down */
|
||||
struct _node *prev, *next; /* left, right */
|
||||
off_t st_size; /* size */
|
||||
struct timespec st_mtimespec; /* last modification time */
|
||||
u_long cksum; /* check sum */
|
||||
char *md5digest; /* MD5 digest */
|
||||
char *sha1digest; /* SHA-1 digest */
|
||||
char *sha256digest; /* SHA-256 digest */
|
||||
char *rmd160digest; /* RIPEMD160 digest */
|
||||
char *slink; /* symbolic link reference */
|
||||
uid_t st_uid; /* uid */
|
||||
gid_t st_gid; /* gid */
|
||||
#define MBITS (S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO)
|
||||
mode_t st_mode; /* mode */
|
||||
u_long st_flags; /* flags */
|
||||
nlink_t st_nlink; /* link count */
|
||||
|
||||
#define F_CKSUM 0x0001 /* check sum */
|
||||
#define F_DONE 0x0002 /* directory done */
|
||||
#define F_GID 0x0004 /* gid */
|
||||
#define F_GNAME 0x0008 /* group name */
|
||||
#define F_IGN 0x0010 /* ignore */
|
||||
#define F_MAGIC 0x0020 /* name has magic chars */
|
||||
#define F_MODE 0x0040 /* mode */
|
||||
#define F_NLINK 0x0080 /* number of links */
|
||||
#define F_SIZE 0x0100 /* size */
|
||||
#define F_SLINK 0x0200 /* link count */
|
||||
#define F_TIME 0x0400 /* modification time */
|
||||
#define F_TYPE 0x0800 /* file type */
|
||||
#define F_UID 0x1000 /* uid */
|
||||
#define F_UNAME 0x2000 /* user name */
|
||||
#define F_VISIT 0x4000 /* file visited */
|
||||
#define F_MD5 0x8000 /* MD5 digest */
|
||||
#define F_NOCHANGE 0x10000 /* If owner/mode "wrong", do */
|
||||
/* not change */
|
||||
#define F_SHA1 0x20000 /* SHA-1 digest */
|
||||
#define F_RMD160 0x40000 /* RIPEMD160 digest */
|
||||
#define F_FLAGS 0x80000 /* file flags */
|
||||
#define F_SHA256 0x100000 /* SHA-256 digest */
|
||||
#define F_OPT 0x200000 /* existence optional */
|
||||
u_int flags; /* items set */
|
||||
|
||||
#define F_BLOCK 0x001 /* block special */
|
||||
#define F_CHAR 0x002 /* char special */
|
||||
#define F_DIR 0x004 /* directory */
|
||||
#define F_FIFO 0x008 /* fifo */
|
||||
#define F_FILE 0x010 /* regular file */
|
||||
#define F_LINK 0x020 /* symbolic link */
|
||||
#define F_SOCK 0x040 /* socket */
|
||||
u_char type; /* file type */
|
||||
|
||||
char name[1]; /* file name (must be last) */
|
||||
} NODE;
|
||||
|
||||
#define RP(p) \
|
||||
((p)->fts_path[0] == '.' && (p)->fts_path[1] == '/' ? \
|
||||
(p)->fts_path + 2 : (p)->fts_path)
|
@ -1,323 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)spec.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fts.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <vis.h>
|
||||
#include "mtree.h"
|
||||
#include "extern.h"
|
||||
|
||||
int lineno; /* Current spec line number. */
|
||||
|
||||
static void set(char *, NODE *);
|
||||
static void unset(char *, NODE *);
|
||||
|
||||
NODE *
|
||||
mtree_readspec(FILE *fi)
|
||||
{
|
||||
NODE *centry, *last;
|
||||
char *p;
|
||||
NODE ginfo, *root;
|
||||
int c_cur, c_next;
|
||||
char buf[2048];
|
||||
|
||||
centry = last = root = NULL;
|
||||
bzero(&ginfo, sizeof(ginfo));
|
||||
c_cur = c_next = 0;
|
||||
for (lineno = 1; fgets(buf, sizeof(buf), fi);
|
||||
++lineno, c_cur = c_next, c_next = 0) {
|
||||
/* Skip empty lines. */
|
||||
if (buf[0] == '\n')
|
||||
continue;
|
||||
|
||||
/* Find end of line. */
|
||||
if ((p = strchr(buf, '\n')) == NULL)
|
||||
errx(1, "line %d too long", lineno);
|
||||
|
||||
/* See if next line is continuation line. */
|
||||
if (p[-1] == '\\') {
|
||||
--p;
|
||||
c_next = 1;
|
||||
}
|
||||
|
||||
/* Null-terminate the line. */
|
||||
*p = '\0';
|
||||
|
||||
/* Skip leading whitespace. */
|
||||
for (p = buf; *p && isspace(*p); ++p);
|
||||
|
||||
/* If nothing but whitespace or comment char, continue. */
|
||||
if (!*p || *p == '#')
|
||||
continue;
|
||||
|
||||
#ifdef DEBUG
|
||||
(void)fprintf(stderr, "line %d: {%s}\n", lineno, p);
|
||||
#endif
|
||||
if (c_cur) {
|
||||
set(p, centry);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Grab file name, "$", "set", or "unset". */
|
||||
if ((p = strtok(p, "\n\t ")) == NULL)
|
||||
errx(1, "line %d: missing field", lineno);
|
||||
|
||||
if (p[0] == '/')
|
||||
switch(p[1]) {
|
||||
case 's':
|
||||
if (strcmp(p + 1, "set"))
|
||||
break;
|
||||
set(NULL, &ginfo);
|
||||
continue;
|
||||
case 'u':
|
||||
if (strcmp(p + 1, "unset"))
|
||||
break;
|
||||
unset(NULL, &ginfo);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strchr(p, '/'))
|
||||
errx(1, "line %d: slash character in file name",
|
||||
lineno);
|
||||
|
||||
if (!strcmp(p, "..")) {
|
||||
/* Don't go up, if haven't gone down. */
|
||||
if (!root)
|
||||
goto noparent;
|
||||
if (last->type != F_DIR || last->flags & F_DONE) {
|
||||
if (last == root)
|
||||
goto noparent;
|
||||
last = last->parent;
|
||||
}
|
||||
last->flags |= F_DONE;
|
||||
continue;
|
||||
|
||||
noparent: errx(1, "line %d: no parent node", lineno);
|
||||
}
|
||||
|
||||
if ((centry = calloc(1, sizeof(NODE) + strlen(p))) == NULL)
|
||||
errx(1, "calloc");
|
||||
*centry = ginfo;
|
||||
#define MAGIC "?*["
|
||||
if (strpbrk(p, MAGIC))
|
||||
centry->flags |= F_MAGIC;
|
||||
if (strunvis(centry->name, p) == -1)
|
||||
errx(1, "filename %s is ill-encoded", p);
|
||||
set(NULL, centry);
|
||||
|
||||
if (!root) {
|
||||
last = root = centry;
|
||||
root->parent = root;
|
||||
} else if (last->type == F_DIR && !(last->flags & F_DONE)) {
|
||||
centry->parent = last;
|
||||
last = last->child = centry;
|
||||
} else {
|
||||
centry->parent = last->parent;
|
||||
centry->prev = last;
|
||||
last = last->next = centry;
|
||||
}
|
||||
}
|
||||
return (root);
|
||||
}
|
||||
|
||||
static void
|
||||
set(char *t, NODE *ip)
|
||||
{
|
||||
int type;
|
||||
char *kw, *val = NULL;
|
||||
struct group *gr;
|
||||
struct passwd *pw;
|
||||
mode_t *m;
|
||||
int value;
|
||||
char *ep;
|
||||
|
||||
for (; (kw = strtok(t, "= \t\n")); t = NULL) {
|
||||
ip->flags |= type = parsekey(kw, &value);
|
||||
if (value && (val = strtok(NULL, " \t\n")) == NULL)
|
||||
errx(1, "line %d: missing value", lineno);
|
||||
switch(type) {
|
||||
case F_CKSUM:
|
||||
ip->cksum = strtoul(val, &ep, 10);
|
||||
if (*ep)
|
||||
errx(1, "line %d: invalid checksum %s",
|
||||
lineno, val);
|
||||
break;
|
||||
case F_MD5:
|
||||
ip->md5digest = strdup(val);
|
||||
if(!ip->md5digest)
|
||||
errx(1, "strdup");
|
||||
break;
|
||||
case F_SHA1:
|
||||
ip->sha1digest = strdup(val);
|
||||
if(!ip->sha1digest)
|
||||
errx(1, "strdup");
|
||||
break;
|
||||
case F_SHA256:
|
||||
ip->sha256digest = strdup(val);
|
||||
if(!ip->sha256digest)
|
||||
errx(1, "strdup");
|
||||
break;
|
||||
case F_RMD160:
|
||||
ip->rmd160digest = strdup(val);
|
||||
if(!ip->rmd160digest)
|
||||
errx(1, "strdup");
|
||||
break;
|
||||
case F_FLAGS:
|
||||
if (strcmp("none", val) == 0)
|
||||
ip->st_flags = 0;
|
||||
else if (strtofflags(&val, &ip->st_flags, NULL) != 0)
|
||||
errx(1, "line %d: invalid flag %s",lineno, val);
|
||||
break;
|
||||
case F_GID:
|
||||
ip->st_gid = strtoul(val, &ep, 10);
|
||||
if (*ep)
|
||||
errx(1, "line %d: invalid gid %s", lineno, val);
|
||||
break;
|
||||
case F_GNAME:
|
||||
if ((gr = getgrnam(val)) == NULL)
|
||||
errx(1, "line %d: unknown group %s", lineno, val);
|
||||
ip->st_gid = gr->gr_gid;
|
||||
break;
|
||||
case F_IGN:
|
||||
/* just set flag bit */
|
||||
break;
|
||||
case F_MODE:
|
||||
if ((m = setmode(val)) == NULL)
|
||||
errx(1, "line %d: invalid file mode %s",
|
||||
lineno, val);
|
||||
ip->st_mode = getmode(m, 0);
|
||||
free(m);
|
||||
break;
|
||||
case F_NLINK:
|
||||
ip->st_nlink = strtoul(val, &ep, 10);
|
||||
if (*ep)
|
||||
errx(1, "line %d: invalid link count %s",
|
||||
lineno, val);
|
||||
break;
|
||||
case F_OPT:
|
||||
/* just set flag bit */
|
||||
break;
|
||||
case F_SIZE:
|
||||
ip->st_size = strtoq(val, &ep, 10);
|
||||
if (*ep)
|
||||
errx(1, "line %d: invalid size %s",
|
||||
lineno, val);
|
||||
break;
|
||||
case F_SLINK:
|
||||
ip->slink = malloc(strlen(val) + 1);
|
||||
if (ip->slink == NULL)
|
||||
errx(1, "malloc");
|
||||
if (strunvis(ip->slink, val) == -1)
|
||||
errx(1, "symlink %s is ill-encoded", val);
|
||||
break;
|
||||
case F_TIME:
|
||||
ip->st_mtimespec.tv_sec = strtoul(val, &ep, 10);
|
||||
if (*ep == '.') {
|
||||
/* Note: we require exactly nine
|
||||
* digits after the decimal point. */
|
||||
val = ep + 1;
|
||||
ip->st_mtimespec.tv_nsec
|
||||
= strtoul(val, &ep, 10);
|
||||
} else
|
||||
ip->st_mtimespec.tv_nsec = 0;
|
||||
if (*ep)
|
||||
errx(1, "line %d: invalid time %s",
|
||||
lineno, val);
|
||||
break;
|
||||
case F_TYPE:
|
||||
switch(*val) {
|
||||
case 'b':
|
||||
if (!strcmp(val, "block"))
|
||||
ip->type = F_BLOCK;
|
||||
break;
|
||||
case 'c':
|
||||
if (!strcmp(val, "char"))
|
||||
ip->type = F_CHAR;
|
||||
break;
|
||||
case 'd':
|
||||
if (!strcmp(val, "dir"))
|
||||
ip->type = F_DIR;
|
||||
break;
|
||||
case 'f':
|
||||
if (!strcmp(val, "file"))
|
||||
ip->type = F_FILE;
|
||||
if (!strcmp(val, "fifo"))
|
||||
ip->type = F_FIFO;
|
||||
break;
|
||||
case 'l':
|
||||
if (!strcmp(val, "link"))
|
||||
ip->type = F_LINK;
|
||||
break;
|
||||
case 's':
|
||||
if (!strcmp(val, "socket"))
|
||||
ip->type = F_SOCK;
|
||||
break;
|
||||
default:
|
||||
errx(1, "line %d: unknown file type %s",
|
||||
lineno, val);
|
||||
}
|
||||
break;
|
||||
case F_UID:
|
||||
ip->st_uid = strtoul(val, &ep, 10);
|
||||
if (*ep)
|
||||
errx(1, "line %d: invalid uid %s", lineno, val);
|
||||
break;
|
||||
case F_UNAME:
|
||||
if ((pw = getpwnam(val)) == NULL)
|
||||
errx(1, "line %d: unknown user %s", lineno, val);
|
||||
ip->st_uid = pw->pw_uid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unset(char *t, NODE *ip)
|
||||
{
|
||||
char *p;
|
||||
|
||||
while ((p = strtok(t, "\n\t ")))
|
||||
ip->flags &= ~parsekey(p, NULL);
|
||||
}
|
@ -1,256 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2003 Poul-Henning Kamp
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <err.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include "mtree.h"
|
||||
#include "extern.h"
|
||||
|
||||
#define FF(a, b, c, d) \
|
||||
(((a)->flags & (c)) && ((b)->flags & (c)) && ((a)->d) != ((b)->d))
|
||||
#define FS(a, b, c, d) \
|
||||
(((a)->flags & (c)) && ((b)->flags & (c)) && strcmp((a)->d,(b)->d))
|
||||
#define FM(a, b, c, d) \
|
||||
(((a)->flags & (c)) && ((b)->flags & (c)) && memcmp(&(a)->d,&(b)->d, sizeof (a)->d))
|
||||
|
||||
static void
|
||||
shownode(NODE *n, int f, char const *path)
|
||||
{
|
||||
struct group *gr;
|
||||
struct passwd *pw;
|
||||
|
||||
printf("%s%s %s", path, n->name, ftype(n->type));
|
||||
if (f & F_CKSUM)
|
||||
printf(" cksum=%lu", n->cksum);
|
||||
if (f & F_GID)
|
||||
printf(" gid=%d", n->st_gid);
|
||||
if (f & F_GNAME) {
|
||||
gr = getgrgid(n->st_gid);
|
||||
if (gr == NULL)
|
||||
printf(" gid=%d", n->st_gid);
|
||||
else
|
||||
printf(" gname=%s", gr->gr_name);
|
||||
}
|
||||
if (f & F_MODE)
|
||||
printf(" mode=%o", n->st_mode);
|
||||
if (f & F_NLINK)
|
||||
printf(" nlink=%ju", (uintmax_t)n->st_nlink);
|
||||
if (f & F_SIZE)
|
||||
printf(" size=%jd", (intmax_t)n->st_size);
|
||||
if (f & F_UID)
|
||||
printf(" uid=%d", n->st_uid);
|
||||
if (f & F_UNAME) {
|
||||
pw = getpwuid(n->st_uid);
|
||||
if (pw == NULL)
|
||||
printf(" uid=%d", n->st_uid);
|
||||
else
|
||||
printf(" uname=%s", pw->pw_name);
|
||||
}
|
||||
if (f & F_MD5)
|
||||
printf(" md5digest=%s", n->md5digest);
|
||||
if (f & F_SHA1)
|
||||
printf(" sha1digest=%s", n->sha1digest);
|
||||
if (f & F_RMD160)
|
||||
printf(" rmd160digest=%s", n->rmd160digest);
|
||||
if (f & F_SHA256)
|
||||
printf(" sha256digest=%s", n->sha256digest);
|
||||
if (f & F_FLAGS)
|
||||
printf(" flags=%s", flags_to_string(n->st_flags));
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static int
|
||||
mismatch(NODE *n1, NODE *n2, int differ, char const *path)
|
||||
{
|
||||
|
||||
if (n2 == NULL) {
|
||||
shownode(n1, differ, path);
|
||||
return (1);
|
||||
}
|
||||
if (n1 == NULL) {
|
||||
printf("\t");
|
||||
shownode(n2, differ, path);
|
||||
return (1);
|
||||
}
|
||||
if (!(differ & keys))
|
||||
return(0);
|
||||
printf("\t\t");
|
||||
shownode(n1, differ, path);
|
||||
printf("\t\t");
|
||||
shownode(n2, differ, path);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
compare_nodes(NODE *n1, NODE *n2, char const *path)
|
||||
{
|
||||
int differs;
|
||||
|
||||
if (n1 != NULL && n1->type == F_LINK)
|
||||
n1->flags &= ~F_MODE;
|
||||
if (n2 != NULL && n2->type == F_LINK)
|
||||
n2->flags &= ~F_MODE;
|
||||
differs = 0;
|
||||
if (n1 == NULL && n2 != NULL) {
|
||||
differs = n2->flags;
|
||||
mismatch(n1, n2, differs, path);
|
||||
return (1);
|
||||
}
|
||||
if (n1 != NULL && n2 == NULL) {
|
||||
differs = n1->flags;
|
||||
mismatch(n1, n2, differs, path);
|
||||
return (1);
|
||||
}
|
||||
if (n1->type != n2->type) {
|
||||
differs = F_TYPE;
|
||||
mismatch(n1, n2, differs, path);
|
||||
return (1);
|
||||
}
|
||||
if (FF(n1, n2, F_CKSUM, cksum))
|
||||
differs |= F_CKSUM;
|
||||
if (FF(n1, n2, F_GID, st_gid))
|
||||
differs |= F_GID;
|
||||
if (FF(n1, n2, F_GNAME, st_gid))
|
||||
differs |= F_GNAME;
|
||||
if (FF(n1, n2, F_MODE, st_mode))
|
||||
differs |= F_MODE;
|
||||
if (FF(n1, n2, F_NLINK, st_nlink))
|
||||
differs |= F_NLINK;
|
||||
if (FF(n1, n2, F_SIZE, st_size))
|
||||
differs |= F_SIZE;
|
||||
if (FS(n1, n2, F_SLINK, slink))
|
||||
differs |= F_SLINK;
|
||||
if (FM(n1, n2, F_TIME, st_mtimespec))
|
||||
differs |= F_TIME;
|
||||
if (FF(n1, n2, F_UID, st_uid))
|
||||
differs |= F_UID;
|
||||
if (FF(n1, n2, F_UNAME, st_uid))
|
||||
differs |= F_UNAME;
|
||||
if (FS(n1, n2, F_MD5, md5digest))
|
||||
differs |= F_MD5;
|
||||
if (FS(n1, n2, F_SHA1, sha1digest))
|
||||
differs |= F_SHA1;
|
||||
if (FS(n1, n2, F_RMD160, rmd160digest))
|
||||
differs |= F_RMD160;
|
||||
if (FS(n1, n2, F_SHA256, sha256digest))
|
||||
differs |= F_SHA256;
|
||||
if (FF(n1, n2, F_FLAGS, st_flags))
|
||||
differs |= F_FLAGS;
|
||||
if (differs) {
|
||||
mismatch(n1, n2, differs, path);
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
static int
|
||||
walk_in_the_forest(NODE *t1, NODE *t2, char const *path)
|
||||
{
|
||||
int r, i;
|
||||
NODE *c1, *c2, *n1, *n2;
|
||||
char *np;
|
||||
|
||||
r = 0;
|
||||
|
||||
if (t1 != NULL)
|
||||
c1 = t1->child;
|
||||
else
|
||||
c1 = NULL;
|
||||
if (t2 != NULL)
|
||||
c2 = t2->child;
|
||||
else
|
||||
c2 = NULL;
|
||||
while (c1 != NULL || c2 != NULL) {
|
||||
n1 = n2 = NULL;
|
||||
if (c1 != NULL)
|
||||
n1 = c1->next;
|
||||
if (c2 != NULL)
|
||||
n2 = c2->next;
|
||||
if (c1 != NULL && c2 != NULL) {
|
||||
if (c1->type != F_DIR && c2->type == F_DIR) {
|
||||
n2 = c2;
|
||||
c2 = NULL;
|
||||
} else if (c1->type == F_DIR && c2->type != F_DIR) {
|
||||
n1 = c1;
|
||||
c1 = NULL;
|
||||
} else {
|
||||
i = strcmp(c1->name, c2->name);
|
||||
if (i > 0) {
|
||||
n1 = c1;
|
||||
c1 = NULL;
|
||||
} else if (i < 0) {
|
||||
n2 = c2;
|
||||
c2 = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c1 == NULL && c2->type == F_DIR) {
|
||||
asprintf(&np, "%s%s/", path, c2->name);
|
||||
i = walk_in_the_forest(c1, c2, np);
|
||||
free(np);
|
||||
i += compare_nodes(c1, c2, path);
|
||||
} else if (c2 == NULL && c1->type == F_DIR) {
|
||||
asprintf(&np, "%s%s/", path, c1->name);
|
||||
i = walk_in_the_forest(c1, c2, np);
|
||||
free(np);
|
||||
i += compare_nodes(c1, c2, path);
|
||||
} else if (c1 == NULL || c2 == NULL) {
|
||||
i = compare_nodes(c1, c2, path);
|
||||
} else if (c1->type == F_DIR && c2->type == F_DIR) {
|
||||
asprintf(&np, "%s%s/", path, c1->name);
|
||||
i = walk_in_the_forest(c1, c2, np);
|
||||
free(np);
|
||||
i += compare_nodes(c1, c2, path);
|
||||
} else {
|
||||
i = compare_nodes(c1, c2, path);
|
||||
}
|
||||
r += i;
|
||||
c1 = n1;
|
||||
c2 = n2;
|
||||
}
|
||||
return (r);
|
||||
}
|
||||
|
||||
int
|
||||
mtree_specspec(FILE *fi, FILE *fj)
|
||||
{
|
||||
int rval;
|
||||
NODE *root1, *root2;
|
||||
|
||||
root1 = mtree_readspec(fi);
|
||||
root2 = mtree_readspec(fj);
|
||||
rval = walk_in_the_forest(root1, root2, "");
|
||||
rval += compare_nodes(root1, root2, "");
|
||||
if (rval > 0)
|
||||
return (MISMATCHEXIT);
|
||||
return (0);
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2003 Poul-Henning Kamp
|
||||
# All rights reserved.
|
||||
#
|
||||
# Please see src/share/examples/etc/bsd-style-copyright.
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
TMP=/tmp/mtree.$$
|
||||
|
||||
rm -rf ${TMP}
|
||||
mkdir -p ${TMP} ${TMP}/mr ${TMP}/mt
|
||||
|
||||
|
||||
mkdir ${TMP}/mt/foo
|
||||
mkdir ${TMP}/mr/\*
|
||||
mtree -c -p ${TMP}/mr | mtree -U -r -p ${TMP}/mt > /dev/null 2>&1
|
||||
if [ -d ${TMP}/mt/foo ] ; then
|
||||
echo "ERROR Mtree create fell for filename with '*' char" 1>&2
|
||||
rm -rf ${TMP}
|
||||
exit 1
|
||||
fi
|
||||
rmdir ${TMP}/mr/\*
|
||||
|
||||
mkdir -p ${TMP}/mt/foo
|
||||
mkdir ${TMP}/mr/\[f\]oo
|
||||
mtree -c -p ${TMP}/mr | mtree -U -r -p ${TMP}/mt > /dev/null 2>&1
|
||||
if [ -d ${TMP}/mt/foo ] ; then
|
||||
echo "ERROR Mtree create fell for filename with '[' char" 1>&2
|
||||
rm -rf ${TMP}
|
||||
exit 1
|
||||
fi
|
||||
rmdir ${TMP}/mr/\[f\]oo
|
||||
|
||||
mkdir -p ${TMP}/mt/foo
|
||||
mkdir ${TMP}/mr/\?oo
|
||||
mtree -c -p ${TMP}/mr | mtree -U -r -p ${TMP}/mt > /dev/null 2>&1
|
||||
if [ -d ${TMP}/mt/foo ] ; then
|
||||
echo "ERROR Mtree create fell for filename with '?' char" 1>&2
|
||||
rm -rf ${TMP}
|
||||
exit 1
|
||||
fi
|
||||
rmdir ${TMP}/mr/\?oo
|
||||
|
||||
mkdir ${TMP}/mr/\#
|
||||
mtree -c -p ${TMP}/mr > ${TMP}/_
|
||||
if mtree -U -r -p ${TMP}/mt < ${TMP}/_ > /dev/null 2>&1 ; then
|
||||
true
|
||||
else
|
||||
echo "ERROR Mtree create fell for filename with '#' char" 1>&2
|
||||
rm -rf ${TMP}
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d ${TMP}/mt/\# ] ; then
|
||||
echo "ERROR Mtree update failed to create name with '#' char" 1>&2
|
||||
rm -rf ${TMP}
|
||||
exit 1
|
||||
fi
|
||||
rmdir ${TMP}/mr/\#
|
||||
|
||||
rm -rf ${TMP}
|
||||
exit 0
|
@ -1,40 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2003 Poul-Henning Kamp
|
||||
# All rights reserved.
|
||||
#
|
||||
# Please see src/share/examples/etc/bsd-style-copyright.
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
TMP=/tmp/mtree.$$
|
||||
|
||||
rm -rf ${TMP}
|
||||
mkdir -p ${TMP} ${TMP}/mr ${TMP}/mt
|
||||
|
||||
|
||||
ln -s "xx this=is=wrong" ${TMP}/mr/foo
|
||||
mtree -c -p ${TMP}/mr > ${TMP}/_
|
||||
|
||||
if mtree -U -r -p ${TMP}/mt < ${TMP}/_ > /dev/null 2>&1 ; then
|
||||
true
|
||||
else
|
||||
echo "ERROR Mtree failed on symlink with space char" 1>&2
|
||||
rm -rf ${TMP}
|
||||
exit 1
|
||||
fi
|
||||
|
||||
x=x`(cd ${TMP}/mr ; ls -l foo 2>&1) || true`
|
||||
y=x`(cd ${TMP}/mt ; ls -l foo 2>&1) || true`
|
||||
|
||||
if [ "$x" != "$y" ] ; then
|
||||
echo "ERROR Recreation of spaced symlink failed" 1>&2
|
||||
rm -rf ${TMP}
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -rf ${TMP}
|
||||
exit 0
|
@ -1,36 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2003 Dan Nelson
|
||||
# All rights reserved.
|
||||
#
|
||||
# Please see src/share/examples/etc/bsd-style-copyright.
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
TMP=/tmp/mtree.$$
|
||||
|
||||
rm -rf ${TMP}
|
||||
mkdir -p ${TMP} ${TMP}/mr ${TMP}/mt
|
||||
|
||||
touch -t 199901020304 ${TMP}/mr/oldfile
|
||||
touch ${TMP}/mt/oldfile
|
||||
|
||||
mtree -c -p ${TMP}/mr > ${TMP}/_
|
||||
|
||||
mtree -U -r -p ${TMP}/mt < ${TMP}/_ > /dev/null
|
||||
|
||||
x=x`(cd ${TMP}/mr ; ls -l 2>&1) || true`
|
||||
y=x`(cd ${TMP}/mt ; ls -l 2>&1) || true`
|
||||
|
||||
if [ "$x" != "$y" ] ; then
|
||||
echo "ERROR Update of mtime failed" 1>&2
|
||||
rm -rf ${TMP}
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -rf ${TMP}
|
||||
exit 0
|
||||
|
@ -1,60 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2003 Poul-Henning Kamp
|
||||
# All rights reserved.
|
||||
#
|
||||
# Please see src/share/examples/etc/bsd-style-copyright.
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
TMP=/tmp/mtree.$$
|
||||
|
||||
rm -rf ${TMP}
|
||||
mkdir -p ${TMP}
|
||||
|
||||
K=uid,uname,gid,gname,flags,md5digest,size,ripemd160digest,sha1digest,sha256digest,cksum
|
||||
|
||||
rm -rf _FOO
|
||||
mkdir _FOO
|
||||
touch _FOO/_uid
|
||||
touch _FOO/_size
|
||||
touch _FOO/zztype
|
||||
|
||||
touch _FOO/_bar
|
||||
mtree -c -K $K -p .. > ${TMP}/_r
|
||||
mtree -c -K $K -p .. > ${TMP}/_r2
|
||||
rm -rf _FOO/_bar
|
||||
|
||||
rm -rf _FOO/zztype
|
||||
mkdir _FOO/zztype
|
||||
|
||||
date > _FOO/_size
|
||||
|
||||
chown nobody _FOO/_uid
|
||||
|
||||
touch _FOO/_foo
|
||||
mtree -c -K $K -p .. > ${TMP}/_t
|
||||
|
||||
rm -fr _FOO
|
||||
|
||||
if mtree -f ${TMP}/_r -f ${TMP}/_r2 ; then
|
||||
true
|
||||
else
|
||||
echo "ERROR Compare identical failed" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if mtree -f ${TMP}/_r -f ${TMP}/_t > ${TMP}/_ ; then
|
||||
echo "ERROR Compare different succeeded" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ `wc -l < ${TMP}/_` -ne 10 ] ; then
|
||||
echo "ERROR wrong number of lines: `wc -l ${TMP}/_`" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
@ -1,51 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2003 Dan Nelson
|
||||
# All rights reserved.
|
||||
#
|
||||
# Please see src/share/examples/etc/bsd-style-copyright.
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
TMP=/tmp/mtree.$$
|
||||
|
||||
rm -rf ${TMP}
|
||||
mkdir -p ${TMP} ${TMP}/mr ${TMP}/mt
|
||||
|
||||
mkdir ${TMP}/mr/a
|
||||
mkdir ${TMP}/mr/b
|
||||
mkdir ${TMP}/mt/a
|
||||
mkdir ${TMP}/mt/b
|
||||
touch ${TMP}/mt/z
|
||||
|
||||
mtree -c -p ${TMP}/mr > ${TMP}/_r
|
||||
mtree -c -p ${TMP}/mt > ${TMP}/_t
|
||||
|
||||
if mtree -f ${TMP}/_r -f ${TMP}/_t > ${TMP}/_ ; then
|
||||
echo "ERROR wrong exit on difference" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ `wc -l < ${TMP}/_` -ne 1 ] ; then
|
||||
echo "ERROR spec/spec compare generated wrong output" 1>&2
|
||||
rm -rf ${TMP}
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if mtree -f ${TMP}/_t -f ${TMP}/_r > ${TMP}/_ ; then
|
||||
echo "ERROR wrong exit on difference" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ `wc -l < ${TMP}/_` -ne 1 ] ; then
|
||||
echo "ERROR spec/spec compare generated wrong output" 1>&2
|
||||
rm -rf ${TMP}
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -rf ${TMP}
|
||||
exit 0
|
||||
|
@ -1,25 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
# Test for 'optional' keyword.
|
||||
#
|
||||
|
||||
TMP=`mktemp -d /tmp/mtree.XXXXXX`
|
||||
mkdir -p ${TMP}/mr ${TMP}/mr/optional-dir ${TMP}/mr/some-dir
|
||||
touch ${TMP}/mr/optional-file ${TMP}/mr/some-file
|
||||
|
||||
mtree -c -p ${TMP}/mr > ${TMP}/_
|
||||
rm -rf ${TMP}/mr/optional-file ${TMP}/mr/optional-dir
|
||||
mtree -p ${TMP}/mr -K optional < ${TMP}/_ > /dev/null
|
||||
|
||||
res=$?
|
||||
|
||||
if [ $res -ne 0 ] ; then
|
||||
echo "ERROR 'optional' keyword failed" 1>&2
|
||||
rm -rf ${TMP}
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -rf ${TMP}
|
||||
exit 0
|
@ -1,261 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)verify.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fts.h>
|
||||
#include <fnmatch.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include "mtree.h"
|
||||
#include "extern.h"
|
||||
|
||||
static NODE *root;
|
||||
static char path[MAXPATHLEN];
|
||||
|
||||
static void miss(NODE *, char *);
|
||||
static int vwalk(void);
|
||||
|
||||
int
|
||||
mtree_verifyspec(FILE *fi)
|
||||
{
|
||||
int rval;
|
||||
|
||||
root = mtree_readspec(fi);
|
||||
rval = vwalk();
|
||||
miss(root, path);
|
||||
return (rval);
|
||||
}
|
||||
|
||||
static int
|
||||
nsort(const FTSENT * const *a, const FTSENT * const *b)
|
||||
{
|
||||
return (strcmp((*a)->fts_name, (*b)->fts_name));
|
||||
}
|
||||
|
||||
static int
|
||||
vwalk(void)
|
||||
{
|
||||
FTS *t;
|
||||
FTSENT *p;
|
||||
NODE *ep, *level;
|
||||
int specdepth, rval;
|
||||
char *argv[2];
|
||||
char dot[] = ".";
|
||||
|
||||
argv[0] = dot;
|
||||
argv[1] = NULL;
|
||||
if ((t = fts_open(argv, ftsoptions, nsort)) == NULL)
|
||||
err(1, "line %d: fts_open", lineno);
|
||||
level = root;
|
||||
specdepth = rval = 0;
|
||||
while (errno = 0, (p = fts_read(t))) {
|
||||
if (check_excludes(p->fts_name, p->fts_path)) {
|
||||
fts_set(t, p, FTS_SKIP);
|
||||
continue;
|
||||
}
|
||||
switch(p->fts_info) {
|
||||
case FTS_D:
|
||||
case FTS_SL:
|
||||
break;
|
||||
case FTS_DP:
|
||||
if (specdepth > p->fts_level) {
|
||||
for (level = level->parent; level->prev;
|
||||
level = level->prev);
|
||||
--specdepth;
|
||||
}
|
||||
continue;
|
||||
case FTS_DNR:
|
||||
case FTS_ERR:
|
||||
case FTS_NS:
|
||||
warnx("%s: %s", RP(p), strerror(p->fts_errno));
|
||||
continue;
|
||||
default:
|
||||
if (dflag)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (specdepth != p->fts_level)
|
||||
goto extra;
|
||||
for (ep = level; ep; ep = ep->next)
|
||||
if ((ep->flags & F_MAGIC &&
|
||||
!fnmatch(ep->name, p->fts_name, FNM_PATHNAME)) ||
|
||||
!strcmp(ep->name, p->fts_name)) {
|
||||
ep->flags |= F_VISIT;
|
||||
if ((ep->flags & F_NOCHANGE) == 0 &&
|
||||
compare(ep->name, ep, p))
|
||||
rval = MISMATCHEXIT;
|
||||
if (ep->flags & F_IGN)
|
||||
(void)fts_set(t, p, FTS_SKIP);
|
||||
else if (ep->child && ep->type == F_DIR &&
|
||||
p->fts_info == FTS_D) {
|
||||
level = ep->child;
|
||||
++specdepth;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (ep)
|
||||
continue;
|
||||
extra:
|
||||
if (!eflag) {
|
||||
(void)printf("%s extra", RP(p));
|
||||
if (rflag) {
|
||||
if ((S_ISDIR(p->fts_statp->st_mode)
|
||||
? rmdir : unlink)(p->fts_accpath)) {
|
||||
(void)printf(", not removed: %s",
|
||||
strerror(errno));
|
||||
} else
|
||||
(void)printf(", removed");
|
||||
}
|
||||
(void)putchar('\n');
|
||||
}
|
||||
(void)fts_set(t, p, FTS_SKIP);
|
||||
}
|
||||
if (errno != 0)
|
||||
err(1, "fts_read()");
|
||||
(void)fts_close(t);
|
||||
if (sflag)
|
||||
warnx("%s checksum: %lu", fullpath, (unsigned long)crc_total);
|
||||
return (rval);
|
||||
}
|
||||
|
||||
static void
|
||||
miss(NODE *p, char *tail)
|
||||
{
|
||||
int create;
|
||||
char *tp;
|
||||
const char *type, *what;
|
||||
int serr;
|
||||
|
||||
for (; p; p = p->next) {
|
||||
if (p->flags & F_OPT && !(p->flags & F_VISIT))
|
||||
continue;
|
||||
if (p->type != F_DIR && (dflag || p->flags & F_VISIT))
|
||||
continue;
|
||||
(void)strcpy(tail, p->name);
|
||||
if (!(p->flags & F_VISIT)) {
|
||||
/* Don't print missing message if file exists as a
|
||||
symbolic link and the -q flag is set. */
|
||||
struct stat statbuf;
|
||||
|
||||
if (qflag && stat(path, &statbuf) == 0)
|
||||
p->flags |= F_VISIT;
|
||||
else
|
||||
(void)printf("%s missing", path);
|
||||
}
|
||||
if (p->type != F_DIR && p->type != F_LINK) {
|
||||
putchar('\n');
|
||||
continue;
|
||||
}
|
||||
|
||||
create = 0;
|
||||
if (p->type == F_LINK)
|
||||
type = "symlink";
|
||||
else
|
||||
type = "directory";
|
||||
if (!(p->flags & F_VISIT) && uflag) {
|
||||
if (!(p->flags & (F_UID | F_UNAME)))
|
||||
(void)printf(" (%s not created: user not specified)", type);
|
||||
else if (!(p->flags & (F_GID | F_GNAME)))
|
||||
(void)printf(" (%s not created: group not specified)", type);
|
||||
else if (p->type == F_LINK) {
|
||||
if (symlink(p->slink, path))
|
||||
(void)printf(" (symlink not created: %s)\n",
|
||||
strerror(errno));
|
||||
else
|
||||
(void)printf(" (created)\n");
|
||||
if (lchown(path, p->st_uid, p->st_gid) == -1) {
|
||||
serr = errno;
|
||||
if (p->st_uid == (uid_t)-1)
|
||||
what = "group";
|
||||
else if (lchown(path, (uid_t)-1,
|
||||
p->st_gid) == -1)
|
||||
what = "user & group";
|
||||
else {
|
||||
what = "user";
|
||||
errno = serr;
|
||||
}
|
||||
(void)printf("%s: %s not modified: %s"
|
||||
"\n", path, what, strerror(errno));
|
||||
}
|
||||
continue;
|
||||
} else if (!(p->flags & F_MODE))
|
||||
(void)printf(" (directory not created: mode not specified)");
|
||||
else if (mkdir(path, S_IRWXU))
|
||||
(void)printf(" (directory not created: %s)",
|
||||
strerror(errno));
|
||||
else {
|
||||
create = 1;
|
||||
(void)printf(" (created)");
|
||||
}
|
||||
}
|
||||
if (!(p->flags & F_VISIT))
|
||||
(void)putchar('\n');
|
||||
|
||||
for (tp = tail; *tp; ++tp);
|
||||
*tp = '/';
|
||||
miss(p->child, tp + 1);
|
||||
*tp = '\0';
|
||||
|
||||
if (!create && !uflag)
|
||||
continue;
|
||||
if (chown(path, p->st_uid, p->st_gid) == -1) {
|
||||
serr = errno;
|
||||
if (p->st_uid == (uid_t)-1)
|
||||
what = "group";
|
||||
else if (chown(path, (uid_t)-1, p->st_gid) == -1)
|
||||
what = "user & group";
|
||||
else {
|
||||
what = "user";
|
||||
errno = serr;
|
||||
}
|
||||
(void)printf("%s: %s not modified: %s\n",
|
||||
path, what, strerror(errno));
|
||||
}
|
||||
if (chmod(path, p->st_mode))
|
||||
(void)printf("%s: permissions not set: %s\n",
|
||||
path, strerror(errno));
|
||||
if ((p->flags & F_FLAGS) && p->st_flags &&
|
||||
chflags(path, p->st_flags))
|
||||
(void)printf("%s: file flags not set: %s\n",
|
||||
path, strerror(errno));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user