Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1123 - (hide annotations) (download)
Wed Aug 18 21:56:57 2010 UTC (13 years, 9 months ago) by niro
File MIME type: text/plain
File size: 5145 byte(s)
-updated to busybox-1.17.1
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 niro 1123 uid_t u = (param.ugid.uid == (uid_t)-1L) ? statbuf->st_uid : param.ugid.uid;
66     gid_t g = (param.ugid.gid == (gid_t)-1L) ? 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 1123 bb_simple_perror_msg(fileName);
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 1123 /* Just -1 might not work: uid_t may be unsigned long */
91     param.ugid.uid = -1L;
92     param.ugid.gid = -1L;
93 niro 816
94 niro 984 #if ENABLE_FEATURE_CHOWN_LONG_OPTIONS
95     applet_long_options = chown_longopts;
96     #endif
97 niro 532 opt_complementary = "-2";
98 niro 816 opt = getopt32(argv, OPT_STR);
99 niro 532 argv += optind;
100    
101 niro 816 /* This matches coreutils behavior (almost - see below) */
102 niro 984 param.chown_func = chown;
103 niro 816 if (OPT_NODEREF
104     /* || (OPT_RECURSE && !OPT_TRAVERSE_TOP): */
105 niro 984 IF_DESKTOP( || (opt & (BIT_RECURSE|BIT_TRAVERSE_TOP)) == BIT_RECURSE)
106 niro 816 ) {
107     param.chown_func = lchown;
108     }
109 niro 532
110 niro 816 flags = ACTION_DEPTHFIRST; /* match coreutils order */
111     if (OPT_RECURSE)
112     flags |= ACTION_RECURSE;
113     if (OPT_TRAVERSE_TOP)
114     flags |= ACTION_FOLLOWLINKS_L0; /* -H/-L: follow links on depth 0 */
115     if (OPT_TRAVERSE)
116     flags |= ACTION_FOLLOWLINKS; /* follow links if -L */
117 niro 532
118 niro 816 parse_chown_usergroup_or_die(&param.ugid, argv[0]);
119 niro 532
120     /* Ok, ready to do the deed now */
121 niro 984 while (*++argv) {
122 niro 532 if (!recursive_action(*argv,
123 niro 816 flags, /* flags */
124     fileAction, /* file action */
125     fileAction, /* dir action */
126     &param, /* user data */
127     0) /* depth */
128 niro 532 ) {
129     retval = EXIT_FAILURE;
130     }
131 niro 984 }
132 niro 532
133     return retval;
134     }
135 niro 816
136     /*
137     Testcase. Run in empty directory.
138    
139     #!/bin/sh
140     t1="/tmp/busybox chown"
141     t2="/usr/bin/chown"
142     create() {
143     rm -rf $1; mkdir $1
144     (
145     cd $1 || exit 1
146     mkdir dir dir2
147     >up
148     >file
149     >dir/file
150     >dir2/file
151     ln -s dir linkdir
152     ln -s file linkfile
153     ln -s ../up dir/linkup
154     ln -s ../dir2 dir/linkupdir2
155     )
156     chown -R 0:0 $1
157     }
158     tst() {
159     create test1
160     create test2
161     echo "[$1]" >>test1.out
162     echo "[$1]" >>test2.out
163     (cd test1; $t1 $1) >>test1.out 2>&1
164     (cd test2; $t2 $1) >>test2.out 2>&1
165     (cd test1; ls -lnR) >out1
166     (cd test2; ls -lnR) >out2
167     echo "chown $1" >out.diff
168     if ! diff -u out1 out2 >>out.diff; then exit 1; fi
169     rm out.diff
170     }
171     tst_for_each() {
172     tst "$1 1:1 file"
173     tst "$1 1:1 dir"
174     tst "$1 1:1 linkdir"
175     tst "$1 1:1 linkfile"
176     }
177     echo "If script produced 'out.diff' file, then at least one testcase failed"
178     >test1.out
179     >test2.out
180     # These match coreutils 6.8:
181     tst_for_each "-v"
182     tst_for_each "-vR"
183     tst_for_each "-vRP"
184     tst_for_each "-vRL"
185     tst_for_each "-vRH"
186     tst_for_each "-vh"
187     tst_for_each "-vhR"
188     tst_for_each "-vhRP"
189     tst_for_each "-vhRL"
190     tst_for_each "-vhRH"
191     # Fix `name' in coreutils output
192     sed 's/`/'"'"'/g' -i test2.out
193     # Compare us with coreutils output
194     diff -u test1.out test2.out
195    
196     */