xref: /original-bsd/usr.bin/chflags/chflags.c (revision 16bc4816)
1 /*
2  * Copyright (c) 1992 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 char copyright[] =
10 "@(#) Copyright (c) 1992 The Regents of the University of California.\n\
11  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)chflags.c	5.3 (Berkeley) 06/01/92";
16 #endif /* not lint */
17 
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <errno.h>
21 #include <fts.h>
22 #include <unistd.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 typedef struct cmdset {
28 	long clrbits;
29 	long setbits;
30 } CMDS;
31 CMDS cmds;
32 int retval;
33 
34 void	 err __P((const char *, ...));
35 void	 error __P((char *));
36 int	 getflags __P((CMDS *, int));
37 void	*setflags __P((char *));
38 void	 usage __P((void));
39 
40 int
41 main(argc, argv)
42 	int argc;
43 	char *argv[];
44 {
45 	register FTS *ftsp;
46 	register FTSENT *p;
47 	register long oflags;
48 	register int oct;
49 	register char *flags;
50 	struct stat sb;
51 	void *set;
52 	int ch, rflag, hflag, Hflag;
53 	char *ep;
54 	int fts_options;
55 
56 	rflag = hflag = Hflag = 0;
57 	fts_options = FTS_PHYSICAL;
58 	while ((ch = getopt(argc, argv, "HRh")) != EOF)
59 		switch((char)ch) {
60 		case 'H':
61 			Hflag = 1;
62 			fts_options |= FTS_COMFOLLOW;
63 			break;
64 		case 'R':
65 			rflag = 1;
66 			break;
67 		case 'h':
68 			hflag = 1;
69 			fts_options &= ~FTS_PHYSICAL;
70 			fts_options |= FTS_LOGICAL;
71 			break;
72       		case '?':
73 		default:
74 			usage();
75 		}
76 	argv += optind;
77 	argc -= optind;
78 
79 	if (argc < 2)
80 		usage();
81 
82 	flags = *argv;
83 	if (*flags >= '0' && *flags <= '7') {
84 		oflags = (int)strtol(flags, &ep, 8);
85                 if (oflags < 0 || *ep)
86                         err("invalid flags: %s", flags);
87                 oct = 1;
88 	} else {
89 		if ((set = setflags(flags)) == NULL)
90                         err("invalid flags: %s", flags);
91 		oct = 0;
92 	}
93 
94 	retval = 0;
95 	if (oct)
96 		fts_options |= FTS_NOSTAT;
97 	if (!(ftsp = fts_open(++argv, fts_options , 0)))
98 		err("%s", strerror(errno));
99 	while (p = fts_read(ftsp))
100 		switch(p->fts_info) {
101 		case FTS_D:
102 			if (!rflag)
103 				fts_set(ftsp, p, FTS_SKIP);
104 			break;
105 		case FTS_DNR:
106 		case FTS_ERR:
107 		case FTS_NS:
108 			err("%s: %s", p->fts_path, strerror(errno));
109 		default:
110                         if (p->fts_info == FTS_SL &&
111                             !(hflag ||
112                             (Hflag && p->fts_level == FTS_ROOTLEVEL)))
113 				continue;
114 			if (chflags(p->fts_accpath, oct ? oflags :
115 			    getflags(set, p->fts_statp->st_flags)))
116 				error(p->fts_path);
117 			break;
118 		}
119 	exit(retval);
120 }
121 
122 /*
123  * These are analogous to the setmode/getmode routines in the C library.
124  */
125 void *
126 setflags(cp)
127 	char *cp;
128 {
129 	register CMDS *fset;
130 	register char *arg;
131 
132 	fset = &cmds;
133 	fset->clrbits = 0;
134 	fset->setbits = 0;
135 	while (cp) {
136 		while ((arg = strsep(&cp, ",")) != NULL && *arg == '\0')
137 			/* void */;
138 		if (!strcasecmp(arg, "dump"))
139 			fset->clrbits |= NODUMP;
140 		else if (!strcasecmp(arg, "nodump"))
141 			fset->setbits |= NODUMP;
142 		else
143 			return (NULL);
144 	}
145 	return (fset);
146 }
147 
148 int
149 getflags(fset, oflags)
150 	register CMDS *fset;
151 	register int oflags;
152 {
153 
154 	oflags &= ~fset->clrbits;
155 	oflags |= fset->setbits;
156 	return (oflags);
157 }
158 
159 #if __STDC__
160 #include <stdarg.h>
161 #else
162 #include <varargs.h>
163 #endif
164 
165 void
166 #if __STDC__
167 err(const char *fmt, ...)
168 #else
169 err(fmt, va_alist)
170 	char *fmt;
171         va_dcl
172 #endif
173 {
174 	va_list ap;
175 #if __STDC__
176 	va_start(ap, fmt);
177 #else
178 	va_start(ap);
179 #endif
180 	(void)fprintf(stderr, "chflags: ");
181 	(void)vfprintf(stderr, fmt, ap);
182 	va_end(ap);
183 	(void)fprintf(stderr, "\n");
184 	exit(1);
185 	/* NOTREACHED */
186 }
187 
188 void
189 error(name)
190 	char *name;
191 {
192 	(void)fprintf(stderr, "chflags: %s: %s.\n", name, strerror(errno));
193 	retval = 1;
194 }
195 
196 void
197 usage()
198 {
199 	(void)fprintf(stderr, "usage: chflags [-HRh] flags file ...\n");
200 	exit(1);
201 }
202