17c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 37c478bd9Sstevel@tonic-gate 47c478bd9Sstevel@tonic-gate /* 57c478bd9Sstevel@tonic-gate * Copyright (c) 1980, 1986, 1990 The Regents of the University of California. 67c478bd9Sstevel@tonic-gate * All rights reserved. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms are permitted 97c478bd9Sstevel@tonic-gate * provided that: (1) source distributions retain this entire copyright 107c478bd9Sstevel@tonic-gate * notice and comment, and (2) distributions including binaries display 117c478bd9Sstevel@tonic-gate * the following acknowledgement: ``This product includes software 127c478bd9Sstevel@tonic-gate * developed by the University of California, Berkeley and its contributors'' 137c478bd9Sstevel@tonic-gate * in the documentation or other materials provided with the distribution 147c478bd9Sstevel@tonic-gate * and in all advertising materials mentioning features or use of this 157c478bd9Sstevel@tonic-gate * software. Neither the name of the University nor the names of its 167c478bd9Sstevel@tonic-gate * contributors may be used to endorse or promote products derived 177c478bd9Sstevel@tonic-gate * from this software without specific prior written permission. 187c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 197c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 207c478bd9Sstevel@tonic-gate * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate 237c478bd9Sstevel@tonic-gate /* 24*355d6bb5Sswilcox * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #ifndef _FSCK_FSCK_H 297c478bd9Sstevel@tonic-gate #define _FSCK_FSCK_H 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.3 */ 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #ifdef __cplusplus 347c478bd9Sstevel@tonic-gate extern "C" { 357c478bd9Sstevel@tonic-gate #endif 367c478bd9Sstevel@tonic-gate 37*355d6bb5Sswilcox #include <stdio.h> 38*355d6bb5Sswilcox #include <stdarg.h> 39*355d6bb5Sswilcox #include <search.h> 40*355d6bb5Sswilcox #include <sys/param.h> 41*355d6bb5Sswilcox #include <sys/types.h> 42*355d6bb5Sswilcox #include <sys/mnttab.h> 43*355d6bb5Sswilcox #include <sys/vfstab.h> 44*355d6bb5Sswilcox #include <sys/fs/ufs_fs.h> 45*355d6bb5Sswilcox #include <sys/fs/ufs_inode.h> 46*355d6bb5Sswilcox 477c478bd9Sstevel@tonic-gate #define MAXDUP 10 /* limit on dup blks (per inode) */ 487c478bd9Sstevel@tonic-gate #define MAXBAD 10 /* limit on bad blks (per inode) */ 49*355d6bb5Sswilcox #define MAXBUFSPACE 40*1024 /* initial space to allocate to buffers */ 507c478bd9Sstevel@tonic-gate #define INOBUFSIZE 56*1024 /* size of buffer to read inodes in pass1 */ 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate #ifndef BUFSIZ 53*355d6bb5Sswilcox #define BUFSIZ MAXPATHLEN 547c478bd9Sstevel@tonic-gate #endif 557c478bd9Sstevel@tonic-gate 56*355d6bb5Sswilcox /* 57*355d6bb5Sswilcox * Inode states in statemap[]. 58*355d6bb5Sswilcox */ 59*355d6bb5Sswilcox #define USTATE 0x01 /* inode not allocated */ 60*355d6bb5Sswilcox #define FSTATE 0x02 /* inode is file */ 61*355d6bb5Sswilcox #define DSTATE 0x04 /* inode is directory */ 62*355d6bb5Sswilcox #define SSTATE 0x08 /* inode is a shadow/acl */ 63*355d6bb5Sswilcox #define STMASK 0x0f /* pick off the basic state/type */ 64*355d6bb5Sswilcox 65*355d6bb5Sswilcox /* flags OR'd into the above */ 66*355d6bb5Sswilcox #define INZLINK 0x0010 /* inode has zero links */ 67*355d6bb5Sswilcox #define INFOUND 0x0020 /* inode was found during descent */ 68*355d6bb5Sswilcox #define INCLEAR 0x0040 /* inode is to be cleared */ 69*355d6bb5Sswilcox #define INORPHAN 0x0080 /* inode is a known orphan (pass3 only) */ 70*355d6bb5Sswilcox #define INDELAYD 0x0200 /* link count update delayed */ 71*355d6bb5Sswilcox #define INMASK 0xfff0 /* pick off the modifiers */ 72*355d6bb5Sswilcox 73*355d6bb5Sswilcox #define FZLINK (FSTATE | INZLINK) 74*355d6bb5Sswilcox #define DZLINK (DSTATE | INZLINK) 75*355d6bb5Sswilcox #define SZLINK (SSTATE | INZLINK) 76*355d6bb5Sswilcox 77*355d6bb5Sswilcox #define DFOUND (DSTATE | INFOUND) 78*355d6bb5Sswilcox 79*355d6bb5Sswilcox #define DCLEAR (DSTATE | INCLEAR) 80*355d6bb5Sswilcox #define FCLEAR (FSTATE | INCLEAR) 81*355d6bb5Sswilcox #define SCLEAR (SSTATE | INCLEAR) 82*355d6bb5Sswilcox 83*355d6bb5Sswilcox /* 84*355d6bb5Sswilcox * These tests depend on the state/type defines above not overlapping bits. 85*355d6bb5Sswilcox * 86*355d6bb5Sswilcox * DUNFOUND === (state == DSTATE || state == DZLINK) 87*355d6bb5Sswilcox * INCLEAR is irrelevant to the determination of 88*355d6bb5Sswilcox * connectedness, so it's not included in this test. 89*355d6bb5Sswilcox * 90*355d6bb5Sswilcox * DVALID === (state == DSTATE || state == DZLINK || state == DFOUND) 91*355d6bb5Sswilcox */ 92*355d6bb5Sswilcox #define S_IS_DUNFOUND(state) (((state) & (DSTATE | INZLINK)) \ 93*355d6bb5Sswilcox == (state)) 94*355d6bb5Sswilcox #define S_IS_DVALID(state) (((state) & (DSTATE | INZLINK | INFOUND | \ 95*355d6bb5Sswilcox INORPHAN)) == (state)) 96*355d6bb5Sswilcox #define S_IS_ZLINK(state) (((state) & INZLINK) != 0) 97*355d6bb5Sswilcox #define INO_IS_DUNFOUND(ino) S_IS_DUNFOUND(statemap[ino]) 98*355d6bb5Sswilcox #define INO_IS_DVALID(ino) S_IS_DVALID(statemap[ino]) 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate /* 1017c478bd9Sstevel@tonic-gate * buffer cache structure. 1027c478bd9Sstevel@tonic-gate */ 1037c478bd9Sstevel@tonic-gate struct bufarea { 1047c478bd9Sstevel@tonic-gate struct bufarea *b_next; /* free list queue */ 1057c478bd9Sstevel@tonic-gate struct bufarea *b_prev; /* free list queue */ 106*355d6bb5Sswilcox diskaddr_t b_bno; /* physical sector number */ 1077c478bd9Sstevel@tonic-gate int b_size; 1087c478bd9Sstevel@tonic-gate int b_errs; 1097c478bd9Sstevel@tonic-gate int b_flags; 1107c478bd9Sstevel@tonic-gate int b_cnt; /* reference cnt */ 1117c478bd9Sstevel@tonic-gate union { 1127c478bd9Sstevel@tonic-gate char *b_buf; /* buffer space */ 1137c478bd9Sstevel@tonic-gate daddr32_t *b_indir; /* indirect block */ 1147c478bd9Sstevel@tonic-gate struct fs *b_fs; /* super block */ 1157c478bd9Sstevel@tonic-gate struct cg *b_cg; /* cylinder group */ 1167c478bd9Sstevel@tonic-gate struct dinode *b_dinode; /* inode block */ 1177c478bd9Sstevel@tonic-gate } b_un; 1187c478bd9Sstevel@tonic-gate char b_dirty; 1197c478bd9Sstevel@tonic-gate }; 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate #define B_INUSE 1 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate #define MINBUFS 5 /* minimum number of buffers required */ 1247c478bd9Sstevel@tonic-gate struct bufarea bufhead; /* head of list of other blks in filesys */ 1257c478bd9Sstevel@tonic-gate struct bufarea sblk; /* file system superblock */ 126*355d6bb5Sswilcox struct bufarea asblk; /* alternate superblock */ 1277c478bd9Sstevel@tonic-gate struct bufarea cgblk; /* cylinder group blocks */ 1287c478bd9Sstevel@tonic-gate struct bufarea *pbp; /* pointer to inode data in buffer pool */ 1297c478bd9Sstevel@tonic-gate struct bufarea *pdirbp; /* pointer to directory data in buffer pool */ 1307c478bd9Sstevel@tonic-gate 131*355d6bb5Sswilcox #define sbdirty() dirty(&sblk) 132*355d6bb5Sswilcox #define cgdirty() dirty(&cgblk) 1337c478bd9Sstevel@tonic-gate #define sblock (*sblk.b_un.b_fs) 1347c478bd9Sstevel@tonic-gate #define cgrp (*cgblk.b_un.b_cg) 1357c478bd9Sstevel@tonic-gate 136*355d6bb5Sswilcox /* 137*355d6bb5Sswilcox * inodesc.id_fix values. See inode.c for a description of their usage. 138*355d6bb5Sswilcox */ 139*355d6bb5Sswilcox enum fixstate { 140*355d6bb5Sswilcox DONTKNOW, NOFIX, FIX, IGNORE 141*355d6bb5Sswilcox }; 142*355d6bb5Sswilcox 143*355d6bb5Sswilcox /* 144*355d6bb5Sswilcox * Tells truncino() whether or not to attempt to update the parent 145*355d6bb5Sswilcox * directory's link count. Also, TI_NODUP flags when we're discarding 146*355d6bb5Sswilcox * fragments that are beyond the original end of the file, and so 147*355d6bb5Sswilcox * should not be considered duplicate-claim candidates. 148*355d6bb5Sswilcox */ 149*355d6bb5Sswilcox #define TI_NOPARENT 0x0001 /* leave parent's di_nlink alone */ 150*355d6bb5Sswilcox #define TI_PARENT 0x0002 /* update parent's di_nlink */ 151*355d6bb5Sswilcox #define TI_NODUP 0x0004 /* not a dup candidate */ 152*355d6bb5Sswilcox 153*355d6bb5Sswilcox /* 154*355d6bb5Sswilcox * Modes for ckinode() and ckinode_common(). 155*355d6bb5Sswilcox * 156*355d6bb5Sswilcox * CKI_TRAVERSE is the common case, and requests a traditional 157*355d6bb5Sswilcox * traversal of blocks or directory entries. 158*355d6bb5Sswilcox * 159*355d6bb5Sswilcox * CKI_TRUNCATE indicates that we're truncating the file, and that any 160*355d6bb5Sswilcox * block indices beyond the end of the target length should be cleared 161*355d6bb5Sswilcox * after the callback has returned (i.e., this is a superset of 162*355d6bb5Sswilcox * CKI_TRAVERSE). idesc->id_truncto is the first logical block number 163*355d6bb5Sswilcox * to clear. If it is less than zero, then the traversal will be 164*355d6bb5Sswilcox * equivalent to a simple CKI_TRAVERSE. 165*355d6bb5Sswilcox */ 166*355d6bb5Sswilcox enum cki_action { CKI_TRAVERSE, CKI_TRUNCATE }; 167*355d6bb5Sswilcox 168*355d6bb5Sswilcox /* 169*355d6bb5Sswilcox * The general definition of an ino_t is an unsigned quantity. 170*355d6bb5Sswilcox * However, the on-disk version is an int32_t, which is signed. 171*355d6bb5Sswilcox * Since we really want to be able to detect wrapped-around 172*355d6bb5Sswilcox * inode numbers and such, we'll use something that's compatible 173*355d6bb5Sswilcox * with what's on disk since that's the only context that really 174*355d6bb5Sswilcox * matters. If an int32_t is found not to be sufficiently large, 175*355d6bb5Sswilcox * this will make it much easier to change later. 176*355d6bb5Sswilcox * 177*355d6bb5Sswilcox * Note that there is one unsigned inode field in the on-disk 178*355d6bb5Sswilcox * inode, ic_oeftflag. Since all other inode fields are signed, 179*355d6bb5Sswilcox * no legitimate inode number can be put into ic_oeftflag that 180*355d6bb5Sswilcox * would overflow into the high bit. Essentially, it should 181*355d6bb5Sswilcox * actually be declared as int32_t just like all the others, and 182*355d6bb5Sswilcox * we're going to pretend that it was. 183*355d6bb5Sswilcox * 184*355d6bb5Sswilcox * None of the routines that we use in ufs_subr.c do anything with 185*355d6bb5Sswilcox * inode numbers. If that changes, then great care will be needed 186*355d6bb5Sswilcox * to deal with the differences in definition of ino_t and fsck_ino_t. 187*355d6bb5Sswilcox * Lint is your friend. 188*355d6bb5Sswilcox */ 189*355d6bb5Sswilcox typedef int32_t fsck_ino_t; 1907c478bd9Sstevel@tonic-gate 191*355d6bb5Sswilcox /* 192*355d6bb5Sswilcox * See the full discussion of the interactions between struct inodesc 193*355d6bb5Sswilcox * and ckinode() in inode.c 194*355d6bb5Sswilcox */ 1957c478bd9Sstevel@tonic-gate struct inodesc { 1967c478bd9Sstevel@tonic-gate enum fixstate id_fix; /* policy on fixing errors */ 197*355d6bb5Sswilcox int (*id_func)(struct inodesc *); 198*355d6bb5Sswilcox /* function to be applied to blocks of inode */ 199*355d6bb5Sswilcox fsck_ino_t id_number; /* inode number described */ 200*355d6bb5Sswilcox fsck_ino_t id_parent; /* for DATA nodes, their parent */ 201*355d6bb5Sswilcox /* also used for extra (*id_func) parameter */ 202*355d6bb5Sswilcox /* and return values */ 203*355d6bb5Sswilcox daddr32_t id_lbn; /* logical fragment number of current block */ 204*355d6bb5Sswilcox daddr32_t id_blkno; /* physical fragment number being examined */ 2057c478bd9Sstevel@tonic-gate int id_numfrags; /* number of frags contained in block */ 206*355d6bb5Sswilcox daddr32_t id_truncto; /* # blocks to truncate to, -1 for no trunc. */ 2077c478bd9Sstevel@tonic-gate offset_t id_filesize; /* for DATA nodes, the size of the directory */ 208*355d6bb5Sswilcox uint_t id_loc; /* for DATA nodes, current location in dir */ 209*355d6bb5Sswilcox daddr32_t id_entryno; /* for DATA nodes, current dir entry number */ 210*355d6bb5Sswilcox daddr32_t id_firsthole; /* for DATA inode, logical block that is */ 211*355d6bb5Sswilcox /* zero but shouldn't be, -1 for no holes */ 2127c478bd9Sstevel@tonic-gate struct direct *id_dirp; /* for DATA nodes, ptr to current entry */ 213*355d6bb5Sswilcox caddr_t id_name; /* for DATA nodes, name to find or enter */ 2147c478bd9Sstevel@tonic-gate char id_type; /* type of descriptor, DATA or ADDR */ 2157c478bd9Sstevel@tonic-gate }; 216*355d6bb5Sswilcox 217*355d6bb5Sswilcox /* file types (0 is reserved for catching bugs) */ 218*355d6bb5Sswilcox #define DATA 1 /* a directory */ 219*355d6bb5Sswilcox #define ACL 2 /* an acl/shadow */ 220*355d6bb5Sswilcox #define ADDR 3 /* anything but a directory or an acl/shadow */ 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate /* 223*355d6bb5Sswilcox * OR'd flags for find_dup_ref()'s mode argument 2247c478bd9Sstevel@tonic-gate */ 225*355d6bb5Sswilcox #define DB_CREATE 0x01 /* if dup record found, make one */ 226*355d6bb5Sswilcox #define DB_INCR 0x02 /* increment block's reference count */ 227*355d6bb5Sswilcox #define DB_DECR 0x04 /* decrement block's reference count */ 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate /* 230*355d6bb5Sswilcox * Cache data structures 2317c478bd9Sstevel@tonic-gate */ 232*355d6bb5Sswilcox struct inoinfo { 233*355d6bb5Sswilcox struct inoinfo *i_nextlist; /* next inode/acl cache entry */ 234*355d6bb5Sswilcox fsck_ino_t i_number; /* inode number of this entry */ 235*355d6bb5Sswilcox fsck_ino_t i_parent; /* inode number of parent */ 236*355d6bb5Sswilcox fsck_ino_t i_dotdot; /* inode number of .. */ 237*355d6bb5Sswilcox fsck_ino_t i_extattr; /* inode of hidden attr dir */ 238*355d6bb5Sswilcox offset_t i_isize; /* size of inode */ 239*355d6bb5Sswilcox size_t i_blkssize; /* size of block array in bytes */ 240*355d6bb5Sswilcox daddr32_t i_blks[1]; /* actually longer */ 2417c478bd9Sstevel@tonic-gate }; 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate /* 244*355d6bb5Sswilcox * Inode cache 2457c478bd9Sstevel@tonic-gate */ 246*355d6bb5Sswilcox struct inoinfo **inphead, **inpsort; 2477c478bd9Sstevel@tonic-gate int64_t numdirs, listmax, inplast; 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate /* 250*355d6bb5Sswilcox * ACL cache 2517c478bd9Sstevel@tonic-gate */ 252*355d6bb5Sswilcox struct inoinfo **aclphead, **aclpsort; 2537c478bd9Sstevel@tonic-gate int64_t numacls, aclmax, aclplast; 2547c478bd9Sstevel@tonic-gate 255*355d6bb5Sswilcox /* 256*355d6bb5Sswilcox * Tree of directories we haven't reconnected or cleared. Any 257*355d6bb5Sswilcox * dir inode that linkup() fails on gets added, any that clri() 258*355d6bb5Sswilcox * succeeds on gets removed. If there are any left at the end of 259*355d6bb5Sswilcox * pass four, then we have a user-forced corrupt filesystem, and 260*355d6bb5Sswilcox * need to set iscorrupt. 261*355d6bb5Sswilcox * 262*355d6bb5Sswilcox * Elements are fsck_ino_t instances (not pointers). 263*355d6bb5Sswilcox */ 264*355d6bb5Sswilcox void *limbo_dirs; 265*355d6bb5Sswilcox 266*355d6bb5Sswilcox /* 267*355d6bb5Sswilcox * Number of directories we actually found in the filesystem, 268*355d6bb5Sswilcox * as opposed to how many the superblock claims there are. 269*355d6bb5Sswilcox */ 270*355d6bb5Sswilcox fsck_ino_t countdirs; 271*355d6bb5Sswilcox 2727c478bd9Sstevel@tonic-gate /* 2737c478bd9Sstevel@tonic-gate * shadowclients and shadowclientinfo are structures for keeping track of 2747c478bd9Sstevel@tonic-gate * shadow inodes that exist, and which regular inodes use them (i.e. are 2757c478bd9Sstevel@tonic-gate * their clients). 2767c478bd9Sstevel@tonic-gate */ 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate struct shadowclients { 279*355d6bb5Sswilcox fsck_ino_t *client; /* an array of inode numbers */ 2807c478bd9Sstevel@tonic-gate int nclients; /* how many inodes in the array are in use (valid) */ 2817c478bd9Sstevel@tonic-gate struct shadowclients *next; /* link to more client inode numbers */ 2827c478bd9Sstevel@tonic-gate }; 2837c478bd9Sstevel@tonic-gate struct shadowclientinfo { 284*355d6bb5Sswilcox fsck_ino_t shadow; /* the shadow inode that this info is for */ 2857c478bd9Sstevel@tonic-gate int totalClients; /* how many inodes total refer to this */ 2867c478bd9Sstevel@tonic-gate struct shadowclients *clients; /* a linked list of wads of clients */ 2877c478bd9Sstevel@tonic-gate struct shadowclientinfo *next; /* link to the next shadow inode */ 2887c478bd9Sstevel@tonic-gate }; 2897c478bd9Sstevel@tonic-gate /* global pointer to this shadow/client information */ 290*355d6bb5Sswilcox struct shadowclientinfo *shadowclientinfo; 291*355d6bb5Sswilcox struct shadowclientinfo *attrclientinfo; 292*355d6bb5Sswilcox 293*355d6bb5Sswilcox /* 294*355d6bb5Sswilcox * In ufs_inode.h ifdef _KERNEL, this is defined as `/@/'. However, 295*355d6bb5Sswilcox * to avoid all sorts of potential confusion (you can't actually use 296*355d6bb5Sswilcox * `foo/@/bar' to get to an attribute), we use something that doesn't 297*355d6bb5Sswilcox * look quite so much like a simple pathname. 298*355d6bb5Sswilcox */ 299*355d6bb5Sswilcox #define XATTR_DIR_NAME " <xattr> " 300*355d6bb5Sswilcox 301*355d6bb5Sswilcox /* 302*355d6bb5Sswilcox * granularity -- how many client inodes do we make space for at a time 303*355d6bb5Sswilcox * initialized in setup.c; 304*355d6bb5Sswilcox */ 3057c478bd9Sstevel@tonic-gate extern int maxshadowclients; 3067c478bd9Sstevel@tonic-gate 307*355d6bb5Sswilcox /* 308*355d6bb5Sswilcox * Initialized global variables. 309*355d6bb5Sswilcox */ 310*355d6bb5Sswilcox extern caddr_t lfname; 311*355d6bb5Sswilcox 312*355d6bb5Sswilcox /* 313*355d6bb5Sswilcox * Unitialized globals. 314*355d6bb5Sswilcox */ 3157c478bd9Sstevel@tonic-gate char *devname; /* name of device being checked */ 316*355d6bb5Sswilcox size_t dev_bsize; /* computed value of DEV_BSIZE */ 3177c478bd9Sstevel@tonic-gate int secsize; /* actual disk sector size */ 3187c478bd9Sstevel@tonic-gate char nflag; /* assume a no response */ 3197c478bd9Sstevel@tonic-gate char yflag; /* assume a yes response */ 320*355d6bb5Sswilcox daddr32_t bflag; /* location of alternate super block */ 3217c478bd9Sstevel@tonic-gate int debug; /* output debugging info */ 3227c478bd9Sstevel@tonic-gate int rflag; /* check raw file systems */ 323*355d6bb5Sswilcox int roflag; /* do normal checks but don't update disk */ 3247c478bd9Sstevel@tonic-gate int fflag; /* check regardless of clean flag (force) */ 325*355d6bb5Sswilcox int mflag; /* sanity check only */ 326*355d6bb5Sswilcox int verbose; /* be chatty */ 3277c478bd9Sstevel@tonic-gate char preen; /* just fix normal inconsistencies */ 3287c478bd9Sstevel@tonic-gate char mountedfs; /* checking mounted device */ 329*355d6bb5Sswilcox int exitstat; /* exit status (see EX* defines below) */ 3307c478bd9Sstevel@tonic-gate char hotroot; /* checking root device */ 331*355d6bb5Sswilcox char rerun; /* rerun fsck. Only used in non-preen mode */ 332*355d6bb5Sswilcox int interrupted; /* 1 => exit EXSIGNAL on exit */ 3337c478bd9Sstevel@tonic-gate char havesb; /* superblock has been read */ 3347c478bd9Sstevel@tonic-gate int fsmodified; /* 1 => write done to file system */ 3357c478bd9Sstevel@tonic-gate int fsreadfd; /* file descriptor for reading file system */ 3367c478bd9Sstevel@tonic-gate int fswritefd; /* file descriptor for writing file system */ 3377c478bd9Sstevel@tonic-gate int iscorrupt; /* known to be corrupt/inconsistent */ 338*355d6bb5Sswilcox /* -1 means mark clean so user can mount+fix */ 3397c478bd9Sstevel@tonic-gate int isdirty; /* 1 => write pending to file system */ 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate int islog; /* logging file system */ 3427c478bd9Sstevel@tonic-gate int islogok; /* log is okay */ 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate int errorlocked; /* set => mounted fs has been error-locked */ 3457c478bd9Sstevel@tonic-gate /* implies fflag "force check flag" */ 3467c478bd9Sstevel@tonic-gate char *elock_combuf; /* error lock comment buffer */ 3477c478bd9Sstevel@tonic-gate char *elock_mountp; /* mount point; used to unlock error-lock */ 3487c478bd9Sstevel@tonic-gate int pid; /* fsck's process id (put in lockfs comment) */ 3497c478bd9Sstevel@tonic-gate int mountfd; /* fd of mount point */ 3507c478bd9Sstevel@tonic-gate struct lockfs *lfp; /* current lockfs status */ 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate daddr32_t maxfsblock; /* number of blocks in the file system */ 353*355d6bb5Sswilcox uint_t largefile_count; /* global largefile counter */ 354*355d6bb5Sswilcox char *mount_point; /* if mounted, this is where */ 3557c478bd9Sstevel@tonic-gate char *blockmap; /* ptr to primary blk allocation map */ 356*355d6bb5Sswilcox fsck_ino_t maxino; /* number of inodes in file system */ 357*355d6bb5Sswilcox fsck_ino_t lastino; /* last inode in use */ 358*355d6bb5Sswilcox ushort_t *statemap; /* ptr to inode state table */ 3597c478bd9Sstevel@tonic-gate short *lncntp; /* ptr to link count table */ 3607c478bd9Sstevel@tonic-gate 361*355d6bb5Sswilcox fsck_ino_t lfdir; /* lost & found directory inode number */ 362*355d6bb5Sswilcox int overflowed_lf; /* tried to wrap lost & found's link count */ 363*355d6bb5Sswilcox int reattached_dir; /* reconnected at least one directory */ 364*355d6bb5Sswilcox int broke_dir_link; /* broke at least one directory hardlink */ 3657c478bd9Sstevel@tonic-gate 366*355d6bb5Sswilcox daddr32_t n_blks; /* number of blocks in use */ 367*355d6bb5Sswilcox fsck_ino_t n_files; /* number of files in use */ 3687c478bd9Sstevel@tonic-gate 369*355d6bb5Sswilcox #define clearinode(dp) { \ 370*355d6bb5Sswilcox *(dp) = zino; \ 371*355d6bb5Sswilcox } 3727c478bd9Sstevel@tonic-gate struct dinode zino; 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate #define testbmap(blkno) isset(blockmap, blkno) 375*355d6bb5Sswilcox #define setbmap(blkno) setbit(blockmap, blkno) 3767c478bd9Sstevel@tonic-gate #define clrbmap(blkno) clrbit(blockmap, blkno) 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate #define STOP 0x01 3797c478bd9Sstevel@tonic-gate #define SKIP 0x02 3807c478bd9Sstevel@tonic-gate #define KEEPON 0x04 3817c478bd9Sstevel@tonic-gate #define ALTERED 0x08 3827c478bd9Sstevel@tonic-gate #define FOUND 0x10 3837c478bd9Sstevel@tonic-gate 384*355d6bb5Sswilcox /* 385*355d6bb5Sswilcox * Support relatively easy debugging of lncntp[] updates. This can't 386*355d6bb5Sswilcox * be a function, because of the (_op) step. Normally, we just do that. 387*355d6bb5Sswilcox */ 388*355d6bb5Sswilcox #define TRACK_LNCNTP(_ino, _op) (_op) 389*355d6bb5Sswilcox 390*355d6bb5Sswilcox /* 391*355d6bb5Sswilcox * See if the net link count for an inode has gone outside 392*355d6bb5Sswilcox * what can be represented on disk. Returning text as NULL 393*355d6bb5Sswilcox * indicates no. 394*355d6bb5Sswilcox * 395*355d6bb5Sswilcox * Remember that link counts are effectively inverted, so 396*355d6bb5Sswilcox * underflow and overflow are reversed as well. 397*355d6bb5Sswilcox * 398*355d6bb5Sswilcox * This check should be done before modifying the actual link 399*355d6bb5Sswilcox * count. 400*355d6bb5Sswilcox */ 401*355d6bb5Sswilcox #define LINK_RANGE(text, current, offset) { \ 402*355d6bb5Sswilcox int net = ((int)(current)) + ((int)(offset)); \ 403*355d6bb5Sswilcox text = NULL; \ 404*355d6bb5Sswilcox if (net > (MAXLINK)) \ 405*355d6bb5Sswilcox text = "UNDERFLOW"; \ 406*355d6bb5Sswilcox else if (net < -(MAXLINK)) \ 407*355d6bb5Sswilcox text = "OVERFLOW"; \ 408*355d6bb5Sswilcox } 4097c478bd9Sstevel@tonic-gate 410*355d6bb5Sswilcox /* 411*355d6bb5Sswilcox * If LINK_RANGE() indicated a problem, this is the boiler-plate 412*355d6bb5Sswilcox * for dealing with it. Usage is: 413*355d6bb5Sswilcox * 414*355d6bb5Sswilcox * LINK_RANGE(text, current, offset); 415*355d6bb5Sswilcox * if (text != NULL) { 416*355d6bb5Sswilcox * LINK_CLEAR(text, ino, mode, idp); 417*355d6bb5Sswilcox * if (statemap[ino] == USTATE) 418*355d6bb5Sswilcox * ...inode was cleared... 419*355d6bb5Sswilcox * } 420*355d6bb5Sswilcox * 421*355d6bb5Sswilcox * Note that clri() will set iscorrupt if the user elects not to 422*355d6bb5Sswilcox * clear the problem inode, so the filesystem won't get reported 423*355d6bb5Sswilcox * as clean when it shouldn't be. 424*355d6bb5Sswilcox */ 425*355d6bb5Sswilcox #define LINK_CLEAR(text, ino, mode, idp) { \ 426*355d6bb5Sswilcox pwarn("%s LINK COUNT %s", file_id((ino), (mode)), (text)); \ 427*355d6bb5Sswilcox pinode((ino)); \ 428*355d6bb5Sswilcox pfatal(""); \ 429*355d6bb5Sswilcox init_inodesc((idp)); \ 430*355d6bb5Sswilcox (idp)->id_type = ADDR; \ 431*355d6bb5Sswilcox (idp)->id_func = pass4check; \ 432*355d6bb5Sswilcox (idp)->id_number = ino; \ 433*355d6bb5Sswilcox (idp)->id_fix = DONTKNOW; \ 434*355d6bb5Sswilcox clri((idp), (text), CLRI_QUIET, CLRI_NOP_CORRUPT); \ 435*355d6bb5Sswilcox } 436*355d6bb5Sswilcox 437*355d6bb5Sswilcox /* 438*355d6bb5Sswilcox * Used for checking link count under/overflow specifically on 439*355d6bb5Sswilcox * the lost+found directory. If the user decides not to do the 440*355d6bb5Sswilcox * clri(), then flag that we've hit this problem and refuse to do 441*355d6bb5Sswilcox * the reconnect. 442*355d6bb5Sswilcox */ 443*355d6bb5Sswilcox #define LFDIR_LINK_RANGE_RVAL(text, current, offset, idp, rval) { \ 444*355d6bb5Sswilcox LINK_RANGE(text, current, offset); \ 445*355d6bb5Sswilcox if (text != NULL) { \ 446*355d6bb5Sswilcox LINK_CLEAR(text, lfdir, IFDIR, idp); \ 447*355d6bb5Sswilcox if (statemap[lfdir] == USTATE) { \ 448*355d6bb5Sswilcox lfdir = 0; \ 449*355d6bb5Sswilcox return (rval); \ 450*355d6bb5Sswilcox } else { \ 451*355d6bb5Sswilcox overflowed_lf++; \ 452*355d6bb5Sswilcox } \ 453*355d6bb5Sswilcox } \ 454*355d6bb5Sswilcox } 455*355d6bb5Sswilcox 456*355d6bb5Sswilcox #define LFDIR_LINK_RANGE_NORVAL(text, current, offset, idp) { \ 457*355d6bb5Sswilcox LINK_RANGE(text, current, offset); \ 458*355d6bb5Sswilcox if (text != NULL) { \ 459*355d6bb5Sswilcox LINK_CLEAR(text, lfdir, IFDIR, idp); \ 460*355d6bb5Sswilcox if (statemap[lfdir] == USTATE) { \ 461*355d6bb5Sswilcox lfdir = 0; \ 462*355d6bb5Sswilcox return; \ 463*355d6bb5Sswilcox } else { \ 464*355d6bb5Sswilcox overflowed_lf++; \ 465*355d6bb5Sswilcox } \ 466*355d6bb5Sswilcox } \ 467*355d6bb5Sswilcox } 468*355d6bb5Sswilcox 469*355d6bb5Sswilcox /* 470*355d6bb5Sswilcox * Values for mounted() and mountedfs. 471*355d6bb5Sswilcox */ 472*355d6bb5Sswilcox #define M_NOMNT 0 /* filesystem is not mounted */ 473*355d6bb5Sswilcox #define M_RO 1 /* filesystem is mounted read-only */ 474*355d6bb5Sswilcox #define M_RW 2 /* filesystem is mounted read-write */ 475*355d6bb5Sswilcox 476*355d6bb5Sswilcox #define EXOKAY 0 /* file system is unmounted and ok */ 477*355d6bb5Sswilcox #define EXBADPARM 1 /* bad parameter(s) given */ 478*355d6bb5Sswilcox #define EXUMNTCHK 32 /* fsck -m: unmounted, needs checking */ 479*355d6bb5Sswilcox #define EXMOUNTED 33 /* file system already mounted, not magic, */ 480*355d6bb5Sswilcox /* or it is magic and mounted read/write */ 481*355d6bb5Sswilcox #define EXNOSTAT 34 /* cannot stat device */ 482*355d6bb5Sswilcox #define EXREBOOTNOW 35 /* modified root or something equally scary */ 483*355d6bb5Sswilcox #define EXFNDERRS 36 /* uncorrectable errors, terminate normally */ 484*355d6bb5Sswilcox #define EXSIGNAL 37 /* a signal was caught during processing */ 485*355d6bb5Sswilcox #define EXERRFATAL 39 /* uncorrectable errors, exit immediately */ 486*355d6bb5Sswilcox #define EXROOTOKAY 40 /* for root, same as 0 */ 487*355d6bb5Sswilcox 488*355d6bb5Sswilcox /* 489*355d6bb5Sswilcox * Values for clri()'s `verbose' and `corrupting' arguments (third 490*355d6bb5Sswilcox * and fourth, respectively). 491*355d6bb5Sswilcox */ 492*355d6bb5Sswilcox #define CLRI_QUIET 1 493*355d6bb5Sswilcox #define CLRI_VERBOSE 2 494*355d6bb5Sswilcox 495*355d6bb5Sswilcox #define CLRI_NOP_OK 1 496*355d6bb5Sswilcox #define CLRI_NOP_CORRUPT 2 497*355d6bb5Sswilcox 498*355d6bb5Sswilcox /* 499*355d6bb5Sswilcox * Filesystems that are `magical' - if they exist in vfstab, 500*355d6bb5Sswilcox * then they have to be mounted for the system to have gotten 501*355d6bb5Sswilcox * far enough to be able to run fsck. Thus, don't get all 502*355d6bb5Sswilcox * bent out of shape if we're asked to check it and it is mounted. 503*355d6bb5Sswilcox * Actual initialization of the array is in main.c 504*355d6bb5Sswilcox */ 505*355d6bb5Sswilcox enum magic { 506*355d6bb5Sswilcox MAGIC_NONE = 0, 507*355d6bb5Sswilcox MAGIC_ROOT = 1, 508*355d6bb5Sswilcox MAGIC_USR = 2, 509*355d6bb5Sswilcox MAGIC_VAR = 3, 510*355d6bb5Sswilcox MAGIC_LIMIT = 4 511*355d6bb5Sswilcox }; 512*355d6bb5Sswilcox extern char *magic_fs[]; 513*355d6bb5Sswilcox 514*355d6bb5Sswilcox /* 515*355d6bb5Sswilcox * Paths needed by calcsb(). 516*355d6bb5Sswilcox */ 517*355d6bb5Sswilcox #define MKFS_PATH "/usr/lib/fs/ufs/mkfs" 518*355d6bb5Sswilcox #define NEWFS_PATH "/usr/lib/fs/ufs/newfs" 519*355d6bb5Sswilcox 520*355d6bb5Sswilcox int acltypeok(struct dinode *); 521*355d6bb5Sswilcox void add_orphan_dir(fsck_ino_t); 522*355d6bb5Sswilcox void adjust(struct inodesc *, int); 523*355d6bb5Sswilcox daddr32_t allocblk(int); 524*355d6bb5Sswilcox fsck_ino_t allocdir(fsck_ino_t, fsck_ino_t, int, int); 525*355d6bb5Sswilcox fsck_ino_t allocino(fsck_ino_t, int); 526*355d6bb5Sswilcox void blkerror(fsck_ino_t, caddr_t, daddr32_t, daddr32_t); 527*355d6bb5Sswilcox void brelse(struct bufarea *); 528*355d6bb5Sswilcox void bufinit(void); 529*355d6bb5Sswilcox void bwrite(int, caddr_t, diskaddr_t, int64_t); 530*355d6bb5Sswilcox void cacheacl(struct dinode *, fsck_ino_t); 531*355d6bb5Sswilcox void cacheino(struct dinode *, fsck_ino_t); 532*355d6bb5Sswilcox void catch(int); 533*355d6bb5Sswilcox void catchquit(int); 534*355d6bb5Sswilcox caddr_t cg_sanity(struct cg *, int, int *); 535*355d6bb5Sswilcox void cgflush(void); 536*355d6bb5Sswilcox int cgisdirty(void); 537*355d6bb5Sswilcox int changeino(fsck_ino_t, caddr_t, fsck_ino_t); 538*355d6bb5Sswilcox int check_mnttab(caddr_t, caddr_t, size_t); 539*355d6bb5Sswilcox int check_vfstab(caddr_t, caddr_t, size_t); 540*355d6bb5Sswilcox int chkrange(daddr32_t, int); 541*355d6bb5Sswilcox void ckfini(void); 542*355d6bb5Sswilcox int ckinode(struct dinode *, struct inodesc *, enum cki_action); 543*355d6bb5Sswilcox void clearattrref(fsck_ino_t); 544*355d6bb5Sswilcox int cleardirentry(fsck_ino_t, fsck_ino_t); 545*355d6bb5Sswilcox void clearshadow(fsck_ino_t, struct shadowclientinfo **); 546*355d6bb5Sswilcox void clri(struct inodesc *, caddr_t, int, int); 547*355d6bb5Sswilcox void deshadow(struct shadowclientinfo *, void (*)(fsck_ino_t)); 548*355d6bb5Sswilcox void direrror(fsck_ino_t, caddr_t, ...); 549*355d6bb5Sswilcox int dirscan(struct inodesc *); 550*355d6bb5Sswilcox void dirty(struct bufarea *); 551*355d6bb5Sswilcox int do_errorlock(int); 552*355d6bb5Sswilcox int dofix(struct inodesc *, caddr_t, ...); 553*355d6bb5Sswilcox void examinelog(daddr32_t, void (*)(daddr32_t)); 554*355d6bb5Sswilcox void errexit(caddr_t, ...); 555*355d6bb5Sswilcox void fileerror(fsck_ino_t, fsck_ino_t, caddr_t, ...); 556*355d6bb5Sswilcox caddr_t file_id(fsck_ino_t, mode_t); 557*355d6bb5Sswilcox int find_dup_ref(daddr32_t, fsck_ino_t, daddr32_t, int); 558*355d6bb5Sswilcox int findino(struct inodesc *); 559*355d6bb5Sswilcox int findname(struct inodesc *); 560*355d6bb5Sswilcox void fix_cg(struct cg *, int); 561*355d6bb5Sswilcox void flush(int, struct bufarea *); 562*355d6bb5Sswilcox void free_dup_state(void); 563*355d6bb5Sswilcox void freeblk(fsck_ino_t, daddr32_t, int); 564*355d6bb5Sswilcox void freeino(fsck_ino_t, int); 565*355d6bb5Sswilcox void freeinodebuf(void); 566*355d6bb5Sswilcox int fsck_asprintf(caddr_t *, caddr_t, ...); 567*355d6bb5Sswilcox int fsck_bread(int, caddr_t, diskaddr_t, size_t); 568*355d6bb5Sswilcox int ftypeok(struct dinode *); 569*355d6bb5Sswilcox struct bufarea *getblk(struct bufarea *, daddr32_t, size_t); 570*355d6bb5Sswilcox struct bufarea *getdatablk(daddr32_t, size_t size); 571*355d6bb5Sswilcox diskaddr_t getdisksize(caddr_t, int); 572*355d6bb5Sswilcox struct inoinfo *getinoinfo(fsck_ino_t); 573*355d6bb5Sswilcox struct dinode *getnextinode(fsck_ino_t); 574*355d6bb5Sswilcox struct dinode *getnextrefresh(void); 575*355d6bb5Sswilcox void getpathname(caddr_t, fsck_ino_t, fsck_ino_t); 576*355d6bb5Sswilcox struct dinode *ginode(fsck_ino_t); 577*355d6bb5Sswilcox caddr_t hasvfsopt(struct vfstab *, caddr_t); 578*355d6bb5Sswilcox int have_dups(void); 579*355d6bb5Sswilcox void init_inodesc(struct inodesc *); 580*355d6bb5Sswilcox void init_inoinfo(struct inoinfo *, struct dinode *, fsck_ino_t); 581*355d6bb5Sswilcox void initbarea(struct bufarea *); 582*355d6bb5Sswilcox int ino_t_cmp(const void *, const void *); 583*355d6bb5Sswilcox int inocached(fsck_ino_t); 584*355d6bb5Sswilcox void inocleanup(void); 585*355d6bb5Sswilcox void inodirty(void); 586*355d6bb5Sswilcox int is_errorlocked(caddr_t); 587*355d6bb5Sswilcox int linkup(fsck_ino_t, fsck_ino_t, caddr_t); 588*355d6bb5Sswilcox int lookup_named_ino(fsck_ino_t, caddr_t); 589*355d6bb5Sswilcox int makeentry(fsck_ino_t, fsck_ino_t, caddr_t); 590*355d6bb5Sswilcox void maybe_convert_attrdir_to_dir(fsck_ino_t); 591*355d6bb5Sswilcox int mounted(caddr_t, caddr_t, size_t); 592*355d6bb5Sswilcox void pass1(void); 593*355d6bb5Sswilcox void pass1b(void); 594*355d6bb5Sswilcox int pass1check(struct inodesc *); 595*355d6bb5Sswilcox void pass2a(void); 596*355d6bb5Sswilcox void pass2b(void); 597*355d6bb5Sswilcox void pass3a(void); 598*355d6bb5Sswilcox void pass3b(void); 599*355d6bb5Sswilcox int pass3bcheck(struct inodesc *); 600*355d6bb5Sswilcox void pass4(void); 601*355d6bb5Sswilcox int pass4check(struct inodesc *); 602*355d6bb5Sswilcox void pass5(void); 603*355d6bb5Sswilcox void pfatal(caddr_t, ...); 604*355d6bb5Sswilcox void pinode(fsck_ino_t); 605*355d6bb5Sswilcox void printclean(void); 606*355d6bb5Sswilcox void propagate(void); 607*355d6bb5Sswilcox void pwarn(caddr_t, ...); 608*355d6bb5Sswilcox caddr_t rawname(caddr_t); 609*355d6bb5Sswilcox void registershadowclient(fsck_ino_t, fsck_ino_t, 610*355d6bb5Sswilcox struct shadowclientinfo **); 611*355d6bb5Sswilcox void remove_orphan_dir(fsck_ino_t); 612*355d6bb5Sswilcox int reply(caddr_t, ...); 613*355d6bb5Sswilcox int report_dups(int); 614*355d6bb5Sswilcox void resetinodebuf(void); 615*355d6bb5Sswilcox char *setup(caddr_t); 616*355d6bb5Sswilcox void truncino(fsck_ino_t, offset_t, int); 617*355d6bb5Sswilcox void unbufinit(void); 618*355d6bb5Sswilcox caddr_t unrawname(caddr_t); 619*355d6bb5Sswilcox void unregistershadow(fsck_ino_t, struct shadowclientinfo **); 620*355d6bb5Sswilcox int updateclean(void); 621*355d6bb5Sswilcox int writable(caddr_t); 622*355d6bb5Sswilcox void write_altsb(int); 623*355d6bb5Sswilcox 624*355d6bb5Sswilcox /* 625*355d6bb5Sswilcox * Functions from the kernel sources (ufs_subr.c, etc). 626*355d6bb5Sswilcox */ 627*355d6bb5Sswilcox extern void fragacct(struct fs *, int, int32_t *, int); 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate #ifdef __cplusplus 6307c478bd9Sstevel@tonic-gate } 6317c478bd9Sstevel@tonic-gate #endif 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate #endif /* _FSCK_FSCK_H */ 634