mirror of
https://github.com/aaru-dps/Aaru.git
synced 2026-07-08 18:16:24 +00:00
[cramfs] Implement mount.
This commit is contained in:
72
Aaru.Filesystems/Cram/Block.cs
Normal file
72
Aaru.Filesystems/Cram/Block.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
// /***************************************************************************
|
||||
// Aaru Data Preservation Suite
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// Filename : Block.cs
|
||||
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||
//
|
||||
// Component : Cram file system plugin.
|
||||
//
|
||||
// --[ 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-2026 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
|
||||
namespace Aaru.Filesystems;
|
||||
|
||||
/// <inheritdoc />
|
||||
public sealed partial class Cram
|
||||
{
|
||||
/// <summary>Reads bytes from the filesystem</summary>
|
||||
/// <param name="offset">Byte offset from start of filesystem</param>
|
||||
/// <param name="length">Number of bytes to read</param>
|
||||
/// <param name="data">Output data buffer</param>
|
||||
/// <returns>Error number indicating success or failure</returns>
|
||||
ErrorNumber ReadBytes(uint offset, uint length, out byte[] data)
|
||||
{
|
||||
data = null;
|
||||
|
||||
// Add base offset
|
||||
uint actualOffset = _baseOffset + offset;
|
||||
|
||||
// Calculate sector and offset
|
||||
uint sectorSize = _imagePlugin.Info.SectorSize;
|
||||
uint startSector = actualOffset / sectorSize;
|
||||
var offsetInSector = (int)(actualOffset % sectorSize);
|
||||
var sectorsToRead = (uint)((offsetInSector + length + sectorSize - 1) / sectorSize);
|
||||
|
||||
ErrorNumber errno = _imagePlugin.ReadSectors(_partition.Start + startSector,
|
||||
false,
|
||||
sectorsToRead,
|
||||
out byte[] sectorData,
|
||||
out _);
|
||||
|
||||
if(errno != ErrorNumber.NoError) return errno;
|
||||
|
||||
data = new byte[length];
|
||||
|
||||
if(offsetInSector + length <= sectorData.Length)
|
||||
Array.Copy(sectorData, offsetInSector, data, 0, length);
|
||||
else
|
||||
Array.Copy(sectorData, offsetInSector, data, 0, sectorData.Length - offsetInSector);
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
}
|
||||
@@ -31,8 +31,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text;
|
||||
using Aaru.CommonTypes.AaruMetadata;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
using Partition = Aaru.CommonTypes.Partition;
|
||||
|
||||
namespace Aaru.Filesystems;
|
||||
|
||||
@@ -41,6 +43,32 @@ namespace Aaru.Filesystems;
|
||||
[SuppressMessage("ReSharper", "UnusedType.Local")]
|
||||
public sealed partial class Cram : IReadOnlyFilesystem
|
||||
{
|
||||
const string MODULE_NAME = "CramFS plugin";
|
||||
|
||||
/// <summary>Cached root directory entries</summary>
|
||||
Dictionary<string, DirectoryEntryInfo> _rootDirectoryCache;
|
||||
|
||||
/// <summary>Encoding used for filenames</summary>
|
||||
Encoding _encoding;
|
||||
|
||||
/// <summary>Image plugin being accessed</summary>
|
||||
IMediaImage _imagePlugin;
|
||||
|
||||
/// <summary>Whether filesystem is mounted</summary>
|
||||
bool _mounted;
|
||||
|
||||
/// <summary>Partition being mounted</summary>
|
||||
Partition _partition;
|
||||
|
||||
/// <summary>The superblock</summary>
|
||||
SuperBlock _superBlock;
|
||||
|
||||
/// <summary>Whether the filesystem is little-endian</summary>
|
||||
bool _littleEndian;
|
||||
|
||||
/// <summary>Base offset for the filesystem (0 or 512 for shifted superblock)</summary>
|
||||
uint _baseOffset;
|
||||
|
||||
#region IFilesystem Members
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
125
Aaru.Filesystems/Cram/Dir.cs
Normal file
125
Aaru.Filesystems/Cram/Dir.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
// /***************************************************************************
|
||||
// Aaru Data Preservation Suite
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// Filename : Dir.cs
|
||||
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||
//
|
||||
// Component : Cram file system plugin.
|
||||
//
|
||||
// --[ 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-2026 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using Aaru.Helpers;
|
||||
using Aaru.Logging;
|
||||
|
||||
namespace Aaru.Filesystems;
|
||||
|
||||
/// <inheritdoc />
|
||||
public sealed partial class Cram
|
||||
{
|
||||
/// <summary>Reads and parses directory contents</summary>
|
||||
/// <param name="offset">Byte offset of the directory data</param>
|
||||
/// <param name="size">Size of the directory in bytes</param>
|
||||
/// <param name="entries">Dictionary to populate with entries</param>
|
||||
/// <returns>Error number indicating success or failure</returns>
|
||||
ErrorNumber ReadDirectoryContents(uint offset, uint size, Dictionary<string, DirectoryEntryInfo> entries)
|
||||
{
|
||||
if(size == 0) return ErrorNumber.NoError;
|
||||
|
||||
// Read the directory data
|
||||
ErrorNumber errno = ReadBytes(offset, size, out byte[] dirData);
|
||||
|
||||
if(errno != ErrorNumber.NoError)
|
||||
{
|
||||
AaruLogging.Debug(MODULE_NAME, "Error reading directory data at offset {0}: {1}", offset, errno);
|
||||
|
||||
return errno;
|
||||
}
|
||||
|
||||
// Parse directory entries
|
||||
// Each entry is: cramfs_inode (12 bytes) + name (padded to 4 bytes)
|
||||
uint currentOffset = 0;
|
||||
|
||||
while(currentOffset < size)
|
||||
{
|
||||
if(currentOffset + 12 > dirData.Length) break;
|
||||
|
||||
var inodeData = new byte[12];
|
||||
Array.Copy(dirData, currentOffset, inodeData, 0, 12);
|
||||
|
||||
Inode inode = _littleEndian
|
||||
? Marshal.ByteArrayToStructureLittleEndian<Inode>(inodeData)
|
||||
: Marshal.ByteArrayToStructureBigEndian<Inode>(inodeData);
|
||||
|
||||
// Name length is stored as (actual_length + 3) / 4, so multiply by 4 to get padded length
|
||||
int nameLen = inode.NameLen << 2;
|
||||
|
||||
if(nameLen == 0)
|
||||
{
|
||||
AaruLogging.Debug(MODULE_NAME, "Zero name length at offset {0}", currentOffset);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(currentOffset + 12 + nameLen > dirData.Length)
|
||||
{
|
||||
AaruLogging.Debug(MODULE_NAME, "Name extends beyond directory data");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Read the name (it's null-padded to 4-byte boundary)
|
||||
var nameBytes = new byte[nameLen];
|
||||
Array.Copy(dirData, currentOffset + 12, nameBytes, 0, nameLen);
|
||||
|
||||
string name = StringHandlers.CToString(nameBytes, _encoding);
|
||||
|
||||
if(string.IsNullOrEmpty(name))
|
||||
{
|
||||
AaruLogging.Debug(MODULE_NAME, "Empty name at offset {0}", currentOffset);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Skip . and .. entries
|
||||
if(name is not "." and not "..")
|
||||
{
|
||||
var entry = new DirectoryEntryInfo
|
||||
{
|
||||
Name = name,
|
||||
Inode = inode,
|
||||
Offset = offset + currentOffset
|
||||
};
|
||||
|
||||
entries.TryAdd(name, entry);
|
||||
}
|
||||
|
||||
currentOffset += (uint)(12 + nameLen);
|
||||
}
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
/// <summary>Checks if a mode indicates a directory</summary>
|
||||
static bool IsDirectory(ushort mode) => (mode & 0xF000) == 0x4000; // S_IFDIR
|
||||
}
|
||||
82
Aaru.Filesystems/Cram/Internal.cs
Normal file
82
Aaru.Filesystems/Cram/Internal.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
// /***************************************************************************
|
||||
// Aaru Data Preservation Suite
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// Filename : Internal.cs
|
||||
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||
//
|
||||
// Component : Cram file system plugin.
|
||||
//
|
||||
// --[ 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-2026 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
|
||||
namespace Aaru.Filesystems;
|
||||
|
||||
/// <inheritdoc />
|
||||
public sealed partial class Cram
|
||||
{
|
||||
/// <summary>Internal representation of a directory entry</summary>
|
||||
sealed class DirectoryEntryInfo
|
||||
{
|
||||
/// <summary>Filename</summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>The cramfs inode</summary>
|
||||
public Inode Inode { get; set; }
|
||||
|
||||
/// <summary>Byte offset of this entry in the filesystem</summary>
|
||||
public uint Offset { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>Directory node for traversing directories</summary>
|
||||
sealed class CramDirNode : IDirNode
|
||||
{
|
||||
/// <summary>Current position in the directory listing</summary>
|
||||
public int Position { get; set; }
|
||||
|
||||
/// <summary>Cached directory entries</summary>
|
||||
public Dictionary<string, DirectoryEntryInfo> Entries { get; set; }
|
||||
|
||||
/// <summary>Entry names for enumeration</summary>
|
||||
public string[] EntryNames { get; set; }
|
||||
/// <inheritdoc />
|
||||
public string Path { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>File node for reading file contents</summary>
|
||||
sealed class CramFileNode : IFileNode
|
||||
{
|
||||
/// <summary>The cramfs inode</summary>
|
||||
internal Inode Inode { get; init; }
|
||||
|
||||
/// <summary>Byte offset of data in the filesystem</summary>
|
||||
internal uint DataOffset { get; init; }
|
||||
/// <inheritdoc />
|
||||
public string Path { get; init; }
|
||||
|
||||
/// <summary>Current read position within the file</summary>
|
||||
public long Offset { get; set; }
|
||||
|
||||
/// <summary>File length in bytes</summary>
|
||||
public long Length { get; init; }
|
||||
}
|
||||
}
|
||||
250
Aaru.Filesystems/Cram/Mount.cs
Normal file
250
Aaru.Filesystems/Cram/Mount.cs
Normal file
@@ -0,0 +1,250 @@
|
||||
// /***************************************************************************
|
||||
// Aaru Data Preservation Suite
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// Filename : Mount.cs
|
||||
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||
//
|
||||
// Component : Cram file system plugin.
|
||||
//
|
||||
// --[ 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-2026 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Aaru.CommonTypes.AaruMetadata;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
using Aaru.Helpers;
|
||||
using Aaru.Logging;
|
||||
using Partition = Aaru.CommonTypes.Partition;
|
||||
|
||||
namespace Aaru.Filesystems;
|
||||
|
||||
/// <inheritdoc />
|
||||
public sealed partial class Cram
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding,
|
||||
Dictionary<string, string> options, string @namespace)
|
||||
{
|
||||
AaruLogging.Debug(MODULE_NAME, "Mounting CramFS volume");
|
||||
|
||||
_imagePlugin = imagePlugin;
|
||||
_partition = partition;
|
||||
_encoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
_rootDirectoryCache = new Dictionary<string, DirectoryEntryInfo>(StringComparer.Ordinal);
|
||||
|
||||
// Read and validate the superblock
|
||||
ErrorNumber errno = ReadSuperBlock();
|
||||
|
||||
if(errno != ErrorNumber.NoError)
|
||||
{
|
||||
AaruLogging.Debug(MODULE_NAME, "Error reading superblock: {0}", errno);
|
||||
|
||||
return errno;
|
||||
}
|
||||
|
||||
AaruLogging.Debug(MODULE_NAME, "Superblock read successfully");
|
||||
|
||||
// Check for unsupported flags
|
||||
var flags = (CramFlags)_superBlock.flags;
|
||||
|
||||
if(((uint)flags & ~(uint)CramSupportedFlags.All) != 0)
|
||||
{
|
||||
AaruLogging.Debug(MODULE_NAME, "Unsupported flags: 0x{0:X8}", _superBlock.flags);
|
||||
|
||||
return ErrorNumber.NotSupported;
|
||||
}
|
||||
|
||||
// Validate root inode is a directory
|
||||
if(!IsDirectory(_superBlock.root.Mode))
|
||||
{
|
||||
AaruLogging.Debug(MODULE_NAME, "Root is not a directory, mode: 0x{0:X4}", _superBlock.root.Mode);
|
||||
|
||||
return ErrorNumber.InvalidArgument;
|
||||
}
|
||||
|
||||
// Load root directory
|
||||
errno = LoadRootDirectory();
|
||||
|
||||
if(errno != ErrorNumber.NoError)
|
||||
{
|
||||
AaruLogging.Debug(MODULE_NAME, "Error loading root directory: {0}", errno);
|
||||
|
||||
return errno;
|
||||
}
|
||||
|
||||
AaruLogging.Debug(MODULE_NAME, "Root directory loaded with {0} entries", _rootDirectoryCache.Count);
|
||||
|
||||
// Build metadata
|
||||
string volumeName = StringHandlers.CToString(_superBlock.name, _encoding);
|
||||
|
||||
Metadata = new FileSystem
|
||||
{
|
||||
Type = FS_TYPE,
|
||||
VolumeName = volumeName,
|
||||
ClusterSize = 4096, // CramFS uses 4K pages
|
||||
Clusters = _superBlock.fsid.blocks,
|
||||
Files = _superBlock.fsid.files,
|
||||
FreeClusters = 0 // CramFS is read-only, no free space
|
||||
};
|
||||
|
||||
_mounted = true;
|
||||
|
||||
AaruLogging.Debug(MODULE_NAME, "Volume mounted successfully");
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber Unmount()
|
||||
{
|
||||
if(!_mounted) return ErrorNumber.AccessDenied;
|
||||
|
||||
AaruLogging.Debug(MODULE_NAME, "Unmounting volume");
|
||||
|
||||
_rootDirectoryCache?.Clear();
|
||||
_mounted = false;
|
||||
_imagePlugin = null;
|
||||
_partition = default(Partition);
|
||||
_superBlock = default(SuperBlock);
|
||||
_encoding = null;
|
||||
_baseOffset = 0;
|
||||
Metadata = null;
|
||||
|
||||
AaruLogging.Debug(MODULE_NAME, "Volume unmounted");
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
/// <summary>Reads and validates the CramFS superblock</summary>
|
||||
/// <returns>Error number indicating success or failure</returns>
|
||||
ErrorNumber ReadSuperBlock()
|
||||
{
|
||||
AaruLogging.Debug(MODULE_NAME, "Reading superblock...");
|
||||
|
||||
// Read the first sector
|
||||
ErrorNumber errno = _imagePlugin.ReadSector(_partition.Start, false, out byte[] sector, out _);
|
||||
|
||||
if(errno != ErrorNumber.NoError)
|
||||
{
|
||||
AaruLogging.Debug(MODULE_NAME, "Error reading first sector: {0}", errno);
|
||||
|
||||
return errno;
|
||||
}
|
||||
|
||||
// Check magic at offset 0
|
||||
var magic = BitConverter.ToUInt32(sector, 0);
|
||||
|
||||
_baseOffset = 0;
|
||||
|
||||
if(magic == CRAM_MAGIC)
|
||||
{
|
||||
_superBlock = Marshal.ByteArrayToStructureLittleEndian<SuperBlock>(sector);
|
||||
_littleEndian = true;
|
||||
}
|
||||
else if(magic == CRAM_CIGAM)
|
||||
{
|
||||
_superBlock = Marshal.ByteArrayToStructureBigEndian<SuperBlock>(sector);
|
||||
_littleEndian = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check at 512 byte offset (some cramfs images have the superblock shifted)
|
||||
if(sector.Length >= 512 + 4)
|
||||
{
|
||||
magic = BitConverter.ToUInt32(sector, 512);
|
||||
|
||||
if(magic == CRAM_MAGIC)
|
||||
{
|
||||
var sbData = new byte[sector.Length - 512];
|
||||
Array.Copy(sector, 512, sbData, 0, sbData.Length);
|
||||
_superBlock = Marshal.ByteArrayToStructureLittleEndian<SuperBlock>(sbData);
|
||||
_littleEndian = true;
|
||||
_baseOffset = 512;
|
||||
}
|
||||
else if(magic == CRAM_CIGAM)
|
||||
{
|
||||
var sbData = new byte[sector.Length - 512];
|
||||
Array.Copy(sector, 512, sbData, 0, sbData.Length);
|
||||
_superBlock = Marshal.ByteArrayToStructureBigEndian<SuperBlock>(sbData);
|
||||
_littleEndian = false;
|
||||
_baseOffset = 512;
|
||||
}
|
||||
else
|
||||
{
|
||||
AaruLogging.Debug(MODULE_NAME, "Invalid magic: 0x{0:X8}", magic);
|
||||
|
||||
return ErrorNumber.InvalidArgument;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AaruLogging.Debug(MODULE_NAME, "Invalid magic: 0x{0:X8}", magic);
|
||||
|
||||
return ErrorNumber.InvalidArgument;
|
||||
}
|
||||
}
|
||||
|
||||
AaruLogging.Debug(MODULE_NAME,
|
||||
"Magic: 0x{0:X8}, little-endian: {1}, base offset: {2}",
|
||||
_superBlock.magic,
|
||||
_littleEndian,
|
||||
_baseOffset);
|
||||
|
||||
// Validate signature
|
||||
string signature = Encoding.ASCII.GetString(_superBlock.signature);
|
||||
|
||||
if(!signature.StartsWith(CRAMFS_SIGNATURE, StringComparison.Ordinal))
|
||||
{
|
||||
AaruLogging.Debug(MODULE_NAME, "Invalid signature: {0}", signature);
|
||||
|
||||
return ErrorNumber.InvalidArgument;
|
||||
}
|
||||
|
||||
AaruLogging.Debug(MODULE_NAME, "Filesystem size: {0} bytes", _superBlock.size);
|
||||
AaruLogging.Debug(MODULE_NAME, "Flags: 0x{0:X8}", _superBlock.flags);
|
||||
AaruLogging.Debug(MODULE_NAME, "Files: {0}, Blocks: {1}", _superBlock.fsid.files, _superBlock.fsid.blocks);
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
/// <summary>Loads and caches the root directory contents</summary>
|
||||
/// <returns>Error number indicating success or failure</returns>
|
||||
ErrorNumber LoadRootDirectory()
|
||||
{
|
||||
// Root directory offset is in the root inode
|
||||
uint rootOffset = _superBlock.root.Offset << 2;
|
||||
uint rootSize = _superBlock.root.Size;
|
||||
|
||||
AaruLogging.Debug(MODULE_NAME, "Root directory offset: {0}, size: {1}", rootOffset, rootSize);
|
||||
|
||||
if(rootOffset == 0)
|
||||
{
|
||||
// Empty filesystem
|
||||
AaruLogging.Debug(MODULE_NAME, "Empty filesystem (root offset is 0)");
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
return ReadDirectoryContents(rootOffset, rootSize, _rootDirectoryCache);
|
||||
}
|
||||
}
|
||||
@@ -31,8 +31,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text;
|
||||
using Aaru.CommonTypes;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
using Aaru.CommonTypes.Structs;
|
||||
@@ -43,14 +41,6 @@ namespace Aaru.Filesystems;
|
||||
[SuppressMessage("ReSharper", "UnusedType.Local")]
|
||||
public sealed partial class Cram
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding,
|
||||
Dictionary<string, string> options, string @namespace) =>
|
||||
throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber Unmount() => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ListXAttr(string path, out List<string> xattrs) => throw new NotImplementedException();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user