Changeset 1765 in MondoRescue for branches/2.2.5/mindi-busybox/e2fsprogs/chattr.c
- Timestamp:
- Nov 4, 2007, 3:16:40 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.5/mindi-busybox/e2fsprogs/chattr.c
r821 r1765 1 /* vi: set sw=4 ts=4: */ 1 2 /* 2 3 * chattr.c - Change file attributes on an ext2 file system … … 19 20 */ 20 21 21 #include <sys/types.h> 22 #include <dirent.h> 23 #include <fcntl.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <unistd.h> 27 #include <string.h> 28 #include <errno.h> 29 #include <sys/param.h> 30 #include <sys/stat.h> 31 #include "ext2fs/ext2_fs.h" 32 33 #ifdef __GNUC__ 34 # define EXT2FS_ATTR(x) __attribute__(x) 35 #else 36 # define EXT2FS_ATTR(x) 37 #endif 38 39 #include "e2fsbb.h" 40 #include "e2p/e2p.h" 22 #include "libbb.h" 23 #include "e2fs_lib.h" 41 24 42 25 #define OPT_ADD 1 … … 44 27 #define OPT_SET 4 45 28 #define OPT_SET_VER 8 46 static int flags;47 static int recursive;48 29 49 static unsigned long version; 50 51 static unsigned long af; 52 static unsigned long rf; 53 static unsigned long sf; 54 55 #ifdef CONFIG_LFS 56 # define LSTAT lstat64 57 # define STRUCT_STAT struct stat64 58 #else 59 # define LSTAT lstat 60 # define STRUCT_STAT struct stat 61 #endif 62 63 struct flags_char { 64 unsigned long flag; 65 char optchar; 66 }; 67 68 static const struct flags_char flags_array[] = { 69 { EXT2_NOATIME_FL, 'A' }, 70 { EXT2_SYNC_FL, 'S' }, 71 { EXT2_DIRSYNC_FL, 'D' }, 72 { EXT2_APPEND_FL, 'a' }, 73 { EXT2_COMPR_FL, 'c' }, 74 { EXT2_NODUMP_FL, 'd' }, 75 { EXT2_IMMUTABLE_FL, 'i' }, 76 { EXT3_JOURNAL_DATA_FL, 'j' }, 77 { EXT2_SECRM_FL, 's' }, 78 { EXT2_UNRM_FL, 'u' }, 79 { EXT2_NOTAIL_FL, 't' }, 80 { EXT2_TOPDIR_FL, 'T' }, 81 { 0, 0 } 30 struct globals { 31 unsigned long version; 32 unsigned long af; 33 unsigned long rf; 34 smallint flags; 35 smallint recursive; 82 36 }; 83 37 84 38 static unsigned long get_flag(char c) 85 39 { 86 const struct flags_char *fp; 87 for (fp = flags_array; fp->flag; fp++) 88 if (fp->optchar == c) 89 return fp->flag; 40 /* Two separate vectors take less space than vector of structs */ 41 static const char flags_letter[] ALIGN1 = "ASDacdijsutT"; 42 static const unsigned long flags_val[] = { 43 /* A */ EXT2_NOATIME_FL, 44 /* S */ EXT2_SYNC_FL, 45 /* D */ EXT2_DIRSYNC_FL, 46 /* a */ EXT2_APPEND_FL, 47 /* c */ EXT2_COMPR_FL, 48 /* d */ EXT2_NODUMP_FL, 49 /* i */ EXT2_IMMUTABLE_FL, 50 /* j */ EXT3_JOURNAL_DATA_FL, 51 /* s */ EXT2_SECRM_FL, 52 /* u */ EXT2_UNRM_FL, 53 /* t */ EXT2_NOTAIL_FL, 54 /* T */ EXT2_TOPDIR_FL, 55 }; 56 const char *fp; 57 58 for (fp = flags_letter; *fp; fp++) 59 if (*fp == c) 60 return flags_val[fp - flags_letter]; 90 61 bb_show_usage(); 91 return 0;92 62 } 93 63 94 static int decode_arg(c har *arg)64 static int decode_arg(const char *arg, struct globals *gp) 95 65 { 96 66 unsigned long *fl; 97 67 char opt = *arg++; 98 68 69 fl = &gp->af; 99 70 if (opt == '-') { 100 flags |= OPT_REM;101 fl = & rf;71 gp->flags |= OPT_REM; 72 fl = &gp->rf; 102 73 } else if (opt == '+') { 103 flags |= OPT_ADD; 104 fl = ⁡ 74 gp->flags |= OPT_ADD; 105 75 } else if (opt == '=') { 106 flags |= OPT_SET; 107 fl = &sf; 76 gp->flags |= OPT_SET; 108 77 } else 109 return EOF;78 return 0; 110 79 111 for (; *arg ; ++arg)112 (*fl) |= get_flag(*arg);80 while (*arg) 81 *fl |= get_flag(*arg++); 113 82 114 83 return 1; 115 84 } 116 85 117 static int chattr_dir_proc(const char *, struct dirent *, void *);86 static void change_attributes(const char *name, struct globals *gp); 118 87 119 static void change_attributes(const char * name) 88 static int chattr_dir_proc(const char *dir_name, struct dirent *de, void *gp) 89 { 90 char *path = concat_subpath_file(dir_name, de->d_name); 91 /* path is NULL if de->d_name is "." or "..", else... */ 92 if (path) { 93 change_attributes(path, gp); 94 free(path); 95 } 96 return 0; 97 } 98 99 static void change_attributes(const char *name, struct globals *gp) 120 100 { 121 101 unsigned long fsflags; 122 STRUCT_STATst;102 struct stat st; 123 103 124 if ( LSTAT(name, &st) == -1) {125 bb_ error_msg("stat %s failed", name);104 if (lstat(name, &st) != 0) { 105 bb_perror_msg("stat %s", name); 126 106 return; 127 107 } 128 if (S_ISLNK(st.st_mode) && recursive)108 if (S_ISLNK(st.st_mode) && gp->recursive) 129 109 return; 130 110 … … 136 116 return; 137 117 138 if ( flags & OPT_SET_VER)139 if (fsetversion(name, version) == -1)140 bb_ error_msg("setting version on %s", name);118 if (gp->flags & OPT_SET_VER) 119 if (fsetversion(name, gp->version) != 0) 120 bb_perror_msg("setting version on %s", name); 141 121 142 if ( flags & OPT_SET) {143 fsflags = sf;122 if (gp->flags & OPT_SET) { 123 fsflags = gp->af; 144 124 } else { 145 if (fgetflags(name, &fsflags) == -1) {146 bb_ error_msg("reading flags on %s", name);125 if (fgetflags(name, &fsflags) != 0) { 126 bb_perror_msg("reading flags on %s", name); 147 127 goto skip_setflags; 148 128 } 149 if (flags & OPT_REM) 150 fsflags &= ~rf; 151 if (flags & OPT_ADD) 152 fsflags |= af; 129 /*if (gp->flags & OPT_REM) - not needed, rf is zero otherwise */ 130 fsflags &= ~gp->rf; 131 /*if (gp->flags & OPT_ADD) - not needed, af is zero otherwise */ 132 fsflags |= gp->af; 133 /* What is this? And why it's not done for SET case? */ 153 134 if (!S_ISDIR(st.st_mode)) 154 135 fsflags &= ~EXT2_DIRSYNC_FL; 155 136 } 156 if (fsetflags(name, fsflags) == -1)157 bb_ error_msg("setting flags on %s", name);137 if (fsetflags(name, fsflags) != 0) 138 bb_perror_msg("setting flags on %s", name); 158 139 159 skip_setflags:160 if ( S_ISDIR(st.st_mode) && recursive)161 iterate_on_dir(name, chattr_dir_proc, NULL);140 skip_setflags: 141 if (gp->recursive && S_ISDIR(st.st_mode)) 142 iterate_on_dir(name, chattr_dir_proc, gp); 162 143 } 163 144 164 static int chattr_dir_proc(const char *dir_name, struct dirent *de, 165 void *private EXT2FS_ATTR((unused))) 166 { 167 /*if (strcmp(de->d_name, ".") && strcmp(de->d_name, "..")) {*/ 168 if (de->d_name[0] == '.' && (de->d_name[1] == '\0' || \ 169 (de->d_name[1] == '.' && de->d_name[2] == '\0'))) { 170 char *path = concat_subpath_file(dir_name, de->d_name); 171 if (path) { 172 change_attributes(path); 173 free(path); 174 } 175 } 176 return 0; 177 } 178 145 int chattr_main(int argc, char **argv); 179 146 int chattr_main(int argc, char **argv) 180 147 { 181 int i;148 struct globals g; 182 149 char *arg; 183 150 151 memset(&g, 0, sizeof(g)); 152 184 153 /* parse the args */ 185 for (i = 1; i < argc; ++i) { 186 arg = argv[i]; 187 154 while ((arg = *++argv)) { 188 155 /* take care of -R and -v <version> */ 189 if (arg[0] == '-') { 190 if (arg[1] == 'R' && arg[2] == '\0') { 191 recursive = 1; 192 continue; 193 } else if (arg[1] == 'v' && arg[2] == '\0') { 194 char *tmp; 195 ++i; 196 if (i >= argc) 197 bb_show_usage(); 198 version = strtol(argv[i], &tmp, 0); 199 if (*tmp) 200 bb_error_msg_and_die("bad version '%s'", arg); 201 flags |= OPT_SET_VER; 156 if (arg[0] == '-' 157 && (arg[1] == 'R' || arg[1] == 'v') 158 && !arg[2] 159 ) { 160 if (arg[1] == 'R') { 161 g.recursive = 1; 202 162 continue; 203 163 } 164 /* arg[1] == 'v' */ 165 if (!*++argv) 166 bb_show_usage(); 167 g.version = xatoul(*argv); 168 g.flags |= OPT_SET_VER; 169 continue; 204 170 } 205 171 206 if ( decode_arg(arg) == EOF)172 if (!decode_arg(arg, &g)) 207 173 break; 208 174 } 209 175 210 176 /* run sanity checks on all the arguments given us */ 211 if ( i >= argc)177 if (!*argv) 212 178 bb_show_usage(); 213 if (( flags & OPT_SET) && ((flags & OPT_ADD) || (flags &OPT_REM)))179 if ((g.flags & OPT_SET) && (g.flags & (OPT_ADD|OPT_REM))) 214 180 bb_error_msg_and_die("= is incompatible with - and +"); 215 if ( (rf & af) != 0)216 bb_error_msg_and_die(" Can't set and unset a flag");217 if (! flags)218 bb_error_msg_and_die(" Must use '-v', =, - or +");181 if (g.rf & g.af) 182 bb_error_msg_and_die("can't set and unset a flag"); 183 if (!g.flags) 184 bb_error_msg_and_die("must use '-v', =, - or +"); 219 185 220 186 /* now run chattr on all the files passed to us */ 221 while (i < argc) 222 change_attributes(argv[i++]); 187 do change_attributes(*argv, &g); while (*++argv); 223 188 224 189 return EXIT_SUCCESS;
Note:
See TracChangeset
for help on using the changeset viewer.