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