Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/e2fsprogs
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- Location:
- branches/stable/mindi-busybox/e2fsprogs
- Files:
-
- 125 deleted
- 5 edited
- 5 copied
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/e2fsprogs/Config.in
r821 r1770 6 6 menu "Linux Ext2 FS Progs" 7 7 8 config C ONFIG_CHATTR8 config CHATTR 9 9 bool "chattr" 10 10 default n … … 12 12 chattr changes the file attributes on a second extended file system. 13 13 14 config CONFIG_E2FSCK15 bool "e2fsck"16 default n17 help18 e2fsck is used to check Linux second extended file systems (ext2fs).19 e2fsck also supports ext2 filesystems countaining a journal (ext3).20 The normal compat symlinks 'fsck.ext2' and 'fsck.ext3' are also21 provided.14 ### config E2FSCK 15 ### bool "e2fsck" 16 ### default n 17 ### help 18 ### e2fsck is used to check Linux second extended file systems (ext2fs). 19 ### e2fsck also supports ext2 filesystems countaining a journal (ext3). 20 ### The normal compat symlinks 'fsck.ext2' and 'fsck.ext3' are also 21 ### provided. 22 22 23 config CONFIG_FSCK23 config FSCK 24 24 bool "fsck" 25 25 default n … … 29 29 checkers (fsck.fstype) available under Linux. 30 30 31 config CONFIG_LSATTR31 config LSATTR 32 32 bool "lsattr" 33 33 default n … … 35 35 lsattr lists the file attributes on a second extended file system. 36 36 37 config CONFIG_MKE2FS38 bool "mke2fs"39 default n40 help41 mke2fs is used to create an ext2/ext3 filesystem. The normal compat42 symlinks 'mkfs.ext2' and 'mkfs.ext3' are also provided.37 ### config MKE2FS 38 ### bool "mke2fs" 39 ### default n 40 ### help 41 ### mke2fs is used to create an ext2/ext3 filesystem. The normal compat 42 ### symlinks 'mkfs.ext2' and 'mkfs.ext3' are also provided. 43 43 44 config CONFIG_TUNE2FS45 bool "tune2fs"46 default n47 help48 tune2fs allows the system administrator to adjust various tunable49 filesystem parameters on Linux ext2/ext3 filesystems.44 ### config TUNE2FS 45 ### bool "tune2fs" 46 ### default n 47 ### help 48 ### tune2fs allows the system administrator to adjust various tunable 49 ### filesystem parameters on Linux ext2/ext3 filesystems. 50 50 51 config CONFIG_E2LABEL52 bool "e2label"53 default n54 depends on CONFIG_TUNE2FS55 help56 e2label will display or change the filesystem label on the ext257 filesystem located on device.51 ### config E2LABEL 52 ### bool "e2label" 53 ### default n 54 ### depends on TUNE2FS 55 ### help 56 ### e2label will display or change the filesystem label on the ext2 57 ### filesystem located on device. 58 58 59 config CONFIG_FINDFS60 bool "findfs"61 default n62 depends on CONFIG_TUNE2FS63 help64 findfs will search the disks in the system looking for a filesystem65 which has a label matching label or a UUID equal to uuid.59 ### config FINDFS 60 ### bool "findfs" 61 ### default n 62 ### depends on TUNE2FS 63 ### help 64 ### findfs will search the disks in the system looking for a filesystem 65 ### which has a label matching label or a UUID equal to uuid. 66 66 67 67 endmenu -
branches/stable/mindi-busybox/e2fsprogs/README
r821 r1770 1 This is a pretty straight rip from the e2fsprogs pkg. 1 Authors and contributors of original e2fsprogs: 2 2 3 See README's in subdirs for specific info. 3 Remy Card <card@masi.ibp.fr> 4 Theodore Ts'o <tytso@mit.edu> 5 Stephen C. Tweedie <sct@redhat.com> 6 Andreas Gruenbacher, <a.gruenbacher@computer.org> 7 Kaz Kylheku <kaz@ashi.footprints.net> 8 F.W. ten Wolde <franky@duteca.et.tudelft.nl> 9 Jeremy Fitzhardinge <jeremy@zip.com.au> 10 M.J.E. Mol <marcel@duteca.et.tudelft.nl> 11 Miquel van Smoorenburg <miquels@drinkel.ow.org> 12 Uwe Ohse <uwe@tirka.gun.de> -
branches/stable/mindi-busybox/e2fsprogs/chattr.c
r821 r1770 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; -
branches/stable/mindi-busybox/e2fsprogs/fsck.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* 2 * pfsck --- A generic, parallelizing front-end for the fsck program.3 * fsck --- A generic, parallelizing front-end for the fsck program. 3 4 * It will automatically try to run fsck programs in parallel if the 4 5 * devices are on separate spindles. It is based on the same ideas as … … 26 27 */ 27 28 28 #include <sys/types.h> 29 #include <sys/wait.h> 30 #include <sys/stat.h> 31 #include <limits.h> 32 #include <stdio.h> 33 #include <ctype.h> 34 #include <string.h> 35 #include <time.h> 36 #include <stdlib.h> 37 #include <errno.h> 38 #include <paths.h> 39 #include <unistd.h> 40 #include <errno.h> 41 #include <signal.h> 42 43 #include "fsck.h" 44 #include "blkid/blkid.h" 45 46 #include "e2fsbb.h" 47 48 #include "busybox.h" 49 50 #ifndef _PATH_MNTTAB 51 #define _PATH_MNTTAB "/etc/fstab" 52 #endif 29 /* All filesystem specific hooks have been removed. 30 * If filesystem cannot be determined, we will execute 31 * "fsck.auto". Currently this also happens if you specify 32 * UUID=xxx or LABEL=xxx as an object to check. 33 * Detection code for that is also probably has to be in fsck.auto. 34 * 35 * In other words, this is _really_ is just a driver program which 36 * spawns actual fsck.something for each filesystem to check. 37 * It doesn't guess filesystem types from on-disk format. 38 */ 39 40 #include "libbb.h" 41 42 #define EXIT_OK 0 43 #define EXIT_NONDESTRUCT 1 44 #define EXIT_DESTRUCT 2 45 #define EXIT_UNCORRECTED 4 46 #define EXIT_ERROR 8 47 #define EXIT_USAGE 16 48 #define FSCK_CANCELED 32 /* Aborted with a signal or ^C */ 53 49 54 50 /* 55 * fsck.h 56 */ 57 58 #ifndef DEFAULT_FSTYPE 59 #define DEFAULT_FSTYPE "ext2" 60 #endif 61 62 #define MAX_DEVICES 32 63 #define MAX_ARGS 32 64 65 /* 66 * Internal structure for mount tabel entries. 51 * Internal structure for mount table entries. 67 52 */ 68 53 69 54 struct fs_info { 70 char *device;71 char *mountpt;72 char *type;73 char *opts;74 int freq;75 int passno;76 int flags;77 55 struct fs_info *next; 56 char *device; 57 char *mountpt; 58 char *type; 59 char *opts; 60 int freq; 61 int passno; 62 int flags; 78 63 }; 79 64 80 65 #define FLAG_DONE 1 81 66 #define FLAG_PROGRESS 2 82 83 67 /* 84 68 * Structure to allow exit codes to be stored 85 69 */ 86 70 struct fsck_instance { 71 struct fsck_instance *next; 87 72 int pid; 88 73 int flags; 89 74 int exit_status; 90 75 time_t start_time; 91 char * prog; 92 char * type; 93 char * device; 94 char * base_device; 95 struct fsck_instance *next; 76 char *prog; 77 char *type; 78 char *device; 79 char *base_device; /* /dev/hda for /dev/hdaN etc */ 96 80 }; 97 81 82 static const char ignored_types[] ALIGN1 = 83 "ignore\0" 84 "iso9660\0" 85 "nfs\0" 86 "proc\0" 87 "sw\0" 88 "swap\0" 89 "tmpfs\0" 90 "devpts\0"; 91 92 #if 0 93 static const char really_wanted[] ALIGN1 = 94 "minix\0" 95 "ext2\0" 96 "ext3\0" 97 "jfs\0" 98 "reiserfs\0" 99 "xiafs\0" 100 "xfs\0"; 101 #endif 102 103 #define BASE_MD "/dev/md" 104 105 static char **devices; 106 static char **args; 107 static int num_devices; 108 static int num_args; 109 static int verbose; 110 111 #define FS_TYPE_FLAG_NORMAL 0 112 #define FS_TYPE_FLAG_OPT 1 113 #define FS_TYPE_FLAG_NEGOPT 2 114 static char **fs_type_list; 115 static uint8_t *fs_type_flag; 116 static smallint fs_type_negated; 117 118 static volatile smallint cancel_requested; 119 static smallint doall; 120 static smallint noexecute; 121 static smallint serialize; 122 static smallint skip_root; 123 /* static smallint like_mount; */ 124 static smallint notitle; 125 static smallint parallel_root; 126 static smallint force_all_parallel; 127 128 /* "progress indicator" code is somewhat buggy and ext[23] specific. 129 * We should be filesystem agnostic. IOW: there should be a well-defined 130 * API for fsck.something, NOT ad-hoc hacks in generic fsck. */ 131 #define DO_PROGRESS_INDICATOR 0 132 #if DO_PROGRESS_INDICATOR 133 static smallint progress; 134 static int progress_fd; 135 #endif 136 137 static int num_running; 138 static int max_running; 139 static char *fstype; 140 static struct fs_info *filesys_info; 141 static struct fs_info *filesys_last; 142 static struct fsck_instance *instance_list; 143 98 144 /* 99 * base_device.c100 *101 145 * Return the "base device" given a particular device; this is used to 102 146 * assure that we only fsck one partition on a particular drive at any 103 147 * one time. Otherwise, the disk heads will be seeking all over the 104 * place. If the base device can 148 * place. If the base device cannot be determined, return NULL. 105 149 * 106 150 * The base_device() function returns an allocated string which must 107 151 * be freed. 108 * 109 */ 110 111 112 #ifdef CONFIG_FEATURE_DEVFS 152 */ 153 #if ENABLE_FEATURE_DEVFS 113 154 /* 114 155 * Required for the uber-silly devfs /dev/ide/host1/bus2/target3/lun3 115 156 * pathames. 116 157 */ 117 static const char * 118 "host", "bus", "target", "lun", 0158 static const char *const devfs_hier[] = { 159 "host", "bus", "target", "lun", NULL 119 160 }; 120 161 #endif … … 123 164 { 124 165 char *str, *cp; 125 #if def CONFIG_FEATURE_DEVFS126 const char * 166 #if ENABLE_FEATURE_DEVFS 167 const char *const *hier; 127 168 const char *disk; 128 169 int len; 129 170 #endif 130 131 cp = str = bb_xstrdup(device); 171 cp = str = xstrdup(device); 132 172 133 173 /* Skip over /dev/; if it's not present, give up. */ … … 135 175 goto errout; 136 176 cp += 5; 137 138 #if 0 /* this is for old stuff no one uses anymore ? */139 /* Skip over /dev/dsk/... */140 if (strncmp(cp, "dsk/", 4) == 0)141 cp += 4;142 #endif143 177 144 178 /* … … 147 181 */ 148 182 if (cp[0] == 'm' && cp[1] == 'd') { 149 *(cp+2)= 0;183 cp[2] = 0; 150 184 return str; 151 185 } … … 154 188 if (strncmp(cp, "rd/", 3) == 0) { 155 189 cp += 3; 156 if (cp[0] != 'c' || cp[2] != 'd' ||157 !isdigit(cp[1])|| !isdigit(cp[3]))190 if (cp[0] != 'c' || !isdigit(cp[1]) 191 || cp[2] != 'd' || !isdigit(cp[3])) 158 192 goto errout; 159 *(cp+4)= 0;193 cp[4] = 0; 160 194 return str; 161 195 } 162 196 163 197 /* Now let's handle /dev/hd* and /dev/sd* devices.... */ 164 if ((cp[0] == 'h' || cp[0] == 's') && (cp[1] == 'd')) {198 if ((cp[0] == 'h' || cp[0] == 's') && cp[1] == 'd') { 165 199 cp += 2; 166 200 /* If there's a single number after /dev/hd, skip it */ … … 170 204 if (!isalpha(*cp)) 171 205 goto errout; 172 *(cp + 1)= 0;206 cp[1] = 0; 173 207 return str; 174 208 } 175 209 176 #if def CONFIG_FEATURE_DEVFS210 #if ENABLE_FEATURE_DEVFS 177 211 /* Now let's handle devfs (ugh) names */ 178 212 len = 0; … … 201 235 cp++; 202 236 } 203 *(cp - 1)= 0;237 cp[-1] = 0; 204 238 return str; 205 239 } … … 225 259 } 226 260 #endif 227 228 errout: 261 errout: 229 262 free(str); 230 263 return NULL; 231 264 } 232 265 233 234 static const char * const ignored_types[] = { 235 "ignore", 236 "iso9660", 237 "nfs", 238 "proc", 239 "sw", 240 "swap", 241 "tmpfs", 242 "devpts", 243 NULL 244 }; 245 246 static const char * const really_wanted[] = { 247 "minix", 248 "ext2", 249 "ext3", 250 "jfs", 251 "reiserfs", 252 "xiafs", 253 "xfs", 254 NULL 255 }; 256 257 #define BASE_MD "/dev/md" 258 259 /* 260 * Global variables for options 261 */ 262 static char *devices[MAX_DEVICES]; 263 static char *args[MAX_ARGS]; 264 static int num_devices, num_args; 265 266 static int verbose; 267 static int doall; 268 static int noexecute; 269 static int serialize; 270 static int skip_root; 271 static int like_mount; 272 static int notitle; 273 static int parallel_root; 274 static int progress; 275 static int progress_fd; 276 static int force_all_parallel; 277 static int num_running; 278 static int max_running; 279 static volatile int cancel_requested; 280 static int kill_sent; 281 static char *fstype; 282 static struct fs_info *filesys_info, *filesys_last; 283 static struct fsck_instance *instance_list; 284 static char *fsck_path; 285 static blkid_cache cache; 286 287 static char *string_copy(const char *s) 288 { 289 char *ret; 290 291 if (!s) 292 return 0; 293 ret = strdup(s); 294 return ret; 295 } 296 297 static int string_to_int(const char *s) 298 { 299 long l; 300 char *p; 301 302 l = strtol(s, &p, 0); 303 if (*p || l == LONG_MIN || l == LONG_MAX || l < 0 || l > INT_MAX) 304 return -1; 266 static void free_instance(struct fsck_instance *p) 267 { 268 free(p->prog); 269 free(p->device); 270 free(p->base_device); 271 free(p); 272 } 273 274 static struct fs_info *create_fs_device(const char *device, const char *mntpnt, 275 const char *type, const char *opts, 276 int freq, int passno) 277 { 278 struct fs_info *fs; 279 280 fs = xzalloc(sizeof(*fs)); 281 fs->device = xstrdup(device); 282 fs->mountpt = xstrdup(mntpnt); 283 fs->type = xstrdup(type); 284 fs->opts = xstrdup(opts ? opts : ""); 285 fs->freq = freq; 286 fs->passno = passno; 287 /*fs->flags = 0; */ 288 /*fs->next = NULL; */ 289 290 if (!filesys_info) 291 filesys_info = fs; 305 292 else 306 return (int) l; 307 } 308 309 static char *skip_over_blank(char *cp) 310 { 311 while (*cp && isspace(*cp)) 312 cp++; 313 return cp; 314 } 315 316 static char *skip_over_word(char *cp) 317 { 318 while (*cp && !isspace(*cp)) 319 cp++; 320 return cp; 293 filesys_last->next = fs; 294 filesys_last = fs; 295 296 return fs; 321 297 } 322 298 323 299 static void strip_line(char *line) 324 300 { 325 char *p;301 char *p = line + strlen(line) - 1; 326 302 327 303 while (*line) { 328 p = line + strlen(line) - 1; 329 if ((*p == '\n') || (*p == '\r')) 330 *p = 0; 331 else 304 if (*p != '\n' && *p != '\r') 332 305 break; 306 *p-- = '\0'; 333 307 } 334 308 } … … 339 313 340 314 word = *buf; 341 if (*word == 0)342 return 0;343 344 word = skip_ over_blank(word);345 next = skip_ over_word(word);315 if (*word == '\0') 316 return NULL; 317 318 word = skip_whitespace(word); 319 next = skip_non_whitespace(word); 346 320 if (*next) 347 *next++ = 0;321 *next++ = '\0'; 348 322 *buf = next; 349 323 return word; … … 352 326 static void parse_escape(char *word) 353 327 { 354 char 328 char *q, c; 355 329 const char *p; 356 330 … … 366 340 } 367 341 } 368 *q = 0; 369 } 370 371 static void free_instance(struct fsck_instance *i) 372 { 373 if (i->prog) 374 free(i->prog); 375 if (i->device) 376 free(i->device); 377 if (i->base_device) 378 free(i->base_device); 379 free(i); 380 return; 381 } 382 383 static struct fs_info *create_fs_device(const char *device, const char *mntpnt, 384 const char *type, const char *opts, 385 int freq, int passno) 386 { 387 struct fs_info *fs; 388 389 if (!(fs = malloc(sizeof(struct fs_info)))) 390 return NULL; 391 392 fs->device = string_copy(device); 393 fs->mountpt = string_copy(mntpnt); 394 fs->type = string_copy(type); 395 fs->opts = string_copy(opts ? opts : ""); 396 fs->freq = freq; 397 fs->passno = passno; 398 fs->flags = 0; 399 fs->next = NULL; 400 401 if (!filesys_info) 402 filesys_info = fs; 403 else 404 filesys_last->next = fs; 405 filesys_last = fs; 406 407 return fs; 408 } 409 410 342 *q = '\0'; 343 } 411 344 412 345 static int parse_fstab_line(char *line, struct fs_info **ret_fs) 413 346 { 414 char *dev,*device, *mntpnt, *type, *opts, *freq, *passno, *cp;347 char *device, *mntpnt, *type, *opts, *freq, *passno, *cp; 415 348 struct fs_info *fs; 416 349 417 350 *ret_fs = 0; 418 351 strip_line(line); 419 if ((cp = strchr(line, '#'))) 420 *cp = 0; /* Ignore everything after the comment char */ 352 cp = strchr(line, '#'); 353 if (cp) 354 *cp = '\0'; /* Ignore everything after the comment char */ 421 355 cp = line; 422 356 423 357 device = parse_word(&cp); 358 if (!device) return 0; /* Allow blank lines */ 424 359 mntpnt = parse_word(&cp); 425 360 type = parse_word(&cp); … … 427 362 freq = parse_word(&cp); 428 363 passno = parse_word(&cp); 429 430 if (!device)431 return 0; /* Allow blank lines */432 364 433 365 if (!mntpnt || !type) … … 441 373 parse_escape(passno); 442 374 443 dev = blkid_get_devname(cache, device, NULL);444 if (dev)445 device = dev;446 447 375 if (strchr(type, ',')) 448 type = 0;376 type = NULL; 449 377 450 378 fs = create_fs_device(device, mntpnt, type ? type : "auto", opts, 451 freq ? atoi(freq) : -1, 452 passno ? atoi(passno) : -1); 453 if (dev) 454 free(dev); 455 456 if (!fs) 457 return -1; 379 freq ? atoi(freq) : -1, 380 passno ? atoi(passno) : -1); 458 381 *ret_fs = fs; 459 382 return 0; 460 383 } 461 384 462 static void interpret_type(struct fs_info *fs) 463 { 464 char *t; 465 466 if (strcmp(fs->type, "auto") != 0) 385 /* Load the filesystem database from /etc/fstab */ 386 static void load_fs_info(const char *filename) 387 { 388 FILE *f; 389 int lineno = 0; 390 int old_fstab = 1; 391 struct fs_info *fs; 392 393 f = fopen_or_warn(filename, "r"); 394 if (f == NULL) { 467 395 return; 468 t = blkid_get_tag_value(cache, "TYPE", fs->device); 469 if (t) { 470 free(fs->type); 471 fs->type = t; 472 } 473 } 474 475 /* 476 * Load the filesystem database from /etc/fstab 477 */ 478 static void load_fs_info(const char *filename) 479 { 480 FILE *f; 481 char buf[1024]; 482 int lineno = 0; 483 int old_fstab = 1; 484 struct fs_info *fs; 485 486 if ((f = fopen(filename, "r")) == NULL) { 487 bb_perror_msg("WARNING: couldn't open %s", filename); 488 return; 489 } 490 while (!feof(f)) { 396 } 397 while (1) { 398 int r; 399 char *buf = xmalloc_getline(f); 400 if (!buf) break; 401 r = parse_fstab_line(buf, &fs); 402 free(buf); 491 403 lineno++; 492 if (!fgets(buf, sizeof(buf), f)) 493 break; 494 buf[sizeof(buf)-1] = 0; 495 if (parse_fstab_line(buf, &fs) < 0) { 404 if (r < 0) { 496 405 bb_error_msg("WARNING: bad format " 497 "on line %d of %s \n", lineno, filename);406 "on line %d of %s", lineno, filename); 498 407 continue; 499 408 } … … 505 414 old_fstab = 0; 506 415 } 507 508 416 fclose(f); 509 417 510 418 if (old_fstab) { 511 fputs("\007\007\007" 512 "WARNING: Your /etc/fstab does not contain the fsck passno\n" 513 " field. I will kludge around things for you, but you\n" 514 " should fix your /etc/fstab file as soon as you can.\n\n", stderr); 515 419 fputs("\007" 420 "WARNING: Your /etc/fstab does not contain the fsck passno field.\n" 421 "I will kludge around things for you, but you should fix\n" 422 "your /etc/fstab file as soon as you can.\n\n", stderr); 516 423 for (fs = filesys_info; fs; fs = fs->next) { 517 424 fs->passno = 1; … … 525 432 struct fs_info *fs; 526 433 527 /* No filesys name given. */528 if (filesys == NULL)529 return NULL;530 531 434 for (fs = filesys_info; fs; fs = fs->next) { 532 if (!strcmp(filesys, fs->device) || 533 (fs->mountpt && !strcmp(filesys, fs->mountpt))) 435 if (strcmp(filesys, fs->device) == 0 436 || (fs->mountpt && strcmp(filesys, fs->mountpt) == 0) 437 ) 534 438 break; 535 439 } … … 538 442 } 539 443 540 /* Find fsck program for a given fs type. */ 541 static char *find_fsck(char *type) 542 { 543 char *s; 544 const char *tpl; 545 char *p = string_copy(fsck_path); 546 struct stat st; 547 548 /* Are we looking for a program or just a type? */ 549 tpl = (strncmp(type, "fsck.", 5) ? "%s/fsck.%s" : "%s/%s"); 550 551 for(s = strtok(p, ":"); s; s = strtok(NULL, ":")) { 552 s = bb_xasprintf(tpl, s, type); 553 if (stat(s, &st) == 0) break; 554 free(s); 555 } 556 free(p); 557 return(s); 558 } 559 444 #if DO_PROGRESS_INDICATOR 560 445 static int progress_active(void) 561 446 { … … 570 455 return 0; 571 456 } 572 573 /* 574 * Execute a particular fsck program, and link it into the list of 575 * child processes we are waiting for. 576 */ 577 static int execute(const char *type, const char *device, const char *mntpt, 578 int interactive) 579 { 580 char *s, *argv[80]; 581 char *prog; 582 int argc, i; 583 struct fsck_instance *inst, *p; 584 pid_t pid; 585 586 inst = malloc(sizeof(struct fsck_instance)); 587 if (!inst) 588 return ENOMEM; 589 memset(inst, 0, sizeof(struct fsck_instance)); 590 591 prog = bb_xasprintf("fsck.%s", type); 592 argv[0] = prog; 593 argc = 1; 594 595 for (i=0; i <num_args; i++) 596 argv[argc++] = string_copy(args[i]); 597 598 if (progress && !progress_active()) { 599 if ((strcmp(type, "ext2") == 0) || 600 (strcmp(type, "ext3") == 0)) { 601 char tmp[80]; 602 snprintf(tmp, 80, "-C%d", progress_fd); 603 argv[argc++] = string_copy(tmp); 604 inst->flags |= FLAG_PROGRESS; 605 } 606 } 607 608 argv[argc++] = string_copy(device); 609 argv[argc] = 0; 610 611 s = find_fsck(prog); 612 if (s == NULL) { 613 bb_error_msg("%s: not found", prog); 614 return ENOENT; 615 } 616 617 if (verbose || noexecute) { 618 printf("[%s (%d) -- %s] ", s, num_running, 619 mntpt ? mntpt : device); 620 for (i=0; i < argc; i++) 621 printf("%s ", argv[i]); 622 printf("\n"); 623 } 624 625 /* Fork and execute the correct program. */ 626 if (noexecute) 627 pid = -1; 628 else if ((pid = fork()) < 0) { 629 perror("fork"); 630 return errno; 631 } else if (pid == 0) { 632 if (!interactive) 633 close(0); 634 (void) execv(s, argv); 635 bb_perror_msg_and_die("%s", argv[0]); 636 } 637 638 for (i = 1; i < argc; i++) 639 free(argv[i]); 640 641 free(s); 642 inst->pid = pid; 643 inst->prog = prog; 644 inst->type = string_copy(type); 645 inst->device = string_copy(device); 646 inst->base_device = base_device(device); 647 inst->start_time = time(0); 648 inst->next = NULL; 649 650 /* 651 * Find the end of the list, so we add the instance on at the end. 652 */ 653 for (p = instance_list; p && p->next; p = p->next); 654 655 if (p) 656 p->next = inst; 657 else 658 instance_list = inst; 659 660 return 0; 661 } 457 #endif 458 662 459 663 460 /* 664 461 * Send a signal to all outstanding fsck child processes 665 462 */ 666 static int kill_all(int signum) 667 { 463 static void kill_all_if_cancel_requested(void) 464 { 465 static smallint kill_sent; 466 668 467 struct fsck_instance *inst; 669 int n = 0; 468 469 if (!cancel_requested || kill_sent) 470 return; 670 471 671 472 for (inst = instance_list; inst; inst = inst->next) { 672 473 if (inst->flags & FLAG_DONE) 673 474 continue; 674 kill(inst->pid, signum); 675 n++; 676 } 677 return n; 475 kill(inst->pid, SIGTERM); 476 } 477 kill_sent = 1; 678 478 } 679 479 … … 684 484 static struct fsck_instance *wait_one(int flags) 685 485 { 686 int 687 int 688 struct fsck_instance *inst, * inst2, *prev;689 pid_t 486 int status; 487 int sig; 488 struct fsck_instance *inst, *prev; 489 pid_t pid; 690 490 691 491 if (!instance_list) … … 694 494 if (noexecute) { 695 495 inst = instance_list; 696 prev = 0;496 prev = NULL; 697 497 #ifdef RANDOM_DEBUG 698 498 while (inst->next && (random() & 1)) { … … 705 505 } 706 506 707 /* 708 * gcc -Wall fails saving throw against stupidity 709 * (inst and prev are thought to be uninitialized variables) 710 */ 711 inst = prev = NULL; 712 507 inst = prev = NULL; /* for gcc */ 713 508 do { 714 509 pid = waitpid(-1, &status, flags); 715 if (cancel_requested && !kill_sent) { 716 kill_all(SIGTERM); 717 kill_sent++; 718 } 719 if ((pid == 0) && (flags & WNOHANG)) 510 kill_all_if_cancel_requested(); 511 if (pid == 0 && (flags & WNOHANG)) 720 512 return NULL; 721 513 if (pid < 0) { 722 if ( (errno == EINTR) || (errno == EAGAIN))514 if (errno == EINTR || errno == EAGAIN) 723 515 continue; 724 516 if (errno == ECHILD) { 725 bb_error_msg("wait: No more child process?!?");517 bb_error_msg("wait: no more child process?!?"); 726 518 return NULL; 727 519 } 728 perror("wait");520 bb_perror_msg("wait"); 729 521 continue; 730 522 } 731 for (prev = 0, inst = instance_list;732 inst;733 prev = inst, inst = inst->next) {523 prev = NULL; 524 inst = instance_list; 525 while (inst) { 734 526 if (inst->pid == pid) 735 527 break; 528 prev = inst; 529 inst = inst->next; 736 530 } 737 531 } while (!inst); … … 741 535 else if (WIFSIGNALED(status)) { 742 536 sig = WTERMSIG(status); 743 if (sig == SIGINT) { 744 status = EXIT_UNCORRECTED; 745 } else { 746 printf("Warning... %s for device %s exited " 747 "with signal %d.\n", 748 inst->prog, inst->device, sig); 537 status = EXIT_UNCORRECTED; 538 if (sig != SIGINT) { 539 printf("Warning... %s %s exited " 540 "with signal %d\n", 541 inst->prog, inst->device, sig); 749 542 status = EXIT_ERROR; 750 543 } 751 544 } else { 752 printf("%s %s: status is %x, should never happen .\n",753 545 printf("%s %s: status is %x, should never happen\n", 546 inst->prog, inst->device, status); 754 547 status = EXIT_ERROR; 755 548 } 756 549 inst->exit_status = status; 757 if (progress && (inst->flags & FLAG_PROGRESS) && 758 !progress_active()) { 550 551 #if DO_PROGRESS_INDICATOR 552 if (progress && (inst->flags & FLAG_PROGRESS) && !progress_active()) { 553 struct fsck_instance *inst2; 759 554 for (inst2 = instance_list; inst2; inst2 = inst2->next) { 760 555 if (inst2->flags & FLAG_DONE) 761 556 continue; 762 if (strcmp(inst2->type, "ext2") && 763 strcmp(inst2->type, "ext3")) 557 if (strcmp(inst2->type, "ext2") != 0 558 && strcmp(inst2->type, "ext3") != 0 559 ) { 764 560 continue; 765 /* 561 } 562 /* ext[23], we will send USR1 563 * (request to start displaying progress bar) 564 * 766 565 * If we've just started the fsck, wait a tiny 767 566 * bit before sending the kill, to give it 768 567 * time to set up the signal handler 769 568 */ 770 if (inst2->start_time < time(0)+2) { 771 if (fork() == 0) { 772 sleep(1); 773 kill(inst2->pid, SIGUSR1); 774 exit(0); 775 } 776 } else 777 kill(inst2->pid, SIGUSR1); 569 if (inst2->start_time >= time(NULL) - 1) 570 sleep(1); 571 kill(inst2->pid, SIGUSR1); 778 572 inst2->flags |= FLAG_PROGRESS; 779 573 break; 780 574 } 781 575 } 782 ret_inst: 576 #endif 577 578 ret_inst: 783 579 if (prev) 784 580 prev->next = inst->next; … … 801 597 { 802 598 struct fsck_instance *inst; 803 int 804 int 599 int global_status = 0; 600 int wait_flags = 0; 805 601 806 602 while ((inst = wait_one(wait_flags))) { … … 818 614 819 615 /* 616 * Execute a particular fsck program, and link it into the list of 617 * child processes we are waiting for. 618 */ 619 static void execute(const char *type, const char *device, const char *mntpt, 620 int interactive) 621 { 622 char *argv[num_args + 4]; /* see count below: */ 623 int argc; 624 int i; 625 struct fsck_instance *inst; 626 pid_t pid; 627 628 inst = xzalloc(sizeof(*inst)); 629 630 argv[0] = xasprintf("fsck.%s", type); /* 1 */ 631 for (i = 0; i < num_args; i++) 632 argv[i+1] = args[i]; /* num_args */ 633 argc = num_args + 1; 634 635 #if DO_PROGRESS_INDICATOR 636 if (progress && !progress_active()) { 637 if (strcmp(type, "ext2") == 0 638 || strcmp(type, "ext3") == 0 639 ) { 640 argv[argc++] = xasprintf("-C%d", progress_fd); /* 1 */ 641 inst->flags |= FLAG_PROGRESS; 642 } 643 } 644 #endif 645 646 argv[argc++] = xstrdup(device); /* 1 */ 647 argv[argc] = NULL; /* 1 */ 648 649 if (verbose || noexecute) { 650 printf("[%s (%d) -- %s]", argv[0], num_running, 651 mntpt ? mntpt : device); 652 for (i = 0; i < argc; i++) 653 printf(" %s", argv[i]); 654 puts(""); 655 } 656 657 /* Fork and execute the correct program. */ 658 pid = -1; 659 if (!noexecute) { 660 pid = spawn(argv); 661 if (pid < 0) 662 bb_perror_msg("%s", argv[0]); 663 } 664 665 for (i = num_args+1; i < argc; i++) 666 free(argv[i]); 667 668 inst->pid = pid; 669 inst->prog = argv[0]; 670 inst->type = xstrdup(type); 671 inst->device = xstrdup(device); 672 inst->base_device = base_device(device); 673 inst->start_time = time(NULL); 674 675 /* Add to the list of running fsck's. 676 * (was adding to the end, but adding to the front is simpler...) */ 677 inst->next = instance_list; 678 instance_list = inst; 679 } 680 681 /* 820 682 * Run the fsck program on a particular device 821 683 * … … 825 687 * 826 688 * If the type isn't specified by the user, then use either the type 827 * specified in /etc/fstab, or DEFAULT_FSTYPE.689 * specified in /etc/fstab, or "auto". 828 690 */ 829 691 static void fsck_device(struct fs_info *fs, int interactive) 830 692 { 831 693 const char *type; 832 int retval; 833 834 interpret_type(fs); 835 836 if (strcmp(fs->type, "auto") != 0) 694 695 if (strcmp(fs->type, "auto") != 0) { 837 696 type = fs->type; 838 else if (fstype && strncmp(fstype, "no", 2) && 839 strncmp(fstype, "opts=", 5) && strncmp(fstype, "loop", 4) && 840 !strchr(fstype, ',')) 697 if (verbose > 2) 698 bb_info_msg("using filesystem type '%s' %s", 699 type, "from fstab"); 700 } else if (fstype 701 && (fstype[0] != 'n' || fstype[1] != 'o') /* != "no" */ 702 && strncmp(fstype, "opts=", 5) != 0 703 && strncmp(fstype, "loop", 4) != 0 704 && !strchr(fstype, ',') 705 ) { 841 706 type = fstype; 842 else 843 type = DEFAULT_FSTYPE; 707 if (verbose > 2) 708 bb_info_msg("using filesystem type '%s' %s", 709 type, "from -t"); 710 } else { 711 type = "auto"; 712 if (verbose > 2) 713 bb_info_msg("using filesystem type '%s' %s", 714 type, "(default)"); 715 } 844 716 845 717 num_running++; 846 retval = execute(type, fs->device, fs->mountpt, interactive); 847 if (retval) { 848 bb_error_msg("Error %d while executing fsck.%s for %s", 849 retval, type, fs->device); 850 num_running--; 851 } 852 } 853 854 855 /* 856 * Deal with the fsck -t argument. 857 */ 858 struct fs_type_compile { 859 char **list; 860 int *type; 861 int negate; 862 } fs_type_compiled; 863 864 #define FS_TYPE_NORMAL 0 865 #define FS_TYPE_OPT 1 866 #define FS_TYPE_NEGOPT 2 867 868 static const char fs_type_syntax_error[] = 869 "Either all or none of the filesystem types passed to -t must be prefixed\n" 870 "with 'no' or '!'."; 871 872 static void compile_fs_type(char *fs_type, struct fs_type_compile *cmp) 873 { 874 char *cp, *list, *s; 875 int num = 2; 876 int negate, first_negate = 1; 877 878 if (fs_type) { 879 for (cp=fs_type; *cp; cp++) { 880 if (*cp == ',') 881 num++; 882 } 883 } 884 885 cmp->list = xcalloc(num, sizeof(char *)); 886 cmp->type = xcalloc(num, sizeof(int)); 887 cmp->negate = 0; 888 889 if (!fs_type) 890 return; 891 892 list = string_copy(fs_type); 893 num = 0; 894 s = strtok(list, ","); 895 while(s) { 896 negate = 0; 897 if (strncmp(s, "no", 2) == 0) { 898 s += 2; 899 negate = 1; 900 } else if (*s == '!') { 901 s++; 902 negate = 1; 903 } 904 if (strcmp(s, "loop") == 0) 905 /* loop is really short-hand for opts=loop */ 906 goto loop_special_case; 907 else if (strncmp(s, "opts=", 5) == 0) { 908 s += 5; 909 loop_special_case: 910 cmp->type[num] = negate ? FS_TYPE_NEGOPT : FS_TYPE_OPT; 911 } else { 912 if (first_negate) { 913 cmp->negate = negate; 914 first_negate = 0; 915 } 916 if ((negate && !cmp->negate) || 917 (!negate && cmp->negate)) { 918 bb_error_msg_and_die("%s", fs_type_syntax_error); 919 } 920 } 921 #if 0 922 printf("Adding %s to list (type %d).\n", s, cmp->type[num]); 923 #endif 924 cmp->list[num++] = string_copy(s); 925 s = strtok(NULL, ","); 926 } 927 free(list); 928 } 929 930 /* 931 * This function returns true if a particular option appears in a 932 * comma-delimited options list 933 */ 934 static int opt_in_list(char *opt, char *optlist) 935 { 936 char *list, *s; 937 938 if (!optlist) 939 return 0; 940 list = string_copy(optlist); 941 942 s = strtok(list, ","); 943 while(s) { 944 if (strcmp(s, opt) == 0) { 945 free(list); 946 return 1; 947 } 948 s = strtok(NULL, ","); 949 } 950 free(list); 951 return 0; 952 } 953 954 /* See if the filesystem matches the criteria given by the -t option */ 955 static int fs_match(struct fs_info *fs, struct fs_type_compile *cmp) 956 { 957 int n, ret = 0, checked_type = 0; 958 char *cp; 959 960 if (cmp->list == 0 || cmp->list[0] == 0) 961 return 1; 962 963 for (n=0; (cp = cmp->list[n]); n++) { 964 switch (cmp->type[n]) { 965 case FS_TYPE_NORMAL: 966 checked_type++; 967 if (strcmp(cp, fs->type) == 0) { 968 ret = 1; 969 } 970 break; 971 case FS_TYPE_NEGOPT: 972 if (opt_in_list(cp, fs->opts)) 973 return 0; 974 break; 975 case FS_TYPE_OPT: 976 if (!opt_in_list(cp, fs->opts)) 977 return 0; 978 break; 979 } 980 } 981 if (checked_type == 0) 982 return 1; 983 return (cmp->negate ? !ret : ret); 984 } 985 986 /* Check if we should ignore this filesystem. */ 987 static int ignore(struct fs_info *fs) 988 { 989 int wanted; 990 char *s; 991 992 /* 993 * If the pass number is 0, ignore it. 994 */ 995 if (fs->passno == 0) 996 return 1; 997 998 interpret_type(fs); 999 1000 /* 1001 * If a specific fstype is specified, and it doesn't match, 1002 * ignore it. 1003 */ 1004 if (!fs_match(fs, &fs_type_compiled)) return 1; 1005 1006 /* Are we ignoring this type? */ 1007 if(compare_string_array(ignored_types, fs->type) >= 0) 1008 return 1; 1009 1010 /* Do we really really want to check this fs? */ 1011 wanted = compare_string_array(really_wanted, fs->type) >= 0; 1012 1013 /* See if the <fsck.fs> program is available. */ 1014 s = find_fsck(fs->type); 1015 if (s == NULL) { 1016 if (wanted) 1017 bb_error_msg("cannot check %s: fsck.%s not found", 1018 fs->device, fs->type); 1019 return 1; 1020 } 1021 free(s); 1022 1023 /* We can and want to check this file system type. */ 1024 return 0; 718 execute(type, fs->device, fs->mountpt, interactive); 1025 719 } 1026 720 … … 1039 733 #ifdef BASE_MD 1040 734 /* Don't check a soft raid disk with any other disk */ 1041 if (instance_list && 1042 (!strncmp(instance_list->device, BASE_MD, sizeof(BASE_MD)-1) || 1043 !strncmp(device, BASE_MD, sizeof(BASE_MD)-1))) 735 if (instance_list 736 && (!strncmp(instance_list->device, BASE_MD, sizeof(BASE_MD)-1) 737 || !strncmp(device, BASE_MD, sizeof(BASE_MD)-1)) 738 ) { 1044 739 return 1; 740 } 1045 741 #endif 1046 742 … … 1051 747 */ 1052 748 if (!base) 1053 return (instance_list != 0); 749 return (instance_list != NULL); 750 1054 751 for (inst = instance_list; inst; inst = inst->next) { 1055 752 if (!inst->base_device || !strcmp(base, inst->base_device)) { … … 1058 755 } 1059 756 } 757 1060 758 free(base); 1061 759 return 0; 1062 760 } 1063 761 762 /* 763 * This function returns true if a particular option appears in a 764 * comma-delimited options list 765 */ 766 static int opt_in_list(char *opt, char *optlist) 767 { 768 char *s; 769 int len; 770 771 if (!optlist) 772 return 0; 773 774 len = strlen(opt); 775 s = optlist - 1; 776 while (1) { 777 s = strstr(s + 1, opt); 778 if (!s) 779 return 0; 780 /* neither "opt.." nor "xxx,opt.."? */ 781 if (s != optlist && s[-1] != ',') 782 continue; 783 /* neither "..opt" nor "..opt,xxx"? */ 784 if (s[len] != '\0' && s[len] != ',') 785 continue; 786 return 1; 787 } 788 } 789 790 /* See if the filesystem matches the criteria given by the -t option */ 791 static int fs_match(struct fs_info *fs) 792 { 793 int n, ret, checked_type; 794 char *cp; 795 796 if (!fs_type_list) 797 return 1; 798 799 ret = 0; 800 checked_type = 0; 801 n = 0; 802 while (1) { 803 cp = fs_type_list[n]; 804 if (!cp) 805 break; 806 switch (fs_type_flag[n]) { 807 case FS_TYPE_FLAG_NORMAL: 808 checked_type++; 809 if (strcmp(cp, fs->type) == 0) 810 ret = 1; 811 break; 812 case FS_TYPE_FLAG_NEGOPT: 813 if (opt_in_list(cp, fs->opts)) 814 return 0; 815 break; 816 case FS_TYPE_FLAG_OPT: 817 if (!opt_in_list(cp, fs->opts)) 818 return 0; 819 break; 820 } 821 n++; 822 } 823 if (checked_type == 0) 824 return 1; 825 826 return (fs_type_negated ? !ret : ret); 827 } 828 829 /* Check if we should ignore this filesystem. */ 830 static int ignore(struct fs_info *fs) 831 { 832 /* 833 * If the pass number is 0, ignore it. 834 */ 835 if (fs->passno == 0) 836 return 1; 837 838 /* 839 * If a specific fstype is specified, and it doesn't match, 840 * ignore it. 841 */ 842 if (!fs_match(fs)) 843 return 1; 844 845 /* Are we ignoring this type? */ 846 if (index_in_strings(ignored_types, fs->type) >= 0) 847 return 1; 848 849 /* We can and want to check this file system type. */ 850 return 0; 851 } 852 1064 853 /* Check all file systems, using the /etc/fstab table. */ 1065 854 static int check_all(void) 1066 855 { 1067 struct fs_info *fs = NULL;856 struct fs_info *fs; 1068 857 int status = EXIT_OK; 1069 int not_done_yet = 1;1070 int passno = 1;1071 int pass _done;858 smallint not_done_yet; 859 smallint pass_done; 860 int passno; 1072 861 1073 862 if (verbose) 1074 fputs("Checking all file systems.\n", stdout);863 puts("Checking all filesystems"); 1075 864 1076 865 /* … … 1089 878 if (!parallel_root) { 1090 879 for (fs = filesys_info; fs; fs = fs->next) { 1091 if ( !strcmp(fs->mountpt, "/"))880 if (LONE_CHAR(fs->mountpt, '/')) 1092 881 break; 1093 882 } … … 1104 893 /* 1105 894 * This is for the bone-headed user who enters the root 1106 * filesystem twice. Skip root will sk ep all root entries.895 * filesystem twice. Skip root will skip all root entries. 1107 896 */ 1108 897 if (skip_root) 1109 898 for (fs = filesys_info; fs; fs = fs->next) 1110 if ( !strcmp(fs->mountpt, "/"))899 if (LONE_CHAR(fs->mountpt, '/')) 1111 900 fs->flags |= FLAG_DONE; 1112 901 902 not_done_yet = 1; 903 passno = 1; 1113 904 while (not_done_yet) { 1114 905 not_done_yet = 0; … … 1126 917 */ 1127 918 if (fs->passno > passno) { 1128 not_done_yet ++;919 not_done_yet = 1; 1129 920 continue; 1130 921 } … … 1149 940 * at one time, apply that limit. 1150 941 */ 1151 if (serialize || 1152 (max_running && (num_running >= max_running))) { 942 if (serialize 943 || (max_running && (num_running >= max_running)) 944 ) { 1153 945 pass_done = 0; 1154 946 break; … … 1163 955 if (pass_done) { 1164 956 if (verbose > 1) 1165 p rintf("----------------------------------\n");957 puts("----------------------------------"); 1166 958 passno++; 1167 959 } else 1168 not_done_yet++; 1169 } 1170 if (cancel_requested && !kill_sent) { 1171 kill_all(SIGTERM); 1172 kill_sent++; 1173 } 960 not_done_yet = 1; 961 } 962 kill_all_if_cancel_requested(); 1174 963 status |= wait_many(FLAG_WAIT_ATLEAST_ONE); 1175 964 return status; 1176 965 } 1177 966 1178 static void signal_cancel(int sig FSCK_ATTR((unused))) 1179 { 1180 cancel_requested++; 1181 } 1182 1183 static void PRS(int argc, char *argv[]) 1184 { 1185 int i, j; 1186 char *arg, *dev, *tmp = 0; 1187 char options[128]; 1188 int opt = 0; 1189 int opts_for_fsck = 0; 1190 struct sigaction sa; 1191 1192 /* 1193 * Set up signal action 1194 */ 1195 memset(&sa, 0, sizeof(struct sigaction)); 1196 sa.sa_handler = signal_cancel; 1197 sigaction(SIGINT, &sa, 0); 1198 sigaction(SIGTERM, &sa, 0); 1199 967 /* 968 * Deal with the fsck -t argument. 969 * Huh, for mount "-t novfat,nfs" means "neither vfat nor nfs"! 970 * Why here we require "-t novfat,nonfs" ?? 971 */ 972 static void compile_fs_type(char *fs_type) 973 { 974 char *s; 975 int num = 2; 976 smallint negate; 977 978 if (fs_type) { 979 s = fs_type; 980 while ((s = strchr(s, ','))) { 981 num++; 982 s++; 983 } 984 } 985 986 fs_type_list = xzalloc(num * sizeof(fs_type_list[0])); 987 fs_type_flag = xzalloc(num * sizeof(fs_type_flag[0])); 988 fs_type_negated = -1; /* not yet known is it negated or not */ 989 990 if (!fs_type) 991 return; 992 993 num = 0; 994 s = fs_type; 995 while (1) { 996 char *comma; 997 998 negate = 0; 999 if (s[0] == 'n' && s[1] == 'o') { /* "no.." */ 1000 s += 2; 1001 negate = 1; 1002 } else if (s[0] == '!') { 1003 s++; 1004 negate = 1; 1005 } 1006 1007 if (strcmp(s, "loop") == 0) 1008 /* loop is really short-hand for opts=loop */ 1009 goto loop_special_case; 1010 if (strncmp(s, "opts=", 5) == 0) { 1011 s += 5; 1012 loop_special_case: 1013 fs_type_flag[num] = negate ? FS_TYPE_FLAG_NEGOPT : FS_TYPE_FLAG_OPT; 1014 } else { 1015 if (fs_type_negated == -1) 1016 fs_type_negated = negate; 1017 if (fs_type_negated != negate) 1018 bb_error_msg_and_die( 1019 "either all or none of the filesystem types passed to -t must be prefixed " 1020 "with 'no' or '!'"); 1021 } 1022 comma = strchr(s, ','); 1023 fs_type_list[num++] = comma ? xstrndup(s, comma-s) : xstrdup(s); 1024 if (!comma) 1025 break; 1026 s = comma + 1; 1027 } 1028 } 1029 1030 static void parse_args(int argc, char **argv) 1031 { 1032 int i, j; 1033 char *arg, *tmp; 1034 char *options = NULL; 1035 int optpos = 0; 1036 int opts_for_fsck = 0; 1037 1038 /* in bss, so already zeroed 1200 1039 num_devices = 0; 1201 1040 num_args = 0; 1202 instance_list = 0; 1203 1204 for (i=1; i < argc; i++) { 1041 instance_list = NULL; 1042 */ 1043 1044 /* TODO: getopt32 */ 1045 for (i = 1; i < argc; i++) { 1205 1046 arg = argv[i]; 1206 if (!arg) 1047 1048 /* "/dev/blk" or "/path" or "UUID=xxx" or "LABEL=xxx" */ 1049 if ((arg[0] == '/' && !opts_for_fsck) || strchr(arg, '=')) { 1050 // FIXME: must check that arg is a blkdev, or resolve 1051 // "/path", "UUID=xxx" or "LABEL=xxx" into block device name 1052 // ("UUID=xxx"/"LABEL=xxx" can probably shifted to fsck.auto duties) 1053 devices = xrealloc(devices, (num_devices+1) * sizeof(devices[0])); 1054 devices[num_devices++] = xstrdup(arg); 1207 1055 continue; 1208 if ((arg[0] == '/' && !opts_for_fsck) || strchr(arg, '=')) { 1209 if (num_devices >= MAX_DEVICES) { 1210 bb_error_msg_and_die("too many devices"); 1211 } 1212 dev = blkid_get_devname(cache, arg, NULL); 1213 if (!dev && strchr(arg, '=')) { 1214 /* 1215 * Check to see if we failed because 1216 * /proc/partitions isn't found. 1217 */ 1218 if (access("/proc/partitions", R_OK) < 0) { 1219 bb_error_msg_and_die("Couldn't open /proc/partitions: %m\n" 1220 "Is /proc mounted?"); 1221 } 1222 /* 1223 * Check to see if this is because 1224 * we're not running as root 1225 */ 1226 if (geteuid()) 1227 bb_error_msg_and_die( 1228 "Must be root to scan for matching filesystems: %s\n", arg); 1229 else 1230 bb_error_msg_and_die( 1231 "Couldn't find matching filesystem: %s", arg); 1232 } 1233 devices[num_devices++] = dev ? dev : string_copy(arg); 1056 } 1057 1058 if (arg[0] != '-' || opts_for_fsck) { 1059 args = xrealloc(args, (num_args+1) * sizeof(args[0])); 1060 args[num_args++] = xstrdup(arg); 1234 1061 continue; 1235 1062 } 1236 if (arg[0] != '-' || opts_for_fsck) { 1237 if (num_args >= MAX_ARGS) { 1238 bb_error_msg_and_die("too many arguments"); 1239 } 1240 args[num_args++] = string_copy(arg); 1241 continue; 1242 } 1243 for (j=1; arg[j]; j++) { 1063 1064 for (j = 1; arg[j]; j++) { 1244 1065 if (opts_for_fsck) { 1245 options[++opt] = arg[j]; 1066 optpos++; 1067 /* one extra for '\0' */ 1068 options = xrealloc(options, optpos + 2); 1069 options[optpos] = arg[j]; 1246 1070 continue; 1247 1071 } 1248 1072 switch (arg[j]) { 1249 1073 case 'A': 1250 doall++; 1251 break; 1074 doall = 1; 1075 break; 1076 #if DO_PROGRESS_INDICATOR 1252 1077 case 'C': 1253 progress++; 1254 if (arg[j+1]) { 1255 progress_fd = string_to_int(arg+j+1); 1256 if (progress_fd < 0) 1257 progress_fd = 0; 1258 else 1259 goto next_arg; 1260 } else if ((i+1) < argc && 1261 !strncmp(argv[i+1], "-", 1) == 0) { 1262 progress_fd = string_to_int(argv[i]); 1263 if (progress_fd < 0) 1264 progress_fd = 0; 1265 else { 1266 goto next_arg; 1267 i++; 1268 } 1078 progress = 1; 1079 if (arg[++j]) { /* -Cn */ 1080 progress_fd = xatoi_u(&arg[j]); 1081 goto next_arg; 1269 1082 } 1270 break; 1083 /* -C n */ 1084 progress_fd = xatoi_u(argv[++i]); 1085 goto next_arg; 1086 #endif 1271 1087 case 'V': 1272 1088 verbose++; 1273 1089 break; 1274 1090 case 'N': 1275 noexecute ++;1091 noexecute = 1; 1276 1092 break; 1277 1093 case 'R': 1278 skip_root ++;1094 skip_root = 1; 1279 1095 break; 1280 1096 case 'T': 1281 notitle ++;1282 break; 1283 case 'M':1284 like_mount ++;1285 break; 1097 notitle = 1; 1098 break; 1099 /* case 'M': 1100 like_mount = 1; 1101 break; */ 1286 1102 case 'P': 1287 parallel_root ++;1103 parallel_root = 1; 1288 1104 break; 1289 1105 case 's': 1290 serialize ++;1106 serialize = 1; 1291 1107 break; 1292 1108 case 't': 1293 tmp = 0;1294 1109 if (fstype) 1295 1110 bb_show_usage(); 1296 if (arg[ j+1])1297 tmp = arg+j+1;1298 else if ( (i+1)< argc)1299 tmp = argv[ ++i];1111 if (arg[++j]) 1112 tmp = &arg[j]; 1113 else if (++i < argc) 1114 tmp = argv[i]; 1300 1115 else 1301 1116 bb_show_usage(); 1302 fstype = string_copy(tmp);1303 compile_fs_type(fstype , &fs_type_compiled);1117 fstype = xstrdup(tmp); 1118 compile_fs_type(fstype); 1304 1119 goto next_arg; 1305 1120 case '-': … … 1310 1125 break; 1311 1126 default: 1312 options[++opt] = arg[j]; 1127 optpos++; 1128 /* one extra for '\0' */ 1129 options = xrealloc(options, optpos + 2); 1130 options[optpos] = arg[j]; 1313 1131 break; 1314 1132 } 1315 1133 } 1316 1317 if (opt ) {1134 next_arg: 1135 if (optpos) { 1318 1136 options[0] = '-'; 1319 options[++opt] = '\0'; 1320 if (num_args >= MAX_ARGS) { 1321 bb_error_msg("too many arguments"); 1322 } 1323 args[num_args++] = string_copy(options); 1324 opt = 0; 1137 options[optpos + 1] = '\0'; 1138 args = xrealloc(args, (num_args+1) * sizeof(args[0])); 1139 args[num_args++] = options; 1140 optpos = 0; 1141 options = NULL; 1325 1142 } 1326 1143 } 1327 1144 if (getenv("FSCK_FORCE_ALL_PARALLEL")) 1328 force_all_parallel++; 1329 if ((tmp = getenv("FSCK_MAX_INST"))) 1330 max_running = atoi(tmp); 1331 } 1332 1333 int fsck_main(int argc, char *argv[]) 1145 force_all_parallel = 1; 1146 tmp = getenv("FSCK_MAX_INST"); 1147 if (tmp) 1148 max_running = xatoi(tmp); 1149 } 1150 1151 static void signal_cancel(int sig ATTRIBUTE_UNUSED) 1152 { 1153 cancel_requested = 1; 1154 } 1155 1156 int fsck_main(int argc, char **argv); 1157 int fsck_main(int argc, char **argv) 1334 1158 { 1335 1159 int i, status = 0; 1336 int interactive = 0;1160 int interactive; 1337 1161 const char *fstab; 1338 1162 struct fs_info *fs; 1339 1340 setvbuf(stdout, NULL, _IONBF, BUFSIZ); 1341 setvbuf(stderr, NULL, _IONBF, BUFSIZ); 1342 1343 blkid_get_cache(&cache, NULL); 1344 PRS(argc, argv); 1163 struct sigaction sa; 1164 1165 memset(&sa, 0, sizeof(sa)); 1166 sa.sa_handler = signal_cancel; 1167 sigaction(SIGINT, &sa, 0); 1168 sigaction(SIGTERM, &sa, 0); 1169 1170 setbuf(stdout, NULL); 1171 1172 parse_args(argc, argv); 1345 1173 1346 1174 if (!notitle) 1347 printf("fsck %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE); 1348 1175 puts("fsck (busybox "BB_VER", "BB_BT")"); 1176 1177 /* Even plain "fsck /dev/hda1" needs fstab to get fs type, 1178 * so we are scanning it anyway */ 1349 1179 fstab = getenv("FSTAB_FILE"); 1350 1180 if (!fstab) 1351 fstab = _PATH_MNTTAB;1181 fstab = "/etc/fstab"; 1352 1182 load_fs_info(fstab); 1353 1183 1354 fsck_path = e2fs_set_sbin_path(); 1355 1356 if ((num_devices == 1) || (serialize)) 1357 interactive = 1; 1184 interactive = (num_devices == 1) | serialize; 1358 1185 1359 1186 /* If -A was specified ("check all"), do that! */ … … 1362 1189 1363 1190 if (num_devices == 0) { 1364 serialize ++;1365 interactive ++;1191 serialize = 1; 1192 interactive = 1; 1366 1193 return check_all(); 1367 1194 } 1368 for (i = 0 ; i < num_devices; i++) { 1195 1196 for (i = 0; i < num_devices; i++) { 1369 1197 if (cancel_requested) { 1370 if (!kill_sent) { 1371 kill_all(SIGTERM); 1372 kill_sent++; 1373 } 1198 kill_all_if_cancel_requested(); 1374 1199 break; 1375 1200 } 1201 1376 1202 fs = lookup(devices[i]); 1377 if (!fs) { 1378 fs = create_fs_device(devices[i], 0, "auto", 1379 0, -1, -1); 1380 if (!fs) 1381 continue; 1382 } 1203 if (!fs) 1204 fs = create_fs_device(devices[i], 0, "auto", 0, -1, -1); 1383 1205 fsck_device(fs, interactive); 1384 if (serialize || 1385 (max_running && (num_running >= max_running))) { 1206 1207 if (serialize 1208 || (max_running && (num_running >= max_running)) 1209 ) { 1386 1210 struct fsck_instance *inst; 1387 1211 … … 1392 1216 } 1393 1217 if (verbose > 1) 1394 p rintf("----------------------------------\n");1218 puts("----------------------------------"); 1395 1219 } 1396 1220 } 1397 1221 status |= wait_many(FLAG_WAIT_ALL); 1398 blkid_put_cache(cache);1399 1222 return status; 1400 1223 } -
branches/stable/mindi-busybox/e2fsprogs/lsattr.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* 2 3 * lsattr.c - List file attributes on an ext2 file system … … 18 19 */ 19 20 20 #include <sys/types.h> 21 #include <dirent.h> 22 #include <errno.h> 23 #include <fcntl.h> 24 #include <getopt.h> 25 #include <stdio.h> 26 #include <unistd.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <sys/param.h> 30 #include <sys/stat.h> 21 #include "libbb.h" 22 #include "e2fs_lib.h" 31 23 32 #include "ext2fs/ext2_fs.h" 33 #include "e2fsbb.h" 34 #include "e2p/e2p.h" 35 36 #define OPT_RECUR 1 37 #define OPT_ALL 2 38 #define OPT_DIRS_OPT 4 39 #define OPT_PF_LONG 8 40 #define OPT_GENERATION 16 41 static int flags; 42 43 #ifdef CONFIG_LFS 44 # define LSTAT lstat64 45 # define STRUCT_STAT struct stat64 46 #else 47 # define LSTAT lstat 48 # define STRUCT_STAT struct stat 49 #endif 24 enum { 25 OPT_RECUR = 0x1, 26 OPT_ALL = 0x2, 27 OPT_DIRS_OPT = 0x4, 28 OPT_PF_LONG = 0x8, 29 OPT_GENERATION = 0x10, 30 }; 50 31 51 32 static void list_attributes(const char *name) … … 54 35 unsigned long generation; 55 36 56 if (fgetflags(name, &fsflags) == -1)37 if (fgetflags(name, &fsflags) != 0) 57 38 goto read_err; 58 if (flags & OPT_GENERATION) { 59 if (fgetversion(name, &generation) == -1) 39 40 if (option_mask32 & OPT_GENERATION) { 41 if (fgetversion(name, &generation) != 0) 60 42 goto read_err; 61 43 printf("%5lu ", generation); 62 44 } 63 45 64 if ( flags& OPT_PF_LONG) {46 if (option_mask32 & OPT_PF_LONG) { 65 47 printf("%-28s ", name); 66 48 print_flags(stdout, fsflags, PFOPT_LONG); 67 p rintf("\n");49 puts(""); 68 50 } else { 69 51 print_flags(stdout, fsflags, 0); … … 72 54 73 55 return; 74 read_err:56 read_err: 75 57 bb_perror_msg("reading %s", name); 76 }77 78 static int lsattr_dir_proc(const char *, struct dirent *, void *);79 80 static void lsattr_args(const char *name)81 {82 STRUCT_STAT st;83 84 if (LSTAT(name, &st) == -1) {85 bb_perror_msg("stating %s", name);86 } else {87 if (S_ISDIR(st.st_mode) && !(flags & OPT_DIRS_OPT))88 iterate_on_dir(name, lsattr_dir_proc, NULL);89 else90 list_attributes(name);91 }92 58 } 93 59 … … 95 61 void *private) 96 62 { 97 STRUCT_STATst;63 struct stat st; 98 64 char *path; 99 65 100 66 path = concat_path_file(dir_name, de->d_name); 101 67 102 if (LSTAT(path, &st) == -1) 103 bb_perror_msg(path); 104 else { 105 if (de->d_name[0] != '.' || (flags & OPT_ALL)) { 106 list_attributes(path); 107 if (S_ISDIR(st.st_mode) && (flags & OPT_RECUR) && 108 (de->d_name[0] != '.' && (de->d_name[1] != '\0' || 109 (de->d_name[1] != '.' && de->d_name[2] != '\0')))) { 110 printf("\n%s:\n", path); 111 iterate_on_dir(path, lsattr_dir_proc, NULL); 112 printf("\n"); 113 } 68 if (lstat(path, &st) != 0) 69 bb_perror_msg("stat %s", path); 70 else if (de->d_name[0] != '.' || (option_mask32 & OPT_ALL)) { 71 list_attributes(path); 72 if (S_ISDIR(st.st_mode) && (option_mask32 & OPT_RECUR) 73 && !DOT_OR_DOTDOT(de->d_name) 74 ) { 75 printf("\n%s:\n", path); 76 iterate_on_dir(path, lsattr_dir_proc, NULL); 77 puts(""); 114 78 } 115 79 } 116 80 117 81 free(path); 118 119 82 return 0; 120 83 } 121 84 85 static void lsattr_args(const char *name) 86 { 87 struct stat st; 88 89 if (lstat(name, &st) == -1) { 90 bb_perror_msg("stat %s", name); 91 } else if (S_ISDIR(st.st_mode) && !(option_mask32 & OPT_DIRS_OPT)) { 92 iterate_on_dir(name, lsattr_dir_proc, NULL); 93 } else { 94 list_attributes(name); 95 } 96 } 97 98 int lsattr_main(int argc, char **argv); 122 99 int lsattr_main(int argc, char **argv) 123 100 { 124 int i; 101 getopt32(argv, "Radlv"); 102 argv += optind; 125 103 126 flags = bb_getopt_ulflags(argc, argv, "Radlv"); 127 128 if (optind > argc - 1) 104 if (!*argv) 129 105 lsattr_args("."); 130 else 131 for (i = optind; i < argc; i++) 132 lsattr_args(argv[i]); 106 else { 107 while (*argv) 108 lsattr_args(*argv++); 109 } 133 110 134 111 return EXIT_SUCCESS;
Note:
See TracChangeset
for help on using the changeset viewer.