* Copyright (c) 1980, 1986, 1993
* The Regents of the University of California. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
static char sccsid
[] = "@(#)setup.c 8.2 (Berkeley) 2/21/94";
#include <ufs/ufs/dinode.h>
#include <sys/disklabel.h>
#define altsblock (*asblk.b_un.b_fs)
#define POWEROF2(num) (((num) & ((num) - 1)) == 0)
struct disklabel
*getdisklabel();
long cg
, size
, asked
, i
, j
;
if (stat(dev
, &statb
) < 0) {
printf("Can't stat %s: %s\n", dev
, strerror(errno
));
if ((statb
.st_mode
& S_IFMT
) != S_IFCHR
) {
pfatal("%s is not a character device", dev
);
if (reply("CONTINUE") == 0)
if ((fsreadfd
= open(dev
, O_RDONLY
)) < 0) {
printf("Can't open %s: %s\n", dev
, strerror(errno
));
if (nflag
|| (fswritefd
= open(dev
, O_WRONLY
)) < 0) {
pfatal("NO WRITE ACCESS");
sblk
.b_un
.b_buf
= malloc(SBSIZE
);
asblk
.b_un
.b_buf
= malloc(SBSIZE
);
if (sblk
.b_un
.b_buf
== NULL
|| asblk
.b_un
.b_buf
== NULL
)
errexit("cannot allocate space for superblock\n");
if (lp
= getdisklabel((char *)NULL
, fsreadfd
))
dev_bsize
= secsize
= lp
->d_secsize
;
dev_bsize
= secsize
= DEV_BSIZE
;
* Read in the superblock, looking for alternates if necessary
if (bflag
|| preen
|| calcsb(dev
, fsreadfd
, &proto
) == 0)
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
);
maxfsblock
= sblock
.fs_size
;
maxino
= 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
> sblock
.fs_nsect
) {
pwarn("IMPOSSIBLE INTERLEAVE=%d IN SUPERBLOCK",
sblock
.fs_interleave
= 1;
if (preen
|| reply("SET TO DEFAULT") == 1) {
if (sblock
.fs_npsect
< sblock
.fs_nsect
||
sblock
.fs_npsect
> sblock
.fs_nsect
*2) {
pwarn("IMPOSSIBLE NPSECT=%d IN SUPERBLOCK",
sblock
.fs_npsect
= sblock
.fs_nsect
;
if (preen
|| reply("SET TO DEFAULT") == 1) {
if (sblock
.fs_inodefmt
>= FS_44INODEFMT
) {
sblock
.fs_qbmask
= ~sblock
.fs_bmask
;
sblock
.fs_qfmask
= ~sblock
.fs_fmask
;
* Convert to new inode format.
if (cvtlevel
>= 2 && sblock
.fs_inodefmt
< FS_44INODEFMT
) {
pwarn("CONVERTING TO NEW INODE FORMAT\n");
else if (!reply("CONVERT TO NEW INODE FORMAT"))
sblock
.fs_inodefmt
= FS_44INODEFMT
;
sizepb
= sblock
.fs_bsize
;
sblock
.fs_maxfilesize
= sblock
.fs_bsize
* NDADDR
- 1;
for (i
= 0; i
< NIADDR
; i
++) {
sizepb
*= NINDIR(&sblock
);
sblock
.fs_maxfilesize
+= sizepb
;
sblock
.fs_maxsymlinklen
= MAXSYMLINKLEN
;
sblock
.fs_qbmask
= ~sblock
.fs_bmask
;
sblock
.fs_qfmask
= ~sblock
.fs_fmask
;
* Convert to new cylinder group format.
if (cvtlevel
>= 1 && sblock
.fs_postblformat
== FS_42POSTBLFMT
) {
pwarn("CONVERTING TO NEW CYLINDER GROUP FORMAT\n");
else if (!reply("CONVERT TO NEW CYLINDER GROUP FORMAT"))
sblock
.fs_postblformat
= FS_DYNAMICPOSTBLFMT
;
(char *)(&sblock
.fs_opostbl
[0][0]) -
(char *)(&sblock
.fs_link
);
sblock
.fs_rotbloff
= &sblock
.fs_space
[0] -
(u_char
*)(&sblock
.fs_link
);
fragroundup(&sblock
, CGSIZE(&sblock
));
bcopy((char *)&sblock
, (char *)&altsblock
,
(size_t)sblock
.fs_sbsize
);
flush(fswritefd
, &asblk
);
* 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(fsreadfd
, (char *)sblock
.fs_csp
[j
],
fsbtodb(&sblock
, sblock
.fs_csaddr
+ j
* sblock
.fs_frag
),
pfatal("BAD SUMMARY INFORMATION");
if (reply("CONTINUE") == 0)
* allocate and initialize the necessary maps
bmapsize
= roundup(howmany(maxfsblock
, NBBY
), sizeof(short));
blockmap
= calloc((unsigned)bmapsize
, sizeof (char));
printf("cannot alloc %u bytes for blockmap\n",
statemap
= calloc((unsigned)(maxino
+ 1), sizeof(char));
printf("cannot alloc %u bytes for statemap\n",
typemap
= calloc((unsigned)(maxino
+ 1), sizeof(char));
printf("cannot alloc %u bytes for typemap\n",
lncntp
= (short *)calloc((unsigned)(maxino
+ 1), sizeof(short));
printf("cannot alloc %u bytes for lncntp\n",
(unsigned)(maxino
+ 1) * sizeof(short));
numdirs
= sblock
.fs_cstotal
.cs_ndir
;
inpsort
= (struct inoinfo
**)calloc((unsigned)listmax
,
sizeof(struct inoinfo
*));
inphead
= (struct inoinfo
**)calloc((unsigned)numdirs
,
sizeof(struct inoinfo
*));
if (inpsort
== NULL
|| inphead
== NULL
) {
printf("cannot alloc %u bytes for inphead\n",
(unsigned)numdirs
* sizeof(struct inoinfo
*));
* Read in the super block and its summary info.
daddr_t super
= bflag
? bflag
: SBOFF
/ dev_bsize
;
if (bread(fsreadfd
, (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); }
{ 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); }
* Compute block size that the filesystem is based on,
* according to fsbtodb, and adjust superblock block number
* so we can tell if this is an alternate later.
dev_bsize
= sblock
.fs_fsize
/ fsbtodb(&sblock
, 1);
sblk
.b_bno
= super
/ dev_bsize
;
* 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.
getblk(&asblk
, cgsblock(&sblock
, sblock
.fs_ncg
- 1), sblock
.fs_sbsize
);
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
;
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
);
* The following should not have to be copied.
altsblock
.fs_fsbtodb
= sblock
.fs_fsbtodb
;
altsblock
.fs_interleave
= sblock
.fs_interleave
;
altsblock
.fs_npsect
= sblock
.fs_npsect
;
altsblock
.fs_nrpos
= sblock
.fs_nrpos
;
altsblock
.fs_qbmask
= sblock
.fs_qbmask
;
altsblock
.fs_qfmask
= sblock
.fs_qfmask
;
altsblock
.fs_state
= sblock
.fs_state
;
altsblock
.fs_maxfilesize
= sblock
.fs_maxfilesize
;
if (bcmp((char *)&sblock
, (char *)&altsblock
, (int)sblock
.fs_sbsize
)) {
"VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN FIRST ALTERNATE");
printf("%s: ", cdevname
);
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 LABELED AS A BSD FILE SYSTEM (%s)\n",
dev
, pp
->p_fstype
< FSMAXTYPES
?
fstypenames
[pp
->p_fstype
] : "unknown");
bzero((char *)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)
dev_bsize
= lp
->d_secsize
;
static struct disklabel lab
;
if (ioctl(fd
, DIOCGDINFO
, (char *)&lab
) < 0) {
return ((struct disklabel
*)NULL
);
pwarn("ioctl (GCINFO): %s\n", strerror(errno
));
errexit("%s: can't read disk label\n", s
);