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