xref: /haiku/src/add-ons/kernel/file_systems/udf/Volume.cpp (revision b8ded2f89783a220c7b3019d48266a682cc79158)
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