2016-07-28 18:13:49 +01:00
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : AmigaDOS.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Amiga Fast File System plugin.
//
// --[ Description ] ----------------------------------------------------------
//
// Identifies the Amiga Fast File System and shows information.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2016 Natalia Portillo
// ****************************************************************************/
2015-04-20 06:26:33 +01:00
using System ;
using System.Text ;
using System.Collections.Generic ;
2015-10-18 22:04:03 +01:00
using DiscImageChef.Console ;
2015-04-20 06:26:33 +01:00
2016-07-21 16:15:39 +01:00
namespace DiscImageChef.Filesystems
2015-04-20 06:26:33 +01:00
{
2016-07-21 16:15:39 +01:00
class AmigaDOSPlugin : Filesystem
2015-04-20 06:26:33 +01:00
{
2015-10-05 20:04:05 +01:00
public AmigaDOSPlugin ( )
2015-04-20 06:26:33 +01:00
{
Name = "Amiga DOS filesystem" ;
PluginUUID = new Guid ( "3c882400-208c-427d-a086-9119852a1bc7" ) ;
2016-07-27 13:32:45 +01:00
}
public AmigaDOSPlugin ( ImagePlugins . ImagePlugin imagePlugin , ulong partitionStart , ulong partitionEnd )
{
Name = "Amiga DOS filesystem" ;
PluginUUID = new Guid ( "3c882400-208c-427d-a086-9119852a1bc7" ) ;
2015-04-20 06:26:33 +01:00
}
/// <summary>
/// Boot block, first 2 sectors
/// </summary>
struct BootBlock
{
/// <summary>
/// Offset 0x00, "DOSx" disk type
/// </summary>
2016-07-28 22:25:26 +01:00
public uint diskType ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x04, Checksum
/// </summary>
2016-07-28 22:25:26 +01:00
public uint checksum ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x08, Pointer to root block, mostly invalid
/// </summary>
2016-07-28 22:25:26 +01:00
public uint root_ptr ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x0C, Boot code, til completion
/// </summary>
public byte [ ] bootCode ;
}
struct RootBlock
{
/// <summary>
/// Offset 0x00, block type, value = T_HEADER (2)
/// </summary>
2016-07-28 22:25:26 +01:00
public uint type ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x04, unused
/// </summary>
2016-07-28 22:25:26 +01:00
public uint headerKey ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x08, unused
/// </summary>
2016-07-28 22:25:26 +01:00
public uint highSeq ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x0C, longs used by hash table
/// </summary>
2016-07-28 22:25:26 +01:00
public uint hashTableSize ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x10, unused
/// </summary>
2016-07-28 22:25:26 +01:00
public uint firstData ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x14, Rootblock checksum
/// </summary>
2016-07-28 22:25:26 +01:00
public uint checksum ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x18, Hashtable, size = (block size / 4) - 56 or size = hashTableSize
/// </summary>
2016-07-28 22:25:26 +01:00
public uint [ ] hashTable ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x18+hashTableSize*4+0, bitmap flag, 0xFFFFFFFF if valid
/// </summary>
2016-07-28 22:25:26 +01:00
public uint bitmapFlag ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x18+hashTableSize*4+4, bitmap pages, 25 entries
/// </summary>
2016-07-28 22:25:26 +01:00
public uint [ ] bitmapPages ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x18+hashTableSize*4+104, pointer to bitmap extension block
/// </summary>
2016-07-28 22:25:26 +01:00
public uint bitmapExtensionBlock ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x18+hashTableSize*4+108, last root alteration days since 1978/01/01
/// </summary>
2016-07-28 22:25:26 +01:00
public uint rDays ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x18+hashTableSize*4+112, last root alteration minutes past midnight
/// </summary>
2016-07-28 22:25:26 +01:00
public uint rMins ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x18+hashTableSize*4+116, last root alteration ticks (1/50 secs)
/// </summary>
2016-07-28 22:25:26 +01:00
public uint rTicks ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x18+hashTableSize*4+120, disk name, pascal string, 32 bytes
/// </summary>
public string diskName ;
/// <summary>
/// Offset 0x18+hashTableSize*4+152, unused
/// </summary>
2016-07-28 22:25:26 +01:00
public uint reserved1 ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x18+hashTableSize*4+156, unused
/// </summary>
2016-07-28 22:25:26 +01:00
public uint reserved2 ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x18+hashTableSize*4+160, last disk alteration days since 1978/01/01
/// </summary>
2016-07-28 22:25:26 +01:00
public uint vDays ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x18+hashTableSize*4+164, last disk alteration minutes past midnight
/// </summary>
2016-07-28 22:25:26 +01:00
public uint vMins ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x18+hashTableSize*4+168, last disk alteration ticks (1/50 secs)
/// </summary>
2016-07-28 22:25:26 +01:00
public uint vTicks ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x18+hashTableSize*4+172, filesystem creation days since 1978/01/01
/// </summary>
2016-07-28 22:25:26 +01:00
public uint cDays ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x18+hashTableSize*4+176, filesystem creation minutes since 1978/01/01
/// </summary>
2016-07-28 22:25:26 +01:00
public uint cMins ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x18+hashTableSize*4+180, filesystem creation ticks since 1978/01/01
/// </summary>
2016-07-28 22:25:26 +01:00
public uint cTicks ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x18+hashTableSize*4+184, unused
/// </summary>
2016-07-28 22:25:26 +01:00
public uint nextHash ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x18+hashTableSize*4+188, unused
/// </summary>
2016-07-28 22:25:26 +01:00
public uint parentDir ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x18+hashTableSize*4+192, first directory cache block
/// </summary>
2016-07-28 22:25:26 +01:00
public uint extension ;
2015-04-20 06:26:33 +01:00
/// <summary>
/// Offset 0x18+hashTableSize*4+196, block secondary type = ST_ROOT (1)
/// </summary>
2016-07-28 22:25:26 +01:00
public uint sec_type ;
2015-04-20 06:26:33 +01:00
}
public override bool Identify ( ImagePlugins . ImagePlugin imagePlugin , ulong partitionStart , ulong partitionEnd )
{
2016-08-08 18:44:08 +01:00
if ( partitionStart > = partitionEnd )
2015-04-20 06:26:33 +01:00
return false ;
BigEndianBitConverter . IsLittleEndian = BitConverter . IsLittleEndian ;
byte [ ] sector = imagePlugin . ReadSector ( 0 + partitionStart ) ;
2016-07-28 22:25:26 +01:00
uint magic = BigEndianBitConverter . ToUInt32 ( sector , 0x00 ) ;
2015-04-20 06:26:33 +01:00
2016-04-19 02:11:47 +01:00
if ( ( magic & 0x6D754600 ) ! = 0x6D754600 & &
2015-04-20 06:26:33 +01:00
( magic & 0x444F5300 ) ! = 0x444F5300 )
return false ;
ulong root_ptr = BigEndianBitConverter . ToUInt32 ( sector , 0x08 ) ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "AmigaDOS plugin" , "Bootblock points to {0} as Rootblock" , root_ptr ) ;
2015-04-20 06:26:33 +01:00
2016-09-13 14:52:31 +01:00
if ( root_ptr = = 0 )
{
root_ptr = ( partitionEnd - partitionStart ) / 2 + partitionStart ;
2015-04-20 06:26:33 +01:00
2016-09-13 14:52:31 +01:00
DicConsole . DebugWriteLine ( "AmigaDOS plugin" , "Nonetheless, going to block {0} for Rootblock" , root_ptr ) ;
}
else
root_ptr + = partitionStart ;
2015-04-20 06:26:33 +01:00
2016-08-08 18:44:08 +01:00
if ( root_ptr > = partitionEnd )
2015-04-20 06:26:33 +01:00
return false ;
sector = imagePlugin . ReadSector ( root_ptr ) ;
2016-07-28 22:25:26 +01:00
uint type = BigEndianBitConverter . ToUInt32 ( sector , 0x00 ) ;
uint hashTableSize = BigEndianBitConverter . ToUInt32 ( sector , 0x0C ) ;
2015-04-20 06:26:33 +01:00
2016-09-13 14:52:31 +01:00
uint blockSize = 0x18 + hashTableSize * 4 + 196 ;
uint sectorsPerBlock = ( uint ) ( blockSize / sector . Length ) ;
if ( blockSize % sector . Length > 0 )
sectorsPerBlock + + ;
sector = imagePlugin . ReadSectors ( root_ptr , sectorsPerBlock ) ;
//if((0x18 + hashTableSize * 4 + 196) > sector.Length)
// return false;
2015-04-20 06:26:33 +01:00
2016-07-28 22:25:26 +01:00
uint sec_type = BigEndianBitConverter . ToUInt32 ( sector , ( int ) ( 0x18 + hashTableSize * 4 + 196 ) ) ;
2015-04-20 06:26:33 +01:00
return type = = 2 & & sec_type = = 1 ;
}
public override void GetInformation ( ImagePlugins . ImagePlugin imagePlugin , ulong partitionStart , ulong partitionEnd , out string information )
{
StringBuilder sbInformation = new StringBuilder ( ) ;
byte [ ] BootBlockSectors = imagePlugin . ReadSectors ( 0 + partitionStart , 2 ) ;
2016-09-13 14:52:31 +01:00
ulong root_ptr = BigEndianBitConverter . ToUInt32 ( BootBlockSectors , 0x08 ) ;
DicConsole . DebugWriteLine ( "AmigaDOS plugin" , "Bootblock points to {0} as Rootblock" , root_ptr ) ;
if ( root_ptr = = 0 )
{
root_ptr = ( partitionEnd - partitionStart ) / 2 + partitionStart ;
DicConsole . DebugWriteLine ( "AmigaDOS plugin" , "Nonetheless, going to block {0} for Rootblock" , root_ptr ) ;
}
else
root_ptr + = partitionStart ;
byte [ ] RootBlockSector = imagePlugin . ReadSector ( root_ptr ) ;
uint hashTableSize = BigEndianBitConverter . ToUInt32 ( RootBlockSector , 0x0C ) ;
uint blockSize = 0x18 + hashTableSize * 4 + 196 ;
uint sectorsPerBlock = ( uint ) ( blockSize / RootBlockSector . Length ) ;
if ( blockSize % RootBlockSector . Length > 0 )
sectorsPerBlock + + ;
RootBlockSector = imagePlugin . ReadSectors ( root_ptr , sectorsPerBlock ) ;
2015-04-20 06:26:33 +01:00
byte [ ] diskName = new byte [ 32 ] ;
BootBlock bootBlk = new BootBlock ( ) ;
RootBlock rootBlk = new RootBlock ( ) ;
2015-12-05 17:10:27 +00:00
xmlFSType = new Schemas . FileSystemType ( ) ;
2015-04-20 06:26:33 +01:00
BigEndianBitConverter . IsLittleEndian = BitConverter . IsLittleEndian ;
bootBlk . diskType = BigEndianBitConverter . ToUInt32 ( BootBlockSectors , 0x00 ) ;
bootBlk . checksum = BigEndianBitConverter . ToUInt32 ( BootBlockSectors , 0x04 ) ;
bootBlk . root_ptr = BigEndianBitConverter . ToUInt32 ( BootBlockSectors , 0x08 ) ;
bootBlk . bootCode = new byte [ BootBlockSectors . Length - 0x0C ] ;
Array . Copy ( BootBlockSectors , 0x0C , bootBlk . bootCode , 0 , BootBlockSectors . Length - 0x0C ) ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "AmigaDOS plugin" , "Stored boot blocks checksum is 0x{0:X8}" , bootBlk . checksum ) ;
DicConsole . DebugWriteLine ( "AmigaDOS plugin" , "Probably incorrect calculated boot blocks checksum is 0x{0:X8}" , AmigaChecksum ( RootBlockSector ) ) ;
Checksums . SHA1Context sha1Ctx = new Checksums . SHA1Context ( ) ;
sha1Ctx . Init ( ) ;
sha1Ctx . Update ( bootBlk . bootCode ) ;
DicConsole . DebugWriteLine ( "AmigaDOS plugin" , "Boot code SHA1 is {0}" , sha1Ctx . End ( ) ) ;
2015-04-20 06:26:33 +01:00
rootBlk . type = BigEndianBitConverter . ToUInt32 ( RootBlockSector , 0x00 ) ;
rootBlk . headerKey = BigEndianBitConverter . ToUInt32 ( RootBlockSector , 0x04 ) ;
rootBlk . highSeq = BigEndianBitConverter . ToUInt32 ( RootBlockSector , 0x08 ) ;
rootBlk . hashTableSize = BigEndianBitConverter . ToUInt32 ( RootBlockSector , 0x0C ) ;
rootBlk . firstData = BigEndianBitConverter . ToUInt32 ( RootBlockSector , 0x10 ) ;
rootBlk . checksum = BigEndianBitConverter . ToUInt32 ( RootBlockSector , 0x14 ) ;
rootBlk . hashTable = new uint [ rootBlk . hashTableSize ] ;
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < rootBlk . hashTableSize ; i + + )
2015-04-20 17:52:08 +01:00
rootBlk . hashTable [ i ] = BigEndianBitConverter . ToUInt32 ( RootBlockSector , 0x18 + i * 4 ) ;
2015-04-20 06:26:33 +01:00
rootBlk . bitmapFlag = BigEndianBitConverter . ToUInt32 ( RootBlockSector , ( int ) ( 0x18 + rootBlk . hashTableSize * 4 + 0 ) ) ;
rootBlk . bitmapPages = new uint [ 25 ] ;
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < 25 ; i + + )
2015-04-20 06:26:33 +01:00
rootBlk . bitmapPages [ i ] = BigEndianBitConverter . ToUInt32 ( RootBlockSector , ( int ) ( 0x18 + rootBlk . hashTableSize * 4 + 4 + i * 4 ) ) ;
rootBlk . bitmapExtensionBlock = BigEndianBitConverter . ToUInt32 ( RootBlockSector , ( int ) ( 0x18 + rootBlk . hashTableSize * 4 + 104 ) ) ;
rootBlk . rDays = BigEndianBitConverter . ToUInt32 ( RootBlockSector , ( int ) ( 0x18 + rootBlk . hashTableSize * 4 + 108 ) ) ;
rootBlk . rMins = BigEndianBitConverter . ToUInt32 ( RootBlockSector , ( int ) ( 0x18 + rootBlk . hashTableSize * 4 + 112 ) ) ;
rootBlk . rTicks = BigEndianBitConverter . ToUInt32 ( RootBlockSector , ( int ) ( 0x18 + rootBlk . hashTableSize * 4 + 116 ) ) ;
2015-04-20 17:52:08 +01:00
Array . Copy ( RootBlockSector , 0x18 + rootBlk . hashTableSize * 4 + 120 , diskName , 0 , 32 ) ;
2015-04-20 06:26:33 +01:00
rootBlk . diskName = StringHandlers . PascalToString ( diskName ) ;
rootBlk . reserved1 = BigEndianBitConverter . ToUInt32 ( RootBlockSector , ( int ) ( 0x18 + rootBlk . hashTableSize * 4 + 152 ) ) ;
rootBlk . reserved2 = BigEndianBitConverter . ToUInt32 ( RootBlockSector , ( int ) ( 0x18 + rootBlk . hashTableSize * 4 + 156 ) ) ;
rootBlk . vDays = BigEndianBitConverter . ToUInt32 ( RootBlockSector , ( int ) ( 0x18 + rootBlk . hashTableSize * 4 + 160 ) ) ;
rootBlk . vMins = BigEndianBitConverter . ToUInt32 ( RootBlockSector , ( int ) ( 0x18 + rootBlk . hashTableSize * 4 + 164 ) ) ;
rootBlk . vTicks = BigEndianBitConverter . ToUInt32 ( RootBlockSector , ( int ) ( 0x18 + rootBlk . hashTableSize * 4 + 168 ) ) ;
rootBlk . cDays = BigEndianBitConverter . ToUInt32 ( RootBlockSector , ( int ) ( 0x18 + rootBlk . hashTableSize * 4 + 172 ) ) ;
rootBlk . cMins = BigEndianBitConverter . ToUInt32 ( RootBlockSector , ( int ) ( 0x18 + rootBlk . hashTableSize * 4 + 176 ) ) ;
rootBlk . cTicks = BigEndianBitConverter . ToUInt32 ( RootBlockSector , ( int ) ( 0x18 + rootBlk . hashTableSize * 4 + 180 ) ) ;
rootBlk . nextHash = BigEndianBitConverter . ToUInt32 ( RootBlockSector , ( int ) ( 0x18 + rootBlk . hashTableSize * 4 + 184 ) ) ;
rootBlk . parentDir = BigEndianBitConverter . ToUInt32 ( RootBlockSector , ( int ) ( 0x18 + rootBlk . hashTableSize * 4 + 188 ) ) ;
rootBlk . extension = BigEndianBitConverter . ToUInt32 ( RootBlockSector , ( int ) ( 0x18 + rootBlk . hashTableSize * 4 + 192 ) ) ;
rootBlk . sec_type = BigEndianBitConverter . ToUInt32 ( RootBlockSector , ( int ) ( 0x18 + rootBlk . hashTableSize * 4 + 196 ) ) ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "AmigaDOS plugin" , "Stored root block checksum is 0x{0:X8}" , rootBlk . checksum ) ;
DicConsole . DebugWriteLine ( "AmigaDOS plugin" , "Probably incorrect calculated root block checksum is 0x{0:X8}" , AmigaChecksum ( RootBlockSector ) ) ;
2015-04-20 06:26:33 +01:00
2016-04-19 02:11:47 +01:00
switch ( bootBlk . diskType & 0xFF )
2015-04-20 06:26:33 +01:00
{
case 0 :
sbInformation . Append ( "Amiga Original File System" ) ;
2015-12-05 17:10:27 +00:00
xmlFSType . Type = "Amiga OFS" ;
2015-04-20 06:26:33 +01:00
break ;
case 1 :
sbInformation . Append ( "Amiga Fast File System" ) ;
2015-12-05 17:10:27 +00:00
xmlFSType . Type = "Amiga FFS" ;
2015-04-20 06:26:33 +01:00
break ;
case 2 :
sbInformation . Append ( "Amiga Original File System with international characters" ) ;
2015-12-05 17:10:27 +00:00
xmlFSType . Type = "Amiga OFS" ;
2015-04-20 06:26:33 +01:00
break ;
case 3 :
sbInformation . Append ( "Amiga Fast File System with international characters" ) ;
2015-12-05 17:10:27 +00:00
xmlFSType . Type = "Amiga FFS" ;
2015-04-20 06:26:33 +01:00
break ;
case 4 :
sbInformation . Append ( "Amiga Original File System with directory cache" ) ;
2015-12-05 17:10:27 +00:00
xmlFSType . Type = "Amiga OFS" ;
2015-04-20 06:26:33 +01:00
break ;
case 5 :
sbInformation . Append ( "Amiga Fast File System with directory cache" ) ;
2015-12-05 17:10:27 +00:00
xmlFSType . Type = "Amiga FFS" ;
2015-04-20 06:26:33 +01:00
break ;
case 6 :
sbInformation . Append ( "Amiga Original File System with long filenames" ) ;
2015-12-05 17:10:27 +00:00
xmlFSType . Type = "Amiga OFS" ;
2015-04-20 06:26:33 +01:00
break ;
case 7 :
sbInformation . Append ( "Amiga Fast File System with long filenames" ) ;
2015-12-05 17:10:27 +00:00
xmlFSType . Type = "Amiga FFS" ;
2015-04-20 06:26:33 +01:00
break ;
}
2016-04-19 02:11:47 +01:00
if ( ( bootBlk . diskType & 0x6D754600 ) = = 0x6D754600 )
2015-04-20 06:26:33 +01:00
sbInformation . Append ( ", with multi-user patches" ) ;
sbInformation . AppendLine ( ) ;
2016-04-19 02:11:47 +01:00
if ( ( bootBlk . diskType & 0xFF ) = = 6 | | ( bootBlk . diskType & 0xFF ) = = 7 )
2015-12-05 17:10:27 +00:00
{
2015-04-20 06:26:33 +01:00
sbInformation . AppendLine ( "AFFS v2, following information may be completely incorrect or garbage." ) ;
2015-12-05 17:10:27 +00:00
xmlFSType . Type = "Amiga FFS2" ;
}
2015-04-20 06:26:33 +01:00
sbInformation . AppendFormat ( "Volume name: {0}" , rootBlk . diskName ) . AppendLine ( ) ;
2016-04-19 02:11:47 +01:00
if ( rootBlk . bitmapFlag = = 0xFFFFFFFF )
2015-04-20 06:26:33 +01:00
sbInformation . AppendLine ( "Volume bitmap is valid" ) ;
2016-04-19 02:11:47 +01:00
if ( rootBlk . bitmapExtensionBlock ! = 0x00000000 & & rootBlk . bitmapExtensionBlock ! = 0xFFFFFFFF )
2015-04-20 06:26:33 +01:00
sbInformation . AppendFormat ( "Bitmap extension at block {0}" , rootBlk . bitmapExtensionBlock ) . AppendLine ( ) ;
2016-04-19 02:11:47 +01:00
if ( ( bootBlk . diskType & 0xFF ) = = 4 | | ( bootBlk . diskType & 0xFF ) = = 5 )
2015-04-20 06:26:33 +01:00
sbInformation . AppendFormat ( "Directory cache starts at block {0}" , rootBlk . extension ) . AppendLine ( ) ;
sbInformation . AppendFormat ( "Volume created on {0}" , DateHandlers . AmigaToDateTime ( rootBlk . cDays , rootBlk . cMins , rootBlk . cTicks ) ) . AppendLine ( ) ;
sbInformation . AppendFormat ( "Volume last modified on {0}" , DateHandlers . AmigaToDateTime ( rootBlk . vDays , rootBlk . vMins , rootBlk . vTicks ) ) . AppendLine ( ) ;
sbInformation . AppendFormat ( "Volume root directory last modified on on {0}" , DateHandlers . AmigaToDateTime ( rootBlk . rDays , rootBlk . rMins , rootBlk . rTicks ) ) . AppendLine ( ) ;
information = sbInformation . ToString ( ) ;
2015-12-04 18:52:23 +00:00
xmlFSType . CreationDate = DateHandlers . AmigaToDateTime ( rootBlk . cDays , rootBlk . cMins , rootBlk . cTicks ) ;
2015-12-06 05:09:31 +00:00
xmlFSType . CreationDateSpecified = true ;
2015-12-04 18:52:23 +00:00
xmlFSType . ModificationDate = DateHandlers . AmigaToDateTime ( rootBlk . vDays , rootBlk . vMins , rootBlk . vTicks ) ;
2015-12-06 05:09:31 +00:00
xmlFSType . ModificationDateSpecified = true ;
2015-12-05 17:10:27 +00:00
xmlFSType . Dirty = rootBlk . bitmapFlag ! = 0xFFFFFFFF ;
2015-12-06 05:09:31 +00:00
xmlFSType . Clusters = ( long ) ( ( partitionEnd - partitionStart ) + 1 ) ;
xmlFSType . ClusterSize = ( int ) imagePlugin . GetSectorSize ( ) ;
2015-04-20 06:26:33 +01:00
}
2016-07-28 22:25:26 +01:00
static uint AmigaChecksum ( byte [ ] data )
2015-04-20 06:26:33 +01:00
{
BigEndianBitConverter . IsLittleEndian = BitConverter . IsLittleEndian ;
2016-07-28 22:25:26 +01:00
uint sum = 0 ;
2015-04-20 06:26:33 +01:00
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < data . Length ; i + = 4 )
2015-04-20 06:26:33 +01:00
sum + = BigEndianBitConverter . ToUInt32 ( data , i ) ;
return sum ;
}
2016-07-21 17:16:08 +01:00
public override Errno Mount ( )
{
return Errno . NotImplemented ;
}
2016-07-22 00:43:22 +01:00
public override Errno Mount ( bool debug )
{
return Errno . NotImplemented ;
}
2016-07-21 17:16:08 +01:00
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 )
{
return Errno . NotImplemented ;
}
public override Errno GetXattr ( string path , string xattr , ref byte [ ] buf )
{
return Errno . NotImplemented ;
}
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 )
{
return Errno . NotImplemented ;
}
2015-04-20 06:26:33 +01:00
}
}