2 * fat-handler - FAT12/16/32 filesystem handler
4 * Copyright © 2006 Marek Szyprowski
5 * Copyright © 2007-2015 The AROS Development Team
7 * This program is free software; you can redistribute it and/or modify it
8 * under the same terms as AROS itself.
16 #define DEBUG_DIRENTRY 0
21 #define DEBUG_NOTIFY 0
23 #define DEBUG_PACKETS 0
24 #define DEBUG_CACHESTATS 0
27 #include <devices/trackdisk.h>
29 #include "fat_struct.h"
33 /* filesystem structures */
35 #define ID_FAT_DISK 0x46415400UL
37 #define ID_FAT12_DISK 0x46415400UL
38 #define ID_FAT16_DISK 0x46415401UL
39 #define ID_FAT32_DISK 0x46415402UL
41 #define ACTION_VOLUME_ADD 16000
42 #define ACTION_VOLUME_REMOVE 16001
44 #define DEF_POOL_SIZE 65536
45 #define DEF_POOL_THRESHOLD DEF_POOL_SIZE
48 /* a handle on something, file or directory */
51 struct FSSuper
*sb
; /* filesystem data */
53 ULONG first_cluster
; /* first cluster of this file */
54 ULONG cur_cluster
; /* cluster that the current sector is within */
56 ULONG cluster_offset
; /* cluster number of this cluster within the current file */
58 ULONG first_sector
; /* first sector in the first cluster, for fat12/16 root dir */
59 ULONG cur_sector
; /* sector number our block is currently in */
61 ULONG sector_offset
; /* current sector as an offset in the current cluster
62 i.e. cur = sector(cur_cluster) + offset */
64 APTR block
; /* current block from the cache */
65 UBYTE
*data
; /* current data buffer (from cache) */
68 /* a handle on a directory */
73 ULONG cur_index
; /* last entry returned, for GetNextDirEntry */
76 /* single directory entry */
79 struct FSSuper
*sb
; /* filesystem data */
81 ULONG cluster
; /* cluster the containing directory starts at */
82 ULONG index
; /* index of this entry */
84 ULONG pos
; /* byte offset within directory that the entry came from */
87 struct FATDirEntry entry
;
88 struct FATLongDirEntry long_entry
;
92 #define FAT_ROOTDIR_MARK 0xFFFFFFFFlu
102 struct MsgPort
* fl_Task
;
105 ULONG magic
; /* we set this to ID_FAT_DISK so we can tell
106 our locks from those of other filesystems */
108 struct MinNode node
; /* node in the list of locks attached to the global lock */
109 struct GlobalLock
*gl
; /* pointer to the global lock for this file */
111 struct IOHandle ioh
; /* handle for reads and writes */
112 ULONG pos
; /* current seek position within the file */
114 BOOL do_notify
; /* if set, send notification on file close (ACTION_END) */
115 struct FSSuper
*sb
; /* pointer to sb, for unlocking when volume is removed */
122 ULONG dir_cluster
; /* first cluster of the directory we're in */
123 ULONG dir_entry
; /* this is our dir entry within dir_cluster */
125 LONG access
; /* access mode, shared or exclusive */
127 ULONG first_cluster
; /* first data cluster */
129 ULONG attr
; /* file attributes, from the dir entry */
130 ULONG size
; /* file size, from the dir entry */
132 UBYTE name
[FAT_MAX_LONG_FILENAME
]; /* copy of the name (bstr) */
134 UBYTE shortname
[FAT_MAX_SHORT_NAME
+ 2]; /* copy of the short name (bstr) */
137 struct MinList locks
; /* list of ExtFileLocks opened on this file */
140 /* a node in the list of notification requests */
145 struct GlobalLock
*gl
; /* pointer to global lock if this file is
146 locked. if it's not, this is NULL */
148 struct NotifyRequest
*nr
; /* the request that DOS passed us */
155 struct MinList locks
; /* global locks */
156 struct GlobalLock root_lock
;
157 struct MinList notifies
;
160 struct VolumeIdentity
162 UBYTE name
[FAT_MAX_SHORT_NAME
+ 2]; /* BCPL string */
163 struct DateStamp create_time
;
170 struct Globals
*glob
;
171 struct DosList
*doslist
;
173 struct VolumeInfo
*info
;
176 ULONG first_device_sector
;
179 ULONG sectorsize_bits
;
181 ULONG cluster_sectors
;
183 ULONG clustersize_bits
;
184 ULONG cluster_sectors_bits
;
186 ULONG first_fat_sector
;
187 ULONG first_data_sector
;
188 ULONG first_rootdir_sector
;
190 ULONG rootdir_sectors
;
193 ULONG clusters_count
;
206 ULONG fat_blocks_count
;
209 ULONG fat_cachesize_bits
;
210 ULONG fat_cache_block
;
211 UWORD fat_cache_no
; /* FAT number that cached FAT blocks belong to */
214 struct FATFSInfo
*fsinfo_buffer
;
216 ULONG rootdir_cluster
;
217 ULONG rootdir_sector
;
219 struct VolumeIdentity volume
;
222 ULONG (*func_get_fat_entry
)(struct FSSuper
*sb
, ULONG n
);
223 void (*func_set_fat_entry
)(struct FSSuper
*sb
, ULONG n
, ULONG val
);
230 struct ExecBase
*gl_SysBase
;
231 struct DosLibrary
*gl_DOSBase
;
232 struct Library
*gl_UtilityBase
;
233 struct Device
*gl_TimerBase
;
236 struct Task
*ourtask
;
237 struct MsgPort
*ourport
;
240 struct MsgPort
*notifyport
;
243 struct DosList
*devnode
;
244 struct FileSysStartupMsg
*fssm
;
246 struct DosPacket
*death_packet
;
250 struct IOExtTD
*diskioreq
;
251 struct IOExtTD
*diskchgreq
;
252 struct MsgPort
*diskport
;
253 ULONG diskchgsig_bit
;
254 struct timerequest
*timereq
;
255 struct MsgPort
*timerport
;
256 ULONG last_num
; /* last block number that was outside boundaries */
263 struct FSSuper
*sb
; /* current sb */
264 struct MinList sblist
; /* sbs with outstanding locks or notifies */
271 /* Character sets translation */
272 UBYTE from_unicode
[65536];
273 UWORD to_unicode
[256];
275 /* Disk change interrupt */
277 struct Interrupt Interrupt
;
278 struct ExecBase
*SysBase
;
284 #define DOSBase (glob->gl_DOSBase)
285 #define SysBase (glob->gl_SysBase)
286 #define UtilityBase (glob->gl_UtilityBase)
287 #define TimerBase (glob->gl_TimerBase)
291 /* new definitions as we refactor the code */
293 /* get the first sector of a cluster */
294 #define SECTOR_FROM_CLUSTER(sb,cl) \
295 ((ULONG) (((cl-2) << sb->cluster_sectors_bits) + sb->first_data_sector))
297 #define FIRST_FILE_CLUSTER(de) \
298 (AROS_LE2WORD((de)->e.entry.first_cluster_lo) | \
299 (((ULONG) AROS_LE2WORD((de)->e.entry.first_cluster_hi)) << 16))
301 #define RESET_HANDLE(ioh) \
304 (ioh)->cluster_offset = (ioh)->sector_offset = 0xffffffff; \
305 if ((ioh)->block != NULL) \
307 Cache_FreeBlock((ioh)->sb->cache, (ioh)->block); \
308 (ioh)->block = NULL; \
313 #define RESET_DIRHANDLE(dh) \
316 RESET_HANDLE(&((dh)->ioh)); \
317 (dh)->cur_index = 0xffffffff; \
321 #define GET_NEXT_CLUSTER(sb,cl) (sb->func_get_fat_entry(sb,cl))
322 #define SET_NEXT_CLUSTER(sb,cl,val) (sb->func_set_fat_entry(sb,cl,val))
324 #define CALC_SHORT_NAME_CHECKSUM(name,checksum) \
329 for (i = 0; i < 11; i++) \
331 ((checksum & 1) ? 0x80 : 0) + (checksum >> 1) + name[i]; \
335 #define LOCKFROMNODE(A) \
336 ((struct ExtFileLock *) \
337 (((BYTE *)(A)) - (IPTR)&((struct ExtFileLock *)NULL)->node))