1 /* $NetBSD: setup.c,v 1.28 2011/09/16 16:13:18 plunky Exp $ */
4 * Copyright (c) 1980, 1986, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * Copyright (c) 1997 Manuel Bouyer.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
44 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
45 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
46 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
47 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
48 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
49 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
50 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
53 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56 #include <sys/cdefs.h>
59 static char sccsid
[] = "@(#)setup.c 8.5 (Berkeley) 11/23/94";
61 __RCSID("$NetBSD: setup.c,v 1.28 2011/09/16 16:13:18 plunky Exp $");
66 #include <sys/param.h>
68 #include <ufs/ext2fs/ext2fs_dinode.h>
69 #include <ufs/ext2fs/ext2fs.h>
71 #include <sys/ioctl.h>
72 #include <sys/disklabel.h>
84 #include "exitvalues.h"
86 void badsb(int, const char *);
87 int calcsb(const char *, int, struct m_ext2fs
*);
88 static struct disklabel
*getdisklabel(const char *, int);
89 static int readsb(int);
92 setup(const char *dev
)
103 struct m_ext2fs proto
;
105 u_int64_t maxfilesize
;
109 doskipclean
= skipclean
;
110 if (stat(dev
, &statb
) < 0) {
111 printf("Can't stat %s: %s\n", dev
, strerror(errno
));
116 if (!S_ISCHR(statb
.st_mode
)) {
117 pfatal("%s is not a character device", dev
);
118 if (reply("CONTINUE") == 0)
123 if ((fsreadfd
= open(dev
, O_RDONLY
)) < 0) {
124 printf("Can't open %s: %s\n", dev
, strerror(errno
));
128 printf("** %s", dev
);
129 if (nflag
|| (fswritefd
= open(dev
, O_WRONLY
)) < 0) {
132 pfatal("NO WRITE ACCESS");
133 printf(" (NO WRITE)");
141 sblk
.b_un
.b_buf
= malloc(SBSIZE
);
142 asblk
.b_un
.b_buf
= malloc(SBSIZE
);
143 if (sblk
.b_un
.b_buf
== NULL
|| asblk
.b_un
.b_buf
== NULL
)
144 errexit("cannot allocate space for superblock");
145 if ((lp
= getdisklabel(NULL
, fsreadfd
)) != NULL
)
146 dev_bsize
= secsize
= lp
->d_secsize
;
148 dev_bsize
= secsize
= DEV_BSIZE
;
150 * Read in the superblock, looking for alternates if necessary
152 if (readsb(1) == 0) {
153 if (bflag
|| preen
|| calcsb(dev
, fsreadfd
, &proto
) == 0)
155 if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0)
157 for (cg
= 1; cg
< proto
.e2fs_ncg
; cg
++) {
158 bflag
= fsbtodb(&proto
,
159 cg
* proto
.e2fs
.e2fs_bpg
+
160 proto
.e2fs
.e2fs_first_dblock
);
164 if (cg
>= proto
.e2fs_ncg
) {
165 printf("%s %s\n%s %s\n%s %s\n",
166 "SEARCH FOR ALTERNATE SUPER-BLOCK",
167 "FAILED. YOU MUST USE THE",
168 "-b OPTION TO FSCK_FFS TO SPECIFY THE",
169 "LOCATION OF AN ALTERNATE",
170 "SUPER-BLOCK TO SUPPLY NEEDED",
171 "INFORMATION; SEE fsck_ext2fs(8).");
175 pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag
);
178 printf("state = %d\n", sblock
.e2fs
.e2fs_state
);
179 if (sblock
.e2fs
.e2fs_state
== E2FS_ISCLEAN
) {
181 pwarn("%sile system is clean; not checking\n",
182 preen
? "f" : "** F");
186 pwarn("** File system is already clean\n");
188 maxfsblock
= sblock
.e2fs
.e2fs_bcount
;
189 maxino
= sblock
.e2fs_ncg
* sblock
.e2fs
.e2fs_ipg
;
190 sizepb
= sblock
.e2fs_bsize
;
191 maxfilesize
= sblock
.e2fs_bsize
* NDADDR
- 1;
192 for (i
= 0; i
< NIADDR
; i
++) {
193 sizepb
*= NINDIR(&sblock
);
194 maxfilesize
+= sizepb
;
197 * Check and potentially fix certain fields in the super block.
199 if (/* (sblock.e2fs.e2fs_rbcount < 0) || */
200 (sblock
.e2fs
.e2fs_rbcount
> sblock
.e2fs
.e2fs_bcount
)) {
201 pfatal("IMPOSSIBLE RESERVED BLOCK COUNT=%d IN SUPERBLOCK",
202 sblock
.e2fs
.e2fs_rbcount
);
203 if (reply("SET TO DEFAULT") == 1) {
204 sblock
.e2fs
.e2fs_rbcount
=
205 sblock
.e2fs
.e2fs_bcount
* MINFREE
/ 100;
210 if (sblock
.e2fs
.e2fs_bpg
!= sblock
.e2fs
.e2fs_fpg
) {
211 pfatal("WRONG FPG=%d (BPG=%d) IN SUPERBLOCK",
212 sblock
.e2fs
.e2fs_fpg
, sblock
.e2fs
.e2fs_bpg
);
215 if (asblk
.b_dirty
&& !bflag
) {
217 flush(fswritefd
, &asblk
);
220 * read in the summary info.
223 sblock
.e2fs_gd
= malloc(sblock
.e2fs_ngdb
* sblock
.e2fs_bsize
);
224 if (sblock
.e2fs_gd
== NULL
)
225 errexit("out of memory");
227 for (i
= 0; i
< sblock
.e2fs_ngdb
; i
++) {
229 (char *)&sblock
.e2fs_gd
[i
* sblock
.e2fs_bsize
/
230 sizeof(struct ext2_gd
)],
231 fsbtodb(&sblock
, ((sblock
.e2fs_bsize
> 1024) ? 0 : 1) +
233 sblock
.e2fs_bsize
) != 0 && !asked
) {
234 pfatal("BAD SUMMARY INFORMATION");
235 if (reply("CONTINUE") == 0)
236 exit(FSCK_EXIT_CHECK_FAILED
);
241 * allocate and initialize the necessary maps
243 bmapsize
= roundup(howmany(maxfsblock
, NBBY
), sizeof(int16_t));
244 blockmap
= calloc((unsigned int)bmapsize
, sizeof(char));
245 if (blockmap
== NULL
) {
246 printf("cannot alloc %u bytes for blockmap\n",
247 (unsigned int)bmapsize
);
250 statemap
= calloc((unsigned int)(maxino
+ 2), sizeof(char));
251 if (statemap
== NULL
) {
252 printf("cannot alloc %u bytes for statemap\n",
253 (unsigned int)(maxino
+ 1));
256 typemap
= calloc((unsigned int)(maxino
+ 1), sizeof(char));
257 if (typemap
== NULL
) {
258 printf("cannot alloc %u bytes for typemap\n",
259 (unsigned int)(maxino
+ 1));
262 lncntp
= calloc((unsigned)(maxino
+ 1), sizeof(int16_t));
263 if (lncntp
== NULL
) {
264 printf("cannot alloc %u bytes for lncntp\n",
265 (unsigned int)((maxino
+ 1) * sizeof(int16_t)));
268 for (numdirs
= 0, cg
= 0; cg
< sblock
.e2fs_ncg
; cg
++) {
269 numdirs
+= fs2h16(sblock
.e2fs_gd
[cg
].ext2bgd_ndirs
);
272 listmax
= numdirs
+ 10;
273 inpsort
= calloc((unsigned int)listmax
, sizeof(struct inoinfo
*));
274 inphead
= calloc((unsigned int)numdirs
, sizeof(struct inoinfo
*));
275 if (inpsort
== NULL
|| inphead
== NULL
) {
276 printf("cannot alloc %u bytes for inphead\n",
277 (unsigned int)(numdirs
* sizeof(struct inoinfo
*)));
289 * Read in the super block and its summary info, convert to host byte order.
294 daddr_t super
= bflag
? bflag
: SBOFF
/ dev_bsize
;
296 if (bread(fsreadfd
, (char *)sblk
.b_un
.b_fs
, super
, (long)SBSIZE
) != 0)
299 sblk
.b_size
= SBSIZE
;
301 /* Copy the superblock in memory */
302 e2fs_sbload(sblk
.b_un
.b_fs
, &sblock
.e2fs
);
305 * run a few consistency checks of the super block
307 if (sblock
.e2fs
.e2fs_magic
!= E2FS_MAGIC
) {
308 badsb(listerr
, "MAGIC NUMBER WRONG");
311 if (sblock
.e2fs
.e2fs_log_bsize
> 2) {
312 badsb(listerr
, "BAD LOG_BSIZE");
315 if (sblock
.e2fs
.e2fs_rev
> E2FS_REV0
&&
316 (!powerof2(sblock
.e2fs
.e2fs_inode_size
) ||
317 sblock
.e2fs
.e2fs_inode_size
< sizeof(struct ext2fs_dinode
) ||
318 sblock
.e2fs
.e2fs_inode_size
>
319 (1024 << sblock
.e2fs
.e2fs_log_bsize
))) {
320 badsb(listerr
, "BAD INODE_SIZE");
324 /* compute the dynamic fields of the in-memory sb */
325 /* compute dynamic sb infos */
327 howmany(sblock
.e2fs
.e2fs_bcount
- sblock
.e2fs
.e2fs_first_dblock
,
328 sblock
.e2fs
.e2fs_bpg
);
329 /* XXX assume hw bsize = 512 */
330 sblock
.e2fs_fsbtodb
= sblock
.e2fs
.e2fs_log_bsize
+ 1;
331 sblock
.e2fs_bsize
= 1024 << sblock
.e2fs
.e2fs_log_bsize
;
332 sblock
.e2fs_bshift
= LOG_MINBSIZE
+ sblock
.e2fs
.e2fs_log_bsize
;
333 sblock
.e2fs_qbmask
= sblock
.e2fs_bsize
- 1;
334 sblock
.e2fs_bmask
= ~sblock
.e2fs_qbmask
;
335 sblock
.e2fs_ngdb
= howmany(sblock
.e2fs_ncg
,
336 sblock
.e2fs_bsize
/ sizeof(struct ext2_gd
));
337 sblock
.e2fs_ipb
= sblock
.e2fs_bsize
/ EXT2_DINODE_SIZE(&sblock
);
338 sblock
.e2fs_itpg
= howmany(sblock
.e2fs
.e2fs_ipg
, sblock
.e2fs_ipb
);
341 * Compute block size that the filesystem is based on,
342 * according to fsbtodb, and adjust superblock block number
343 * so we can tell if this is an alternate later.
346 dev_bsize
= sblock
.e2fs_bsize
/ fsbtodb(&sblock
, 1);
347 sblk
.b_bno
= super
/ dev_bsize
;
349 if (sblock
.e2fs_ncg
== 1) {
350 /* no alternate superblock; assume it's okay */
354 getblk(&asblk
, 1 * sblock
.e2fs
.e2fs_bpg
+ sblock
.e2fs
.e2fs_first_dblock
,
364 * Set all possible fields that could differ, then do check
365 * of whole super block against an alternate super block.
366 * When an alternate super-block is specified this check is skipped.
368 asblk
.b_un
.b_fs
->e2fs_rbcount
= sblk
.b_un
.b_fs
->e2fs_rbcount
;
369 asblk
.b_un
.b_fs
->e2fs_fbcount
= sblk
.b_un
.b_fs
->e2fs_fbcount
;
370 asblk
.b_un
.b_fs
->e2fs_ficount
= sblk
.b_un
.b_fs
->e2fs_ficount
;
371 asblk
.b_un
.b_fs
->e2fs_mtime
= sblk
.b_un
.b_fs
->e2fs_mtime
;
372 asblk
.b_un
.b_fs
->e2fs_wtime
= sblk
.b_un
.b_fs
->e2fs_wtime
;
373 asblk
.b_un
.b_fs
->e2fs_mnt_count
= sblk
.b_un
.b_fs
->e2fs_mnt_count
;
374 asblk
.b_un
.b_fs
->e2fs_max_mnt_count
=
375 sblk
.b_un
.b_fs
->e2fs_max_mnt_count
;
376 asblk
.b_un
.b_fs
->e2fs_state
= sblk
.b_un
.b_fs
->e2fs_state
;
377 asblk
.b_un
.b_fs
->e2fs_beh
= sblk
.b_un
.b_fs
->e2fs_beh
;
378 asblk
.b_un
.b_fs
->e2fs_lastfsck
= sblk
.b_un
.b_fs
->e2fs_lastfsck
;
379 asblk
.b_un
.b_fs
->e2fs_fsckintv
= sblk
.b_un
.b_fs
->e2fs_fsckintv
;
380 asblk
.b_un
.b_fs
->e2fs_ruid
= sblk
.b_un
.b_fs
->e2fs_ruid
;
381 asblk
.b_un
.b_fs
->e2fs_rgid
= sblk
.b_un
.b_fs
->e2fs_rgid
;
382 asblk
.b_un
.b_fs
->e2fs_block_group_nr
=
383 sblk
.b_un
.b_fs
->e2fs_block_group_nr
;
384 asblk
.b_un
.b_fs
->e2fs_features_rocompat
&= ~EXT2F_ROCOMPAT_LARGEFILE
;
385 asblk
.b_un
.b_fs
->e2fs_features_rocompat
|=
386 sblk
.b_un
.b_fs
->e2fs_features_rocompat
& EXT2F_ROCOMPAT_LARGEFILE
;
387 if (sblock
.e2fs
.e2fs_rev
> E2FS_REV0
&&
388 ((sblock
.e2fs
.e2fs_features_incompat
& ~EXT2F_INCOMPAT_SUPP
) ||
389 (sblock
.e2fs
.e2fs_features_rocompat
& ~EXT2F_ROCOMPAT_SUPP
))) {
391 printf("compat 0x%08x, incompat 0x%08x, compat_ro "
393 sblock
.e2fs
.e2fs_features_compat
,
394 sblock
.e2fs
.e2fs_features_incompat
,
395 sblock
.e2fs
.e2fs_features_rocompat
);
397 badsb(listerr
, "INCOMPATIBLE FEATURE BITS IN SUPER BLOCK");
400 if (memcmp(sblk
.b_un
.b_fs
, asblk
.b_un
.b_fs
, SBSIZE
)) {
402 u_int32_t
*nlp
, *olp
, *endlp
;
404 printf("superblock mismatches\n");
405 nlp
= (u_int32_t
*)asblk
.b_un
.b_fs
;
406 olp
= (u_int32_t
*)sblk
.b_un
.b_fs
;
407 endlp
= olp
+ (SBSIZE
/ sizeof(*olp
));
408 for ( ; olp
< endlp
; olp
++, nlp
++) {
411 printf("offset %ld, original %ld, "
413 (long)(olp
- (u_int32_t
*)sblk
.b_un
.b_fs
),
419 "VALUES IN SUPER BLOCK DISAGREE WITH "
420 "THOSE IN FIRST ALTERNATE");
428 copyback_sb(struct bufarea
*bp
)
430 /* Copy the in-memory superblock back to buffer */
431 bp
->b_un
.b_fs
->e2fs_icount
= h2fs32(sblock
.e2fs
.e2fs_icount
);
432 bp
->b_un
.b_fs
->e2fs_bcount
= h2fs32(sblock
.e2fs
.e2fs_bcount
);
433 bp
->b_un
.b_fs
->e2fs_rbcount
= h2fs32(sblock
.e2fs
.e2fs_rbcount
);
434 bp
->b_un
.b_fs
->e2fs_fbcount
= h2fs32(sblock
.e2fs
.e2fs_fbcount
);
435 bp
->b_un
.b_fs
->e2fs_ficount
= h2fs32(sblock
.e2fs
.e2fs_ficount
);
436 bp
->b_un
.b_fs
->e2fs_first_dblock
=
437 h2fs32(sblock
.e2fs
.e2fs_first_dblock
);
438 bp
->b_un
.b_fs
->e2fs_log_bsize
= h2fs32(sblock
.e2fs
.e2fs_log_bsize
);
439 bp
->b_un
.b_fs
->e2fs_fsize
= h2fs32(sblock
.e2fs
.e2fs_fsize
);
440 bp
->b_un
.b_fs
->e2fs_bpg
= h2fs32(sblock
.e2fs
.e2fs_bpg
);
441 bp
->b_un
.b_fs
->e2fs_fpg
= h2fs32(sblock
.e2fs
.e2fs_fpg
);
442 bp
->b_un
.b_fs
->e2fs_ipg
= h2fs32(sblock
.e2fs
.e2fs_ipg
);
443 bp
->b_un
.b_fs
->e2fs_mtime
= h2fs32(sblock
.e2fs
.e2fs_mtime
);
444 bp
->b_un
.b_fs
->e2fs_wtime
= h2fs32(sblock
.e2fs
.e2fs_wtime
);
445 bp
->b_un
.b_fs
->e2fs_lastfsck
= h2fs32(sblock
.e2fs
.e2fs_lastfsck
);
446 bp
->b_un
.b_fs
->e2fs_fsckintv
= h2fs32(sblock
.e2fs
.e2fs_fsckintv
);
447 bp
->b_un
.b_fs
->e2fs_creator
= h2fs32(sblock
.e2fs
.e2fs_creator
);
448 bp
->b_un
.b_fs
->e2fs_rev
= h2fs32(sblock
.e2fs
.e2fs_rev
);
449 bp
->b_un
.b_fs
->e2fs_mnt_count
= h2fs16(sblock
.e2fs
.e2fs_mnt_count
);
450 bp
->b_un
.b_fs
->e2fs_max_mnt_count
=
451 h2fs16(sblock
.e2fs
.e2fs_max_mnt_count
);
452 bp
->b_un
.b_fs
->e2fs_magic
= h2fs16(sblock
.e2fs
.e2fs_magic
);
453 bp
->b_un
.b_fs
->e2fs_state
= h2fs16(sblock
.e2fs
.e2fs_state
);
454 bp
->b_un
.b_fs
->e2fs_beh
= h2fs16(sblock
.e2fs
.e2fs_beh
);
455 bp
->b_un
.b_fs
->e2fs_ruid
= h2fs16(sblock
.e2fs
.e2fs_ruid
);
456 bp
->b_un
.b_fs
->e2fs_rgid
= h2fs16(sblock
.e2fs
.e2fs_rgid
);
460 badsb(int listerr
, const char *s
)
466 printf("%s: ", cdevname());
467 pfatal("BAD SUPER BLOCK: %s\n", s
);
471 * Calculate a prototype superblock based on information in the disk label.
472 * When done the cgsblock macro can be calculated and the fs_ncg field
473 * can be used. Do NOT attempt to use other macros without verifying that
474 * their needed information is available!
478 calcsb(const char *dev
, int devfd
, struct m_ext2fs
*fs
)
481 errexit("%s: calcsb: can't read disk label under minix", dev
);
483 struct disklabel
*lp
;
484 struct partition
*pp
;
487 cp
= strchr(dev
, '\0');
489 ((*cp
< 'a' || *cp
> 'h') && !isdigit((unsigned char)*cp
))) {
490 pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev
);
493 lp
= getdisklabel(dev
, devfd
);
494 if (isdigit((unsigned char)*cp
))
495 pp
= &lp
->d_partitions
[0];
497 pp
= &lp
->d_partitions
[*cp
- 'a'];
498 if (pp
->p_fstype
!= FS_EX2FS
) {
499 pfatal("%s: NOT LABELED AS A EXT2 FILE SYSTEM (%s)\n",
500 dev
, pp
->p_fstype
< FSMAXTYPES
?
501 fstypenames
[pp
->p_fstype
] : "unknown");
504 memset(fs
, 0, sizeof(struct m_ext2fs
));
505 fs
->e2fs_bsize
= pp
->p_fsize
;
506 fs
->e2fs
.e2fs_log_bsize
= pp
->p_fsize
/ 1024;
507 fs
->e2fs
.e2fs_bcount
= (pp
->p_size
* DEV_BSIZE
) / fs
->e2fs_bsize
;
508 fs
->e2fs
.e2fs_first_dblock
= (fs
->e2fs
.e2fs_log_bsize
== 0) ? 1 : 0;
509 fs
->e2fs
.e2fs_bpg
= fs
->e2fs_bsize
* NBBY
;
510 fs
->e2fs_bshift
= LOG_MINBSIZE
+ fs
->e2fs
.e2fs_log_bsize
;
511 fs
->e2fs_qbmask
= fs
->e2fs_bsize
- 1;
512 fs
->e2fs_bmask
= ~fs
->e2fs_qbmask
;
514 howmany(fs
->e2fs
.e2fs_bcount
- fs
->e2fs
.e2fs_first_dblock
,
516 fs
->e2fs_fsbtodb
= fs
->e2fs
.e2fs_log_bsize
+ 1;
517 fs
->e2fs_ngdb
= howmany(fs
->e2fs_ncg
,
518 fs
->e2fs_bsize
/ sizeof(struct ext2_gd
));
524 static struct disklabel
*
525 getdisklabel(const char *s
, int fd
)
527 static struct disklabel lab
;
532 errexit("%s: can't read disk label under minix", s
);
534 if (ioctl(fd
, DIOCGDINFO
, (char *)&lab
) < 0) {
537 pwarn("ioctl (GCINFO): %s\n", strerror(errno
));
538 errexit("%s: can't read disk label", s
);
549 1 /* block bitmap */ +
550 1 /* inode bitmap */ +
552 if (sblock
.e2fs
.e2fs_rev
> E2FS_REV0
&&
553 sblock
.e2fs
.e2fs_features_rocompat
& EXT2F_ROCOMPAT_SPARSESUPER
) {
554 if (cg_has_sb(c
) == 0)
557 overh
+= 1 /* superblock */ + sblock
.e2fs_ngdb
;