f6ecfd6f86879143039528bdf4f5d207feb34b35
[oweals/busybox.git] / chmod_chown_chgrp.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Mini chown/chmod/chgrp implementation for busybox
4  *
5  *
6  * Copyright (C) 1999,2000 by Lineo, inc.
7  * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  *
23  */
24
25 #include "busybox.h"
26 #define BB_DECLARE_EXTERN
27 #define bb_need_invalid_option
28 #define bb_need_too_few_args
29 #include "messages.c"
30
31 #include <stdio.h>
32
33
34 static long uid = -1;
35 static long gid = -1;
36 static int whichApp;
37 static char *theMode = NULL;
38
39
40 #define CHGRP_APP   1
41 #define CHOWN_APP   2
42 #define CHMOD_APP   3
43
44 static int fileAction(const char *fileName, struct stat *statbuf, void* junk)
45 {
46         switch (whichApp) {
47         case CHGRP_APP:
48         case CHOWN_APP:
49 #if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
50                 if (lchown
51                         (fileName, (whichApp == CHOWN_APP) ? uid : statbuf->st_uid,
52                          (gid == -1) ? statbuf->st_gid : gid) == 0)
53 #else
54                 if (chown
55                         (fileName, (whichApp == CHOWN_APP) ? uid : statbuf->st_uid,
56                          (gid == -1) ? statbuf->st_gid : gid) == 0)
57 #endif
58                 {
59                         return (TRUE);
60                 }
61                 break;
62         case CHMOD_APP:
63                 /* Parse the specified modes */
64                 if (parse_mode(theMode, &(statbuf->st_mode)) == FALSE) {
65                         error_msg_and_die( "unknown mode: %s\n", theMode);
66                 }
67                 if (chmod(fileName, statbuf->st_mode) == 0)
68                         return (TRUE);
69                 break;
70         }
71         perror(fileName);
72         return (FALSE);
73 }
74
75 int chmod_chown_chgrp_main(int argc, char **argv)
76 {
77         int stopIt = FALSE;
78         int recursiveFlag = FALSE;
79         char *groupName=NULL;
80         char *p=NULL;
81         const char *appUsage;
82
83         whichApp = (strcmp(applet_name, "chown") == 0)? 
84                         CHOWN_APP : (strcmp(applet_name, "chmod") == 0)? 
85                                 CHMOD_APP : CHGRP_APP;
86
87         appUsage = (whichApp == CHOWN_APP)? 
88                         chown_usage : (whichApp == CHMOD_APP) ? chmod_usage : chgrp_usage;
89
90         if (argc < 2)
91                 usage(appUsage);
92         argv++;
93
94         /* Parse options */
95         while (--argc >= 0 && *argv && (**argv == '-')) {
96                 while (stopIt==FALSE && *++(*argv)) {
97                         switch (**argv) {
98                                 case 'R':
99                                         recursiveFlag = TRUE;
100                                         break;
101                                 default:
102                                         theMode=*argv-1;
103                                         stopIt = TRUE;
104                         }
105                 }
106                 if (stopIt==TRUE)
107                         break;
108                 argv++;
109         }
110
111         if (argc == 0 || *argv == NULL) {
112                 error_msg(too_few_args);
113         }
114
115         if (whichApp == CHMOD_APP) {
116                 if (theMode==NULL)
117                         theMode = *argv;
118         } else {
119
120                 /* Find the selected group */
121                 if (whichApp == CHGRP_APP) {
122                         groupName = *argv;
123                         gid = strtoul(groupName, &p, 10);       /* maybe it's already numeric */
124                         if (groupName == p)
125                                 gid = my_getgrnam(groupName);
126                         if (gid == -1)
127                                 goto bad_group;
128                 } else {
129                         groupName = strchr(*argv, '.');
130                         if (groupName == NULL)
131                                 groupName = strchr(*argv, ':');
132                         if (groupName) {
133                                 *groupName++ = '\0';
134                                 gid = strtoul(groupName, &p, 10);
135                                 if (groupName == p)
136                                         gid = my_getgrnam(groupName);
137                                 if (gid == -1)
138                                         goto bad_group;
139                         } else
140                                 gid = -1;
141                 }
142
143
144                 /* Find the selected user (if appropriate)  */
145                 if (whichApp == CHOWN_APP) {
146                         uid = strtoul(*argv, &p, 10);   /* if numeric ... */
147                         if (*argv == p)
148                                 uid = my_getpwnam(*argv);
149                         if (uid == -1) {
150                                 error_msg_and_die( "unknown user name: %s\n", *argv);
151                         }
152                 }
153         }
154
155         /* Ok, ready to do the deed now */
156         if (argc < 1) {
157                 error_msg_and_die(too_few_args);
158         }
159         while (argc-- > 1) {
160                 if (recursive_action (*(++argv), recursiveFlag, FALSE, FALSE, 
161                                         fileAction, fileAction, NULL) == FALSE)
162                         return EXIT_FAILURE;
163         }
164         return EXIT_SUCCESS;
165
166   bad_group:
167         error_msg_and_die( "unknown group name: %s\n", groupName);
168 }
169
170 /*
171 Local Variables:
172 c-file-style: "linux"
173 c-basic-offset: 4
174 tab-width: 4
175 End:
176 */