142302Sbostic /*-
2*61857Sbostic * Copyright (c) 1990, 1993
3*61857Sbostic * The Regents of the University of California. All rights reserved.
442302Sbostic *
542302Sbostic * %sccs.include.redist.c%
642302Sbostic */
742302Sbostic
842302Sbostic #ifndef lint
9*61857Sbostic static char sccsid[] = "@(#)verify.c 8.1 (Berkeley) 06/06/93";
1042302Sbostic #endif /* not lint */
1142302Sbostic
1242336Sbostic #include <sys/param.h>
1342302Sbostic #include <sys/stat.h>
1442336Sbostic #include <dirent.h>
1542336Sbostic #include <fts.h>
1654711Sbostic #include <fnmatch.h>
1742337Sbostic #include <unistd.h>
1842302Sbostic #include <errno.h>
1942302Sbostic #include <stdio.h>
2042302Sbostic #include "mtree.h"
2151884Sbostic #include "extern.h"
2242302Sbostic
2351884Sbostic extern int crc_total, ftsoptions;
2451884Sbostic extern int dflag, eflag, rflag, sflag, uflag;
2551884Sbostic extern char fullpath[MAXPATHLEN];
2642302Sbostic
2751884Sbostic static NODE *root;
2842336Sbostic static char path[MAXPATHLEN];
2942302Sbostic
3051884Sbostic static void miss __P((NODE *, char *));
3151884Sbostic static int vwalk __P((void));
3251884Sbostic
3351884Sbostic int
verify()3442302Sbostic verify()
3542302Sbostic {
3651884Sbostic int rval;
3751884Sbostic
3851884Sbostic root = spec();
3951884Sbostic rval = vwalk();
4042336Sbostic miss(root, path);
4151884Sbostic return (rval);
4242302Sbostic }
4342302Sbostic
4451884Sbostic static int
vwalk()4542336Sbostic vwalk()
4642302Sbostic {
4742336Sbostic register FTS *t;
4842336Sbostic register FTSENT *p;
4942340Sbostic register NODE *ep, *level;
5051884Sbostic int ftsdepth, specdepth, rval;
5143891Sbostic char *argv[2];
5242302Sbostic
5343891Sbostic argv[0] = ".";
5451884Sbostic argv[1] = NULL;
5551884Sbostic if ((t = fts_open(argv, ftsoptions, NULL)) == NULL)
5651884Sbostic err("fts_open: %s", strerror(errno));
5742336Sbostic level = root;
5851884Sbostic ftsdepth = specdepth = rval = 0;
5945604Sbostic while (p = fts_read(t)) {
6042336Sbostic switch(p->fts_info) {
6142336Sbostic case FTS_D:
6251884Sbostic ++ftsdepth;
6342336Sbostic break;
6442336Sbostic case FTS_DP:
6551884Sbostic --ftsdepth;
6644864Strent if (specdepth > ftsdepth) {
6744864Strent for (level = level->parent; level->prev;
6844864Strent level = level->prev);
6951884Sbostic --specdepth;
7044864Strent }
7142336Sbostic continue;
7247239Sbostic case FTS_DNR:
7342336Sbostic case FTS_ERR:
7447239Sbostic case FTS_NS:
7551884Sbostic (void)fprintf(stderr, "mtree: %s: %s\n",
7642336Sbostic RP(p), strerror(errno));
7742336Sbostic continue;
7842336Sbostic default:
7942336Sbostic if (dflag)
8042336Sbostic continue;
8142302Sbostic }
8242336Sbostic
8342336Sbostic for (ep = level; ep; ep = ep->next)
8454711Sbostic if (ep->flags & F_MAGIC &&
8554711Sbostic !fnmatch(ep->name, p->fts_name, FNM_PATHNAME) ||
8642337Sbostic !strcmp(ep->name, p->fts_name)) {
8742302Sbostic ep->flags |= F_VISIT;
8851884Sbostic if (compare(ep->name, ep, p))
8951884Sbostic rval = MISMATCHEXIT;
9053191Sbostic if (ep->flags & F_IGN)
9153191Sbostic (void)fts_set(t, p, FTS_SKIP);
9253191Sbostic else if (ep->child && ep->type == F_DIR &&
9344864Strent p->fts_info == FTS_D) {
9442336Sbostic level = ep->child;
9551884Sbostic ++specdepth;
9644864Strent }
9742336Sbostic break;
9842302Sbostic }
9944864Strent
10042336Sbostic if (ep)
10142336Sbostic continue;
10242336Sbostic if (!eflag) {
10342336Sbostic (void)printf("extra: %s", RP(p));
10442336Sbostic if (rflag) {
10542336Sbostic if (unlink(p->fts_accpath)) {
10642336Sbostic (void)printf(", not removed: %s",
10742336Sbostic strerror(errno));
10842336Sbostic } else
10942336Sbostic (void)printf(", removed");
11042302Sbostic }
11142336Sbostic (void)putchar('\n');
11242302Sbostic }
11345604Sbostic (void)fts_set(t, p, FTS_SKIP);
11442302Sbostic }
11545604Sbostic (void)fts_close(t);
11651884Sbostic if (sflag)
11751884Sbostic (void)fprintf(stderr,
11851884Sbostic "mtree: %s checksum: %lu\n", fullpath, crc_total);
11951884Sbostic return (rval);
12042302Sbostic }
12142302Sbostic
12251884Sbostic static void
miss(p,tail)12342336Sbostic miss(p, tail)
12442340Sbostic register NODE *p;
12542302Sbostic register char *tail;
12642302Sbostic {
12742302Sbostic register int create;
12842336Sbostic register char *tp;
12942302Sbostic
13042336Sbostic for (; p; p = p->next) {
13142340Sbostic if (p->type != F_DIR && (dflag || p->flags & F_VISIT))
13242302Sbostic continue;
13342336Sbostic (void)strcpy(tail, p->name);
13442340Sbostic if (!(p->flags & F_VISIT))
13542336Sbostic (void)printf("missing: %s", path);
13642340Sbostic if (p->type != F_DIR) {
13742336Sbostic putchar('\n');
13842336Sbostic continue;
13942336Sbostic }
14042336Sbostic
14142302Sbostic create = 0;
14242340Sbostic if (!(p->flags & F_VISIT) && uflag)
14351884Sbostic if (!(p->flags & (F_UID | F_UNAME)))
14451884Sbostic (void)printf(" (not created: user not specified)");
14551884Sbostic else if (!(p->flags & (F_GID | F_GNAME)))
14651884Sbostic (void)printf(" (not created: group not specified)");
14751884Sbostic else if (!(p->flags & F_MODE))
14851884Sbostic (void)printf(" (not created: mode not specified)");
14942336Sbostic else if (mkdir(path, S_IRWXU))
15042336Sbostic (void)printf(" (not created: %s)",
15142302Sbostic strerror(errno));
15242302Sbostic else {
15342302Sbostic create = 1;
15442336Sbostic (void)printf(" (created)");
15542302Sbostic }
15642302Sbostic
15742340Sbostic if (!(p->flags & F_VISIT))
15842336Sbostic (void)putchar('\n');
15942302Sbostic
16042336Sbostic for (tp = tail; *tp; ++tp);
16142336Sbostic *tp = '/';
16242336Sbostic miss(p->child, tp + 1);
16342336Sbostic *tp = '\0';
16442336Sbostic
16542336Sbostic if (!create)
16642336Sbostic continue;
16742340Sbostic if (chown(path, p->st_uid, p->st_gid)) {
16851884Sbostic (void)printf("%s: user/group/mode not modified: %s\n",
16942336Sbostic path, strerror(errno));
17042336Sbostic continue;
17142336Sbostic }
17242340Sbostic if (chmod(path, p->st_mode))
17342336Sbostic (void)printf("%s: permissions not set: %s\n",
17442336Sbostic path, strerror(errno));
17542302Sbostic }
17642302Sbostic }
177