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