mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Added support for U.C.S.D. Pascal filesystem, closes #31
This commit is contained in:
@@ -1,3 +1,15 @@
|
|||||||
|
2016-07-31 Natalia Portillo <claunia@claunia.com>
|
||||||
|
|
||||||
|
* Dir.cs:
|
||||||
|
* File.cs:
|
||||||
|
* Info.cs:
|
||||||
|
* Super.cs:
|
||||||
|
* Consts.cs:
|
||||||
|
* Structs.cs:
|
||||||
|
* UCSDPascal.cs:
|
||||||
|
* DiscImageChef.Filesystems.csproj: Added support for U.C.S.D.
|
||||||
|
Pascal filesystem, closes #31
|
||||||
|
|
||||||
2016-07-31 Natalia Portillo <claunia@claunia.com>
|
2016-07-31 Natalia Portillo <claunia@claunia.com>
|
||||||
|
|
||||||
* Super.cs: Reports correct filesystem version on Statfs();
|
* Super.cs: Reports correct filesystem version on Statfs();
|
||||||
|
|||||||
@@ -71,6 +71,13 @@
|
|||||||
<Compile Include="LisaFS\File.cs" />
|
<Compile Include="LisaFS\File.cs" />
|
||||||
<Compile Include="LisaFS\Extent.cs" />
|
<Compile Include="LisaFS\Extent.cs" />
|
||||||
<Compile Include="LisaFS\Encoding.cs" />
|
<Compile Include="LisaFS\Encoding.cs" />
|
||||||
|
<Compile Include="UCSDPascal\UCSDPascal.cs" />
|
||||||
|
<Compile Include="UCSDPascal\Consts.cs" />
|
||||||
|
<Compile Include="UCSDPascal\File.cs" />
|
||||||
|
<Compile Include="UCSDPascal\Info.cs" />
|
||||||
|
<Compile Include="UCSDPascal\Structs.cs" />
|
||||||
|
<Compile Include="UCSDPascal\Super.cs" />
|
||||||
|
<Compile Include="UCSDPascal\Dir.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -105,6 +112,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="LisaFS\" />
|
<Folder Include="LisaFS\" />
|
||||||
|
<Folder Include="UCSDPascal\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="..\LICENSE.LGPL">
|
<EmbeddedResource Include="..\LICENSE.LGPL">
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
// Filename : Consts.cs
|
// Filename : Consts.cs
|
||||||
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||||
//
|
//
|
||||||
// Component : Component
|
// Component : U.C.S.D. Pascal filesystem plugin.
|
||||||
//
|
//
|
||||||
// --[ Description ] ----------------------------------------------------------
|
// --[ Description ] ----------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Description
|
// U.C.S.D. Pascal filesystem constants.
|
||||||
//
|
//
|
||||||
// --[ License ] --------------------------------------------------------------
|
// --[ License ] --------------------------------------------------------------
|
||||||
//
|
//
|
||||||
@@ -29,13 +29,32 @@
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Copyright © 2011-2016 Natalia Portillo
|
// Copyright © 2011-2016 Natalia Portillo
|
||||||
// ****************************************************************************/
|
// ****************************************************************************/
|
||||||
using System;
|
|
||||||
namespace DiscImageChef.Filesystems.UCSDPascal
|
namespace DiscImageChef.Filesystems.UCSDPascal
|
||||||
{
|
{
|
||||||
public class Consts
|
// Information from Call-A.P.P.L.E. Pascal Disk Directory Structure
|
||||||
|
public partial class PascalPlugin : Filesystem
|
||||||
{
|
{
|
||||||
public Consts()
|
enum PascalFileKind : short
|
||||||
{
|
{
|
||||||
|
/// <summary>Disk volume entry</summary>
|
||||||
|
Volume = 0,
|
||||||
|
/// <summary>File containing bad blocks</summary>
|
||||||
|
Bad,
|
||||||
|
/// <summary>Code file, machine executable</summary>
|
||||||
|
Code,
|
||||||
|
/// <summary>Text file, human readable</summary>
|
||||||
|
Text,
|
||||||
|
/// <summary>Information file for debugger</summary>
|
||||||
|
Info,
|
||||||
|
/// <summary>Data file</summary>
|
||||||
|
Data,
|
||||||
|
/// <summary>Graphics vectors</summary>
|
||||||
|
Graf,
|
||||||
|
/// <summary>Graphics screen image</summary>
|
||||||
|
Foto,
|
||||||
|
/// <summary>Security, not used</summary>
|
||||||
|
Secure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
// Filename : Dir.cs
|
// Filename : Dir.cs
|
||||||
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||||
//
|
//
|
||||||
// Component : Component
|
// Component : U.C.S.D. Pascal filesystem plugin.
|
||||||
//
|
//
|
||||||
// --[ Description ] ----------------------------------------------------------
|
// --[ Description ] ----------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Description
|
// Methods to handle show the U.C.S.D. Pascal catalog as a directory.
|
||||||
//
|
//
|
||||||
// --[ License ] --------------------------------------------------------------
|
// --[ License ] --------------------------------------------------------------
|
||||||
//
|
//
|
||||||
@@ -29,13 +29,35 @@
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Copyright © 2011-2016 Natalia Portillo
|
// Copyright © 2011-2016 Natalia Portillo
|
||||||
// ****************************************************************************/
|
// ****************************************************************************/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace DiscImageChef.Filesystems.UCSDPascal
|
namespace DiscImageChef.Filesystems.UCSDPascal
|
||||||
{
|
{
|
||||||
public class Dir
|
// Information from Call-A.P.P.L.E. Pascal Disk Directory Structure
|
||||||
|
public partial class PascalPlugin : Filesystem
|
||||||
{
|
{
|
||||||
public Dir()
|
public override Errno ReadDir(string path, ref List<string> contents)
|
||||||
{
|
{
|
||||||
|
if(!mounted)
|
||||||
|
return Errno.AccessDenied;
|
||||||
|
|
||||||
|
if(!string.IsNullOrEmpty(path) && string.Compare(path, "/", StringComparison.OrdinalIgnoreCase) != 0)
|
||||||
|
return Errno.NotSupported;
|
||||||
|
|
||||||
|
contents = new List<string>();
|
||||||
|
foreach(PascalFileEntry ent in fileEntries)
|
||||||
|
contents.Add(StringHandlers.PascalToString(ent.filename));
|
||||||
|
|
||||||
|
if(debug)
|
||||||
|
{
|
||||||
|
contents.Add("$");
|
||||||
|
contents.Add("$Boot");
|
||||||
|
}
|
||||||
|
|
||||||
|
contents.Sort();
|
||||||
|
return Errno.NoError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
// Filename : File.cs
|
// Filename : File.cs
|
||||||
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||||
//
|
//
|
||||||
// Component : Component
|
// Component : U.C.S.D. Pascal filesystem plugin.
|
||||||
//
|
//
|
||||||
// --[ Description ] ----------------------------------------------------------
|
// --[ Description ] ----------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Description
|
// Methods to handle files.
|
||||||
//
|
//
|
||||||
// --[ License ] --------------------------------------------------------------
|
// --[ License ] --------------------------------------------------------------
|
||||||
//
|
//
|
||||||
@@ -29,13 +29,142 @@
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Copyright © 2011-2016 Natalia Portillo
|
// Copyright © 2011-2016 Natalia Portillo
|
||||||
// ****************************************************************************/
|
// ****************************************************************************/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace DiscImageChef.Filesystems.UCSDPascal
|
namespace DiscImageChef.Filesystems.UCSDPascal
|
||||||
{
|
{
|
||||||
public class File
|
// Information from Call-A.P.P.L.E. Pascal Disk Directory Structure
|
||||||
|
public partial class PascalPlugin : Filesystem
|
||||||
{
|
{
|
||||||
public File()
|
public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
|
||||||
{
|
{
|
||||||
|
if(!mounted)
|
||||||
|
return Errno.AccessDenied;
|
||||||
|
|
||||||
|
return Errno.NotImplemented;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Errno GetAttributes(string path, ref FileAttributes attributes)
|
||||||
|
{
|
||||||
|
if(!mounted)
|
||||||
|
return Errno.AccessDenied;
|
||||||
|
|
||||||
|
string[] pathElements = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
if(pathElements.Length != 1)
|
||||||
|
return Errno.NotSupported;
|
||||||
|
|
||||||
|
PascalFileEntry entry;
|
||||||
|
Errno error = GetFileEntry(path, out entry);
|
||||||
|
|
||||||
|
if(error == Errno.NoError)
|
||||||
|
{
|
||||||
|
attributes = new FileAttributes();
|
||||||
|
attributes = FileAttributes.File;
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Errno Read(string path, long offset, long size, ref byte[] buf)
|
||||||
|
{
|
||||||
|
if(!mounted)
|
||||||
|
return Errno.AccessDenied;
|
||||||
|
|
||||||
|
string[] pathElements = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
if(pathElements.Length != 1)
|
||||||
|
return Errno.NotSupported;
|
||||||
|
|
||||||
|
byte[] file;
|
||||||
|
Errno error;
|
||||||
|
|
||||||
|
if(debug &&
|
||||||
|
(string.Compare(path, "$", StringComparison.InvariantCulture) == 0
|
||||||
|
|| string.Compare(path, "$Boot", StringComparison.InvariantCulture) == 0))
|
||||||
|
{
|
||||||
|
if(string.Compare(path, "$", StringComparison.InvariantCulture) == 0)
|
||||||
|
file = catalogBlocks;
|
||||||
|
else
|
||||||
|
file = bootBlocks;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PascalFileEntry entry;
|
||||||
|
error = GetFileEntry(path, out entry);
|
||||||
|
|
||||||
|
if(error != Errno.NoError)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
byte[] tmp = device.ReadSectors((ulong)entry.firstBlock, (uint)(entry.lastBlock - entry.firstBlock + 1));
|
||||||
|
file = new byte[(entry.lastBlock - entry.firstBlock) * device.GetSectorSize() + entry.lastBytes];
|
||||||
|
Array.Copy(tmp, 0, file, 0, file.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(offset >= file.Length || size == 0 || offset + size == file.Length)
|
||||||
|
{
|
||||||
|
buf = new byte[0];
|
||||||
|
return Errno.NoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(offset + size > file.Length)
|
||||||
|
size = file.Length - offset;
|
||||||
|
|
||||||
|
buf = new byte[size];
|
||||||
|
|
||||||
|
Array.Copy(file, offset, buf, 0, size);
|
||||||
|
|
||||||
|
return Errno.NoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Errno Stat(string path, ref FileEntryInfo stat)
|
||||||
|
{
|
||||||
|
if(!mounted)
|
||||||
|
return Errno.AccessDenied;
|
||||||
|
|
||||||
|
if(!mounted)
|
||||||
|
return Errno.AccessDenied;
|
||||||
|
|
||||||
|
string[] pathElements = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
if(pathElements.Length != 1)
|
||||||
|
return Errno.NotSupported;
|
||||||
|
|
||||||
|
PascalFileEntry entry;
|
||||||
|
Errno error = GetFileEntry(path, out entry);
|
||||||
|
|
||||||
|
if(error != Errno.NoError)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
stat = new FileEntryInfo();
|
||||||
|
stat.Attributes = new FileAttributes();
|
||||||
|
stat.Attributes = FileAttributes.File;
|
||||||
|
stat.Blocks = entry.lastBlock - entry.firstBlock + 1;
|
||||||
|
stat.BlockSize = device.GetSectorSize();
|
||||||
|
stat.DeviceNo = 0;
|
||||||
|
stat.GID = 0;
|
||||||
|
stat.Inode = 0;
|
||||||
|
stat.LastWriteTimeUtc = DateHandlers.UCSDPascalToDateTime(entry.mtime);
|
||||||
|
stat.Length = (entry.lastBlock - entry.firstBlock) * device.GetSectorSize() + entry.lastBytes;
|
||||||
|
stat.Links = 1;
|
||||||
|
stat.Mode = 0x124;
|
||||||
|
stat.UID = 0;
|
||||||
|
|
||||||
|
return Errno.NoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
Errno GetFileEntry(string path, out PascalFileEntry entry)
|
||||||
|
{
|
||||||
|
entry = new PascalFileEntry();
|
||||||
|
|
||||||
|
foreach(PascalFileEntry ent in fileEntries)
|
||||||
|
{
|
||||||
|
if(string.Compare(path, StringHandlers.PascalToString(ent.filename), StringComparison.InvariantCultureIgnoreCase) == 0)
|
||||||
|
{
|
||||||
|
entry = ent;
|
||||||
|
return Errno.NoError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Errno.NoSuchFile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
// Filename : Info.cs
|
// Filename : Info.cs
|
||||||
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||||
//
|
//
|
||||||
// Component : Component
|
// Component : U.C.S.D. Pascal filesystem plugin.
|
||||||
//
|
//
|
||||||
// --[ Description ] ----------------------------------------------------------
|
// --[ Description ] ----------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Description
|
// Identifies the U.C.S.D. Pascal filesystem and shows information.
|
||||||
//
|
//
|
||||||
// --[ License ] --------------------------------------------------------------
|
// --[ License ] --------------------------------------------------------------
|
||||||
//
|
//
|
||||||
@@ -29,13 +29,133 @@
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Copyright © 2011-2016 Natalia Portillo
|
// Copyright © 2011-2016 Natalia Portillo
|
||||||
// ****************************************************************************/
|
// ****************************************************************************/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace DiscImageChef.Filesystems.UCSDPascal
|
namespace DiscImageChef.Filesystems.UCSDPascal
|
||||||
{
|
{
|
||||||
public class Info
|
// Information from Call-A.P.P.L.E. Pascal Disk Directory Structure
|
||||||
|
public partial class PascalPlugin : Filesystem
|
||||||
{
|
{
|
||||||
public Info()
|
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionStart, ulong partitionEnd)
|
||||||
{
|
{
|
||||||
|
if(imagePlugin.GetSectors() < 3)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Blocks 0 and 1 are boot code
|
||||||
|
byte[] volBlock = imagePlugin.ReadSector(2 + partitionStart);
|
||||||
|
|
||||||
|
PascalVolumeEntry volEntry = new PascalVolumeEntry();
|
||||||
|
|
||||||
|
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
|
||||||
|
|
||||||
|
volEntry.firstBlock = BigEndianBitConverter.ToInt16(volBlock, 0x00);
|
||||||
|
volEntry.lastBlock = BigEndianBitConverter.ToInt16(volBlock, 0x02);
|
||||||
|
volEntry.entryType = (PascalFileKind)BigEndianBitConverter.ToInt16(volBlock, 0x04);
|
||||||
|
volEntry.volumeName = new byte[8];
|
||||||
|
Array.Copy(volBlock, 0x06, volEntry.volumeName, 0, 8);
|
||||||
|
volEntry.blocks = BigEndianBitConverter.ToInt16(volBlock, 0x0E);
|
||||||
|
volEntry.files = BigEndianBitConverter.ToInt16(volBlock, 0x10);
|
||||||
|
volEntry.dummy = BigEndianBitConverter.ToInt16(volBlock, 0x12);
|
||||||
|
volEntry.lastBoot = BigEndianBitConverter.ToInt16(volBlock, 0x14);
|
||||||
|
volEntry.tail = BigEndianBitConverter.ToInt32(volBlock, 0x16);
|
||||||
|
|
||||||
|
// First block is always 0 (even is it's sector 2)
|
||||||
|
if(volEntry.firstBlock != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Last volume record block must be after first block, and before end of device
|
||||||
|
if(volEntry.lastBlock <= volEntry.firstBlock || (ulong)volEntry.lastBlock > imagePlugin.GetSectors() - 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Volume record entry type must be volume or secure
|
||||||
|
if(volEntry.entryType != PascalFileKind.Volume && volEntry.entryType != PascalFileKind.Secure)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Volume name is max 7 characters
|
||||||
|
if(volEntry.volumeName[0] > 7)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Volume blocks is equal to volume sectors
|
||||||
|
if(volEntry.blocks < 0 || (ulong)volEntry.blocks != imagePlugin.GetSectors())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// There can be not less than zero files
|
||||||
|
if(volEntry.files < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionStart, ulong partitionEnd, out string information)
|
||||||
|
{
|
||||||
|
StringBuilder sbInformation = new StringBuilder();
|
||||||
|
information = "";
|
||||||
|
|
||||||
|
if(imagePlugin.GetSectors() < 3)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Blocks 0 and 1 are boot code
|
||||||
|
byte[] volBlock = imagePlugin.ReadSector(2 + partitionStart);
|
||||||
|
|
||||||
|
PascalVolumeEntry volEntry = new PascalVolumeEntry();
|
||||||
|
|
||||||
|
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
|
||||||
|
|
||||||
|
volEntry.firstBlock = BigEndianBitConverter.ToInt16(volBlock, 0x00);
|
||||||
|
volEntry.lastBlock = BigEndianBitConverter.ToInt16(volBlock, 0x02);
|
||||||
|
volEntry.entryType = (PascalFileKind)BigEndianBitConverter.ToInt16(volBlock, 0x04);
|
||||||
|
volEntry.volumeName = new byte[8];
|
||||||
|
Array.Copy(volBlock, 0x06, volEntry.volumeName, 0, 8);
|
||||||
|
volEntry.blocks = BigEndianBitConverter.ToInt16(volBlock, 0x0E);
|
||||||
|
volEntry.files = BigEndianBitConverter.ToInt16(volBlock, 0x10);
|
||||||
|
volEntry.dummy = BigEndianBitConverter.ToInt16(volBlock, 0x12);
|
||||||
|
volEntry.lastBoot = BigEndianBitConverter.ToInt16(volBlock, 0x14);
|
||||||
|
volEntry.tail = BigEndianBitConverter.ToInt32(volBlock, 0x16);
|
||||||
|
|
||||||
|
// First block is always 0 (even is it's sector 2)
|
||||||
|
if(volEntry.firstBlock != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Last volume record block must be after first block, and before end of device
|
||||||
|
if(volEntry.lastBlock <= volEntry.firstBlock || (ulong)volEntry.lastBlock > imagePlugin.GetSectors() - 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Volume record entry type must be volume or secure
|
||||||
|
if(volEntry.entryType != PascalFileKind.Volume && volEntry.entryType != PascalFileKind.Secure)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Volume name is max 7 characters
|
||||||
|
if(volEntry.volumeName[0] > 7)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Volume blocks is equal to volume sectors
|
||||||
|
if(volEntry.blocks < 0 || (ulong)volEntry.blocks != imagePlugin.GetSectors())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// There can be not less than zero files
|
||||||
|
if(volEntry.files < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sbInformation.AppendFormat("Volume record spans from block {0} to block {1}", volEntry.firstBlock, volEntry.lastBlock).AppendLine();
|
||||||
|
sbInformation.AppendFormat("Volume name: {0}", StringHandlers.PascalToString(volEntry.volumeName)).AppendLine();
|
||||||
|
sbInformation.AppendFormat("Volume has {0} blocks", volEntry.blocks).AppendLine();
|
||||||
|
sbInformation.AppendFormat("Volume has {0} files", volEntry.files).AppendLine();
|
||||||
|
sbInformation.AppendFormat("Volume last booted at {0}", DateHandlers.UCSDPascalToDateTime(volEntry.lastBoot)).AppendLine();
|
||||||
|
|
||||||
|
information = sbInformation.ToString();
|
||||||
|
|
||||||
|
xmlFSType = new Schemas.FileSystemType();
|
||||||
|
xmlFSType.Bootable = !ArrayHelpers.ArrayIsNullOrEmpty(imagePlugin.ReadSectors(partitionStart, 2));
|
||||||
|
xmlFSType.Clusters = volEntry.blocks;
|
||||||
|
xmlFSType.ClusterSize = (int)imagePlugin.GetSectorSize();
|
||||||
|
xmlFSType.Files = volEntry.files;
|
||||||
|
xmlFSType.FilesSpecified = true;
|
||||||
|
xmlFSType.Type = "UCSD Pascal";
|
||||||
|
xmlFSType.VolumeName = StringHandlers.PascalToString(volEntry.volumeName);
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
// Filename : Structs.cs
|
// Filename : Structs.cs
|
||||||
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||||
//
|
//
|
||||||
// Component : Component
|
// Component : U.C.S.D. Pascal filesystem plugin.
|
||||||
//
|
//
|
||||||
// --[ Description ] ----------------------------------------------------------
|
// --[ Description ] ----------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Description
|
// U.C.S.D. Pascal filesystem structures.
|
||||||
//
|
//
|
||||||
// --[ License ] --------------------------------------------------------------
|
// --[ License ] --------------------------------------------------------------
|
||||||
//
|
//
|
||||||
@@ -29,13 +29,48 @@
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Copyright © 2011-2016 Natalia Portillo
|
// Copyright © 2011-2016 Natalia Portillo
|
||||||
// ****************************************************************************/
|
// ****************************************************************************/
|
||||||
using System;
|
|
||||||
namespace DiscImageChef.Filesystems.UCSDPascal
|
namespace DiscImageChef.Filesystems.UCSDPascal
|
||||||
{
|
{
|
||||||
public class Structs
|
// Information from Call-A.P.P.L.E. Pascal Disk Directory Structure
|
||||||
|
public partial class PascalPlugin : Filesystem
|
||||||
{
|
{
|
||||||
public Structs()
|
struct PascalVolumeEntry
|
||||||
{
|
{
|
||||||
|
/// <summary>0x00, first block of volume entry</summary>
|
||||||
|
public short firstBlock;
|
||||||
|
/// <summary>0x02, last block of volume entry</summary>
|
||||||
|
public short lastBlock;
|
||||||
|
/// <summary>0x04, entry type</summary>
|
||||||
|
public PascalFileKind entryType;
|
||||||
|
/// <summary>0x06, volume name</summary>
|
||||||
|
public byte[] volumeName;
|
||||||
|
/// <summary>0x0E, block in volume</summary>
|
||||||
|
public short blocks;
|
||||||
|
/// <summary>0x10, files in volume</summary>
|
||||||
|
public short files;
|
||||||
|
/// <summary>0x12, dummy</summary>
|
||||||
|
public short dummy;
|
||||||
|
/// <summary>0x14, last booted</summary>
|
||||||
|
public short lastBoot;
|
||||||
|
/// <summary>0x16, tail to make record same size as <see cref="PascalFileEntry"/></summary>
|
||||||
|
public int tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PascalFileEntry
|
||||||
|
{
|
||||||
|
/// <summary>0x00, first block of file</summary>
|
||||||
|
public short firstBlock;
|
||||||
|
/// <summary>0x02, last block of file</summary>
|
||||||
|
public short lastBlock;
|
||||||
|
/// <summary>0x04, entry type</summary>
|
||||||
|
public PascalFileKind entryType;
|
||||||
|
/// <summary>0x06, file name</summary>
|
||||||
|
public byte[] filename;
|
||||||
|
/// <summary>0x16, bytes used in last block</summary>
|
||||||
|
public short lastBytes;
|
||||||
|
/// <summary>0x18, modification time</summary>
|
||||||
|
public short mtime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
// Filename : Super.cs
|
// Filename : Super.cs
|
||||||
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||||
//
|
//
|
||||||
// Component : Component
|
// Component : U.C.S.D. Pascal filesystem plugin.
|
||||||
//
|
//
|
||||||
// --[ Description ] ----------------------------------------------------------
|
// --[ Description ] ----------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Description
|
// Handles mounting and umounting the U.C.S.D. Pascal filesystem.
|
||||||
//
|
//
|
||||||
// --[ License ] --------------------------------------------------------------
|
// --[ License ] --------------------------------------------------------------
|
||||||
//
|
//
|
||||||
@@ -29,13 +29,108 @@
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Copyright © 2011-2016 Natalia Portillo
|
// Copyright © 2011-2016 Natalia Portillo
|
||||||
// ****************************************************************************/
|
// ****************************************************************************/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace DiscImageChef.Filesystems.UCSDPascal
|
namespace DiscImageChef.Filesystems.UCSDPascal
|
||||||
{
|
{
|
||||||
public class Super
|
// Information from Call-A.P.P.L.E. Pascal Disk Directory Structure
|
||||||
|
public partial class PascalPlugin : Filesystem
|
||||||
{
|
{
|
||||||
public Super()
|
public override Errno Mount()
|
||||||
{
|
{
|
||||||
|
return Mount(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Errno Mount(bool debug)
|
||||||
|
{
|
||||||
|
this.debug = debug;
|
||||||
|
if(device.GetSectors() < 3)
|
||||||
|
return Errno.InvalidArgument;
|
||||||
|
|
||||||
|
// Blocks 0 and 1 are boot code
|
||||||
|
catalogBlocks = device.ReadSector(2);
|
||||||
|
|
||||||
|
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
|
||||||
|
|
||||||
|
mountedVolEntry.firstBlock = BigEndianBitConverter.ToInt16(catalogBlocks, 0x00);
|
||||||
|
mountedVolEntry.lastBlock = BigEndianBitConverter.ToInt16(catalogBlocks, 0x02);
|
||||||
|
mountedVolEntry.entryType = (PascalFileKind)BigEndianBitConverter.ToInt16(catalogBlocks, 0x04);
|
||||||
|
mountedVolEntry.volumeName = new byte[8];
|
||||||
|
Array.Copy(catalogBlocks, 0x06, mountedVolEntry.volumeName, 0, 8);
|
||||||
|
mountedVolEntry.blocks = BigEndianBitConverter.ToInt16(catalogBlocks, 0x0E);
|
||||||
|
mountedVolEntry.files = BigEndianBitConverter.ToInt16(catalogBlocks, 0x10);
|
||||||
|
mountedVolEntry.dummy = BigEndianBitConverter.ToInt16(catalogBlocks, 0x12);
|
||||||
|
mountedVolEntry.lastBoot = BigEndianBitConverter.ToInt16(catalogBlocks, 0x14);
|
||||||
|
mountedVolEntry.tail = BigEndianBitConverter.ToInt32(catalogBlocks, 0x16);
|
||||||
|
|
||||||
|
if(mountedVolEntry.firstBlock != 0 || mountedVolEntry.lastBlock <= mountedVolEntry.firstBlock ||
|
||||||
|
(ulong)mountedVolEntry.lastBlock > device.GetSectors() - 2 ||
|
||||||
|
(mountedVolEntry.entryType != PascalFileKind.Volume && mountedVolEntry.entryType != PascalFileKind.Secure) ||
|
||||||
|
mountedVolEntry.volumeName[0] > 7 || mountedVolEntry.blocks < 0 || (ulong)mountedVolEntry.blocks != device.GetSectors() ||
|
||||||
|
mountedVolEntry.files < 0)
|
||||||
|
return Errno.InvalidArgument;
|
||||||
|
|
||||||
|
catalogBlocks = device.ReadSectors(2, (uint)(mountedVolEntry.lastBlock - mountedVolEntry.firstBlock - 2));
|
||||||
|
int offset = 26;
|
||||||
|
|
||||||
|
fileEntries = new List<PascalFileEntry>();
|
||||||
|
while(offset + 26 < catalogBlocks.Length)
|
||||||
|
{
|
||||||
|
PascalFileEntry entry = new PascalFileEntry();
|
||||||
|
entry.filename = new byte[16];
|
||||||
|
entry.firstBlock = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x00);
|
||||||
|
entry.lastBlock = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x02);
|
||||||
|
entry.entryType = (PascalFileKind)BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x04);
|
||||||
|
Array.Copy(catalogBlocks, offset + 0x06, entry.filename, 0, 16);
|
||||||
|
entry.lastBytes = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x16);
|
||||||
|
entry.mtime = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x18);
|
||||||
|
|
||||||
|
if(entry.filename[0] <= 15 && entry.filename[0] > 0)
|
||||||
|
fileEntries.Add(entry);
|
||||||
|
|
||||||
|
offset += 26;
|
||||||
|
}
|
||||||
|
|
||||||
|
bootBlocks = device.ReadSectors(0, 2);
|
||||||
|
|
||||||
|
xmlFSType = new Schemas.FileSystemType();
|
||||||
|
xmlFSType.Bootable = !ArrayHelpers.ArrayIsNullOrEmpty(bootBlocks);
|
||||||
|
xmlFSType.Clusters = mountedVolEntry.blocks;
|
||||||
|
xmlFSType.ClusterSize = (int)device.GetSectorSize();
|
||||||
|
xmlFSType.Files = mountedVolEntry.files;
|
||||||
|
xmlFSType.FilesSpecified = true;
|
||||||
|
xmlFSType.Type = "UCSD Pascal";
|
||||||
|
xmlFSType.VolumeName = StringHandlers.PascalToString(mountedVolEntry.volumeName);
|
||||||
|
|
||||||
|
mounted = true;
|
||||||
|
|
||||||
|
return Errno.NoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Errno Unmount()
|
||||||
|
{
|
||||||
|
mounted = false;
|
||||||
|
fileEntries = null;
|
||||||
|
return Errno.NoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Errno StatFs(ref FileSystemInfo stat)
|
||||||
|
{
|
||||||
|
stat = new FileSystemInfo();
|
||||||
|
stat.Blocks = mountedVolEntry.blocks;
|
||||||
|
stat.FilenameLength = 16;
|
||||||
|
stat.Files = (ulong)mountedVolEntry.files;
|
||||||
|
stat.FreeBlocks = 0;
|
||||||
|
stat.PluginId = PluginUUID;
|
||||||
|
stat.Type = "UCSD Pascal";
|
||||||
|
|
||||||
|
stat.FreeBlocks = mountedVolEntry.blocks - (mountedVolEntry.lastBlock - mountedVolEntry.firstBlock + 1);
|
||||||
|
foreach(PascalFileEntry entry in fileEntries)
|
||||||
|
stat.FreeBlocks -= (entry.lastBlock - entry.firstBlock + 1);
|
||||||
|
|
||||||
|
return Errno.NotImplemented;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
//
|
//
|
||||||
// --[ Description ] ----------------------------------------------------------
|
// --[ Description ] ----------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Identifies the U.C.S.D. Pascal filesystem and shows information.
|
// Constructors and common variables for the U.C.S.D. Pascal filesystem plugin.
|
||||||
//
|
//
|
||||||
// --[ License ] --------------------------------------------------------------
|
// --[ License ] --------------------------------------------------------------
|
||||||
//
|
//
|
||||||
@@ -32,266 +32,48 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
|
||||||
using DiscImageChef.ImagePlugins;
|
using DiscImageChef.ImagePlugins;
|
||||||
|
|
||||||
namespace DiscImageChef.Filesystems
|
namespace DiscImageChef.Filesystems.UCSDPascal
|
||||||
{
|
{
|
||||||
// Information from Call-A.P.P.L.E. Pascal Disk Directory Structure
|
// Information from Call-A.P.P.L.E. Pascal Disk Directory Structure
|
||||||
public class PascalPlugin : Filesystem
|
public partial class PascalPlugin : Filesystem
|
||||||
{
|
{
|
||||||
|
bool mounted;
|
||||||
|
bool debug;
|
||||||
|
readonly ImagePlugin device;
|
||||||
|
|
||||||
|
PascalVolumeEntry mountedVolEntry;
|
||||||
|
List<PascalFileEntry> fileEntries;
|
||||||
|
byte[] bootBlocks;
|
||||||
|
byte[] catalogBlocks;
|
||||||
|
|
||||||
public PascalPlugin()
|
public PascalPlugin()
|
||||||
{
|
{
|
||||||
Name = "U.C.S.D. Pascal filesystem";
|
Name = "U.C.S.D. Pascal filesystem";
|
||||||
PluginUUID = new Guid("B0AC2CB5-72AA-473A-9200-270B5A2C2D53");
|
PluginUUID = new Guid("B0AC2CB5-72AA-473A-9200-270B5A2C2D53");
|
||||||
}
|
}
|
||||||
|
|
||||||
public PascalPlugin(ImagePlugins.ImagePlugin imagePlugin, ulong partitionStart, ulong partitionEnd)
|
public PascalPlugin(ImagePlugin imagePlugin, ulong partitionStart, ulong partitionEnd)
|
||||||
{
|
{
|
||||||
|
device = imagePlugin;
|
||||||
Name = "U.C.S.D. Pascal filesystem";
|
Name = "U.C.S.D. Pascal filesystem";
|
||||||
PluginUUID = new Guid("B0AC2CB5-72AA-473A-9200-270B5A2C2D53");
|
PluginUUID = new Guid("B0AC2CB5-72AA-473A-9200-270B5A2C2D53");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionStart, ulong partitionEnd)
|
|
||||||
{
|
|
||||||
if(imagePlugin.GetSectors() < 3)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Blocks 0 and 1 are boot code
|
|
||||||
byte[] volBlock = imagePlugin.ReadSector(2 + partitionStart);
|
|
||||||
|
|
||||||
PascalVolumeEntry volEntry = new PascalVolumeEntry();
|
|
||||||
|
|
||||||
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
|
|
||||||
|
|
||||||
volEntry.firstBlock = BigEndianBitConverter.ToInt16(volBlock, 0x00);
|
|
||||||
volEntry.lastBlock = BigEndianBitConverter.ToInt16(volBlock, 0x02);
|
|
||||||
volEntry.entryType = (PascalFileKind)BigEndianBitConverter.ToInt16(volBlock, 0x04);
|
|
||||||
volEntry.volumeName = new byte[8];
|
|
||||||
Array.Copy(volBlock, 0x06, volEntry.volumeName, 0, 8);
|
|
||||||
volEntry.blocks = BigEndianBitConverter.ToInt16(volBlock, 0x0E);
|
|
||||||
volEntry.files = BigEndianBitConverter.ToInt16(volBlock, 0x10);
|
|
||||||
volEntry.dummy = BigEndianBitConverter.ToInt16(volBlock, 0x12);
|
|
||||||
volEntry.lastBoot = BigEndianBitConverter.ToInt16(volBlock, 0x14);
|
|
||||||
volEntry.tail = BigEndianBitConverter.ToInt32(volBlock, 0x16);
|
|
||||||
|
|
||||||
// First block is always 0 (even is it's sector 2)
|
|
||||||
if(volEntry.firstBlock != 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Last volume record block must be after first block, and before end of device
|
|
||||||
if(volEntry.lastBlock <= volEntry.firstBlock || (ulong)volEntry.lastBlock > imagePlugin.GetSectors() - 2)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Volume record entry type must be volume or secure
|
|
||||||
if(volEntry.entryType != PascalFileKind.Volume && volEntry.entryType != PascalFileKind.Secure)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Volume name is max 7 characters
|
|
||||||
if(volEntry.volumeName[0] > 7)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Volume blocks is equal to volume sectors
|
|
||||||
if(volEntry.blocks < 0 || (ulong)volEntry.blocks != imagePlugin.GetSectors())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// There can be not less than zero files
|
|
||||||
if(volEntry.files < 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionStart, ulong partitionEnd, out string information)
|
|
||||||
{
|
|
||||||
StringBuilder sbInformation = new StringBuilder();
|
|
||||||
information = "";
|
|
||||||
|
|
||||||
if(imagePlugin.GetSectors() < 3)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Blocks 0 and 1 are boot code
|
|
||||||
byte[] volBlock = imagePlugin.ReadSector(2 + partitionStart);
|
|
||||||
|
|
||||||
PascalVolumeEntry volEntry = new PascalVolumeEntry();
|
|
||||||
|
|
||||||
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
|
|
||||||
|
|
||||||
volEntry.firstBlock = BigEndianBitConverter.ToInt16(volBlock, 0x00);
|
|
||||||
volEntry.lastBlock = BigEndianBitConverter.ToInt16(volBlock, 0x02);
|
|
||||||
volEntry.entryType = (PascalFileKind)BigEndianBitConverter.ToInt16(volBlock, 0x04);
|
|
||||||
volEntry.volumeName = new byte[8];
|
|
||||||
Array.Copy(volBlock, 0x06, volEntry.volumeName, 0, 8);
|
|
||||||
volEntry.blocks = BigEndianBitConverter.ToInt16(volBlock, 0x0E);
|
|
||||||
volEntry.files = BigEndianBitConverter.ToInt16(volBlock, 0x10);
|
|
||||||
volEntry.dummy = BigEndianBitConverter.ToInt16(volBlock, 0x12);
|
|
||||||
volEntry.lastBoot = BigEndianBitConverter.ToInt16(volBlock, 0x14);
|
|
||||||
volEntry.tail = BigEndianBitConverter.ToInt32(volBlock, 0x16);
|
|
||||||
|
|
||||||
// First block is always 0 (even is it's sector 2)
|
|
||||||
if(volEntry.firstBlock != 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Last volume record block must be after first block, and before end of device
|
|
||||||
if(volEntry.lastBlock <= volEntry.firstBlock || (ulong)volEntry.lastBlock > imagePlugin.GetSectors() - 2)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Volume record entry type must be volume or secure
|
|
||||||
if(volEntry.entryType != PascalFileKind.Volume && volEntry.entryType != PascalFileKind.Secure)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Volume name is max 7 characters
|
|
||||||
if(volEntry.volumeName[0] > 7)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Volume blocks is equal to volume sectors
|
|
||||||
if(volEntry.blocks < 0 || (ulong)volEntry.blocks != imagePlugin.GetSectors())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// There can be not less than zero files
|
|
||||||
if(volEntry.files < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
sbInformation.AppendFormat("Volume record spans from block {0} to block {1}", volEntry.firstBlock, volEntry.lastBlock).AppendLine();
|
|
||||||
sbInformation.AppendFormat("Volume name: {0}", StringHandlers.PascalToString(volEntry.volumeName)).AppendLine();
|
|
||||||
sbInformation.AppendFormat("Volume has {0} blocks", volEntry.blocks).AppendLine();
|
|
||||||
sbInformation.AppendFormat("Volume has {0} files", volEntry.files).AppendLine();
|
|
||||||
sbInformation.AppendFormat("Volume last booted at {0}", DateHandlers.UCSDPascalToDateTime(volEntry.lastBoot)).AppendLine();
|
|
||||||
|
|
||||||
information = sbInformation.ToString();
|
|
||||||
|
|
||||||
byte[] bootBlocks = imagePlugin.ReadSectors(partitionStart, 2);
|
|
||||||
|
|
||||||
xmlFSType = new Schemas.FileSystemType();
|
|
||||||
xmlFSType.Bootable = !ArrayHelpers.ArrayIsNullOrEmpty(bootBlocks);
|
|
||||||
xmlFSType.Clusters = volEntry.blocks;
|
|
||||||
xmlFSType.ClusterSize = (int)imagePlugin.GetSectorSize();
|
|
||||||
xmlFSType.Files = volEntry.files;
|
|
||||||
xmlFSType.FilesSpecified = true;
|
|
||||||
xmlFSType.Type = "UCSD Pascal";
|
|
||||||
xmlFSType.VolumeName = StringHandlers.PascalToString(volEntry.volumeName);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum PascalFileKind : short
|
|
||||||
{
|
|
||||||
/// <summary>Disk volume entry</summary>
|
|
||||||
Volume = 0,
|
|
||||||
/// <summary>File containing bad blocks</summary>
|
|
||||||
Bad,
|
|
||||||
/// <summary>Code file, machine executable</summary>
|
|
||||||
Code,
|
|
||||||
/// <summary>Text file, human readable</summary>
|
|
||||||
Text,
|
|
||||||
/// <summary>Information file for debugger</summary>
|
|
||||||
Info,
|
|
||||||
/// <summary>Data file</summary>
|
|
||||||
Data,
|
|
||||||
/// <summary>Graphics vectors</summary>
|
|
||||||
Graf,
|
|
||||||
/// <summary>Graphics screen image</summary>
|
|
||||||
Foto,
|
|
||||||
/// <summary>Security, not used</summary>
|
|
||||||
Secure
|
|
||||||
}
|
|
||||||
|
|
||||||
struct PascalVolumeEntry
|
|
||||||
{
|
|
||||||
/// <summary>0x00, first block of volume entry</summary>
|
|
||||||
public short firstBlock;
|
|
||||||
/// <summary>0x02, last block of volume entry</summary>
|
|
||||||
public short lastBlock;
|
|
||||||
/// <summary>0x04, entry type</summary>
|
|
||||||
public PascalFileKind entryType;
|
|
||||||
/// <summary>0x06, volume name</summary>
|
|
||||||
public byte[] volumeName;
|
|
||||||
/// <summary>0x0E, block in volume</summary>
|
|
||||||
public short blocks;
|
|
||||||
/// <summary>0x10, files in volume</summary>
|
|
||||||
public short files;
|
|
||||||
/// <summary>0x12, dummy</summary>
|
|
||||||
public short dummy;
|
|
||||||
/// <summary>0x14, last booted</summary>
|
|
||||||
public short lastBoot;
|
|
||||||
/// <summary>0x16, tail to make record same size as <see cref="PascalFileEntry"/></summary>
|
|
||||||
public int tail;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct PascalFileEntry
|
|
||||||
{
|
|
||||||
/// <summary>0x00, first block of file</summary>
|
|
||||||
public short firstBlock;
|
|
||||||
/// <summary>0x02, last block of file</summary>
|
|
||||||
public short lastBlock;
|
|
||||||
/// <summary>0x04, entry type</summary>
|
|
||||||
public PascalFileKind entryType;
|
|
||||||
/// <summary>0x06, file name</summary>
|
|
||||||
public byte[] filename;
|
|
||||||
/// <summary>0x16, bytes used in last block</summary>
|
|
||||||
public short lastBytes;
|
|
||||||
/// <summary>0x18, modification time</summary>
|
|
||||||
public short mtime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Errno Mount()
|
|
||||||
{
|
|
||||||
return Errno.NotImplemented;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Errno Mount(bool debug)
|
|
||||||
{
|
|
||||||
return Errno.NotImplemented;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Errno Unmount()
|
|
||||||
{
|
|
||||||
return Errno.NotImplemented;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
|
|
||||||
{
|
|
||||||
return Errno.NotImplemented;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Errno GetAttributes(string path, ref FileAttributes attributes)
|
|
||||||
{
|
|
||||||
return Errno.NotImplemented;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Errno ListXAttr(string path, ref List<string> xattrs)
|
public override Errno ListXAttr(string path, ref List<string> xattrs)
|
||||||
{
|
{
|
||||||
return Errno.NotImplemented;
|
return Errno.NotSupported;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Errno GetXattr(string path, string xattr, ref byte[] buf)
|
public override Errno GetXattr(string path, string xattr, ref byte[] buf)
|
||||||
{
|
{
|
||||||
return Errno.NotImplemented;
|
return Errno.NotSupported;
|
||||||
}
|
|
||||||
|
|
||||||
public override Errno Read(string path, long offset, long size, ref byte[] buf)
|
|
||||||
{
|
|
||||||
return Errno.NotImplemented;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Errno ReadDir(string path, ref List<string> contents)
|
|
||||||
{
|
|
||||||
return Errno.NotImplemented;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Errno StatFs(ref FileSystemInfo stat)
|
|
||||||
{
|
|
||||||
return Errno.NotImplemented;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Errno Stat(string path, ref FileEntryInfo stat)
|
|
||||||
{
|
|
||||||
return Errno.NotImplemented;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Errno ReadLink(string path, ref string dest)
|
public override Errno ReadLink(string path, ref string dest)
|
||||||
{
|
{
|
||||||
return Errno.NotImplemented;
|
return Errno.NotSupported;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
2016-07-31 Natalia Portillo <claunia@claunia.com>
|
||||||
|
|
||||||
|
* DateHandlers.cs: Added support for U.C.S.D. Pascal
|
||||||
|
filesystem, closes #31
|
||||||
|
|
||||||
2016-07-29 Natalia Portillo <claunia@claunia.com>
|
2016-07-29 Natalia Portillo <claunia@claunia.com>
|
||||||
|
|
||||||
* DiscImageChef.Helpers.csproj: Bump to version 3.1.0.
|
* DiscImageChef.Helpers.csproj: Bump to version 3.1.0.
|
||||||
|
|||||||
@@ -140,6 +140,16 @@ namespace DiscImageChef
|
|||||||
temp = temp.AddMinutes(minutes);
|
temp = temp.AddMinutes(minutes);
|
||||||
return temp.AddMilliseconds(ticks * 20);
|
return temp.AddMilliseconds(ticks * 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static DateTime UCSDPascalToDateTime(short dateRecord)
|
||||||
|
{
|
||||||
|
int year = ((dateRecord & 0xFE00) >> 9) + 1900;
|
||||||
|
int day = (dateRecord & 0x01F0) >> 4;
|
||||||
|
int month = (dateRecord & 0x000F);
|
||||||
|
|
||||||
|
DicConsole.DebugWriteLine("UCSDPascalToDateTime handler", "dateRecord = 0x{0:X4}, year = {1}, month = {2}, day = {3}", dateRecord, year, month, day);
|
||||||
|
return new DateTime(year, month, day);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ Supported partitioning schemes
|
|||||||
Supported file systems for read-only operations
|
Supported file systems for read-only operations
|
||||||
===============================================
|
===============================================
|
||||||
* Apple Lisa file system
|
* Apple Lisa file system
|
||||||
|
* U.C.S.D Pascal file system
|
||||||
|
|
||||||
Supported file systems for identification and information only
|
Supported file systems for identification and information only
|
||||||
==============================================================
|
==============================================================
|
||||||
|
|||||||
1
TODO
1
TODO
@@ -21,7 +21,6 @@ Filesystem plugins:
|
|||||||
--- Add support for SFS filesystem
|
--- Add support for SFS filesystem
|
||||||
--- Add support for PFS3 filesystem
|
--- Add support for PFS3 filesystem
|
||||||
--- Add support for Apple DOS filesystems
|
--- Add support for Apple DOS filesystems
|
||||||
--- Add support for UCSD/Pascal filesystem
|
|
||||||
--- Add support for AMSDOS filesystem
|
--- Add support for AMSDOS filesystem
|
||||||
--- Add support for CP/M filesystem
|
--- Add support for CP/M filesystem
|
||||||
--- Add support for CBM filesystem
|
--- Add support for CBM filesystem
|
||||||
|
|||||||
Reference in New Issue
Block a user