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