1 //---------------------------------------------------------------------- 2 // This software is part of the OpenBeOS distribution and is covered 3 // by the OpenBeOS license. 4 // 5 // Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net 6 // Mad props to Axel Dörfler and his BFS implementation, from which 7 // this UDF implementation draws much influence (and a little code :-P). 8 //--------------------------------------------------------------------- 9 #ifndef _UDF_VOLUME_H 10 #define _UDF_VOLUME_H 11 12 /*! \file Volume.h 13 */ 14 15 #include <KernelExport.h> 16 extern "C" { 17 #ifndef _IMPEXP_KERNEL 18 # define _IMPEXP_KERNEL 19 #endif 20 21 #include <fsproto.h> 22 } 23 24 #include "kernel_cpp.h" 25 #include "UdfDebug.h" 26 27 #include "CS0String.h" 28 #include "DiskStructures.h" 29 #include "PartitionMap.h" 30 31 namespace Udf { 32 33 class Icb; 34 35 class Volume { 36 public: 37 static status_t Identify(int device, off_t offset, off_t length, uint32 blockSize, char *volumeName); 38 39 Volume(nspace_id id); 40 41 status_t Mount(const char *deviceName, off_t volumeStart, off_t volumeLength, uint32 flags, 42 uint32 blockSize = 2048); 43 status_t Unmount(); 44 45 const char *Name() const; 46 int Device() const { return fDevice; } 47 nspace_id Id() const { return fId; } 48 49 off_t Offset() const { return fOffset; } 50 off_t Length() const { return fLength; } 51 52 uint32 BlockSize() const { return fBlockSize; } 53 uint32 BlockShift() const { return fBlockShift; } 54 55 off_t AddressForRelativeBlock(off_t block) { return (Offset() + block) * BlockSize(); } 56 off_t RelativeAddress(off_t address) { return Offset() * BlockSize() + address; } 57 58 bool IsReadOnly() const { return fReadOnly; } 59 60 vnode_id ToVnodeId(off_t block) const { return (vnode_id)block; } 61 62 template <class AddressType> 63 ssize_t Read(AddressType address, ssize_t length, void *data); 64 65 #if (!DRIVE_SETUP_ADDON) 66 Icb* RootIcb() { return fRootIcb; } 67 #endif 68 69 status_t MapAddress(udf_long_address address, off_t *mappedAddress); 70 off_t MapAddress(udf_extent_address address); 71 status_t MapBlock(udf_long_address address, off_t *mappedBlock); 72 off_t MapAddress(udf_short_address address); 73 private: 74 Volume(); // unimplemented 75 Volume(const Volume &ref); // unimplemented 76 Volume& operator=(const Volume &ref); // unimplemented 77 78 status_t _InitStatus() const { return fInitStatus; } 79 // Private _InitStatus() status_t values 80 enum { 81 B_UNINITIALIZED = B_ERRORS_END+1, //!< Completely uninitialized 82 B_DEVICE_INITIALIZED, //!< Initialized enough to access underlying device safely 83 B_IDENTIFIED, //!< Verified to be a UDF volume on disc 84 B_LOGICAL_VOLUME_INITIALIZED, //!< Initialized enough to map addresses 85 86 B_INITIALIZED = B_OK, 87 }; 88 89 90 // Called by Mount(), either directly or indirectly 91 status_t _Init(int device, off_t offset, off_t length, int blockSize); 92 status_t _Identify(); 93 status_t _Mount(); 94 status_t _WalkVolumeRecognitionSequence(); 95 status_t _WalkAnchorVolumeDescriptorSequences(); 96 status_t _WalkVolumeDescriptorSequence(udf_extent_address extent); 97 status_t _InitFileSetDescriptor(); 98 99 private: 100 nspace_id fId; 101 int fDevice; 102 bool fReadOnly; 103 104 off_t fOffset; //!< Starting block of the volume on the given device 105 off_t fLength; //!< Block length of volume on the given device 106 uint32 fBlockSize; 107 uint32 fBlockShift; 108 109 status_t fInitStatus; 110 111 udf_logical_descriptor fLogicalVD; 112 PartitionMap fPartitionMap; 113 #if (!DRIVE_SETUP_ADDON) 114 Icb *fRootIcb; // Destroyed by vfs via callback to udf_release_node() 115 #endif 116 CS0String fName; 117 }; 118 119 //---------------------------------------------------------------------- 120 // Template functions 121 //---------------------------------------------------------------------- 122 123 124 template <class AddressType> 125 status_t 126 Volume::Read(AddressType address, ssize_t length, void *data) 127 { 128 DEBUG_INIT(CF_PRIVATE | CF_HIGH_VOLUME, "Volume"); 129 off_t mappedAddress; 130 status_t err = data ? B_OK : B_BAD_VALUE; 131 if (!err) 132 err = MapAddress(address, &mappedAddress); 133 if (!err) { 134 ssize_t bytesRead = read_pos(fDevice, mappedAddress, data, BlockSize()); 135 if (bytesRead != (ssize_t)BlockSize()) { 136 err = B_IO_ERROR; 137 PRINT(("read_pos(pos:%Ld, len:%ld) failed with: 0x%lx\n", mappedAddress, 138 length, bytesRead)); 139 } 140 } 141 RETURN(err); 142 } 143 144 145 }; // namespace Udf 146 147 #endif // _UDF_VOLUME_H 148