2 * Copyright 1999 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.
28 #pragma ident "%Z%%M% %I% %E% SMI"
33 #include <sys/param.h>
34 #include <sys/types.h>
35 #include <sys/sysmacros.h>
36 #include <sys/mntent.h>
37 #include <sys/vnode.h>
38 #include <sys/fs/udf_volume.h>
46 * for each large file ( size > MAXOFF_T) this global counter
47 * gets incremented here.
50 extern unsigned int largefile_count
;
51 extern void pwarn(char *, ...);
52 extern void pfatal(char *, ...);
53 extern void errexit(char *, ...);
55 extern int32_t verifytag(struct tag
*, uint32_t, struct tag
*, int);
56 extern char *tagerrs
[];
57 extern void maketag(struct tag
*, struct tag
*);
58 extern void flush(int32_t, struct bufarea
*);
59 extern void putfilentry(struct bufarea
*);
60 extern int32_t bread(int32_t, char *, daddr_t
, long);
61 extern void bwrite(int, char *, daddr_t
, long);
62 extern int32_t dofix(struct inodesc
*, char *);
63 extern int32_t reply(char *);
64 extern void ud_swap_short_ad(short_ad_t
*);
65 extern void ud_swap_long_ad(long_ad_t
*);
67 extern void dump16(char *, char *);
69 static void adjust(struct fileinfo
*);
70 static void opndir(struct file_entry
*);
71 static int32_t getdir(struct file_entry
*, struct bufarea
**,
72 u_offset_t
*, struct file_id
**);
73 static void ckinode(struct file_entry
*);
74 struct bufarea
*getfilentry();
76 /* Fields for traversing an allocation extent */
77 static uint32_t dir_adrsize
;
78 static uint32_t dir_adrindx
;
79 static uint32_t dir_naddrs
;
80 static uint8_t *extbuf
;
81 static uint8_t *dir_adrlist
;
83 /* Keep track of where we are in the directory */
84 static u_offset_t dir_baseoff
;
85 static uint32_t dir_basesize
;
86 static uint8_t *dirbuf
;
87 static uint8_t *dir_fidp
;
88 static uint32_t baseblock
;
90 #define MAXFIDSIZE 2048
92 static uint8_t fidbuf
[MAXFIDSIZE
];
97 register struct file_entry
*fp
;
98 register struct fileinfo
*fip
;
99 register struct bufarea
*bp
;
100 struct file_id
*fidp
;
104 (void) cachefile(rootblock
, rootlen
);
105 fip
= &inphead
[0]; /* The root */
106 fip
->fe_lseen
= 0; /* Didn't get here through directory */
107 n_files
= n_dirs
= 0;
108 while (fip
->fe_block
) {
109 u_offset_t offset
, end
;
111 markbusy(fip
->fe_block
, fip
->fe_len
);
112 bp
= getfilentry(fip
->fe_block
, fip
->fe_len
);
114 pwarn(gettext("Unable to read file entry at %x\n"),
119 fp
= (struct file_entry
*)bp
->b_un
.b_buf
;
120 fip
->fe_lcount
= fp
->fe_lcount
;
121 fip
->fe_type
= fp
->fe_icb_tag
.itag_ftype
;
122 if (fp
->fe_uniq_id
>= maxuniqid
)
123 maxuniqid
= fp
->fe_uniq_id
+ 1;
125 if (fip
->fe_block
== rootblock
&&
126 fip
->fe_type
!= FTYPE_DIRECTORY
)
127 errexit(gettext("Root file entry is not a "
131 (void) printf("do %x len %d type %d lcount %d"
132 " lseen %d end %llx\n",
133 fip
->fe_block
, fip
->fe_len
,
134 fip
->fe_type
, fip
->fe_lcount
,
135 fip
->fe_lseen
, fp
->fe_info_len
);
137 switch (fip
->fe_type
) {
138 case FTYPE_DIRECTORY
:
141 end
= fp
->fe_info_len
;
144 for (offset
= 0; offset
< end
;
145 offset
+= FID_LENGTH(fidp
)) {
146 err
= getdir(fp
, &fbp
, &offset
, &fidp
);
148 pwarn(gettext("Bad directory entry in "
149 "file %x at offset %llx\n"),
150 fip
->fe_block
, offset
);
153 if (fidp
->fid_flags
& FID_DELETED
)
155 (void) cachefile(fidp
->fid_icb
.lad_ext_loc
,
156 fidp
->fid_icb
.lad_ext_len
);
163 fbp
->b_flags
&= ~B_INUSE
;
165 (void) printf("Done %x\n", fip
->fe_block
);
176 bp
->b_flags
&= ~B_INUSE
;
178 /* At end of this set of fips, get the next set */
179 if ((++fip
)->fe_block
== (uint32_t)-1)
180 fip
= fip
->fe_nexthash
;
183 /* Find bad link counts */
185 while (fip
->fe_block
) {
186 if (fip
->fe_lcount
!= fip
->fe_lseen
)
188 /* At end of this set of fips, get the next set */
189 if ((++fip
)->fe_block
== (uint32_t)-1)
190 fip
= fip
->fe_nexthash
;
195 opndir(struct file_entry
*fp
)
210 switch (fp
->fe_icb_tag
.itag_flags
& 0x3) {
211 case ICB_FLAG_SHORT_AD
:
212 dir_adrsize
= sizeof (short_ad_t
);
213 dir_naddrs
= fp
->fe_len_adesc
/ sizeof (short_ad_t
);
214 dir_adrlist
= (uint8_t *)(fp
->fe_spec
+ fp
->fe_len_ear
);
216 case ICB_FLAG_LONG_AD
:
217 dir_adrsize
= sizeof (long_ad_t
);
218 dir_naddrs
= fp
->fe_len_adesc
/ sizeof (long_ad_t
);
219 dir_adrlist
= (uint8_t *)(fp
->fe_spec
+ fp
->fe_len_ear
);
221 case ICB_FLAG_EXT_AD
:
222 errexit(gettext("Can't handle ext_ads in directories/n"));
224 case ICB_FLAG_ONE_AD
:
228 dir_basesize
= fp
->fe_len_adesc
;
229 dir_fidp
= (uint8_t *)(fp
->fe_spec
+ fp
->fe_len_ear
);
230 baseblock
= fp
->fe_tag
.tag_loc
;
235 /* Allocate and read in an allocation extent */
238 getallocext(struct file_entry
*fp
, uint32_t loc
, uint32_t len
)
244 struct alloc_ext_desc
*aep
;
247 (void) printf(" allocext loc %x len %x\n", loc
, len
);
248 nb
= roundup(len
, secsize
);
251 extbuf
= (uint8_t *)malloc(nb
);
253 errexit(gettext("Can't allocate directory extent buffer\n"));
254 if (bread(fsreadfd
, (char *)extbuf
,
255 fsbtodb(loc
+ part_start
), nb
) != 0) {
256 (void) fprintf(stderr
,
257 gettext("Can't read allocation extent\n"));
261 aep
= (struct alloc_ext_desc
*)extbuf
;
262 err
= verifytag(&aep
->aed_tag
, loc
, &aep
->aed_tag
, UD_ALLOC_EXT_DESC
);
265 gettext("Bad tag on alloc extent: %s\n"), tagerrs
[err
]);
269 dir_adrlist
= (uint8_t *)(aep
+ 1);
270 dir_naddrs
= aep
->aed_len_aed
/ dir_adrsize
;
273 /* Swap the descriptors */
274 for (i
= 0, ap
= dir_adrlist
; i
< dir_naddrs
; i
++, ap
+= dir_adrsize
) {
275 if (dir_adrsize
== sizeof (short_ad_t
)) {
277 ud_swap_short_ad((short_ad_t
*)ap
);
278 } else if (dir_adrsize
== sizeof (long_ad_t
)) {
280 ud_swap_long_ad((long_ad_t
*)ap
);
288 * Variables used in this function and their relationships:
289 * *poffset - read pointer in the directory
290 * dir_baseoff - offset at start of dirbuf
291 * dir_baselen - length of valid data in current extent
292 * dir_adrindx - index into current allocation extent for location of
294 * dir_naddrs - number of entries in current allocation extent
295 * dir_fidp - pointer to dirbuf or immediate data in file entry
296 * baseblock - block address of dir_baseoff
297 * newoff - *poffset - dir_baseoff
301 getdir(struct file_entry
*fp
, struct bufarea
**fbp
,
302 u_offset_t
*poffset
, struct file_id
**fidpp
)
305 register struct file_id
*fidp
= (struct file_id
*)fidbuf
;
306 register struct short_ad
*sap
;
307 register struct long_ad
*lap
;
308 register int i
, newoff
, xoff
= 0;
309 uint32_t block
= 0, nb
, len
, left
;
318 (void) printf("getdir %llx\n", offset
);
319 newoff
= offset
- dir_baseoff
;
320 if (newoff
>= dir_basesize
) {
327 block
= baseblock
+ (newoff
/ secsize
);
332 switch (fp
->fe_icb_tag
.itag_flags
& 0x3) {
333 case ICB_FLAG_SHORT_AD
:
335 sap
= &((short_ad_t
*)dir_adrlist
)[dir_adrindx
];
336 for (i
= dir_adrindx
; i
< dir_naddrs
; i
++, sap
++) {
337 len
= EXTLEN(sap
->sad_ext_len
);
338 type
= EXTYPE(sap
->sad_ext_len
);
340 if (i
< dir_naddrs
- 1)
341 errexit(gettext("Allocation extent not "
342 "at end of list\n"));
343 markbusy(sap
->sad_ext_loc
, len
);
344 if (getallocext(fp
, sap
->sad_ext_loc
, len
))
354 " loc %x len %x\n", sap
->sad_ext_loc
,
359 (void) printf(" loc %x len %x\n", sap
->sad_ext_loc
,
361 baseblock
= sap
->sad_ext_loc
;
366 markbusy(sap
->sad_ext_loc
, len
);
368 *poffset
+= dir_basesize
;
371 nb
= roundup(len
, secsize
);
372 dirbuf
= (uint8_t *)malloc(nb
);
374 errexit(gettext("Can't allocate directory extent "
376 if (bread(fsreadfd
, (char *)dirbuf
,
377 fsbtodb(baseblock
+ part_start
), nb
) != 0) {
378 errexit(gettext("Can't read directory extent\n"));
382 case ICB_FLAG_LONG_AD
:
384 lap
= &((long_ad_t
*)dir_adrlist
)[dir_adrindx
];
385 for (i
= dir_adrindx
; i
< dir_naddrs
; i
++, lap
++) {
386 len
= EXTLEN(lap
->lad_ext_len
);
387 type
= EXTYPE(lap
->lad_ext_len
);
389 if (i
< dir_naddrs
- 1)
390 errexit(gettext("Allocation extent not "
391 "at end of list\n"));
392 markbusy(lap
->lad_ext_loc
, len
);
393 if (getallocext(fp
, lap
->lad_ext_loc
, len
))
403 " loc %x len %x\n", lap
->lad_ext_loc
,
408 (void) printf(" loc %x len %x\n", lap
->lad_ext_loc
,
410 baseblock
= lap
->lad_ext_loc
;
415 markbusy(lap
->lad_ext_loc
, len
);
417 *poffset
+= dir_basesize
;
420 nb
= roundup(len
, secsize
);
421 dirbuf
= (uint8_t *)malloc(nb
);
423 errexit(gettext("Can't allocate directory extent "
425 if (bread(fsreadfd
, (char *)dirbuf
,
426 fsbtodb(baseblock
+ part_start
), nb
) != 0) {
427 errexit(gettext("Can't read directory extent\n"));
431 case ICB_FLAG_EXT_AD
:
433 case ICB_FLAG_ONE_AD
:
434 errexit(gettext("Logic error in getdir - at ICB_FLAG_ONE_AD "
440 (void) printf("getdirend blk %x dir_baseoff %llx newoff %x\n",
441 block
, dir_baseoff
, newoff
);
442 left
= dir_basesize
- newoff
;
443 if (xoff
+ left
> MAXFIDSIZE
)
444 left
= MAXFIDSIZE
- xoff
;
445 bcopy((char *)dir_fidp
+ newoff
, (char *)fidbuf
+ xoff
, left
);
448 * If we have a fid that crosses an extent boundary, then force
449 * a read of the next extent, and fill up the rest of the fid.
451 if (xoff
< sizeof (fidp
->fid_tag
) ||
452 xoff
< sizeof (fidp
->fid_tag
) + SWAP16(fidp
->fid_tag
.tag_crc_len
)) {
455 (void) printf("block crossing at offset %llx\n",
459 err
= verifytag(&fidp
->fid_tag
, block
, &fidp
->fid_tag
, UD_FILE_ID_DESC
);
461 dump16((char *)fidp
, "\n");
464 pwarn(gettext("Bad directory tag: %s\n"), tagerrs
[err
]);
472 ckinode(struct file_entry
*fp
)
474 register struct short_ad
*sap
;
475 register struct long_ad
*lap
;
476 register int i
, type
, len
;
478 switch (fp
->fe_icb_tag
.itag_flags
& 0x3) {
479 case ICB_FLAG_SHORT_AD
:
480 dir_adrsize
= sizeof (short_ad_t
);
481 dir_naddrs
= fp
->fe_len_adesc
/ sizeof (short_ad_t
);
483 sap
= (short_ad_t
*)(fp
->fe_spec
+ fp
->fe_len_ear
);
485 for (i
= 0; i
< dir_naddrs
; i
++, sap
++) {
486 len
= EXTLEN(sap
->sad_ext_len
);
487 type
= EXTYPE(sap
->sad_ext_len
);
489 markbusy(sap
->sad_ext_loc
, len
);
492 " loc %x len %x\n", sap
->sad_ext_loc
,
495 markbusy(sap
->sad_ext_loc
, len
);
496 /* This changes dir_naddrs and dir_adrlist */
497 if (getallocext(fp
, sap
->sad_ext_loc
, len
))
500 sap
= (short_ad_t
*)dir_adrlist
;
505 case ICB_FLAG_LONG_AD
:
506 dir_adrsize
= sizeof (long_ad_t
);
507 dir_naddrs
= fp
->fe_len_adesc
/ sizeof (long_ad_t
);
509 lap
= (long_ad_t
*)(fp
->fe_spec
+ fp
->fe_len_ear
);
511 for (i
= 0; i
< dir_naddrs
; i
++, lap
++) {
512 len
= EXTLEN(lap
->lad_ext_len
);
513 type
= EXTYPE(lap
->lad_ext_len
);
515 markbusy(lap
->lad_ext_loc
, len
);
518 " loc %x len %x\n", lap
->lad_ext_loc
,
521 markbusy(sap
->sad_ext_loc
, len
);
522 /* This changes dir_naddrs and dir_adrlist */
523 if (getallocext(fp
, lap
->lad_ext_loc
, len
))
526 lap
= (long_ad_t
*)dir_adrlist
;
531 case ICB_FLAG_EXT_AD
:
533 case ICB_FLAG_ONE_AD
:
539 adjust(struct fileinfo
*fip
)
541 register struct file_entry
*fp
;
542 register struct bufarea
*bp
;
544 bp
= getfilentry(fip
->fe_block
, fip
->fe_len
);
546 errexit(gettext("Unable to read file entry at %x\n"),
549 fp
= (struct file_entry
*)bp
->b_un
.b_buf
;
550 pwarn(gettext("LINK COUNT %s I=%x"),
551 fip
->fe_type
== FTYPE_DIRECTORY
? "DIR" :
552 fip
->fe_type
== FTYPE_SYMLINK
? "SYM" :
553 fip
->fe_type
== FTYPE_FILE
? "FILE" : "???", fip
->fe_block
);
554 (void) printf(gettext(" COUNT %d SHOULD BE %d"),
555 fip
->fe_lcount
, fip
->fe_lseen
);
557 if (fip
->fe_lseen
> fip
->fe_lcount
) {
559 pfatal(gettext("LINK COUNT INCREASING"));
561 (void) printf(gettext(" (ADJUSTED)\n"));
563 if (preen
|| reply(gettext("ADJUST")) == 1) {
564 fp
->fe_lcount
= fip
->fe_lseen
;
567 flush(fswritefd
, bp
);
569 bp
->b_flags
&= ~B_INUSE
;
576 register char *bp
, *fp
;
577 struct inodesc idesc
;
582 /* Flip bits in the busy map */
584 for (i
= 0, bp
= busymap
; i
< part_bmp_bytes
; i
++, bp
++)
587 /* Mark leftovers in byte as allocated */
589 bp
[-1] &= (unsigned)0xff >> (NBBY
- part_len
% NBBY
);
592 bzero((char *)&idesc
, sizeof (struct inodesc
));
593 idesc
.id_type
= ADDR
;
594 if (bcmp(bp
, fp
, part_bmp_bytes
) != 0 &&
595 dofix(&idesc
, gettext("BLK(S) MISSING IN FREE BITMAP"))) {
596 bcopy(bp
, fp
, part_bmp_bytes
);
597 maketag(&spacep
->sbd_tag
, &spacep
->sbd_tag
);
598 bwrite(fswritefd
, (char *)spacep
, fsbtodb(part_bmp_loc
),
599 part_bmp_sectors
* secsize
);
606 struct lvid_iu
*lviup
;
607 struct inodesc idesc
;
609 bzero((char *)&idesc
, sizeof (struct inodesc
));
610 idesc
.id_type
= ADDR
;
611 lviup
= (struct lvid_iu
*)&lvintp
->lvid_fst
[2];
612 if ((lvintp
->lvid_fst
[0] != part_len
- n_blks
||
613 lvintp
->lvid_int_type
!= LVI_CLOSE
||
614 lviup
->lvidiu_nfiles
!= n_files
||
615 lviup
->lvidiu_ndirs
!= n_dirs
||
616 lvintp
->lvid_uniqid
< maxuniqid
) &&
617 dofix(&idesc
, gettext("LOGICAL VOLUME INTEGRITY COUNTS WRONG"))) {
618 lvintp
->lvid_int_type
= LVI_CLOSE
;
619 lvintp
->lvid_fst
[0] = part_len
- n_blks
;
620 lviup
->lvidiu_nfiles
= n_files
;
621 lviup
->lvidiu_ndirs
= n_dirs
;
622 lvintp
->lvid_uniqid
= maxuniqid
;
623 maketag(&lvintp
->lvid_tag
, &lvintp
->lvid_tag
);
624 bwrite(fswritefd
, (char *)lvintp
, fsbtodb(lvintblock
),