10Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 20Sstevel@tonic-gate /* All Rights Reserved */ 30Sstevel@tonic-gate 40Sstevel@tonic-gate /* 50Sstevel@tonic-gate * Copyright (c) 1980, 1986, 1990 The Regents of the University of California. 60Sstevel@tonic-gate * All rights reserved. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * Redistribution and use in source and binary forms are permitted 90Sstevel@tonic-gate * provided that: (1) source distributions retain this entire copyright 100Sstevel@tonic-gate * notice and comment, and (2) distributions including binaries display 110Sstevel@tonic-gate * the following acknowledgement: ``This product includes software 120Sstevel@tonic-gate * developed by the University of California, Berkeley and its contributors'' 130Sstevel@tonic-gate * in the documentation or other materials provided with the distribution 140Sstevel@tonic-gate * and in all advertising materials mentioning features or use of this 150Sstevel@tonic-gate * software. Neither the name of the University nor the names of its 160Sstevel@tonic-gate * contributors may be used to endorse or promote products derived 170Sstevel@tonic-gate * from this software without specific prior written permission. 180Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 190Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 200Sstevel@tonic-gate * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate 230Sstevel@tonic-gate /* 24*4132Sabalfour * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 250Sstevel@tonic-gate * Use is subject to license terms. 260Sstevel@tonic-gate */ 270Sstevel@tonic-gate 280Sstevel@tonic-gate #ifndef _FSCK_FSCK_H 290Sstevel@tonic-gate #define _FSCK_FSCK_H 300Sstevel@tonic-gate 310Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.3 */ 320Sstevel@tonic-gate 330Sstevel@tonic-gate #ifdef __cplusplus 340Sstevel@tonic-gate extern "C" { 350Sstevel@tonic-gate #endif 360Sstevel@tonic-gate 37392Sswilcox #include <stdio.h> 38392Sswilcox #include <stdarg.h> 39392Sswilcox #include <search.h> 40392Sswilcox #include <sys/param.h> 41392Sswilcox #include <sys/types.h> 42392Sswilcox #include <sys/mnttab.h> 43392Sswilcox #include <sys/vfstab.h> 44392Sswilcox #include <sys/fs/ufs_fs.h> 45392Sswilcox #include <sys/fs/ufs_inode.h> 46392Sswilcox 470Sstevel@tonic-gate #define MAXDUP 10 /* limit on dup blks (per inode) */ 480Sstevel@tonic-gate #define MAXBAD 10 /* limit on bad blks (per inode) */ 49392Sswilcox #define MAXBUFSPACE 40*1024 /* initial space to allocate to buffers */ 500Sstevel@tonic-gate #define INOBUFSIZE 56*1024 /* size of buffer to read inodes in pass1 */ 510Sstevel@tonic-gate 520Sstevel@tonic-gate #ifndef BUFSIZ 53392Sswilcox #define BUFSIZ MAXPATHLEN 540Sstevel@tonic-gate #endif 550Sstevel@tonic-gate 56392Sswilcox /* 57392Sswilcox * Inode states in statemap[]. 58392Sswilcox */ 59392Sswilcox #define USTATE 0x01 /* inode not allocated */ 60392Sswilcox #define FSTATE 0x02 /* inode is file */ 61392Sswilcox #define DSTATE 0x04 /* inode is directory */ 62392Sswilcox #define SSTATE 0x08 /* inode is a shadow/acl */ 63392Sswilcox #define STMASK 0x0f /* pick off the basic state/type */ 64392Sswilcox 65392Sswilcox /* flags OR'd into the above */ 66392Sswilcox #define INZLINK 0x0010 /* inode has zero links */ 67392Sswilcox #define INFOUND 0x0020 /* inode was found during descent */ 68392Sswilcox #define INCLEAR 0x0040 /* inode is to be cleared */ 69392Sswilcox #define INORPHAN 0x0080 /* inode is a known orphan (pass3 only) */ 70392Sswilcox #define INDELAYD 0x0200 /* link count update delayed */ 71392Sswilcox #define INMASK 0xfff0 /* pick off the modifiers */ 72392Sswilcox 73392Sswilcox #define FZLINK (FSTATE | INZLINK) 74392Sswilcox #define DZLINK (DSTATE | INZLINK) 75392Sswilcox #define SZLINK (SSTATE | INZLINK) 76392Sswilcox 77392Sswilcox #define DFOUND (DSTATE | INFOUND) 78392Sswilcox 79392Sswilcox #define DCLEAR (DSTATE | INCLEAR) 80392Sswilcox #define FCLEAR (FSTATE | INCLEAR) 81392Sswilcox #define SCLEAR (SSTATE | INCLEAR) 82392Sswilcox 83392Sswilcox /* 84392Sswilcox * These tests depend on the state/type defines above not overlapping bits. 85392Sswilcox * 86392Sswilcox * DUNFOUND === (state == DSTATE || state == DZLINK) 87392Sswilcox * INCLEAR is irrelevant to the determination of 88392Sswilcox * connectedness, so it's not included in this test. 89392Sswilcox * 90392Sswilcox * DVALID === (state == DSTATE || state == DZLINK || state == DFOUND) 91392Sswilcox */ 92392Sswilcox #define S_IS_DUNFOUND(state) (((state) & (DSTATE | INZLINK)) \ 93392Sswilcox == (state)) 94392Sswilcox #define S_IS_DVALID(state) (((state) & (DSTATE | INZLINK | INFOUND | \ 95392Sswilcox INORPHAN)) == (state)) 96392Sswilcox #define S_IS_ZLINK(state) (((state) & INZLINK) != 0) 97392Sswilcox #define INO_IS_DUNFOUND(ino) S_IS_DUNFOUND(statemap[ino]) 98392Sswilcox #define INO_IS_DVALID(ino) S_IS_DVALID(statemap[ino]) 990Sstevel@tonic-gate 1000Sstevel@tonic-gate /* 1010Sstevel@tonic-gate * buffer cache structure. 1020Sstevel@tonic-gate */ 1030Sstevel@tonic-gate struct bufarea { 1040Sstevel@tonic-gate struct bufarea *b_next; /* free list queue */ 1050Sstevel@tonic-gate struct bufarea *b_prev; /* free list queue */ 106392Sswilcox diskaddr_t b_bno; /* physical sector number */ 1070Sstevel@tonic-gate int b_size; 1080Sstevel@tonic-gate int b_errs; 1090Sstevel@tonic-gate int b_flags; 1100Sstevel@tonic-gate int b_cnt; /* reference cnt */ 1110Sstevel@tonic-gate union { 1120Sstevel@tonic-gate char *b_buf; /* buffer space */ 1130Sstevel@tonic-gate daddr32_t *b_indir; /* indirect block */ 1140Sstevel@tonic-gate struct fs *b_fs; /* super block */ 1150Sstevel@tonic-gate struct cg *b_cg; /* cylinder group */ 1160Sstevel@tonic-gate struct dinode *b_dinode; /* inode block */ 1170Sstevel@tonic-gate } b_un; 1180Sstevel@tonic-gate char b_dirty; 1190Sstevel@tonic-gate }; 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate #define B_INUSE 1 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate #define MINBUFS 5 /* minimum number of buffers required */ 1240Sstevel@tonic-gate struct bufarea bufhead; /* head of list of other blks in filesys */ 1250Sstevel@tonic-gate struct bufarea sblk; /* file system superblock */ 126392Sswilcox struct bufarea asblk; /* alternate superblock */ 1270Sstevel@tonic-gate struct bufarea cgblk; /* cylinder group blocks */ 1280Sstevel@tonic-gate struct bufarea *pbp; /* pointer to inode data in buffer pool */ 1290Sstevel@tonic-gate struct bufarea *pdirbp; /* pointer to directory data in buffer pool */ 1300Sstevel@tonic-gate 131392Sswilcox #define sbdirty() dirty(&sblk) 132392Sswilcox #define cgdirty() dirty(&cgblk) 1330Sstevel@tonic-gate #define sblock (*sblk.b_un.b_fs) 1340Sstevel@tonic-gate #define cgrp (*cgblk.b_un.b_cg) 1350Sstevel@tonic-gate 136392Sswilcox /* 137392Sswilcox * inodesc.id_fix values. See inode.c for a description of their usage. 138392Sswilcox */ 139392Sswilcox enum fixstate { 140392Sswilcox DONTKNOW, NOFIX, FIX, IGNORE 141392Sswilcox }; 142392Sswilcox 143392Sswilcox /* 144392Sswilcox * Tells truncino() whether or not to attempt to update the parent 145392Sswilcox * directory's link count. Also, TI_NODUP flags when we're discarding 146392Sswilcox * fragments that are beyond the original end of the file, and so 147392Sswilcox * should not be considered duplicate-claim candidates. 148392Sswilcox */ 149392Sswilcox #define TI_NOPARENT 0x0001 /* leave parent's di_nlink alone */ 150392Sswilcox #define TI_PARENT 0x0002 /* update parent's di_nlink */ 151392Sswilcox #define TI_NODUP 0x0004 /* not a dup candidate */ 1520Sstevel@tonic-gate 153392Sswilcox /* 154392Sswilcox * Modes for ckinode() and ckinode_common(). 155392Sswilcox * 156392Sswilcox * CKI_TRAVERSE is the common case, and requests a traditional 157392Sswilcox * traversal of blocks or directory entries. 158392Sswilcox * 159392Sswilcox * CKI_TRUNCATE indicates that we're truncating the file, and that any 160392Sswilcox * block indices beyond the end of the target length should be cleared 161392Sswilcox * after the callback has returned (i.e., this is a superset of 162392Sswilcox * CKI_TRAVERSE). idesc->id_truncto is the first logical block number 163392Sswilcox * to clear. If it is less than zero, then the traversal will be 164392Sswilcox * equivalent to a simple CKI_TRAVERSE. 165392Sswilcox */ 166392Sswilcox enum cki_action { CKI_TRAVERSE, CKI_TRUNCATE }; 167392Sswilcox 168392Sswilcox /* 169392Sswilcox * The general definition of an ino_t is an unsigned quantity. 170392Sswilcox * However, the on-disk version is an int32_t, which is signed. 171392Sswilcox * Since we really want to be able to detect wrapped-around 172392Sswilcox * inode numbers and such, we'll use something that's compatible 173392Sswilcox * with what's on disk since that's the only context that really 174392Sswilcox * matters. If an int32_t is found not to be sufficiently large, 175392Sswilcox * this will make it much easier to change later. 176392Sswilcox * 177392Sswilcox * Note that there is one unsigned inode field in the on-disk 178392Sswilcox * inode, ic_oeftflag. Since all other inode fields are signed, 179392Sswilcox * no legitimate inode number can be put into ic_oeftflag that 180392Sswilcox * would overflow into the high bit. Essentially, it should 181392Sswilcox * actually be declared as int32_t just like all the others, and 182392Sswilcox * we're going to pretend that it was. 183392Sswilcox * 184392Sswilcox * None of the routines that we use in ufs_subr.c do anything with 185392Sswilcox * inode numbers. If that changes, then great care will be needed 186392Sswilcox * to deal with the differences in definition of ino_t and fsck_ino_t. 187392Sswilcox * Lint is your friend. 188392Sswilcox */ 189392Sswilcox typedef int32_t fsck_ino_t; 1900Sstevel@tonic-gate 1910Sstevel@tonic-gate /* 192392Sswilcox * See the full discussion of the interactions between struct inodesc 193392Sswilcox * and ckinode() in inode.c 1940Sstevel@tonic-gate */ 195392Sswilcox struct inodesc { 196392Sswilcox enum fixstate id_fix; /* policy on fixing errors */ 197392Sswilcox int (*id_func)(struct inodesc *); 198392Sswilcox /* function to be applied to blocks of inode */ 199392Sswilcox fsck_ino_t id_number; /* inode number described */ 200392Sswilcox fsck_ino_t id_parent; /* for DATA nodes, their parent */ 201392Sswilcox /* also used for extra (*id_func) parameter */ 202392Sswilcox /* and return values */ 203392Sswilcox daddr32_t id_lbn; /* logical fragment number of current block */ 204392Sswilcox daddr32_t id_blkno; /* physical fragment number being examined */ 205392Sswilcox int id_numfrags; /* number of frags contained in block */ 206392Sswilcox daddr32_t id_truncto; /* # blocks to truncate to, -1 for no trunc. */ 207392Sswilcox offset_t id_filesize; /* for DATA nodes, the size of the directory */ 208392Sswilcox uint_t id_loc; /* for DATA nodes, current location in dir */ 209392Sswilcox daddr32_t id_entryno; /* for DATA nodes, current dir entry number */ 210392Sswilcox daddr32_t id_firsthole; /* for DATA inode, logical block that is */ 211392Sswilcox /* zero but shouldn't be, -1 for no holes */ 212392Sswilcox struct direct *id_dirp; /* for DATA nodes, ptr to current entry */ 213392Sswilcox caddr_t id_name; /* for DATA nodes, name to find or enter */ 214392Sswilcox char id_type; /* type of descriptor, DATA or ADDR */ 2150Sstevel@tonic-gate }; 216392Sswilcox 217392Sswilcox /* file types (0 is reserved for catching bugs) */ 218392Sswilcox #define DATA 1 /* a directory */ 219392Sswilcox #define ACL 2 /* an acl/shadow */ 220392Sswilcox #define ADDR 3 /* anything but a directory or an acl/shadow */ 2210Sstevel@tonic-gate 2220Sstevel@tonic-gate /* 223392Sswilcox * OR'd flags for find_dup_ref()'s mode argument 2240Sstevel@tonic-gate */ 225392Sswilcox #define DB_CREATE 0x01 /* if dup record found, make one */ 226392Sswilcox #define DB_INCR 0x02 /* increment block's reference count */ 227392Sswilcox #define DB_DECR 0x04 /* decrement block's reference count */ 2280Sstevel@tonic-gate 2290Sstevel@tonic-gate /* 230392Sswilcox * Cache data structures 2310Sstevel@tonic-gate */ 2320Sstevel@tonic-gate struct inoinfo { 233392Sswilcox struct inoinfo *i_nextlist; /* next inode/acl cache entry */ 234392Sswilcox fsck_ino_t i_number; /* inode number of this entry */ 235392Sswilcox fsck_ino_t i_parent; /* inode number of parent */ 236392Sswilcox fsck_ino_t i_dotdot; /* inode number of .. */ 237392Sswilcox fsck_ino_t i_extattr; /* inode of hidden attr dir */ 238392Sswilcox offset_t i_isize; /* size of inode */ 239392Sswilcox size_t i_blkssize; /* size of block array in bytes */ 2400Sstevel@tonic-gate daddr32_t i_blks[1]; /* actually longer */ 241392Sswilcox }; 242392Sswilcox 243392Sswilcox /* 244392Sswilcox * Inode cache 245392Sswilcox */ 246392Sswilcox struct inoinfo **inphead, **inpsort; 2470Sstevel@tonic-gate int64_t numdirs, listmax, inplast; 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate /* 250392Sswilcox * ACL cache 2510Sstevel@tonic-gate */ 252392Sswilcox struct inoinfo **aclphead, **aclpsort; 2530Sstevel@tonic-gate int64_t numacls, aclmax, aclplast; 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate /* 256392Sswilcox * Tree of directories we haven't reconnected or cleared. Any 257392Sswilcox * dir inode that linkup() fails on gets added, any that clri() 258392Sswilcox * succeeds on gets removed. If there are any left at the end of 259392Sswilcox * pass four, then we have a user-forced corrupt filesystem, and 260392Sswilcox * need to set iscorrupt. 261392Sswilcox * 262392Sswilcox * Elements are fsck_ino_t instances (not pointers). 263392Sswilcox */ 264392Sswilcox void *limbo_dirs; 265392Sswilcox 266392Sswilcox /* 267392Sswilcox * Number of directories we actually found in the filesystem, 268392Sswilcox * as opposed to how many the superblock claims there are. 269392Sswilcox */ 270392Sswilcox fsck_ino_t countdirs; 271392Sswilcox 272392Sswilcox /* 2730Sstevel@tonic-gate * shadowclients and shadowclientinfo are structures for keeping track of 2740Sstevel@tonic-gate * shadow inodes that exist, and which regular inodes use them (i.e. are 2750Sstevel@tonic-gate * their clients). 2760Sstevel@tonic-gate */ 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate struct shadowclients { 279392Sswilcox fsck_ino_t *client; /* an array of inode numbers */ 2800Sstevel@tonic-gate int nclients; /* how many inodes in the array are in use (valid) */ 2810Sstevel@tonic-gate struct shadowclients *next; /* link to more client inode numbers */ 2820Sstevel@tonic-gate }; 2830Sstevel@tonic-gate struct shadowclientinfo { 284392Sswilcox fsck_ino_t shadow; /* the shadow inode that this info is for */ 2850Sstevel@tonic-gate int totalClients; /* how many inodes total refer to this */ 2860Sstevel@tonic-gate struct shadowclients *clients; /* a linked list of wads of clients */ 2870Sstevel@tonic-gate struct shadowclientinfo *next; /* link to the next shadow inode */ 2880Sstevel@tonic-gate }; 2890Sstevel@tonic-gate /* global pointer to this shadow/client information */ 290392Sswilcox struct shadowclientinfo *shadowclientinfo; 291392Sswilcox struct shadowclientinfo *attrclientinfo; 292392Sswilcox 293392Sswilcox /* 294392Sswilcox * In ufs_inode.h ifdef _KERNEL, this is defined as `/@/'. However, 295392Sswilcox * to avoid all sorts of potential confusion (you can't actually use 296392Sswilcox * `foo/@/bar' to get to an attribute), we use something that doesn't 297392Sswilcox * look quite so much like a simple pathname. 298392Sswilcox */ 299392Sswilcox #define XATTR_DIR_NAME " <xattr> " 300392Sswilcox 301392Sswilcox /* 302392Sswilcox * granularity -- how many client inodes do we make space for at a time 303392Sswilcox * initialized in setup.c; 304392Sswilcox */ 3050Sstevel@tonic-gate extern int maxshadowclients; 306392Sswilcox 307392Sswilcox /* 308392Sswilcox * Initialized global variables. 309392Sswilcox */ 310392Sswilcox extern caddr_t lfname; 3110Sstevel@tonic-gate 312392Sswilcox /* 313392Sswilcox * Unitialized globals. 314392Sswilcox */ 3150Sstevel@tonic-gate char *devname; /* name of device being checked */ 316392Sswilcox size_t dev_bsize; /* computed value of DEV_BSIZE */ 3170Sstevel@tonic-gate int secsize; /* actual disk sector size */ 3180Sstevel@tonic-gate char nflag; /* assume a no response */ 3190Sstevel@tonic-gate char yflag; /* assume a yes response */ 320392Sswilcox daddr32_t bflag; /* location of alternate super block */ 3210Sstevel@tonic-gate int debug; /* output debugging info */ 3220Sstevel@tonic-gate int rflag; /* check raw file systems */ 323392Sswilcox int roflag; /* do normal checks but don't update disk */ 3240Sstevel@tonic-gate int fflag; /* check regardless of clean flag (force) */ 325392Sswilcox int mflag; /* sanity check only */ 326392Sswilcox int verbose; /* be chatty */ 3270Sstevel@tonic-gate char preen; /* just fix normal inconsistencies */ 3280Sstevel@tonic-gate char mountedfs; /* checking mounted device */ 329392Sswilcox int exitstat; /* exit status (see EX* defines below) */ 3300Sstevel@tonic-gate char hotroot; /* checking root device */ 331392Sswilcox char rerun; /* rerun fsck. Only used in non-preen mode */ 332392Sswilcox int interrupted; /* 1 => exit EXSIGNAL on exit */ 3330Sstevel@tonic-gate char havesb; /* superblock has been read */ 3340Sstevel@tonic-gate int fsmodified; /* 1 => write done to file system */ 3350Sstevel@tonic-gate int fsreadfd; /* file descriptor for reading file system */ 3360Sstevel@tonic-gate int fswritefd; /* file descriptor for writing file system */ 3370Sstevel@tonic-gate int iscorrupt; /* known to be corrupt/inconsistent */ 338392Sswilcox /* -1 means mark clean so user can mount+fix */ 3390Sstevel@tonic-gate int isdirty; /* 1 => write pending to file system */ 3400Sstevel@tonic-gate 3410Sstevel@tonic-gate int islog; /* logging file system */ 3420Sstevel@tonic-gate int islogok; /* log is okay */ 3430Sstevel@tonic-gate 3440Sstevel@tonic-gate int errorlocked; /* set => mounted fs has been error-locked */ 3450Sstevel@tonic-gate /* implies fflag "force check flag" */ 3460Sstevel@tonic-gate char *elock_combuf; /* error lock comment buffer */ 3470Sstevel@tonic-gate char *elock_mountp; /* mount point; used to unlock error-lock */ 3480Sstevel@tonic-gate int pid; /* fsck's process id (put in lockfs comment) */ 3490Sstevel@tonic-gate int mountfd; /* fd of mount point */ 3500Sstevel@tonic-gate struct lockfs *lfp; /* current lockfs status */ 3510Sstevel@tonic-gate 3520Sstevel@tonic-gate daddr32_t maxfsblock; /* number of blocks in the file system */ 353392Sswilcox uint_t largefile_count; /* global largefile counter */ 354392Sswilcox char *mount_point; /* if mounted, this is where */ 3550Sstevel@tonic-gate char *blockmap; /* ptr to primary blk allocation map */ 356392Sswilcox fsck_ino_t maxino; /* number of inodes in file system */ 357392Sswilcox fsck_ino_t lastino; /* last inode in use */ 358392Sswilcox ushort_t *statemap; /* ptr to inode state table */ 3590Sstevel@tonic-gate short *lncntp; /* ptr to link count table */ 3600Sstevel@tonic-gate 361392Sswilcox fsck_ino_t lfdir; /* lost & found directory inode number */ 362392Sswilcox int overflowed_lf; /* tried to wrap lost & found's link count */ 363392Sswilcox int reattached_dir; /* reconnected at least one directory */ 364392Sswilcox int broke_dir_link; /* broke at least one directory hardlink */ 3650Sstevel@tonic-gate 366392Sswilcox daddr32_t n_blks; /* number of blocks in use */ 367392Sswilcox fsck_ino_t n_files; /* number of files in use */ 3680Sstevel@tonic-gate 369392Sswilcox #define clearinode(dp) { \ 370392Sswilcox *(dp) = zino; \ 371392Sswilcox } 3720Sstevel@tonic-gate struct dinode zino; 3730Sstevel@tonic-gate 374392Sswilcox #define testbmap(blkno) isset(blockmap, blkno) 3750Sstevel@tonic-gate #define setbmap(blkno) setbit(blockmap, blkno) 3760Sstevel@tonic-gate #define clrbmap(blkno) clrbit(blockmap, blkno) 3770Sstevel@tonic-gate 3780Sstevel@tonic-gate #define STOP 0x01 3790Sstevel@tonic-gate #define SKIP 0x02 3800Sstevel@tonic-gate #define KEEPON 0x04 3810Sstevel@tonic-gate #define ALTERED 0x08 3820Sstevel@tonic-gate #define FOUND 0x10 3830Sstevel@tonic-gate 384392Sswilcox /* 385392Sswilcox * Support relatively easy debugging of lncntp[] updates. This can't 386392Sswilcox * be a function, because of the (_op) step. Normally, we just do that. 387392Sswilcox */ 388392Sswilcox #define TRACK_LNCNTP(_ino, _op) (_op) 389392Sswilcox 390392Sswilcox /* 391392Sswilcox * See if the net link count for an inode has gone outside 392392Sswilcox * what can be represented on disk. Returning text as NULL 393392Sswilcox * indicates no. 394392Sswilcox * 395392Sswilcox * Remember that link counts are effectively inverted, so 396392Sswilcox * underflow and overflow are reversed as well. 397392Sswilcox * 398392Sswilcox * This check should be done before modifying the actual link 399392Sswilcox * count. 400392Sswilcox */ 401392Sswilcox #define LINK_RANGE(text, current, offset) { \ 402392Sswilcox int net = ((int)(current)) + ((int)(offset)); \ 403392Sswilcox text = NULL; \ 404392Sswilcox if (net > (MAXLINK)) \ 405392Sswilcox text = "UNDERFLOW"; \ 406392Sswilcox else if (net < -(MAXLINK)) \ 407392Sswilcox text = "OVERFLOW"; \ 408392Sswilcox } 409392Sswilcox 410392Sswilcox /* 411392Sswilcox * If LINK_RANGE() indicated a problem, this is the boiler-plate 412392Sswilcox * for dealing with it. Usage is: 413392Sswilcox * 414392Sswilcox * LINK_RANGE(text, current, offset); 415392Sswilcox * if (text != NULL) { 416392Sswilcox * LINK_CLEAR(text, ino, mode, idp); 417392Sswilcox * if (statemap[ino] == USTATE) 418392Sswilcox * ...inode was cleared... 419392Sswilcox * } 420392Sswilcox * 421392Sswilcox * Note that clri() will set iscorrupt if the user elects not to 422392Sswilcox * clear the problem inode, so the filesystem won't get reported 423392Sswilcox * as clean when it shouldn't be. 424392Sswilcox */ 425392Sswilcox #define LINK_CLEAR(text, ino, mode, idp) { \ 426392Sswilcox pwarn("%s LINK COUNT %s", file_id((ino), (mode)), (text)); \ 427392Sswilcox pinode((ino)); \ 428392Sswilcox pfatal(""); \ 429392Sswilcox init_inodesc((idp)); \ 430392Sswilcox (idp)->id_type = ADDR; \ 431392Sswilcox (idp)->id_func = pass4check; \ 432392Sswilcox (idp)->id_number = ino; \ 433392Sswilcox (idp)->id_fix = DONTKNOW; \ 434392Sswilcox clri((idp), (text), CLRI_QUIET, CLRI_NOP_CORRUPT); \ 435392Sswilcox } 436392Sswilcox 437392Sswilcox /* 438392Sswilcox * Used for checking link count under/overflow specifically on 439392Sswilcox * the lost+found directory. If the user decides not to do the 440392Sswilcox * clri(), then flag that we've hit this problem and refuse to do 441392Sswilcox * the reconnect. 442392Sswilcox */ 443392Sswilcox #define LFDIR_LINK_RANGE_RVAL(text, current, offset, idp, rval) { \ 444392Sswilcox LINK_RANGE(text, current, offset); \ 445392Sswilcox if (text != NULL) { \ 446392Sswilcox LINK_CLEAR(text, lfdir, IFDIR, idp); \ 447392Sswilcox if (statemap[lfdir] == USTATE) { \ 448392Sswilcox lfdir = 0; \ 449392Sswilcox return (rval); \ 450392Sswilcox } else { \ 451392Sswilcox overflowed_lf++; \ 452392Sswilcox } \ 453392Sswilcox } \ 454392Sswilcox } 455392Sswilcox 456392Sswilcox #define LFDIR_LINK_RANGE_NORVAL(text, current, offset, idp) { \ 457392Sswilcox LINK_RANGE(text, current, offset); \ 458392Sswilcox if (text != NULL) { \ 459392Sswilcox LINK_CLEAR(text, lfdir, IFDIR, idp); \ 460392Sswilcox if (statemap[lfdir] == USTATE) { \ 461392Sswilcox lfdir = 0; \ 462392Sswilcox return; \ 463392Sswilcox } else { \ 464392Sswilcox overflowed_lf++; \ 465392Sswilcox } \ 466392Sswilcox } \ 467392Sswilcox } 468392Sswilcox 469392Sswilcox /* 470392Sswilcox * Values for mounted() and mountedfs. 471392Sswilcox */ 472392Sswilcox #define M_NOMNT 0 /* filesystem is not mounted */ 473392Sswilcox #define M_RO 1 /* filesystem is mounted read-only */ 474392Sswilcox #define M_RW 2 /* filesystem is mounted read-write */ 475392Sswilcox 476392Sswilcox #define EXOKAY 0 /* file system is unmounted and ok */ 477392Sswilcox #define EXBADPARM 1 /* bad parameter(s) given */ 478392Sswilcox #define EXUMNTCHK 32 /* fsck -m: unmounted, needs checking */ 479392Sswilcox #define EXMOUNTED 33 /* file system already mounted, not magic, */ 480392Sswilcox /* or it is magic and mounted read/write */ 481392Sswilcox #define EXNOSTAT 34 /* cannot stat device */ 482392Sswilcox #define EXREBOOTNOW 35 /* modified root or something equally scary */ 483392Sswilcox #define EXFNDERRS 36 /* uncorrectable errors, terminate normally */ 484392Sswilcox #define EXSIGNAL 37 /* a signal was caught during processing */ 485392Sswilcox #define EXERRFATAL 39 /* uncorrectable errors, exit immediately */ 486392Sswilcox #define EXROOTOKAY 40 /* for root, same as 0 */ 487392Sswilcox 488392Sswilcox /* 489392Sswilcox * Values for clri()'s `verbose' and `corrupting' arguments (third 490392Sswilcox * and fourth, respectively). 491392Sswilcox */ 492392Sswilcox #define CLRI_QUIET 1 493392Sswilcox #define CLRI_VERBOSE 2 494392Sswilcox 495392Sswilcox #define CLRI_NOP_OK 1 496392Sswilcox #define CLRI_NOP_CORRUPT 2 4970Sstevel@tonic-gate 498392Sswilcox /* 499392Sswilcox * Filesystems that are `magical' - if they exist in vfstab, 500392Sswilcox * then they have to be mounted for the system to have gotten 501392Sswilcox * far enough to be able to run fsck. Thus, don't get all 502392Sswilcox * bent out of shape if we're asked to check it and it is mounted. 503392Sswilcox * Actual initialization of the array is in main.c 504392Sswilcox */ 505392Sswilcox enum magic { 506392Sswilcox MAGIC_NONE = 0, 507392Sswilcox MAGIC_ROOT = 1, 508392Sswilcox MAGIC_USR = 2, 509504Sswilcox MAGIC_LIMIT = 3 510392Sswilcox }; 511392Sswilcox extern char *magic_fs[]; 512392Sswilcox 513392Sswilcox /* 514392Sswilcox * Paths needed by calcsb(). 515392Sswilcox */ 516392Sswilcox #define MKFS_PATH "/usr/lib/fs/ufs/mkfs" 517392Sswilcox #define NEWFS_PATH "/usr/lib/fs/ufs/newfs" 518392Sswilcox 519392Sswilcox int acltypeok(struct dinode *); 520392Sswilcox void add_orphan_dir(fsck_ino_t); 521392Sswilcox void adjust(struct inodesc *, int); 522392Sswilcox daddr32_t allocblk(int); 523392Sswilcox fsck_ino_t allocdir(fsck_ino_t, fsck_ino_t, int, int); 524392Sswilcox fsck_ino_t allocino(fsck_ino_t, int); 525392Sswilcox void blkerror(fsck_ino_t, caddr_t, daddr32_t, daddr32_t); 526392Sswilcox void brelse(struct bufarea *); 527392Sswilcox void bufinit(void); 528392Sswilcox void bwrite(int, caddr_t, diskaddr_t, int64_t); 529392Sswilcox void cacheacl(struct dinode *, fsck_ino_t); 530392Sswilcox void cacheino(struct dinode *, fsck_ino_t); 531392Sswilcox void catch(int); 532392Sswilcox void catchquit(int); 5333219Sabalfour caddr_t cg_sanity(struct cg *, int); 534392Sswilcox void cgflush(void); 535392Sswilcox int cgisdirty(void); 536392Sswilcox int changeino(fsck_ino_t, caddr_t, fsck_ino_t); 537392Sswilcox int check_mnttab(caddr_t, caddr_t, size_t); 538392Sswilcox int check_vfstab(caddr_t, caddr_t, size_t); 539392Sswilcox int chkrange(daddr32_t, int); 540392Sswilcox void ckfini(void); 541392Sswilcox int ckinode(struct dinode *, struct inodesc *, enum cki_action); 542392Sswilcox void clearattrref(fsck_ino_t); 543392Sswilcox int cleardirentry(fsck_ino_t, fsck_ino_t); 544392Sswilcox void clearshadow(fsck_ino_t, struct shadowclientinfo **); 545392Sswilcox void clri(struct inodesc *, caddr_t, int, int); 546392Sswilcox void deshadow(struct shadowclientinfo *, void (*)(fsck_ino_t)); 547392Sswilcox void direrror(fsck_ino_t, caddr_t, ...); 548392Sswilcox int dirscan(struct inodesc *); 549392Sswilcox void dirty(struct bufarea *); 550392Sswilcox int do_errorlock(int); 551392Sswilcox int dofix(struct inodesc *, caddr_t, ...); 552*4132Sabalfour void examinelog(void (*)(daddr32_t)); 553392Sswilcox void errexit(caddr_t, ...); 554392Sswilcox void fileerror(fsck_ino_t, fsck_ino_t, caddr_t, ...); 555392Sswilcox caddr_t file_id(fsck_ino_t, mode_t); 556392Sswilcox int find_dup_ref(daddr32_t, fsck_ino_t, daddr32_t, int); 557392Sswilcox int findino(struct inodesc *); 558392Sswilcox int findname(struct inodesc *); 559392Sswilcox void fix_cg(struct cg *, int); 560392Sswilcox void flush(int, struct bufarea *); 561392Sswilcox void free_dup_state(void); 562392Sswilcox void freeblk(fsck_ino_t, daddr32_t, int); 563392Sswilcox void freeino(fsck_ino_t, int); 564392Sswilcox void freeinodebuf(void); 565392Sswilcox int fsck_asprintf(caddr_t *, caddr_t, ...); 566392Sswilcox int fsck_bread(int, caddr_t, diskaddr_t, size_t); 567392Sswilcox int ftypeok(struct dinode *); 568392Sswilcox struct bufarea *getblk(struct bufarea *, daddr32_t, size_t); 569392Sswilcox struct bufarea *getdatablk(daddr32_t, size_t size); 570392Sswilcox diskaddr_t getdisksize(caddr_t, int); 571392Sswilcox struct inoinfo *getinoinfo(fsck_ino_t); 572392Sswilcox struct dinode *getnextinode(fsck_ino_t); 573392Sswilcox struct dinode *getnextrefresh(void); 574392Sswilcox void getpathname(caddr_t, fsck_ino_t, fsck_ino_t); 575392Sswilcox struct dinode *ginode(fsck_ino_t); 576392Sswilcox caddr_t hasvfsopt(struct vfstab *, caddr_t); 577392Sswilcox int have_dups(void); 578392Sswilcox void init_inodesc(struct inodesc *); 579392Sswilcox void init_inoinfo(struct inoinfo *, struct dinode *, fsck_ino_t); 580392Sswilcox void initbarea(struct bufarea *); 581392Sswilcox int ino_t_cmp(const void *, const void *); 582392Sswilcox int inocached(fsck_ino_t); 583392Sswilcox void inocleanup(void); 584392Sswilcox void inodirty(void); 585392Sswilcox int is_errorlocked(caddr_t); 586392Sswilcox int linkup(fsck_ino_t, fsck_ino_t, caddr_t); 587392Sswilcox int lookup_named_ino(fsck_ino_t, caddr_t); 588392Sswilcox int makeentry(fsck_ino_t, fsck_ino_t, caddr_t); 589392Sswilcox void maybe_convert_attrdir_to_dir(fsck_ino_t); 590392Sswilcox int mounted(caddr_t, caddr_t, size_t); 591392Sswilcox void pass1(void); 592392Sswilcox void pass1b(void); 593392Sswilcox int pass1check(struct inodesc *); 594504Sswilcox void pass2(void); 595392Sswilcox void pass3a(void); 596392Sswilcox void pass3b(void); 597392Sswilcox int pass3bcheck(struct inodesc *); 598392Sswilcox void pass4(void); 599392Sswilcox int pass4check(struct inodesc *); 600392Sswilcox void pass5(void); 601392Sswilcox void pfatal(caddr_t, ...); 602392Sswilcox void pinode(fsck_ino_t); 603392Sswilcox void printclean(void); 604392Sswilcox void propagate(void); 605392Sswilcox void pwarn(caddr_t, ...); 606392Sswilcox caddr_t rawname(caddr_t); 607392Sswilcox void registershadowclient(fsck_ino_t, fsck_ino_t, 608392Sswilcox struct shadowclientinfo **); 609392Sswilcox void remove_orphan_dir(fsck_ino_t); 610392Sswilcox int reply(caddr_t, ...); 611392Sswilcox int report_dups(int); 612392Sswilcox void resetinodebuf(void); 613392Sswilcox char *setup(caddr_t); 614392Sswilcox void truncino(fsck_ino_t, offset_t, int); 615392Sswilcox void unbufinit(void); 616392Sswilcox caddr_t unrawname(caddr_t); 617392Sswilcox void unregistershadow(fsck_ino_t, struct shadowclientinfo **); 618392Sswilcox int updateclean(void); 619392Sswilcox int writable(caddr_t); 620392Sswilcox void write_altsb(int); 621392Sswilcox 622392Sswilcox /* 623392Sswilcox * Functions from the kernel sources (ufs_subr.c, etc). 624392Sswilcox */ 625392Sswilcox extern void fragacct(struct fs *, int, int32_t *, int); 6260Sstevel@tonic-gate 6270Sstevel@tonic-gate #ifdef __cplusplus 6280Sstevel@tonic-gate } 6290Sstevel@tonic-gate #endif 6300Sstevel@tonic-gate 6310Sstevel@tonic-gate #endif /* _FSCK_FSCK_H */ 632