blob: c9ea39bf5d4ae35ba57633966dce946ce00f41c9 [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
Eric Andersencc8ed391999-10-05 16:24:54 +000024#include <stdio.h>
Eric Andersen2b69c401999-10-05 22:58:32 +000025#include <grp.h>
26#include <pwd.h>
27#include "internal.h"
Eric Andersencc8ed391999-10-05 16:24:54 +000028
Eric Andersencc8ed391999-10-05 16:24:54 +000029
Eric Andersence8f3b91999-10-20 07:03:36 +000030static uid_t uid=-1;
31static gid_t gid=-1;
Eric Andersen1b61f411999-10-13 18:56:42 +000032static int whichApp;
Eric Andersen2b69c401999-10-05 22:58:32 +000033static char* invocationName=NULL;
Eric Andersended62591999-11-18 00:19:26 +000034static char* theMode=NULL;
Eric Andersen2b69c401999-10-05 22:58:32 +000035
36
Eric Andersen1b61f411999-10-13 18:56:42 +000037#define CHGRP_APP 1
38#define CHOWN_APP 2
39#define CHMOD_APP 3
40
Eric Andersend73dc5b1999-11-10 23:13:02 +000041static const char chgrp_usage[] = "chgrp [OPTION]... GROUP FILE...\n\n"
Eric Andersen2b69c401999-10-05 22:58:32 +000042 "Change the group membership of each FILE to GROUP.\n"
Eric Andersend73dc5b1999-11-10 23:13:02 +000043 "\nOptions:\n\t-R\tchange files and directories recursively\n";
44static const char chown_usage[] = "chown [OPTION]... OWNER[.[GROUP] FILE...\n\n"
Eric Andersen2b69c401999-10-05 22:58:32 +000045 "Change the owner and/or group of each FILE to OWNER and/or GROUP.\n"
Eric Andersend73dc5b1999-11-10 23:13:02 +000046 "\nOptions:\n\t-R\tchange files and directories recursively\n";
47static const char chmod_usage[] = "chmod [-R] MODE[,MODE]... FILE...\n\n"
Eric Andersen1b61f411999-10-13 18:56:42 +000048"Each MODE is one or more of the letters ugoa, one of the symbols +-= and\n"
49"one or more of the letters rwxst.\n\n"
Eric Andersend73dc5b1999-11-10 23:13:02 +000050 "\nOptions:\n\t-R\tchange files and directories recursively.\n";
Eric Andersen2b69c401999-10-05 22:58:32 +000051
52
Eric Andersen9b587181999-10-17 05:43:39 +000053static int fileAction(const char *fileName, struct stat* statbuf)
Eric Andersencc8ed391999-10-05 16:24:54 +000054{
Eric Andersen9b587181999-10-17 05:43:39 +000055 switch (whichApp) {
56 case CHGRP_APP:
57 case CHOWN_APP:
Eric Andersence8f3b91999-10-20 07:03:36 +000058 if (chown(fileName, (whichApp==CHOWN_APP)? uid : statbuf->st_uid,
59 (gid==-1)? statbuf->st_gid : gid) == 0) {
Eric Andersen9b587181999-10-17 05:43:39 +000060 return( TRUE);
Eric Andersence8f3b91999-10-20 07:03:36 +000061 }
62 break;
Eric Andersen9b587181999-10-17 05:43:39 +000063 case CHMOD_APP:
Eric Andersended62591999-11-18 00:19:26 +000064 /* Parse the specified modes */
65 if ( parse_mode(theMode, &(statbuf->st_mode)) == FALSE ) {
66 fprintf(stderr, "%s: Unknown mode: %s\n", invocationName, theMode);
67 exit( FALSE);
68 }
69 if (chmod(fileName, statbuf->st_mode) == 0)
Eric Andersen9b587181999-10-17 05:43:39 +000070 return( TRUE);
Eric Andersence8f3b91999-10-20 07:03:36 +000071 break;
Eric Andersen2b69c401999-10-05 22:58:32 +000072 }
Eric Andersen1b61f411999-10-13 18:56:42 +000073 perror(fileName);
74 return( FALSE);
Eric Andersencc8ed391999-10-05 16:24:54 +000075}
76
Eric Andersen1b61f411999-10-13 18:56:42 +000077int chmod_chown_chgrp_main(int argc, char **argv)
Eric Andersencc8ed391999-10-05 16:24:54 +000078{
Eric Andersen2b69c401999-10-05 22:58:32 +000079 int recursiveFlag=FALSE;
80 char *groupName;
Eric Andersend73dc5b1999-11-10 23:13:02 +000081 const char *appUsage;
Eric Andersen2b69c401999-10-05 22:58:32 +000082
Eric Andersen1b61f411999-10-13 18:56:42 +000083 whichApp = (strcmp(*argv, "chown")==0)? CHOWN_APP : (strcmp(*argv, "chmod")==0)? CHMOD_APP : CHGRP_APP;
Eric Andersen2b69c401999-10-05 22:58:32 +000084
Eric Andersend73dc5b1999-11-10 23:13:02 +000085 appUsage = (whichApp==CHOWN_APP)? chown_usage : (whichApp==CHMOD_APP)? chmod_usage : chgrp_usage;
86
87 if (argc < 2)
88 usage( appUsage);
Eric Andersen2b69c401999-10-05 22:58:32 +000089 invocationName=*argv;
90 argc--;
91 argv++;
92
93 /* Parse options */
94 while (**argv == '-') {
95 while (*++(*argv)) switch (**argv) {
96 case 'R':
97 recursiveFlag = TRUE;
98 break;
99 default:
100 fprintf(stderr, "Unknown option: %c\n", **argv);
Eric Andersend73dc5b1999-11-10 23:13:02 +0000101 usage( appUsage);
Eric Andersencc8ed391999-10-05 16:24:54 +0000102 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000103 argc--;
Eric Andersen2b69c401999-10-05 22:58:32 +0000104 argv++;
105 }
106
Eric Andersen1b61f411999-10-13 18:56:42 +0000107 if ( whichApp == CHMOD_APP ) {
Eric Andersended62591999-11-18 00:19:26 +0000108 theMode=*argv;
Eric Andersen1b61f411999-10-13 18:56:42 +0000109 } else {
Eric Andersencc8ed391999-10-05 16:24:54 +0000110
Eric Andersen1b61f411999-10-13 18:56:42 +0000111 /* Find the selected group */
Eric Andersenc4996011999-10-20 22:08:37 +0000112 if ( whichApp==CHGRP_APP ) {
Eric Andersen1b61f411999-10-13 18:56:42 +0000113 groupName = *argv;
Eric Andersence8f3b91999-10-20 07:03:36 +0000114 gid = my_getgrnam(groupName);
115 if (gid == -1)
116 goto bad_group;
117 } else {
118 groupName = strchr(*argv, '.');
119 if (groupName) {
120 *groupName++ = '\0';
121 gid = my_getgrnam(groupName);
122 if (gid == -1)
123 goto bad_group;
124 } else
125 gid = -1;
Eric Andersen1b61f411999-10-13 18:56:42 +0000126 }
Eric Andersence8f3b91999-10-20 07:03:36 +0000127
Eric Andersen1b61f411999-10-13 18:56:42 +0000128
129 /* Find the selected user (if appropriate) */
Eric Andersence8f3b91999-10-20 07:03:36 +0000130 if (whichApp==CHOWN_APP) {
131 uid = my_getpwnam(*argv);
132 if (uid == -1) {
Eric Andersen1b61f411999-10-13 18:56:42 +0000133 fprintf(stderr, "%s: Unknown user name: %s\n", invocationName, *argv);
134 exit( FALSE);
135 }
Eric Andersen1b61f411999-10-13 18:56:42 +0000136 }
137 }
138
Eric Andersen2b69c401999-10-05 22:58:32 +0000139 /* Ok, ready to do the deed now */
140 if (argc <= 1) {
141 fprintf(stderr, "%s: too few arguments", invocationName);
Eric Andersen2ce1edc1999-10-12 15:42:48 +0000142 exit( FALSE);
Eric Andersen2b69c401999-10-05 22:58:32 +0000143 }
144 while (argc-- > 1) {
Eric Andersenbed30e91999-10-18 19:02:32 +0000145 if (recursiveAction( *(++argv), recursiveFlag, TRUE, FALSE, fileAction, fileAction)==FALSE)
Eric Andersenf6be9441999-10-13 21:12:06 +0000146 exit( FALSE);
Eric Andersen2b69c401999-10-05 22:58:32 +0000147 }
Eric Andersen2ce1edc1999-10-12 15:42:48 +0000148 exit(TRUE);
Eric Andersence8f3b91999-10-20 07:03:36 +0000149
150bad_group:
151 fprintf(stderr, "%s: Unknown group name: %s\n", invocationName, groupName);
152 exit( FALSE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000153}
Eric Andersen1b61f411999-10-13 18:56:42 +0000154
Eric Andersene77ae3a1999-10-19 20:03:34 +0000155