Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/coreutils/chown.c
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/coreutils/chown.c
r821 r1770 8 8 */ 9 9 10 /* BB_AUDIT SUSv3 defects - unsupported options -h, -H, -L, and -P. */ 11 /* BB_AUDIT GNU defects - unsupported options -h, -c, -f, -v, and long options. */ 12 /* BB_AUDIT Note: gnu chown does not support -H, -L, or -P. */ 10 /* BB_AUDIT SUSv3 defects - none? */ 11 /* BB_AUDIT GNU defects - unsupported long options. */ 13 12 /* http://www.opengroup.org/onlinepubs/007904975/utilities/chown.html */ 14 13 15 #include <stdlib.h> 16 #include <unistd.h> 17 #include <string.h> 18 #include "busybox.h" 14 #include "libbb.h" 19 15 20 static uid_t uid = -1; 21 static gid_t gid = -1; 16 /* This is a NOEXEC applet. Be very careful! */ 22 17 23 static int (*chown_func)(const char *, uid_t, gid_t) = chown; 18 19 #define OPT_STR ("Rh" USE_DESKTOP("vcfLHP")) 20 #define BIT_RECURSE 1 21 #define OPT_RECURSE (option_mask32 & 1) 22 #define OPT_NODEREF (option_mask32 & 2) 23 #define OPT_VERBOSE (USE_DESKTOP(option_mask32 & 0x04) SKIP_DESKTOP(0)) 24 #define OPT_CHANGED (USE_DESKTOP(option_mask32 & 0x08) SKIP_DESKTOP(0)) 25 #define OPT_QUIET (USE_DESKTOP(option_mask32 & 0x10) SKIP_DESKTOP(0)) 26 /* POSIX options 27 * -L traverse every symbolic link to a directory encountered 28 * -H if a command line argument is a symbolic link to a directory, traverse it 29 * -P do not traverse any symbolic links (default) 30 * We do not conform to the following: 31 * "Specifying more than one of -H, -L, and -P is not an error. 32 * The last option specified shall determine the behavior of the utility." */ 33 /* -L */ 34 #define BIT_TRAVERSE 0x20 35 #define OPT_TRAVERSE (USE_DESKTOP(option_mask32 & BIT_TRAVERSE) SKIP_DESKTOP(0)) 36 /* -H or -L */ 37 #define BIT_TRAVERSE_TOP (0x20|0x40) 38 #define OPT_TRAVERSE_TOP (USE_DESKTOP(option_mask32 & BIT_TRAVERSE_TOP) SKIP_DESKTOP(0)) 39 40 typedef int (*chown_fptr)(const char *, uid_t, gid_t); 41 42 static struct bb_uidgid_t ugid = { -1, -1 }; 24 43 25 44 static int fileAction(const char *fileName, struct stat *statbuf, 26 void ATTRIBUTE_UNUSED *junk)45 void *cf, int depth) 27 46 { 28 if (!chown_func(fileName, 29 (uid == (uid_t)-1) ? statbuf->st_uid : uid, 30 (gid == (gid_t)-1) ? statbuf->st_gid : gid)) { 47 uid_t u = (ugid.uid == (uid_t)-1) ? statbuf->st_uid : ugid.uid; 48 gid_t g = (ugid.gid == (gid_t)-1) ? statbuf->st_gid : ugid.gid; 49 50 if (!((chown_fptr)cf)(fileName, u, g)) { 51 if (OPT_VERBOSE 52 || (OPT_CHANGED && (statbuf->st_uid != u || statbuf->st_gid != g)) 53 ) { 54 printf("changed ownership of '%s' to %u:%u\n", 55 fileName, (unsigned)u, (unsigned)g); 56 } 31 57 return TRUE; 32 58 } 33 bb_perror_msg("%s", fileName); /* A filename could have % in it... */ 59 if (!OPT_QUIET) 60 bb_perror_msg("%s", fileName); /* A filename can have % in it... */ 34 61 return FALSE; 35 62 } 36 63 37 #define FLAG_R 1 38 #define FLAG_h 2 39 64 int chown_main(int argc, char **argv); 40 65 int chown_main(int argc, char **argv) 41 66 { 67 int retval = EXIT_SUCCESS; 42 68 int flags; 43 int retval = EXIT_SUCCESS; 44 char *groupName; 69 chown_fptr chown_func; 45 70 46 flags = bb_getopt_ulflags(argc, argv, "Rh"); 71 opt_complementary = "-2"; 72 getopt32(argv, OPT_STR); 73 argv += optind; 47 74 48 if (flags & FLAG_h) chown_func = lchown; 49 50 if (argc - optind < 2) { 51 bb_show_usage(); 75 /* This matches coreutils behavior (almost - see below) */ 76 chown_func = chown; 77 if (OPT_NODEREF 78 /* || (OPT_RECURSE && !OPT_TRAVERSE_TOP): */ 79 USE_DESKTOP( || (option_mask32 & (BIT_RECURSE|BIT_TRAVERSE_TOP)) == BIT_RECURSE) 80 ) { 81 chown_func = lchown; 52 82 } 53 83 54 argv += optind; 84 flags = ACTION_DEPTHFIRST; /* match coreutils order */ 85 if (OPT_RECURSE) 86 flags |= ACTION_RECURSE; 87 if (OPT_TRAVERSE_TOP) 88 flags |= ACTION_FOLLOWLINKS_L0; /* -H/-L: follow links on depth 0 */ 89 if (OPT_TRAVERSE) 90 flags |= ACTION_FOLLOWLINKS; /* follow links if -L */ 55 91 56 /* First, check if there is a group name here */ 57 if ((groupName = strchr(*argv, '.')) == NULL) { 58 groupName = strchr(*argv, ':'); 59 } 60 61 /* Check for the username and groupname */ 62 if (groupName) { 63 *groupName++ = '\0'; 64 gid = get_ug_id(groupName, bb_xgetgrnam); 65 } 66 if (--groupName != *argv) uid = get_ug_id(*argv, bb_xgetpwnam); 67 ++argv; 92 parse_chown_usergroup_or_die(&ugid, argv[0]); 68 93 69 94 /* Ok, ready to do the deed now */ 95 argv++; 70 96 do { 71 if (! recursive_action (*argv, (flags & FLAG_R), FALSE, FALSE, 72 fileAction, fileAction, NULL)) { 97 if (!recursive_action(*argv, 98 flags, /* flags */ 99 fileAction, /* file action */ 100 fileAction, /* dir action */ 101 chown_func, /* user data */ 102 0) /* depth */ 103 ) { 73 104 retval = EXIT_FAILURE; 74 105 } … … 77 108 return retval; 78 109 } 110 111 /* 112 Testcase. Run in empty directory. 113 114 #!/bin/sh 115 t1="/tmp/busybox chown" 116 t2="/usr/bin/chown" 117 create() { 118 rm -rf $1; mkdir $1 119 ( 120 cd $1 || exit 1 121 mkdir dir dir2 122 >up 123 >file 124 >dir/file 125 >dir2/file 126 ln -s dir linkdir 127 ln -s file linkfile 128 ln -s ../up dir/linkup 129 ln -s ../dir2 dir/linkupdir2 130 ) 131 chown -R 0:0 $1 132 } 133 tst() { 134 create test1 135 create test2 136 echo "[$1]" >>test1.out 137 echo "[$1]" >>test2.out 138 (cd test1; $t1 $1) >>test1.out 2>&1 139 (cd test2; $t2 $1) >>test2.out 2>&1 140 (cd test1; ls -lnR) >out1 141 (cd test2; ls -lnR) >out2 142 echo "chown $1" >out.diff 143 if ! diff -u out1 out2 >>out.diff; then exit 1; fi 144 rm out.diff 145 } 146 tst_for_each() { 147 tst "$1 1:1 file" 148 tst "$1 1:1 dir" 149 tst "$1 1:1 linkdir" 150 tst "$1 1:1 linkfile" 151 } 152 echo "If script produced 'out.diff' file, then at least one testcase failed" 153 >test1.out 154 >test2.out 155 # These match coreutils 6.8: 156 tst_for_each "-v" 157 tst_for_each "-vR" 158 tst_for_each "-vRP" 159 tst_for_each "-vRL" 160 tst_for_each "-vRH" 161 tst_for_each "-vh" 162 tst_for_each "-vhR" 163 tst_for_each "-vhRP" 164 tst_for_each "-vhRL" 165 tst_for_each "-vhRH" 166 # Fix `name' in coreutils output 167 sed 's/`/'"'"'/g' -i test2.out 168 # Compare us with coreutils output 169 diff -u test1.out test2.out 170 171 */
Note:
See TracChangeset
for help on using the changeset viewer.