made "test" an ash built-in.
[oweals/busybox.git] / coreutils / chmod.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Mini chmod implementation for busybox
4  *
5  * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
6  *
7  * Reworked by (C) 2002 Vladimir Oleynik <dzo@simtreas.ru>
8  *  to correctly parse '-rwxgoa'
9  *
10  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
11  */
12
13 /* BB_AUDIT SUSv3 compliant */
14 /* BB_AUDIT GNU defects - unsupported options -c, -f, -v, and long options. */
15 /* http://www.opengroup.org/onlinepubs/007904975/utilities/chmod.html */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include <sys/stat.h>
22 #include "busybox.h"
23
24 static int fileAction(const char *fileName, struct stat *statbuf, void* junk)
25 {
26         if (!bb_parse_mode((char *)junk, &(statbuf->st_mode)))
27                 bb_error_msg_and_die( "invalid mode: %s", (char *)junk);
28         if (chmod(fileName, statbuf->st_mode) == 0)
29                 return (TRUE);
30         bb_perror_msg("%s", fileName);  /* Avoid multibyte problems. */
31         return (FALSE);
32 }
33
34 int chmod_main(int ATTRIBUTE_UNUSED argc, char **argv)
35 {
36         int retval = EXIT_SUCCESS;
37         int recursiveFlag = FALSE;
38         int count;
39         char *smode;
40         char **p;
41         char *p0;
42         char opt = '-';
43
44         ++argv;
45         count = 0;
46
47         for (p = argv  ; *p ; p++) {
48                 p0 = p[0];
49                 if (p0[0] == opt) {
50                         if ((p0[1] == '-') && !p0[2]) {
51                                 opt = 0;        /* Disable further option processing. */
52                                 continue;
53                         }
54                         if (p0[1] == 'R') {
55                                 char *s = p0 + 2;
56                                 while (*s == 'R') {
57                                         ++s;
58                                 }
59                                 if (*s) {
60                                         bb_show_usage();
61                                 }
62                                 recursiveFlag = TRUE;
63                                 continue;
64                         }
65                         if (count) {
66                                 bb_show_usage();
67                         }
68                 }
69                 argv[count] = p0;
70                 ++count;
71         }
72
73         argv[count] = NULL;
74
75         if (count < 2) {
76                 bb_show_usage();
77         }
78
79         smode = *argv;
80         ++argv;
81
82         /* Ok, ready to do the deed now */
83         do {
84                 if (! recursive_action (*argv, recursiveFlag, TRUE, FALSE,
85                                                                 fileAction,     fileAction, smode)) {
86                         retval = EXIT_FAILURE;
87                 }
88         } while (*++argv);
89
90         return retval;
91 }