]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/mtree/verify.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / mtree / verify.c
1 /*      $NetBSD: verify.c,v 1.43 2012/10/05 01:31:05 christos Exp $     */
2
3 /*-
4  * Copyright (c) 1990, 1993
5  *      The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31
32 #if HAVE_NBTOOL_CONFIG_H
33 #include "nbtool_config.h"
34 #endif
35
36 #include <sys/cdefs.h>
37 #if defined(__RCSID) && !defined(lint)
38 #if 0
39 static char sccsid[] = "@(#)verify.c    8.1 (Berkeley) 6/6/93";
40 #else
41 __RCSID("$NetBSD: verify.c,v 1.43 2012/10/05 01:31:05 christos Exp $");
42 #endif
43 #endif /* not lint */
44
45 #include <sys/param.h>
46 #include <sys/stat.h>
47
48 #if ! HAVE_NBTOOL_CONFIG_H
49 #include <dirent.h>
50 #endif
51
52 #include <errno.h>
53 #include <fnmatch.h>
54 #include <stdio.h>
55 #include <string.h>
56 #include <unistd.h>
57
58 #include "extern.h"
59
60 static NODE *root;
61 static char path[MAXPATHLEN];
62
63 static void     miss(NODE *, char *);
64 static int      vwalk(void);
65
66 int
67 verify(FILE *fi)
68 {
69         int rval;
70
71         root = spec(fi);
72         rval = vwalk();
73         miss(root, path);
74         return (rval);
75 }
76
77 static int
78 vwalk(void)
79 {
80         FTS *t;
81         FTSENT *p;
82         NODE *ep, *level;
83         int specdepth, rval;
84         char *argv[2];
85         char  dot[] = ".";
86         argv[0] = dot;
87         argv[1] = NULL;
88
89         if ((t = fts_open(argv, ftsoptions, NULL)) == NULL)
90                 mtree_err("fts_open: %s", strerror(errno));
91         level = root;
92         specdepth = rval = 0;
93         while ((p = fts_read(t)) != NULL) {
94                 if (check_excludes(p->fts_name, p->fts_path)) {
95                         fts_set(t, p, FTS_SKIP);
96                         continue;
97                 }
98                 switch(p->fts_info) {
99                 case FTS_D:
100                 case FTS_SL:
101                         break;
102                 case FTS_DP:
103                         if (specdepth > p->fts_level) {
104                                 for (level = level->parent; level->prev;
105                                     level = level->prev)
106                                         continue;
107                                 --specdepth;
108                         }
109                         continue;
110                 case FTS_DNR:
111                 case FTS_ERR:
112                 case FTS_NS:
113                         warnx("%s: %s", RP(p), strerror(p->fts_errno));
114                         continue;
115                 default:
116                         if (dflag)
117                                 continue;
118                 }
119
120                 if (specdepth != p->fts_level)
121                         goto extra;
122                 for (ep = level; ep; ep = ep->next)
123                         if ((ep->flags & F_MAGIC &&
124                             !fnmatch(ep->name, p->fts_name, FNM_PATHNAME)) ||
125                             !strcmp(ep->name, p->fts_name)) {
126                                 ep->flags |= F_VISIT;
127                                 if ((ep->flags & F_NOCHANGE) == 0 &&
128                                     compare(ep, p))
129                                         rval = MISMATCHEXIT;
130                                 if (!(ep->flags & F_IGN) &&
131                                     ep->type == F_DIR &&
132                                     p->fts_info == FTS_D) {
133                                         if (ep->child) {
134                                                 level = ep->child;
135                                                 ++specdepth;
136                                         }
137                                 } else
138                                         fts_set(t, p, FTS_SKIP);
139                                 break;
140                         }
141
142                 if (ep)
143                         continue;
144  extra:
145                 if (!eflag && !(dflag && p->fts_info == FTS_SL)) {
146                         printf("extra: %s", RP(p));
147                         if (rflag) {
148                                 if ((S_ISDIR(p->fts_statp->st_mode)
149                                     ? rmdir : unlink)(p->fts_accpath)) {
150                                         printf(", not removed: %s",
151                                             strerror(errno));
152                                 } else
153                                         printf(", removed");
154                         }
155                         putchar('\n');
156                 }
157                 fts_set(t, p, FTS_SKIP);
158         }
159         fts_close(t);
160         if (sflag)
161                 warnx("%s checksum: %u", fullpath, crc_total);
162         return (rval);
163 }
164
165 static void
166 miss(NODE *p, char *tail)
167 {
168         int create;
169         char *tp;
170         const char *type;
171         u_int32_t flags;
172
173         for (; p; p = p->next) {
174                 if (p->flags & F_OPT && !(p->flags & F_VISIT))
175                         continue;
176                 if (p->type != F_DIR && (dflag || p->flags & F_VISIT))
177                         continue;
178                 strcpy(tail, p->name);
179                 if (!(p->flags & F_VISIT)) {
180                         /* Don't print missing message if file exists as a 
181                            symbolic link and the -q flag is set. */
182                         struct stat statbuf;
183
184                         if (qflag && stat(path, &statbuf) == 0 &&
185                             S_ISDIR(statbuf.st_mode))
186                                 p->flags |= F_VISIT;
187                         else
188                                 (void)printf("%s missing", path);
189                 }
190                 switch (p->type) {
191                 case F_BLOCK:
192                 case F_CHAR:
193                         type = "device";
194                         break;
195                 case F_DIR:
196                         type = "directory";
197                         break;
198                 case F_LINK:
199                         type = "symlink";
200                         break;
201                 default:
202                         putchar('\n');
203                         continue;
204                 }
205
206                 create = 0;
207                 if (!(p->flags & F_VISIT) && uflag) {
208                         if (mtree_Wflag || p->type == F_LINK)
209                                 goto createit;
210                         if (!(p->flags & (F_UID | F_UNAME)))
211                             printf(
212                                 " (%s not created: user not specified)", type);
213                         else if (!(p->flags & (F_GID | F_GNAME)))
214                             printf(
215                                 " (%s not created: group not specified)", type);
216                         else if (!(p->flags & F_MODE))
217                             printf(
218                                 " (%s not created: mode not specified)", type);
219                         else
220  createit:
221                         switch (p->type) {
222                         case F_BLOCK:
223                         case F_CHAR:
224                                 if (mtree_Wflag)
225                                         continue;
226                                 if (!(p->flags & F_DEV))
227                                         printf(
228                                     " (%s not created: device not specified)",
229                                             type);
230                                 else if (mknod(path,
231                                     p->st_mode | nodetoino(p->type),
232                                     p->st_rdev) == -1)
233                                         printf(" (%s not created: %s)\n",
234                                             type, strerror(errno));
235                                 else
236                                         create = 1;
237                                 break;
238                         case F_LINK:
239                                 if (!(p->flags & F_SLINK))
240                                         printf(
241                                     " (%s not created: link not specified)\n",
242                                             type);
243                                 else if (symlink(p->slink, path))
244                                         printf(
245                                             " (%s not created: %s)\n",
246                                             type, strerror(errno));
247                                 else
248                                         create = 1;
249                                 break;
250                         case F_DIR:
251                                 if (mkdir(path, S_IRWXU|S_IRWXG|S_IRWXO))
252                                         printf(" (not created: %s)",
253                                             strerror(errno));
254                                 else
255                                         create = 1;
256                                 break;
257                         default:
258                                 mtree_err("can't create create %s",
259                                     nodetype(p->type));
260                         }
261                 }
262                 if (create)
263                         printf(" (created)");
264                 if (p->type == F_DIR) {
265                         if (!(p->flags & F_VISIT))
266                                 putchar('\n');
267                         for (tp = tail; *tp; ++tp)
268                                 continue;
269                         *tp = '/';
270                         miss(p->child, tp + 1);
271                         *tp = '\0';
272                 } else
273                         putchar('\n');
274
275                 if (!create || mtree_Wflag)
276                         continue;
277                 if ((p->flags & (F_UID | F_UNAME)) &&
278                     (p->flags & (F_GID | F_GNAME)) &&
279                     (lchown(path, p->st_uid, p->st_gid))) {
280                         printf("%s: user/group/mode not modified: %s\n",
281                             path, strerror(errno));
282                         printf("%s: warning: file mode %snot set\n", path,
283                             (p->flags & F_FLAGS) ? "and file flags " : "");
284                         continue;
285                 }
286                 if (p->flags & F_MODE) {
287                         if (lchmod(path, p->st_mode))
288                                 printf("%s: permissions not set: %s\n",
289                                     path, strerror(errno));
290                 }
291 #if HAVE_STRUCT_STAT_ST_FLAGS
292                 if ((p->flags & F_FLAGS) && p->st_flags) {
293                         if (iflag)
294                                 flags = p->st_flags;
295                         else
296                                 flags = p->st_flags & ~SP_FLGS;
297                         if (lchflags(path, flags))
298                                 printf("%s: file flags not set: %s\n",
299                                     path, strerror(errno));
300                 }
301 #endif  /* HAVE_STRUCT_STAT_ST_FLAGS */
302         }
303 }