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