Begin implementation of Apple Macintosh HFS/HFS+ filesystem format

This commit is contained in:
Michael Becker 2015-06-16 16:05:27 -04:00
parent 078c6522f0
commit ed025ccc09
24 changed files with 1029 additions and 2 deletions

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8" ?>
<UniversalEditor Version="4.0">
<Associations>
<Association>
<Filters>
<Filter Title="Apple hierarchical file system (HFS)">
<FileNameFilters>
<FileNameFilter>*.hfs</FileNameFilter>
<FileNameFilter>*.hfv</FileNameFilter>
</FileNameFilters>
<!--
<MagicByteSequences>
<MagicByteSequence Offset="1024">
<MagicByte Type="HexString">4244</MagicByte>
</MagicByteSequence>
</MagicByteSequences>
-->
</Filter>
</Filters>
<ObjectModels>
<ObjectModel TypeName="UniversalEditor.ObjectModels.FileSystem.FileSystemObjectModel" />
</ObjectModels>
<DataFormats>
<DataFormat TypeName="UniversalEditor.DataFormats.FileSystem.Apple.HFS.HFSDataFormat" />
</DataFormats>
</Association>
</Associations>
</UniversalEditor>

View File

@ -100,6 +100,7 @@
<Content Include="Extensions\DatabaseAdministrator\Themes\VisualStudio2012\Images\Templates\Project\Database Administrator\32x32\Database Project.png" />
<Content Include="Extensions\FileSystem\Associations\7Zip.xml" />
<Content Include="Extensions\FileSystem\Associations\ALTools.xml" />
<Content Include="Extensions\FileSystem\Associations\Apple\HFS\HFSDataFormat.xml" />
<Content Include="Extensions\FileSystem\Associations\AR.xml" />
<Content Include="Extensions\FileSystem\Associations\ARC.xml" />
<Content Include="Extensions\FileSystem\Associations\Archive.xml" />
@ -657,10 +658,10 @@
<None Include="Templates\Project\File Distribution\Images\Torrent.xcf" />
</ItemGroup>
<Target Name="Build">
<Copy SourceFiles="@(Content)" DestinationFiles="@(Content-&gt;'$(OutputPath)%(RelativeDir)%(Filename)%(Extension)')" />
<Copy SourceFiles="@(Content)" DestinationFiles="@(Content->'$(OutputPath)%(RelativeDir)%(Filename)%(Extension)')" />
</Target>
<Target Name="Clean">
<Delete Files="@(Content-&gt;'$(OutputPath)%(RelativeDir)%(Filename)%(Extension)')" />
<Delete Files="@(Content->'$(OutputPath)%(RelativeDir)%(Filename)%(Extension)')" />
</Target>
<Target Name="Rebuild" DependsOnTargets="Clean;Build">
</Target>

View File

@ -0,0 +1,405 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UniversalEditor.IO;
using UniversalEditor.ObjectModels.FileSystem;
using UniversalEditor.DataFormats.FileSystem.Apple.HFS.Internal;
using UniversalEditor.DataFormats.FileSystem.Apple.HFS.Internal.CatalogRecords;
namespace UniversalEditor.DataFormats.FileSystem.Apple.HFS
{
public class HFSDataFormat : DataFormat
{
private static DataFormatReference _dfr = null;
protected override DataFormatReference MakeReferenceInternal()
{
if (_dfr == null)
{
_dfr = base.MakeReferenceInternal();
_dfr.Capabilities.Add(typeof(FileSystemObjectModel), DataFormatCapabilities.All);
_dfr.ExportOptions.Add(new CustomOptionText("VolumeName", "Volume &name"));
_dfr.ExportOptions.Add(new CustomOptionNumber("VolumeBackupSequenceNumber", "&Backup sequence number", 0, Int16.MinValue, Int16.MaxValue));
_dfr.ExportOptions.Add(new CustomOptionNumber("VolumeWriteCount", "Volume &write count"));
_dfr.Sources.Add("https://developer.apple.com/legacy/library/documentation/mac/Files/Files-102.html");
_dfr.Sources.Add("http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/fs/hfs/hfs.h");
_dfr.Sources.Add("www.fenestrated.net/~macman/mirrors/Apple Technotes (As of 2002)/tn/tn1150.html");
}
return _dfr;
}
private string mvarVolumeName = String.Empty;
public string VolumeName { get { return mvarVolumeName; } set { mvarVolumeName = value; } }
private short mvarVolumeBackupSequenceNumber = 0;
public short VolumeBackupSequenceNumber { get { return mvarVolumeBackupSequenceNumber; } set { mvarVolumeBackupSequenceNumber = value; } }
private int mvarVolumeWriteCount = 0;
public int VolumeWriteCount { get { return mvarVolumeWriteCount; } set { mvarVolumeWriteCount = value; } }
private const int LOGICAL_BLOCK_SIZE = 512;
public void SeekToLogicalBlock(long index)
{
long offset = (LOGICAL_BLOCK_SIZE * index);
base.Accessor.Seek(offset, IO.SeekOrigin.Begin);
}
protected override void LoadInternal(ref ObjectModel objectModel)
{
FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel);
if (fsom == null) throw new ObjectModelNotSupportedException();
Reader reader = base.Accessor.Reader;
reader.Seek(0, SeekOrigin.Begin); // debug only, remove when finished
// let's not forget that Mac OS legacy filesystems are big-endian
reader.Endianness = Endianness.BigEndian;
// Logical blocks 0 and 1 of the volume are the Boot blocks which contain system
// startup information. For example, the names of the System and Shell (usually
// the Finder) files which are loaded at startup.
HFSMasterDirectoryBlock _mdb = new HFSMasterDirectoryBlock();
#region Master Directory Block
{
// Logical block 2 contains the Master Directory Block (MDB). This defines a wide
// variety of data about the volume itself, for example date & time stamps for when the
// volume was created, the location of the other volume structures such as the Volume
// Bitmap or the size of logical structures such as allocation blocks. There is also a
// duplicate of the MDB called the Alternate Master Directory Block (aka Alternate MDB)
// located at the opposite end of the volume in the second to last logical block. This
// is intended mainly for use by disk utilities and is only updated when either the
// Catalog File or Extents Overflow File grow in size.
SeekToLogicalBlock(2);
byte[] signature = reader.ReadBytes(2);
if (signature.Match(new byte[] { 0x42, 0x44 }))
{
// HFS volume
}
else if (signature.Match(new byte[] { 0xD2, 0xD7 }))
{
// obsolete flat MFS volume
throw new InvalidDataFormatException("MFS volume not supported yet");
}
else
{
throw new InvalidDataFormatException("File does not contain 'BD' at logical block 2");
}
_mdb.creationTimestamp = reader.ReadInt32();
_mdb.modificationTimestamp = reader.ReadInt32();
_mdb.volumeAttributes = (HFSVolumeAttributes)reader.ReadInt16();
_mdb.rootDirectoryFileCount = reader.ReadUInt16();
_mdb.volumeBitmapFirstBlockIndex = reader.ReadUInt16();
_mdb.nextAllocationSearchStart = reader.ReadInt16();
_mdb.allocationBlockCount = reader.ReadUInt16();
_mdb.allocationBlockSize = reader.ReadInt32();
// allocation block sanity check - must be a multiple of 512 bytes
if ((_mdb.allocationBlockSize % 512) != 0) throw new InvalidDataFormatException("Allocation block size is not a multiple of 512");
_mdb.defaultClumpSize = reader.ReadInt32();
_mdb.firstAllocationBlockIndex = reader.ReadInt16();
_mdb.nextUnusedCatalogNodeID = reader.ReadInt32();
_mdb.unusedAllocationBlockCount = reader.ReadUInt16();
mvarVolumeName = ReadHFSName(reader, 27);
_mdb.lastBackupTimestamp = reader.ReadInt32();
mvarVolumeBackupSequenceNumber = reader.ReadInt16();
mvarVolumeWriteCount = reader.ReadInt32();
_mdb.clumpSizeForExtentsOverflowFile = reader.ReadInt32();
_mdb.clumpSizeForCatalogFile = reader.ReadInt32();
_mdb.rootDirectoryDirectoryCount = reader.ReadUInt16();
_mdb.totalFileCount = reader.ReadInt32();
_mdb.totalDirectoryCount =reader.ReadInt32();
_mdb.finderInfo = reader.ReadInt32Array(8); // information used by the Finder
_mdb.volumeCacheBlockCount = reader.ReadUInt16();
_mdb.volumeBitmapCacheBlockCount = reader.ReadUInt16();
_mdb.commonVolumeCacheBlockCount = reader.ReadUInt16();
// ExtDataRec: ARRAY[3] of ExtDescriptor
int extentsOverflowFileSize = reader.ReadInt32();
_mdb.extentRecordsForExtentsOverflowFile = ReadHFSExtentDescriptorArray(reader, 3);
int catalogFileSize = reader.ReadInt32();
_mdb.extentRecordsForCatalogFile = ReadHFSExtentDescriptorArray(reader, 3);
int irgs = _mdb.extentRecordsForCatalogFile[0].firstAllocationBlockIndex;
int crgs = _mdb.extentRecordsForCatalogFile[0].allocationBlockCount;
reader.Seek(13815, SeekOrigin.Begin);
HFSCatalogRecord hfscr = ReadHFSCatalogRecord(reader);
}
#endregion
#region Volume bitmap
{
SeekToLogicalBlock(_mdb.volumeBitmapFirstBlockIndex);
}
#endregion
#region
#endregion
}
private string ReadHFSName(Reader reader, int length = 31)
{
byte nameLength = reader.ReadByte();
string name = reader.ReadFixedLengthString(length);
if (nameLength < name.Length)
{
// clip off the rest of the unused characters for the volume name
name = name.Substring(0, nameLength);
}
return name;
}
private HFSCatalogRecord ReadHFSCatalogRecord(Reader reader)
{
HFSCatalogRecordType type = (HFSCatalogRecordType)reader.ReadInt16();
switch (type)
{
case HFSCatalogRecordType.Directory:
case HFSCatalogRecordType.ExtendedDirectory:
{
HFSCatalogDirectoryRecord rec = new HFSCatalogDirectoryRecord();
rec.type = type;
rec.flags = (HFSDirectoryFlags)reader.ReadInt16();
if (type == HFSCatalogRecordType.ExtendedDirectory)
{
rec.directoryValence = reader.ReadInt32();
}
else
{
rec.directoryValence = reader.ReadInt16();
}
rec.directoryID = reader.ReadInt32();
rec.creationTimestamp = reader.ReadInt32();
if (type == HFSCatalogRecordType.ExtendedDirectory)
{
rec.modificationTimestamp = reader.ReadInt32();
rec.attributeModificationTimestamp = reader.ReadInt32();
rec.lastAccessTimestamp = reader.ReadInt32();
}
else
{
rec.modificationTimestamp = reader.ReadInt32();
}
rec.lastBackupTimestamp = reader.ReadInt32();
if (type == HFSCatalogRecordType.ExtendedDirectory)
{
rec.permissions = ReadHFSPlusPermissions(reader);
}
rec.finderUserInformation = ReadHFSDInfo(reader);
rec.finderAdditionalInformation = ReadHFSDXInfo(reader);
if (type == HFSCatalogRecordType.ExtendedDirectory)
{
rec.textEncoding = (HFSPlusTextEncoding)reader.ReadUInt32();
uint reserved = reader.ReadUInt32();
}
else
{
int[] reserved = reader.ReadInt32Array(4);
}
return rec;
}
case HFSCatalogRecordType.ExtendedFile:
case HFSCatalogRecordType.File:
{
HFSCatalogFileRecord rec = new HFSCatalogFileRecord();
rec.type = type;
if (type == HFSCatalogRecordType.ExtendedFile)
{
rec.flags = (HFSFileFlags)reader.ReadUInt16();
uint reserved1 = reader.ReadUInt32();
rec.fileID = reader.ReadInt32();
rec.creationTimestamp = reader.ReadInt32();
rec.modificationTimestamp = reader.ReadInt32();
rec.attributeModificationTimestamp = reader.ReadInt32();
rec.lastAccessTimestamp = reader.ReadInt32();
rec.lastBackupTimestamp = reader.ReadInt32();
rec.permissions = ReadHFSPlusPermissions(reader);
rec.finderUserInformation = ReadHFSFInfo(reader);
rec.finderAdditionalInformation = ReadHFSFXInfo(reader);
rec.textEncoding = (HFSPlusTextEncoding)reader.ReadUInt32();
uint reserved2 = reader.ReadUInt32();
rec.dataFork = ReadHFSPlusForkData(reader);
rec.resourceFork = ReadHFSPlusForkData(reader);
}
else
{
rec.flags = (HFSFileFlags)reader.ReadSByte();
rec.fileType = reader.ReadSByte();
rec.finderUserInformation = ReadHFSFInfo(reader);
rec.fileID = reader.ReadInt32();
rec.dataForkFirstAllocationBlock = reader.ReadInt16();
rec.dataForkLogicalEOF = reader.ReadInt32();
rec.dataForkPhysicalEOF = reader.ReadInt32();
rec.resourceForkFirstAllocationBlock = reader.ReadInt16();
rec.resourceForkLogicalEOF = reader.ReadInt32();
rec.resourceForkPhysicalEOF = reader.ReadInt32();
rec.creationTimestamp = reader.ReadInt32();
rec.modificationTimestamp = reader.ReadInt32();
rec.lastBackupTimestamp = reader.ReadInt32();
rec.finderAdditionalInformation = ReadHFSFXInfo(reader);
rec.fileClumpSize = reader.ReadInt16();
rec.firstDataForkExtentRecord = ReadHFSExtentDescriptorArray(reader, 3);
rec.firstResourceForkExtentRecord = ReadHFSExtentDescriptorArray(reader, 3);
rec.reserved2 = reader.ReadInt32();
}
return rec;
}
case HFSCatalogRecordType.DirectoryThread:
{
HFSCatalogDirectoryThreadRecord rec = new HFSCatalogDirectoryThreadRecord();
rec.type = type;
rec.reserved2 = reader.ReadInt32Array(2);
rec.parentID = reader.ReadInt32();
rec.fileName = ReadHFSName(reader);
return rec;
}
case HFSCatalogRecordType.FileThread:
{
HFSCatalogFileThreadRecord rec = new HFSCatalogFileThreadRecord();
rec.type = type;
rec.reserved2 = reader.ReadInt32Array(2);
rec.parentID = reader.ReadInt32();
byte fileNameLength = reader.ReadByte();
rec.fileName = reader.ReadFixedLengthString(fileNameLength);
return rec;
}
}
return null;
}
private HFSPlusForkData ReadHFSPlusForkData(Reader reader)
{
HFSPlusForkData item = new HFSPlusForkData();
item.logicalSize = reader.ReadUInt64();
item.clumpSize = reader.ReadUInt32();
item.totalBlocks = reader.ReadUInt32();
item.extents = ReadHFSPlusExtentRecord(reader);
return item;
}
private HFSPlusExtentDescriptor[] ReadHFSPlusExtentRecord(Reader reader)
{
HFSPlusExtentDescriptor[] item = new HFSPlusExtentDescriptor[8];
for (int i = 0; i < 8; i++)
{
item[i] = ReadHFSPlusExtentDescriptor(reader);
}
return item;
}
private HFSPlusExtentDescriptor ReadHFSPlusExtentDescriptor(Reader reader)
{
HFSPlusExtentDescriptor item = new HFSPlusExtentDescriptor();
item.startBlock = reader.ReadUInt32();
item.blockCount = reader.ReadUInt32();
return item;
}
private HFSPlusPermissions ReadHFSPlusPermissions(Reader reader)
{
HFSPlusPermissions item = new HFSPlusPermissions();
item.ownerID = reader.ReadUInt32();
item.groupID = reader.ReadUInt32();
item.permissions = reader.ReadUInt32();
item.specialDevice = reader.ReadUInt32();
return item;
}
private HFSDInfo ReadHFSDInfo(Reader reader)
{
HFSDInfo item = new HFSDInfo();
item.rect = ReadHFSRect(reader);
item.flags = (HFSDInfoFlags)reader.ReadInt16();
item.location = ReadHFSPoint(reader);
item.view = reader.ReadInt16();
return item;
}
private HFSDXInfo ReadHFSDXInfo(Reader reader)
{
HFSDXInfo item = new HFSDXInfo();
item.scroll = ReadHFSPoint(reader);
item.openChain = reader.ReadInt32();
item.reserved = reader.ReadInt16();
item.comment = reader.ReadInt16();
item.putAway = reader.ReadInt32();
return item;
}
private HFSFInfo ReadHFSFInfo(Reader reader)
{
HFSFInfo item = new HFSFInfo();
item.type = reader.ReadFixedLengthString(4);
item.creator = reader.ReadFixedLengthString(4);
item.fdFlags = (HFSFInfoFlags)reader.ReadInt16();
item.location = ReadHFSPoint(reader);
item.parentFolderID = reader.ReadInt16();
return item;
}
private HFSFXInfo ReadHFSFXInfo(Reader reader)
{
HFSFXInfo item = new HFSFXInfo();
item.iconID = reader.ReadInt16();
item.reserved = reader.ReadBytes(8);
item.comment = reader.ReadInt16();
item.putAway = reader.ReadInt32();
return item;
}
private HFSRect ReadHFSRect(Reader reader)
{
HFSRect item = new HFSRect();
item.top = reader.ReadInt16();
item.bottom = reader.ReadInt16();
item.left = reader.ReadInt16();
item.right = reader.ReadInt16();
return item;
}
private HFSPoint ReadHFSPoint(Reader reader)
{
HFSPoint item = new HFSPoint();
item.x = reader.ReadInt16();
item.y = reader.ReadInt16();
return item;
}
private HFSExtentDescriptor[] ReadHFSExtentDescriptorArray(Reader reader, int count)
{
HFSExtentDescriptor[] items = new HFSExtentDescriptor[count];
for (int i = 0; i < count; i++)
{
items[i] = ReadHFSExtentDescriptor(reader);
}
return items;
}
private HFSExtentDescriptor ReadHFSExtentDescriptor(Reader reader)
{
HFSExtentDescriptor item = new HFSExtentDescriptor();
item.firstAllocationBlockIndex = reader.ReadInt16();
item.allocationBlockCount = reader.ReadInt16();
return item;
}
protected override void SaveInternal(ObjectModel objectModel)
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.FileSystem.Apple.HFS
{
public enum HFSDirectoryFlags : short
{
None = 0
}
}

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.FileSystem.Apple.HFS
{
public struct HFSExtentDescriptor
{
public short firstAllocationBlockIndex;
public short allocationBlockCount;
}
}

View File

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.FileSystem.Apple.HFS
{
[Flags()]
public enum HFSFileFlags : short
{
None = 0x00,
/// <summary>
/// If set, this file is locked and cannot be written to.
/// </summary>
Locked = 0x01,
/// <summary>
/// If set, a file thread record exists for this file.
/// </summary>
ThreadRecordExists = 0x02,
/// <summary>
/// If set, the file record is used.
/// </summary>
Used = 0x40
}
}

View File

@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.FileSystem.Apple.HFS
{
public enum HFSPlusTextEncoding
{
MacRoman = 0,
MacJapanese = 1,
MacChineseTraditional = 2,
MacKorean = 3,
MacArabic = 4,
MacHebrew = 5,
MacGreek = 6,
MacCyrillic = 7,
MacDevanagari = 9,
MacGurmukhi = 10,
MacGujarati = 11,
MacOriya = 12,
MacBengali = 13,
MacTamil = 14,
MacTelugu = 15,
MacKannada = 16,
MacMalayalam = 17,
MacSinhalese = 18,
MacBurmese = 19,
MacKhmer = 20,
MacThai = 21,
MacLaotian = 22,
MacGeorgian = 23,
MacArmenian = 24,
MacChineseSimplified = 25,
MacTibetan = 26,
MacMongolian = 27,
MacEthiopic = 28,
MacCentralEurRoman = 29,
MacVietnamese = 30,
MacExtArabic = 31,
MacSymbol = 33,
MacDingbats = 34,
MacTurkish = 35,
MacCroatian = 36,
MacIcelandic = 37,
MacRomanian = 38,
MacFarsi49 = 49,
MacFarsi140 = 140,
MacUkrainian48 = 48,
MacUkrainian152 = 152
}
}

View File

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.FileSystem.Apple.HFS
{
[Flags()]
public enum HFSVolumeAttributes : short
{
/// <summary>
/// Set if the volume is locked by hardware
/// </summary>
HardwareLocked = 0x0040,
/// <summary>
/// Set if the volume was successfully unmounted
/// </summary>
SuccessfullyUnmounted = 0x0080,
/// <summary>
/// Set if the volume has had its bad blocks spared
/// </summary>
BadBlocksSpared = 0x0100,
/// <summary>
/// Set if the volume is locked by software
/// </summary>
SoftwareLocked = 0x0400
}
}

View File

@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.FileSystem.Apple.HFS.Internal.CatalogRecords
{
internal class HFSCatalogDirectoryRecord : HFSCatalogRecord
{
/// <summary>
/// Directory flags.
/// </summary>
public HFSDirectoryFlags flags;
/// <summary>
/// The directory valence (the number of files and folders directly contained by this
/// folder). This is equal to the number of file and folder records whose key's parentID is
/// equal to this folder's folderID.
/// </summary>
/// <remarks>
/// The current Mac OS File Manager programming interfaces require folders to have a valence
/// less than 32,767. An implementation must enforce this restriction if it wants the volume
/// to be usable by Mac OS. Values of 32,768 and larger are problematic; 32,767 and smaller
/// are OK. It's an implementation restriction for the older Mac OS APIs; items 32,768 and
/// beyond would be unreachable by PBGetCatInfo. As a practical matter, many programs are
/// likely to fails with anywhere near that many items in a single folder. So, the volume
/// format allows more than 32,767 items in a folder, but it's probably not a good idea to
/// exceed that limit right now.
/// </remarks>
public int directoryValence;
/// <summary>
/// The directory ID.
/// </summary>
public int directoryID;
/// <summary>
/// The date and time this directory was created.
/// </summary>
public int creationTimestamp;
/// <summary>
/// The date and time this directory was last modified.
/// </summary>
public int modificationTimestamp;
/// <summary>
/// HFS+ only. The date and time at which a named fork of this directory was last modified.
/// </summary>
public int attributeModificationTimestamp;
/// <summary>
/// HFS+ only.
/// </summary>
public int lastAccessTimestamp;
/// <summary>
/// The date and time this directory was last backed up.
/// </summary>
public int lastBackupTimestamp;
public HFSPlusPermissions permissions;
/// <summary>
/// Information used by the Finder.
/// </summary>
public HFSDInfo finderUserInformation;
/// <summary>
/// Additional information used by the Finder.
/// </summary>
public HFSDXInfo finderAdditionalInformation;
public HFSPlusTextEncoding textEncoding;
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.FileSystem.Apple.HFS.Internal.CatalogRecords
{
internal class HFSCatalogDirectoryThreadRecord : HFSCatalogRecord
{
public int[/*2*/] reserved2;
/// <summary>
/// Parent ID for this directory.
/// </summary>
public int parentID;
/// <summary>
/// File name of this directory.
/// </summary>
public string fileName;
}
}

View File

@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.FileSystem.Apple.HFS.Internal.CatalogRecords
{
internal class HFSCatalogFileRecord : HFSCatalogRecord
{
/// <summary>
/// File flags.
/// </summary>
public HFSFileFlags flags;
/// <summary>
/// The file type. This field should always contain 0.
/// </summary>
public sbyte fileType;
/// <summary>
/// The file's Finder information.
/// </summary>
public HFSFInfo finderUserInformation;
/// <summary>
/// The file ID.
/// </summary>
public int fileID;
/// <summary>
/// The first allocation block of the data fork.
/// </summary>
public short dataForkFirstAllocationBlock;
/// <summary>
/// The logical EOF of the data fork.
/// </summary>
public int dataForkLogicalEOF;
/// <summary>
/// The physical EOF of the data fork.
/// </summary>
public int dataForkPhysicalEOF;
/// <summary>
/// The first allocation block of the resource fork.
/// </summary>
public short resourceForkFirstAllocationBlock;
/// <summary>
/// The logical EOF of the resource fork.
/// </summary>
public int resourceForkLogicalEOF;
/// <summary>
/// The physical EOF of the resource fork.
/// </summary>
public int resourceForkPhysicalEOF;
/// <summary>
/// The date and time this file was created.
/// </summary>
public int creationTimestamp;
/// <summary>
/// The date and time this file was last modified.
/// </summary>
public int modificationTimestamp;
/// <summary>
/// HFS+ only
/// </summary>
public int attributeModificationTimestamp;
/// <summary>
/// HFS+ only
/// </summary>
public int lastAccessTimestamp;
/// <summary>
/// The date and time this file was last backed up.
/// </summary>
public int lastBackupTimestamp;
/// <summary>
/// HFS+ only
/// </summary>
public HFSPlusPermissions permissions;
/// <summary>
/// Additional information used by the Finder.
/// </summary>
public HFSFXInfo finderAdditionalInformation;
/// <summary>
/// HFS+ only
/// </summary>
public HFSPlusTextEncoding textEncoding;
/// <summary>
/// The file clump size.
/// </summary>
public short fileClumpSize;
/// <summary>
/// The first extent record of the file's data fork.
/// </summary>
public HFSExtentDescriptor[] firstDataForkExtentRecord;
/// <summary>
/// The first extent record of the file's resource fork.
/// </summary>
public HFSExtentDescriptor[] firstResourceForkExtentRecord;
/// <summary>
/// Reserved.
/// </summary>
public int reserved2;
/// <summary>
/// HFS+ only
/// </summary>
public HFSPlusForkData dataFork;
/// <summary>
/// HFS+ only
/// </summary>
public HFSPlusForkData resourceFork;
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.FileSystem.Apple.HFS.Internal.CatalogRecords
{
internal class HFSCatalogFileThreadRecord : HFSCatalogRecord
{
public int[/*2*/] reserved2;
/// <summary>
/// Parent ID for this file.
/// </summary>
public int parentID;
/// <summary>
/// File name of this file.
/// </summary>
public string fileName;
}
}

View File

@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.FileSystem.Apple.HFS.Internal
{
internal enum HFSCatalogRecordType : short
{
/// <summary>
/// HFS+ folder record
/// </summary>
ExtendedDirectory = 0x0001,
/// <summary>
/// HFS+ file record
/// </summary>
ExtendedFile = 0x0002,
/// <summary>
/// HFS+ folder thread record
/// </summary>
ExtendedDirectoryThread = 0x0003,
/// <summary>
/// HFS+ file thread record
/// </summary>
ExtendedFileThread = 0x0004,
/// <summary>
/// HFS folder record
/// </summary>
Directory = 0x0100,
/// <summary>
/// HFS file record
/// </summary>
File = 0x0200,
/// <summary>
/// HFS folder thread record
/// </summary>
DirectoryThread = 0x0300,
/// <summary>
/// HFS file thread record
/// </summary>
FileThread = 0x0400
}
internal class HFSCatalogRecord
{
public HFSCatalogRecordType type;
}
}

View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.FileSystem.Apple.HFS.Internal
{
internal enum HFSDInfoFlags : short
{
Inited = 0x0100,
Locked = 0x1000,
Invisible = 0x4000
}
internal struct HFSDInfo
{
// hfs_finfo
public HFSRect rect;
public HFSDInfoFlags flags;
public HFSPoint location;
public short view;
}
}

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.FileSystem.Apple.HFS.Internal
{
internal struct HFSDXInfo
{
public HFSPoint scroll;
public int openChain;
public short reserved;
public short comment;
public int putAway;
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.FileSystem.Apple.HFS.Internal
{
internal enum HFSFInfoFlags : short
{
Inited = 0x0100,
Locked = 0x1000,
Invisible = 0x4000
}
internal struct HFSFInfo
{
// hfs_finfo
public string type;
public string creator;
public HFSFInfoFlags fdFlags;
public HFSPoint location;
public short parentFolderID;
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.FileSystem.Apple.HFS.Internal
{
internal struct HFSFXInfo
{
public short iconID;
public byte[] reserved;
public short comment;
public int putAway;
}
}

View File

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.FileSystem.Apple.HFS
{
internal struct HFSMasterDirectoryBlock
{
public int creationTimestamp;
public int modificationTimestamp;
public HFSVolumeAttributes volumeAttributes;
public ushort rootDirectoryFileCount;
public ushort volumeBitmapFirstBlockIndex;
public short nextAllocationSearchStart;
public ushort allocationBlockCount;
public int allocationBlockSize;
public int defaultClumpSize;
public short firstAllocationBlockIndex;
public int nextUnusedCatalogNodeID;
public ushort unusedAllocationBlockCount;
public int lastBackupTimestamp;
public int clumpSizeForExtentsOverflowFile;
public int clumpSizeForCatalogFile;
public ushort rootDirectoryDirectoryCount;
public int totalFileCount;
public int totalDirectoryCount;
public int[] finderInfo;
public ushort volumeCacheBlockCount;
public ushort volumeBitmapCacheBlockCount;
public ushort commonVolumeCacheBlockCount;
public HFSExtentDescriptor[] extentRecordsForExtentsOverflowFile;
public HFSExtentDescriptor[] extentRecordsForCatalogFile;
}
}

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.FileSystem.Apple.HFS.Internal
{
internal struct HFSPlusExtentDescriptor
{
public uint startBlock;
public uint blockCount;
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.FileSystem.Apple.HFS.Internal
{
internal struct HFSPlusForkData
{
public ulong logicalSize;
public uint clumpSize;
public uint totalBlocks;
public HFSPlusExtentDescriptor[] extents;
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.FileSystem.Apple.HFS.Internal
{
internal struct HFSPlusPermissions
{
public uint ownerID;
public uint groupID;
public uint permissions;
public uint specialDevice;
}
}

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.FileSystem.Apple.HFS.Internal
{
internal struct HFSPoint
{
public short x;
public short y;
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.FileSystem.Apple.HFS.Internal
{
internal struct HFSRect
{
public short top;
public short bottom;
public short left;
public short right;
}
}

View File

@ -44,6 +44,27 @@
<Compile Include="DataFormats\FileSystem\ALTools\EGG\EGGDataFormat.cs" />
<Compile Include="DataFormats\FileSystem\ALTools\EGG\Internal\BlockInfo.cs" />
<Compile Include="DataFormats\FileSystem\ALTools\EGG\Internal\FileInfo.cs" />
<Compile Include="DataFormats\FileSystem\Apple\HFS\HFSDataFormat.cs" />
<Compile Include="DataFormats\FileSystem\Apple\HFS\HFSDirectoryFlags.cs" />
<Compile Include="DataFormats\FileSystem\Apple\HFS\HFSExtentDescriptor.cs" />
<Compile Include="DataFormats\FileSystem\Apple\HFS\HFSFileFlags.cs" />
<Compile Include="DataFormats\FileSystem\Apple\HFS\Internal\CatalogRecords\HFSCatalogFileThreadRecord.cs" />
<Compile Include="DataFormats\FileSystem\Apple\HFS\Internal\CatalogRecords\HFSCatalogDirectoryThreadRecord.cs" />
<Compile Include="DataFormats\FileSystem\Apple\HFS\Internal\CatalogRecords\HFSCatalogFileRecord.cs" />
<Compile Include="DataFormats\FileSystem\Apple\HFS\Internal\CatalogRecords\HFSCatalogDirectoryRecord.cs" />
<Compile Include="DataFormats\FileSystem\Apple\HFS\Internal\HFSDInfo.cs" />
<Compile Include="DataFormats\FileSystem\Apple\HFS\Internal\HFSDXInfo.cs" />
<Compile Include="DataFormats\FileSystem\Apple\HFS\Internal\HFSCatalogRecord.cs" />
<Compile Include="DataFormats\FileSystem\Apple\HFS\Internal\HFSFInfo.cs" />
<Compile Include="DataFormats\FileSystem\Apple\HFS\Internal\HFSFXInfo.cs" />
<Compile Include="DataFormats\FileSystem\Apple\HFS\Internal\HFSMasterDirectoryBlock.cs" />
<Compile Include="DataFormats\FileSystem\Apple\HFS\HFSVolumeAttributes.cs" />
<Compile Include="DataFormats\FileSystem\Apple\HFS\Internal\HFSPlusExtentDescriptor.cs" />
<Compile Include="DataFormats\FileSystem\Apple\HFS\Internal\HFSPlusForkData.cs" />
<Compile Include="DataFormats\FileSystem\Apple\HFS\Internal\HFSPlusPermissions.cs" />
<Compile Include="DataFormats\FileSystem\Apple\HFS\HFSPlusTextEncoding.cs" />
<Compile Include="DataFormats\FileSystem\Apple\HFS\Internal\HFSPoint.cs" />
<Compile Include="DataFormats\FileSystem\Apple\HFS\Internal\HFSRect.cs" />
<Compile Include="DataFormats\FileSystem\Aquarnoid\GOB\GOBDataFormat.cs" />
<Compile Include="DataFormats\FileSystem\ARC\ARCDataFormat.cs" />
<Compile Include="DataFormats\FileSystem\ARJ\ARJCompressionMethod.cs" />