Example #1
0
        private Errno GetLastError()
        {
            Errno errno = Stdlib.GetLastError();

            Trace.TraceError(errno.ToString());
            return(errno);
        }
Example #2
0
        public void AcquireExclusiveLock()
        {
            _fd = Mono.Unix.Native.Syscall.open(
                _lockFile,
                Mono.Unix.Native.OpenFlags.O_CREAT |
                Mono.Unix.Native.OpenFlags.O_WRONLY |
                Mono.Unix.Native.OpenFlags.O_APPEND |
                Mono.Unix.Native.OpenFlags.O_NONBLOCK,
                FilePermissions.ACCESSPERMS);

            if (_fd == -1)
            {
                _fd = 0;
                Errno error = Mono.Unix.Native.Syscall.GetLastError();
                throw new Exception("FileRWLock: file open returned:  " + error.ToString());
            }

            int ret = flock(_fd, LOCK_EX | LOCK_NB);

            if (ret == -1)
            {
                Errno error = Mono.Unix.Native.Syscall.GetLastError();
                throw new Exception("AcquireExLock flock returned: " + error.ToString());
            }

            if (_fd != 0)
            {
                Mono.Unix.Native.Syscall.close(_fd);
                _fd = 0;
            }
            //LinuxEventProvider.LogInfo("Bindings", "Acquired exclusive lock on: " + _windowsLockFile);
        }
Example #3
0
        public void CreateAndCloseLockFile()
        {
            if (!File.Exists(_lockFile))
            {
                File.Create(_lockFile);
            }

            //
            // Create the file.
            //

            int fd = Mono.Unix.Native.Syscall.open(
                _lockFile,
                Mono.Unix.Native.OpenFlags.O_CREAT | Mono.Unix.Native.OpenFlags.O_WRONLY | Mono.Unix.Native.OpenFlags.O_APPEND | Mono.Unix.Native.OpenFlags.O_NONBLOCK,
                FilePermissions.ACCESSPERMS);

            if (fd == -1)
            {
                Errno error = Mono.Unix.Native.Syscall.GetLastError();
                throw new Exception("FileRWLock: file open returned:  " + error.ToString());
            }

            _fd = 0;

            //
            // close the file.
            //

            Mono.Unix.Native.Syscall.close(fd);
        }
Example #4
0
        public void AcquireSharedLock()
        {
            int ret = flock(_fd, LOCK_SH | LOCK_NB);

            if (ret == -1)
            {
                Errno error = Mono.Unix.Native.Syscall.GetLastError();
                throw new Exception("AcquireSharedLock flock returned: " + error.ToString());
            }
        }
Example #5
0
 public override string ToString()
 {
     if (Shell.Windows)
     {
         return(errorCode + ": " + base.Message);
     }
     else
     {
         return(errno.ToString() + ": " + base.Message);
     }
 }
Example #6
0
        /*
         * ~FileRWLock()
         * {
         *  if (_fd != 0)
         *  {
         *      Mono.Unix.Native.Syscall.close(_fd);
         *      _fd = 0;
         *  }
         * }
         */

        public void InitializeAsyncLocks()
        {
            //
            // Create the file.
            //

            int fd = Mono.Unix.Native.Syscall.open(
                _lockFile,
                Mono.Unix.Native.OpenFlags.O_CREAT | Mono.Unix.Native.OpenFlags.O_WRONLY | Mono.Unix.Native.OpenFlags.O_APPEND | Mono.Unix.Native.OpenFlags.O_NONBLOCK,
                FilePermissions.ACCESSPERMS);

            if (fd == -1)
            {
                Errno error = Mono.Unix.Native.Syscall.GetLastError();
                throw new Exception("FileRWLock: file open returned:  " + error.ToString());
            }

            _fd = fd;

            //
            // close the file.
            //

            Mono.Unix.Native.Syscall.close(fd);

            uint groupId = (uint)Mono.Unix.Native.Syscall.getgrnam("kudu_group").gr_gid;

            //
            // chown the file file
            //

            Mono.Unix.Native.Syscall.chown(_lockFile, Mono.Unix.Native.Syscall.getuid(), groupId);

            //
            // setup permissions 770 on the file.
            //

            Mono.Unix.Native.FilePermissions permissions =
                Mono.Unix.Native.FilePermissions.S_IRWXU |
                Mono.Unix.Native.FilePermissions.S_IRGRP |
                Mono.Unix.Native.FilePermissions.S_IWGRP |
                Mono.Unix.Native.FilePermissions.S_IXGRP;

            //
            // chmod the file.
            //

            Mono.Unix.Native.Syscall.chmod(_lockFile, permissions);
        }
Example #7
0
        public virtual void Release()
        {
            int ret = flock(_fd, LOCK_UN | LOCK_NB);

            if (ret == -1)
            {
                Errno error = Mono.Unix.Native.Syscall.GetLastError();
                throw new Exception("ReleaseExLock flock returned: " + error.ToString());
            }
            if (_fd != 0)
            {
                Mono.Unix.Native.Syscall.close(_fd);
                _fd = 0;
            }
        }
Example #8
0
        public void Release()
        {
            int ret = flock(_fd, LOCK_UN | LOCK_NB);

            if (ret == -1)
            {
                Errno error = Mono.Unix.Native.Syscall.GetLastError();
                throw new Exception("AcquireExLock flock returned: " + error.ToString());
            }
            //LinuxEventProvider.LogInfo("Bindings", "Released exclusive lock on: " + _windowsLockFile);
            if (_fd != 0)
            {
                Mono.Unix.Native.Syscall.close(_fd);
                _fd = 0;
            }
        }
        /// <summary>
        /// Gets the extended attribute.
        /// </summary>
        /// <returns>The extended attribute.</returns>
        /// <param name="path">Path to the file or folder.</param>
        /// <param name="key">Key of the extended attribute.</param>
        public string GetExtendedAttribute(string path, string key)
        {
            path = Path.GetFullPath(path);
            if (!File.Exists(path) && !Directory.Exists(path))
            {
                throw new FileNotFoundException(string.Format("{0}: on path \"{1}\"", "No such file or directory", path), path);
            }

#if __MonoCS__
            byte[] value;
            long   ret = Syscall.getxattr(path, prefix + key, out value);
#if __COCOA__
            if (ret != 0)
            {
                // On MacOS 93 means no value is found
                if (ret == 93)
                {
                    return(null);
                }
            }
#else
            if (ret == -1)
            {
                Errno error = Syscall.GetLastError();
                if (error.ToString().Equals("ENODATA"))
                {
                    return(null);
                }
                else
                {
                    throw new ExtendedAttributeException(string.Format("{0}: on path \"{1}\"", Syscall.GetLastError().ToString(), path));
                }
            }
#endif
            if (value == null)
            {
                return(null);
            }
            else
            {
                return(Encoding.UTF8.GetString(value));
            }
#else
            throw new WrongPlatformException();
#endif
        }
        /// <summary>
        /// Determines whether Extended Attributes are active on the filesystem.
        /// </summary>
        /// <param name="path">Path to be checked</param>
        /// <returns><c>true</c> if this instance is feature available the specified path; otherwise, <c>false</c>.</returns>
        public bool IsFeatureAvailable(string path)
        {
#if __MonoCS__
            if (!File.Exists(path) && !Directory.Exists(path))
            {
                throw new ArgumentException(
                          string.Format(
                              "Given path \"{0}\" does not exists",
                              path));
            }

            byte[] value;
            string key      = "test";
            long   ret      = Syscall.getxattr(path, prefix + key, out value);
            bool   retValue = true;
            if (ret != 0)
            {
#if __COCOA__
                // Feature not supported is errno 102
                if (ret == 102)
                {
                    retValue = false;
                }
#else
                Errno error = Syscall.GetLastError();
                if (error.ToString().Equals("EOPNOTSUPP"))
                {
                    retValue = false;
                }
#endif
            }

            return(retValue);
#else
            throw new WrongPlatformException();
#endif
        }
Example #11
0
        static void ExtractFilesInDir(string path, IReadOnlyFilesystem fs, string volumeName, string outputDir,
                                      bool doXattrs)
        {
            if (path.StartsWith('/'))
            {
                path = path.Substring(1);
            }

            Errno error = fs.ReadDir(path, out List <string> directory);

            if (error != Errno.NoError)
            {
                AaruConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString());

                return;
            }

            foreach (string entry in directory)
            {
                error = fs.Stat(path + "/" + entry, out FileEntryInfo stat);

                if (error == Errno.NoError)
                {
                    string outputPath;

                    if (stat.Attributes.HasFlag(FileAttributes.Directory))
                    {
                        outputPath = Path.Combine(outputDir, fs.XmlFsType.Type, volumeName, path, entry);

                        Directory.CreateDirectory(outputPath);

                        AaruConsole.WriteLine("Created subdirectory at {0}", outputPath);

                        ExtractFilesInDir(path + "/" + entry, fs, volumeName, outputDir, doXattrs);

                        var di = new DirectoryInfo(outputPath);

                        #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
                        try
                        {
                            if (stat.CreationTimeUtc.HasValue)
                            {
                                di.CreationTimeUtc = stat.CreationTimeUtc.Value;
                            }
                        }
                        catch
                        {
                            // ignored
                        }

                        try
                        {
                            if (stat.LastWriteTimeUtc.HasValue)
                            {
                                di.LastWriteTimeUtc = stat.LastWriteTimeUtc.Value;
                            }
                        }
                        catch
                        {
                            // ignored
                        }

                        try
                        {
                            if (stat.AccessTimeUtc.HasValue)
                            {
                                di.LastAccessTimeUtc = stat.AccessTimeUtc.Value;
                            }
                        }
                        catch
                        {
                            // ignored
                        }
                        #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body

                        continue;
                    }

                    FileStream outputFile;

                    if (doXattrs)
                    {
                        error = fs.ListXAttr(path + "/" + entry, out List <string> xattrs);

                        if (error == Errno.NoError)
                        {
                            foreach (string xattr in xattrs)
                            {
                                byte[] xattrBuf = new byte[0];
                                error = fs.GetXattr(path + "/" + entry, xattr, ref xattrBuf);

                                if (error != Errno.NoError)
                                {
                                    continue;
                                }

                                outputPath = Path.Combine(outputDir, fs.XmlFsType.Type, volumeName, path, ".xattrs", xattr);

                                Directory.CreateDirectory(outputPath);

                                outputPath = Path.Combine(outputPath, entry);

                                if (!File.Exists(outputPath))
                                {
                                    outputFile = new FileStream(outputPath, FileMode.CreateNew, FileAccess.ReadWrite,
                                                                FileShare.None);

                                    outputFile.Write(xattrBuf, 0, xattrBuf.Length);
                                    outputFile.Close();
                                    var fi = new FileInfo(outputPath);
                                    #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
                                    try
                                    {
                                        if (stat.CreationTimeUtc.HasValue)
                                        {
                                            fi.CreationTimeUtc = stat.CreationTimeUtc.Value;
                                        }
                                    }
                                    catch
                                    {
                                        // ignored
                                    }

                                    try
                                    {
                                        if (stat.LastWriteTimeUtc.HasValue)
                                        {
                                            fi.LastWriteTimeUtc = stat.LastWriteTimeUtc.Value;
                                        }
                                    }
                                    catch
                                    {
                                        // ignored
                                    }

                                    try
                                    {
                                        if (stat.AccessTimeUtc.HasValue)
                                        {
                                            fi.LastAccessTimeUtc = stat.AccessTimeUtc.Value;
                                        }
                                    }
                                    catch
                                    {
                                        // ignored
                                    }
                                    #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
                                    AaruConsole.WriteLine("Written {0} bytes of xattr {1} from file {2} to {3}",
                                                          xattrBuf.Length, xattr, entry, outputPath);
                                }
                                else
                                {
                                    AaruConsole.ErrorWriteLine("Cannot write xattr {0} for {1}, output exists", xattr,
                                                               entry);
                                }
                            }
                        }
                    }

                    outputPath = Path.Combine(outputDir, fs.XmlFsType.Type, volumeName, path);

                    Directory.CreateDirectory(outputPath);

                    outputPath = Path.Combine(outputPath, entry);

                    if (!File.Exists(outputPath))
                    {
                        byte[] outBuf = new byte[0];

                        error = fs.Read(path + "/" + entry, 0, stat.Length, ref outBuf);

                        if (error == Errno.NoError)
                        {
                            outputFile = new FileStream(outputPath, FileMode.CreateNew, FileAccess.ReadWrite,
                                                        FileShare.None);

                            outputFile.Write(outBuf, 0, outBuf.Length);
                            outputFile.Close();
                            var fi = new FileInfo(outputPath);
                            #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
                            try
                            {
                                if (stat.CreationTimeUtc.HasValue)
                                {
                                    fi.CreationTimeUtc = stat.CreationTimeUtc.Value;
                                }
                            }
                            catch
                            {
                                // ignored
                            }

                            try
                            {
                                if (stat.LastWriteTimeUtc.HasValue)
                                {
                                    fi.LastWriteTimeUtc = stat.LastWriteTimeUtc.Value;
                                }
                            }
                            catch
                            {
                                // ignored
                            }

                            try
                            {
                                if (stat.AccessTimeUtc.HasValue)
                                {
                                    fi.LastAccessTimeUtc = stat.AccessTimeUtc.Value;
                                }
                            }
                            catch
                            {
                                // ignored
                            }
                            #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
                            AaruConsole.WriteLine("Written {0} bytes of file {1} to {2}", outBuf.Length, entry,
                                                  outputPath);
                        }
                        else
                        {
                            AaruConsole.ErrorWriteLine("Error {0} reading file {1}", error, entry);
                        }
                    }
                    else
                    {
                        AaruConsole.ErrorWriteLine("Cannot write file {0}, output exists", entry);
                    }
                }
                else
                {
                    AaruConsole.ErrorWriteLine("Error reading file {0}", entry);
                }
            }
        }
Example #12
0
        static void ListFilesInDir(string path, IReadOnlyFilesystem fs, bool longFormat)
        {
            if (path.StartsWith('/'))
            {
                path = path.Substring(1);
            }

            AaruConsole.WriteLine(string.IsNullOrEmpty(path) ? "Root directory" : $"Directory: {path}");

            Errno error = fs.ReadDir(path, out List <string> directory);

            if (error != Errno.NoError)
            {
                AaruConsole.ErrorWriteLine("Error {0} reading root directory {1}", error.ToString(), path);

                return;
            }

            Dictionary <string, FileEntryInfo> stats = new Dictionary <string, FileEntryInfo>();

            foreach (string entry in directory)
            {
                fs.Stat(path + "/" + entry, out FileEntryInfo stat);

                stats.Add(entry, stat);
            }

            foreach (KeyValuePair <string, FileEntryInfo> entry in
                     stats.OrderBy(e => e.Value?.Attributes.HasFlag(FileAttributes.Directory) == false))
            {
                if (longFormat)
                {
                    if (entry.Value != null)
                    {
                        if (entry.Value.Attributes.HasFlag(FileAttributes.Directory))
                        {
                            AaruConsole.WriteLine("{0, 10:d} {0, 12:T}  {1, -20}  {2}", entry.Value.CreationTimeUtc,
                                                  "<DIR>", entry.Key);
                        }
                        else
                        {
                            AaruConsole.WriteLine("{0, 10:d} {0, 12:T}  {1, 6}{2, 14:N0}  {3}",
                                                  entry.Value.CreationTimeUtc, entry.Value.Inode, entry.Value.Length,
                                                  entry.Key);
                        }

                        error = fs.ListXAttr(path + "/" + entry.Key, out List <string> xattrs);

                        if (error != Errno.NoError)
                        {
                            continue;
                        }

                        foreach (string xattr in xattrs)
                        {
                            byte[] xattrBuf = new byte[0];
                            error = fs.GetXattr(path + "/" + entry.Key, xattr, ref xattrBuf);

                            if (error == Errno.NoError)
                            {
                                AaruConsole.WriteLine("\t\t{0}\t{1:##,#}", xattr, xattrBuf.Length);
                            }
                        }
                    }
                    else
                    {
                        AaruConsole.WriteLine("{0, 47}{1}", string.Empty, entry.Key);
                    }
                }
                else
                {
                    AaruConsole.
                    WriteLine(entry.Value?.Attributes.HasFlag(FileAttributes.Directory) == true ? "{0}/" : "{0}",
                              entry.Key);
                }
            }

            AaruConsole.WriteLine();

            foreach (KeyValuePair <string, FileEntryInfo> subdirectory in
                     stats.Where(e => e.Value?.Attributes.HasFlag(FileAttributes.Directory) == true))
            {
                ListFilesInDir(path + "/" + subdirectory.Key, fs, longFormat);
            }
        }
Example #13
0
        /// <summary>
        ///     Mounts an Apple Lisa filesystem
        /// </summary>
        public Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding,
                           Dictionary <string, string> options, string @namespace)
        {
            try
            {
                device   = imagePlugin;
                Encoding = new LisaRoman();

                // Lisa OS is unable to work on disks without tags.
                // This code is designed like that.
                // However with some effort the code may be modified to ignore them.
                if (device.Info.ReadableSectorTags == null ||
                    !device.Info.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag))
                {
                    DicConsole.DebugWriteLine("LisaFS plugin", "Underlying device does not support Lisa tags");
                    return(Errno.InOutError);
                }

                // Minimal LisaOS disk is 3.5" single sided double density, 800 sectors
                if (device.Info.Sectors < 800)
                {
                    DicConsole.DebugWriteLine("LisaFS plugin", "Device is too small");
                    return(Errno.InOutError);
                }

                // MDDF cannot be at end of device, of course
                volumePrefix = device.Info.Sectors;

                // LisaOS searches sectors until tag tells MDDF resides there, so we'll search 100 sectors
                for (ulong i = 0; i < 100; i++)
                {
                    DecodeTag(device.ReadSectorTag(i, SectorTagType.AppleSectorTag), out LisaTag.PriamTag searchTag);

                    DicConsole.DebugWriteLine("LisaFS plugin", "Sector {0}, file ID 0x{1:X4}", i, searchTag.FileId);

                    if (volumePrefix == device.Info.Sectors && searchTag.FileId == FILEID_LOADER_SIGNED)
                    {
                        volumePrefix = i - 1;
                    }

                    if (searchTag.FileId != FILEID_MDDF)
                    {
                        continue;
                    }

                    devTagSize = device.ReadSectorTag(i, SectorTagType.AppleSectorTag).Length;

                    byte[] sector = device.ReadSector(i);
                    mddf = new MDDF();
                    byte[] pString = new byte[33];

                    mddf.fsversion = BigEndianBitConverter.ToUInt16(sector, 0x00);
                    mddf.volid     = BigEndianBitConverter.ToUInt64(sector, 0x02);
                    mddf.volnum    = BigEndianBitConverter.ToUInt16(sector, 0x0A);
                    Array.Copy(sector, 0x0C, pString, 0, 33);
                    mddf.volname  = StringHandlers.PascalToString(pString, Encoding);
                    mddf.unknown1 = sector[0x2D];
                    Array.Copy(sector, 0x2E, pString, 0, 33);
                    // Prevent garbage
                    mddf.password       = pString[0] <= 32 ? StringHandlers.PascalToString(pString, Encoding) : "";
                    mddf.unknown2       = sector[0x4F];
                    mddf.machine_id     = BigEndianBitConverter.ToUInt32(sector, 0x50);
                    mddf.master_copy_id = BigEndianBitConverter.ToUInt32(sector, 0x54);
                    uint lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x58);
                    mddf.dtvc                         = DateHandlers.LisaToDateTime(lisaTime);
                    lisaTime                          = BigEndianBitConverter.ToUInt32(sector, 0x5C);
                    mddf.dtcc                         = DateHandlers.LisaToDateTime(lisaTime);
                    lisaTime                          = BigEndianBitConverter.ToUInt32(sector, 0x60);
                    mddf.dtvb                         = DateHandlers.LisaToDateTime(lisaTime);
                    lisaTime                          = BigEndianBitConverter.ToUInt32(sector, 0x64);
                    mddf.dtvs                         = DateHandlers.LisaToDateTime(lisaTime);
                    mddf.unknown3                     = BigEndianBitConverter.ToUInt32(sector, 0x68);
                    mddf.mddf_block                   = BigEndianBitConverter.ToUInt32(sector, 0x6C);
                    mddf.volsize_minus_one            = BigEndianBitConverter.ToUInt32(sector, 0x70);
                    mddf.volsize_minus_mddf_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x74);
                    mddf.vol_size                     = BigEndianBitConverter.ToUInt32(sector, 0x78);
                    mddf.blocksize                    = BigEndianBitConverter.ToUInt16(sector, 0x7C);
                    mddf.datasize                     = BigEndianBitConverter.ToUInt16(sector, 0x7E);
                    mddf.unknown4                     = BigEndianBitConverter.ToUInt16(sector, 0x80);
                    mddf.unknown5                     = BigEndianBitConverter.ToUInt32(sector, 0x82);
                    mddf.unknown6                     = BigEndianBitConverter.ToUInt32(sector, 0x86);
                    mddf.clustersize                  = BigEndianBitConverter.ToUInt16(sector, 0x8A);
                    mddf.fs_size                      = BigEndianBitConverter.ToUInt32(sector, 0x8C);
                    mddf.unknown7                     = BigEndianBitConverter.ToUInt32(sector, 0x90);
                    mddf.srec_ptr                     = BigEndianBitConverter.ToUInt32(sector, 0x94);
                    mddf.unknown9                     = BigEndianBitConverter.ToUInt16(sector, 0x98);
                    mddf.srec_len                     = BigEndianBitConverter.ToUInt16(sector, 0x9A);
                    mddf.unknown10                    = BigEndianBitConverter.ToUInt32(sector, 0x9C);
                    mddf.unknown11                    = BigEndianBitConverter.ToUInt32(sector, 0xA0);
                    mddf.unknown12                    = BigEndianBitConverter.ToUInt32(sector, 0xA4);
                    mddf.unknown13                    = BigEndianBitConverter.ToUInt32(sector, 0xA8);
                    mddf.unknown14                    = BigEndianBitConverter.ToUInt32(sector, 0xAC);
                    mddf.filecount                    = BigEndianBitConverter.ToUInt16(sector, 0xB0);
                    mddf.unknown15                    = BigEndianBitConverter.ToUInt32(sector, 0xB2);
                    mddf.unknown16                    = BigEndianBitConverter.ToUInt32(sector, 0xB6);
                    mddf.freecount                    = BigEndianBitConverter.ToUInt32(sector, 0xBA);
                    mddf.unknown17                    = BigEndianBitConverter.ToUInt16(sector, 0xBE);
                    mddf.unknown18                    = BigEndianBitConverter.ToUInt32(sector, 0xC0);
                    mddf.overmount_stamp              = BigEndianBitConverter.ToUInt64(sector, 0xC4);
                    mddf.serialization                = BigEndianBitConverter.ToUInt32(sector, 0xCC);
                    mddf.unknown19                    = BigEndianBitConverter.ToUInt32(sector, 0xD0);
                    mddf.unknown_timestamp            = BigEndianBitConverter.ToUInt32(sector, 0xD4);
                    mddf.unknown20                    = BigEndianBitConverter.ToUInt32(sector, 0xD8);
                    mddf.unknown21                    = BigEndianBitConverter.ToUInt32(sector, 0xDC);
                    mddf.unknown22                    = BigEndianBitConverter.ToUInt32(sector, 0xE0);
                    mddf.unknown23                    = BigEndianBitConverter.ToUInt32(sector, 0xE4);
                    mddf.unknown24                    = BigEndianBitConverter.ToUInt32(sector, 0xE8);
                    mddf.unknown25                    = BigEndianBitConverter.ToUInt32(sector, 0xEC);
                    mddf.unknown26                    = BigEndianBitConverter.ToUInt32(sector, 0xF0);
                    mddf.unknown27                    = BigEndianBitConverter.ToUInt32(sector, 0xF4);
                    mddf.unknown28                    = BigEndianBitConverter.ToUInt32(sector, 0xF8);
                    mddf.unknown29                    = BigEndianBitConverter.ToUInt32(sector, 0xFC);
                    mddf.unknown30                    = BigEndianBitConverter.ToUInt32(sector, 0x100);
                    mddf.unknown31                    = BigEndianBitConverter.ToUInt32(sector, 0x104);
                    mddf.unknown32                    = BigEndianBitConverter.ToUInt32(sector, 0x108);
                    mddf.unknown33                    = BigEndianBitConverter.ToUInt32(sector, 0x10C);
                    mddf.unknown34                    = BigEndianBitConverter.ToUInt32(sector, 0x110);
                    mddf.unknown35                    = BigEndianBitConverter.ToUInt32(sector, 0x114);
                    mddf.backup_volid                 = BigEndianBitConverter.ToUInt64(sector, 0x118);
                    mddf.label_size                   = BigEndianBitConverter.ToUInt16(sector, 0x120);
                    mddf.fs_overhead                  = BigEndianBitConverter.ToUInt16(sector, 0x122);
                    mddf.result_scavenge              = BigEndianBitConverter.ToUInt16(sector, 0x124);
                    mddf.boot_code                    = BigEndianBitConverter.ToUInt16(sector, 0x126);
                    mddf.boot_environ                 = BigEndianBitConverter.ToUInt16(sector, 0x6C);
                    mddf.unknown36                    = BigEndianBitConverter.ToUInt32(sector, 0x12A);
                    mddf.unknown37                    = BigEndianBitConverter.ToUInt32(sector, 0x12E);
                    mddf.unknown38                    = BigEndianBitConverter.ToUInt32(sector, 0x132);
                    mddf.vol_sequence                 = BigEndianBitConverter.ToUInt16(sector, 0x136);
                    mddf.vol_left_mounted             = sector[0x138];

                    // Check that the MDDF is correct
                    if (mddf.mddf_block != i - volumePrefix ||
                        mddf.vol_size > device.Info.Sectors ||
                        mddf.vol_size - 1 !=
                        mddf.volsize_minus_one ||
                        mddf.vol_size - i - 1 !=
                        mddf.volsize_minus_mddf_minus_one - volumePrefix ||
                        mddf.datasize >
                        mddf.blocksize || mddf.blocksize < device.Info.SectorSize ||
                        mddf.datasize != device.Info.SectorSize)
                    {
                        DicConsole.DebugWriteLine("LisaFS plugin", "Incorrect MDDF found");
                        return(Errno.InvalidArgument);
                    }

                    // Check MDDF version
                    switch (mddf.fsversion)
                    {
                    case LISA_V1:
                        DicConsole.DebugWriteLine("LisaFS plugin", "Mounting LisaFS v1");
                        break;

                    case LISA_V2:
                        DicConsole.DebugWriteLine("LisaFS plugin", "Mounting LisaFS v2");
                        break;

                    case LISA_V3:
                        DicConsole.DebugWriteLine("LisaFS plugin", "Mounting LisaFS v3");
                        break;

                    default:
                        DicConsole.ErrorWriteLine("Cannot mount LisaFS version {0}", mddf.fsversion.ToString());
                        return(Errno.NotSupported);
                    }

                    // Initialize caches
                    extentCache     = new Dictionary <short, ExtentFile>();
                    systemFileCache = new Dictionary <short, byte[]>();
                    fileCache       = new Dictionary <short, byte[]>();
                    //catalogCache = new Dictionary<short, List<CatalogEntry>>();
                    fileSizeCache = new Dictionary <short, int>();

                    mounted = true;
                    if (options == null)
                    {
                        options = GetDefaultOptions();
                    }
                    if (options.TryGetValue("debug", out string debugString))
                    {
                        bool.TryParse(debugString, out debug);
                    }

                    if (debug)
                    {
                        printedExtents = new List <short>();
                    }

                    // Read the S-Records file
                    Errno error = ReadSRecords();
                    if (error != Errno.NoError)
                    {
                        DicConsole.ErrorWriteLine("Error {0} reading S-Records file.", error);
                        return(error);
                    }

                    directoryDtcCache = new Dictionary <short, DateTime> {
                        { DIRID_ROOT, mddf.dtcc }
                    };

                    // Read the Catalog File
                    error = ReadCatalog();

                    if (error != Errno.NoError)
                    {
                        DicConsole.DebugWriteLine("LisaFS plugin", "Cannot read Catalog File, error {0}",
                                                  error.ToString());
                        mounted = false;
                        return(error);
                    }

                    // If debug, cache system files
                    if (debug)
                    {
                        error = ReadSystemFile(FILEID_BOOT_SIGNED, out _);
                        if (error != Errno.NoError)
                        {
                            DicConsole.DebugWriteLine("LisaFS plugin", "Unable to read boot blocks");
                            mounted = false;
                            return(error);
                        }

                        error = ReadSystemFile(FILEID_LOADER_SIGNED, out _);
                        if (error != Errno.NoError)
                        {
                            DicConsole.DebugWriteLine("LisaFS plugin", "Unable to read boot loader");
                            mounted = false;
                            return(error);
                        }

                        error = ReadSystemFile((short)FILEID_MDDF, out _);
                        if (error != Errno.NoError)
                        {
                            DicConsole.DebugWriteLine("LisaFS plugin", "Unable to read MDDF");
                            mounted = false;
                            return(error);
                        }

                        error = ReadSystemFile((short)FILEID_BITMAP, out _);
                        if (error != Errno.NoError)
                        {
                            DicConsole.DebugWriteLine("LisaFS plugin", "Unable to read volume bitmap");
                            mounted = false;
                            return(error);
                        }

                        error = ReadSystemFile((short)FILEID_SRECORD, out _);
                        if (error != Errno.NoError)
                        {
                            DicConsole.DebugWriteLine("LisaFS plugin", "Unable to read S-Records file");
                            mounted = false;
                            return(error);
                        }
                    }

                    // Create XML metadata for mounted filesystem
                    XmlFsType = new FileSystemType();
                    if (DateTime.Compare(mddf.dtvb, DateHandlers.LisaToDateTime(0)) > 0)
                    {
                        XmlFsType.BackupDate          = mddf.dtvb;
                        XmlFsType.BackupDateSpecified = true;
                    }

                    XmlFsType.Clusters    = mddf.vol_size;
                    XmlFsType.ClusterSize = (uint)(mddf.clustersize * mddf.datasize);
                    if (DateTime.Compare(mddf.dtvc, DateHandlers.LisaToDateTime(0)) > 0)
                    {
                        XmlFsType.CreationDate          = mddf.dtvc;
                        XmlFsType.CreationDateSpecified = true;
                    }

                    XmlFsType.Dirty                 = mddf.vol_left_mounted != 0;
                    XmlFsType.Files                 = mddf.filecount;
                    XmlFsType.FilesSpecified        = true;
                    XmlFsType.FreeClusters          = mddf.freecount;
                    XmlFsType.FreeClustersSpecified = true;
                    XmlFsType.Type         = "LisaFS";
                    XmlFsType.VolumeName   = mddf.volname;
                    XmlFsType.VolumeSerial = $"{mddf.volid:X16}";

                    return(Errno.NoError);
                }

                DicConsole.DebugWriteLine("LisaFS plugin", "Not a Lisa filesystem");
                return(Errno.NotSupported);
            }
            catch (Exception ex)
            {
                DicConsole.ErrorWriteLine("Exception {0}, {1}, {2}", ex.Message, ex.InnerException, ex.StackTrace);
                return(Errno.InOutError);
            }
        }
        /// <summary>
        /// Removes the extended attribute.
        /// </summary>
        /// <param name="path">Removes attribute from this path.</param>
        /// <param name="key">Key of the attribute, which should be removed.</param>
        public void RemoveExtendedAttribute(string path, string key)
        {
            path = Path.GetFullPath(path);
            if (!File.Exists(path) && !Directory.Exists(path))
            {
                throw new FileNotFoundException(string.Format("{0}: on path \"{1}\"", "No such file or directory", path), path);
            }

#if __MonoCS__
            long ret = Syscall.removexattr(path, prefix + key);
            if (ret != 0)
            {
#if !__COCOA__
                Errno errno = Syscall.GetLastError();
                if (errno != Errno.ENODATA)
                {
                    throw new ExtendedAttributeException(string.Format("{0}: on path \"{1}\"", errno.ToString(), path));
                }
#endif
            }
#else
            throw new WrongPlatformException();
#endif
        }
        /// <summary>
        /// Retrieves the error information from the native implementation and constructs a new <see cref="NativeException"/> object, that can be thrown afterwards.
        /// </summary>
        /// <param name="nativeMethodName">Name of the native API method which returned the error code.</param>
        /// <param name="errorCode">The error code returned by the native API method.</param>
        /// <param name="errnoResolvable">This will tell whether the retrieved errno could be resolved into a symbolic representation.</param>
        /// <param name="errnoSymbolic">This will hold the symbolic value of the retrieved errno; check the <paramref name="errnoResolvable"/> parameter beforehand!</param>
        private NativeException RetrieveErrnoAndBuildException(string nativeMethodName, NativeErrorCodes errorCode, out bool errnoResolvable, out Errno errnoSymbolic)
        {
            // Retrieve errno
            var  errnoStringBuffer = new StringBuilder(256);
            long errno             = GetLastErrnoValue(errnoStringBuffer, errnoStringBuffer.Capacity);

            // Try to resolve to symbolic representation
            errnoResolvable = NativeConvert.TryToErrno((int)errno, out errnoSymbolic);

            // Create native exception object
            return(new NativeException(nativeMethodName, errorCode, errno, (errnoResolvable ? errnoSymbolic.ToString() + ", " : "") + errnoStringBuffer.ToString()));
        }