Implement OS/2 and eCS namespaces using .LONGNAME EA in FAT12 and FAT16.

This commit is contained in:
2019-04-27 22:21:13 +01:00
parent fe4bcd63f2
commit b2c008eb02
5 changed files with 170 additions and 60 deletions

View File

@@ -74,58 +74,9 @@ namespace DiscImageChef.Filesystems.FAT
if(entry.ea_handle == 0) return Errno.NoError;
int aIndex = entry.ea_handle >> 7;
// First 0x20 bytes are the magic number and unused words
ushort a = BitConverter.ToUInt16(cachedEaData, aIndex * 2 + 0x20);
eas = GetEas(entry.ea_handle);
ushort b = BitConverter.ToUInt16(cachedEaData, entry.ea_handle * 2 + 0x200);
uint eaCluster = (uint)(a + b);
if(b == EA_UNUSED) return Errno.NoError;
EaHeader header =
Marshal.ByteArrayToStructureLittleEndian<EaHeader>(cachedEaData, (int)(eaCluster * bytesPerCluster),
Marshal.SizeOf<EaHeader>());
if(header.magic != 0x4145) return Errno.NoError;
uint eaLen = BitConverter.ToUInt32(cachedEaData,
(int)(eaCluster * bytesPerCluster) + Marshal.SizeOf<EaHeader>());
byte[] eaData = new byte[eaLen];
Array.Copy(cachedEaData, (int)(eaCluster * bytesPerCluster) + Marshal.SizeOf<EaHeader>(), eaData, 0, eaLen);
eas = new Dictionary<string, byte[]>();
if(true) eas.Add("com.microsoft.os2.fea", eaData);
int pos = 4;
while(pos < eaData.Length)
{
byte fEA = eaData[pos++];
byte cbName = eaData[pos++];
ushort cbValue = BitConverter.ToUInt16(eaData, pos);
pos += 2;
string name = Encoding.ASCII.GetString(eaData, pos, cbName);
pos += cbName;
pos++;
byte[] data = new byte[cbValue];
Array.Copy(eaData, pos, data, 0, cbValue);
pos += cbValue;
// OS/2 System Attributes
if(name[0] == '.')
{
// This is WorkPlace System information so it's IBM
if(name == ".CLASSINFO") name = "com.ibm.os2.classinfo";
else name = "com.microsoft.os2" + name.ToLower();
}
eas.Add(name, data);
}
if(eas is null) return Errno.NoError;
eaCache.Add(path.ToLower(cultureInfo), eas);
xattrs = eas.Keys.ToList();
@@ -162,6 +113,64 @@ namespace DiscImageChef.Filesystems.FAT
return Errno.NoError;
}
Dictionary<string, byte[]> GetEas(ushort eaHandle)
{
int aIndex = eaHandle >> 7;
// First 0x20 bytes are the magic number and unused words
ushort a = BitConverter.ToUInt16(cachedEaData, aIndex * 2 + 0x20);
ushort b = BitConverter.ToUInt16(cachedEaData, eaHandle * 2 + 0x200);
uint eaCluster = (uint)(a + b);
if(b == EA_UNUSED) return null;
EaHeader header =
Marshal.ByteArrayToStructureLittleEndian<EaHeader>(cachedEaData, (int)(eaCluster * bytesPerCluster),
Marshal.SizeOf<EaHeader>());
if(header.magic != 0x4145) return null;
uint eaLen = BitConverter.ToUInt32(cachedEaData,
(int)(eaCluster * bytesPerCluster) + Marshal.SizeOf<EaHeader>());
byte[] eaData = new byte[eaLen];
Array.Copy(cachedEaData, (int)(eaCluster * bytesPerCluster) + Marshal.SizeOf<EaHeader>(), eaData, 0, eaLen);
Dictionary<string, byte[]> eas = new Dictionary<string, byte[]>();
if(debug) eas.Add("com.microsoft.os2.fea", eaData);
int pos = 4;
while(pos < eaData.Length)
{
byte fEA = eaData[pos++];
byte cbName = eaData[pos++];
ushort cbValue = BitConverter.ToUInt16(eaData, pos);
pos += 2;
string name = Encoding.ASCII.GetString(eaData, pos, cbName);
pos += cbName;
pos++;
byte[] data = new byte[cbValue];
Array.Copy(eaData, pos, data, 0, cbValue);
pos += cbValue;
// OS/2 System Attributes
if(name[0] == '.')
{
// This is WorkPlace System information so it's IBM
if(name == ".CLASSINFO") name = "com.ibm.os2.classinfo";
else name = "com.microsoft.os2" + name.ToLower();
}
eas.Add(name, data);
}
return eas;
}
void CacheEaData()
{
if(eaDirEntry.start_cluster == 0) return;