1 1.59 andvar /* $NetBSD: fsck.h,v 1.59 2025/03/04 07:42:19 andvar Exp $ */ 2 1.8 cgd 3 1.1 cgd /* 4 1.6 mycroft * Copyright (c) 1980, 1986, 1993 5 1.6 mycroft * The Regents of the University of California. All rights reserved. 6 1.1 cgd * 7 1.32 fvdl * 8 1.32 fvdl * This software was developed for the FreeBSD Project by Marshall 9 1.32 fvdl * Kirk McKusick and Network Associates Laboratories, the Security 10 1.32 fvdl * Research Division of Network Associates, Inc. under DARPA/SPAWAR 11 1.32 fvdl * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS 12 1.32 fvdl * research program 13 1.32 fvdl * 14 1.1 cgd * Redistribution and use in source and binary forms, with or without 15 1.1 cgd * modification, are permitted provided that the following conditions 16 1.1 cgd * are met: 17 1.1 cgd * 1. Redistributions of source code must retain the above copyright 18 1.1 cgd * notice, this list of conditions and the following disclaimer. 19 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 20 1.1 cgd * notice, this list of conditions and the following disclaimer in the 21 1.1 cgd * documentation and/or other materials provided with the distribution. 22 1.35 agc * 3. Neither the name of the University nor the names of its contributors 23 1.1 cgd * may be used to endorse or promote products derived from this software 24 1.1 cgd * without specific prior written permission. 25 1.1 cgd * 26 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 1.1 cgd * SUCH DAMAGE. 37 1.1 cgd * 38 1.14 lukem * @(#)fsck.h 8.4 (Berkeley) 5/9/95 39 1.1 cgd */ 40 1.1 cgd 41 1.14 lukem #include <stdio.h> 42 1.49 bouyer #include <sys/queue.h> 43 1.19 bouyer #include <machine/bswap.h> 44 1.14 lukem 45 1.41 christos #ifdef PROGRESS 46 1.40 christos #include "progress.h" 47 1.41 christos #endif /* PROGRESS */ 48 1.40 christos 49 1.1 cgd #define MAXDUP 10 /* limit on dup blks (per inode) */ 50 1.1 cgd #define MAXBAD 10 /* limit on bad blks (per inode) */ 51 1.1 cgd #define MAXBUFSPACE 40*1024 /* maximum space to allocate to buffers */ 52 1.1 cgd #define INOBUFSIZE 56*1024 /* size of buffer to read inodes in pass1 */ 53 1.1 cgd 54 1.32 fvdl union dinode { 55 1.32 fvdl struct ufs1_dinode dp1; 56 1.32 fvdl struct ufs2_dinode dp2; 57 1.32 fvdl }; 58 1.32 fvdl #define DIP(dp, field) \ 59 1.32 fvdl (is_ufs2 ? (dp)->dp2.di_##field : (dp)->dp1.di_##field) 60 1.32 fvdl 61 1.45 skrll #define DIP_SET(dp, field, val) do { \ 62 1.45 skrll if (is_ufs2) \ 63 1.45 skrll (dp)->dp2.di_##field = (val); \ 64 1.45 skrll else \ 65 1.45 skrll (dp)->dp1.di_##field = (val); \ 66 1.45 skrll } while (0) 67 1.45 skrll 68 1.1 cgd #ifndef BUFSIZ 69 1.1 cgd #define BUFSIZ 1024 70 1.1 cgd #endif 71 1.1 cgd 72 1.32 fvdl /* 73 1.32 fvdl * Each inode on the filesystem is described by the following structure. 74 1.32 fvdl * The linkcnt is initially set to the value in the inode. Each time it 75 1.32 fvdl * is found during the descent in passes 2, 3, and 4 the count is 76 1.32 fvdl * decremented. Any inodes whose count is non-zero after pass 4 needs to 77 1.32 fvdl * have its link count adjusted by the value remaining in ino_linkcnt. 78 1.32 fvdl */ 79 1.32 fvdl struct inostat { 80 1.32 fvdl char ino_state; /* state of inode, see below */ 81 1.32 fvdl char ino_type; /* type of inode */ 82 1.32 fvdl short ino_linkcnt; /* number of links not found */ 83 1.32 fvdl }; 84 1.32 fvdl /* 85 1.32 fvdl * Inode states. 86 1.32 fvdl */ 87 1.1 cgd #define USTATE 01 /* inode not allocated */ 88 1.1 cgd #define FSTATE 02 /* inode is file */ 89 1.1 cgd #define DSTATE 03 /* inode is directory */ 90 1.1 cgd #define DFOUND 04 /* directory found during descent */ 91 1.1 cgd #define DCLEAR 05 /* directory is to be cleared */ 92 1.1 cgd #define FCLEAR 06 /* file is to be cleared */ 93 1.22 mycroft #define DMARK 07 /* used in propagate()'s traversal algorithm */ 94 1.1 cgd 95 1.1 cgd /* 96 1.32 fvdl * Inode state information is contained on per cylinder group lists 97 1.32 fvdl * which are described by the following structure. 98 1.32 fvdl */ 99 1.54 joerg extern struct inostatlist { 100 1.57 christos size_t il_numalloced; /* number of inodes allocated in this cg */ 101 1.32 fvdl struct inostat *il_stat;/* inostat info for this cylinder group */ 102 1.32 fvdl } *inostathead; 103 1.32 fvdl 104 1.32 fvdl /* 105 1.1 cgd * buffer cache structure. 106 1.1 cgd */ 107 1.1 cgd struct bufarea { 108 1.14 lukem struct bufarea *b_next; /* free list queue */ 109 1.14 lukem struct bufarea *b_prev; /* free list queue */ 110 1.30 fvdl daddr_t b_bno; 111 1.14 lukem int b_size; 112 1.14 lukem int b_errs; 113 1.14 lukem int b_flags; 114 1.1 cgd union { 115 1.14 lukem char *b_buf; /* buffer space */ 116 1.32 fvdl int32_t *b_indir1; /* indirect block */ 117 1.32 fvdl int64_t *b_indir2; /* indirect block */ 118 1.14 lukem struct fs *b_fs; /* super block */ 119 1.14 lukem struct cg *b_cg; /* cylinder group */ 120 1.32 fvdl struct ufs1_dinode *b_dinode1; /* UFS1 inode block */ 121 1.32 fvdl struct ufs2_dinode *b_dinode2; /* UFS2 inode block */ 122 1.50 rin #ifndef NO_APPLE_UFS 123 1.29 dbj struct appleufslabel *b_appleufs; /* Apple UFS volume label */ 124 1.50 rin #endif 125 1.1 cgd } b_un; 126 1.14 lukem char b_dirty; 127 1.1 cgd }; 128 1.1 cgd 129 1.32 fvdl #define IBLK(bp, i) \ 130 1.32 fvdl (is_ufs2 ? (bp)->b_un.b_indir2[i] : (bp)->b_un.b_indir1[i]) 131 1.32 fvdl 132 1.45 skrll #define IBLK_SET(bp, i, val) do { \ 133 1.45 skrll if (is_ufs2) \ 134 1.45 skrll (bp)->b_un.b_indir2[i] = (val); \ 135 1.45 skrll else \ 136 1.45 skrll (bp)->b_un.b_indir1[i] = (val); \ 137 1.45 skrll } while (0) 138 1.32 fvdl 139 1.1 cgd #define B_INUSE 1 140 1.1 cgd 141 1.1 cgd #define MINBUFS 5 /* minimum number of buffers required */ 142 1.54 joerg extern struct bufarea bufhead; /* head of list of other blks in filesys */ 143 1.54 joerg extern struct bufarea sblk; /* file system superblock */ 144 1.54 joerg extern struct bufarea asblk; /* file system superblock */ 145 1.54 joerg extern struct bufarea cgblk; /* cylinder group blocks */ 146 1.50 rin #ifndef NO_APPLE_UFS 147 1.54 joerg extern struct bufarea appleufsblk; /* Apple UFS volume label */ 148 1.50 rin #endif 149 1.54 joerg extern struct bufarea *pdirbp; /* current directory contents */ 150 1.54 joerg extern struct bufarea *pbp; /* current inode block */ 151 1.1 cgd 152 1.1 cgd #define dirty(bp) (bp)->b_dirty = 1 153 1.1 cgd #define initbarea(bp) \ 154 1.1 cgd (bp)->b_dirty = 0; \ 155 1.30 fvdl (bp)->b_bno = (daddr_t)-1; \ 156 1.1 cgd (bp)->b_flags = 0; 157 1.1 cgd 158 1.54 joerg extern struct fs *sblock; 159 1.54 joerg extern struct fs *altsblock; 160 1.54 joerg extern struct cg *cgrp; 161 1.54 joerg extern struct fs *sblocksave; 162 1.17 bouyer #define sbdirty() \ 163 1.17 bouyer do { \ 164 1.32 fvdl memmove(sblk.b_un.b_fs, sblock, SBLOCKSIZE); \ 165 1.37 dbj sb_oldfscompat_write(sblk.b_un.b_fs, sblocksave); \ 166 1.17 bouyer if (needswap) \ 167 1.33 fvdl ffs_sb_swap(sblk.b_un.b_fs, sblk.b_un.b_fs); \ 168 1.56 chs cvt_magic(sblk.b_un.b_fs); \ 169 1.17 bouyer sblk.b_dirty = 1; \ 170 1.17 bouyer } while (0) 171 1.17 bouyer #define cgdirty() do {copyback_cg(&cgblk); cgblk.b_dirty = 1;} while (0) 172 1.1 cgd 173 1.29 dbj #define appleufsdirty() \ 174 1.29 dbj do { \ 175 1.29 dbj appleufsblk.b_un.b_appleufs->ul_checksum = 0; \ 176 1.29 dbj appleufsblk.b_un.b_appleufs->ul_checksum = \ 177 1.29 dbj ffs_appleufs_cksum(appleufsblk.b_un.b_appleufs); \ 178 1.29 dbj appleufsblk.b_dirty = 1; \ 179 1.29 dbj } while (0) 180 1.29 dbj 181 1.1 cgd enum fixstate {DONTKNOW, NOFIX, FIX, IGNORE}; 182 1.1 cgd 183 1.1 cgd struct inodesc { 184 1.1 cgd enum fixstate id_fix; /* policy on fixing errors */ 185 1.12 christos int (*id_func) /* function to be applied to blocks of inode */ 186 1.42 xtraeme (struct inodesc *); 187 1.1 cgd ino_t id_number; /* inode number described */ 188 1.1 cgd ino_t id_parent; /* for DATA nodes, their parent */ 189 1.30 fvdl daddr_t id_blkno; /* current block number being examined */ 190 1.1 cgd int id_numfrags; /* number of frags contained in block */ 191 1.16 lukem int64_t id_filesize; /* for DATA nodes, the size of the directory */ 192 1.1 cgd int id_loc; /* for DATA nodes, current location in dir */ 193 1.32 fvdl int64_t id_entryno; /* for DATA nodes, current entry number */ 194 1.1 cgd struct direct *id_dirp; /* for DATA nodes, ptr to current entry */ 195 1.43 christos const char *id_name; /* for DATA nodes, name to find or enter */ 196 1.1 cgd char id_type; /* type of descriptor, DATA or ADDR */ 197 1.59 andvar uid_t id_uid; /* ownership of inode described */ 198 1.49 bouyer gid_t id_gid; 199 1.1 cgd }; 200 1.1 cgd /* file types */ 201 1.1 cgd #define DATA 1 202 1.38 hannken #define SNAP 2 203 1.38 hannken #define ADDR 3 204 1.1 cgd 205 1.1 cgd /* 206 1.1 cgd * Linked list of duplicate blocks. 207 1.58 riastrad * 208 1.1 cgd * The list is composed of two parts. The first part of the 209 1.1 cgd * list (from duplist through the node pointed to by muldup) 210 1.58 riastrad * contains a single copy of each duplicate block that has been 211 1.1 cgd * found. The second part of the list (from muldup to the end) 212 1.1 cgd * contains duplicate blocks that have been found more than once. 213 1.1 cgd * To check if a block has been found as a duplicate it is only 214 1.58 riastrad * necessary to search from duplist through muldup. To find the 215 1.1 cgd * total number of times that a block has been found as a duplicate 216 1.31 wiz * the entire list must be searched for occurrences of the block 217 1.1 cgd * in question. The following diagram shows a sample list where 218 1.1 cgd * w (found twice), x (found once), y (found three times), and z 219 1.1 cgd * (found once) are duplicate block numbers: 220 1.1 cgd * 221 1.1 cgd * w -> y -> x -> z -> y -> w -> y 222 1.1 cgd * ^ ^ 223 1.1 cgd * | | 224 1.1 cgd * duplist muldup 225 1.1 cgd */ 226 1.1 cgd struct dups { 227 1.1 cgd struct dups *next; 228 1.30 fvdl daddr_t dup; 229 1.1 cgd }; 230 1.54 joerg extern struct dups *duplist; /* head of dup list */ 231 1.54 joerg extern struct dups *muldup; /* end of unique duplicate dup block numbers */ 232 1.1 cgd 233 1.1 cgd /* 234 1.1 cgd * Linked list of inodes with zero link counts. 235 1.1 cgd */ 236 1.1 cgd struct zlncnt { 237 1.1 cgd struct zlncnt *next; 238 1.1 cgd ino_t zlncnt; 239 1.1 cgd }; 240 1.54 joerg extern struct zlncnt *zlnhead; /* head of zero link count list */ 241 1.1 cgd 242 1.1 cgd /* 243 1.1 cgd * Inode cache data structures. 244 1.1 cgd */ 245 1.54 joerg extern struct inoinfo { 246 1.1 cgd struct inoinfo *i_nexthash; /* next entry in hash chain */ 247 1.39 mycroft struct inoinfo *i_child, *i_sibling; 248 1.1 cgd ino_t i_number; /* inode number of this entry */ 249 1.1 cgd ino_t i_parent; /* inode number of parent */ 250 1.1 cgd ino_t i_dotdot; /* inode number of `..' */ 251 1.1 cgd size_t i_isize; /* size of inode */ 252 1.1 cgd u_int i_numblks; /* size of block array in bytes */ 253 1.32 fvdl int64_t i_blks[1]; /* actually longer */ 254 1.1 cgd } **inphead, **inpsort; 255 1.54 joerg extern long numdirs, dirhash, listmax, inplast; 256 1.1 cgd 257 1.49 bouyer /* 258 1.49 bouyer * quota usage structures 259 1.49 bouyer */ 260 1.49 bouyer struct uquot { 261 1.49 bouyer uint64_t uq_b; /* block usage */ 262 1.49 bouyer uint64_t uq_i; /* inode usage */ 263 1.49 bouyer SLIST_ENTRY(uquot) uq_entries; 264 1.49 bouyer uint32_t uq_uid; /* uid/gid of the owner */ 265 1.49 bouyer }; 266 1.49 bouyer SLIST_HEAD(uquot_hash, uquot); 267 1.54 joerg extern struct uquot_hash *uquot_user_hash; 268 1.54 joerg extern struct uquot_hash *uquot_group_hash; 269 1.54 joerg extern uint8_t q2h_hash_shift; 270 1.54 joerg extern uint16_t q2h_hash_mask; 271 1.54 joerg 272 1.54 joerg extern long dev_bsize; /* computed value of DEV_BSIZE */ 273 1.54 joerg extern long secsize; /* actual disk sector size */ 274 1.54 joerg extern char nflag; /* assume a no response */ 275 1.54 joerg extern char yflag; /* assume a yes response */ 276 1.54 joerg extern int Uflag; /* resolve user names */ 277 1.54 joerg extern int bflag; /* location of alternate super block */ 278 1.54 joerg extern int debug; /* output debugging info */ 279 1.54 joerg extern int zflag; /* zero unused directory space */ 280 1.54 joerg extern int cvtlevel; /* convert to newer file system format */ 281 1.54 joerg extern int doinglevel1; /* converting to new cylinder group format */ 282 1.54 joerg extern int doinglevel2; /* converting to new inode format */ 283 1.56 chs extern int doing2ea; /* converting UFS2 to UFS2ea */ 284 1.56 chs extern int doing2noea; /* converting UFS2ea to UFS2 */ 285 1.54 joerg extern int newinofmt; /* filesystem has new inode format */ 286 1.54 joerg extern char usedsoftdep; /* just fix soft dependency inconsistencies */ 287 1.54 joerg extern int preen; /* just fix normal inconsistencies */ 288 1.54 joerg extern int quiet; /* Don't print anything if clean */ 289 1.54 joerg extern int forceimage; /* file system is an image file */ 290 1.54 joerg extern int is_ufs2; /* we're dealing with an UFS2 filesystem */ 291 1.56 chs extern int is_ufs2ea; /* is the variant that supports exattrs */ 292 1.54 joerg extern int markclean; /* mark file system clean when done */ 293 1.54 joerg extern char havesb; /* superblock has been read */ 294 1.54 joerg extern char skipclean; /* skip clean file systems if preening */ 295 1.54 joerg extern int fsmodified; /* 1 => write done to file system */ 296 1.54 joerg extern int fsreadfd; /* file descriptor for reading file system */ 297 1.54 joerg extern int fswritefd; /* file descriptor for writing file system */ 298 1.54 joerg extern int rerun; /* rerun fsck. Only used in non-preen mode */ 299 1.54 joerg extern char resolved; /* cleared if unresolved changes => not clean */ 300 1.50 rin 301 1.50 rin #ifndef NO_FFS_EI 302 1.54 joerg extern int endian; /* endian coversion */ 303 1.54 joerg extern int doswap; /* convert byte order */ 304 1.54 joerg extern int needswap; /* need to convert byte order in memory */ 305 1.54 joerg extern int do_blkswap; /* need to do block addr byteswap */ 306 1.54 joerg extern int do_dirswap; /* need to do dir entry byteswap */ 307 1.50 rin #else 308 1.50 rin /* Disable Endian-Independent FFS support for install media */ 309 1.50 rin #define endian (0) 310 1.50 rin #define doswap (0) 311 1.50 rin #define needswap (0) 312 1.50 rin #define do_blkswap (0) 313 1.50 rin #define do_dirswap (0) 314 1.52 rin #define ffs_cg_swap(a, b, c) __nothing 315 1.52 rin #define ffs_csum_swap(a, b, c) __nothing 316 1.52 rin #define ffs_sb_swap(a, b) __nothing 317 1.52 rin #define swap_dinode1(a, b) __nothing 318 1.52 rin #define swap_dinode2(a, b) __nothing 319 1.50 rin #endif 320 1.50 rin 321 1.50 rin #ifndef NO_APPLE_UFS 322 1.54 joerg extern int isappleufs; /* filesystem is Apple UFS */ 323 1.50 rin #else 324 1.50 rin /* Disable Apple UFS support for install media */ 325 1.50 rin #define isappleufs (0) 326 1.50 rin #endif 327 1.1 cgd 328 1.54 joerg extern daddr_t maxfsblock; /* number of blocks in the file system */ 329 1.54 joerg extern char *blockmap; /* ptr to primary blk allocation map */ 330 1.54 joerg extern ino_t maxino; /* number of inodes in file system */ 331 1.1 cgd 332 1.54 joerg extern int dirblksiz; 333 1.29 dbj 334 1.21 scw extern ino_t lfdir; /* lost & found directory inode number */ 335 1.43 christos extern const char *lfname; /* lost & found directory name */ 336 1.24 christos extern int lfmode; /* lost & found directory creation mode */ 337 1.1 cgd 338 1.54 joerg extern daddr_t n_blks; /* number of blocks in use */ 339 1.54 joerg extern ino_t n_files; /* number of files in use */ 340 1.28 lukem 341 1.54 joerg extern long countdirs; 342 1.32 fvdl 343 1.54 joerg extern int got_siginfo; /* received a SIGINFO */ 344 1.1 cgd 345 1.32 fvdl #define clearinode(dp) \ 346 1.32 fvdl do { \ 347 1.32 fvdl if (is_ufs2) \ 348 1.34 fvdl (dp)->dp2 = ufs2_zino; \ 349 1.34 fvdl else \ 350 1.32 fvdl (dp)->dp1 = ufs1_zino; \ 351 1.32 fvdl } while (0) 352 1.32 fvdl 353 1.54 joerg extern struct ufs1_dinode ufs1_zino; 354 1.54 joerg extern struct ufs2_dinode ufs2_zino; 355 1.1 cgd 356 1.1 cgd #define setbmap(blkno) setbit(blockmap, blkno) 357 1.1 cgd #define testbmap(blkno) isset(blockmap, blkno) 358 1.1 cgd #define clrbmap(blkno) clrbit(blockmap, blkno) 359 1.1 cgd 360 1.1 cgd #define STOP 0x01 361 1.1 cgd #define SKIP 0x02 362 1.1 cgd #define KEEPON 0x04 363 1.1 cgd #define ALTERED 0x08 364 1.1 cgd #define FOUND 0x10 365 1.1 cgd 366 1.50 rin #ifndef NO_FFS_EI 367 1.17 bouyer /* some inline functs to help the byte-swapping mess */ 368 1.44 perry static inline u_int16_t iswap16 (u_int16_t); 369 1.44 perry static inline u_int32_t iswap32 (u_int32_t); 370 1.44 perry static inline u_int64_t iswap64 (u_int64_t); 371 1.17 bouyer 372 1.48 drochner static inline u_int16_t 373 1.48 drochner iswap16(u_int16_t x) 374 1.17 bouyer { 375 1.17 bouyer if (needswap) 376 1.17 bouyer return bswap16(x); 377 1.17 bouyer else return x; 378 1.17 bouyer } 379 1.17 bouyer 380 1.48 drochner static inline u_int32_t 381 1.48 drochner iswap32(u_int32_t x) 382 1.17 bouyer { 383 1.17 bouyer if (needswap) 384 1.17 bouyer return bswap32(x); 385 1.17 bouyer else return x; 386 1.17 bouyer } 387 1.17 bouyer 388 1.48 drochner static inline u_int64_t 389 1.48 drochner iswap64(u_int64_t x) 390 1.17 bouyer { 391 1.17 bouyer if (needswap) 392 1.17 bouyer return bswap64(x); 393 1.17 bouyer else return x; 394 1.17 bouyer } 395 1.50 rin #else 396 1.50 rin #define iswap16(x) (x) 397 1.50 rin #define iswap32(x) (x) 398 1.50 rin #define iswap64(x) (x) 399 1.50 rin #endif /* NO_FFS_EI */ 400 1.55 jdolecek 401 1.55 jdolecek #ifdef NO_IOBUF_ALIGNED 402 1.55 jdolecek #define aligned_alloc(align, size) malloc((size)) 403 1.55 jdolecek #endif 404