1e1f5f06bSSalvatore Benedetto /*
2c530d46cSJé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"
12c530d46cSJé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. */
Volume(fs_volume * fsVolume)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
~Volume()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
Mount(const char * deviceName,off_t offset,off_t length,uint32 blockSize,uint32 flags)480c342879SSalvatore Benedetto Volume::Mount(const char *deviceName, off_t offset, off_t length,
4921c162a3STyler Dauwalder uint32 blockSize, uint32 flags)
5021c162a3STyler Dauwalder {
51*7e5b0f96SJérôme Duval TRACE(("Volume::Mount: deviceName = `%s', offset = %" B_PRIdOFF ", length "
52*7e5b0f96SJérôme Duval "= %" B_PRIdOFF ", blockSize: %" B_PRIu32 ", flags: %" B_PRIu32 "\n",
53*7e5b0f96SJérôme Duval deviceName, offset, length, blockSize, 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
67c530d46cSJé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,
90c530d46cSJérôme Duval fPrimaryVolumeDescriptor, logicalVolumeDescriptor,
91c530d46cSJé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, "
137*7e5b0f96SJérôme Duval "start: %" B_PRIu32 ", length: %" B_PRIu32 ")\n",
138*7e5b0f96SJérôme Duval map->partition_number(), descriptor->start(),
139*7e5b0f96SJérôme Duval descriptor->length()));
1400c342879SSalvatore Benedetto status = _SetPartition(i, partition);
1410c342879SSalvatore Benedetto if (!status)
142d4e8b936STyler Dauwalder physicalCount++;
143d4e8b936STyler Dauwalder }
14421c162a3STyler Dauwalder } else {
14589264fe4SSalvatore Benedetto TRACE_ERROR(("Volume::Mount: no matching partition descriptor found!\n"));
1460c342879SSalvatore Benedetto status = B_ERROR;
147d4e8b936STyler Dauwalder }
148d4e8b936STyler Dauwalder } else if (header->type() == 2) {
1491379cacaSTyler Dauwalder // Figure out what kind of type 2 partition map we have based
150d4e8b936STyler Dauwalder // on the type identifier
1511379cacaSTyler Dauwalder const entity_id &typeId = header->partition_type_id();
152d4e8b936STyler Dauwalder DUMP(typeId);
153d4e8b936STyler Dauwalder DUMP(kSparablePartitionMapId);
154d4e8b936STyler Dauwalder if (typeId.matches(kVirtualPartitionMapId)) {
1550c342879SSalvatore Benedetto TRACE(("map type: virtual\n"));
1561379cacaSTyler Dauwalder virtual_partition_map* map =
1571379cacaSTyler Dauwalder reinterpret_cast<virtual_partition_map*>(header);
158d4e8b936STyler Dauwalder virtualCount++;
159d4e8b936STyler Dauwalder (void)map; // kill the warning for now
160d4e8b936STyler Dauwalder } else if (typeId.matches(kSparablePartitionMapId)) {
1610c342879SSalvatore Benedetto TRACE(("map type: sparable\n"));
1621379cacaSTyler Dauwalder sparable_partition_map* map =
1631379cacaSTyler Dauwalder reinterpret_cast<sparable_partition_map*>(header);
164d4e8b936STyler Dauwalder sparableCount++;
165d4e8b936STyler Dauwalder (void)map; // kill the warning for now
166d4e8b936STyler Dauwalder } else if (typeId.matches(kMetadataPartitionMapId)) {
1670c342879SSalvatore Benedetto TRACE(("map type: metadata\n"));
1681379cacaSTyler Dauwalder metadata_partition_map* map =
1691379cacaSTyler Dauwalder reinterpret_cast<metadata_partition_map*>(header);
170c530d46cSJérôme Duval
171c530d46cSJérôme Duval
172c530d46cSJérôme Duval // Find the corresponding partition descriptor
173c530d46cSJérôme Duval partition_descriptor *descriptor = NULL;
174c530d46cSJérôme Duval for (uint8 j = 0; j < partitionDescriptorCount; j++) {
175c530d46cSJérôme Duval if (map->partition_number() ==
176c530d46cSJérôme Duval partitionDescriptors[j].partition_number()) {
177c530d46cSJérôme Duval descriptor = &partitionDescriptors[j];
178c530d46cSJérôme Duval break;
179c530d46cSJérôme Duval }
180c530d46cSJérôme Duval }
181c530d46cSJérôme Duval Partition *parent = _GetPartition(map->partition_number());
182c530d46cSJérôme Duval // Create and add the partition
183c530d46cSJérôme Duval if (descriptor != NULL && parent != NULL) {
184c530d46cSJérôme Duval MetadataPartition *partition
185c530d46cSJérôme Duval = new(nothrow) MetadataPartition(this,
186c530d46cSJérôme Duval map->partition_number(), *parent,
187c530d46cSJérôme Duval map->metadata_file_location(),
188c530d46cSJérôme Duval map->metadata_mirror_file_location(),
189c530d46cSJérôme Duval map->metadata_bitmap_file_location(),
190c530d46cSJérôme Duval map->allocation_unit_size(),
191c530d46cSJérôme Duval map->alignment_unit_size(),
192c530d46cSJérôme Duval map->flags() & 1);
193c530d46cSJérôme Duval status = partition ? partition->InitCheck() : B_NO_MEMORY;
194c530d46cSJérôme Duval if (!status) {
195c530d46cSJérôme Duval TRACE(("Volume::Mount: adding MetadataPartition()"));
196c530d46cSJérôme Duval status = _SetPartition(i, partition);
197c530d46cSJérôme Duval if (status == B_OK)
198d4e8b936STyler Dauwalder metadataCount++;
199c530d46cSJérôme Duval } else {
200c530d46cSJérôme Duval TRACE_ERROR(("Volume::Mount: metadata partition "
201*7e5b0f96SJérôme Duval "creation failed! 0x%" B_PRIx32 "\n", status));
202c530d46cSJérôme Duval }
203c530d46cSJérôme Duval } else {
204c530d46cSJérôme Duval TRACE_ERROR(("Volume::Mount: no matching partition descriptor found!\n"));
205c530d46cSJérôme Duval status = B_ERROR;
206c530d46cSJérôme Duval }
207d4e8b936STyler Dauwalder } else {
2080c342879SSalvatore Benedetto TRACE(("map type: unrecognized (`%.23s')\n",
209d4e8b936STyler Dauwalder typeId.identifier()));
2100c342879SSalvatore Benedetto status = B_ERROR;
21121c162a3STyler Dauwalder }
212d4e8b936STyler Dauwalder } else {
2130c342879SSalvatore Benedetto TRACE(("Invalid partition type %d found!\n", header->type()));
2140c342879SSalvatore Benedetto status = B_ERROR;
215d4e8b936STyler Dauwalder }
21621c162a3STyler Dauwalder offset += header->length();
21721c162a3STyler Dauwalder }
21821c162a3STyler Dauwalder
219d4e8b936STyler Dauwalder // Do some checking as to what sorts of partitions we've actually found.
2200c342879SSalvatore Benedetto if (!status) {
2210c342879SSalvatore Benedetto status = (physicalCount == 1 && virtualCount == 0
222c530d46cSJérôme Duval && sparableCount == 0)
223d4e8b936STyler Dauwalder || (physicalCount == 2 && virtualCount == 0
224c530d46cSJérôme Duval && sparableCount == 0)
225d4e8b936STyler Dauwalder ? B_OK : B_ERROR;
2260c342879SSalvatore Benedetto if (status) {
2270c342879SSalvatore Benedetto TRACE(("Invalid partition layout found:\n"));
2280c342879SSalvatore Benedetto TRACE((" physical partitions: %d\n", physicalCount));
2290c342879SSalvatore Benedetto TRACE((" virtual partitions: %d\n", virtualCount));
2300c342879SSalvatore Benedetto TRACE((" sparable partitions: %d\n", sparableCount));
2310c342879SSalvatore Benedetto TRACE((" metadata partitions: %d\n", metadataCount));
232d4e8b936STyler Dauwalder }
233d4e8b936STyler Dauwalder }
234d4e8b936STyler Dauwalder
235d4e8b936STyler Dauwalder // We're now going to start creating Icb's, which will expect
236d4e8b936STyler Dauwalder // certain parts of the volume to be initialized properly. Thus,
237d4e8b936STyler Dauwalder // we initialize those parts here.
2380c342879SSalvatore Benedetto if (!status) {
239d4e8b936STyler Dauwalder fDevice = device;
240d4e8b936STyler Dauwalder fOffset = offset;
2410c342879SSalvatore Benedetto fLength = length;
242d4e8b936STyler Dauwalder fBlockSize = blockSize;
243d4e8b936STyler Dauwalder fBlockShift = blockShift;
244d4e8b936STyler Dauwalder }
245*7e5b0f96SJérôme Duval TRACE(("Volume::Mount: device = %d, offset = %" B_PRIdOFF ", length = %"
246*7e5b0f96SJérôme Duval B_PRIdOFF ", blockSize = %" B_PRIu32 ", blockShift = %" B_PRIu32 "\n",
247*7e5b0f96SJérôme Duval device, offset, length, blockSize, blockShift));
248d4e8b936STyler Dauwalder // At this point we've found a valid set of volume descriptors and
249d4e8b936STyler Dauwalder // our partitions are all set up. We now need to investigate the file
250d4e8b936STyler Dauwalder // set descriptor pointed to by the logical volume descriptor.
2510c342879SSalvatore Benedetto if (!status) {
252e0c80398SSalvatore Benedetto TRACE(("Volume::Mount: Partition has been set up\n"));
253d4e8b936STyler Dauwalder MemoryChunk chunk(logicalVolumeDescriptor.file_set_address().length());
25421c162a3STyler Dauwalder
2550c342879SSalvatore Benedetto status = chunk.InitCheck();
25621c162a3STyler Dauwalder
2570c342879SSalvatore Benedetto if (!status) {
258d4e8b936STyler Dauwalder off_t address;
259d4e8b936STyler Dauwalder // Read in the file set descriptor
2600c342879SSalvatore Benedetto status = MapBlock(logicalVolumeDescriptor.file_set_address(),
261d4e8b936STyler Dauwalder &address);
2620c342879SSalvatore Benedetto if (!status)
263d4e8b936STyler Dauwalder address <<= blockShift;
2640c342879SSalvatore Benedetto if (!status) {
265e0c80398SSalvatore Benedetto ssize_t bytesRead
266e0c80398SSalvatore Benedetto = read_pos(device, address, chunk.Data(), blockSize);
267d8b4553aSTyler Dauwalder if (bytesRead != ssize_t(blockSize)) {
2680c342879SSalvatore Benedetto status = B_IO_ERROR;
269*7e5b0f96SJérôme Duval TRACE_ERROR(("read_pos(pos:%" B_PRIdOFF ", len:%" B_PRIu32
270*7e5b0f96SJérôme Duval ") failed with: 0x%lx\n", address, blockSize,
271*7e5b0f96SJérôme Duval bytesRead));
272d4e8b936STyler Dauwalder }
273d4e8b936STyler Dauwalder }
274d4e8b936STyler Dauwalder // See if it's valid, and if so, create the root icb
2750c342879SSalvatore Benedetto if (!status) {
2761379cacaSTyler Dauwalder file_set_descriptor *fileSet =
2771379cacaSTyler Dauwalder reinterpret_cast<file_set_descriptor*>(chunk.Data());
27817b66e62STyler Dauwalder PDUMP(fileSet);
2790c342879SSalvatore Benedetto status = fileSet->tag().id() == TAGID_FILE_SET_DESCRIPTOR
280d8b4553aSTyler Dauwalder ? B_OK : B_ERROR;
2810c342879SSalvatore Benedetto if (!status)
2820c342879SSalvatore Benedetto status = fileSet->tag().init_check(
28317b66e62STyler Dauwalder logicalVolumeDescriptor.file_set_address().block());
2840c342879SSalvatore Benedetto if (!status) {
28521c162a3STyler Dauwalder PDUMP(fileSet);
286f50008f9STyler Dauwalder fRootIcb = new(nothrow) Icb(this, fileSet->root_directory_icb());
287e0c80398SSalvatore Benedetto if (fRootIcb == NULL || fRootIcb->InitCheck() != B_OK)
288e0c80398SSalvatore Benedetto return B_NO_MEMORY;
289d8b4553aSTyler Dauwalder }
290e0c80398SSalvatore Benedetto
291*7e5b0f96SJérôme Duval TRACE(("Volume::Mount: Root Node id = %" B_PRIdINO "\n",
292*7e5b0f96SJérôme Duval fRootIcb->Id()));
2930c342879SSalvatore Benedetto if (!status) {
294e0c80398SSalvatore Benedetto status = publish_vnode(fFSVolume, fRootIcb->Id(), fRootIcb,
295e0c80398SSalvatore Benedetto &gUDFVnodeOps, fRootIcb->Mode(), 0);
296e0c80398SSalvatore Benedetto if (status != B_OK) {
297e0c80398SSalvatore Benedetto TRACE_ERROR(("Error creating vnode for root icb! "
298*7e5b0f96SJérôme Duval "status = 0x%" B_PRIx32 ", `%s'\n", status,
2990c342879SSalvatore Benedetto strerror(status)));
300d4e8b936STyler Dauwalder // Clean up the icb we created, since _Unset()
301d4e8b936STyler Dauwalder // won't do this for us.
302d4e8b936STyler Dauwalder delete fRootIcb;
303d4e8b936STyler Dauwalder fRootIcb = NULL;
304d4e8b936STyler Dauwalder }
305*7e5b0f96SJérôme Duval TRACE(("Volume::Mount: Root vnode published. Id = %"
306*7e5b0f96SJérôme Duval B_PRIdINO "\n", fRootIcb->Id()));
307d4e8b936STyler Dauwalder }
308d4e8b936STyler Dauwalder }
30921c162a3STyler Dauwalder }
31021c162a3STyler Dauwalder }
31121c162a3STyler Dauwalder
312d4e8b936STyler Dauwalder // If we've made it this far, we're good to go; set the volume
313d4e8b936STyler Dauwalder // name and then flag that we're mounted. On the other hand, if
314d4e8b936STyler Dauwalder // an error occurred, we need to clean things up.
3150c342879SSalvatore Benedetto if (!status) {
316d4e8b936STyler Dauwalder fName.SetTo(logicalVolumeDescriptor.logical_volume_identifier());
317d4e8b936STyler Dauwalder fMounted = true;
318d4e8b936STyler Dauwalder } else {
319d4e8b936STyler Dauwalder _Unset();
32021c162a3STyler Dauwalder }
32121c162a3STyler Dauwalder
3220c342879SSalvatore Benedetto RETURN(status);
3234ac73018STyler Dauwalder }
3244ac73018STyler Dauwalder
3259fd15595SSalvatore Benedetto
326a71fd512STyler Dauwalder const char*
Name() const327a71fd512STyler Dauwalder Volume::Name() const {
328dce2dc5cSTyler Dauwalder return fName.Utf8();
329a71fd512STyler Dauwalder }
3303f4628f1STyler Dauwalder
331d4e8b936STyler Dauwalder /*! \brief Maps the given logical block to a physical block.
3323f4628f1STyler Dauwalder */
3333f4628f1STyler Dauwalder status_t
MapBlock(long_address address,off_t * mappedBlock)3341379cacaSTyler Dauwalder Volume::MapBlock(long_address address, off_t *mappedBlock)
3350d383564STyler Dauwalder {
336*7e5b0f96SJérôme Duval TRACE(("Volume::MapBlock: partition = %d, block = %" B_PRIu32
337*7e5b0f96SJérôme Duval ", mappedBlock = %p\n", address.partition(), address.block(),
338*7e5b0f96SJérôme Duval mappedBlock));
339*7e5b0f96SJérôme Duval DEBUG_INIT_ETC("Volume", ("partition = %d, block = %" B_PRIu32
340*7e5b0f96SJérôme Duval ", mappedBlock = %p", address.partition(), address.block(),
341*7e5b0f96SJérôme Duval mappedBlock));
342d4e8b936STyler Dauwalder status_t error = mappedBlock ? B_OK : B_BAD_VALUE;
343d4e8b936STyler Dauwalder if (!error) {
344d4e8b936STyler Dauwalder Partition *partition = _GetPartition(address.partition());
345d4e8b936STyler Dauwalder error = partition ? B_OK : B_BAD_ADDRESS;
346d4e8b936STyler Dauwalder if (!error)
347d4e8b936STyler Dauwalder error = partition->MapBlock(address.block(), *mappedBlock);
3483f4628f1STyler Dauwalder }
349d4e8b936STyler Dauwalder RETURN(error);
3503f4628f1STyler Dauwalder }
3513f4628f1STyler Dauwalder
352d4e8b936STyler Dauwalder /*! \brief Unsets the volume and deletes any partitions.
353d4e8b936STyler Dauwalder
354d4e8b936STyler Dauwalder Does *not* delete the root icb object.
355d4e8b936STyler Dauwalder */
356d4e8b936STyler Dauwalder void
_Unset()357d4e8b936STyler Dauwalder Volume::_Unset()
358d4e8b936STyler Dauwalder {
359d8b4553aSTyler Dauwalder DEBUG_INIT("Volume");
360ed3ea3b0SJérôme Duval // delete our partitions
361ed3ea3b0SJérôme Duval for (int i = 0; i < UDF_MAX_PARTITION_MAPS; i++)
362ed3ea3b0SJérôme Duval _SetPartition(i, NULL);
363e1f5f06bSSalvatore Benedetto fFSVolume->id = 0;
364bb4462fdSTyler Dauwalder if (fDevice >= 0) {
365e1f5f06bSSalvatore Benedetto block_cache_delete(fBlockCache, true);
366237ced11STyler Dauwalder close(fDevice);
367bb4462fdSTyler Dauwalder }
368ed3ea3b0SJérôme Duval fBlockCache = NULL;
369237ced11STyler Dauwalder fDevice = -1;
370d4e8b936STyler Dauwalder fMounted = false;
371d4e8b936STyler Dauwalder fOffset = 0;
372d4e8b936STyler Dauwalder fLength = 0;
373d4e8b936STyler Dauwalder fBlockSize = 0;
374d4e8b936STyler Dauwalder fBlockShift = 0;
375dce2dc5cSTyler Dauwalder fName.SetTo("", 0);
376d4e8b936STyler Dauwalder }
377d4e8b936STyler Dauwalder
378d4e8b936STyler Dauwalder /*! \brief Sets the partition associated with the given number after
379d4e8b936STyler Dauwalder deleting any previously associated partition.
380d4e8b936STyler Dauwalder
381d4e8b936STyler Dauwalder \param number The partition number (should be the same as the index
382d4e8b936STyler Dauwalder into the lvd's partition map array).
383d4e8b936STyler Dauwalder \param partition The new partition (may be NULL).
3843f4628f1STyler Dauwalder */
3853f4628f1STyler Dauwalder status_t
_SetPartition(uint number,Partition * partition)386d4e8b936STyler Dauwalder Volume::_SetPartition(uint number, Partition *partition)
3873f4628f1STyler Dauwalder {
388d4e8b936STyler Dauwalder status_t error = number < UDF_MAX_PARTITION_MAPS
389d4e8b936STyler Dauwalder ? B_OK : B_BAD_VALUE;
390d4e8b936STyler Dauwalder if (!error) {
391d4e8b936STyler Dauwalder delete fPartitions[number];
392d4e8b936STyler Dauwalder fPartitions[number] = partition;
3933f4628f1STyler Dauwalder }
394d4e8b936STyler Dauwalder return error;
3950d383564STyler Dauwalder }
3960d383564STyler Dauwalder
397d4e8b936STyler Dauwalder /*! \brief Returns the partition associated with the given number, or
398d4e8b936STyler Dauwalder NULL if no such partition exists or the number is invalid.
3993f4628f1STyler Dauwalder */
400e1f5f06bSSalvatore Benedetto Partition*
_GetPartition(uint number)401d4e8b936STyler Dauwalder Volume::_GetPartition(uint number)
4023f4628f1STyler Dauwalder {
403d4e8b936STyler Dauwalder return (number < UDF_MAX_PARTITION_MAPS)
404d4e8b936STyler Dauwalder ? fPartitions[number] : NULL;
4053f4628f1STyler Dauwalder }
406