recreate root directory if missing or trashed
[unix-history] / usr / src / sbin / fsck / main.c
CommitLineData
fa95fc59 1#ifndef lint
993a756c 2static char version[] = "@(#)main.c 3.3 (Berkeley) %G%";
fa95fc59 3#endif
07670f7d 4
4d308541 5#include <sys/param.h>
4d308541 6#include <sys/inode.h>
f7635e39 7#include <sys/fs.h>
7718c0e6
KM
8#include <sys/stat.h>
9#include <sys/wait.h>
10#include <fstab.h>
11#include <strings.h>
f7635e39 12#include "fsck.h"
6e884967 13
7718c0e6
KM
14char *rawname(), *unrawname(), *blockcheck();
15int catch();
16int (*signal())();
17
18main(argc, argv)
19 int argc;
20 char *argv[];
21{
22 struct fstab *fsp;
23 int pid, passno, anygtr, sumstatus;
24 char *name;
25
26 sync();
27 while (--argc > 0 && **++argv == '-') {
28 switch (*++*argv) {
29
30 case 'p':
31 preen++;
32 break;
33
34 case 'b':
35 if (argv[0][1] != '\0') {
36 bflag = atoi(argv[0]+1);
37 } else {
38 bflag = atoi(*++argv);
39 argc--;
40 }
41 printf("Alternate super block location: %d\n", bflag);
42 break;
43
44 case 'd':
45 debug++;
46 break;
47
48 case 'n': /* default no answer flag */
49 case 'N':
50 nflag++;
51 yflag = 0;
52 break;
53
54 case 'y': /* default yes answer flag */
55 case 'Y':
56 yflag++;
57 nflag = 0;
58 break;
59
60 default:
61 errexit("%c option?\n", **argv);
62 }
63 }
64 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
65 (void)signal(SIGINT, catch);
66 if (argc) {
67 while (argc-- > 0) {
68 hotroot = 0;
69 checkfilesys(*argv++);
70 }
71 exit(0);
72 }
73 sumstatus = 0;
74 passno = 1;
75 do {
76 anygtr = 0;
77 if (setfsent() == 0)
78 errexit("Can't open checklist file: %s\n", FSTAB);
79 while ((fsp = getfsent()) != 0) {
80 if (strcmp(fsp->fs_type, FSTAB_RW) &&
81 strcmp(fsp->fs_type, FSTAB_RO) &&
82 strcmp(fsp->fs_type, FSTAB_RQ))
83 continue;
84 if (preen == 0 ||
85 passno == 1 && fsp->fs_passno == passno) {
86 name = blockcheck(fsp->fs_spec);
87 if (name != NULL)
88 checkfilesys(name);
89 else if (preen)
90 exit(8);
91 } else if (fsp->fs_passno > passno) {
92 anygtr = 1;
93 } else if (fsp->fs_passno == passno) {
94 pid = fork();
95 if (pid < 0) {
96 perror("fork");
97 exit(8);
98 }
99 if (pid == 0) {
100 name = blockcheck(fsp->fs_spec);
101 if (name == NULL)
102 exit(8);
103 checkfilesys(name);
104 exit(0);
105 }
106 }
107 }
108 if (preen) {
109 union wait status;
110 while (wait(&status) != -1)
111 sumstatus |= status.w_retcode;
112 }
113 passno++;
114 } while (anygtr);
115 if (sumstatus)
116 exit(8);
117 (void)endfsent();
118 exit(0);
119}
120
d2c95d76
BJ
121checkfilesys(filesys)
122 char *filesys;
6e884967 123{
993a756c 124 daddr_t n_ffree, n_bfree;
6e884967 125
d2c95d76
BJ
126 devname = filesys;
127 if (setup(filesys) == 0) {
6e884967 128 if (preen)
d2c95d76 129 pfatal("CAN'T CHECK FILE SYSTEM.");
6e884967
KM
130 return;
131 }
993a756c
KM
132 /*
133 * 1: scan inodes tallying blocks used
134 */
690f77ba
KM
135 if (preen == 0) {
136 printf("** Last Mounted on %s\n", sblock.fs_fsmnt);
6e884967
KM
137 if (hotroot)
138 printf("** Root file system\n");
139 printf("** Phase 1 - Check Blocks and Sizes\n");
140 }
d2c95d76
BJ
141 pass1();
142
993a756c
KM
143 /*
144 * 1b: locate first references to duplicates, if any
145 */
d2c95d76
BJ
146 if (enddup != &duplist[0]) {
147 if (preen)
148 pfatal("INTERNAL ERROR: dups with -p");
149 printf("** Phase 1b - Rescan For More DUPS\n");
150 pass1b();
151 }
152
993a756c
KM
153 /*
154 * 2: traverse directories from root to mark all connected directories
155 */
d2c95d76
BJ
156 if (preen == 0)
157 printf("** Phase 2 - Check Pathnames\n");
158 pass2();
159
993a756c
KM
160 /*
161 * 3: scan inodes looking for disconnected directories
162 */
d2c95d76
BJ
163 if (preen == 0)
164 printf("** Phase 3 - Check Connectivity\n");
165 pass3();
166
993a756c
KM
167 /*
168 * 4: scan inodes looking for disconnected files; check reference counts
169 */
d2c95d76
BJ
170 if (preen == 0)
171 printf("** Phase 4 - Check Reference Counts\n");
172 pass4();
173
993a756c
KM
174 /*
175 * 5: check and repair resource counts in cylinder groups
176 */
d2c95d76
BJ
177 if (preen == 0)
178 printf("** Phase 5 - Check Cyl groups\n");
179 pass5();
180
993a756c
KM
181 /*
182 * print out summary statistics
183 */
184 n_ffree = sblock.fs_cstotal.cs_nffree;
185 n_bfree = sblock.fs_cstotal.cs_nbfree;
186 pwarn("%d files, %d used, %d free (%d frags, %d blocks)\n", n_files,
187 n_blks, n_ffree + sblock.fs_frag * n_bfree, n_ffree, n_bfree);
188 if (debug && (n_files -= imax - ROOTINO - sblock.fs_cstotal.cs_nifree))
189 printf("%d files missing\n", n_files);
190 if (debug) {
191 n_blks += sblock.fs_ncg *
192 (cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
193 n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
194 n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
195 if (n_blks -= fmax - (n_ffree + sblock.fs_frag * n_bfree))
196 printf("%d blocks missing\n", n_blks);
d2c95d76 197 }
d2c95d76 198 if (dfile.mod) {
1a724405 199 (void)time(&sblock.fs_time);
d2c95d76
BJ
200 sbdirty();
201 }
202 ckfini();
203 free(blockmap);
d2c95d76 204 free(statemap);
1a724405 205 free((char *)lncntp);
addfa1aa
BJ
206 if (!dfile.mod)
207 return;
208 if (!preen) {
209 printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
210 if (hotroot)
211 printf("\n***** REBOOT UNIX *****\n");
212 }
213 if (hotroot) {
214 sync();
215 exit(4);
f5971be7 216 }
f5971be7 217}
7718c0e6
KM
218
219char *
220blockcheck(name)
221 char *name;
222{
223 struct stat stslash, stblock, stchar;
224 char *raw;
225 int looped = 0;
226
227 hotroot = 0;
228 if (stat("/", &stslash) < 0){
229 printf("Can't stat root\n");
230 return (0);
231 }
232retry:
233 if (stat(name, &stblock) < 0){
234 printf("Can't stat %s\n", name);
235 return (0);
236 }
237 if (stblock.st_mode & S_IFBLK) {
238 raw = rawname(name);
239 if (stat(raw, &stchar) < 0){
240 printf("Can't stat %s\n", raw);
241 return (0);
242 }
243 if (stchar.st_mode & S_IFCHR) {
244 if (stslash.st_dev == stblock.st_rdev) {
245 hotroot++;
246 raw = unrawname(name);
247 }
248 return (raw);
249 } else {
250 printf("%s is not a character device\n", raw);
251 return (0);
252 }
253 } else if (stblock.st_mode & S_IFCHR) {
254 if (looped) {
255 printf("Can't make sense out of name %s\n", name);
256 return (0);
257 }
258 name = unrawname(name);
259 looped++;
260 goto retry;
261 }
262 printf("Can't make sense out of name %s\n", name);
263 return (0);
264}
265
266char *
267unrawname(cp)
268 char *cp;
269{
270 char *dp = rindex(cp, '/');
271 struct stat stb;
272
273 if (dp == 0)
274 return (cp);
275 if (stat(cp, &stb) < 0)
276 return (cp);
277 if ((stb.st_mode&S_IFMT) != S_IFCHR)
278 return (cp);
279 if (*(dp+1) != 'r')
280 return (cp);
281 (void)strcpy(dp+1, dp+2);
282 return (cp);
283}
284
285char *
286rawname(cp)
287 char *cp;
288{
289 static char rawbuf[32];
290 char *dp = rindex(cp, '/');
291
292 if (dp == 0)
293 return (0);
294 *dp = 0;
295 (void)strcpy(rawbuf, cp);
296 *dp = '/';
297 (void)strcat(rawbuf, "/r");
298 (void)strcat(rawbuf, dp+1);
299 return (rawbuf);
300}