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