blob: d3e267827a15506f226fb97d3ad822c2e5dd4de1 [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 *
Erik Andersen61677fe2000-04-13 01:18:56 +00006 * Copyright (C) 1999,2000 by Lineo, inc.
Eric Andersenc4996011999-10-20 22:08:37 +00007 * 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
Mark Whitleyeec2f632000-06-06 18:11:46 +000028#define bb_need_too_few_args
Erik Andersenfac10d72000-02-07 05:29:42 +000029#include "messages.c"
30
Eric Andersencc8ed391999-10-05 16:24:54 +000031#include <stdio.h>
Eric Andersen2b69c401999-10-05 22:58:32 +000032#include <grp.h>
33#include <pwd.h>
Eric Andersencc8ed391999-10-05 16:24:54 +000034
Eric Andersencc8ed391999-10-05 16:24:54 +000035
Erik Andersen5b46d792000-05-17 05:24:24 +000036static unsigned long uid = -1;
37static unsigned long gid = -1;
Eric Andersen1b61f411999-10-13 18:56:42 +000038static int whichApp;
Erik Andersene49d5ec2000-02-08 19:58:47 +000039static char *invocationName = NULL;
40static char *theMode = NULL;
Eric Andersen2b69c401999-10-05 22:58:32 +000041
42
Eric Andersen1b61f411999-10-13 18:56:42 +000043#define CHGRP_APP 1
44#define CHOWN_APP 2
45#define CHMOD_APP 3
46
Erik Andersen1d1d9502000-04-21 01:26:49 +000047static const char chgrp_usage[] = "chgrp [OPTION]... GROUP FILE...\n"
48#ifndef BB_FEATURE_TRIVIAL_HELP
49 "\nChange the group membership of each FILE to GROUP.\n"
50 "\nOptions:\n\t-R\tChanges files and directories recursively.\n"
51#endif
52 ;
Erik Andersene49d5ec2000-02-08 19:58:47 +000053static const char chown_usage[] =
Erik Andersen1d1d9502000-04-21 01:26:49 +000054 "chown [OPTION]... OWNER[<.|:>[GROUP] FILE...\n"
55#ifndef BB_FEATURE_TRIVIAL_HELP
56 "\nChange the owner and/or group of each FILE to OWNER and/or GROUP.\n"
57 "\nOptions:\n\t-R\tChanges files and directories recursively.\n"
58#endif
59 ;
Erik Andersene49d5ec2000-02-08 19:58:47 +000060static const char chmod_usage[] =
Erik Andersen1d1d9502000-04-21 01:26:49 +000061 "chmod [-R] MODE[,MODE]... FILE...\n"
62#ifndef BB_FEATURE_TRIVIAL_HELP
63 "\nEach MODE is one or more of the letters ugoa, one of the symbols +-= and\n"
Erik Andersene49d5ec2000-02-08 19:58:47 +000064 "one or more of the letters rwxst.\n\n"
Erik Andersen1d1d9502000-04-21 01:26:49 +000065 "\nOptions:\n\t-R\tChanges files and directories recursively.\n"
66#endif
67 ;
Eric Andersen2b69c401999-10-05 22:58:32 +000068
69
Erik Andersen3364d782000-03-28 00:58:14 +000070static int fileAction(const char *fileName, struct stat *statbuf, void* junk)
Eric Andersencc8ed391999-10-05 16:24:54 +000071{
Erik Andersene49d5ec2000-02-08 19:58:47 +000072 switch (whichApp) {
Eric Andersen9b587181999-10-17 05:43:39 +000073 case CHGRP_APP:
74 case CHOWN_APP:
John Beppubf3a8382000-01-24 12:06:22 +000075#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
Erik Andersene49d5ec2000-02-08 19:58:47 +000076 if (lchown
77 (fileName, (whichApp == CHOWN_APP) ? uid : statbuf->st_uid,
78 (gid == -1) ? statbuf->st_gid : gid) == 0)
John Beppubf3a8382000-01-24 12:06:22 +000079#else
Erik Andersene49d5ec2000-02-08 19:58:47 +000080 if (chown
81 (fileName, (whichApp == CHOWN_APP) ? uid : statbuf->st_uid,
82 (gid == -1) ? statbuf->st_gid : gid) == 0)
John Beppubf3a8382000-01-24 12:06:22 +000083#endif
Erik Andersene49d5ec2000-02-08 19:58:47 +000084 {
85 return (TRUE);
86 }
87 break;
Eric Andersen9b587181999-10-17 05:43:39 +000088 case CHMOD_APP:
Erik Andersene49d5ec2000-02-08 19:58:47 +000089 /* Parse the specified modes */
90 if (parse_mode(theMode, &(statbuf->st_mode)) == FALSE) {
Erik Andersen9ffdaa62000-02-11 21:55:04 +000091 fatalError( "%s: unknown mode: %s\n", invocationName, theMode);
Erik Andersene49d5ec2000-02-08 19:58:47 +000092 }
93 if (chmod(fileName, statbuf->st_mode) == 0)
94 return (TRUE);
95 break;
96 }
97 perror(fileName);
98 return (FALSE);
Eric Andersencc8ed391999-10-05 16:24:54 +000099}
100
Eric Andersen1b61f411999-10-13 18:56:42 +0000101int chmod_chown_chgrp_main(int argc, char **argv)
Eric Andersencc8ed391999-10-05 16:24:54 +0000102{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000103 int recursiveFlag = FALSE;
Eric Andersenb6106152000-06-19 17:25:40 +0000104 char *groupName=NULL;
105 char *p=NULL;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000106 const char *appUsage;
Eric Andersen2b69c401999-10-05 22:58:32 +0000107
Erik Andersen246cc6d2000-03-07 07:41:42 +0000108 whichApp = (strcmp(*argv, "chown") == 0)?
Erik Andersen9ffdaa62000-02-11 21:55:04 +0000109 CHOWN_APP : (strcmp(*argv, "chmod") == 0)?
110 CHMOD_APP : CHGRP_APP;
Eric Andersen2b69c401999-10-05 22:58:32 +0000111
Erik Andersen246cc6d2000-03-07 07:41:42 +0000112 appUsage = (whichApp == CHOWN_APP)?
Erik Andersen9ffdaa62000-02-11 21:55:04 +0000113 chown_usage : (whichApp == CHMOD_APP) ? chmod_usage : chgrp_usage;
Eric Andersend73dc5b1999-11-10 23:13:02 +0000114
Erik Andersene49d5ec2000-02-08 19:58:47 +0000115 if (argc < 2)
116 usage(appUsage);
117 invocationName = *argv;
Eric Andersen2b69c401999-10-05 22:58:32 +0000118 argv++;
Eric Andersencc8ed391999-10-05 16:24:54 +0000119
Erik Andersene49d5ec2000-02-08 19:58:47 +0000120 /* Parse options */
Mark Whitleyeec2f632000-06-06 18:11:46 +0000121 while (--argc >= 0 && *argv && (**argv == '-')) {
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000122 while (*++(*argv)) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000123 switch (**argv) {
Mark Whitleyeec2f632000-06-06 18:11:46 +0000124 case 'R':
125 recursiveFlag = TRUE;
126 break;
127 default:
128 fprintf(stderr, invalid_option, invocationName, **argv);
129 usage(appUsage);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000130 }
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000131 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000132 argv++;
133 }
134
Mark Whitleyeec2f632000-06-06 18:11:46 +0000135 if (argc == 0 || *argv == NULL) {
136 fprintf(stderr, too_few_args, invocationName);
137 usage(appUsage);
138 }
139
Erik Andersene49d5ec2000-02-08 19:58:47 +0000140 if (whichApp == CHMOD_APP) {
141 theMode = *argv;
Eric Andersence8f3b91999-10-20 07:03:36 +0000142 } else {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000143
144 /* Find the selected group */
145 if (whichApp == CHGRP_APP) {
146 groupName = *argv;
147 gid = strtoul(groupName, &p, 10); /* maybe it's already numeric */
148 if (groupName == p)
149 gid = my_getgrnam(groupName);
150 if (gid == -1)
151 goto bad_group;
152 } else {
153 groupName = strchr(*argv, '.');
Erik Andersen632bb572000-04-18 22:09:06 +0000154 if (groupName == NULL)
155 groupName = strchr(*argv, ':');
Erik Andersene49d5ec2000-02-08 19:58:47 +0000156 if (groupName) {
157 *groupName++ = '\0';
158 gid = strtoul(groupName, &p, 10);
159 if (groupName == p)
160 gid = my_getgrnam(groupName);
161 if (gid == -1)
162 goto bad_group;
163 } else
164 gid = -1;
165 }
166
167
168 /* Find the selected user (if appropriate) */
169 if (whichApp == CHOWN_APP) {
170 uid = strtoul(*argv, &p, 10); /* if numeric ... */
171 if (*argv == p)
172 uid = my_getpwnam(*argv);
173 if (uid == -1) {
Erik Andersen9ffdaa62000-02-11 21:55:04 +0000174 fatalError( "%s: unknown user name: %s\n",
Erik Andersene49d5ec2000-02-08 19:58:47 +0000175 invocationName, *argv);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000176 }
177 }
Eric Andersen1b61f411999-10-13 18:56:42 +0000178 }
Eric Andersence8f3b91999-10-20 07:03:36 +0000179
Erik Andersene49d5ec2000-02-08 19:58:47 +0000180 /* Ok, ready to do the deed now */
181 if (argc <= 1) {
Erik Andersen9ffdaa62000-02-11 21:55:04 +0000182 fatalError( "%s: too few arguments\n", invocationName);
Eric Andersen1b61f411999-10-13 18:56:42 +0000183 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000184 while (argc-- > 1) {
Erik Andersen632bb572000-04-18 22:09:06 +0000185 if (recursiveAction (*(++argv), recursiveFlag, FALSE, FALSE,
Erik Andersen3364d782000-03-28 00:58:14 +0000186 fileAction, fileAction, NULL) == FALSE)
Erik Andersene49d5ec2000-02-08 19:58:47 +0000187 exit(FALSE);
188 }
189 exit(TRUE);
Eric Andersence8f3b91999-10-20 07:03:36 +0000190
Erik Andersene49d5ec2000-02-08 19:58:47 +0000191 bad_group:
Erik Andersen9ffdaa62000-02-11 21:55:04 +0000192 fatalError( "%s: unknown group name: %s\n", invocationName, groupName);
Eric Andersencc8ed391999-10-05 16:24:54 +0000193}
Erik Andersen029011b2000-03-04 21:19:32 +0000194
195/*
196Local Variables:
197c-file-style: "linux"
198c-basic-offset: 4
199tab-width: 4
200End:
201*/