1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate * Copyright 1999 Sun Microsystems, Inc. All rights reserved.
3*0Sstevel@tonic-gate * Use is subject to license terms.
4*0Sstevel@tonic-gate */
5*0Sstevel@tonic-gate
6*0Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
7*0Sstevel@tonic-gate /* All Rights Reserved */
8*0Sstevel@tonic-gate
9*0Sstevel@tonic-gate /*
10*0Sstevel@tonic-gate * Copyright (c) 1980, 1986, 1990 The Regents of the University of California.
11*0Sstevel@tonic-gate * All rights reserved.
12*0Sstevel@tonic-gate *
13*0Sstevel@tonic-gate * Redistribution and use in source and binary forms are permitted
14*0Sstevel@tonic-gate * provided that: (1) source distributions retain this entire copyright
15*0Sstevel@tonic-gate * notice and comment, and (2) distributions including binaries display
16*0Sstevel@tonic-gate * the following acknowledgement: ``This product includes software
17*0Sstevel@tonic-gate * developed by the University of California, Berkeley and its contributors''
18*0Sstevel@tonic-gate * in the documentation or other materials provided with the distribution
19*0Sstevel@tonic-gate * and in all advertising materials mentioning features or use of this
20*0Sstevel@tonic-gate * software. Neither the name of the University nor the names of its
21*0Sstevel@tonic-gate * contributors may be used to endorse or promote products derived
22*0Sstevel@tonic-gate * from this software without specific prior written permission.
23*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
24*0Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
25*0Sstevel@tonic-gate * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
26*0Sstevel@tonic-gate */
27*0Sstevel@tonic-gate
28*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
29*0Sstevel@tonic-gate
30*0Sstevel@tonic-gate #include <stdio.h>
31*0Sstevel@tonic-gate #include <strings.h>
32*0Sstevel@tonic-gate #include <malloc.h>
33*0Sstevel@tonic-gate #include <sys/param.h>
34*0Sstevel@tonic-gate #include <sys/types.h>
35*0Sstevel@tonic-gate #include <sys/sysmacros.h>
36*0Sstevel@tonic-gate #include <sys/mntent.h>
37*0Sstevel@tonic-gate #include <sys/vnode.h>
38*0Sstevel@tonic-gate #include <sys/fs/udf_volume.h>
39*0Sstevel@tonic-gate #include <sys/dkio.h>
40*0Sstevel@tonic-gate #include <sys/vtoc.h>
41*0Sstevel@tonic-gate #include "fsck.h"
42*0Sstevel@tonic-gate #include "udfs.h"
43*0Sstevel@tonic-gate #include <locale.h>
44*0Sstevel@tonic-gate
45*0Sstevel@tonic-gate /*
46*0Sstevel@tonic-gate * for each large file ( size > MAXOFF_T) this global counter
47*0Sstevel@tonic-gate * gets incremented here.
48*0Sstevel@tonic-gate */
49*0Sstevel@tonic-gate
50*0Sstevel@tonic-gate extern unsigned int largefile_count;
51*0Sstevel@tonic-gate extern void pwarn(char *, ...);
52*0Sstevel@tonic-gate extern void pfatal(char *, ...);
53*0Sstevel@tonic-gate extern void errexit(char *, ...);
54*0Sstevel@tonic-gate
55*0Sstevel@tonic-gate extern int32_t verifytag(struct tag *, uint32_t, struct tag *, int);
56*0Sstevel@tonic-gate extern char *tagerrs[];
57*0Sstevel@tonic-gate extern void maketag(struct tag *, struct tag *);
58*0Sstevel@tonic-gate extern void flush(int32_t, struct bufarea *);
59*0Sstevel@tonic-gate extern void putfilentry(struct bufarea *);
60*0Sstevel@tonic-gate extern int32_t bread(int32_t, char *, daddr_t, long);
61*0Sstevel@tonic-gate extern void bwrite(int, char *, daddr_t, long);
62*0Sstevel@tonic-gate extern int32_t dofix(struct inodesc *, char *);
63*0Sstevel@tonic-gate extern int32_t reply(char *);
64*0Sstevel@tonic-gate extern void ud_swap_short_ad(short_ad_t *);
65*0Sstevel@tonic-gate extern void ud_swap_long_ad(long_ad_t *);
66*0Sstevel@tonic-gate
67*0Sstevel@tonic-gate extern void dump16(char *, char *);
68*0Sstevel@tonic-gate
69*0Sstevel@tonic-gate static void adjust(struct fileinfo *);
70*0Sstevel@tonic-gate static void opndir(struct file_entry *);
71*0Sstevel@tonic-gate static int32_t getdir(struct file_entry *, struct bufarea **,
72*0Sstevel@tonic-gate u_offset_t *, struct file_id **);
73*0Sstevel@tonic-gate static void ckinode(struct file_entry *);
74*0Sstevel@tonic-gate struct bufarea *getfilentry();
75*0Sstevel@tonic-gate
76*0Sstevel@tonic-gate /* Fields for traversing an allocation extent */
77*0Sstevel@tonic-gate static uint32_t dir_adrsize;
78*0Sstevel@tonic-gate static uint32_t dir_adrindx;
79*0Sstevel@tonic-gate static uint32_t dir_naddrs;
80*0Sstevel@tonic-gate static uint8_t *extbuf;
81*0Sstevel@tonic-gate static uint8_t *dir_adrlist;
82*0Sstevel@tonic-gate
83*0Sstevel@tonic-gate /* Keep track of where we are in the directory */
84*0Sstevel@tonic-gate static u_offset_t dir_baseoff;
85*0Sstevel@tonic-gate static uint32_t dir_basesize;
86*0Sstevel@tonic-gate static uint8_t *dirbuf;
87*0Sstevel@tonic-gate static uint8_t *dir_fidp;
88*0Sstevel@tonic-gate static uint32_t baseblock;
89*0Sstevel@tonic-gate
90*0Sstevel@tonic-gate #define MAXFIDSIZE 2048
91*0Sstevel@tonic-gate
92*0Sstevel@tonic-gate static uint8_t fidbuf[MAXFIDSIZE];
93*0Sstevel@tonic-gate
94*0Sstevel@tonic-gate void
pass1()95*0Sstevel@tonic-gate pass1()
96*0Sstevel@tonic-gate {
97*0Sstevel@tonic-gate register struct file_entry *fp;
98*0Sstevel@tonic-gate register struct fileinfo *fip;
99*0Sstevel@tonic-gate register struct bufarea *bp;
100*0Sstevel@tonic-gate struct file_id *fidp;
101*0Sstevel@tonic-gate struct bufarea *fbp;
102*0Sstevel@tonic-gate int err;
103*0Sstevel@tonic-gate
104*0Sstevel@tonic-gate (void) cachefile(rootblock, rootlen);
105*0Sstevel@tonic-gate fip = &inphead[0]; /* The root */
106*0Sstevel@tonic-gate fip->fe_lseen = 0; /* Didn't get here through directory */
107*0Sstevel@tonic-gate n_files = n_dirs = 0;
108*0Sstevel@tonic-gate while (fip->fe_block) {
109*0Sstevel@tonic-gate u_offset_t offset, end;
110*0Sstevel@tonic-gate
111*0Sstevel@tonic-gate markbusy(fip->fe_block, fip->fe_len);
112*0Sstevel@tonic-gate bp = getfilentry(fip->fe_block, fip->fe_len);
113*0Sstevel@tonic-gate if (bp == NULL) {
114*0Sstevel@tonic-gate pwarn(gettext("Unable to read file entry at %x\n"),
115*0Sstevel@tonic-gate fip->fe_block);
116*0Sstevel@tonic-gate goto next;
117*0Sstevel@tonic-gate }
118*0Sstevel@tonic-gate /* LINTED */
119*0Sstevel@tonic-gate fp = (struct file_entry *)bp->b_un.b_buf;
120*0Sstevel@tonic-gate fip->fe_lcount = fp->fe_lcount;
121*0Sstevel@tonic-gate fip->fe_type = fp->fe_icb_tag.itag_ftype;
122*0Sstevel@tonic-gate if (fp->fe_uniq_id >= maxuniqid)
123*0Sstevel@tonic-gate maxuniqid = fp->fe_uniq_id + 1;
124*0Sstevel@tonic-gate
125*0Sstevel@tonic-gate if (fip->fe_block == rootblock &&
126*0Sstevel@tonic-gate fip->fe_type != FTYPE_DIRECTORY)
127*0Sstevel@tonic-gate errexit(gettext("Root file entry is not a "
128*0Sstevel@tonic-gate "directory\n"));
129*0Sstevel@tonic-gate
130*0Sstevel@tonic-gate if (debug) {
131*0Sstevel@tonic-gate (void) printf("do %x len %d type %d lcount %d"
132*0Sstevel@tonic-gate " lseen %d end %llx\n",
133*0Sstevel@tonic-gate fip->fe_block, fip->fe_len,
134*0Sstevel@tonic-gate fip->fe_type, fip->fe_lcount,
135*0Sstevel@tonic-gate fip->fe_lseen, fp->fe_info_len);
136*0Sstevel@tonic-gate }
137*0Sstevel@tonic-gate switch (fip->fe_type) {
138*0Sstevel@tonic-gate case FTYPE_DIRECTORY:
139*0Sstevel@tonic-gate n_dirs++;
140*0Sstevel@tonic-gate offset = 0;
141*0Sstevel@tonic-gate end = fp->fe_info_len;
142*0Sstevel@tonic-gate fbp = NULL;
143*0Sstevel@tonic-gate opndir(fp);
144*0Sstevel@tonic-gate for (offset = 0; offset < end;
145*0Sstevel@tonic-gate offset += FID_LENGTH(fidp)) {
146*0Sstevel@tonic-gate err = getdir(fp, &fbp, &offset, &fidp);
147*0Sstevel@tonic-gate if (err) {
148*0Sstevel@tonic-gate pwarn(gettext("Bad directory entry in "
149*0Sstevel@tonic-gate "file %x at offset %llx\n"),
150*0Sstevel@tonic-gate fip->fe_block, offset);
151*0Sstevel@tonic-gate offset = end;
152*0Sstevel@tonic-gate }
153*0Sstevel@tonic-gate if (fidp->fid_flags & FID_DELETED)
154*0Sstevel@tonic-gate continue;
155*0Sstevel@tonic-gate (void) cachefile(fidp->fid_icb.lad_ext_loc,
156*0Sstevel@tonic-gate fidp->fid_icb.lad_ext_len);
157*0Sstevel@tonic-gate }
158*0Sstevel@tonic-gate if (dirbuf) {
159*0Sstevel@tonic-gate free(dirbuf);
160*0Sstevel@tonic-gate dirbuf = NULL;
161*0Sstevel@tonic-gate }
162*0Sstevel@tonic-gate if (fbp)
163*0Sstevel@tonic-gate fbp->b_flags &= ~B_INUSE;
164*0Sstevel@tonic-gate if (debug)
165*0Sstevel@tonic-gate (void) printf("Done %x\n", fip->fe_block);
166*0Sstevel@tonic-gate break;
167*0Sstevel@tonic-gate
168*0Sstevel@tonic-gate case FTYPE_FILE:
169*0Sstevel@tonic-gate case FTYPE_SYMLINK:
170*0Sstevel@tonic-gate ckinode(fp);
171*0Sstevel@tonic-gate default:
172*0Sstevel@tonic-gate n_files++;
173*0Sstevel@tonic-gate break;
174*0Sstevel@tonic-gate }
175*0Sstevel@tonic-gate putfilentry(bp);
176*0Sstevel@tonic-gate bp->b_flags &= ~B_INUSE;
177*0Sstevel@tonic-gate next:
178*0Sstevel@tonic-gate /* At end of this set of fips, get the next set */
179*0Sstevel@tonic-gate if ((++fip)->fe_block == (uint32_t)-1)
180*0Sstevel@tonic-gate fip = fip->fe_nexthash;
181*0Sstevel@tonic-gate }
182*0Sstevel@tonic-gate
183*0Sstevel@tonic-gate /* Find bad link counts */
184*0Sstevel@tonic-gate fip = &inphead[0];
185*0Sstevel@tonic-gate while (fip->fe_block) {
186*0Sstevel@tonic-gate if (fip->fe_lcount != fip->fe_lseen)
187*0Sstevel@tonic-gate adjust(fip);
188*0Sstevel@tonic-gate /* At end of this set of fips, get the next set */
189*0Sstevel@tonic-gate if ((++fip)->fe_block == (uint32_t)-1)
190*0Sstevel@tonic-gate fip = fip->fe_nexthash;
191*0Sstevel@tonic-gate }
192*0Sstevel@tonic-gate }
193*0Sstevel@tonic-gate
194*0Sstevel@tonic-gate static void
opndir(struct file_entry * fp)195*0Sstevel@tonic-gate opndir(struct file_entry *fp)
196*0Sstevel@tonic-gate {
197*0Sstevel@tonic-gate if (dirbuf) {
198*0Sstevel@tonic-gate free(dirbuf);
199*0Sstevel@tonic-gate dirbuf = NULL;
200*0Sstevel@tonic-gate }
201*0Sstevel@tonic-gate if (extbuf) {
202*0Sstevel@tonic-gate free(extbuf);
203*0Sstevel@tonic-gate extbuf = NULL;
204*0Sstevel@tonic-gate }
205*0Sstevel@tonic-gate
206*0Sstevel@tonic-gate dir_baseoff = 0;
207*0Sstevel@tonic-gate dir_basesize = 0;
208*0Sstevel@tonic-gate dir_adrindx = 0;
209*0Sstevel@tonic-gate
210*0Sstevel@tonic-gate switch (fp->fe_icb_tag.itag_flags & 0x3) {
211*0Sstevel@tonic-gate case ICB_FLAG_SHORT_AD:
212*0Sstevel@tonic-gate dir_adrsize = sizeof (short_ad_t);
213*0Sstevel@tonic-gate dir_naddrs = fp->fe_len_adesc / sizeof (short_ad_t);
214*0Sstevel@tonic-gate dir_adrlist = (uint8_t *)(fp->fe_spec + fp->fe_len_ear);
215*0Sstevel@tonic-gate break;
216*0Sstevel@tonic-gate case ICB_FLAG_LONG_AD:
217*0Sstevel@tonic-gate dir_adrsize = sizeof (long_ad_t);
218*0Sstevel@tonic-gate dir_naddrs = fp->fe_len_adesc / sizeof (long_ad_t);
219*0Sstevel@tonic-gate dir_adrlist = (uint8_t *)(fp->fe_spec + fp->fe_len_ear);
220*0Sstevel@tonic-gate break;
221*0Sstevel@tonic-gate case ICB_FLAG_EXT_AD:
222*0Sstevel@tonic-gate errexit(gettext("Can't handle ext_ads in directories/n"));
223*0Sstevel@tonic-gate break;
224*0Sstevel@tonic-gate case ICB_FLAG_ONE_AD:
225*0Sstevel@tonic-gate dir_adrsize = 0;
226*0Sstevel@tonic-gate dir_naddrs = 0;
227*0Sstevel@tonic-gate dir_adrlist = NULL;
228*0Sstevel@tonic-gate dir_basesize = fp->fe_len_adesc;
229*0Sstevel@tonic-gate dir_fidp = (uint8_t *)(fp->fe_spec + fp->fe_len_ear);
230*0Sstevel@tonic-gate baseblock = fp->fe_tag.tag_loc;
231*0Sstevel@tonic-gate break;
232*0Sstevel@tonic-gate }
233*0Sstevel@tonic-gate }
234*0Sstevel@tonic-gate
235*0Sstevel@tonic-gate /* Allocate and read in an allocation extent */
236*0Sstevel@tonic-gate /* ARGSUSED */
237*0Sstevel@tonic-gate int
getallocext(struct file_entry * fp,uint32_t loc,uint32_t len)238*0Sstevel@tonic-gate getallocext(struct file_entry *fp, uint32_t loc, uint32_t len)
239*0Sstevel@tonic-gate {
240*0Sstevel@tonic-gate uint32_t nb;
241*0Sstevel@tonic-gate uint8_t *ap;
242*0Sstevel@tonic-gate int i;
243*0Sstevel@tonic-gate int err;
244*0Sstevel@tonic-gate struct alloc_ext_desc *aep;
245*0Sstevel@tonic-gate
246*0Sstevel@tonic-gate if (debug)
247*0Sstevel@tonic-gate (void) printf(" allocext loc %x len %x\n", loc, len);
248*0Sstevel@tonic-gate nb = roundup(len, secsize);
249*0Sstevel@tonic-gate if (extbuf)
250*0Sstevel@tonic-gate free(extbuf);
251*0Sstevel@tonic-gate extbuf = (uint8_t *)malloc(nb);
252*0Sstevel@tonic-gate if (extbuf == NULL)
253*0Sstevel@tonic-gate errexit(gettext("Can't allocate directory extent buffer\n"));
254*0Sstevel@tonic-gate if (bread(fsreadfd, (char *)extbuf,
255*0Sstevel@tonic-gate fsbtodb(loc + part_start), nb) != 0) {
256*0Sstevel@tonic-gate (void) fprintf(stderr,
257*0Sstevel@tonic-gate gettext("Can't read allocation extent\n"));
258*0Sstevel@tonic-gate return (1);
259*0Sstevel@tonic-gate }
260*0Sstevel@tonic-gate /* LINTED */
261*0Sstevel@tonic-gate aep = (struct alloc_ext_desc *)extbuf;
262*0Sstevel@tonic-gate err = verifytag(&aep->aed_tag, loc, &aep->aed_tag, UD_ALLOC_EXT_DESC);
263*0Sstevel@tonic-gate if (err) {
264*0Sstevel@tonic-gate (void) printf(
265*0Sstevel@tonic-gate gettext("Bad tag on alloc extent: %s\n"), tagerrs[err]);
266*0Sstevel@tonic-gate free(extbuf);
267*0Sstevel@tonic-gate return (1);
268*0Sstevel@tonic-gate }
269*0Sstevel@tonic-gate dir_adrlist = (uint8_t *)(aep + 1);
270*0Sstevel@tonic-gate dir_naddrs = aep->aed_len_aed / dir_adrsize;
271*0Sstevel@tonic-gate dir_adrindx = 0;
272*0Sstevel@tonic-gate
273*0Sstevel@tonic-gate /* Swap the descriptors */
274*0Sstevel@tonic-gate for (i = 0, ap = dir_adrlist; i < dir_naddrs; i++, ap += dir_adrsize) {
275*0Sstevel@tonic-gate if (dir_adrsize == sizeof (short_ad_t)) {
276*0Sstevel@tonic-gate /* LINTED */
277*0Sstevel@tonic-gate ud_swap_short_ad((short_ad_t *)ap);
278*0Sstevel@tonic-gate } else if (dir_adrsize == sizeof (long_ad_t)) {
279*0Sstevel@tonic-gate /* LINTED */
280*0Sstevel@tonic-gate ud_swap_long_ad((long_ad_t *)ap);
281*0Sstevel@tonic-gate }
282*0Sstevel@tonic-gate }
283*0Sstevel@tonic-gate
284*0Sstevel@tonic-gate return (0);
285*0Sstevel@tonic-gate }
286*0Sstevel@tonic-gate
287*0Sstevel@tonic-gate /*
288*0Sstevel@tonic-gate * Variables used in this function and their relationships:
289*0Sstevel@tonic-gate * *poffset - read pointer in the directory
290*0Sstevel@tonic-gate * dir_baseoff - offset at start of dirbuf
291*0Sstevel@tonic-gate * dir_baselen - length of valid data in current extent
292*0Sstevel@tonic-gate * dir_adrindx - index into current allocation extent for location of
293*0Sstevel@tonic-gate * dir_baseoff
294*0Sstevel@tonic-gate * dir_naddrs - number of entries in current allocation extent
295*0Sstevel@tonic-gate * dir_fidp - pointer to dirbuf or immediate data in file entry
296*0Sstevel@tonic-gate * baseblock - block address of dir_baseoff
297*0Sstevel@tonic-gate * newoff - *poffset - dir_baseoff
298*0Sstevel@tonic-gate */
299*0Sstevel@tonic-gate /* ARGSUSED1 */
300*0Sstevel@tonic-gate static int32_t
getdir(struct file_entry * fp,struct bufarea ** fbp,u_offset_t * poffset,struct file_id ** fidpp)301*0Sstevel@tonic-gate getdir(struct file_entry *fp, struct bufarea **fbp,
302*0Sstevel@tonic-gate u_offset_t *poffset, struct file_id **fidpp)
303*0Sstevel@tonic-gate {
304*0Sstevel@tonic-gate /* LINTED */
305*0Sstevel@tonic-gate register struct file_id *fidp = (struct file_id *)fidbuf;
306*0Sstevel@tonic-gate register struct short_ad *sap;
307*0Sstevel@tonic-gate register struct long_ad *lap;
308*0Sstevel@tonic-gate register int i, newoff, xoff = 0;
309*0Sstevel@tonic-gate uint32_t block = 0, nb, len, left;
310*0Sstevel@tonic-gate u_offset_t offset;
311*0Sstevel@tonic-gate int err, type;
312*0Sstevel@tonic-gate
313*0Sstevel@tonic-gate
314*0Sstevel@tonic-gate again:
315*0Sstevel@tonic-gate offset = *poffset;
316*0Sstevel@tonic-gate again2:
317*0Sstevel@tonic-gate if (debug)
318*0Sstevel@tonic-gate (void) printf("getdir %llx\n", offset);
319*0Sstevel@tonic-gate newoff = offset - dir_baseoff;
320*0Sstevel@tonic-gate if (newoff >= dir_basesize) {
321*0Sstevel@tonic-gate if (dirbuf) {
322*0Sstevel@tonic-gate free(dirbuf);
323*0Sstevel@tonic-gate dirbuf = NULL;
324*0Sstevel@tonic-gate }
325*0Sstevel@tonic-gate } else {
326*0Sstevel@tonic-gate if (block == 0)
327*0Sstevel@tonic-gate block = baseblock + (newoff / secsize);
328*0Sstevel@tonic-gate goto nextone;
329*0Sstevel@tonic-gate }
330*0Sstevel@tonic-gate
331*0Sstevel@tonic-gate again3:
332*0Sstevel@tonic-gate switch (fp->fe_icb_tag.itag_flags & 0x3) {
333*0Sstevel@tonic-gate case ICB_FLAG_SHORT_AD:
334*0Sstevel@tonic-gate /* LINTED */
335*0Sstevel@tonic-gate sap = &((short_ad_t *)dir_adrlist)[dir_adrindx];
336*0Sstevel@tonic-gate for (i = dir_adrindx; i < dir_naddrs; i++, sap++) {
337*0Sstevel@tonic-gate len = EXTLEN(sap->sad_ext_len);
338*0Sstevel@tonic-gate type = EXTYPE(sap->sad_ext_len);
339*0Sstevel@tonic-gate if (type == 3) {
340*0Sstevel@tonic-gate if (i < dir_naddrs - 1)
341*0Sstevel@tonic-gate errexit(gettext("Allocation extent not "
342*0Sstevel@tonic-gate "at end of list\n"));
343*0Sstevel@tonic-gate markbusy(sap->sad_ext_loc, len);
344*0Sstevel@tonic-gate if (getallocext(fp, sap->sad_ext_loc, len))
345*0Sstevel@tonic-gate return (1);
346*0Sstevel@tonic-gate goto again3;
347*0Sstevel@tonic-gate }
348*0Sstevel@tonic-gate if (newoff < len)
349*0Sstevel@tonic-gate break;
350*0Sstevel@tonic-gate newoff -= len;
351*0Sstevel@tonic-gate dir_baseoff += len;
352*0Sstevel@tonic-gate if (debug)
353*0Sstevel@tonic-gate (void) printf(
354*0Sstevel@tonic-gate " loc %x len %x\n", sap->sad_ext_loc,
355*0Sstevel@tonic-gate len);
356*0Sstevel@tonic-gate }
357*0Sstevel@tonic-gate dir_adrindx = i;
358*0Sstevel@tonic-gate if (debug)
359*0Sstevel@tonic-gate (void) printf(" loc %x len %x\n", sap->sad_ext_loc,
360*0Sstevel@tonic-gate sap->sad_ext_len);
361*0Sstevel@tonic-gate baseblock = sap->sad_ext_loc;
362*0Sstevel@tonic-gate if (block == 0)
363*0Sstevel@tonic-gate block = baseblock;
364*0Sstevel@tonic-gate dir_basesize = len;
365*0Sstevel@tonic-gate if (type < 2)
366*0Sstevel@tonic-gate markbusy(sap->sad_ext_loc, len);
367*0Sstevel@tonic-gate if (type != 0) {
368*0Sstevel@tonic-gate *poffset += dir_basesize;
369*0Sstevel@tonic-gate goto again;
370*0Sstevel@tonic-gate }
371*0Sstevel@tonic-gate nb = roundup(len, secsize);
372*0Sstevel@tonic-gate dirbuf = (uint8_t *)malloc(nb);
373*0Sstevel@tonic-gate if (dirbuf == NULL)
374*0Sstevel@tonic-gate errexit(gettext("Can't allocate directory extent "
375*0Sstevel@tonic-gate "buffer\n"));
376*0Sstevel@tonic-gate if (bread(fsreadfd, (char *)dirbuf,
377*0Sstevel@tonic-gate fsbtodb(baseblock + part_start), nb) != 0) {
378*0Sstevel@tonic-gate errexit(gettext("Can't read directory extent\n"));
379*0Sstevel@tonic-gate }
380*0Sstevel@tonic-gate dir_fidp = dirbuf;
381*0Sstevel@tonic-gate break;
382*0Sstevel@tonic-gate case ICB_FLAG_LONG_AD:
383*0Sstevel@tonic-gate /* LINTED */
384*0Sstevel@tonic-gate lap = &((long_ad_t *)dir_adrlist)[dir_adrindx];
385*0Sstevel@tonic-gate for (i = dir_adrindx; i < dir_naddrs; i++, lap++) {
386*0Sstevel@tonic-gate len = EXTLEN(lap->lad_ext_len);
387*0Sstevel@tonic-gate type = EXTYPE(lap->lad_ext_len);
388*0Sstevel@tonic-gate if (type == 3) {
389*0Sstevel@tonic-gate if (i < dir_naddrs - 1)
390*0Sstevel@tonic-gate errexit(gettext("Allocation extent not "
391*0Sstevel@tonic-gate "at end of list\n"));
392*0Sstevel@tonic-gate markbusy(lap->lad_ext_loc, len);
393*0Sstevel@tonic-gate if (getallocext(fp, lap->lad_ext_loc, len))
394*0Sstevel@tonic-gate return (1);
395*0Sstevel@tonic-gate goto again3;
396*0Sstevel@tonic-gate }
397*0Sstevel@tonic-gate if (newoff < len)
398*0Sstevel@tonic-gate break;
399*0Sstevel@tonic-gate newoff -= len;
400*0Sstevel@tonic-gate dir_baseoff += len;
401*0Sstevel@tonic-gate if (debug)
402*0Sstevel@tonic-gate (void) printf(
403*0Sstevel@tonic-gate " loc %x len %x\n", lap->lad_ext_loc,
404*0Sstevel@tonic-gate len);
405*0Sstevel@tonic-gate }
406*0Sstevel@tonic-gate dir_adrindx = i;
407*0Sstevel@tonic-gate if (debug)
408*0Sstevel@tonic-gate (void) printf(" loc %x len %x\n", lap->lad_ext_loc,
409*0Sstevel@tonic-gate lap->lad_ext_len);
410*0Sstevel@tonic-gate baseblock = lap->lad_ext_loc;
411*0Sstevel@tonic-gate if (block == 0)
412*0Sstevel@tonic-gate block = baseblock;
413*0Sstevel@tonic-gate dir_basesize = len;
414*0Sstevel@tonic-gate if (type < 2)
415*0Sstevel@tonic-gate markbusy(lap->lad_ext_loc, len);
416*0Sstevel@tonic-gate if (type != 0) {
417*0Sstevel@tonic-gate *poffset += dir_basesize;
418*0Sstevel@tonic-gate goto again;
419*0Sstevel@tonic-gate }
420*0Sstevel@tonic-gate nb = roundup(len, secsize);
421*0Sstevel@tonic-gate dirbuf = (uint8_t *)malloc(nb);
422*0Sstevel@tonic-gate if (dirbuf == NULL)
423*0Sstevel@tonic-gate errexit(gettext("Can't allocate directory extent "
424*0Sstevel@tonic-gate "buffer\n"));
425*0Sstevel@tonic-gate if (bread(fsreadfd, (char *)dirbuf,
426*0Sstevel@tonic-gate fsbtodb(baseblock + part_start), nb) != 0) {
427*0Sstevel@tonic-gate errexit(gettext("Can't read directory extent\n"));
428*0Sstevel@tonic-gate }
429*0Sstevel@tonic-gate dir_fidp = dirbuf;
430*0Sstevel@tonic-gate break;
431*0Sstevel@tonic-gate case ICB_FLAG_EXT_AD:
432*0Sstevel@tonic-gate break;
433*0Sstevel@tonic-gate case ICB_FLAG_ONE_AD:
434*0Sstevel@tonic-gate errexit(gettext("Logic error in getdir - at ICB_FLAG_ONE_AD "
435*0Sstevel@tonic-gate "case\n"));
436*0Sstevel@tonic-gate break;
437*0Sstevel@tonic-gate }
438*0Sstevel@tonic-gate nextone:
439*0Sstevel@tonic-gate if (debug)
440*0Sstevel@tonic-gate (void) printf("getdirend blk %x dir_baseoff %llx newoff %x\n",
441*0Sstevel@tonic-gate block, dir_baseoff, newoff);
442*0Sstevel@tonic-gate left = dir_basesize - newoff;
443*0Sstevel@tonic-gate if (xoff + left > MAXFIDSIZE)
444*0Sstevel@tonic-gate left = MAXFIDSIZE - xoff;
445*0Sstevel@tonic-gate bcopy((char *)dir_fidp + newoff, (char *)fidbuf + xoff, left);
446*0Sstevel@tonic-gate xoff += left;
447*0Sstevel@tonic-gate /*
448*0Sstevel@tonic-gate * If we have a fid that crosses an extent boundary, then force
449*0Sstevel@tonic-gate * a read of the next extent, and fill up the rest of the fid.
450*0Sstevel@tonic-gate */
451*0Sstevel@tonic-gate if (xoff < sizeof (fidp->fid_tag) ||
452*0Sstevel@tonic-gate xoff < sizeof (fidp->fid_tag) + SWAP16(fidp->fid_tag.tag_crc_len)) {
453*0Sstevel@tonic-gate offset += left;
454*0Sstevel@tonic-gate if (debug)
455*0Sstevel@tonic-gate (void) printf("block crossing at offset %llx\n",
456*0Sstevel@tonic-gate offset);
457*0Sstevel@tonic-gate goto again2;
458*0Sstevel@tonic-gate }
459*0Sstevel@tonic-gate err = verifytag(&fidp->fid_tag, block, &fidp->fid_tag, UD_FILE_ID_DESC);
460*0Sstevel@tonic-gate if (debug) {
461*0Sstevel@tonic-gate dump16((char *)fidp, "\n");
462*0Sstevel@tonic-gate }
463*0Sstevel@tonic-gate if (err) {
464*0Sstevel@tonic-gate pwarn(gettext("Bad directory tag: %s\n"), tagerrs[err]);
465*0Sstevel@tonic-gate return (err);
466*0Sstevel@tonic-gate }
467*0Sstevel@tonic-gate *fidpp = fidp;
468*0Sstevel@tonic-gate return (0);
469*0Sstevel@tonic-gate }
470*0Sstevel@tonic-gate
471*0Sstevel@tonic-gate static void
ckinode(struct file_entry * fp)472*0Sstevel@tonic-gate ckinode(struct file_entry *fp)
473*0Sstevel@tonic-gate {
474*0Sstevel@tonic-gate register struct short_ad *sap;
475*0Sstevel@tonic-gate register struct long_ad *lap;
476*0Sstevel@tonic-gate register int i, type, len;
477*0Sstevel@tonic-gate
478*0Sstevel@tonic-gate switch (fp->fe_icb_tag.itag_flags & 0x3) {
479*0Sstevel@tonic-gate case ICB_FLAG_SHORT_AD:
480*0Sstevel@tonic-gate dir_adrsize = sizeof (short_ad_t);
481*0Sstevel@tonic-gate dir_naddrs = fp->fe_len_adesc / sizeof (short_ad_t);
482*0Sstevel@tonic-gate /* LINTED */
483*0Sstevel@tonic-gate sap = (short_ad_t *)(fp->fe_spec + fp->fe_len_ear);
484*0Sstevel@tonic-gate again1:
485*0Sstevel@tonic-gate for (i = 0; i < dir_naddrs; i++, sap++) {
486*0Sstevel@tonic-gate len = EXTLEN(sap->sad_ext_len);
487*0Sstevel@tonic-gate type = EXTYPE(sap->sad_ext_len);
488*0Sstevel@tonic-gate if (type < 2)
489*0Sstevel@tonic-gate markbusy(sap->sad_ext_loc, len);
490*0Sstevel@tonic-gate if (debug)
491*0Sstevel@tonic-gate (void) printf(
492*0Sstevel@tonic-gate " loc %x len %x\n", sap->sad_ext_loc,
493*0Sstevel@tonic-gate sap->sad_ext_len);
494*0Sstevel@tonic-gate if (type == 3) {
495*0Sstevel@tonic-gate markbusy(sap->sad_ext_loc, len);
496*0Sstevel@tonic-gate /* This changes dir_naddrs and dir_adrlist */
497*0Sstevel@tonic-gate if (getallocext(fp, sap->sad_ext_loc, len))
498*0Sstevel@tonic-gate break;
499*0Sstevel@tonic-gate /* LINTED */
500*0Sstevel@tonic-gate sap = (short_ad_t *)dir_adrlist;
501*0Sstevel@tonic-gate goto again1;
502*0Sstevel@tonic-gate }
503*0Sstevel@tonic-gate }
504*0Sstevel@tonic-gate break;
505*0Sstevel@tonic-gate case ICB_FLAG_LONG_AD:
506*0Sstevel@tonic-gate dir_adrsize = sizeof (long_ad_t);
507*0Sstevel@tonic-gate dir_naddrs = fp->fe_len_adesc / sizeof (long_ad_t);
508*0Sstevel@tonic-gate /* LINTED */
509*0Sstevel@tonic-gate lap = (long_ad_t *)(fp->fe_spec + fp->fe_len_ear);
510*0Sstevel@tonic-gate again2:
511*0Sstevel@tonic-gate for (i = 0; i < dir_naddrs; i++, lap++) {
512*0Sstevel@tonic-gate len = EXTLEN(lap->lad_ext_len);
513*0Sstevel@tonic-gate type = EXTYPE(lap->lad_ext_len);
514*0Sstevel@tonic-gate if (type < 2)
515*0Sstevel@tonic-gate markbusy(lap->lad_ext_loc, len);
516*0Sstevel@tonic-gate if (debug)
517*0Sstevel@tonic-gate (void) printf(
518*0Sstevel@tonic-gate " loc %x len %x\n", lap->lad_ext_loc,
519*0Sstevel@tonic-gate lap->lad_ext_len);
520*0Sstevel@tonic-gate if (type == 3) {
521*0Sstevel@tonic-gate markbusy(sap->sad_ext_loc, len);
522*0Sstevel@tonic-gate /* This changes dir_naddrs and dir_adrlist */
523*0Sstevel@tonic-gate if (getallocext(fp, lap->lad_ext_loc, len))
524*0Sstevel@tonic-gate break;
525*0Sstevel@tonic-gate /* LINTED */
526*0Sstevel@tonic-gate lap = (long_ad_t *)dir_adrlist;
527*0Sstevel@tonic-gate goto again2;
528*0Sstevel@tonic-gate }
529*0Sstevel@tonic-gate }
530*0Sstevel@tonic-gate break;
531*0Sstevel@tonic-gate case ICB_FLAG_EXT_AD:
532*0Sstevel@tonic-gate break;
533*0Sstevel@tonic-gate case ICB_FLAG_ONE_AD:
534*0Sstevel@tonic-gate break;
535*0Sstevel@tonic-gate }
536*0Sstevel@tonic-gate }
537*0Sstevel@tonic-gate
538*0Sstevel@tonic-gate static void
adjust(struct fileinfo * fip)539*0Sstevel@tonic-gate adjust(struct fileinfo *fip)
540*0Sstevel@tonic-gate {
541*0Sstevel@tonic-gate register struct file_entry *fp;
542*0Sstevel@tonic-gate register struct bufarea *bp;
543*0Sstevel@tonic-gate
544*0Sstevel@tonic-gate bp = getfilentry(fip->fe_block, fip->fe_len);
545*0Sstevel@tonic-gate if (bp == NULL)
546*0Sstevel@tonic-gate errexit(gettext("Unable to read file entry at %x\n"),
547*0Sstevel@tonic-gate fip->fe_block);
548*0Sstevel@tonic-gate /* LINTED */
549*0Sstevel@tonic-gate fp = (struct file_entry *)bp->b_un.b_buf;
550*0Sstevel@tonic-gate pwarn(gettext("LINK COUNT %s I=%x"),
551*0Sstevel@tonic-gate fip->fe_type == FTYPE_DIRECTORY ? "DIR" :
552*0Sstevel@tonic-gate fip->fe_type == FTYPE_SYMLINK ? "SYM" :
553*0Sstevel@tonic-gate fip->fe_type == FTYPE_FILE ? "FILE" : "???", fip->fe_block);
554*0Sstevel@tonic-gate (void) printf(gettext(" COUNT %d SHOULD BE %d"),
555*0Sstevel@tonic-gate fip->fe_lcount, fip->fe_lseen);
556*0Sstevel@tonic-gate if (preen) {
557*0Sstevel@tonic-gate if (fip->fe_lseen > fip->fe_lcount) {
558*0Sstevel@tonic-gate (void) printf("\n");
559*0Sstevel@tonic-gate pfatal(gettext("LINK COUNT INCREASING"));
560*0Sstevel@tonic-gate }
561*0Sstevel@tonic-gate (void) printf(gettext(" (ADJUSTED)\n"));
562*0Sstevel@tonic-gate }
563*0Sstevel@tonic-gate if (preen || reply(gettext("ADJUST")) == 1) {
564*0Sstevel@tonic-gate fp->fe_lcount = fip->fe_lseen;
565*0Sstevel@tonic-gate putfilentry(bp);
566*0Sstevel@tonic-gate dirty(bp);
567*0Sstevel@tonic-gate flush(fswritefd, bp);
568*0Sstevel@tonic-gate }
569*0Sstevel@tonic-gate bp->b_flags &= ~B_INUSE;
570*0Sstevel@tonic-gate }
571*0Sstevel@tonic-gate
572*0Sstevel@tonic-gate void
dofreemap()573*0Sstevel@tonic-gate dofreemap()
574*0Sstevel@tonic-gate {
575*0Sstevel@tonic-gate register int i;
576*0Sstevel@tonic-gate register char *bp, *fp;
577*0Sstevel@tonic-gate struct inodesc idesc;
578*0Sstevel@tonic-gate
579*0Sstevel@tonic-gate if (freemap == NULL)
580*0Sstevel@tonic-gate return;
581*0Sstevel@tonic-gate
582*0Sstevel@tonic-gate /* Flip bits in the busy map */
583*0Sstevel@tonic-gate bp = busymap;
584*0Sstevel@tonic-gate for (i = 0, bp = busymap; i < part_bmp_bytes; i++, bp++)
585*0Sstevel@tonic-gate *bp = ~*bp;
586*0Sstevel@tonic-gate
587*0Sstevel@tonic-gate /* Mark leftovers in byte as allocated */
588*0Sstevel@tonic-gate if (part_len % NBBY)
589*0Sstevel@tonic-gate bp[-1] &= (unsigned)0xff >> (NBBY - part_len % NBBY);
590*0Sstevel@tonic-gate bp = busymap;
591*0Sstevel@tonic-gate fp = freemap;
592*0Sstevel@tonic-gate bzero((char *)&idesc, sizeof (struct inodesc));
593*0Sstevel@tonic-gate idesc.id_type = ADDR;
594*0Sstevel@tonic-gate if (bcmp(bp, fp, part_bmp_bytes) != 0 &&
595*0Sstevel@tonic-gate dofix(&idesc, gettext("BLK(S) MISSING IN FREE BITMAP"))) {
596*0Sstevel@tonic-gate bcopy(bp, fp, part_bmp_bytes);
597*0Sstevel@tonic-gate maketag(&spacep->sbd_tag, &spacep->sbd_tag);
598*0Sstevel@tonic-gate bwrite(fswritefd, (char *)spacep, fsbtodb(part_bmp_loc),
599*0Sstevel@tonic-gate part_bmp_sectors * secsize);
600*0Sstevel@tonic-gate }
601*0Sstevel@tonic-gate }
602*0Sstevel@tonic-gate
603*0Sstevel@tonic-gate void
dolvint()604*0Sstevel@tonic-gate dolvint()
605*0Sstevel@tonic-gate {
606*0Sstevel@tonic-gate struct lvid_iu *lviup;
607*0Sstevel@tonic-gate struct inodesc idesc;
608*0Sstevel@tonic-gate
609*0Sstevel@tonic-gate bzero((char *)&idesc, sizeof (struct inodesc));
610*0Sstevel@tonic-gate idesc.id_type = ADDR;
611*0Sstevel@tonic-gate lviup = (struct lvid_iu *)&lvintp->lvid_fst[2];
612*0Sstevel@tonic-gate if ((lvintp->lvid_fst[0] != part_len - n_blks ||
613*0Sstevel@tonic-gate lvintp->lvid_int_type != LVI_CLOSE ||
614*0Sstevel@tonic-gate lviup->lvidiu_nfiles != n_files ||
615*0Sstevel@tonic-gate lviup->lvidiu_ndirs != n_dirs ||
616*0Sstevel@tonic-gate lvintp->lvid_uniqid < maxuniqid) &&
617*0Sstevel@tonic-gate dofix(&idesc, gettext("LOGICAL VOLUME INTEGRITY COUNTS WRONG"))) {
618*0Sstevel@tonic-gate lvintp->lvid_int_type = LVI_CLOSE;
619*0Sstevel@tonic-gate lvintp->lvid_fst[0] = part_len - n_blks;
620*0Sstevel@tonic-gate lviup->lvidiu_nfiles = n_files;
621*0Sstevel@tonic-gate lviup->lvidiu_ndirs = n_dirs;
622*0Sstevel@tonic-gate lvintp->lvid_uniqid = maxuniqid;
623*0Sstevel@tonic-gate maketag(&lvintp->lvid_tag, &lvintp->lvid_tag);
624*0Sstevel@tonic-gate bwrite(fswritefd, (char *)lvintp, fsbtodb(lvintblock),
625*0Sstevel@tonic-gate lvintlen);
626*0Sstevel@tonic-gate }
627*0Sstevel@tonic-gate }
628