xref: /haiku/src/add-ons/kernel/file_systems/udf/UdfStructures.h (revision 49a6a0ebf3eb74e92ea0b1155c8bef5d507b246d)
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 /*! \file UdfStructures.h
20 
21 	\brief UDF on-disk data structure declarations
22 
23 	UDF is a specialization of the ECMA-167 standard. For the most part,
24 	ECMA-167 structures are used by UDF with special restrictions. In a
25 	few instances, UDF introduces its own structures to augment those
26 	supplied by ECMA-167; those structures are clearly marked.
27 
28 	For UDF info: <a href='http://www.osta.org'>http://www.osta.org</a>
29 	For ECMA info: <a href='http://www.ecma-international.org'>http://www.ecma-international.org</a>
30 
31 	For lack of a better place to store this info, the structures that
32 	are allowed to have length greater than the logical block size are
33 	as follows (other length restrictions may be found in UDF-2.01 5.1):
34 	- \c logical_volume_descriptor
35 	- \c unallocated_space_descriptor
36 	- \c logical_volume_integrity_descriptor
37 	- \c space_bitmap_descriptor
38 
39 	Other links of interest:
40 	- <a href='http://www.extra.research.philips.com/udf/'>Philips UDF verifier</a>
41 	- <a href='http://www.hi-ho.ne.jp/y-komachi/committees/fpro/fpro.htm'>Possible test disc image generator (?)</a>
42 */
43 
44 //----------------------------------------------------------------------
45 // ECMA-167 Part 1
46 //----------------------------------------------------------------------
47 
48 /*! \brief Character set specifications
49 
50 	The character_set_info field shall be set to the ASCII string
51 	"OSTA Compressed Unicode" (padded right with NULL chars).
52 
53 	See also: ECMA 167 1/7.2.1, UDF-2.01 2.1.2
54 */
55 struct charspec {
56 public:
57 	charspec(uint8 type = 0, const char *info = NULL);
58 
59 	void dump() const;
60 
character_set_typecharspec61 	uint8 character_set_type() const { return _character_set_type; }
character_set_infocharspec62 	const char* character_set_info() const { return _character_set_info; }
character_set_infocharspec63 	char* character_set_info() { return _character_set_info; }
64 
set_character_set_typecharspec65 	void set_character_set_type(uint8 type) { _character_set_type = type; }
66 	void set_character_set_info(const char *info);
67 private:
68 	uint8 _character_set_type;	//!< to be set to 0 to indicate CS0
69 	char _character_set_info[63];	//!< "OSTA Compressed Unicode"
70 } __attribute__((packed));
71 
72 extern const charspec kCs0CharacterSet;
73 
74 /*! \brief Date and time stamp
75 
76 	See also: ECMA 167 1/7.3, UDF-2.01 2.1.4
77 */
78 class timestamp {
79 private:
80 	union type_and_timezone_accessor {
81 		uint16 type_and_timezone;
82 		struct {
83 			uint16 timezone:12,
84 			       type:4;
85 		} bits;
86 	};
87 
88 public:
timestamp()89 	timestamp() { _clear(); }
90 	timestamp(time_t time);
91 
92 	void dump() const;
93 
94 	// Get functions
type_and_timezone()95 	uint16 type_and_timezone() const { return B_LENDIAN_TO_HOST_INT16(_type_and_timezone); }
type()96 	uint8 type() const {
97 		type_and_timezone_accessor t;
98 		t.type_and_timezone = type_and_timezone();
99 		return t.bits.type;
100 	}
timezone()101 	int16 timezone() const {
102 		type_and_timezone_accessor t;
103 		t.type_and_timezone = type_and_timezone();
104 		int16 result = t.bits.timezone;
105 		// Fill the lefmost bits with ones if timezone is negative
106 		result <<= 4;
107 		result >>= 4;
108 		return result;
109 	}
year()110 	uint16 year() const { return B_LENDIAN_TO_HOST_INT16(_year); }
month()111 	uint8 month() const { return _month; }
day()112 	uint8 day() const { return _day; }
hour()113 	uint8 hour() const { return _hour; }
minute()114 	uint8 minute() const { return _minute; }
second()115 	uint8 second() const { return _second; }
centisecond()116 	uint8 centisecond() const { return _centisecond; }
hundred_microsecond()117 	uint8 hundred_microsecond() const { return _hundred_microsecond; }
microsecond()118 	uint8 microsecond() const { return _microsecond; }
119 
120 	// Set functions
set_type_and_timezone(uint16 type_and_timezone)121 	void set_type_and_timezone(uint16 type_and_timezone) {
122 		_type_and_timezone = B_HOST_TO_LENDIAN_INT16(type_and_timezone); }
set_type(uint8 type)123 	void set_type(uint8 type) {
124 		type_and_timezone_accessor t;
125 		t.type_and_timezone = type_and_timezone();
126 		t.bits.type = type;
127 		set_type_and_timezone(t.type_and_timezone);
128 	}
set_timezone(int16 tz)129 	void set_timezone(int16 tz) {
130 		type_and_timezone_accessor t;
131 		t.type_and_timezone = type_and_timezone();
132 		t.bits.timezone = tz;
133 		set_type_and_timezone(t.type_and_timezone);
134 	}
set_year(uint16 year)135 	void set_year(uint16 year) { _year = B_HOST_TO_LENDIAN_INT16(year); }
set_month(uint8 month)136 	void set_month(uint8 month) { _month = month; }
set_day(uint8 day)137 	void set_day(uint8 day) { _day = day; }
set_hour(uint8 hour)138 	void set_hour(uint8 hour) { _hour = hour; }
set_minute(uint8 minute)139 	void set_minute(uint8 minute) { _minute = minute; }
set_second(uint8 second)140 	void set_second(uint8 second) { _second = second; }
set_centisecond(uint8 centisecond)141 	void set_centisecond(uint8 centisecond) { _centisecond = centisecond; }
set_hundred_microsecond(uint8 hundred_microsecond)142 	void set_hundred_microsecond(uint8 hundred_microsecond) {
143 		_hundred_microsecond = hundred_microsecond; }
set_microsecond(uint8 microsecond)144 	void set_microsecond(uint8 microsecond) { _microsecond = microsecond; }
145 private:
146 	void _clear();
147 
148 	uint16 _type_and_timezone;
149 	uint16 _year;
150 	uint8 _month;
151 	uint8 _day;
152 	uint8 _hour;
153 	uint8 _minute;
154 	uint8 _second;
155 	uint8 _centisecond;
156 	uint8 _hundred_microsecond;
157 	uint8 _microsecond;
158 
159 } __attribute__((packed));
160 
161 
162 /*! \brief UDF ID Identify Suffix
163 
164 	See also: UDF 2.50 2.1.5.3
165 */
166 struct udf_id_suffix {
167 public:
168 	udf_id_suffix(uint16 udfRevision, uint8 os_class, uint8 os_identifier);
169 
170 	//! Note that revision 2.50 is denoted by 0x0250.
udf_revisionudf_id_suffix171 	uint16 udf_revision() const { return _udf_revision; }
os_classudf_id_suffix172 	uint8 os_class() const { return _os_class; }
os_identifierudf_id_suffix173 	uint8 os_identifier() const { return _os_identifier; }
174 
set_os_classudf_id_suffix175 	void set_os_class(uint8 os_class) { _os_class = os_class; }
set_os_identifierudf_id_suffix176 	void set_os_identifier(uint8 identifier) { _os_identifier = identifier; }
177 private:
178 	uint16 _udf_revision;
179 	uint8 _os_class;
180 	uint8 _os_identifier;
181 	array<uint8, 4> _reserved;
182 };
183 
184 /*! \brief Implementation ID Identify Suffix
185 
186 	See also: UDF 2.50 2.1.5.3
187 */
188 struct implementation_id_suffix {
189 public:
190 	implementation_id_suffix(uint8 os_class, uint8 os_identifier);
191 
os_classimplementation_id_suffix192 	uint8 os_class() const { return _os_class; }
os_identifierimplementation_id_suffix193 	uint8 os_identifier() const { return _os_identifier; }
194 
set_os_classimplementation_id_suffix195 	void set_os_class(uint8 os_class) { _os_class = os_class; }
set_os_identifierimplementation_id_suffix196 	void set_os_identifier(uint8 identifier) { _os_identifier = identifier; }
197 private:
198 	uint8 _os_class;
199 	uint8 _os_identifier;
200 	array<uint8, 6> _implementation_use;
201 };
202 
203 /*! \brief Operating system classes for implementation_id_suffixes
204 
205 	See also: Udf 2.50 6.3
206 */
207 enum {
208 	OS_UNDEFINED = 0,
209 	OS_DOS,
210 	OS_OS2,
211 	OS_MACOS,
212 	OS_UNIX,
213 	OS_WIN9X,
214 	OS_WINNT,
215 	OS_OS400,
216 	OS_BEOS,
217 	OS_WINCE
218 };
219 
220 /*! \brief BeOS operating system classes identifiers for implementation_id_suffixes
221 
222 	See also: Udf 2.50 6.3
223 */
224 enum {
225 	BEOS_GENERIC = 0,
226 	BEOS_OPENBEOS = 1	// not part of the standard, but perhaps someday. :-)
227 };
228 
229 /*! \brief Domain ID Identify Suffix
230 
231 	See also: UDF 2.50 2.1.5.3
232 */
233 struct domain_id_suffix {
234 public:
235 	domain_id_suffix(uint16 udfRevision, uint8 domainFlags);
236 
237 	//! Note that revision 2.50 is denoted by 0x0250.
udf_revisiondomain_id_suffix238 	uint16 udf_revision() const { return _udf_revision; }
domain_flagsdomain_id_suffix239 	uint8 domain_flags() const { return _domain_flags; }
240 
set_udf_revisiondomain_id_suffix241 	void set_udf_revision(uint16 revision) { _udf_revision = B_HOST_TO_LENDIAN_INT16(revision); }
set_domain_flagsdomain_id_suffix242 	void set_domain_flags(uint8 flags) { _domain_flags = flags; }
243 private:
244 	uint16 _udf_revision;
245 	uint8 _domain_flags;
246 	array<uint8, 5> _reserved;
247 };
248 
249 /*! \brief Domain flags
250 
251 	See also: UDF 2.50 2.1.5.3
252 */
253 enum {
254 	DF_HARD_WRITE_PROTECT = 0x01,
255 	DF_SOFT_WRITE_PROTECT = 0x02
256 };
257 
258 /*! \brief Identifier used to designate the implementation responsible
259 	for writing associated data structures on the medium.
260 
261 	See also: ECMA 167 1/7.4, UDF 2.01 2.1.5
262 */
263 struct entity_id {
264 public:
265 	static const int kIdentifierLength = 23;
266 	static const int kIdentifierSuffixLength = 8;
267 
268 	entity_id(uint8 flags = 0, const char *identifier = NULL,
269 	          uint8 *identifier_suffix = NULL);
270 	entity_id(uint8 flags, const char *identifier,
271 	          const udf_id_suffix &suffix);
272 	entity_id(uint8 flags, const char *identifier,
273 	          const implementation_id_suffix &suffix);
274 	entity_id(uint8 flags, const char *identifier,
275 	          const domain_id_suffix &suffix);
276 
277 	void dump() const;
278 	bool matches(const entity_id &id) const;
279 
280 	// Get functions
flagsentity_id281 	uint8 flags() const { return _flags; }
identifierentity_id282 	const char* identifier() const { return _identifier; }
identifierentity_id283 	char* identifier() { return _identifier; }
identifier_suffixentity_id284 	const array<uint8, kIdentifierSuffixLength>& identifier_suffix() const { return _identifier_suffix; }
identifier_suffixentity_id285 	array<uint8, kIdentifierSuffixLength>& identifier_suffix() { return _identifier_suffix; }
286 
287 	// Set functions
set_flagsentity_id288 	void set_flags(uint8 flags) { _flags = flags; }
289 private:
290 	uint8 _flags;
291 	char _identifier[kIdentifierLength];
292 	array<uint8, kIdentifierSuffixLength> _identifier_suffix;
293 } __attribute__((packed));
294 
295 extern entity_id kMetadataPartitionMapId;
296 extern entity_id kSparablePartitionMapId;
297 extern entity_id kVirtualPartitionMapId;
298 extern entity_id kImplementationId;
299 extern entity_id kPartitionContentsId1xx;
300 extern entity_id kPartitionContentsId2xx;
301 extern entity_id kUdfId;
302 extern entity_id kLogicalVolumeInfoId150;
303 extern entity_id kLogicalVolumeInfoId201;
304 extern entity_id kDomainId150;
305 extern entity_id kDomainId201;
306 extern void init_entities(void);
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 */
338 struct volume_structure_descriptor_header {
339 public:
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
350 extern const char* kVSDID_BEA;
351 extern const char* kVSDID_TEA;
352 extern const char* kVSDID_BOOT;
353 extern const char* kVSDID_ISO;
354 extern const char* kVSDID_ECMA167_2;
355 extern const char* kVSDID_ECMA167_3;
356 extern 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 */
369 struct extent_address {
370 public:
371 	extent_address(uint32 location = 0, uint32 length = 0);
372 
373 	void dump() const;
374 
lengthextent_address375 	uint32 length() const { return B_LENDIAN_TO_HOST_INT32(_length); }
locationextent_address376 	uint32 location() const { return B_LENDIAN_TO_HOST_INT32(_location); }
377 
set_lengthextent_address378 	void set_length(int32 length) { _length = B_HOST_TO_LENDIAN_INT32(length); }
set_locationextent_address379 	void set_location(int32 location) { _location = B_HOST_TO_LENDIAN_INT32(location); }
380 private:
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 */
390 struct logical_block_address {
391 public:
392 	void dump() const;
393 	logical_block_address(uint16 partition = 0, uint32 block = 0);
394 
blocklogical_block_address395 	uint32 block() const { return B_LENDIAN_TO_HOST_INT32(_block); }
partitionlogical_block_address396 	uint16 partition() const { return B_LENDIAN_TO_HOST_INT16(_partition); }
397 
set_blocklogical_block_address398 	void set_block(uint32 block) { _block = B_HOST_TO_LENDIAN_INT32(block); }
set_partitionlogical_block_address399 	void set_partition(uint16 partition) { _partition = B_HOST_TO_LENDIAN_INT16(partition); }
400 
401 private:
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 */
411 enum 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 */
423 struct short_address {
424 private:
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 
435 public:
436 	void dump() const;
437 
typeshort_address438 	uint8 type() const {
439 		type_and_length_accessor t;
440 		t.type_and_length = type_and_length();
441 		return t.bits.type;
442 	}
lengthshort_address443 	uint32 length() const {
444 		type_and_length_accessor t;
445 		t.type_and_length = type_and_length();
446 		return t.bits.length;
447 	}
blockshort_address448 	uint32 block() const { return B_LENDIAN_TO_HOST_INT32(_block); }
449 
set_typeshort_address450 	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 	}
set_lengthshort_address456 	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 	}
set_blockshort_address462 	void set_block(uint32 block) { _block = B_HOST_TO_LENDIAN_INT32(block); }
463 private:
type_and_lengthshort_address464 	uint32 type_and_length() const { return B_LENDIAN_TO_HOST_INT32(_type_and_length); }
set_type_and_lengthshort_address465 	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 */
476 struct long_address {
477 private:
478 	union type_and_length_accessor {
479 		uint32 type_and_length;
480 		struct {
481 			uint32 length:30,
482 			       type:2;
483 		} bits;
484 	};
485 
486 public:
487 	long_address(uint16 partition = 0, uint32 block = 0, uint32 length = 0,
488 	             uint8 type = 0);
489 
490 	void dump() const;
491 
typelong_address492 	uint8 type() const {
493 		type_and_length_accessor t;
494 		t.type_and_length = type_and_length();
495 		return t.bits.type;
496 	}
lengthlong_address497 	uint32 length() const {
498 		type_and_length_accessor t;
499 		t.type_and_length = type_and_length();
500 		return t.bits.length;
501 	}
502 
blocklong_address503 	uint32 block() const { return _location.block(); }
partitionlong_address504 	uint16 partition() const { return _location.partition(); }
505 
implementation_uselong_address506 	const array<uint8, 6>& implementation_use() const { return _implementation_use; }
implementation_uselong_address507 	array<uint8, 6>& implementation_use() { return _implementation_use; }
508 
flagslong_address509 	uint16 flags() const { return B_LENDIAN_TO_HOST_INT16(_accessor().flags); }
unique_idlong_address510 	uint32 unique_id() const { return B_LENDIAN_TO_HOST_INT32(_accessor().unique_id); }
511 
set_typelong_address512 	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 	}
set_lengthlong_address518 	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 	}
set_blocklong_address524 	void set_block(uint32 block) { _location.set_block(block); }
set_partitionlong_address525 	void set_partition(uint16 partition) { _location.set_partition(partition); }
526 
set_flagslong_address527 	void set_flags(uint16 flags) { _accessor().flags = B_HOST_TO_LENDIAN_INT16(flags); }
set_unique_idlong_address528 	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 
541 private:
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 
_accessorlong_address548 	_implementation_use_accessor& _accessor() { return
549 		*reinterpret_cast<_implementation_use_accessor*>(implementation_use().data); }
_accessorlong_address550 	const _implementation_use_accessor& _accessor() const { return
551 		*reinterpret_cast<const _implementation_use_accessor*>(implementation_use().data); }
552 
type_and_lengthlong_address553 	uint32 type_and_length() const { return B_LENDIAN_TO_HOST_INT32(_type_and_length); }
set_type_and_lengthlong_address554 	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 */
570 struct descriptor_tag {
571 public:
572 	void dump() const;
573 
574 	status_t init_check(uint32 block, bool calculateCrc = true);
575 
iddescriptor_tag576 	uint16 id() const { return B_LENDIAN_TO_HOST_INT16(_id); }
versiondescriptor_tag577 	uint16 version() const { return B_LENDIAN_TO_HOST_INT16(_version); }
checksumdescriptor_tag578 	uint8 checksum() const { return _checksum; }
serial_numberdescriptor_tag579 	uint16 serial_number() const { return B_LENDIAN_TO_HOST_INT16(_serial_number); }
crcdescriptor_tag580 	uint16 crc() const { return B_LENDIAN_TO_HOST_INT16(_crc); }
crc_lengthdescriptor_tag581 	uint16 crc_length() const { return B_LENDIAN_TO_HOST_INT16(_crc_length); }
locationdescriptor_tag582 	uint32 location() const { return B_LENDIAN_TO_HOST_INT32(_location); }
583 
set_iddescriptor_tag584 	void set_id(uint16 id) { _id = B_HOST_TO_LENDIAN_INT16(id); }
set_versiondescriptor_tag585 	void set_version(uint16 version) { _version = B_HOST_TO_LENDIAN_INT16(version); }
set_checksumdescriptor_tag586 	void set_checksum(uint8 checksum) { _checksum = checksum; }
set_serial_numberdescriptor_tag587 	void set_serial_number(uint16 serial_number) { _serial_number = B_HOST_TO_LENDIAN_INT16(serial_number); }
set_crcdescriptor_tag588 	void set_crc(uint16 crc) { _crc = B_HOST_TO_LENDIAN_INT16(crc); }
set_crc_lengthdescriptor_tag589 	void set_crc_length(uint16 crc_length) { _crc_length = B_HOST_TO_LENDIAN_INT16(crc_length); }
set_locationdescriptor_tag590 	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 = 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 	}
630 private:
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 */
659 enum 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 
690 const char *tag_id_to_string(tag_id id);
691 
692 extern const uint16 kCrcTable[256];
693 
694 /*! \brief Primary volume descriptor
695 */
696 struct primary_volume_descriptor {
697 public:
698 	void dump() const;
699 
700 	// Get functions
tagprimary_volume_descriptor701 	const descriptor_tag & tag() const { return _tag; }
tagprimary_volume_descriptor702 	descriptor_tag & tag() { return _tag; }
703 
vds_numberprimary_volume_descriptor704 	uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); }
primary_volume_descriptor_numberprimary_volume_descriptor705 	uint32 primary_volume_descriptor_number() const { return B_LENDIAN_TO_HOST_INT32(_primary_volume_descriptor_number); }
706 
volume_identifierprimary_volume_descriptor707 	const array<char, 32>& volume_identifier() const { return _volume_identifier; }
volume_identifierprimary_volume_descriptor708 	array<char, 32>& volume_identifier() { return _volume_identifier; }
709 
volume_sequence_numberprimary_volume_descriptor710 	uint16 volume_sequence_number() const { return B_LENDIAN_TO_HOST_INT16(_volume_sequence_number); }
max_volume_sequence_numberprimary_volume_descriptor711 	uint16 max_volume_sequence_number() const { return B_LENDIAN_TO_HOST_INT16(_max_volume_sequence_number); }
interchange_levelprimary_volume_descriptor712 	uint16 interchange_level() const { return B_LENDIAN_TO_HOST_INT16(_interchange_level); }
max_interchange_levelprimary_volume_descriptor713 	uint16 max_interchange_level() const { return B_LENDIAN_TO_HOST_INT16(_max_interchange_level); }
character_set_listprimary_volume_descriptor714 	uint32 character_set_list() const { return B_LENDIAN_TO_HOST_INT32(_character_set_list); }
max_character_set_listprimary_volume_descriptor715 	uint32 max_character_set_list() const { return B_LENDIAN_TO_HOST_INT32(_max_character_set_list); }
716 
volume_set_identifierprimary_volume_descriptor717 	const array<char, 128>& volume_set_identifier() const { return _volume_set_identifier; }
volume_set_identifierprimary_volume_descriptor718 	array<char, 128>& volume_set_identifier() { return _volume_set_identifier; }
719 
descriptor_character_setprimary_volume_descriptor720 	const charspec& descriptor_character_set() const { return _descriptor_character_set; }
descriptor_character_setprimary_volume_descriptor721 	charspec& descriptor_character_set() { return _descriptor_character_set; }
722 
explanatory_character_setprimary_volume_descriptor723 	const charspec& explanatory_character_set() const { return _explanatory_character_set; }
explanatory_character_setprimary_volume_descriptor724 	charspec& explanatory_character_set() { return _explanatory_character_set; }
725 
volume_abstractprimary_volume_descriptor726 	const extent_address& volume_abstract() const { return _volume_abstract; }
volume_abstractprimary_volume_descriptor727 	extent_address& volume_abstract() { return _volume_abstract; }
volume_copyright_noticeprimary_volume_descriptor728 	const extent_address& volume_copyright_notice() const { return _volume_copyright_notice; }
volume_copyright_noticeprimary_volume_descriptor729 	extent_address& volume_copyright_notice() { return _volume_copyright_notice; }
730 
application_idprimary_volume_descriptor731 	const entity_id& application_id() const { return _application_id; }
application_idprimary_volume_descriptor732 	entity_id& application_id() { return _application_id; }
733 
recording_date_and_timeprimary_volume_descriptor734 	const timestamp& recording_date_and_time() const { return _recording_date_and_time; }
recording_date_and_timeprimary_volume_descriptor735 	timestamp& recording_date_and_time() { return _recording_date_and_time; }
736 
implementation_idprimary_volume_descriptor737 	const entity_id& implementation_id() const { return _implementation_id; }
implementation_idprimary_volume_descriptor738 	entity_id& implementation_id() { return _implementation_id; }
739 
implementation_useprimary_volume_descriptor740 	const array<uint8, 64>& implementation_use() const { return _implementation_use; }
implementation_useprimary_volume_descriptor741 	array<uint8, 64>& implementation_use() { return _implementation_use; }
742 
predecessor_volume_descriptor_sequence_locationprimary_volume_descriptor743 	uint32 predecessor_volume_descriptor_sequence_location() const
744 	  { return B_LENDIAN_TO_HOST_INT32(_predecessor_volume_descriptor_sequence_location); }
flagsprimary_volume_descriptor745 	uint16 flags() const { return B_LENDIAN_TO_HOST_INT16(_flags); }
746 
reservedprimary_volume_descriptor747 	const array<uint8, 22>& reserved() const { return _reserved; }
reservedprimary_volume_descriptor748 	array<uint8, 22>& reserved() { return _reserved; }
749 
750 	// Set functions
set_vds_numberprimary_volume_descriptor751 	void set_vds_number(uint32 number)
752 	  { _vds_number = B_HOST_TO_LENDIAN_INT32(number); }
set_primary_volume_descriptor_numberprimary_volume_descriptor753 	void set_primary_volume_descriptor_number(uint32 number)
754 	  { _primary_volume_descriptor_number = B_HOST_TO_LENDIAN_INT32(number); }
set_volume_sequence_numberprimary_volume_descriptor755 	void set_volume_sequence_number(uint16 number)
756 	  { _volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); }
set_max_volume_sequence_numberprimary_volume_descriptor757 	void set_max_volume_sequence_number(uint16 number)
758 	  { _max_volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); }
set_interchange_levelprimary_volume_descriptor759 	void set_interchange_level(uint16 level)
760 	  { _interchange_level = B_HOST_TO_LENDIAN_INT16(level); }
set_max_interchange_levelprimary_volume_descriptor761 	void set_max_interchange_level(uint16 level)
762 	  { _max_interchange_level = B_HOST_TO_LENDIAN_INT16(level); }
set_character_set_listprimary_volume_descriptor763 	void set_character_set_list(uint32 list)
764 	  { _character_set_list = B_HOST_TO_LENDIAN_INT32(list); }
set_max_character_set_listprimary_volume_descriptor765 	void set_max_character_set_list(uint32 list)
766 	  { _max_character_set_list = B_HOST_TO_LENDIAN_INT32(list); }
set_predecessor_volume_descriptor_sequence_locationprimary_volume_descriptor767 	void set_predecessor_volume_descriptor_sequence_location(uint32 location)
768 	  { _predecessor_volume_descriptor_sequence_location = B_HOST_TO_LENDIAN_INT32(location); }
set_flagsprimary_volume_descriptor769 	void set_flags(uint16 flags)
770 	  { _flags = B_HOST_TO_LENDIAN_INT16(flags); }
771 
772 private:
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 */
827 struct anchor_volume_descriptor {
828 public:
anchor_volume_descriptoranchor_volume_descriptor829 	anchor_volume_descriptor() { memset(_reserved.data, 0, _reserved.size()); }
830 	void dump() const;
831 
taganchor_volume_descriptor832 	descriptor_tag & tag() { return _tag; }
taganchor_volume_descriptor833 	const descriptor_tag & tag() const { return _tag; }
834 
main_vdsanchor_volume_descriptor835 	extent_address& main_vds() { return _main_vds; }
main_vdsanchor_volume_descriptor836 	const extent_address& main_vds() const { return _main_vds; }
837 
reserve_vdsanchor_volume_descriptor838 	extent_address& reserve_vds() { return _reserve_vds; }
reserve_vdsanchor_volume_descriptor839 	const extent_address& reserve_vds() const { return _reserve_vds; }
840 private:
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 */
854 struct 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 */
867 struct logical_volume_info {
868 public:
869 	void dump() const;
870 
character_setlogical_volume_info871 	charspec& character_set() { return _character_set; }
character_setlogical_volume_info872 	const charspec& character_set() const { return _character_set; }
873 
logical_volume_idlogical_volume_info874 	array<char, 128>& logical_volume_id() { return _logical_volume_id; }
logical_volume_idlogical_volume_info875 	const array<char, 128>& logical_volume_id() const { return _logical_volume_id; }
876 
logical_volume_info_1logical_volume_info877 	array<char, 36>& logical_volume_info_1() { return _logical_volume_info.data[0]; }
logical_volume_info_1logical_volume_info878 	const array<char, 36>& logical_volume_info_1() const { return _logical_volume_info.data[0]; }
879 
logical_volume_info_2logical_volume_info880 	array<char, 36>& logical_volume_info_2() { return _logical_volume_info.data[1]; }
logical_volume_info_2logical_volume_info881 	const array<char, 36>& logical_volume_info_2() const { return _logical_volume_info.data[1]; }
882 
logical_volume_info_3logical_volume_info883 	array<char, 36>& logical_volume_info_3() { return _logical_volume_info.data[2]; }
logical_volume_info_3logical_volume_info884 	const array<char, 36>& logical_volume_info_3() const { return _logical_volume_info.data[2]; }
885 
implementation_idlogical_volume_info886 	entity_id& implementation_id() { return _implementation_id; }
implementation_idlogical_volume_info887 	const entity_id& implementation_id() const { return _implementation_id; }
888 
implementation_uselogical_volume_info889 	array<uint8, 128>& implementation_use() { return _implementation_use; }
implementation_uselogical_volume_info890 	const array<uint8, 128>& implementation_use() const { return _implementation_use; }
891 private:
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 */
903 struct implementation_use_descriptor {
904 public:
905 	void dump() const;
906 
907 	// Get functions
tagimplementation_use_descriptor908 	const descriptor_tag & tag() const { return _tag; }
tagimplementation_use_descriptor909 	descriptor_tag & tag() { return _tag; }
910 
vds_numberimplementation_use_descriptor911 	uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); }
912 
implementation_idimplementation_use_descriptor913 	const entity_id& implementation_id() const { return _implementation_id; }
implementation_idimplementation_use_descriptor914 	entity_id& implementation_id() { return _implementation_id; }
915 
implementation_useimplementation_use_descriptor916 	const array<uint8, 460>& implementation_use() const { return _implementation_use; }
implementation_useimplementation_use_descriptor917 	array<uint8, 460>& implementation_use() { return _implementation_use; }
918 
919 	// Only valid if implementation_id() returns Udf::kLogicalVolumeInfoId.
infoimplementation_use_descriptor920 	logical_volume_info& info() { return *reinterpret_cast<logical_volume_info*>(_implementation_use.data); }
infoimplementation_use_descriptor921 	const logical_volume_info& info() const { return *reinterpret_cast<const logical_volume_info*>(_implementation_use.data); }
922 
923 	// Set functions
set_vds_numberimplementation_use_descriptor924 	void set_vds_number(uint32 number) { _vds_number = B_HOST_TO_LENDIAN_INT32(number); }
925 private:
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 */
936 const uint8 kMaxPartitionDescriptors = 2;
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 */
944 struct partition_descriptor {
945 private:
946 	union partition_flags_accessor {
947 		uint16 partition_flags;
948 		struct {
949 			uint16 allocated:1,
950 			       reserved:15;
951 		} bits;
952 	};
953 
954 public:
955 	void dump() const;
956 
957 	// Get functions
tagpartition_descriptor958 	const descriptor_tag & tag() const { return _tag; }
tagpartition_descriptor959 	descriptor_tag & tag() { return _tag; }
960 
vds_numberpartition_descriptor961 	uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); }
partition_flagspartition_descriptor962 	uint16 partition_flags() const { return B_LENDIAN_TO_HOST_INT16(_partition_flags); }
allocatedpartition_descriptor963 	bool allocated() const {
964 		partition_flags_accessor f;
965 		f.partition_flags = partition_flags();
966 		return f.bits.allocated;
967 	}
partition_numberpartition_descriptor968 	uint16 partition_number() const { return B_LENDIAN_TO_HOST_INT16(_partition_number); }
969 
partition_contentspartition_descriptor970 	const entity_id& partition_contents() const { return _partition_contents; }
partition_contentspartition_descriptor971 	entity_id& partition_contents() { return _partition_contents; }
972 
partition_contents_usepartition_descriptor973 	const array<uint8, 128>& partition_contents_use() const { return _partition_contents_use; }
partition_contents_usepartition_descriptor974 	array<uint8, 128>& partition_contents_use() { return _partition_contents_use; }
975 
access_typepartition_descriptor976 	uint32 access_type() const { return B_LENDIAN_TO_HOST_INT32(_access_type); }
startpartition_descriptor977 	uint32 start() const { return B_LENDIAN_TO_HOST_INT32(_start); }
lengthpartition_descriptor978 	uint32 length() const { return B_LENDIAN_TO_HOST_INT32(_length); }
979 
implementation_idpartition_descriptor980 	const entity_id& implementation_id() const { return _implementation_id; }
implementation_idpartition_descriptor981 	entity_id& implementation_id() { return _implementation_id; }
982 
implementation_usepartition_descriptor983 	const array<uint8, 128>& implementation_use() const { return _implementation_use; }
implementation_usepartition_descriptor984 	array<uint8, 128>& implementation_use() { return _implementation_use; }
985 
reservedpartition_descriptor986 	const array<uint8, 156>& reserved() const { return _reserved; }
reservedpartition_descriptor987 	array<uint8, 156>& reserved() { return _reserved; }
988 
989 	// Set functions
set_vds_numberpartition_descriptor990 	void set_vds_number(uint32 number) { _vds_number = B_HOST_TO_LENDIAN_INT32(number); }
set_partition_flagspartition_descriptor991 	void set_partition_flags(uint16 flags) { _partition_flags = B_HOST_TO_LENDIAN_INT16(flags); }
set_allocatedpartition_descriptor992 	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 	}
set_partition_numberpartition_descriptor998 	void set_partition_number(uint16 number) { _partition_number = B_HOST_TO_LENDIAN_INT16(number); }
set_access_typepartition_descriptor999 	void set_access_type(uint32 type) { _access_type = B_HOST_TO_LENDIAN_INT32(type); }
set_startpartition_descriptor1000 	void set_start(uint32 start) { _start = B_HOST_TO_LENDIAN_INT32(start); }
set_lengthpartition_descriptor1001 	void set_length(uint32 length) { _length = B_HOST_TO_LENDIAN_INT32(length); }
1002 
1003 private:
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 
1031 enum 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 */
1044 struct logical_volume_descriptor {
1045 	void dump() const;
1046 
1047 	// Get functions
taglogical_volume_descriptor1048 	const descriptor_tag & tag() const { return _tag; }
taglogical_volume_descriptor1049 	descriptor_tag & tag() { return _tag; }
1050 
vds_numberlogical_volume_descriptor1051 	uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); }
1052 
character_setlogical_volume_descriptor1053 	const charspec& character_set() const { return _character_set; }
character_setlogical_volume_descriptor1054 	charspec& character_set() { return _character_set; }
1055 
logical_volume_identifierlogical_volume_descriptor1056 	const array<char, 128>& logical_volume_identifier() const { return _logical_volume_identifier; }
logical_volume_identifierlogical_volume_descriptor1057 	array<char, 128>& logical_volume_identifier() { return _logical_volume_identifier; }
1058 
logical_block_sizelogical_volume_descriptor1059 	uint32 logical_block_size() const { return B_LENDIAN_TO_HOST_INT32(_logical_block_size); }
1060 
domain_idlogical_volume_descriptor1061 	const entity_id& domain_id() const { return _domain_id; }
domain_idlogical_volume_descriptor1062 	entity_id& domain_id() { return _domain_id; }
1063 
logical_volume_contents_uselogical_volume_descriptor1064 	const array<uint8, 16>& logical_volume_contents_use() const { return _logical_volume_contents_use; }
logical_volume_contents_uselogical_volume_descriptor1065 	array<uint8, 16>& logical_volume_contents_use() { return _logical_volume_contents_use; }
1066 
file_set_addresslogical_volume_descriptor1067 	const long_address& file_set_address() const { return *reinterpret_cast<const long_address*>(&_logical_volume_contents_use); }
file_set_addresslogical_volume_descriptor1068 	long_address& file_set_address() { return *reinterpret_cast<long_address*>(&_logical_volume_contents_use); }
1069 
map_table_lengthlogical_volume_descriptor1070 	uint32 map_table_length() const { return B_LENDIAN_TO_HOST_INT32(_map_table_length); }
partition_map_countlogical_volume_descriptor1071 	uint32 partition_map_count() const { return B_LENDIAN_TO_HOST_INT32(_partition_map_count); }
1072 
implementation_idlogical_volume_descriptor1073 	const entity_id& implementation_id() const { return _implementation_id; }
implementation_idlogical_volume_descriptor1074 	entity_id& implementation_id() { return _implementation_id; }
1075 
implementation_uselogical_volume_descriptor1076 	const array<uint8, 128>& implementation_use() const { return _implementation_use; }
implementation_uselogical_volume_descriptor1077 	array<uint8, 128>& implementation_use() { return _implementation_use; }
1078 
integrity_sequence_extentlogical_volume_descriptor1079 	const extent_address& integrity_sequence_extent() const { return _integrity_sequence_extent; }
integrity_sequence_extentlogical_volume_descriptor1080 	extent_address& integrity_sequence_extent() { return _integrity_sequence_extent; }
1081 
partition_mapslogical_volume_descriptor1082 	const uint8* partition_maps() const { return _partition_maps; }
partition_mapslogical_volume_descriptor1083 	uint8* partition_maps() { return _partition_maps; }
1084 
1085 	// Set functions
set_vds_numberlogical_volume_descriptor1086 	void set_vds_number(uint32 number) { _vds_number = B_HOST_TO_LENDIAN_INT32(number); }
set_logical_block_sizelogical_volume_descriptor1087 	void set_logical_block_size(uint32 size) { _logical_block_size = B_HOST_TO_LENDIAN_INT32(size); }
1088 
set_map_table_lengthlogical_volume_descriptor1089 	void set_map_table_length(uint32 length) { _map_table_length = B_HOST_TO_LENDIAN_INT32(length); }
set_partition_map_countlogical_volume_descriptor1090 	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 
1095 private:
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
1145 extern const uint32 kLogicalVolumeDescriptorBaseSize;
1146 
1147 /*! \brief (Mostly) common portion of various partition maps
1148 
1149 	See also: ECMA-167 3/10.7.1
1150 */
1151 struct partition_map_header {
1152 public:
typepartition_map_header1153 	uint8 type() const { return _type; }
lengthpartition_map_header1154 	uint8 length() const { return _length; }
map_datapartition_map_header1155 	uint8 *map_data() { return _map_data; }
map_datapartition_map_header1156 	const uint8 *map_data() const { return _map_data; }
1157 
partition_type_idpartition_map_header1158 	entity_id& partition_type_id()
1159 		{ return *reinterpret_cast<entity_id*>(&_map_data[2]); }
partition_type_idpartition_map_header1160 	const entity_id& partition_type_id() const
1161 		{ return *reinterpret_cast<const entity_id*>(&_map_data[2]); }
1162 
set_typepartition_map_header1163 	void set_type(uint8 type) { _type = type; }
set_lengthpartition_map_header1164 	void set_length(uint8 length) { _length = length; }
1165 private:
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 */
1176 struct physical_partition_map {
1177 public:
1178 	void dump();
1179 
typephysical_partition_map1180 	uint8 type() const { return _type; }
lengthphysical_partition_map1181 	uint8 length() const { return _length; }
1182 
volume_sequence_numberphysical_partition_map1183 	uint16 volume_sequence_number() const {
1184 		return B_LENDIAN_TO_HOST_INT16(_volume_sequence_number); }
partition_numberphysical_partition_map1185 	uint16 partition_number() const {
1186 		return B_LENDIAN_TO_HOST_INT16(_partition_number); }
1187 
set_typephysical_partition_map1188 	void set_type(uint8 type) { _type = type; }
set_lengthphysical_partition_map1189 	void set_length(uint8 length) { _length = length; }
set_volume_sequence_numberphysical_partition_map1190 	void set_volume_sequence_number(uint16 number) {
1191 		_volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); }
set_partition_numberphysical_partition_map1192 	void set_partition_number(uint16 number) {
1193 		_partition_number = B_HOST_TO_LENDIAN_INT16(number); }
1194 private:
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 */
1210 struct 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 */
1242 struct sparable_partition_map {
1243 public:
1244 	void dump();
1245 
typesparable_partition_map1246 	uint8 type() const { return _type; }
lengthsparable_partition_map1247 	uint8 length() const { return _length; }
1248 
partition_type_idsparable_partition_map1249 	entity_id& partition_type_id() { return _partition_type_id; }
partition_type_idsparable_partition_map1250 	const entity_id& partition_type_id() const { return _partition_type_id; }
1251 
volume_sequence_numbersparable_partition_map1252 	uint16 volume_sequence_number() const {
1253 		return B_LENDIAN_TO_HOST_INT16(_volume_sequence_number); }
partition_numbersparable_partition_map1254 	uint16 partition_number() const {
1255 		return B_LENDIAN_TO_HOST_INT16(_partition_number); }
packet_lengthsparable_partition_map1256 	uint16 packet_length() const {
1257 		return B_LENDIAN_TO_HOST_INT16(_packet_length); }
sparing_table_countsparable_partition_map1258 	uint8 sparing_table_count() const { return _sparing_table_count; }
sparing_table_sizesparable_partition_map1259 	uint32 sparing_table_size() const {
1260 		return B_LENDIAN_TO_HOST_INT32(_sparing_table_size); }
sparing_table_locationsparable_partition_map1261 	uint32 sparing_table_location(uint8 index) const {
1262 		return B_LENDIAN_TO_HOST_INT32(_sparing_table_locations[index]); }
1263 
1264 
set_typesparable_partition_map1265 	void set_type(uint8 type) { _type = type; }
set_lengthsparable_partition_map1266 	void set_length(uint8 length) { _length = length; }
set_volume_sequence_numbersparable_partition_map1267 	void set_volume_sequence_number(uint16 number) {
1268 		_volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); }
set_partition_numbersparable_partition_map1269 	void set_partition_number(uint16 number) {
1270 		_partition_number = B_HOST_TO_LENDIAN_INT16(number); }
set_packet_lengthsparable_partition_map1271 	void set_packet_length(uint16 length) {
1272 		_packet_length = B_HOST_TO_LENDIAN_INT16(length); }
set_sparing_table_countsparable_partition_map1273 	void set_sparing_table_count(uint8 count) {
1274 		_sparing_table_count = count; }
set_sparing_table_sizesparable_partition_map1275 	void set_sparing_table_size(uint32 size) {
1276 		_sparing_table_size = B_HOST_TO_LENDIAN_INT32(size); }
set_sparing_table_locationsparable_partition_map1277 	void set_sparing_table_location(uint8 index, uint32 location) {
1278 		_sparing_table_locations[index] = B_HOST_TO_LENDIAN_INT32(location); }
1279 private:
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 */
1309 struct metadata_partition_map {
1310 public:
partition_type_idmetadata_partition_map1311 	entity_id& partition_type_id() { return _partition_type_id; }
partition_type_idmetadata_partition_map1312 	const entity_id& partition_type_id() const { return _partition_type_id; }
1313 
volume_sequence_numbermetadata_partition_map1314 	uint16 volume_sequence_number() const {
1315 		return B_LENDIAN_TO_HOST_INT16(_volume_sequence_number); }
set_volume_sequence_numbermetadata_partition_map1316 	void set_volume_sequence_number(uint16 number) {
1317 		_volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); }
1318 
partition_numbermetadata_partition_map1319 	uint16 partition_number() const {
1320 		return B_LENDIAN_TO_HOST_INT16(_partition_number); }
set_partition_numbermetadata_partition_map1321 	void set_partition_number(uint16 number) {
1322 		_partition_number = B_HOST_TO_LENDIAN_INT16(number); }
1323 
metadata_file_locationmetadata_partition_map1324 	uint32 metadata_file_location() const {
1325 		return B_LENDIAN_TO_HOST_INT32(_metadata_file_location); }
set_metadata_file_locationmetadata_partition_map1326 	void set_metadata_file_location(uint32 location) {
1327 		_metadata_file_location = B_HOST_TO_LENDIAN_INT32(location); }
1328 
metadata_mirror_file_locationmetadata_partition_map1329 	uint32 metadata_mirror_file_location() const {
1330 		return B_LENDIAN_TO_HOST_INT32(_metadata_mirror_file_location); }
set_metadata_mirror_file_locationmetadata_partition_map1331 	void set_metadata_mirror_file_location(uint32 location) {
1332 		_metadata_mirror_file_location = B_HOST_TO_LENDIAN_INT32(location); }
1333 
metadata_bitmap_file_locationmetadata_partition_map1334 	uint32 metadata_bitmap_file_location() const {
1335 		return B_LENDIAN_TO_HOST_INT32(_metadata_bitmap_file_location); }
set_metadata_bitmap_file_locationmetadata_partition_map1336 	void set_metadata_bitmap_file_location(uint32 location) {
1337 		_metadata_bitmap_file_location = B_HOST_TO_LENDIAN_INT32(location); }
1338 
allocation_unit_sizemetadata_partition_map1339 	uint32 allocation_unit_size() const {
1340 		return B_LENDIAN_TO_HOST_INT32(_allocation_unit_size); }
set_allocation_unit_sizemetadata_partition_map1341 	void set_allocation_unit_size(uint32 size) {
1342 		_allocation_unit_size = B_HOST_TO_LENDIAN_INT32(size); }
1343 
alignment_unit_sizemetadata_partition_map1344 	uint32 alignment_unit_size() const {
1345 		return B_LENDIAN_TO_HOST_INT32(_alignment_unit_size); }
set_alignment_unit_sizemetadata_partition_map1346 	void set_alignment_unit_size(uint32 size) {
1347 		_alignment_unit_size = B_HOST_TO_LENDIAN_INT32(size); }
1348 
flagsmetadata_partition_map1349 	uint8 flags() const { return _flags; }
set_flagsmetadata_partition_map1350 	void set_flags(uint8 flags) { _flags = flags; }
1351 
1352 private:
1353 	uint8 type;
1354 	uint8 length;
1355 	uint8 reserved1[2];
1356 
1357 	/*! - flags: 0
1358 	    - identifier: "*UDF Metadata Partition"
1359 	    - identifier_suffix: per UDF-2.50 2.1.5
1360 	*/
1361 	entity_id _partition_type_id;
1362 	uint16 _volume_sequence_number;
1363 
1364 	/*! corresponding type 1 or type 2 sparable partition
1365 	    map in same logical volume
1366 	*/
1367 	uint16 _partition_number;
1368 	uint32 _metadata_file_location;
1369 	uint32 _metadata_mirror_file_location;
1370 	uint32 _metadata_bitmap_file_location;
1371 	uint32 _allocation_unit_size;
1372 	uint16 _alignment_unit_size;
1373 	uint8 _flags;
1374 	uint8 reserved2[5];
1375 } __attribute__((packed));
1376 
1377 
1378 /*! \brief Unallocated space descriptor
1379 
1380 	See also: ECMA-167 3/10.8
1381 */
1382 struct unallocated_space_descriptor {
1383 	void dump() const;
1384 
1385 	// Get functions
tagunallocated_space_descriptor1386 	const descriptor_tag & tag() const { return _tag; }
tagunallocated_space_descriptor1387 	descriptor_tag & tag() { return _tag; }
vds_numberunallocated_space_descriptor1388 	uint32 vds_number() const { return B_LENDIAN_TO_HOST_INT32(_vds_number); }
allocation_descriptor_countunallocated_space_descriptor1389 	uint32 allocation_descriptor_count() const { return B_LENDIAN_TO_HOST_INT32(_allocation_descriptor_count); }
allocation_descriptorsunallocated_space_descriptor1390 	extent_address* allocation_descriptors() { return _allocation_descriptors; }
1391 
1392 	// Set functions
set_vds_numberunallocated_space_descriptor1393 	void set_vds_number(uint32 number) { _vds_number = B_HOST_TO_LENDIAN_INT32(number); }
set_allocation_descriptor_countunallocated_space_descriptor1394 	void set_allocation_descriptor_count(uint32 count) { _allocation_descriptor_count = B_HOST_TO_LENDIAN_INT32(count); }
1395 private:
1396 	descriptor_tag  _tag;
1397 	uint32 _vds_number;
1398 	uint32 _allocation_descriptor_count;
1399 	extent_address _allocation_descriptors[0];
1400 } __attribute__((packed));
1401 
1402 
1403 /*! \brief Terminating descriptor
1404 
1405 	See also: ECMA-167 3/10.9
1406 */
1407 struct terminating_descriptor {
terminating_descriptorterminating_descriptor1408 	terminating_descriptor() { memset(_reserved.data, 0, _reserved.size()); }
1409 	void dump() const;
1410 
1411 	// Get functions
tagterminating_descriptor1412 	const descriptor_tag & tag() const { return _tag; }
tagterminating_descriptor1413 	descriptor_tag & tag() { return _tag; }
1414 private:
1415 	descriptor_tag  _tag;
1416 	array<uint8, 496> _reserved;
1417 } __attribute__((packed));
1418 
1419 
1420 /*! \brief Logical volume integrity descriptor
1421 
1422 	See also: ECMA-167 3/10.10, UDF-2.50 2.2.6
1423 */
1424 struct logical_volume_integrity_descriptor {
1425 public:
1426 	static const uint32 minimum_implementation_use_length = 46;
1427 
1428 	void dump() const;
descriptor_sizelogical_volume_integrity_descriptor1429 	uint32 descriptor_size() const { return sizeof(*this)+implementation_use_length()
1430 	                                 + partition_count()*sizeof(uint32)*2; }
1431 
taglogical_volume_integrity_descriptor1432 	descriptor_tag& tag() { return _tag; }
taglogical_volume_integrity_descriptor1433 	const descriptor_tag& tag() const { return _tag; }
1434 
recording_timelogical_volume_integrity_descriptor1435 	timestamp& recording_time() { return _recording_time; }
recording_timelogical_volume_integrity_descriptor1436 	const timestamp& recording_time() const { return _recording_time; }
1437 
integrity_typelogical_volume_integrity_descriptor1438 	uint32 integrity_type() const { return B_LENDIAN_TO_HOST_INT32(_integrity_type); }
1439 
next_integrity_extentlogical_volume_integrity_descriptor1440 	extent_address& next_integrity_extent() { return _next_integrity_extent; }
next_integrity_extentlogical_volume_integrity_descriptor1441 	const extent_address& next_integrity_extent() const { return _next_integrity_extent; }
1442 
logical_volume_contents_uselogical_volume_integrity_descriptor1443 	array<uint8, 32>& logical_volume_contents_use() { return _logical_volume_contents_use; }
logical_volume_contents_uselogical_volume_integrity_descriptor1444 	const array<uint8, 32>& logical_volume_contents_use() const { return _logical_volume_contents_use; }
1445 
1446 	// next_unique_id() field is actually stored in the logical_volume_contents_use()
1447 	// field, per UDF-2.50 3.2.1
next_unique_idlogical_volume_integrity_descriptor1448 	uint64 next_unique_id() const { return B_LENDIAN_TO_HOST_INT64(_next_unique_id()); }
1449 
partition_countlogical_volume_integrity_descriptor1450 	uint32 partition_count() const { return B_LENDIAN_TO_HOST_INT32(_partition_count); }
implementation_use_lengthlogical_volume_integrity_descriptor1451 	uint32 implementation_use_length() const { return B_LENDIAN_TO_HOST_INT32(_implementation_use_length); }
1452 
1453 	/*! \todo double-check the pointer arithmetic here. */
free_space_tablelogical_volume_integrity_descriptor1454 	uint32* free_space_table() { return reinterpret_cast<uint32*>(reinterpret_cast<uint8*>(this)+80); }
free_space_tablelogical_volume_integrity_descriptor1455 	const uint32* free_space_table() const { return reinterpret_cast<const uint32*>(reinterpret_cast<const uint8*>(this)+80); }
size_tablelogical_volume_integrity_descriptor1456 	uint32* size_table() { return reinterpret_cast<uint32*>(reinterpret_cast<uint8*>(free_space_table())+partition_count()*sizeof(uint32)); }
size_tablelogical_volume_integrity_descriptor1457 	const uint32* size_table() const { return reinterpret_cast<const uint32*>(reinterpret_cast<const uint8*>(free_space_table())+partition_count()*sizeof(uint32)); }
implementation_uselogical_volume_integrity_descriptor1458 	uint8* implementation_use() { return reinterpret_cast<uint8*>(reinterpret_cast<uint8*>(size_table())+partition_count()*sizeof(uint32)); }
implementation_uselogical_volume_integrity_descriptor1459 	const uint8* implementation_use() const { return reinterpret_cast<const uint8*>(reinterpret_cast<const uint8*>(size_table())+partition_count()*sizeof(uint32)); }
1460 
1461 	// accessors for fields stored in implementation_use() field per UDF-2.50 2.2.6.4
implementation_idlogical_volume_integrity_descriptor1462 	entity_id& implementation_id() { return _accessor().id; }
implementation_idlogical_volume_integrity_descriptor1463 	const entity_id& implementation_id() const { return _accessor().id; }
file_countlogical_volume_integrity_descriptor1464 	uint32 file_count() const { return B_LENDIAN_TO_HOST_INT32(_accessor().file_count); }
directory_countlogical_volume_integrity_descriptor1465 	uint32 directory_count() const { return B_LENDIAN_TO_HOST_INT32(_accessor().directory_count); }
minimum_udf_read_revisionlogical_volume_integrity_descriptor1466 	uint16 minimum_udf_read_revision() const { return B_LENDIAN_TO_HOST_INT16(_accessor().minimum_udf_read_revision); }
minimum_udf_write_revisionlogical_volume_integrity_descriptor1467 	uint16 minimum_udf_write_revision() const { return B_LENDIAN_TO_HOST_INT16(_accessor().minimum_udf_write_revision); }
maximum_udf_write_revisionlogical_volume_integrity_descriptor1468 	uint16 maximum_udf_write_revision() const { return B_LENDIAN_TO_HOST_INT16(_accessor().maximum_udf_write_revision); }
1469 
1470 	// set functions
set_integrity_typelogical_volume_integrity_descriptor1471 	void set_integrity_type(uint32 type) { _integrity_type = B_HOST_TO_LENDIAN_INT32(type); }
set_next_unique_idlogical_volume_integrity_descriptor1472 	void set_next_unique_id(uint64 id) { _next_unique_id() = B_HOST_TO_LENDIAN_INT64(id); }
set_partition_countlogical_volume_integrity_descriptor1473 	void set_partition_count(uint32 count) { _partition_count = B_HOST_TO_LENDIAN_INT32(count); }
set_implementation_use_lengthlogical_volume_integrity_descriptor1474 	void set_implementation_use_length(uint32 length) { _implementation_use_length = B_HOST_TO_LENDIAN_INT32(length); }
1475 
1476 	// set functions for fields stored in implementation_use() field per UDF-2.50 2.2.6.4
set_file_countlogical_volume_integrity_descriptor1477 	void set_file_count(uint32 count) { _accessor().file_count = B_HOST_TO_LENDIAN_INT32(count); }
set_directory_countlogical_volume_integrity_descriptor1478 	void set_directory_count(uint32 count) { _accessor().directory_count = B_HOST_TO_LENDIAN_INT32(count); }
set_minimum_udf_read_revisionlogical_volume_integrity_descriptor1479 	void set_minimum_udf_read_revision(uint16 revision) { _accessor().minimum_udf_read_revision = B_HOST_TO_LENDIAN_INT16(revision); }
set_minimum_udf_write_revisionlogical_volume_integrity_descriptor1480 	void set_minimum_udf_write_revision(uint16 revision) { _accessor().minimum_udf_write_revision = B_HOST_TO_LENDIAN_INT16(revision); }
set_maximum_udf_write_revisionlogical_volume_integrity_descriptor1481 	void set_maximum_udf_write_revision(uint16 revision) { _accessor().maximum_udf_write_revision = B_HOST_TO_LENDIAN_INT16(revision); }
1482 
1483 private:
1484 	struct _lvid_implementation_use_accessor {
1485 		entity_id id;
1486 		uint32 file_count;
1487 		uint32 directory_count;
1488 		uint16 minimum_udf_read_revision;
1489 		uint16 minimum_udf_write_revision;
1490 		uint16 maximum_udf_write_revision;
1491 	};
1492 
_accessorlogical_volume_integrity_descriptor1493 	_lvid_implementation_use_accessor& _accessor() {
1494 		return *reinterpret_cast<_lvid_implementation_use_accessor*>(implementation_use());
1495 	}
_accessorlogical_volume_integrity_descriptor1496 	const _lvid_implementation_use_accessor& _accessor() const {
1497 		return *reinterpret_cast<const _lvid_implementation_use_accessor*>(implementation_use());
1498 	}
1499 
_next_unique_idlogical_volume_integrity_descriptor1500 	uint64& _next_unique_id() { return *reinterpret_cast<uint64*>(logical_volume_contents_use().data); }
_next_unique_idlogical_volume_integrity_descriptor1501 	const uint64& _next_unique_id() const { return *reinterpret_cast<const uint64*>(logical_volume_contents_use().data); }
1502 
1503 	descriptor_tag  _tag;
1504 	timestamp _recording_time;
1505 	uint32 _integrity_type;
1506 	extent_address _next_integrity_extent;
1507 	array<uint8, 32> _logical_volume_contents_use;
1508 	uint32 _partition_count;
1509 	uint32 _implementation_use_length;
1510 
1511 } __attribute__((packed));
1512 
1513 /*! \brief Logical volume integrity types
1514 */
1515 enum {
1516 	INTEGRITY_OPEN = 0,
1517 	INTEGRITY_CLOSED = 1,
1518 };
1519 
1520 /*! \brief Highest currently supported UDF read revision.
1521 */
1522 #define UDF_MAX_READ_REVISION 0x0250
1523 
1524 //----------------------------------------------------------------------
1525 // ECMA-167 Part 4
1526 //----------------------------------------------------------------------
1527 
1528 
1529 
1530 /*! \brief File set descriptor
1531 
1532 	Contains all the pertinent info about a file set (i.e. a hierarchy of files)
1533 
1534 	According to UDF-2.01, only one file set descriptor shall be recorded,
1535 	except on WORM media, where the following rules apply:
1536 	- Multiple file sets are allowed only on WORM media
1537 	- The default file set shall be the one with highest value \c file_set_number field.
1538 	- Only the default file set may be flagged as writeable. All others shall be
1539 	  flagged as "hard write protect".
1540 	- No writeable file set may reference metadata structures which are referenced
1541 	  (directly or indirectly) by any other file set. Writeable file sets may, however,
1542 	  reference actual file data extents that are also referenced by other file sets.
1543 */
1544 struct file_set_descriptor {
1545 	void dump() const;
1546 
1547 	// Get functions
tagfile_set_descriptor1548 	const descriptor_tag & tag() const { return _tag; }
tagfile_set_descriptor1549 	descriptor_tag & tag() { return _tag; }
1550 
recording_date_and_timefile_set_descriptor1551 	const timestamp& recording_date_and_time() const { return _recording_date_and_time; }
recording_date_and_timefile_set_descriptor1552 	timestamp& recording_date_and_time() { return _recording_date_and_time; }
1553 
interchange_levelfile_set_descriptor1554 	uint16 interchange_level() const { return B_LENDIAN_TO_HOST_INT16(_interchange_level); }
max_interchange_levelfile_set_descriptor1555 	uint16 max_interchange_level() const { return B_LENDIAN_TO_HOST_INT16(_max_interchange_level); }
character_set_listfile_set_descriptor1556 	uint32 character_set_list() const { return B_LENDIAN_TO_HOST_INT32(_character_set_list); }
max_character_set_listfile_set_descriptor1557 	uint32 max_character_set_list() const { return B_LENDIAN_TO_HOST_INT32(_max_character_set_list); }
file_set_numberfile_set_descriptor1558 	uint32 file_set_number() const { return B_LENDIAN_TO_HOST_INT32(_file_set_number); }
file_set_descriptor_numberfile_set_descriptor1559 	uint32 file_set_descriptor_number() const { return B_LENDIAN_TO_HOST_INT32(_file_set_descriptor_number); }
1560 
logical_volume_id_character_setfile_set_descriptor1561 	const charspec& logical_volume_id_character_set() const { return _logical_volume_id_character_set; }
logical_volume_id_character_setfile_set_descriptor1562 	charspec& logical_volume_id_character_set() { return _logical_volume_id_character_set; }
1563 
logical_volume_idfile_set_descriptor1564 	const array<char, 128>& logical_volume_id() const { return _logical_volume_id; }
logical_volume_idfile_set_descriptor1565 	array<char, 128>& logical_volume_id() { return _logical_volume_id; }
1566 
file_set_id_character_setfile_set_descriptor1567 	const charspec& file_set_id_character_set() const { return _file_set_id_character_set; }
file_set_id_character_setfile_set_descriptor1568 	charspec& file_set_id_character_set() { return _file_set_id_character_set; }
1569 
file_set_idfile_set_descriptor1570 	const array<char, 32>& file_set_id() const { return _file_set_id; }
file_set_idfile_set_descriptor1571 	array<char, 32>& file_set_id() { return _file_set_id; }
1572 
copyright_file_idfile_set_descriptor1573 	const array<char, 32>& copyright_file_id() const { return _copyright_file_id; }
copyright_file_idfile_set_descriptor1574 	array<char, 32>& copyright_file_id() { return _copyright_file_id; }
1575 
abstract_file_idfile_set_descriptor1576 	const array<char, 32>& abstract_file_id() const { return _abstract_file_id; }
abstract_file_idfile_set_descriptor1577 	array<char, 32>& abstract_file_id() { return _abstract_file_id; }
1578 
root_directory_icbfile_set_descriptor1579 	const long_address& root_directory_icb() const { return _root_directory_icb; }
root_directory_icbfile_set_descriptor1580 	long_address& root_directory_icb() { return _root_directory_icb; }
1581 
domain_idfile_set_descriptor1582 	const entity_id& domain_id() const { return _domain_id; }
domain_idfile_set_descriptor1583 	entity_id& domain_id() { return _domain_id; }
1584 
next_extentfile_set_descriptor1585 	const long_address& next_extent() const { return _next_extent; }
next_extentfile_set_descriptor1586 	long_address& next_extent() { return _next_extent; }
1587 
system_stream_directory_icbfile_set_descriptor1588 	const long_address& system_stream_directory_icb() const { return _system_stream_directory_icb; }
system_stream_directory_icbfile_set_descriptor1589 	long_address& system_stream_directory_icb() { return _system_stream_directory_icb; }
1590 
reservedfile_set_descriptor1591 	const array<uint8, 32>& reserved() const { return _reserved; }
reservedfile_set_descriptor1592 	array<uint8, 32>& reserved() { return _reserved; }
1593 
1594 	// Set functions
set_interchange_levelfile_set_descriptor1595 	void set_interchange_level(uint16 level) { _interchange_level = B_HOST_TO_LENDIAN_INT16(level); }
set_max_interchange_levelfile_set_descriptor1596 	void set_max_interchange_level(uint16 level) { _max_interchange_level = B_HOST_TO_LENDIAN_INT16(level); }
set_character_set_listfile_set_descriptor1597 	void set_character_set_list(uint32 list) { _character_set_list = B_HOST_TO_LENDIAN_INT32(list); }
set_max_character_set_listfile_set_descriptor1598 	void set_max_character_set_list(uint32 list) { _max_character_set_list = B_HOST_TO_LENDIAN_INT32(list); }
set_file_set_numberfile_set_descriptor1599 	void set_file_set_number(uint32 number) { _file_set_number = B_HOST_TO_LENDIAN_INT32(number); }
set_file_set_descriptor_numberfile_set_descriptor1600 	void set_file_set_descriptor_number(uint32 number) { _file_set_descriptor_number = B_HOST_TO_LENDIAN_INT32(number); }
1601 private:
1602 	descriptor_tag  _tag;
1603 	timestamp _recording_date_and_time;
1604 	uint16 _interchange_level;			//!< To be set to 3 (see UDF-2.01 2.3.2.1)
1605 	uint16 _max_interchange_level;		//!< To be set to 3 (see UDF-2.01 2.3.2.2)
1606 	uint32 _character_set_list;
1607 	uint32 _max_character_set_list;
1608 	uint32 _file_set_number;
1609 	uint32 _file_set_descriptor_number;
1610 	charspec _logical_volume_id_character_set;	//!< To be set to kCSOCharspec
1611 	array<char, 128> _logical_volume_id;
1612 	charspec _file_set_id_character_set;
1613 	array<char, 32> _file_set_id;
1614 	array<char, 32> _copyright_file_id;
1615 	array<char, 32> _abstract_file_id;
1616 	long_address _root_directory_icb;
1617 	entity_id _domain_id;
1618 	long_address _next_extent;
1619 	long_address _system_stream_directory_icb;
1620 	array<uint8, 32> _reserved;
1621 } __attribute__((packed));
1622 
1623 
1624 /*! \brief Partition header descriptor
1625 
1626 	Contains references to unallocated and freed space data structures.
1627 
1628 	Note that unallocated space is space ready to be written with no
1629 	preprocessing. Freed space is space needing preprocessing (i.e.
1630 	a special write pass) before use.
1631 
1632 	Per UDF-2.01 2.3.3, the use of tables or bitmaps shall be consistent,
1633 	i.e. only one type or the other shall be used, not both.
1634 
1635 	To indicate disuse of a certain field, the fields of the allocation
1636 	descriptor shall all be set to 0.
1637 
1638 	See also: ECMA-167 4/14.3, UDF-2.01 2.2.3
1639 */
1640 struct partition_header_descriptor {
1641 	long_address unallocated_space_table;
1642 	long_address unallocated_space_bitmap;
1643 	/*! Unused, per UDF-2.01 2.2.3 */
1644 	long_address partition_integrity_table;
1645 	long_address freed_space_table;
1646 	long_address freed_space_bitmap;
1647 	uint8 reserved[88];
1648 } __attribute__((packed));
1649 
1650 #define kMaxFileIdSize (sizeof(file_id_descriptor)+512+3)
1651 
1652 /*! \brief File identifier descriptor
1653 
1654 	Identifies the name of a file entry, and the location of its corresponding
1655 	ICB.
1656 
1657 	See also: ECMA-167 4/14.4, UDF-2.01 2.3.4
1658 
1659 	\todo Check pointer arithmetic
1660 */
1661 struct file_id_descriptor {
1662 public:
descriptor_sizefile_id_descriptor1663 	uint32 descriptor_size() const { return total_length(); }
1664 	void dump() const;
1665 
tagfile_id_descriptor1666 	descriptor_tag & tag() { return _tag; }
tagfile_id_descriptor1667 	const descriptor_tag & tag() const { return _tag; }
1668 
version_numberfile_id_descriptor1669 	uint16 version_number() const { return B_LENDIAN_TO_HOST_INT16(_version_number); }
1670 
characteristicsfile_id_descriptor1671 	uint8 characteristics() const { return _characteristics; }
1672 
may_be_hiddenfile_id_descriptor1673 	bool may_be_hidden() const {
1674 		characteristics_accessor c;
1675 		c.all = characteristics();
1676 		return c.bits.may_be_hidden;
1677 	}
1678 
is_directoryfile_id_descriptor1679 	bool is_directory() const {
1680 		characteristics_accessor c;
1681 		c.all = characteristics();
1682 		return c.bits.is_directory;
1683 	}
1684 
is_deletedfile_id_descriptor1685 	bool is_deleted() const {
1686 		characteristics_accessor c;
1687 		c.all = characteristics();
1688 		return c.bits.is_deleted;
1689 	}
1690 
is_parentfile_id_descriptor1691 	bool is_parent() const {
1692 		characteristics_accessor c;
1693 		c.all = characteristics();
1694 		return c.bits.is_parent;
1695 	}
1696 
is_metadata_streamfile_id_descriptor1697 	bool is_metadata_stream() const {
1698 		characteristics_accessor c;
1699 		c.all = characteristics();
1700 		return c.bits.is_metadata_stream;
1701 	}
1702 
id_lengthfile_id_descriptor1703 	uint8 id_length() const { return _id_length; }
1704 
icbfile_id_descriptor1705 	long_address& icb() { return _icb; }
icbfile_id_descriptor1706 	const long_address& icb() const { return _icb; }
1707 
implementation_use_lengthfile_id_descriptor1708 	uint16 implementation_use_length() const { return B_LENDIAN_TO_HOST_INT16(_implementation_use_length); }
1709 
1710 	/*! If implementation_use_length is greater than 0, the first 32
1711 		bytes of implementation_use() shall be an entity_id identifying
1712 		the implementation that generated the rest of the data in the
1713 		implementation_use() field.
1714 	*/
implementation_usefile_id_descriptor1715 	uint8* implementation_use() { return ((uint8*)this)+(38); }
idfile_id_descriptor1716 	char* id() { return ((char*)this)+(38)+implementation_use_length(); }
idfile_id_descriptor1717 	const char* id() const { return ((const char*)this)+(38)+implementation_use_length(); }
1718 
structure_lengthfile_id_descriptor1719 	uint16 structure_length() const { return (38) + id_length() + implementation_use_length(); }
padding_lengthfile_id_descriptor1720 	uint16 padding_length() const { return ((structure_length()+3)/4)*4 - structure_length(); }
total_lengthfile_id_descriptor1721 	uint16 total_length() const { return structure_length() + padding_length(); }
1722 
1723 	// Set functions
set_version_numberfile_id_descriptor1724 	void set_version_number(uint16 number) { _version_number = B_HOST_TO_LENDIAN_INT16(number); }
1725 
set_characteristicsfile_id_descriptor1726 	void set_characteristics(uint8 characteristics) { _characteristics = characteristics; }
1727 
set_may_be_hiddenfile_id_descriptor1728 	void set_may_be_hidden(bool how) {
1729 		characteristics_accessor c;
1730 		c.all = characteristics();
1731 		c.bits.may_be_hidden = how;
1732 		set_characteristics(c.all);
1733 	}
1734 
set_is_directoryfile_id_descriptor1735 	void set_is_directory(bool how) {
1736 		characteristics_accessor c;
1737 		c.all = characteristics();
1738 		c.bits.is_directory = how;
1739 		set_characteristics(c.all);
1740 	}
1741 
set_is_deletedfile_id_descriptor1742 	void set_is_deleted(bool how) {
1743 		characteristics_accessor c;
1744 		c.all = characteristics();
1745 		c.bits.is_deleted = how;
1746 		set_characteristics(c.all);
1747 	}
1748 
set_is_parentfile_id_descriptor1749 	void set_is_parent(bool how) {
1750 		characteristics_accessor c;
1751 		c.all = characteristics();
1752 		c.bits.is_parent = how;
1753 		set_characteristics(c.all);
1754 	}
1755 
set_is_metadata_streamfile_id_descriptor1756 	void set_is_metadata_stream(bool how) {
1757 		characteristics_accessor c;
1758 		c.all = characteristics();
1759 		c.bits.is_metadata_stream = how;
1760 		set_characteristics(c.all);
1761 	}
1762 
1763 
set_id_lengthfile_id_descriptor1764 	void set_id_length(uint8 id_length) { _id_length = id_length; }
set_implementation_use_lengthfile_id_descriptor1765 	void set_implementation_use_length(uint16 implementation_use_length) { _implementation_use_length = B_HOST_TO_LENDIAN_INT16(implementation_use_length); }
1766 
1767 
1768 
1769 private:
1770 	union characteristics_accessor {
1771 		uint8 all;
1772 		struct {
1773 			uint8	may_be_hidden:1,
1774 					is_directory:1,
1775 					is_deleted:1,
1776 					is_parent:1,
1777 					is_metadata_stream:1,
1778 					reserved_characteristics:3;
1779 		} bits;
1780 	};
1781 
1782 	descriptor_tag  _tag;
1783 	/*! According to ECMA-167: 1 <= valid version_number <= 32767, 32768 <= reserved <= 65535.
1784 
1785 		However, according to UDF-2.01, there shall be exactly one version of
1786 		a file, and it shall be 1.
1787 	 */
1788 	uint16 _version_number;
1789 	/*! \todo Check UDF-2.01 2.3.4.2 for some more restrictions. */
1790 	uint8 _characteristics;
1791 	uint8 _id_length;
1792 	long_address _icb;
1793 	uint16 _implementation_use_length;
1794 } __attribute__((packed));
1795 
1796 
1797 /*! \brief Allocation extent descriptor
1798 
1799 	See also: ECMA-167 4/14.5
1800 */
1801 struct allocation_extent_descriptor {
1802 	descriptor_tag  tag;
1803 	uint32 previous_allocation_extent_location;
1804 	uint32 length_of_allocation_descriptors;
1805 
1806 	/*! \todo Check that this is really how things work: */
allocation_descriptorsallocation_extent_descriptor1807 	uint8* allocation_descriptors() { return (uint8*)(reinterpret_cast<uint8*>(this)+sizeof(allocation_extent_descriptor)); }
1808 } __attribute__((packed));
1809 
1810 
1811 /*! \brief icb_tag::file_type values
1812 
1813 	See also ECMA-167 4/14.6.6
1814 */
1815 enum icb_file_types {
1816 	ICB_TYPE_UNSPECIFIED = 0,
1817 	ICB_TYPE_UNALLOCATED_SPACE_ENTRY,
1818 	ICB_TYPE_PARTITION_INTEGRITY_ENTRY,
1819 	ICB_TYPE_INDIRECT_ENTRY,
1820 	ICB_TYPE_DIRECTORY,
1821 	ICB_TYPE_REGULAR_FILE,
1822 	ICB_TYPE_BLOCK_SPECIAL_DEVICE,
1823 	ICB_TYPE_CHARACTER_SPECIAL_DEVICE,
1824 	ICB_TYPE_EXTENDED_ATTRIBUTES_FILE,
1825 	ICB_TYPE_FIFO,
1826 	ICB_TYPE_ISSOCK,
1827 	ICB_TYPE_TERMINAL,
1828 	ICB_TYPE_SYMLINK,
1829 	ICB_TYPE_STREAM_DIRECTORY,
1830 
1831 	ICB_TYPE_RESERVED_START = 14,
1832 	ICB_TYPE_RESERVED_END = 247,
1833 
1834 	ICB_TYPE_CUSTOM_START = 248,
1835 	ICB_TYPE_CUSTOM_END = 255,
1836 };
1837 
1838 /*!	\brief idb_entry_tag::_flags::descriptor_flags() values
1839 
1840 	See also ECMA-167 4/14.6.8
1841 */
1842 enum icb_descriptor_types {
1843 	ICB_DESCRIPTOR_TYPE_SHORT = 0,
1844 	ICB_DESCRIPTOR_TYPE_LONG,
1845 	ICB_DESCRIPTOR_TYPE_EXTENDED,
1846 	ICB_DESCRIPTOR_TYPE_EMBEDDED,
1847 };
1848 
1849 /*!	\brief idb_entry_tag::strategy_type() values
1850 
1851 	See also UDF-2.50 2.3.5.1
1852 */
1853 enum icb_strategy_types {
1854 	ICB_STRATEGY_SINGLE = 4,
1855 	ICB_STRATEGY_LINKED_LIST = 4096
1856 };
1857 
1858 /*! \brief ICB entry tag
1859 
1860 	Common tag found in all ICB entries (in addition to, and immediately following,
1861 	the descriptor tag).
1862 
1863 	See also: ECMA-167 4/14.6, UDF-2.01 2.3.5
1864 */
1865 struct icb_entry_tag {
1866 public:
1867 	union flags_accessor {
1868 		uint16 all_flags;
1869 		struct {
1870 			uint16	descriptor_flags:3,
1871 					if_directory_then_sort:1,	//!< To be set to 0 per UDF-2.01 2.3.5.4
1872 					non_relocatable:1,
1873 					archive:1,
1874 					setuid:1,
1875 					setgid:1,
1876 					sticky:1,
1877 					contiguous:1,
1878 					system:1,
1879 					transformed:1,
1880 					multi_version:1,			//!< To be set to 0 per UDF-2.01 2.3.5.4
1881 					is_stream:1,
1882 					reserved_icb_entry_flags:2;
1883 		} flags;
1884 	};
1885 
1886 public:
1887 	void dump() const;
1888 
prior_recorded_number_of_direct_entriesicb_entry_tag1889 	uint32 prior_recorded_number_of_direct_entries() const { return B_LENDIAN_TO_HOST_INT32(_prior_recorded_number_of_direct_entries); }
strategy_typeicb_entry_tag1890 	uint16 strategy_type() const { return B_LENDIAN_TO_HOST_INT16(_strategy_type); }
1891 
strategy_parametersicb_entry_tag1892 	array<uint8, 2>& strategy_parameters() { return _strategy_parameters; }
strategy_parametersicb_entry_tag1893 	const array<uint8, 2>& strategy_parameters() const { return _strategy_parameters; }
1894 
entry_counticb_entry_tag1895 	uint16 entry_count() const { return B_LENDIAN_TO_HOST_INT16(_entry_count); }
reservedicb_entry_tag1896 	uint8& reserved() { return _reserved; }
file_typeicb_entry_tag1897 	uint8 file_type() const { return _file_type; }
parent_icb_locationicb_entry_tag1898 	logical_block_address& parent_icb_location() { return _parent_icb_location; }
parent_icb_locationicb_entry_tag1899 	const logical_block_address& parent_icb_location() const { return _parent_icb_location; }
1900 
flagsicb_entry_tag1901 	uint16 flags() const { return B_LENDIAN_TO_HOST_INT16(_flags); }
flags_accessicb_entry_tag1902 	flags_accessor& flags_access() { return *reinterpret_cast<flags_accessor*>(&_flags); }
1903 
1904 	// flags accessor functions
descriptor_flagsicb_entry_tag1905 	uint8 descriptor_flags() const {
1906 		flags_accessor f;
1907 		f.all_flags = flags();
1908 		return f.flags.descriptor_flags;
1909 	}
1910 /*	void set_descriptor_flags(uint8 value) {
1911 		flags_accessor f;
1912 		f.all_flags = flags();
1913 		f.flags.descriptor_flags = value;
1914 		set_flags
1915 */
1916 
set_prior_recorded_number_of_direct_entriesicb_entry_tag1917 	void set_prior_recorded_number_of_direct_entries(uint32 entries) { _prior_recorded_number_of_direct_entries = B_LENDIAN_TO_HOST_INT32(entries); }
set_strategy_typeicb_entry_tag1918 	void set_strategy_type(uint16 type) { _strategy_type = B_HOST_TO_LENDIAN_INT16(type); }
1919 
set_entry_counticb_entry_tag1920 	void set_entry_count(uint16 count) { _entry_count = B_LENDIAN_TO_HOST_INT16(count); }
set_file_typeicb_entry_tag1921 	void set_file_type(uint8 type) { _file_type = type; }
1922 
set_flagsicb_entry_tag1923 	void set_flags(uint16 flags) { _flags = B_LENDIAN_TO_HOST_INT16(flags); }
1924 
1925 private:
1926 	uint32 _prior_recorded_number_of_direct_entries;
1927 	/*! Per UDF-2.01 2.3.5.1, only strategy types 4 and 4096 shall be supported.
1928 
1929 		\todo Describe strategy types here.
1930 	*/
1931 	uint16 _strategy_type;
1932 	array<uint8, 2> _strategy_parameters;
1933 	uint16 _entry_count;
1934 	uint8 _reserved;
1935 	/*! \brief icb_file_type value identifying the type of this icb entry */
1936 	uint8 _file_type;
1937 	logical_block_address _parent_icb_location;
1938 	uint16 _flags;
1939 } __attribute__((packed));
1940 
1941 /*! \brief Header portion of an ICB entry.
1942 */
1943 struct icb_header {
1944 public:
1945 	void dump() const;
1946 
tagicb_header1947 	descriptor_tag  &tag() { return _tag; }
tagicb_header1948 	const descriptor_tag  &tag() const { return _tag; }
1949 
icb_tagicb_header1950 	icb_entry_tag &icb_tag() { return _icb_tag; }
icb_tagicb_header1951 	const icb_entry_tag &icb_tag() const { return _icb_tag; }
1952 private:
1953 	descriptor_tag  _tag;
1954 	icb_entry_tag _icb_tag;
1955 };
1956 
1957 /*! \brief Indirect ICB entry
1958 */
1959 struct indirect_icb_entry {
1960 	descriptor_tag  tag;
1961 	icb_entry_tag icb_tag;
1962 	long_address indirect_icb;
1963 } __attribute__((packed));
1964 
1965 
1966 /*! \brief Terminal ICB entry
1967 */
1968 struct terminal_icb_entry {
1969 	descriptor_tag  tag;
1970 	icb_entry_tag icb_tag;
1971 } __attribute__((packed));
1972 
1973 enum permissions {
1974 	OTHER_EXECUTE	 	= 0x0001,
1975 	OTHER_WRITE			= 0x0002,
1976 	OTHER_READ			= 0x0004,
1977 	OTHER_ATTRIBUTES	= 0x0008,
1978 	OTHER_DELETE		= 0x0010,
1979 	GROUP_EXECUTE	 	= 0x0020,
1980 	GROUP_WRITE			= 0x0040,
1981 	GROUP_READ			= 0x0080,
1982 	GROUP_ATTRIBUTES	= 0x0100,
1983 	GROUP_DELETE		= 0x0200,
1984 	USER_EXECUTE	 	= 0x0400,
1985 	USER_WRITE			= 0x0800,
1986 	USER_READ			= 0x1000,
1987 	USER_ATTRIBUTES		= 0x2000,
1988 	USER_DELETE			= 0x4000,
1989 };
1990 
1991 /*! \brief File ICB entry
1992 
1993 	See also: ECMA-167 4/14.9
1994 
1995 	\todo Check pointer math.
1996 */
1997 struct file_icb_entry {
1998 	void dump() const;
descriptor_sizefile_icb_entry1999 	uint32 descriptor_size() const { return sizeof(*this)+extended_attributes_length()
2000 	                                 +allocation_descriptors_length(); }
descriptor_namefile_icb_entry2001 	const char* descriptor_name() const { return "file_icb_entry"; }
2002 
2003 	// get functions
tagfile_icb_entry2004 	descriptor_tag & tag() { return _tag; }
tagfile_icb_entry2005 	const descriptor_tag & tag() const { return _tag; }
2006 
icb_tagfile_icb_entry2007 	icb_entry_tag& icb_tag() { return _icb_tag; }
icb_tagfile_icb_entry2008 	const icb_entry_tag& icb_tag() const { return _icb_tag; }
2009 
uidfile_icb_entry2010 	uint32 uid() const { return B_LENDIAN_TO_HOST_INT32(_uid); }
gidfile_icb_entry2011 	uint32 gid() const { return B_LENDIAN_TO_HOST_INT32(_gid); }
permissionsfile_icb_entry2012 	uint32 permissions() const { return B_LENDIAN_TO_HOST_INT32(_permissions); }
file_link_countfile_icb_entry2013 	uint16 file_link_count() const { return B_LENDIAN_TO_HOST_INT16(_file_link_count); }
record_formatfile_icb_entry2014 	uint8 record_format() const { return _record_format; }
record_display_attributesfile_icb_entry2015 	uint8 record_display_attributes() const { return _record_display_attributes; }
record_lengthfile_icb_entry2016 	uint8 record_length() const { return _record_length; }
information_lengthfile_icb_entry2017 	uint64 information_length() const { return B_LENDIAN_TO_HOST_INT64(_information_length); }
logical_blocks_recordedfile_icb_entry2018 	uint64 logical_blocks_recorded() const { return B_LENDIAN_TO_HOST_INT64(_logical_blocks_recorded); }
2019 
access_date_and_timefile_icb_entry2020 	timestamp& access_date_and_time() { return _access_date_and_time; }
access_date_and_timefile_icb_entry2021 	const timestamp& access_date_and_time() const { return _access_date_and_time; }
2022 
modification_date_and_timefile_icb_entry2023 	timestamp& modification_date_and_time() { return _modification_date_and_time; }
modification_date_and_timefile_icb_entry2024 	const timestamp& modification_date_and_time() const { return _modification_date_and_time; }
2025 
attribute_date_and_timefile_icb_entry2026 	timestamp& attribute_date_and_time() { return _attribute_date_and_time; }
attribute_date_and_timefile_icb_entry2027 	const timestamp& attribute_date_and_time() const { return _attribute_date_and_time; }
2028 
checkpointfile_icb_entry2029 	uint32 checkpoint() const { return B_LENDIAN_TO_HOST_INT32(_checkpoint); }
2030 
extended_attribute_icbfile_icb_entry2031 	long_address& extended_attribute_icb() { return _extended_attribute_icb; }
extended_attribute_icbfile_icb_entry2032 	const long_address& extended_attribute_icb() const { return _extended_attribute_icb; }
2033 
implementation_idfile_icb_entry2034 	entity_id& implementation_id() { return _implementation_id; }
implementation_idfile_icb_entry2035 	const entity_id& implementation_id() const { return _implementation_id; }
2036 
unique_idfile_icb_entry2037 	uint64 unique_id() const { return B_LENDIAN_TO_HOST_INT64(_unique_id); }
extended_attributes_lengthfile_icb_entry2038 	uint32 extended_attributes_length() const { return B_LENDIAN_TO_HOST_INT32(_extended_attributes_length); }
allocation_descriptors_lengthfile_icb_entry2039 	uint32 allocation_descriptors_length() const { return B_LENDIAN_TO_HOST_INT32(_allocation_descriptors_length); }
2040 
extended_attributesfile_icb_entry2041 	uint8* extended_attributes() { return _end(); }
extended_attributesfile_icb_entry2042 	const uint8* extended_attributes() const { return _end(); }
allocation_descriptorsfile_icb_entry2043 	uint8* allocation_descriptors() { return _end()+extended_attributes_length(); }
allocation_descriptorsfile_icb_entry2044 	const uint8* allocation_descriptors() const { return _end()+extended_attributes_length(); }
2045 
2046 	// set functions
set_uidfile_icb_entry2047 	void set_uid(uint32 uid) { _uid = B_HOST_TO_LENDIAN_INT32(uid); }
set_gidfile_icb_entry2048 	void set_gid(uint32 gid) { _gid = B_HOST_TO_LENDIAN_INT32(gid); }
set_permissionsfile_icb_entry2049 	void set_permissions(uint32 permissions) { _permissions = B_HOST_TO_LENDIAN_INT32(permissions); }
2050 
set_file_link_countfile_icb_entry2051 	void set_file_link_count(uint16 count) { _file_link_count = B_HOST_TO_LENDIAN_INT16(count); }
set_record_formatfile_icb_entry2052 	void set_record_format(uint8 format) { _record_format = format; }
set_record_display_attributesfile_icb_entry2053 	void set_record_display_attributes(uint8 attributes) { _record_display_attributes = attributes; }
set_record_lengthfile_icb_entry2054 	void set_record_length(uint8 length) { _record_length = length; }
2055 
set_information_lengthfile_icb_entry2056 	void set_information_length(uint64 length) { _information_length = B_HOST_TO_LENDIAN_INT64(length); }
set_logical_blocks_recordedfile_icb_entry2057 	void set_logical_blocks_recorded(uint64 blocks) { _logical_blocks_recorded = B_HOST_TO_LENDIAN_INT64(blocks); }
2058 
set_checkpointfile_icb_entry2059 	void set_checkpoint(uint32 checkpoint) { _checkpoint = B_HOST_TO_LENDIAN_INT32(checkpoint); }
2060 
set_unique_idfile_icb_entry2061 	void set_unique_id(uint64 id) { _unique_id = B_HOST_TO_LENDIAN_INT64(id); }
2062 
set_extended_attributes_lengthfile_icb_entry2063 	void set_extended_attributes_length(uint32 length) { _extended_attributes_length = B_HOST_TO_LENDIAN_INT32(length); }
set_allocation_descriptors_lengthfile_icb_entry2064 	void set_allocation_descriptors_length(uint32 length) { _allocation_descriptors_length = B_HOST_TO_LENDIAN_INT32(length); }
2065 
2066 	// extended_file_icb_entry compatability functions
creation_date_and_timefile_icb_entry2067 	timestamp& creation_date_and_time() { return _attribute_date_and_time; }
creation_date_and_timefile_icb_entry2068 	const timestamp& creation_date_and_time() const { return _attribute_date_and_time; }
2069 
2070 
set_object_sizefile_icb_entry2071 	void set_object_size(uint64 size) { }
set_reservedfile_icb_entry2072 	void set_reserved(uint32 reserved) { }
stream_directory_icbfile_icb_entry2073 	long_address& stream_directory_icb() { return _dummy_stream_directory_icb; }
stream_directory_icbfile_icb_entry2074 	const long_address& stream_directory_icb() const { return _dummy_stream_directory_icb; }
2075 
2076 
2077 private:
2078 	static const uint32 _descriptor_length = 176;
2079 	static long_address _dummy_stream_directory_icb;
_endfile_icb_entry2080 	uint8* _end() { return reinterpret_cast<uint8*>(this)+_descriptor_length; }
_endfile_icb_entry2081 	const uint8* _end() const { return reinterpret_cast<const uint8*>(this)+_descriptor_length; }
2082 
2083 	descriptor_tag  _tag;
2084 	icb_entry_tag _icb_tag;
2085 	uint32 _uid;
2086 	uint32 _gid;
2087 	/*! \todo List perms in comment and add handy union thingy */
2088 	uint32 _permissions;
2089 	/*! Identifies the number of file identifier descriptors referencing
2090 		this icb.
2091 	*/
2092 	uint16 _file_link_count;
2093 	uint8 _record_format;				//!< To be set to 0 per UDF-2.01 2.3.6.1
2094 	uint8 _record_display_attributes;	//!< To be set to 0 per UDF-2.01 2.3.6.2
2095 	uint8 _record_length;				//!< To be set to 0 per UDF-2.01 2.3.6.3
2096 	uint64 _information_length;
2097 	uint64 _logical_blocks_recorded;		//!< To be 0 for files and dirs with embedded data
2098 	timestamp _access_date_and_time;
2099 	timestamp _modification_date_and_time;
2100 
2101 	// NOTE: data members following this point in the descriptor are in
2102 	// different locations in extended file entries
2103 
2104 	timestamp _attribute_date_and_time;
2105 	/*! \brief Initially 1, may be incremented upon user request. */
2106 	uint32 _checkpoint;
2107 	long_address _extended_attribute_icb;
2108 	entity_id _implementation_id;
2109 	/*! \brief The unique id identifying this file entry
2110 
2111 		The id of the root directory of a file set shall be 0.
2112 
2113 		\todo Detail the system specific requirements for unique ids from UDF-2.01
2114 	*/
2115 	uint64 _unique_id;
2116 	uint32 _extended_attributes_length;
2117 	uint32 _allocation_descriptors_length;
2118 
2119 };
2120 
2121 
2122 /*! \brief Extended file ICB entry
2123 
2124 	See also: ECMA-167 4/14.17
2125 
2126 	\todo Check pointer math.
2127 */
2128 struct extended_file_icb_entry {
2129 	void dump() const;
descriptor_sizeextended_file_icb_entry2130 	uint32 descriptor_size() const { return sizeof(*this)+extended_attributes_length()
2131 	                                 +allocation_descriptors_length(); }
descriptor_nameextended_file_icb_entry2132 	const char* descriptor_name() const { return "extended_file_icb_entry"; }
2133 
2134 	// get functions
tagextended_file_icb_entry2135 	descriptor_tag & tag() { return _tag; }
tagextended_file_icb_entry2136 	const descriptor_tag & tag() const { return _tag; }
2137 
icb_tagextended_file_icb_entry2138 	icb_entry_tag& icb_tag() { return _icb_tag; }
icb_tagextended_file_icb_entry2139 	const icb_entry_tag& icb_tag() const { return _icb_tag; }
2140 
uidextended_file_icb_entry2141 	uint32 uid() const { return B_LENDIAN_TO_HOST_INT32(_uid); }
gidextended_file_icb_entry2142 	uint32 gid() const { return B_LENDIAN_TO_HOST_INT32(_gid); }
permissionsextended_file_icb_entry2143 	uint32 permissions() const { return B_LENDIAN_TO_HOST_INT32(_permissions); }
file_link_countextended_file_icb_entry2144 	uint16 file_link_count() const { return B_LENDIAN_TO_HOST_INT16(_file_link_count); }
record_formatextended_file_icb_entry2145 	uint8 record_format() const { return _record_format; }
record_display_attributesextended_file_icb_entry2146 	uint8 record_display_attributes() const { return _record_display_attributes; }
record_lengthextended_file_icb_entry2147 	uint32 record_length() const { return _record_length; }
information_lengthextended_file_icb_entry2148 	uint64 information_length() const { return B_LENDIAN_TO_HOST_INT64(_information_length); }
object_sizeextended_file_icb_entry2149 	uint64 object_size() const { return B_LENDIAN_TO_HOST_INT64(_object_size); }
logical_blocks_recordedextended_file_icb_entry2150 	uint64 logical_blocks_recorded() const { return B_LENDIAN_TO_HOST_INT64(_logical_blocks_recorded); }
2151 
access_date_and_timeextended_file_icb_entry2152 	timestamp& access_date_and_time() { return _access_date_and_time; }
access_date_and_timeextended_file_icb_entry2153 	const timestamp& access_date_and_time() const { return _access_date_and_time; }
2154 
modification_date_and_timeextended_file_icb_entry2155 	timestamp& modification_date_and_time() { return _modification_date_and_time; }
modification_date_and_timeextended_file_icb_entry2156 	const timestamp& modification_date_and_time() const { return _modification_date_and_time; }
2157 
creation_date_and_timeextended_file_icb_entry2158 	timestamp& creation_date_and_time() { return _creation_date_and_time; }
creation_date_and_timeextended_file_icb_entry2159 	const timestamp& creation_date_and_time() const { return _creation_date_and_time; }
2160 
attribute_date_and_timeextended_file_icb_entry2161 	timestamp& attribute_date_and_time() { return _attribute_date_and_time; }
attribute_date_and_timeextended_file_icb_entry2162 	const timestamp& attribute_date_and_time() const { return _attribute_date_and_time; }
2163 
checkpointextended_file_icb_entry2164 	uint32 checkpoint() const { return B_LENDIAN_TO_HOST_INT32(_checkpoint); }
2165 
extended_attribute_icbextended_file_icb_entry2166 	long_address& extended_attribute_icb() { return _extended_attribute_icb; }
extended_attribute_icbextended_file_icb_entry2167 	const long_address& extended_attribute_icb() const { return _extended_attribute_icb; }
2168 
stream_directory_icbextended_file_icb_entry2169 	long_address& stream_directory_icb() { return _stream_directory_icb; }
stream_directory_icbextended_file_icb_entry2170 	const long_address& stream_directory_icb() const { return _stream_directory_icb; }
2171 
implementation_idextended_file_icb_entry2172 	entity_id& implementation_id() { return _implementation_id; }
implementation_idextended_file_icb_entry2173 	const entity_id& implementation_id() const { return _implementation_id; }
2174 
unique_idextended_file_icb_entry2175 	uint64 unique_id() const { return B_LENDIAN_TO_HOST_INT64(_unique_id); }
extended_attributes_lengthextended_file_icb_entry2176 	uint32 extended_attributes_length() const { return B_LENDIAN_TO_HOST_INT32(_extended_attributes_length); }
allocation_descriptors_lengthextended_file_icb_entry2177 	uint32 allocation_descriptors_length() const { return B_LENDIAN_TO_HOST_INT32(_allocation_descriptors_length); }
2178 
extended_attributesextended_file_icb_entry2179 	uint8* extended_attributes() { return _end(); }
extended_attributesextended_file_icb_entry2180 	const uint8* extended_attributes() const { return _end(); }
allocation_descriptorsextended_file_icb_entry2181 	uint8* allocation_descriptors() { return _end()+extended_attributes_length(); }
allocation_descriptorsextended_file_icb_entry2182 	const uint8* allocation_descriptors() const { return _end()+extended_attributes_length(); }
2183 
2184 	// set functions
set_uidextended_file_icb_entry2185 	void set_uid(uint32 uid) { _uid = B_HOST_TO_LENDIAN_INT32(uid); }
set_gidextended_file_icb_entry2186 	void set_gid(uint32 gid) { _gid = B_HOST_TO_LENDIAN_INT32(gid); }
set_permissionsextended_file_icb_entry2187 	void set_permissions(uint32 permissions) { _permissions = B_HOST_TO_LENDIAN_INT32(permissions); }
2188 
set_file_link_countextended_file_icb_entry2189 	void set_file_link_count(uint16 count) { _file_link_count = B_HOST_TO_LENDIAN_INT16(count); }
set_record_formatextended_file_icb_entry2190 	void set_record_format(uint8 format) { _record_format = format; }
set_record_display_attributesextended_file_icb_entry2191 	void set_record_display_attributes(uint8 attributes) { _record_display_attributes = attributes; }
set_record_lengthextended_file_icb_entry2192 	void set_record_length(uint32 length) { _record_length = B_HOST_TO_LENDIAN_INT32(length); }
2193 
set_information_lengthextended_file_icb_entry2194 	void set_information_length(uint64 length) { _information_length = B_HOST_TO_LENDIAN_INT64(length); }
set_object_sizeextended_file_icb_entry2195 	void set_object_size(uint64 size) { _object_size = B_HOST_TO_LENDIAN_INT64(size); }
set_logical_blocks_recordedextended_file_icb_entry2196 	void set_logical_blocks_recorded(uint64 blocks) { _logical_blocks_recorded = B_HOST_TO_LENDIAN_INT64(blocks); }
2197 
set_checkpointextended_file_icb_entry2198 	void set_checkpoint(uint32 checkpoint) { _checkpoint = B_HOST_TO_LENDIAN_INT32(checkpoint); }
set_reservedextended_file_icb_entry2199 	void set_reserved(uint32 reserved) { _reserved = B_HOST_TO_LENDIAN_INT32(reserved); }
2200 
set_unique_idextended_file_icb_entry2201 	void set_unique_id(uint64 id) { _unique_id = B_HOST_TO_LENDIAN_INT64(id); }
2202 
set_extended_attributes_lengthextended_file_icb_entry2203 	void set_extended_attributes_length(uint32 length) { _extended_attributes_length = B_HOST_TO_LENDIAN_INT32(length); }
set_allocation_descriptors_lengthextended_file_icb_entry2204 	void set_allocation_descriptors_length(uint32 length) { _allocation_descriptors_length = B_HOST_TO_LENDIAN_INT32(length); }
2205 
2206 private:
2207 	static const uint32 _descriptor_length = 216;
_endextended_file_icb_entry2208 	uint8* _end() { return reinterpret_cast<uint8*>(this)+_descriptor_length; }
_endextended_file_icb_entry2209 	const uint8* _end() const { return reinterpret_cast<const uint8*>(this)+_descriptor_length; }
2210 
2211 	descriptor_tag  _tag;
2212 	icb_entry_tag _icb_tag;
2213 	uint32 _uid;
2214 	uint32 _gid;
2215 	/*! \todo List perms in comment and add handy union thingy */
2216 	uint32 _permissions;
2217 	/*! Identifies the number of file identifier descriptors referencing
2218 		this icb.
2219 	*/
2220 	uint16 _file_link_count;
2221 	uint8 _record_format;				//!< To be set to 0 per UDF-2.01 2.3.6.1
2222 	uint8 _record_display_attributes;	//!< To be set to 0 per UDF-2.01 2.3.6.2
2223 	uint32 _record_length;				//!< To be set to 0 per UDF-2.01 2.3.6.3
2224 	uint64 _information_length;
2225 	uint64 _object_size;
2226 	uint64 _logical_blocks_recorded;		//!< To be 0 for files and dirs with embedded data
2227 	timestamp _access_date_and_time;
2228 	timestamp _modification_date_and_time;
2229 	timestamp _creation_date_and_time;	// <== EXTENDED FILE ENTRY ONLY
2230 	timestamp _attribute_date_and_time;
2231 	/*! \brief Initially 1, may be incremented upon user request. */
2232 	uint32 _checkpoint;
2233 	uint32 _reserved;	// <== EXTENDED FILE ENTRY ONLY
2234 	long_address _extended_attribute_icb;
2235 	long_address _stream_directory_icb;	// <== EXTENDED FILE ENTRY ONLY
2236 	entity_id _implementation_id;
2237 	/*! \brief The unique id identifying this file entry
2238 
2239 		The id of the root directory of a file set shall be 0.
2240 
2241 		\todo Detail the system specific requirements for unique ids from UDF-2.01 3.2.1.1
2242 	*/
2243 	uint64 _unique_id;
2244 	uint32 _extended_attributes_length;
2245 	uint32 _allocation_descriptors_length;
2246 
2247 };
2248 
2249 
2250 #endif	// _UDF_DISK_STRUCTURES_H
2251 
2252