xref: /haiku/src/add-ons/kernel/file_systems/udf/Volume.cpp (revision 0d383564c32019d5dfb1effaf055c94c41c5898d)
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 
11*0d383564STyler Dauwalder #include "MemoryChunk.h"
1229008bcfSTyler Dauwalder 
1329008bcfSTyler Dauwalder using namespace UDF;
1429008bcfSTyler Dauwalder 
1529008bcfSTyler Dauwalder //----------------------------------------------------------------------
1629008bcfSTyler Dauwalder // Volume
1729008bcfSTyler Dauwalder //----------------------------------------------------------------------
1829008bcfSTyler Dauwalder 
1929008bcfSTyler Dauwalder /*! \brief Creates an unmounted volume with the given id.
2029008bcfSTyler Dauwalder */
2129008bcfSTyler Dauwalder Volume::Volume(nspace_id id)
2229008bcfSTyler Dauwalder 	: fID(id)
2329008bcfSTyler Dauwalder 	, fDevice(0)
2429008bcfSTyler Dauwalder 	, fReadOnly(false)
254ac73018STyler Dauwalder 	, fStartAddress(0)
264ac73018STyler Dauwalder 	, fBlockSize(0)
274ac73018STyler Dauwalder 	, fInitStatus(B_UNINITIALIZED)
2829008bcfSTyler Dauwalder {
2929008bcfSTyler Dauwalder }
3029008bcfSTyler Dauwalder 
3129008bcfSTyler Dauwalder status_t
3229008bcfSTyler Dauwalder Volume::Identify(int device, off_t base)
3329008bcfSTyler Dauwalder {
3429008bcfSTyler Dauwalder 	return B_ERROR;
3529008bcfSTyler Dauwalder }
3629008bcfSTyler Dauwalder 
3729008bcfSTyler Dauwalder /*! \brief Attempts to mount the given device.
3829008bcfSTyler Dauwalder */
3929008bcfSTyler Dauwalder status_t
404ac73018STyler Dauwalder Volume::Mount(const char *deviceName, off_t volumeStart, off_t volumeLength,
414ac73018STyler Dauwalder               uint32 flags, uint32 blockSize)
4229008bcfSTyler Dauwalder {
43565457fdSTyler Dauwalder 	DEBUG_INIT_ETC(CF_PUBLIC | CF_VOLUME_OPS, "Volume",
44565457fdSTyler Dauwalder 		("devName = `%s'", deviceName));
4529008bcfSTyler Dauwalder 	if (!deviceName)
4629008bcfSTyler Dauwalder 		RETURN_ERROR(B_BAD_VALUE);
474ac73018STyler Dauwalder 	if (_InitStatus() == B_INITIALIZED)
484ac73018STyler Dauwalder 		RETURN_ERROR(B_BUSY);
494ac73018STyler Dauwalder 			// Already mounted, thank you for asking
5029008bcfSTyler Dauwalder 
5129008bcfSTyler Dauwalder 	fReadOnly = flags & B_READ_ONLY;
524ac73018STyler Dauwalder 	fStartAddress = volumeStart;
534ac73018STyler Dauwalder 	fLength = volumeLength;
544ac73018STyler Dauwalder 	fBlockSize = blockSize;
5529008bcfSTyler Dauwalder 
5629008bcfSTyler Dauwalder 	// Open the device, trying read only if readwrite fails
5729008bcfSTyler Dauwalder 	fDevice = open(deviceName, fReadOnly ? O_RDONLY : O_RDWR);
5829008bcfSTyler Dauwalder 	if (fDevice < B_OK && !fReadOnly) {
5929008bcfSTyler Dauwalder 		fReadOnly = true;
6029008bcfSTyler Dauwalder 		fDevice = open(deviceName, O_RDONLY);
6129008bcfSTyler Dauwalder 	}
6229008bcfSTyler Dauwalder 	if (fDevice < B_OK)
6329008bcfSTyler Dauwalder 		RETURN_ERROR(fDevice);
6429008bcfSTyler Dauwalder 
6529008bcfSTyler Dauwalder 	// If the device is actually a normal file, try to disable the cache
6629008bcfSTyler Dauwalder 	// for the file in the parent filesystem
6729008bcfSTyler Dauwalder 	struct stat stat;
684ac73018STyler Dauwalder 	status_t err = fstat(fDevice, &stat) < 0 ? B_ERROR : B_OK;
6929008bcfSTyler Dauwalder 	if (!err) {
7029008bcfSTyler Dauwalder 		if (stat.st_mode & S_IFREG && ioctl(fDevice, IOCTL_FILE_UNCACHED_IO, NULL) < 0) {
714ac73018STyler Dauwalder 			// Apparently it's a bad thing if you can't disable the file
724ac73018STyler Dauwalder 			// cache for a non-device disk image you're trying to mount...
734ac73018STyler Dauwalder 			DIE(("Unable to disable cache of underlying file system. "
744ac73018STyler Dauwalder 			     "I hear that's bad. :-(\n"));
7529008bcfSTyler Dauwalder 		}
764ac73018STyler Dauwalder 		// So far so good. The device is ready to be accessed now.
774ac73018STyler Dauwalder 		fInitStatus = B_DEVICE_INITIALIZED;
7829008bcfSTyler Dauwalder 	}
7929008bcfSTyler Dauwalder 
8029008bcfSTyler Dauwalder 	// Now identify the volume
814ac73018STyler Dauwalder 	if (!err)
824ac73018STyler Dauwalder 		err = _Identify();
8329008bcfSTyler Dauwalder 
844ac73018STyler Dauwalder 	RETURN(B_ERROR);
854ac73018STyler Dauwalder }
864ac73018STyler Dauwalder 
87*0d383564STyler Dauwalder off_t
88*0d383564STyler Dauwalder Volume::_MapAddress(udf_extent_address address)
89*0d383564STyler Dauwalder {
90*0d383564STyler Dauwalder 	return address.location() * BlockSize();
91*0d383564STyler Dauwalder }
92*0d383564STyler Dauwalder 
93*0d383564STyler Dauwalder off_t
94*0d383564STyler Dauwalder Volume::_MapAddress(udf_long_address address)
95*0d383564STyler Dauwalder {
96*0d383564STyler Dauwalder 	return 0;
97*0d383564STyler Dauwalder }
98*0d383564STyler Dauwalder 
99*0d383564STyler Dauwalder off_t
100*0d383564STyler Dauwalder Volume::_MapAddress(udf_short_address address)
101*0d383564STyler Dauwalder {
102*0d383564STyler Dauwalder 	return 0;
103*0d383564STyler Dauwalder }
104*0d383564STyler Dauwalder 
105*0d383564STyler Dauwalder status_t
106*0d383564STyler Dauwalder Volume::_Read(udf_extent_address address, ssize_t length, void *data)
107*0d383564STyler Dauwalder {
108*0d383564STyler Dauwalder 	DEBUG_INIT(CF_PRIVATE | CF_HIGH_VOLUME, "Volume");
109*0d383564STyler Dauwalder 	off_t mappedAddress = _MapAddress(address);
110*0d383564STyler Dauwalder 	status_t err = data ? B_OK : B_BAD_VALUE;
111*0d383564STyler Dauwalder 	if (!err) {
112*0d383564STyler Dauwalder 		ssize_t bytesRead = read_pos(fDevice, mappedAddress, data, BlockSize());
113*0d383564STyler Dauwalder 		if (bytesRead != (ssize_t)BlockSize()) {
114*0d383564STyler Dauwalder 			err = B_IO_ERROR;
115*0d383564STyler Dauwalder 			PRINT(("read_pos(pos:%lld, len:%ld) failed with: 0x%lx\n", mappedAddress,
116*0d383564STyler Dauwalder 			       length, bytesRead));
117*0d383564STyler Dauwalder 		}
118*0d383564STyler Dauwalder 	}
119*0d383564STyler Dauwalder 	return err;
120*0d383564STyler Dauwalder }
121*0d383564STyler Dauwalder 
1224ac73018STyler Dauwalder /*!	\brief Walks through the volume recognition and descriptor sequences,
1234ac73018STyler Dauwalder 	gathering volume description info as it goes.
1244ac73018STyler Dauwalder 
1254ac73018STyler Dauwalder 	Note that the 512 avdp location is, technically speaking, only valid on
1264ac73018STyler Dauwalder 	unlosed CD-R media in the absense of an avdp at 256. For now I'm not
1274ac73018STyler Dauwalder 	bothering with such silly details, and instead am just checking for it
1284ac73018STyler Dauwalder 	last.
1294ac73018STyler Dauwalder */
1304ac73018STyler Dauwalder status_t
1314ac73018STyler Dauwalder Volume::_Identify()
1324ac73018STyler Dauwalder {
133565457fdSTyler Dauwalder 	DEBUG_INIT(CF_PRIVATE | CF_VOLUME_OPS, "Volume");
1344ac73018STyler Dauwalder 
1354ac73018STyler Dauwalder 	status_t err = _InitStatus() == B_DEVICE_INITIALIZED ? B_OK : B_BAD_VALUE;
1364ac73018STyler Dauwalder 
1374ac73018STyler Dauwalder 	// Check for a valid volume recognition sequence
1384ac73018STyler Dauwalder 	if (!err)
1394ac73018STyler Dauwalder 		err = _WalkVolumeRecognitionSequence();
1404ac73018STyler Dauwalder 
1414ac73018STyler Dauwalder 	// Now hunt down a volume descriptor sequence from one of
1424ac73018STyler Dauwalder 	// the anchor volume pointers (if there are any).
143*0d383564STyler Dauwalder 	if (!err)
144*0d383564STyler Dauwalder 		err = _WalkAnchorVolumeDescriptorSequences();
1454ac73018STyler Dauwalder 
146*0d383564STyler Dauwalder 	// At this point we've found a valid set of volume descriptors. We
147*0d383564STyler Dauwalder 	// now need to investigate the file set descriptor pointed to by
148*0d383564STyler Dauwalder 	// the logical volume descriptor
149*0d383564STyler Dauwalder 	if (!err)
150*0d383564STyler Dauwalder 		err = _InitFileSetDescriptor();
1514ac73018STyler Dauwalder 
1524ac73018STyler Dauwalder 	RETURN(err);
1534ac73018STyler Dauwalder }
1544ac73018STyler Dauwalder 
155565457fdSTyler Dauwalder /*! \brief Walks the iso9660/ecma-167 volume recognition sequence, returning
156565457fdSTyler Dauwalder 	\c B_OK if the presence of a UDF filesystem on this volume is likely.
157565457fdSTyler Dauwalder 
158565457fdSTyler Dauwalder 	\return \c B_OK: An ECMA-167 vsd was found, or at least one extended area
159565457fdSTyler Dauwalder 	                 vsd was found and no ECMA-168 vsds were found.
160565457fdSTyler Dauwalder 	\return "error code": Only iso9660 vsds were found, an ECMA-168 vsd was
161565457fdSTyler Dauwalder 	                      found (but no ECMA-167 vsd), or an error occurred.
162565457fdSTyler Dauwalder */
1634ac73018STyler Dauwalder status_t
1644ac73018STyler Dauwalder Volume::_WalkVolumeRecognitionSequence()
1654ac73018STyler Dauwalder {
166565457fdSTyler Dauwalder 	DEBUG_INIT(CF_PRIVATE | CF_VOLUME_OPS, "Volume");
1674ac73018STyler Dauwalder 	// vrs starts at block 16. Each volume structure descriptor (vsd)
1684ac73018STyler Dauwalder 	// should be one block long. We're expecting to find 0 or more iso9660
1694ac73018STyler Dauwalder 	// vsd's followed by some ECMA-167 vsd's.
170*0d383564STyler Dauwalder 	MemoryChunk chunk(BlockSize());
171*0d383564STyler Dauwalder 	status_t err = chunk.InitCheck();
1724ac73018STyler Dauwalder 	if (!err) {
1734ac73018STyler Dauwalder 		bool foundISO = false;
1744ac73018STyler Dauwalder 		bool foundExtended = false;
1754ac73018STyler Dauwalder 		bool foundECMA167 = false;
1764ac73018STyler Dauwalder 		bool foundECMA168 = false;
1774ac73018STyler Dauwalder 		bool foundBoot = false;
1784ac73018STyler Dauwalder 		for (uint32 block = 16; true; block++) {
1794ac73018STyler Dauwalder 	    	PRINT(("block %ld: ", block))
180565457fdSTyler Dauwalder 			off_t address = AddressForRelativeBlock(block);
181*0d383564STyler Dauwalder 			ssize_t bytesRead = read_pos(fDevice, address, chunk.Data(), BlockSize());
1824ac73018STyler Dauwalder 			if (bytesRead == (ssize_t)BlockSize())
1834ac73018STyler Dauwalder 		    {
184*0d383564STyler Dauwalder 		    	udf_volume_structure_descriptor_header* descriptor =
185*0d383564STyler Dauwalder 		    	  reinterpret_cast<udf_volume_structure_descriptor_header*>(chunk.Data());
186*0d383564STyler Dauwalder 				if (descriptor->id_matches(kVSDID_ISO)) {
1874ac73018STyler Dauwalder 					SIMPLE_PRINT(("found ISO9660 descriptor\n"));
1884ac73018STyler Dauwalder 					foundISO = true;
189*0d383564STyler Dauwalder 				} else if (descriptor->id_matches(kVSDID_BEA)) {
1904ac73018STyler Dauwalder 					SIMPLE_PRINT(("found BEA descriptor\n"));
1914ac73018STyler Dauwalder 					foundExtended = true;
192*0d383564STyler Dauwalder 				} else if (descriptor->id_matches(kVSDID_TEA)) {
1934ac73018STyler Dauwalder 					SIMPLE_PRINT(("found TEA descriptor\n"));
1944ac73018STyler Dauwalder 					foundExtended = true;
195*0d383564STyler Dauwalder 				} else if (descriptor->id_matches(kVSDID_ECMA167_2)) {
1964ac73018STyler Dauwalder 					SIMPLE_PRINT(("found ECMA-167 rev 2 descriptor\n"));
1974ac73018STyler Dauwalder 					foundECMA167 = true;
198*0d383564STyler Dauwalder 				} else if (descriptor->id_matches(kVSDID_ECMA167_3)) {
1994ac73018STyler Dauwalder 					SIMPLE_PRINT(("found ECMA-167 rev 3 descriptor\n"));
2004ac73018STyler Dauwalder 					foundECMA167 = true;
201*0d383564STyler Dauwalder 				} else if (descriptor->id_matches(kVSDID_BOOT)) {
2024ac73018STyler Dauwalder 					SIMPLE_PRINT(("found boot descriptor\n"));
2034ac73018STyler Dauwalder 					foundBoot = true;
204*0d383564STyler Dauwalder 				} else if (descriptor->id_matches(kVSDID_ECMA168)) {
2054ac73018STyler Dauwalder 					SIMPLE_PRINT(("found ECMA-168 descriptor\n"));
2064ac73018STyler Dauwalder 					foundECMA168 = true;
2074ac73018STyler Dauwalder 				} else {
208*0d383564STyler Dauwalder 					SIMPLE_PRINT(("found invalid descriptor, id = `%.5s'\n", descriptor->id));
2094ac73018STyler Dauwalder 					break;
2104ac73018STyler Dauwalder 				}
2114ac73018STyler Dauwalder 			} else {
2124ac73018STyler Dauwalder 				SIMPLE_PRINT(("read_pos(pos:%lld, len:%ld) failed with: 0x%lx\n", address,
2134ac73018STyler Dauwalder 				        BlockSize(), bytesRead));
2144ac73018STyler Dauwalder 				break;
2154ac73018STyler Dauwalder 			}
2164ac73018STyler Dauwalder 		}
2174ac73018STyler Dauwalder 
2184ac73018STyler Dauwalder 		// If we find an ECMA-167 descriptor, OR if we find a beginning
2194ac73018STyler Dauwalder 		// or terminating extended area descriptor with NO ECMA-168
2204ac73018STyler Dauwalder 		// descriptors, we return B_OK to signal that we should go
2214ac73018STyler Dauwalder 		// looking for valid anchors.
2224ac73018STyler Dauwalder 		err = foundECMA167 || (foundExtended && !foundECMA168) ? B_OK : B_ERROR;
2234ac73018STyler Dauwalder 	}
2244ac73018STyler Dauwalder 
2254ac73018STyler Dauwalder 	RETURN(err);
2264ac73018STyler Dauwalder }
2274ac73018STyler Dauwalder 
2284ac73018STyler Dauwalder status_t
229*0d383564STyler Dauwalder Volume::_WalkAnchorVolumeDescriptorSequences()
230*0d383564STyler Dauwalder {
231*0d383564STyler Dauwalder 	DEBUG_INIT(CF_PRIVATE | CF_VOLUME_OPS, "Volume");
232*0d383564STyler Dauwalder 		const uint8 avds_location_count = 4;
233*0d383564STyler Dauwalder 		const off_t avds_locations[avds_location_count] = { 256,
234*0d383564STyler Dauwalder 		                                                    Length()-256,
235*0d383564STyler Dauwalder 		                                                    Length(),
236*0d383564STyler Dauwalder 		                                                    512,
237*0d383564STyler Dauwalder 		                                                  };
238*0d383564STyler Dauwalder 		bool found_vds = false;
239*0d383564STyler Dauwalder 
240*0d383564STyler Dauwalder 		for (int32 i = 0; i < avds_location_count; i++) {
241*0d383564STyler Dauwalder 			off_t block = avds_locations[i];
242*0d383564STyler Dauwalder 			off_t address = AddressForRelativeBlock(block);
243*0d383564STyler Dauwalder 			MemoryChunk chunk(BlockSize());
244*0d383564STyler Dauwalder 			udf_anchor_descriptor *anchor = NULL;
245*0d383564STyler Dauwalder 
246*0d383564STyler Dauwalder 			status_t anchorErr = chunk.InitCheck();
247*0d383564STyler Dauwalder 			if (!anchorErr) {
248*0d383564STyler Dauwalder 				ssize_t bytesRead = read_pos(fDevice, address, chunk.Data(), BlockSize());
249*0d383564STyler Dauwalder 				anchorErr = bytesRead == (ssize_t)BlockSize() ? B_OK : B_IO_ERROR;
250*0d383564STyler Dauwalder 				if (anchorErr) {
251*0d383564STyler Dauwalder 					PRINT(("block %lld: read_pos(pos:%lld, len:%ld) failed with error 0x%lx\n",
252*0d383564STyler Dauwalder 					       block, address, BlockSize(), bytesRead));
253*0d383564STyler Dauwalder 				}
254*0d383564STyler Dauwalder 			}
255*0d383564STyler Dauwalder 			if (!anchorErr) {
256*0d383564STyler Dauwalder 				anchor = reinterpret_cast<udf_anchor_descriptor*>(chunk.Data());
257*0d383564STyler Dauwalder 				anchorErr = anchor->tag().init_check(block);
258*0d383564STyler Dauwalder 				if (anchorErr) {
259*0d383564STyler Dauwalder 					PRINT(("block %lld: invalid anchor\n", block));
260*0d383564STyler Dauwalder 				} else {
261*0d383564STyler Dauwalder 					PRINT(("block %lld: valid anchor\n", block));
262*0d383564STyler Dauwalder 				}
263*0d383564STyler Dauwalder 			}
264*0d383564STyler Dauwalder 			if (!anchorErr) {
265*0d383564STyler Dauwalder 				PRINT(("block %lld: anchor:\n", block));
266*0d383564STyler Dauwalder 				PDUMP(anchor);
267*0d383564STyler Dauwalder 				// Found an avds, so try the main sequence first, then
268*0d383564STyler Dauwalder 				// the reserve sequence if the main one fails.
269*0d383564STyler Dauwalder 				anchorErr = _WalkVolumeDescriptorSequence(anchor->main_vds());
270*0d383564STyler Dauwalder 				if (anchorErr)
271*0d383564STyler Dauwalder 					anchorErr = _WalkVolumeDescriptorSequence(anchor->reserve_vds());
272*0d383564STyler Dauwalder 
273*0d383564STyler Dauwalder 
274*0d383564STyler Dauwalder 			}
275*0d383564STyler Dauwalder 			if (!anchorErr) {
276*0d383564STyler Dauwalder 				PRINT(("block %lld: found valid vds\n", avds_locations[i]));
277*0d383564STyler Dauwalder 				found_vds = true;
278*0d383564STyler Dauwalder 				break;
279*0d383564STyler Dauwalder 			} //else {
280*0d383564STyler Dauwalder 				// Both failed, so loop around and try another avds
281*0d383564STyler Dauwalder //				PRINT(("block %lld: vds search failed\n", avds_locations[i]));
282*0d383564STyler Dauwalder //			}
283*0d383564STyler Dauwalder 		}
284*0d383564STyler Dauwalder 		status_t err = found_vds ? B_OK : B_ERROR;
285*0d383564STyler Dauwalder 		RETURN(err);
286*0d383564STyler Dauwalder }
287*0d383564STyler Dauwalder 
288*0d383564STyler Dauwalder status_t
289*0d383564STyler Dauwalder Volume::_WalkVolumeDescriptorSequence(udf_extent_address extent)
2904ac73018STyler Dauwalder {
291565457fdSTyler Dauwalder 	DEBUG_INIT_ETC(CF_PRIVATE | CF_VOLUME_OPS, "Volume", ("loc:%ld, len:%ld",
292565457fdSTyler Dauwalder 	           extent.location(), extent.length()));
293565457fdSTyler Dauwalder 	uint32 count = extent.length()/BlockSize();
294*0d383564STyler Dauwalder 
295*0d383564STyler Dauwalder 	bool foundLogicalVD = false;
296*0d383564STyler Dauwalder 
297565457fdSTyler Dauwalder 	for (uint32 i = 0; i < count; i++)
298565457fdSTyler Dauwalder 	{
299565457fdSTyler Dauwalder 		off_t block = extent.location()+i;
300565457fdSTyler Dauwalder 		off_t address = AddressForRelativeBlock(block);
301*0d383564STyler Dauwalder 		MemoryChunk chunk(BlockSize());
302*0d383564STyler Dauwalder 		udf_tag *tag = NULL;
303*0d383564STyler Dauwalder 
304*0d383564STyler Dauwalder 		PRINT(("descriptor #%ld (block %lld):\n", i, block));
305*0d383564STyler Dauwalder 
306*0d383564STyler Dauwalder 		status_t err = chunk.InitCheck();
307565457fdSTyler Dauwalder 		if (!err) {
308*0d383564STyler Dauwalder 			ssize_t bytesRead = read_pos(fDevice, address, chunk.Data(), BlockSize());
309565457fdSTyler Dauwalder 			err = bytesRead == (ssize_t)BlockSize() ? B_OK : B_IO_ERROR;
310565457fdSTyler Dauwalder 			if (err) {
311565457fdSTyler Dauwalder 				PRINT(("block %lld: read_pos(pos:%lld, len:%ld) failed with error 0x%lx\n",
312565457fdSTyler Dauwalder 				       block, address, BlockSize(), bytesRead));
313565457fdSTyler Dauwalder 			}
314565457fdSTyler Dauwalder 		}
315565457fdSTyler Dauwalder 		if (!err) {
316*0d383564STyler Dauwalder 			tag = reinterpret_cast<udf_tag*>(chunk.Data());
317*0d383564STyler Dauwalder 			err = tag->init_check(block);
318*0d383564STyler Dauwalder 		}
319*0d383564STyler Dauwalder 		if (!err) {
320*0d383564STyler Dauwalder 			// Now decide what type of descriptor we have
321*0d383564STyler Dauwalder 			switch (tag->id()) {
322*0d383564STyler Dauwalder 				case TAGID_UNDEFINED:
323*0d383564STyler Dauwalder 					break;
324*0d383564STyler Dauwalder 
325*0d383564STyler Dauwalder 				case TAGID_PRIMARY_VOLUME_DESCRIPTOR:
326*0d383564STyler Dauwalder 				{
327*0d383564STyler Dauwalder 					udf_primary_descriptor *primary = reinterpret_cast<udf_primary_descriptor*>(tag);
328*0d383564STyler Dauwalder 					PDUMP(primary);
329*0d383564STyler Dauwalder 					break;
330*0d383564STyler Dauwalder 				}
331*0d383564STyler Dauwalder 
332*0d383564STyler Dauwalder 				case TAGID_ANCHOR_VOLUME_DESCRIPTOR_POINTER:
333*0d383564STyler Dauwalder 					break;
334*0d383564STyler Dauwalder 
335*0d383564STyler Dauwalder 				case TAGID_VOLUME_DESCRIPTOR_POINTER:
336*0d383564STyler Dauwalder 					break;
337*0d383564STyler Dauwalder 
338*0d383564STyler Dauwalder 				case TAGID_IMPLEMENTATION_USE_VOLUME_DESCRIPTOR:
339*0d383564STyler Dauwalder 				{
340*0d383564STyler Dauwalder 					udf_implementation_use_descriptor *imp_use = reinterpret_cast<udf_implementation_use_descriptor*>(tag);
341*0d383564STyler Dauwalder 					PDUMP(imp_use);
342*0d383564STyler Dauwalder 					break;
343*0d383564STyler Dauwalder 				}
344*0d383564STyler Dauwalder 
345*0d383564STyler Dauwalder 				case TAGID_PARTITION_DESCRIPTOR:
346*0d383564STyler Dauwalder 				{
347*0d383564STyler Dauwalder 					udf_partition_descriptor *partition = reinterpret_cast<udf_partition_descriptor*>(tag);
348*0d383564STyler Dauwalder 					PDUMP(partition);
349*0d383564STyler Dauwalder 					if (partition->tag().init_check(block) == B_OK) {
350*0d383564STyler Dauwalder 						udf_partition_descriptor *current = fPartitionMap.Find(partition->partition_number());
351*0d383564STyler Dauwalder 						if (!current || current->vds_number() < partition->vds_number()) {
352*0d383564STyler Dauwalder 							PRINT(("adding partition #%d with vds_number %ld to partition map\n",
353*0d383564STyler Dauwalder 							       partition->partition_number(), partition->vds_number()));
354*0d383564STyler Dauwalder 							fPartitionMap.Add(partition);
355*0d383564STyler Dauwalder 						}
356*0d383564STyler Dauwalder 					}
357*0d383564STyler Dauwalder 					break;
358*0d383564STyler Dauwalder 				}
359*0d383564STyler Dauwalder 
360*0d383564STyler Dauwalder 				case TAGID_LOGICAL_VOLUME_DESCRIPTOR:
361*0d383564STyler Dauwalder 				{
362*0d383564STyler Dauwalder 					udf_logical_descriptor *logical = reinterpret_cast<udf_logical_descriptor*>(tag);
363*0d383564STyler Dauwalder 					PDUMP(logical);
364*0d383564STyler Dauwalder 					if (foundLogicalVD) {
365*0d383564STyler Dauwalder 						// Keep the vd with the highest vds_number
366*0d383564STyler Dauwalder 						if (logical->vds_number() > fLogicalVD.vds_number())
367*0d383564STyler Dauwalder 							fLogicalVD = *(logical);
368565457fdSTyler Dauwalder 					} else {
369*0d383564STyler Dauwalder 						fLogicalVD = *(logical);
370*0d383564STyler Dauwalder 						foundLogicalVD = true;
371*0d383564STyler Dauwalder 					}
372*0d383564STyler Dauwalder 					break;
373*0d383564STyler Dauwalder 				}
374*0d383564STyler Dauwalder 
375*0d383564STyler Dauwalder 				case TAGID_UNALLOCATED_SPACE_DESCRIPTOR:
376*0d383564STyler Dauwalder 				{
377*0d383564STyler Dauwalder 					udf_unallocated_space_descriptor *unallocated = reinterpret_cast<udf_unallocated_space_descriptor*>(tag);
378*0d383564STyler Dauwalder 					PDUMP(unallocated);
379*0d383564STyler Dauwalder 					break;
380*0d383564STyler Dauwalder 				}
381*0d383564STyler Dauwalder 
382*0d383564STyler Dauwalder 				case TAGID_TERMINATING_DESCRIPTOR:
383*0d383564STyler Dauwalder 				{
384*0d383564STyler Dauwalder 					udf_terminating_descriptor *terminating = reinterpret_cast<udf_terminating_descriptor*>(tag);
385*0d383564STyler Dauwalder 					PDUMP(terminating);
386*0d383564STyler Dauwalder 					break;
387*0d383564STyler Dauwalder 				}
388*0d383564STyler Dauwalder 
389*0d383564STyler Dauwalder 				case TAGID_LOGICAL_VOLUME_INTEGRITY_DESCRIPTOR:
390*0d383564STyler Dauwalder 					// Not found in this descriptor sequence
391*0d383564STyler Dauwalder 					break;
392*0d383564STyler Dauwalder 
393*0d383564STyler Dauwalder 				default:
394*0d383564STyler Dauwalder 					break;
395*0d383564STyler Dauwalder 
396565457fdSTyler Dauwalder 			}
397565457fdSTyler Dauwalder 		}
398565457fdSTyler Dauwalder 	}
3994ac73018STyler Dauwalder 
400*0d383564STyler Dauwalder 	status_t err = foundLogicalVD ? B_OK : B_ERROR;
401*0d383564STyler Dauwalder 	if (!err) {
402*0d383564STyler Dauwalder 		PRINT(("partition map:\n"));
403*0d383564STyler Dauwalder 		DUMP(fPartitionMap);
404*0d383564STyler Dauwalder 	}
405*0d383564STyler Dauwalder 	RETURN(err);
40629008bcfSTyler Dauwalder }
40729008bcfSTyler Dauwalder 
408*0d383564STyler Dauwalder status_t
409*0d383564STyler Dauwalder Volume::_InitFileSetDescriptor()
410*0d383564STyler Dauwalder {
411*0d383564STyler Dauwalder 	DEBUG_INIT(CF_PRIVATE | CF_VOLUME_OPS, "Volume");
412*0d383564STyler Dauwalder 	MemoryChunk chunk(fLogicalVD.file_set_address().length());
413*0d383564STyler Dauwalder 	udf_file_set_descriptor* fileSet = NULL;
414*0d383564STyler Dauwalder 
415*0d383564STyler Dauwalder 	udf_extent_address ad;
416*0d383564STyler Dauwalder 	ad.set_length(2048);
417*0d383564STyler Dauwalder 	ad.set_location(257);
418*0d383564STyler Dauwalder 	status_t err = chunk.InitCheck();
419*0d383564STyler Dauwalder 	if (!err)
420*0d383564STyler Dauwalder 		err = _Read(ad, fLogicalVD.file_set_address().length(), chunk.Data());
421*0d383564STyler Dauwalder //		err = _Read(fLogicalVD.file_set_address(), fLogicalVD.file_set_address().length(), fileSet);
422*0d383564STyler Dauwalder 	if (!err) {
423*0d383564STyler Dauwalder 		fileSet = reinterpret_cast<udf_file_set_descriptor*>(chunk.Data());
424*0d383564STyler Dauwalder 		fileSet->tag().init_check(0);
425*0d383564STyler Dauwalder 		PDUMP(fileSet);
426*0d383564STyler Dauwalder 	}
427*0d383564STyler Dauwalder 	return err;
428*0d383564STyler Dauwalder }