xref: /haiku/src/add-ons/kernel/file_systems/udf/UdfStructures.h (revision ead0c3e203ab5b40df7493668344db8e1c33b933)
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 #ifndef _UDF_DISK_STRUCTURES_H
8 #define _UDF_DISK_STRUCTURES_H
9 
10 #include <string.h>
11 
12 #include <ByteOrder.h>
13 #include <SupportDefs.h>
14 
15 #include "kernel_cpp.h"
16 #include "UdfDebug.h"
17 
18 #include "Array.h"
19 
20 /*! \file DiskStructures.h
21 
22 	\brief UDF on-disk data structure declarations
23 
24 	UDF is a specialization of the ECMA-167 standard. For the most part,
25 	ECMA-167 structures are used by UDF with special restrictions. In a
26 	few instances, UDF introduces its own structures to augment those
27 	supplied by ECMA-167; those structures are clearly marked.
28 
29 	For UDF info: <a href='http://www.osta.org'>http://www.osta.org</a>
30 	For ECMA info: <a href='http://www.ecma-international.org'>http://www.ecma-international.org</a>
31 
32 	For lack of a better place to store this info, the structures that
33 	are allowed to have length greater than the logical block size are
34 	as follows (other length restrictions may be found in UDF-2.01 5.1):
35 	- \c logical_volume_descriptor
36 	- \c unallocated_space_descriptor
37 	- \c logical_volume_integrity_descriptor
38 	- \c space_bitmap_descriptor
39 
40 	Other links of interest:
41 	- <a href='http://www.extra.research.philips.com/udf/'>Philips UDF verifier</a>
42 	- <a href='http://www.hi-ho.ne.jp/y-komachi/committees/fpro/fpro.htm'>Possible test disc image generator (?)</a>
43 */
44 
45 namespace Udf {
46 
47 //----------------------------------------------------------------------
48 // ECMA-167 Part 1
49 //----------------------------------------------------------------------
50 
51 /*! \brief Character set specifications
52 
53 	The character_set_info field shall be set to the ASCII string
54 	"OSTA Compressed Unicode" (padded right with NULL chars).
55 
56 	See also: ECMA 167 1/7.2.1, UDF-2.01 2.1.2
57 */
58 struct charspec {
59 public:
60 	void dump() const;
61 
62 	uint8 character_set_type() const { return _character_set_type; }
63 	const char* character_set_info() const { return _character_set_info; }
64 	char* character_set_info() { return _character_set_info; }
65 
66 	void set_character_set_type(uint8 type) { _character_set_type = type; }
67 private:
68 	uint8 _character_set_type;	//!< to be set to 0 to indicate CS0
69 	char _character_set_info[63];	//!< "OSTA Compressed Unicode"
70 } __attribute__((packed));
71 
72 
73 extern const charspec kCS0Charspec;
74 
75 
76 /*! \brief Date and time stamp
77 
78 	See also: ECMA 167 1/7.3, UDF-2.01 2.1.4
79 */
80 class timestamp {
81 private:
82 	union type_and_timezone_accessor {
83 		uint16 type_and_timezone;
84 		struct {
85 			uint16 type:4,
86 			       timezone:12;
87 		} bits;
88 	};
89 
90 public:
91 	void dump() const;
92 
93 	// Get functions
94 	uint16 type_and_timezone() const { return B_LENDIAN_TO_HOST_INT16(_type_and_timezone); }
95 	uint8 type() const {
96 		type_and_timezone_accessor t;
97 		t.type_and_timezone = type_and_timezone();
98 		return t.bits.type;
99 	}
100 	int16 timezone() const {
101 		type_and_timezone_accessor t;
102 		t.type_and_timezone = type_and_timezone();
103 		return t.bits.timezone;
104 	}
105 	uint16 year() const { return B_LENDIAN_TO_HOST_INT16(_year); }
106 	uint8 month() const { return _month; }
107 	uint8 day() const { return _day; }
108 	uint8 hour() const { return _hour; }
109 	uint8 minute() const { return _minute; }
110 	uint8 second() const { return _second; }
111 	uint8 centisecond() const { return _centisecond; }
112 	uint8 hundred_microsecond() const { return _hundred_microsecond; }
113 	uint8 microsecond() const { return _microsecond; }
114 
115 	// Set functions
116 	void set_type_and_timezone(uint16 type_and_timezone) { _type_and_timezone = B_HOST_TO_LENDIAN_INT16(type_and_timezone); }
117 	void set_type(uint8 type) {
118 		type_and_timezone_accessor t;
119 		t.type_and_timezone = type_and_timezone();
120 		t.bits.type = type;
121 		set_type_and_timezone(t.type_and_timezone);
122 	}
123 	void set_timezone(uint8 timezone) {
124 		type_and_timezone_accessor t;
125 		t.type_and_timezone = type_and_timezone();
126 		t.bits.timezone = timezone;
127 		set_type_and_timezone(t.type_and_timezone);
128 	}
129 	void set_year(uint16 year) { _year = B_HOST_TO_LENDIAN_INT16(year); }
130 	void set_month(uint8 month) { _month = month; }
131 	void set_day(uint8 day) { _day = day; }
132 	void set_hour(uint8 hour) { _hour = hour; }
133 	void set_minute(uint8 minute) { _minute = minute; }
134 	void set_second(uint8 second) { _second = second; }
135 	void set_centisecond(uint8 centisecond) { _centisecond = centisecond; }
136 	void set_hundred_microsecond(uint8 hundred_microsecond) { _hundred_microsecond = hundred_microsecond; }
137 	void set_microsecond(uint8 microsecond) { _microsecond = microsecond; }
138 private:
139 	uint16 _type_and_timezone;
140 	uint16 _year;
141 	uint8 _month;
142 	uint8 _day;
143 	uint8 _hour;
144 	uint8 _minute;
145 	uint8 _second;
146 	uint8 _centisecond;
147 	uint8 _hundred_microsecond;
148 	uint8 _microsecond;
149 
150 } __attribute__((packed));
151 
152 
153 /*! \brief Identifier used to designate the implementation responsible
154 	for writing associated data structures on the medium.
155 
156 	See also: ECMA 167 1/7.4, UDF 2.01 2.1.5
157 */
158 struct entity_id {
159 public:
160 	entity_id(uint8 flags = 0, char *identifier = NULL,
161 	              char *identifier_suffix = NULL);
162 
163 	void dump() const;
164 	bool matches(const entity_id &id) const;
165 
166 	// Get functions
167 	uint8 flags() const { return _flags; }
168 	const char* identifier() const { return _identifier; }
169 	char* identifier() { return _identifier; }
170 	const char* identifier_suffix() const { return _identifier_suffix; }
171 	char* identifier_suffix() { return _identifier_suffix; }
172 
173 	// Set functions
174 	void set_flags(uint8 flags) { _flags = flags; }
175 
176 	static const int kIdentifierLength = 23;
177 	static const int kIdentifierSuffixLength = 8;
178 private:
179 	uint8 _flags;
180 	char _identifier[kIdentifierLength];
181 	char _identifier_suffix[kIdentifierSuffixLength];
182 } __attribute__((packed));
183 
184 extern const entity_id kMetadataPartitionMapId;
185 extern const entity_id kSparablePartitionMapId;
186 extern const entity_id kVirtualPartitionMapId;
187 
188 //----------------------------------------------------------------------
189 // ECMA-167 Part 2
190 //----------------------------------------------------------------------
191 
192 
193 /*! \brief Header for volume structure descriptors
194 
195 	Each descriptor consumes an entire block. All unused trailing
196 	bytes in the descriptor should be set to 0.
197 
198 	The following descriptors contain no more information than
199 	that contained in the header:
200 
201 	- BEA01:
202 	  - type: 0
203 	  - id: "BEA01"
204 	  - version: 1
205 
206 	- TEA01:
207 	  - type: 0
208 	  - id: "TEA01"
209 	  - version: 1
210 
211 	- NSR03:
212 	  - type: 0
213 	  - id: "NSR03"
214 	  - version: 1
215 
216 	See also: ECMA 167 2/9.1
217 */
218 struct volume_structure_descriptor_header {
219 	uint8 type;
220 	char id[5];
221 	uint8 version;
222 
223 	bool id_matches(const char *id);
224 } __attribute__((packed));
225 
226 // Volume structure descriptor ids
227 extern const char* kVSDID_BEA;
228 extern const char* kVSDID_TEA;
229 extern const char* kVSDID_BOOT;
230 extern const char* kVSDID_ISO;
231 extern const char* kVSDID_ECMA167_2;
232 extern const char* kVSDID_ECMA167_3;
233 extern const char* kVSDID_ECMA168;
234 
235 //----------------------------------------------------------------------
236 // ECMA-167 Part 3
237 //----------------------------------------------------------------------
238 
239 
240 /*! \brief Location and length of a contiguous chunk of data on the volume.
241 
242 	\c _location is an absolute block address.
243 
244 	See also: ECMA 167 3/7.1
245 */
246 struct extent_address {
247 public:
248 	void dump() const;
249 
250 	uint32 length() const { return B_LENDIAN_TO_HOST_INT32(_length); }
251 	uint32 location() const { return B_LENDIAN_TO_HOST_INT32(_location); }
252 
253 	void set_length(int32 length) { _length = B_HOST_TO_LENDIAN_INT32(length); }
254 	void set_location(int32 location) { _location = B_HOST_TO_LENDIAN_INT32(location); }
255 private:
256 	uint32 _length;
257 	uint32 _location;
258 } __attribute__((packed));
259 
260 
261 /*! \brief Location of a logical block within a logical volume.
262 
263 	See also: ECMA 167 4/7.1
264 */
265 struct logical_block_address {
266 public:
267 	void dump() const;
268 
269 	uint32 block() const { return B_LENDIAN_TO_HOST_INT32(_block); }
270 	uint16 partition() const { return B_LENDIAN_TO_HOST_INT16(_partition); }
271 
272 	void set_block(uint32 block) { _block = B_HOST_TO_LENDIAN_INT32(block); }
273 	void set_partition(uint16 partition) { _partition = B_HOST_TO_LENDIAN_INT16(partition); }
274 
275 private:
276 	uint32 _block;	//!< Block location relative to start of corresponding partition
277 	uint16 _partition;	//!< Numeric partition id within logical volume
278 } __attribute__((packed));
279 
280 /*! \brief Extent types used in short_address, long_address,
281 	and extended_address.
282 
283 	See also: ECMA-167 4/14.14.1.1
284 */
285 enum extent_type {
286 	EXTENT_TYPE_RECORDED = 0,	//!< Allocated and recorded
287 	EXTENT_TYPE_ALLOCATED,		//!< Allocated but unrecorded
288 	EXTENT_TYPE_UNALLOCATED,	//!< Unallocated and unrecorded
289 	EXTENT_TYPE_CONTINUATION,	//!< Specifies next extent of descriptors
290 };
291 
292 
293 /*! \brief Allocation descriptor.
294 
295 	See also: ECMA 167 4/14.14.1
296 */
297 struct short_address {
298 private:
299 	union type_and_length_accessor {
300 		uint32 type_and_length;
301 		struct {
302 			uint32 length:30,
303 			       type:2;
304 //			uint32 type:2,
305 //			       length:30;
306 		} bits;
307 	};
308 
309 public:
310 	void dump() const;
311 
312 	uint8 type() const {
313 		type_and_length_accessor t;
314 		t.type_and_length = type_and_length();
315 		return t.bits.type;
316 	}
317 	uint32 length() const {
318 		type_and_length_accessor t;
319 		t.type_and_length = type_and_length();
320 		return t.bits.length;
321 	}
322 	uint32 block() const { return B_LENDIAN_TO_HOST_INT32(_block); }
323 
324 	void set_type(uint8 type) {
325 		type_and_length_accessor t;
326 		t.type_and_length = type_and_length();
327 		t.bits.type = type;
328 		set_type_and_length(t.type_and_length);
329 	}
330 	void set_length(uint32 length) {
331 		type_and_length_accessor t;
332 		t.type_and_length = type_and_length();
333 		t.bits.length = length;
334 		set_type_and_length(t.type_and_length);
335 	}
336 	void set_block(uint32 block) { _block = B_HOST_TO_LENDIAN_INT32(block); }
337 private:
338 	uint32 type_and_length() const { return B_LENDIAN_TO_HOST_INT32(_type_and_length); }
339 	void set_type_and_length(uint32 value) { _type_and_length = B_HOST_TO_LENDIAN_INT32(value); }
340 
341 	uint32 _type_and_length;
342 	uint32 _block;
343 } __attribute__((packed));
344 
345 
346 /*! \brief Allocation descriptor w/ 6 byte implementation use field.
347 
348 	See also: ECMA 167 4/14.14.2
349 */
350 struct long_address {
351 private:
352 	union type_and_length_accessor {
353 		uint32 type_and_length;
354 		struct {
355 			uint32 length:30,
356 			       type:2;
357 		} bits;
358 	};
359 
360 public:
361 	void dump() const;
362 
363 	uint8 type() const {
364 		type_and_length_accessor t;
365 		t.type_and_length = type_and_length();
366 		return t.bits.type;
367 	}
368 	uint32 length() const {
369 		type_and_length_accessor t;
370 		t.type_and_length = type_and_length();
371 		return t.bits.length;
372 	}
373 
374 	uint32 block() const { return _location.block(); }
375 	uint16 partition() const { return _location.partition(); }
376 
377 	const array<uint8, 6>& implementation_use() const { return _implementation_use; }
378 	array<uint8, 6>& implementation_use() { return _implementation_use; }
379 
380 	void set_type(uint8 type) {
381 		type_and_length_accessor t;
382 		t.type_and_length = type_and_length();
383 		t.bits.type = type;
384 		set_type_and_length(t.type_and_length);
385 	}
386 	void set_length(uint32 length) {
387 		type_and_length_accessor t;
388 		t.type_and_length = type_and_length();
389 		t.bits.length = length;
390 		set_type_and_length(t.type_and_length);
391 	}
392 	void set_block(uint32 block) { _location.set_block(block); }
393 	void set_partition(uint16 partition) { _location.set_partition(partition); }
394 
395 	void set_to(uint32 block, uint16 partition, uint32 length = 1,
396 	       uint8 type = EXTENT_TYPE_RECORDED)
397 	{
398 		set_block(block);
399 		set_partition(partition);
400 		set_length(length);
401 		set_type(type);
402 	}
403 
404 private:
405 	uint32 type_and_length() const { return B_LENDIAN_TO_HOST_INT32(_type_and_length); }
406 	void set_type_and_length(uint32 value) { _type_and_length = B_HOST_TO_LENDIAN_INT32(value); }
407 
408 	uint32 _type_and_length;
409 	logical_block_address _location;
410 	array<uint8, 6> _implementation_use;
411 } __attribute__((packed));
412 
413 /*! \brief Common tag found at the beginning of most udf descriptor structures.
414 
415 	For error checking, \c descriptor_tag  structures have:
416 	- The disk location of the tag redundantly stored in the tag itself
417 	- A checksum value for the tag
418 	- A CRC value and length
419 
420 	See also: ECMA 167 1/7.2, UDF 2.01 2.2.1, UDF 2.01 2.3.1
421 */
422 struct descriptor_tag  {
423 public:
424 	void dump() const;
425 
426 	status_t init_check(uint32 diskBlock);
427 
428 	uint16 id() const { return B_LENDIAN_TO_HOST_INT16(_id); }
429 	uint16 version() const { return B_LENDIAN_TO_HOST_INT16(_version); }
430 	uint8 checksum() const { return _checksum; }
431 	uint16 serial_number() const { return B_LENDIAN_TO_HOST_INT16(_serial_number); }
432 	uint16 crc() const { return B_LENDIAN_TO_HOST_INT16(_crc); }
433 	uint16 crc_length() const { return B_LENDIAN_TO_HOST_INT16(_crc_length); }
434 	uint32 location() const { return B_LENDIAN_TO_HOST_INT32(_location); }
435 
436 	void set_id(uint16 id) { _id = B_HOST_TO_LENDIAN_INT16(id); }
437 	void set_version(uint16 version) { _version = B_HOST_TO_LENDIAN_INT16(version); }
438 	void set_checksum(uint8 checksum) { _checksum = checksum; }
439 	void set_serial_number(uint16 serial_number) { _serial_number = B_HOST_TO_LENDIAN_INT16(serial_number); }
440 	void set_crc(uint16 crc) { _crc = B_HOST_TO_LENDIAN_INT16(crc); }
441 	void set_crc_length(uint16 crc_length) { _crc_length = B_HOST_TO_LENDIAN_INT16(crc_length); }
442 	void set_location(uint32 location) { _location = B_HOST_TO_LENDIAN_INT32(location); }
443 
444 private:
445 	uint16 _id;
446 	uint16 _version;
447 	uint8 _checksum;			//!< Sum modulo 256 of bytes 0-3 and 5-15 of this struct.
448 	uint8 _reserved;			//!< Set to #00.
449 	uint16 _serial_number;
450 	uint16 _crc;				//!< May be 0 if \c crc_length field is 0.
451 	/*! \brief Length of the data chunk used to calculate CRC.
452 
453 		If 0, no CRC was calculated, and the \c crc field must be 0.
454 
455 		According to UDF-2.01 2.3.1.2, the CRC shall be calculated for all descriptors
456 		unless otherwise noted, and this field shall be set to:
457 
458 		<code>(descriptor length) - (descriptor tag length)</code>
459 	*/
460 	uint16 _crc_length;
461 	/*! \brief Address of this tag within its partition (for error checking).
462 
463 		For virtually addressed structures (i.e. those accessed thru a VAT), this
464 		shall be the virtual address, not the physical or logical address.
465 	*/
466 	uint32 _location;
467 
468 } __attribute__((packed));
469 
470 
471 /*! \c descriptor_tag ::id values
472 */
473 enum tag_id {
474 	TAGID_UNDEFINED	= 0,
475 
476 	// ECMA 167, PART 3
477 	TAGID_PRIMARY_VOLUME_DESCRIPTOR,
478 	TAGID_ANCHOR_VOLUME_DESCRIPTOR_POINTER,
479 	TAGID_VOLUME_DESCRIPTOR_POINTER,
480 	TAGID_IMPLEMENTATION_USE_VOLUME_DESCRIPTOR,
481 	TAGID_PARTITION_DESCRIPTOR,
482 	TAGID_LOGICAL_VOLUME_DESCRIPTOR,
483 	TAGID_UNALLOCATED_SPACE_DESCRIPTOR,
484 	TAGID_TERMINATING_DESCRIPTOR,
485 	TAGID_LOGICAL_VOLUME_INTEGRITY_DESCRIPTOR,
486 
487 	TAGID_CUSTOM_START = 65280,
488 	TAGID_CUSTOM_END = 65535,
489 
490 	// ECMA 167, PART 4
491 	TAGID_FILE_SET_DESCRIPTOR = 256,
492 	TAGID_FILE_IDENTIFIER_DESCRIPTOR,
493 	TAGID_ALLOCATION_EXTENT_DESCRIPTOR,
494 	TAGID_INDIRECT_ENTRY,
495 	TAGID_TERMINAL_ENTRY,
496 	TAGID_FILE_ENTRY,
497 	TAGID_EXTENDED_ATTRIBUTE_HEADER_DESCRIPTOR,
498 	TAGID_UNALLOCATED_SPACE_ENTRY,
499 	TAGID_SPACE_BITMAP_DESCRIPTOR,
500 	TAGID_PARTITION_INTEGRITY_ENTRY,
501 	TAGID_EXTENDED_FILE_ENTRY,
502 };
503 
504 const char *tag_id_to_string(tag_id id);
505 
506 /*! \brief Primary volume descriptor
507 */
508 struct primary_volume_descriptor {
509 public:
510 	void dump() const;
511 
512 	// Get functions
513 	const descriptor_tag & tag() const { return _tag; }
514 	descriptor_tag & tag() { return _tag; }
515 
516 	uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); }
517 	uint32 primary_volume_descriptor_number() const { return B_LENDIAN_TO_HOST_INT32(_primary_volume_descriptor_number); }
518 
519 	const array<char, 32>& volume_identifier() const { return _volume_identifier; }
520 	array<char, 32>& volume_identifier() { return _volume_identifier; }
521 
522 	uint16 volume_sequence_number() const { return B_LENDIAN_TO_HOST_INT16(_volume_sequence_number); }
523 	uint16 max_volume_sequence_number() const { return B_LENDIAN_TO_HOST_INT16(_max_volume_sequence_number); }
524 	uint16 interchange_level() const { return B_LENDIAN_TO_HOST_INT16(_interchange_level); }
525 	uint16 max_interchange_level() const { return B_LENDIAN_TO_HOST_INT16(_max_interchange_level); }
526 	uint32 character_set_list() const { return B_LENDIAN_TO_HOST_INT32(_character_set_list); }
527 	uint32 max_character_set_list() const { return B_LENDIAN_TO_HOST_INT32(_max_character_set_list); }
528 
529 	const array<char, 128>& volume_set_identifier() const { return _volume_set_identifier; }
530 	array<char, 128>& volume_set_identifier() { return _volume_set_identifier; }
531 
532 	const charspec& descriptor_character_set() const { return _descriptor_character_set; }
533 	charspec& descriptor_character_set() { return _descriptor_character_set; }
534 
535 	const charspec& explanatory_character_set() const { return _explanatory_character_set; }
536 	charspec& explanatory_character_set() { return _explanatory_character_set; }
537 
538 	const extent_address& volume_abstract() const { return _volume_abstract; }
539 	extent_address& volume_abstract() { return _volume_abstract; }
540 	const extent_address& volume_copyright_notice() const { return _volume_copyright_notice; }
541 	extent_address& volume_copyright_notice() { return _volume_copyright_notice; }
542 
543 	const entity_id& application_id() const { return _application_id; }
544 	entity_id& application_id() { return _application_id; }
545 
546 	const timestamp& recording_date_and_time() const { return _recording_date_and_time; }
547 	timestamp& recording_date_and_time() { return _recording_date_and_time; }
548 
549 	const entity_id& implementation_id() const { return _implementation_id; }
550 	entity_id& implementation_id() { return _implementation_id; }
551 
552 	const array<uint8, 64>& implementation_use() const { return _implementation_use; }
553 	array<uint8, 64>& implementation_use() { return _implementation_use; }
554 
555 	uint32 predecessor_volume_descriptor_sequence_location() const
556 	  { return B_LENDIAN_TO_HOST_INT32(_predecessor_volume_descriptor_sequence_location); }
557 	uint16 flags() const { return B_LENDIAN_TO_HOST_INT16(_flags); }
558 
559 	// Set functions
560 	void set_vds_number(uint32 number)
561 	  { _vds_number = B_HOST_TO_LENDIAN_INT32(number); }
562 	void set_primary_volume_descriptor_number(uint32 number)
563 	  { _primary_volume_descriptor_number = B_HOST_TO_LENDIAN_INT32(number); }
564 	void set_volume_sequence_number(uint16 number)
565 	  { _volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); }
566 	void set_max_volume_sequence_number(uint16 number)
567 	  { _max_volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); }
568 	void set_interchange_level(uint16 level)
569 	  { _interchange_level = B_HOST_TO_LENDIAN_INT16(level); }
570 	void set_max_interchange_level(uint16 level)
571 	  { _max_interchange_level = B_HOST_TO_LENDIAN_INT16(level); }
572 	void set_character_set_list(uint32 list)
573 	  { _character_set_list = B_HOST_TO_LENDIAN_INT32(list); }
574 	void set_max_character_set_list(uint32 list)
575 	  { _max_character_set_list = B_HOST_TO_LENDIAN_INT32(list); }
576 	void set_predecessor_volume_descriptor_sequence_location(uint32 location)
577 	  { _predecessor_volume_descriptor_sequence_location = B_HOST_TO_LENDIAN_INT32(location); }
578 	void set_flags(uint16 flags)
579 	  { _flags = B_HOST_TO_LENDIAN_INT16(flags); }
580 
581 private:
582 	descriptor_tag  _tag;
583 	uint32 _vds_number;
584 	uint32 _primary_volume_descriptor_number;
585 	array<char, 32> _volume_identifier;
586 	uint16 _volume_sequence_number;
587 	uint16 _max_volume_sequence_number;
588 	uint16 _interchange_level; //!< to be set to 3 if part of multivolume set, 2 otherwise
589 	uint16 _max_interchange_level; //!< to be set to 3 unless otherwise directed by user
590 	uint32 _character_set_list;
591 	uint32 _max_character_set_list;
592 	array<char, 128> _volume_set_identifier;
593 
594 	/*! \brief Identifies the character set for the \c volume_identifier
595 		and \c volume_set_identifier fields.
596 
597 		To be set to CS0.
598 	*/
599 	charspec _descriptor_character_set;
600 
601 	/*! \brief Identifies the character set used in the \c volume_abstract
602 		and \c volume_copyright_notice extents.
603 
604 		To be set to CS0.
605 	*/
606 	charspec _explanatory_character_set;
607 
608 	extent_address _volume_abstract;
609 	extent_address _volume_copyright_notice;
610 
611 	entity_id _application_id;
612 	timestamp _recording_date_and_time;
613 	entity_id _implementation_id;
614 	array<uint8, 64> _implementation_use;
615 	uint32 _predecessor_volume_descriptor_sequence_location;
616 	uint16 _flags;
617 	char _reserved[22];
618 
619 } __attribute__((packed));
620 
621 
622 /*! \brief Anchor Volume Descriptor Pointer
623 
624 	vd recorded at preset locations in the partition, used as a reference
625 	point to the main vd sequences
626 
627 	According to UDF 2.01, an avdp shall be recorded in at least 2 of
628 	the 3 following locations, where N is the last recordable sector
629 	of the partition:
630 	- 256
631 	- (N - 256)
632 	- N
633 
634 	See also: ECMA 167 3/10.2, UDF-2.01 2.2.3
635 */
636 struct anchor_volume_descriptor {
637 public:
638 	void dump() const;
639 
640 	descriptor_tag & tag() { return _tag; }
641 	const descriptor_tag & tag() const { return _tag; }
642 
643 	extent_address& main_vds() { return _main_vds; }
644 	const extent_address& main_vds() const { return _main_vds; }
645 
646 	extent_address& reserve_vds() { return _reserve_vds; }
647 	const extent_address& reserve_vds() const { return _reserve_vds; }
648 private:
649 	descriptor_tag  _tag;
650 	extent_address _main_vds;	//!< min length of 16 sectors
651 	extent_address _reserve_vds;	//!< min length of 16 sectors
652 	char _reserved[480];
653 } __attribute__((packed));
654 
655 
656 /*! \brief Volume Descriptor Pointer
657 
658 	Used to chain extents of volume descriptor sequences together.
659 
660 	See also: ECMA 167 3/10.3
661 */
662 struct descriptor_pointer {
663 	descriptor_tag  tag;
664 	uint32 vds_number;
665 	extent_address next;
666 } __attribute__((packed));
667 
668 
669 /*! \brief Implementation Use Volume Descriptor
670 
671 	See also: ECMA 167 3/10.4
672 */
673 struct implementation_use_descriptor {
674 public:
675 	void dump() const;
676 
677 	// Get functions
678 	const descriptor_tag & tag() const { return _tag; }
679 	descriptor_tag & tag() { return _tag; }
680 
681 	uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); }
682 
683 	const entity_id& implementation_id() const { return _implementation_id; }
684 	entity_id& implementation_id() { return _implementation_id; }
685 
686 	const array<uint8, 460>& implementation_use() const { return _implementation_use; }
687 	array<uint8, 460>& implementation_use() { return _implementation_use; }
688 
689 	// Set functions
690 	void set_vds_number(uint32 number) { _vds_number = B_HOST_TO_LENDIAN_INT32(number); }
691 private:
692 	descriptor_tag  _tag;
693 	uint32 _vds_number;
694 	entity_id _implementation_id;
695 	array<uint8, 460> _implementation_use;
696 } __attribute__((packed));
697 
698 
699 /*! \brief Maximum number of partition descriptors to be found in volume
700 	descriptor sequence, per UDF-2.50
701 */
702 extern const uint8 kMaxPartitionDescriptors;
703 #define UDF_MAX_PARTITION_MAPS 2
704 #define UDF_MAX_PARTITION_MAP_SIZE 64
705 
706 /*! \brief Partition Descriptor
707 
708 	See also: ECMA 167 3/10.5
709 */
710 struct partition_descriptor {
711 private:
712 	union partition_flags_accessor {
713 		uint16 partition_flags;
714 		struct {
715 			uint16 allocated:1,
716 			       reserved:15;
717 		} bits;
718 	};
719 
720 public:
721 	void dump() const;
722 
723 	// Get functions
724 	const descriptor_tag & tag() const { return _tag; }
725 	descriptor_tag & tag() { return _tag; }
726 
727 	uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); }
728 	uint16 partition_flags() const { return B_LENDIAN_TO_HOST_INT16(_partition_flags); }
729 	bool allocated() const {
730 		partition_flags_accessor f;
731 		f.partition_flags = partition_flags();
732 		return f.bits.allocated;
733 	}
734 	uint16 partition_number() const { return B_LENDIAN_TO_HOST_INT16(_partition_number); }
735 
736 	const entity_id& partition_contents() const { return _partition_contents; }
737 	entity_id& partition_contents() { return _partition_contents; }
738 
739 	const array<uint8, 128>& partition_contents_use() const { return _partition_contents_use; }
740 	array<uint8, 128>& partition_contents_use() { return _partition_contents_use; }
741 
742 	uint32 access_type() const { return B_LENDIAN_TO_HOST_INT32(_access_type); }
743 	uint32 start() const { return B_LENDIAN_TO_HOST_INT32(_start); }
744 	uint32 length() const { return B_LENDIAN_TO_HOST_INT32(_length); }
745 
746 	const entity_id& implementation_id() const { return _implementation_id; }
747 	entity_id& implementation_id() { return _implementation_id; }
748 
749 	const array<uint8, 128>& implementation_use() const { return _implementation_use; }
750 	array<uint8, 128>& implementation_use() { return _implementation_use; }
751 
752 	// Set functions
753 	void set_vds_number(uint32 number) { _vds_number = B_HOST_TO_LENDIAN_INT32(number); }
754 	void set_partition_flags(uint16 flags) { _partition_flags = B_HOST_TO_LENDIAN_INT16(flags); }
755 	void set_allocated(bool allocated) {
756 		partition_flags_accessor f;
757 		f.partition_flags = partition_flags();
758 		f.bits.allocated = allocated;
759 		set_partition_flags(f.partition_flags);
760 	}
761 
762 	void set_access_type(uint32 type) { _access_type = B_HOST_TO_LENDIAN_INT32(type); }
763 	void set_start(uint32 start) { _start = B_HOST_TO_LENDIAN_INT32(start); }
764 	void set_length(uint32 length) { _length = B_HOST_TO_LENDIAN_INT32(length); }
765 
766 private:
767 	descriptor_tag  _tag;
768 	uint32 _vds_number;
769 	/*! Bit 0: If 0, shall mean volume space has not been allocated. If 1,
770 	    shall mean volume space has been allocated.
771 	*/
772 	uint16 _partition_flags;
773 	uint16 _partition_number;
774 
775 	/*! - "+NSR03" Volume recorded according to ECMA-167, i.e. UDF
776 		- "+CD001" Volume recorded according to ECMA-119, i.e. iso9660
777 		- "+FDC01" Volume recorded according to ECMA-107
778 		- "+CDW02" Volume recorded according to ECMA-168
779 	*/
780 	entity_id _partition_contents;
781 	array<uint8, 128> _partition_contents_use;
782 
783 	/*! See \c partition_access_type enum
784 	*/
785 	uint32 _access_type;
786 	uint32 _start;
787 	uint32 _length;
788 	entity_id _implementation_id;
789 	array<uint8, 128> _implementation_use;
790 	uint8 _reserved[156];
791 } __attribute__((packed));
792 
793 
794 enum partition_access_type {
795 	PAT_UNSPECIFIED,
796 	PAT_READ_ONLY,
797 	PAT_WRITE_ONCE,
798 	PAT_REWRITABLE,
799 	PAT_OVERWRITABLE,
800 };
801 
802 
803 /*! \brief Logical volume descriptor
804 
805 	See also: ECMA 167 3/10.6, UDF-2.01 2.2.4
806 */
807 struct logical_volume_descriptor {
808 	void dump() const;
809 
810 	// Get functions
811 	const descriptor_tag & tag() const { return _tag; }
812 	descriptor_tag & tag() { return _tag; }
813 
814 	uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); }
815 
816 	const charspec& character_set() const { return _character_set; }
817 	charspec& character_set() { return _character_set; }
818 
819 	const array<char, 128>& logical_volume_identifier() const { return _logical_volume_identifier; }
820 	array<char, 128>& logical_volume_identifier() { return _logical_volume_identifier; }
821 
822 	uint32 logical_block_size() const { return B_LENDIAN_TO_HOST_INT32(_logical_block_size); }
823 
824 	const entity_id& domain_id() const { return _domain_id; }
825 	entity_id& domain_id() { return _domain_id; }
826 
827 	const array<uint8, 16>& logical_volume_contents_use() const { return _logical_volume_contents_use; }
828 	array<uint8, 16>& logical_volume_contents_use() { return _logical_volume_contents_use; }
829 
830 	const long_address& file_set_address() const { return _file_set_address; }
831 	long_address& file_set_address() { return _file_set_address; }
832 
833 	uint32 map_table_length() const { return B_LENDIAN_TO_HOST_INT32(_map_table_length); }
834 	uint32 partition_map_count() const { return B_LENDIAN_TO_HOST_INT32(_partition_map_count); }
835 
836 	const entity_id& implementation_id() const { return _implementation_id; }
837 	entity_id& implementation_id() { return _implementation_id; }
838 
839 	const array<uint8, 128>& implementation_use() const { return _implementation_use; }
840 	array<uint8, 128>& implementation_use() { return _implementation_use; }
841 
842 	const extent_address& integrity_sequence_extent() const { return _integrity_sequence_extent; }
843 	extent_address& integrity_sequence_extent() { return _integrity_sequence_extent; }
844 
845 	const uint8* partition_maps() const { return _partition_maps; }
846 	uint8* partition_maps() { return _partition_maps; }
847 
848 	// Set functions
849 	void set_vds_number(uint32 number) { _vds_number = B_HOST_TO_LENDIAN_INT32(number); }
850 	void set_logical_block_size(uint32 size) { _logical_block_size = B_HOST_TO_LENDIAN_INT32(size); }
851 
852 	void set_map_table_length(uint32 length) { _map_table_length = B_HOST_TO_LENDIAN_INT32(length); }
853 	void set_partition_map_count(uint32 count) { _partition_map_count = B_HOST_TO_LENDIAN_INT32(count); }
854 
855 	// Other functions
856 	logical_volume_descriptor& operator=(const logical_volume_descriptor &rhs);
857 
858 private:
859 	descriptor_tag  _tag;
860 	uint32 _vds_number;
861 
862 	/*! \brief Identifies the character set for the
863 		\c logical_volume_identifier field.
864 
865 		To be set to CS0.
866 	*/
867 	charspec _character_set;
868 	array<char, 128> _logical_volume_identifier;
869 	uint32 _logical_block_size;
870 
871 	/*! \brief To be set to 0 or "*OSTA UDF Compliant". See UDF specs.
872 	*/
873 	entity_id _domain_id;
874 
875 	union {
876 		/*! \brief For UDF, shall contain a \c long_address which identifies
877 			the location of the logical volume's first file set.
878 		*/
879 		array<uint8, 16> _logical_volume_contents_use;
880 		long_address _file_set_address;
881 	};
882 
883 	uint32 _map_table_length;
884 	uint32 _partition_map_count;
885 	entity_id _implementation_id;
886 	array<uint8, 128> _implementation_use;
887 
888 	/*! \brief Logical volume integrity sequence location.
889 
890 		For re/overwritable media, shall be a min of 8KB in length.
891 		For WORM media, shall be quite frickin large, as a new volume
892 		must be added to the set if the extent fills up (since you
893 		can't chain lvis's I guess).
894 	*/
895 	extent_address _integrity_sequence_extent;
896 
897 	/*! \brief Restricted to maps of type 1 for normal maps and
898 		UDF type 2 for virtual maps or maps on systems not supporting
899 		defect management.
900 
901 		Note that we actually allocate memory for the partition maps
902 		here due to the fact that we allocate logical_volume_descriptor
903 		objects on the stack sometimes.
904 
905 		See UDF-2.01 2.2.8, 2.2.9
906 	*/
907 	uint8 _partition_maps[UDF_MAX_PARTITION_MAPS * UDF_MAX_PARTITION_MAP_SIZE];
908 } __attribute__((packed));
909 
910 
911 /*! \brief (Mostly) common portion of various partition maps
912 
913 	See also: ECMA-167 3/10.7.1
914 */
915 struct partition_map_header {
916 public:
917 	uint8 type() const { return _type; }
918 	uint8 length() const { return _length; }
919 	uint8 *map_data() { return _map_data; }
920 	const uint8 *map_data() const { return _map_data; }
921 
922 	entity_id& partition_type_id()
923 		{ return *reinterpret_cast<entity_id*>(&_map_data[2]); }
924 	const entity_id& partition_type_id() const
925 		{ return *reinterpret_cast<const entity_id*>(&_map_data[2]); }
926 
927 	void set_type(uint8 type) { _type = type; }
928 	void set_length(uint8 length) { _length = length; }
929 private:
930 	uint8 _type;
931 	uint8 _length;
932 	uint8 _map_data[0];
933 };// __attribute__((packed));
934 
935 
936 /*! \brief Physical partition map (i.e. ECMA-167 Type 1 partition map)
937 
938 	See also: ECMA-167 3/10.7.2
939 */
940 struct physical_partition_map {
941 public:
942 	void dump();
943 
944 	uint8 type() const { return _type; }
945 	uint8 length() const { return _length; }
946 
947 	uint16 volume_sequence_number() const {
948 		return B_LENDIAN_TO_HOST_INT16(_volume_sequence_number); }
949 	uint16 partition_number() const {
950 		return B_LENDIAN_TO_HOST_INT16(_partition_number); }
951 
952 	void set_type(uint8 type) { _type = type; }
953 	void set_length(uint8 length) { _length = length; }
954 	void set_volume_sequence_number(uint16 number) {
955 		_volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); }
956 	void set_partition_number(uint16 number) {
957 		_partition_number = B_HOST_TO_LENDIAN_INT16(number); }
958 private:
959 	uint8 _type;
960 	uint8 _length;
961 	uint16 _volume_sequence_number;
962 	uint16 _partition_number;
963 } __attribute__((packed));
964 
965 
966 /* ----UDF Specific---- */
967 /*! \brief Virtual partition map
968 
969 	Note that this map is a customization of the ECMA-167
970 	type 2 partition map.
971 
972 	See also: UDF-2.01 2.2.8
973 */
974 struct virtual_partition_map {
975 	uint8 type;
976 	uint8 length;
977 	uint8 reserved1[2];
978 
979 	/*! - flags: 0
980 	    - identifier: "*UDF Virtual Partition"
981 	    - identifier_suffix: per UDF-2.01 2.1.5.3
982 	*/
983 	entity_id partition_type_id;
984 	uint16 volume_sequence_number;
985 
986 	/*! corresponding type 1 partition map in same logical volume
987 	*/
988 	uint16 partition_number;
989 	uint8 reserved2[24];
990 } __attribute__((packed));
991 
992 
993 /*! \brief Maximum number of redundant sparing tables found in
994 	sparable_partition_map structures.
995 */
996 #define UDF_MAX_SPARING_TABLE_COUNT 4
997 
998 /* ----UDF Specific---- */
999 /*! \brief Sparable partition map
1000 
1001 	Note that this map is a customization of the ECMA-167
1002 	type 2 partition map.
1003 
1004 	See also: UDF-2.01 2.2.9
1005 */
1006 struct sparable_partition_map {
1007 public:
1008 	void dump();
1009 
1010 	uint8 type() const { return _type; }
1011 	uint8 length() const { return _length; }
1012 
1013 	entity_id& partition_type_id() { return _partition_type_id; }
1014 	const entity_id& partition_type_id() const { return _partition_type_id; }
1015 
1016 	uint16 volume_sequence_number() const {
1017 		return B_LENDIAN_TO_HOST_INT16(_volume_sequence_number); }
1018 	uint16 partition_number() const {
1019 		return B_LENDIAN_TO_HOST_INT16(_partition_number); }
1020 	uint16 packet_length() const {
1021 		return B_LENDIAN_TO_HOST_INT16(_packet_length); }
1022 	uint8 sparing_table_count() const { return _sparing_table_count; }
1023 	uint32 sparing_table_size() const {
1024 		return B_LENDIAN_TO_HOST_INT32(_sparing_table_size); }
1025 	uint32 sparing_table_location(uint8 index) const {
1026 		return B_LENDIAN_TO_HOST_INT32(_sparing_table_locations[index]); }
1027 
1028 
1029 	void set_type(uint8 type) { _type = type; }
1030 	void set_length(uint8 length) { _length = length; }
1031 	void set_volume_sequence_number(uint16 number) {
1032 		_volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); }
1033 	void set_partition_number(uint16 number) {
1034 		_partition_number = B_HOST_TO_LENDIAN_INT16(number); }
1035 	void set_packet_length(uint16 length) {
1036 		_packet_length = B_HOST_TO_LENDIAN_INT16(length); }
1037 	void set_sparing_table_count(uint8 count) {
1038 		_sparing_table_count = count; }
1039 	void set_sparing_table_size(uint32 size) {
1040 		_sparing_table_size = B_HOST_TO_LENDIAN_INT32(size); }
1041 	void set_sparing_table_location(uint8 index, uint32 location) {
1042 		_sparing_table_locations[index] = B_HOST_TO_LENDIAN_INT32(location); }
1043 private:
1044 	uint8 _type;
1045 	uint8 _length;
1046 	uint8 _reserved1[2];
1047 
1048 	/*! - flags: 0
1049 	    - identifier: "*UDF Sparable Partition"
1050 	    - identifier_suffix: per UDF-2.01 2.1.5.3
1051 	*/
1052 	entity_id _partition_type_id;
1053 	uint16 _volume_sequence_number;
1054 
1055 	//! partition number of corresponding partition descriptor
1056 	uint16 _partition_number;
1057 	uint16 _packet_length;
1058 	uint8 _sparing_table_count;
1059 	uint8 _reserved2;
1060 	uint32 _sparing_table_size;
1061 	uint32 _sparing_table_locations[UDF_MAX_SPARING_TABLE_COUNT];
1062 } __attribute__((packed));
1063 
1064 
1065 /* ----UDF Specific---- */
1066 /*! \brief Metadata partition map
1067 
1068 	Note that this map is a customization of the ECMA-167
1069 	type 2 partition map.
1070 
1071 	See also: UDF-2.50 2.2.10
1072 */
1073 struct metadata_partition_map {
1074 	uint8 type;
1075 	uint8 length;
1076 	uint8 reserved1[2];
1077 
1078 	/*! - flags: 0
1079 	    - identifier: "*UDF Metadata Partition"
1080 	    - identifier_suffix: per UDF-2.50 2.1.5
1081 	*/
1082 	entity_id partition_type_id;
1083 	uint16 volume_sequence_number;
1084 
1085 	/*! corresponding type 1 or type 2 sparable partition
1086 	    map in same logical volume
1087 	*/
1088 	uint16 partition_number;
1089 	uint8 reserved2[24];
1090 } __attribute__((packed));
1091 
1092 
1093 /*! \brief Unallocated space descriptor
1094 
1095 	See also: ECMA-167 3/10.8
1096 */
1097 struct unallocated_space_descriptor {
1098 	void dump() const;
1099 
1100 	// Get functions
1101 	const descriptor_tag & tag() const { return _tag; }
1102 	descriptor_tag & tag() { return _tag; }
1103 	uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); }
1104 	uint32 allocation_descriptor_count() const { return B_LENDIAN_TO_HOST_INT32(_allocation_descriptor_count); }
1105 	extent_address* allocation_descriptors() { return _allocation_descriptors; }
1106 
1107 	// Set functions
1108 	void set_vds_number(uint32 number) { _vds_number = B_HOST_TO_LENDIAN_INT32(number); }
1109 	void set_allocation_descriptor_count(uint32 count) { _allocation_descriptor_count = B_HOST_TO_LENDIAN_INT32(count); }
1110 private:
1111 	descriptor_tag  _tag;
1112 	uint32 _vds_number;
1113 	uint32 _allocation_descriptor_count;
1114 	extent_address _allocation_descriptors[0];
1115 } __attribute__((packed));
1116 
1117 
1118 /*! \brief Terminating descriptor
1119 
1120 	See also: ECMA-167 3/10.9
1121 */
1122 struct terminating_descriptor {
1123 	void dump() const;
1124 
1125 	// Get functions
1126 	const descriptor_tag & tag() const { return _tag; }
1127 	descriptor_tag & tag() { return _tag; }
1128 
1129 private:
1130 	descriptor_tag  _tag;
1131 	uint8 _reserved[496];
1132 } __attribute__((packed));
1133 
1134 
1135 /*! \brief Logical volume integrity descriptor
1136 
1137 	See also: ECMA-167 3/10.10
1138 */
1139 struct logical_volume_integrity_descriptor {
1140 	descriptor_tag  tag;
1141 	timestamp recording_time;
1142 	uint32 integrity_type;
1143 	extent_address next_integrity_extent;
1144 	array<uint8, 32> logical_volume_contents_use;
1145 	uint32 partition_count;
1146 	uint32 implementation_use_length;
1147 
1148 	/*! \todo double-check the pointer arithmetic here. */
1149 	uint32* free_space_table() { return (uint32*)(this+80); }
1150 	uint32* size_table() { return (uint32*)(free_space_table()+partition_count*sizeof(uint32)); }
1151 	uint8* implementation_use() { return (uint8*)(size_table()+partition_count*sizeof(uint32)); }
1152 
1153 } __attribute__((packed));
1154 
1155 /*! \brief Logical volume integrity types
1156 */
1157 enum {
1158 	LVIT_OPEN = 1,
1159 	LVIT_CLOSED,
1160 };
1161 
1162 //----------------------------------------------------------------------
1163 // ECMA-167 Part 4
1164 //----------------------------------------------------------------------
1165 
1166 
1167 
1168 /*! \brief File set descriptor
1169 
1170 	Contains all the pertinent info about a file set (i.e. a hierarchy of files)
1171 
1172 	According to UDF-2.01, only one file set descriptor shall be recorded,
1173 	except on WORM media, where the following rules apply:
1174 	- Multiple file sets are allowed only on WORM media
1175 	- The default file set shall be the one with highest value \c file_set_number field.
1176 	- Only the default file set may be flagged as writeable. All others shall be
1177 	  flagged as "hard write protect".
1178 	- No writeable file set may reference metadata structures which are referenced
1179 	  (directly or indirectly) by any other file set. Writeable file sets may, however,
1180 	  reference actual file data extents that are also referenced by other file sets.
1181 */
1182 struct file_set_descriptor {
1183 	void dump() const;
1184 
1185 	// Get functions
1186 	const descriptor_tag & tag() const { return _tag; }
1187 	descriptor_tag & tag() { return _tag; }
1188 
1189 	const timestamp& recording_date_and_time() const { return _recording_date_and_time; }
1190 	timestamp& recording_date_and_time() { return _recording_date_and_time; }
1191 
1192 	uint16 interchange_level() const { return B_LENDIAN_TO_HOST_INT16(_interchange_level); }
1193 	uint16 max_interchange_level() const { return B_LENDIAN_TO_HOST_INT16(_max_interchange_level); }
1194 	uint32 character_set_list() const { return B_LENDIAN_TO_HOST_INT32(_character_set_list); }
1195 	uint32 max_character_set_list() const { return B_LENDIAN_TO_HOST_INT32(_max_character_set_list); }
1196 	uint32 file_set_number() const { return B_LENDIAN_TO_HOST_INT32(_file_set_number); }
1197 	uint32 file_set_descriptor_number() const { return B_LENDIAN_TO_HOST_INT32(_file_set_descriptor_number); }
1198 
1199 	const charspec& logical_volume_id_character_set() const { return _logical_volume_id_character_set; }
1200 	charspec& logical_volume_id_character_set() { return _logical_volume_id_character_set; }
1201 
1202 	const array<char, 128>& logical_volume_id() const { return _logical_volume_id; }
1203 	array<char, 128>& logical_volume_id() { return _logical_volume_id; }
1204 
1205 	const array<char, 32>& file_set_id() const { return _file_set_id; }
1206 	array<char, 32>& file_set_id() { return _file_set_id; }
1207 
1208 	const array<char, 32>& copyright_file_id() const { return _copyright_file_id; }
1209 	array<char, 32>& copyright_file_id() { return _copyright_file_id; }
1210 
1211 	const array<char, 32>& abstract_file_id() const { return _abstract_file_id; }
1212 	array<char, 32>& abstract_file_id() { return _abstract_file_id; }
1213 
1214 	const charspec& file_set_charspec() const { return _file_set_charspec; }
1215 	charspec& file_set_charspec() { return _file_set_charspec; }
1216 
1217 	const long_address& root_directory_icb() const { return _root_directory_icb; }
1218 	long_address& root_directory_icb() { return _root_directory_icb; }
1219 
1220 	const entity_id& domain_id() const { return _domain_id; }
1221 	entity_id& domain_id() { return _domain_id; }
1222 
1223 	const long_address& next_extent() const { return _next_extent; }
1224 	long_address& next_extent() { return _next_extent; }
1225 
1226 	const long_address& system_stream_directory_icb() const { return _system_stream_directory_icb; }
1227 	long_address& system_stream_directory_icb() { return _system_stream_directory_icb; }
1228 
1229 	// Set functions
1230 	void set_interchange_level(uint16 level) { _interchange_level = B_HOST_TO_LENDIAN_INT16(level); }
1231 	void set_max_interchange_level(uint16 level) { _max_interchange_level = B_HOST_TO_LENDIAN_INT16(level); }
1232 	void set_character_set_list(uint32 list) { _character_set_list = B_HOST_TO_LENDIAN_INT32(list); }
1233 	void set_max_character_set_list(uint32 list) { _max_character_set_list = B_HOST_TO_LENDIAN_INT32(list); }
1234 	void set_file_set_number(uint32 number) { _file_set_number = B_HOST_TO_LENDIAN_INT32(number); }
1235 	void set_file_set_descriptor_number(uint32 number) { _file_set_descriptor_number = B_HOST_TO_LENDIAN_INT32(number); }
1236 private:
1237 	descriptor_tag  _tag;
1238 	timestamp _recording_date_and_time;
1239 	uint16 _interchange_level;			//!< To be set to 3 (see UDF-2.01 2.3.2.1)
1240 	uint16 _max_interchange_level;		//!< To be set to 3 (see UDF-2.01 2.3.2.2)
1241 	uint32 _character_set_list;
1242 	uint32 _max_character_set_list;
1243 	uint32 _file_set_number;
1244 	uint32 _file_set_descriptor_number;
1245 	charspec _logical_volume_id_character_set;	//!< To be set to kCSOCharspec
1246 	array<char, 128> _logical_volume_id;
1247 	charspec _file_set_charspec;
1248 	array<char, 32> _file_set_id;
1249 	array<char, 32> _copyright_file_id;
1250 	array<char, 32> _abstract_file_id;
1251 	long_address _root_directory_icb;
1252 	entity_id _domain_id;
1253 	long_address _next_extent;
1254 	long_address _system_stream_directory_icb;
1255 	uint8 _reserved[32];
1256 } __attribute__((packed));
1257 
1258 
1259 /*! \brief Partition header descriptor
1260 
1261 	Contains references to unallocated and freed space data structures.
1262 
1263 	Note that unallocated space is space ready to be written with no
1264 	preprocessing. Freed space is space needing preprocessing (i.e.
1265 	a special write pass) before use.
1266 
1267 	Per UDF-2.01 2.3.3, the use of tables or bitmaps shall be consistent,
1268 	i.e. only one type or the other shall be used, not both.
1269 
1270 	To indicate disuse of a certain field, the fields of the allocation
1271 	descriptor shall all be set to 0.
1272 
1273 	See also: ECMA-167 4/14.3, UDF-2.01 2.2.3
1274 */
1275 struct partition_header_descriptor {
1276 	long_address unallocated_space_table;
1277 	long_address unallocated_space_bitmap;
1278 	/*! Unused, per UDF-2.01 2.2.3 */
1279 	long_address partition_integrity_table;
1280 	long_address freed_space_table;
1281 	long_address freed_space_bitmap;
1282 	uint8 reserved[88];
1283 } __attribute__((packed));
1284 
1285 #define kMaxFileIdSize (sizeof(file_id_descriptor)+512+3)
1286 
1287 /*! \brief File identifier descriptor
1288 
1289 	Identifies the name of a file entry, and the location of its corresponding
1290 	ICB.
1291 
1292 	See also: ECMA-167 4/14.4, UDF-2.01 2.3.4
1293 
1294 	\todo Check pointer arithmetic
1295 */
1296 struct file_id_descriptor {
1297 public:
1298 	void dump() const;
1299 
1300 	descriptor_tag & tag() { return _tag; }
1301 	const descriptor_tag & tag() const { return _tag; }
1302 
1303 	uint16 version_number() const { return B_LENDIAN_TO_HOST_INT16(_version_number); }
1304 
1305 	uint8 characteristics() const { return _characteristics; }
1306 
1307 	bool may_be_hidden() const {
1308 		characteristics_accessor c;
1309 		c.all = characteristics();
1310 		return c.bits.may_be_hidden;
1311 	}
1312 
1313 	bool is_directory() const {
1314 		characteristics_accessor c;
1315 		c.all = characteristics();
1316 		return c.bits.is_directory;
1317 	}
1318 
1319 	bool is_deleted() const {
1320 		characteristics_accessor c;
1321 		c.all = characteristics();
1322 		return c.bits.is_deleted;
1323 	}
1324 
1325 	bool is_parent() const {
1326 		characteristics_accessor c;
1327 		c.all = characteristics();
1328 		return c.bits.is_parent;
1329 	}
1330 
1331 	bool is_metadata_stream() const {
1332 		characteristics_accessor c;
1333 		c.all = characteristics();
1334 		return c.bits.is_metadata_stream;
1335 	}
1336 
1337 	uint8 id_length() const { return _id_length; }
1338 
1339 	long_address& icb() { return _icb; }
1340 	const long_address& icb() const { return _icb; }
1341 
1342 	uint8 implementation_use_length() const { return _implementation_use_length; }
1343 
1344 	/*! If implementation_use_length is greater than 0, the first 32
1345 		bytes of implementation_use() shall be an entity_id identifying
1346 		the implementation that generated the rest of the data in the
1347 		implementation_use() field.
1348 	*/
1349 	uint8* implementation_use() { return ((uint8*)this)+38; }
1350 	char* id() { return ((char*)this)+38+implementation_use_length(); }
1351 	const char* id() const { return ((const char*)this)+38+implementation_use_length(); }
1352 
1353 	uint16 structure_length() const { return 38 + id_length() + implementation_use_length(); }
1354 	uint16 padding_length() const { return ((structure_length()+3)/4)*4 - structure_length(); }
1355 	uint16 total_length() const { return structure_length() + padding_length(); }
1356 
1357 	// Set functions
1358 	void set_version_number(uint16 number) { _version_number = B_HOST_TO_LENDIAN_INT16(number); }
1359 
1360 	void set_characteristics(uint8 characteristics) { _characteristics = characteristics; }
1361 
1362 	void set_may_be_hidden(bool how) {
1363 		characteristics_accessor c;
1364 		c.all = characteristics();
1365 		c.bits.may_be_hidden = how;
1366 		set_characteristics(c.all);
1367 	}
1368 
1369 	void set_is_directory(bool how) {
1370 		characteristics_accessor c;
1371 		c.all = characteristics();
1372 		c.bits.is_directory = how;
1373 		set_characteristics(c.all);
1374 	}
1375 
1376 	void set_is_deleted(bool how) {
1377 		characteristics_accessor c;
1378 		c.all = characteristics();
1379 		c.bits.is_deleted = how;
1380 		set_characteristics(c.all);
1381 	}
1382 
1383 	void set_is_parent(bool how) {
1384 		characteristics_accessor c;
1385 		c.all = characteristics();
1386 		c.bits.is_parent = how;
1387 		set_characteristics(c.all);
1388 	}
1389 
1390 	void set_is_metadata_stream(bool how) {
1391 		characteristics_accessor c;
1392 		c.all = characteristics();
1393 		c.bits.is_metadata_stream = how;
1394 		set_characteristics(c.all);
1395 	}
1396 
1397 
1398 	void set_id_length(uint8 id_length) { _id_length = id_length; }
1399 	void set_implementation_use_length(uint8 implementation_use_length) { _implementation_use_length = implementation_use_length; }
1400 
1401 
1402 
1403 private:
1404 	union characteristics_accessor {
1405 		uint8 all;
1406 		struct {
1407 			uint8	may_be_hidden:1,
1408 					is_directory:1,
1409 					is_deleted:1,
1410 					is_parent:1,
1411 					is_metadata_stream:1,
1412 					reserved_characteristics:3;
1413 		} bits;
1414 	};
1415 
1416 	descriptor_tag  _tag;
1417 	/*! According to ECMA-167: 1 <= valid version_number <= 32767, 32768 <= reserved <= 65535.
1418 
1419 		However, according to UDF-2.01, there shall be exactly one version of
1420 		a file, and it shall be 1.
1421 	 */
1422 	uint16 _version_number;
1423 	/*! \todo Check UDF-2.01 2.3.4.2 for some more restrictions. */
1424 	uint8 _characteristics;
1425 	uint8 _id_length;
1426 	long_address _icb;
1427 	uint8 _implementation_use_length;
1428 } __attribute__((packed));
1429 
1430 
1431 /*! \brief Allocation extent descriptor
1432 
1433 	See also: ECMA-167 4/14.5
1434 */
1435 struct allocation_extent_descriptor {
1436 	descriptor_tag  tag;
1437 	uint32 previous_allocation_extent_location;
1438 	uint32 length_of_allocation_descriptors;
1439 
1440 	/*! \todo Check that this is really how things work: */
1441 	uint8* allocation_descriptors() { return (uint8*)(this+sizeof(allocation_extent_descriptor)); }
1442 } __attribute__((packed));
1443 
1444 
1445 /*! \brief icb_tag::file_type values
1446 
1447 	See also ECMA-167 4/14.6.6
1448 */
1449 enum icb_file_types {
1450 	ICB_TYPE_UNSPECIFIED = 0,
1451 	ICB_TYPE_UNALLOCATED_SPACE_ENTRY,
1452 	ICB_TYPE_PARTITION_INTEGRITY_ENTRY,
1453 	ICB_TYPE_INDIRECT_ENTRY,
1454 	ICB_TYPE_DIRECTORY,
1455 	ICB_TYPE_REGULAR_FILE,
1456 	ICB_TYPE_BLOCK_SPECIAL_DEVICE,
1457 	ICB_TYPE_CHARACTER_SPECIAL_DEVICE,
1458 	ICB_TYPE_EXTENDED_ATTRIBUTES_FILE,
1459 	ICB_TYPE_FIFO,
1460 	ICB_TYPE_ISSOCK,
1461 	ICB_TYPE_TERMINAL,
1462 	ICB_TYPE_SYMLINK,
1463 	ICB_TYPE_STREAM_DIRECTORY,
1464 
1465 	ICB_TYPE_RESERVED_START = 14,
1466 	ICB_TYPE_RESERVED_END = 247,
1467 
1468 	ICB_TYPE_CUSTOM_START = 248,
1469 	ICB_TYPE_CUSTOM_END = 255,
1470 };
1471 
1472 /*!	\brief idb_entry_tag::_flags::descriptor_flags() values
1473 
1474 	See also ECMA-167 4/14.6.8
1475 */
1476 enum icb_descriptor_types {
1477 	ICB_DESCRIPTOR_TYPE_SHORT = 0,
1478 	ICB_DESCRIPTOR_TYPE_LONG,
1479 	ICB_DESCRIPTOR_TYPE_EXTENDED,
1480 	ICB_DESCRIPTOR_TYPE_EMBEDDED,
1481 };
1482 
1483 /*! \brief ICB entry tag
1484 
1485 	Common tag found in all ICB entries (in addition to, and immediately following,
1486 	the descriptor tag).
1487 
1488 	See also: ECMA-167 4/14.6, UDF-2.01 2.3.5
1489 */
1490 struct icb_entry_tag {
1491 private:
1492 	union flags_accessor {
1493 		uint16 all_flags;
1494 		struct {
1495 			uint16	descriptor_flags:3,
1496 					if_directory_then_sort:1,	//!< To be set to 0 per UDF-2.01 2.3.5.4
1497 					non_relocatable:1,
1498 					archive:1,
1499 					setuid:1,
1500 					setgid:1,
1501 					sticky:1,
1502 					contiguous:1,
1503 					system:1,
1504 					transformed:1,
1505 					multi_version:1,			//!< To be set to 0 per UDF-2.01 2.3.5.4
1506 					is_stream:1,
1507 					reserved_icb_entry_flags:2;
1508 		} flags;
1509 	};
1510 
1511 public:
1512 	void dump() const;
1513 
1514 	uint32 prior_recorded_number_of_direct_entries() const { return B_LENDIAN_TO_HOST_INT32(_prior_recorded_number_of_direct_entries); }
1515 	uint16 strategy_type() const { return B_LENDIAN_TO_HOST_INT16(_strategy_type); }
1516 
1517 	array<uint8, 2>& strategy_parameters() { return _strategy_parameters; }
1518 	const array<uint8, 2>& strategy_parameters() const { return _strategy_parameters; }
1519 
1520 	uint16 entry_count() const { return B_LENDIAN_TO_HOST_INT16(_entry_count); }
1521 	uint8 file_type() const { return _file_type; }
1522 	logical_block_address& parent_icb_location() { return _parent_icb_location; }
1523 	const logical_block_address& parent_icb_location() const { return _parent_icb_location; }
1524 
1525 	uint16 flags() const { return B_LENDIAN_TO_HOST_INT16(_flags); }
1526 
1527 	// flags accessor functions
1528 	uint8 descriptor_flags() const {
1529 		flags_accessor f;
1530 		f.all_flags = flags();
1531 		return f.flags.descriptor_flags;
1532 	}
1533 
1534 	void set_prior_recorded_number_of_direct_entries(uint32 entries) { _prior_recorded_number_of_direct_entries = B_LENDIAN_TO_HOST_INT32(entries); }
1535 	void set_strategy_type(uint16 type) { _strategy_type = B_HOST_TO_LENDIAN_INT16(type); }
1536 
1537 	void set_entry_count(uint16 count) { _entry_count = B_LENDIAN_TO_HOST_INT16(count); }
1538 	void set_file_type(uint8 type) { _file_type = type; }
1539 
1540 	void set_flags(uint16 flags) { _flags = B_LENDIAN_TO_HOST_INT16(flags); }
1541 
1542 private:
1543 	uint32 _prior_recorded_number_of_direct_entries;
1544 	/*! Per UDF-2.01 2.3.5.1, only strategy types 4 and 4096 shall be supported.
1545 
1546 		\todo Describe strategy types here.
1547 	*/
1548 	uint16 _strategy_type;
1549 	array<uint8, 2> _strategy_parameters;
1550 	uint16 _entry_count;
1551 	uint8 _reserved;
1552 	/*! \brief icb_file_type value identifying the type of this icb entry */
1553 	uint8 _file_type;
1554 	logical_block_address _parent_icb_location;
1555 	uint16 _flags;
1556 } __attribute__((packed));
1557 
1558 /*! \brief Header portion of an ICB entry.
1559 */
1560 struct icb_header {
1561 public:
1562 	void dump() const;
1563 
1564 	descriptor_tag  &tag() { return _tag; }
1565 	const descriptor_tag  &tag() const { return _tag; }
1566 
1567 	icb_entry_tag &icb_tag() { return _icb_tag; }
1568 	const icb_entry_tag &icb_tag() const { return _icb_tag; }
1569 private:
1570 	descriptor_tag  _tag;
1571 	icb_entry_tag _icb_tag;
1572 };
1573 
1574 /*! \brief Indirect ICB entry
1575 */
1576 struct indirect_icb_entry {
1577 	descriptor_tag  tag;
1578 	icb_entry_tag icb_tag;
1579 	long_address indirect_icb;
1580 } __attribute__((packed));
1581 
1582 
1583 /*! \brief Terminal ICB entry
1584 */
1585 struct terminal_icb_entry {
1586 	descriptor_tag  tag;
1587 	icb_entry_tag icb_tag;
1588 } __attribute__((packed));
1589 
1590 
1591 /*! \brief File ICB entry
1592 
1593 	See also: ECMA-167 4/14.9
1594 
1595 	\todo Check pointer math.
1596 */
1597 struct file_icb_entry {
1598 	// get functions
1599 	descriptor_tag & tag() { return _tag; }
1600 	const descriptor_tag & tag() const { return _tag; }
1601 
1602 	icb_entry_tag& icb_tag() { return _icb_tag; }
1603 	const icb_entry_tag& icb_tag() const { return _icb_tag; }
1604 
1605 	uint32 uid() { return B_LENDIAN_TO_HOST_INT32(_uid); }
1606 	uint32 gid() { return B_LENDIAN_TO_HOST_INT32(_gid); }
1607 	uint32 permissions() { return B_LENDIAN_TO_HOST_INT32(_permissions); }
1608 	uint16 file_link_count() { return B_LENDIAN_TO_HOST_INT16(_file_link_count); }
1609 	uint8 record_format() { return _record_format; }
1610 	uint8 record_display_attributes() { return _record_display_attributes; }
1611 	uint8 record_length() { return _record_length; }
1612 	uint64 information_length() { return B_LENDIAN_TO_HOST_INT64(_information_length); }
1613 	uint64 logical_blocks_recorded() { return B_LENDIAN_TO_HOST_INT64(_logical_blocks_recorded); }
1614 
1615 	timestamp& access_date_and_time() { return _access_date_and_time; }
1616 	const timestamp& access_date_and_time() const { return _access_date_and_time; }
1617 
1618 	timestamp& modification_date_and_time() { return _modification_date_and_time; }
1619 	const timestamp& modification_date_and_time() const { return _modification_date_and_time; }
1620 
1621 	timestamp& attribute_date_and_time() { return _attribute_date_and_time; }
1622 	const timestamp& attribute_date_and_time() const { return _attribute_date_and_time; }
1623 
1624 	uint32 checkpoint() { return B_LENDIAN_TO_HOST_INT32(_checkpoint); }
1625 
1626 	long_address& extended_attribute_icb() { return _extended_attribute_icb; }
1627 	const long_address& extended_attribute_icb() const { return _extended_attribute_icb; }
1628 
1629 	entity_id& implementation_id() { return _implementation_id; }
1630 	const entity_id& implementation_id() const { return _implementation_id; }
1631 
1632 	uint64 unique_id() { return B_LENDIAN_TO_HOST_INT64(_unique_id); }
1633 	uint32 extended_attributes_length() { return B_LENDIAN_TO_HOST_INT32(_extended_attributes_length); }
1634 	uint32 allocation_descriptors_length() { return B_LENDIAN_TO_HOST_INT32(_allocation_descriptors_length); }
1635 
1636 	uint8* extended_attributes() { return ((uint8*)(this))+sizeof(file_icb_entry); }
1637 	uint8* allocation_descriptors() { return ((uint8*)(this))+sizeof(file_icb_entry)+extended_attributes_length(); }
1638 
1639 	// set functions
1640 	void set_uid(uint32 uid) { _uid = B_HOST_TO_LENDIAN_INT32(uid); }
1641 	void set_gid(uint32 gid) { _gid = B_HOST_TO_LENDIAN_INT32(gid); }
1642 	void set_permissions(uint32 permissions) { _permissions = B_HOST_TO_LENDIAN_INT32(permissions); }
1643 
1644 	void set_file_link_count(uint16 count) { _file_link_count = B_HOST_TO_LENDIAN_INT16(count); }
1645 	void set_record_format(uint8 format) { _record_format = format; }
1646 	void set_record_display_attributes(uint8 attributes) { _record_display_attributes = attributes; }
1647 	void set_record_length(uint8 length) { _record_length = length; }
1648 
1649 	void set_information_length(uint64 length) { _information_length = B_HOST_TO_LENDIAN_INT64(length); }
1650 	void set_logical_blocks_recorded(uint64 blocks) { _logical_blocks_recorded = B_HOST_TO_LENDIAN_INT64(blocks); }
1651 
1652 	void set_checkpoint(uint32 checkpoint) { _checkpoint = B_HOST_TO_LENDIAN_INT32(checkpoint); }
1653 
1654 	void set_unique_id(uint64 id) { _unique_id = B_HOST_TO_LENDIAN_INT64(id); }
1655 
1656 	void set_extended_attributes_length(uint32 length) { _extended_attributes_length = B_HOST_TO_LENDIAN_INT32(length); }
1657 	void set_allocation_descriptors_length(uint32 length) { _allocation_descriptors_length = B_HOST_TO_LENDIAN_INT32(length); }
1658 
1659 private:
1660 	descriptor_tag  _tag;
1661 	icb_entry_tag _icb_tag;
1662 	uint32 _uid;
1663 	uint32 _gid;
1664 	/*! \todo List perms in comment and add handy union thingy */
1665 	uint32 _permissions;
1666 	/*! Identifies the number of file identifier descriptors referencing
1667 		this icb.
1668 	*/
1669 	uint16 _file_link_count;
1670 	uint8 _record_format;				//!< To be set to 0 per UDF-2.01 2.3.6.1
1671 	uint8 _record_display_attributes;	//!< To be set to 0 per UDF-2.01 2.3.6.2
1672 	uint8 _record_length;				//!< To be set to 0 per UDF-2.01 2.3.6.3
1673 	uint64 _information_length;
1674 	uint64 _logical_blocks_recorded;		//!< To be 0 for files and dirs with embedded data
1675 	timestamp _access_date_and_time;
1676 	timestamp _modification_date_and_time;
1677 
1678 	// NOTE: data members following this point in the descriptor are in
1679 	// different locations in extended file entries
1680 
1681 	timestamp _attribute_date_and_time;
1682 	/*! \brief Initially 1, may be incremented upon user request. */
1683 	uint32 _checkpoint;
1684 	long_address _extended_attribute_icb;
1685 	entity_id _implementation_id;
1686 	/*! \brief The unique id identifying this file entry
1687 
1688 		The id of the root directory of a file set shall be 0.
1689 
1690 		\todo Detail the system specific requirements for unique ids from UDF-2.01
1691 	*/
1692 	uint64 _unique_id;
1693 	uint32 _extended_attributes_length;
1694 	uint32 _allocation_descriptors_length;
1695 
1696 };
1697 
1698 
1699 /*! \brief Extended file ICB entry
1700 
1701 	See also: ECMA-167 4/14.17
1702 
1703 	\todo Check pointer math.
1704 */
1705 struct extended_file_icb_entry {
1706 	// get functions
1707 	descriptor_tag & tag() { return _tag; }
1708 	const descriptor_tag & tag() const { return _tag; }
1709 
1710 	icb_entry_tag& icb_tag() { return _icb_tag; }
1711 	const icb_entry_tag& icb_tag() const { return _icb_tag; }
1712 
1713 	uint32 uid() { return B_LENDIAN_TO_HOST_INT32(_uid); }
1714 	uint32 gid() { return B_LENDIAN_TO_HOST_INT32(_gid); }
1715 	uint32 permissions() { return B_LENDIAN_TO_HOST_INT32(_permissions); }
1716 	uint16 file_link_count() { return B_LENDIAN_TO_HOST_INT16(_file_link_count); }
1717 	uint8 record_format() { return _record_format; }
1718 	uint8 record_display_attributes() { return _record_display_attributes; }
1719 	uint8 record_length() { return _record_length; }
1720 	uint64 information_length() { return B_LENDIAN_TO_HOST_INT64(_information_length); }
1721 	uint64 logical_blocks_recorded() { return B_LENDIAN_TO_HOST_INT64(_logical_blocks_recorded); }
1722 
1723 	timestamp& access_date_and_time() { return _access_date_and_time; }
1724 	const timestamp& access_date_and_time() const { return _access_date_and_time; }
1725 
1726 	timestamp& modification_date_and_time() { return _modification_date_and_time; }
1727 	const timestamp& modification_date_and_time() const { return _modification_date_and_time; }
1728 
1729 	timestamp& attribute_date_and_time() { return _attribute_date_and_time; }
1730 	const timestamp& attribute_date_and_time() const { return _attribute_date_and_time; }
1731 
1732 	uint32 checkpoint() { return B_LENDIAN_TO_HOST_INT32(_checkpoint); }
1733 
1734 	long_address& extended_attribute_icb() { return _extended_attribute_icb; }
1735 	const long_address& extended_attribute_icb() const { return _extended_attribute_icb; }
1736 
1737 	entity_id& implementation_id() { return _implementation_id; }
1738 	const entity_id& implementation_id() const { return _implementation_id; }
1739 
1740 	uint64 unique_id() { return B_LENDIAN_TO_HOST_INT64(_unique_id); }
1741 	uint32 extended_attributes_length() { return B_LENDIAN_TO_HOST_INT32(_extended_attributes_length); }
1742 	uint32 allocation_descriptors_length() { return B_LENDIAN_TO_HOST_INT32(_allocation_descriptors_length); }
1743 
1744 	uint8* extended_attributes() { return (uint8*)(this+sizeof(*this)); }
1745 	uint8* allocation_descriptors() { return (uint8*)(this+sizeof(*this)+extended_attributes_length()); }
1746 
1747 	// set functions
1748 	void set_uid(uint32 uid) { _uid = B_HOST_TO_LENDIAN_INT32(uid); }
1749 	void set_gid(uint32 gid) { _gid = B_HOST_TO_LENDIAN_INT32(gid); }
1750 	void set_permissions(uint32 permissions) { _permissions = B_HOST_TO_LENDIAN_INT32(permissions); }
1751 
1752 	void set_file_link_count(uint16 count) { _file_link_count = B_HOST_TO_LENDIAN_INT16(count); }
1753 	void set_record_format(uint8 format) { _record_format = format; }
1754 	void set_record_display_attributes(uint8 attributes) { _record_display_attributes = attributes; }
1755 	void set_record_length(uint8 length) { _record_length = length; }
1756 
1757 	void set_information_length(uint64 length) { _information_length = B_HOST_TO_LENDIAN_INT64(length); }
1758 	void set_logical_blocks_recorded(uint64 blocks) { _logical_blocks_recorded = B_HOST_TO_LENDIAN_INT64(blocks); }
1759 
1760 	void set_checkpoint(uint32 checkpoint) { _checkpoint = B_HOST_TO_LENDIAN_INT32(checkpoint); }
1761 
1762 	void set_unique_id(uint64 id) { _unique_id = B_HOST_TO_LENDIAN_INT64(id); }
1763 
1764 	void set_extended_attributes_length(uint32 length) { _extended_attributes_length = B_HOST_TO_LENDIAN_INT32(length); }
1765 	void set_allocation_descriptors_length(uint32 length) { _allocation_descriptors_length = B_HOST_TO_LENDIAN_INT32(length); }
1766 
1767 private:
1768 	descriptor_tag  _tag;
1769 	icb_entry_tag _icb_tag;
1770 	uint32 _uid;
1771 	uint32 _gid;
1772 	/*! \todo List perms in comment and add handy union thingy */
1773 	uint32 _permissions;
1774 	/*! Identifies the number of file identifier descriptors referencing
1775 		this icb.
1776 	*/
1777 	uint16 _file_link_count;
1778 	uint8 _record_format;				//!< To be set to 0 per UDF-2.01 2.3.6.1
1779 	uint8 _record_display_attributes;	//!< To be set to 0 per UDF-2.01 2.3.6.2
1780 	uint8 _record_length;				//!< To be set to 0 per UDF-2.01 2.3.6.3
1781 	uint64 _information_length;
1782 	uint64 _logical_blocks_recorded;		//!< To be 0 for files and dirs with embedded data
1783 	timestamp _access_date_and_time;
1784 	timestamp _modification_date_and_time;
1785 	timestamp _creation_date_and_time;	// <== EXTENDED FILE ENTRY ONLY
1786 	timestamp _attribute_date_and_time;
1787 	/*! \brief Initially 1, may be incremented upon user request. */
1788 	uint32 _checkpoint;
1789 	uint32 _reserved;	// <== EXTENDED FILE ENTRY ONLY
1790 	long_address _extended_attribute_icb;
1791 	long_address _stream_directory_icb;	// <== EXTENDED FILE ENTRY ONLY
1792 	entity_id _implementation_id;
1793 	/*! \brief The unique id identifying this file entry
1794 
1795 		The id of the root directory of a file set shall be 0.
1796 
1797 		\todo Detail the system specific requirements for unique ids from UDF-2.01 3.2.1.1
1798 	*/
1799 	uint64 _unique_id;
1800 	uint32 _extended_attributes_length;
1801 	uint32 _allocation_descriptors_length;
1802 
1803 };
1804 
1805 
1806 };	// namespace Udf
1807 
1808 #endif	// _UDF_DISK_STRUCTURES_H
1809 
1810