blob: 8bda06861b7ff4096203270ade5aea16db9ca72b [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 Andersenf6be9441999-10-13 21:12:06 +000034static mode_t mode=0644;
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 Andersen4bea32a1999-10-06 00:30:51 +000041static const char chgrp_usage[] = "[OPTION]... GROUP FILE...\n"
Eric Andersen2b69c401999-10-05 22:58:32 +000042 "Change the group membership of each FILE to GROUP.\n"
43 "\n\tOptions:\n" "\t-R\tchange files and directories recursively\n";
Eric Andersen4bea32a1999-10-06 00:30:51 +000044static const char chown_usage[] = "[OPTION]... OWNER[.[GROUP] FILE...\n"
Eric Andersen2b69c401999-10-05 22:58:32 +000045 "Change the owner and/or group of each FILE to OWNER and/or GROUP.\n"
46 "\n\tOptions:\n" "\t-R\tchange files and directories recursively\n";
Eric Andersen1b61f411999-10-13 18:56:42 +000047static const char chmod_usage[] = "[-R] MODE[,MODE]... FILE...\n"
48"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"
50 "\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 Andersence8f3b91999-10-20 07:03:36 +000064 if (chmod(fileName, mode) == 0)
Eric Andersen9b587181999-10-17 05:43:39 +000065 return( TRUE);
Eric Andersence8f3b91999-10-20 07:03:36 +000066 break;
Eric Andersen2b69c401999-10-05 22:58:32 +000067 }
Eric Andersen1b61f411999-10-13 18:56:42 +000068 perror(fileName);
69 return( FALSE);
Eric Andersencc8ed391999-10-05 16:24:54 +000070}
71
Eric Andersen1b61f411999-10-13 18:56:42 +000072int chmod_chown_chgrp_main(int argc, char **argv)
Eric Andersencc8ed391999-10-05 16:24:54 +000073{
Eric Andersen2b69c401999-10-05 22:58:32 +000074 int recursiveFlag=FALSE;
75 char *groupName;
Eric Andersen2b69c401999-10-05 22:58:32 +000076
Eric Andersen1b61f411999-10-13 18:56:42 +000077 whichApp = (strcmp(*argv, "chown")==0)? CHOWN_APP : (strcmp(*argv, "chmod")==0)? CHMOD_APP : CHGRP_APP;
Eric Andersen2b69c401999-10-05 22:58:32 +000078
79 if (argc < 2) {
80 fprintf(stderr, "Usage: %s %s", *argv,
Eric Andersen1b61f411999-10-13 18:56:42 +000081 (whichApp==TRUE)? chown_usage : chgrp_usage);
Eric Andersen2ce1edc1999-10-12 15:42:48 +000082 exit( FALSE);
Eric Andersen2b69c401999-10-05 22:58:32 +000083 }
84 invocationName=*argv;
85 argc--;
86 argv++;
87
88 /* Parse options */
89 while (**argv == '-') {
90 while (*++(*argv)) switch (**argv) {
91 case 'R':
92 recursiveFlag = TRUE;
93 break;
94 default:
95 fprintf(stderr, "Unknown option: %c\n", **argv);
Eric Andersen2ce1edc1999-10-12 15:42:48 +000096 exit( FALSE);
Eric Andersencc8ed391999-10-05 16:24:54 +000097 }
Eric Andersencc8ed391999-10-05 16:24:54 +000098 argc--;
Eric Andersen2b69c401999-10-05 22:58:32 +000099 argv++;
100 }
101
Eric Andersen1b61f411999-10-13 18:56:42 +0000102 if ( whichApp == CHMOD_APP ) {
103 /* Find the specified modes */
Eric Andersenabc7d591999-10-19 00:27:50 +0000104 mode &= S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
Eric Andersenf6be9441999-10-13 21:12:06 +0000105 if ( parse_mode(*argv, &mode) == FALSE ) {
Eric Andersen1b61f411999-10-13 18:56:42 +0000106 fprintf(stderr, "%s: Unknown mode: %s\n", invocationName, *argv);
Eric Andersen2ce1edc1999-10-12 15:42:48 +0000107 exit( FALSE);
Eric Andersen2b69c401999-10-05 22:58:32 +0000108 }
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