GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/mtree/verify.c Lines: 51 90 56.7 %
Date: 2017-11-07 Branches: 50 102 49.0 %

Line Branch Exec Source
1
/*	$OpenBSD: verify.c,v 1.21 2016/08/16 16:41:46 krw Exp $	*/
2
/*	$NetBSD: verify.c,v 1.10 1995/03/07 21:26:28 cgd Exp $	*/
3
4
/*-
5
 * Copyright (c) 1990, 1993
6
 *	The Regents of the University of California.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 */
32
33
#include <sys/stat.h>
34
#include <dirent.h>
35
#include <fts.h>
36
#include <fnmatch.h>
37
#include <unistd.h>
38
#include <errno.h>
39
#include <stdio.h>
40
#include <limits.h>
41
#include "mtree.h"
42
#include "extern.h"
43
44
extern u_int32_t crc_total;
45
extern int ftsoptions;
46
extern int dflag, eflag, qflag, rflag, sflag, uflag;
47
extern char fullpath[PATH_MAX];
48
49
static NODE *root;
50
static char path[PATH_MAX];
51
52
static void	miss(NODE *, char *, size_t);
53
static int	vwalk(void);
54
55
int
56
verify(void)
57
{
58
	int rval;
59
60
20
	root = spec();
61
10
	rval = vwalk();
62
10
	miss(root, path, sizeof(path));
63
10
	return (rval);
64
}
65
66
static int
67
vwalk(void)
68
{
69
	FTS *t;
70
	FTSENT *p;
71
	NODE *ep, *level;
72
	int specdepth, rval;
73
20
	char *argv[2];
74
75
10
	argv[0] = ".";
76
10
	argv[1] = NULL;
77
10
	if ((t = fts_open(argv, ftsoptions, dsort)) == NULL)
78
		error("fts_open: %s", strerror(errno));
79
10
	level = root;
80
	specdepth = rval = 0;
81
24485
	while ((p = fts_read(t))) {
82

23808
		switch(p->fts_info) {
83
		case FTS_D:
84
			break;
85
		case FTS_DP:
86
1409
			if (specdepth > p->fts_level) {
87
2012
				for (level = level->parent; level->prev;
88
				      level = level->prev);
89
130
				--specdepth;
90
130
			}
91
			continue;
92
		case FTS_DNR:
93
		case FTS_ERR:
94
		case FTS_NS:
95
			(void)fprintf(stderr, "mtree: %s: %s\n",
96
			    RP(p), strerror(p->fts_errno));
97
			continue;
98
		default:
99
19595
			if (dflag)
100
				continue;
101
		}
102
103
2804
		if (specdepth != p->fts_level)
104
			goto extra;
105
33632
		for (ep = level; ep; ep = ep->next)
106

30466
			if ((ep->flags & F_MAGIC &&
107
			    !fnmatch(ep->name, p->fts_name, FNM_PATHNAME)) ||
108
15233
			    !strcmp(ep->name, p->fts_name)) {
109
752
				ep->flags |= F_VISIT;
110

1502
				if ((ep->flags & F_NOCHANGE) == 0 &&
111
750
				    compare(ep->name, ep, p))
112
1
					rval = MISMATCHEXIT;
113
752
				if (ep->flags & F_IGN)
114
18
					(void)fts_set(t, p, FTS_SKIP);
115

994
				else if (ep->child && ep->type == F_DIR &&
116
130
				    p->fts_info == FTS_D) {
117
					level = ep->child;
118
130
					++specdepth;
119
130
				}
120
				break;
121
			}
122
123
2335
		if (ep)
124
			continue;
125
extra:
126
2052
		if (!eflag) {
127
			(void)printf("extra: %s", RP(p));
128
			if (rflag) {
129
				if ((S_ISDIR(p->fts_statp->st_mode)
130
				    ? rmdir : unlink)(p->fts_accpath)) {
131
					(void)printf(", not removed: %s",
132
					    strerror(errno));
133
					rval = ERROREXIT;
134
				} else
135
					(void)printf(", removed");
136
			} else
137
				rval = MISMATCHEXIT;
138
			(void)putchar('\n');
139
		}
140
2052
		(void)fts_set(t, p, FTS_SKIP);
141
	}
142
10
	(void)fts_close(t);
143
10
	if (sflag)
144
		(void)fprintf(stderr,
145
		    "mtree: %s checksum: %u\n", fullpath, crc_total);
146
10
	return (rval);
147
10
}
148
149
static void
150
miss(NODE *p, char *tail, size_t len)
151
{
152
	int create;
153
	char *tp;
154
155
3710
	for (; p; p = p->next) {
156

888
		if ((p->flags & F_OPT) && !(p->flags & F_VISIT))
157
			continue;
158

880
		if (p->type != F_DIR && (dflag || p->flags & F_VISIT))
159
			continue;
160
688
		(void)strlcpy(tail, p->name, len);
161
688
		if (!(p->flags & F_VISIT)) {
162
			/* Don't print missing message if file exists as a
163
			   symbolic link and the -q flag is set. */
164
			struct stat statbuf;
165
166
			if (qflag && stat(path, &statbuf) == 0)
167
				p->flags |= F_VISIT;
168
			else
169
				(void)printf("missing: %s", path);
170
		}
171
688
		if (p->type != F_DIR) {
172
			putchar('\n');
173
			continue;
174
		}
175
176
		create = 0;
177
688
		if (!(p->flags & F_VISIT) && uflag) {
178
			if (!(p->flags & (F_UID | F_UNAME)))
179
			    (void)printf(" (not created: user not specified)");
180
			else if (!(p->flags & (F_GID | F_GNAME)))
181
			    (void)printf(" (not created: group not specified)");
182
			else if (!(p->flags & F_MODE))
183
			    (void)printf(" (not created: mode not specified)");
184
			else if (mkdir(path, S_IRWXU))
185
				(void)printf(" (not created: %s)",
186
				    strerror(errno));
187
			else {
188
				create = 1;
189
				(void)printf(" (created)");
190
			}
191
		}
192
193
688
		if (!(p->flags & F_VISIT))
194
			(void)putchar('\n');
195
196
9344
		for (tp = tail; *tp; ++tp);
197
688
		*tp = '/';
198
688
		miss(p->child, tp + 1, len - (tp + 1 - tail));
199
688
		*tp = '\0';
200
201
688
		if (!create)
202
			continue;
203
		if (chown(path, p->st_uid, p->st_gid)) {
204
			(void)printf("%s: user/group/mode not modified: %s\n",
205
			    path, strerror(errno));
206
			continue;
207
		}
208
		if (chmod(path, p->st_mode))
209
			(void)printf("%s: permissions not set: %s\n",
210
			    path, strerror(errno));
211
	}
212
698
}