xref: /haiku/src/add-ons/kernel/file_systems/fat/dosfs.h (revision 342a1b221b5bb385410f758df2c625b70cafdd03)
1 /*
2  * Copyright 1999-2001, Be Incorporated.   All Rights Reserved.
3  * Copyright 2024, Haiku, Inc. All rights reserved.
4  * This file may be used under the terms of the Be Sample Code License.
5  */
6 #ifndef DOSFS_H_
7 #define DOSFS_H_
8 
9 
10 #ifdef FS_SHELL
11 #include "fssh_defines.h"
12 #else
13 #include <SupportDefs.h>
14 #endif
15 
16 
17 #define CACHED_BLOCK_SIZE 512
18 #define BUF_CACHE_SIZE 20
19 
20 // notify every second if the file size has changed
21 #define INODE_NOTIFICATION_INTERVAL 1000000LL
22 
23 // the value given to the VFS as the preferred length of a read and write
24 #define FAT_IO_SIZE 65536
25 
26 #define read16(buffer, off) B_LENDIAN_TO_HOST_INT16(*(uint16*)&buffer[off])
27 
28 #define read32(buffer, off) B_LENDIAN_TO_HOST_INT32(*(uint32*)&buffer[off])
29 
30 // true only for the root directory in a FAT12/FAT16 volume
31 #define IS_FIXED_ROOT(fatNode) ((fatNode)->de_StartCluster == 0)
32 
33 #define SECTORS_PER_CLUSTER(fat_volume) \
34 	((fat_volume->pm_bpcluster) / (fat_volume->pm_BlkPerSec * DEV_BSIZE))
35 #define BLOCKS_PER_CLUSTER(fatVolume) (fatVolume->pm_bpcluster / DEV_BSIZE)
36 
37 #define vIS_DATA_CLUSTER(fatVolume, cluster) \
38 	(((cluster) >= 2) && ((uint32)(cluster) <= fatVolume->pm_maxcluster))
39 #define IS_DATA_CLUSTER(cluster) vIS_DATA_CLUSTER(fatVolume, cluster)
40 
41 #define MOUNTED_READ_ONLY(fatVolume) \
42 	((fatVolume->pm_flags & MSDOSFSMNT_RONLY) != 0 \
43 		|| (fatVolume->pm_mountp->mnt_flag & MNT_RDONLY) != 0)
44 // these 2 flags are redundant (a side effect of simulating pieces of the FreeBSD VFS);
45 // both are checked to err on the side of caution
46 
47 /* Unfortunately, ino_t's are defined as signed. This causes problems with
48  * programs (notably cp) that use the modulo of a ino_t as a
49  * hash function to index an array. This means the high bit of every ino_t
50  * is off-limits. Luckily, FAT32 is actually FAT28, so dosfs can make do with
51  * only 63 bits.
52  */
53 #define INVALID_VNID_BITS_MASK (0x9LL << 60)
54 // the lower limit of the range of artificial inode numbers (the numbers used
55 // when the location-based inode is already taken by a renamed or deleted file)
56 #define ARTIFICIAL_VNID_BITS (0x6LL << 60)
57 #define DIR_INDEX_VNID_BITS 0
58 
59 #define IS_DIR_INDEX_VNID(vnid) (((vnid) & ARTIFICIAL_VNID_BITS) == DIR_INDEX_VNID_BITS)
60 #define IS_ARTIFICIAL_VNID(vnid) (((vnid) & ARTIFICIAL_VNID_BITS) == ARTIFICIAL_VNID_BITS)
61 #define IS_INVALID_VNID(vnid) \
62 	((!IS_DIR_INDEX_VNID(vnid) && !IS_ARTIFICIAL_VNID(vnid)) || ((vnid) & INVALID_VNID_BITS_MASK))
63 
64 // FreeBSD macros, modified to be compatible with Haiku's struct dirent.
65 // GENERIC_DIRSIZ returns an appropriate value for dirent::d_reclen.
66 #define _GENERIC_DIRLEN(namlen) ((offsetof(struct dirent, d_name) + (namlen) + 1 + 7) & ~7)
67 #define GENERIC_DIRSIZ(dp) _GENERIC_DIRLEN(strlen((dp)->d_name))
68 
69 struct mount;
70 struct vnode;
71 struct fs_vnode_ops;
72 struct fs_volume_ops;
73 
74 
75 enum FatType { fat12, fat16, fat32 };
76 
77 
78 extern const char* LABEL_ILLEGAL;
79 extern struct fs_vnode_ops gFATVnodeOps;
80 extern struct fs_volume_ops gFATVolumeOps;
81 
82 
83 #ifdef __cplusplus
84 extern "C"
85 {
86 #endif
87 status_t _dosfs_access(const struct mount* bsdVolume, const struct vnode* bsdNode,
88 	const int mode);
89 status_t assign_inode(struct mount* volume, ino_t* inode);
90 bool node_exists(struct mount* bsdVolume, uint64_t inode);
91 status_t discard_clusters(struct vnode* bsdNode, off_t newLength);
92 #ifdef __cplusplus
93 }
94 #endif
95 
96 
97 #endif // DOSFS_H_
98