Add support for Human68k 18.3 filenames in FAT.

This commit is contained in:
2019-04-28 18:12:44 +01:00
parent baf6f46eb2
commit 2d660035a9
5 changed files with 94 additions and 18 deletions

View File

@@ -221,7 +221,8 @@ namespace DiscImageChef.Filesystems.FAT
Nt, Nt,
Lfn, Lfn,
Os2, Os2,
Ecs Ecs,
Human
} }
[Flags] [Flags]

View File

@@ -211,6 +211,26 @@ namespace DiscImageChef.Filesystems.FAT
if(extension != "") filename = name + "." + extension; if(extension != "") filename = name + "." + extension;
else filename = name; else filename = name;
if(@namespace == Namespace.Human)
{
HumanDirectoryEntry humanEntry =
Marshal.ByteArrayToStructureLittleEndian<HumanDirectoryEntry>(directoryBuffer, pos,
Marshal
.SizeOf<HumanDirectoryEntry
>());
completeEntry.HumanDirent = humanEntry;
name = StringHandlers.CToString(humanEntry.name1, Encoding).TrimEnd();
extension = StringHandlers.CToString(humanEntry.extension, Encoding).TrimEnd();
string name2 = StringHandlers.CToString(humanEntry.name2, Encoding).TrimEnd();
if(extension != "") filename = name + name2 + "." + extension;
else filename = name + name2;
completeEntry.HumanName = filename;
}
// Using array accessor ensures that repeated entries just get substituted. // Using array accessor ensures that repeated entries just get substituted.
// Repeated entries are not allowed but some bad implementations (e.g. FAT32.IFS)allow to create them // Repeated entries are not allowed but some bad implementations (e.g. FAT32.IFS)allow to create them
// when using spaces // when using spaces

View File

@@ -127,17 +127,20 @@ namespace DiscImageChef.Filesystems.FAT
stat = new FileEntryInfo stat = new FileEntryInfo
{ {
Attributes = new FileAttributes(), Attributes = new FileAttributes(),
Blocks = entry.size / bytesPerCluster, Blocks = entry.size / bytesPerCluster,
BlockSize = bytesPerCluster, BlockSize = bytesPerCluster,
Length = entry.size, Length = entry.size,
Inode = (ulong)(fat32 ? (entry.ea_handle << 16) + entry.start_cluster : entry.start_cluster), Inode = (ulong)(fat32 ? (entry.ea_handle << 16) + entry.start_cluster : entry.start_cluster),
Links = 1, Links = 1,
CreationTime = DateHandlers.DosToDateTime(entry.cdate, entry.ctime), CreationTime = DateHandlers.DosToDateTime(entry.cdate, entry.ctime)
LastWriteTime = DateHandlers.DosToDateTime(entry.mdate, entry.mtime)
}; };
stat.CreationTime = stat.CreationTime?.AddMilliseconds(entry.ctime_ms * 10); if(@namespace != Namespace.Human)
{
stat.LastWriteTime = DateHandlers.DosToDateTime(entry.mdate, entry.mtime);
stat.CreationTime = stat.CreationTime?.AddMilliseconds(entry.ctime_ms * 10);
}
if(entry.size % bytesPerCluster > 0) stat.Blocks++; if(entry.size % bytesPerCluster > 0) stat.Blocks++;

View File

@@ -867,6 +867,22 @@ namespace DiscImageChef.Filesystems.FAT
public readonly uint size; public readonly uint size;
} }
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct HumanDirectoryEntry
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public readonly byte[] name1;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public readonly byte[] extension;
public readonly FatAttributes attributes;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public readonly byte[] name2;
public readonly ushort mtime;
public readonly ushort mdate;
public readonly ushort start_cluster;
public readonly uint size;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)] [StructLayout(LayoutKind.Sequential, Pack = 1)]
struct LfnEntry struct LfnEntry
{ {
@@ -897,17 +913,22 @@ namespace DiscImageChef.Filesystems.FAT
class CompleteDirectoryEntry class CompleteDirectoryEntry
{ {
public DirectoryEntry Dirent; public DirectoryEntry Dirent;
public DirectoryEntry Fat32Ea; public DirectoryEntry Fat32Ea;
public string Lfn; public HumanDirectoryEntry HumanDirent;
public string Longname; public string HumanName;
public string Shortname; public string Lfn;
public string Longname;
public string Shortname;
public override string ToString() public override string ToString()
{ {
// This ensures LFN takes preference when eCS is in use // This ensures LFN takes preference when eCS is in use
if(!string.IsNullOrEmpty(Lfn)) return Lfn; if(!string.IsNullOrEmpty(Lfn)) return Lfn;
// This ensures Humans takes preference when present
if(!string.IsNullOrEmpty(HumanName)) return HumanName;
return !string.IsNullOrEmpty(Longname) ? Longname : Shortname; return !string.IsNullOrEmpty(Longname) ? Longname : Shortname;
} }
} }

View File

@@ -60,7 +60,6 @@ namespace DiscImageChef.Filesystems.FAT
public Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, public Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding,
Dictionary<string, string> options, string @namespace) Dictionary<string, string> options, string @namespace)
{ {
Encoding = encoding ?? Encoding.GetEncoding("IBM437");
XmlFsType = new FileSystemType(); XmlFsType = new FileSystemType();
if(options == null) options = GetDefaultOptions(); if(options == null) options = GetDefaultOptions();
if(options.TryGetValue("debug", out string debugString)) bool.TryParse(debugString, out debug); if(options.TryGetValue("debug", out string debugString)) bool.TryParse(debugString, out debug);
@@ -85,6 +84,9 @@ namespace DiscImageChef.Filesystems.FAT
case "lfn": case "lfn":
this.@namespace = Namespace.Lfn; this.@namespace = Namespace.Lfn;
break; break;
case "human":
this.@namespace = Namespace.Human;
break;
default: return Errno.InvalidArgument; default: return Errno.InvalidArgument;
} }
@@ -227,10 +229,21 @@ namespace DiscImageChef.Filesystems.FAT
} }
case BpbKind.Human: case BpbKind.Human:
// If not debug set Human68k namespace and ShiftJIS codepage as defaults
if(!debug)
{
this.@namespace = Namespace.Human;
encoding = Encoding.GetEncoding("shift_jis");
}
XmlFsType.Bootable = true; XmlFsType.Bootable = true;
break; break;
} }
Encoding = encoding ?? (bpbKind == BpbKind.Human
? Encoding.GetEncoding("shift_jis")
: Encoding.GetEncoding("IBM437"));
ulong firstRootSector = 0; ulong firstRootSector = 0;
if(!fat32) if(!fat32)
@@ -527,6 +540,26 @@ namespace DiscImageChef.Filesystems.FAT
completeEntry.Shortname = filename; completeEntry.Shortname = filename;
if(this.@namespace == Namespace.Human)
{
HumanDirectoryEntry humanEntry =
Marshal.ByteArrayToStructureLittleEndian<HumanDirectoryEntry>(rootDirectory, i,
Marshal
.SizeOf<HumanDirectoryEntry
>());
completeEntry.HumanDirent = humanEntry;
name = StringHandlers.CToString(humanEntry.name1, Encoding).TrimEnd();
extension = StringHandlers.CToString(humanEntry.extension, Encoding).TrimEnd();
string name2 = StringHandlers.CToString(humanEntry.name2, Encoding).TrimEnd();
if(extension != "") filename = name + name2 + "." + extension;
else filename = name + name2;
completeEntry.HumanName = filename;
}
if(!fat32 && filename == "EA DATA. SF") if(!fat32 && filename == "EA DATA. SF")
{ {
eaDirEntry = entry; eaDirEntry = entry;
@@ -699,8 +732,6 @@ namespace DiscImageChef.Filesystems.FAT
} }
} }
System.Console.WriteLine("First cluster sector: {0}", firstClusterSector);
System.Console.WriteLine("Sectors per cluster: {0}", sectorsPerCluster);
mounted = true; mounted = true;
return Errno.NoError; return Errno.NoError;
} }