1 /* 2 * Copyright 2011, Jérôme Duval, korli@users.berlios.de. 3 * Copyright 2008, Axel Dörfler, axeld@pinc-software.de. 4 * This file may be used under the terms of the MIT License. 5 */ 6 #ifndef INODE_H 7 #define INODE_H 8 9 10 #include <fs_cache.h> 11 #include <lock.h> 12 #include <string.h> 13 14 #include "DirectoryIterator.h" 15 #include "exfat.h" 16 #include "SplayTree.h" 17 #include "Volume.h" 18 19 20 //#define TRACE_EXFAT 21 #ifdef TRACE_EXFAT 22 # define TRACEI(x...) dprintf("\33[34mexfat:\33[0m " x) 23 #else 24 # define TRACEI(x...) ; 25 #endif 26 27 28 struct InodesTreeDefinition; 29 30 31 class Inode : EntryVisitor { 32 public: 33 Inode(Volume* volume, cluster_t cluster, 34 uint32 offset); 35 Inode(Volume* volume, ino_t ino); 36 ~Inode(); 37 38 status_t InitCheck(); 39 40 ino_t ID() const { return fID; } 41 ino_t Parent() const { return fParent; } 42 cluster_t Cluster() const { return fCluster; } 43 uint32 Offset() const { return fOffset; } 44 cluster_t StartCluster() const 45 { return fFileInfoEntry.file_info.StartCluster(); } 46 bool IsContiguous() const 47 { return fFileInfoEntry.file_info.IsContiguous(); } 48 cluster_t NextCluster(cluster_t cluster) const; 49 50 rw_lock* Lock() { return &fLock; } 51 52 status_t UpdateNodeFromDisk(); 53 54 bool IsDirectory() const 55 { return S_ISDIR(Mode()); } 56 bool IsFile() const 57 { return S_ISREG(Mode()); } 58 bool IsSymLink() const 59 { return S_ISLNK(Mode()); } 60 status_t CheckPermissions(int accessMode) const; 61 62 mode_t Mode() const; 63 off_t Size() const { return fFileInfoEntry.file_info.Size(); } 64 uid_t UserID() const { return 0;/*fNode.UserID();*/ } 65 gid_t GroupID() const { return 0;/*fNode.GroupID();*/ } 66 void GetChangeTime(struct timespec ×pec) const 67 { GetModificationTime(timespec); } 68 void GetModificationTime(struct timespec ×pec) const 69 { _GetTimespec(fFileEntry.file.ModificationDate(), 70 fFileEntry.file.ModificationTime(), timespec); } 71 void GetCreationTime(struct timespec ×pec) const 72 { _GetTimespec(fFileEntry.file.CreationDate(), 73 fFileEntry.file.CreationTime(), timespec); } 74 void GetAccessTime(struct timespec ×pec) const 75 { _GetTimespec(fFileEntry.file.AccessDate(), 76 fFileEntry.file.AccessTime(), timespec); } 77 78 Volume* GetVolume() const { return fVolume; } 79 80 status_t FindBlock(off_t logical, off_t& physical, 81 off_t *_length = NULL); 82 status_t ReadAt(off_t pos, uint8 *buffer, size_t *length); 83 status_t FillGapWithZeros(off_t start, off_t end); 84 85 void* FileCache() const { return fCache; } 86 void* Map() const { return fMap; } 87 88 bool VisitFile(struct exfat_entry*); 89 bool VisitFileInfo(struct exfat_entry*); 90 91 private: 92 friend struct InodesInoTreeDefinition; 93 friend struct InodesClusterTreeDefinition; 94 95 Inode(Volume* volume); 96 Inode(const Inode&); 97 Inode &operator=(const Inode&); 98 // no implementation 99 100 void _GetTimespec(uint16 date, uint16 time, 101 struct timespec ×pec) const; 102 void _Init(); 103 104 rw_lock fLock; 105 ::Volume* fVolume; 106 ino_t fID; 107 ino_t fParent; 108 cluster_t fCluster; 109 uint32 fOffset; 110 uint32 fFlags; 111 void* fCache; 112 void* fMap; 113 status_t fInitStatus; 114 115 SplayTreeLink<Inode> fInoTreeLink; 116 Inode* fInoTreeNext; 117 SplayTreeLink<Inode> fClusterTreeLink; 118 Inode* fClusterTreeNext; 119 120 struct exfat_entry fFileEntry; 121 struct exfat_entry fFileInfoEntry; 122 }; 123 124 125 // The Vnode class provides a convenience layer upon get_vnode(), so that 126 // you don't have to call put_vnode() anymore, which may make code more 127 // readable in some cases 128 129 class Vnode { 130 public: 131 Vnode(Volume* volume, ino_t id) 132 : 133 fInode(NULL) 134 { 135 SetTo(volume, id); 136 } 137 138 Vnode() 139 : 140 fStatus(B_NO_INIT), 141 fInode(NULL) 142 { 143 } 144 145 ~Vnode() 146 { 147 Unset(); 148 } 149 150 status_t InitCheck() 151 { 152 return fStatus; 153 } 154 155 void Unset() 156 { 157 if (fInode != NULL) { 158 put_vnode(fInode->GetVolume()->FSVolume(), fInode->ID()); 159 fInode = NULL; 160 fStatus = B_NO_INIT; 161 } 162 } 163 164 status_t SetTo(Volume* volume, ino_t id) 165 { 166 Unset(); 167 168 return fStatus = get_vnode(volume->FSVolume(), id, (void**)&fInode); 169 } 170 171 status_t Get(Inode** _inode) 172 { 173 *_inode = fInode; 174 return fStatus; 175 } 176 177 void Keep() 178 { 179 TRACEI("Vnode::Keep()\n"); 180 fInode = NULL; 181 } 182 183 private: 184 status_t fStatus; 185 Inode* fInode; 186 }; 187 188 189 struct InodesInoTreeDefinition { 190 typedef ino_t KeyType; 191 typedef Inode NodeType; 192 193 static KeyType GetKey(const NodeType* node) 194 { 195 return node->ID(); 196 } 197 198 static SplayTreeLink<NodeType>* GetLink(NodeType* node) 199 { 200 return &node->fInoTreeLink; 201 } 202 203 static int Compare(KeyType key, const NodeType* node) 204 { 205 return key == node->ID() ? 0 206 : (key < node->ID() ? -1 : 1); 207 } 208 209 static NodeType** GetListLink(NodeType* node) 210 { 211 return &node->fInoTreeNext; 212 } 213 }; 214 215 typedef IteratableSplayTree<InodesInoTreeDefinition> InodesInoTree; 216 217 struct InodesClusterTreeDefinition { 218 typedef cluster_t KeyType; 219 typedef Inode NodeType; 220 221 static KeyType GetKey(const NodeType* node) 222 { 223 return node->Cluster(); 224 } 225 226 static SplayTreeLink<NodeType>* GetLink(NodeType* node) 227 { 228 return &node->fClusterTreeLink; 229 } 230 231 static int Compare(KeyType key, const NodeType* node) 232 { 233 return key == node->Cluster() ? 0 234 : (key < node->Cluster() ? -1 : 1); 235 } 236 237 static NodeType** GetListLink(NodeType* node) 238 { 239 return &node->fClusterTreeNext; 240 } 241 }; 242 243 typedef IteratableSplayTree<InodesClusterTreeDefinition> InodesClusterTree; 244 245 #endif // INODE_H 246