xref: /haiku/src/add-ons/kernel/file_systems/udf/UdfStructures.cpp (revision 002f37b0cca92e4cf72857c72ac95db5a8b09615)
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, "*OpenBeOS 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:   %ld\n", length()));
462 	PRINT(("location: %ld\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:     %ld\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:   %ld\n", length()));
502 	PRINT(("block:    %ld\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:      %ld\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: %ld, calculateCrc: %s",
549 	               block, bool_to_string(calculateCrc)));
550 	PRINT(("location   (parameter)    == %ld\n", block));
551 	PRINT(("location   (in structure) == %ld\n", location()));
552 	if (calculateCrc) {
553 		PRINT(("crc        (calculated)   == %d\n",
554 		       calculate_crc(reinterpret_cast<uint8*>(this)+sizeof(descriptor_tag),
555 		       crc_length())))
556 	} else {
557 		PRINT(("crc        (calculated)   == (not calculated)\n"));
558 	}
559 	PRINT(("crc        (in structure) == %d\n", crc()));
560 	PRINT(("crc_length (in structure) == %d\n", crc_length()));
561 	// location
562 	status_t error = (block == location()) ? B_OK : B_NO_INIT;
563 	// checksum
564 	if (!error) {
565 		uint32 sum = 0;
566 		for (int i = 0; i <= 3; i++)
567 			sum += reinterpret_cast<uint8*>(this)[i];
568 		for (int i = 5; i <= 15; i++)
569 			sum += reinterpret_cast<uint8*>(this)[i];
570 		error = sum % 256 == checksum() ? B_OK : B_NO_INIT;
571 	}
572 	// crc
573 	if (!error && calculateCrc) {
574 		uint16 _crc = calculate_crc(reinterpret_cast<uint8*>(this)
575 		               + sizeof(descriptor_tag), crc_length());
576 		error = _crc == crc() ? B_OK : B_NO_INIT;
577 	}
578 	RETURN(error);
579 }
580 
581 //----------------------------------------------------------------------
582 // primary_volume_descriptor
583 //----------------------------------------------------------------------
584 
585 void
586 primary_volume_descriptor::dump() const
587 {
588 	DUMP_INIT("primary_volume_descriptor");
589 
590 	UdfString string;
591 
592 	PRINT(("tag:\n"));
593 	DUMP(tag());
594 	PRINT(("vds_number:                       %ld\n", vds_number()));
595 	PRINT(("primary_volume_descriptor_number: %ld\n", primary_volume_descriptor_number()));
596 	string = volume_identifier();
597 	PRINT(("volume_identifier:                `%s'\n", string.Utf8()));
598 	PRINT(("volume_sequence_number:           %d\n", volume_sequence_number()));
599 	PRINT(("max_volume_sequence_number:       %d\n", max_volume_sequence_number()));
600 	PRINT(("interchange_level:                %d\n", interchange_level()));
601 	PRINT(("max_interchange_level:            %d\n", max_interchange_level()));
602 	PRINT(("character_set_list:               %ld\n", character_set_list()));
603 	PRINT(("max_character_set_list:           %ld\n", max_character_set_list()));
604 	string = volume_set_identifier();
605 	PRINT(("volume_set_identifier:            `%s'\n", string.Utf8()));
606 	PRINT(("descriptor_character_set:\n"));
607 	DUMP(descriptor_character_set());
608 	PRINT(("explanatory_character_set:\n"));
609 	DUMP(explanatory_character_set());
610 	PRINT(("volume_abstract:\n"));
611 	DUMP(volume_abstract());
612 	PRINT(("volume_copyright_notice:\n"));
613 	DUMP(volume_copyright_notice());
614 	PRINT(("application_id:\n"));
615 	DUMP(application_id());
616 	PRINT(("recording_date_and_time:\n"));
617 	DUMP(recording_date_and_time());
618 	PRINT(("implementation_id:\n"));
619 	DUMP(implementation_id());
620 	PRINT(("implementation_use:\n"));
621 	DUMP(implementation_use());
622 	PRINT(("predecessor_vds_location:         %ld\n",
623 	       predecessor_volume_descriptor_sequence_location()));
624 	PRINT(("flags:                            %d\n", flags()));
625 }
626 
627 
628 //----------------------------------------------------------------------
629 // anchor_volume_descriptor_pointer
630 //----------------------------------------------------------------------
631 
632 void
633 anchor_volume_descriptor::dump() const
634 {
635 	DUMP_INIT("anchor_volume_descriptor");
636 	PRINT(("tag:\n"));
637 	DUMP(tag());
638 	PRINT(("main_vds:\n"));
639 	DUMP(main_vds());
640 	PRINT(("reserve_vds:\n"));
641 	DUMP(reserve_vds());
642 }
643 
644 //----------------------------------------------------------------------
645 // logical_volume_info
646 //----------------------------------------------------------------------
647 
648 void
649 logical_volume_info::dump() const
650 {
651 	UdfString string;
652 	DUMP_INIT("logical_volume_information");
653 	PRINT(("character_set:\n"));
654 	DUMP(character_set());
655 	string = logical_volume_id();
656 	PRINT(("logical_volume_id: `%s'\n", string.Utf8()));
657 	for (uint32 i = 0; i < _logical_volume_info.length(); i++) {
658 		string = _logical_volume_info[i];
659 		PRINT(("logical_volume_info #%ld: %s\n", i, string.Utf8()));
660 	}
661 	PRINT(("implementation_id:\n"));
662 	DUMP(implementation_id());
663 	PRINT(("implementation_use:\n"));
664 	DUMP(implementation_use());
665 }
666 
667 //----------------------------------------------------------------------
668 // implementation_use_descriptor
669 //----------------------------------------------------------------------
670 
671 void
672 implementation_use_descriptor::dump() const
673 {
674 	DUMP_INIT("implementation_use_descriptor");
675 	PRINT(("tag:\n"));
676 	DUMP(tag());
677 	PRINT(("vds_number: %ld\n", vds_number()));
678 	PRINT(("implementation_id:\n"));
679 	DUMP(implementation_id());
680 	PRINT(("implementation_use: XXX\n"));
681 	DUMP(implementation_use());
682 }
683 
684 //----------------------------------------------------------------------
685 // partition_descriptor
686 //----------------------------------------------------------------------
687 
688 void
689 partition_descriptor::dump() const
690 {
691 	DUMP_INIT("partition_descriptor");
692 	PRINT(("tag:\n"));
693 	DUMP(tag());
694 	PRINT(("vds_number:                %ld\n", vds_number()));
695 	PRINT(("partition_flags:           %d\n", partition_flags()));
696 	PRINT(("partition_flags.allocated: %s\n", allocated() ? "true" : "false"));
697 	PRINT(("partition_number:          %d\n", partition_number()));
698 	PRINT(("partition_contents:\n"));
699 	DUMP(partition_contents());
700 	PRINT(("partition_contents_use:    XXX\n"));
701 	DUMP(partition_contents_use());
702 	PRINT(("access_type:               %ld\n", access_type()));
703 	PRINT(("start:                     %ld\n", start()));
704 	PRINT(("length:                    %ld\n", length()));
705 	PRINT(("implementation_id:\n"));
706 	DUMP(implementation_id());
707 	PRINT(("implementation_use:        XXX\n"));
708 	DUMP(implementation_use());
709 }
710 
711 //----------------------------------------------------------------------
712 // logical_volume_descriptor
713 //----------------------------------------------------------------------
714 
715 void
716 logical_volume_descriptor::dump() const
717 {
718 	DUMP_INIT("logical_volume_descriptor");
719 	PRINT(("tag:\n"));
720 	DUMP(tag());
721 	PRINT(("vds_number:                %ld\n", vds_number()));
722 	PRINT(("character_set:\n"));
723 	DUMP(character_set());
724 	UdfString string(logical_volume_identifier());
725 	PRINT(("logical_volume_identifier: `%s'\n", string.Utf8()));
726 	PRINT(("logical_block_size:        %ld\n", logical_block_size()));
727 	PRINT(("domain_id:\n"));
728 	DUMP(domain_id());
729 	PRINT(("logical_volume_contents_use:\n"));
730 	DUMP(logical_volume_contents_use());
731 	PRINT(("file_set_address:\n"));
732 	DUMP(file_set_address());
733 	PRINT(("map_table_length:          %ld\n", map_table_length()));
734 	PRINT(("partition_map_count:       %ld\n", partition_map_count()));
735 	PRINT(("implementation_id:\n"));
736 	DUMP(implementation_id());
737 	PRINT(("implementation_use:\n"));
738 	DUMP(implementation_use());
739 	PRINT(("integrity_sequence_extent:\n"));
740 	DUMP(integrity_sequence_extent());
741 //	PRINT(("partition_maps:\n"));
742 	const uint8 *maps = partition_maps();
743 	int offset = 0;
744 	for (uint i = 0; i < partition_map_count(); i++) {
745 		PRINT(("partition_map #%d:\n", i));
746 		uint8 type = maps[offset];
747 		uint8 length = maps[offset+1];
748 		PRINT(("  type: %d\n", type));
749 		PRINT(("  length: %d\n", length));
750 		switch (type) {
751 			case 1:
752 				for (int j = 0; j < length-2; j++)
753 					PRINT(("  data[%d]: %d\n", j, maps[offset+2+j]));
754 				break;
755 			case 2: {
756 				PRINT(("  partition_number: %d\n", *reinterpret_cast<const uint16*>(&(maps[offset+38]))));
757 				PRINT(("  entity_id:\n"));
758 				const entity_id *id = reinterpret_cast<const entity_id*>(&(maps[offset+4]));
759 				if (id)	// To kill warning when DEBUG==0
760 					PDUMP(id);
761 				break;
762 			}
763 		}
764 		offset += maps[offset+1];
765 	}
766 	// \todo dump partition_maps
767 }
768 
769 
770 logical_volume_descriptor&
771 logical_volume_descriptor::operator=(const logical_volume_descriptor &rhs)
772 {
773 	_tag = rhs._tag;
774 	_vds_number = rhs._vds_number;
775 	_character_set = rhs._character_set;
776 	_logical_volume_identifier = rhs._logical_volume_identifier;
777 	_logical_block_size = rhs._logical_block_size;
778 	_domain_id = rhs._domain_id;
779 	_logical_volume_contents_use = rhs._logical_volume_contents_use;
780 	_map_table_length = rhs._map_table_length;
781 	_partition_map_count = rhs._partition_map_count;
782 	_implementation_id = rhs._implementation_id;
783 	_implementation_use = rhs._implementation_use;
784 	_integrity_sequence_extent = rhs._integrity_sequence_extent;
785 	// copy the partition maps one by one
786 	uint8 *lhsMaps = partition_maps();
787 	const uint8 *rhsMaps = rhs.partition_maps();
788 	int offset = 0;
789 	for (uint8 i = 0; i < rhs.partition_map_count(); i++) {
790 		uint8 length = rhsMaps[offset+1];
791 		memcpy(&lhsMaps[offset], &rhsMaps[offset], length);
792 		offset += length;
793 	}
794 	return *this;
795 }
796 
797 
798 //----------------------------------------------------------------------
799 // physical_partition_map
800 //----------------------------------------------------------------------
801 
802 void
803 physical_partition_map::dump()
804 {
805 	DUMP_INIT("physical_partition_map");
806 	PRINT(("type: %d\n", type()));
807 	PRINT(("length: %d\n", length()));
808 	PRINT(("volume_sequence_number: %d\n", volume_sequence_number()));
809 	PRINT(("partition_number: %d\n", partition_number()));
810 }
811 
812 //----------------------------------------------------------------------
813 // sparable_partition_map
814 //----------------------------------------------------------------------
815 
816 void
817 sparable_partition_map::dump()
818 {
819 	DUMP_INIT("sparable_partition_map");
820 	PRINT(("type: %d\n", type()));
821 	PRINT(("length: %d\n", length()));
822 	PRINT(("partition_type_id:"));
823 	DUMP(partition_type_id());
824 	PRINT(("volume_sequence_number: %d\n", volume_sequence_number()));
825 	PRINT(("partition_number: %d\n", partition_number()));
826 	PRINT(("sparing_table_count: %d\n", sparing_table_count()));
827 	PRINT(("sparing_table_size: %ld\n", sparing_table_size()));
828 	PRINT(("sparing_table_locations:"));
829 	for (uint8 i = 0; i < sparing_table_count(); i++)
830 		PRINT(("  %d: %ld\n", i, sparing_table_location(i)));
831 }
832 
833 //----------------------------------------------------------------------
834 // unallocated_space_descriptor
835 //----------------------------------------------------------------------
836 
837 void
838 unallocated_space_descriptor::dump() const
839 {
840 	DUMP_INIT("unallocated_space_descriptor");
841 	PRINT(("tag:\n"));
842 	DUMP(tag());
843 	PRINT(("vds_number:                  %ld\n", vds_number()));
844 	PRINT(("allocation_descriptor_count: %ld\n", allocation_descriptor_count()));
845 	// \todo dump alloc_descriptors
846 }
847 
848 
849 //----------------------------------------------------------------------
850 // terminating_descriptor
851 //----------------------------------------------------------------------
852 
853 void
854 terminating_descriptor::dump() const
855 {
856 	DUMP_INIT("terminating_descriptor");
857 	PRINT(("tag:\n"));
858 	DUMP(tag());
859 }
860 
861 //----------------------------------------------------------------------
862 // file_set_descriptor
863 //----------------------------------------------------------------------
864 
865 void
866 file_set_descriptor::dump() const
867 {
868 	DUMP_INIT("file_set_descriptor");
869 	PRINT(("tag:\n"));
870 	DUMP(tag());
871 	PRINT(("recording_date_and_time:\n"));
872 	DUMP(recording_date_and_time());
873 	PRINT(("interchange_level: %d\n", interchange_level()));
874 	PRINT(("max_interchange_level: %d\n", max_interchange_level()));
875 	PRINT(("character_set_list: %ld\n", character_set_list()));
876 	PRINT(("max_character_set_list: %ld\n", max_character_set_list()));
877 	PRINT(("file_set_number: %ld\n", file_set_number()));
878 	PRINT(("file_set_descriptor_number: %ld\n", file_set_descriptor_number()));
879 	PRINT(("logical_volume_id_character_set:\n"));
880 	DUMP(logical_volume_id_character_set());
881 	PRINT(("logical_volume_id:\n"));
882 	DUMP(logical_volume_id());
883 	PRINT(("file_set_id_character_set:\n"));
884 	DUMP(file_set_id_character_set());
885 	PRINT(("file_set_id:\n"));
886 	DUMP(file_set_id());
887 	PRINT(("copyright_file_id:\n"));
888 	DUMP(copyright_file_id());
889 	PRINT(("abstract_file_id:\n"));
890 	DUMP(abstract_file_id());
891 	PRINT(("root_directory_icb:\n"));
892 	DUMP(root_directory_icb());
893 	PRINT(("domain_id:\n"));
894 	DUMP(domain_id());
895 	PRINT(("next_extent:\n"));
896 	DUMP(next_extent());
897 	PRINT(("system_stream_directory_icb:\n"));
898 	DUMP(system_stream_directory_icb());
899 }
900 
901 //----------------------------------------------------------------------
902 // logical_volume_integrity_descriptor
903 //----------------------------------------------------------------------
904 
905 void
906 logical_volume_integrity_descriptor::dump() const
907 {
908 	DUMP_INIT("logical_volume_integrity_descriptor");
909 	PRINT(("tag:\n"));
910 	DUMP(tag());
911 	PRINT(("recording_time:\n"));
912 	DUMP(recording_time());
913 	PRINT(("integrity_type:             "));
914 	switch (integrity_type()) {
915 		case INTEGRITY_OPEN:
916 			SIMPLE_PRINT(("open\n"));
917 			break;
918 		case INTEGRITY_CLOSED:
919 			SIMPLE_PRINT(("closed\n"));
920 			break;
921 		default:
922 			SIMPLE_PRINT(("invalid integrity type (%ld)", integrity_type()));
923 			break;
924 	}
925 	PRINT(("next_integrity_extent:\n"));
926 	DUMP(next_integrity_extent());
927 	PRINT(("logical_volume_contents_use:\n"));
928 	DUMP(logical_volume_contents_use());
929 	PRINT(("next_unique_id:             %Ld\n", next_unique_id()));
930 	PRINT(("partition_count:            %ld\n", partition_count()));
931 	PRINT(("implementation_use_length:  %ld\n", implementation_use_length()));
932 	if (partition_count() > 0) {
933 		PRINT(("free_space_table:\n"));
934 		for (uint32 i = 0; i < partition_count(); i++) {
935 			PRINT(("partition %ld: %ld free blocks\n", i, free_space_table()[i]));
936 		}
937 		PRINT(("size_table:\n"));
938 		for (uint32 i = 0; i < partition_count(); i++) {
939 			PRINT(("partition %ld: %ld blocks large\n", i, size_table()[i]));
940 		}
941 	}
942 
943 	if (implementation_use_length() >= minimum_implementation_use_length) {
944 		PRINT(("implementation_id:\n"));
945 		DUMP(implementation_id());
946 		PRINT(("file_count:                 %ld\n", file_count()));
947 		PRINT(("directory_count:            %ld\n", directory_count()));
948 		PRINT(("minimum_udf_read_revision:  0x%04x\n", minimum_udf_read_revision()));
949 		PRINT(("minimum_udf_write_revision: 0x%04x\n", minimum_udf_write_revision()));
950 		PRINT(("maximum_udf_write_revision: 0x%04x\n", maximum_udf_write_revision()));
951 	} else {
952 		PRINT(("NOTE: implementation_use() field of insufficient length to contain \n"));
953 		PRINT(("      appropriate UDF-2.50 2.2.6.4 fields.\n"));
954 	}
955 }
956 
957 //----------------------------------------------------------------------
958 // file_id_descriptor
959 //----------------------------------------------------------------------
960 
961 void
962 file_id_descriptor::dump() const
963 {
964 	DUMP_INIT("file_id_descriptor");
965 	PRINT(("tag:\n"));
966 	DUMP(tag());
967 	PRINT(("version_number:            %d\n", version_number()));
968 	PRINT(("may_be_hidden:             %d\n", may_be_hidden()));
969 	PRINT(("is_directory:              %d\n", is_directory()));
970 	PRINT(("is_deleted:                %d\n", is_deleted()));
971 	PRINT(("is_parent:                 %d\n", is_parent()));
972 	PRINT(("is_metadata_stream:        %d\n", is_metadata_stream()));
973 	PRINT(("id_length:                 %d\n", id_length()));
974 	PRINT(("icb:\n"));
975 	DUMP(icb());
976 	PRINT(("implementation_use_length: %d\n", is_parent()));
977 	UdfString fileId(id());
978 	PRINT(("id: `%s'", fileId.Utf8()));
979 }
980 
981 //----------------------------------------------------------------------
982 // icb_entry_tag
983 //----------------------------------------------------------------------
984 
985 void
986 icb_entry_tag::dump() const
987 {
988 	DUMP_INIT("icb_entry_tag");
989 	PRINT(("prior_entries: %ld\n", prior_recorded_number_of_direct_entries()));
990 	PRINT(("strategy_type: %d\n", strategy_type()));
991 	PRINT(("strategy_parameters:\n"));
992 	DUMP(strategy_parameters());
993 	PRINT(("entry_count: %d\n", entry_count()));
994 	PRINT(("file_type: %d\n", file_type()));
995 	PRINT(("parent_icb_location:\n"));
996 	DUMP(parent_icb_location());
997 	PRINT(("all_flags: %d\n", flags()));
998 
999 /*
1000 	uint32 prior_recorded_number_of_direct_entries;
1001 	uint16 strategy_type;
1002 	array<uint8, 2> strategy_parameters;
1003 	uint16 entry_count;
1004 	uint8 reserved;
1005 	uint8 file_type;
1006 	logical_block_address parent_icb_location;
1007 	union {
1008 		uint16 all_flags;
1009 		struct {
1010 			uint16	descriptor_flags:3,
1011 					if_directory_then_sort:1,	//!< To be set to 0 per UDF-2.01 2.3.5.4
1012 					non_relocatable:1,
1013 					archive:1,
1014 					setuid:1,
1015 					setgid:1,
1016 					sticky:1,
1017 					contiguous:1,
1018 					system:1,
1019 					transformed:1,
1020 					multi_version:1,			//!< To be set to 0 per UDF-2.01 2.3.5.4
1021 					is_stream:1,
1022 					reserved_icb_entry_flags:2;
1023 		} flags;
1024 	};
1025 
1026 */
1027 
1028 }
1029 
1030 //----------------------------------------------------------------------
1031 // icb_header
1032 //----------------------------------------------------------------------
1033 
1034 void
1035 icb_header::dump() const
1036 {
1037 	DUMP_INIT("icb_header");
1038 
1039 	PRINT(("tag:\n"));
1040 	DUMP(tag());
1041 	PRINT(("icb_tag:\n"));
1042 	DUMP(icb_tag());
1043 
1044 }
1045 
1046 //----------------------------------------------------------------------
1047 // file_icb_entry
1048 //----------------------------------------------------------------------
1049 
1050 long_address file_icb_entry::_dummy_stream_directory_icb;
1051 
1052 void
1053 file_icb_entry::dump() const
1054 {
1055 	DUMP_INIT("file_icb_entry");
1056 
1057 	PRINT(("tag:\n"));
1058 	DUMP(tag());
1059 	PRINT(("icb_tag:\n"));
1060 	DUMP(icb_tag());
1061 
1062 	PRINT(("uid:                       %lu, 0x%lx\n", uid(), uid()));
1063 	PRINT(("gid:                       %lu, 0x%lx\n", gid(), gid()));
1064 	PRINT(("permissions:               %ld, 0x%lx\n", permissions(), permissions()));
1065 	PRINT(("file_link_count:           %d\n", file_link_count()));
1066 	PRINT(("record_format:             %d\n", record_format()));
1067 	PRINT(("record_display_attributes: %d\n", record_display_attributes()));
1068 	PRINT(("record_length:             %d\n", record_length()));
1069 	PRINT(("information_length:        %Ld\n", information_length()));
1070 	PRINT(("logical_blocks_recorded:   %Ld\n", logical_blocks_recorded()));
1071 	PRINT(("access_date_and_time:\n"));
1072 	DUMP(access_date_and_time());
1073 	PRINT(("modification_date_and_time:\n"));
1074 	DUMP(modification_date_and_time());
1075 	PRINT(("attribute_date_and_time:\n"));
1076 	DUMP(attribute_date_and_time());
1077 	PRINT(("checkpoint:                %ld\n", checkpoint()));
1078 
1079 	PRINT(("extended_attribute_icb:\n"));
1080 	DUMP(extended_attribute_icb());
1081 	PRINT(("implementation_id:\n"));
1082 	DUMP(implementation_id());
1083 
1084 	PRINT(("unique_id: %Ld\n", unique_id()));
1085 	PRINT(("extended_attributes_length:    %ld\n", extended_attributes_length()));
1086 	PRINT(("allocation_descriptors_length: %ld\n", allocation_descriptors_length()));
1087 
1088 	PRINT(("allocation_descriptors:\n"));
1089 	switch (icb_tag().descriptor_flags()) {
1090 		case ICB_DESCRIPTOR_TYPE_SHORT:
1091 			PRINT(("  short descriptors...\n"));
1092 			break;
1093 		case ICB_DESCRIPTOR_TYPE_LONG:
1094 		{
1095 			const long_address *address = reinterpret_cast<const long_address*>(allocation_descriptors());
1096 			for (uint32 length = allocation_descriptors_length();
1097 				   length >= sizeof(long_address);
1098 				     length -= sizeof(long_address), address++)
1099 			{
1100 				PDUMP(address);
1101 			}
1102 			break;
1103 		}
1104 		case ICB_DESCRIPTOR_TYPE_EXTENDED:
1105 			PRINT(("  extended descriptors...\n"));
1106 			break;
1107 		case ICB_DESCRIPTOR_TYPE_EMBEDDED:
1108 			PRINT(("  embedded descriptors...\n"));
1109 			break;
1110 		default:
1111 			PRINT(("  invalid descriptors type\n"));
1112 			break;
1113 	}
1114 }
1115 
1116 //----------------------------------------------------------------------
1117 // extended_file_icb_entry
1118 //----------------------------------------------------------------------
1119 
1120 void
1121 extended_file_icb_entry::dump() const
1122 {
1123 	DUMP_INIT("extended_file_icb_entry");
1124 
1125 	PRINT(("tag:\n"));
1126 	DUMP(tag());
1127 	PRINT(("icb_tag:\n"));
1128 	DUMP(icb_tag());
1129 
1130 	PRINT(("uid:                       %lu, 0x%lx\n", uid(), uid()));
1131 	PRINT(("gid:                       %lu, 0x%lx\n", gid(), gid()));
1132 	PRINT(("permissions:               %ld, 0x%lx\n", permissions(), permissions()));
1133 	PRINT(("file_link_count:           %d\n", file_link_count()));
1134 	PRINT(("record_format:             %d\n", record_format()));
1135 	PRINT(("record_display_attributes: %d\n", record_display_attributes()));
1136 	PRINT(("record_length:             %ld\n", record_length()));
1137 	PRINT(("information_length:        %Ld\n", information_length()));
1138 	PRINT(("logical_blocks_recorded:   %Ld\n", logical_blocks_recorded()));
1139 	PRINT(("access_date_and_time:\n"));
1140 	DUMP(access_date_and_time());
1141 	PRINT(("modification_date_and_time:\n"));
1142 	DUMP(modification_date_and_time());
1143 	PRINT(("creation_date_and_time:\n"));
1144 	DUMP(creation_date_and_time());
1145 	PRINT(("attribute_date_and_time:\n"));
1146 	DUMP(attribute_date_and_time());
1147 	PRINT(("checkpoint:                %ld\n", checkpoint()));
1148 
1149 	PRINT(("extended_attribute_icb:\n"));
1150 	DUMP(extended_attribute_icb());
1151 	PRINT(("stream_directory_icb:\n"));
1152 	DUMP(stream_directory_icb());
1153 	PRINT(("implementation_id:\n"));
1154 	DUMP(implementation_id());
1155 
1156 	PRINT(("unique_id: %Ld\n", unique_id()));
1157 	PRINT(("extended_attributes_length:    %ld\n", extended_attributes_length()));
1158 	PRINT(("allocation_descriptors_length: %ld\n", allocation_descriptors_length()));
1159 
1160 	PRINT(("allocation_descriptors:\n"));
1161 	switch (icb_tag().descriptor_flags()) {
1162 		case ICB_DESCRIPTOR_TYPE_SHORT:
1163 			PRINT(("  short descriptors...\n"));
1164 			break;
1165 		case ICB_DESCRIPTOR_TYPE_LONG:
1166 		{
1167 			const long_address *address = reinterpret_cast<const long_address*>(allocation_descriptors());
1168 			for (uint32 length = allocation_descriptors_length();
1169 				   length >= sizeof(long_address);
1170 				     length -= sizeof(long_address), address++)
1171 			{
1172 				PDUMP(address);
1173 			}
1174 			break;
1175 		}
1176 		case ICB_DESCRIPTOR_TYPE_EXTENDED:
1177 			PRINT(("  extended descriptors...\n"));
1178 			break;
1179 		case ICB_DESCRIPTOR_TYPE_EMBEDDED:
1180 			PRINT(("  embedded descriptors...\n"));
1181 			break;
1182 		default:
1183 			PRINT(("  invalid descriptors type\n"));
1184 			break;
1185 	}
1186 }
1187