1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1999,2000 by Sun Microsystems, Inc. 24 * All rights reserved. 25 * Copyright 2024 MNX Cloud, Inc. 26 */ 27 28 #ifndef _FSCK_PCFS_H 29 #define _FSCK_PCFS_H 30 31 /* 32 * Structures used by the pcfs file system checker. 33 */ 34 35 #ifdef __cplusplus 36 extern "C" { 37 #endif 38 39 #include <sys/types.h> 40 41 /* 42 * The root directory of FAT12/16 file systems doesn't sit in 43 * a cluster. 44 */ 45 #define FAKE_ROOTDIR_CLUST -1 46 47 /* 48 * The first available cluster number for a FAT fs is always the same, 2. 49 */ 50 #define FIRST_CLUSTER 2 51 52 #define RETURN_ON_OPEN_FAILURE 0 53 #define EXIT_ON_OPEN_FAILURE 1 54 55 #define NO_FAT_IN_SUMMARY 0 56 #define INCLUDE_FAT_IN_SUMMARY 1 57 58 #define RDCLUST_DONT_CACHE 0 59 #define RDCLUST_DO_CACHE 1 60 61 /* 62 * Return values for sanityCheckSize() 63 */ 64 #define SIZE_MATCHED 0 65 #define TRUNCATED 1 66 67 #define RDCLUST_MAX_RETRY 3 68 #define RDCLUST_GOOD 0 69 #define RDCLUST_FAIL -1 70 #define RDCLUST_MEMERR -2 71 #define RDCLUST_BADINPUT -3 72 73 typedef union clustDataTypes { 74 struct pcdir *dirp; 75 uchar_t *bytes; 76 } ClusterContents; 77 78 struct cached { 79 int32_t clusterNum; 80 ClusterContents clusterData; 81 short modified; 82 struct cached *next; 83 }; 84 85 typedef struct cached CachedCluster; 86 87 struct nameinfo { 88 char *fullName; 89 int references; 90 }; 91 92 /* 93 * This structure is shared between all structures belonging to 94 * a single file. The refcnt is a 24 bit integer, that should be 95 * sufficient for 4GB files, even when someone uses 256 byte clusters 96 * (4K is the typical cluster size, 512 bytes is probably the minimum) 97 * The inefficiency of using a bit field is compensated by the memory 98 * savings and prevented paging on large filesystems. 99 */ 100 struct clinfo { 101 struct pcdir *dirent; 102 union { 103 struct clinfo *_nextfree; 104 struct pcdir *_longent; 105 } _unionelem; 106 int32_t longEntStartClust; 107 int refcnt:24; 108 uint_t flags:8; 109 uchar_t *saved; 110 struct nameinfo *path; 111 }; 112 113 /* 114 * #define dirent conflicts with other dirent uses, so we used the 115 * second element instead of the first one one as union for the free 116 * list 117 */ 118 #define longent _unionelem._longent 119 #define nextfree _unionelem._nextfree 120 121 typedef struct clinfo ClusterInfo; 122 123 /* 124 * Return values for allocInUse 125 */ 126 #define CLINFO_PREVIOUSLY_ALLOCED 1 127 #define CLINFO_NEWLY_ALLOCED 0 128 129 #define CLINFO_BAD 0x1 130 #define CLINFO_ORPHAN 0x2 131 #define CLINFO_HIDDEN 0x4 132 133 /* 134 * Traversal operations for wandering the file system metadata 135 */ 136 #define PCFS_NO_SUBDIRS 0 137 #define PCFS_VISIT_SUBDIRS 1 138 139 #define PCFS_TRAVERSE_ALL 1 /* visit all nodes */ 140 #define PCFS_FIND_ATTR 2 /* search for matching attribute */ 141 #define PCFS_FIND_STATUS 3 /* search for same status */ 142 #define PCFS_FIND_CHKS 4 /* find FILENNNN.CHK files */ 143 144 /* 145 * Booleans for markInUse, whether or not file is marked hidden. 146 */ 147 #define VISIBLE 0 148 #define HIDDEN 1 149 150 /* 151 * Indices for various parts of the FILEnnnn.CHK name 152 */ 153 #define CHKNAME_F 0 154 #define CHKNAME_I 1 155 #define CHKNAME_L 2 156 #define CHKNAME_E 3 157 #define CHKNAME_THOUSANDS 4 158 #define CHKNAME_HUNDREDS 5 159 #define CHKNAME_TENS 6 160 #define CHKNAME_ONES 7 161 #define CHKNAME_C 0 162 #define CHKNAME_H 1 163 #define CHKNAME_K 2 164 165 /* 166 * Largest value that will fit into our lost+found naming scheme of 167 * FILEnnnn.CHK. 168 */ 169 #define MAXCHKVAL 9999 170 171 extern size_t bpsec; 172 extern bool AlwaysYes; /* assume a yes answer to all questions */ 173 extern bool AlwaysNo; /* assume a no answer to all questions */ 174 175 /* 176 * Function prototypes 177 */ 178 extern struct pcdir *addRootDirEnt(int fd, struct pcdir *copyme); 179 extern struct pcdir *newDirEnt(struct pcdir *copyme); 180 extern int32_t extractStartCluster(struct pcdir *dp); 181 extern int32_t findImpactedCluster(struct pcdir *modified); 182 extern int32_t readFATEntry(int32_t currentCluster); 183 extern uint32_t extractSize(struct pcdir *dp); 184 extern int32_t nextInChain(int32_t currentCluster); 185 extern char *nextAvailableCHKName(int *chosen); 186 extern void truncChainWithBadCluster(int fd, struct pcdir *dp, 187 int32_t startCluster); 188 extern void mountSanityCheckFails(void); 189 extern void markClusterModified(int32_t clusterNum); 190 extern void scanAndFixMetadata(int fd); 191 extern void updateDirEnt_Start(struct pcdir *dp, int32_t newStart); 192 extern void addEntryToCHKList(int chkNumber); 193 extern void createCHKNameList(int fd); 194 extern void updateDirEnt_Name(struct pcdir *dp, char *newName); 195 extern void updateDirEnt_Size(struct pcdir *dp, uint32_t newSize); 196 extern void getRootDirectory(int fd); 197 extern void writeClusterMods(int fd); 198 extern void writeRootDirMods(int fd); 199 extern void traverseFromRoot(int fd, int depth, int descend, int operation, 200 char matchRequired, struct pcdir **found, int32_t *lastDirCluster, 201 struct pcdir **dirEnd, char *recordPath, int *pathLen); 202 extern void findBadClusters(int fd); 203 extern void markFreeInFAT(int32_t clusterNum); 204 extern void markLastInFAT(int32_t clusterNum); 205 extern void writeFATEntry(int32_t currentCluster, int32_t value); 206 extern void markBadInFAT(int32_t clusterNum); 207 extern void printSummary(FILE *outDest); 208 extern void squirrelPath(struct nameinfo *pathInfo, int32_t clusterNum); 209 extern void usingCHKName(void *nameCookie); 210 extern void writeFATMods(int fd); 211 extern void traverseDir(int fd, int32_t startAt, int depth, int descend, 212 int operation, char matchRequired, struct pcdir **found, 213 int32_t *lastDirCluster, struct pcdir **dirEnd, char *recordPath, 214 int *pathLen); 215 extern void splitChain(int fd, struct pcdir *dp, int32_t problemCluster, 216 struct pcdir **newdp, int32_t *orphanStart); 217 extern void preenBail(char *outString); 218 extern void readBPB(int fd); 219 extern void getFAT(int fd); 220 extern int checkFAT32CleanBit(int fd); 221 extern int reservedInFAT(int32_t clusterNum); 222 extern int isMarkedBad(int32_t clusterNum); 223 extern int readCluster(int fd, int32_t clusterNum, uchar_t **data, 224 int32_t *datasize, int shouldCache); 225 extern int freeInFAT(int32_t clusterNum); 226 extern int lastInFAT(int32_t clusterNum); 227 extern int markInUse(int fd, int32_t clusterNum, struct pcdir *referencer, 228 struct pcdir *longRef, int32_t longStartCluster, int isHidden, 229 ClusterInfo **template); 230 extern int badInFAT(int32_t clusterNum); 231 232 #ifdef __cplusplus 233 } 234 #endif 235 236 #endif /* _FSCK_PCFS_H */ 237