/[base]/head/bin/chmod/chmod.c
ViewVC logotype

Contents of /head/bin/chmod/chmod.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 326025 - (show annotations) (download)
Mon Nov 20 19:49:47 2017 UTC (6 years, 7 months ago) by pfg
File MIME type: text/plain
File size: 6606 byte(s)
General further adoption of SPDX licensing ID tags.

Mainly focus on files that use BSD 3-Clause license.

The Software Package Data Exchange (SPDX) group provides a specification
to make it easier for automated tools to detect and summarize well known
opensource licenses. We are gradually adopting the specification, noting
that the tags are considered only advisory and do not, in any way,
superceed or replace the license texts.

Special thanks to Wind River for providing access to "The Duke of
Highlander" tool: an older (2014) run over FreeBSD tree was useful as a
starting point.

1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1989, 1993, 1994
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 0
33 #ifndef lint
34 static char const copyright[] =
35 "@(#) Copyright (c) 1989, 1993, 1994\n\
36 The Regents of the University of California. All rights reserved.\n";
37 #endif /* not lint */
38
39 #ifndef lint
40 static char sccsid[] = "@(#)chmod.c 8.8 (Berkeley) 4/1/94";
41 #endif /* not lint */
42 #endif
43 #include <sys/cdefs.h>
44 __FBSDID("$FreeBSD$");
45
46 #include <sys/param.h>
47 #include <sys/stat.h>
48
49 #include <err.h>
50 #include <errno.h>
51 #include <fcntl.h>
52 #include <fts.h>
53 #include <limits.h>
54 #include <signal.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <unistd.h>
59
60 static volatile sig_atomic_t siginfo;
61
62 static void usage(void);
63 static int may_have_nfs4acl(const FTSENT *ent, int hflag);
64
65 static void
66 siginfo_handler(int sig __unused)
67 {
68
69 siginfo = 1;
70 }
71
72 int
73 main(int argc, char *argv[])
74 {
75 FTS *ftsp;
76 FTSENT *p;
77 mode_t *set;
78 int Hflag, Lflag, Rflag, ch, fflag, fts_options, hflag, rval;
79 int vflag;
80 char *mode;
81 mode_t newmode;
82
83 set = NULL;
84 Hflag = Lflag = Rflag = fflag = hflag = vflag = 0;
85 while ((ch = getopt(argc, argv, "HLPRXfghorstuvwx")) != -1)
86 switch (ch) {
87 case 'H':
88 Hflag = 1;
89 Lflag = 0;
90 break;
91 case 'L':
92 Lflag = 1;
93 Hflag = 0;
94 break;
95 case 'P':
96 Hflag = Lflag = 0;
97 break;
98 case 'R':
99 Rflag = 1;
100 break;
101 case 'f':
102 fflag = 1;
103 break;
104 case 'h':
105 /*
106 * In System V the -h option causes chmod to change
107 * the mode of the symbolic link. 4.4BSD's symbolic
108 * links didn't have modes, so it was an undocumented
109 * noop. In FreeBSD 3.0, lchmod(2) is introduced and
110 * this option does real work.
111 */
112 hflag = 1;
113 break;
114 /*
115 * XXX
116 * "-[rwx]" are valid mode commands. If they are the entire
117 * argument, getopt has moved past them, so decrement optind.
118 * Regardless, we're done argument processing.
119 */
120 case 'g': case 'o': case 'r': case 's':
121 case 't': case 'u': case 'w': case 'X': case 'x':
122 if (argv[optind - 1][0] == '-' &&
123 argv[optind - 1][1] == ch &&
124 argv[optind - 1][2] == '\0')
125 --optind;
126 goto done;
127 case 'v':
128 vflag++;
129 break;
130 case '?':
131 default:
132 usage();
133 }
134 done: argv += optind;
135 argc -= optind;
136
137 if (argc < 2)
138 usage();
139
140 (void)signal(SIGINFO, siginfo_handler);
141
142 if (Rflag) {
143 if (hflag)
144 errx(1, "the -R and -h options may not be "
145 "specified together.");
146 if (Lflag) {
147 fts_options = FTS_LOGICAL;
148 } else {
149 fts_options = FTS_PHYSICAL;
150
151 if (Hflag) {
152 fts_options |= FTS_COMFOLLOW;
153 }
154 }
155 } else if (hflag) {
156 fts_options = FTS_PHYSICAL;
157 } else {
158 fts_options = FTS_LOGICAL;
159 }
160
161 mode = *argv;
162 if ((set = setmode(mode)) == NULL)
163 errx(1, "invalid file mode: %s", mode);
164
165 if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL)
166 err(1, "fts_open");
167 for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
168 int atflag;
169
170 if ((fts_options & FTS_LOGICAL) ||
171 ((fts_options & FTS_COMFOLLOW) &&
172 p->fts_level == FTS_ROOTLEVEL))
173 atflag = 0;
174 else
175 atflag = AT_SYMLINK_NOFOLLOW;
176
177 switch (p->fts_info) {
178 case FTS_D:
179 if (!Rflag)
180 fts_set(ftsp, p, FTS_SKIP);
181 break;
182 case FTS_DNR: /* Warn, chmod. */
183 warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
184 rval = 1;
185 break;
186 case FTS_DP: /* Already changed at FTS_D. */
187 continue;
188 case FTS_ERR: /* Warn, continue. */
189 case FTS_NS:
190 warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
191 rval = 1;
192 continue;
193 default:
194 break;
195 }
196 newmode = getmode(set, p->fts_statp->st_mode);
197 /*
198 * With NFSv4 ACLs, it is possible that applying a mode
199 * identical to the one computed from an ACL will change
200 * that ACL.
201 */
202 if (may_have_nfs4acl(p, hflag) == 0 &&
203 (newmode & ALLPERMS) == (p->fts_statp->st_mode & ALLPERMS))
204 continue;
205 if (fchmodat(AT_FDCWD, p->fts_accpath, newmode, atflag) == -1
206 && !fflag) {
207 warn("%s", p->fts_path);
208 rval = 1;
209 } else if (vflag || siginfo) {
210 (void)printf("%s", p->fts_path);
211
212 if (vflag > 1 || siginfo) {
213 char m1[12], m2[12];
214
215 strmode(p->fts_statp->st_mode, m1);
216 strmode((p->fts_statp->st_mode &
217 S_IFMT) | newmode, m2);
218 (void)printf(": 0%o [%s] -> 0%o [%s]",
219 p->fts_statp->st_mode, m1,
220 (p->fts_statp->st_mode & S_IFMT) |
221 newmode, m2);
222 }
223 (void)printf("\n");
224 siginfo = 0;
225 }
226 }
227 if (errno)
228 err(1, "fts_read");
229 exit(rval);
230 }
231
232 static void
233 usage(void)
234 {
235 (void)fprintf(stderr,
236 "usage: chmod [-fhv] [-R [-H | -L | -P]] mode file ...\n");
237 exit(1);
238 }
239
240 static int
241 may_have_nfs4acl(const FTSENT *ent, int hflag)
242 {
243 int ret;
244 static dev_t previous_dev = NODEV;
245 static int supports_acls = -1;
246
247 if (previous_dev != ent->fts_statp->st_dev) {
248 previous_dev = ent->fts_statp->st_dev;
249 supports_acls = 0;
250
251 if (hflag)
252 ret = lpathconf(ent->fts_accpath, _PC_ACL_NFS4);
253 else
254 ret = pathconf(ent->fts_accpath, _PC_ACL_NFS4);
255 if (ret > 0)
256 supports_acls = 1;
257 else if (ret < 0 && errno != EINVAL)
258 warn("%s", ent->fts_path);
259 }
260
261 return (supports_acls);
262 }

Properties

Name Value
svn:keywords FreeBSD=%H

  ViewVC Help
Powered by ViewVC 1.1.27