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
45namespace 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*/
58struct charspec {
59public:
60	charspec(uint8 type = 0, const char *info = NULL);
61
62	void dump() const;
63
64	uint8 character_set_type() const { return _character_set_type; }
65	const char* character_set_info() const { return _character_set_info; }
66	char* character_set_info() { return _character_set_info; }
67
68	void set_character_set_type(uint8 type) { _character_set_type = type; }
69	void set_character_set_info(const char *info);
70private:
71	uint8 _character_set_type;	//!< to be set to 0 to indicate CS0
72	char _character_set_info[63];	//!< "OSTA Compressed Unicode"
73} __attribute__((packed));
74
75extern const charspec kCs0CharacterSet;
76
77/*! \brief Date and time stamp
78
79	See also: ECMA 167 1/7.3, UDF-2.01 2.1.4
80*/
81class timestamp {
82private:
83	union type_and_timezone_accessor {
84		uint16 type_and_timezone;
85		struct {
86			uint16 timezone:12,
87			       type:4;
88		} bits;
89	};
90
91public:
92	timestamp() { _clear(); }
93	timestamp(time_t time);
94
95	void dump() const;
96
97	// Get functions
98	uint16 type_and_timezone() const { return B_LENDIAN_TO_HOST_INT16(_type_and_timezone); }
99	uint8 type() const {
100		type_and_timezone_accessor t;
101		t.type_and_timezone = type_and_timezone();
102		return t.bits.type;
103	}
104	int16 timezone() const {
105		type_and_timezone_accessor t;
106		t.type_and_timezone = type_and_timezone();
107		int16 result = t.bits.timezone;
108		// Fill the lefmost bits with ones if timezone is negative
109		result <<= 4;
110		result >>= 4;
111		return result;
112	}
113	uint16 year() const { return B_LENDIAN_TO_HOST_INT16(_year); }
114	uint8 month() const { return _month; }
115	uint8 day() const { return _day; }
116	uint8 hour() const { return _hour; }
117	uint8 minute() const { return _minute; }
118	uint8 second() const { return _second; }
119	uint8 centisecond() const { return _centisecond; }
120	uint8 hundred_microsecond() const { return _hundred_microsecond; }
121	uint8 microsecond() const { return _microsecond; }
122
123	// Set functions
124	void set_type_and_timezone(uint16 type_and_timezone) { _type_and_timezone = B_HOST_TO_LENDIAN_INT16(type_and_timezone); }
125	void set_type(uint8 type) {
126		type_and_timezone_accessor t;
127		t.type_and_timezone = type_and_timezone();
128		t.bits.type = type;
129		set_type_and_timezone(t.type_and_timezone);
130	}
131	void set_timezone(int16 tz) {
132		type_and_timezone_accessor t;
133		t.type_and_timezone = type_and_timezone();
134		t.bits.timezone = tz;
135		set_type_and_timezone(t.type_and_timezone);
136	}
137	void set_year(uint16 year) { _year = B_HOST_TO_LENDIAN_INT16(year); }
138	void set_month(uint8 month) { _month = month; }
139	void set_day(uint8 day) { _day = day; }
140	void set_hour(uint8 hour) { _hour = hour; }
141	void set_minute(uint8 minute) { _minute = minute; }
142	void set_second(uint8 second) { _second = second; }
143	void set_centisecond(uint8 centisecond) { _centisecond = centisecond; }
144	void set_hundred_microsecond(uint8 hundred_microsecond) { _hundred_microsecond = hundred_microsecond; }
145	void set_microsecond(uint8 microsecond) { _microsecond = microsecond; }
146private:
147	void _clear();
148
149	uint16 _type_and_timezone;
150	uint16 _year;
151	uint8 _month;
152	uint8 _day;
153	uint8 _hour;
154	uint8 _minute;
155	uint8 _second;
156	uint8 _centisecond;
157	uint8 _hundred_microsecond;
158	uint8 _microsecond;
159
160} __attribute__((packed));
161
162
163/*! \brief UDF ID Identify Suffix
164
165	See also: UDF 2.50 2.1.5.3
166*/
167struct udf_id_suffix {
168public:
169	udf_id_suffix(uint16 udfRevision, uint8 os_class, uint8 os_identifier);
170
171	//! Note that revision 2.50 is denoted by 0x0250.
172	uint16 udf_revision() const { return _udf_revision; }
173	uint8 os_class() const { return _os_class; }
174	uint8 os_identifier() const { return _os_identifier; }
175
176	void set_os_class(uint8 os_class) { _os_class = os_class; }
177	void set_os_identifier(uint8 identifier) { _os_identifier = identifier; }
178private:
179	uint16 _udf_revision;
180	uint8 _os_class;
181	uint8 _os_identifier;
182	array<uint8, 4> _reserved;
183};
184
185/*! \brief Implementation ID Identify Suffix
186
187	See also: UDF 2.50 2.1.5.3
188*/
189struct implementation_id_suffix {
190public:
191	implementation_id_suffix(uint8 os_class, uint8 os_identifier);
192
193	uint8 os_class() const { return _os_class; }
194	uint8 os_identifier() const { return _os_identifier; }
195
196	void set_os_class(uint8 os_class) { _os_class = os_class; }
197	void set_os_identifier(uint8 identifier) { _os_identifier = identifier; }
198private:
199	uint8 _os_class;
200	uint8 _os_identifier;
201	array<uint8, 6> _implementation_use;
202};
203
204/*! \brief Operating system classes for implementation_id_suffixes
205
206	See also: Udf 2.50 6.3
207*/
208enum {
209	OS_UNDEFINED = 0,
210	OS_DOS,
211	OS_OS2,
212	OS_MACOS,
213	OS_UNIX,
214	OS_WIN9X,
215	OS_WINNT,
216	OS_OS400,
217	OS_BEOS,
218	OS_WINCE
219};
220
221/*! \brief BeOS operating system classes identifiers for implementation_id_suffixes
222
223	See also: Udf 2.50 6.3
224*/
225enum {
226	BEOS_GENERIC = 0,
227	BEOS_OPENBEOS = 1	// not part of the standard, but perhaps someday. :-)
228};
229
230/*! \brief Domain ID Identify Suffix
231
232	See also: UDF 2.50 2.1.5.3
233*/
234struct domain_id_suffix {
235public:
236	domain_id_suffix(uint16 udfRevision, uint8 domainFlags);
237
238	//! Note that revision 2.50 is denoted by 0x0250.
239	uint16 udf_revision() const { return _udf_revision; }
240	uint8 domain_flags() const { return _domain_flags; }
241
242	void set_udf_revision(uint16 revision) { _udf_revision = B_HOST_TO_LENDIAN_INT16(revision); }
243	void set_domain_flags(uint8 flags) { _domain_flags = flags; }
244private:
245	uint16 _udf_revision;
246	uint8 _domain_flags;
247	array<uint8, 5> _reserved;
248};
249
250/*! \brief Domain flags
251
252	See also: UDF 2.50 2.1.5.3
253*/
254enum {
255	DF_HARD_WRITE_PROTECT = 0x01,
256	DF_SOFT_WRITE_PROTECT = 0x02
257};
258
259/*! \brief Identifier used to designate the implementation responsible
260	for writing associated data structures on the medium.
261
262	See also: ECMA 167 1/7.4, UDF 2.01 2.1.5
263*/
264struct entity_id {
265public:
266	static const int kIdentifierLength = 23;
267	static const int kIdentifierSuffixLength = 8;
268
269	entity_id(uint8 flags = 0, char *identifier = NULL,
270	          uint8 *identifier_suffix = NULL);
271	entity_id(uint8 flags, char *identifier,
272	          const udf_id_suffix &suffix);
273	entity_id(uint8 flags, char *identifier,
274	          const implementation_id_suffix &suffix);
275	entity_id(uint8 flags, char *identifier,
276	          const domain_id_suffix &suffix);
277
278	void dump() const;
279	bool matches(const entity_id &id) const;
280
281	// Get functions
282	uint8 flags() const { return _flags; }
283	const char* identifier() const { return _identifier; }
284	char* identifier() { return _identifier; }
285	const array<uint8, kIdentifierSuffixLength>& identifier_suffix() const { return _identifier_suffix; }
286	array<uint8, kIdentifierSuffixLength>& identifier_suffix() { return _identifier_suffix; }
287
288	// Set functions
289	void set_flags(uint8 flags) { _flags = flags; }
290private:
291	uint8 _flags;
292	char _identifier[kIdentifierLength];
293	array<uint8, kIdentifierSuffixLength> _identifier_suffix;
294} __attribute__((packed));
295
296extern const entity_id kMetadataPartitionMapId;
297extern const entity_id kSparablePartitionMapId;
298extern const entity_id kVirtualPartitionMapId;
299extern const entity_id kImplementationId;
300extern const entity_id kPartitionContentsId1xx;
301extern const entity_id kPartitionContentsId2xx;
302extern const entity_id kUdfId;
303extern const entity_id kLogicalVolumeInfoId150;
304extern const entity_id kLogicalVolumeInfoId201;
305extern const entity_id kDomainId150;
306extern const entity_id kDomainId201;
307
308//----------------------------------------------------------------------
309// ECMA-167 Part 2
310//----------------------------------------------------------------------
311
312
313/*! \brief Header for volume structure descriptors
314
315	Each descriptor consumes an entire block. All unused trailing
316	bytes in the descriptor should be set to 0.
317
318	The following descriptors contain no more information than
319	that contained in the header:
320
321	- BEA01:
322	  - type: 0
323	  - id: "BEA01"
324	  - version: 1
325
326	- TEA01:
327	  - type: 0
328	  - id: "TEA01"
329	  - version: 1
330
331	- NSR03:
332	  - type: 0
333	  - id: "NSR03"
334	  - version: 1
335
336	See also: ECMA 167 2/9.1
337*/
338struct volume_structure_descriptor_header {
339public:
340	volume_structure_descriptor_header(uint8 type, const char *id, uint8 version);
341
342	uint8 type;
343	char id[5];
344	uint8 version;
345
346	bool id_matches(const char *id);
347} __attribute__((packed));
348
349// Volume structure descriptor ids
350extern const char* kVSDID_BEA;
351extern const char* kVSDID_TEA;
352extern const char* kVSDID_BOOT;
353extern const char* kVSDID_ISO;
354extern const char* kVSDID_ECMA167_2;
355extern const char* kVSDID_ECMA167_3;
356extern const char* kVSDID_ECMA168;
357
358//----------------------------------------------------------------------
359// ECMA-167 Part 3
360//----------------------------------------------------------------------
361
362
363/*! \brief Location and length of a contiguous chunk of data on the volume.
364
365	\c _location is an absolute block address.
366
367	See also: ECMA 167 3/7.1
368*/
369struct extent_address {
370public:
371	extent_address(uint32 location = 0, uint32 length = 0);
372
373	void dump() const;
374
375	uint32 length() const { return B_LENDIAN_TO_HOST_INT32(_length); }
376	uint32 location() const { return B_LENDIAN_TO_HOST_INT32(_location); }
377
378	void set_length(int32 length) { _length = B_HOST_TO_LENDIAN_INT32(length); }
379	void set_location(int32 location) { _location = B_HOST_TO_LENDIAN_INT32(location); }
380private:
381	uint32 _length;
382	uint32 _location;
383} __attribute__((packed));
384
385
386/*! \brief Location of a logical block within a logical volume.
387
388	See also: ECMA 167 4/7.1
389*/
390struct logical_block_address {
391public:
392	void dump() const;
393	logical_block_address(uint16 partition = 0, uint32 block = 0);
394
395	uint32 block() const { return B_LENDIAN_TO_HOST_INT32(_block); }
396	uint16 partition() const { return B_LENDIAN_TO_HOST_INT16(_partition); }
397
398	void set_block(uint32 block) { _block = B_HOST_TO_LENDIAN_INT32(block); }
399	void set_partition(uint16 partition) { _partition = B_HOST_TO_LENDIAN_INT16(partition); }
400
401private:
402	uint32 _block;	//!< Block location relative to start of corresponding partition
403	uint16 _partition;	//!< Numeric partition id within logical volume
404} __attribute__((packed));
405
406/*! \brief Extent types used in short_address, long_address,
407	and extended_address.
408
409	See also: ECMA-167 4/14.14.1.1
410*/
411enum extent_type {
412	EXTENT_TYPE_RECORDED = 0,	//!< Allocated and recorded
413	EXTENT_TYPE_ALLOCATED,		//!< Allocated but unrecorded
414	EXTENT_TYPE_UNALLOCATED,	//!< Unallocated and unrecorded
415	EXTENT_TYPE_CONTINUATION,	//!< Specifies next extent of descriptors
416};
417
418
419/*! \brief Allocation descriptor.
420
421	See also: ECMA 167 4/14.14.1
422*/
423struct short_address {
424private:
425	union type_and_length_accessor {
426		uint32 type_and_length;
427		struct {
428			uint32 length:30,
429			       type:2;
430//			uint32 type:2,
431//			       length:30;
432		} bits;
433	};
434
435public:
436	void dump() const;
437
438	uint8 type() const {
439		type_and_length_accessor t;
440		t.type_and_length = type_and_length();
441		return t.bits.type;
442	}
443	uint32 length() const {
444		type_and_length_accessor t;
445		t.type_and_length = type_and_length();
446		return t.bits.length;
447	}
448	uint32 block() const { return B_LENDIAN_TO_HOST_INT32(_block); }
449
450	void set_type(uint8 type) {
451		type_and_length_accessor t;
452		t.type_and_length = type_and_length();
453		t.bits.type = type;
454		set_type_and_length(t.type_and_length);
455	}
456	void set_length(uint32 length) {
457		type_and_length_accessor t;
458		t.type_and_length = type_and_length();
459		t.bits.length = length;
460		set_type_and_length(t.type_and_length);
461	}
462	void set_block(uint32 block) { _block = B_HOST_TO_LENDIAN_INT32(block); }
463private:
464	uint32 type_and_length() const { return B_LENDIAN_TO_HOST_INT32(_type_and_length); }
465	void set_type_and_length(uint32 value) { _type_and_length = B_HOST_TO_LENDIAN_INT32(value); }
466
467	uint32 _type_and_length;
468	uint32 _block;
469} __attribute__((packed));
470
471
472/*! \brief Allocation descriptor w/ 6 byte implementation use field.
473
474	See also: ECMA 167 4/14.14.2
475*/
476struct long_address {
477private:
478	union type_and_length_accessor {
479		uint32 type_and_length;
480		struct {
481			uint32 length:30,
482			       type:2;
483		} bits;
484	};
485
486public:
487	long_address(uint16 partition = 0, uint32 block = 0, uint32 length = 0,
488	             uint8 type = 0);
489
490	void dump() const;
491
492	uint8 type() const {
493		type_and_length_accessor t;
494		t.type_and_length = type_and_length();
495		return t.bits.type;
496	}
497	uint32 length() const {
498		type_and_length_accessor t;
499		t.type_and_length = type_and_length();
500		return t.bits.length;
501	}
502
503	uint32 block() const { return _location.block(); }
504	uint16 partition() const { return _location.partition(); }
505
506	const array<uint8, 6>& implementation_use() const { return _implementation_use; }
507	array<uint8, 6>& implementation_use() { return _implementation_use; }
508
509	uint16 flags() const { return B_LENDIAN_TO_HOST_INT16(_accessor().flags); }
510	uint32 unique_id() const { return B_LENDIAN_TO_HOST_INT32(_accessor().unique_id); }
511
512	void set_type(uint8 type) {
513		type_and_length_accessor t;
514		t.type_and_length = type_and_length();
515		t.bits.type = type;
516		set_type_and_length(t.type_and_length);
517	}
518	void set_length(uint32 length) {
519		type_and_length_accessor t;
520		t.type_and_length = type_and_length();
521		t.bits.length = length;
522		set_type_and_length(t.type_and_length);
523	}
524	void set_block(uint32 block) { _location.set_block(block); }
525	void set_partition(uint16 partition) { _location.set_partition(partition); }
526
527	void set_flags(uint16 flags) { _accessor().flags = B_HOST_TO_LENDIAN_INT16(flags); }
528	void set_unique_id(uint32 id) { _accessor().unique_id = B_HOST_TO_LENDIAN_INT32(id); }
529
530	void set_to(uint32 block, uint16 partition, uint32 length = 1,
531	       uint8 type = EXTENT_TYPE_RECORDED, uint16 flags = 0, uint32 unique_id = 0)
532	{
533		set_block(block);
534		set_partition(partition);
535		set_length(length);
536		set_type(type);
537		set_flags(flags);
538		set_unique_id(unique_id);
539	}
540
541private:
542	//! See UDF-2.50 2.3.4.3
543	struct _implementation_use_accessor {
544		uint16 flags;
545		uint32 unique_id;
546	} __attribute__((packed));
547
548	_implementation_use_accessor& _accessor() { return
549		*reinterpret_cast<_implementation_use_accessor*>(implementation_use().data); }
550	const _implementation_use_accessor& _accessor() const { return
551		*reinterpret_cast<const _implementation_use_accessor*>(implementation_use().data); }
552
553	uint32 type_and_length() const { return B_LENDIAN_TO_HOST_INT32(_type_and_length); }
554	void set_type_and_length(uint32 value) { _type_and_length = B_HOST_TO_LENDIAN_INT32(value); }
555
556	uint32 _type_and_length;
557	logical_block_address _location;
558	array<uint8, 6> _implementation_use;
559} __attribute__((packed));
560
561/*! \brief Common tag found at the beginning of most udf descriptor structures.
562
563	For error checking, \c descriptor_tag  structures have:
564	- The disk location of the tag redundantly stored in the tag itself
565	- A checksum value for the tag
566	- A CRC value and length
567
568	See also: ECMA 167 1/7.2, UDF 2.01 2.2.1, UDF 2.01 2.3.1
569*/
570struct descriptor_tag {
571public:
572	void dump() const;
573
574	status_t init_check(uint32 block, bool calculateCrc = true);
575
576	uint16 id() const { return B_LENDIAN_TO_HOST_INT16(_id); }
577	uint16 version() const { return B_LENDIAN_TO_HOST_INT16(_version); }
578	uint8 checksum() const { return _checksum; }
579	uint16 serial_number() const { return B_LENDIAN_TO_HOST_INT16(_serial_number); }
580	uint16 crc() const { return B_LENDIAN_TO_HOST_INT16(_crc); }
581	uint16 crc_length() const { return B_LENDIAN_TO_HOST_INT16(_crc_length); }
582	uint32 location() const { return B_LENDIAN_TO_HOST_INT32(_location); }
583
584	void set_id(uint16 id) { _id = B_HOST_TO_LENDIAN_INT16(id); }
585	void set_version(uint16 version) { _version = B_HOST_TO_LENDIAN_INT16(version); }
586	void set_checksum(uint8 checksum) { _checksum = checksum; }
587	void set_serial_number(uint16 serial_number) { _serial_number = B_HOST_TO_LENDIAN_INT16(serial_number); }
588	void set_crc(uint16 crc) { _crc = B_HOST_TO_LENDIAN_INT16(crc); }
589	void set_crc_length(uint16 crc_length) { _crc_length = B_HOST_TO_LENDIAN_INT16(crc_length); }
590	void set_location(uint32 location) { _location = B_HOST_TO_LENDIAN_INT32(location); }
591
592	/*! \brief Calculates and sets the crc length, crc checksumm, and
593		checksum for the tag.
594
595		This function should not be called until all member variables in
596		the descriptor_tag's enclosing descriptor and all member variables
597		in the descriptor_tag itself other than crc_length, crc, and checksum
598		have been set (since the checksum is based off of values in the
599		descriptor_tag, and the crc is based off the values in and the
600		size of the	enclosing descriptor).
601
602		\param The tag's enclosing descriptor.
603		\param The size of the tag's enclosing descriptor (including the
604		       tag); only necessary if different from sizeof(Descriptor).
605	*/
606	template <class Descriptor>
607	void
608	set_checksums(Descriptor &descriptor, uint16 size = sizeof(Descriptor))
609	{
610
611		// check that this tag is actually owned by
612		// the given descriptor
613		if (this == &descriptor.tag())
614		{
615			// crc_length, based off provided descriptor
616			set_crc_length(size - sizeof(descriptor_tag));
617			// crc
618			uint16 crc = Udf::calculate_crc(reinterpret_cast<uint8*>(this)
619			               + sizeof(descriptor_tag), crc_length());
620			set_crc(crc);
621			// checksum (which depends on the other two values)
622			uint32 sum = 0;
623			for (int i = 0; i <= 3; i++)
624				sum += reinterpret_cast<uint8*>(this)[i];
625			for (int i = 5; i <= 15; i++)
626				sum += reinterpret_cast<uint8*>(this)[i];
627			set_checksum(sum % 256);
628		}
629	}
630private:
631	uint16 _id;
632	uint16 _version;
633	uint8 _checksum;			//!< Sum modulo 256 of bytes 0-3 and 5-15 of this struct.
634	uint8 _reserved;			//!< Set to #00.
635	uint16 _serial_number;
636	uint16 _crc;				//!< May be 0 if \c crc_length field is 0.
637	/*! \brief Length of the data chunk used to calculate CRC.
638
639		If 0, no CRC was calculated, and the \c crc field must be 0.
640
641		According to UDF-2.01 2.3.1.2, the CRC shall be calculated for all descriptors
642		unless otherwise noted, and this field shall be set to:
643
644		<code>(descriptor length) - (descriptor tag length)</code>
645	*/
646	uint16 _crc_length;
647	/*! \brief Address of this tag within its partition (for error checking).
648
649		For virtually addressed structures (i.e. those accessed thru a VAT), this
650		shall be the virtual address, not the physical or logical address.
651	*/
652	uint32 _location;
653
654} __attribute__((packed));
655
656
657/*! \c descriptor_tag ::id values
658*/
659enum tag_id {
660	TAGID_UNDEFINED	= 0,
661
662	// ECMA 167, PART 3
663	TAGID_PRIMARY_VOLUME_DESCRIPTOR,
664	TAGID_ANCHOR_VOLUME_DESCRIPTOR_POINTER,
665	TAGID_VOLUME_DESCRIPTOR_POINTER,
666	TAGID_IMPLEMENTATION_USE_VOLUME_DESCRIPTOR,
667	TAGID_PARTITION_DESCRIPTOR,
668	TAGID_LOGICAL_VOLUME_DESCRIPTOR,
669	TAGID_UNALLOCATED_SPACE_DESCRIPTOR,
670	TAGID_TERMINATING_DESCRIPTOR,
671	TAGID_LOGICAL_VOLUME_INTEGRITY_DESCRIPTOR,
672
673	TAGID_CUSTOM_START = 65280,
674	TAGID_CUSTOM_END = 65535,
675
676	// ECMA 167, PART 4
677	TAGID_FILE_SET_DESCRIPTOR = 256,
678	TAGID_FILE_ID_DESCRIPTOR,
679	TAGID_ALLOCATION_EXTENT_DESCRIPTOR,
680	TAGID_INDIRECT_ENTRY,
681	TAGID_TERMINAL_ENTRY,
682	TAGID_FILE_ENTRY,
683	TAGID_EXTENDED_ATTRIBUTE_HEADER_DESCRIPTOR,
684	TAGID_UNALLOCATED_SPACE_ENTRY,
685	TAGID_SPACE_BITMAP_DESCRIPTOR,
686	TAGID_PARTITION_INTEGRITY_ENTRY,
687	TAGID_EXTENDED_FILE_ENTRY,
688};
689
690const char *tag_id_to_string(tag_id id);
691
692extern const uint16 kCrcTable[256];
693
694/*! \brief Primary volume descriptor
695*/
696struct primary_volume_descriptor {
697public:
698	void dump() const;
699
700	// Get functions
701	const descriptor_tag & tag() const { return _tag; }
702	descriptor_tag & tag() { return _tag; }
703
704	uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); }
705	uint32 primary_volume_descriptor_number() const { return B_LENDIAN_TO_HOST_INT32(_primary_volume_descriptor_number); }
706
707	const array<char, 32>& volume_identifier() const { return _volume_identifier; }
708	array<char, 32>& volume_identifier() { return _volume_identifier; }
709
710	uint16 volume_sequence_number() const { return B_LENDIAN_TO_HOST_INT16(_volume_sequence_number); }
711	uint16 max_volume_sequence_number() const { return B_LENDIAN_TO_HOST_INT16(_max_volume_sequence_number); }
712	uint16 interchange_level() const { return B_LENDIAN_TO_HOST_INT16(_interchange_level); }
713	uint16 max_interchange_level() const { return B_LENDIAN_TO_HOST_INT16(_max_interchange_level); }
714	uint32 character_set_list() const { return B_LENDIAN_TO_HOST_INT32(_character_set_list); }
715	uint32 max_character_set_list() const { return B_LENDIAN_TO_HOST_INT32(_max_character_set_list); }
716
717	const array<char, 128>& volume_set_identifier() const { return _volume_set_identifier; }
718	array<char, 128>& volume_set_identifier() { return _volume_set_identifier; }
719
720	const charspec& descriptor_character_set() const { return _descriptor_character_set; }
721	charspec& descriptor_character_set() { return _descriptor_character_set; }
722
723	const charspec& explanatory_character_set() const { return _explanatory_character_set; }
724	charspec& explanatory_character_set() { return _explanatory_character_set; }
725
726	const extent_address& volume_abstract() const { return _volume_abstract; }
727	extent_address& volume_abstract() { return _volume_abstract; }
728	const extent_address& volume_copyright_notice() const { return _volume_copyright_notice; }
729	extent_address& volume_copyright_notice() { return _volume_copyright_notice; }
730
731	const entity_id& application_id() const { return _application_id; }
732	entity_id& application_id() { return _application_id; }
733
734	const timestamp& recording_date_and_time() const { return _recording_date_and_time; }
735	timestamp& recording_date_and_time() { return _recording_date_and_time; }
736
737	const entity_id& implementation_id() const { return _implementation_id; }
738	entity_id& implementation_id() { return _implementation_id; }
739
740	const array<uint8, 64>& implementation_use() const { return _implementation_use; }
741	array<uint8, 64>& implementation_use() { return _implementation_use; }
742
743	uint32 predecessor_volume_descriptor_sequence_location() const
744	  { return B_LENDIAN_TO_HOST_INT32(_predecessor_volume_descriptor_sequence_location); }
745	uint16 flags() const { return B_LENDIAN_TO_HOST_INT16(_flags); }
746
747	const array<uint8, 22>& reserved() const { return _reserved; }
748	array<uint8, 22>& reserved() { return _reserved; }
749
750	// Set functions
751	void set_vds_number(uint32 number)
752	  { _vds_number = B_HOST_TO_LENDIAN_INT32(number); }
753	void set_primary_volume_descriptor_number(uint32 number)
754	  { _primary_volume_descriptor_number = B_HOST_TO_LENDIAN_INT32(number); }
755	void set_volume_sequence_number(uint16 number)
756	  { _volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); }
757	void set_max_volume_sequence_number(uint16 number)
758	  { _max_volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); }
759	void set_interchange_level(uint16 level)
760	  { _interchange_level = B_HOST_TO_LENDIAN_INT16(level); }
761	void set_max_interchange_level(uint16 level)
762	  { _max_interchange_level = B_HOST_TO_LENDIAN_INT16(level); }
763	void set_character_set_list(uint32 list)
764	  { _character_set_list = B_HOST_TO_LENDIAN_INT32(list); }
765	void set_max_character_set_list(uint32 list)
766	  { _max_character_set_list = B_HOST_TO_LENDIAN_INT32(list); }
767	void set_predecessor_volume_descriptor_sequence_location(uint32 location)
768	  { _predecessor_volume_descriptor_sequence_location = B_HOST_TO_LENDIAN_INT32(location); }
769	void set_flags(uint16 flags)
770	  { _flags = B_HOST_TO_LENDIAN_INT16(flags); }
771
772private:
773	descriptor_tag  _tag;
774	uint32 _vds_number;
775	uint32 _primary_volume_descriptor_number;
776	array<char, 32> _volume_identifier;
777	uint16 _volume_sequence_number;
778	uint16 _max_volume_sequence_number;
779	uint16 _interchange_level; //!< to be set to 3 if part of multivolume set, 2 otherwise
780	uint16 _max_interchange_level; //!< to be set to 3 unless otherwise directed by user
781	uint32 _character_set_list;
782	uint32 _max_character_set_list;
783	array<char, 128> _volume_set_identifier;
784
785	/*! \brief Identifies the character set for the \c volume_identifier
786		and \c volume_set_identifier fields.
787
788		To be set to CS0.
789	*/
790	charspec _descriptor_character_set;
791
792	/*! \brief Identifies the character set used in the \c volume_abstract
793		and \c volume_copyright_notice extents.
794
795		To be set to CS0.
796	*/
797	charspec _explanatory_character_set;
798
799	extent_address _volume_abstract;
800	extent_address _volume_copyright_notice;
801
802	entity_id _application_id;
803	timestamp _recording_date_and_time;
804	entity_id _implementation_id;
805	array<uint8, 64> _implementation_use;
806	uint32 _predecessor_volume_descriptor_sequence_location;
807	uint16 _flags;
808	array<uint8, 22> _reserved;
809
810} __attribute__((packed));
811
812
813/*! \brief Anchor Volume Descriptor Pointer
814
815	vd recorded at preset locations in the partition, used as a reference
816	point to the main vd sequences
817
818	According to UDF 2.01, an avdp shall be recorded in at least 2 of
819	the 3 following locations, where N is the last recordable sector
820	of the partition:
821	- 256
822	- (N - 256)
823	- N
824
825	See also: ECMA 167 3/10.2, UDF-2.01 2.2.3
826*/
827struct anchor_volume_descriptor {
828public:
829	anchor_volume_descriptor() { memset(_reserved.data, 0, _reserved.size()); }
830	void dump() const;
831
832	descriptor_tag & tag() { return _tag; }
833	const descriptor_tag & tag() const { return _tag; }
834
835	extent_address& main_vds() { return _main_vds; }
836	const extent_address& main_vds() const { return _main_vds; }
837
838	extent_address& reserve_vds() { return _reserve_vds; }
839	const extent_address& reserve_vds() const { return _reserve_vds; }
840private:
841	descriptor_tag  _tag;
842	extent_address _main_vds;	//!< min length of 16 sectors
843	extent_address _reserve_vds;	//!< min length of 16 sectors
844	array<uint8, 480> _reserved;
845} __attribute__((packed));
846
847
848/*! \brief Volume Descriptor Pointer
849
850	Used to chain extents of volume descriptor sequences together.
851
852	See also: ECMA 167 3/10.3
853*/
854struct descriptor_pointer {
855	descriptor_tag  tag;
856	uint32 vds_number;
857	extent_address next;
858} __attribute__((packed));
859
860
861/*! \brief UDF Implementation Use Volume Descriptor struct found in
862	implementation_use() field of implementation_use_descriptor when
863	said descriptor's implementation_id() field specifies "*UDF LV Info"
864
865	See also: UDF 2.50 2.2.7
866*/
867struct logical_volume_info {
868public:
869	void dump() const;
870
871	charspec& character_set() { return _character_set; }
872	const charspec& character_set() const { return _character_set; }
873
874	array<char, 128>& logical_volume_id() { return _logical_volume_id; }
875	const array<char, 128>& logical_volume_id() const { return _logical_volume_id; }
876
877	array<char, 36>& logical_volume_info_1() { return _logical_volume_info.data[0]; }
878	const array<char, 36>& logical_volume_info_1() const { return _logical_volume_info.data[0]; }
879
880	array<char, 36>& logical_volume_info_2() { return _logical_volume_info.data[1]; }
881	const array<char, 36>& logical_volume_info_2() const { return _logical_volume_info.data[1]; }
882
883	array<char, 36>& logical_volume_info_3() { return _logical_volume_info.data[2]; }
884	const array<char, 36>& logical_volume_info_3() const { return _logical_volume_info.data[2]; }
885
886	entity_id& implementation_id() { return _implementation_id; }
887	const entity_id& implementation_id() const { return _implementation_id; }
888
889	array<uint8, 128>& implementation_use() { return _implementation_use; }
890	const array<uint8, 128>& implementation_use() const { return _implementation_use; }
891private:
892	charspec _character_set;
893	array<char, 128> _logical_volume_id;				// d-string
894	array<array<char, 36>, 3> _logical_volume_info;	// d-strings
895	entity_id _implementation_id;
896	array<uint8, 128> _implementation_use;
897} __attribute__((packed));
898
899/*! \brief Implementation Use Volume Descriptor
900
901	See also: ECMA 167 3/10.4
902*/
903struct implementation_use_descriptor {
904public:
905	void dump() const;
906
907	// Get functions
908	const descriptor_tag & tag() const { return _tag; }
909	descriptor_tag & tag() { return _tag; }
910
911	uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); }
912
913	const entity_id& implementation_id() const { return _implementation_id; }
914	entity_id& implementation_id() { return _implementation_id; }
915
916	const array<uint8, 460>& implementation_use() const { return _implementation_use; }
917	array<uint8, 460>& implementation_use() { return _implementation_use; }
918
919	// Only valid if implementation_id() returns Udf::kLogicalVolumeInfoId.
920	logical_volume_info& info() { return *reinterpret_cast<logical_volume_info*>(_implementation_use.data); }
921	const logical_volume_info& info() const { return *reinterpret_cast<const logical_volume_info*>(_implementation_use.data); }
922
923	// Set functions
924	void set_vds_number(uint32 number) { _vds_number = B_HOST_TO_LENDIAN_INT32(number); }
925private:
926	descriptor_tag  _tag;
927	uint32 _vds_number;
928	entity_id _implementation_id;
929	array<uint8, 460> _implementation_use;
930} __attribute__((packed));
931
932
933/*! \brief Maximum number of partition descriptors to be found in volume
934	descriptor sequence, per UDF-2.50
935*/
936extern const uint8 kMaxPartitionDescriptors;
937#define UDF_MAX_PARTITION_MAPS 2
938#define UDF_MAX_PARTITION_MAP_SIZE 64
939
940/*! \brief Partition Descriptor
941
942	See also: ECMA 167 3/10.5
943*/
944struct partition_descriptor {
945private:
946	union partition_flags_accessor {
947		uint16 partition_flags;
948		struct {
949			uint16 allocated:1,
950			       reserved:15;
951		} bits;
952	};
953
954public:
955	void dump() const;
956
957	// Get functions
958	const descriptor_tag & tag() const { return _tag; }
959	descriptor_tag & tag() { return _tag; }
960
961	uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); }
962	uint16 partition_flags() const { return B_LENDIAN_TO_HOST_INT16(_partition_flags); }
963	bool allocated() const {
964		partition_flags_accessor f;
965		f.partition_flags = partition_flags();
966		return f.bits.allocated;
967	}
968	uint16 partition_number() const { return B_LENDIAN_TO_HOST_INT16(_partition_number); }
969
970	const entity_id& partition_contents() const { return _partition_contents; }
971	entity_id& partition_contents() { return _partition_contents; }
972
973	const array<uint8, 128>& partition_contents_use() const { return _partition_contents_use; }
974	array<uint8, 128>& partition_contents_use() { return _partition_contents_use; }
975
976	uint32 access_type() const { return B_LENDIAN_TO_HOST_INT32(_access_type); }
977	uint32 start() const { return B_LENDIAN_TO_HOST_INT32(_start); }
978	uint32 length() const { return B_LENDIAN_TO_HOST_INT32(_length); }
979
980	const entity_id& implementation_id() const { return _implementation_id; }
981	entity_id& implementation_id() { return _implementation_id; }
982
983	const array<uint8, 128>& implementation_use() const { return _implementation_use; }
984	array<uint8, 128>& implementation_use() { return _implementation_use; }
985
986	const array<uint8, 156>& reserved() const { return _reserved; }
987	array<uint8, 156>& reserved() { return _reserved; }
988
989	// Set functions
990	void set_vds_number(uint32 number) { _vds_number = B_HOST_TO_LENDIAN_INT32(number); }
991	void set_partition_flags(uint16 flags) { _partition_flags = B_HOST_TO_LENDIAN_INT16(flags); }
992	void set_allocated(bool allocated) {
993		partition_flags_accessor f;
994		f.partition_flags = partition_flags();
995		f.bits.allocated = allocated;
996		set_partition_flags(f.partition_flags);
997	}
998	void set_partition_number(uint16 number) { _partition_number = B_HOST_TO_LENDIAN_INT16(number); }
999	void set_access_type(uint32 type) { _access_type = B_HOST_TO_LENDIAN_INT32(type); }
1000	void set_start(uint32 start) { _start = B_HOST_TO_LENDIAN_INT32(start); }
1001	void set_length(uint32 length) { _length = B_HOST_TO_LENDIAN_INT32(length); }
1002
1003private:
1004	descriptor_tag  _tag;
1005	uint32 _vds_number;
1006	/*! Bit 0: If 0, shall mean volume space has not been allocated. If 1,
1007	    shall mean volume space has been allocated.
1008	*/
1009	uint16 _partition_flags;
1010	uint16 _partition_number;
1011
1012	/*! - "+NSR03" Volume recorded according to ECMA-167, i.e. UDF
1013		- "+CD001" Volume recorded according to ECMA-119, i.e. iso9660
1014		- "+FDC01" Volume recorded according to ECMA-107
1015		- "+CDW02" Volume recorded according to ECMA-168
1016	*/
1017	entity_id _partition_contents;
1018	array<uint8, 128> _partition_contents_use;
1019
1020	/*! See \c partition_access_type enum
1021	*/
1022	uint32 _access_type;
1023	uint32 _start;
1024	uint32 _length;
1025	entity_id _implementation_id;
1026	array<uint8, 128> _implementation_use;
1027	array<uint8, 156> _reserved;
1028} __attribute__((packed));
1029
1030
1031enum partition_access_type {
1032	ACCESS_UNSPECIFIED,
1033	ACCESS_READ_ONLY,
1034	ACCESS_WRITE_ONCE,
1035	ACCESS_REWRITABLE,
1036	ACCESS_OVERWRITABLE,
1037};
1038
1039
1040/*! \brief Logical volume descriptor
1041
1042	See also: ECMA 167 3/10.6, UDF-2.01 2.2.4
1043*/
1044struct logical_volume_descriptor {
1045	void dump() const;
1046
1047	// Get functions
1048	const descriptor_tag & tag() const { return _tag; }
1049	descriptor_tag & tag() { return _tag; }
1050
1051	uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); }
1052
1053	const charspec& character_set() const { return _character_set; }
1054	charspec& character_set() { return _character_set; }
1055
1056	const array<char, 128>& logical_volume_identifier() const { return _logical_volume_identifier; }
1057	array<char, 128>& logical_volume_identifier() { return _logical_volume_identifier; }
1058
1059	uint32 logical_block_size() const { return B_LENDIAN_TO_HOST_INT32(_logical_block_size); }
1060
1061	const entity_id& domain_id() const { return _domain_id; }
1062	entity_id& domain_id() { return _domain_id; }
1063
1064	const array<uint8, 16>& logical_volume_contents_use() const { return _logical_volume_contents_use; }
1065	array<uint8, 16>& logical_volume_contents_use() { return _logical_volume_contents_use; }
1066
1067	const long_address& file_set_address() const { return *reinterpret_cast<const long_address*>(&_logical_volume_contents_use); }
1068	long_address& file_set_address() { return *reinterpret_cast<long_address*>(&_logical_volume_contents_use); }
1069
1070	uint32 map_table_length() const { return B_LENDIAN_TO_HOST_INT32(_map_table_length); }
1071	uint32 partition_map_count() const { return B_LENDIAN_TO_HOST_INT32(_partition_map_count); }
1072
1073	const entity_id& implementation_id() const { return _implementation_id; }
1074	entity_id& implementation_id() { return _implementation_id; }
1075
1076	const array<uint8, 128>& implementation_use() const { return _implementation_use; }
1077	array<uint8, 128>& implementation_use() { return _implementation_use; }
1078
1079	const extent_address& integrity_sequence_extent() const { return _integrity_sequence_extent; }
1080	extent_address& integrity_sequence_extent() { return _integrity_sequence_extent; }
1081
1082	const uint8* partition_maps() const { return _partition_maps; }
1083	uint8* partition_maps() { return _partition_maps; }
1084
1085	// Set functions
1086	void set_vds_number(uint32 number) { _vds_number = B_HOST_TO_LENDIAN_INT32(number); }
1087	void set_logical_block_size(uint32 size) { _logical_block_size = B_HOST_TO_LENDIAN_INT32(size); }
1088
1089	void set_map_table_length(uint32 length) { _map_table_length = B_HOST_TO_LENDIAN_INT32(length); }
1090	void set_partition_map_count(uint32 count) { _partition_map_count = B_HOST_TO_LENDIAN_INT32(count); }
1091
1092	// Other functions
1093	logical_volume_descriptor& operator=(const logical_volume_descriptor &rhs);
1094
1095private:
1096	descriptor_tag  _tag;
1097	uint32 _vds_number;
1098
1099	/*! \brief Identifies the character set for the
1100		\c logical_volume_identifier field.
1101
1102		To be set to CS0.
1103	*/
1104	charspec _character_set;
1105	array<char, 128> _logical_volume_identifier;
1106	uint32 _logical_block_size;
1107
1108	/*! \brief To be set to 0 or "*OSTA UDF Compliant". See UDF specs.
1109	*/
1110	entity_id _domain_id;
1111
1112	/*! \brief For UDF, shall contain a \c long_address which identifies
1113		the location of the logical volume's first file set.
1114	*/
1115	array<uint8, 16> _logical_volume_contents_use;
1116
1117	uint32 _map_table_length;
1118	uint32 _partition_map_count;
1119	entity_id _implementation_id;
1120	array<uint8, 128> _implementation_use;
1121
1122	/*! \brief Logical volume integrity sequence location.
1123
1124		For re/overwritable media, shall be a min of 8KB in length.
1125		For WORM media, shall be quite frickin large, as a new volume
1126		must be added to the set if the extent fills up (since you
1127		can't chain lvis's I guess).
1128	*/
1129	extent_address _integrity_sequence_extent;
1130
1131	/*! \brief Restricted to maps of type 1 for normal maps and
1132		UDF type 2 for virtual maps or maps on systems not supporting
1133		defect management.
1134
1135		Note that we actually allocate memory for the partition maps
1136		here due to the fact that we allocate logical_volume_descriptor
1137		objects on the stack sometimes.
1138
1139		See UDF-2.01 2.2.8, 2.2.9
1140	*/
1141	uint8 _partition_maps[UDF_MAX_PARTITION_MAPS * UDF_MAX_PARTITION_MAP_SIZE];
1142} __attribute__((packed));
1143
1144//! Base size (excluding partition maps) of lvd
1145extern const uint32 kLogicalVolumeDescriptorBaseSize;
1146
1147/*! \brief (Mostly) common portion of various partition maps
1148
1149	See also: ECMA-167 3/10.7.1
1150*/
1151struct partition_map_header {
1152public:
1153	uint8 type() const { return _type; }
1154	uint8 length() const { return _length; }
1155	uint8 *map_data() { return _map_data; }
1156	const uint8 *map_data() const { return _map_data; }
1157
1158	entity_id& partition_type_id()
1159		{ return *reinterpret_cast<entity_id*>(&_map_data[2]); }
1160	const entity_id& partition_type_id() const
1161		{ return *reinterpret_cast<const entity_id*>(&_map_data[2]); }
1162
1163	void set_type(uint8 type) { _type = type; }
1164	void set_length(uint8 length) { _length = length; }
1165private:
1166	uint8 _type;
1167	uint8 _length;
1168	uint8 _map_data[0];
1169};// __attribute__((packed));
1170
1171
1172/*! \brief Physical partition map (i.e. ECMA-167 Type 1 partition map)
1173
1174	See also: ECMA-167 3/10.7.2
1175*/
1176struct physical_partition_map {
1177public:
1178	void dump();
1179
1180	uint8 type() const { return _type; }
1181	uint8 length() const { return _length; }
1182
1183	uint16 volume_sequence_number() const {
1184		return B_LENDIAN_TO_HOST_INT16(_volume_sequence_number); }
1185	uint16 partition_number() const {
1186		return B_LENDIAN_TO_HOST_INT16(_partition_number); }
1187
1188	void set_type(uint8 type) { _type = type; }
1189	void set_length(uint8 length) { _length = length; }
1190	void set_volume_sequence_number(uint16 number) {
1191		_volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); }
1192	void set_partition_number(uint16 number) {
1193		_partition_number = B_HOST_TO_LENDIAN_INT16(number); }
1194private:
1195	uint8 _type;
1196	uint8 _length;
1197	uint16 _volume_sequence_number;
1198	uint16 _partition_number;
1199} __attribute__((packed));
1200
1201
1202/* ----UDF Specific---- */
1203/*! \brief Virtual partition map
1204
1205	Note that this map is a customization of the ECMA-167
1206	type 2 partition map.
1207
1208	See also: UDF-2.01 2.2.8
1209*/
1210struct virtual_partition_map {
1211	uint8 type;
1212	uint8 length;
1213	uint8 reserved1[2];
1214
1215	/*! - flags: 0
1216	    - identifier: "*UDF Virtual Partition"
1217	    - identifier_suffix: per UDF-2.01 2.1.5.3
1218	*/
1219	entity_id partition_type_id;
1220	uint16 volume_sequence_number;
1221
1222	/*! corresponding type 1 partition map in same logical volume
1223	*/
1224	uint16 partition_number;
1225	uint8 reserved2[24];
1226} __attribute__((packed));
1227
1228
1229/*! \brief Maximum number of redundant sparing tables found in
1230	sparable_partition_map structures.
1231*/
1232#define UDF_MAX_SPARING_TABLE_COUNT 4
1233
1234/* ----UDF Specific---- */
1235/*! \brief Sparable partition map
1236
1237	Note that this map is a customization of the ECMA-167
1238	type 2 partition map.
1239
1240	See also: UDF-2.01 2.2.9
1241*/
1242struct sparable_partition_map {
1243public:
1244	void dump();
1245
1246	uint8 type() const { return _type; }
1247	uint8 length() const { return _length; }
1248
1249	entity_id& partition_type_id() { return _partition_type_id; }
1250	const entity_id& partition_type_id() const { return _partition_type_id; }
1251
1252	uint16 volume_sequence_number() const {
1253		return B_LENDIAN_TO_HOST_INT16(_volume_sequence_number); }
1254	uint16 partition_number() const {
1255		return B_LENDIAN_TO_HOST_INT16(_partition_number); }
1256	uint16 packet_length() const {
1257		return B_LENDIAN_TO_HOST_INT16(_packet_length); }
1258	uint8 sparing_table_count() const { return _sparing_table_count; }
1259	uint32 sparing_table_size() const {
1260		return B_LENDIAN_TO_HOST_INT32(_sparing_table_size); }
1261	uint32 sparing_table_location(uint8 index) const {
1262		return B_LENDIAN_TO_HOST_INT32(_sparing_table_locations[index]); }
1263
1264
1265	void set_type(uint8 type) { _type = type; }
1266	void set_length(uint8 length) { _length = length; }
1267	void set_volume_sequence_number(uint16 number) {
1268		_volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); }
1269	void set_partition_number(uint16 number) {
1270		_partition_number = B_HOST_TO_LENDIAN_INT16(number); }
1271	void set_packet_length(uint16 length) {
1272		_packet_length = B_HOST_TO_LENDIAN_INT16(length); }
1273	void set_sparing_table_count(uint8 count) {
1274		_sparing_table_count = count; }
1275	void set_sparing_table_size(uint32 size) {
1276		_sparing_table_size = B_HOST_TO_LENDIAN_INT32(size); }
1277	void set_sparing_table_location(uint8 index, uint32 location) {
1278		_sparing_table_locations[index] = B_HOST_TO_LENDIAN_INT32(location); }
1279private:
1280	uint8 _type;
1281	uint8 _length;
1282	uint8 _reserved1[2];
1283
1284	/*! - flags: 0
1285	    - identifier: "*UDF Sparable Partition"
1286	    - identifier_suffix: per UDF-2.01 2.1.5.3
1287	*/
1288	entity_id _partition_type_id;
1289	uint16 _volume_sequence_number;
1290
1291	//! partition number of corresponding partition descriptor
1292	uint16 _partition_number;
1293	uint16 _packet_length;
1294	uint8 _sparing_table_count;
1295	uint8 _reserved2;
1296	uint32 _sparing_table_size;
1297	uint32 _sparing_table_locations[UDF_MAX_SPARING_TABLE_COUNT];
1298} __attribute__((packed));
1299
1300
1301/* ----UDF Specific---- */
1302/*! \brief Metadata partition map
1303
1304	Note that this map is a customization of the ECMA-167
1305	type 2 partition map.
1306
1307	See also: UDF-2.50 2.2.10
1308*/
1309struct metadata_partition_map {
1310	uint8 type;
1311	uint8 length;
1312	uint8 reserved1[2];
1313
1314	/*! - flags: 0
1315	    - identifier: "*UDF Metadata Partition"
1316	    - identifier_suffix: per UDF-2.50 2.1.5
1317	*/
1318	entity_id partition_type_id;
1319	uint16 volume_sequence_number;
1320
1321	/*! corresponding type 1 or type 2 sparable partition
1322	    map in same logical volume
1323	*/
1324	uint16 partition_number;
1325	uint8 reserved2[24];
1326} __attribute__((packed));
1327
1328
1329/*! \brief Unallocated space descriptor
1330
1331	See also: ECMA-167 3/10.8
1332*/
1333struct unallocated_space_descriptor {
1334	void dump() const;
1335
1336	// Get functions
1337	const descriptor_tag & tag() const { return _tag; }
1338	descriptor_tag & tag() { return _tag; }
1339	uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); }
1340	uint32 allocation_descriptor_count() const { return B_LENDIAN_TO_HOST_INT32(_allocation_descriptor_count); }
1341	extent_address* allocation_descriptors() { return _allocation_descriptors; }
1342
1343	// Set functions
1344	void set_vds_number(uint32 number) { _vds_number = B_HOST_TO_LENDIAN_INT32(number); }
1345	void set_allocation_descriptor_count(uint32 count) { _allocation_descriptor_count = B_HOST_TO_LENDIAN_INT32(count); }
1346private:
1347	descriptor_tag  _tag;
1348	uint32 _vds_number;
1349	uint32 _allocation_descriptor_count;
1350	extent_address _allocation_descriptors[0];
1351} __attribute__((packed));
1352
1353
1354/*! \brief Terminating descriptor
1355
1356	See also: ECMA-167 3/10.9
1357*/
1358struct terminating_descriptor {
1359	terminating_descriptor() { memset(_reserved.data, 0, _reserved.size()); }
1360	void dump() const;
1361
1362	// Get functions
1363	const descriptor_tag & tag() const { return _tag; }
1364	descriptor_tag & tag() { return _tag; }
1365private:
1366	descriptor_tag  _tag;
1367	array<uint8, 496> _reserved;
1368} __attribute__((packed));
1369
1370
1371/*! \brief Logical volume integrity descriptor
1372
1373	See also: ECMA-167 3/10.10, UDF-2.50 2.2.6
1374*/
1375struct logical_volume_integrity_descriptor {
1376public:
1377	static const uint32 minimum_implementation_use_length = 46;
1378
1379	void dump() const;
1380	uint32 descriptor_size() const { return sizeof(*this)+implementation_use_length()
1381	                                 + partition_count()*sizeof(uint32)*2; }
1382
1383	descriptor_tag& tag() { return _tag; }
1384	const descriptor_tag& tag() const { return _tag; }
1385
1386	timestamp& recording_time() { return _recording_time; }
1387	const timestamp& recording_time() const { return _recording_time; }
1388
1389	uint32 integrity_type() const { return B_LENDIAN_TO_HOST_INT32(_integrity_type); }
1390
1391	extent_address& next_integrity_extent() { return _next_integrity_extent; }
1392	const extent_address& next_integrity_extent() const { return _next_integrity_extent; }
1393
1394	array<uint8, 32>& logical_volume_contents_use() { return _logical_volume_contents_use; }
1395	const array<uint8, 32>& logical_volume_contents_use() const { return _logical_volume_contents_use; }
1396
1397	// next_unique_id() field is actually stored in the logical_volume_contents_use()
1398	// field, per UDF-2.50 3.2.1
1399	uint64 next_unique_id() const { return B_LENDIAN_TO_HOST_INT64(_next_unique_id()); }
1400
1401	uint32 partition_count() const { return B_LENDIAN_TO_HOST_INT32(_partition_count); }
1402	uint32 implementation_use_length() const { return B_LENDIAN_TO_HOST_INT32(_implementation_use_length); }
1403
1404	/*! \todo double-check the pointer arithmetic here. */
1405	uint32* free_space_table() { return reinterpret_cast<uint32*>(reinterpret_cast<uint8*>(this)+80); }
1406	const uint32* free_space_table() const { return reinterpret_cast<const uint32*>(reinterpret_cast<const uint8*>(this)+80); }
1407	uint32* size_table() { return reinterpret_cast<uint32*>(reinterpret_cast<uint8*>(free_space_table())+partition_count()*sizeof(uint32)); }
1408	const uint32* size_table() const { return reinterpret_cast<const uint32*>(reinterpret_cast<const uint8*>(free_space_table())+partition_count()*sizeof(uint32)); }
1409	uint8* implementation_use() { return reinterpret_cast<uint8*>(reinterpret_cast<uint8*>(size_table())+partition_count()*sizeof(uint32)); }
1410	const uint8* implementation_use() const { return reinterpret_cast<const uint8*>(reinterpret_cast<const uint8*>(size_table())+partition_count()*sizeof(uint32)); }
1411
1412	// accessors for fields stored in implementation_use() field per UDF-2.50 2.2.6.4
1413	entity_id& implementation_id() { return _accessor().id; }
1414	const entity_id& implementation_id() const { return _accessor().id; }
1415	uint32 file_count() const { return B_LENDIAN_TO_HOST_INT32(_accessor().file_count); }
1416	uint32 directory_count() const { return B_LENDIAN_TO_HOST_INT32(_accessor().directory_count); }
1417	uint16 minimum_udf_read_revision() const { return B_LENDIAN_TO_HOST_INT16(_accessor().minimum_udf_read_revision); }
1418	uint16 minimum_udf_write_revision() const { return B_LENDIAN_TO_HOST_INT16(_accessor().minimum_udf_write_revision); }
1419	uint16 maximum_udf_write_revision() const { return B_LENDIAN_TO_HOST_INT16(_accessor().maximum_udf_write_revision); }
1420
1421	// set functions
1422	void set_integrity_type(uint32 type) { _integrity_type = B_HOST_TO_LENDIAN_INT32(type); }
1423	void set_next_unique_id(uint64 id) { _next_unique_id() = B_HOST_TO_LENDIAN_INT64(id); }
1424	void set_partition_count(uint32 count) { _partition_count = B_HOST_TO_LENDIAN_INT32(count); }
1425	void set_implementation_use_length(uint32 length) { _implementation_use_length = B_HOST_TO_LENDIAN_INT32(length); }
1426
1427	// set functions for fields stored in implementation_use() field per UDF-2.50 2.2.6.4
1428	void set_file_count(uint32 count) { _accessor().file_count = B_HOST_TO_LENDIAN_INT32(count); }
1429	void set_directory_count(uint32 count) { _accessor().directory_count = B_HOST_TO_LENDIAN_INT32(count); }
1430	void set_minimum_udf_read_revision(uint16 revision) { _accessor().minimum_udf_read_revision = B_HOST_TO_LENDIAN_INT16(revision); }
1431	void set_minimum_udf_write_revision(uint16 revision) { _accessor().minimum_udf_write_revision = B_HOST_TO_LENDIAN_INT16(revision); }
1432	void set_maximum_udf_write_revision(uint16 revision) { _accessor().maximum_udf_write_revision = B_HOST_TO_LENDIAN_INT16(revision); }
1433
1434private:
1435	struct _lvid_implementation_use_accessor {
1436		entity_id id;
1437		uint32 file_count;
1438		uint32 directory_count;
1439		uint16 minimum_udf_read_revision;
1440		uint16 minimum_udf_write_revision;
1441		uint16 maximum_udf_write_revision;
1442	};
1443
1444	_lvid_implementation_use_accessor& _accessor() {
1445		return *reinterpret_cast<_lvid_implementation_use_accessor*>(implementation_use());
1446	}
1447	const _lvid_implementation_use_accessor& _accessor() const {
1448		return *reinterpret_cast<const _lvid_implementation_use_accessor*>(implementation_use());
1449	}
1450
1451	uint64& _next_unique_id() { return *reinterpret_cast<uint64*>(logical_volume_contents_use().data); }
1452	const uint64& _next_unique_id() const { return *reinterpret_cast<const uint64*>(logical_volume_contents_use().data); }
1453
1454	descriptor_tag  _tag;
1455	timestamp _recording_time;
1456	uint32 _integrity_type;
1457	extent_address _next_integrity_extent;
1458	array<uint8, 32> _logical_volume_contents_use;
1459	uint32 _partition_count;
1460	uint32 _implementation_use_length;
1461
1462} __attribute__((packed));
1463
1464/*! \brief Logical volume integrity types
1465*/
1466enum {
1467	INTEGRITY_OPEN = 0,
1468	INTEGRITY_CLOSED = 1,
1469};
1470
1471/*! \brief Highest currently supported UDF read revision.
1472*/
1473#define UDF_MAX_READ_REVISION 0x0201
1474
1475//----------------------------------------------------------------------
1476// ECMA-167 Part 4
1477//----------------------------------------------------------------------
1478
1479
1480
1481/*! \brief File set descriptor
1482
1483	Contains all the pertinent info about a file set (i.e. a hierarchy of files)
1484
1485	According to UDF-2.01, only one file set descriptor shall be recorded,
1486	except on WORM media, where the following rules apply:
1487	- Multiple file sets are allowed only on WORM media
1488	- The default file set shall be the one with highest value \c file_set_number field.
1489	- Only the default file set may be flagged as writeable. All others shall be
1490	  flagged as "hard write protect".
1491	- No writeable file set may reference metadata structures which are referenced
1492	  (directly or indirectly) by any other file set. Writeable file sets may, however,
1493	  reference actual file data extents that are also referenced by other file sets.
1494*/
1495struct file_set_descriptor {
1496	void dump() const;
1497
1498	// Get functions
1499	const descriptor_tag & tag() const { return _tag; }
1500	descriptor_tag & tag() { return _tag; }
1501
1502	const timestamp& recording_date_and_time() const { return _recording_date_and_time; }
1503	timestamp& recording_date_and_time() { return _recording_date_and_time; }
1504
1505	uint16 interchange_level() const { return B_LENDIAN_TO_HOST_INT16(_interchange_level); }
1506	uint16 max_interchange_level() const { return B_LENDIAN_TO_HOST_INT16(_max_interchange_level); }
1507	uint32 character_set_list() const { return B_LENDIAN_TO_HOST_INT32(_character_set_list); }
1508	uint32 max_character_set_list() const { return B_LENDIAN_TO_HOST_INT32(_max_character_set_list); }
1509	uint32 file_set_number() const { return B_LENDIAN_TO_HOST_INT32(_file_set_number); }
1510	uint32 file_set_descriptor_number() const { return B_LENDIAN_TO_HOST_INT32(_file_set_descriptor_number); }
1511
1512	const charspec& logical_volume_id_character_set() const { return _logical_volume_id_character_set; }
1513	charspec& logical_volume_id_character_set() { return _logical_volume_id_character_set; }
1514
1515	const array<char, 128>& logical_volume_id() const { return _logical_volume_id; }
1516	array<char, 128>& logical_volume_id() { return _logical_volume_id; }
1517
1518	const charspec& file_set_id_character_set() const { return _file_set_id_character_set; }
1519	charspec& file_set_id_character_set() { return _file_set_id_character_set; }
1520
1521	const array<char, 32>& file_set_id() const { return _file_set_id; }
1522	array<char, 32>& file_set_id() { return _file_set_id; }
1523
1524	const array<char, 32>& copyright_file_id() const { return _copyright_file_id; }
1525	array<char, 32>& copyright_file_id() { return _copyright_file_id; }
1526
1527	const array<char, 32>& abstract_file_id() const { return _abstract_file_id; }
1528	array<char, 32>& abstract_file_id() { return _abstract_file_id; }
1529
1530	const long_address& root_directory_icb() const { return _root_directory_icb; }
1531	long_address& root_directory_icb() { return _root_directory_icb; }
1532
1533	const entity_id& domain_id() const { return _domain_id; }
1534	entity_id& domain_id() { return _domain_id; }
1535
1536	const long_address& next_extent() const { return _next_extent; }
1537	long_address& next_extent() { return _next_extent; }
1538
1539	const long_address& system_stream_directory_icb() const { return _system_stream_directory_icb; }
1540	long_address& system_stream_directory_icb() { return _system_stream_directory_icb; }
1541
1542	const array<uint8, 32>& reserved() const { return _reserved; }
1543	array<uint8, 32>& reserved() { return _reserved; }
1544
1545	// Set functions
1546	void set_interchange_level(uint16 level) { _interchange_level = B_HOST_TO_LENDIAN_INT16(level); }
1547	void set_max_interchange_level(uint16 level) { _max_interchange_level = B_HOST_TO_LENDIAN_INT16(level); }
1548	void set_character_set_list(uint32 list) { _character_set_list = B_HOST_TO_LENDIAN_INT32(list); }
1549	void set_max_character_set_list(uint32 list) { _max_character_set_list = B_HOST_TO_LENDIAN_INT32(list); }
1550	void set_file_set_number(uint32 number) { _file_set_number = B_HOST_TO_LENDIAN_INT32(number); }
1551	void set_file_set_descriptor_number(uint32 number) { _file_set_descriptor_number = B_HOST_TO_LENDIAN_INT32(number); }
1552private:
1553	descriptor_tag  _tag;
1554	timestamp _recording_date_and_time;
1555	uint16 _interchange_level;			//!< To be set to 3 (see UDF-2.01 2.3.2.1)
1556	uint16 _max_interchange_level;		//!< To be set to 3 (see UDF-2.01 2.3.2.2)
1557	uint32 _character_set_list;
1558	uint32 _max_character_set_list;
1559	uint32 _file_set_number;
1560	uint32 _file_set_descriptor_number;
1561	charspec _logical_volume_id_character_set;	//!< To be set to kCSOCharspec
1562	array<char, 128> _logical_volume_id;
1563	charspec _file_set_id_character_set;
1564	array<char, 32> _file_set_id;
1565	array<char, 32> _copyright_file_id;
1566	array<char, 32> _abstract_file_id;
1567	long_address _root_directory_icb;
1568	entity_id _domain_id;
1569	long_address _next_extent;
1570	long_address _system_stream_directory_icb;
1571	array<uint8, 32> _reserved;
1572} __attribute__((packed));
1573
1574
1575/*! \brief Partition header descriptor
1576
1577	Contains references to unallocated and freed space data structures.
1578
1579	Note that unallocated space is space ready to be written with no
1580	preprocessing. Freed space is space needing preprocessing (i.e.
1581	a special write pass) before use.
1582
1583	Per UDF-2.01 2.3.3, the use of tables or bitmaps shall be consistent,
1584	i.e. only one type or the other shall be used, not both.
1585
1586	To indicate disuse of a certain field, the fields of the allocation
1587	descriptor shall all be set to 0.
1588
1589	See also: ECMA-167 4/14.3, UDF-2.01 2.2.3
1590*/
1591struct partition_header_descriptor {
1592	long_address unallocated_space_table;
1593	long_address unallocated_space_bitmap;
1594	/*! Unused, per UDF-2.01 2.2.3 */
1595	long_address partition_integrity_table;
1596	long_address freed_space_table;
1597	long_address freed_space_bitmap;
1598	uint8 reserved[88];
1599} __attribute__((packed));
1600
1601#define kMaxFileIdSize (sizeof(file_id_descriptor)+512+3)
1602
1603/*! \brief File identifier descriptor
1604
1605	Identifies the name of a file entry, and the location of its corresponding
1606	ICB.
1607
1608	See also: ECMA-167 4/14.4, UDF-2.01 2.3.4
1609
1610	\todo Check pointer arithmetic
1611*/
1612struct file_id_descriptor {
1613public:
1614	uint32 descriptor_size() const { return total_length(); }
1615	void dump() const;
1616
1617	descriptor_tag & tag() { return _tag; }
1618	const descriptor_tag & tag() const { return _tag; }
1619
1620	uint16 version_number() const { return B_LENDIAN_TO_HOST_INT16(_version_number); }
1621
1622	uint8 characteristics() const { return _characteristics; }
1623
1624	bool may_be_hidden() const {
1625		characteristics_accessor c;
1626		c.all = characteristics();
1627		return c.bits.may_be_hidden;
1628	}
1629
1630	bool is_directory() const {
1631		characteristics_accessor c;
1632		c.all = characteristics();
1633		return c.bits.is_directory;
1634	}
1635
1636	bool is_deleted() const {
1637		characteristics_accessor c;
1638		c.all = characteristics();
1639		return c.bits.is_deleted;
1640	}
1641
1642	bool is_parent() const {
1643		characteristics_accessor c;
1644		c.all = characteristics();
1645		return c.bits.is_parent;
1646	}
1647
1648	bool is_metadata_stream() const {
1649		characteristics_accessor c;
1650		c.all = characteristics();
1651		return c.bits.is_metadata_stream;
1652	}
1653
1654	uint8 id_length() const { return _id_length; }
1655
1656	long_address& icb() { return _icb; }
1657	const long_address& icb() const { return _icb; }
1658
1659	uint16 implementation_use_length() const { return B_LENDIAN_TO_HOST_INT16(_implementation_use_length); }
1660
1661	/*! If implementation_use_length is greater than 0, the first 32
1662		bytes of implementation_use() shall be an entity_id identifying
1663		the implementation that generated the rest of the data in the
1664		implementation_use() field.
1665	*/
1666	uint8* implementation_use() { return ((uint8*)this)+(38); }
1667	char* id() { return ((char*)this)+(38)+implementation_use_length(); }
1668	const char* id() const { return ((const char*)this)+(38)+implementation_use_length(); }
1669
1670	uint16 structure_length() const { return (38) + id_length() + implementation_use_length(); }
1671	uint16 padding_length() const { return ((structure_length()+3)/4)*4 - structure_length(); }
1672	uint16 total_length() const { return structure_length() + padding_length(); }
1673
1674	// Set functions
1675	void set_version_number(uint16 number) { _version_number = B_HOST_TO_LENDIAN_INT16(number); }
1676
1677	void set_characteristics(uint8 characteristics) { _characteristics = characteristics; }
1678
1679	void set_may_be_hidden(bool how) {
1680		characteristics_accessor c;
1681		c.all = characteristics();
1682		c.bits.may_be_hidden = how;
1683		set_characteristics(c.all);
1684	}
1685
1686	void set_is_directory(bool how) {
1687		characteristics_accessor c;
1688		c.all = characteristics();
1689		c.bits.is_directory = how;
1690		set_characteristics(c.all);
1691	}
1692
1693	void set_is_deleted(bool how) {
1694		characteristics_accessor c;
1695		c.all = characteristics();
1696		c.bits.is_deleted = how;
1697		set_characteristics(c.all);
1698	}
1699
1700	void set_is_parent(bool how) {
1701		characteristics_accessor c;
1702		c.all = characteristics();
1703		c.bits.is_parent = how;
1704		set_characteristics(c.all);
1705	}
1706
1707	void set_is_metadata_stream(bool how) {
1708		characteristics_accessor c;
1709		c.all = characteristics();
1710		c.bits.is_metadata_stream = how;
1711		set_characteristics(c.all);
1712	}
1713
1714
1715	void set_id_length(uint8 id_length) { _id_length = id_length; }
1716	void set_implementation_use_length(uint16 implementation_use_length) { _implementation_use_length = B_HOST_TO_LENDIAN_INT16(implementation_use_length); }
1717
1718
1719
1720private:
1721	union characteristics_accessor {
1722		uint8 all;
1723		struct {
1724			uint8	may_be_hidden:1,
1725					is_directory:1,
1726					is_deleted:1,
1727					is_parent:1,
1728					is_metadata_stream:1,
1729					reserved_characteristics:3;
1730		} bits;
1731	};
1732
1733	descriptor_tag  _tag;
1734	/*! According to ECMA-167: 1 <= valid version_number <= 32767, 32768 <= reserved <= 65535.
1735
1736		However, according to UDF-2.01, there shall be exactly one version of
1737		a file, and it shall be 1.
1738	 */
1739	uint16 _version_number;
1740	/*! \todo Check UDF-2.01 2.3.4.2 for some more restrictions. */
1741	uint8 _characteristics;
1742	uint8 _id_length;
1743	long_address _icb;
1744	uint16 _implementation_use_length;
1745} __attribute__((packed));
1746
1747
1748/*! \brief Allocation extent descriptor
1749
1750	See also: ECMA-167 4/14.5
1751*/
1752struct allocation_extent_descriptor {
1753	descriptor_tag  tag;
1754	uint32 previous_allocation_extent_location;
1755	uint32 length_of_allocation_descriptors;
1756
1757	/*! \todo Check that this is really how things work: */
1758	uint8* allocation_descriptors() { return (uint8*)(reinterpret_cast<uint8*>(this)+sizeof(allocation_extent_descriptor)); }
1759} __attribute__((packed));
1760
1761
1762/*! \brief icb_tag::file_type values
1763
1764	See also ECMA-167 4/14.6.6
1765*/
1766enum icb_file_types {
1767	ICB_TYPE_UNSPECIFIED = 0,
1768	ICB_TYPE_UNALLOCATED_SPACE_ENTRY,
1769	ICB_TYPE_PARTITION_INTEGRITY_ENTRY,
1770	ICB_TYPE_INDIRECT_ENTRY,
1771	ICB_TYPE_DIRECTORY,
1772	ICB_TYPE_REGULAR_FILE,
1773	ICB_TYPE_BLOCK_SPECIAL_DEVICE,
1774	ICB_TYPE_CHARACTER_SPECIAL_DEVICE,
1775	ICB_TYPE_EXTENDED_ATTRIBUTES_FILE,
1776	ICB_TYPE_FIFO,
1777	ICB_TYPE_ISSOCK,
1778	ICB_TYPE_TERMINAL,
1779	ICB_TYPE_SYMLINK,
1780	ICB_TYPE_STREAM_DIRECTORY,
1781
1782	ICB_TYPE_RESERVED_START = 14,
1783	ICB_TYPE_RESERVED_END = 247,
1784
1785	ICB_TYPE_CUSTOM_START = 248,
1786	ICB_TYPE_CUSTOM_END = 255,
1787};
1788
1789/*!	\brief idb_entry_tag::_flags::descriptor_flags() values
1790
1791	See also ECMA-167 4/14.6.8
1792*/
1793enum icb_descriptor_types {
1794	ICB_DESCRIPTOR_TYPE_SHORT = 0,
1795	ICB_DESCRIPTOR_TYPE_LONG,
1796	ICB_DESCRIPTOR_TYPE_EXTENDED,
1797	ICB_DESCRIPTOR_TYPE_EMBEDDED,
1798};
1799
1800/*!	\brief idb_entry_tag::strategy_type() values
1801
1802	See also UDF-2.50 2.3.5.1
1803*/
1804enum icb_strategy_types {
1805	ICB_STRATEGY_SINGLE = 4,
1806	ICB_STRATEGY_LINKED_LIST = 4096
1807};
1808
1809/*! \brief ICB entry tag
1810
1811	Common tag found in all ICB entries (in addition to, and immediately following,
1812	the descriptor tag).
1813
1814	See also: ECMA-167 4/14.6, UDF-2.01 2.3.5
1815*/
1816struct icb_entry_tag {
1817public:
1818	union flags_accessor {
1819		uint16 all_flags;
1820		struct {
1821			uint16	descriptor_flags:3,
1822					if_directory_then_sort:1,	//!< To be set to 0 per UDF-2.01 2.3.5.4
1823					non_relocatable:1,
1824					archive:1,
1825					setuid:1,
1826					setgid:1,
1827					sticky:1,
1828					contiguous:1,
1829					system:1,
1830					transformed:1,
1831					multi_version:1,			//!< To be set to 0 per UDF-2.01 2.3.5.4
1832					is_stream:1,
1833					reserved_icb_entry_flags:2;
1834		} flags;
1835	};
1836
1837public:
1838	void dump() const;
1839
1840	uint32 prior_recorded_number_of_direct_entries() const { return B_LENDIAN_TO_HOST_INT32(_prior_recorded_number_of_direct_entries); }
1841	uint16 strategy_type() const { return B_LENDIAN_TO_HOST_INT16(_strategy_type); }
1842
1843	array<uint8, 2>& strategy_parameters() { return _strategy_parameters; }
1844	const array<uint8, 2>& strategy_parameters() const { return _strategy_parameters; }
1845
1846	uint16 entry_count() const { return B_LENDIAN_TO_HOST_INT16(_entry_count); }
1847	uint8& reserved() { return _reserved; }
1848	uint8 file_type() const { return _file_type; }
1849	logical_block_address& parent_icb_location() { return _parent_icb_location; }
1850	const logical_block_address& parent_icb_location() const { return _parent_icb_location; }
1851
1852	uint16 flags() const { return B_LENDIAN_TO_HOST_INT16(_flags); }
1853	flags_accessor& flags_access() { return *reinterpret_cast<flags_accessor*>(&_flags); }
1854
1855	// flags accessor functions
1856	uint8 descriptor_flags() const {
1857		flags_accessor f;
1858		f.all_flags = flags();
1859		return f.flags.descriptor_flags;
1860	}
1861/*	void set_descriptor_flags(uint8 value) {
1862		flags_accessor f;
1863		f.all_flags = flags();
1864		f.flags.descriptor_flags = value;
1865		set_flags
1866*/
1867
1868	void set_prior_recorded_number_of_direct_entries(uint32 entries) { _prior_recorded_number_of_direct_entries = B_LENDIAN_TO_HOST_INT32(entries); }
1869	void set_strategy_type(uint16 type) { _strategy_type = B_HOST_TO_LENDIAN_INT16(type); }
1870
1871	void set_entry_count(uint16 count) { _entry_count = B_LENDIAN_TO_HOST_INT16(count); }
1872	void set_file_type(uint8 type) { _file_type = type; }
1873
1874	void set_flags(uint16 flags) { _flags = B_LENDIAN_TO_HOST_INT16(flags); }
1875
1876private:
1877	uint32 _prior_recorded_number_of_direct_entries;
1878	/*! Per UDF-2.01 2.3.5.1, only strategy types 4 and 4096 shall be supported.
1879
1880		\todo Describe strategy types here.
1881	*/
1882	uint16 _strategy_type;
1883	array<uint8, 2> _strategy_parameters;
1884	uint16 _entry_count;
1885	uint8 _reserved;
1886	/*! \brief icb_file_type value identifying the type of this icb entry */
1887	uint8 _file_type;
1888	logical_block_address _parent_icb_location;
1889	uint16 _flags;
1890} __attribute__((packed));
1891
1892/*! \brief Header portion of an ICB entry.
1893*/
1894struct icb_header {
1895public:
1896	void dump() const;
1897
1898	descriptor_tag  &tag() { return _tag; }
1899	const descriptor_tag  &tag() const { return _tag; }
1900
1901	icb_entry_tag &icb_tag() { return _icb_tag; }
1902	const icb_entry_tag &icb_tag() const { return _icb_tag; }
1903private:
1904	descriptor_tag  _tag;
1905	icb_entry_tag _icb_tag;
1906};
1907
1908/*! \brief Indirect ICB entry
1909*/
1910struct indirect_icb_entry {
1911	descriptor_tag  tag;
1912	icb_entry_tag icb_tag;
1913	long_address indirect_icb;
1914} __attribute__((packed));
1915
1916
1917/*! \brief Terminal ICB entry
1918*/
1919struct terminal_icb_entry {
1920	descriptor_tag  tag;
1921	icb_entry_tag icb_tag;
1922} __attribute__((packed));
1923
1924enum permissions {
1925	OTHER_EXECUTE	 	= 0x0001,
1926	OTHER_WRITE			= 0x0002,
1927	OTHER_READ			= 0x0004,
1928	OTHER_ATTRIBUTES	= 0x0008,
1929	OTHER_DELETE		= 0x0010,
1930	GROUP_EXECUTE	 	= 0x0020,
1931	GROUP_WRITE			= 0x0040,
1932	GROUP_READ			= 0x0080,
1933	GROUP_ATTRIBUTES	= 0x0100,
1934	GROUP_DELETE		= 0x0200,
1935	USER_EXECUTE	 	= 0x0400,
1936	USER_WRITE			= 0x0800,
1937	USER_READ			= 0x1000,
1938	USER_ATTRIBUTES		= 0x2000,
1939	USER_DELETE			= 0x4000,
1940};
1941
1942/*! \brief File ICB entry
1943
1944	See also: ECMA-167 4/14.9
1945
1946	\todo Check pointer math.
1947*/
1948struct file_icb_entry {
1949	void dump() const;
1950	uint32 descriptor_size() const { return sizeof(*this)+extended_attributes_length()
1951	                                 +allocation_descriptors_length(); }
1952	const char* descriptor_name() const { return "file_icb_entry"; }
1953
1954	// get functions
1955	descriptor_tag & tag() { return _tag; }
1956	const descriptor_tag & tag() const { return _tag; }
1957
1958	icb_entry_tag& icb_tag() { return _icb_tag; }
1959	const icb_entry_tag& icb_tag() const { return _icb_tag; }
1960
1961	uint32 uid() const { return B_LENDIAN_TO_HOST_INT32(_uid); }
1962	uint32 gid() const { return B_LENDIAN_TO_HOST_INT32(_gid); }
1963	uint32 permissions() const { return B_LENDIAN_TO_HOST_INT32(_permissions); }
1964	uint16 file_link_count() const { return B_LENDIAN_TO_HOST_INT16(_file_link_count); }
1965	uint8 record_format() const { return _record_format; }
1966	uint8 record_display_attributes() const { return _record_display_attributes; }
1967	uint8 record_length() const { return _record_length; }
1968	uint64 information_length() const { return B_LENDIAN_TO_HOST_INT64(_information_length); }
1969	uint64 logical_blocks_recorded() const { return B_LENDIAN_TO_HOST_INT64(_logical_blocks_recorded); }
1970
1971	timestamp& access_date_and_time() { return _access_date_and_time; }
1972	const timestamp& access_date_and_time() const { return _access_date_and_time; }
1973
1974	timestamp& modification_date_and_time() { return _modification_date_and_time; }
1975	const timestamp& modification_date_and_time() const { return _modification_date_and_time; }
1976
1977	timestamp& attribute_date_and_time() { return _attribute_date_and_time; }
1978	const timestamp& attribute_date_and_time() const { return _attribute_date_and_time; }
1979
1980	uint32 checkpoint() const { return B_LENDIAN_TO_HOST_INT32(_checkpoint); }
1981
1982	long_address& extended_attribute_icb() { return _extended_attribute_icb; }
1983	const long_address& extended_attribute_icb() const { return _extended_attribute_icb; }
1984
1985	entity_id& implementation_id() { return _implementation_id; }
1986	const entity_id& implementation_id() const { return _implementation_id; }
1987
1988	uint64 unique_id() const { return B_LENDIAN_TO_HOST_INT64(_unique_id); }
1989	uint32 extended_attributes_length() const { return B_LENDIAN_TO_HOST_INT32(_extended_attributes_length); }
1990	uint32 allocation_descriptors_length() const { return B_LENDIAN_TO_HOST_INT32(_allocation_descriptors_length); }
1991
1992	uint8* extended_attributes() { return _end(); }
1993	const uint8* extended_attributes() const { return _end(); }
1994	uint8* allocation_descriptors() { return _end()+extended_attributes_length(); }
1995	const uint8* allocation_descriptors() const { return _end()+extended_attributes_length(); }
1996
1997	// set functions
1998	void set_uid(uint32 uid) { _uid = B_HOST_TO_LENDIAN_INT32(uid); }
1999	void set_gid(uint32 gid) { _gid = B_HOST_TO_LENDIAN_INT32(gid); }
2000	void set_permissions(uint32 permissions) { _permissions = B_HOST_TO_LENDIAN_INT32(permissions); }
2001
2002	void set_file_link_count(uint16 count) { _file_link_count = B_HOST_TO_LENDIAN_INT16(count); }
2003	void set_record_format(uint8 format) { _record_format = format; }
2004	void set_record_display_attributes(uint8 attributes) { _record_display_attributes = attributes; }
2005	void set_record_length(uint8 length) { _record_length = length; }
2006
2007	void set_information_length(uint64 length) { _information_length = B_HOST_TO_LENDIAN_INT64(length); }
2008	void set_logical_blocks_recorded(uint64 blocks) { _logical_blocks_recorded = B_HOST_TO_LENDIAN_INT64(blocks); }
2009
2010	void set_checkpoint(uint32 checkpoint) { _checkpoint = B_HOST_TO_LENDIAN_INT32(checkpoint); }
2011
2012	void set_unique_id(uint64 id) { _unique_id = B_HOST_TO_LENDIAN_INT64(id); }
2013
2014	void set_extended_attributes_length(uint32 length) { _extended_attributes_length = B_HOST_TO_LENDIAN_INT32(length); }
2015	void set_allocation_descriptors_length(uint32 length) { _allocation_descriptors_length = B_HOST_TO_LENDIAN_INT32(length); }
2016
2017	// extended_file_icb_entry compatability functions
2018	timestamp& creation_date_and_time() { return _attribute_date_and_time; }
2019	const timestamp& creation_date_and_time() const { return _attribute_date_and_time; }
2020
2021
2022	void set_object_size(uint64 size) { }
2023	void set_reserved(uint32 reserved) { }
2024	long_address& stream_directory_icb() { return _dummy_stream_directory_icb; }
2025	const long_address& stream_directory_icb() const { return _dummy_stream_directory_icb; }
2026
2027
2028private:
2029	static const uint32 _descriptor_length = 176;
2030	static long_address _dummy_stream_directory_icb;
2031	uint8* _end() { return reinterpret_cast<uint8*>(this)+_descriptor_length; }
2032	const uint8* _end() const { return reinterpret_cast<const uint8*>(this)+_descriptor_length; }
2033
2034	descriptor_tag  _tag;
2035	icb_entry_tag _icb_tag;
2036	uint32 _uid;
2037	uint32 _gid;
2038	/*! \todo List perms in comment and add handy union thingy */
2039	uint32 _permissions;
2040	/*! Identifies the number of file identifier descriptors referencing
2041		this icb.
2042	*/
2043	uint16 _file_link_count;
2044	uint8 _record_format;				//!< To be set to 0 per UDF-2.01 2.3.6.1
2045	uint8 _record_display_attributes;	//!< To be set to 0 per UDF-2.01 2.3.6.2
2046	uint8 _record_length;				//!< To be set to 0 per UDF-2.01 2.3.6.3
2047	uint64 _information_length;
2048	uint64 _logical_blocks_recorded;		//!< To be 0 for files and dirs with embedded data
2049	timestamp _access_date_and_time;
2050	timestamp _modification_date_and_time;
2051
2052	// NOTE: data members following this point in the descriptor are in
2053	// different locations in extended file entries
2054
2055	timestamp _attribute_date_and_time;
2056	/*! \brief Initially 1, may be incremented upon user request. */
2057	uint32 _checkpoint;
2058	long_address _extended_attribute_icb;
2059	entity_id _implementation_id;
2060	/*! \brief The unique id identifying this file entry
2061
2062		The id of the root directory of a file set shall be 0.
2063
2064		\todo Detail the system specific requirements for unique ids from UDF-2.01
2065	*/
2066	uint64 _unique_id;
2067	uint32 _extended_attributes_length;
2068	uint32 _allocation_descriptors_length;
2069
2070};
2071
2072
2073/*! \brief Extended file ICB entry
2074
2075	See also: ECMA-167 4/14.17
2076
2077	\todo Check pointer math.
2078*/
2079struct extended_file_icb_entry {
2080	void dump() const;
2081	uint32 descriptor_size() const { return sizeof(*this)+extended_attributes_length()
2082	                                 +allocation_descriptors_length(); }
2083	const char* descriptor_name() const { return "extended_file_icb_entry"; }
2084
2085	// get functions
2086	descriptor_tag & tag() { return _tag; }
2087	const descriptor_tag & tag() const { return _tag; }
2088
2089	icb_entry_tag& icb_tag() { return _icb_tag; }
2090	const icb_entry_tag& icb_tag() const { return _icb_tag; }
2091
2092	uint32 uid() const { return B_LENDIAN_TO_HOST_INT32(_uid); }
2093	uint32 gid() const { return B_LENDIAN_TO_HOST_INT32(_gid); }
2094	uint32 permissions() const { return B_LENDIAN_TO_HOST_INT32(_permissions); }
2095	uint16 file_link_count() const { return B_LENDIAN_TO_HOST_INT16(_file_link_count); }
2096	uint8 record_format() const { return _record_format; }
2097	uint8 record_display_attributes() const { return _record_display_attributes; }
2098	uint32 record_length() const { return _record_length; }
2099	uint64 information_length() const { return B_LENDIAN_TO_HOST_INT64(_information_length); }
2100	uint64 object_size() const { return B_LENDIAN_TO_HOST_INT64(_object_size); }
2101	uint64 logical_blocks_recorded() const { return B_LENDIAN_TO_HOST_INT64(_logical_blocks_recorded); }
2102
2103	timestamp& access_date_and_time() { return _access_date_and_time; }
2104	const timestamp& access_date_and_time() const { return _access_date_and_time; }
2105
2106	timestamp& modification_date_and_time() { return _modification_date_and_time; }
2107	const timestamp& modification_date_and_time() const { return _modification_date_and_time; }
2108
2109	timestamp& creation_date_and_time() { return _creation_date_and_time; }
2110	const timestamp& creation_date_and_time() const { return _creation_date_and_time; }
2111
2112	timestamp& attribute_date_and_time() { return _attribute_date_and_time; }
2113	const timestamp& attribute_date_and_time() const { return _attribute_date_and_time; }
2114
2115	uint32 checkpoint() const { return B_LENDIAN_TO_HOST_INT32(_checkpoint); }
2116
2117	long_address& extended_attribute_icb() { return _extended_attribute_icb; }
2118	const long_address& extended_attribute_icb() const { return _extended_attribute_icb; }
2119
2120	long_address& stream_directory_icb() { return _stream_directory_icb; }
2121	const long_address& stream_directory_icb() const { return _stream_directory_icb; }
2122
2123	entity_id& implementation_id() { return _implementation_id; }
2124	const entity_id& implementation_id() const { return _implementation_id; }
2125
2126	uint64 unique_id() const { return B_LENDIAN_TO_HOST_INT64(_unique_id); }
2127	uint32 extended_attributes_length() const { return B_LENDIAN_TO_HOST_INT32(_extended_attributes_length); }
2128	uint32 allocation_descriptors_length() const { return B_LENDIAN_TO_HOST_INT32(_allocation_descriptors_length); }
2129
2130	uint8* extended_attributes() { return _end(); }
2131	const uint8* extended_attributes() const { return _end(); }
2132	uint8* allocation_descriptors() { return _end()+extended_attributes_length(); }
2133	const uint8* allocation_descriptors() const { return _end()+extended_attributes_length(); }
2134
2135	// set functions
2136	void set_uid(uint32 uid) { _uid = B_HOST_TO_LENDIAN_INT32(uid); }
2137	void set_gid(uint32 gid) { _gid = B_HOST_TO_LENDIAN_INT32(gid); }
2138	void set_permissions(uint32 permissions) { _permissions = B_HOST_TO_LENDIAN_INT32(permissions); }
2139
2140	void set_file_link_count(uint16 count) { _file_link_count = B_HOST_TO_LENDIAN_INT16(count); }
2141	void set_record_format(uint8 format) { _record_format = format; }
2142	void set_record_display_attributes(uint8 attributes) { _record_display_attributes = attributes; }
2143	void set_record_length(uint32 length) { _record_length = B_HOST_TO_LENDIAN_INT32(length); }
2144
2145	void set_information_length(uint64 length) { _information_length = B_HOST_TO_LENDIAN_INT64(length); }
2146	void set_object_size(uint64 size) { _object_size = B_HOST_TO_LENDIAN_INT64(size); }
2147	void set_logical_blocks_recorded(uint64 blocks) { _logical_blocks_recorded = B_HOST_TO_LENDIAN_INT64(blocks); }
2148
2149	void set_checkpoint(uint32 checkpoint) { _checkpoint = B_HOST_TO_LENDIAN_INT32(checkpoint); }
2150	void set_reserved(uint32 reserved) { _reserved = B_HOST_TO_LENDIAN_INT32(reserved); }
2151
2152	void set_unique_id(uint64 id) { _unique_id = B_HOST_TO_LENDIAN_INT64(id); }
2153
2154	void set_extended_attributes_length(uint32 length) { _extended_attributes_length = B_HOST_TO_LENDIAN_INT32(length); }
2155	void set_allocation_descriptors_length(uint32 length) { _allocation_descriptors_length = B_HOST_TO_LENDIAN_INT32(length); }
2156
2157private:
2158	static const uint32 _descriptor_length = 216;
2159	uint8* _end() { return reinterpret_cast<uint8*>(this)+_descriptor_length; }
2160	const uint8* _end() const { return reinterpret_cast<const uint8*>(this)+_descriptor_length; }
2161
2162	descriptor_tag  _tag;
2163	icb_entry_tag _icb_tag;
2164	uint32 _uid;
2165	uint32 _gid;
2166	/*! \todo List perms in comment and add handy union thingy */
2167	uint32 _permissions;
2168	/*! Identifies the number of file identifier descriptors referencing
2169		this icb.
2170	*/
2171	uint16 _file_link_count;
2172	uint8 _record_format;				//!< To be set to 0 per UDF-2.01 2.3.6.1
2173	uint8 _record_display_attributes;	//!< To be set to 0 per UDF-2.01 2.3.6.2
2174	uint32 _record_length;				//!< To be set to 0 per UDF-2.01 2.3.6.3
2175	uint64 _information_length;
2176	uint64 _object_size;
2177	uint64 _logical_blocks_recorded;		//!< To be 0 for files and dirs with embedded data
2178	timestamp _access_date_and_time;
2179	timestamp _modification_date_and_time;
2180	timestamp _creation_date_and_time;	// <== EXTENDED FILE ENTRY ONLY
2181	timestamp _attribute_date_and_time;
2182	/*! \brief Initially 1, may be incremented upon user request. */
2183	uint32 _checkpoint;
2184	uint32 _reserved;	// <== EXTENDED FILE ENTRY ONLY
2185	long_address _extended_attribute_icb;
2186	long_address _stream_directory_icb;	// <== EXTENDED FILE ENTRY ONLY
2187	entity_id _implementation_id;
2188	/*! \brief The unique id identifying this file entry
2189
2190		The id of the root directory of a file set shall be 0.
2191
2192		\todo Detail the system specific requirements for unique ids from UDF-2.01 3.2.1.1
2193	*/
2194	uint64 _unique_id;
2195	uint32 _extended_attributes_length;
2196	uint32 _allocation_descriptors_length;
2197
2198};
2199
2200
2201};	// namespace Udf
2202
2203#endif	// _UDF_DISK_STRUCTURES_H
2204
2205