blob: 9714e1ca57ed84a017dfe1294dc23e137f4c93bf [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 *
Eric Andersen8ec10a92001-01-27 09:33:39 +00006 * Copyright (C) 1999,2000,2001 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
Eric Andersencbe31da2001-02-20 06:14:08 +000025#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <unistd.h>
Eric Andersen3570a342000-09-25 21:45:58 +000029#include "busybox.h"
Erik Andersenfac10d72000-02-07 05:29:42 +000030#define BB_DECLARE_EXTERN
31#define bb_need_invalid_option
Mark Whitleyeec2f632000-06-06 18:11:46 +000032#define bb_need_too_few_args
Erik Andersenfac10d72000-02-07 05:29:42 +000033#include "messages.c"
34
Eric Andersencc8ed391999-10-05 16:24:54 +000035
Eric Andersencc8ed391999-10-05 16:24:54 +000036
Eric Andersen58361a42000-07-14 06:27:54 +000037static long uid = -1;
38static long gid = -1;
Eric Andersen1b61f411999-10-13 18:56:42 +000039static int whichApp;
Erik Andersene49d5ec2000-02-08 19:58:47 +000040static 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 Andersen3364d782000-03-28 00:58:14 +000047static int fileAction(const char *fileName, struct stat *statbuf, void* junk)
Eric Andersencc8ed391999-10-05 16:24:54 +000048{
Erik Andersene49d5ec2000-02-08 19:58:47 +000049 switch (whichApp) {
Eric Andersen9b587181999-10-17 05:43:39 +000050 case CHGRP_APP:
51 case CHOWN_APP:
Eric Andersenb6b519b2001-04-09 23:52:18 +000052 /* Don't use lchown for libc5 or glibc older then 2.1.x */
John Beppubf3a8382000-01-24 12:06:22 +000053#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
Erik Andersene49d5ec2000-02-08 19:58:47 +000054 if (lchown
55 (fileName, (whichApp == CHOWN_APP) ? uid : statbuf->st_uid,
56 (gid == -1) ? statbuf->st_gid : gid) == 0)
John Beppubf3a8382000-01-24 12:06:22 +000057#else
Erik Andersene49d5ec2000-02-08 19:58:47 +000058 if (chown
59 (fileName, (whichApp == CHOWN_APP) ? uid : statbuf->st_uid,
60 (gid == -1) ? statbuf->st_gid : gid) == 0)
John Beppubf3a8382000-01-24 12:06:22 +000061#endif
Erik Andersene49d5ec2000-02-08 19:58:47 +000062 {
63 return (TRUE);
64 }
65 break;
Eric Andersen9b587181999-10-17 05:43:39 +000066 case CHMOD_APP:
Erik Andersene49d5ec2000-02-08 19:58:47 +000067 /* Parse the specified modes */
68 if (parse_mode(theMode, &(statbuf->st_mode)) == FALSE) {
Matt Kraaidd19c692001-01-31 19:00:21 +000069 error_msg_and_die( "unknown mode: %s", theMode);
Erik Andersene49d5ec2000-02-08 19:58:47 +000070 }
71 if (chmod(fileName, statbuf->st_mode) == 0)
72 return (TRUE);
73 break;
74 }
75 perror(fileName);
76 return (FALSE);
Eric Andersencc8ed391999-10-05 16:24:54 +000077}
78
Eric Andersen1b61f411999-10-13 18:56:42 +000079int chmod_chown_chgrp_main(int argc, char **argv)
Eric Andersencc8ed391999-10-05 16:24:54 +000080{
Eric Andersence82c8a2000-08-22 01:00:56 +000081 int stopIt = FALSE;
Erik Andersene49d5ec2000-02-08 19:58:47 +000082 int recursiveFlag = FALSE;
Eric Andersenb6106152000-06-19 17:25:40 +000083 char *groupName=NULL;
84 char *p=NULL;
Eric Andersen2b69c401999-10-05 22:58:32 +000085
Eric Andersen704d2a62001-01-31 17:29:12 +000086 whichApp = (applet_name[2]=='o')? /* chown */
87 CHOWN_APP : (applet_name[2]=='m')? /* chmod */
88 CHMOD_APP : CHGRP_APP;
Eric Andersen2b69c401999-10-05 22:58:32 +000089
Erik Andersene49d5ec2000-02-08 19:58:47 +000090 if (argc < 2)
Eric Andersen67991cf2001-02-14 21:23:06 +000091 show_usage();
Eric Andersen2b69c401999-10-05 22:58:32 +000092 argv++;
Eric Andersencc8ed391999-10-05 16:24:54 +000093
Erik Andersene49d5ec2000-02-08 19:58:47 +000094 /* Parse options */
Mark Whitleyeec2f632000-06-06 18:11:46 +000095 while (--argc >= 0 && *argv && (**argv == '-')) {
Eric Andersence82c8a2000-08-22 01:00:56 +000096 while (stopIt==FALSE && *++(*argv)) {
Erik Andersene49d5ec2000-02-08 19:58:47 +000097 switch (**argv) {
Mark Whitleyeec2f632000-06-06 18:11:46 +000098 case 'R':
99 recursiveFlag = TRUE;
100 break;
101 default:
Eric Andersence82c8a2000-08-22 01:00:56 +0000102 theMode=*argv-1;
103 stopIt = TRUE;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000104 }
Eric Andersen2b6ab3c2000-06-13 06:54:53 +0000105 }
Eric Andersence82c8a2000-08-22 01:00:56 +0000106 if (stopIt==TRUE)
107 break;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000108 argv++;
109 }
110
Mark Whitleyeec2f632000-06-06 18:11:46 +0000111 if (argc == 0 || *argv == NULL) {
Mark Whitleyf57c9442000-12-07 19:56:48 +0000112 error_msg(too_few_args);
Mark Whitleyeec2f632000-06-06 18:11:46 +0000113 }
114
Erik Andersene49d5ec2000-02-08 19:58:47 +0000115 if (whichApp == CHMOD_APP) {
Eric Andersence82c8a2000-08-22 01:00:56 +0000116 if (theMode==NULL)
117 theMode = *argv;
Eric Andersence8f3b91999-10-20 07:03:36 +0000118 } else {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000119
120 /* Find the selected group */
121 if (whichApp == CHGRP_APP) {
122 groupName = *argv;
123 gid = strtoul(groupName, &p, 10); /* maybe it's already numeric */
124 if (groupName == p)
125 gid = my_getgrnam(groupName);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000126 } else {
127 groupName = strchr(*argv, '.');
Erik Andersen632bb572000-04-18 22:09:06 +0000128 if (groupName == NULL)
129 groupName = strchr(*argv, ':');
Erik Andersene49d5ec2000-02-08 19:58:47 +0000130 if (groupName) {
131 *groupName++ = '\0';
132 gid = strtoul(groupName, &p, 10);
133 if (groupName == p)
134 gid = my_getgrnam(groupName);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000135 } else
136 gid = -1;
137 }
138
139
140 /* Find the selected user (if appropriate) */
141 if (whichApp == CHOWN_APP) {
142 uid = strtoul(*argv, &p, 10); /* if numeric ... */
143 if (*argv == p)
144 uid = my_getpwnam(*argv);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000145 }
Eric Andersen1b61f411999-10-13 18:56:42 +0000146 }
Eric Andersence8f3b91999-10-20 07:03:36 +0000147
Erik Andersene49d5ec2000-02-08 19:58:47 +0000148 /* Ok, ready to do the deed now */
Eric Andersence82c8a2000-08-22 01:00:56 +0000149 if (argc < 1) {
Mark Whitleyf57c9442000-12-07 19:56:48 +0000150 error_msg_and_die(too_few_args);
Eric Andersen1b61f411999-10-13 18:56:42 +0000151 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000152 while (argc-- > 1) {
Mark Whitleyf57c9442000-12-07 19:56:48 +0000153 if (recursive_action (*(++argv), recursiveFlag, FALSE, FALSE,
Erik Andersen3364d782000-03-28 00:58:14 +0000154 fileAction, fileAction, NULL) == FALSE)
Matt Kraai3e856ce2000-12-01 02:55:13 +0000155 return EXIT_FAILURE;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000156 }
Matt Kraai3e856ce2000-12-01 02:55:13 +0000157 return EXIT_SUCCESS;
Eric Andersence8f3b91999-10-20 07:03:36 +0000158
Eric Andersencc8ed391999-10-05 16:24:54 +0000159}
Erik Andersen029011b2000-03-04 21:19:32 +0000160
161/*
162Local Variables:
163c-file-style: "linux"
164c-basic-offset: 4
165tab-width: 4
166End:
167*/