mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Replace Read method with ReadFile method that uses the file node in IFileSystem.
This commit is contained in:
Submodule Aaru.CommonTypes updated: d580412b08...c723c09aaa
@@ -31,7 +31,6 @@
|
||||
// Copyright © 2011-2023 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Aaru.CommonTypes.AaruMetadata;
|
||||
@@ -165,7 +164,7 @@ public sealed partial class Sidecar
|
||||
StatusChangeTime = stat.StatusChangeTimeUtc
|
||||
};
|
||||
|
||||
byte[] data = Array.Empty<byte>();
|
||||
byte[] data = null;
|
||||
|
||||
if(stat.Length > 0)
|
||||
{
|
||||
@@ -173,28 +172,36 @@ public sealed partial class Sidecar
|
||||
UpdateStatus(string.Format(Localization.Core.Hashing_file_0_1, path, filename));
|
||||
InitProgress2();
|
||||
|
||||
while(position < stat.Length - 1048576)
|
||||
{
|
||||
if(_aborted)
|
||||
return file;
|
||||
ErrorNumber error = filesystem.OpenFile(path + "/" + filename, out IFileNode fileNode);
|
||||
|
||||
if(error == ErrorNumber.NoError)
|
||||
{
|
||||
data = new byte[1048576];
|
||||
filesystem.Read(path + "/" + filename, position, 1048576, ref data);
|
||||
|
||||
while(position < stat.Length - 1048576)
|
||||
{
|
||||
if(_aborted)
|
||||
return file;
|
||||
|
||||
// TODO: Better error handling
|
||||
filesystem.ReadFile(fileNode, 1048576, data, out _);
|
||||
|
||||
UpdateProgress2(Localization.Core.Hashing_file_byte_0_of_1, position, stat.Length);
|
||||
|
||||
fileChkWorker.Update(data);
|
||||
|
||||
position += 1048576;
|
||||
}
|
||||
|
||||
data = new byte[stat.Length - position];
|
||||
filesystem.ReadFile(fileNode, data.Length, data, out _);
|
||||
|
||||
UpdateProgress2(Localization.Core.Hashing_file_byte_0_of_1, position, stat.Length);
|
||||
|
||||
fileChkWorker.Update(data);
|
||||
|
||||
position += 1048576;
|
||||
filesystem.CloseFile(fileNode);
|
||||
}
|
||||
|
||||
data = new byte[stat.Length - position];
|
||||
filesystem.Read(path + "/" + filename, position, stat.Length - position, ref data);
|
||||
|
||||
UpdateProgress2(Localization.Core.Hashing_file_byte_0_of_1, position, stat.Length);
|
||||
|
||||
fileChkWorker.Update(data);
|
||||
|
||||
EndProgress2();
|
||||
|
||||
file.Checksums = fileChkWorker.End();
|
||||
|
||||
@@ -145,57 +145,28 @@ public sealed partial class AppleDOS
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber Read(string path, long offset, long size, ref byte[] buf)
|
||||
public ErrorNumber ReadFile(IFileNode node, long length, byte[] buffer, out long read)
|
||||
{
|
||||
read = 0;
|
||||
|
||||
if(!_mounted)
|
||||
return ErrorNumber.AccessDenied;
|
||||
|
||||
string[] pathElements = path.Split(new[]
|
||||
{
|
||||
'/'
|
||||
}, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if(pathElements.Length != 1)
|
||||
return ErrorNumber.NotSupported;
|
||||
|
||||
byte[] file;
|
||||
string filename = pathElements[0].ToUpperInvariant();
|
||||
|
||||
if(filename.Length > 30)
|
||||
return ErrorNumber.NameTooLong;
|
||||
|
||||
if(_debug && (string.Compare(path, "$", StringComparison.InvariantCulture) == 0 ||
|
||||
string.Compare(path, "$Boot", StringComparison.InvariantCulture) == 0 ||
|
||||
string.Compare(path, "$Vtoc", StringComparison.InvariantCulture) == 0))
|
||||
if(string.Compare(path, "$", StringComparison.InvariantCulture) == 0)
|
||||
file = _catalogBlocks;
|
||||
else if(string.Compare(path, "$Vtoc", StringComparison.InvariantCulture) == 0)
|
||||
file = _vtocBlocks;
|
||||
else
|
||||
file = _bootBlocks;
|
||||
else
|
||||
{
|
||||
if(!_fileCache.TryGetValue(filename, out file))
|
||||
{
|
||||
ErrorNumber error = CacheFile(filename);
|
||||
|
||||
if(error != ErrorNumber.NoError)
|
||||
return error;
|
||||
|
||||
if(!_fileCache.TryGetValue(filename, out file))
|
||||
return ErrorNumber.InvalidArgument;
|
||||
}
|
||||
}
|
||||
|
||||
if(offset >= file.Length)
|
||||
if(buffer is null ||
|
||||
buffer.Length < length)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
|
||||
if(size + offset >= file.Length)
|
||||
size = file.Length - offset;
|
||||
if(node is not AppleDosFileNode mynode)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
|
||||
buf = new byte[size];
|
||||
read = length;
|
||||
|
||||
Array.Copy(file, offset, buf, 0, size);
|
||||
if(length + mynode.Offset >= mynode.Length)
|
||||
read = mynode.Length - mynode.Offset;
|
||||
|
||||
Array.Copy(mynode._cache, mynode.Offset, buffer, 0, read);
|
||||
|
||||
mynode.Offset += read;
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
@@ -218,57 +218,28 @@ public sealed partial class AppleMFS
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber Read(string path, long offset, long size, ref byte[] buf)
|
||||
public ErrorNumber ReadFile(IFileNode node, long length, byte[] buffer, out long read)
|
||||
{
|
||||
read = 0;
|
||||
|
||||
if(!_mounted)
|
||||
return ErrorNumber.AccessDenied;
|
||||
|
||||
byte[] file;
|
||||
ErrorNumber error = ErrorNumber.NoError;
|
||||
|
||||
switch(_debug)
|
||||
{
|
||||
case true when string.Compare(path, "$", StringComparison.InvariantCulture) == 0:
|
||||
file = _directoryBlocks;
|
||||
|
||||
break;
|
||||
case true when string.Compare(path, "$Boot", StringComparison.InvariantCulture) == 0 && _bootBlocks != null:
|
||||
file = _bootBlocks;
|
||||
|
||||
break;
|
||||
case true when string.Compare(path, "$Bitmap", StringComparison.InvariantCulture) == 0:
|
||||
file = _blockMapBytes;
|
||||
|
||||
break;
|
||||
case true when string.Compare(path, "$MDB", StringComparison.InvariantCulture) == 0:
|
||||
file = _mdbBlocks;
|
||||
|
||||
break;
|
||||
default:
|
||||
error = ReadFile(path, out file, false, false);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(error != ErrorNumber.NoError)
|
||||
return error;
|
||||
|
||||
if(size == 0)
|
||||
{
|
||||
buf = Array.Empty<byte>();
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
if(offset >= file.Length)
|
||||
if(buffer is null ||
|
||||
buffer.Length < length)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
|
||||
if(size + offset >= file.Length)
|
||||
size = file.Length - offset;
|
||||
if(node is not AppleMfsFileNode mynode)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
|
||||
buf = new byte[size];
|
||||
read = length;
|
||||
|
||||
Array.Copy(file, offset, buf, 0, size);
|
||||
if(length + mynode.Offset >= mynode.Length)
|
||||
read = mynode.Length - mynode.Offset;
|
||||
|
||||
Array.Copy(mynode._cache, mynode.Offset, buffer, 0, read);
|
||||
|
||||
mynode.Offset += read;
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
@@ -123,40 +123,28 @@ public sealed partial class CPM
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber Read(string path, long offset, long size, ref byte[] buf)
|
||||
public ErrorNumber ReadFile(IFileNode node, long length, byte[] buffer, out long read)
|
||||
{
|
||||
read = 0;
|
||||
|
||||
if(!_mounted)
|
||||
return ErrorNumber.AccessDenied;
|
||||
|
||||
if(size == 0)
|
||||
{
|
||||
buf = Array.Empty<byte>();
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
if(offset < 0)
|
||||
if(buffer is null ||
|
||||
buffer.Length < length)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
|
||||
string[] pathElements = path.Split(new[]
|
||||
{
|
||||
'/'
|
||||
}, StringSplitOptions.RemoveEmptyEntries);
|
||||
if(node is not CpmFileNode mynode)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
|
||||
if(pathElements.Length != 1)
|
||||
return ErrorNumber.NotSupported;
|
||||
read = length;
|
||||
|
||||
if(!_fileCache.TryGetValue(pathElements[0].ToUpperInvariant(), out byte[] file))
|
||||
return ErrorNumber.NoSuchFile;
|
||||
if(length + mynode.Offset >= mynode.Length)
|
||||
read = mynode.Length - mynode.Offset;
|
||||
|
||||
if(offset >= file.Length)
|
||||
return ErrorNumber.EINVAL;
|
||||
Array.Copy(mynode._cache, mynode.Offset, buffer, 0, read);
|
||||
|
||||
if(size + offset >= file.Length)
|
||||
size = file.Length - offset;
|
||||
|
||||
buf = new byte[size];
|
||||
Array.Copy(file, offset, buf, 0, size);
|
||||
mynode.Offset += read;
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
@@ -133,65 +133,52 @@ public sealed partial class FAT
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber Read(string path, long offset, long size, ref byte[] buf)
|
||||
public ErrorNumber ReadFile(IFileNode node, long length, byte[] buffer, out long read)
|
||||
{
|
||||
read = 0;
|
||||
|
||||
if(!_mounted)
|
||||
return ErrorNumber.AccessDenied;
|
||||
|
||||
ErrorNumber err = Stat(path, out FileEntryInfo stat);
|
||||
|
||||
if(err != ErrorNumber.NoError)
|
||||
return err;
|
||||
|
||||
if(stat.Attributes.HasFlag(FileAttributes.Directory) &&
|
||||
!_debug)
|
||||
return ErrorNumber.IsDirectory;
|
||||
|
||||
if(size == 0)
|
||||
{
|
||||
buf = Array.Empty<byte>();
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
if(offset >= stat.Length)
|
||||
if(buffer is null ||
|
||||
buffer.Length < length)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
|
||||
if(size + offset >= stat.Length)
|
||||
size = stat.Length - offset;
|
||||
|
||||
uint[] clusters = GetClusters((uint)stat.Inode);
|
||||
|
||||
if(clusters is null)
|
||||
if(node is not FatFileNode mynode)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
|
||||
long firstCluster = offset / _bytesPerCluster;
|
||||
long offsetInCluster = offset % _bytesPerCluster;
|
||||
long sizeInClusters = (size + offsetInCluster) / _bytesPerCluster;
|
||||
read = length;
|
||||
|
||||
if((size + offsetInCluster) % _bytesPerCluster > 0)
|
||||
if(length + mynode.Offset >= mynode.Length)
|
||||
read = mynode.Length - mynode.Offset;
|
||||
|
||||
long firstCluster = mynode.Offset / _bytesPerCluster;
|
||||
long offsetInCluster = mynode.Offset % _bytesPerCluster;
|
||||
long sizeInClusters = (read + offsetInCluster) / _bytesPerCluster;
|
||||
|
||||
if((read + offsetInCluster) % _bytesPerCluster > 0)
|
||||
sizeInClusters++;
|
||||
|
||||
var ms = new MemoryStream();
|
||||
|
||||
for(int i = 0; i < sizeInClusters; i++)
|
||||
{
|
||||
if(i + firstCluster >= clusters.Length)
|
||||
if(i + firstCluster >= mynode._clusters.Length)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
|
||||
ErrorNumber errno =
|
||||
_image.ReadSectors(_firstClusterSector + (clusters[i + firstCluster] * _sectorsPerCluster),
|
||||
_sectorsPerCluster, out byte[] buffer);
|
||||
_image.ReadSectors(_firstClusterSector + (mynode._clusters[i + firstCluster] * _sectorsPerCluster),
|
||||
_sectorsPerCluster, out byte[] buf);
|
||||
|
||||
if(errno != ErrorNumber.NoError)
|
||||
return errno;
|
||||
|
||||
ms.Write(buffer, 0, buffer.Length);
|
||||
ms.Write(buf, 0, buf.Length);
|
||||
}
|
||||
|
||||
ms.Position = offsetInCluster;
|
||||
buf = new byte[size];
|
||||
ms.EnsureRead(buf, 0, (int)size);
|
||||
ms.EnsureRead(buffer, 0, (int)read);
|
||||
mynode.Offset += read;
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
@@ -130,55 +130,53 @@ public sealed partial class XboxFatPlugin
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber Read(string path, long offset, long size, ref byte[] buf)
|
||||
public ErrorNumber ReadFile(IFileNode node, long length, byte[] buffer, out long read)
|
||||
{
|
||||
read = 0;
|
||||
|
||||
if(!_mounted)
|
||||
return ErrorNumber.AccessDenied;
|
||||
|
||||
ErrorNumber err = Stat(path, out FileEntryInfo stat);
|
||||
|
||||
if(err != ErrorNumber.NoError)
|
||||
return err;
|
||||
|
||||
if(stat.Attributes.HasFlag(FileAttributes.Directory) &&
|
||||
!_debug)
|
||||
return ErrorNumber.IsDirectory;
|
||||
|
||||
if(offset >= stat.Length)
|
||||
if(buffer is null ||
|
||||
buffer.Length < length)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
|
||||
if(size + offset >= stat.Length)
|
||||
size = stat.Length - offset;
|
||||
if(node is not FatxFileNode mynode)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
|
||||
uint[] clusters = GetClusters((uint)stat.Inode);
|
||||
read = length;
|
||||
|
||||
long firstCluster = offset / _bytesPerCluster;
|
||||
long offsetInCluster = offset % _bytesPerCluster;
|
||||
long sizeInClusters = (size + offsetInCluster) / _bytesPerCluster;
|
||||
if(length + mynode.Offset >= mynode.Length)
|
||||
read = mynode.Length - mynode.Offset;
|
||||
|
||||
if((size + offsetInCluster) % _bytesPerCluster > 0)
|
||||
long firstCluster = mynode.Offset / _bytesPerCluster;
|
||||
long offsetInCluster = mynode.Offset % _bytesPerCluster;
|
||||
long sizeInClusters = (read + offsetInCluster) / _bytesPerCluster;
|
||||
|
||||
if((read + offsetInCluster) % _bytesPerCluster > 0)
|
||||
sizeInClusters++;
|
||||
|
||||
var ms = new MemoryStream();
|
||||
|
||||
for(int i = 0; i < sizeInClusters; i++)
|
||||
{
|
||||
if(i + firstCluster >= clusters.Length)
|
||||
if(i + firstCluster >= mynode._clusters.Length)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
|
||||
ErrorNumber errno =
|
||||
_imagePlugin.ReadSectors(_firstClusterSector + ((clusters[i + firstCluster] - 1) * _sectorsPerCluster),
|
||||
_sectorsPerCluster, out byte[] buffer);
|
||||
_imagePlugin.
|
||||
ReadSectors(_firstClusterSector + ((mynode._clusters[i + firstCluster] - 1) * _sectorsPerCluster),
|
||||
_sectorsPerCluster, out byte[] buf);
|
||||
|
||||
if(errno != ErrorNumber.NoError)
|
||||
return errno;
|
||||
|
||||
ms.Write(buffer, 0, buffer.Length);
|
||||
ms.Write(buf, 0, buf.Length);
|
||||
}
|
||||
|
||||
ms.Position = offsetInCluster;
|
||||
buf = new byte[size];
|
||||
ms.EnsureRead(buf, 0, (int)size);
|
||||
ms.EnsureRead(buffer, 0, (int)read);
|
||||
mynode.Offset += read;
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
@@ -135,64 +135,71 @@ public sealed partial class ISO9660
|
||||
|
||||
// TODO: Resolve symbolic link
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber Read(string path, long offset, long size, ref byte[] buf)
|
||||
public ErrorNumber ReadFile(IFileNode node, long length, byte[] buffer, out long read)
|
||||
{
|
||||
buf = null;
|
||||
read = 0;
|
||||
|
||||
if(!_mounted)
|
||||
return ErrorNumber.AccessDenied;
|
||||
|
||||
ErrorNumber err = GetFileEntry(path, out DecodedDirectoryEntry entry);
|
||||
|
||||
if(err != ErrorNumber.NoError)
|
||||
return err;
|
||||
|
||||
if(entry.Flags.HasFlag(FileFlags.Directory) &&
|
||||
!_debug)
|
||||
return ErrorNumber.IsDirectory;
|
||||
|
||||
if(entry.Extents is null)
|
||||
if(buffer is null ||
|
||||
buffer.Length < length)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
|
||||
if(entry.Size == 0)
|
||||
if(node is not Iso9660FileNode mynode)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
|
||||
read = length;
|
||||
|
||||
if(length + mynode.Offset >= mynode.Length)
|
||||
read = mynode.Length - mynode.Offset;
|
||||
|
||||
long offset = mynode.Offset + (mynode._dentry.XattrLength * _blockSize);
|
||||
|
||||
if(mynode._dentry.CdiSystemArea?.attributes.HasFlag(CdiAttributes.DigitalAudio) != true ||
|
||||
mynode._dentry.Extents.Count != 1)
|
||||
{
|
||||
buf = Array.Empty<byte>();
|
||||
ErrorNumber err = ReadWithExtents(offset, read, mynode._dentry.Extents,
|
||||
mynode._dentry.XA?.signature == XA_MAGIC &&
|
||||
mynode._dentry.XA?.attributes.HasFlag(XaAttributes.Interleaved) == true,
|
||||
mynode._dentry.XA?.filenumber ?? 0, out byte[] buf);
|
||||
|
||||
if(err != ErrorNumber.NoError)
|
||||
{
|
||||
read = 0;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
Array.Copy(buf, 0, buffer, 0, read);
|
||||
|
||||
node.Offset += read;
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
if(offset >= (long)entry.Size)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
|
||||
if(size + offset >= (long)entry.Size)
|
||||
size = (long)entry.Size - offset;
|
||||
|
||||
offset += entry.XattrLength * _blockSize;
|
||||
|
||||
if(entry.CdiSystemArea?.attributes.HasFlag(CdiAttributes.DigitalAudio) != true ||
|
||||
entry.Extents.Count != 1)
|
||||
return ReadWithExtents(offset, size, entry.Extents,
|
||||
entry.XA?.signature == XA_MAGIC &&
|
||||
entry.XA?.attributes.HasFlag(XaAttributes.Interleaved) == true,
|
||||
entry.XA?.filenumber ?? 0, out buf);
|
||||
|
||||
try
|
||||
{
|
||||
long firstSector = offset / 2352;
|
||||
long offsetInSector = offset % 2352;
|
||||
long sizeInSectors = (size + offsetInSector) / 2352;
|
||||
long sizeInSectors = (read + offsetInSector) / 2352;
|
||||
|
||||
if((size + offsetInSector) % 2352 > 0)
|
||||
if((read + offsetInSector) % 2352 > 0)
|
||||
sizeInSectors++;
|
||||
|
||||
ErrorNumber errno = _image.ReadSectorsLong((ulong)(entry.Extents[0].extent + firstSector),
|
||||
(uint)sizeInSectors, out byte[] buffer);
|
||||
ErrorNumber errno = _image.ReadSectorsLong((ulong)(mynode._dentry.Extents[0].extent + firstSector),
|
||||
(uint)sizeInSectors, out byte[] buf);
|
||||
|
||||
if(errno != ErrorNumber.NoError)
|
||||
return errno;
|
||||
{
|
||||
read = 0;
|
||||
|
||||
buf = new byte[size];
|
||||
Array.Copy(buffer, offsetInSector, buf, 0, size);
|
||||
return errno;
|
||||
}
|
||||
|
||||
Array.Copy(buf, offsetInSector, buffer, 0, read);
|
||||
|
||||
node.Offset += read;
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
@@ -201,6 +208,8 @@ public sealed partial class ISO9660
|
||||
AaruConsole.DebugWriteLine("ISO9660 plugin", Localization.Exception_reading_CD_i_audio_file);
|
||||
AaruConsole.DebugWriteLine("ISO9660 plugin", "{0}", e);
|
||||
|
||||
read = 0;
|
||||
|
||||
return ErrorNumber.UnexpectedException;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,27 +101,30 @@ public sealed partial class LisaFS
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber Read(string path, long offset, long size, ref byte[] buf)
|
||||
public ErrorNumber ReadFile(IFileNode node, long length, byte[] buffer, out long read)
|
||||
{
|
||||
if(size == 0)
|
||||
{
|
||||
buf = Array.Empty<byte>();
|
||||
read = 0;
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
if(!_mounted)
|
||||
return ErrorNumber.AccessDenied;
|
||||
|
||||
if(offset < 0)
|
||||
if(buffer is null ||
|
||||
buffer.Length < length)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
|
||||
ErrorNumber error = LookupFileId(path, out short fileId, out _);
|
||||
if(node is not LisaFileNode mynode)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
|
||||
if(error != ErrorNumber.NoError)
|
||||
return error;
|
||||
read = length;
|
||||
|
||||
byte[] tmp;
|
||||
if(length + mynode.Offset >= mynode.Length)
|
||||
read = mynode.Length - mynode.Offset;
|
||||
|
||||
byte[] tmp;
|
||||
ErrorNumber error;
|
||||
|
||||
if(_debug)
|
||||
switch(fileId)
|
||||
switch(mynode._fileId)
|
||||
{
|
||||
case FILEID_BOOT_SIGNED:
|
||||
case FILEID_LOADER_SIGNED:
|
||||
@@ -129,28 +132,27 @@ public sealed partial class LisaFS
|
||||
case (short)FILEID_BITMAP:
|
||||
case (short)FILEID_SRECORD:
|
||||
case (short)FILEID_CATALOG:
|
||||
error = ReadSystemFile(fileId, out tmp);
|
||||
error = ReadSystemFile(mynode._fileId, out tmp);
|
||||
|
||||
break;
|
||||
default:
|
||||
error = ReadFile(fileId, out tmp);
|
||||
error = ReadFile(mynode._fileId, out tmp);
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
error = ReadFile(fileId, out tmp);
|
||||
error = ReadFile(mynode._fileId, out tmp);
|
||||
|
||||
if(error != ErrorNumber.NoError)
|
||||
{
|
||||
read = 0;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
if(offset >= tmp.Length)
|
||||
return ErrorNumber.EINVAL;
|
||||
Array.Copy(tmp, mynode.Offset, buffer, 0, read);
|
||||
|
||||
if(size + offset >= tmp.Length)
|
||||
size = tmp.Length - offset;
|
||||
|
||||
buf = new byte[size];
|
||||
Array.Copy(tmp, offset, buf, 0, size);
|
||||
mynode.Offset += read;
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
@@ -122,60 +122,52 @@ public sealed partial class OperaFS
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber Read(string path, long offset, long size, ref byte[] buf)
|
||||
public ErrorNumber ReadFile(IFileNode node, long length, byte[] buffer, out long read)
|
||||
{
|
||||
buf = null;
|
||||
read = 0;
|
||||
|
||||
if(!_mounted)
|
||||
return ErrorNumber.AccessDenied;
|
||||
|
||||
ErrorNumber err = GetFileEntry(path, out DirectoryEntryWithPointers entry);
|
||||
|
||||
if(err != ErrorNumber.NoError)
|
||||
return err;
|
||||
|
||||
if((entry.Entry.flags & FLAGS_MASK) == (uint)FileFlags.Directory &&
|
||||
!_debug)
|
||||
return ErrorNumber.IsDirectory;
|
||||
|
||||
if(entry.Pointers.Length < 1)
|
||||
if(buffer is null ||
|
||||
buffer.Length < length)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
|
||||
if(entry.Entry.byte_count == 0)
|
||||
{
|
||||
buf = Array.Empty<byte>();
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
if(offset >= entry.Entry.byte_count)
|
||||
if(node is not OperaFileNode mynode)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
|
||||
if(size + offset >= entry.Entry.byte_count)
|
||||
size = entry.Entry.byte_count - offset;
|
||||
read = length;
|
||||
|
||||
long firstBlock = offset / entry.Entry.block_size;
|
||||
long offsetInBlock = offset % entry.Entry.block_size;
|
||||
long sizeInBlocks = (size + offsetInBlock) / entry.Entry.block_size;
|
||||
if(length + mynode.Offset >= mynode.Length)
|
||||
read = mynode.Length - mynode.Offset;
|
||||
|
||||
if((size + offsetInBlock) % entry.Entry.block_size > 0)
|
||||
long firstBlock = mynode.Offset / mynode._dentry.Entry.block_size;
|
||||
long offsetInBlock = mynode.Offset % mynode._dentry.Entry.block_size;
|
||||
long sizeInBlocks = (read + offsetInBlock) / mynode._dentry.Entry.block_size;
|
||||
|
||||
if((read + offsetInBlock) % mynode._dentry.Entry.block_size > 0)
|
||||
sizeInBlocks++;
|
||||
|
||||
uint fileBlockSizeRatio;
|
||||
|
||||
if(_image.Info.SectorSize is 2336 or 2352 or 2448)
|
||||
fileBlockSizeRatio = entry.Entry.block_size / 2048;
|
||||
fileBlockSizeRatio = mynode._dentry.Entry.block_size / 2048;
|
||||
else
|
||||
fileBlockSizeRatio = entry.Entry.block_size / _image.Info.SectorSize;
|
||||
fileBlockSizeRatio = mynode._dentry.Entry.block_size / _image.Info.SectorSize;
|
||||
|
||||
ErrorNumber errno = _image.ReadSectors((ulong)(entry.Pointers[0] + (firstBlock * fileBlockSizeRatio)),
|
||||
(uint)(sizeInBlocks * fileBlockSizeRatio), out byte[] buffer);
|
||||
ErrorNumber errno = _image.ReadSectors((ulong)(mynode._dentry.Pointers[0] + (firstBlock * fileBlockSizeRatio)),
|
||||
(uint)(sizeInBlocks * fileBlockSizeRatio), out byte[] buf);
|
||||
|
||||
if(errno != ErrorNumber.NoError)
|
||||
return errno;
|
||||
{
|
||||
read = 0;
|
||||
|
||||
buf = new byte[size];
|
||||
Array.Copy(buffer, offsetInBlock, buf, 0, size);
|
||||
return errno;
|
||||
}
|
||||
|
||||
Array.Copy(buf, offsetInBlock, buffer, 0, read);
|
||||
|
||||
mynode.Offset += read;
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
@@ -138,52 +138,27 @@ public sealed partial class PascalPlugin
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber Read(string path, long offset, long size, ref byte[] buf)
|
||||
public ErrorNumber ReadFile(IFileNode node, long length, byte[] buffer, out long read)
|
||||
{
|
||||
read = 0;
|
||||
|
||||
if(!_mounted)
|
||||
return ErrorNumber.AccessDenied;
|
||||
|
||||
string[] pathElements = path.Split(new[]
|
||||
{
|
||||
'/'
|
||||
}, StringSplitOptions.RemoveEmptyEntries);
|
||||
if(buffer is null ||
|
||||
buffer.Length < length)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
|
||||
if(pathElements.Length != 1)
|
||||
return ErrorNumber.NotSupported;
|
||||
if(node is not PascalFileNode mynode)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
|
||||
byte[] file;
|
||||
read = length;
|
||||
|
||||
if(_debug && (string.Compare(path, "$", StringComparison.InvariantCulture) == 0 ||
|
||||
string.Compare(path, "$Boot", StringComparison.InvariantCulture) == 0))
|
||||
file = string.Compare(path, "$", StringComparison.InvariantCulture) == 0 ? _catalogBlocks : _bootBlocks;
|
||||
else
|
||||
{
|
||||
ErrorNumber error = GetFileEntry(path, out PascalFileEntry entry);
|
||||
if(length + mynode.Offset >= mynode.Length)
|
||||
read = mynode.Length - mynode.Offset;
|
||||
|
||||
if(error != ErrorNumber.NoError)
|
||||
return error;
|
||||
|
||||
error = _device.ReadSectors((ulong)entry.FirstBlock * _multiplier,
|
||||
(uint)(entry.LastBlock - entry.FirstBlock) * _multiplier, out byte[] tmp);
|
||||
|
||||
if(error != ErrorNumber.NoError)
|
||||
return error;
|
||||
|
||||
file = new byte[((entry.LastBlock - entry.FirstBlock - 1) * _device.Info.SectorSize * _multiplier) +
|
||||
entry.LastBytes];
|
||||
|
||||
Array.Copy(tmp, 0, file, 0, file.Length);
|
||||
}
|
||||
|
||||
if(offset >= file.Length)
|
||||
return ErrorNumber.EINVAL;
|
||||
|
||||
if(size + offset >= file.Length)
|
||||
size = file.Length - offset;
|
||||
|
||||
buf = new byte[size];
|
||||
|
||||
Array.Copy(file, offset, buf, 0, size);
|
||||
Array.Copy(mynode._cache, mynode.Offset, buffer, 0, read);
|
||||
mynode.Offset += read;
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ using System.Linq;
|
||||
using System.Reactive;
|
||||
using System.Threading.Tasks;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
using Aaru.CommonTypes.Interop;
|
||||
using Aaru.CommonTypes.Structs;
|
||||
using Aaru.Console;
|
||||
@@ -316,9 +317,15 @@ public sealed class SubdirectoryViewModel
|
||||
|
||||
try
|
||||
{
|
||||
byte[] outBuf = Array.Empty<byte>();
|
||||
byte[] outBuf = new byte[file.Stat.Length];
|
||||
|
||||
ErrorNumber error = _model.Plugin.Read(_model.Path + "/" + file.Name, 0, file.Stat.Length, ref outBuf);
|
||||
ErrorNumber error = _model.Plugin.OpenFile(_model.Path + "/" + file.Name, out IFileNode fileNode);
|
||||
|
||||
if(error == ErrorNumber.NoError)
|
||||
{
|
||||
error = _model.Plugin.ReadFile(fileNode, file.Stat.Length, outBuf, out _);
|
||||
_model.Plugin.CloseFile(fileNode);
|
||||
}
|
||||
|
||||
if(error != ErrorNumber.NoError)
|
||||
{
|
||||
|
||||
@@ -309,7 +309,14 @@ public abstract class ReadOnlyFilesystemTest : FilesystemTest
|
||||
static string BuildFile(IReadOnlyFilesystem fs, string path, long length)
|
||||
{
|
||||
byte[] buffer = new byte[length];
|
||||
fs.Read(path, 0, length, ref buffer);
|
||||
|
||||
ErrorNumber error = fs.OpenFile(path, out IFileNode fileNode);
|
||||
|
||||
if(error != ErrorNumber.NoError)
|
||||
return Md5Context.Data(buffer, out _);
|
||||
|
||||
fs.ReadFile(fileNode, length, buffer, out _);
|
||||
fs.CloseFile(fileNode);
|
||||
|
||||
return Md5Context.Data(buffer, out _);
|
||||
}
|
||||
@@ -426,7 +433,7 @@ public abstract class ReadOnlyFilesystemTest : FilesystemTest
|
||||
|
||||
if(child.Value.Info.Attributes.HasFlag(FileAttributes.Directory))
|
||||
{
|
||||
ret = fs.Read(childPath, 0, 1, ref buffer);
|
||||
ret = fs.OpenFile(childPath, out _);
|
||||
|
||||
Assert.AreEqual(ErrorNumber.IsDirectory, ret,
|
||||
string.Format(Localization.Got_wrong_data_for_directory_0_in_1, childPath, testFile));
|
||||
@@ -507,14 +514,26 @@ public abstract class ReadOnlyFilesystemTest : FilesystemTest
|
||||
static void TestFile(IReadOnlyFilesystem fs, string path, string md5, long length, string testFile)
|
||||
{
|
||||
byte[] buffer = new byte[length];
|
||||
ErrorNumber ret = fs.Read(path, 0, length, ref buffer);
|
||||
ErrorNumber ret = fs.OpenFile(path, out IFileNode fileNode);
|
||||
|
||||
Assert.AreEqual(ErrorNumber.NoError, ret,
|
||||
string.Format(Localization.Unexpected_error_0_when_reading_1_in_2, ret, path, testFile));
|
||||
|
||||
ret = fs.ReadFile(fileNode, length, buffer, out long readBytes);
|
||||
|
||||
Assert.AreEqual(ErrorNumber.NoError, ret,
|
||||
string.Format(Localization.Unexpected_error_0_when_reading_1_in_2, ret, path, testFile));
|
||||
|
||||
Assert.AreEqual(length, readBytes,
|
||||
string.Format(Localization.Got_less_bytes_0_than_expected_1_when_reading_2_in_3, readBytes,
|
||||
length, path, testFile));
|
||||
|
||||
fs.CloseFile(fileNode);
|
||||
|
||||
string data = Md5Context.Data(buffer, out _);
|
||||
|
||||
Assert.AreEqual(md5, data, $"Got MD5 {data} for \"{path}\" in {testFile} but expected {md5}");
|
||||
Assert.AreEqual(md5, data,
|
||||
string.Format(Localization.Got_MD5_0_for_1_in_2_but_expected_3, data, path, testFile, md5));
|
||||
}
|
||||
|
||||
static void TestFileXattrs(IReadOnlyFilesystem fs, string path, Dictionary<string, string> xattrs, string testFile)
|
||||
|
||||
@@ -251,14 +251,24 @@ public abstract class FsExtractHashIssueTest
|
||||
expectedXattrs);
|
||||
}
|
||||
|
||||
byte[] outBuf = Array.Empty<byte>();
|
||||
byte[] buffer = new byte[stat.Length];
|
||||
ErrorNumber ret = fs.OpenFile(path + "/" + entry, out IFileNode fileNode);
|
||||
|
||||
error = fs.Read(path + "/" + entry, 0, stat.Length, ref outBuf);
|
||||
Assert.AreEqual(ErrorNumber.NoError, ret,
|
||||
string.Format(Localization.Error_0_reading_file_1, ret, path + "/" + entry));
|
||||
|
||||
Assert.AreEqual(ErrorNumber.NoError, error,
|
||||
string.Format(Localization.Error_0_reading_file_1, error, path + "/" + entry));
|
||||
ret = fs.ReadFile(fileNode, stat.Length, buffer, out long readBytes);
|
||||
|
||||
string calculatedMd5 = Md5Context.Data(outBuf, out _);
|
||||
Assert.AreEqual(ErrorNumber.NoError, ret,
|
||||
string.Format(Localization.Error_0_reading_file_1, ret, path + "/" + entry));
|
||||
|
||||
Assert.AreEqual(stat.Length, readBytes,
|
||||
string.Format(Localization.Error_0_reading_file_1, readBytes, stat.Length,
|
||||
path + "/" + entry));
|
||||
|
||||
fs.CloseFile(fileNode);
|
||||
|
||||
string calculatedMd5 = Md5Context.Data(buffer, out _);
|
||||
|
||||
Assert.AreEqual(fileData.Md5, calculatedMd5,
|
||||
string.Format(Localization.Invalid_checksum_for_file_0, path + "/" + entry));
|
||||
|
||||
@@ -168,12 +168,20 @@ public abstract class FsExtractIssueTest
|
||||
}
|
||||
}
|
||||
|
||||
byte[] outBuf = Array.Empty<byte>();
|
||||
byte[] buffer = new byte[stat.Length];
|
||||
ErrorNumber ret = fs.OpenFile(path + "/" + entry, out IFileNode fileNode);
|
||||
|
||||
error = fs.Read(path + "/" + entry, 0, stat.Length, ref outBuf);
|
||||
Assert.AreEqual(ErrorNumber.NoError, ret,
|
||||
string.Format(Localization.Error_0_reading_file_1, ret, path + "/" + entry));
|
||||
|
||||
Assert.AreEqual(ErrorNumber.NoError, error,
|
||||
string.Format(Localization.Error_0_reading_file_1, error, path + "/" + entry));
|
||||
ret = fs.ReadFile(fileNode, stat.Length, buffer, out long readBytes);
|
||||
|
||||
Assert.AreEqual(ErrorNumber.NoError, ret,
|
||||
string.Format(Localization.Error_0_reading_file_1, ret, path + "/" + entry));
|
||||
|
||||
Assert.AreEqual(stat.Length, readBytes,
|
||||
string.Format(Localization.Error_0_reading_file_1, readBytes, stat.Length,
|
||||
path + "/" + entry));
|
||||
}
|
||||
}
|
||||
}
|
||||
2399
Aaru.Tests/Localization/Localization.Designer.cs
generated
2399
Aaru.Tests/Localization/Localization.Designer.cs
generated
File diff suppressed because it is too large
Load Diff
@@ -540,4 +540,10 @@
|
||||
<data name="Subchannel_hash_output_0" xml:space="preserve">
|
||||
<value>Subchannel hash (output): {0}</value>
|
||||
</data>
|
||||
<data name="Got_less_bytes_0_than_expected_1_when_reading_2_in_3" xml:space="preserve">
|
||||
<value>Got less bytes ({0}) than expected ({1}) when reading {2} in {3}</value>
|
||||
</data>
|
||||
<data name="Got_MD5_0_for_1_in_2_but_expected_3" xml:space="preserve">
|
||||
<value>Got MD5 {0} for "{1}" in {2} but expected {3}</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -601,31 +601,39 @@ sealed class ExtractFilesCommand : Command
|
||||
ctx.AddTask(string.Format(UI.Reading_file_0, Markup.Escape(entry)));
|
||||
|
||||
task.MaxValue = stat.Length;
|
||||
byte[] outBuf = null;
|
||||
byte[] outBuf = new byte[BUFFER_SIZE];
|
||||
error = fs.OpenFile(path + "/" + entry, out IFileNode fileNode);
|
||||
|
||||
while(position < stat.Length)
|
||||
if(error == ErrorNumber.NoError)
|
||||
{
|
||||
long bytesToRead;
|
||||
|
||||
if(stat.Length - position > BUFFER_SIZE)
|
||||
bytesToRead = BUFFER_SIZE;
|
||||
else
|
||||
bytesToRead = stat.Length - position;
|
||||
|
||||
error = fs.Read(path + "/" + entry, position, bytesToRead, ref outBuf);
|
||||
|
||||
if(error == ErrorNumber.NoError)
|
||||
outputFile.Write(outBuf, 0, (int)bytesToRead);
|
||||
else
|
||||
while(position < stat.Length)
|
||||
{
|
||||
AaruConsole.ErrorWriteLine(UI.Error_0_reading_file_1, error, entry);
|
||||
long bytesToRead;
|
||||
|
||||
break;
|
||||
if(stat.Length - position > BUFFER_SIZE)
|
||||
bytesToRead = BUFFER_SIZE;
|
||||
else
|
||||
bytesToRead = stat.Length - position;
|
||||
|
||||
error = fs.ReadFile(fileNode, bytesToRead, outBuf, out long bytesRead);
|
||||
|
||||
if(error == ErrorNumber.NoError)
|
||||
outputFile.Write(outBuf, 0, (int)bytesRead);
|
||||
else
|
||||
{
|
||||
AaruConsole.ErrorWriteLine(UI.Error_0_reading_file_1, error, entry);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
position += bytesToRead;
|
||||
task.Increment(bytesToRead);
|
||||
}
|
||||
|
||||
position += bytesToRead;
|
||||
task.Increment(bytesToRead);
|
||||
fs.CloseFile(fileNode);
|
||||
}
|
||||
else
|
||||
AaruConsole.ErrorWriteLine(UI.Error_0_reading_file_1, error, entry);
|
||||
});
|
||||
|
||||
outputFile.Close();
|
||||
|
||||
Reference in New Issue
Block a user