1 /* 2 * Copyright 2011, Jérôme Duval, korli@users.berlios.de. 3 * Copyright 2008-2010, Axel Dörfler, axeld@pinc-software.de. 4 * This file may be used under the terms of the MIT License. 5 */ 6 #ifndef VOLUME_H 7 #define VOLUME_H 8 9 10 #include <lock.h> 11 #include <string.h> 12 13 #include "exfat.h" 14 #include "SplayTree.h" 15 16 17 struct node_key { 18 cluster_t cluster; 19 uint32 offset; 20 }; 21 22 struct node { 23 struct node_key key; 24 ino_t ino; 25 ino_t parent; 26 SplayTreeLink<struct node> nodeTreeLink; 27 SplayTreeLink<struct node> inoTreeLink; 28 }; 29 30 31 struct NodeTreeDefinition { 32 typedef struct node_key KeyType; 33 typedef struct node NodeType; 34 35 static KeyType GetKey(const NodeType* node) 36 { 37 return node->key; 38 } 39 40 static SplayTreeLink<NodeType>* GetLink(NodeType* node) 41 { 42 return &node->nodeTreeLink; 43 } 44 45 static int Compare(KeyType key, const NodeType* node) 46 { 47 if (key.cluster == node->key.cluster) { 48 if (key.offset == node->key.offset) 49 return 0; 50 return key.offset < node->key.offset ? -1 : 1; 51 } 52 return key.cluster < node->key.cluster ? -1 : 1; 53 } 54 }; 55 56 struct InoTreeDefinition { 57 typedef ino_t KeyType; 58 typedef struct node NodeType; 59 60 static KeyType GetKey(const NodeType* node) 61 { 62 return node->ino; 63 } 64 65 static SplayTreeLink<NodeType>* GetLink(NodeType* node) 66 { 67 return &node->inoTreeLink; 68 } 69 70 static int Compare(KeyType key, const NodeType* node) 71 { 72 if (key != node->ino) 73 return key < node->ino ? -1 : 1; 74 return 0; 75 } 76 }; 77 78 79 typedef SplayTree<NodeTreeDefinition> NodeTree; 80 typedef SplayTree<InoTreeDefinition> InoTree; 81 class Inode; 82 struct InodesInoTreeDefinition; 83 typedef IteratableSplayTree<InodesInoTreeDefinition> InodesInoTree; 84 struct InodesClusterTreeDefinition; 85 typedef IteratableSplayTree<InodesClusterTreeDefinition> InodesClusterTree; 86 87 88 enum volume_flags { 89 VOLUME_READ_ONLY = 0x0001 90 }; 91 92 93 class Volume { 94 public: 95 Volume(fs_volume* volume); 96 ~Volume(); 97 98 status_t Mount(const char* device, uint32 flags); 99 status_t Unmount(); 100 101 bool IsValidSuperBlock(); 102 bool IsReadOnly() const 103 { return (fFlags & VOLUME_READ_ONLY) != 0; } 104 105 Inode* RootNode() const { return fRootNode; } 106 int Device() const { return fDevice; } 107 108 dev_t ID() const 109 { return fFSVolume ? fFSVolume->id : -1; } 110 fs_volume* FSVolume() const { return fFSVolume; } 111 const char* Name() const; 112 void SetName(const char* name) 113 { strlcpy(fName, name, sizeof(fName)); } 114 115 uint32 BlockSize() const { return fBlockSize; } 116 uint32 EntriesPerBlock() const 117 { return fEntriesPerBlock; } 118 uint32 EntriesPerCluster() 119 { return fEntriesPerBlock 120 << SuperBlock().BlocksPerClusterShift(); } 121 size_t ClusterSize() { return fBlockSize 122 << SuperBlock().BlocksPerClusterShift(); } 123 exfat_super_block& SuperBlock() { return fSuperBlock; } 124 125 status_t LoadSuperBlock(); 126 127 // cache access 128 void* BlockCache() { return fBlockCache; } 129 130 static status_t Identify(int fd, exfat_super_block* superBlock); 131 132 status_t ClusterToBlock(cluster_t cluster, 133 fsblock_t &block); 134 Inode * FindInode(ino_t id); 135 Inode * FindInode(cluster_t cluster); 136 cluster_t NextCluster(cluster_t cluster); 137 ino_t GetIno(cluster_t cluster, uint32 offset, ino_t parent); 138 struct node_key* GetNode(ino_t ino, ino_t &parent); 139 private: 140 ino_t _NextID() { return fNextId++; } 141 142 mutex fLock; 143 fs_volume* fFSVolume; 144 int fDevice; 145 exfat_super_block fSuperBlock; 146 char fName[32]; 147 148 uint16 fFlags; 149 uint32 fBlockSize; 150 uint32 fEntriesPerBlock; 151 Inode* fRootNode; 152 ino_t fNextId; 153 154 void* fBlockCache; 155 InodesInoTree* fInodesInoTree; 156 InodesClusterTree* fInodesClusterTree; 157 NodeTree fNodeTree; 158 InoTree fInoTree; 159 }; 160 161 #endif // VOLUME_H 162 163