1e1f5f06bSSalvatore Benedetto /* 2*c530d46cSJérôme Duval * Copyright 2012, Jérôme Duval, korli@users.berlios.de. 3e1f5f06bSSalvatore Benedetto * Copyright 2008, Salvatore Benedetto, salvatore.benedetto@gmail.com 4e1f5f06bSSalvatore Benedetto * Copyright 2003, Tyler Dauwalder, tyler@dauwalder.net. 5e1f5f06bSSalvatore Benedetto * Distributed under the terms of the MIT License. 6e1f5f06bSSalvatore Benedetto */ 7e1f5f06bSSalvatore Benedetto 829008bcfSTyler Dauwalder #include "Volume.h" 929008bcfSTyler Dauwalder 103f4628f1STyler Dauwalder #include "Icb.h" 110d383564STyler Dauwalder #include "MemoryChunk.h" 12*c530d46cSJérôme Duval #include "MetadataPartition.h" 13d4e8b936STyler Dauwalder #include "PhysicalPartition.h" 1421c162a3STyler Dauwalder #include "Recognition.h" 1529008bcfSTyler Dauwalder 16e0c80398SSalvatore Benedetto extern fs_volume_ops gUDFVolumeOps; 17e0c80398SSalvatore Benedetto extern fs_vnode_ops gUDFVnodeOps; 1829008bcfSTyler Dauwalder 19e1f5f06bSSalvatore Benedetto /*! \brief Creates an unmounted volume with the given id. */ 20e1f5f06bSSalvatore Benedetto Volume::Volume(fs_volume *fsVolume) 21e1f5f06bSSalvatore Benedetto : 22e1f5f06bSSalvatore Benedetto fBlockCache(NULL), 23e1f5f06bSSalvatore Benedetto fBlockShift(0), 24e1f5f06bSSalvatore Benedetto fBlockSize(0), 25e1f5f06bSSalvatore Benedetto fDevice(-1), 26e1f5f06bSSalvatore Benedetto fFSVolume(fsVolume), 27e1f5f06bSSalvatore Benedetto fLength(0), 28e1f5f06bSSalvatore Benedetto fMounted(false), 29e1f5f06bSSalvatore Benedetto fOffset(0), 30e1f5f06bSSalvatore Benedetto fRootIcb(NULL) 3129008bcfSTyler Dauwalder { 3221c162a3STyler Dauwalder for (int i = 0; i < UDF_MAX_PARTITION_MAPS; i++) 3321c162a3STyler Dauwalder fPartitions[i] = NULL; 3429008bcfSTyler Dauwalder } 3529008bcfSTyler Dauwalder 360c342879SSalvatore Benedetto 37d4e8b936STyler Dauwalder Volume::~Volume() 3829008bcfSTyler Dauwalder { 39d4e8b936STyler Dauwalder _Unset(); 4029008bcfSTyler Dauwalder } 4129008bcfSTyler Dauwalder 420c342879SSalvatore Benedetto 4329008bcfSTyler Dauwalder /*! \brief Attempts to mount the given device. 443f4628f1STyler Dauwalder 459fd15595SSalvatore Benedetto \param lenght The length of the device in number of blocks 4629008bcfSTyler Dauwalder */ 4729008bcfSTyler Dauwalder status_t 480c342879SSalvatore Benedetto Volume::Mount(const char *deviceName, off_t offset, off_t length, 4921c162a3STyler Dauwalder uint32 blockSize, uint32 flags) 5021c162a3STyler Dauwalder { 510c342879SSalvatore Benedetto TRACE(("Volume::Mount: deviceName = `%s', offset = %Ld, length = %Ld, " 520c342879SSalvatore Benedetto "blockSize: %ld, flags: %ld\n", deviceName, offset, length, blockSize, 530c342879SSalvatore Benedetto flags)); 5421c162a3STyler Dauwalder if (!deviceName) 550c342879SSalvatore Benedetto return B_BAD_VALUE; 560c342879SSalvatore Benedetto if (Mounted()) 5721c162a3STyler Dauwalder // Already mounted, thank you for asking 580c342879SSalvatore Benedetto return B_BUSY; 5921c162a3STyler Dauwalder 6021c162a3STyler Dauwalder // Open the device read only 6121c162a3STyler Dauwalder int device = open(deviceName, O_RDONLY); 620c342879SSalvatore Benedetto if (device < B_OK) { 630c342879SSalvatore Benedetto TRACE_ERROR(("Volume::Mount: failed to open device = %s\n", deviceName)); 640c342879SSalvatore Benedetto return device; 650c342879SSalvatore Benedetto } 6621c162a3STyler Dauwalder 67*c530d46cSJérôme Duval DEBUG_INIT_ETC("Volume", ("deviceName: %s", deviceName)); 680c342879SSalvatore Benedetto status_t status = B_OK; 6921c162a3STyler Dauwalder 7021c162a3STyler Dauwalder // If the device is actually a normal file, try to disable the cache 7121c162a3STyler Dauwalder // for the file in the parent filesystem 72e1f5f06bSSalvatore Benedetto #if 0 // _KERNEL_MODE 7321c162a3STyler Dauwalder struct stat stat; 7421c162a3STyler Dauwalder error = fstat(device, &stat) < 0 ? B_ERROR : B_OK; 7521c162a3STyler Dauwalder if (!error) { 7621c162a3STyler Dauwalder if (stat.st_mode & S_IFREG && ioctl(device, IOCTL_FILE_UNCACHED_IO, NULL) < 0) { 7721c162a3STyler Dauwalder DIE(("Unable to disable cache of underlying file system.\n")); 7821c162a3STyler Dauwalder } 7921c162a3STyler Dauwalder } 80e376a854STyler Dauwalder #endif 8121c162a3STyler Dauwalder 829b8775eaSTyler Dauwalder logical_volume_descriptor logicalVolumeDescriptor; 83e1f5f06bSSalvatore Benedetto partition_descriptor partitionDescriptors[kMaxPartitionDescriptors]; 8421c162a3STyler Dauwalder uint8 partitionDescriptorCount; 8521c162a3STyler Dauwalder uint32 blockShift; 8621c162a3STyler Dauwalder 871379cacaSTyler Dauwalder // Run through the volume recognition and descriptor sequences to 881379cacaSTyler Dauwalder // see if we have a potentially valid UDF volume on our hands 890c342879SSalvatore Benedetto status = udf_recognize(device, offset, length, blockSize, blockShift, 90*c530d46cSJérôme Duval fPrimaryVolumeDescriptor, logicalVolumeDescriptor, 91*c530d46cSJérôme Duval partitionDescriptors, partitionDescriptorCount); 9221c162a3STyler Dauwalder 9321c162a3STyler Dauwalder // Set up the block cache 94e0c80398SSalvatore Benedetto if (!status) { 95e0c80398SSalvatore Benedetto TRACE(("Volume::Mount: partition recognized\n")); 960c342879SSalvatore Benedetto fBlockCache = block_cache_create(device, length, blockSize, IsReadOnly()); 97e0c80398SSalvatore Benedetto } else { 980c342879SSalvatore Benedetto TRACE_ERROR(("Volume::Mount: failed to recognize partition\n")); 990c342879SSalvatore Benedetto return status; 1000c342879SSalvatore Benedetto } 10121c162a3STyler Dauwalder 102d4e8b936STyler Dauwalder int physicalCount = 0; 103d4e8b936STyler Dauwalder int virtualCount = 0; 104d4e8b936STyler Dauwalder int sparableCount = 0; 105d4e8b936STyler Dauwalder int metadataCount = 0; 106d4e8b936STyler Dauwalder 10721c162a3STyler Dauwalder // Set up the partitions 10821c162a3STyler Dauwalder // Set up physical and sparable partitions first 109e0c80398SSalvatore Benedetto offset = 0; 110d4e8b936STyler Dauwalder for (uint8 i = 0; i < logicalVolumeDescriptor.partition_map_count() 1110c342879SSalvatore Benedetto && !status; i++) 112d4e8b936STyler Dauwalder { 11321c162a3STyler Dauwalder uint8 *maps = logicalVolumeDescriptor.partition_maps(); 114e0c80398SSalvatore Benedetto partition_map_header *header = (partition_map_header *)(maps + offset); 115e0c80398SSalvatore Benedetto TRACE(("Volume::Mount: partition map %d (type %d):\n", i, 116e0c80398SSalvatore Benedetto header->type())); 11721c162a3STyler Dauwalder if (header->type() == 1) { 118e0c80398SSalvatore Benedetto TRACE(("Volume::Mount: map type -> physical\n")); 119e0c80398SSalvatore Benedetto physical_partition_map* map = (physical_partition_map *)header; 120d4e8b936STyler Dauwalder // Find the corresponding partition descriptor 1211379cacaSTyler Dauwalder partition_descriptor *descriptor = NULL; 122d4e8b936STyler Dauwalder for (uint8 j = 0; j < partitionDescriptorCount; j++) { 123d4e8b936STyler Dauwalder if (map->partition_number() == 124e0c80398SSalvatore Benedetto partitionDescriptors[j].partition_number()) { 125d4e8b936STyler Dauwalder descriptor = &partitionDescriptors[j]; 126d4e8b936STyler Dauwalder break; 127d4e8b936STyler Dauwalder } 128d4e8b936STyler Dauwalder } 129d4e8b936STyler Dauwalder // Create and add the partition 130d4e8b936STyler Dauwalder if (descriptor) { 131e0c80398SSalvatore Benedetto PhysicalPartition *partition 132e0c80398SSalvatore Benedetto = new(nothrow) PhysicalPartition(map->partition_number(), 133e0c80398SSalvatore Benedetto descriptor->start(), descriptor->length()); 1340c342879SSalvatore Benedetto status = partition ? B_OK : B_NO_MEMORY; 1350c342879SSalvatore Benedetto if (!status) { 136e0c80398SSalvatore Benedetto TRACE(("Volume::Mount: adding PhysicalPartition(number: %d, " 137e0c80398SSalvatore Benedetto "start: %ld, length: %ld)\n", map->partition_number(), 138d4e8b936STyler Dauwalder descriptor->start(), descriptor->length())); 1390c342879SSalvatore Benedetto status = _SetPartition(i, partition); 1400c342879SSalvatore Benedetto if (!status) 141d4e8b936STyler Dauwalder physicalCount++; 142d4e8b936STyler Dauwalder } 14321c162a3STyler Dauwalder } else { 14489264fe4SSalvatore Benedetto TRACE_ERROR(("Volume::Mount: no matching partition descriptor found!\n")); 1450c342879SSalvatore Benedetto status = B_ERROR; 146d4e8b936STyler Dauwalder } 147d4e8b936STyler Dauwalder } else if (header->type() == 2) { 1481379cacaSTyler Dauwalder // Figure out what kind of type 2 partition map we have based 149d4e8b936STyler Dauwalder // on the type identifier 1501379cacaSTyler Dauwalder const entity_id &typeId = header->partition_type_id(); 151d4e8b936STyler Dauwalder DUMP(typeId); 152d4e8b936STyler Dauwalder DUMP(kSparablePartitionMapId); 153d4e8b936STyler Dauwalder if (typeId.matches(kVirtualPartitionMapId)) { 1540c342879SSalvatore Benedetto TRACE(("map type: virtual\n")); 1551379cacaSTyler Dauwalder virtual_partition_map* map = 1561379cacaSTyler Dauwalder reinterpret_cast<virtual_partition_map*>(header); 157d4e8b936STyler Dauwalder virtualCount++; 158d4e8b936STyler Dauwalder (void)map; // kill the warning for now 159d4e8b936STyler Dauwalder } else if (typeId.matches(kSparablePartitionMapId)) { 1600c342879SSalvatore Benedetto TRACE(("map type: sparable\n")); 1611379cacaSTyler Dauwalder sparable_partition_map* map = 1621379cacaSTyler Dauwalder reinterpret_cast<sparable_partition_map*>(header); 163d4e8b936STyler Dauwalder sparableCount++; 164d4e8b936STyler Dauwalder (void)map; // kill the warning for now 165d4e8b936STyler Dauwalder } else if (typeId.matches(kMetadataPartitionMapId)) { 1660c342879SSalvatore Benedetto TRACE(("map type: metadata\n")); 1671379cacaSTyler Dauwalder metadata_partition_map* map = 1681379cacaSTyler Dauwalder reinterpret_cast<metadata_partition_map*>(header); 169*c530d46cSJérôme Duval 170*c530d46cSJérôme Duval 171*c530d46cSJérôme Duval // Find the corresponding partition descriptor 172*c530d46cSJérôme Duval partition_descriptor *descriptor = NULL; 173*c530d46cSJérôme Duval for (uint8 j = 0; j < partitionDescriptorCount; j++) { 174*c530d46cSJérôme Duval if (map->partition_number() == 175*c530d46cSJérôme Duval partitionDescriptors[j].partition_number()) { 176*c530d46cSJérôme Duval descriptor = &partitionDescriptors[j]; 177*c530d46cSJérôme Duval break; 178*c530d46cSJérôme Duval } 179*c530d46cSJérôme Duval } 180*c530d46cSJérôme Duval Partition *parent = _GetPartition(map->partition_number()); 181*c530d46cSJérôme Duval // Create and add the partition 182*c530d46cSJérôme Duval if (descriptor != NULL && parent != NULL) { 183*c530d46cSJérôme Duval MetadataPartition *partition 184*c530d46cSJérôme Duval = new(nothrow) MetadataPartition(this, 185*c530d46cSJérôme Duval map->partition_number(), *parent, 186*c530d46cSJérôme Duval map->metadata_file_location(), 187*c530d46cSJérôme Duval map->metadata_mirror_file_location(), 188*c530d46cSJérôme Duval map->metadata_bitmap_file_location(), 189*c530d46cSJérôme Duval map->allocation_unit_size(), 190*c530d46cSJérôme Duval map->alignment_unit_size(), 191*c530d46cSJérôme Duval map->flags() & 1); 192*c530d46cSJérôme Duval status = partition ? partition->InitCheck() : B_NO_MEMORY; 193*c530d46cSJérôme Duval if (!status) { 194*c530d46cSJérôme Duval TRACE(("Volume::Mount: adding MetadataPartition()")); 195*c530d46cSJérôme Duval status = _SetPartition(i, partition); 196*c530d46cSJérôme Duval if (status == B_OK) 197d4e8b936STyler Dauwalder metadataCount++; 198*c530d46cSJérôme Duval } else { 199*c530d46cSJérôme Duval TRACE_ERROR(("Volume::Mount: metadata partition " 200*c530d46cSJérôme Duval "creation failed! 0x%lx\n", status)); 201*c530d46cSJérôme Duval } 202*c530d46cSJérôme Duval } else { 203*c530d46cSJérôme Duval TRACE_ERROR(("Volume::Mount: no matching partition descriptor found!\n")); 204*c530d46cSJérôme Duval status = B_ERROR; 205*c530d46cSJérôme Duval } 206d4e8b936STyler Dauwalder } else { 2070c342879SSalvatore Benedetto TRACE(("map type: unrecognized (`%.23s')\n", 208d4e8b936STyler Dauwalder typeId.identifier())); 2090c342879SSalvatore Benedetto status = B_ERROR; 21021c162a3STyler Dauwalder } 211d4e8b936STyler Dauwalder } else { 2120c342879SSalvatore Benedetto TRACE(("Invalid partition type %d found!\n", header->type())); 2130c342879SSalvatore Benedetto status = B_ERROR; 214d4e8b936STyler Dauwalder } 21521c162a3STyler Dauwalder offset += header->length(); 21621c162a3STyler Dauwalder } 21721c162a3STyler Dauwalder 218d4e8b936STyler Dauwalder // Do some checking as to what sorts of partitions we've actually found. 2190c342879SSalvatore Benedetto if (!status) { 2200c342879SSalvatore Benedetto status = (physicalCount == 1 && virtualCount == 0 221*c530d46cSJérôme Duval && sparableCount == 0) 222d4e8b936STyler Dauwalder || (physicalCount == 2 && virtualCount == 0 223*c530d46cSJérôme Duval && sparableCount == 0) 224d4e8b936STyler Dauwalder ? B_OK : B_ERROR; 2250c342879SSalvatore Benedetto if (status) { 2260c342879SSalvatore Benedetto TRACE(("Invalid partition layout found:\n")); 2270c342879SSalvatore Benedetto TRACE((" physical partitions: %d\n", physicalCount)); 2280c342879SSalvatore Benedetto TRACE((" virtual partitions: %d\n", virtualCount)); 2290c342879SSalvatore Benedetto TRACE((" sparable partitions: %d\n", sparableCount)); 2300c342879SSalvatore Benedetto TRACE((" metadata partitions: %d\n", metadataCount)); 231d4e8b936STyler Dauwalder } 232d4e8b936STyler Dauwalder } 233d4e8b936STyler Dauwalder 234d4e8b936STyler Dauwalder // We're now going to start creating Icb's, which will expect 235d4e8b936STyler Dauwalder // certain parts of the volume to be initialized properly. Thus, 236d4e8b936STyler Dauwalder // we initialize those parts here. 2370c342879SSalvatore Benedetto if (!status) { 238d4e8b936STyler Dauwalder fDevice = device; 239d4e8b936STyler Dauwalder fOffset = offset; 2400c342879SSalvatore Benedetto fLength = length; 241d4e8b936STyler Dauwalder fBlockSize = blockSize; 242d4e8b936STyler Dauwalder fBlockShift = blockShift; 243d4e8b936STyler Dauwalder } 24420d84995SRene Gollent TRACE(("Volume::Mount: device = %d, offset = %Ld, length = %Ld, " 24520d84995SRene Gollent "blockSize = %ld, blockShift = %ld\n", device, offset, length, 24689264fe4SSalvatore Benedetto blockSize, blockShift)); 247d4e8b936STyler Dauwalder // At this point we've found a valid set of volume descriptors and 248d4e8b936STyler Dauwalder // our partitions are all set up. We now need to investigate the file 249d4e8b936STyler Dauwalder // set descriptor pointed to by the logical volume descriptor. 2500c342879SSalvatore Benedetto if (!status) { 251e0c80398SSalvatore Benedetto TRACE(("Volume::Mount: Partition has been set up\n")); 252d4e8b936STyler Dauwalder MemoryChunk chunk(logicalVolumeDescriptor.file_set_address().length()); 25321c162a3STyler Dauwalder 2540c342879SSalvatore Benedetto status = chunk.InitCheck(); 25521c162a3STyler Dauwalder 2560c342879SSalvatore Benedetto if (!status) { 257d4e8b936STyler Dauwalder off_t address; 258d4e8b936STyler Dauwalder // Read in the file set descriptor 2590c342879SSalvatore Benedetto status = MapBlock(logicalVolumeDescriptor.file_set_address(), 260d4e8b936STyler Dauwalder &address); 2610c342879SSalvatore Benedetto if (!status) 262d4e8b936STyler Dauwalder address <<= blockShift; 2630c342879SSalvatore Benedetto if (!status) { 264e0c80398SSalvatore Benedetto ssize_t bytesRead 265e0c80398SSalvatore Benedetto = read_pos(device, address, chunk.Data(), blockSize); 266d8b4553aSTyler Dauwalder if (bytesRead != ssize_t(blockSize)) { 2670c342879SSalvatore Benedetto status = B_IO_ERROR; 268e0c80398SSalvatore Benedetto TRACE_ERROR(("read_pos(pos:%Ld, len:%ld) failed with: 0x%lx\n", 269d4e8b936STyler Dauwalder address, blockSize, bytesRead)); 270d4e8b936STyler Dauwalder } 271d4e8b936STyler Dauwalder } 272d4e8b936STyler Dauwalder // See if it's valid, and if so, create the root icb 2730c342879SSalvatore Benedetto if (!status) { 2741379cacaSTyler Dauwalder file_set_descriptor *fileSet = 2751379cacaSTyler Dauwalder reinterpret_cast<file_set_descriptor*>(chunk.Data()); 27617b66e62STyler Dauwalder PDUMP(fileSet); 2770c342879SSalvatore Benedetto status = fileSet->tag().id() == TAGID_FILE_SET_DESCRIPTOR 278d8b4553aSTyler Dauwalder ? B_OK : B_ERROR; 2790c342879SSalvatore Benedetto if (!status) 2800c342879SSalvatore Benedetto status = fileSet->tag().init_check( 28117b66e62STyler Dauwalder logicalVolumeDescriptor.file_set_address().block()); 2820c342879SSalvatore Benedetto if (!status) { 28321c162a3STyler Dauwalder PDUMP(fileSet); 284f50008f9STyler Dauwalder fRootIcb = new(nothrow) Icb(this, fileSet->root_directory_icb()); 285e0c80398SSalvatore Benedetto if (fRootIcb == NULL || fRootIcb->InitCheck() != B_OK) 286e0c80398SSalvatore Benedetto return B_NO_MEMORY; 287d8b4553aSTyler Dauwalder } 288e0c80398SSalvatore Benedetto 28920d84995SRene Gollent TRACE(("Volume::Mount: Root Node id = %Ld\n", fRootIcb->Id())); 2900c342879SSalvatore Benedetto if (!status) { 291e0c80398SSalvatore Benedetto status = publish_vnode(fFSVolume, fRootIcb->Id(), fRootIcb, 292e0c80398SSalvatore Benedetto &gUDFVnodeOps, fRootIcb->Mode(), 0); 293e0c80398SSalvatore Benedetto if (status != B_OK) { 294e0c80398SSalvatore Benedetto TRACE_ERROR(("Error creating vnode for root icb! " 2950c342879SSalvatore Benedetto "status = 0x%lx, `%s'\n", status, 2960c342879SSalvatore Benedetto strerror(status))); 297d4e8b936STyler Dauwalder // Clean up the icb we created, since _Unset() 298d4e8b936STyler Dauwalder // won't do this for us. 299d4e8b936STyler Dauwalder delete fRootIcb; 300d4e8b936STyler Dauwalder fRootIcb = NULL; 301d4e8b936STyler Dauwalder } 30220d84995SRene Gollent TRACE(("Volume::Mount: Root vnode published. Id = %Ld\n", 303e0c80398SSalvatore Benedetto fRootIcb->Id())); 304d4e8b936STyler Dauwalder } 305d4e8b936STyler Dauwalder } 30621c162a3STyler Dauwalder } 30721c162a3STyler Dauwalder } 30821c162a3STyler Dauwalder 309d4e8b936STyler Dauwalder // If we've made it this far, we're good to go; set the volume 310d4e8b936STyler Dauwalder // name and then flag that we're mounted. On the other hand, if 311d4e8b936STyler Dauwalder // an error occurred, we need to clean things up. 3120c342879SSalvatore Benedetto if (!status) { 313d4e8b936STyler Dauwalder fName.SetTo(logicalVolumeDescriptor.logical_volume_identifier()); 314d4e8b936STyler Dauwalder fMounted = true; 315d4e8b936STyler Dauwalder } else { 316d4e8b936STyler Dauwalder _Unset(); 31721c162a3STyler Dauwalder } 31821c162a3STyler Dauwalder 3190c342879SSalvatore Benedetto RETURN(status); 3204ac73018STyler Dauwalder } 3214ac73018STyler Dauwalder 3229fd15595SSalvatore Benedetto 323a71fd512STyler Dauwalder const char* 324a71fd512STyler Dauwalder Volume::Name() const { 325dce2dc5cSTyler Dauwalder return fName.Utf8(); 326a71fd512STyler Dauwalder } 3273f4628f1STyler Dauwalder 328d4e8b936STyler Dauwalder /*! \brief Maps the given logical block to a physical block. 3293f4628f1STyler Dauwalder */ 3303f4628f1STyler Dauwalder status_t 3311379cacaSTyler Dauwalder Volume::MapBlock(long_address address, off_t *mappedBlock) 3320d383564STyler Dauwalder { 333e0c80398SSalvatore Benedetto TRACE(("Volume::MapBlock: partition = %d, block = %ld, mappedBlock = %p\n", 3341379cacaSTyler Dauwalder address.partition(), address.block(), mappedBlock)); 335*c530d46cSJérôme Duval DEBUG_INIT_ETC("Volume", ("partition = %d, block = %ld, mappedBlock = %p", 336*c530d46cSJérôme Duval address.partition(), address.block(), mappedBlock)); 337d4e8b936STyler Dauwalder status_t error = mappedBlock ? B_OK : B_BAD_VALUE; 338d4e8b936STyler Dauwalder if (!error) { 339d4e8b936STyler Dauwalder Partition *partition = _GetPartition(address.partition()); 340d4e8b936STyler Dauwalder error = partition ? B_OK : B_BAD_ADDRESS; 341d4e8b936STyler Dauwalder if (!error) 342d4e8b936STyler Dauwalder error = partition->MapBlock(address.block(), *mappedBlock); 3433f4628f1STyler Dauwalder } 344d4e8b936STyler Dauwalder RETURN(error); 3453f4628f1STyler Dauwalder } 3463f4628f1STyler Dauwalder 347d4e8b936STyler Dauwalder /*! \brief Unsets the volume and deletes any partitions. 348d4e8b936STyler Dauwalder 349d4e8b936STyler Dauwalder Does *not* delete the root icb object. 350d4e8b936STyler Dauwalder */ 351d4e8b936STyler Dauwalder void 352d4e8b936STyler Dauwalder Volume::_Unset() 353d4e8b936STyler Dauwalder { 354d8b4553aSTyler Dauwalder DEBUG_INIT("Volume"); 355e1f5f06bSSalvatore Benedetto fFSVolume->id = 0; 356bb4462fdSTyler Dauwalder if (fDevice >= 0) { 357e1f5f06bSSalvatore Benedetto block_cache_delete(fBlockCache, true); 358237ced11STyler Dauwalder close(fDevice); 359bb4462fdSTyler Dauwalder } 360237ced11STyler Dauwalder fDevice = -1; 361d4e8b936STyler Dauwalder fMounted = false; 362d4e8b936STyler Dauwalder fOffset = 0; 363d4e8b936STyler Dauwalder fLength = 0; 364d4e8b936STyler Dauwalder fBlockSize = 0; 365d4e8b936STyler Dauwalder fBlockShift = 0; 366dce2dc5cSTyler Dauwalder fName.SetTo("", 0); 367d4e8b936STyler Dauwalder // delete our partitions 368d4e8b936STyler Dauwalder for (int i = 0; i < UDF_MAX_PARTITION_MAPS; i++) 369d4e8b936STyler Dauwalder _SetPartition(i, NULL); 370d4e8b936STyler Dauwalder } 371d4e8b936STyler Dauwalder 372d4e8b936STyler Dauwalder /*! \brief Sets the partition associated with the given number after 373d4e8b936STyler Dauwalder deleting any previously associated partition. 374d4e8b936STyler Dauwalder 375d4e8b936STyler Dauwalder \param number The partition number (should be the same as the index 376d4e8b936STyler Dauwalder into the lvd's partition map array). 377d4e8b936STyler Dauwalder \param partition The new partition (may be NULL). 3783f4628f1STyler Dauwalder */ 3793f4628f1STyler Dauwalder status_t 380d4e8b936STyler Dauwalder Volume::_SetPartition(uint number, Partition *partition) 3813f4628f1STyler Dauwalder { 382d4e8b936STyler Dauwalder status_t error = number < UDF_MAX_PARTITION_MAPS 383d4e8b936STyler Dauwalder ? B_OK : B_BAD_VALUE; 384d4e8b936STyler Dauwalder if (!error) { 385d4e8b936STyler Dauwalder delete fPartitions[number]; 386d4e8b936STyler Dauwalder fPartitions[number] = partition; 3873f4628f1STyler Dauwalder } 388d4e8b936STyler Dauwalder return error; 3890d383564STyler Dauwalder } 3900d383564STyler Dauwalder 391d4e8b936STyler Dauwalder /*! \brief Returns the partition associated with the given number, or 392d4e8b936STyler Dauwalder NULL if no such partition exists or the number is invalid. 3933f4628f1STyler Dauwalder */ 394e1f5f06bSSalvatore Benedetto Partition* 395d4e8b936STyler Dauwalder Volume::_GetPartition(uint number) 3963f4628f1STyler Dauwalder { 397d4e8b936STyler Dauwalder return (number < UDF_MAX_PARTITION_MAPS) 398d4e8b936STyler Dauwalder ? fPartitions[number] : NULL; 3993f4628f1STyler Dauwalder } 400