178138a3ba120422a7d15ced1184c7f2a9e3972e
[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,2001 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 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35
36
37 static long uid = -1;
38 static long gid = -1;
39 static int whichApp;
40 static char *theMode = NULL;
41
42
43 #define CHGRP_APP   1
44 #define CHOWN_APP   2
45 #define CHMOD_APP   3
46
47 static int fileAction(const char *fileName, struct stat *statbuf, void* junk)
48 {
49         switch (whichApp) {
50         case CHGRP_APP:
51         case CHOWN_APP:
52 #if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
53                 if (lchown
54                         (fileName, (whichApp == CHOWN_APP) ? uid : statbuf->st_uid,
55                          (gid == -1) ? statbuf->st_gid : gid) == 0)
56 #else
57                 if (chown
58                         (fileName, (whichApp == CHOWN_APP) ? uid : statbuf->st_uid,
59                          (gid == -1) ? statbuf->st_gid : gid) == 0)
60 #endif
61                 {
62                         return (TRUE);
63                 }
64                 break;
65         case CHMOD_APP:
66                 /* Parse the specified modes */
67                 if (parse_mode(theMode, &(statbuf->st_mode)) == FALSE) {
68                         error_msg_and_die( "unknown mode: %s\n", theMode);
69                 }
70                 if (chmod(fileName, statbuf->st_mode) == 0)
71                         return (TRUE);
72                 break;
73         }
74         perror(fileName);
75         return (FALSE);
76 }
77
78 int chmod_chown_chgrp_main(int argc, char **argv)
79 {
80         int stopIt = FALSE;
81         int recursiveFlag = FALSE;
82         char *groupName=NULL;
83         char *p=NULL;
84         const char *appUsage;
85
86         whichApp = (applet_name[2]=='o')?           /* chown */
87                 CHOWN_APP : (applet_name[2]=='m')?      /* chmod */
88                 CHMOD_APP : CHGRP_APP;
89
90         appUsage = (whichApp == CHOWN_APP)? 
91                         chown_usage : (whichApp == CHMOD_APP) ? chmod_usage : chgrp_usage;
92
93         if (argc < 2)
94                 usage(appUsage);
95         argv++;
96
97         /* Parse options */
98         while (--argc >= 0 && *argv && (**argv == '-')) {
99                 while (stopIt==FALSE && *++(*argv)) {
100                         switch (**argv) {
101                                 case 'R':
102                                         recursiveFlag = TRUE;
103                                         break;
104                                 default:
105                                         theMode=*argv-1;
106                                         stopIt = TRUE;
107                         }
108                 }
109                 if (stopIt==TRUE)
110                         break;
111                 argv++;
112         }
113
114         if (argc == 0 || *argv == NULL) {
115                 error_msg(too_few_args);
116         }
117
118         if (whichApp == CHMOD_APP) {
119                 if (theMode==NULL)
120                         theMode = *argv;
121         } else {
122
123                 /* Find the selected group */
124                 if (whichApp == CHGRP_APP) {
125                         groupName = *argv;
126                         gid = strtoul(groupName, &p, 10);       /* maybe it's already numeric */
127                         if (groupName == p)
128                                 gid = my_getgrnam(groupName);
129                         if (gid == -1)
130                                 goto bad_group;
131                 } else {
132                         groupName = strchr(*argv, '.');
133                         if (groupName == NULL)
134                                 groupName = strchr(*argv, ':');
135                         if (groupName) {
136                                 *groupName++ = '\0';
137                                 gid = strtoul(groupName, &p, 10);
138                                 if (groupName == p)
139                                         gid = my_getgrnam(groupName);
140                                 if (gid == -1)
141                                         goto bad_group;
142                         } else
143                                 gid = -1;
144                 }
145
146
147                 /* Find the selected user (if appropriate)  */
148                 if (whichApp == CHOWN_APP) {
149                         uid = strtoul(*argv, &p, 10);   /* if numeric ... */
150                         if (*argv == p)
151                                 uid = my_getpwnam(*argv);
152                         if (uid == -1) {
153                                 error_msg_and_die( "unknown user name: %s\n", *argv);
154                         }
155                 }
156         }
157
158         /* Ok, ready to do the deed now */
159         if (argc < 1) {
160                 error_msg_and_die(too_few_args);
161         }
162         while (argc-- > 1) {
163                 if (recursive_action (*(++argv), recursiveFlag, FALSE, FALSE, 
164                                         fileAction, fileAction, NULL) == FALSE)
165                         return EXIT_FAILURE;
166         }
167         return EXIT_SUCCESS;
168
169   bad_group:
170         error_msg_and_die( "unknown group name: %s\n", groupName);
171 }
172
173 /*
174 Local Variables:
175 c-file-style: "linux"
176 c-basic-offset: 4
177 tab-width: 4
178 End:
179 */