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