// /*************************************************************************** // The Disc Image Chef // ---------------------------------------------------------------------------- // // Filename : Dir.cs // Author(s) : Natalia Portillo // // Component : CP/M filesystem plugin. // // --[ Description ] ---------------------------------------------------------- // // Methods to show the CP/M filesystem directory. // // --[ 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-2019 Natalia Portillo // ****************************************************************************/ using System; using System.Collections.Generic; using System.Text; using DiscImageChef.CommonTypes.Structs; using DiscImageChef.Helpers; namespace DiscImageChef.Filesystems.CPM { partial class CPM { public Errno ReadDir(string path, out List contents) { contents = null; if(!mounted) return Errno.AccessDenied; if(!string.IsNullOrEmpty(path) && string.Compare(path, "/", StringComparison.OrdinalIgnoreCase) != 0) return Errno.NotSupported; contents = new List(dirList); return Errno.NoError; } /// /// Checks that the given directory blocks follow the CP/M filesystem directory specification /// Corrupted directories will fail. /// FAT firectories will false positive if all files start with 0x05, and do not use full extentions, for example: /// "σAFILE.GZ" (using code page 437) /// /// False if the directory does not follow the directory specification /// Directory blocks. bool CheckDir(byte[] directory) { try { if(directory == null) return false; int fileCount = 0; for(int off = 0; off < directory.Length; off += 32) { DirectoryEntry entry = Marshal.ByteArrayToStructureLittleEndian(directory, off, 32); if((entry.statusUser & 0x7F) < 0x20) { for(int f = 0; f < 8; f++) if(entry.filename[f] < 0x20 && entry.filename[f] != 0x00) return false; for(int e = 0; e < 3; e++) if(entry.extension[e] < 0x20 && entry.extension[e] != 0x00) return false; if(!ArrayHelpers.ArrayIsNullOrWhiteSpace(entry.filename)) fileCount++; } else if(entry.statusUser == 0x20) { for(int f = 0; f < 8; f++) if(entry.filename[f] < 0x20 && entry.filename[f] != 0x00) return false; for(int e = 0; e < 3; e++) if(entry.extension[e] < 0x20 && entry.extension[e] != 0x00) return false; label = Encoding.ASCII.GetString(directory, off + 1, 11).Trim(); labelCreationDate = new byte[4]; labelUpdateDate = new byte[4]; Array.Copy(directory, off + 24, labelCreationDate, 0, 4); Array.Copy(directory, off + 28, labelUpdateDate, 0, 4); } else if(entry.statusUser == 0x21) if(directory[off + 1] == 0x00) thirdPartyTimestamps = true; else standardTimestamps |= directory[off + 21] == 0x00 && directory[off + 31] == 0x00; } return fileCount > 0; } catch { return false; } } } }