2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
7 /* All Rights Reserved */
10 * Copyright (c) 1980, 1986, 1990 The Regents of the University of California.
11 * All rights reserved.
13 * Redistribution and use in source and binary forms are permitted
14 * provided that: (1) source distributions retain this entire copyright
15 * notice and comment, and (2) distributions including binaries display
16 * the following acknowledgement: ``This product includes software
17 * developed by the University of California, Berkeley and its contributors''
18 * in the documentation or other materials provided with the distribution
19 * and in all advertising materials mentioning features or use of this
20 * software. Neither the name of the University nor the names of its
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
35 #include <sys/param.h>
36 #include <sys/types.h>
37 #include <sys/sysmacros.h>
38 #include <sys/mntent.h>
39 #include <sys/mnttab.h>
41 #include <sys/filio.h>
42 #include <sys/isa_defs.h> /* for ENDIAN defines */
43 #include <sys/int_const.h>
44 #include <sys/vnode.h>
47 #include <sys/fcntl.h>
49 #include <sys/vfstab.h>
50 #include <sys/fs/udf_volume.h>
56 extern void errexit(char *, ...);
57 extern int32_t mounted(char *);
58 extern void pwarn(char *, ...);
59 extern void pfatal(char *, ...);
60 extern void printclean();
61 extern void bufinit();
63 extern int32_t bread(int32_t, char *, daddr_t
, long);
64 extern int32_t reply(char *);
66 static int32_t readvolseq(int32_t);
67 static uint32_t get_last_block();
68 extern int32_t verifytag(struct tag
*, uint32_t, struct tag
*, int);
69 extern char *tagerrs
[];
71 #define POWEROF2(num) (((num) & ((num) - 1)) == 0)
76 char avdbuf
[MAXBSIZE
]; /* buffer for anchor volume descriptor */
77 char *main_vdbuf
; /* buffer for entire main volume sequence */
78 char *res_vdbuf
; /* buffer for reserved volume sequence */
79 int serialnum
= -1; /* set from primary volume descriptor */
86 static char devstr
[MAXPATHLEN
];
87 char *raw
, *rawname(), *unrawname();
91 if (stat("/", &statb
) < 0)
92 errexit(gettext("Can't stat root\n"));
93 rootdev
= statb
.st_dev
;
96 (void) strncpy(devstr
, dev
, sizeof (devstr
));
98 if (stat(devstr
, &statb
) < 0) {
99 (void) printf(gettext("Can't stat %s\n"), devstr
);
104 * A mount point is specified. But the mount point doesn't
105 * match entries in the /etc/vfstab.
106 * Search mnttab, because if the fs is error locked, it is
107 * allowed to be fsck'd while mounted.
109 if ((statb
.st_mode
& S_IFMT
) == S_IFDIR
) {
110 (void) printf(gettext("%s is not a block or "
111 "character device\n"), dev
);
115 if ((statb
.st_mode
& S_IFMT
) == S_IFBLK
) {
116 if (rootdev
== statb
.st_rdev
)
118 else if (ustat(statb
.st_rdev
, &ustatb
) == 0) {
119 (void) printf(gettext("%s is a mounted file system, "
125 if ((statb
.st_mode
& S_IFMT
) == S_IFDIR
) {
127 struct vfstab vfsbuf
;
129 * Check vfstab for a mount point with this name
131 if ((vfstab
= fopen(VFSTAB
, "r")) == NULL
) {
132 errexit(gettext("Can't open checklist file: %s\n"),
135 while (getvfsent(vfstab
, &vfsbuf
) == 0) {
136 if (strcmp(devstr
, vfsbuf
.vfs_mountp
) == 0) {
137 if (strcmp(vfsbuf
.vfs_fstype
,
138 MNTTYPE_UDFS
) != 0) {
140 * found the entry but it is not a
141 * udfs filesystem, don't check it
143 (void) fclose(vfstab
);
146 (void) strcpy(devstr
, vfsbuf
.vfs_special
);
149 unrawname(vfsbuf
.vfs_special
));
150 (void) strcpy(devstr
, raw
);
155 (void) fclose(vfstab
);
157 } else if (((statb
.st_mode
& S_IFMT
) != S_IFBLK
) &&
158 ((statb
.st_mode
& S_IFMT
) != S_IFCHR
)) {
160 pwarn(gettext("file is not a block or "
161 "character device.\n"));
162 else if (reply(gettext("file is not a block or "
163 "character device; OK"))
167 * To fsck regular files (fs images)
168 * we need to clear the rflag since
169 * regular files don't have raw names. --CW
174 if (mounted(devstr
)) {
178 (void) printf(gettext("%s is mounted, fsck on BLOCK "
179 "device ignored\n"), devstr
);
182 sync(); /* call sync, only when devstr's mounted */
185 char blockname
[MAXPATHLEN
];
187 * For root device check, must check
190 (void) strcpy(blockname
, devstr
);
191 if (stat(unrawname(blockname
), &statb
) < 0) {
192 (void) printf(gettext("Can't stat %s\n"), blockname
);
197 if (rootdev
== statb
.st_rdev
)
199 if ((fsreadfd
= open(devstr
, O_RDONLY
)) < 0) {
200 (void) printf(gettext("Can't open %s\n"), devstr
);
204 if (preen
== 0 || debug
!= 0)
205 (void) printf("** %s", devstr
);
207 if (nflag
|| (fswritefd
= open(devstr
, O_WRONLY
)) < 0) {
210 pfatal(gettext("(NO WRITE ACCESS)\n"));
211 (void) printf(gettext(" (NO WRITE)"));
215 if (debug
&& (hotroot
|| mountedfs
)) {
216 (void) printf("** %s", devstr
);
218 (void) printf(" is root fs%s",
219 mountedfs
? " and": "");
221 (void) printf(" is mounted");
223 (void) printf(".\n");
226 if (readvolseq(1) == 0)
228 if (fflag
== 0 && preen
&&
229 lvintp
->lvid_int_type
== LVI_CLOSE
) {
235 inphash
= (struct fileinfo
**)calloc(FEGROW
,
236 sizeof (struct fileinfo
*));
237 inphead
= (struct fileinfo
*)calloc(FEGROW
+ 1,
238 sizeof (struct fileinfo
));
239 if (inphead
== NULL
|| inphash
== NULL
) {
240 (void) printf(gettext("cannot alloc %ld bytes for inphead\n"),
241 listmax
* sizeof (struct fileinfo
));
245 inplast
= &inphead
[listmax
];
257 check_pri_vol_desc(struct tag
*tp
)
259 pvolp
= (struct pri_vol_desc
*)tp
;
264 check_avdp(struct tag
*tp
)
266 avdp
= (struct anch_vol_desc_ptr
*)tp
;
271 check_vdp(struct tag
*tp
)
273 volp
= (struct vdp_desc
*)tp
;
278 check_iuvd(struct tag
*tp
)
280 iudp
= (struct iuvd_desc
*)tp
;
285 check_part_desc(struct tag
*tp
)
287 partp
= (struct part_desc
*)tp
;
289 pheadp
= (struct phdr_desc
*)&partp
->pd_pc_use
;
290 part_start
= partp
->pd_part_start
;
291 part_len
= partp
->pd_part_length
;
293 (void) printf("partition start %x len %x\n", part_start
,
299 check_log_desc(struct tag
*tp
)
301 logvp
= (struct log_vol_desc
*)tp
;
306 check_unall_desc(struct tag
*tp
)
308 unallp
= (struct unall_desc
*)tp
;
314 check_term_desc(struct tag
*tp
)
320 check_lvint(struct tag
*tp
)
323 lvintp
= (struct log_vol_int_desc
*)tp
;
328 dump16(char *cp
, char *nl
)
334 for (i
= 0; i
< 16; i
+= 4) {
336 ptr
= (long *)(cp
+ i
);
337 (void) printf("%08lx ", *ptr
);
343 * Read in the super block and its summary info.
347 readvolseq(int32_t listerr
)
351 struct anch_vol_desc_ptr
*avp
;
358 disk_size
= get_last_block();
360 (void) printf("Disk partition size: %x\n", disk_size
);
363 avp
= (struct anch_vol_desc_ptr
*)avdbuf
;
365 for (fsbsize
= 512; fsbsize
<= MAXBSIZE
; fsbsize
<<= 1) {
366 avdp
= FIRSTAVDP
* fsbsize
/ DEV_BSIZE
;
367 if (bread(fsreadfd
, avdbuf
, avdp
, fsbsize
) != 0)
369 err
= verifytag(tp
, FIRSTAVDP
, tp
, UD_ANCH_VOL_DESC
);
371 (void) printf("bsize %ld tp->tag %d, %s\n", fsbsize
,
372 tp
->tag_id
, tagerrs
[err
]);
376 if (fsbsize
> MAXBSIZE
)
377 errexit(gettext("Can't find anchor volume descriptor\n"));
380 (void) printf("fsbsize = %ld\n", fsbsize
);
381 main_vdbuf
= malloc(avp
->avd_main_vdse
.ext_len
);
382 res_vdbuf
= malloc(avp
->avd_res_vdse
.ext_len
);
383 if (main_vdbuf
== NULL
|| res_vdbuf
== NULL
)
384 errexit("cannot allocate space for volume sequences\n");
386 (void) printf("reading volume sequences "
387 "(%d bytes at %x and %x)\n",
388 avp
->avd_main_vdse
.ext_len
, avp
->avd_main_vdse
.ext_loc
,
389 avp
->avd_res_vdse
.ext_loc
);
390 if (bread(fsreadfd
, main_vdbuf
, fsbtodb(avp
->avd_main_vdse
.ext_loc
),
391 avp
->avd_main_vdse
.ext_len
) != 0)
393 if (bread(fsreadfd
, res_vdbuf
, fsbtodb(avp
->avd_res_vdse
.ext_loc
),
394 avp
->avd_res_vdse
.ext_len
) != 0)
396 end
= (uint8_t *)main_vdbuf
+ avp
->avd_main_vdse
.ext_len
;
397 nextblock
= avp
->avd_main_vdse
.ext_loc
;
398 for (cp
= (uint8_t *)main_vdbuf
; cp
< end
; cp
+= fsbsize
, nextblock
++) {
400 tp
= (struct tag
*)cp
;
401 err
= verifytag(tp
, nextblock
, tp
, 0);
403 dump16((char *)cp
, "");
404 (void) printf("blk %lx err %s tag %d\n", nextblock
,
405 tagerrs
[err
], tp
->tag_id
);
408 if (serialnum
>= 0 && tp
->tag_sno
!= serialnum
) {
409 (void) printf(gettext("serial number mismatch "
410 "tag type %d, block %lx\n"), tp
->tag_id
,
414 switch (tp
->tag_id
) {
415 case UD_PRI_VOL_DESC
:
416 serialnum
= tp
->tag_sno
;
418 (void) printf("serial number = %d\n",
421 err
= check_pri_vol_desc(tp
);
423 case UD_ANCH_VOL_DESC
:
424 err
= check_avdp(tp
);
426 case UD_VOL_DESC_PTR
:
429 case UD_IMPL_USE_DESC
:
430 err
= check_iuvd(tp
);
433 err
= check_part_desc(tp
);
435 case UD_LOG_VOL_DESC
:
436 err
= check_log_desc(tp
);
438 case UD_UNALL_SPA_DESC
:
439 err
= check_unall_desc(tp
);
442 err
= check_term_desc(tp
);
446 err
= check_lvint(tp
);
449 (void) printf(gettext("Invalid volume "
450 "sequence tag %d\n"), tp
->tag_id
);
453 (void) printf(gettext("Volume sequence tag error %s\n"),
458 if (!partp
|| !logvp
) {
459 (void) printf(gettext("Missing partition header or"
460 " logical volume descriptor\n"));
464 /* Get the logical volume integrity descriptor */
465 lvintblock
= logvp
->lvd_int_seq_ext
.ext_loc
;
466 lvintlen
= logvp
->lvd_int_seq_ext
.ext_len
;
467 lvintp
= (struct log_vol_int_desc
*)malloc(lvintlen
);
469 (void) printf("Logvolint at %x for %d bytes\n", lvintblock
,
471 if (lvintp
== NULL
) {
472 (void) printf(gettext("Can't allocate space for logical"
473 " volume integrity sequence\n"));
476 if (bread(fsreadfd
, (char *)lvintp
,
477 fsbtodb(lvintblock
), lvintlen
) != 0) {
480 err
= verifytag(&lvintp
->lvid_tag
, lvintblock
, &lvintp
->lvid_tag
,
483 dump16((char *)lvintp
, "\n");
486 (void) printf(gettext("Log_vol_int tag error: %s, tag = %d\n"),
487 tagerrs
[err
], lvintp
->lvid_tag
.tag_id
);
491 /* Get pointer to implementation use area */
492 lviup
= (struct lvid_iu
*)&lvintp
->lvid_fst
[lvintp
->lvid_npart
*2];
494 (void) printf("free space %d total %d ", lvintp
->lvid_fst
[0],
495 lvintp
->lvid_fst
[1]);
496 (void) printf(gettext("nfiles %d ndirs %d\n"), lviup
->lvidiu_nfiles
,
497 lviup
->lvidiu_ndirs
);
500 /* Set up free block map and read in the existing free space map */
501 freelen
= pheadp
->phdr_usb
.sad_ext_len
;
503 (void) printf(gettext("No partition free map\n"));
505 part_bmp_bytes
= (part_len
+ NBBY
- 1) / NBBY
;
506 busymap
= calloc((unsigned)part_bmp_bytes
, sizeof (char));
507 if (busymap
== NULL
) {
508 (void) printf(gettext("Can't allocate free block bitmap\n"));
513 (part_bmp_bytes
+ SPACEMAP_OFF
+ secsize
- 1) /
515 part_bmp_loc
= pheadp
->phdr_usb
.sad_ext_loc
+ part_start
;
517 /* Mark the partition map blocks busy */
518 markbusy(pheadp
->phdr_usb
.sad_ext_loc
,
519 part_bmp_sectors
* secsize
);
521 spacep
= (struct space_bmap_desc
*)
522 malloc(secsize
*part_bmp_sectors
);
523 if (spacep
== NULL
) {
524 (void) printf(gettext("Can't allocate partition "
528 if (bread(fsreadfd
, (char *)spacep
, fsbtodb(part_bmp_loc
),
529 part_bmp_sectors
* secsize
) != 0)
531 cp
= (uint8_t *)spacep
;
532 err
= verifytag(&spacep
->sbd_tag
, pheadp
->phdr_usb
.sad_ext_loc
,
533 &spacep
->sbd_tag
, UD_SPA_BMAP_DESC
);
535 dump16((char *)cp
, "");
536 (void) printf("blk %x err %s tag %d\n", part_bmp_loc
,
537 tagerrs
[err
], spacep
->sbd_tag
.tag_id
);
539 freemap
= (char *)cp
+ SPACEMAP_OFF
;
541 (void) printf("err %s tag %x space bitmap at %x"
542 " length %d nbits %d nbytes %d\n",
543 tagerrs
[err
], spacep
->sbd_tag
.tag_id
,
544 part_bmp_loc
, part_bmp_sectors
,
545 spacep
->sbd_nbits
, spacep
->sbd_nbytes
);
547 (void) printf(gettext("Space bitmap tag error, %s, "
549 tagerrs
[err
], spacep
->sbd_tag
.tag_id
);
554 /* Get the fileset descriptor */
555 lap
= (long_ad_t
*)&logvp
->lvd_lvcu
;
556 filesetblock
= lap
->lad_ext_loc
;
557 filesetlen
= lap
->lad_ext_len
;
558 markbusy(filesetblock
, filesetlen
);
560 (void) printf("Fileset descriptor at %x for %d bytes\n",
561 filesetblock
, filesetlen
);
563 (void) printf(gettext("No file set descriptor found\n"));
566 fileset
= (struct file_set_desc
*)malloc(filesetlen
);
567 if (fileset
== NULL
) {
568 (void) printf(gettext("Unable to allocate fileset\n"));
571 if (bread(fsreadfd
, (char *)fileset
, fsbtodb(filesetblock
+ part_start
),
575 err
= verifytag(&fileset
->fsd_tag
, filesetblock
, &fileset
->fsd_tag
,
578 (void) printf(gettext("Fileset tag error, tag = %d, %s\n"),
579 fileset
->fsd_tag
.tag_id
, tagerrs
[err
]);
583 /* Get the address of the root file entry */
584 lap
= (long_ad_t
*)&fileset
->fsd_root_icb
;
585 rootblock
= lap
->lad_ext_loc
;
586 rootlen
= lap
->lad_ext_len
;
588 (void) printf("Root at %x for %d bytes\n", rootblock
, rootlen
);
598 struct dk_cinfo dki_info
;
600 if (ioctl(fsreadfd
, DKIOCGVTOC
, (intptr_t)&vtoc
) != 0) {
601 (void) fprintf(stderr
, gettext("Unable to read VTOC\n"));
605 if (vtoc
.v_sanity
!= VTOC_SANE
) {
606 (void) fprintf(stderr
, gettext("Vtoc.v_sanity != VTOC_SANE\n"));
610 if (ioctl(fsreadfd
, DKIOCINFO
, (intptr_t)&dki_info
) != 0) {
611 (void) fprintf(stderr
,
612 gettext("Could not get the slice information\n"));
616 if (dki_info
.dki_partition
> V_NUMPAR
) {
617 (void) fprintf(stderr
,
618 gettext("dki_info.dki_partition > V_NUMPAR\n"));
622 return ((uint32_t)vtoc
.v_part
[dki_info
.dki_partition
].p_size
);