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