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