From caebccb1486a8366106e4e07e08bf255df4f3afa Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Fri, 19 Jul 2019 16:34:43 +0100 Subject: [PATCH] Implement ISO9660 stat. --- DiscImageChef.Filesystems/ISO9660/File.cs | 64 ++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/DiscImageChef.Filesystems/ISO9660/File.cs b/DiscImageChef.Filesystems/ISO9660/File.cs index ce79d9156..661606eb9 100644 --- a/DiscImageChef.Filesystems/ISO9660/File.cs +++ b/DiscImageChef.Filesystems/ISO9660/File.cs @@ -1,4 +1,7 @@ using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; using DiscImageChef.CommonTypes.Structs; namespace DiscImageChef.Filesystems.ISO9660 @@ -11,6 +14,65 @@ namespace DiscImageChef.Filesystems.ISO9660 public Errno Read(string path, long offset, long size, ref byte[] buf) => throw new NotImplementedException(); - public Errno Stat(string path, out FileEntryInfo stat) => throw new NotImplementedException(); + public Errno Stat(string path, out FileEntryInfo stat) + { + stat = null; + if(!mounted) return Errno.AccessDenied; + + Errno err = GetFileEntry(path, out DecodedDirectoryEntry entry); + if(err != Errno.NoError) return err; + + stat = new FileEntryInfo + { + Attributes = new FileAttributes(), + Blocks = entry.Size / 2048, // TODO: XA + BlockSize = 2048, + Length = entry.Size, + Inode = entry.Extent, + Links = 1, + LastWriteTimeUtc = entry.Timestamp + }; + + if(entry.Size % 2048 > 0) stat.Blocks++; + + if(entry.Flags.HasFlag(FileFlags.Directory)) stat.Attributes |= FileAttributes.Directory; + if(entry.Flags.HasFlag(FileFlags.Hidden)) stat.Attributes |= FileAttributes.Hidden; + + return Errno.NoError; + } + + Errno GetFileEntry(string path, out DecodedDirectoryEntry entry) + { + entry = null; + + string cutPath = path.StartsWith("/") + ? path.Substring(1).ToLower(CultureInfo.CurrentUICulture) + : path.ToLower(CultureInfo.CurrentUICulture); + string[] pieces = cutPath.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries); + + if(pieces.Length == 0) return Errno.InvalidArgument; + + string parentPath = string.Join("/", pieces, 0, pieces.Length - 1); + + if(!directoryCache.TryGetValue(parentPath, out _)) + { + Errno err = ReadDir(parentPath, out _); + + if(err != Errno.NoError) return err; + } + + Dictionary parent; + + if(pieces.Length == 1) parent = rootDirectoryCache; + else if(!directoryCache.TryGetValue(parentPath, out parent)) return Errno.InvalidArgument; + + KeyValuePair dirent = + parent.FirstOrDefault(t => t.Key.ToLower(CultureInfo.CurrentUICulture) == pieces[pieces.Length - 1]); + + if(string.IsNullOrEmpty(dirent.Key)) return Errno.NoSuchFile; + + entry = dirent.Value; + return Errno.NoError; + } } } \ No newline at end of file