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