From 429a40de129c86ed076b3292890517aa5ed953d4 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Wed, 10 Apr 2019 20:25:16 +0100 Subject: [PATCH] Implement Stat in Xbox FAT plugin. --- DiscImageChef.Filesystems/FATX/Dir.cs | 2 +- DiscImageChef.Filesystems/FATX/FATX.cs | 3 +- DiscImageChef.Filesystems/FATX/File.cs | 85 ++++++++++++++++++++++++- DiscImageChef.Filesystems/FATX/Super.cs | 4 +- 4 files changed, 88 insertions(+), 6 deletions(-) diff --git a/DiscImageChef.Filesystems/FATX/Dir.cs b/DiscImageChef.Filesystems/FATX/Dir.cs index 28fe2d261..a60c6c321 100644 --- a/DiscImageChef.Filesystems/FATX/Dir.cs +++ b/DiscImageChef.Filesystems/FATX/Dir.cs @@ -59,7 +59,7 @@ namespace DiscImageChef.Filesystems.FATX return Errno.NoError; } - string[] pieces = cutPath.Split('/'); + string[] pieces = cutPath.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries); KeyValuePair entry = rootDirectory.FirstOrDefault(t => t.Key.ToLower(cultureInfo) == pieces[0]); diff --git a/DiscImageChef.Filesystems/FATX/FATX.cs b/DiscImageChef.Filesystems/FATX/FATX.cs index f27ca7ba3..47c346951 100644 --- a/DiscImageChef.Filesystems/FATX/FATX.cs +++ b/DiscImageChef.Filesystems/FATX/FATX.cs @@ -34,7 +34,6 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Text; -using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Structs; using Schemas; @@ -45,6 +44,7 @@ namespace DiscImageChef.Filesystems.FATX { uint bytesPerCluster; CultureInfo cultureInfo; + bool debug; Dictionary> directoryCache; ushort[] fat16; uint[] fat32; @@ -53,7 +53,6 @@ namespace DiscImageChef.Filesystems.FATX IMediaImage imagePlugin; bool littleEndian; bool mounted; - Partition partition; Dictionary rootDirectory; uint sectorsPerCluster; FileSystemInfo stat; diff --git a/DiscImageChef.Filesystems/FATX/File.cs b/DiscImageChef.Filesystems/FATX/File.cs index 66a2fc512..b94ebc74c 100644 --- a/DiscImageChef.Filesystems/FATX/File.cs +++ b/DiscImageChef.Filesystems/FATX/File.cs @@ -32,6 +32,7 @@ using System; using System.Collections.Generic; +using System.Linq; using DiscImageChef.CommonTypes.Structs; namespace DiscImageChef.Filesystems.FATX @@ -66,7 +67,59 @@ namespace DiscImageChef.Filesystems.FATX stat = null; if(!mounted) return Errno.AccessDenied; - throw new NotImplementedException(); + if(debug && (string.IsNullOrEmpty(path) || path == "$" || path == "/")) + { + stat = new FileEntryInfo + { + Attributes = FileAttributes.Directory | FileAttributes.System | FileAttributes.Hidden, + Blocks = GetClusters(superblock.rootDirectoryCluster).Length, + BlockSize = bytesPerCluster, + DeviceNo = 0, + GID = 0, + Length = GetClusters(superblock.rootDirectoryCluster).Length * bytesPerCluster, + Inode = superblock.rootDirectoryCluster, + Links = 1, + Mode = 0x16D, + UID = 0 + }; + + return Errno.NoError; + } + + Errno err = GetFileEntry(path, out DirectoryEntry entry); + if(err != Errno.NoError) return err; + + stat = new FileEntryInfo + { + Attributes = new FileAttributes(), + Blocks = entry.length / bytesPerCluster, + BlockSize = bytesPerCluster, + DeviceNo = 0, + GID = 0, + Length = entry.length, + Inode = entry.firstCluster, + Links = 1, + Mode = (uint)(entry.attributes.HasFlag(Attributes.Directory) ? 0x16D : 0x124), + UID = 0, + CreationTime = DateHandlers.DosToDateTime(entry.creationDate, entry.creationTime).AddYears(20), + AccessTime = DateHandlers.DosToDateTime(entry.lastAccessDate, entry.lastAccessTime).AddYears(20), + LastWriteTime = DateHandlers.DosToDateTime(entry.lastWrittenDate, entry.lastWrittenTime) + .AddYears(20) + }; + + if(entry.attributes.HasFlag(Attributes.Directory)) + { + stat.Attributes |= FileAttributes.Directory; + stat.Blocks = GetClusters(entry.firstCluster).Length; + stat.Length = stat.Blocks * stat.BlockSize; + } + + if(entry.attributes.HasFlag(Attributes.ReadOnly)) stat.Attributes |= FileAttributes.ReadOnly; + if(entry.attributes.HasFlag(Attributes.Hidden)) stat.Attributes |= FileAttributes.Hidden; + if(entry.attributes.HasFlag(Attributes.System)) stat.Attributes |= FileAttributes.System; + if(entry.attributes.HasFlag(Attributes.Archive)) stat.Attributes |= FileAttributes.Archive; + + return Errno.NoError; } uint[] GetClusters(uint startCluster) @@ -98,5 +151,35 @@ namespace DiscImageChef.Filesystems.FATX return clusters.ToArray(); } + + Errno GetFileEntry(string path, out DirectoryEntry entry) + { + entry = new DirectoryEntry(); + + string cutPath = + path.StartsWith("/") ? path.Substring(0).ToLower(cultureInfo) : path.ToLower(cultureInfo); + string[] pieces = cutPath.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries); + + if(pieces.Length == 0) return Errno.InvalidArgument; + + string parentPath = string.Join("/", pieces, 0, pieces.Length - 1); + + Errno err = ReadDir(parentPath, out _); + + if(err != Errno.NoError) return err; + + Dictionary parent; + + if(pieces.Length == 1) parent = rootDirectory; + else if(!directoryCache.TryGetValue(parentPath, out parent)) return Errno.InvalidArgument; + + KeyValuePair dirent = + parent.FirstOrDefault(t => t.Key.ToLower(cultureInfo) == pieces[pieces.Length - 1]); + + if(string.IsNullOrEmpty(dirent.Key)) return Errno.NoSuchFile; + + entry = dirent.Value; + return Errno.NoError; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/FATX/Super.cs b/DiscImageChef.Filesystems/FATX/Super.cs index 399244f3a..20c51686f 100644 --- a/DiscImageChef.Filesystems/FATX/Super.cs +++ b/DiscImageChef.Filesystems/FATX/Super.cs @@ -51,6 +51,8 @@ namespace DiscImageChef.Filesystems.FATX { Encoding = Encoding.GetEncoding("iso-8859-15"); littleEndian = true; + if(options == null) options = GetDefaultOptions(); + if(options.TryGetValue("debug", out string debugString)) bool.TryParse(debugString, out debug); if(imagePlugin.Info.SectorSize < 512) return Errno.InvalidArgument; @@ -157,7 +159,6 @@ namespace DiscImageChef.Filesystems.FATX } sectorsPerCluster = (uint)(superblock.sectorsPerCluster * logicalSectorsPerPhysicalSectors); - this.partition = partition; this.imagePlugin = imagePlugin; firstClusterSector = fatStartSector + fatSize; bytesPerCluster = sectorsPerCluster * imagePlugin.Info.SectorSize; @@ -221,7 +222,6 @@ namespace DiscImageChef.Filesystems.FATX fat16 = null; fat32 = null; imagePlugin = null; - partition = new Partition(); mounted = false; return Errno.NoError;