blob: e197ee3e8c6b1c61d69bbeceb8ce3604ec7e0343 [file] [log] [blame]
Erik Andersene49d5ec2000-02-08 19:58:47 +00001/* vi: set sw=4 ts=4: */
Eric Andersen2b69c401999-10-05 22:58:32 +00002/*
Eric Andersen1b61f411999-10-13 18:56:42 +00003 * Mini chown/chmod/chgrp implementation for busybox
Eric Andersen2b69c401999-10-05 22:58:32 +00004 *
Eric Andersenc4996011999-10-20 22:08:37 +00005 *
6 * Copyright (C) 1999 by Lineo, inc.
7 * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
Eric Andersen2b69c401999-10-05 22:58:32 +00008 *
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
Erik Andersenfac10d72000-02-07 05:29:42 +000025#include "internal.h"
26#define BB_DECLARE_EXTERN
27#define bb_need_invalid_option
28#include "messages.c"
29
Eric Andersencc8ed391999-10-05 16:24:54 +000030#include <stdio.h>
Eric Andersen2b69c401999-10-05 22:58:32 +000031#include <grp.h>
32#include <pwd.h>
Eric Andersencc8ed391999-10-05 16:24:54 +000033
Eric Andersencc8ed391999-10-05 16:24:54 +000034
Erik Andersen04e97022000-01-29 07:06:24 +000035static uid_t uid = -1;
36static gid_t gid = -1;
Eric Andersen1b61f411999-10-13 18:56:42 +000037static int whichApp;
Erik Andersene49d5ec2000-02-08 19:58:47 +000038static char *invocationName = NULL;
39static char *theMode = NULL;
Eric Andersen2b69c401999-10-05 22:58:32 +000040
41
Eric Andersen1b61f411999-10-13 18:56:42 +000042#define CHGRP_APP 1
43#define CHOWN_APP 2
44#define CHMOD_APP 3
45
Eric Andersend73dc5b1999-11-10 23:13:02 +000046static const char chgrp_usage[] = "chgrp [OPTION]... GROUP FILE...\n\n"
Erik Andersene49d5ec2000-02-08 19:58:47 +000047 "Change the group membership of each FILE to GROUP.\n"
48
49 "\nOptions:\n\t-R\tchange files and directories recursively\n";
50static const char chown_usage[] =
51 "chown [OPTION]... OWNER[.[GROUP] FILE...\n\n"
52 "Change the owner and/or group of each FILE to OWNER and/or GROUP.\n"
53
54 "\nOptions:\n\t-R\tchange files and directories recursively\n";
55static const char chmod_usage[] =
56 "chmod [-R] MODE[,MODE]... FILE...\n\n"
57 "Each MODE is one or more of the letters ugoa, one of the symbols +-= and\n"
58
59 "one or more of the letters rwxst.\n\n"
60 "\nOptions:\n\t-R\tchange files and directories recursively.\n";
Eric Andersen2b69c401999-10-05 22:58:32 +000061
62
Erik Andersene49d5ec2000-02-08 19:58:47 +000063static int fileAction(const char *fileName, struct stat *statbuf)
Eric Andersencc8ed391999-10-05 16:24:54 +000064{
Erik Andersene49d5ec2000-02-08 19:58:47 +000065 switch (whichApp) {
Eric Andersen9b587181999-10-17 05:43:39 +000066 case CHGRP_APP:
67 case CHOWN_APP:
John Beppubf3a8382000-01-24 12:06:22 +000068#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
Erik Andersene49d5ec2000-02-08 19:58:47 +000069 if (lchown
70 (fileName, (whichApp == CHOWN_APP) ? uid : statbuf->st_uid,
71 (gid == -1) ? statbuf->st_gid : gid) == 0)
John Beppubf3a8382000-01-24 12:06:22 +000072#else
Erik Andersene49d5ec2000-02-08 19:58:47 +000073 if (chown
74 (fileName, (whichApp == CHOWN_APP) ? uid : statbuf->st_uid,
75 (gid == -1) ? statbuf->st_gid : gid) == 0)
John Beppubf3a8382000-01-24 12:06:22 +000076#endif
Erik Andersene49d5ec2000-02-08 19:58:47 +000077 {
78 return (TRUE);
79 }
80 break;
Eric Andersen9b587181999-10-17 05:43:39 +000081 case CHMOD_APP:
Erik Andersene49d5ec2000-02-08 19:58:47 +000082 /* Parse the specified modes */
83 if (parse_mode(theMode, &(statbuf->st_mode)) == FALSE) {
Erik Andersen9ffdaa62000-02-11 21:55:04 +000084 fatalError( "%s: unknown mode: %s\n", invocationName, theMode);
Erik Andersene49d5ec2000-02-08 19:58:47 +000085 }
86 if (chmod(fileName, statbuf->st_mode) == 0)
87 return (TRUE);
88 break;
89 }
90 perror(fileName);
91 return (FALSE);
Eric Andersencc8ed391999-10-05 16:24:54 +000092}
93
Eric Andersen1b61f411999-10-13 18:56:42 +000094int chmod_chown_chgrp_main(int argc, char **argv)
Eric Andersencc8ed391999-10-05 16:24:54 +000095{
Erik Andersene49d5ec2000-02-08 19:58:47 +000096 int recursiveFlag = FALSE;
97 char *groupName;
98 char *p;
99 const char *appUsage;
Eric Andersen2b69c401999-10-05 22:58:32 +0000100
Erik Andersen246cc6d2000-03-07 07:41:42 +0000101 whichApp = (strcmp(*argv, "chown") == 0)?
Erik Andersen9ffdaa62000-02-11 21:55:04 +0000102 CHOWN_APP : (strcmp(*argv, "chmod") == 0)?
103 CHMOD_APP : CHGRP_APP;
Eric Andersen2b69c401999-10-05 22:58:32 +0000104
Erik Andersen246cc6d2000-03-07 07:41:42 +0000105 appUsage = (whichApp == CHOWN_APP)?
Erik Andersen9ffdaa62000-02-11 21:55:04 +0000106 chown_usage : (whichApp == CHMOD_APP) ? chmod_usage : chgrp_usage;
Eric Andersend73dc5b1999-11-10 23:13:02 +0000107
Erik Andersene49d5ec2000-02-08 19:58:47 +0000108 if (argc < 2)
109 usage(appUsage);
110 invocationName = *argv;
Eric Andersencc8ed391999-10-05 16:24:54 +0000111 argc--;
Eric Andersen2b69c401999-10-05 22:58:32 +0000112 argv++;
Eric Andersencc8ed391999-10-05 16:24:54 +0000113
Erik Andersene49d5ec2000-02-08 19:58:47 +0000114 /* Parse options */
115 while (**argv == '-') {
116 while (*++(*argv))
117 switch (**argv) {
118 case 'R':
119 recursiveFlag = TRUE;
120 break;
121 default:
122 fprintf(stderr, invalid_option, invocationName, **argv);
123 usage(appUsage);
124 }
125 argc--;
126 argv++;
127 }
128
129 if (whichApp == CHMOD_APP) {
130 theMode = *argv;
Eric Andersence8f3b91999-10-20 07:03:36 +0000131 } else {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000132
133 /* Find the selected group */
134 if (whichApp == CHGRP_APP) {
135 groupName = *argv;
136 gid = strtoul(groupName, &p, 10); /* maybe it's already numeric */
137 if (groupName == p)
138 gid = my_getgrnam(groupName);
139 if (gid == -1)
140 goto bad_group;
141 } else {
142 groupName = strchr(*argv, '.');
143 if (groupName) {
144 *groupName++ = '\0';
145 gid = strtoul(groupName, &p, 10);
146 if (groupName == p)
147 gid = my_getgrnam(groupName);
148 if (gid == -1)
149 goto bad_group;
150 } else
151 gid = -1;
152 }
153
154
155 /* Find the selected user (if appropriate) */
156 if (whichApp == CHOWN_APP) {
157 uid = strtoul(*argv, &p, 10); /* if numeric ... */
158 if (*argv == p)
159 uid = my_getpwnam(*argv);
160 if (uid == -1) {
Erik Andersen9ffdaa62000-02-11 21:55:04 +0000161 fatalError( "%s: unknown user name: %s\n",
Erik Andersene49d5ec2000-02-08 19:58:47 +0000162 invocationName, *argv);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000163 }
164 }
Eric Andersen1b61f411999-10-13 18:56:42 +0000165 }
Eric Andersence8f3b91999-10-20 07:03:36 +0000166
Erik Andersene49d5ec2000-02-08 19:58:47 +0000167 /* Ok, ready to do the deed now */
168 if (argc <= 1) {
Erik Andersen9ffdaa62000-02-11 21:55:04 +0000169 fatalError( "%s: too few arguments\n", invocationName);
Eric Andersen1b61f411999-10-13 18:56:42 +0000170 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000171 while (argc-- > 1) {
172 if (recursiveAction
173 (*(++argv), recursiveFlag, TRUE, FALSE, fileAction,
174 fileAction) == FALSE)
175 exit(FALSE);
176 }
177 exit(TRUE);
Eric Andersence8f3b91999-10-20 07:03:36 +0000178
Erik Andersene49d5ec2000-02-08 19:58:47 +0000179 bad_group:
Erik Andersen9ffdaa62000-02-11 21:55:04 +0000180 fatalError( "%s: unknown group name: %s\n", invocationName, groupName);
Eric Andersencc8ed391999-10-05 16:24:54 +0000181}
Erik Andersen029011b2000-03-04 21:19:32 +0000182
183/*
184Local Variables:
185c-file-style: "linux"
186c-basic-offset: 4
187tab-width: 4
188End:
189*/