diff --git a/Aaru.Filesystems/SonyPFS/File.cs b/Aaru.Filesystems/SonyPFS/File.cs index eaca64d60..670d53fb7 100644 --- a/Aaru.Filesystems/SonyPFS/File.cs +++ b/Aaru.Filesystems/SonyPFS/File.cs @@ -30,6 +30,8 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Runtime.InteropServices; +using System.Text; using Aaru.CommonTypes.Enums; using Aaru.CommonTypes.Interfaces; using Aaru.CommonTypes.Structs; @@ -219,6 +221,49 @@ public partial class SonyPFS return ErrorNumber.NoError; } + /// + public ErrorNumber ReadLink(string path, out string dest) + { + dest = null; + + if(!_mounted) return ErrorNumber.AccessDenied; + + ErrorNumber err = GetFileEntry(path, out DirEntry entry); + + if(err != ErrorNumber.NoError) return err; + + err = ReadInode(entry.Inode, entry.SubPart, out Inode inode); + + if(err != ErrorNumber.NoError) return err; + + if((inode.mode & (ushort)FileType.IFMT) != (ushort)FileType.IFLNK) return ErrorNumber.InvalidArgument; + + // Symlink target is stored as raw bytes starting at data[1] in the inode + // data[0] is the inode's own block; data[1..] onward contains the path string + // Reinterpret data[1..] as bytes + int blockInfoSize = Marshal.SizeOf(); + int maxStringBytes = (PFS_INODE_MAX_BLOCKS - 1) * blockInfoSize; + var linkBytes = new byte[maxStringBytes]; + + for(var i = 1; i < inode.data.Length; i++) + { + int offset = (i - 1) * blockInfoSize; + + byte[] biBytes = Helpers.Marshal.StructureToByteArrayLittleEndian(inode.data[i]); + + Array.Copy(biBytes, 0, linkBytes, offset, blockInfoSize); + } + + // Find null terminator + int len = Array.IndexOf(linkBytes, (byte)0); + + if(len < 0) len = maxStringBytes; + + dest = Encoding.ASCII.GetString(linkBytes, 0, len); + + return ErrorNumber.NoError; + } + /// Resolves a path to a DirEntry by walking the directory tree. ErrorNumber GetFileEntry(string path, out DirEntry entry) { diff --git a/Aaru.Filesystems/SonyPFS/Unimplemented.cs b/Aaru.Filesystems/SonyPFS/Unimplemented.cs deleted file mode 100644 index ab5731f4b..000000000 --- a/Aaru.Filesystems/SonyPFS/Unimplemented.cs +++ /dev/null @@ -1,38 +0,0 @@ -// /*************************************************************************** -// Aaru Data Preservation Suite -// ---------------------------------------------------------------------------- -// -// Filename : Unimplemented.cs -// Author(s) : Natalia Portillo -// -// Component : PlayStation FileSystem 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 . -// -// ---------------------------------------------------------------------------- -// Copyright © 2011-2026 Natalia Portillo -// ****************************************************************************/ - -using System; -using Aaru.CommonTypes.Enums; - -namespace Aaru.Filesystems; - -public partial class SonyPFS -{ - /// - public ErrorNumber ReadLink(string path, out string dest) => throw new NotImplementedException(); -} \ No newline at end of file