-#include <stdlib.h>
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini chown/chmod/chgrp implementation for busybox
+ *
+ *
+ * Copyright (C) 1999,2000,2001 by Lineo, inc.
+ * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
-#include <sys/stat.h>
-#include "internal.h"
+#include <getopt.h>
+#include "busybox.h"
-const char chmod_usage[] = "chmod [-R] mode file [file ...]\n"
-"\nmode may be an octal integer representing the bit pattern for the\n"
-"\tnew mode, or a symbolic value matching the pattern\n"
-"\t[ugoa]{+|-|=}[rwxst] .\n"
-"\t\tu:\tUser\n"
-"\t\tg:\tGroup\n"
-"\t\to:\tOthers\n"
-"\t\ta:\tAll\n"
-"\n"
-"\n+:\tAdd privilege\n"
-"\n-:\tRemove privilege\n"
-"\n=:\tSet privilege\n"
-"\n"
-"\t\tr:\tRead\n"
-"\t\tw:\tWrite\n"
-"\t\tx:\tExecute\n"
-"\t\ts:\tSet User ID\n"
-"\t\tt:\t\"Sticky\" Text\n"
-"\n"
-"\tModes may be concatenated, as in \"u=rwx,g=rx,o=rx,-t,-s\n"
-"\n"
-"\t-R:\tRecursively change the mode of all files and directories\n"
-"\t\tunder the argument directory.";
+static int fileAction(const char *fileName, struct stat *statbuf, void* junk)
+{
+ if (!parse_mode((char *)junk, &(statbuf->st_mode)))
+ error_msg_and_die("internal error");
+ if (chmod(fileName, statbuf->st_mode) == 0)
+ return (TRUE);
+ perror(fileName);
+ return (FALSE);
+}
-int
-parse_mode(
- const char * s
-,mode_t * or
-,mode_t * and
-,int * group_execute)
+int chmod_main(int argc, char **argv)
{
- /* [ugoa]{+|-|=}[rwxstl] */
- mode_t mode = 0;
- mode_t groups = S_ISVTX;
- char type;
- char c;
+ int i;
+ int opt;
+ int recursiveFlag = FALSE;
- do {
- for ( ; ; ) {
- switch ( c = *s++ ) {
- case '\0':
- return -1;
- case 'u':
- groups |= S_ISUID|S_IRWXU;
- continue;
- case 'g':
- groups |= S_ISGID|S_IRWXG;
- continue;
- case 'o':
- groups |= S_IRWXO;
- continue;
- case 'a':
- groups |= S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
- continue;
- case '+':
- case '=':
- case '-':
- type = c;
- if ( groups == S_ISVTX ) /* The default is "all" */
- groups |= S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
+ /* do normal option parsing */
+ while ((opt = getopt(argc, argv, "R")) > 0) {
+ switch (opt) {
+ case 'R':
+ recursiveFlag = TRUE;
break;
default:
- if ( c >= '0' && c <= '7' && mode == 0 && groups == S_ISVTX ) {
- *and = 0;
- *or = strtol(--s, 0, 010);
- return 0;
- }
- else
- return -1;
- }
- break;
+ show_usage();
}
+ }
- while ( (c = *s++) != '\0' ) {
- switch ( c ) {
- case ',':
- break;
- case 'r':
- mode |= S_IRUSR|S_IRGRP|S_IROTH;
- continue;
- case 'w':
- mode |= S_IWUSR|S_IWGRP|S_IWOTH;
- continue;
- case 'x':
- mode |= S_IXUSR|S_IXGRP|S_IXOTH;
- continue;
- case 's':
- if ( group_execute != 0 && (groups & S_IRWXG) ) {
- if ( *group_execute < 0 )
- return -1;
- if ( type != '-' ) {
- mode |= S_IXGRP;
- *group_execute = 1;
- }
- }
- mode |= S_ISUID|S_ISGID;
- continue;
- case 'l':
- if ( *group_execute > 0 )
- return -1;
- if ( type != '-' ) {
- *and &= ~S_IXGRP;
- *group_execute = -1;
- }
- mode |= S_ISGID;
- groups |= S_ISGID;
- continue;
- case 't':
- mode |= S_ISVTX;
- continue;
- default:
- return -1;
- }
- break;
- }
- switch ( type ) {
- case '=':
- *and &= ~(groups);
- /* fall through */
- case '+':
- *or |= mode & groups;
- break;
- case '-':
- *and &= ~(mode & groups);
- *or &= *and;
- break;
+ if (argc > optind && argc > 2 && argv[optind]) {
+ /* Parse the specified mode */
+ mode_t mode;
+ if (parse_mode(argv[optind], &mode) == FALSE) {
+ error_msg_and_die( "unknown mode: %s", argv[optind]);
}
- } while ( c == ',' );
- return 0;
-}
-
-extern int
-chmod_main(struct FileInfo * i, int argc, char * * argv)
-{
- i->andWithMode = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
- i->orWithMode = 0;
+ } else {
+ error_msg_and_die(too_few_args);
+ }
- while ( argc >= 3 ) {
- if ( parse_mode(argv[1], &i->orWithMode, &i->andWithMode, 0)
- == 0 ) {
- argc--;
- argv++;
+ /* Ok, ready to do the deed now */
+ for (i = optind + 1; i < argc; i++) {
+ if (recursive_action (argv[i], recursiveFlag, FALSE, FALSE, fileAction,
+ fileAction, argv[optind]) == FALSE) {
+ return EXIT_FAILURE;
}
- else if ( strcmp(argv[1], "-R") == 0 ) {
- i->recursive = 1;
- argc--;
- argv++;
- }
- else
- break;
}
-
- i->changeMode = 1;
- i->complainInPostProcess = 1;
-
- return monadic_main(i, argc, argv);
+ return EXIT_SUCCESS;
}
+
+/*
+Local Variables:
+c-file-style: "linux"
+c-basic-offset: 4
+tab-width: 4
+End:
+*/