129008bcfSTyler Dauwalder //---------------------------------------------------------------------- 229008bcfSTyler Dauwalder // This software is part of the OpenBeOS distribution and is covered 329008bcfSTyler Dauwalder // by the OpenBeOS license. 429008bcfSTyler Dauwalder // 529008bcfSTyler Dauwalder // Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net 629008bcfSTyler Dauwalder // Mad props to Axel Dörfler and his BFS implementation, from which 729008bcfSTyler Dauwalder // this UDF implementation draws much influence (and a little code :-P). 829008bcfSTyler Dauwalder //---------------------------------------------------------------------- 929008bcfSTyler Dauwalder #include "Volume.h" 1029008bcfSTyler Dauwalder 113f4628f1STyler Dauwalder #include "Icb.h" 120d383564STyler Dauwalder #include "MemoryChunk.h" 13*21c162a3STyler Dauwalder #include "Recognition.h" 1429008bcfSTyler Dauwalder 153f4628f1STyler Dauwalder using namespace Udf; 1629008bcfSTyler Dauwalder 1729008bcfSTyler Dauwalder //---------------------------------------------------------------------- 1829008bcfSTyler Dauwalder // Volume 1929008bcfSTyler Dauwalder //---------------------------------------------------------------------- 2029008bcfSTyler Dauwalder 2129008bcfSTyler Dauwalder /*! \brief Creates an unmounted volume with the given id. 2229008bcfSTyler Dauwalder */ 2329008bcfSTyler Dauwalder Volume::Volume(nspace_id id) 243f4628f1STyler Dauwalder : fId(id) 2529008bcfSTyler Dauwalder , fDevice(0) 2629008bcfSTyler Dauwalder , fReadOnly(false) 27*21c162a3STyler Dauwalder , fMounted(false) 28bb182cf3STyler Dauwalder , fOffset(0) 294ac73018STyler Dauwalder , fBlockSize(0) 30a71fd512STyler Dauwalder , fBlockShift(0) 314ac73018STyler Dauwalder , fInitStatus(B_UNINITIALIZED) 3262426f64STyler Dauwalder #if (!DRIVE_SETUP_ADDON) 333f4628f1STyler Dauwalder , fRootIcb(NULL) 3462426f64STyler Dauwalder #endif 3529008bcfSTyler Dauwalder { 36*21c162a3STyler Dauwalder for (int i = 0; i < UDF_MAX_PARTITION_MAPS; i++) 37*21c162a3STyler Dauwalder fPartitions[i] = NULL; 3829008bcfSTyler Dauwalder } 3929008bcfSTyler Dauwalder 4029008bcfSTyler Dauwalder status_t 4162426f64STyler Dauwalder Volume::Identify(int device, off_t offset, off_t length, uint32 blockSize, char *volumeName) 4229008bcfSTyler Dauwalder { 4362426f64STyler Dauwalder DEBUG_INIT_ETC(CF_PUBLIC | CF_VOLUME_OPS, "static Volume", 44bb182cf3STyler Dauwalder ("device: %d, offset: %Ld, volumeName: %p", device, offset, volumeName)); 4562426f64STyler Dauwalder if (!volumeName) 4662426f64STyler Dauwalder RETURN(B_BAD_VALUE); 4762426f64STyler Dauwalder 4862426f64STyler Dauwalder // FILE *file = fopen("/boot/home/Desktop/outputIdentify.txt", "w+"); 4962426f64STyler Dauwalder 5062426f64STyler Dauwalder Volume volume(0); 5162426f64STyler Dauwalder status_t err = volume._Init(device, offset, length, blockSize); 5262426f64STyler Dauwalder // fprintf(file, "error = 0x%lx, `%s'\n", err, strerror(err)); 5362426f64STyler Dauwalder // fflush(file); 5462426f64STyler Dauwalder if (!err) 5562426f64STyler Dauwalder err = volume._Identify(); 5662426f64STyler Dauwalder // fprintf(file, "error = 0x%lx, `%s'\n", err, strerror(err)); 5762426f64STyler Dauwalder // fflush(file); 5862426f64STyler Dauwalder if (!err) 5962426f64STyler Dauwalder strcpy(volumeName, volume.Name()); 6062426f64STyler Dauwalder // fprintf(file, "error = 0x%lx, `%s'\n", err, strerror(err)); 6162426f64STyler Dauwalder // fflush(file); 6262426f64STyler Dauwalder 6362426f64STyler Dauwalder // fclose(file); 6462426f64STyler Dauwalder RETURN(err); 6529008bcfSTyler Dauwalder } 6629008bcfSTyler Dauwalder 6729008bcfSTyler Dauwalder /*! \brief Attempts to mount the given device. 683f4628f1STyler Dauwalder 693f4628f1STyler Dauwalder \param volumeStart The block on the given device whereat the volume begins. 703f4628f1STyler Dauwalder \param volumeLength The block length of the volume on the given device. 7129008bcfSTyler Dauwalder */ 7229008bcfSTyler Dauwalder status_t 73*21c162a3STyler Dauwalder Volume::Mount2(const char *deviceName, off_t offset, off_t length, 74*21c162a3STyler Dauwalder uint32 blockSize, uint32 flags) 75*21c162a3STyler Dauwalder { 76*21c162a3STyler Dauwalder DEBUG_INIT_ETC(CF_PUBLIC | CF_VOLUME_OPS, "Volume", 77*21c162a3STyler Dauwalder ("deviceName: `%s', offset: %Ld, length: %Ld, blockSize: %ld, " 78*21c162a3STyler Dauwalder "flags: %ld", deviceName, offset, length, blockSize, flags)); 79*21c162a3STyler Dauwalder if (!deviceName) 80*21c162a3STyler Dauwalder RETURN(B_BAD_VALUE); 81*21c162a3STyler Dauwalder if (Mounted()) { 82*21c162a3STyler Dauwalder // Already mounted, thank you for asking 83*21c162a3STyler Dauwalder RETURN(B_BUSY); 84*21c162a3STyler Dauwalder } 85*21c162a3STyler Dauwalder 86*21c162a3STyler Dauwalder // Open the device read only 87*21c162a3STyler Dauwalder int device = open(deviceName, O_RDONLY); 88*21c162a3STyler Dauwalder if (device < B_OK) 89*21c162a3STyler Dauwalder RETURN(device); 90*21c162a3STyler Dauwalder 91*21c162a3STyler Dauwalder status_t error = B_OK; 92*21c162a3STyler Dauwalder 93*21c162a3STyler Dauwalder // If the device is actually a normal file, try to disable the cache 94*21c162a3STyler Dauwalder // for the file in the parent filesystem 95*21c162a3STyler Dauwalder struct stat stat; 96*21c162a3STyler Dauwalder error = fstat(device, &stat) < 0 ? B_ERROR : B_OK; 97*21c162a3STyler Dauwalder if (!error) { 98*21c162a3STyler Dauwalder if (stat.st_mode & S_IFREG && ioctl(device, IOCTL_FILE_UNCACHED_IO, NULL) < 0) { 99*21c162a3STyler Dauwalder DIE(("Unable to disable cache of underlying file system.\n")); 100*21c162a3STyler Dauwalder } 101*21c162a3STyler Dauwalder } 102*21c162a3STyler Dauwalder 103*21c162a3STyler Dauwalder udf_logical_descriptor logicalVolumeDescriptor; 104*21c162a3STyler Dauwalder udf_partition_descriptor partitionDescriptors[Udf::kMaxPartitionDescriptors]; 105*21c162a3STyler Dauwalder uint8 partitionDescriptorCount; 106*21c162a3STyler Dauwalder uint32 blockShift; 107*21c162a3STyler Dauwalder 108*21c162a3STyler Dauwalder error = udf_recognize(device, offset, length, blockSize, blockShift, 109*21c162a3STyler Dauwalder logicalVolumeDescriptor, partitionDescriptors, 110*21c162a3STyler Dauwalder partitionDescriptorCount); 111*21c162a3STyler Dauwalder 112*21c162a3STyler Dauwalder // Set up the block cache 113*21c162a3STyler Dauwalder if (!error) 114*21c162a3STyler Dauwalder error = init_cache_for_device(device, length); 115*21c162a3STyler Dauwalder 116*21c162a3STyler Dauwalder // Set up the partitions 117*21c162a3STyler Dauwalder if (!error) { 118*21c162a3STyler Dauwalder // Set up physical and sparable partitions first 119*21c162a3STyler Dauwalder int offset = 0; 120*21c162a3STyler Dauwalder for (uint8 i = 0; i < logicalVolumeDescriptor.partition_map_count(); i++) { 121*21c162a3STyler Dauwalder uint8 *maps = logicalVolumeDescriptor.partition_maps(); 122*21c162a3STyler Dauwalder udf_generic_partition_map *header = 123*21c162a3STyler Dauwalder reinterpret_cast<udf_generic_partition_map*>(maps+offset); 124*21c162a3STyler Dauwalder // logicalVolumeDescriptor.partition_maps() + offset); 125*21c162a3STyler Dauwalder PRINT(("partition map %d (type %d):\n", i, header->type())); 126*21c162a3STyler Dauwalder if (header->type() == 1) { 127*21c162a3STyler Dauwalder // udf_physical_partition_map* map = 128*21c162a3STyler Dauwalder // reinterpret_cast<udf_physical_partition_map*>(header); 129*21c162a3STyler Dauwalder // PDUMP(map); 130*21c162a3STyler Dauwalder PDUMP(reinterpret_cast<udf_physical_partition_map*>(header)); 131*21c162a3STyler Dauwalder } else { 132*21c162a3STyler Dauwalder udf_sparable_partition_map* map = 133*21c162a3STyler Dauwalder reinterpret_cast<udf_sparable_partition_map*>(header); 134*21c162a3STyler Dauwalder DUMP(map->partition_type_id()); 135*21c162a3STyler Dauwalder } 136*21c162a3STyler Dauwalder 137*21c162a3STyler Dauwalder offset += header->length(); 138*21c162a3STyler Dauwalder } 139*21c162a3STyler Dauwalder } 140*21c162a3STyler Dauwalder 141*21c162a3STyler Dauwalder RETURN(B_ERROR); 142*21c162a3STyler Dauwalder 143*21c162a3STyler Dauwalder // At this point we've found a valid set of volume descriptors, and we 144*21c162a3STyler Dauwalder // have our partitions set up. We 145*21c162a3STyler Dauwalder // now need to investigate the file set descriptor pointed to by 146*21c162a3STyler Dauwalder // the logical volume descriptor 147*21c162a3STyler Dauwalder if (!error) { 148*21c162a3STyler Dauwalder MemoryChunk chunk(fLogicalVolumeDescriptor.file_set_address().length()); 149*21c162a3STyler Dauwalder 150*21c162a3STyler Dauwalder status_t error = chunk.InitCheck(); 151*21c162a3STyler Dauwalder 152*21c162a3STyler Dauwalder if (!error) { 153*21c162a3STyler Dauwalder error = Read(fLogicalVolumeDescriptor.file_set_address(), 154*21c162a3STyler Dauwalder fLogicalVolumeDescriptor.file_set_address().length(), 155*21c162a3STyler Dauwalder chunk.Data()); 156*21c162a3STyler Dauwalder if (!error) { 157*21c162a3STyler Dauwalder udf_file_set_descriptor *fileSet = 158*21c162a3STyler Dauwalder reinterpret_cast<udf_file_set_descriptor*>(chunk.Data()); 159*21c162a3STyler Dauwalder fileSet->tag().init_check(0); 160*21c162a3STyler Dauwalder PDUMP(fileSet); 161*21c162a3STyler Dauwalder fRootIcb = new Icb(this, fileSet->root_directory_icb()); 162*21c162a3STyler Dauwalder error = fRootIcb ? fRootIcb->InitCheck() : B_NO_MEMORY; 163*21c162a3STyler Dauwalder } 164*21c162a3STyler Dauwalder } 165*21c162a3STyler Dauwalder } 166*21c162a3STyler Dauwalder 167*21c162a3STyler Dauwalder if (!error) { 168*21c162a3STyler Dauwalder // Success, create a vnode for the root 169*21c162a3STyler Dauwalder error = new_vnode(Id(), RootIcb()->Id(), (void*)RootIcb()); 170*21c162a3STyler Dauwalder if (error) { 171*21c162a3STyler Dauwalder PRINT(("Error create vnode for root icb! error = 0x%lx, `%s'\n", 172*21c162a3STyler Dauwalder error, strerror(error))); 173*21c162a3STyler Dauwalder } 174*21c162a3STyler Dauwalder } 175*21c162a3STyler Dauwalder 176*21c162a3STyler Dauwalder fInitStatus = error < B_OK ? B_UNINITIALIZED : B_LOGICAL_VOLUME_INITIALIZED; 177*21c162a3STyler Dauwalder 178*21c162a3STyler Dauwalder // set name and other member variables 179*21c162a3STyler Dauwalder if (!error) { 180*21c162a3STyler Dauwalder 181*21c162a3STyler Dauwalder } 182*21c162a3STyler Dauwalder 183*21c162a3STyler Dauwalder fDevice = device; 184*21c162a3STyler Dauwalder fReadOnly = true; 185*21c162a3STyler Dauwalder fOffset = offset; 186*21c162a3STyler Dauwalder fLength = length; 187*21c162a3STyler Dauwalder fBlockSize = blockSize; 188*21c162a3STyler Dauwalder 189*21c162a3STyler Dauwalder RETURN(error); 190*21c162a3STyler Dauwalder 191*21c162a3STyler Dauwalder /* if (!error && volumeName) { 192*21c162a3STyler Dauwalder CS0String name(logicalVolumeDescriptor.logical_volume_identifier()); 193*21c162a3STyler Dauwalder strcpy(volumeName, name.String()); 194*21c162a3STyler Dauwalder } 195*21c162a3STyler Dauwalder */ 196*21c162a3STyler Dauwalder /* 197*21c162a3STyler Dauwalder status_t error = _Init(device, volumeStart, volumeLength, blockSize); 198*21c162a3STyler Dauwalder if (!error) 199*21c162a3STyler Dauwalder error = _Identify(); 200*21c162a3STyler Dauwalder if (!error) 201*21c162a3STyler Dauwalder error = _Mount(); 202*21c162a3STyler Dauwalder 203*21c162a3STyler Dauwalder if (error) 204*21c162a3STyler Dauwalder fInitStatus = B_UNINITIALIZED; 205*21c162a3STyler Dauwalder 206*21c162a3STyler Dauwalder RETURN(error); 207*21c162a3STyler Dauwalder 208*21c162a3STyler Dauwalder */ 209*21c162a3STyler Dauwalder } 210*21c162a3STyler Dauwalder 211*21c162a3STyler Dauwalder 212*21c162a3STyler Dauwalder /*! \brief Attempts to mount the given device. 213*21c162a3STyler Dauwalder 214*21c162a3STyler Dauwalder \param volumeStart The block on the given device whereat the volume begins. 215*21c162a3STyler Dauwalder \param volumeLength The block length of the volume on the given device. 216*21c162a3STyler Dauwalder */ 217*21c162a3STyler Dauwalder status_t 2184ac73018STyler Dauwalder Volume::Mount(const char *deviceName, off_t volumeStart, off_t volumeLength, 2194ac73018STyler Dauwalder uint32 flags, uint32 blockSize) 22029008bcfSTyler Dauwalder { 221565457fdSTyler Dauwalder DEBUG_INIT_ETC(CF_PUBLIC | CF_VOLUME_OPS, "Volume", 222bb182cf3STyler Dauwalder ("deviceName: `%s', offset: %Ld, length %Ld", deviceName, volumeStart, volumeLength)); 22329008bcfSTyler Dauwalder if (!deviceName) 22462426f64STyler Dauwalder RETURN(B_BAD_VALUE); 2254ac73018STyler Dauwalder if (_InitStatus() == B_INITIALIZED) 22662426f64STyler Dauwalder RETURN(B_BUSY); 2274ac73018STyler Dauwalder // Already mounted, thank you for asking 22829008bcfSTyler Dauwalder 22962426f64STyler Dauwalder // Open the device read only 23062426f64STyler Dauwalder int device = open(deviceName, O_RDONLY); 23162426f64STyler Dauwalder if (device < B_OK) 23262426f64STyler Dauwalder RETURN(device); 233a71fd512STyler Dauwalder 23462426f64STyler Dauwalder status_t err = _Init(device, volumeStart, volumeLength, blockSize); 23562426f64STyler Dauwalder if (!err) 2364ac73018STyler Dauwalder err = _Identify(); 23762426f64STyler Dauwalder if (!err) 23862426f64STyler Dauwalder err = _Mount(); 239a71fd512STyler Dauwalder 24062426f64STyler Dauwalder if (err) 24162426f64STyler Dauwalder fInitStatus = B_UNINITIALIZED; 2423f4628f1STyler Dauwalder 2433f4628f1STyler Dauwalder RETURN(err); 2444ac73018STyler Dauwalder } 2454ac73018STyler Dauwalder 246a71fd512STyler Dauwalder const char* 247a71fd512STyler Dauwalder Volume::Name() const { 248a71fd512STyler Dauwalder return fName.String(); 249a71fd512STyler Dauwalder } 2503f4628f1STyler Dauwalder 2510d383564STyler Dauwalder off_t 252a71fd512STyler Dauwalder Volume::MapAddress(udf_extent_address address) 2530d383564STyler Dauwalder { 2540d383564STyler Dauwalder return address.location() * BlockSize(); 2550d383564STyler Dauwalder } 2560d383564STyler Dauwalder 2573f4628f1STyler Dauwalder 2583f4628f1STyler Dauwalder /*! \brief Maps the given \c udf_long_address to an absolute block address. 2593f4628f1STyler Dauwalder */ 2603f4628f1STyler Dauwalder status_t 261a71fd512STyler Dauwalder Volume::MapBlock(udf_long_address address, off_t *mappedBlock) 2620d383564STyler Dauwalder { 2633f4628f1STyler Dauwalder DEBUG_INIT_ETC(CF_PRIVATE | CF_HIGH_VOLUME, "Volume", ("long_address(block: %ld, partition: %d), %p", 2643f4628f1STyler Dauwalder address.block(), address.partition(), mappedBlock)); 2653f4628f1STyler Dauwalder status_t err = mappedBlock ? B_OK : B_BAD_VALUE; 2663f4628f1STyler Dauwalder if (!err) 26762426f64STyler Dauwalder err = _InitStatus() >= B_IDENTIFIED ? B_OK : B_NO_INIT; 2683f4628f1STyler Dauwalder if (!err) { 269b4bfabdeSTyler Dauwalder const udf_partition_descriptor* partition = fPartitionMap.Find(address.partition()); 2703f4628f1STyler Dauwalder err = partition ? B_OK : B_BAD_ADDRESS; 2713f4628f1STyler Dauwalder if (!err) { 272bb182cf3STyler Dauwalder *mappedBlock = partition->start() + address.block(); 2733f4628f1STyler Dauwalder } 2743f4628f1STyler Dauwalder if (!err) { 275bb182cf3STyler Dauwalder PRINT(("mapped to block %Ld\n", *mappedBlock)); 2763f4628f1STyler Dauwalder } 2773f4628f1STyler Dauwalder } 278a71fd512STyler Dauwalder RETURN(err); 2793f4628f1STyler Dauwalder } 2803f4628f1STyler Dauwalder 2813f4628f1STyler Dauwalder /*! \brief Maps the given \c udf_long_address to an absolute byte address. 2823f4628f1STyler Dauwalder */ 2833f4628f1STyler Dauwalder status_t 284a71fd512STyler Dauwalder Volume::MapAddress(udf_long_address address, off_t *mappedAddress) 2853f4628f1STyler Dauwalder { 2863f4628f1STyler Dauwalder DEBUG_INIT_ETC(CF_PRIVATE | CF_HIGH_VOLUME, "Volume", ("long_address(block: %ld, partition: %d), %p", 2873f4628f1STyler Dauwalder address.block(), address.partition(), mappedAddress)); 288a71fd512STyler Dauwalder status_t err = MapBlock(address, mappedAddress); 2893f4628f1STyler Dauwalder if (!err) 2903f4628f1STyler Dauwalder *mappedAddress = *mappedAddress * BlockSize(); 2913f4628f1STyler Dauwalder if (!err) { 292bb182cf3STyler Dauwalder PRINT(("mapped to address %Ld\n", *mappedAddress)); 2933f4628f1STyler Dauwalder } 2943f4628f1STyler Dauwalder RETURN_ERROR(err); 2950d383564STyler Dauwalder } 2960d383564STyler Dauwalder 2970d383564STyler Dauwalder off_t 298a71fd512STyler Dauwalder Volume::MapAddress(udf_short_address address) 2990d383564STyler Dauwalder { 3000d383564STyler Dauwalder return 0; 3010d383564STyler Dauwalder } 3020d383564STyler Dauwalder 3033f4628f1STyler Dauwalder /*status_t 3040d383564STyler Dauwalder Volume::_Read(udf_extent_address address, ssize_t length, void *data) 3050d383564STyler Dauwalder { 3060d383564STyler Dauwalder DEBUG_INIT(CF_PRIVATE | CF_HIGH_VOLUME, "Volume"); 307a71fd512STyler Dauwalder off_t mappedAddress = MapAddress(address); 3080d383564STyler Dauwalder status_t err = data ? B_OK : B_BAD_VALUE; 3090d383564STyler Dauwalder if (!err) { 3100d383564STyler Dauwalder ssize_t bytesRead = read_pos(fDevice, mappedAddress, data, BlockSize()); 3110d383564STyler Dauwalder if (bytesRead != (ssize_t)BlockSize()) { 3120d383564STyler Dauwalder err = B_IO_ERROR; 313bb182cf3STyler Dauwalder PRINT(("read_pos(pos:%Ld, len:%ld) failed with: 0x%lx\n", mappedAddress, 3140d383564STyler Dauwalder length, bytesRead)); 3150d383564STyler Dauwalder } 3160d383564STyler Dauwalder } 3173f4628f1STyler Dauwalder RETURN(err); 3180d383564STyler Dauwalder } 3193f4628f1STyler Dauwalder */ 3200d383564STyler Dauwalder 3213f4628f1STyler Dauwalder /*template <class AddressType> 3223f4628f1STyler Dauwalder status_t 3233f4628f1STyler Dauwalder Volume::_Read(AddressType address, ssize_t length, void *data) 3243f4628f1STyler Dauwalder { 3253f4628f1STyler Dauwalder DEBUG_INIT(CF_PRIVATE | CF_HIGH_VOLUME, "Volume"); 3263f4628f1STyler Dauwalder off_t mappedAddress; 3273f4628f1STyler Dauwalder status_t err = data ? B_OK : B_BAD_VALUE; 3283f4628f1STyler Dauwalder if (!err) 329a71fd512STyler Dauwalder err = MapAddress(address, &mappedAddress); 3303f4628f1STyler Dauwalder if (!err) { 3313f4628f1STyler Dauwalder ssize_t bytesRead = read_pos(fDevice, mappedAddress, data, BlockSize()); 3323f4628f1STyler Dauwalder if (bytesRead != (ssize_t)BlockSize()) { 3333f4628f1STyler Dauwalder err = B_IO_ERROR; 334bb182cf3STyler Dauwalder PRINT(("read_pos(pos:%Ld, len:%ld) failed with: 0x%lx\n", mappedAddress, 3353f4628f1STyler Dauwalder length, bytesRead)); 3363f4628f1STyler Dauwalder } 3373f4628f1STyler Dauwalder } 3383f4628f1STyler Dauwalder RETURN(err); 3393f4628f1STyler Dauwalder } 3403f4628f1STyler Dauwalder */ 34162426f64STyler Dauwalder status_t 34262426f64STyler Dauwalder Volume::_Init(int device, off_t offset, off_t length, int blockSize) 34362426f64STyler Dauwalder { 34462426f64STyler Dauwalder DEBUG_INIT(CF_PRIVATE | CF_HIGH_VOLUME, "Volume"); 34562426f64STyler Dauwalder if (_InitStatus() == B_INITIALIZED) 34662426f64STyler Dauwalder RETURN_ERROR(B_BUSY); 34762426f64STyler Dauwalder 34862426f64STyler Dauwalder // Check the block size 34962426f64STyler Dauwalder uint32 bitCount = 0; 35062426f64STyler Dauwalder for (int i = 0; i < 32; i++) { 35162426f64STyler Dauwalder // Zero out all bits except bit i 35262426f64STyler Dauwalder uint32 block = blockSize & (uint32(1) << i); 35362426f64STyler Dauwalder if (block) { 35462426f64STyler Dauwalder if (++bitCount > 1) { 35564df0549STyler Dauwalder PRINT(("Block size must be a power of two! (blockSize = %d)\n", blockSize)); 35662426f64STyler Dauwalder RETURN(B_BAD_VALUE); 35762426f64STyler Dauwalder } else { 35862426f64STyler Dauwalder fBlockShift = i; 35962426f64STyler Dauwalder PRINT(("BlockShift() = %ld\n", BlockShift())); 36062426f64STyler Dauwalder } 36162426f64STyler Dauwalder } 36262426f64STyler Dauwalder } 36362426f64STyler Dauwalder 36462426f64STyler Dauwalder fDevice = device; 36562426f64STyler Dauwalder fReadOnly = true; 366bb182cf3STyler Dauwalder fOffset = offset; 36762426f64STyler Dauwalder fLength = length; 36862426f64STyler Dauwalder fBlockSize = blockSize; 36962426f64STyler Dauwalder 37062426f64STyler Dauwalder status_t err = B_OK; 37162426f64STyler Dauwalder 37262426f64STyler Dauwalder #if (!DRIVE_SETUP_ADDON) 37362426f64STyler Dauwalder // If the device is actually a normal file, try to disable the cache 37462426f64STyler Dauwalder // for the file in the parent filesystem 37562426f64STyler Dauwalder struct stat stat; 37662426f64STyler Dauwalder err = fstat(fDevice, &stat) < 0 ? B_ERROR : B_OK; 37762426f64STyler Dauwalder if (!err) { 37862426f64STyler Dauwalder if (stat.st_mode & S_IFREG && ioctl(fDevice, IOCTL_FILE_UNCACHED_IO, NULL) < 0) { 37962426f64STyler Dauwalder // Apparently it's a bad thing if you can't disable the file 38062426f64STyler Dauwalder // cache for a non-device disk image you're trying to mount... 38162426f64STyler Dauwalder DIE(("Unable to disable cache of underlying file system. " 38262426f64STyler Dauwalder "I hear that's bad. :-(\n")); 38362426f64STyler Dauwalder } 38462426f64STyler Dauwalder } 38562426f64STyler Dauwalder #endif 38662426f64STyler Dauwalder 38762426f64STyler Dauwalder fInitStatus = err < B_OK ? B_UNINITIALIZED : B_DEVICE_INITIALIZED; 38862426f64STyler Dauwalder 38962426f64STyler Dauwalder RETURN(err); 39062426f64STyler Dauwalder } 39162426f64STyler Dauwalder 3924ac73018STyler Dauwalder /*! \brief Walks through the volume recognition and descriptor sequences, 3934ac73018STyler Dauwalder gathering volume description info as it goes. 3944ac73018STyler Dauwalder 3954ac73018STyler Dauwalder Note that the 512 avdp location is, technically speaking, only valid on 3964ac73018STyler Dauwalder unlosed CD-R media in the absense of an avdp at 256. For now I'm not 3974ac73018STyler Dauwalder bothering with such silly details, and instead am just checking for it 3984ac73018STyler Dauwalder last. 3994ac73018STyler Dauwalder */ 4004ac73018STyler Dauwalder status_t 4014ac73018STyler Dauwalder Volume::_Identify() 4024ac73018STyler Dauwalder { 403565457fdSTyler Dauwalder DEBUG_INIT(CF_PRIVATE | CF_VOLUME_OPS, "Volume"); 4044ac73018STyler Dauwalder 4054ac73018STyler Dauwalder status_t err = _InitStatus() == B_DEVICE_INITIALIZED ? B_OK : B_BAD_VALUE; 4064ac73018STyler Dauwalder 4074ac73018STyler Dauwalder // Check for a valid volume recognition sequence 4084ac73018STyler Dauwalder if (!err) 4094ac73018STyler Dauwalder err = _WalkVolumeRecognitionSequence(); 4104ac73018STyler Dauwalder 4114ac73018STyler Dauwalder // Now hunt down a volume descriptor sequence from one of 4124ac73018STyler Dauwalder // the anchor volume pointers (if there are any). 4130d383564STyler Dauwalder if (!err) 4140d383564STyler Dauwalder err = _WalkAnchorVolumeDescriptorSequences(); 4154ac73018STyler Dauwalder 41662426f64STyler Dauwalder // Set the volume name 41762426f64STyler Dauwalder if (!err) { 41862426f64STyler Dauwalder // FILE *file = fopen("/boot/home/Desktop/vdoutput.txt", "w+"); 41962426f64STyler Dauwalder // fprint 42062426f64STyler Dauwalder 421*21c162a3STyler Dauwalder fName.SetTo(fLogicalVolumeDescriptor.logical_volume_identifier()); 42262426f64STyler Dauwalder } 42362426f64STyler Dauwalder 42462426f64STyler Dauwalder fInitStatus = err < B_OK ? B_UNINITIALIZED : B_IDENTIFIED; 42562426f64STyler Dauwalder 42662426f64STyler Dauwalder RETURN(err); 42762426f64STyler Dauwalder } 42862426f64STyler Dauwalder 42962426f64STyler Dauwalder status_t 43062426f64STyler Dauwalder Volume::_Mount() 43162426f64STyler Dauwalder { 43262426f64STyler Dauwalder DEBUG_INIT(CF_PRIVATE | CF_VOLUME_OPS, "Volume"); 43362426f64STyler Dauwalder 43462426f64STyler Dauwalder status_t err = _InitStatus() == B_IDENTIFIED ? B_OK : B_BAD_VALUE; 43562426f64STyler Dauwalder 43662426f64STyler Dauwalder #if (!DRIVE_SETUP_ADDON) 43762426f64STyler Dauwalder if (!err) 43862426f64STyler Dauwalder err = init_cache_for_device(Device(), Length()); 43962426f64STyler Dauwalder 4400d383564STyler Dauwalder // At this point we've found a valid set of volume descriptors. We 4410d383564STyler Dauwalder // now need to investigate the file set descriptor pointed to by 4420d383564STyler Dauwalder // the logical volume descriptor 44362426f64STyler Dauwalder if (!err) 4440d383564STyler Dauwalder err = _InitFileSetDescriptor(); 44562426f64STyler Dauwalder 44662426f64STyler Dauwalder if (!err) { 44762426f64STyler Dauwalder // Success, create a vnode for the root 44862426f64STyler Dauwalder err = new_vnode(Id(), RootIcb()->Id(), (void*)RootIcb()); 44962426f64STyler Dauwalder if (err) { 45062426f64STyler Dauwalder PRINT(("Error create vnode for root icb! error = 0x%lx, `%s'\n", 45162426f64STyler Dauwalder err, strerror(err))); 4523f4628f1STyler Dauwalder } 45362426f64STyler Dauwalder } 45462426f64STyler Dauwalder 45562426f64STyler Dauwalder fInitStatus = err < B_OK ? B_UNINITIALIZED : B_LOGICAL_VOLUME_INITIALIZED; 45662426f64STyler Dauwalder #endif 4574ac73018STyler Dauwalder 4584ac73018STyler Dauwalder RETURN(err); 4594ac73018STyler Dauwalder } 4604ac73018STyler Dauwalder 461565457fdSTyler Dauwalder /*! \brief Walks the iso9660/ecma-167 volume recognition sequence, returning 462565457fdSTyler Dauwalder \c B_OK if the presence of a UDF filesystem on this volume is likely. 463565457fdSTyler Dauwalder 464565457fdSTyler Dauwalder \return \c B_OK: An ECMA-167 vsd was found, or at least one extended area 465565457fdSTyler Dauwalder vsd was found and no ECMA-168 vsds were found. 466565457fdSTyler Dauwalder \return "error code": Only iso9660 vsds were found, an ECMA-168 vsd was 467565457fdSTyler Dauwalder found (but no ECMA-167 vsd), or an error occurred. 468565457fdSTyler Dauwalder */ 4694ac73018STyler Dauwalder status_t 4704ac73018STyler Dauwalder Volume::_WalkVolumeRecognitionSequence() 4714ac73018STyler Dauwalder { 472565457fdSTyler Dauwalder DEBUG_INIT(CF_PRIVATE | CF_VOLUME_OPS, "Volume"); 4734ac73018STyler Dauwalder // vrs starts at block 16. Each volume structure descriptor (vsd) 4744ac73018STyler Dauwalder // should be one block long. We're expecting to find 0 or more iso9660 4754ac73018STyler Dauwalder // vsd's followed by some ECMA-167 vsd's. 4760d383564STyler Dauwalder MemoryChunk chunk(BlockSize()); 4770d383564STyler Dauwalder status_t err = chunk.InitCheck(); 4784ac73018STyler Dauwalder if (!err) { 4794ac73018STyler Dauwalder bool foundISO = false; 4804ac73018STyler Dauwalder bool foundExtended = false; 4814ac73018STyler Dauwalder bool foundECMA167 = false; 4824ac73018STyler Dauwalder bool foundECMA168 = false; 4834ac73018STyler Dauwalder bool foundBoot = false; 4844ac73018STyler Dauwalder for (uint32 block = 16; true; block++) { 4854ac73018STyler Dauwalder PRINT(("block %ld: ", block)) 486565457fdSTyler Dauwalder off_t address = AddressForRelativeBlock(block); 4870d383564STyler Dauwalder ssize_t bytesRead = read_pos(fDevice, address, chunk.Data(), BlockSize()); 4884ac73018STyler Dauwalder if (bytesRead == (ssize_t)BlockSize()) 4894ac73018STyler Dauwalder { 4900d383564STyler Dauwalder udf_volume_structure_descriptor_header* descriptor = 4910d383564STyler Dauwalder reinterpret_cast<udf_volume_structure_descriptor_header*>(chunk.Data()); 4920d383564STyler Dauwalder if (descriptor->id_matches(kVSDID_ISO)) { 4934ac73018STyler Dauwalder SIMPLE_PRINT(("found ISO9660 descriptor\n")); 4944ac73018STyler Dauwalder foundISO = true; 4950d383564STyler Dauwalder } else if (descriptor->id_matches(kVSDID_BEA)) { 4964ac73018STyler Dauwalder SIMPLE_PRINT(("found BEA descriptor\n")); 4974ac73018STyler Dauwalder foundExtended = true; 4980d383564STyler Dauwalder } else if (descriptor->id_matches(kVSDID_TEA)) { 4994ac73018STyler Dauwalder SIMPLE_PRINT(("found TEA descriptor\n")); 5004ac73018STyler Dauwalder foundExtended = true; 5010d383564STyler Dauwalder } else if (descriptor->id_matches(kVSDID_ECMA167_2)) { 5024ac73018STyler Dauwalder SIMPLE_PRINT(("found ECMA-167 rev 2 descriptor\n")); 5034ac73018STyler Dauwalder foundECMA167 = true; 5040d383564STyler Dauwalder } else if (descriptor->id_matches(kVSDID_ECMA167_3)) { 5054ac73018STyler Dauwalder SIMPLE_PRINT(("found ECMA-167 rev 3 descriptor\n")); 5064ac73018STyler Dauwalder foundECMA167 = true; 5070d383564STyler Dauwalder } else if (descriptor->id_matches(kVSDID_BOOT)) { 5084ac73018STyler Dauwalder SIMPLE_PRINT(("found boot descriptor\n")); 5094ac73018STyler Dauwalder foundBoot = true; 5100d383564STyler Dauwalder } else if (descriptor->id_matches(kVSDID_ECMA168)) { 5114ac73018STyler Dauwalder SIMPLE_PRINT(("found ECMA-168 descriptor\n")); 5124ac73018STyler Dauwalder foundECMA168 = true; 5134ac73018STyler Dauwalder } else { 5140d383564STyler Dauwalder SIMPLE_PRINT(("found invalid descriptor, id = `%.5s'\n", descriptor->id)); 5154ac73018STyler Dauwalder break; 5164ac73018STyler Dauwalder } 5174ac73018STyler Dauwalder } else { 518bb182cf3STyler Dauwalder SIMPLE_PRINT(("read_pos(pos:%Ld, len:%ld) failed with: 0x%lx\n", address, 5194ac73018STyler Dauwalder BlockSize(), bytesRead)); 5204ac73018STyler Dauwalder break; 5214ac73018STyler Dauwalder } 5224ac73018STyler Dauwalder } 5234ac73018STyler Dauwalder 5244ac73018STyler Dauwalder // If we find an ECMA-167 descriptor, OR if we find a beginning 5254ac73018STyler Dauwalder // or terminating extended area descriptor with NO ECMA-168 5264ac73018STyler Dauwalder // descriptors, we return B_OK to signal that we should go 5274ac73018STyler Dauwalder // looking for valid anchors. 5284ac73018STyler Dauwalder err = foundECMA167 || (foundExtended && !foundECMA168) ? B_OK : B_ERROR; 5294ac73018STyler Dauwalder } 5304ac73018STyler Dauwalder 5314ac73018STyler Dauwalder RETURN(err); 5324ac73018STyler Dauwalder } 5334ac73018STyler Dauwalder 5344ac73018STyler Dauwalder status_t 5350d383564STyler Dauwalder Volume::_WalkAnchorVolumeDescriptorSequences() 5360d383564STyler Dauwalder { 5370d383564STyler Dauwalder DEBUG_INIT(CF_PRIVATE | CF_VOLUME_OPS, "Volume"); 5380d383564STyler Dauwalder const uint8 avds_location_count = 4; 5393fc7b565STyler Dauwalder const off_t avds_locations[avds_location_count] = { 5403fc7b565STyler Dauwalder 256, 5410d383564STyler Dauwalder Length()-256, 5420d383564STyler Dauwalder Length(), 5430d383564STyler Dauwalder 512, 5440d383564STyler Dauwalder }; 5450d383564STyler Dauwalder bool found_vds = false; 5460d383564STyler Dauwalder 5470d383564STyler Dauwalder for (int32 i = 0; i < avds_location_count; i++) { 5480d383564STyler Dauwalder off_t block = avds_locations[i]; 5490d383564STyler Dauwalder off_t address = AddressForRelativeBlock(block); 5500d383564STyler Dauwalder MemoryChunk chunk(BlockSize()); 5510d383564STyler Dauwalder udf_anchor_descriptor *anchor = NULL; 5520d383564STyler Dauwalder 5530d383564STyler Dauwalder status_t anchorErr = chunk.InitCheck(); 5540d383564STyler Dauwalder if (!anchorErr) { 5550d383564STyler Dauwalder ssize_t bytesRead = read_pos(fDevice, address, chunk.Data(), BlockSize()); 5560d383564STyler Dauwalder anchorErr = bytesRead == (ssize_t)BlockSize() ? B_OK : B_IO_ERROR; 5570d383564STyler Dauwalder if (anchorErr) { 558bb182cf3STyler Dauwalder PRINT(("block %Ld: read_pos(pos:%Ld, len:%ld) failed with error 0x%lx\n", 5590d383564STyler Dauwalder block, address, BlockSize(), bytesRead)); 5600d383564STyler Dauwalder } 5610d383564STyler Dauwalder } 5620d383564STyler Dauwalder if (!anchorErr) { 5630d383564STyler Dauwalder anchor = reinterpret_cast<udf_anchor_descriptor*>(chunk.Data()); 564bb182cf3STyler Dauwalder anchorErr = anchor->tag().init_check(block+Offset()); 5650d383564STyler Dauwalder if (anchorErr) { 566bb182cf3STyler Dauwalder PRINT(("block %Ld: invalid anchor\n", block)); 5670d383564STyler Dauwalder } else { 568bb182cf3STyler Dauwalder PRINT(("block %Ld: valid anchor\n", block)); 5690d383564STyler Dauwalder } 5700d383564STyler Dauwalder } 5710d383564STyler Dauwalder if (!anchorErr) { 572bb182cf3STyler Dauwalder PRINT(("block %Ld: anchor:\n", block)); 5730d383564STyler Dauwalder PDUMP(anchor); 5740d383564STyler Dauwalder // Found an avds, so try the main sequence first, then 5750d383564STyler Dauwalder // the reserve sequence if the main one fails. 5760d383564STyler Dauwalder anchorErr = _WalkVolumeDescriptorSequence(anchor->main_vds()); 5770d383564STyler Dauwalder if (anchorErr) 5780d383564STyler Dauwalder anchorErr = _WalkVolumeDescriptorSequence(anchor->reserve_vds()); 5790d383564STyler Dauwalder 5800d383564STyler Dauwalder 5810d383564STyler Dauwalder } 5820d383564STyler Dauwalder if (!anchorErr) { 583bb182cf3STyler Dauwalder PRINT(("block %Ld: found valid vds\n", avds_locations[i])); 5840d383564STyler Dauwalder found_vds = true; 5850d383564STyler Dauwalder break; 5860d383564STyler Dauwalder } //else { 5870d383564STyler Dauwalder // Both failed, so loop around and try another avds 588bb182cf3STyler Dauwalder // PRINT(("block %Ld: vds search failed\n", avds_locations[i])); 5890d383564STyler Dauwalder // } 5900d383564STyler Dauwalder } 5910d383564STyler Dauwalder status_t err = found_vds ? B_OK : B_ERROR; 5920d383564STyler Dauwalder RETURN(err); 5930d383564STyler Dauwalder } 5940d383564STyler Dauwalder 5950d383564STyler Dauwalder status_t 5960d383564STyler Dauwalder Volume::_WalkVolumeDescriptorSequence(udf_extent_address extent) 5974ac73018STyler Dauwalder { 598565457fdSTyler Dauwalder DEBUG_INIT_ETC(CF_PRIVATE | CF_VOLUME_OPS, "Volume", ("loc:%ld, len:%ld", 599565457fdSTyler Dauwalder extent.location(), extent.length())); 600565457fdSTyler Dauwalder uint32 count = extent.length()/BlockSize(); 6010d383564STyler Dauwalder 6020d383564STyler Dauwalder bool foundLogicalVD = false; 6030d383564STyler Dauwalder 604565457fdSTyler Dauwalder for (uint32 i = 0; i < count; i++) 605565457fdSTyler Dauwalder { 606565457fdSTyler Dauwalder off_t block = extent.location()+i; 607bb182cf3STyler Dauwalder off_t address = block << BlockShift(); //AddressForRelativeBlock(block); 6080d383564STyler Dauwalder MemoryChunk chunk(BlockSize()); 6090d383564STyler Dauwalder udf_tag *tag = NULL; 6100d383564STyler Dauwalder 611bb182cf3STyler Dauwalder PRINT(("descriptor #%ld (block %Ld):\n", i, block)); 6120d383564STyler Dauwalder 6130d383564STyler Dauwalder status_t err = chunk.InitCheck(); 614565457fdSTyler Dauwalder if (!err) { 6150d383564STyler Dauwalder ssize_t bytesRead = read_pos(fDevice, address, chunk.Data(), BlockSize()); 616565457fdSTyler Dauwalder err = bytesRead == (ssize_t)BlockSize() ? B_OK : B_IO_ERROR; 617565457fdSTyler Dauwalder if (err) { 618bb182cf3STyler Dauwalder PRINT(("block %Ld: read_pos(pos:%Ld, len:%ld) failed with error 0x%lx\n", 619565457fdSTyler Dauwalder block, address, BlockSize(), bytesRead)); 620565457fdSTyler Dauwalder } 621565457fdSTyler Dauwalder } 622565457fdSTyler Dauwalder if (!err) { 6230d383564STyler Dauwalder tag = reinterpret_cast<udf_tag*>(chunk.Data()); 6240d383564STyler Dauwalder err = tag->init_check(block); 6250d383564STyler Dauwalder } 6260d383564STyler Dauwalder if (!err) { 6270d383564STyler Dauwalder // Now decide what type of descriptor we have 6280d383564STyler Dauwalder switch (tag->id()) { 6290d383564STyler Dauwalder case TAGID_UNDEFINED: 6300d383564STyler Dauwalder break; 6310d383564STyler Dauwalder 6320d383564STyler Dauwalder case TAGID_PRIMARY_VOLUME_DESCRIPTOR: 6330d383564STyler Dauwalder { 6340d383564STyler Dauwalder udf_primary_descriptor *primary = reinterpret_cast<udf_primary_descriptor*>(tag); 6350d383564STyler Dauwalder PDUMP(primary); 6360d383564STyler Dauwalder break; 6370d383564STyler Dauwalder } 6380d383564STyler Dauwalder 6390d383564STyler Dauwalder case TAGID_ANCHOR_VOLUME_DESCRIPTOR_POINTER: 6400d383564STyler Dauwalder break; 6410d383564STyler Dauwalder 6420d383564STyler Dauwalder case TAGID_VOLUME_DESCRIPTOR_POINTER: 6430d383564STyler Dauwalder break; 6440d383564STyler Dauwalder 6450d383564STyler Dauwalder case TAGID_IMPLEMENTATION_USE_VOLUME_DESCRIPTOR: 6460d383564STyler Dauwalder { 6470d383564STyler Dauwalder udf_implementation_use_descriptor *imp_use = reinterpret_cast<udf_implementation_use_descriptor*>(tag); 6480d383564STyler Dauwalder PDUMP(imp_use); 6490d383564STyler Dauwalder break; 6500d383564STyler Dauwalder } 6510d383564STyler Dauwalder 6520d383564STyler Dauwalder case TAGID_PARTITION_DESCRIPTOR: 6530d383564STyler Dauwalder { 6540d383564STyler Dauwalder udf_partition_descriptor *partition = reinterpret_cast<udf_partition_descriptor*>(tag); 6550d383564STyler Dauwalder PDUMP(partition); 6560d383564STyler Dauwalder if (partition->tag().init_check(block) == B_OK) { 657b4bfabdeSTyler Dauwalder const udf_partition_descriptor *current = fPartitionMap.Find(partition->partition_number()); 6580d383564STyler Dauwalder if (!current || current->vds_number() < partition->vds_number()) { 6590d383564STyler Dauwalder PRINT(("adding partition #%d with vds_number %ld to partition map\n", 6600d383564STyler Dauwalder partition->partition_number(), partition->vds_number())); 6610d383564STyler Dauwalder fPartitionMap.Add(partition); 6620d383564STyler Dauwalder } 6630d383564STyler Dauwalder } 6640d383564STyler Dauwalder break; 6650d383564STyler Dauwalder } 6660d383564STyler Dauwalder 6670d383564STyler Dauwalder case TAGID_LOGICAL_VOLUME_DESCRIPTOR: 6680d383564STyler Dauwalder { 6690d383564STyler Dauwalder udf_logical_descriptor *logical = reinterpret_cast<udf_logical_descriptor*>(tag); 6700d383564STyler Dauwalder PDUMP(logical); 6710d383564STyler Dauwalder if (foundLogicalVD) { 6720d383564STyler Dauwalder // Keep the vd with the highest vds_number 673*21c162a3STyler Dauwalder if (logical->vds_number() > fLogicalVolumeDescriptor.vds_number()) 674*21c162a3STyler Dauwalder fLogicalVolumeDescriptor = *(logical); 675565457fdSTyler Dauwalder } else { 676*21c162a3STyler Dauwalder fLogicalVolumeDescriptor = *(logical); 6770d383564STyler Dauwalder foundLogicalVD = true; 6780d383564STyler Dauwalder } 6790d383564STyler Dauwalder break; 6800d383564STyler Dauwalder } 6810d383564STyler Dauwalder 6820d383564STyler Dauwalder case TAGID_UNALLOCATED_SPACE_DESCRIPTOR: 6830d383564STyler Dauwalder { 6840d383564STyler Dauwalder udf_unallocated_space_descriptor *unallocated = reinterpret_cast<udf_unallocated_space_descriptor*>(tag); 6850d383564STyler Dauwalder PDUMP(unallocated); 6860d383564STyler Dauwalder break; 6870d383564STyler Dauwalder } 6880d383564STyler Dauwalder 6890d383564STyler Dauwalder case TAGID_TERMINATING_DESCRIPTOR: 6900d383564STyler Dauwalder { 6910d383564STyler Dauwalder udf_terminating_descriptor *terminating = reinterpret_cast<udf_terminating_descriptor*>(tag); 6920d383564STyler Dauwalder PDUMP(terminating); 6930d383564STyler Dauwalder break; 6940d383564STyler Dauwalder } 6950d383564STyler Dauwalder 6960d383564STyler Dauwalder case TAGID_LOGICAL_VOLUME_INTEGRITY_DESCRIPTOR: 6970d383564STyler Dauwalder // Not found in this descriptor sequence 6980d383564STyler Dauwalder break; 6990d383564STyler Dauwalder 7000d383564STyler Dauwalder default: 7010d383564STyler Dauwalder break; 7020d383564STyler Dauwalder 703565457fdSTyler Dauwalder } 704565457fdSTyler Dauwalder } 705565457fdSTyler Dauwalder } 7064ac73018STyler Dauwalder 7070d383564STyler Dauwalder status_t err = foundLogicalVD ? B_OK : B_ERROR; 7080d383564STyler Dauwalder if (!err) { 7090d383564STyler Dauwalder PRINT(("partition map:\n")); 7100d383564STyler Dauwalder DUMP(fPartitionMap); 7110d383564STyler Dauwalder } 7120d383564STyler Dauwalder RETURN(err); 71329008bcfSTyler Dauwalder } 71429008bcfSTyler Dauwalder 7150d383564STyler Dauwalder status_t 7160d383564STyler Dauwalder Volume::_InitFileSetDescriptor() 7170d383564STyler Dauwalder { 7180d383564STyler Dauwalder DEBUG_INIT(CF_PRIVATE | CF_VOLUME_OPS, "Volume"); 719*21c162a3STyler Dauwalder MemoryChunk chunk(fLogicalVolumeDescriptor.file_set_address().length()); 7200d383564STyler Dauwalder 7210d383564STyler Dauwalder status_t err = chunk.InitCheck(); 72262426f64STyler Dauwalder 72362426f64STyler Dauwalder #if (!DRIVE_SETUP_ADDON) 7240d383564STyler Dauwalder if (!err) { 725*21c162a3STyler Dauwalder // err = Read(ad, fLogicalVolumeDescriptor.file_set_address().length(), chunk.Data()); 726*21c162a3STyler Dauwalder err = Read(fLogicalVolumeDescriptor.file_set_address(), fLogicalVolumeDescriptor.file_set_address().length(), chunk.Data()); 7273f4628f1STyler Dauwalder if (!err) { 7283f4628f1STyler Dauwalder udf_file_set_descriptor *fileSet = reinterpret_cast<udf_file_set_descriptor*>(chunk.Data()); 7290d383564STyler Dauwalder fileSet->tag().init_check(0); 7300d383564STyler Dauwalder PDUMP(fileSet); 7313f4628f1STyler Dauwalder fRootIcb = new Icb(this, fileSet->root_directory_icb()); 7323f4628f1STyler Dauwalder err = fRootIcb ? fRootIcb->InitCheck() : B_NO_MEMORY; 7330d383564STyler Dauwalder } 7340d383564STyler Dauwalder } 73562426f64STyler Dauwalder #endif 7363f4628f1STyler Dauwalder 7373f4628f1STyler Dauwalder RETURN(err); 7383f4628f1STyler Dauwalder } 7393f4628f1STyler Dauwalder 740