Ejemplo n.º 1
0
        ContentsFileType SidecarFile(IReadOnlyFilesystem filesystem, string path, string filename, FileEntryInfo stat)
        {
            var file          = new ContentsFileType();
            var fileChkWorker = new Checksum();

            if (stat.AccessTimeUtc.HasValue)
            {
                file.accessTime          = stat.AccessTimeUtc.Value;
                file.accessTimeSpecified = true;
            }

            file.attributes = (ulong)stat.Attributes;

            if (stat.BackupTimeUtc.HasValue)
            {
                file.backupTime          = stat.BackupTimeUtc.Value;
                file.backupTimeSpecified = true;
            }

            if (stat.CreationTimeUtc.HasValue)
            {
                file.creationTime          = stat.CreationTimeUtc.Value;
                file.creationTimeSpecified = true;
            }

            if (stat.DeviceNo.HasValue)
            {
                file.deviceNumber          = stat.DeviceNo.Value;
                file.deviceNumberSpecified = true;
            }

            file.inode = stat.Inode;

            if (stat.LastWriteTimeUtc.HasValue)
            {
                file.lastWriteTime          = stat.LastWriteTimeUtc.Value;
                file.lastWriteTimeSpecified = true;
            }

            file.length = (ulong)stat.Length;
            file.links  = stat.Links;
            file.name   = filename;

            if (stat.GID.HasValue)
            {
                file.posixGroupId          = stat.GID.Value;
                file.posixGroupIdSpecified = true;
            }

            if (stat.Mode.HasValue)
            {
                file.posixMode          = stat.Mode.Value;
                file.posixModeSpecified = true;
            }

            if (stat.UID.HasValue)
            {
                file.posixUserId          = stat.UID.Value;
                file.posixUserIdSpecified = true;
            }

            if (stat.StatusChangeTimeUtc.HasValue)
            {
                file.statusChangeTime          = stat.StatusChangeTimeUtc.Value;
                file.statusChangeTimeSpecified = true;
            }

            byte[] data = new byte[0];

            if (stat.Length > 0)
            {
                long position = 0;
                UpdateStatus($"Hashing file {path}/{filename}...");
                InitProgress2();

                while (position < stat.Length - 1048576)
                {
                    if (aborted)
                    {
                        return(file);
                    }

                    data = new byte[1048576];
                    filesystem.Read(path + "/" + filename, position, 1048576, ref data);

                    UpdateProgress2("Hashing file byte {0} of {1}", position, stat.Length);

                    fileChkWorker.Update(data);

                    position += 1048576;
                }

                data = new byte[stat.Length - position];
                filesystem.Read(path + "/" + filename, position, stat.Length - position, ref data);

                UpdateProgress2("Hashing file byte {0} of {1}", position, stat.Length);

                fileChkWorker.Update(data);

                EndProgress();

                file.Checksums = fileChkWorker.End().ToArray();
            }
            else
            {
                file.Checksums = emptyChecksums;
            }

            Errno ret = filesystem.ListXAttr(path + "/" + filename, out List <string> xattrs);

            if (ret != Errno.NoError)
            {
                return(file);
            }

            List <ExtendedAttributeType> xattrTypes = new List <ExtendedAttributeType>();

            foreach (string xattr in xattrs)
            {
                ret = filesystem.GetXattr(path + "/" + filename, xattr, ref data);

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

                var xattrChkWorker = new Checksum();
                xattrChkWorker.Update(data);

                xattrTypes.Add(new ExtendedAttributeType
                {
                    Checksums = xattrChkWorker.End().ToArray(), length = (ulong)data.Length, name = xattr
                });
            }

            if (xattrTypes.Count > 0)
            {
                file.ExtendedAttributes = xattrTypes.OrderBy(x => x.name).ToArray();
            }

            return(file);
        }
Ejemplo n.º 2
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:##,#}  {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
                {
                    if (entry.Value != null &&
                        entry.Value.Attributes.HasFlag(FileAttributes.Directory))
                    {
                        AaruConsole.WriteLine("{0}/", entry.Key);
                    }
                    else
                    {
                        AaruConsole.WriteLine("{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);
            }
        }
Ejemplo n.º 3
0
        internal static void DoLs(LsOptions options)
        {
            DicConsole.DebugWriteLine("Ls command", "--debug={0}", options.Debug);
            DicConsole.DebugWriteLine("Ls command", "--verbose={0}", options.Verbose);
            DicConsole.DebugWriteLine("Ls command", "--input={0}", options.InputFile);

            FiltersList filtersList = new FiltersList();
            IFilter     inputFilter = filtersList.GetFilter(options.InputFile);

            Dictionary <string, string> parsedOptions = Options.Parse(options.Options);

            DicConsole.DebugWriteLine("Ls command", "Parsed options:");
            foreach (KeyValuePair <string, string> parsedOption in parsedOptions)
            {
                DicConsole.DebugWriteLine("Ls command", "{0} = {1}", parsedOption.Key, parsedOption.Value);
            }
            parsedOptions.Add("debug", options.Debug.ToString());

            if (inputFilter == null)
            {
                DicConsole.ErrorWriteLine("Cannot open specified file.");
                return;
            }

            Encoding encoding = null;

            if (options.EncodingName != null)
            {
                try
                {
                    encoding = Claunia.Encoding.Encoding.GetEncoding(options.EncodingName);
                    if (options.Verbose)
                    {
                        DicConsole.VerboseWriteLine("Using encoding for {0}.", encoding.EncodingName);
                    }
                }
                catch (ArgumentException)
                {
                    DicConsole.ErrorWriteLine("Specified encoding is not supported.");
                    return;
                }
            }

            PluginBase plugins = GetPluginBase.Instance;

            try
            {
                IMediaImage imageFormat = ImageFormat.Detect(inputFilter);

                if (imageFormat == null)
                {
                    DicConsole.WriteLine("Image format not identified, not proceeding with analysis.");
                    return;
                }

                if (options.Verbose)
                {
                    DicConsole.VerboseWriteLine("Image format identified by {0} ({1}).", imageFormat.Name,
                                                imageFormat.Id);
                }
                else
                {
                    DicConsole.WriteLine("Image format identified by {0}.", imageFormat.Name);
                }

                try
                {
                    if (!imageFormat.Open(inputFilter))
                    {
                        DicConsole.WriteLine("Unable to open image format");
                        DicConsole.WriteLine("No error given");
                        return;
                    }

                    DicConsole.DebugWriteLine("Ls command", "Correctly opened image file.");
                    DicConsole.DebugWriteLine("Ls command", "Image without headers is {0} bytes.",
                                              imageFormat.Info.ImageSize);
                    DicConsole.DebugWriteLine("Ls command", "Image has {0} sectors.", imageFormat.Info.Sectors);
                    DicConsole.DebugWriteLine("Ls command", "Image identifies disk type as {0}.",
                                              imageFormat.Info.MediaType);

                    Core.Statistics.AddMediaFormat(imageFormat.Format);
                    Core.Statistics.AddMedia(imageFormat.Info.MediaType, false);
                    Core.Statistics.AddFilter(inputFilter.Name);
                }
                catch (Exception ex)
                {
                    DicConsole.ErrorWriteLine("Unable to open image format");
                    DicConsole.ErrorWriteLine("Error: {0}", ex.Message);
                    return;
                }

                List <Partition> partitions = Core.Partitions.GetAll(imageFormat);
                Core.Partitions.AddSchemesToStats(partitions);

                List <string>       idPlugins;
                IReadOnlyFilesystem plugin;
                Errno error;
                if (partitions.Count == 0)
                {
                    DicConsole.DebugWriteLine("Ls command", "No partitions found");
                }
                else
                {
                    DicConsole.WriteLine("{0} partitions found.", partitions.Count);

                    for (int i = 0; i < partitions.Count; i++)
                    {
                        DicConsole.WriteLine();
                        DicConsole.WriteLine("Partition {0}:", partitions[i].Sequence);

                        DicConsole.WriteLine("Identifying filesystem on partition");

                        Core.Filesystems.Identify(imageFormat, out idPlugins, partitions[i]);
                        if (idPlugins.Count == 0)
                        {
                            DicConsole.WriteLine("Filesystem not identified");
                        }
                        else if (idPlugins.Count > 1)
                        {
                            DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins");

                            foreach (string pluginName in idPlugins)
                            {
                                if (plugins.ReadOnlyFilesystems.TryGetValue(pluginName, out plugin))
                                {
                                    DicConsole.WriteLine($"As identified by {plugin.Name}.");
                                    IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin
                                                             .GetType()
                                                             .GetConstructor(Type.EmptyTypes)
                                                             ?.Invoke(new object[] { });

                                    if (fs == null)
                                    {
                                        continue;
                                    }

                                    error = fs.Mount(imageFormat, partitions[i], encoding, parsedOptions);
                                    if (error == Errno.NoError)
                                    {
                                        error = fs.ReadDir("/", out List <string> rootDir);
                                        if (error == Errno.NoError)
                                        {
                                            foreach (string entry in rootDir)
                                            {
                                                DicConsole.WriteLine("{0}", entry);
                                            }
                                        }
                                        else
                                        {
                                            DicConsole.ErrorWriteLine("Error {0} reading root directory {0}",
                                                                      error.ToString());
                                        }

                                        Core.Statistics.AddFilesystem(fs.XmlFsType.Type);
                                    }
                                    else
                                    {
                                        DicConsole.ErrorWriteLine("Unable to mount device, error {0}",
                                                                  error.ToString());
                                    }
                                }
                            }
                        }
                        else
                        {
                            plugins.ReadOnlyFilesystems.TryGetValue(idPlugins[0], out plugin);
                            if (plugin == null)
                            {
                                continue;
                            }

                            DicConsole.WriteLine($"Identified by {plugin.Name}.");
                            IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin
                                                     .GetType().GetConstructor(Type.EmptyTypes)
                                                     ?.Invoke(new object[] { });
                            if (fs == null)
                            {
                                continue;
                            }

                            error = fs.Mount(imageFormat, partitions[i], encoding, parsedOptions);
                            if (error == Errno.NoError)
                            {
                                error = fs.ReadDir("/", out List <string> rootDir);
                                if (error == Errno.NoError)
                                {
                                    foreach (string entry in rootDir)
                                    {
                                        DicConsole.WriteLine("{0}", entry);
                                    }
                                }
                                else
                                {
                                    DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString());
                                }

                                Core.Statistics.AddFilesystem(fs.XmlFsType.Type);
                            }
                            else
                            {
                                DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString());
                            }
                        }
                    }
                }

                Partition wholePart = new Partition
                {
                    Name   = "Whole device",
                    Length = imageFormat.Info.Sectors,
                    Size   = imageFormat.Info.Sectors * imageFormat.Info.SectorSize
                };

                Core.Filesystems.Identify(imageFormat, out idPlugins, wholePart);
                if (idPlugins.Count == 0)
                {
                    DicConsole.WriteLine("Filesystem not identified");
                }
                else if (idPlugins.Count > 1)
                {
                    DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins");

                    foreach (string pluginName in idPlugins)
                    {
                        if (plugins.ReadOnlyFilesystems.TryGetValue(pluginName, out plugin))
                        {
                            DicConsole.WriteLine($"As identified by {plugin.Name}.");
                            IReadOnlyFilesystem fs = (IReadOnlyFilesystem)plugin
                                                     .GetType().GetConstructor(Type.EmptyTypes)
                                                     ?.Invoke(new object[] { });
                            if (fs == null)
                            {
                                continue;
                            }

                            error = fs.Mount(imageFormat, wholePart, encoding, parsedOptions);
                            if (error == Errno.NoError)
                            {
                                error = fs.ReadDir("/", out List <string> rootDir);
                                if (error == Errno.NoError)
                                {
                                    foreach (string entry in rootDir)
                                    {
                                        DicConsole.WriteLine("{0}", entry);
                                    }
                                }
                                else
                                {
                                    DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString());
                                }

                                Core.Statistics.AddFilesystem(fs.XmlFsType.Type);
                            }
                            else
                            {
                                DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString());
                            }
                        }
                    }
                }
                else
                {
                    plugins.ReadOnlyFilesystems.TryGetValue(idPlugins[0], out plugin);
                    if (plugin != null)
                    {
                        DicConsole.WriteLine($"Identified by {plugin.Name}.");
                        IReadOnlyFilesystem fs =
                            (IReadOnlyFilesystem)plugin
                            .GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { });
                        if (fs != null)
                        {
                            error = fs.Mount(imageFormat, wholePart, encoding, parsedOptions);
                            if (error == Errno.NoError)
                            {
                                error = fs.ReadDir("/", out List <string> rootDir);
                                if (error == Errno.NoError)
                                {
                                    foreach (string entry in rootDir)
                                    {
                                        if (options.Long)
                                        {
                                            error = fs.Stat(entry, out FileEntryInfo stat);
                                            if (error == Errno.NoError)
                                            {
                                                DicConsole.WriteLine("{0}\t{1}\t{2} bytes\t{3}", stat.CreationTimeUtc,
                                                                     stat.Inode, stat.Length, entry);

                                                error = fs.ListXAttr(entry, out List <string> xattrs);
                                                if (error != Errno.NoError)
                                                {
                                                    continue;
                                                }

                                                foreach (string xattr in xattrs)
                                                {
                                                    byte[] xattrBuf = new byte[0];
                                                    error = fs.GetXattr(entry, xattr, ref xattrBuf);
                                                    if (error == Errno.NoError)
                                                    {
                                                        DicConsole.WriteLine("\t\t{0}\t{1} bytes", xattr,
                                                                             xattrBuf.Length);
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                DicConsole.WriteLine("{0}", entry);
                                            }
                                        }
                                        else
                                        {
                                            DicConsole.WriteLine("{0}", entry);
                                        }
                                    }
                                }
                                else
                                {
                                    DicConsole.ErrorWriteLine("Error {0} reading root directory {0}", error.ToString());
                                }

                                Core.Statistics.AddFilesystem(fs.XmlFsType.Type);
                            }
                            else
                            {
                                DicConsole.ErrorWriteLine("Unable to mount device, error {0}", error.ToString());
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                DicConsole.ErrorWriteLine($"Error reading file: {ex.Message}");
                DicConsole.DebugWriteLine("Ls command", ex.StackTrace);
            }

            Core.Statistics.AddCommand("ls");
        }
Ejemplo n.º 4
0
        void TestDirectory(IReadOnlyFilesystem fs, string path, Dictionary <string, FileData> children, string testFile)
        {
            Errno ret = fs.ReadDir(path, out List <string> contents);

            Assert.AreEqual(Errno.NoError, ret,
                            $"Unexpected error {ret} when reading directory \"{path}\" of {testFile}.");

            if (children.Count == 0 &&
                contents.Count == 0)
            {
                return;
            }

            if (path == "/")
            {
                path = "";
            }

            List <string> expectedNotFound = new List <string>();

            foreach (KeyValuePair <string, FileData> child in children)
            {
                string childPath = $"{path}/{child.Key}";
                ret = fs.Stat(childPath, out FileEntryInfo stat);

                if (ret == Errno.NoSuchFile ||
                    !contents.Contains(child.Key))
                {
                    expectedNotFound.Add(child.Key);

                    continue;
                }

                contents.Remove(child.Key);

                Assert.AreEqual(Errno.NoError, ret,
                                $"Unexpected error {ret} retrieving stats for \"{childPath}\" in {testFile}");

                stat.Should().BeEquivalentTo(child.Value.Info, $"Wrong info for \"{childPath}\" in {testFile}");

                byte[] buffer = new byte[0];

                if (child.Value.Info.Attributes.HasFlag(FileAttributes.Directory))
                {
                    ret = fs.Read(childPath, 0, 1, ref buffer);

                    Assert.AreEqual(Errno.IsDirectory, ret,
                                    $"Got wrong data for directory \"{childPath}\" in {testFile}");

                    Assert.IsNotNull(child.Value.Children,
                                     $"Contents for \"{childPath}\" in {testFile} must be defined in unit test declaration!");

                    if (child.Value.Children != null)
                    {
                        TestDirectory(fs, childPath, child.Value.Children, testFile);
                    }
                }
                else if (child.Value.Info.Attributes.HasFlag(FileAttributes.Symlink))
                {
                    ret = fs.ReadLink(childPath, out string link);

                    Assert.AreEqual(Errno.NoError, ret,
                                    $"Got wrong data for symbolic link \"{childPath}\" in {testFile}");

                    Assert.AreEqual(child.Value.LinkTarget, link,
                                    $"Invalid target for symbolic link \"{childPath}\" in {testFile}");
                }
                else
                {
                    // This ensure the buffer does not hang for collection
                    TestFile(fs, childPath, child.Value.MD5, child.Value.Info.Length, testFile);
                }

                ret = fs.ListXAttr(childPath, out List <string> xattrs);

                if (ret == Errno.NotSupported)
                {
                    Assert.IsNull(child.Value.XattrsWithMd5,
                                  $"Defined extended attributes for \"{childPath}\" in {testFile} are not supported by filesystem.");

                    continue;
                }

                Assert.AreEqual(Errno.NoError, ret,
                                $"Unexpected error {ret} when listing extended attributes for \"{childPath}\" in {testFile}");

                if (xattrs.Count > 0)
                {
                    Assert.IsNotNull(child.Value.XattrsWithMd5,
                                     $"Extended attributes for \"{childPath}\" in {testFile} must be defined in unit test declaration!");
                }

                if (xattrs.Count > 0 ||
                    child.Value.XattrsWithMd5?.Count > 0)
                {
                    TestFileXattrs(fs, childPath, child.Value.XattrsWithMd5, testFile);
                }
            }

            Assert.IsEmpty(expectedNotFound,
                           $"Could not find the children of \"{path}\" in {testFile}: {string.Join(" ", expectedNotFound)}");

            Assert.IsEmpty(contents,
                           $"Found the following unexpected children of \"{path}\" in {testFile}: {string.Join(" ", contents)}");
        }
Ejemplo n.º 5
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)
            {
                DicConsole.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))
                    {
                        Directory.CreateDirectory(Path.Combine(outputDir, fs.XmlFsType.Type, volumeName));

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

                        Directory.CreateDirectory(outputPath);

                        DicConsole.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;
                                }

                                Directory.CreateDirectory(Path.Combine(outputDir, fs.XmlFsType.Type, volumeName,
                                                                       ".xattrs", xattr));

                                outputPath = Path.Combine(outputDir, fs.XmlFsType.Type, volumeName, ".xattrs", xattr,
                                                          path, 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
                                    DicConsole.WriteLine("Written {0} bytes of xattr {1} from file {2} to {3}",
                                                         xattrBuf.Length, xattr, entry, outputPath);
                                }
                                else
                                {
                                    DicConsole.ErrorWriteLine("Cannot write xattr {0} for {1}, output exists", xattr,
                                                              entry);
                                }
                            }
                        }
                    }

                    Directory.CreateDirectory(Path.Combine(outputDir, fs.XmlFsType.Type, volumeName));

                    outputPath = Path.Combine(outputDir, fs.XmlFsType.Type, volumeName, path, 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
                            DicConsole.WriteLine("Written {0} bytes of file {1} to {2}", outBuf.Length, entry,
                                                 outputPath);
                        }
                        else
                        {
                            DicConsole.ErrorWriteLine("Error {0} reading file {1}", error, entry);
                        }
                    }
                    else
                    {
                        DicConsole.ErrorWriteLine("Cannot write file {0}, output exists", entry);
                    }
                }
                else
                {
                    DicConsole.ErrorWriteLine("Error reading file {0}", entry);
                }
            }
        }