Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/coreutils/chmod.c
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/coreutils/chmod.c
r821 r1770 12 12 13 13 /* BB_AUDIT SUSv3 compliant */ 14 /* BB_AUDIT GNU defects - unsupported options -c, -f, -v, andlong options. */14 /* BB_AUDIT GNU defects - unsupported long options. */ 15 15 /* http://www.opengroup.org/onlinepubs/007904975/utilities/chmod.html */ 16 16 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <string.h> 20 #include <unistd.h> 21 #include <sys/stat.h> 22 #include "busybox.h" 17 #include "libbb.h" 23 18 24 static int fileAction(const char *fileName, struct stat *statbuf, void* junk) 19 /* This is a NOEXEC applet. Be very careful! */ 20 21 22 #define OPT_RECURSE (option_mask32 & 1) 23 #define OPT_VERBOSE (USE_DESKTOP(option_mask32 & 2) SKIP_DESKTOP(0)) 24 #define OPT_CHANGED (USE_DESKTOP(option_mask32 & 4) SKIP_DESKTOP(0)) 25 #define OPT_QUIET (USE_DESKTOP(option_mask32 & 8) SKIP_DESKTOP(0)) 26 #define OPT_STR "R" USE_DESKTOP("vcf") 27 28 /* coreutils: 29 * chmod never changes the permissions of symbolic links; the chmod 30 * system call cannot change their permissions. This is not a problem 31 * since the permissions of symbolic links are never used. 32 * However, for each symbolic link listed on the command line, chmod changes 33 * the permissions of the pointed-to file. In contrast, chmod ignores 34 * symbolic links encountered during recursive directory traversals. 35 */ 36 37 static int fileAction(const char *fileName, struct stat *statbuf, void* param, int depth) 25 38 { 26 if (!bb_parse_mode((char *)junk, &(statbuf->st_mode))) 27 bb_error_msg_and_die( "invalid mode: %s", (char *)junk); 28 if (chmod(fileName, statbuf->st_mode) == 0) 29 return (TRUE); 30 bb_perror_msg("%s", fileName); /* Avoid multibyte problems. */ 31 return (FALSE); 39 mode_t newmode; 40 41 /* match coreutils behavior */ 42 if (depth == 0) { 43 /* statbuf holds lstat result, but we need stat (follow link) */ 44 if (stat(fileName, statbuf)) 45 goto err; 46 } else { /* depth > 0: skip links */ 47 if (S_ISLNK(statbuf->st_mode)) 48 return TRUE; 49 } 50 newmode = statbuf->st_mode; 51 52 if (!bb_parse_mode((char *)param, &newmode)) 53 bb_error_msg_and_die("invalid mode: %s", (char *)param); 54 55 if (chmod(fileName, newmode) == 0) { 56 if (OPT_VERBOSE 57 || (OPT_CHANGED && statbuf->st_mode != newmode) 58 ) { 59 printf("mode of '%s' changed to %04o (%s)\n", fileName, 60 newmode & 07777, bb_mode_string(newmode)+1); 61 } 62 return TRUE; 63 } 64 err: 65 if (!OPT_QUIET) 66 bb_perror_msg("%s", fileName); 67 return FALSE; 32 68 } 33 69 34 int chmod_main(int ATTRIBUTE_UNUSED argc, char **argv) 70 int chmod_main(int argc, char **argv); 71 int chmod_main(int argc, char **argv) 35 72 { 36 73 int retval = EXIT_SUCCESS; 37 int recursiveFlag = FALSE; 38 int count; 74 char *arg, **argp; 39 75 char *smode; 40 char **p;41 char *p0;42 char opt = '-';43 76 44 ++argv; 45 count = 0; 46 47 for (p = argv ; *p ; p++) { 48 p0 = p[0]; 49 if (p0[0] == opt) { 50 if ((p0[1] == '-') && !p0[2]) { 51 opt = 0; /* Disable further option processing. */ 52 continue; 53 } 54 if (p0[1] == 'R') { 55 char *s = p0 + 2; 56 while (*s == 'R') { 57 ++s; 58 } 59 if (*s) { 60 bb_show_usage(); 61 } 62 recursiveFlag = TRUE; 63 continue; 64 } 65 if (count) { 66 bb_show_usage(); 67 } 77 /* Convert first encountered -r into ar, -w into aw etc 78 * so that getopt would not eat it */ 79 argp = argv; 80 while ((arg = *++argp)) { 81 /* Mode spec must be the first arg (sans -R etc) */ 82 /* (protect against mishandling e.g. "chmod 644 -r") */ 83 if (arg[0] != '-') { 84 arg = NULL; 85 break; 68 86 } 69 argv[count] = p0; 70 ++count; 87 /* An option. Not a -- or valid option? */ 88 if (arg[1] && !strchr("-"OPT_STR, arg[1])) { 89 arg[0] = 'a'; 90 break; 91 } 71 92 } 72 93 73 argv[count] = NULL; 94 /* Parse options */ 95 opt_complementary = "-2"; 96 getopt32(argv, ("-"OPT_STR) + 1); /* Reuse string */ 97 argv += optind; 74 98 75 if (count < 2) { 76 bb_show_usage(); 77 } 78 79 smode = *argv; 80 ++argv; 99 /* Restore option-like mode if needed */ 100 if (arg) arg[0] = '-'; 81 101 82 102 /* Ok, ready to do the deed now */ 103 smode = *argv++; 83 104 do { 84 if (! recursive_action (*argv, recursiveFlag, TRUE, FALSE, 85 fileAction, fileAction, smode)) { 105 if (!recursive_action(*argv, 106 OPT_RECURSE, // recurse 107 fileAction, // file action 108 fileAction, // dir action 109 smode, // user data 110 0) // depth 111 ) { 86 112 retval = EXIT_FAILURE; 87 113 } … … 90 116 return retval; 91 117 } 118 119 /* 120 Security: chmod is too important and too subtle. 121 This is a test script (busybox chmod versus coreutils). 122 Run it in empty directory. 123 124 #!/bin/sh 125 t1="/tmp/busybox chmod" 126 t2="/usr/bin/chmod" 127 create() { 128 rm -rf $1; mkdir $1 129 ( 130 cd $1 || exit 1 131 mkdir dir 132 >up 133 >file 134 >dir/file 135 ln -s dir linkdir 136 ln -s file linkfile 137 ln -s ../up dir/up 138 ) 139 } 140 tst() { 141 (cd test1; $t1 $1) 142 (cd test2; $t2 $1) 143 (cd test1; ls -lR) >out1 144 (cd test2; ls -lR) >out2 145 echo "chmod $1" >out.diff 146 if ! diff -u out1 out2 >>out.diff; then exit 1; fi 147 rm out.diff 148 } 149 echo "If script produced 'out.diff' file, then at least one testcase failed" 150 create test1; create test2 151 tst "a+w file" 152 tst "a-w dir" 153 tst "a+w linkfile" 154 tst "a-w linkdir" 155 tst "-R a+w file" 156 tst "-R a-w dir" 157 tst "-R a+w linkfile" 158 tst "-R a-w linkdir" 159 tst "a-r,a+x linkfile" 160 */
Note:
See TracChangeset
for help on using the changeset viewer.