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