xref: /original-bsd/usr.bin/chflags/chflags.c (revision e3fc45e1)
1 /*
2  * Copyright (c) 1989 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) 1989 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.1 (Berkeley) 12/12/91";
16 #endif /* not lint */
17 
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fts.h>
21 #include <stdio.h>
22 #include <string.h>
23 
24 extern int errno;
25 int retval;
26 
27 main(argc, argv)
28 	int argc;
29 	char **argv;
30 {
31 	extern int optind;
32 	register FTS *fts;
33 	register FTSENT *p;
34 	register int oct, oflags;
35 	register char *flags;
36 	void *set, *setflags();
37 	struct stat sb;
38 	int ch, fflag, rflag;
39 
40 	fflag = rflag = 0;
41 	while ((ch = getopt(argc, argv, "Rf")) != EOF)
42 		switch((char)ch) {
43 		case 'R':
44 			rflag = 1;
45 			break;
46 		case 'f':		/* no longer documented */
47 			fflag = 1;
48 			break;
49 		case '?':
50 		default:
51 			usage();
52 		}
53 	argv += optind;
54 	argc -= optind;
55 
56 	if (argc < 2)
57 		usage();
58 
59 	flags = *argv;
60 	if (*flags >= '0' && *flags <= '7') {
61 		oflags = (int)strtol(flags, (char **)NULL, 8);
62 		oct = 1;
63 	} else {
64 		if (!(set = setflags(flags))) {
65 			(void)fprintf(stderr, "chflags: invalid flags.\n");
66 			exit(1);
67 		}
68 		oct = 0;
69 	}
70 
71 	retval = 0;
72 	if (rflag) {
73 		if (!(fts = fts_open(++argv,
74 		    oct ? FTS_NOSTAT|FTS_PHYSICAL : FTS_PHYSICAL, 0))) {
75 			(void)fprintf(stderr, "chflags: %s.\n",
76 			    strerror(errno));
77 			exit(1);
78 		}
79 		while (p = fts_read(fts))
80 			switch(p->fts_info) {
81 			case FTS_D:
82 				break;
83 			case FTS_DNR:
84 			case FTS_ERR:
85 			case FTS_NS:
86 				(void)fprintf(stderr, "chflags: %s: %s.\n",
87 				    p->fts_path, strerror(errno));
88 				exit(1);
89 			default:
90 				if (chflags(p->fts_accpath, oct ? oflags :
91 				    getflags(set, p->fts_statb.st_flags)) &&
92 				    !fflag)
93 					error(p->fts_path);
94 				break;
95 			}
96 		exit(retval);
97 	}
98 	if (oct) {
99 		while (*++argv)
100 			if (chflags(*argv, oflags) && !fflag)
101 				error(*argv);
102 	} else
103 		while (*++argv)
104 			if ((lstat(*argv, &sb) ||
105 			    chflags(*argv, getflags(set, sb.st_flags))) &&
106 			    !fflag)
107 				error(*argv);
108 	exit(retval);
109 }
110 
111 error(name)
112 	char *name;
113 {
114 	(void)fprintf(stderr, "chflags: %s: %s.\n", name, strerror(errno));
115 	retval = 1;
116 }
117 
118 usage()
119 {
120 	(void)fprintf(stderr, "Usage: chflags [-R] flags file ...\n");
121 	exit(1);
122 }
123 
124 /*
125  * These are analogous to the setmode/getmode routines in the C library.
126  */
127 struct cmdset {
128 	long	clrbits;
129 	long	setbits;
130 } cmds;
131 
132 void *
133 setflags(cp)
134 	char *cp;
135 {
136 	register struct cmdset *fset;
137 	register char *arg;
138 
139 	fset = &cmds;
140 	fset->clrbits = 0;
141 	fset->setbits = 0;
142 	while (cp) {
143 		while ((arg = strsep(&cp, ",")) != NULL && *arg == '\0')
144 			/* void */;
145 		if (!strcasecmp(arg, "dump"))
146 			fset->clrbits |= NODUMP;
147 		else if (!strcasecmp(arg, "nodump"))
148 			fset->setbits |= NODUMP;
149 		else
150 			return (NULL);
151 	}
152 	return (fset);
153 }
154 
155 getflags(fset, oflags)
156 	register struct cmdset *fset;
157 	register int oflags;
158 {
159 
160 	oflags &= ~fset->clrbits;
161 	oflags |= fset->setbits;
162 	return (oflags);
163 }
164