1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1992-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
20 ***********************************************************************/
30 static const char usage
[] =
31 "[-?\n@(#)$Id: chmod (AT&T Research) 2009-07-02 $\n]"
33 "[+NAME?chmod - change the access permissions of files]"
34 "[+DESCRIPTION?\bchmod\b changes the permission of each file "
35 "according to mode, which can be either a symbolic representation "
36 "of changes to make, or an octal number representing the bit "
37 "pattern for the new permissions.]"
38 "[+?Symbolic mode strings consist of one or more comma separated list "
39 "of operations that can be perfomed on the mode. Each operation is of "
40 "the form \auser\a \aop\a \aperm\a where \auser\a is zero or more of "
41 "the following letters:]{"
42 "[+u?User permission bits.]"
43 "[+g?Group permission bits.]"
44 "[+o?Other permission bits.]"
45 "[+a?All permission bits. This is the default if none are specified.]"
47 "[+?The \aperm\a portion consists of zero or more of the following letters:]{"
48 "[+r?Read permission.]"
49 "[+s?Setuid when \bu\b is selected for \awho\a and setgid when \bg\b "
50 "is selected for \awho\a.]"
51 "[+w?Write permission.]"
52 "[+x?Execute permission for files, search permission for directories.]"
53 "[+X?Same as \bx\b except that it is ignored for files that do not "
54 "already have at least one \bx\b bit set.]"
55 "[+l?Exclusive lock bit on systems that support it. Group execute "
57 "[+t?Sticky bit on systems that support it.]"
59 "[+?The \aop\a portion consists of one or more of the following characters:]{"
60 "[++?Cause the permission selected to be added to the existing "
61 "permissions. | is equivalent to +.]"
62 "[+-?Cause the permission selected to be removed to the existing "
64 "[+=?Cause the permission to be set to the given permissions.]"
65 "[+&?Cause the permission selected to be \aand\aed with the existing "
67 "[+^?Cause the permission selected to be propagated to more "
68 "restrictive groups.]"
70 "[+?Symbolic modes with the \auser\a portion omitted are subject to "
71 "\bumask\b(2) settings unless the \b=\b \aop\a or the "
72 "\b--ignore-umask\b option is specified.]"
73 "[+?A numeric mode is from one to four octal digits (0-7), "
74 "derived by adding up the bits with values 4, 2, and 1. "
75 "Any omitted digits are assumed to be leading zeros. The "
76 "first digit selects the set user ID (4) and set group ID "
77 "(2) and save text image (1) attributes. The second digit "
78 "selects permissions for the user who owns the file: read "
79 "(4), write (2), and execute (1); the third selects permissions"
80 "for other users in the file's group, with the same values; "
81 "and the fourth for other users not in the file's group, with "
84 "[+?For symbolic links, by default, \bchmod\b changes the mode on the file "
85 "referenced by the symbolic link, not on the symbolic link itself. "
86 "The \b-h\b options can be specified to change the mode of the link. "
87 "When traversing directories with \b-R\b, \bchmod\b either follows "
88 "symbolic links or does not follow symbolic links, based on the "
89 "options \b-H\b, \b-L\b, and \b-P\b. The configuration parameter "
90 "\bPATH_RESOLVE\b determines the default behavior if none of these "
91 "options is specified.]"
93 "[+?When the \b-c\b or \b-v\b options are specified, change notifications "
94 "are written to standard output using the format, "
95 "\b%s: mode changed to %0.4o (%s)\b, with arguments of the "
96 "pathname, the numeric mode, and the resulting permission bits as "
97 "would be displayed by the \bls\b command.]"
99 "[+?For backwards compatibility, if an invalid option is given that is a valid "
100 "symbolic mode specification, \bchmod\b treats this as a mode "
101 "specification rather than as an option specification.]"
103 "[H:metaphysical?Follow symbolic links for command arguments; otherwise don't "
104 "follow symbolic links when traversing directories.]"
105 "[L:logical|follow?Follow symbolic links when traversing directories.]"
106 "[P:physical|nofollow?Don't follow symbolic links when traversing directories.]"
107 "[R:recursive?Change the mode for files in subdirectories recursively.]"
108 "[c:changes?Describe only files whose permission actually change.]"
109 "[f:quiet|silent?Do not report files whose permissioins fail to change.]"
110 "[h:symlink?Change the mode of the symbolic links on systems that "
112 "[i:ignore-umask?Ignore the \bumask\b(2) value in symbolic mode "
113 "expressions. This is probably how you expect \bchmod\b to work.]"
114 "[n:show?Show actions but do not change any file modes.]"
115 "[F:reference?Omit the \amode\a operand and use the mode of \afile\a "
117 "[v:verbose?Describe changed permissions of all files.]"
122 "[+0?All files changed successfully.]"
123 "[+>0?Unable to change mode of one or more files.]"
125 "[+SEE ALSO?\bchgrp\b(1), \bchown\b(1), \btw\b(1), \bgetconf\b(1), \bls\b(1), "
130 #if defined(__STDPP__directive) && defined(__STDPP__hide)
131 __STDPP__directive pragma pp
:hide lchmod
133 #define lchmod ______lchmod
140 #include "FEATURE/symlink"
142 #if defined(__STDPP__directive) && defined(__STDPP__hide)
143 __STDPP__directive pragma pp
:nohide lchmod
148 extern int lchmod(const char*, mode_t
);
151 b_chmod(int argc
, char** argv
, void* context
)
154 register int force
= 0;
156 register char* amode
= 0;
160 int (*chmodf
)(const char*, mode_t
);
170 cmdinit(argc
, argv
, context
, ERROR_CATALOG
, ERROR_NOTIFY
);
171 flags
= fts_flags() | FTS_TOP
| FTS_NOPOSTORDER
| FTS_NOSEEDOTDIR
;
174 * NOTE: we diverge from the normal optget boilerplate
175 * to allow `chmod -x etc' to fall through
180 switch (optget(argv
, usage
))
203 if (stat(opt_info
.arg
, &st
))
204 error(ERROR_exit(1), "%s: cannot stat", opt_info
.arg
);
209 flags
|= FTS_META
|FTS_PHYSICAL
;
213 flags
&= ~(FTS_META
|FTS_PHYSICAL
);
218 flags
|= FTS_PHYSICAL
;
226 error(ERROR_usage(2), "%s", opt_info
.arg
);
231 argv
+= opt_info
.index
;
232 if (error_info
.errors
|| !*argv
|| !amode
&& !*(argv
+ 1))
233 error(ERROR_usage(2), "%s", optusage(NiL
));
235 flags
&= ~(FTS_META
|FTS_PHYSICAL
);
243 mode
= strperm(amode
, &last
, 0);
248 error(ERROR_exit(1), "%s: invalid mode", amode
);
256 if (!(fts
= fts_open(argv
, flags
, NiL
)))
260 error(ERROR_system(1), "%s: not found", *argv
);
262 while (!sh_checksig(context
) && (ent
= fts_read(fts
)))
263 switch (ent
->fts_info
)
268 if (!(flags
& FTS_PHYSICAL
) || (flags
& FTS_META
) && ent
->fts_level
== 1)
269 fts_set(NiL
, ent
, FTS_FOLLOW
);
278 mode
= strperm(amode
, &last
, ent
->fts_statp
->st_mode
);
279 if (show
|| (*chmodf
)(ent
->fts_accpath
, mode
) >= 0)
281 if (notify
== 2 || notify
== 1 && (mode
&S_IPERM
) != (ent
->fts_statp
->st_mode
&S_IPERM
))
282 sfprintf(sfstdout
, "%s: mode changed to %0.4o (%s)\n", ent
->fts_path
, mode
, fmtmode(mode
, 1)+1);
285 error(ERROR_system(0), "%s: cannot change mode", ent
->fts_accpath
);
289 error(ERROR_warn(0), "%s: directory causes cycle", ent
->fts_accpath
);
293 error(ERROR_system(0), "%s: cannot read directory", ent
->fts_accpath
);
297 error(ERROR_system(0), "%s: cannot search directory", ent
->fts_accpath
);
301 error(ERROR_system(0), "%s: not found", ent
->fts_accpath
);
307 return error_info
.errors
!= 0;