1/*
2	Copyright 1999-2001, Be Incorporated.   All Rights Reserved.
3	This file may be used under the terms of the Be Sample Code License.
4*/
5#ifndef _DOSFS_H_
6#define _DOSFS_H_
7
8
9#include <KernelExport.h>
10#include <fs_interface.h>
11#include <lock.h>
12
13
14//#define DEBUG 1
15
16
17#define	LOCK(l)		recursive_lock_lock(&l);
18#define	UNLOCK(l)	recursive_lock_unlock(&l);
19
20
21/* Unfortunately, ino_t's are defined as signed. This causes problems with
22 * programs (notably cp) that use the modulo of a ino_t as a
23 * hash function to index an array. This means the high bit of every ino_t
24 * is off-limits. Luckily, FAT32 is actually FAT28, so dosfs can make do with
25 * only 63 bits.
26 */
27#define ARTIFICIAL_VNID_BITS	(0x6LL << 60)
28#define DIR_CLUSTER_VNID_BITS	(0x4LL << 60)
29#define DIR_INDEX_VNID_BITS		0
30#define INVALID_VNID_BITS_MASK	(0x9LL << 60)
31
32#define IS_DIR_CLUSTER_VNID(vnid) \
33	(((vnid) & ARTIFICIAL_VNID_BITS) == DIR_CLUSTER_VNID_BITS)
34
35#define IS_DIR_INDEX_VNID(vnid) \
36	(((vnid) & ARTIFICIAL_VNID_BITS) == DIR_INDEX_VNID_BITS)
37
38#define IS_ARTIFICIAL_VNID(vnid) \
39	(((vnid) & ARTIFICIAL_VNID_BITS) == ARTIFICIAL_VNID_BITS)
40
41#define IS_INVALID_VNID(vnid) \
42	((!IS_DIR_CLUSTER_VNID((vnid)) && \
43			!IS_DIR_INDEX_VNID((vnid)) && \
44			!IS_ARTIFICIAL_VNID((vnid))) || \
45		((vnid) & INVALID_VNID_BITS_MASK))
46
47#define GENERATE_DIR_INDEX_VNID(dircluster, index) \
48	(DIR_INDEX_VNID_BITS | ((ino_t)(dircluster) << 32) | (index))
49
50#define GENERATE_DIR_CLUSTER_VNID(dircluster, filecluster) \
51	(DIR_CLUSTER_VNID_BITS | ((ino_t)(dircluster) << 32) | (filecluster))
52
53#define CLUSTER_OF_DIR_CLUSTER_VNID(vnid) \
54	((uint32)((vnid) & 0xffffffff))
55
56#define INDEX_OF_DIR_INDEX_VNID(vnid) \
57	((uint32)((vnid) & 0xffffffff))
58
59#define DIR_OF_VNID(vnid) \
60	((uint32)(((vnid) >> 32) & ~0xf0000000))
61
62#define VNODE_PARENT_DIR_CLUSTER(vnode) \
63	CLUSTER_OF_DIR_CLUSTER_VNID((vnode)->dir_vnid)
64
65
66typedef struct vnode {
67	ino_t		vnid;			// self id
68	ino_t		dir_vnid;		// parent vnode id (directory containing entry)
69	void		*cache;
70	void		*file_map;
71
72	uint32		disk_image;		// 0 = no, 1 = BEOS, 2 = IMAGE.BE
73
74	/* iteration is incremented each time the fat chain changes. it's used by
75	 * the file read/write code to determine if it needs to retraverse the
76	 * fat chain
77	 */
78	uint32		iteration;
79
80	/* any changes to this block of information should immediately be reflected
81	 * on the disk (or at least in the cache) so that get_next_dirent continues
82	 * to function properly
83	 */
84	uint32		sindex, eindex;	// starting and ending index of directory entry
85	uint32		cluster;		// starting cluster of the data
86	uint32		mode;			// dos-style attributes
87	off_t		st_size;		// in bytes
88	time_t		st_time;
89	time_t		st_crtim;
90
91	uint32		end_cluster;	// last cluster of the data
92
93	const char *mime;			// mime type (null if none)
94
95	bool		dirty;			// track if vnode had been written to
96
97#if TRACK_FILENAME
98	char		*filename;
99#endif
100} vnode;
101
102// mode bits
103#define FAT_READ_ONLY	1
104#define FAT_HIDDEN		2
105#define FAT_SYSTEM		4
106#define FAT_VOLUME		8
107#define FAT_SUBDIR		16
108#define FAT_ARCHIVE		32
109
110
111struct vcache_entry;
112
113typedef struct _nspace {
114	fs_volume		*volume;		// fs_volume passed in to fs_mount
115	dev_t			id;
116	int				fd;				// File descriptor
117	char			device[256];
118	uint32			flags;			// see <fcntl.be.h> for modes
119	void			*fBlockCache;
120
121	// info from bpb
122	uint32	bytes_per_sector;
123	uint32	sectors_per_cluster;
124	uint32	reserved_sectors;
125	uint32	fat_count;
126	uint32	root_entries_count;
127	uint32	total_sectors;
128	uint32	sectors_per_fat;
129	uint8	media_descriptor;
130	uint16	fsinfo_sector;
131
132	uint32	total_clusters;			// data clusters, that is
133	uint32	free_clusters;
134	uint8	fat_bits;
135	bool	fat_mirrored;			// true if fat mirroring on
136	uint8	active_fat;
137
138	uint32	root_start;				// for fat12 + fat16 only
139	uint32	root_sectors;			// for fat12 + fat16 only
140	vnode	root_vnode;				// root directory
141	int32	vol_entry;				// index in root directory
142	char	vol_label[12];			// lfn's need not apply
143
144	uint32	data_start;
145	uint32	last_allocated;			// last allocated cluster
146
147	ino_t	beos_vnid;				// vnid of \BEOS directory
148	bool	respect_disk_image;
149
150	int		fs_flags;				// flags for this mount
151
152	recursive_lock	vlock;					// volume lock
153
154	// vcache state
155	struct {
156		rw_lock	lock;
157		ino_t	cur_vnid;
158		uint32	cache_size;
159		struct vcache_entry **by_vnid, **by_loc;
160	} vcache;
161
162	struct {
163		uint32	entries;
164		uint32	allocated;
165		ino_t	*vnid_list;
166	} dlist;
167} nspace;
168
169#define FS_FLAGS_OP_SYNC		0x1
170#define FS_FLAGS_LOCK_DOOR		0x2
171
172#define LOCK_VOL(vol) \
173	if (vol == NULL) { dprintf("null vol\n"); return EINVAL; } else LOCK((vol)->vlock)
174
175#define UNLOCK_VOL(vol) \
176	UNLOCK((vol)->vlock)
177
178#define TOUCH(x) ((void)(x))
179
180extern fs_vnode_ops gFATVnodeOps;
181extern fs_volume_ops gFATVolumeOps;
182
183/* debug levels */
184extern int debug_attr, debug_dir, debug_dlist, debug_dosfs, debug_encodings,
185		debug_fat, debug_file, debug_iter, debug_vcache;
186
187status_t _dosfs_sync(nspace *vol);
188
189#endif
190