using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using DiscImageChef.CommonTypes.Structs; namespace DiscImageChef.Filesystems.ISO9660 { public partial class ISO9660 { public Errno MapBlock(string path, long fileBlock, out long deviceBlock) { deviceBlock = 0; if(!mounted) return Errno.AccessDenied; Errno err = GetFileEntry(path, out DecodedDirectoryEntry entry); if(err != Errno.NoError) return err; if(entry.Flags.HasFlag(FileFlags.Directory) && !debug) return Errno.IsDirectory; deviceBlock = entry.Extent + fileBlock; return Errno.NoError; } public Errno GetAttributes(string path, out FileAttributes attributes) { attributes = new FileAttributes(); if(!mounted) return Errno.AccessDenied; Errno err = Stat(path, out FileEntryInfo stat); if(err != Errno.NoError) return err; attributes = stat.Attributes; return Errno.NoError; } public Errno Read(string path, long offset, long size, ref byte[] buf) => 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; } } }