diff options
Diffstat (limited to 'chmod.c')
-rw-r--r-- | chmod.c | 161 |
1 files changed, 98 insertions, 63 deletions
@@ -1,41 +1,54 @@ | |||
1 | #include <stdlib.h> | 1 | /* |
2 | * Mini chmod implementation for busybox | ||
3 | * | ||
4 | * Copyright (C) 1998 by Erik Andersen <andersee@debian.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
2 | #include <stdio.h> | 22 | #include <stdio.h> |
3 | #include <unistd.h> | 23 | #include <grp.h> |
4 | #include <sys/stat.h> | 24 | #include <pwd.h> |
5 | #include "internal.h" | 25 | #include "internal.h" |
6 | 26 | ||
7 | const char chmod_usage[] = "chmod [-R] mode file [file ...]\n" | 27 | |
8 | "\nmode may be an octal integer representing the bit pattern for the\n" | 28 | static mode_t mode=7777; |
9 | "\tnew mode, or a symbolic value matching the pattern\n" | 29 | |
10 | "\t[ugoa]{+|-|=}[rwxst] .\n" | 30 | |
11 | "\t\tu:\tUser\n" | 31 | static const char chmod_usage[] = "[-R] MODE[,MODE]... FILE...\n" |
12 | "\t\tg:\tGroup\n" | 32 | "Each MODE is one or more of the letters ugoa, one of the symbols +-= and\n" |
13 | "\t\to:\tOthers\n" | 33 | "one or more of the letters rwxst.\n\n" |
14 | "\t\ta:\tAll\n" | 34 | "\t-R\tchange files and directories recursively.\n"; |
15 | "\n" | 35 | |
16 | "\n+:\tAdd privilege\n" | 36 | |
17 | "\n-:\tRemove privilege\n" | 37 | |
18 | "\n=:\tSet privilege\n" | 38 | static int fileAction(const char *fileName) |
19 | "\n" | 39 | { |
20 | "\t\tr:\tRead\n" | 40 | struct stat statBuf; |
21 | "\t\tw:\tWrite\n" | 41 | if ((stat(fileName, &statBuf) < 0) || |
22 | "\t\tx:\tExecute\n" | 42 | (chmod(fileName, mode)) < 0) { |
23 | "\t\ts:\tSet User ID\n" | 43 | perror(fileName); |
24 | "\t\tt:\t\"Sticky\" Text\n" | 44 | return( FALSE); |
25 | "\n" | 45 | } |
26 | "\tModes may be concatenated, as in \"u=rwx,g=rx,o=rx,-t,-s\n" | 46 | return( TRUE); |
27 | "\n" | 47 | } |
28 | "\t-R:\tRecursively change the mode of all files and directories\n" | 48 | |
29 | "\t\tunder the argument directory."; | 49 | /* [ugoa]{+|-|=}[rwxstl] */ |
30 | 50 | int parse_mode( const char* s, mode_t* or, mode_t* and, int* group_execute) | |
31 | int | ||
32 | parse_mode( | ||
33 | const char * s | ||
34 | ,mode_t * or | ||
35 | ,mode_t * and | ||
36 | ,int * group_execute) | ||
37 | { | 51 | { |
38 | /* [ugoa]{+|-|=}[rwxstl] */ | ||
39 | mode_t mode = 0; | 52 | mode_t mode = 0; |
40 | mode_t groups = S_ISVTX; | 53 | mode_t groups = S_ISVTX; |
41 | char type; | 54 | char type; |
@@ -45,7 +58,7 @@ parse_mode( | |||
45 | for ( ; ; ) { | 58 | for ( ; ; ) { |
46 | switch ( c = *s++ ) { | 59 | switch ( c = *s++ ) { |
47 | case '\0': | 60 | case '\0': |
48 | return -1; | 61 | return (FALSE); |
49 | case 'u': | 62 | case 'u': |
50 | groups |= S_ISUID|S_IRWXU; | 63 | groups |= S_ISUID|S_IRWXU; |
51 | continue; | 64 | continue; |
@@ -69,10 +82,10 @@ parse_mode( | |||
69 | if ( c >= '0' && c <= '7' && mode == 0 && groups == S_ISVTX ) { | 82 | if ( c >= '0' && c <= '7' && mode == 0 && groups == S_ISVTX ) { |
70 | *and = 0; | 83 | *and = 0; |
71 | *or = strtol(--s, 0, 010); | 84 | *or = strtol(--s, 0, 010); |
72 | return 0; | 85 | return (TRUE); |
73 | } | 86 | } |
74 | else | 87 | else |
75 | return -1; | 88 | return (FALSE); |
76 | } | 89 | } |
77 | break; | 90 | break; |
78 | } | 91 | } |
@@ -93,7 +106,7 @@ parse_mode( | |||
93 | case 's': | 106 | case 's': |
94 | if ( group_execute != 0 && (groups & S_IRWXG) ) { | 107 | if ( group_execute != 0 && (groups & S_IRWXG) ) { |
95 | if ( *group_execute < 0 ) | 108 | if ( *group_execute < 0 ) |
96 | return -1; | 109 | return (FALSE); |
97 | if ( type != '-' ) { | 110 | if ( type != '-' ) { |
98 | mode |= S_IXGRP; | 111 | mode |= S_IXGRP; |
99 | *group_execute = 1; | 112 | *group_execute = 1; |
@@ -103,7 +116,7 @@ parse_mode( | |||
103 | continue; | 116 | continue; |
104 | case 'l': | 117 | case 'l': |
105 | if ( *group_execute > 0 ) | 118 | if ( *group_execute > 0 ) |
106 | return -1; | 119 | return (FALSE); |
107 | if ( type != '-' ) { | 120 | if ( type != '-' ) { |
108 | *and &= ~S_IXGRP; | 121 | *and &= ~S_IXGRP; |
109 | *group_execute = -1; | 122 | *group_execute = -1; |
@@ -115,7 +128,7 @@ parse_mode( | |||
115 | mode |= S_ISVTX; | 128 | mode |= S_ISVTX; |
116 | continue; | 129 | continue; |
117 | default: | 130 | default: |
118 | return -1; | 131 | return (FALSE); |
119 | } | 132 | } |
120 | break; | 133 | break; |
121 | } | 134 | } |
@@ -132,32 +145,54 @@ parse_mode( | |||
132 | break; | 145 | break; |
133 | } | 146 | } |
134 | } while ( c == ',' ); | 147 | } while ( c == ',' ); |
135 | return 0; | 148 | return (TRUE); |
136 | } | 149 | } |
137 | 150 | ||
138 | extern int | 151 | |
139 | chmod_main(struct FileInfo * i, int argc, char * * argv) | 152 | int chmod_main(int argc, char **argv) |
140 | { | 153 | { |
141 | i->andWithMode = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO; | 154 | int recursiveFlag=FALSE; |
142 | i->orWithMode = 0; | 155 | mode_t andWithMode = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO; |
143 | 156 | mode_t orWithMode = 0; | |
144 | while ( argc >= 3 ) { | 157 | char *invocationName=*argv; |
145 | if ( parse_mode(argv[1], &i->orWithMode, &i->andWithMode, 0) | ||
146 | == 0 ) { | ||
147 | argc--; | ||
148 | argv++; | ||
149 | } | ||
150 | else if ( strcmp(argv[1], "-R") == 0 ) { | ||
151 | i->recursive = 1; | ||
152 | argc--; | ||
153 | argv++; | ||
154 | } | ||
155 | else | ||
156 | break; | ||
157 | } | ||
158 | 158 | ||
159 | i->changeMode = 1; | 159 | if (argc < 3) { |
160 | i->complainInPostProcess = 1; | 160 | fprintf(stderr, "Usage: %s %s", invocationName, chmod_usage); |
161 | exit( FALSE); | ||
162 | } | ||
163 | argc--; | ||
164 | argv++; | ||
165 | |||
166 | /* Parse options */ | ||
167 | while (**argv == '-') { | ||
168 | while (*++(*argv)) switch (**argv) { | ||
169 | case 'R': | ||
170 | recursiveFlag = TRUE; | ||
171 | break; | ||
172 | default: | ||
173 | fprintf(stderr, "Unknown option: %c\n", **argv); | ||
174 | exit( FALSE); | ||
175 | } | ||
176 | argc--; | ||
177 | argv++; | ||
178 | } | ||
179 | |||
180 | /* Find the selected group */ | ||
181 | if ( parse_mode(*argv, &orWithMode, &andWithMode, 0) == FALSE ) { | ||
182 | fprintf(stderr, "%s: Unknown mode: %s\n", invocationName, *argv); | ||
183 | exit( FALSE); | ||
184 | } | ||
185 | mode &= andWithMode; | ||
186 | mode |= orWithMode; | ||
161 | 187 | ||
162 | return monadic_main(i, argc, argv); | 188 | /* Ok, ready to do the deed now */ |
189 | if (argc <= 1) { | ||
190 | fprintf(stderr, "%s: too few arguments", invocationName); | ||
191 | exit( FALSE); | ||
192 | } | ||
193 | while (argc-- > 1) { | ||
194 | argv++; | ||
195 | recursiveAction( *argv, recursiveFlag, TRUE, fileAction, fileAction); | ||
196 | } | ||
197 | exit(TRUE); | ||
163 | } | 198 | } |