More stuff
No binary (build failed)
—
(log yok)
| @@ -16,12 +16,10 @@ static const struct Applet applets[] = { | |
| #ifdef BB_CAT //bin | |
| {"cat", cat_more_main}, | |
| #endif | |
| - | #ifdef BB_CHMOD //bin |
| - | {"chmod", chmod_main}, |
| - | #endif |
| - | #ifdef BB_CHOWN //bin |
| - | {"chown", chown_main}, |
| - | {"chgrp", chown_main}, |
| + | #ifdef BB_CHMOD_CHOWN_CHGRP //bin |
| + | {"chmod", chmod_chown_chgrp_main}, |
| + | {"chown", chmod_chown_chgrp_main}, |
| + | {"chgrp", chmod_chown_chgrp_main}, |
| #endif | |
| #ifdef BB_CHROOT //sbin | |
| {"chroot", chroot_main}, | |
| @@ -844,7 +844,7 @@ static void saveDirectory (const char *dirName, const struct stat *statbuf) | |
| DIR *dir; | |
| struct dirent *entry; | |
| int needSlash; | |
| - | char fullName[PATH_LEN]; |
| + | char fullName[NAME_MAX]; |
| /* | |
| * Construct the directory name as used in the tar file by appending | |
| @@ -16,12 +16,10 @@ static const struct Applet applets[] = { | |
| #ifdef BB_CAT //bin | |
| {"cat", cat_more_main}, | |
| #endif | |
| - | #ifdef BB_CHMOD //bin |
| - | {"chmod", chmod_main}, |
| - | #endif |
| - | #ifdef BB_CHOWN //bin |
| - | {"chown", chown_main}, |
| - | {"chgrp", chown_main}, |
| + | #ifdef BB_CHMOD_CHOWN_CHGRP //bin |
| + | {"chmod", chmod_chown_chgrp_main}, |
| + | {"chown", chmod_chown_chgrp_main}, |
| + | {"chgrp", chmod_chown_chgrp_main}, |
| #endif | |
| #ifdef BB_CHROOT //sbin | |
| {"chroot", chroot_main}, | |
| @@ -6,8 +6,7 @@ | |
| //#define BB_BLOCK_DEVICE | |
| #define BB_BUSYBOX | |
| #define BB_CAT | |
| - | //#define BB_CHMOD |
| - | #define BB_CHOWN |
| + | #define BB_CHMOD_CHOWN_CHGRP |
| #define BB_CHROOT | |
| #define BB_CLEAR | |
| #define BB_CP | |
| @@ -1,41 +1,54 @@ | |
| - | #include <stdlib.h> |
| + | /* |
| + | * Mini chmod implementation for busybox |
| + | * |
| + | * Copyright (C) 1998 by Erik Andersen <[email protected]> |
| + | * |
| + | * 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 <unistd.h> |
| - | #include <sys/stat.h> |
| + | #include <grp.h> |
| + | #include <pwd.h> |
| #include "internal.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."; |
| - | |
| - | int |
| - | parse_mode( |
| - | const char * s |
| - | ,mode_t * or |
| - | ,mode_t * and |
| - | ,int * group_execute) |
| + | |
| + | static mode_t mode=7777; |
| + | |
| + | |
| + | static const char chmod_usage[] = "[-R] MODE[,MODE]... FILE...\n" |
| + | "Each MODE is one or more of the letters ugoa, one of the symbols +-= and\n" |
| + | "one or more of the letters rwxst.\n\n" |
| + | "\t-R\tchange files and directories recursively.\n"; |
| + | |
| + | |
| + | |
| + | static int fileAction(const char *fileName) |
| + | { |
| + | struct stat statBuf; |
| + | if ((stat(fileName, &statBuf) < 0) || |
| + | (chmod(fileName, mode)) < 0) { |
| + | perror(fileName); |
| + | return( FALSE); |
| + | } |
| + | return( TRUE); |
| + | } |
| + | |
| + | /* [ugoa]{+|-|=}[rwxstl] */ |
| + | int parse_mode( const char* s, mode_t* or, mode_t* and, int* group_execute) |
| { | |
| - | /* [ugoa]{+|-|=}[rwxstl] */ |
| mode_t mode = 0; | |
| mode_t groups = S_ISVTX; | |
| char type; | |
| @@ -45,7 +58,7 @@ parse_mode( | |
| for ( ; ; ) { | |
| switch ( c = *s++ ) { | |
| case '\0': | |
| - | return -1; |
| + | return (FALSE); |
| case 'u': | |
| groups |= S_ISUID|S_IRWXU; | |
| continue; | |
| @@ -69,10 +82,10 @@ parse_mode( | |
| if ( c >= '0' && c <= '7' && mode == 0 && groups == S_ISVTX ) { | |
| *and = 0; | |
| *or = strtol(--s, 0, 010); | |
| - | return 0; |
| + | return (TRUE); |
| } | |
| else | |
| - | return -1; |
| + | return (FALSE); |
| } | |
| break; | |
| } | |
| @@ -93,7 +106,7 @@ parse_mode( | |
| case 's': | |
| if ( group_execute != 0 && (groups & S_IRWXG) ) { | |
| if ( *group_execute < 0 ) | |
| - | return -1; |
| + | return (FALSE); |
| if ( type != '-' ) { | |
| mode |= S_IXGRP; | |
| *group_execute = 1; | |
| @@ -103,7 +116,7 @@ parse_mode( | |
| continue; | |
| case 'l': | |
| if ( *group_execute > 0 ) | |
| - | return -1; |
| + | return (FALSE); |
| if ( type != '-' ) { | |
| *and &= ~S_IXGRP; | |
| *group_execute = -1; | |
| @@ -115,7 +128,7 @@ parse_mode( | |
| mode |= S_ISVTX; | |
| continue; | |
| default: | |
| - | return -1; |
| + | return (FALSE); |
| } | |
| break; | |
| } | |
| @@ -132,32 +145,54 @@ parse_mode( | |
| break; | |
| } | |
| } while ( c == ',' ); | |
| - | return 0; |
| + | return (TRUE); |
| } | |
| - | extern int |
| - | chmod_main(struct FileInfo * i, int argc, char * * argv) |
| + | |
| + | int chmod_main(int argc, char **argv) |
| { | |
| - | i->andWithMode = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO; |
| - | i->orWithMode = 0; |
| - | |
| - | while ( argc >= 3 ) { |
| - | if ( parse_mode(argv[1], &i->orWithMode, &i->andWithMode, 0) |
| - | == 0 ) { |
| - | argc--; |
| - | argv++; |
| - | } |
| - | else if ( strcmp(argv[1], "-R") == 0 ) { |
| - | i->recursive = 1; |
| - | argc--; |
| - | argv++; |
| - | } |
| - | else |
| - | break; |
| - | } |
| + | int recursiveFlag=FALSE; |
| + | mode_t andWithMode = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO; |
| + | mode_t orWithMode = 0; |
| + | char *invocationName=*argv; |
| - | i->changeMode = 1; |
| - | i->complainInPostProcess = 1; |
| + | if (argc < 3) { |
| + | fprintf(stderr, "Usage: %s %s", invocationName, chmod_usage); |
| + | exit( FALSE); |
| + | } |
| + | argc--; |
| + | argv++; |
| + | |
| + | /* Parse options */ |
| + | while (**argv == '-') { |
| + | while (*++(*argv)) switch (**argv) { |
| + | case 'R': |
| + | recursiveFlag = TRUE; |
| + | break; |
| + | default: |
| + | fprintf(stderr, "Unknown option: %c\n", **argv); |
| + | exit( FALSE); |
| + | } |
| + | argc--; |
| + | argv++; |
| + | } |
| + | |
| + | /* Find the selected group */ |
| + | if ( parse_mode(*argv, &orWithMode, &andWithMode, 0) == FALSE ) { |
| + | fprintf(stderr, "%s: Unknown mode: %s\n", invocationName, *argv); |
| + | exit( FALSE); |
| + | } |
| + | mode &= andWithMode; |
| + | mode |= orWithMode; |
| - | return monadic_main(i, argc, argv); |
| + | /* Ok, ready to do the deed now */ |
| + | if (argc <= 1) { |
| + | fprintf(stderr, "%s: too few arguments", invocationName); |
| + | exit( FALSE); |
| + | } |
| + | while (argc-- > 1) { |
| + | argv++; |
| + | recursiveAction( *argv, recursiveFlag, TRUE, fileAction, fileAction); |
| + | } |
| + | exit(TRUE); |
| } | |
| @@ -1,5 +1,5 @@ | |
| /* | |
| - | * Mini chown/chgrp implementation for busybox |
| + | * Mini chown/chmod/chgrp implementation for busybox |
| * | |
| * Copyright (C) 1998 by Erik Andersen <[email protected]> | |
| * | |
| @@ -27,33 +27,150 @@ | |
| static int uid=-1; | |
| static int gid=0; | |
| - | static int chownApp; |
| + | static int whichApp; |
| static char* invocationName=NULL; | |
| + | static mode_t mode=7777; |
| + | #define CHGRP_APP 1 |
| + | #define CHOWN_APP 2 |
| + | #define CHMOD_APP 3 |
| + | |
| static const char chgrp_usage[] = "[OPTION]... GROUP FILE...\n" | |
| "Change the group membership of each FILE to GROUP.\n" | |
| "\n\tOptions:\n" "\t-R\tchange files and directories recursively\n"; | |
| static const char chown_usage[] = "[OPTION]... OWNER[.[GROUP] FILE...\n" | |
| "Change the owner and/or group of each FILE to OWNER and/or GROUP.\n" | |
| "\n\tOptions:\n" "\t-R\tchange files and directories recursively\n"; | |
| + | static const char chmod_usage[] = "[-R] MODE[,MODE]... FILE...\n" |
| + | "Each MODE is one or more of the letters ugoa, one of the symbols +-= and\n" |
| + | "one or more of the letters rwxst.\n\n" |
| + | "\t-R\tchange files and directories recursively.\n"; |
| static int fileAction(const char *fileName) | |
| { | |
| struct stat statBuf; | |
| - | if ((stat(fileName, &statBuf) < 0) || |
| - | (chown(fileName, |
| - | ((chownApp==TRUE)? uid: statBuf.st_uid), |
| - | gid) < 0)) { |
| - | perror(fileName); |
| - | return( FALSE); |
| + | if (stat(fileName, &statBuf) < 0) { |
| + | switch (whichApp) { |
| + | case CHGRP_APP: |
| + | case CHOWN_APP: |
| + | if (chown(fileName, ((whichApp==CHOWN_APP)? uid: statBuf.st_uid), gid) < 0) |
| + | return( TRUE); |
| + | case CHMOD_APP: |
| + | if (chmod(fileName, mode)) |
| + | return( TRUE); |
| + | } |
| } | |
| - | return( TRUE); |
| + | perror(fileName); |
| + | return( FALSE); |
| } | |
| - | int chown_main(int argc, char **argv) |
| + | /* [ugoa]{+|-|=}[rwxstl] */ |
| + | int parse_mode( const char* s, mode_t* or, mode_t* and, int* group_execute) |
| + | { |
| + | mode_t mode = 0; |
| + | mode_t groups = S_ISVTX; |
| + | char type; |
| + | char c; |
| + | |
| + | do { |
| + | for ( ; ; ) { |
| + | switch ( c = *s++ ) { |
| + | case '\0': |
| + | return (FALSE); |
| + | 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; |
| + | break; |
| + | default: |
| + | if ( c >= '0' && c <= '7' && mode == 0 && groups == S_ISVTX ) { |
| + | *and = 0; |
| + | *or = strtol(--s, 0, 010); |
| + | return (TRUE); |
| + | } |
| + | else |
| + | return (FALSE); |
| + | } |
| + | break; |
| + | } |
| + | |
| + | 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 (FALSE); |
| + | if ( type != '-' ) { |
| + | mode |= S_IXGRP; |
| + | *group_execute = 1; |
| + | } |
| + | } |
| + | mode |= S_ISUID|S_ISGID; |
| + | continue; |
| + | case 'l': |
| + | if ( *group_execute > 0 ) |
| + | return (FALSE); |
| + | if ( type != '-' ) { |
| + | *and &= ~S_IXGRP; |
| + | *group_execute = -1; |
| + | } |
| + | mode |= S_ISGID; |
| + | groups |= S_ISGID; |
| + | continue; |
| + | case 't': |
| + | mode |= S_ISVTX; |
| + | continue; |
| + | default: |
| + | return (FALSE); |
| + | } |
| + | break; |
| + | } |
| + | switch ( type ) { |
| + | case '=': |
| + | *and &= ~(groups); |
| + | /* fall through */ |
| + | case '+': |
| + | *or |= mode & groups; |
| + | break; |
| + | case '-': |
| + | *and &= ~(mode & groups); |
| + | *or &= *and; |
| + | break; |
| + | } |
| + | } while ( c == ',' ); |
| + | return (TRUE); |
| + | } |
| + | |
| + | |
| + | int chmod_chown_chgrp_main(int argc, char **argv) |
| { | |
| struct group *grp; | |
| struct passwd *pwd; | |
| @@ -61,11 +178,11 @@ int chown_main(int argc, char **argv) | |
| char *groupName; | |
| - | chownApp = (strcmp(*argv, "chown")==0)? TRUE : FALSE; |
| + | whichApp = (strcmp(*argv, "chown")==0)? CHOWN_APP : (strcmp(*argv, "chmod")==0)? CHMOD_APP : CHGRP_APP; |
| if (argc < 2) { | |
| fprintf(stderr, "Usage: %s %s", *argv, | |
| - | (chownApp==TRUE)? chown_usage : chgrp_usage); |
| + | (whichApp==TRUE)? chown_usage : chgrp_usage); |
| exit( FALSE); | |
| } | |
| invocationName=*argv; | |
| @@ -86,29 +203,40 @@ int chown_main(int argc, char **argv) | |
| argv++; | |
| } | |
| - | /* Find the selected group */ |
| - | groupName = strchr(*argv, '.'); |
| - | if ( chownApp==TRUE && groupName ) |
| - | *groupName++ = '\0'; |
| - | else |
| - | groupName = *argv; |
| - | grp = getgrnam(groupName); |
| - | if (grp == NULL) { |
| - | fprintf(stderr, "%s: Unknown group name: %s\n", invocationName, groupName); |
| - | exit( FALSE); |
| - | } |
| - | gid = grp->gr_gid; |
| + | if ( whichApp == CHMOD_APP ) { |
| + | /* Find the specified modes */ |
| + | if ( parse_mode(*argv, &orWithMode, &andWithMode, 0) == FALSE ) { |
| + | fprintf(stderr, "%s: Unknown mode: %s\n", invocationName, *argv); |
| + | exit( FALSE); |
| + | } |
| + | mode &= andWithMode; |
| + | mode |= orWithMode; |
| + | } else { |
| - | /* Find the selected user (if appropriate) */ |
| - | if (chownApp==TRUE) { |
| - | pwd = getpwnam(*argv); |
| - | if (pwd == NULL) { |
| - | fprintf(stderr, "%s: Unknown user name: %s\n", invocationName, *argv); |
| + | /* Find the selected group */ |
| + | groupName = strchr(*argv, '.'); |
| + | if ( whichApp==TRUE && groupName ) |
| + | *groupName++ = '\0'; |
| + | else |
| + | groupName = *argv; |
| + | grp = getgrnam(groupName); |
| + | if (grp == NULL) { |
| + | fprintf(stderr, "%s: Unknown group name: %s\n", invocationName, groupName); |
| exit( FALSE); | |
| } | |
| - | uid = pwd->pw_uid; |
| - | } |
| + | gid = grp->gr_gid; |
| + | /* Find the selected user (if appropriate) */ |
| + | if (whichApp==TRUE) { |
| + | pwd = getpwnam(*argv); |
| + | if (pwd == NULL) { |
| + | fprintf(stderr, "%s: Unknown user name: %s\n", invocationName, *argv); |
| + | exit( FALSE); |
| + | } |
| + | uid = pwd->pw_uid; |
| + | } |
| + | } |
| + | |
| /* Ok, ready to do the deed now */ | |
| if (argc <= 1) { | |
| fprintf(stderr, "%s: too few arguments", invocationName); | |
| @@ -120,3 +248,4 @@ int chown_main(int argc, char **argv) | |
| } | |
| exit(TRUE); | |
| } | |
| + | |
| @@ -1,41 +1,54 @@ | |
| - | #include <stdlib.h> |
| + | /* |
| + | * Mini chmod implementation for busybox |
| + | * |
| + | * Copyright (C) 1998 by Erik Andersen <[email protected]> |
| + | * |
| + | * 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 <unistd.h> |
| - | #include <sys/stat.h> |
| + | #include <grp.h> |
| + | #include <pwd.h> |
| #include "internal.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."; |
| - | |
| - | int |
| - | parse_mode( |
| - | const char * s |
| - | ,mode_t * or |
| - | ,mode_t * and |
| - | ,int * group_execute) |
| + | |
| + | static mode_t mode=7777; |
| + | |
| + | |
| + | static const char chmod_usage[] = "[-R] MODE[,MODE]... FILE...\n" |
| + | "Each MODE is one or more of the letters ugoa, one of the symbols +-= and\n" |
| + | "one or more of the letters rwxst.\n\n" |
| + | "\t-R\tchange files and directories recursively.\n"; |
| + | |
| + | |
| + | |
| + | static int fileAction(const char *fileName) |
| + | { |
| + | struct stat statBuf; |
| + | if ((stat(fileName, &statBuf) < 0) || |
| + | (chmod(fileName, mode)) < 0) { |
| + | perror(fileName); |
| + | return( FALSE); |
| + | } |
| + | return( TRUE); |
| + | } |
| + | |
| + | /* [ugoa]{+|-|=}[rwxstl] */ |
| + | int parse_mode( const char* s, mode_t* or, mode_t* and, int* group_execute) |
| { | |
| - | /* [ugoa]{+|-|=}[rwxstl] */ |
| mode_t mode = 0; | |
| mode_t groups = S_ISVTX; | |
| char type; | |
| @@ -45,7 +58,7 @@ parse_mode( | |
| for ( ; ; ) { | |
| switch ( c = *s++ ) { | |
| case '\0': | |
| - | return -1; |
| + | return (FALSE); |
| case 'u': | |
| groups |= S_ISUID|S_IRWXU; | |
| continue; | |
| @@ -69,10 +82,10 @@ parse_mode( | |
| if ( c >= '0' && c <= '7' && mode == 0 && groups == S_ISVTX ) { | |
| *and = 0; | |
| *or = strtol(--s, 0, 010); | |
| - | return 0; |
| + | return (TRUE); |
| } | |
| else | |
| - | return -1; |
| + | return (FALSE); |
| } | |
| break; | |
| } | |
| @@ -93,7 +106,7 @@ parse_mode( | |
| case 's': | |
| if ( group_execute != 0 && (groups & S_IRWXG) ) { | |
| if ( *group_execute < 0 ) | |
| - | return -1; |
| + | return (FALSE); |
| if ( type != '-' ) { | |
| mode |= S_IXGRP; | |
| *group_execute = 1; | |
| @@ -103,7 +116,7 @@ parse_mode( | |
| continue; | |
| case 'l': | |
| if ( *group_execute > 0 ) | |
| - | return -1; |
| + | return (FALSE); |
| if ( type != '-' ) { | |
| *and &= ~S_IXGRP; | |
| *group_execute = -1; | |
| @@ -115,7 +128,7 @@ parse_mode( | |
| mode |= S_ISVTX; | |
| continue; | |
| default: | |
| - | return -1; |
| + | return (FALSE); |
| } | |
| break; | |
| } | |
| @@ -132,32 +145,54 @@ parse_mode( | |
| break; | |
| } | |
| } while ( c == ',' ); | |
| - | return 0; |
| + | return (TRUE); |
| } | |
| - | extern int |
| - | chmod_main(struct FileInfo * i, int argc, char * * argv) |
| + | |
| + | int chmod_main(int argc, char **argv) |
| { | |
| - | i->andWithMode = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO; |
| - | i->orWithMode = 0; |
| - | |
| - | while ( argc >= 3 ) { |
| - | if ( parse_mode(argv[1], &i->orWithMode, &i->andWithMode, 0) |
| - | == 0 ) { |
| - | argc--; |
| - | argv++; |
| - | } |
| - | else if ( strcmp(argv[1], "-R") == 0 ) { |
| - | i->recursive = 1; |
| - | argc--; |
| - | argv++; |
| - | } |
| - | else |
| - | break; |
| - | } |
| + | int recursiveFlag=FALSE; |
| + | mode_t andWithMode = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO; |
| + | mode_t orWithMode = 0; |
| + | char *invocationName=*argv; |
| - | i->changeMode = 1; |
| - | i->complainInPostProcess = 1; |
| + | if (argc < 3) { |
| + | fprintf(stderr, "Usage: %s %s", invocationName, chmod_usage); |
| + | exit( FALSE); |
| + | } |
| + | argc--; |
| + | argv++; |
| + | |
| + | /* Parse options */ |
| + | while (**argv == '-') { |
| + | while (*++(*argv)) switch (**argv) { |
| + | case 'R': |
| + | recursiveFlag = TRUE; |
| + | break; |
| + | default: |
| + | fprintf(stderr, "Unknown option: %c\n", **argv); |
| + | exit( FALSE); |
| + | } |
| + | argc--; |
| + | argv++; |
| + | } |
| + | |
| + | /* Find the selected group */ |
| + | if ( parse_mode(*argv, &orWithMode, &andWithMode, 0) == FALSE ) { |
| + | fprintf(stderr, "%s: Unknown mode: %s\n", invocationName, *argv); |
| + | exit( FALSE); |
| + | } |
| + | mode &= andWithMode; |
| + | mode |= orWithMode; |
| - | return monadic_main(i, argc, argv); |
| + | /* Ok, ready to do the deed now */ |
| + | if (argc <= 1) { |
| + | fprintf(stderr, "%s: too few arguments", invocationName); |
| + | exit( FALSE); |
| + | } |
| + | while (argc-- > 1) { |
| + | argv++; |
| + | recursiveAction( *argv, recursiveFlag, TRUE, fileAction, fileAction); |
| + | } |
| + | exit(TRUE); |
| } | |
| @@ -1,5 +1,5 @@ | |
| /* | |
| - | * Mini chown/chgrp implementation for busybox |
| + | * Mini chown/chmod/chgrp implementation for busybox |
| * | |
| * Copyright (C) 1998 by Erik Andersen <[email protected]> | |
| * | |
| @@ -27,33 +27,150 @@ | |
| static int uid=-1; | |
| static int gid=0; | |
| - | static int chownApp; |
| + | static int whichApp; |
| static char* invocationName=NULL; | |
| + | static mode_t mode=7777; |
| + | #define CHGRP_APP 1 |
| + | #define CHOWN_APP 2 |
| + | #define CHMOD_APP 3 |
| + | |
| static const char chgrp_usage[] = "[OPTION]... GROUP FILE...\n" | |
| "Change the group membership of each FILE to GROUP.\n" | |
| "\n\tOptions:\n" "\t-R\tchange files and directories recursively\n"; | |
| static const char chown_usage[] = "[OPTION]... OWNER[.[GROUP] FILE...\n" | |
| "Change the owner and/or group of each FILE to OWNER and/or GROUP.\n" | |
| "\n\tOptions:\n" "\t-R\tchange files and directories recursively\n"; | |
| + | static const char chmod_usage[] = "[-R] MODE[,MODE]... FILE...\n" |
| + | "Each MODE is one or more of the letters ugoa, one of the symbols +-= and\n" |
| + | "one or more of the letters rwxst.\n\n" |
| + | "\t-R\tchange files and directories recursively.\n"; |
| static int fileAction(const char *fileName) | |
| { | |
| struct stat statBuf; | |
| - | if ((stat(fileName, &statBuf) < 0) || |
| - | (chown(fileName, |
| - | ((chownApp==TRUE)? uid: statBuf.st_uid), |
| - | gid) < 0)) { |
| - | perror(fileName); |
| - | return( FALSE); |
| + | if (stat(fileName, &statBuf) < 0) { |
| + | switch (whichApp) { |
| + | case CHGRP_APP: |
| + | case CHOWN_APP: |
| + | if (chown(fileName, ((whichApp==CHOWN_APP)? uid: statBuf.st_uid), gid) < 0) |
| + | return( TRUE); |
| + | case CHMOD_APP: |
| + | if (chmod(fileName, mode)) |
| + | return( TRUE); |
| + | } |
| } | |
| - | return( TRUE); |
| + | perror(fileName); |
| + | return( FALSE); |
| } | |
| - | int chown_main(int argc, char **argv) |
| + | /* [ugoa]{+|-|=}[rwxstl] */ |
| + | int parse_mode( const char* s, mode_t* or, mode_t* and, int* group_execute) |
| + | { |
| + | mode_t mode = 0; |
| + | mode_t groups = S_ISVTX; |
| + | char type; |
| + | char c; |
| + | |
| + | do { |
| + | for ( ; ; ) { |
| + | switch ( c = *s++ ) { |
| + | case '\0': |
| + | return (FALSE); |
| + | 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; |
| + | break; |
| + | default: |
| + | if ( c >= '0' && c <= '7' && mode == 0 && groups == S_ISVTX ) { |
| + | *and = 0; |
| + | *or = strtol(--s, 0, 010); |
| + | return (TRUE); |
| + | } |
| + | else |
| + | return (FALSE); |
| + | } |
| + | break; |
| + | } |
| + | |
| + | 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 (FALSE); |
| + | if ( type != '-' ) { |
| + | mode |= S_IXGRP; |
| + | *group_execute = 1; |
| + | } |
| + | } |
| + | mode |= S_ISUID|S_ISGID; |
| + | continue; |
| + | case 'l': |
| + | if ( *group_execute > 0 ) |
| + | return (FALSE); |
| + | if ( type != '-' ) { |
| + | *and &= ~S_IXGRP; |
| + | *group_execute = -1; |
| + | } |
| + | mode |= S_ISGID; |
| + | groups |= S_ISGID; |
| + | continue; |
| + | case 't': |
| + | mode |= S_ISVTX; |
| + | continue; |
| + | default: |
| + | return (FALSE); |
| + | } |
| + | break; |
| + | } |
| + | switch ( type ) { |
| + | case '=': |
| + | *and &= ~(groups); |
| + | /* fall through */ |
| + | case '+': |
| + | *or |= mode & groups; |
| + | break; |
| + | case '-': |
| + | *and &= ~(mode & groups); |
| + | *or &= *and; |
| + | break; |
| + | } |
| + | } while ( c == ',' ); |
| + | return (TRUE); |
| + | } |
| + | |
| + | |
| + | int chmod_chown_chgrp_main(int argc, char **argv) |
| { | |
| struct group *grp; | |
| struct passwd *pwd; | |
| @@ -61,11 +178,11 @@ int chown_main(int argc, char **argv) | |
| char *groupName; | |
| - | chownApp = (strcmp(*argv, "chown")==0)? TRUE : FALSE; |
| + | whichApp = (strcmp(*argv, "chown")==0)? CHOWN_APP : (strcmp(*argv, "chmod")==0)? CHMOD_APP : CHGRP_APP; |
| if (argc < 2) { | |
| fprintf(stderr, "Usage: %s %s", *argv, | |
| - | (chownApp==TRUE)? chown_usage : chgrp_usage); |
| + | (whichApp==TRUE)? chown_usage : chgrp_usage); |
| exit( FALSE); | |
| } | |
| invocationName=*argv; | |
| @@ -86,29 +203,40 @@ int chown_main(int argc, char **argv) | |
| argv++; | |
| } | |
| - | /* Find the selected group */ |
| - | groupName = strchr(*argv, '.'); |
| - | if ( chownApp==TRUE && groupName ) |
| - | *groupName++ = '\0'; |
| - | else |
| - | groupName = *argv; |
| - | grp = getgrnam(groupName); |
| - | if (grp == NULL) { |
| - | fprintf(stderr, "%s: Unknown group name: %s\n", invocationName, groupName); |
| - | exit( FALSE); |
| - | } |
| - | gid = grp->gr_gid; |
| + | if ( whichApp == CHMOD_APP ) { |
| + | /* Find the specified modes */ |
| + | if ( parse_mode(*argv, &orWithMode, &andWithMode, 0) == FALSE ) { |
| + | fprintf(stderr, "%s: Unknown mode: %s\n", invocationName, *argv); |
| + | exit( FALSE); |
| + | } |
| + | mode &= andWithMode; |
| + | mode |= orWithMode; |
| + | } else { |
| - | /* Find the selected user (if appropriate) */ |
| - | if (chownApp==TRUE) { |
| - | pwd = getpwnam(*argv); |
| - | if (pwd == NULL) { |
| - | fprintf(stderr, "%s: Unknown user name: %s\n", invocationName, *argv); |
| + | /* Find the selected group */ |
| + | groupName = strchr(*argv, '.'); |
| + | if ( whichApp==TRUE && groupName ) |
| + | *groupName++ = '\0'; |
| + | else |
| + | groupName = *argv; |
| + | grp = getgrnam(groupName); |
| + | if (grp == NULL) { |
| + | fprintf(stderr, "%s: Unknown group name: %s\n", invocationName, groupName); |
| exit( FALSE); | |
| } | |
| - | uid = pwd->pw_uid; |
| - | } |
| + | gid = grp->gr_gid; |
| + | /* Find the selected user (if appropriate) */ |
| + | if (whichApp==TRUE) { |
| + | pwd = getpwnam(*argv); |
| + | if (pwd == NULL) { |
| + | fprintf(stderr, "%s: Unknown user name: %s\n", invocationName, *argv); |
| + | exit( FALSE); |
| + | } |
| + | uid = pwd->pw_uid; |
| + | } |
| + | } |
| + | |
| /* Ok, ready to do the deed now */ | |
| if (argc <= 1) { | |
| fprintf(stderr, "%s: too few arguments", invocationName); | |
| @@ -120,3 +248,4 @@ int chown_main(int argc, char **argv) | |
| } | |
| exit(TRUE); | |
| } | |
| + | |
| @@ -59,9 +59,7 @@ extern int block_device_main(int argc, char** argv); | |
| extern int cat_more_main(int argc, char** argv); | |
| extern int more_main(int argc, char** argv); | |
| extern int cp_main(int argc, char** argv); | |
| - | extern int chgrp_main(int argc, char** argv); |
| - | extern int chmod_main(int argc, char** argv); |
| - | extern int chown_main(int argc, char** argv); |
| + | extern int chmod_chown_chgrp_main(int argc, char** argv); |
| extern int chroot_main(int argc, char** argv); | |
| extern int clear_main(int argc, char** argv); | |
| extern int date_main(int argc, char** argv); | |
| @@ -844,7 +844,7 @@ static void saveDirectory (const char *dirName, const struct stat *statbuf) | |
| DIR *dir; | |
| struct dirent *entry; | |
| int needSlash; | |
| - | char fullName[PATH_LEN]; |
| + | char fullName[NAME_MAX]; |
| /* | |
| * Construct the directory name as used in the tar file by appending | |