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