dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / fs.d / udfs / fsck / setup.c
blobea1c5f7cef470de87025665db1e4f8ef2b2ae652
1 /*
2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
7 /* All Rights Reserved */
9 /*
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 #define DKTYPENAMES
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <ustat.h>
34 #include <errno.h>
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>
40 #include <sys/dkio.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>
45 #include <sys/stat.h>
46 #include <sys/file.h>
47 #include <sys/fcntl.h>
48 #include <string.h>
49 #include <sys/vfstab.h>
50 #include <sys/fs/udf_volume.h>
51 #include <sys/vtoc.h>
52 #include <locale.h>
54 #include "fsck.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();
62 extern void ckfini();
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)
73 extern int mflag;
74 extern char hotroot;
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 */
81 char *
82 setup(char *dev)
84 dev_t rootdev;
85 struct stat statb;
86 static char devstr[MAXPATHLEN];
87 char *raw, *rawname(), *unrawname();
88 struct ustat ustatb;
90 havesb = 0;
91 if (stat("/", &statb) < 0)
92 errexit(gettext("Can't stat root\n"));
93 rootdev = statb.st_dev;
95 devname = devstr;
96 (void) strncpy(devstr, dev, sizeof (devstr));
97 restat:
98 if (stat(devstr, &statb) < 0) {
99 (void) printf(gettext("Can't stat %s\n"), devstr);
100 exitstat = 34;
101 return (0);
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);
112 return (0);
115 if ((statb.st_mode & S_IFMT) == S_IFBLK) {
116 if (rootdev == statb.st_rdev)
117 hotroot++;
118 else if (ustat(statb.st_rdev, &ustatb) == 0) {
119 (void) printf(gettext("%s is a mounted file system, "
120 "ignored\n"), dev);
121 exitstat = 33;
122 return (0);
125 if ((statb.st_mode & S_IFMT) == S_IFDIR) {
126 FILE *vfstab;
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"),
133 VFSTAB);
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);
144 return (0);
146 (void) strcpy(devstr, vfsbuf.vfs_special);
147 if (rflag) {
148 raw = rawname(
149 unrawname(vfsbuf.vfs_special));
150 (void) strcpy(devstr, raw);
152 goto restat;
155 (void) fclose(vfstab);
157 } else if (((statb.st_mode & S_IFMT) != S_IFBLK) &&
158 ((statb.st_mode & S_IFMT) != S_IFCHR)) {
159 if (preen)
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"))
164 == 0)
165 return (0);
167 * To fsck regular files (fs images)
168 * we need to clear the rflag since
169 * regular files don't have raw names. --CW
171 rflag = 0;
174 if (mounted(devstr)) {
175 if (rflag)
176 mountedfs++;
177 else {
178 (void) printf(gettext("%s is mounted, fsck on BLOCK "
179 "device ignored\n"), devstr);
180 exit(33);
182 sync(); /* call sync, only when devstr's mounted */
184 if (rflag) {
185 char blockname[MAXPATHLEN];
187 * For root device check, must check
188 * block devices.
190 (void) strcpy(blockname, devstr);
191 if (stat(unrawname(blockname), &statb) < 0) {
192 (void) printf(gettext("Can't stat %s\n"), blockname);
193 exitstat = 34;
194 return (0);
197 if (rootdev == statb.st_rdev)
198 hotroot++;
199 if ((fsreadfd = open(devstr, O_RDONLY)) < 0) {
200 (void) printf(gettext("Can't open %s\n"), devstr);
201 exitstat = 34;
202 return (0);
204 if (preen == 0 || debug != 0)
205 (void) printf("** %s", devstr);
207 if (nflag || (fswritefd = open(devstr, O_WRONLY)) < 0) {
208 fswritefd = -1;
209 if (preen && !debug)
210 pfatal(gettext("(NO WRITE ACCESS)\n"));
211 (void) printf(gettext(" (NO WRITE)"));
213 if (preen == 0)
214 (void) printf("\n");
215 if (debug && (hotroot || mountedfs)) {
216 (void) printf("** %s", devstr);
217 if (hotroot)
218 (void) printf(" is root fs%s",
219 mountedfs? " and": "");
220 if (mountedfs)
221 (void) printf(" is mounted");
223 (void) printf(".\n");
225 fsmodified = 0;
226 if (readvolseq(1) == 0)
227 return (0);
228 if (fflag == 0 && preen &&
229 lvintp->lvid_int_type == LVI_CLOSE) {
230 iscorrupt = 0;
231 printclean();
232 return (0);
234 listmax = FEGROW;
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));
242 goto badsb;
244 inpnext = inphead;
245 inplast = &inphead[listmax];
247 bufinit();
248 return (devstr);
250 badsb:
251 ckfini();
252 exitstat = 39;
253 return (0);
256 static int
257 check_pri_vol_desc(struct tag *tp)
259 pvolp = (struct pri_vol_desc *)tp;
260 return (0);
263 static int
264 check_avdp(struct tag *tp)
266 avdp = (struct anch_vol_desc_ptr *)tp;
267 return (0);
270 static int
271 check_vdp(struct tag *tp)
273 volp = (struct vdp_desc *)tp;
274 return (0);
277 static int
278 check_iuvd(struct tag *tp)
280 iudp = (struct iuvd_desc *)tp;
281 return (0);
284 static int
285 check_part_desc(struct tag *tp)
287 partp = (struct part_desc *)tp;
288 /* LINTED */
289 pheadp = (struct phdr_desc *)&partp->pd_pc_use;
290 part_start = partp->pd_part_start;
291 part_len = partp->pd_part_length;
292 if (debug)
293 (void) printf("partition start %x len %x\n", part_start,
294 part_len);
295 return (0);
298 static int
299 check_log_desc(struct tag *tp)
301 logvp = (struct log_vol_desc *)tp;
302 return (0);
305 static int
306 check_unall_desc(struct tag *tp)
308 unallp = (struct unall_desc *)tp;
309 return (0);
312 /* ARGSUSED */
313 static int
314 check_term_desc(struct tag *tp)
316 return (0);
319 static int
320 check_lvint(struct tag *tp)
322 /* LINTED */
323 lvintp = (struct log_vol_int_desc *)tp;
324 return (0);
327 void
328 dump16(char *cp, char *nl)
330 int i;
331 long *ptr;
334 for (i = 0; i < 16; i += 4) {
335 /* LINTED */
336 ptr = (long *)(cp + i);
337 (void) printf("%08lx ", *ptr);
339 (void) printf(nl);
343 * Read in the super block and its summary info.
345 /* ARGSUSED */
346 static int
347 readvolseq(int32_t listerr)
349 struct tag *tp;
350 long_ad_t *lap;
351 struct anch_vol_desc_ptr *avp;
352 uint8_t *cp, *end;
353 daddr_t nextblock;
354 int err;
355 long freelen;
356 daddr_t avdp;
358 disk_size = get_last_block();
359 if (debug)
360 (void) printf("Disk partition size: %x\n", disk_size);
362 /* LINTED */
363 avp = (struct anch_vol_desc_ptr *)avdbuf;
364 tp = &avp->avd_tag;
365 for (fsbsize = 512; fsbsize <= MAXBSIZE; fsbsize <<= 1) {
366 avdp = FIRSTAVDP * fsbsize / DEV_BSIZE;
367 if (bread(fsreadfd, avdbuf, avdp, fsbsize) != 0)
368 return (0);
369 err = verifytag(tp, FIRSTAVDP, tp, UD_ANCH_VOL_DESC);
370 if (debug)
371 (void) printf("bsize %ld tp->tag %d, %s\n", fsbsize,
372 tp->tag_id, tagerrs[err]);
373 if (err == 0)
374 break;
376 if (fsbsize > MAXBSIZE)
377 errexit(gettext("Can't find anchor volume descriptor\n"));
378 secsize = fsbsize;
379 if (debug)
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");
385 if (debug)
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)
392 return (0);
393 if (bread(fsreadfd, res_vdbuf, fsbtodb(avp->avd_res_vdse.ext_loc),
394 avp->avd_res_vdse.ext_len) != 0)
395 return (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++) {
399 /* LINTED */
400 tp = (struct tag *)cp;
401 err = verifytag(tp, nextblock, tp, 0);
402 if (debug) {
403 dump16((char *)cp, "");
404 (void) printf("blk %lx err %s tag %d\n", nextblock,
405 tagerrs[err], tp->tag_id);
407 if (err == 0) {
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,
411 nextblock);
412 continue;
414 switch (tp->tag_id) {
415 case UD_PRI_VOL_DESC:
416 serialnum = tp->tag_sno;
417 if (debug) {
418 (void) printf("serial number = %d\n",
419 serialnum);
421 err = check_pri_vol_desc(tp);
422 break;
423 case UD_ANCH_VOL_DESC:
424 err = check_avdp(tp);
425 break;
426 case UD_VOL_DESC_PTR:
427 err = check_vdp(tp);
428 break;
429 case UD_IMPL_USE_DESC:
430 err = check_iuvd(tp);
431 break;
432 case UD_PART_DESC:
433 err = check_part_desc(tp);
434 break;
435 case UD_LOG_VOL_DESC:
436 err = check_log_desc(tp);
437 break;
438 case UD_UNALL_SPA_DESC:
439 err = check_unall_desc(tp);
440 break;
441 case UD_TERM_DESC:
442 err = check_term_desc(tp);
443 goto done;
444 break;
445 case UD_LOG_VOL_INT:
446 err = check_lvint(tp);
447 break;
448 default:
449 (void) printf(gettext("Invalid volume "
450 "sequence tag %d\n"), tp->tag_id);
452 } else {
453 (void) printf(gettext("Volume sequence tag error %s\n"),
454 tagerrs[err]);
457 done:
458 if (!partp || !logvp) {
459 (void) printf(gettext("Missing partition header or"
460 " logical volume descriptor\n"));
461 return (0);
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);
468 if (debug)
469 (void) printf("Logvolint at %x for %d bytes\n", lvintblock,
470 lvintlen);
471 if (lvintp == NULL) {
472 (void) printf(gettext("Can't allocate space for logical"
473 " volume integrity sequence\n"));
474 return (0);
476 if (bread(fsreadfd, (char *)lvintp,
477 fsbtodb(lvintblock), lvintlen) != 0) {
478 return (0);
480 err = verifytag(&lvintp->lvid_tag, lvintblock, &lvintp->lvid_tag,
481 UD_LOG_VOL_INT);
482 if (debug) {
483 dump16((char *)lvintp, "\n");
485 if (err) {
486 (void) printf(gettext("Log_vol_int tag error: %s, tag = %d\n"),
487 tagerrs[err], lvintp->lvid_tag.tag_id);
488 return (0);
491 /* Get pointer to implementation use area */
492 lviup = (struct lvid_iu *)&lvintp->lvid_fst[lvintp->lvid_npart*2];
493 if (debug) {
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;
502 if (freelen == 0) {
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"));
509 return (0);
511 if (freelen) {
512 part_bmp_sectors =
513 (part_bmp_bytes + SPACEMAP_OFF + secsize - 1) /
514 secsize;
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 "
525 "map\n"));
526 return (0);
528 if (bread(fsreadfd, (char *)spacep, fsbtodb(part_bmp_loc),
529 part_bmp_sectors * secsize) != 0)
530 return (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);
534 if (debug) {
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;
540 if (debug)
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);
546 if (err) {
547 (void) printf(gettext("Space bitmap tag error, %s, "
548 "tag = %d\n"),
549 tagerrs[err], spacep->sbd_tag.tag_id);
550 return (0);
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);
559 if (debug)
560 (void) printf("Fileset descriptor at %x for %d bytes\n",
561 filesetblock, filesetlen);
562 if (!filesetlen) {
563 (void) printf(gettext("No file set descriptor found\n"));
564 return (0);
566 fileset = (struct file_set_desc *)malloc(filesetlen);
567 if (fileset == NULL) {
568 (void) printf(gettext("Unable to allocate fileset\n"));
569 return (0);
571 if (bread(fsreadfd, (char *)fileset, fsbtodb(filesetblock + part_start),
572 filesetlen) != 0) {
573 return (0);
575 err = verifytag(&fileset->fsd_tag, filesetblock, &fileset->fsd_tag,
576 UD_FILE_SET_DESC);
577 if (err) {
578 (void) printf(gettext("Fileset tag error, tag = %d, %s\n"),
579 fileset->fsd_tag.tag_id, tagerrs[err]);
580 return (0);
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;
587 if (debug)
588 (void) printf("Root at %x for %d bytes\n", rootblock, rootlen);
590 havesb = 1;
591 return (1);
594 uint32_t
595 get_last_block()
597 struct vtoc vtoc;
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"));
602 return (0);
605 if (vtoc.v_sanity != VTOC_SANE) {
606 (void) fprintf(stderr, gettext("Vtoc.v_sanity != VTOC_SANE\n"));
607 return (0);
610 if (ioctl(fsreadfd, DKIOCINFO, (intptr_t)&dki_info) != 0) {
611 (void) fprintf(stderr,
612 gettext("Could not get the slice information\n"));
613 return (0);
616 if (dki_info.dki_partition > V_NUMPAR) {
617 (void) fprintf(stderr,
618 gettext("dki_info.dki_partition > V_NUMPAR\n"));
619 return (0);
622 return ((uint32_t)vtoc.v_part[dki_info.dki_partition].p_size);