]>
Commit | Line | Data |
---|---|---|
726f69e2 KZ |
1 | /* |
2 | * fs-util A simple generic frontend for the for the fsck and mkfs | |
3 | * programs under Linux. See the manual pages for details. | |
4 | * | |
5 | * Usage: fsck [-AV] [-t fstype] [fs-options] device | |
6 | * mkfs [-V] [-t fstype] [fs-options] device< [size] | |
7 | * | |
8 | * Authors: David Engel, <david@ods.com> | |
9 | * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> | |
10 | */ | |
11 | ||
12 | ||
13 | #include <sys/types.h> | |
14 | #include <sys/wait.h> | |
15 | #include <errno.h> | |
16 | #include <limits.h> | |
17 | #include <stdio.h> | |
18 | #include <stdlib.h> | |
19 | #include <string.h> | |
20 | #include <errno.h> | |
21 | #include <mntent.h> | |
22 | #include <unistd.h> | |
23 | #include <getopt.h> | |
24 | ||
25 | ||
26 | #ifndef DEFAULT_FSTYPE | |
27 | # define DEFAULT_FSTYPE "minix" | |
28 | #endif | |
29 | ||
30 | #define _PATH_PROG "%s.%s" | |
31 | #define _PROG_FSCK "fsck" | |
32 | ||
33 | #define EXIT_OK 0 | |
34 | #define EXIT_NONDESTRUCT 1 | |
35 | #define EXIT_DESTRUCT 2 | |
36 | #define EXIT_UNCORRECTED 4 | |
37 | #define EXIT_ERROR 8 | |
38 | #define EXIT_USAGE 16 | |
39 | #define EXIT_LIBRARY 128 | |
40 | ||
41 | static char *Version = "1.8"; | |
42 | static char *ignored_types[] = { | |
43 | "ignore", | |
44 | "iso9660", | |
45 | "msdos", | |
46 | "nfs", | |
47 | "proc", | |
48 | "sw", | |
49 | "swap", | |
50 | NULL | |
51 | }; | |
52 | ||
53 | ||
54 | /* Execute a program. */ | |
55 | int do_exec(char *prog, char **argv, int verbose) | |
56 | { | |
57 | char *args[33]; | |
58 | register int i; | |
59 | int pid, status; | |
60 | ||
61 | /* Build the vector. */ | |
62 | i = 0; | |
63 | args[i++] = prog; | |
64 | while(*argv != NULL && i < 32) | |
65 | args[i++] = *argv++; | |
66 | args[i] = NULL; | |
67 | ||
68 | if (verbose) { | |
69 | i = 0; | |
70 | while(args[i] != NULL) { | |
71 | printf("%s ", args[i]); | |
72 | i++; | |
73 | } | |
74 | printf("\n"); | |
75 | if (verbose > 1) | |
76 | return EXIT_OK; | |
77 | } | |
78 | ||
79 | /* Fork and execute the correct program. */ | |
80 | if ((pid = fork()) < 0) { | |
81 | perror("fork"); | |
82 | status = EXIT_ERROR; | |
83 | } else if (pid == 0) { | |
84 | (void) execvp(args[0], args); | |
85 | perror(args[0]); | |
86 | exit(EXIT_ERROR); | |
87 | } else { | |
88 | while(wait(&status) != pid) | |
89 | ; | |
90 | status = WEXITSTATUS(status); | |
91 | } | |
92 | ||
93 | return status; | |
94 | } | |
95 | ||
96 | ||
97 | /* Check if we have to ignore a file system type. */ | |
98 | int ignore(char *type, char *opts) | |
99 | { | |
100 | char *cp; | |
101 | char **ip; | |
102 | ||
103 | ip = ignored_types; | |
104 | while (*ip != NULL) { | |
105 | if (!strcmp(type, *ip)) | |
106 | return 1; | |
107 | ip++; | |
108 | } | |
109 | ||
110 | for (cp = strtok(opts, ","); cp != NULL; cp = strtok(NULL, ",")) { | |
111 | if (!strcmp(cp, "noauto")) | |
112 | return 1; | |
113 | } | |
114 | ||
115 | return 0; | |
116 | } | |
117 | ||
118 | ||
119 | /* Check all file systems, using the /etc/fstab table. */ | |
120 | int check_all(int verbose, char **argv) | |
121 | { | |
122 | char path[PATH_MAX]; | |
123 | char *args[33]; | |
124 | FILE *mntfile; | |
125 | struct mntent *mp; | |
126 | register int i; | |
127 | int status = EXIT_OK; | |
128 | ||
129 | if (verbose) | |
130 | printf("Checking all file systems.\n"); | |
131 | ||
132 | /* Create an array of arguments. */ | |
133 | i = 0; | |
134 | while (*argv != NULL && i < 32) | |
135 | args[i++] = *argv++; | |
136 | args[i] = NULL; | |
137 | args[i + 1] = NULL; | |
138 | ||
139 | /* Open the mount table. */ | |
140 | if ((mntfile = setmntent(MNTTAB, "r")) == NULL) { | |
141 | perror(MNTTAB); | |
142 | exit(EXIT_ERROR); | |
143 | } | |
144 | ||
145 | /* Walk through the /etc/fstab file. */ | |
146 | while ((mp = getmntent(mntfile)) != NULL) { | |
147 | if (verbose) | |
148 | printf("%-7s %-15s %-15s ", mp->mnt_type, | |
149 | mp->mnt_fsname, mp->mnt_dir); | |
150 | if (ignore(mp->mnt_type, mp->mnt_opts)) { | |
151 | if (verbose) | |
152 | printf("(ignored)\n"); | |
153 | continue; | |
154 | } | |
155 | ||
156 | /* Build program name. */ | |
157 | sprintf(path, _PATH_PROG, _PROG_FSCK, mp->mnt_type); | |
158 | args[i] = mp->mnt_fsname; | |
159 | status |= do_exec(path, args, verbose); | |
160 | } | |
161 | ||
162 | (void) endmntent(mntfile); | |
163 | ||
164 | return status; | |
165 | } | |
166 | ||
167 | ||
168 | /* Lookup filesys in /etc/fstab and return the corresponding entry. */ | |
169 | struct mntent *lookup(char *filesys) | |
170 | { | |
171 | FILE *mntfile; | |
172 | struct mntent *mp; | |
173 | ||
174 | /* No filesys name given. */ | |
175 | if (filesys == NULL) | |
176 | return NULL; | |
177 | ||
178 | /* Open the mount table. */ | |
179 | if ((mntfile = setmntent(MNTTAB, "r")) == NULL) { | |
180 | perror(MNTTAB); | |
181 | exit(EXIT_ERROR); | |
182 | } | |
183 | ||
184 | while ((mp = getmntent(mntfile)) != NULL) { | |
185 | if (!strcmp(filesys, mp->mnt_fsname) || | |
186 | !strcmp(filesys, mp->mnt_dir)) | |
187 | break; | |
188 | } | |
189 | ||
190 | (void) endmntent(mntfile); | |
191 | ||
192 | return mp; | |
193 | } | |
194 | ||
195 | ||
196 | void usage(int fsck, char *prog) | |
197 | { | |
198 | if (fsck) { | |
199 | fprintf(stderr, "Usage: fsck [-AV] [-t fstype] [fs-options] filesys\n"); | |
200 | } else { | |
201 | fprintf(stderr, "Usage: mkfs [-V] [-t fstype] [fs-options] filesys [size]\n"); | |
202 | } | |
203 | ||
204 | exit(EXIT_USAGE); | |
205 | } | |
206 | ||
207 | ||
208 | void main(int argc, char *argv[]) | |
209 | { | |
210 | char path[PATH_MAX]; | |
211 | char *oldpath, newpath[PATH_MAX]; | |
212 | register char *sp; | |
213 | struct mntent *fsent; | |
214 | char *fstype = NULL; | |
215 | int verbose = 0; | |
216 | int doall = 0; | |
217 | int i, fsck, more; | |
218 | ||
219 | /* Must be 1 for "fsck" and 0 for "mkfs". */ | |
220 | if ((sp = strrchr(argv[0], '/')) != NULL) | |
221 | sp++; | |
222 | else | |
223 | sp = argv[0]; | |
224 | if (!strcmp(sp, _PROG_FSCK)) | |
225 | fsck = 1; | |
226 | else | |
227 | fsck = 0; | |
228 | ||
229 | /* Check commandline options. */ | |
230 | opterr = 0; | |
231 | more = 0; | |
232 | while ((more == 0) && ((i = getopt(argc, argv, "AVt:")) != EOF)) | |
233 | switch(i) { | |
234 | case 'A': | |
235 | doall++; | |
236 | break; | |
237 | case 'V': | |
238 | verbose++; | |
239 | break; | |
240 | case 't': | |
241 | if (optarg == NULL) | |
242 | usage(fsck, sp); | |
243 | fstype = optarg; | |
244 | break; | |
245 | default: | |
246 | more = 1; | |
247 | break; /* start of specific arguments */ | |
248 | } | |
249 | ||
250 | /* Did we get any specific arguments? */ | |
251 | if (more) | |
252 | optind--; | |
253 | ||
254 | /* Print our version number if requested. */ | |
255 | if (verbose) | |
256 | printf("%s (fsutil) version %s (%s)\n", argv[0], | |
257 | Version, __DATE__); | |
258 | ||
259 | /* Update our PATH to include /etc/fs and /etc. */ | |
260 | strcpy(newpath, "PATH=/etc/fs:/etc:"); | |
261 | if ((oldpath = getenv("PATH")) != NULL) | |
262 | strcat(newpath, oldpath); | |
263 | putenv(newpath); | |
264 | ||
265 | /* If -A was specified ("check all"), double-check. */ | |
266 | if (doall) { | |
267 | if (!fsck || (fstype != NULL)) | |
268 | usage(fsck, sp); | |
269 | exit(check_all(verbose, &argv[optind])); | |
270 | } else { | |
271 | /* If -t wasn't specified, we must deduce fstype. */ | |
272 | if (fstype == NULL) { | |
273 | /* make sure that "filesys" was specified */ | |
274 | if (optind >= argc) | |
275 | usage(fsck, sp); | |
276 | /* then try looking for it in /etc/fstab */ | |
277 | if ((fsent = lookup(argv[argc - 1])) != NULL) { | |
278 | argv[argc - 1] = fsent->mnt_fsname; | |
279 | fstype = fsent->mnt_type; | |
280 | } else { | |
281 | if (!fsck && optind < argc-1) { | |
282 | if ((fsent = lookup(argv[argc - 2])) != NULL) { | |
283 | argv[argc - 2] = fsent->mnt_fsname; | |
284 | fstype = fsent->mnt_type; | |
285 | } | |
286 | } | |
287 | } | |
288 | /* if we still don't know, use the default */ | |
289 | if (fstype == NULL) fstype = DEFAULT_FSTYPE; | |
290 | } | |
291 | ||
292 | /* Build program name. */ | |
293 | sprintf(path, _PATH_PROG, sp, fstype); | |
294 | exit(do_exec(path, &argv[optind], verbose)); | |
295 | } | |
296 | /*NOTREACHED*/ | |
297 | } |