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 12 #include "ext2.h" 13 #include "BlockAllocator.h" 14 #include "InodeAllocator.h" 15 #include "Transaction.h" 16 17 class Inode; 18 class Journal; 19 20 21 enum volume_flags { 22 VOLUME_READ_ONLY = 0x0001 23 }; 24 25 26 class Volume : public TransactionListener { 27 public: 28 Volume(fs_volume* volume); 29 ~Volume(); 30 31 status_t Mount(const char* device, uint32 flags); 32 status_t Unmount(); 33 34 bool IsValidSuperBlock(); 35 bool IsReadOnly() const 36 { return (fFlags & VOLUME_READ_ONLY) != 0; } 37 mutex& Lock(); 38 bool HasExtendedAttributes() const; 39 40 Inode* RootNode() const { return fRootNode; } 41 int Device() const { return fDevice; } 42 43 dev_t ID() const 44 { return fFSVolume ? fFSVolume->id : -1; } 45 fs_volume* FSVolume() const { return fFSVolume; } 46 const char* Name() const; 47 void SetName(const char* name); 48 49 uint32 NumInodes() const 50 { return fNumInodes; } 51 uint32 NumGroups() const 52 { return fNumGroups; } 53 fsblock_t NumBlocks() const 54 { return fSuperBlock.NumBlocks( 55 Has64bitFeature()); } 56 off_t NumFreeBlocks() const 57 { return fFreeBlocks; } 58 uint32 FirstDataBlock() const 59 { return fFirstDataBlock; } 60 61 uint32 BlockSize() const { return fBlockSize; } 62 uint32 BlockShift() const { return fBlockShift; } 63 uint32 BlocksPerGroup() const 64 { return fSuperBlock.BlocksPerGroup(); } 65 uint32 InodeSize() const 66 { return fSuperBlock.InodeSize(); } 67 uint32 InodesPerGroup() const 68 { return fSuperBlock.InodesPerGroup(); } 69 ext2_super_block& SuperBlock() { return fSuperBlock; } 70 71 status_t GetInodeBlock(ino_t id, off_t& block); 72 uint32 InodeBlockIndex(ino_t id) const; 73 status_t GetBlockGroup(int32 index, 74 ext2_block_group** _group); 75 status_t WriteBlockGroup(Transaction& transaction, 76 int32 index); 77 78 Journal* GetJournal() { return fJournal; } 79 80 bool IndexedDirectories() const 81 { return (fSuperBlock.CompatibleFeatures() 82 & EXT2_FEATURE_DIRECTORY_INDEX) != 0; } 83 bool HasJournalFeature() const 84 { return (fSuperBlock.CompatibleFeatures() 85 & EXT2_FEATURE_HAS_JOURNAL) != 0; } 86 bool Has64bitFeature() const 87 { return (fSuperBlock.IncompatibleFeatures() 88 & EXT2_INCOMPATIBLE_FEATURE_64BIT) != 0; } 89 bool HasExtentsFeature() const 90 { return (fSuperBlock.IncompatibleFeatures() 91 & EXT2_INCOMPATIBLE_FEATURE_EXTENTS) 92 != 0; } 93 bool HasChecksumFeature() const 94 { return (fSuperBlock.ReadOnlyFeatures() 95 & EXT2_READ_ONLY_FEATURE_GDT_CSUM) != 0; } 96 bool HasMetaGroupFeature() const 97 { return (fSuperBlock.IncompatibleFeatures() 98 & EXT2_INCOMPATIBLE_FEATURE_META_GROUP) 99 != 0; } 100 bool HasMetaGroupChecksumFeature() const 101 { return (fSuperBlock.ReadOnlyFeatures() 102 & EXT4_READ_ONLY_FEATURE_METADATA_CSUM) 103 != 0; } 104 bool HasChecksumSeedFeature() const 105 { return (fSuperBlock.IncompatibleFeatures() 106 & EXT2_INCOMPATIBLE_FEATURE_CSUM_SEED) 107 != 0; } 108 uint8 DefaultHashVersion() const 109 { return fSuperBlock.default_hash_version; } 110 bool HugeFiles() const 111 { return (fSuperBlock.ReadOnlyFeatures() 112 & EXT2_READ_ONLY_FEATURE_HUGE_FILE) != 0; } 113 status_t ActivateLargeFiles(Transaction& transaction); 114 status_t ActivateDirNLink(Transaction& transaction); 115 116 status_t SaveOrphan(Transaction& transaction, 117 ino_t newID, ino_t &oldID); 118 status_t RemoveOrphan(Transaction& transaction, 119 ino_t id); 120 121 status_t AllocateInode(Transaction& transaction, 122 Inode* parent, int32 mode, ino_t& id); 123 status_t FreeInode(Transaction& transaction, ino_t id, 124 bool isDirectory); 125 126 status_t AllocateBlocks(Transaction& transaction, 127 uint32 minimum, uint32 maximum, 128 uint32& blockGroup, fsblock_t& start, 129 uint32& length); 130 status_t FreeBlocks(Transaction& transaction, 131 fsblock_t start, uint32 length); 132 133 status_t LoadSuperBlock(); 134 status_t WriteSuperBlock(Transaction& transaction); 135 136 // cache access 137 void* BlockCache() { return fBlockCache; } 138 139 uint32 ChecksumSeed() const 140 { return fChecksumSeed; } 141 uint16 GroupDescriptorSize() const 142 { return fGroupDescriptorSize; } 143 144 status_t FlushDevice(); 145 status_t Sync(); 146 147 static status_t Identify(int fd, ext2_super_block* superBlock); 148 149 // TransactionListener functions 150 void TransactionDone(bool success); 151 void RemovedFromTransaction(); 152 153 private: 154 static uint32 _UnsupportedIncompatibleFeatures( 155 ext2_super_block& superBlock); 156 static uint32 _UnsupportedReadOnlyFeatures( 157 ext2_super_block& superBlock); 158 uint32 _GroupDescriptorBlock(uint32 blockIndex); 159 uint16 _GroupCheckSum(ext2_block_group *group, 160 int32 index); 161 void _SuperBlockChecksumSeed(); 162 bool _VerifySuperBlock(); 163 164 private: 165 mutex fLock; 166 fs_volume* fFSVolume; 167 int fDevice; 168 ext2_super_block fSuperBlock; 169 170 BlockAllocator* fBlockAllocator; 171 InodeAllocator fInodeAllocator; 172 Journal* fJournal; 173 Inode* fJournalInode; 174 175 uint32 fFlags; 176 uint32 fBlockSize; 177 uint32 fBlockShift; 178 uint32 fFirstDataBlock; 179 180 uint32 fNumInodes; 181 uint32 fNumGroups; 182 off_t fFreeBlocks; 183 uint32 fFreeInodes; 184 uint32 fGroupsPerBlock; 185 uint8** fGroupBlocks; 186 uint32 fInodesPerBlock; 187 uint16 fGroupDescriptorSize; 188 189 void* fBlockCache; 190 Inode* fRootNode; 191 192 uint32 fChecksumSeed; 193 }; 194 195 196 inline mutex& 197 Volume::Lock() 198 { 199 return fLock; 200 } 201 202 #endif // VOLUME_H 203