* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
static char sccsid
[] = "@(#)setup.c 5.13 (Berkeley) %G%";
#include <sys/disklabel.h>
#define POWEROF2(num) (((num) & ((num) - 1)) == 0)
long cg
, ncg
, size
, i
, j
;
if (stat("/", &statb
) < 0)
errexit("Can't stat root\n");
if (stat(dev
, &statb
) < 0) {
printf("Can't stat %s\n", dev
);
if ((statb
.st_mode
& S_IFMT
) == S_IFBLK
)
else if ((statb
.st_mode
& S_IFMT
) == S_IFCHR
)
if (reply("file is not a block or character device; OK") == 0)
if (rootdev
== statb
.st_rdev
)
if ((dfile
.rfdes
= open(dev
, O_RDONLY
)) < 0) {
printf("Can't open %s\n", dev
);
if (nflag
|| (dfile
.wfdes
= open(dev
, O_WRONLY
)) < 0) {
pfatal("NO WRITE ACCESS");
* Read in the superblock, looking for alternates if necessary
if (bflag
|| calcsb(dev
, dfile
.rfdes
, &proto
) == 0 || preen
)
if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0)
for (cg
= 0; cg
< proto
.fs_ncg
; cg
++) {
bflag
= fsbtodb(&proto
, cgsblock(&proto
, cg
));
if (cg
>= proto
.fs_ncg
) {
printf("%s %s\n%s %s\n%s %s\n",
"SEARCH FOR ALTERNATE SUPER-BLOCK",
"FAILED. YOU MUST USE THE",
"-b OPTION TO FSCK TO SPECIFY THE",
"LOCATION OF AN ALTERNATE",
"SUPER-BLOCK TO SUPPLY NEEDED",
"INFORMATION; SEE fsck(8).");
pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag
);
imax
= sblock
.fs_ncg
* sblock
.fs_ipg
;
* Check and potentially fix certain fields in the super block.
if (sblock
.fs_optim
!= FS_OPTTIME
&& sblock
.fs_optim
!= FS_OPTSPACE
) {
pfatal("UNDEFINED OPTIMIZATION IN SUPERBLOCK");
if (reply("SET TO DEFAULT") == 1) {
sblock
.fs_optim
= FS_OPTTIME
;
if ((sblock
.fs_minfree
< 0 || sblock
.fs_minfree
> 99)) {
pfatal("IMPOSSIBLE MINFREE=%d IN SUPERBLOCK",
if (reply("SET TO DEFAULT") == 1) {
if (sblock
.fs_interleave
< 1) {
sblock
.fs_interleave
= 1;
if (sblock
.fs_npsect
< sblock
.fs_nsect
) {
sblock
.fs_npsect
= sblock
.fs_nsect
;
* read in the summary info.
for (i
= 0, j
= 0; i
< sblock
.fs_cssize
; i
+= sblock
.fs_bsize
, j
++) {
size
= sblock
.fs_cssize
- i
< sblock
.fs_bsize
?
sblock
.fs_cssize
- i
: sblock
.fs_bsize
;
sblock
.fs_csp
[j
] = (struct csum
*)calloc(1, (unsigned)size
);
if (bread(&dfile
, (char *)sblock
.fs_csp
[j
],
fsbtodb(&sblock
, sblock
.fs_csaddr
+ j
* sblock
.fs_frag
),
* allocate and initialize the necessary maps
bmapsz
= roundup(howmany(fmax
, NBBY
), sizeof(short));
blockmap
= calloc((unsigned)bmapsz
, sizeof (char));
printf("cannot alloc %d bytes for blockmap\n", bmapsz
);
statemap
= calloc((unsigned)(imax
+ 1), sizeof(char));
printf("cannot alloc %d bytes for statemap\n", imax
+ 1);
lncntp
= (short *)calloc((unsigned)(imax
+ 1), sizeof(short));
printf("cannot alloc %d bytes for lncntp\n",
(imax
+ 1) * sizeof(short));
* Read in the super block and its summary info.
struct disklabel
*getdisklabel(), *lp
;
# define altsblock asblk.b_un.b_fs
daddr_t super
= bflag
? bflag
* DEV_BSIZE
: SBOFF
;
if (bread(&dfile
, (char *)&sblock
, super
, (long)SBSIZE
) != 0)
* run a few consistency checks of the super block
if (sblock
.fs_magic
!= FS_MAGIC
)
{ badsb(listerr
, "MAGIC NUMBER WRONG"); return (0); }
{ badsb(listerr
, "NCG OUT OF RANGE"); return (0); }
if (sblock
.fs_cpg
< 1 || sblock
.fs_cpg
> MAXCPG
)
{ badsb(listerr
, "CPG OUT OF RANGE"); return (0); }
if (sblock
.fs_ncg
* sblock
.fs_cpg
< sblock
.fs_ncyl
||
(sblock
.fs_ncg
- 1) * sblock
.fs_cpg
>= sblock
.fs_ncyl
)
{ badsb(listerr
, "NCYL LESS THAN NCG*CPG"); return (0); }
if (sblock
.fs_sbsize
> SBSIZE
)
{ badsb(listerr
, "SIZE PREPOSTEROUSLY LARGE"); return (0); }
* Set all possible fields that could differ, then do check
* of whole super block against an alternate super block.
* When an alternate super-block is specified this check is skipped.
dev_bsize
= sblock
.fs_fsize
/ fsbtodb(&sblock
, 1);
if (lp
= getdisklabel((char *)NULL
, dfile
.rfdes
))
sblk
.b_bno
= sblk
.b_bno
/ dev_bsize
;
getblk(&asblk
, cgsblock(&sblock
, sblock
.fs_ncg
- 1), sblock
.fs_sbsize
);
if (asblk
.b_errs
!= NULL
)
altsblock
.fs_fsbtodb
= sblock
.fs_fsbtodb
;
altsblock
.fs_link
= sblock
.fs_link
;
altsblock
.fs_rlink
= sblock
.fs_rlink
;
altsblock
.fs_time
= sblock
.fs_time
;
altsblock
.fs_cstotal
= sblock
.fs_cstotal
;
altsblock
.fs_cgrotor
= sblock
.fs_cgrotor
;
altsblock
.fs_fmod
= sblock
.fs_fmod
;
altsblock
.fs_clean
= sblock
.fs_clean
;
altsblock
.fs_ronly
= sblock
.fs_ronly
;
altsblock
.fs_flags
= sblock
.fs_flags
;
altsblock
.fs_maxcontig
= sblock
.fs_maxcontig
;
altsblock
.fs_minfree
= sblock
.fs_minfree
;
altsblock
.fs_optim
= sblock
.fs_optim
;
altsblock
.fs_rotdelay
= sblock
.fs_rotdelay
;
altsblock
.fs_maxbpg
= sblock
.fs_maxbpg
;
altsblock
.fs_npsect
= sblock
.fs_npsect
;
altsblock
.fs_interleave
= sblock
.fs_interleave
;
bcopy((char *)sblock
.fs_csp
, (char *)altsblock
.fs_csp
,
bcopy((char *)sblock
.fs_fsmnt
, (char *)altsblock
.fs_fsmnt
,
bcopy((char *)sblock
.fs_sparecon
, (char *)altsblock
.fs_sparecon
,
sizeof sblock
.fs_sparecon
);
if (bcmp((char *)&sblock
, (char *)&altsblock
, (int)sblock
.fs_sbsize
)) {
"VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN FIRST ALTERNATE");
pfatal("BAD SUPER BLOCK: %s\n", s
);
* Calculate a prototype superblock based on information in the disk label.
* When done the cgsblock macro can be calculated and the fs_ncg field
* can be used. Do NOT attempt to use other macros without verifying that
* their needed information is available!
register struct disklabel
*lp
;
register struct partition
*pp
;
cp
= index(dev
, '\0') - 1;
if (cp
== (char *)-1 || (*cp
< 'a' || *cp
> 'h') && !isdigit(*cp
)) {
pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev
);
lp
= getdisklabel(dev
, devfd
);
pp
= &lp
->d_partitions
[0];
pp
= &lp
->d_partitions
[*cp
- 'a'];
if (pp
->p_fstype
!= FS_BSDFFS
) {
pfatal("%s: NOT FORMATTED AS A BSD FILE SYSTEM (%s)\n",
dev
, pp
->p_fstype
< FSMAXTYPES
?
fstypenames
[pp
->p_fstype
] : "unknown");
bzero(fs
, sizeof(struct fs
));
fs
->fs_fsize
= pp
->p_fsize
;
fs
->fs_frag
= pp
->p_frag
;
fs
->fs_size
= pp
->p_size
;
fs
->fs_ntrak
= lp
->d_ntracks
;
fs
->fs_nsect
= lp
->d_nsectors
;
fs
->fs_spc
= lp
->d_secpercyl
;
fs
->fs_nspf
= fs
->fs_fsize
/ lp
->d_secsize
;
howmany(lp
->d_bbsize
+ lp
->d_sbsize
, fs
->fs_fsize
),
fs
->fs_cgmask
= 0xffffffff;
for (i
= fs
->fs_ntrak
; i
> 1; i
>>= 1)
if (!POWEROF2(fs
->fs_ntrak
))
fs
->fs_cgoffset
= roundup(
howmany(fs
->fs_nsect
, NSPF(fs
)), fs
->fs_frag
);
fs
->fs_fpg
= (fs
->fs_cpg
* fs
->fs_spc
) / NSPF(fs
);
fs
->fs_ncg
= howmany(fs
->fs_size
/ fs
->fs_spc
, fs
->fs_cpg
);
for (fs
->fs_fsbtodb
= 0, i
= NSPF(fs
); i
> 1; i
>>= 1)
static struct disklabel lab
;
if (ioctl(fd
, DIOCGDINFO
, (char *)&lab
) < 0) {
return ((struct disklabel
*)NULL
);
perror("ioctl (GDINFO)");
errexit("%s: can't read disk label", s
);