521 lines
18 KiB
C
521 lines
18 KiB
C
/*++
|
||
|
||
Copyright (c) 1996-2000 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
Udf.h
|
||
|
||
Abstract:
|
||
|
||
This module contains all definitions specified by the OSTA UDF standard which
|
||
are not defined in ISO 13346 and associated errta. UDF is a subset of ISO 13346
|
||
which restricts many facets of the ISO standard and is currently standardized
|
||
by the Optical Storage Technology Association (http://www.osta.org). Some
|
||
aspects of the structures we read may seem illogical unless viewed in this light.
|
||
|
||
Unless otherwise specified, section references will be to ISO 13346.
|
||
|
||
Also unless otherwise specified, all descriptors mentioned will be sector aligned
|
||
|
||
A UDF volume is recognized by searching the Volume Recognition Area (2/8.3) for a
|
||
Volume Structure Descriptor (2/9.1) which advertises itself as NSR02, the filesystem
|
||
format specified by ISO 13346 section 4. This is aligned to match ISO 9660, and the
|
||
first descriptor may in fact be a 9660 PVD. ISO 13346 descriptors are bounded by
|
||
a Begin Extended Area descriptor (2/9.2) and a Terminate Extended Area descriptor
|
||
(2/9.3).
|
||
|
||
+-------+-------+ +-------+ +-------+
|
||
| | | | | | |
|
||
| CD001 | BEA01 | ... | NSR02 | ... | TEA01 |
|
||
| | | | | | |
|
||
+-------+-------+ +-------+ +-------+
|
||
|
||
A UDF volume is then discovered by looking for an Anchor Volume Descriptor (3/10.2),
|
||
which reveals the location of a pair of extents of the physical volume that contain
|
||
copies of the Volume Descriptor Sequence. Both of these copies are defined to be
|
||
equivalent (duplication is intended for diasaster recovery).
|
||
|
||
+-------+ +------------------------------------+
|
||
| | -----------> | |
|
||
| AVD | | Main Volume Descriptor Sequence |
|
||
| | ----+ | |
|
||
+-------+ | +------------------------------------+
|
||
|
|
||
| +------------------------------------+
|
||
| | |
|
||
+------> | Reserve Volume Descriptor Sequence |
|
||
| |
|
||
+------------------------------------+
|
||
|
||
An ISO 13346 logical (mountable) volume is composed of a number Np of physical partitions
|
||
spread across a number Nd of physical volumes (media), all of which may be multiply
|
||
referenced to create a numbed Nv of logical volumes. While ISO 13346 allows this level of
|
||
complexity, UDF restricts as follows: Nv = 1 and Np = Nd except if Nd = 1 then perhaps
|
||
Np = 2 and one partition is read/write while the other is readonly. There are three levels
|
||
of conforming implementations which are defined by ISO 1336 in 3/11 which progress from 1,
|
||
a restricted Nd = 1, to 3 where Nd > 1. This is a readonly level 2 implementation, which
|
||
is an unrestricted single physical media implementation - other than those imposed by UDF.
|
||
|
||
A Volume Descriptor Sequence is composed of a number of descriptors which collectively nail
|
||
down a volume:
|
||
|
||
Primary Volume Descriptor (PVD) Identification of the physical media and its
|
||
(3/10.1) relation to a volume set.
|
||
|
||
Volume Descriptor Pointer (VSD) Identification of a continuing extent of the Volume
|
||
(3/10.3) Descriptor Sequence (the VDS need not be a single
|
||
extent).
|
||
|
||
Implementation Use Volume Desciptor (IUVD) Exactly that.
|
||
(3/10.4)
|
||
|
||
Partition Descriptor (PD) Identification of a linear extent of sectors
|
||
(3/10.5) on a physical media (type 1) or an implementation
|
||
defined object (type 2).
|
||
|
||
Logical Volume Descriptor (LVD) Identification of a mountable volume by
|
||
(3/10.6) referring to partition(s) and a location for
|
||
a File Set Descriptor.
|
||
|
||
Unallocated Space Descriptor (USD) Identification of an unallocated extents of the
|
||
(3/10.8) media which could be added to existing partitions
|
||
or allocated through new partitions.
|
||
|
||
Terminating Descriptor (TD) A method of terminating the Volume Descriptor
|
||
(3/10.9) Sequence. A VDS may also be terminated by an
|
||
unrecorded sector or running to the end of an
|
||
extent.
|
||
|
||
An ISO 13346 volume set is a grouping of physical media, identified collectively by examining
|
||
the PVD of each unit. A Volume Descriptor Sequence is recorded on each constituent of the volume
|
||
set, but only the volume with the highest Volume Sequence Number may contain LVD. An LVD may
|
||
refer to any PD on any member of the volume set.
|
||
|
||
Each descriptor contains a Volume Sequence Number which allows an otherwise identification
|
||
equivalent descriptor (i.e., specifies the same Partition Number (for PD), same Logical
|
||
Volume Identifier (for LVD), etc. (3/8.4.3)) to override one of lower VSN.
|
||
|
||
So, a picture of what a Volume Descriptor Sequence could look like is
|
||
|
||
+------+------+------+------+------+
|
||
| | | | | |
|
||
| PVD | LVD | PD | PD | VDP |
|
||
| | | | | |
|
||
+------+------+------+------+------+
|
||
|
|
||
| +------+------+------+------+
|
||
| | | | | |
|
||
+->| USD | IUVD | IUVD | TD |
|
||
| | | | |
|
||
+------+------+------+------+
|
||
|
||
The LVD points to a File Set Descriptor (4/14.1), which finally points to a root directory.
|
||
|
||
// @@BEGIN_DDKSPLIT
|
||
|
||
Author:
|
||
|
||
Dan Lovinger [DanLo] 10-Jul-1996
|
||
|
||
Revision History:
|
||
|
||
Tom Jolly [TomJolly] 1-March-2000 UDF 2.01 support
|
||
|
||
// @@END_DDKSPLIT
|
||
|
||
--*/
|
||
|
||
#ifndef _UDF_
|
||
#define _UDF_
|
||
|
||
#include <iso13346.h>
|
||
|
||
//
|
||
// This is the version of UDF that we recognize, per the Domain Identifier
|
||
// specification in UDF 2.1.5.3.
|
||
//
|
||
// The values below indicate we understand UDF 2.01. We will also define
|
||
// specific revisions so that we can assert correctness for some structures
|
||
// that we know appeared for the first time in certain specifications.
|
||
//
|
||
//
|
||
|
||
#define UDF_VERSION_100 0x0100
|
||
#define UDF_VERSION_101 0x0101
|
||
#define UDF_VERSION_102 0x0102
|
||
#define UDF_VERSION_150 0x0150
|
||
#define UDF_VERSION_200 0x0200
|
||
#define UDF_VERSION_201 0x0201
|
||
|
||
#define UDF_VERSION_RECOGNIZED UDF_VERSION_201
|
||
|
||
#define UDF_VERSION_MINIMUM UDF_VERSION_100
|
||
|
||
|
||
//
|
||
// Method 2 Fixup.
|
||
//
|
||
// This really isn't UDF, but for lack of a better place ... and since we are doing
|
||
// the work for UDF only. In the filesystem. Sigh.
|
||
//
|
||
// Various bad CD-ROM units, when reading fixed-packet CD-RW media, fail to map out
|
||
// the runin/out blocks that follow each packet of 32 sectors on the media. As a
|
||
// result, we have to fixup all of the byte offsets to read the image.
|
||
//
|
||
// Note: fixed packet. Variable packet discs do have the runin/out exposed, but
|
||
// imaging software will have realized this and numbered sectors right.
|
||
//
|
||
// Normally we would refuse to deal with this garbage, but Adaptec made the decision
|
||
// for us by having their reader handle these drives. So that we don't have to deal
|
||
// with endless "but it works with Adaptec", we've got to do it here.
|
||
//
|
||
// This is really depressing.
|
||
//
|
||
|
||
#define CDRW_PACKET_LENGTH 32
|
||
#define CDRW_RUNOUT_LENGTH 7
|
||
|
||
//
|
||
// LONGLONG UdfMethod2TransformByteOffset (
|
||
// PVCB Vcb,
|
||
// LONGLONG ByteOffset
|
||
// )
|
||
//
|
||
// Takes a normal byteoffset and adds in the differential implied by the number
|
||
// of runout areas it spans.
|
||
//
|
||
|
||
#define UdfMethod2TransformByteOffset(V, BO) \
|
||
((BO) + LlBytesFromSectors((V), ((LlSectorsFromBytes((V), BO) / CDRW_PACKET_LENGTH) * CDRW_RUNOUT_LENGTH)))
|
||
|
||
#define UdfMethod2TransformSector(V, S) \
|
||
((S) + ((S) / CDRW_PACKET_LENGTH) * CDRW_RUNOUT_LENGTH)
|
||
|
||
//
|
||
// ULONG UdfMethod2NextRunoutInSectors (
|
||
// PVCB Vcb,
|
||
// LONGLONG ByteOffset
|
||
// )
|
||
//
|
||
// Takes a normal byteoffset and figures out how many sectors remain until the next
|
||
// (forward) runout area.
|
||
//
|
||
|
||
#define UdfMethod2NextRunoutInSectors(V, BO) \
|
||
(CDRW_PACKET_LENGTH - (LlSectorsFromBytes((V), (BO)) % CDRW_PACKET_LENGTH))
|
||
|
||
|
||
//
|
||
// Generic constants
|
||
//
|
||
|
||
#define BYTE_COUNT_8_DOT_3 (24)
|
||
|
||
//
|
||
// Constants for the name transform algorithm. Names greater than MAXLEN will be
|
||
// rendered. MAX_PATH comes from user-side includes that we don't get here.
|
||
//
|
||
// UDF specifies rules for converting names from illegal->legal forms for a given OS.
|
||
// The rest of the constants/macros are used to convert the clipped code for these
|
||
// algorithims into a form we can directly use.
|
||
//
|
||
// The NativeCharLength question is really not answerable for the non-8.3 case, since
|
||
// NT internally is completely ignorant of the eventual destination of the name.
|
||
//
|
||
|
||
#define MAX_PATH 260
|
||
|
||
#define MAX_LEN (MAX_PATH - 5)
|
||
#define EXT_LEN 5
|
||
#define CRC_LEN 5
|
||
|
||
#define DOS_NAME_LEN 8
|
||
#define DOS_EXT_LEN 3
|
||
#define DOS_CRC_LEN 4
|
||
|
||
#define IsFileNameCharLegal(c) UdfIsCharacterLegal(c)
|
||
#define IsDeviceName(s, n) FALSE
|
||
#define NativeCharLength(c) 1
|
||
#define UnicodeToUpper(c) (c)
|
||
|
||
#define INT16 SHORT
|
||
#define UINT16 USHORT
|
||
#define UNICODE_CHAR WCHAR
|
||
|
||
#define PERIOD (L'.')
|
||
#define SPACE (L' ')
|
||
#define CRC_MARK (L'#')
|
||
#define ILLEGAL_CHAR_MARK (L'_')
|
||
|
||
//
|
||
// Place a non-tail recursable depth limit on ICB hierarchies. We cannot read
|
||
// ICB hierarchies that are deeper than this.
|
||
//
|
||
|
||
#define UDF_ICB_RECURSION_LIMIT 10
|
||
|
||
|
||
//
|
||
// Entity ID (REGID) Suffixes are used in UDF to encode extra information away from
|
||
// the string data in the Identifier. See UDF 2.1.4.2.
|
||
//
|
||
|
||
//
|
||
// A Domain Suffix is encoded for the Logical Volume Descriptor and File Set Descriptor
|
||
//
|
||
|
||
typedef struct _UDF_SUFFIX_DOMAIN {
|
||
|
||
USHORT UdfRevision;
|
||
UCHAR Flags;
|
||
UCHAR Reserved[5];
|
||
|
||
} UDF_SUFFIX_DOMAIN, *PUDF_SUFFIX_DOMAIN;
|
||
|
||
#define UDF_SUFFIX_DOMAIN_FLAG_HARD_WRITEPROTECT 0x01
|
||
#define UDF_SUFFIX_DOMAIN_FLAG_SOFT_WRITEPROTECT 0x02
|
||
|
||
//
|
||
// A UDF Suffix is encoded for extended attributes, Implementation Use Volume
|
||
// Descriptors and VATs (among others).
|
||
//
|
||
|
||
typedef struct _UDF_SUFFIX_UDF {
|
||
|
||
USHORT UdfRevision;
|
||
UCHAR OSClass;
|
||
UCHAR OSIdentifier;
|
||
UCHAR Reserved[4];
|
||
|
||
} UDF_SUFFIX_UDF, *PUDF_SUFFIX_UDF;
|
||
|
||
//
|
||
// An Implementation Suffix is encoded for almost every other structure containing
|
||
// an Entity ID.
|
||
//
|
||
|
||
typedef struct _UDF_SUFFIX_IMPLEMENTATION {
|
||
|
||
UCHAR OSClass;
|
||
UCHAR OSIdentifier;
|
||
UCHAR ImplementationUse[6];
|
||
|
||
} UDF_SUFFIX_IMPLEMENTATION, *PUDF_SUFFIX_IMPLEMENTATION;
|
||
|
||
//
|
||
// OS Classes and Identifiers are defined by OSTA as of UDF 1.50
|
||
//
|
||
// We also take the minor liberty of defining an invalid set for
|
||
// the purposes of hinting internally that we don't care about them.
|
||
// It is unlikely that UDF will ever hit 255, even though these are
|
||
// technically avaliable for allocation.
|
||
//
|
||
|
||
#define OSCLASS_INVALID 255
|
||
#define OSIDENTIFIER_INVALID 255
|
||
|
||
|
||
#define OSCLASS_UNDEFINED 0
|
||
#define OSCLASS_DOS 1
|
||
#define OSCLASS_OS2 2
|
||
#define OSCLASS_MACOS 3
|
||
#define OSCLASS_UNIX 4
|
||
#define OSCLASS_WIN9X 5
|
||
#define OSCLASS_WINNT 6
|
||
|
||
#define OSIDENTIFIER_DOS_DOS 0
|
||
|
||
#define OSIDENTIFIER_OS2_OS2 0
|
||
|
||
#define OSIDENTIFIER_MACOS_MACOS7 0
|
||
|
||
#define OSIDENTIFIER_UNIX_GENERIC 0
|
||
#define OSIDENTIFIER_UNIX_AIX 1
|
||
#define OSIDENTIFIER_UNIX_SOLARIS 2
|
||
#define OSIDENTIFIER_UNIX_HPUX 3
|
||
#define OSIDENTIFIER_UNIX_IRIX 4
|
||
#define OSIDENTIFIER_UNIX_LINUX 5
|
||
#define OSIDENTIFIER_UNIX_MKLINUX 6
|
||
#define OSIDENTIFIER_UNIX_FREEBSD 7
|
||
|
||
#define OSIDENTIFIER_WIN9X_WIN95 0
|
||
|
||
#define OSIDENTIFIED_WINNT_WINNT 0
|
||
|
||
|
||
//
|
||
// Character Set Lists are actually just a 32bit word where each bit N on/off specifies
|
||
// that Character Set N is used on the volume. Per UDF, the only character set we
|
||
// recognize is CS0, so construct a bitmask Character Set List for that. (1/7.2.11)
|
||
//
|
||
|
||
#define UDF_CHARSETLIST 0x00000001
|
||
|
||
|
||
//
|
||
// Generic partition map for UDF. This allows partition maps to be typed and the
|
||
// UDF entity identifier for the various type 2 maps to be inspected.
|
||
//
|
||
|
||
typedef struct _PARTMAP_UDF_GENERIC {
|
||
|
||
UCHAR Type; // Partition Map Type = 2
|
||
UCHAR Length; // Partition Map Length = 64
|
||
UCHAR Reserved2[2]; // Reserved Padding
|
||
REGID PartID; // Paritition Entity Identifier
|
||
UCHAR Reserved24[28]; // Reserved Padding
|
||
|
||
} PARTMAP_UDF_GENERIC, *PPARTMAP_UDF_GENERIC;
|
||
|
||
//
|
||
// UDF 1.50 CD UDF Partition Types
|
||
//
|
||
|
||
//////////
|
||
// UDF Virtual Partitions are identified via a type 2 partition map of the following form.
|
||
//////////
|
||
|
||
typedef struct _PARTMAP_VIRTUAL {
|
||
|
||
UCHAR Type; // Partition Map Type = 2
|
||
UCHAR Length; // Partition Map Length = 64
|
||
UCHAR Reserved2[2]; // Reserved Padding
|
||
REGID PartID; // Paritition Entity Identifier
|
||
// == UdfVirtualPartitionDomainIdentifier
|
||
USHORT VolSetSeq; // Volume Set Sequence
|
||
USHORT Partition; // Related Partition
|
||
UCHAR Reserved40[24]; // Reserved Padding
|
||
|
||
} PARTMAP_VIRTUAL, *PPARTMAP_VIRTUAL;
|
||
|
||
|
||
//
|
||
// UDF 2.00 CD UDF VAT Header
|
||
//
|
||
// Note that values in this record supedcede those in the LDV or LVID
|
||
//
|
||
|
||
typedef struct _VAT_HEADER {
|
||
|
||
USHORT Length; // Header length = 152 + ImpUseLength
|
||
USHORT ImpUseLength;
|
||
|
||
UCHAR VolumeID[128];
|
||
|
||
ULONG PreviousVatIcbLbn;
|
||
|
||
ULONG FileFidCount;
|
||
ULONG NonParentDirFidCount;
|
||
|
||
USHORT MinUdfReadRevision;
|
||
USHORT MinUdfWriteRevision;
|
||
USHORT MaxUdfWriteRevision;
|
||
USHORT Reserved;
|
||
|
||
UCHAR ImpUse[0];
|
||
|
||
// VAT entries immediately follow impuse data.
|
||
//
|
||
// UINT32 Lba of virtual sector 0
|
||
// UINT32 Lba of virtual sector 1
|
||
// ...
|
||
|
||
} VAT_HEADER, *PVAT_HEADER;
|
||
|
||
|
||
//
|
||
// A UDF 1.50 VAT minimally contains a mapping for a single block, the REGID identifying
|
||
// the VAT, and the identification of a previous VAT ICB location.
|
||
//
|
||
// A UDF 2.0x VAT minimally contains a VAT header, and a mapping for a single block.
|
||
//
|
||
// We also identify
|
||
// an arbitrary sanity limit that the VAT isn't bigger than 8mb since it is extremely
|
||
// difficult to imagine such a VAT existing in practice since each sector describes
|
||
// (on most of our media) 2048/4 = 512 entries ... meaning at 8mb the VAT would
|
||
// describe ~2^21 blocks. 4/12/01 Increased for DVD-R.
|
||
//
|
||
|
||
#define UDF_CDUDF_TRAILING_DATA_SIZE (sizeof(REGID) + sizeof(ULONG))
|
||
|
||
#define UDF_CDUDF_MINIMUM_150_VAT_SIZE (sizeof(ULONG) + UDF_CDUDF_TRAILING_DATA_SIZE)
|
||
#define UDF_CDUDF_MINIMUM_20x_VAT_SIZE (sizeof(ULONG) + sizeof( VAT_HEADER))
|
||
|
||
#define UDF_CDUDF_MAXIMUM_VAT_SIZE (16 * 1024 * 1024)
|
||
|
||
//////////
|
||
// UDF Sparable Partitions are identified via a type 2 partition map of the following form.
|
||
//////////
|
||
|
||
typedef struct _PARTMAP_SPARABLE {
|
||
|
||
UCHAR Type; // Partition Map Type = 2
|
||
UCHAR Length; // Partition Map Length = 64
|
||
UCHAR Reserved2[2]; // Reserved Padding
|
||
REGID PartID; // Paritition Entity Identifier
|
||
// == UdfSparablePartitionDomainIdentifier
|
||
USHORT VolSetSeq; // Volume Set Sequence
|
||
USHORT Partition; // Related Partition
|
||
USHORT PacketLength; // Packet Length == 32 (number of data blocks
|
||
// per packet)
|
||
UCHAR NumSparingTables; // Number of pparing tables on the media
|
||
UCHAR Reserved43; // Reserved Padding
|
||
ULONG TableSize; // Size of sparing tables
|
||
ULONG TableLocation[4]; // Location of each sparing table (each
|
||
// sparing table should be in a distinct packet)
|
||
|
||
} PARTMAP_SPARABLE, *PPARTMAP_SPARABLE;
|
||
|
||
//
|
||
// Sparing tables lead off with this header structure.
|
||
//
|
||
|
||
typedef struct _SPARING_TABLE_HEADER {
|
||
|
||
DESTAG Destag; // Ident = 0
|
||
REGID RegID; // == UdfSparingTableIdentifier
|
||
USHORT TableEntries; // Number of entries in the table
|
||
USHORT Reserved50; // Reserved Padding
|
||
ULONG Sequence; // Sequence Number (incremented on rewrite of table)
|
||
|
||
} *PSPARING_TABLE_HEADER, SPARING_TABLE_HEADER;
|
||
|
||
//
|
||
// Sparing table map entries.
|
||
//
|
||
|
||
typedef struct _SPARING_TABLE_ENTRY {
|
||
|
||
ULONG Original; // Original LBN
|
||
ULONG Mapped; // Mapped PSN
|
||
|
||
} *PSPARING_TABLE_ENTRY, SPARING_TABLE_ENTRY;
|
||
|
||
//
|
||
// Fixed values for original sectors, indicating that either the
|
||
// mapped packet is avaliable for sparing use or is defective.
|
||
//
|
||
|
||
#define UDF_SPARING_AVALIABLE 0xffffffff
|
||
#define UDF_SPARING_DEFECTIVE 0xfffffff0
|
||
|
||
//
|
||
// The unit of media in each sparing packet is fixed at 32 physical sectors.
|
||
//
|
||
|
||
#define UDF_SPARING_PACKET_LENGTH CDRW_PACKET_LENGTH
|
||
|
||
//
|
||
// Additional Values defined in UDF, over and above those in ISO13346.h
|
||
//
|
||
|
||
// ICBTAG_FILE_T_... - Values for icbtag_FileType
|
||
|
||
#define ICBTAG_FILE_T_VAT 248 // VAT (new format - UDF 2.00 and later)
|
||
#define ICBTAG_FILE_T_REALTIME 249 // Real Time File (UDF 2.01, 2.3.5.2.1)
|
||
|
||
|
||
#endif // _UDF_
|
||
|