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