1 /* $NetBSD: setup.c,v 1.32 2014/12/04 01:41:37 christos 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.32 2014/12/04 01:41:37 christos 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
)
99 struct m_ext2fs proto
;
101 u_int64_t maxfilesize
;
105 doskipclean
= skipclean
;
106 if (stat(dev
, &statb
) < 0) {
107 printf("Can't stat %s: %s\n", dev
, strerror(errno
));
110 #if !defined(__minix)
111 if (!S_ISCHR(statb
.st_mode
)) {
112 pfatal("%s is not a character device", dev
);
113 if (reply("CONTINUE") == 0)
116 #endif /* !defined(__minix) */
117 if ((fsreadfd
= open(dev
, O_RDONLY
)) < 0) {
118 printf("Can't open %s: %s\n", dev
, strerror(errno
));
122 printf("** %s", dev
);
123 if (nflag
|| (fswritefd
= open(dev
, O_WRONLY
)) < 0) {
126 pfatal("NO WRITE ACCESS");
127 printf(" (NO WRITE)");
135 sblk
.b_un
.b_buf
= malloc(SBSIZE
);
136 asblk
.b_un
.b_buf
= malloc(SBSIZE
);
137 if (sblk
.b_un
.b_buf
== NULL
|| asblk
.b_un
.b_buf
== NULL
)
138 errexit("cannot allocate space for superblock");
139 if ((lp
= getdisklabel(NULL
, fsreadfd
)) != NULL
)
140 dev_bsize
= secsize
= lp
->d_secsize
;
142 dev_bsize
= secsize
= DEV_BSIZE
;
144 * Read in the superblock, looking for alternates if necessary
146 if (readsb(1) == 0) {
147 if (bflag
|| preen
|| calcsb(dev
, fsreadfd
, &proto
) == 0)
149 if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0)
151 for (cg
= 1; cg
< proto
.e2fs_ncg
; cg
++) {
152 bflag
= EXT2_FSBTODB(&proto
,
153 cg
* proto
.e2fs
.e2fs_bpg
+
154 proto
.e2fs
.e2fs_first_dblock
);
158 if (cg
>= proto
.e2fs_ncg
) {
159 printf("%s %s\n%s %s\n%s %s\n",
160 "SEARCH FOR ALTERNATE SUPER-BLOCK",
161 "FAILED. YOU MUST USE THE",
162 "-b OPTION TO FSCK_FFS TO SPECIFY THE",
163 "LOCATION OF AN ALTERNATE",
164 "SUPER-BLOCK TO SUPPLY NEEDED",
165 "INFORMATION; SEE fsck_ext2fs(8).");
169 pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag
);
172 printf("state = %d\n", sblock
.e2fs
.e2fs_state
);
173 if (sblock
.e2fs
.e2fs_state
== E2FS_ISCLEAN
) {
175 pwarn("%sile system is clean; not checking\n",
176 preen
? "f" : "** F");
180 pwarn("** File system is already clean\n");
182 maxfsblock
= sblock
.e2fs
.e2fs_bcount
;
183 maxino
= sblock
.e2fs_ncg
* sblock
.e2fs
.e2fs_ipg
;
184 sizepb
= sblock
.e2fs_bsize
;
185 maxfilesize
= sblock
.e2fs_bsize
* EXT2FS_NDADDR
- 1;
186 for (i
= 0; i
< EXT2FS_NIADDR
; i
++) {
187 sizepb
*= EXT2_NINDIR(&sblock
);
188 maxfilesize
+= sizepb
;
191 * Check and potentially fix certain fields in the super block.
193 if (/* (sblock.e2fs.e2fs_rbcount < 0) || */
194 (sblock
.e2fs
.e2fs_rbcount
> sblock
.e2fs
.e2fs_bcount
)) {
195 pfatal("IMPOSSIBLE RESERVED BLOCK COUNT=%d IN SUPERBLOCK",
196 sblock
.e2fs
.e2fs_rbcount
);
197 if (reply("SET TO DEFAULT") == 1) {
198 sblock
.e2fs
.e2fs_rbcount
=
199 sblock
.e2fs
.e2fs_bcount
* MINFREE
/ 100;
204 if (sblock
.e2fs
.e2fs_bpg
!= sblock
.e2fs
.e2fs_fpg
) {
205 pfatal("WRONG FPG=%d (BPG=%d) IN SUPERBLOCK",
206 sblock
.e2fs
.e2fs_fpg
, sblock
.e2fs
.e2fs_bpg
);
209 if (asblk
.b_dirty
&& !bflag
) {
211 flush(fswritefd
, &asblk
);
214 * read in the summary info.
217 sblock
.e2fs_gd
= malloc(sblock
.e2fs_ngdb
* sblock
.e2fs_bsize
);
218 if (sblock
.e2fs_gd
== NULL
)
219 errexit("out of memory");
221 for (i
= 0; i
< sblock
.e2fs_ngdb
; i
++) {
223 (char *)&sblock
.e2fs_gd
[i
* sblock
.e2fs_bsize
/
224 sizeof(struct ext2_gd
)],
225 EXT2_FSBTODB(&sblock
, ((sblock
.e2fs_bsize
> 1024) ? 0 : 1) +
227 sblock
.e2fs_bsize
) != 0 && !asked
) {
228 pfatal("BAD SUMMARY INFORMATION");
229 if (reply("CONTINUE") == 0)
230 exit(FSCK_EXIT_CHECK_FAILED
);
235 * allocate and initialize the necessary maps
237 bmapsize
= roundup(howmany(maxfsblock
, NBBY
), sizeof(int16_t));
238 blockmap
= calloc((unsigned int)bmapsize
, sizeof(char));
239 if (blockmap
== NULL
) {
240 printf("cannot alloc %u bytes for blockmap\n",
241 (unsigned int)bmapsize
);
244 statemap
= calloc((unsigned int)(maxino
+ 2), sizeof(char));
245 if (statemap
== NULL
) {
246 printf("cannot alloc %u bytes for statemap\n",
247 (unsigned int)(maxino
+ 1));
250 typemap
= calloc((unsigned int)(maxino
+ 1), sizeof(char));
251 if (typemap
== NULL
) {
252 printf("cannot alloc %u bytes for typemap\n",
253 (unsigned int)(maxino
+ 1));
256 lncntp
= calloc((unsigned)(maxino
+ 1), sizeof(int16_t));
257 if (lncntp
== NULL
) {
258 printf("cannot alloc %u bytes for lncntp\n",
259 (unsigned int)((maxino
+ 1) * sizeof(int16_t)));
262 for (numdirs
= 0, cg
= 0; cg
< sblock
.e2fs_ncg
; cg
++) {
263 numdirs
+= fs2h16(sblock
.e2fs_gd
[cg
].ext2bgd_ndirs
);
266 listmax
= numdirs
+ 10;
267 inpsort
= calloc((unsigned int)listmax
, sizeof(struct inoinfo
*));
268 inphead
= calloc((unsigned int)numdirs
, sizeof(struct inoinfo
*));
269 if (inpsort
== NULL
|| inphead
== NULL
) {
270 printf("cannot alloc %u bytes for inphead\n",
271 (unsigned int)(numdirs
* sizeof(struct inoinfo
*)));
283 * Read in the super block and its summary info, convert to host byte order.
288 daddr_t super
= bflag
? bflag
: SBOFF
/ dev_bsize
;
290 if (bread(fsreadfd
, (char *)sblk
.b_un
.b_fs
, super
, (long)SBSIZE
) != 0)
293 sblk
.b_size
= SBSIZE
;
295 /* Copy the superblock in memory */
296 e2fs_sbload(sblk
.b_un
.b_fs
, &sblock
.e2fs
);
299 * run a few consistency checks of the super block
301 if (sblock
.e2fs
.e2fs_magic
!= E2FS_MAGIC
) {
302 badsb(listerr
, "MAGIC NUMBER WRONG");
305 if (sblock
.e2fs
.e2fs_log_bsize
> 2) {
306 badsb(listerr
, "BAD LOG_BSIZE");
309 if (sblock
.e2fs
.e2fs_rev
> E2FS_REV0
&&
310 (!powerof2(sblock
.e2fs
.e2fs_inode_size
) ||
311 sblock
.e2fs
.e2fs_inode_size
< sizeof(struct ext2fs_dinode
) ||
312 sblock
.e2fs
.e2fs_inode_size
>
313 (1024 << sblock
.e2fs
.e2fs_log_bsize
))) {
314 badsb(listerr
, "BAD INODE_SIZE");
318 /* compute the dynamic fields of the in-memory sb */
319 /* compute dynamic sb infos */
321 howmany(sblock
.e2fs
.e2fs_bcount
- sblock
.e2fs
.e2fs_first_dblock
,
322 sblock
.e2fs
.e2fs_bpg
);
323 /* XXX assume hw bsize = 512 */
324 sblock
.e2fs_fsbtodb
= sblock
.e2fs
.e2fs_log_bsize
+ 1;
325 sblock
.e2fs_bsize
= 1024 << sblock
.e2fs
.e2fs_log_bsize
;
326 sblock
.e2fs_bshift
= LOG_MINBSIZE
+ sblock
.e2fs
.e2fs_log_bsize
;
327 sblock
.e2fs_qbmask
= sblock
.e2fs_bsize
- 1;
328 sblock
.e2fs_bmask
= ~sblock
.e2fs_qbmask
;
329 sblock
.e2fs_ngdb
= howmany(sblock
.e2fs_ncg
,
330 sblock
.e2fs_bsize
/ sizeof(struct ext2_gd
));
331 sblock
.e2fs_ipb
= sblock
.e2fs_bsize
/ EXT2_DINODE_SIZE(&sblock
);
332 sblock
.e2fs_itpg
= howmany(sblock
.e2fs
.e2fs_ipg
, sblock
.e2fs_ipb
);
335 * Compute block size that the filesystem is based on,
336 * according to fsbtodb, and adjust superblock block number
337 * so we can tell if this is an alternate later.
340 dev_bsize
= sblock
.e2fs_bsize
/ EXT2_FSBTODB(&sblock
, 1);
341 sblk
.b_bno
= super
/ dev_bsize
;
343 if (sblock
.e2fs_ncg
== 1) {
344 /* no alternate superblock; assume it's okay */
348 getblk(&asblk
, 1 * sblock
.e2fs
.e2fs_bpg
+ sblock
.e2fs
.e2fs_first_dblock
,
358 * Set all possible fields that could differ, then do check
359 * of whole super block against an alternate super block.
360 * When an alternate super-block is specified this check is skipped.
362 asblk
.b_un
.b_fs
->e2fs_rbcount
= sblk
.b_un
.b_fs
->e2fs_rbcount
;
363 asblk
.b_un
.b_fs
->e2fs_fbcount
= sblk
.b_un
.b_fs
->e2fs_fbcount
;
364 asblk
.b_un
.b_fs
->e2fs_ficount
= sblk
.b_un
.b_fs
->e2fs_ficount
;
365 asblk
.b_un
.b_fs
->e2fs_mtime
= sblk
.b_un
.b_fs
->e2fs_mtime
;
366 asblk
.b_un
.b_fs
->e2fs_wtime
= sblk
.b_un
.b_fs
->e2fs_wtime
;
367 asblk
.b_un
.b_fs
->e2fs_mnt_count
= sblk
.b_un
.b_fs
->e2fs_mnt_count
;
368 asblk
.b_un
.b_fs
->e2fs_max_mnt_count
=
369 sblk
.b_un
.b_fs
->e2fs_max_mnt_count
;
370 asblk
.b_un
.b_fs
->e2fs_state
= sblk
.b_un
.b_fs
->e2fs_state
;
371 asblk
.b_un
.b_fs
->e2fs_beh
= sblk
.b_un
.b_fs
->e2fs_beh
;
372 asblk
.b_un
.b_fs
->e2fs_lastfsck
= sblk
.b_un
.b_fs
->e2fs_lastfsck
;
373 asblk
.b_un
.b_fs
->e2fs_fsckintv
= sblk
.b_un
.b_fs
->e2fs_fsckintv
;
374 asblk
.b_un
.b_fs
->e2fs_ruid
= sblk
.b_un
.b_fs
->e2fs_ruid
;
375 asblk
.b_un
.b_fs
->e2fs_rgid
= sblk
.b_un
.b_fs
->e2fs_rgid
;
376 asblk
.b_un
.b_fs
->e2fs_block_group_nr
=
377 sblk
.b_un
.b_fs
->e2fs_block_group_nr
;
378 asblk
.b_un
.b_fs
->e2fs_features_rocompat
&= ~EXT2F_ROCOMPAT_LARGEFILE
;
379 asblk
.b_un
.b_fs
->e2fs_features_rocompat
|=
380 sblk
.b_un
.b_fs
->e2fs_features_rocompat
& EXT2F_ROCOMPAT_LARGEFILE
;
381 if (sblock
.e2fs
.e2fs_rev
> E2FS_REV0
&&
382 ((sblock
.e2fs
.e2fs_features_incompat
& ~EXT2F_INCOMPAT_SUPP
) ||
383 (sblock
.e2fs
.e2fs_features_rocompat
& ~EXT2F_ROCOMPAT_SUPP
))) {
385 printf("compat 0x%08x, incompat 0x%08x, compat_ro "
387 sblock
.e2fs
.e2fs_features_compat
,
388 sblock
.e2fs
.e2fs_features_incompat
,
389 sblock
.e2fs
.e2fs_features_rocompat
);
391 badsb(listerr
, "INCOMPATIBLE FEATURE BITS IN SUPER BLOCK");
394 if (memcmp(sblk
.b_un
.b_fs
, asblk
.b_un
.b_fs
, SBSIZE
)) {
396 u_int32_t
*nlp
, *olp
, *endlp
;
398 printf("superblock mismatches\n");
399 nlp
= (u_int32_t
*)asblk
.b_un
.b_fs
;
400 olp
= (u_int32_t
*)sblk
.b_un
.b_fs
;
401 endlp
= olp
+ (SBSIZE
/ sizeof(*olp
));
402 for ( ; olp
< endlp
; olp
++, nlp
++) {
405 printf("offset %ld, original %ld, "
407 (long)(olp
- (u_int32_t
*)sblk
.b_un
.b_fs
),
413 "VALUES IN SUPER BLOCK DISAGREE WITH "
414 "THOSE IN FIRST ALTERNATE");
422 copyback_sb(struct bufarea
*bp
)
424 /* Copy the in-memory superblock back to buffer */
425 bp
->b_un
.b_fs
->e2fs_icount
= h2fs32(sblock
.e2fs
.e2fs_icount
);
426 bp
->b_un
.b_fs
->e2fs_bcount
= h2fs32(sblock
.e2fs
.e2fs_bcount
);
427 bp
->b_un
.b_fs
->e2fs_rbcount
= h2fs32(sblock
.e2fs
.e2fs_rbcount
);
428 bp
->b_un
.b_fs
->e2fs_fbcount
= h2fs32(sblock
.e2fs
.e2fs_fbcount
);
429 bp
->b_un
.b_fs
->e2fs_ficount
= h2fs32(sblock
.e2fs
.e2fs_ficount
);
430 bp
->b_un
.b_fs
->e2fs_first_dblock
=
431 h2fs32(sblock
.e2fs
.e2fs_first_dblock
);
432 bp
->b_un
.b_fs
->e2fs_log_bsize
= h2fs32(sblock
.e2fs
.e2fs_log_bsize
);
433 bp
->b_un
.b_fs
->e2fs_fsize
= h2fs32(sblock
.e2fs
.e2fs_fsize
);
434 bp
->b_un
.b_fs
->e2fs_bpg
= h2fs32(sblock
.e2fs
.e2fs_bpg
);
435 bp
->b_un
.b_fs
->e2fs_fpg
= h2fs32(sblock
.e2fs
.e2fs_fpg
);
436 bp
->b_un
.b_fs
->e2fs_ipg
= h2fs32(sblock
.e2fs
.e2fs_ipg
);
437 bp
->b_un
.b_fs
->e2fs_mtime
= h2fs32(sblock
.e2fs
.e2fs_mtime
);
438 bp
->b_un
.b_fs
->e2fs_wtime
= h2fs32(sblock
.e2fs
.e2fs_wtime
);
439 bp
->b_un
.b_fs
->e2fs_lastfsck
= h2fs32(sblock
.e2fs
.e2fs_lastfsck
);
440 bp
->b_un
.b_fs
->e2fs_fsckintv
= h2fs32(sblock
.e2fs
.e2fs_fsckintv
);
441 bp
->b_un
.b_fs
->e2fs_creator
= h2fs32(sblock
.e2fs
.e2fs_creator
);
442 bp
->b_un
.b_fs
->e2fs_rev
= h2fs32(sblock
.e2fs
.e2fs_rev
);
443 bp
->b_un
.b_fs
->e2fs_mnt_count
= h2fs16(sblock
.e2fs
.e2fs_mnt_count
);
444 bp
->b_un
.b_fs
->e2fs_max_mnt_count
=
445 h2fs16(sblock
.e2fs
.e2fs_max_mnt_count
);
446 bp
->b_un
.b_fs
->e2fs_magic
= h2fs16(sblock
.e2fs
.e2fs_magic
);
447 bp
->b_un
.b_fs
->e2fs_state
= h2fs16(sblock
.e2fs
.e2fs_state
);
448 bp
->b_un
.b_fs
->e2fs_beh
= h2fs16(sblock
.e2fs
.e2fs_beh
);
449 bp
->b_un
.b_fs
->e2fs_ruid
= h2fs16(sblock
.e2fs
.e2fs_ruid
);
450 bp
->b_un
.b_fs
->e2fs_rgid
= h2fs16(sblock
.e2fs
.e2fs_rgid
);
454 badsb(int listerr
, const char *s
)
460 printf("%s: ", cdevname());
461 pfatal("BAD SUPER BLOCK: %s\n", s
);
465 * Calculate a prototype superblock based on information in the disk label.
466 * When done the cgsblock macro can be calculated and the fs_ncg field
467 * can be used. Do NOT attempt to use other macros without verifying that
468 * their needed information is available!
472 calcsb(const char *dev
, int devfd
, struct m_ext2fs
*fs
)
475 errexit("%s: calcsb: can't read disk label under minix", dev
);
477 struct disklabel
*lp
;
478 struct partition
*pp
;
481 cp
= strchr(dev
, '\0');
483 ((*cp
< 'a' || *cp
> 'h') && !isdigit((unsigned char)*cp
))) {
484 pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev
);
487 lp
= getdisklabel(dev
, devfd
);
488 if (isdigit((unsigned char)*cp
))
489 pp
= &lp
->d_partitions
[0];
491 pp
= &lp
->d_partitions
[*cp
- 'a'];
492 if (pp
->p_fstype
!= FS_EX2FS
) {
493 pfatal("%s: NOT LABELED AS A EXT2 FILE SYSTEM (%s)\n",
494 dev
, pp
->p_fstype
< FSMAXTYPES
?
495 fstypenames
[pp
->p_fstype
] : "unknown");
498 if (pp
->p_fsize
== 0) {
499 pfatal("%s: PARTITION SIZE IS 0\n", dev
);
502 memset(fs
, 0, sizeof(struct m_ext2fs
));
503 fs
->e2fs_bsize
= pp
->p_fsize
;
504 fs
->e2fs
.e2fs_log_bsize
= pp
->p_fsize
/ 1024;
505 fs
->e2fs
.e2fs_bcount
= (pp
->p_size
* DEV_BSIZE
) / fs
->e2fs_bsize
;
506 fs
->e2fs
.e2fs_first_dblock
= (fs
->e2fs
.e2fs_log_bsize
== 0) ? 1 : 0;
507 fs
->e2fs
.e2fs_bpg
= fs
->e2fs_bsize
* NBBY
;
508 fs
->e2fs_bshift
= LOG_MINBSIZE
+ fs
->e2fs
.e2fs_log_bsize
;
509 fs
->e2fs_qbmask
= fs
->e2fs_bsize
- 1;
510 fs
->e2fs_bmask
= ~fs
->e2fs_qbmask
;
512 howmany(fs
->e2fs
.e2fs_bcount
- fs
->e2fs
.e2fs_first_dblock
,
514 fs
->e2fs_fsbtodb
= fs
->e2fs
.e2fs_log_bsize
+ 1;
515 fs
->e2fs_ngdb
= howmany(fs
->e2fs_ncg
,
516 fs
->e2fs_bsize
/ sizeof(struct ext2_gd
));
519 #endif /* defined(__minix) */
522 static struct disklabel
*
523 getdisklabel(const char *s
, int fd
)
525 static struct disklabel lab
;
530 errexit("%s: can't read disk label under minix", s
);
532 if (ioctl(fd
, DIOCGDINFO
, (char *)&lab
) < 0) {
535 pwarn("ioctl (GCINFO): %s\n", strerror(errno
));
536 errexit("%s: can't read disk label", s
);
538 #endif /* defined(__minix) */
547 1 /* block bitmap */ +
548 1 /* inode bitmap */ +
550 if (sblock
.e2fs
.e2fs_rev
> E2FS_REV0
&&
551 sblock
.e2fs
.e2fs_features_rocompat
& EXT2F_ROCOMPAT_SPARSESUPER
) {
552 if (cg_has_sb(c
) == 0)
555 overh
+= 1 /* superblock */ + sblock
.e2fs_ngdb
;