1//----------------------------------------------------------------------
2//  This software is part of the OpenBeOS distribution and is covered
3//  by the OpenBeOS license.
4//
5//  Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net
6//----------------------------------------------------------------------
7
8/*! \file UdfStructures.cpp
9
10	UDF on-disk data structure definitions
11*/
12
13#include "UdfStructures.h"
14
15#include <string.h>
16
17#include "UdfString.h"
18#include "Utils.h"
19
20using namespace Udf;
21
22//----------------------------------------------------------------------
23// Constants
24//----------------------------------------------------------------------
25
26const charspec Udf::kCs0CharacterSet(0, "OSTA Compressed Unicode");
27//const charspec kCs0Charspec = { _character_set_type: 0,
28//                                _character_set_info: "OSTA Compressed Unicode"
29//                                                    "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
30//                                                    "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
31//                              };
32
33// Volume structure descriptor ids
34const char* Udf::kVSDID_BEA 		= "BEA01";
35const char* Udf::kVSDID_TEA 		= "TEA01";
36const char* Udf::kVSDID_BOOT 		= "BOOT2";
37const char* Udf::kVSDID_ISO 		= "CD001";
38const char* Udf::kVSDID_ECMA167_2 	= "NSR02";
39const char* Udf::kVSDID_ECMA167_3 	= "NSR03";
40const char* Udf::kVSDID_ECMA168		= "CDW02";
41
42// entity_ids
43const entity_id Udf::kMetadataPartitionMapId(0, "*UDF Metadata Partition");
44const entity_id Udf::kSparablePartitionMapId(0, "*UDF Sparable Partition");
45const entity_id Udf::kVirtualPartitionMapId(0, "*UDF Virtual Partition");
46const entity_id Udf::kImplementationId(0, "*OpenBeOS UDF", implementation_id_suffix(OS_BEOS, BEOS_GENERIC));
47const entity_id Udf::kPartitionContentsId1xx(0, "+NSR02");
48const entity_id Udf::kPartitionContentsId2xx(0, "+NSR03");
49const entity_id Udf::kLogicalVolumeInfoId150(0, "*UDF LV Info", udf_id_suffix(0x0150, OS_BEOS, BEOS_GENERIC));
50const entity_id Udf::kLogicalVolumeInfoId201(0, "*UDF LV Info", udf_id_suffix(0x0201, OS_BEOS, BEOS_GENERIC));
51const entity_id Udf::kDomainId150(0, "*OSTA UDF Compliant", domain_id_suffix(0x0150,
52                                  DF_HARD_WRITE_PROTECT));
53const entity_id Udf::kDomainId201(0, "*OSTA UDF Compliant", domain_id_suffix(0x0201,
54                                  DF_HARD_WRITE_PROTECT));
55
56//! crc 010041 table, as generated by crc_table.cpp
57const uint16 Udf::kCrcTable[256] = {
58    0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
59    0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
60    0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
61    0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
62    0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
63    0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
64    0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
65    0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
66    0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
67    0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
68    0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
69    0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
70    0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
71    0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
72    0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
73    0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
74    0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
75    0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
76    0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
77    0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
78    0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
79    0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
80    0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
81    0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
82    0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
83    0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
84    0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
85    0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
86    0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
87    0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
88    0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
89    0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
90};
91
92const uint32 Udf::kLogicalVolumeDescriptorBaseSize = sizeof(logical_volume_descriptor)
93                                                     - (UDF_MAX_PARTITION_MAPS
94                                                        * UDF_MAX_PARTITION_MAP_SIZE);
95
96
97//----------------------------------------------------------------------
98// Helper functions
99//----------------------------------------------------------------------
100
101const char *Udf::tag_id_to_string(tag_id id)
102{
103	switch (id) {
104		case TAGID_UNDEFINED:
105			return "undefined";
106
107		case TAGID_PRIMARY_VOLUME_DESCRIPTOR:
108			return "primary volume descriptor";
109		case TAGID_ANCHOR_VOLUME_DESCRIPTOR_POINTER:
110			return "anchor volume descriptor pointer";
111		case TAGID_VOLUME_DESCRIPTOR_POINTER:
112			return "volume descriptor pointer";
113		case TAGID_IMPLEMENTATION_USE_VOLUME_DESCRIPTOR:
114			return "implementation use volume descriptor";
115		case TAGID_PARTITION_DESCRIPTOR:
116			return "partition descriptor";
117		case TAGID_LOGICAL_VOLUME_DESCRIPTOR:
118			return "logical volume descriptor";
119		case TAGID_UNALLOCATED_SPACE_DESCRIPTOR:
120			return "unallocated space descriptor";
121		case TAGID_TERMINATING_DESCRIPTOR:
122			return "terminating descriptor";
123		case TAGID_LOGICAL_VOLUME_INTEGRITY_DESCRIPTOR:
124			return "logical volume integrity descriptor";
125
126		case TAGID_FILE_SET_DESCRIPTOR:
127			return "file set descriptor";
128		case TAGID_FILE_ID_DESCRIPTOR:
129			return "file identifier descriptor";
130		case TAGID_ALLOCATION_EXTENT_DESCRIPTOR:
131			return "allocation extent descriptor";
132		case TAGID_INDIRECT_ENTRY:
133			return "indirect entry";
134		case TAGID_TERMINAL_ENTRY:
135			return "terminal entry";
136		case TAGID_FILE_ENTRY:
137			return "file entry";
138		case TAGID_EXTENDED_ATTRIBUTE_HEADER_DESCRIPTOR:
139			return "extended attribute header descriptor";
140		case TAGID_UNALLOCATED_SPACE_ENTRY:
141			return "unallocated space entry";
142		case TAGID_SPACE_BITMAP_DESCRIPTOR:
143			return "space bitmap descriptor";
144		case TAGID_PARTITION_INTEGRITY_ENTRY:
145			return "partition integrity entry";
146		case TAGID_EXTENDED_FILE_ENTRY:
147			return "extended file entry";
148
149		default:
150			if (TAGID_CUSTOM_START <= id && id <= TAGID_CUSTOM_END)
151				return "custom";
152			return "reserved";
153	}
154}
155
156
157//----------------------------------------------------------------------
158// volume_structure_descriptor_header
159//----------------------------------------------------------------------
160
161volume_structure_descriptor_header::volume_structure_descriptor_header(uint8 type, const char *_id, uint8 version)
162	: type(type)
163	, version(version)
164{
165	memcpy(id, _id, 5);
166}
167
168
169/*! \brief Returns true if the given \a id matches the header's id.
170*/
171bool
172volume_structure_descriptor_header::id_matches(const char *id)
173{
174	return strncmp(this->id, id, 5) == 0;
175}
176
177
178//----------------------------------------------------------------------
179// charspec
180//----------------------------------------------------------------------
181
182charspec::charspec(uint8 type, const char *info)
183{
184	set_character_set_type(type);
185	set_character_set_info(info);
186}
187
188void
189charspec::dump() const
190{
191	DUMP_INIT("charspec");
192	PRINT(("character_set_type: %d\n", character_set_type()));
193	PRINT(("character_set_info: `%s'\n", character_set_info()));
194}
195
196void
197charspec::set_character_set_info(const char *info)
198{
199	memset(_character_set_info, 0, 63);
200	if (info)
201		strncpy(_character_set_info, info, 63);
202}
203
204//----------------------------------------------------------------------
205// timestamp
206//----------------------------------------------------------------------
207
208#if _KERNEL_MODE
209static
210int
211get_month_length(int month, int year)
212{
213	if (0 <= month && month < 12 && year >= 1970) {
214		const int monthLengths[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
215		int result = monthLengths[month];
216		if (month == 1 && ((year - 1968) % 4 == 0))
217			result++;
218		return result;
219	} else {
220		DEBUG_INIT_ETC(NULL, ("month: %d, year: %d", month, year));
221		PRINT(("Invalid month or year! Returning 0\n"));
222		return 0;
223	}
224}
225#endif
226
227timestamp::timestamp(time_t time)
228{
229#if !_KERNEL_MODE
230	// Is it me, or is localtime() broken?
231	tm *local = localtime(&time);
232	if (local) {
233		set_microsecond(0);
234		set_hundred_microsecond(0);
235		set_centisecond(0);
236		set_second(local->tm_sec);
237		set_minute(local->tm_min);
238		set_hour(local->tm_hour);
239		set_day(local->tm_mday);
240		set_month(local->tm_mon+1);
241		set_year(local->tm_year+1900);
242		set_type(1);
243		set_timezone(local->tm_gmtoff / 60);
244	} else {
245		_clear();
246	}
247#else	// no localtime() in the R5 kernel...
248	// real_time_clock() is returning the time offset by -16 hours.
249	// Considering I'm -8 hours from GMT, this doesn't really make
250	// sense. For the moment I'm offsetting it manually here, but
251	// I'm not sure what the freaking deal is, and unfortunately,
252	// localtime() appears to be broken...
253	time += 16 * 60 * 60;
254
255	set_microsecond(0);
256	set_hundred_microsecond(0);
257	set_centisecond(0);
258	set_second(time % 60);
259	time = time / 60;	// convert to minutes
260	set_minute(time % 60);
261	time = time / 60;	// convert to hours
262	set_hour(time % 24);
263	time = time / 24;	// convert to days
264
265	// From here we start at time == 0 and count up
266	// by days until we figure out what the day, month,
267	// and year are.
268	int year = 0;
269	int month = 0;
270	time_t clock = 0;
271	for (clock = 0;
272	       clock + get_month_length(month, year+1970) < time;
273	         clock += get_month_length(month, year+1970))
274	{
275		month++;
276		if (month == 12) {
277			year++;
278			month = 0;
279		}
280	}
281	int day = time - clock;
282	set_day(day);
283	set_month(month+1);
284	set_year(year+1970);
285	set_type(1);
286	set_timezone(-2047); // -2047 == no timezone specified
287#endif
288}
289
290void
291timestamp::dump() const
292{
293	DUMP_INIT("timestamp");
294	PRINT(("type:                %d\n", type()));
295	PRINT(("timezone:            %d\n", timezone()));
296	PRINT(("year:                %d\n", year()));
297	PRINT(("month:               %d\n", month()));
298	PRINT(("day:                 %d\n", day()));
299	PRINT(("hour:                %d\n", hour()));
300	PRINT(("minute:              %d\n", minute()));
301	PRINT(("second:              %d\n", second()));
302	PRINT(("centisecond:         %d\n", centisecond()));
303	PRINT(("hundred_microsecond: %d\n", hundred_microsecond()));
304	PRINT(("microsecond:         %d\n", microsecond()));
305}
306
307void
308timestamp::_clear()
309{
310	set_microsecond(0);
311	set_hundred_microsecond(0);
312	set_centisecond(0);
313	set_second(0);
314	set_minute(0);
315	set_hour(0);
316	set_day(0);
317	set_month(0);
318	set_year(0);
319	set_type(0);
320	set_timezone(0);
321}
322
323//----------------------------------------------------------------------
324// udf_id_suffix
325//----------------------------------------------------------------------
326
327udf_id_suffix::udf_id_suffix(uint16 udfRevision, uint8 os_class,
328                             uint8 os_identifier)
329	: _udf_revision(udfRevision)
330	, _os_class(os_class)
331	, _os_identifier(os_identifier)
332{
333	memset(_reserved.data, 0, _reserved.size());
334}
335
336//----------------------------------------------------------------------
337// implementation_id_suffix
338//----------------------------------------------------------------------
339
340implementation_id_suffix::implementation_id_suffix(uint8 os_class,
341                                                   uint8 os_identifier)
342	: _os_class(os_class)
343	, _os_identifier(os_identifier)
344{
345	memset(_implementation_use.data, 0, _implementation_use.size());
346}
347
348//----------------------------------------------------------------------
349// domain_id_suffix
350//----------------------------------------------------------------------
351
352domain_id_suffix::domain_id_suffix(uint16 udfRevision, uint8 domainFlags)
353	: _udf_revision(udfRevision)
354	, _domain_flags(domainFlags)
355{
356	memset(_reserved.data, 0, _reserved.size());
357}
358
359//----------------------------------------------------------------------
360// entity_id
361//----------------------------------------------------------------------
362
363entity_id::entity_id(uint8 flags, char *identifier, uint8 *identifier_suffix)
364	: _flags(flags)
365{
366	memset(_identifier, 0, kIdentifierLength);
367	if (identifier)
368		strncpy(_identifier, identifier, kIdentifierLength);
369	if (identifier_suffix)
370		memcpy(_identifier_suffix.data, identifier_suffix, kIdentifierSuffixLength);
371	else
372		memset(_identifier_suffix.data, 0, kIdentifierSuffixLength);
373}
374
375entity_id::entity_id(uint8 flags, char *identifier,
376	                 const udf_id_suffix &suffix)
377	: _flags(flags)
378{
379	memset(_identifier, 0, kIdentifierLength);
380	if (identifier)
381		strncpy(_identifier, identifier, kIdentifierLength);
382	memcpy(_identifier_suffix.data, &suffix, kIdentifierSuffixLength);
383}
384
385entity_id::entity_id(uint8 flags, char *identifier,
386	                 const implementation_id_suffix &suffix)
387	: _flags(flags)
388{
389	memset(_identifier, 0, kIdentifierLength);
390	if (identifier)
391		strncpy(_identifier, identifier, kIdentifierLength);
392	memcpy(_identifier_suffix.data, &suffix, kIdentifierSuffixLength);
393}
394
395entity_id::entity_id(uint8 flags, char *identifier,
396	                 const domain_id_suffix &suffix)
397	: _flags(flags)
398{
399	memset(_identifier, 0, kIdentifierLength);
400	if (identifier)
401		strncpy(_identifier, identifier, kIdentifierLength);
402	memcpy(_identifier_suffix.data, &suffix, kIdentifierSuffixLength);
403}
404
405void
406entity_id::dump() const
407{
408	DUMP_INIT("entity_id");
409	PRINT(("flags:             %d\n", flags()));
410	PRINT(("identifier:        `%.23s'\n", identifier()));
411	PRINT(("identifier_suffix:\n"));
412	DUMP(identifier_suffix());
413}
414
415bool
416entity_id::matches(const entity_id &id) const
417{
418	bool result = true;
419	for (int i = 0; i < entity_id::kIdentifierLength; i++) {
420		if (identifier()[i] != id.identifier()[i]) {
421			result = false;
422			break;
423		}
424	}
425	return result;
426}
427
428//----------------------------------------------------------------------
429// extent_address
430//----------------------------------------------------------------------
431
432extent_address::extent_address(uint32 location, uint32 length)
433{
434	set_location(location);
435	set_length(length);
436}
437
438void
439extent_address::dump() const
440{
441	DUMP_INIT("extent_address");
442	PRINT(("length:   %ld\n", length()));
443	PRINT(("location: %ld\n", location()));
444}
445
446//----------------------------------------------------------------------
447// logical_block_address
448//----------------------------------------------------------------------
449
450void
451logical_block_address::dump() const
452{
453	DUMP_INIT("logical_block_address");
454	PRINT(("block:     %ld\n", block()));
455	PRINT(("partition: %d\n", partition()));
456}
457
458logical_block_address::logical_block_address(uint16 partition, uint32 block)
459{
460	set_partition(partition);
461	set_block(block);
462}
463
464//----------------------------------------------------------------------
465// long_address
466//----------------------------------------------------------------------
467
468long_address::long_address(uint16 partition, uint32 block, uint32 length,
469	                       uint8 type)
470{
471	set_partition(partition);
472	set_block(block);
473	set_length(length);
474	set_type(type);
475	memset(_implementation_use.data, 0, _implementation_use.size());
476}
477
478void
479long_address::dump() const
480{
481	DUMP_INIT("long_address");
482	PRINT(("length:   %ld\n", length()));
483	PRINT(("block:    %ld\n", block()));
484	PRINT(("partition: %d\n", partition()));
485	PRINT(("implementation_use:\n"));
486	DUMP(implementation_use());
487}
488
489//----------------------------------------------------------------------
490// descriptor_tag
491//----------------------------------------------------------------------
492
493void
494descriptor_tag::dump() const
495{
496	DUMP_INIT("descriptor_tag");
497	PRINT(("id:            %d (%s)\n", id(), tag_id_to_string(tag_id(id()))));
498	PRINT(("version:       %d\n", version()));
499	PRINT(("checksum:      %d\n", checksum()));
500	PRINT(("serial_number: %d\n", serial_number()));
501	PRINT(("crc:           %d\n", crc()));
502	PRINT(("crc_length:    %d\n", crc_length()));
503	PRINT(("location:      %ld\n", location()));
504}
505
506
507/*! \brief Calculates the tag's CRC, verifies the tag's checksum, and
508	verifies the tag's location on the medium.
509
510	Note that this function makes the assumption that the descriptor_tag
511	is the first data member in a larger descriptor structure, the remainder
512	of which immediately follows the descriptor_tag itself in memory. This
513	is generally a safe assumption, as long as the entire descriptor (and
514	not the its tag) is read in before init_check() is called. If this is
515	not the case, it's best to call this function with a \a calculateCrc
516	value of false, to keep from trying to calculate a crc value on invalid
517	and possibly unowned memory.
518
519	\param block The block location of this descriptor as taken from the
520	             corresponding allocation descriptor. If the address specifies
521	             a block in a partition, the partition block is the desired
522	             location, not the mapped physical disk block.
523	\param calculateCrc Whether or not to perform the crc calculation
524	                    on the descriptor data following the tag.
525*/
526status_t
527descriptor_tag::init_check(uint32 block, bool calculateCrc)
528{
529	DEBUG_INIT_ETC("descriptor_tag", ("location: %ld, calculateCrc: %s",
530	               block, bool_to_string(calculateCrc)));
531	PRINT(("location   (paramater)    == %ld\n", block));
532	PRINT(("location   (in structure) == %ld\n", location()));
533	if (calculateCrc) {
534		PRINT(("crc        (calculated)   == %d\n",
535		       Udf::calculate_crc(reinterpret_cast<uint8*>(this)+sizeof(descriptor_tag),
536		       crc_length())))
537	} else {
538		PRINT(("crc        (calculated)   == (not calculated)\n"));
539	}
540	PRINT(("crc        (in structure) == %d\n", crc()));
541	PRINT(("crc_length (in structure) == %d\n", crc_length()));
542	// location
543	status_t error = (block == location()) ? B_OK : B_NO_INIT;
544	// checksum
545	if (!error) {
546		uint32 sum = 0;
547		for (int i = 0; i <= 3; i++)
548			sum += reinterpret_cast<uint8*>(this)[i];
549		for (int i = 5; i <= 15; i++)
550			sum += reinterpret_cast<uint8*>(this)[i];
551		error = sum % 256 == checksum() ? B_OK : B_NO_INIT;
552	}
553	// crc
554	if (!error && calculateCrc) {
555		uint16 _crc = Udf::calculate_crc(reinterpret_cast<uint8*>(this)
556		               + sizeof(descriptor_tag), crc_length());
557		error = _crc == crc() ? B_OK : B_NO_INIT;
558	}
559	RETURN(error);
560}
561
562//----------------------------------------------------------------------
563// primary_volume_descriptor
564//----------------------------------------------------------------------
565
566void
567primary_volume_descriptor::dump() const
568{
569	DUMP_INIT("primary_volume_descriptor");
570
571	String string;
572
573	PRINT(("tag:\n"));
574	DUMP(tag());
575	PRINT(("vds_number:                       %ld\n", vds_number()));
576	PRINT(("primary_volume_descriptor_number: %ld\n", primary_volume_descriptor_number()));
577	string = volume_identifier();
578	PRINT(("volume_identifier:                `%s'\n", string.Utf8()));
579	PRINT(("volume_sequence_number:           %d\n", volume_sequence_number()));
580	PRINT(("max_volume_sequence_number:       %d\n", max_volume_sequence_number()));
581	PRINT(("interchange_level:                %d\n", interchange_level()));
582	PRINT(("max_interchange_level:            %d\n", max_interchange_level()));
583	PRINT(("character_set_list:               %ld\n", character_set_list()));
584	PRINT(("max_character_set_list:           %ld\n", max_character_set_list()));
585	string = volume_set_identifier();
586	PRINT(("volume_set_identifier:            `%s'\n", string.Utf8()));
587	PRINT(("descriptor_character_set:\n"));
588	DUMP(descriptor_character_set());
589	PRINT(("explanatory_character_set:\n"));
590	DUMP(explanatory_character_set());
591	PRINT(("volume_abstract:\n"));
592	DUMP(volume_abstract());
593	PRINT(("volume_copyright_notice:\n"));
594	DUMP(volume_copyright_notice());
595	PRINT(("application_id:\n"));
596	DUMP(application_id());
597	PRINT(("recording_date_and_time:\n"));
598	DUMP(recording_date_and_time());
599	PRINT(("implementation_id:\n"));
600	DUMP(implementation_id());
601	PRINT(("implementation_use:\n"));
602	DUMP(implementation_use());
603	PRINT(("predecessor_vds_location:         %ld\n",
604	       predecessor_volume_descriptor_sequence_location()));
605	PRINT(("flags:                            %d\n", flags()));
606}
607
608
609//----------------------------------------------------------------------
610// anchor_volume_descriptor_pointer
611//----------------------------------------------------------------------
612
613void
614anchor_volume_descriptor::dump() const
615{
616	DUMP_INIT("anchor_volume_descriptor");
617	PRINT(("tag:\n"));
618	DUMP(tag());
619	PRINT(("main_vds:\n"));
620	DUMP(main_vds());
621	PRINT(("reserve_vds:\n"));
622	DUMP(reserve_vds());
623}
624
625//----------------------------------------------------------------------
626// logical_volume_info
627//----------------------------------------------------------------------
628
629void
630logical_volume_info::dump() const
631{
632	String string;
633	DUMP_INIT("logical_volume_information");
634	PRINT(("character_set:\n"));
635	DUMP(character_set());
636	string = logical_volume_id();
637	PRINT(("logical_volume_id: `%s'\n", string.Utf8()));
638	for (uint32 i = 0; i < _logical_volume_info.length(); i++) {
639		string = _logical_volume_info[i];
640		PRINT(("logical_volume_info #%ld: %s\n", i, string.Utf8()));
641	}
642	PRINT(("implementation_id:\n"));
643	DUMP(implementation_id());
644	PRINT(("implementation_use:\n"));
645	DUMP(implementation_use());
646}
647
648//----------------------------------------------------------------------
649// implementation_use_descriptor
650//----------------------------------------------------------------------
651
652void
653implementation_use_descriptor::dump() const
654{
655	DUMP_INIT("implementation_use_descriptor");
656	PRINT(("tag:\n"));
657	DUMP(tag());
658	PRINT(("vds_number: %ld\n", vds_number()));
659	PRINT(("implementation_id:\n"));
660	DUMP(implementation_id());
661	PRINT(("implementation_use: XXX\n"));
662	DUMP(implementation_use());
663}
664
665//----------------------------------------------------------------------
666// partition_descriptor
667//----------------------------------------------------------------------
668
669const uint8 Udf::kMaxPartitionDescriptors = 2;
670
671void
672partition_descriptor::dump() const
673{
674	DUMP_INIT("partition_descriptor");
675	PRINT(("tag:\n"));
676	DUMP(tag());
677	PRINT(("vds_number:                %ld\n", vds_number()));
678	PRINT(("partition_flags:           %d\n", partition_flags()));
679	PRINT(("partition_flags.allocated: %s\n", allocated() ? "true" : "false"));
680	PRINT(("partition_number:          %d\n", partition_number()));
681	PRINT(("partition_contents:\n"));
682	DUMP(partition_contents());
683	PRINT(("partition_contents_use:    XXX\n"));
684	DUMP(partition_contents_use());
685	PRINT(("access_type:               %ld\n", access_type()));
686	PRINT(("start:                     %ld\n", start()));
687	PRINT(("length:                    %ld\n", length()));
688	PRINT(("implementation_id:\n"));
689	DUMP(implementation_id());
690	PRINT(("implementation_use:        XXX\n"));
691	DUMP(implementation_use());
692}
693
694//----------------------------------------------------------------------
695// logical_volume_descriptor
696//----------------------------------------------------------------------
697
698void
699logical_volume_descriptor::dump() const
700{
701	DUMP_INIT("logical_volume_descriptor");
702	PRINT(("tag:\n"));
703	DUMP(tag());
704	PRINT(("vds_number:                %ld\n", vds_number()));
705	PRINT(("character_set:\n"));
706	DUMP(character_set());
707	String string(logical_volume_identifier());
708	PRINT(("logical_volume_identifier: `%s'\n", string.Utf8()));
709	PRINT(("logical_block_size:        %ld\n", logical_block_size()));
710	PRINT(("domain_id:\n"));
711	DUMP(domain_id());
712	PRINT(("logical_volume_contents_use:\n"));
713	DUMP(logical_volume_contents_use());
714	PRINT(("file_set_address:\n"));
715	DUMP(file_set_address());
716	PRINT(("map_table_length:          %ld\n", map_table_length()));
717	PRINT(("partition_map_count:       %ld\n", partition_map_count()));
718	PRINT(("implementation_id:\n"));
719	DUMP(implementation_id());
720	PRINT(("implementation_use:\n"));
721	DUMP(implementation_use());
722	PRINT(("integrity_sequence_extent:\n"));
723	DUMP(integrity_sequence_extent());
724//	PRINT(("partition_maps:\n"));
725	const uint8 *maps = partition_maps();
726	int offset = 0;
727	for (uint i = 0; i < partition_map_count(); i++) {
728		PRINT(("partition_map #%d:\n", i));
729		uint8 type = maps[offset];
730		uint8 length = maps[offset+1];
731		PRINT(("  type: %d\n", type));
732		PRINT(("  length: %d\n", length));
733		switch (type) {
734			case 1:
735				for (int j = 0; j < length-2; j++)
736					PRINT(("  data[%d]: %d\n", j, maps[offset+2+j]));
737				break;
738			case 2: {
739				PRINT(("  partition_number: %d\n", *reinterpret_cast<const uint16*>(&(maps[offset+38]))));
740				PRINT(("  entity_id:\n"));
741				const entity_id *id = reinterpret_cast<const entity_id*>(&(maps[offset+4]));
742				if (id)	// To kill warning when DEBUG==0
743					PDUMP(id);
744				break;
745			}
746		}
747		offset += maps[offset+1];
748	}
749	// \todo dump partition_maps
750}
751
752
753logical_volume_descriptor&
754logical_volume_descriptor::operator=(const logical_volume_descriptor &rhs)
755{
756	_tag = rhs._tag;
757	_vds_number = rhs._vds_number;
758	_character_set = rhs._character_set;
759	_logical_volume_identifier = rhs._logical_volume_identifier;
760	_logical_block_size = rhs._logical_block_size;
761	_domain_id = rhs._domain_id;
762	_logical_volume_contents_use = rhs._logical_volume_contents_use;
763	_map_table_length = rhs._map_table_length;
764	_partition_map_count = rhs._partition_map_count;
765	_implementation_id = rhs._implementation_id;
766	_implementation_use = rhs._implementation_use;
767	_integrity_sequence_extent = rhs._integrity_sequence_extent;
768	// copy the partition maps one by one
769	uint8 *lhsMaps = partition_maps();
770	const uint8 *rhsMaps = rhs.partition_maps();
771	int offset = 0;
772	for (uint8 i = 0; i < rhs.partition_map_count(); i++) {
773		uint8 length = rhsMaps[offset+1];
774		memcpy(&lhsMaps[offset], &rhsMaps[offset], length);
775		offset += length;
776	}
777	return *this;
778}
779
780
781//----------------------------------------------------------------------
782// physical_partition_map
783//----------------------------------------------------------------------
784
785void
786physical_partition_map::dump()
787{
788	DUMP_INIT("physical_partition_map");
789	PRINT(("type: %d\n", type()));
790	PRINT(("length: %d\n", length()));
791	PRINT(("volume_sequence_number: %d\n", volume_sequence_number()));
792	PRINT(("partition_number: %d\n", partition_number()));
793}
794
795//----------------------------------------------------------------------
796// sparable_partition_map
797//----------------------------------------------------------------------
798
799void
800sparable_partition_map::dump()
801{
802	DUMP_INIT("sparable_partition_map");
803	PRINT(("type: %d\n", type()));
804	PRINT(("length: %d\n", length()));
805	PRINT(("partition_type_id:"));
806	DUMP(partition_type_id());
807	PRINT(("volume_sequence_number: %d\n", volume_sequence_number()));
808	PRINT(("partition_number: %d\n", partition_number()));
809	PRINT(("sparing_table_count: %d\n", sparing_table_count()));
810	PRINT(("sparing_table_size: %ld\n", sparing_table_size()));
811	PRINT(("sparing_table_locations:"));
812	for (uint8 i = 0; i < sparing_table_count(); i++)
813		PRINT(("  %d: %ld\n", i, sparing_table_location(i)));
814}
815
816//----------------------------------------------------------------------
817// unallocated_space_descriptor
818//----------------------------------------------------------------------
819
820void
821unallocated_space_descriptor::dump() const
822{
823	DUMP_INIT("unallocated_space_descriptor");
824	PRINT(("tag:\n"));
825	DUMP(tag());
826	PRINT(("vds_number:                  %ld\n", vds_number()));
827	PRINT(("allocation_descriptor_count: %ld\n", allocation_descriptor_count()));
828	// \todo dump alloc_descriptors
829}
830
831
832//----------------------------------------------------------------------
833// terminating_descriptor
834//----------------------------------------------------------------------
835
836void
837terminating_descriptor::dump() const
838{
839	DUMP_INIT("terminating_descriptor");
840	PRINT(("tag:\n"));
841	DUMP(tag());
842}
843
844//----------------------------------------------------------------------
845// file_set_descriptor
846//----------------------------------------------------------------------
847
848void
849file_set_descriptor::dump() const
850{
851	DUMP_INIT("file_set_descriptor");
852	PRINT(("tag:\n"));
853	DUMP(tag());
854	PRINT(("recording_date_and_time:\n"));
855	DUMP(recording_date_and_time());
856	PRINT(("interchange_level: %d\n", interchange_level()));
857	PRINT(("max_interchange_level: %d\n", max_interchange_level()));
858	PRINT(("character_set_list: %ld\n", character_set_list()));
859	PRINT(("max_character_set_list: %ld\n", max_character_set_list()));
860	PRINT(("file_set_number: %ld\n", file_set_number()));
861	PRINT(("file_set_descriptor_number: %ld\n", file_set_descriptor_number()));
862	PRINT(("logical_volume_id_character_set:\n"));
863	DUMP(logical_volume_id_character_set());
864	PRINT(("logical_volume_id:\n"));
865	DUMP(logical_volume_id());
866	PRINT(("file_set_id_character_set:\n"));
867	DUMP(file_set_id_character_set());
868	PRINT(("file_set_id:\n"));
869	DUMP(file_set_id());
870	PRINT(("copyright_file_id:\n"));
871	DUMP(copyright_file_id());
872	PRINT(("abstract_file_id:\n"));
873	DUMP(abstract_file_id());
874	PRINT(("root_directory_icb:\n"));
875	DUMP(root_directory_icb());
876	PRINT(("domain_id:\n"));
877	DUMP(domain_id());
878	PRINT(("next_extent:\n"));
879	DUMP(next_extent());
880	PRINT(("system_stream_directory_icb:\n"));
881	DUMP(system_stream_directory_icb());
882}
883
884//----------------------------------------------------------------------
885// logical_volume_integrity_descriptor
886//----------------------------------------------------------------------
887
888void
889logical_volume_integrity_descriptor::dump() const
890{
891	DUMP_INIT("logical_volume_integrity_descriptor");
892	PRINT(("tag:\n"));
893	DUMP(tag());
894	PRINT(("recording_time:\n"));
895	DUMP(recording_time());
896	PRINT(("integrity_type:             "));
897	switch (integrity_type()) {
898		case INTEGRITY_OPEN:
899			SIMPLE_PRINT(("open\n"));
900			break;
901		case INTEGRITY_CLOSED:
902			SIMPLE_PRINT(("closed\n"));
903			break;
904		default:
905			SIMPLE_PRINT(("invalid integrity type (%ld)", integrity_type()));
906			break;
907	}
908	PRINT(("next_integrity_extent:\n"));
909	DUMP(next_integrity_extent());
910	PRINT(("logical_volume_contents_use:\n"));
911	DUMP(logical_volume_contents_use());
912	PRINT(("next_unique_id:             %Ld\n", next_unique_id()));
913	PRINT(("partition_count:            %ld\n", partition_count()));
914	PRINT(("implementation_use_length:  %ld\n", implementation_use_length()));
915	if (partition_count() > 0) {
916		PRINT(("free_space_table:\n"));
917		for (uint32 i = 0; i < partition_count(); i++) {
918			PRINT(("partition %ld: %ld free blocks\n", i, free_space_table()[i]));
919		}
920		PRINT(("size_table:\n"));
921		for (uint32 i = 0; i < partition_count(); i++) {
922			PRINT(("partition %ld: %ld blocks large\n", i, size_table()[i]));
923		}
924	}
925
926	if (implementation_use_length() >= minimum_implementation_use_length) {
927		PRINT(("implementation_id:\n"));
928		DUMP(implementation_id());
929		PRINT(("file_count:                 %ld\n", file_count()));
930		PRINT(("directory_count:            %ld\n", directory_count()));
931		PRINT(("minimum_udf_read_revision:  0x%04x\n", minimum_udf_read_revision()));
932		PRINT(("minimum_udf_write_revision: 0x%04x\n", minimum_udf_write_revision()));
933		PRINT(("maximum_udf_write_revision: 0x%04x\n", maximum_udf_write_revision()));
934	} else {
935		PRINT(("NOTE: implementation_use() field of insufficient length to contain \n"));
936		PRINT(("      appropriate UDF-2.50 2.2.6.4 fields.\n"));
937	}
938}
939
940//----------------------------------------------------------------------
941// file_id_descriptor
942//----------------------------------------------------------------------
943
944void
945file_id_descriptor::dump() const
946{
947	DUMP_INIT("file_id_descriptor");
948	PRINT(("tag:\n"));
949	DUMP(tag());
950	PRINT(("version_number:            %d\n", version_number()));
951	PRINT(("may_be_hidden:             %d\n", may_be_hidden()));
952	PRINT(("is_directory:              %d\n", is_directory()));
953	PRINT(("is_deleted:                %d\n", is_deleted()));
954	PRINT(("is_parent:                 %d\n", is_parent()));
955	PRINT(("is_metadata_stream:        %d\n", is_metadata_stream()));
956	PRINT(("id_length:                 %d\n", id_length()));
957	PRINT(("icb:\n"));
958	DUMP(icb());
959	PRINT(("implementation_use_length: %d\n", is_parent()));
960	String fileId(id());
961	PRINT(("id: `%s'", fileId.Utf8()));
962}
963
964//----------------------------------------------------------------------
965// icb_entry_tag
966//----------------------------------------------------------------------
967
968void
969icb_entry_tag::dump() const
970{
971	DUMP_INIT("icb_entry_tag");
972	PRINT(("prior_entries: %ld\n", prior_recorded_number_of_direct_entries()));
973	PRINT(("strategy_type: %d\n", strategy_type()));
974	PRINT(("strategy_parameters:\n"));
975	DUMP(strategy_parameters());
976	PRINT(("entry_count: %d\n", entry_count()));
977	PRINT(("file_type: %d\n", file_type()));
978	PRINT(("parent_icb_location:\n"));
979	DUMP(parent_icb_location());
980	PRINT(("all_flags: %d\n", flags()));
981
982/*
983	uint32 prior_recorded_number_of_direct_entries;
984	uint16 strategy_type;
985	array<uint8, 2> strategy_parameters;
986	uint16 entry_count;
987	uint8 reserved;
988	uint8 file_type;
989	logical_block_address parent_icb_location;
990	union {
991		uint16 all_flags;
992		struct {
993			uint16	descriptor_flags:3,
994					if_directory_then_sort:1,	//!< To be set to 0 per UDF-2.01 2.3.5.4
995					non_relocatable:1,
996					archive:1,
997					setuid:1,
998					setgid:1,
999					sticky:1,
1000					contiguous:1,
1001					system:1,
1002					transformed:1,
1003					multi_version:1,			//!< To be set to 0 per UDF-2.01 2.3.5.4
1004					is_stream:1,
1005					reserved_icb_entry_flags:2;
1006		} flags;
1007	};
1008
1009*/
1010
1011}
1012
1013//----------------------------------------------------------------------
1014// icb_header
1015//----------------------------------------------------------------------
1016
1017void
1018icb_header::dump() const
1019{
1020	DUMP_INIT("icb_header");
1021
1022	PRINT(("tag:\n"));
1023	DUMP(tag());
1024	PRINT(("icb_tag:\n"));
1025	DUMP(icb_tag());
1026
1027}
1028
1029//----------------------------------------------------------------------
1030// file_icb_entry
1031//----------------------------------------------------------------------
1032
1033long_address file_icb_entry::_dummy_stream_directory_icb;
1034
1035void
1036file_icb_entry::dump() const
1037{
1038	DUMP_INIT("file_icb_entry");
1039
1040	PRINT(("tag:\n"));
1041	DUMP(tag());
1042	PRINT(("icb_tag:\n"));
1043	DUMP(icb_tag());
1044
1045	PRINT(("uid:                       %lu, 0x%lx\n", uid(), uid()));
1046	PRINT(("gid:                       %lu, 0x%lx\n", gid(), gid()));
1047	PRINT(("permissions:               %ld, 0x%lx\n", permissions(), permissions()));
1048	PRINT(("file_link_count:           %d\n", file_link_count()));
1049	PRINT(("record_format:             %d\n", record_format()));
1050	PRINT(("record_display_attributes: %d\n", record_display_attributes()));
1051	PRINT(("record_length:             %d\n", record_length()));
1052	PRINT(("information_length:        %Ld\n", information_length()));
1053	PRINT(("logical_blocks_recorded:   %Ld\n", logical_blocks_recorded()));
1054	PRINT(("access_date_and_time:\n"));
1055	DUMP(access_date_and_time());
1056	PRINT(("modification_date_and_time:\n"));
1057	DUMP(modification_date_and_time());
1058	PRINT(("attribute_date_and_time:\n"));
1059	DUMP(attribute_date_and_time());
1060	PRINT(("checkpoint:                %ld\n", checkpoint()));
1061
1062	PRINT(("extended_attribute_icb:\n"));
1063	DUMP(extended_attribute_icb());
1064	PRINT(("implementation_id:\n"));
1065	DUMP(implementation_id());
1066
1067	PRINT(("unique_id: %Ld\n", unique_id()));
1068	PRINT(("extended_attributes_length:    %ld\n", extended_attributes_length()));
1069	PRINT(("allocation_descriptors_length: %ld\n", allocation_descriptors_length()));
1070
1071	PRINT(("allocation_descriptors:\n"));
1072	switch (icb_tag().descriptor_flags()) {
1073		case ICB_DESCRIPTOR_TYPE_SHORT:
1074			PRINT(("  short descriptors...\n"));
1075			break;
1076		case ICB_DESCRIPTOR_TYPE_LONG:
1077		{
1078			const long_address *address = reinterpret_cast<const long_address*>(allocation_descriptors());
1079			for (uint32 length = allocation_descriptors_length();
1080				   length >= sizeof(long_address);
1081				     length -= sizeof(long_address), address++)
1082			{
1083				PDUMP(address);
1084			}
1085			break;
1086		}
1087		case ICB_DESCRIPTOR_TYPE_EXTENDED:
1088			PRINT(("  extended descriptors...\n"));
1089			break;
1090		case ICB_DESCRIPTOR_TYPE_EMBEDDED:
1091			PRINT(("  embedded descriptors...\n"));
1092			break;
1093		default:
1094			PRINT(("  invalid descriptors type\n"));
1095			break;
1096	}
1097}
1098
1099//----------------------------------------------------------------------
1100// extended_file_icb_entry
1101//----------------------------------------------------------------------
1102
1103void
1104extended_file_icb_entry::dump() const
1105{
1106	DUMP_INIT("extended_file_icb_entry");
1107
1108	PRINT(("tag:\n"));
1109	DUMP(tag());
1110	PRINT(("icb_tag:\n"));
1111	DUMP(icb_tag());
1112
1113	PRINT(("uid:                       %lu, 0x%lx\n", uid(), uid()));
1114	PRINT(("gid:                       %lu, 0x%lx\n", gid(), gid()));
1115	PRINT(("permissions:               %ld, 0x%lx\n", permissions(), permissions()));
1116	PRINT(("file_link_count:           %d\n", file_link_count()));
1117	PRINT(("record_format:             %d\n", record_format()));
1118	PRINT(("record_display_attributes: %d\n", record_display_attributes()));
1119	PRINT(("record_length:             %ld\n", record_length()));
1120	PRINT(("information_length:        %Ld\n", information_length()));
1121	PRINT(("logical_blocks_recorded:   %Ld\n", logical_blocks_recorded()));
1122	PRINT(("access_date_and_time:\n"));
1123	DUMP(access_date_and_time());
1124	PRINT(("modification_date_and_time:\n"));
1125	DUMP(modification_date_and_time());
1126	PRINT(("creation_date_and_time:\n"));
1127	DUMP(creation_date_and_time());
1128	PRINT(("attribute_date_and_time:\n"));
1129	DUMP(attribute_date_and_time());
1130	PRINT(("checkpoint:                %ld\n", checkpoint()));
1131
1132	PRINT(("extended_attribute_icb:\n"));
1133	DUMP(extended_attribute_icb());
1134	PRINT(("stream_directory_icb:\n"));
1135	DUMP(stream_directory_icb());
1136	PRINT(("implementation_id:\n"));
1137	DUMP(implementation_id());
1138
1139	PRINT(("unique_id: %Ld\n", unique_id()));
1140	PRINT(("extended_attributes_length:    %ld\n", extended_attributes_length()));
1141	PRINT(("allocation_descriptors_length: %ld\n", allocation_descriptors_length()));
1142
1143	PRINT(("allocation_descriptors:\n"));
1144	switch (icb_tag().descriptor_flags()) {
1145		case ICB_DESCRIPTOR_TYPE_SHORT:
1146			PRINT(("  short descriptors...\n"));
1147			break;
1148		case ICB_DESCRIPTOR_TYPE_LONG:
1149		{
1150			const long_address *address = reinterpret_cast<const long_address*>(allocation_descriptors());
1151			for (uint32 length = allocation_descriptors_length();
1152				   length >= sizeof(long_address);
1153				     length -= sizeof(long_address), address++)
1154			{
1155				PDUMP(address);
1156			}
1157			break;
1158		}
1159		case ICB_DESCRIPTOR_TYPE_EXTENDED:
1160			PRINT(("  extended descriptors...\n"));
1161			break;
1162		case ICB_DESCRIPTOR_TYPE_EMBEDDED:
1163			PRINT(("  embedded descriptors...\n"));
1164			break;
1165		default:
1166			PRINT(("  invalid descriptors type\n"));
1167			break;
1168	}
1169}
1170