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