Replace Read method with ReadFile method that uses the file node in IFileSystem.

This commit is contained in:
2022-12-19 11:03:51 +00:00
parent 0fc479a529
commit b4b2868c22
18 changed files with 1780 additions and 1271 deletions

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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)
{

View File

@@ -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)

View File

@@ -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));

View File

@@ -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));
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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>

View File

@@ -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();