|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char sccsid[] = "@(#)setup.c 5.19 (Berkeley) 5/7/88";
9: #endif not lint
10:
11: #define DKTYPENAMES
12: #include <sys/param.h>
13: #include <sys/inode.h>
14: #include <sys/fs.h>
15: #include <sys/stat.h>
16: #include <sys/ioctl.h>
17: #include <sys/disklabel.h>
18: #include <sys/file.h>
19: #include <machine/endian.h>
20: #include <ctype.h>
21: #include "fsck.h"
22:
23: BUFAREA asblk;
24: #define altsblock (*asblk.b_un.b_fs)
25: #define POWEROF2(num) (((num) & ((num) - 1)) == 0)
26:
27: char *calloc();
28: char *index();
29:
30: setup(dev)
31: char *dev;
32: {
33: dev_t rootdev;
34: long cg, ncg, size, asked, i, j;
35: struct disklabel *getdisklabel(), *lp;
36: struct stat statb;
37: struct fs proto;
38:
39: havesb = 0;
40: if (stat("/", &statb) < 0)
41: errexit("Can't stat root\n");
42: rootdev = statb.st_dev;
43: if (stat(dev, &statb) < 0) {
44: perror(dev);
45: printf("Can't stat %s\n", dev);
46: return (0);
47: }
48: rawflg = 0;
49: if ((statb.st_mode & S_IFMT) == S_IFBLK)
50: ;
51: else if ((statb.st_mode & S_IFMT) == S_IFCHR)
52: rawflg++;
53: else {
54: if (reply("file is not a block or character device; OK") == 0)
55: return (0);
56: }
57: if (rootdev == statb.st_rdev)
58: hotroot++;
59: if ((dfile.rfdes = open(dev, O_RDONLY)) < 0) {
60: perror(dev);
61: printf("Can't open %s\n", dev);
62: return (0);
63: }
64: if (preen == 0)
65: printf("** %s", dev);
66: if (nflag || (dfile.wfdes = open(dev, O_WRONLY)) < 0) {
67: dfile.wfdes = -1;
68: if (preen)
69: pfatal("NO WRITE ACCESS");
70: printf(" (NO WRITE)");
71: }
72: if (preen == 0)
73: printf("\n");
74: dfile.mod = 0;
75: lfdir = 0;
76: initbarea(&sblk);
77: initbarea(&asblk);
78: sblk.b_un.b_buf = (char *)malloc(SBSIZE);
79: asblk.b_un.b_buf = (char *)malloc(SBSIZE);
80: if (sblk.b_un.b_buf == 0 || asblk.b_un.b_buf == 0)
81: errexit("cannot allocate space for superblock\n");
82: if (lp = getdisklabel((char *)NULL, dfile.rfdes))
83: dev_bsize = secsize = lp->d_secsize;
84: else
85: dev_bsize = secsize = DEV_BSIZE;
86: /*
87: * Read in the superblock, looking for alternates if necessary
88: */
89: if (readsb(1) == 0) {
90: if (bflag || preen || calcsb(dev, dfile.rfdes, &proto) == 0)
91: return(0);
92: if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0)
93: return (0);
94: for (cg = 0; cg < proto.fs_ncg; cg++) {
95: bflag = fsbtodb(&proto, cgsblock(&proto, cg));
96: if (readsb(0) != 0)
97: break;
98: }
99: if (cg >= proto.fs_ncg) {
100: printf("%s %s\n%s %s\n%s %s\n",
101: "SEARCH FOR ALTERNATE SUPER-BLOCK",
102: "FAILED. YOU MUST USE THE",
103: "-b OPTION TO FSCK TO SPECIFY THE",
104: "LOCATION OF AN ALTERNATE",
105: "SUPER-BLOCK TO SUPPLY NEEDED",
106: "INFORMATION; SEE fsck(8).");
107: return(0);
108: }
109: pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag);
110: }
111: fmax = sblock.fs_size;
112: imax = sblock.fs_ncg * sblock.fs_ipg;
113: /*
114: * Check and potentially fix certain fields in the super block.
115: */
116: if (sblock.fs_optim != FS_OPTTIME && sblock.fs_optim != FS_OPTSPACE) {
117: pfatal("UNDEFINED OPTIMIZATION IN SUPERBLOCK");
118: if (reply("SET TO DEFAULT") == 1) {
119: sblock.fs_optim = FS_OPTTIME;
120: sbdirty();
121: }
122: }
123: if ((sblock.fs_minfree < 0 || sblock.fs_minfree > 99)) {
124: pfatal("IMPOSSIBLE MINFREE=%d IN SUPERBLOCK",
125: sblock.fs_minfree);
126: if (reply("SET TO DEFAULT") == 1) {
127: sblock.fs_minfree = 10;
128: sbdirty();
129: }
130: }
131: if (sblock.fs_interleave < 1) {
132: pwarn("IMPOSSIBLE INTERLEAVE=%d IN SUPERBLOCK",
133: sblock.fs_interleave);
134: sblock.fs_interleave = 1;
135: if (preen)
136: printf(" (FIXED)\n");
137: if (preen || reply("SET TO DEFAULT") == 1) {
138: sbdirty();
139: dirty(&asblk);
140: }
141: }
142: if (sblock.fs_npsect < sblock.fs_nsect) {
143: pwarn("IMPOSSIBLE NPSECT=%d IN SUPERBLOCK",
144: sblock.fs_npsect);
145: sblock.fs_npsect = sblock.fs_nsect;
146: if (preen)
147: printf(" (FIXED)\n");
148: if (preen || reply("SET TO DEFAULT") == 1) {
149: sbdirty();
150: dirty(&asblk);
151: }
152: }
153: if (cvtflag) {
154: if (sblock.fs_postblformat == FS_42POSTBLFMT) {
155: /*
156: * Requested to convert from old format to new format
157: */
158: if (preen)
159: pwarn("CONVERTING TO NEW FILE SYSTEM FORMAT\n");
160: else if (!reply("CONVERT TO NEW FILE SYSTEM FORMAT"))
161: return(0);
162: sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT;
163: sblock.fs_nrpos = 8;
164: sblock.fs_postbloff =
165: (char *)(&sblock.fs_opostbl[0][0]) -
166: (char *)(&sblock.fs_link);
167: sblock.fs_rotbloff = &sblock.fs_space[0] -
168: (u_char *)(&sblock.fs_link);
169: /*
170: * Planning now for future expansion.
171: */
172: # if (BYTE_ORDER == BIG_ENDIAN)
173: sblock.fs_qbmask.val[0] = 0;
174: sblock.fs_qbmask.val[1] = ~sblock.fs_bmask;
175: sblock.fs_qfmask.val[0] = 0;
176: sblock.fs_qfmask.val[1] = ~sblock.fs_fmask;
177: # endif /* BIG_ENDIAN */
178: # if (BYTE_ORDER == LITTLE_ENDIAN)
179: sblock.fs_qbmask.val[0] = ~sblock.fs_bmask;
180: sblock.fs_qbmask.val[1] = 0;
181: sblock.fs_qfmask.val[0] = ~sblock.fs_fmask;
182: sblock.fs_qfmask.val[1] = 0;
183: # endif /* LITTLE_ENDIAN */
184: sbdirty();
185: dirty(&asblk);
186: } else if (sblock.fs_postblformat == FS_DYNAMICPOSTBLFMT) {
187: /*
188: * Requested to convert from new format to old format
189: */
190: if (sblock.fs_nrpos != 8 || sblock.fs_ipg > 2048 ||
191: sblock.fs_cpg > 32 || sblock.fs_cpc > 16) {
192: printf(
193: "PARAMETERS OF CURRENT FILE SYSTEM DO NOT\n\t");
194: errexit(
195: "ALLOW CONVERSION TO OLD FILE SYSTEM FORMAT\n");
196: }
197: if (preen)
198: pwarn("CONVERTING TO OLD FILE SYSTEM FORMAT\n");
199: else if (!reply("CONVERT TO OLD FILE SYSTEM FORMAT"))
200: return(0);
201: sblock.fs_postblformat = FS_42POSTBLFMT;
202: sbdirty();
203: dirty(&asblk);
204: } else {
205: errexit("UNKNOWN FILE SYSTEM FORMAT\n");
206: }
207: }
208: if (asblk.b_dirty) {
209: bcopy((char *)&sblock, (char *)&altsblock, sblock.fs_sbsize);
210: flush(&dfile, &asblk);
211: }
212: /*
213: * read in the summary info.
214: */
215: asked = 0;
216: for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
217: size = sblock.fs_cssize - i < sblock.fs_bsize ?
218: sblock.fs_cssize - i : sblock.fs_bsize;
219: sblock.fs_csp[j] = (struct csum *)calloc(1, (unsigned)size);
220: if (bread(&dfile, (char *)sblock.fs_csp[j],
221: fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
222: size) != 0 && !asked) {
223: pfatal("BAD SUMMARY INFORMATION");
224: if (reply("CONTINUE") == 0)
225: errexit("");
226: asked++;
227: }
228: }
229: /*
230: * allocate and initialize the necessary maps
231: */
232: bmapsz = roundup(howmany(fmax, NBBY), sizeof(short));
233: blockmap = calloc((unsigned)bmapsz, sizeof (char));
234: if (blockmap == NULL) {
235: printf("cannot alloc %d bytes for blockmap\n", bmapsz);
236: goto badsb;
237: }
238: statemap = calloc((unsigned)(imax + 1), sizeof(char));
239: if (statemap == NULL) {
240: printf("cannot alloc %d bytes for statemap\n", imax + 1);
241: goto badsb;
242: }
243: lncntp = (short *)calloc((unsigned)(imax + 1), sizeof(short));
244: if (lncntp == NULL) {
245: printf("cannot alloc %d bytes for lncntp\n",
246: (imax + 1) * sizeof(short));
247: goto badsb;
248: }
249:
250: bufinit();
251: return (1);
252:
253: badsb:
254: ckfini();
255: return (0);
256: }
257:
258: /*
259: * Read in the super block and its summary info.
260: */
261: readsb(listerr)
262: int listerr;
263: {
264: off_t sboff;
265: daddr_t super = bflag ? bflag : SBOFF / dev_bsize;
266:
267: if (bread(&dfile, (char *)&sblock, super, (long)SBSIZE) != 0)
268: return (0);
269: sblk.b_bno = super;
270: sblk.b_size = SBSIZE;
271: /*
272: * run a few consistency checks of the super block
273: */
274: if (sblock.fs_magic != FS_MAGIC)
275: { badsb(listerr, "MAGIC NUMBER WRONG"); return (0); }
276: if (sblock.fs_ncg < 1)
277: { badsb(listerr, "NCG OUT OF RANGE"); return (0); }
278: if (sblock.fs_cpg < 1)
279: { badsb(listerr, "CPG OUT OF RANGE"); return (0); }
280: if (sblock.fs_ncg * sblock.fs_cpg < sblock.fs_ncyl ||
281: (sblock.fs_ncg - 1) * sblock.fs_cpg >= sblock.fs_ncyl)
282: { badsb(listerr, "NCYL LESS THAN NCG*CPG"); return (0); }
283: if (sblock.fs_sbsize > SBSIZE)
284: { badsb(listerr, "SIZE PREPOSTEROUSLY LARGE"); return (0); }
285: /*
286: * Compute block size that the filesystem is based on,
287: * according to fsbtodb, and adjust superblock block number
288: * so we can tell if this is an alternate later.
289: */
290: super *= dev_bsize;
291: dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1);
292: sblk.b_bno = super / dev_bsize;
293: /*
294: * Set all possible fields that could differ, then do check
295: * of whole super block against an alternate super block.
296: * When an alternate super-block is specified this check is skipped.
297: */
298: getblk(&asblk, cgsblock(&sblock, sblock.fs_ncg - 1), sblock.fs_sbsize);
299: if (asblk.b_errs != NULL)
300: return (0);
301: if (bflag) {
302: havesb = 1;
303: return (1);
304: }
305: altsblock.fs_link = sblock.fs_link;
306: altsblock.fs_rlink = sblock.fs_rlink;
307: altsblock.fs_time = sblock.fs_time;
308: altsblock.fs_cstotal = sblock.fs_cstotal;
309: altsblock.fs_cgrotor = sblock.fs_cgrotor;
310: altsblock.fs_fmod = sblock.fs_fmod;
311: altsblock.fs_clean = sblock.fs_clean;
312: altsblock.fs_ronly = sblock.fs_ronly;
313: altsblock.fs_flags = sblock.fs_flags;
314: altsblock.fs_maxcontig = sblock.fs_maxcontig;
315: altsblock.fs_minfree = sblock.fs_minfree;
316: altsblock.fs_optim = sblock.fs_optim;
317: altsblock.fs_rotdelay = sblock.fs_rotdelay;
318: altsblock.fs_maxbpg = sblock.fs_maxbpg;
319: bcopy((char *)sblock.fs_csp, (char *)altsblock.fs_csp,
320: sizeof sblock.fs_csp);
321: bcopy((char *)sblock.fs_fsmnt, (char *)altsblock.fs_fsmnt,
322: sizeof sblock.fs_fsmnt);
323: bcopy((char *)sblock.fs_sparecon, (char *)altsblock.fs_sparecon,
324: sizeof sblock.fs_sparecon);
325: /*
326: * The following should not have to be copied.
327: */
328: altsblock.fs_fsbtodb = sblock.fs_fsbtodb;
329: altsblock.fs_interleave = sblock.fs_interleave;
330: altsblock.fs_npsect = sblock.fs_npsect;
331: altsblock.fs_nrpos = sblock.fs_nrpos;
332: if (bcmp((char *)&sblock, (char *)&altsblock, (int)sblock.fs_sbsize)) {
333: badsb(listerr,
334: "VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN FIRST ALTERNATE");
335: return (0);
336: }
337: havesb = 1;
338: return (1);
339: }
340:
341: badsb(listerr, s)
342: int listerr;
343: char *s;
344: {
345:
346: if (!listerr)
347: return;
348: if (preen)
349: printf("%s: ", devname);
350: pfatal("BAD SUPER BLOCK: %s\n", s);
351: }
352:
353: /*
354: * Calculate a prototype superblock based on information in the disk label.
355: * When done the cgsblock macro can be calculated and the fs_ncg field
356: * can be used. Do NOT attempt to use other macros without verifying that
357: * their needed information is available!
358: */
359: calcsb(dev, devfd, fs)
360: char *dev;
361: int devfd;
362: register struct fs *fs;
363: {
364: register struct disklabel *lp;
365: register struct partition *pp;
366: register char *cp;
367: int i;
368: struct disklabel *getdisklabel();
369:
370: cp = index(dev, '\0') - 1;
371: if (cp == (char *)-1 || (*cp < 'a' || *cp > 'h') && !isdigit(*cp)) {
372: pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev);
373: return (0);
374: }
375: lp = getdisklabel(dev, devfd);
376: if (isdigit(*cp))
377: pp = &lp->d_partitions[0];
378: else
379: pp = &lp->d_partitions[*cp - 'a'];
380: if (pp->p_fstype != FS_BSDFFS) {
381: pfatal("%s: NOT LABELED AS A BSD FILE SYSTEM (%s)\n",
382: dev, pp->p_fstype < FSMAXTYPES ?
383: fstypenames[pp->p_fstype] : "unknown");
384: return (0);
385: }
386: bzero(fs, sizeof(struct fs));
387: fs->fs_fsize = pp->p_fsize;
388: fs->fs_frag = pp->p_frag;
389: fs->fs_cpg = pp->p_cpg;
390: fs->fs_size = pp->p_size;
391: fs->fs_ntrak = lp->d_ntracks;
392: fs->fs_nsect = lp->d_nsectors;
393: fs->fs_spc = lp->d_secpercyl;
394: fs->fs_nspf = fs->fs_fsize / lp->d_secsize;
395: fs->fs_sblkno = roundup(
396: howmany(lp->d_bbsize + lp->d_sbsize, fs->fs_fsize),
397: fs->fs_frag);
398: fs->fs_cgmask = 0xffffffff;
399: for (i = fs->fs_ntrak; i > 1; i >>= 1)
400: fs->fs_cgmask <<= 1;
401: if (!POWEROF2(fs->fs_ntrak))
402: fs->fs_cgmask <<= 1;
403: fs->fs_cgoffset = roundup(
404: howmany(fs->fs_nsect, NSPF(fs)), fs->fs_frag);
405: fs->fs_fpg = (fs->fs_cpg * fs->fs_spc) / NSPF(fs);
406: fs->fs_ncg = howmany(fs->fs_size / fs->fs_spc, fs->fs_cpg);
407: for (fs->fs_fsbtodb = 0, i = NSPF(fs); i > 1; i >>= 1)
408: fs->fs_fsbtodb++;
409: dev_bsize = lp->d_secsize;
410: return (1);
411: }
412:
413: struct disklabel *
414: getdisklabel(s, fd)
415: char *s;
416: int fd;
417: {
418: static struct disklabel lab;
419:
420: if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) {
421: if (s == NULL)
422: return ((struct disklabel *)NULL);
423: pwarn("");
424: perror("ioctl (GDINFO)");
425: errexit("%s: can't read disk label", s);
426: }
427: return (&lab);
428: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.