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*39542a18Sabalfour * Copyright 2007 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 37355d6bb5Sswilcox #include <stdio.h> 38355d6bb5Sswilcox #include <stdarg.h> 39355d6bb5Sswilcox #include <search.h> 40355d6bb5Sswilcox #include <sys/param.h> 41355d6bb5Sswilcox #include <sys/types.h> 42355d6bb5Sswilcox #include <sys/mnttab.h> 43355d6bb5Sswilcox #include <sys/vfstab.h> 44355d6bb5Sswilcox #include <sys/fs/ufs_fs.h> 45355d6bb5Sswilcox #include <sys/fs/ufs_inode.h> 46355d6bb5Sswilcox 477c478bd9Sstevel@tonic-gate #define MAXDUP 10 /* limit on dup blks (per inode) */ 487c478bd9Sstevel@tonic-gate #define MAXBAD 10 /* limit on bad blks (per inode) */ 49355d6bb5Sswilcox #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 53355d6bb5Sswilcox #define BUFSIZ MAXPATHLEN 547c478bd9Sstevel@tonic-gate #endif 557c478bd9Sstevel@tonic-gate 56355d6bb5Sswilcox /* 57355d6bb5Sswilcox * Inode states in statemap[]. 58355d6bb5Sswilcox */ 59355d6bb5Sswilcox #define USTATE 0x01 /* inode not allocated */ 60355d6bb5Sswilcox #define FSTATE 0x02 /* inode is file */ 61355d6bb5Sswilcox #define DSTATE 0x04 /* inode is directory */ 62355d6bb5Sswilcox #define SSTATE 0x08 /* inode is a shadow/acl */ 63355d6bb5Sswilcox #define STMASK 0x0f /* pick off the basic state/type */ 64355d6bb5Sswilcox 65355d6bb5Sswilcox /* flags OR'd into the above */ 66355d6bb5Sswilcox #define INZLINK 0x0010 /* inode has zero links */ 67355d6bb5Sswilcox #define INFOUND 0x0020 /* inode was found during descent */ 68355d6bb5Sswilcox #define INCLEAR 0x0040 /* inode is to be cleared */ 69355d6bb5Sswilcox #define INORPHAN 0x0080 /* inode is a known orphan (pass3 only) */ 70355d6bb5Sswilcox #define INDELAYD 0x0200 /* link count update delayed */ 71355d6bb5Sswilcox #define INMASK 0xfff0 /* pick off the modifiers */ 72355d6bb5Sswilcox 73355d6bb5Sswilcox #define FZLINK (FSTATE | INZLINK) 74355d6bb5Sswilcox #define DZLINK (DSTATE | INZLINK) 75355d6bb5Sswilcox #define SZLINK (SSTATE | INZLINK) 76355d6bb5Sswilcox 77355d6bb5Sswilcox #define DFOUND (DSTATE | INFOUND) 78355d6bb5Sswilcox 79355d6bb5Sswilcox #define DCLEAR (DSTATE | INCLEAR) 80355d6bb5Sswilcox #define FCLEAR (FSTATE | INCLEAR) 81355d6bb5Sswilcox #define SCLEAR (SSTATE | INCLEAR) 82355d6bb5Sswilcox 83355d6bb5Sswilcox /* 84355d6bb5Sswilcox * These tests depend on the state/type defines above not overlapping bits. 85355d6bb5Sswilcox * 86355d6bb5Sswilcox * DUNFOUND === (state == DSTATE || state == DZLINK) 87355d6bb5Sswilcox * INCLEAR is irrelevant to the determination of 88355d6bb5Sswilcox * connectedness, so it's not included in this test. 89355d6bb5Sswilcox * 90355d6bb5Sswilcox * DVALID === (state == DSTATE || state == DZLINK || state == DFOUND) 91355d6bb5Sswilcox */ 92355d6bb5Sswilcox #define S_IS_DUNFOUND(state) (((state) & (DSTATE | INZLINK)) \ 93355d6bb5Sswilcox == (state)) 94355d6bb5Sswilcox #define S_IS_DVALID(state) (((state) & (DSTATE | INZLINK | INFOUND | \ 95355d6bb5Sswilcox INORPHAN)) == (state)) 96355d6bb5Sswilcox #define S_IS_ZLINK(state) (((state) & INZLINK) != 0) 97355d6bb5Sswilcox #define INO_IS_DUNFOUND(ino) S_IS_DUNFOUND(statemap[ino]) 98355d6bb5Sswilcox #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 */ 106355d6bb5Sswilcox 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 */ 126355d6bb5Sswilcox 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 131355d6bb5Sswilcox #define sbdirty() dirty(&sblk) 132355d6bb5Sswilcox #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 136355d6bb5Sswilcox /* 137355d6bb5Sswilcox * inodesc.id_fix values. See inode.c for a description of their usage. 138355d6bb5Sswilcox */ 139355d6bb5Sswilcox enum fixstate { 140355d6bb5Sswilcox DONTKNOW, NOFIX, FIX, IGNORE 141355d6bb5Sswilcox }; 1427c478bd9Sstevel@tonic-gate 143355d6bb5Sswilcox /* 144355d6bb5Sswilcox * Tells truncino() whether or not to attempt to update the parent 145355d6bb5Sswilcox * directory's link count. Also, TI_NODUP flags when we're discarding 146355d6bb5Sswilcox * fragments that are beyond the original end of the file, and so 147355d6bb5Sswilcox * should not be considered duplicate-claim candidates. 148355d6bb5Sswilcox */ 149355d6bb5Sswilcox #define TI_NOPARENT 0x0001 /* leave parent's di_nlink alone */ 150355d6bb5Sswilcox #define TI_PARENT 0x0002 /* update parent's di_nlink */ 151355d6bb5Sswilcox #define TI_NODUP 0x0004 /* not a dup candidate */ 152355d6bb5Sswilcox 153355d6bb5Sswilcox /* 154355d6bb5Sswilcox * Modes for ckinode() and ckinode_common(). 155355d6bb5Sswilcox * 156355d6bb5Sswilcox * CKI_TRAVERSE is the common case, and requests a traditional 157355d6bb5Sswilcox * traversal of blocks or directory entries. 158355d6bb5Sswilcox * 159355d6bb5Sswilcox * CKI_TRUNCATE indicates that we're truncating the file, and that any 160355d6bb5Sswilcox * block indices beyond the end of the target length should be cleared 161355d6bb5Sswilcox * after the callback has returned (i.e., this is a superset of 162355d6bb5Sswilcox * CKI_TRAVERSE). idesc->id_truncto is the first logical block number 163355d6bb5Sswilcox * to clear. If it is less than zero, then the traversal will be 164355d6bb5Sswilcox * equivalent to a simple CKI_TRAVERSE. 165355d6bb5Sswilcox */ 166355d6bb5Sswilcox enum cki_action { CKI_TRAVERSE, CKI_TRUNCATE }; 167355d6bb5Sswilcox 168355d6bb5Sswilcox /* 169355d6bb5Sswilcox * The general definition of an ino_t is an unsigned quantity. 170355d6bb5Sswilcox * However, the on-disk version is an int32_t, which is signed. 171355d6bb5Sswilcox * Since we really want to be able to detect wrapped-around 172355d6bb5Sswilcox * inode numbers and such, we'll use something that's compatible 173355d6bb5Sswilcox * with what's on disk since that's the only context that really 174355d6bb5Sswilcox * matters. If an int32_t is found not to be sufficiently large, 175355d6bb5Sswilcox * this will make it much easier to change later. 176355d6bb5Sswilcox * 177355d6bb5Sswilcox * Note that there is one unsigned inode field in the on-disk 178355d6bb5Sswilcox * inode, ic_oeftflag. Since all other inode fields are signed, 179355d6bb5Sswilcox * no legitimate inode number can be put into ic_oeftflag that 180355d6bb5Sswilcox * would overflow into the high bit. Essentially, it should 181355d6bb5Sswilcox * actually be declared as int32_t just like all the others, and 182355d6bb5Sswilcox * we're going to pretend that it was. 183355d6bb5Sswilcox * 184355d6bb5Sswilcox * None of the routines that we use in ufs_subr.c do anything with 185355d6bb5Sswilcox * inode numbers. If that changes, then great care will be needed 186355d6bb5Sswilcox * to deal with the differences in definition of ino_t and fsck_ino_t. 187355d6bb5Sswilcox * Lint is your friend. 188355d6bb5Sswilcox */ 189355d6bb5Sswilcox typedef int32_t fsck_ino_t; 190355d6bb5Sswilcox 191355d6bb5Sswilcox /* 192355d6bb5Sswilcox * See the full discussion of the interactions between struct inodesc 193355d6bb5Sswilcox * and ckinode() in inode.c 194355d6bb5Sswilcox */ 1957c478bd9Sstevel@tonic-gate struct inodesc { 1967c478bd9Sstevel@tonic-gate enum fixstate id_fix; /* policy on fixing errors */ 197355d6bb5Sswilcox int (*id_func)(struct inodesc *); 198355d6bb5Sswilcox /* function to be applied to blocks of inode */ 199355d6bb5Sswilcox fsck_ino_t id_number; /* inode number described */ 200355d6bb5Sswilcox fsck_ino_t id_parent; /* for DATA nodes, their parent */ 201355d6bb5Sswilcox /* also used for extra (*id_func) parameter */ 202355d6bb5Sswilcox /* and return values */ 203355d6bb5Sswilcox daddr32_t id_lbn; /* logical fragment number of current block */ 204355d6bb5Sswilcox daddr32_t id_blkno; /* physical fragment number being examined */ 2057c478bd9Sstevel@tonic-gate int id_numfrags; /* number of frags contained in block */ 206355d6bb5Sswilcox 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 */ 2087c478bd9Sstevel@tonic-gate uint_t id_loc; /* for DATA nodes, current location in dir */ 209355d6bb5Sswilcox daddr32_t id_entryno; /* for DATA nodes, current dir entry number */ 210355d6bb5Sswilcox daddr32_t id_firsthole; /* for DATA inode, logical block that is */ 211355d6bb5Sswilcox /* zero but shouldn't be, -1 for no holes */ 2127c478bd9Sstevel@tonic-gate struct direct *id_dirp; /* for DATA nodes, ptr to current entry */ 213355d6bb5Sswilcox 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 }; 216355d6bb5Sswilcox 217355d6bb5Sswilcox /* file types (0 is reserved for catching bugs) */ 218355d6bb5Sswilcox #define DATA 1 /* a directory */ 219355d6bb5Sswilcox #define ACL 2 /* an acl/shadow */ 220355d6bb5Sswilcox #define ADDR 3 /* anything but a directory or an acl/shadow */ 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate /* 223355d6bb5Sswilcox * OR'd flags for find_dup_ref()'s mode argument 2247c478bd9Sstevel@tonic-gate */ 225355d6bb5Sswilcox #define DB_CREATE 0x01 /* if dup record found, make one */ 226355d6bb5Sswilcox #define DB_INCR 0x02 /* increment block's reference count */ 227355d6bb5Sswilcox #define DB_DECR 0x04 /* decrement block's reference count */ 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate /* 230355d6bb5Sswilcox * Cache data structures 2317c478bd9Sstevel@tonic-gate */ 2327c478bd9Sstevel@tonic-gate struct inoinfo { 233355d6bb5Sswilcox struct inoinfo *i_nextlist; /* next inode/acl cache entry */ 234355d6bb5Sswilcox fsck_ino_t i_number; /* inode number of this entry */ 235355d6bb5Sswilcox fsck_ino_t i_parent; /* inode number of parent */ 236355d6bb5Sswilcox fsck_ino_t i_dotdot; /* inode number of .. */ 237355d6bb5Sswilcox fsck_ino_t i_extattr; /* inode of hidden attr dir */ 2387c478bd9Sstevel@tonic-gate offset_t i_isize; /* size of inode */ 239355d6bb5Sswilcox size_t i_blkssize; /* size of block array in bytes */ 2407c478bd9Sstevel@tonic-gate daddr32_t i_blks[1]; /* actually longer */ 241355d6bb5Sswilcox }; 242355d6bb5Sswilcox 243355d6bb5Sswilcox /* 244355d6bb5Sswilcox * Inode cache 245355d6bb5Sswilcox */ 246355d6bb5Sswilcox struct inoinfo **inphead, **inpsort; 2477c478bd9Sstevel@tonic-gate int64_t numdirs, listmax, inplast; 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate /* 250355d6bb5Sswilcox * ACL cache 2517c478bd9Sstevel@tonic-gate */ 252355d6bb5Sswilcox struct inoinfo **aclphead, **aclpsort; 2537c478bd9Sstevel@tonic-gate int64_t numacls, aclmax, aclplast; 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate /* 256355d6bb5Sswilcox * Tree of directories we haven't reconnected or cleared. Any 257355d6bb5Sswilcox * dir inode that linkup() fails on gets added, any that clri() 258355d6bb5Sswilcox * succeeds on gets removed. If there are any left at the end of 259355d6bb5Sswilcox * pass four, then we have a user-forced corrupt filesystem, and 260355d6bb5Sswilcox * need to set iscorrupt. 261355d6bb5Sswilcox * 262355d6bb5Sswilcox * Elements are fsck_ino_t instances (not pointers). 263355d6bb5Sswilcox */ 264355d6bb5Sswilcox void *limbo_dirs; 265355d6bb5Sswilcox 266355d6bb5Sswilcox /* 267355d6bb5Sswilcox * Number of directories we actually found in the filesystem, 268355d6bb5Sswilcox * as opposed to how many the superblock claims there are. 269355d6bb5Sswilcox */ 270355d6bb5Sswilcox fsck_ino_t countdirs; 271355d6bb5Sswilcox 272355d6bb5Sswilcox /* 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 { 279355d6bb5Sswilcox 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 { 284355d6bb5Sswilcox 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 */ 290355d6bb5Sswilcox struct shadowclientinfo *shadowclientinfo; 291355d6bb5Sswilcox struct shadowclientinfo *attrclientinfo; 2927c478bd9Sstevel@tonic-gate 293355d6bb5Sswilcox /* 294355d6bb5Sswilcox * In ufs_inode.h ifdef _KERNEL, this is defined as `/@/'. However, 295355d6bb5Sswilcox * to avoid all sorts of potential confusion (you can't actually use 296355d6bb5Sswilcox * `foo/@/bar' to get to an attribute), we use something that doesn't 297355d6bb5Sswilcox * look quite so much like a simple pathname. 298355d6bb5Sswilcox */ 299355d6bb5Sswilcox #define XATTR_DIR_NAME " <xattr> " 300355d6bb5Sswilcox 301355d6bb5Sswilcox /* 302355d6bb5Sswilcox * granularity -- how many client inodes do we make space for at a time 303355d6bb5Sswilcox * initialized in setup.c; 304355d6bb5Sswilcox */ 305355d6bb5Sswilcox extern int maxshadowclients; 306355d6bb5Sswilcox 307355d6bb5Sswilcox /* 308355d6bb5Sswilcox * Initialized global variables. 309355d6bb5Sswilcox */ 310355d6bb5Sswilcox extern caddr_t lfname; 311355d6bb5Sswilcox 312355d6bb5Sswilcox /* 313355d6bb5Sswilcox * Unitialized globals. 314355d6bb5Sswilcox */ 3157c478bd9Sstevel@tonic-gate char *devname; /* name of device being checked */ 316355d6bb5Sswilcox 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 */ 320355d6bb5Sswilcox 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 */ 323355d6bb5Sswilcox int roflag; /* do normal checks but don't update disk */ 3247c478bd9Sstevel@tonic-gate int fflag; /* check regardless of clean flag (force) */ 325355d6bb5Sswilcox int mflag; /* sanity check only */ 326355d6bb5Sswilcox int verbose; /* be chatty */ 3277c478bd9Sstevel@tonic-gate char preen; /* just fix normal inconsistencies */ 3287c478bd9Sstevel@tonic-gate char mountedfs; /* checking mounted device */ 329355d6bb5Sswilcox int exitstat; /* exit status (see EX* defines below) */ 3307c478bd9Sstevel@tonic-gate char hotroot; /* checking root device */ 331355d6bb5Sswilcox char rerun; /* rerun fsck. Only used in non-preen mode */ 332355d6bb5Sswilcox 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 */ 338355d6bb5Sswilcox /* -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 */ 353355d6bb5Sswilcox uint_t largefile_count; /* global largefile counter */ 354355d6bb5Sswilcox char *mount_point; /* if mounted, this is where */ 3557c478bd9Sstevel@tonic-gate char *blockmap; /* ptr to primary blk allocation map */ 356355d6bb5Sswilcox fsck_ino_t maxino; /* number of inodes in file system */ 357355d6bb5Sswilcox fsck_ino_t lastino; /* last inode in use */ 358355d6bb5Sswilcox ushort_t *statemap; /* ptr to inode state table */ 3597c478bd9Sstevel@tonic-gate short *lncntp; /* ptr to link count table */ 3607c478bd9Sstevel@tonic-gate 361355d6bb5Sswilcox fsck_ino_t lfdir; /* lost & found directory inode number */ 362355d6bb5Sswilcox int overflowed_lf; /* tried to wrap lost & found's link count */ 363355d6bb5Sswilcox int reattached_dir; /* reconnected at least one directory */ 364355d6bb5Sswilcox int broke_dir_link; /* broke at least one directory hardlink */ 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate daddr32_t n_blks; /* number of blocks in use */ 367355d6bb5Sswilcox fsck_ino_t n_files; /* number of files in use */ 3687c478bd9Sstevel@tonic-gate 369355d6bb5Sswilcox #define clearinode(dp) { \ 370355d6bb5Sswilcox *(dp) = zino; \ 371355d6bb5Sswilcox } 3727c478bd9Sstevel@tonic-gate struct dinode zino; 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate #define testbmap(blkno) isset(blockmap, blkno) 375355d6bb5Sswilcox #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 384355d6bb5Sswilcox /* 385355d6bb5Sswilcox * Support relatively easy debugging of lncntp[] updates. This can't 386355d6bb5Sswilcox * be a function, because of the (_op) step. Normally, we just do that. 387355d6bb5Sswilcox */ 388355d6bb5Sswilcox #define TRACK_LNCNTP(_ino, _op) (_op) 3897c478bd9Sstevel@tonic-gate 390355d6bb5Sswilcox /* 391355d6bb5Sswilcox * See if the net link count for an inode has gone outside 392355d6bb5Sswilcox * what can be represented on disk. Returning text as NULL 393355d6bb5Sswilcox * indicates no. 394355d6bb5Sswilcox * 395355d6bb5Sswilcox * Remember that link counts are effectively inverted, so 396355d6bb5Sswilcox * underflow and overflow are reversed as well. 397355d6bb5Sswilcox * 398355d6bb5Sswilcox * This check should be done before modifying the actual link 399355d6bb5Sswilcox * count. 400355d6bb5Sswilcox */ 401355d6bb5Sswilcox #define LINK_RANGE(text, current, offset) { \ 402355d6bb5Sswilcox int net = ((int)(current)) + ((int)(offset)); \ 403355d6bb5Sswilcox text = NULL; \ 404355d6bb5Sswilcox if (net > (MAXLINK)) \ 405355d6bb5Sswilcox text = "UNDERFLOW"; \ 406355d6bb5Sswilcox else if (net < -(MAXLINK)) \ 407355d6bb5Sswilcox text = "OVERFLOW"; \ 408355d6bb5Sswilcox } 409355d6bb5Sswilcox 410355d6bb5Sswilcox /* 411355d6bb5Sswilcox * If LINK_RANGE() indicated a problem, this is the boiler-plate 412355d6bb5Sswilcox * for dealing with it. Usage is: 413355d6bb5Sswilcox * 414355d6bb5Sswilcox * LINK_RANGE(text, current, offset); 415355d6bb5Sswilcox * if (text != NULL) { 416355d6bb5Sswilcox * LINK_CLEAR(text, ino, mode, idp); 417355d6bb5Sswilcox * if (statemap[ino] == USTATE) 418355d6bb5Sswilcox * ...inode was cleared... 419355d6bb5Sswilcox * } 420355d6bb5Sswilcox * 421355d6bb5Sswilcox * Note that clri() will set iscorrupt if the user elects not to 422355d6bb5Sswilcox * clear the problem inode, so the filesystem won't get reported 423355d6bb5Sswilcox * as clean when it shouldn't be. 424355d6bb5Sswilcox */ 425355d6bb5Sswilcox #define LINK_CLEAR(text, ino, mode, idp) { \ 426355d6bb5Sswilcox pwarn("%s LINK COUNT %s", file_id((ino), (mode)), (text)); \ 427355d6bb5Sswilcox pinode((ino)); \ 428355d6bb5Sswilcox pfatal(""); \ 429355d6bb5Sswilcox init_inodesc((idp)); \ 430355d6bb5Sswilcox (idp)->id_type = ADDR; \ 431355d6bb5Sswilcox (idp)->id_func = pass4check; \ 432355d6bb5Sswilcox (idp)->id_number = ino; \ 433355d6bb5Sswilcox (idp)->id_fix = DONTKNOW; \ 434355d6bb5Sswilcox clri((idp), (text), CLRI_QUIET, CLRI_NOP_CORRUPT); \ 435355d6bb5Sswilcox } 436355d6bb5Sswilcox 437355d6bb5Sswilcox /* 438355d6bb5Sswilcox * Used for checking link count under/overflow specifically on 439355d6bb5Sswilcox * the lost+found directory. If the user decides not to do the 440355d6bb5Sswilcox * clri(), then flag that we've hit this problem and refuse to do 441355d6bb5Sswilcox * the reconnect. 442355d6bb5Sswilcox */ 443355d6bb5Sswilcox #define LFDIR_LINK_RANGE_RVAL(text, current, offset, idp, rval) { \ 444355d6bb5Sswilcox LINK_RANGE(text, current, offset); \ 445355d6bb5Sswilcox if (text != NULL) { \ 446355d6bb5Sswilcox LINK_CLEAR(text, lfdir, IFDIR, idp); \ 447355d6bb5Sswilcox if (statemap[lfdir] == USTATE) { \ 448355d6bb5Sswilcox lfdir = 0; \ 449355d6bb5Sswilcox return (rval); \ 450355d6bb5Sswilcox } else { \ 451355d6bb5Sswilcox overflowed_lf++; \ 452355d6bb5Sswilcox } \ 453355d6bb5Sswilcox } \ 454355d6bb5Sswilcox } 455355d6bb5Sswilcox 456355d6bb5Sswilcox #define LFDIR_LINK_RANGE_NORVAL(text, current, offset, idp) { \ 457355d6bb5Sswilcox LINK_RANGE(text, current, offset); \ 458355d6bb5Sswilcox if (text != NULL) { \ 459355d6bb5Sswilcox LINK_CLEAR(text, lfdir, IFDIR, idp); \ 460355d6bb5Sswilcox if (statemap[lfdir] == USTATE) { \ 461355d6bb5Sswilcox lfdir = 0; \ 462355d6bb5Sswilcox return; \ 463355d6bb5Sswilcox } else { \ 464355d6bb5Sswilcox overflowed_lf++; \ 465355d6bb5Sswilcox } \ 466355d6bb5Sswilcox } \ 467355d6bb5Sswilcox } 468355d6bb5Sswilcox 469355d6bb5Sswilcox /* 470355d6bb5Sswilcox * Values for mounted() and mountedfs. 471355d6bb5Sswilcox */ 472355d6bb5Sswilcox #define M_NOMNT 0 /* filesystem is not mounted */ 473355d6bb5Sswilcox #define M_RO 1 /* filesystem is mounted read-only */ 474355d6bb5Sswilcox #define M_RW 2 /* filesystem is mounted read-write */ 475355d6bb5Sswilcox 476355d6bb5Sswilcox #define EXOKAY 0 /* file system is unmounted and ok */ 477355d6bb5Sswilcox #define EXBADPARM 1 /* bad parameter(s) given */ 478355d6bb5Sswilcox #define EXUMNTCHK 32 /* fsck -m: unmounted, needs checking */ 479355d6bb5Sswilcox #define EXMOUNTED 33 /* file system already mounted, not magic, */ 480355d6bb5Sswilcox /* or it is magic and mounted read/write */ 481355d6bb5Sswilcox #define EXNOSTAT 34 /* cannot stat device */ 482355d6bb5Sswilcox #define EXREBOOTNOW 35 /* modified root or something equally scary */ 483355d6bb5Sswilcox #define EXFNDERRS 36 /* uncorrectable errors, terminate normally */ 484355d6bb5Sswilcox #define EXSIGNAL 37 /* a signal was caught during processing */ 485355d6bb5Sswilcox #define EXERRFATAL 39 /* uncorrectable errors, exit immediately */ 486355d6bb5Sswilcox #define EXROOTOKAY 40 /* for root, same as 0 */ 487355d6bb5Sswilcox 488355d6bb5Sswilcox /* 489355d6bb5Sswilcox * Values for clri()'s `verbose' and `corrupting' arguments (third 490355d6bb5Sswilcox * and fourth, respectively). 491355d6bb5Sswilcox */ 492355d6bb5Sswilcox #define CLRI_QUIET 1 493355d6bb5Sswilcox #define CLRI_VERBOSE 2 494355d6bb5Sswilcox 495355d6bb5Sswilcox #define CLRI_NOP_OK 1 496355d6bb5Sswilcox #define CLRI_NOP_CORRUPT 2 497355d6bb5Sswilcox 498355d6bb5Sswilcox /* 499355d6bb5Sswilcox * Filesystems that are `magical' - if they exist in vfstab, 500355d6bb5Sswilcox * then they have to be mounted for the system to have gotten 501355d6bb5Sswilcox * far enough to be able to run fsck. Thus, don't get all 502355d6bb5Sswilcox * bent out of shape if we're asked to check it and it is mounted. 503355d6bb5Sswilcox * Actual initialization of the array is in main.c 504355d6bb5Sswilcox */ 505355d6bb5Sswilcox enum magic { 506355d6bb5Sswilcox MAGIC_NONE = 0, 507355d6bb5Sswilcox MAGIC_ROOT = 1, 508355d6bb5Sswilcox MAGIC_USR = 2, 509b9a41fd3Sswilcox MAGIC_LIMIT = 3 510355d6bb5Sswilcox }; 511355d6bb5Sswilcox extern char *magic_fs[]; 512355d6bb5Sswilcox 513355d6bb5Sswilcox /* 514355d6bb5Sswilcox * Paths needed by calcsb(). 515355d6bb5Sswilcox */ 516355d6bb5Sswilcox #define MKFS_PATH "/usr/lib/fs/ufs/mkfs" 517355d6bb5Sswilcox #define NEWFS_PATH "/usr/lib/fs/ufs/newfs" 518355d6bb5Sswilcox 519355d6bb5Sswilcox int acltypeok(struct dinode *); 520355d6bb5Sswilcox void add_orphan_dir(fsck_ino_t); 521355d6bb5Sswilcox void adjust(struct inodesc *, int); 522355d6bb5Sswilcox daddr32_t allocblk(int); 523355d6bb5Sswilcox fsck_ino_t allocdir(fsck_ino_t, fsck_ino_t, int, int); 524355d6bb5Sswilcox fsck_ino_t allocino(fsck_ino_t, int); 525355d6bb5Sswilcox void blkerror(fsck_ino_t, caddr_t, daddr32_t, daddr32_t); 526355d6bb5Sswilcox void brelse(struct bufarea *); 527355d6bb5Sswilcox void bufinit(void); 528355d6bb5Sswilcox void bwrite(int, caddr_t, diskaddr_t, int64_t); 529355d6bb5Sswilcox void cacheacl(struct dinode *, fsck_ino_t); 530355d6bb5Sswilcox void cacheino(struct dinode *, fsck_ino_t); 531355d6bb5Sswilcox void catch(int); 532355d6bb5Sswilcox void catchquit(int); 53377a343abSabalfour caddr_t cg_sanity(struct cg *, int); 534355d6bb5Sswilcox void cgflush(void); 535355d6bb5Sswilcox int cgisdirty(void); 536355d6bb5Sswilcox int changeino(fsck_ino_t, caddr_t, fsck_ino_t); 537355d6bb5Sswilcox int check_mnttab(caddr_t, caddr_t, size_t); 538355d6bb5Sswilcox int check_vfstab(caddr_t, caddr_t, size_t); 539355d6bb5Sswilcox int chkrange(daddr32_t, int); 540355d6bb5Sswilcox void ckfini(void); 541355d6bb5Sswilcox int ckinode(struct dinode *, struct inodesc *, enum cki_action); 542355d6bb5Sswilcox void clearattrref(fsck_ino_t); 543355d6bb5Sswilcox int cleardirentry(fsck_ino_t, fsck_ino_t); 544355d6bb5Sswilcox void clearshadow(fsck_ino_t, struct shadowclientinfo **); 545355d6bb5Sswilcox void clri(struct inodesc *, caddr_t, int, int); 546355d6bb5Sswilcox void deshadow(struct shadowclientinfo *, void (*)(fsck_ino_t)); 547355d6bb5Sswilcox void direrror(fsck_ino_t, caddr_t, ...); 548355d6bb5Sswilcox int dirscan(struct inodesc *); 549355d6bb5Sswilcox void dirty(struct bufarea *); 550355d6bb5Sswilcox int do_errorlock(int); 551355d6bb5Sswilcox int dofix(struct inodesc *, caddr_t, ...); 552*39542a18Sabalfour void examinelog(void (*)(daddr32_t)); 553355d6bb5Sswilcox void errexit(caddr_t, ...); 554355d6bb5Sswilcox void fileerror(fsck_ino_t, fsck_ino_t, caddr_t, ...); 555355d6bb5Sswilcox caddr_t file_id(fsck_ino_t, mode_t); 556355d6bb5Sswilcox int find_dup_ref(daddr32_t, fsck_ino_t, daddr32_t, int); 557355d6bb5Sswilcox int findino(struct inodesc *); 558355d6bb5Sswilcox int findname(struct inodesc *); 559355d6bb5Sswilcox void fix_cg(struct cg *, int); 560355d6bb5Sswilcox void flush(int, struct bufarea *); 561355d6bb5Sswilcox void free_dup_state(void); 562355d6bb5Sswilcox void freeblk(fsck_ino_t, daddr32_t, int); 563355d6bb5Sswilcox void freeino(fsck_ino_t, int); 564355d6bb5Sswilcox void freeinodebuf(void); 565355d6bb5Sswilcox int fsck_asprintf(caddr_t *, caddr_t, ...); 566355d6bb5Sswilcox int fsck_bread(int, caddr_t, diskaddr_t, size_t); 567355d6bb5Sswilcox int ftypeok(struct dinode *); 568355d6bb5Sswilcox struct bufarea *getblk(struct bufarea *, daddr32_t, size_t); 569355d6bb5Sswilcox struct bufarea *getdatablk(daddr32_t, size_t size); 570355d6bb5Sswilcox diskaddr_t getdisksize(caddr_t, int); 571355d6bb5Sswilcox struct inoinfo *getinoinfo(fsck_ino_t); 572355d6bb5Sswilcox struct dinode *getnextinode(fsck_ino_t); 573355d6bb5Sswilcox struct dinode *getnextrefresh(void); 574355d6bb5Sswilcox void getpathname(caddr_t, fsck_ino_t, fsck_ino_t); 575355d6bb5Sswilcox struct dinode *ginode(fsck_ino_t); 576355d6bb5Sswilcox caddr_t hasvfsopt(struct vfstab *, caddr_t); 577355d6bb5Sswilcox int have_dups(void); 578355d6bb5Sswilcox void init_inodesc(struct inodesc *); 579355d6bb5Sswilcox void init_inoinfo(struct inoinfo *, struct dinode *, fsck_ino_t); 580355d6bb5Sswilcox void initbarea(struct bufarea *); 581355d6bb5Sswilcox int ino_t_cmp(const void *, const void *); 582355d6bb5Sswilcox int inocached(fsck_ino_t); 583355d6bb5Sswilcox void inocleanup(void); 584355d6bb5Sswilcox void inodirty(void); 585355d6bb5Sswilcox int is_errorlocked(caddr_t); 586355d6bb5Sswilcox int linkup(fsck_ino_t, fsck_ino_t, caddr_t); 587355d6bb5Sswilcox int lookup_named_ino(fsck_ino_t, caddr_t); 588355d6bb5Sswilcox int makeentry(fsck_ino_t, fsck_ino_t, caddr_t); 589355d6bb5Sswilcox void maybe_convert_attrdir_to_dir(fsck_ino_t); 590355d6bb5Sswilcox int mounted(caddr_t, caddr_t, size_t); 591355d6bb5Sswilcox void pass1(void); 592355d6bb5Sswilcox void pass1b(void); 593355d6bb5Sswilcox int pass1check(struct inodesc *); 594b9a41fd3Sswilcox void pass2(void); 595355d6bb5Sswilcox void pass3a(void); 596355d6bb5Sswilcox void pass3b(void); 597355d6bb5Sswilcox int pass3bcheck(struct inodesc *); 598355d6bb5Sswilcox void pass4(void); 599355d6bb5Sswilcox int pass4check(struct inodesc *); 600355d6bb5Sswilcox void pass5(void); 601355d6bb5Sswilcox void pfatal(caddr_t, ...); 602355d6bb5Sswilcox void pinode(fsck_ino_t); 603355d6bb5Sswilcox void printclean(void); 604355d6bb5Sswilcox void propagate(void); 605355d6bb5Sswilcox void pwarn(caddr_t, ...); 606355d6bb5Sswilcox caddr_t rawname(caddr_t); 607355d6bb5Sswilcox void registershadowclient(fsck_ino_t, fsck_ino_t, 608355d6bb5Sswilcox struct shadowclientinfo **); 609355d6bb5Sswilcox void remove_orphan_dir(fsck_ino_t); 610355d6bb5Sswilcox int reply(caddr_t, ...); 611355d6bb5Sswilcox int report_dups(int); 612355d6bb5Sswilcox void resetinodebuf(void); 613355d6bb5Sswilcox char *setup(caddr_t); 614355d6bb5Sswilcox void truncino(fsck_ino_t, offset_t, int); 615355d6bb5Sswilcox void unbufinit(void); 616355d6bb5Sswilcox caddr_t unrawname(caddr_t); 617355d6bb5Sswilcox void unregistershadow(fsck_ino_t, struct shadowclientinfo **); 618355d6bb5Sswilcox int updateclean(void); 619355d6bb5Sswilcox int writable(caddr_t); 620355d6bb5Sswilcox void write_altsb(int); 621355d6bb5Sswilcox 622355d6bb5Sswilcox /* 623355d6bb5Sswilcox * Functions from the kernel sources (ufs_subr.c, etc). 624355d6bb5Sswilcox */ 625355d6bb5Sswilcox extern void fragacct(struct fs *, int, int32_t *, int); 6267c478bd9Sstevel@tonic-gate 6277c478bd9Sstevel@tonic-gate #ifdef __cplusplus 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate #endif 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate #endif /* _FSCK_FSCK_H */ 632