Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/coreutils/chown.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 984 - (hide annotations) (download)
Sun May 30 11:32:42 2010 UTC (13 years, 11 months ago) by niro
File MIME type: text/plain
File size: 5120 byte(s)
-updated to busybox-1.16.1 and enabled blkid/uuid support in default config
1 niro 532 /* vi: set sw=4 ts=4: */
2     /*
3     * Mini chown implementation for busybox
4     *
5     * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
6     *
7     * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
8     */
9    
10 niro 816 /* BB_AUDIT SUSv3 defects - none? */
11 niro 532 /* http://www.opengroup.org/onlinepubs/007904975/utilities/chown.html */
12    
13 niro 816 #include "libbb.h"
14 niro 532
15 niro 816 /* This is a NOEXEC applet. Be very careful! */
16 niro 532
17    
18 niro 984 #define OPT_STR ("Rh" IF_DESKTOP("vcfLHP"))
19 niro 816 #define BIT_RECURSE 1
20     #define OPT_RECURSE (opt & 1)
21     #define OPT_NODEREF (opt & 2)
22 niro 984 #define OPT_VERBOSE (IF_DESKTOP(opt & 0x04) IF_NOT_DESKTOP(0))
23     #define OPT_CHANGED (IF_DESKTOP(opt & 0x08) IF_NOT_DESKTOP(0))
24     #define OPT_QUIET (IF_DESKTOP(opt & 0x10) IF_NOT_DESKTOP(0))
25 niro 816 /* POSIX options
26     * -L traverse every symbolic link to a directory encountered
27 niro 532 * -H if a command line argument is a symbolic link to a directory, traverse it
28     * -P do not traverse any symbolic links (default)
29 niro 816 * We do not conform to the following:
30     * "Specifying more than one of -H, -L, and -P is not an error.
31     * The last option specified shall determine the behavior of the utility." */
32     /* -L */
33     #define BIT_TRAVERSE 0x20
34 niro 984 #define OPT_TRAVERSE (IF_DESKTOP(opt & BIT_TRAVERSE) IF_NOT_DESKTOP(0))
35 niro 816 /* -H or -L */
36     #define BIT_TRAVERSE_TOP (0x20|0x40)
37 niro 984 #define OPT_TRAVERSE_TOP (IF_DESKTOP(opt & BIT_TRAVERSE_TOP) IF_NOT_DESKTOP(0))
38 niro 532
39 niro 984 #if ENABLE_FEATURE_CHOWN_LONG_OPTIONS
40     static const char chown_longopts[] ALIGN1 =
41     "recursive\0" No_argument "R"
42     "dereference\0" No_argument "\xff"
43     "no-dereference\0" No_argument "h"
44     # if ENABLE_DESKTOP
45     "changes\0" No_argument "c"
46     "silent\0" No_argument "f"
47     "quiet\0" No_argument "f"
48     "verbose\0" No_argument "v"
49     # endif
50     ;
51     #endif
52    
53 niro 816 typedef int (*chown_fptr)(const char *, uid_t, gid_t);
54    
55     struct param_t {
56     struct bb_uidgid_t ugid;
57     chown_fptr chown_func;
58     };
59    
60     static int FAST_FUNC fileAction(const char *fileName, struct stat *statbuf,
61     void *vparam, int depth UNUSED_PARAM)
62 niro 532 {
63 niro 816 #define param (*(struct param_t*)vparam)
64     #define opt option_mask32
65     uid_t u = (param.ugid.uid == (uid_t)-1) ? statbuf->st_uid : param.ugid.uid;
66     gid_t g = (param.ugid.gid == (gid_t)-1) ? statbuf->st_gid : param.ugid.gid;
67 niro 532
68 niro 816 if (param.chown_func(fileName, u, g) == 0) {
69 niro 532 if (OPT_VERBOSE
70 niro 816 || (OPT_CHANGED && (statbuf->st_uid != u || statbuf->st_gid != g))
71 niro 532 ) {
72     printf("changed ownership of '%s' to %u:%u\n",
73 niro 816 fileName, (unsigned)u, (unsigned)g);
74 niro 532 }
75     return TRUE;
76     }
77     if (!OPT_QUIET)
78 niro 816 bb_simple_perror_msg(fileName); /* A filename can have % in it... */
79 niro 532 return FALSE;
80 niro 816 #undef opt
81     #undef param
82 niro 532 }
83    
84 niro 816 int chown_main(int argc UNUSED_PARAM, char **argv)
85 niro 532 {
86     int retval = EXIT_SUCCESS;
87 niro 816 int opt, flags;
88     struct param_t param;
89 niro 532
90 niro 816 param.ugid.uid = -1;
91     param.ugid.gid = -1;
92    
93 niro 984 #if ENABLE_FEATURE_CHOWN_LONG_OPTIONS
94     applet_long_options = chown_longopts;
95     #endif
96 niro 532 opt_complementary = "-2";
97 niro 816 opt = getopt32(argv, OPT_STR);
98 niro 532 argv += optind;
99    
100 niro 816 /* This matches coreutils behavior (almost - see below) */
101 niro 984 param.chown_func = chown;
102 niro 816 if (OPT_NODEREF
103     /* || (OPT_RECURSE && !OPT_TRAVERSE_TOP): */
104 niro 984 IF_DESKTOP( || (opt & (BIT_RECURSE|BIT_TRAVERSE_TOP)) == BIT_RECURSE)
105 niro 816 ) {
106     param.chown_func = lchown;
107     }
108 niro 532
109 niro 816 flags = ACTION_DEPTHFIRST; /* match coreutils order */
110     if (OPT_RECURSE)
111     flags |= ACTION_RECURSE;
112     if (OPT_TRAVERSE_TOP)
113     flags |= ACTION_FOLLOWLINKS_L0; /* -H/-L: follow links on depth 0 */
114     if (OPT_TRAVERSE)
115     flags |= ACTION_FOLLOWLINKS; /* follow links if -L */
116 niro 532
117 niro 816 parse_chown_usergroup_or_die(&param.ugid, argv[0]);
118 niro 532
119     /* Ok, ready to do the deed now */
120 niro 984 while (*++argv) {
121 niro 532 if (!recursive_action(*argv,
122 niro 816 flags, /* flags */
123     fileAction, /* file action */
124     fileAction, /* dir action */
125     &param, /* user data */
126     0) /* depth */
127 niro 532 ) {
128     retval = EXIT_FAILURE;
129     }
130 niro 984 }
131 niro 532
132     return retval;
133     }
134 niro 816
135     /*
136     Testcase. Run in empty directory.
137    
138     #!/bin/sh
139     t1="/tmp/busybox chown"
140     t2="/usr/bin/chown"
141     create() {
142     rm -rf $1; mkdir $1
143     (
144     cd $1 || exit 1
145     mkdir dir dir2
146     >up
147     >file
148     >dir/file
149     >dir2/file
150     ln -s dir linkdir
151     ln -s file linkfile
152     ln -s ../up dir/linkup
153     ln -s ../dir2 dir/linkupdir2
154     )
155     chown -R 0:0 $1
156     }
157     tst() {
158     create test1
159     create test2
160     echo "[$1]" >>test1.out
161     echo "[$1]" >>test2.out
162     (cd test1; $t1 $1) >>test1.out 2>&1
163     (cd test2; $t2 $1) >>test2.out 2>&1
164     (cd test1; ls -lnR) >out1
165     (cd test2; ls -lnR) >out2
166     echo "chown $1" >out.diff
167     if ! diff -u out1 out2 >>out.diff; then exit 1; fi
168     rm out.diff
169     }
170     tst_for_each() {
171     tst "$1 1:1 file"
172     tst "$1 1:1 dir"
173     tst "$1 1:1 linkdir"
174     tst "$1 1:1 linkfile"
175     }
176     echo "If script produced 'out.diff' file, then at least one testcase failed"
177     >test1.out
178     >test2.out
179     # These match coreutils 6.8:
180     tst_for_each "-v"
181     tst_for_each "-vR"
182     tst_for_each "-vRP"
183     tst_for_each "-vRL"
184     tst_for_each "-vRH"
185     tst_for_each "-vh"
186     tst_for_each "-vhR"
187     tst_for_each "-vhRP"
188     tst_for_each "-vhRL"
189     tst_for_each "-vhRH"
190     # Fix `name' in coreutils output
191     sed 's/`/'"'"'/g' -i test2.out
192     # Compare us with coreutils output
193     diff -u test1.out test2.out
194    
195     */