blob: b4c5da9360f412da14241ef7112de8e10a527278 [file] [log] [blame]
Eric Andersen2b69c401999-10-05 22:58:32 +00001/*
Eric Andersen1b61f411999-10-13 18:56:42 +00002 * Mini chown/chmod/chgrp implementation for busybox
Eric Andersen2b69c401999-10-05 22:58:32 +00003 *
Eric Andersenc4996011999-10-20 22:08:37 +00004 *
5 * Copyright (C) 1999 by Lineo, inc.
6 * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
Eric Andersen2b69c401999-10-05 22:58:32 +00007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
Erik Andersenfac10d72000-02-07 05:29:42 +000024#include "internal.h"
25#define BB_DECLARE_EXTERN
26#define bb_need_invalid_option
27#include "messages.c"
28
Eric Andersencc8ed391999-10-05 16:24:54 +000029#include <stdio.h>
Eric Andersen2b69c401999-10-05 22:58:32 +000030#include <grp.h>
31#include <pwd.h>
Eric Andersencc8ed391999-10-05 16:24:54 +000032
Eric Andersencc8ed391999-10-05 16:24:54 +000033
Erik Andersen04e97022000-01-29 07:06:24 +000034static uid_t uid = -1;
35static gid_t gid = -1;
Eric Andersen1b61f411999-10-13 18:56:42 +000036static int whichApp;
Eric Andersen2b69c401999-10-05 22:58:32 +000037static char* invocationName=NULL;
Eric Andersended62591999-11-18 00:19:26 +000038static char* theMode=NULL;
Eric Andersen2b69c401999-10-05 22:58:32 +000039
40
Eric Andersen1b61f411999-10-13 18:56:42 +000041#define CHGRP_APP 1
42#define CHOWN_APP 2
43#define CHMOD_APP 3
44
Eric Andersend73dc5b1999-11-10 23:13:02 +000045static const char chgrp_usage[] = "chgrp [OPTION]... GROUP FILE...\n\n"
Eric Andersen2b69c401999-10-05 22:58:32 +000046 "Change the group membership of each FILE to GROUP.\n"
Eric Andersend73dc5b1999-11-10 23:13:02 +000047 "\nOptions:\n\t-R\tchange files and directories recursively\n";
48static const char chown_usage[] = "chown [OPTION]... OWNER[.[GROUP] FILE...\n\n"
Eric Andersen2b69c401999-10-05 22:58:32 +000049 "Change the owner and/or group of each FILE to OWNER and/or GROUP.\n"
Eric Andersend73dc5b1999-11-10 23:13:02 +000050 "\nOptions:\n\t-R\tchange files and directories recursively\n";
51static const char chmod_usage[] = "chmod [-R] MODE[,MODE]... FILE...\n\n"
Eric Andersen1b61f411999-10-13 18:56:42 +000052"Each MODE is one or more of the letters ugoa, one of the symbols +-= and\n"
53"one or more of the letters rwxst.\n\n"
Eric Andersend73dc5b1999-11-10 23:13:02 +000054 "\nOptions:\n\t-R\tchange files and directories recursively.\n";
Eric Andersen2b69c401999-10-05 22:58:32 +000055
56
Eric Andersen9b587181999-10-17 05:43:39 +000057static int fileAction(const char *fileName, struct stat* statbuf)
Eric Andersencc8ed391999-10-05 16:24:54 +000058{
Eric Andersen9b587181999-10-17 05:43:39 +000059 switch (whichApp) {
60 case CHGRP_APP:
61 case CHOWN_APP:
John Beppubf3a8382000-01-24 12:06:22 +000062#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
John Beppua4a8fd02000-01-23 13:38:32 +000063 if (lchown(fileName, (whichApp==CHOWN_APP)? uid : statbuf->st_uid,
John Beppubf3a8382000-01-24 12:06:22 +000064 (gid==-1)? statbuf->st_gid : gid) == 0)
65#else
66 if (chown(fileName, (whichApp==CHOWN_APP)? uid : statbuf->st_uid,
67 (gid==-1)? statbuf->st_gid : gid) == 0)
68#endif
69 {
Eric Andersen9b587181999-10-17 05:43:39 +000070 return( TRUE);
Eric Andersence8f3b91999-10-20 07:03:36 +000071 }
72 break;
Eric Andersen9b587181999-10-17 05:43:39 +000073 case CHMOD_APP:
Eric Andersended62591999-11-18 00:19:26 +000074 /* Parse the specified modes */
75 if ( parse_mode(theMode, &(statbuf->st_mode)) == FALSE ) {
Erik Andersenfac10d72000-02-07 05:29:42 +000076 fprintf(stderr, "%s: unknown mode: %s\n", invocationName, theMode);
Eric Andersended62591999-11-18 00:19:26 +000077 exit( FALSE);
78 }
79 if (chmod(fileName, statbuf->st_mode) == 0)
Eric Andersen9b587181999-10-17 05:43:39 +000080 return( TRUE);
Eric Andersence8f3b91999-10-20 07:03:36 +000081 break;
Eric Andersen2b69c401999-10-05 22:58:32 +000082 }
Eric Andersen1b61f411999-10-13 18:56:42 +000083 perror(fileName);
84 return( FALSE);
Eric Andersencc8ed391999-10-05 16:24:54 +000085}
86
Eric Andersen1b61f411999-10-13 18:56:42 +000087int chmod_chown_chgrp_main(int argc, char **argv)
Eric Andersencc8ed391999-10-05 16:24:54 +000088{
Eric Andersen2b69c401999-10-05 22:58:32 +000089 int recursiveFlag=FALSE;
90 char *groupName;
Erik Andersenfac10d72000-02-07 05:29:42 +000091 char *p;
Eric Andersend73dc5b1999-11-10 23:13:02 +000092 const char *appUsage;
Eric Andersen2b69c401999-10-05 22:58:32 +000093
Eric Andersen1b61f411999-10-13 18:56:42 +000094 whichApp = (strcmp(*argv, "chown")==0)? CHOWN_APP : (strcmp(*argv, "chmod")==0)? CHMOD_APP : CHGRP_APP;
Eric Andersen2b69c401999-10-05 22:58:32 +000095
Eric Andersend73dc5b1999-11-10 23:13:02 +000096 appUsage = (whichApp==CHOWN_APP)? chown_usage : (whichApp==CHMOD_APP)? chmod_usage : chgrp_usage;
97
98 if (argc < 2)
99 usage( appUsage);
Erik Andersen04e97022000-01-29 07:06:24 +0000100 invocationName = *argv;
Eric Andersen2b69c401999-10-05 22:58:32 +0000101 argc--;
102 argv++;
103
104 /* Parse options */
105 while (**argv == '-') {
106 while (*++(*argv)) switch (**argv) {
107 case 'R':
108 recursiveFlag = TRUE;
109 break;
110 default:
Erik Andersenfac10d72000-02-07 05:29:42 +0000111 fprintf(stderr, invalid_option, invocationName, **argv);
Eric Andersend73dc5b1999-11-10 23:13:02 +0000112 usage( appUsage);
Eric Andersencc8ed391999-10-05 16:24:54 +0000113 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000114 argc--;
Eric Andersen2b69c401999-10-05 22:58:32 +0000115 argv++;
116 }
117
Eric Andersen1b61f411999-10-13 18:56:42 +0000118 if ( whichApp == CHMOD_APP ) {
Erik Andersen04e97022000-01-29 07:06:24 +0000119 theMode = *argv;
Eric Andersen1b61f411999-10-13 18:56:42 +0000120 } else {
Eric Andersencc8ed391999-10-05 16:24:54 +0000121
Eric Andersen1b61f411999-10-13 18:56:42 +0000122 /* Find the selected group */
Eric Andersenc4996011999-10-20 22:08:37 +0000123 if ( whichApp==CHGRP_APP ) {
Eric Andersen1b61f411999-10-13 18:56:42 +0000124 groupName = *argv;
Erik Andersenfac10d72000-02-07 05:29:42 +0000125 gid = strtoul(groupName, &p, 10); /* maybe it's already numeric */
126 if (groupName == p)
127 gid = my_getgrnam(groupName);
Eric Andersence8f3b91999-10-20 07:03:36 +0000128 if (gid == -1)
129 goto bad_group;
130 } else {
131 groupName = strchr(*argv, '.');
132 if (groupName) {
133 *groupName++ = '\0';
Erik Andersenfac10d72000-02-07 05:29:42 +0000134 gid = strtoul(groupName, &p, 10);
135 if (groupName == p)
136 gid = my_getgrnam(groupName);
Eric Andersence8f3b91999-10-20 07:03:36 +0000137 if (gid == -1)
138 goto bad_group;
139 } else
140 gid = -1;
Eric Andersen1b61f411999-10-13 18:56:42 +0000141 }
Eric Andersence8f3b91999-10-20 07:03:36 +0000142
Eric Andersen1b61f411999-10-13 18:56:42 +0000143
144 /* Find the selected user (if appropriate) */
Eric Andersence8f3b91999-10-20 07:03:36 +0000145 if (whichApp==CHOWN_APP) {
Erik Andersenfac10d72000-02-07 05:29:42 +0000146 uid = strtoul(*argv, &p, 10); /* if numeric ...*/
147 if (*argv == p)
148 uid = my_getpwnam(*argv);
Eric Andersence8f3b91999-10-20 07:03:36 +0000149 if (uid == -1) {
Erik Andersenfac10d72000-02-07 05:29:42 +0000150 fprintf(stderr, "%s: unknown user name: %s\n", invocationName, *argv);
Eric Andersen1b61f411999-10-13 18:56:42 +0000151 exit( FALSE);
152 }
Eric Andersen1b61f411999-10-13 18:56:42 +0000153 }
154 }
155
Eric Andersen2b69c401999-10-05 22:58:32 +0000156 /* Ok, ready to do the deed now */
157 if (argc <= 1) {
Erik Andersenfac10d72000-02-07 05:29:42 +0000158 fprintf(stderr, "%s: too few arguments\n", invocationName);
Eric Andersen2ce1edc1999-10-12 15:42:48 +0000159 exit( FALSE);
Eric Andersen2b69c401999-10-05 22:58:32 +0000160 }
161 while (argc-- > 1) {
Eric Andersenbed30e91999-10-18 19:02:32 +0000162 if (recursiveAction( *(++argv), recursiveFlag, TRUE, FALSE, fileAction, fileAction)==FALSE)
Eric Andersenf6be9441999-10-13 21:12:06 +0000163 exit( FALSE);
Eric Andersen2b69c401999-10-05 22:58:32 +0000164 }
Eric Andersen2ce1edc1999-10-12 15:42:48 +0000165 exit(TRUE);
Eric Andersence8f3b91999-10-20 07:03:36 +0000166
167bad_group:
Erik Andersenfac10d72000-02-07 05:29:42 +0000168 fprintf(stderr, "%s: unknown group name: %s\n", invocationName, groupName);
Eric Andersence8f3b91999-10-20 07:03:36 +0000169 exit( FALSE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000170}
Eric Andersen1b61f411999-10-13 18:56:42 +0000171
Eric Andersene77ae3a1999-10-19 20:03:34 +0000172