diff --git a/Library/DiscUtils.Core/Archives/TarFileBuilder.cs b/Library/DiscUtils.Core/Archives/TarFileBuilder.cs index c5eed3bfc..cfab95504 100644 --- a/Library/DiscUtils.Core/Archives/TarFileBuilder.cs +++ b/Library/DiscUtils.Core/Archives/TarFileBuilder.cs @@ -1,5 +1,5 @@ // -// Copyright (c) 2008-2011, Kenneth Bell +// Copyright (c) 2008-2024, Kenneth Bell, Olof Lagerkvist and contributors // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), @@ -24,6 +24,7 @@ using DiscUtils.Streams; using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.IO; namespace DiscUtils.Archives; @@ -74,6 +75,11 @@ public long TotalSize public int FileCount => _files.Count; + protected virtual void AddFile(UnixBuildFileRecord file) + { + _files.Add(file); + } + /// /// Add a directory to the tar archive. /// @@ -114,7 +120,7 @@ public void AddDirectory( /// The file data. public void AddFile(string name, byte[] buffer) { - _files.Add(new UnixBuildFileRecord(name, buffer)); + AddFile(new UnixBuildFileRecord(name, buffer)); } /// @@ -124,7 +130,7 @@ public void AddFile(string name, byte[] buffer) /// The file to add. public void AddFile(string name, string sourcefile) { - _files.Add(new UnixBuildFileRecord(name, File.ReadAllBytes(sourcefile))); + AddFile(new UnixBuildFileRecord(name, File.ReadAllBytes(sourcefile))); } /// @@ -139,7 +145,7 @@ public void AddFile(string name, string sourcefile) public void AddFile( string name, byte[] buffer, int ownerId, int groupId, UnixFilePermissions fileMode, DateTime modificationTime) { - _files.Add(new UnixBuildFileRecord(name, buffer, fileMode, ownerId, groupId, modificationTime)); + AddFile(new UnixBuildFileRecord(name, buffer, fileMode, ownerId, groupId, modificationTime)); } /// @@ -154,7 +160,7 @@ public void AddFile( public void AddFile( string name, string sourcefile, int ownerId, int groupId, UnixFilePermissions fileMode, DateTime modificationTime) { - _files.Add(new UnixBuildFileRecord(name, File.ReadAllBytes(sourcefile), fileMode, ownerId, groupId, modificationTime)); + AddFile(new UnixBuildFileRecord(name, File.ReadAllBytes(sourcefile), fileMode, ownerId, groupId, modificationTime)); } /// @@ -164,7 +170,7 @@ public void AddFile( /// The file data. public void AddFile(string name, Stream stream) { - _files.Add(new UnixBuildFileRecord(name, stream)); + AddFile(new UnixBuildFileRecord(name, stream)); } /// @@ -179,7 +185,7 @@ public void AddFile(string name, Stream stream) public void AddFile( string name, Stream stream, int ownerId, int groupId, UnixFilePermissions fileMode, DateTime modificationTime) { - _files.Add(new UnixBuildFileRecord(name, stream, fileMode, ownerId, groupId, modificationTime)); + AddFile(new UnixBuildFileRecord(name, stream, fileMode, ownerId, groupId, modificationTime)); } protected override List FixExtents(out long totalLength) diff --git a/Library/DiscUtils.Core/Archives/UnixBuildFileRecord.cs b/Library/DiscUtils.Core/Archives/UnixBuildFileRecord.cs index c9622f921..dafb70468 100644 --- a/Library/DiscUtils.Core/Archives/UnixBuildFileRecord.cs +++ b/Library/DiscUtils.Core/Archives/UnixBuildFileRecord.cs @@ -1,5 +1,5 @@ // -// Copyright (c) 2008-2011, Kenneth Bell +// Copyright (c) 2008-2024, Kenneth Bell, Olof Lagerkvist and contributors // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), @@ -26,7 +26,8 @@ using System.IO; namespace DiscUtils.Archives; -internal sealed class UnixBuildFileRecord + +public sealed class UnixBuildFileRecord { private string _name; private UnixFilePermissions _fileMode; diff --git a/Library/DiscUtils.Core/IFileSystemBuilder.cs b/Library/DiscUtils.Core/IFileSystemBuilder.cs index dd805a4da..fbf148fb8 100644 --- a/Library/DiscUtils.Core/IFileSystemBuilder.cs +++ b/Library/DiscUtils.Core/IFileSystemBuilder.cs @@ -1,5 +1,5 @@ // -// Copyright (c) 2008-2011, Kenneth Bell +// Copyright (c) 2008-2024, Kenneth Bell, Olof Lagerkvist and contributors // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), @@ -33,6 +33,8 @@ public interface IFileSystemBuilder string VolumeIdentifier { get; set; } + event EventHandler ProgressChanged; + void AddDirectory(string name); void AddDirectory(string name, DateTime creationTime, DateTime writtenTime, DateTime accessedTime, FileAttributes attributes); diff --git a/Library/DiscUtils.Core/ProgressEventArgs.cs b/Library/DiscUtils.Core/ProgressEventArgs.cs new file mode 100644 index 000000000..33de31a82 --- /dev/null +++ b/Library/DiscUtils.Core/ProgressEventArgs.cs @@ -0,0 +1,32 @@ +// +// Copyright (c) 2008-2024, Kenneth Bell, Olof Lagerkvist and contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace DiscUtils; + +// EventArgs class for progress reporting +public class ProgressEventArgs : EventArgs +{ + public long TotalFiles { get; set; } + public long TotalItems { get; set; } +} diff --git a/Library/DiscUtils.Iso9660/BuildDirectoryInfo.cs b/Library/DiscUtils.Iso9660/BuildDirectoryInfo.cs index 42de7863c..44902ed88 100644 --- a/Library/DiscUtils.Iso9660/BuildDirectoryInfo.cs +++ b/Library/DiscUtils.Iso9660/BuildDirectoryInfo.cs @@ -1,5 +1,5 @@ // -// Copyright (c) 2008-2011, Kenneth Bell +// Copyright (c) 2008-2024, Kenneth Bell, Olof Lagerkvist and contributors // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), @@ -41,9 +41,9 @@ public sealed class BuildDirectoryInfo : BuildDirectoryMember private List _sortedMembers; internal BuildDirectoryInfo(string name, BuildDirectoryInfo parent) - : base(name, MakeShortDirName(name, parent)) + : base(name, MakeShortDirName(name)) { - _parent = parent == null ? this : parent; + _parent = parent ?? this; HierarchyDepth = parent == null ? 0 : parent.HierarchyDepth + 1; _members = new(StringComparer.OrdinalIgnoreCase, entry => entry.Name); } @@ -147,7 +147,7 @@ private static int WriteMember(BuildDirectoryMember m, string nameOverride, Enco return dr.WriteTo(buffer, nameEnc); } - private static string MakeShortDirName(string longName, BuildDirectoryInfo dir) + private static string MakeShortDirName(string longName) { if (IsoUtilities.IsValidDirectoryName(longName)) { diff --git a/Library/DiscUtils.Iso9660/CDBuilder.cs b/Library/DiscUtils.Iso9660/CDBuilder.cs index 3f45e0adb..de4094995 100644 --- a/Library/DiscUtils.Iso9660/CDBuilder.cs +++ b/Library/DiscUtils.Iso9660/CDBuilder.cs @@ -1,5 +1,5 @@ // -// Copyright (c) 2008-2011, Kenneth Bell +// Copyright (c) 2008-2024, Kenneth Bell, Olof Lagerkvist and contributors // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), @@ -56,6 +56,23 @@ public sealed class CDBuilder : StreamBuilder, IFileSystemBuilder private readonly List _files; private readonly BuildDirectoryInfo _rootDirectory; + // Progress reporting event + public event EventHandler ProgressChanged; + + private ProgressEventArgs progressEventArgs; + + // Method for updating progress + private void UpdateProgress() + { + if (ProgressChanged is not null) + { + progressEventArgs ??= new(); + progressEventArgs.TotalFiles = _files.Count; + progressEventArgs.TotalItems = _files.Count + _dirs.Count; + ProgressChanged(this, progressEventArgs); + } + } + /// /// Initializes a new instance of the CDBuilder class. /// @@ -180,6 +197,8 @@ public BuildDirectoryInfo AddDirectory(string name) private void AddFile(BuildFileInfo fi) { _files.Add(fi); + + UpdateProgress(); } /// @@ -311,7 +330,7 @@ protected override List FixExtents(out long totalLength) _bootEntry.WriteTo(bootCatalog, 0x20); fixedRegions.Add(new BuilderBufferExtent(bootCatalogPos, bootCatalog)); - + // Don't add to focus, we already skipped the length of the bootCatalog } @@ -628,11 +647,11 @@ void IFileSystemBuilder.AddFile(string name, byte[] content, DateTime creationTi void IFileSystemBuilder.AddFile(string name, Stream source, DateTime creationTime, DateTime writtenTime, DateTime accessedTime, FileAttributes attributes) => AddFile(name, source).CreationTime = writtenTime; - + void IFileSystemBuilder.AddFile(string name, string sourcePath, DateTime creationTime, DateTime writtenTime, DateTime accessedTime, FileAttributes attributes) => AddFile(name, sourcePath).CreationTime = writtenTime; bool IFileSystemBuilder.Exists(string path) => GetFile(path) != null; public IFileSystem GenerateFileSystem() => new CDReader(Build(), UseJoliet); -} \ No newline at end of file +} diff --git a/Library/DiscUtils.SquashFs/BuilderDirectory.cs b/Library/DiscUtils.SquashFs/BuilderDirectory.cs index a73ea7017..ec98e115a 100644 --- a/Library/DiscUtils.SquashFs/BuilderDirectory.cs +++ b/Library/DiscUtils.SquashFs/BuilderDirectory.cs @@ -1,5 +1,5 @@ // -// Copyright (c) 2008-2011, Kenneth Bell +// Copyright (c) 2008-2024, Kenneth Bell, Olof Lagerkvist and contributors // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), @@ -43,7 +43,7 @@ public BuilderDirectory() public void AddChild(string name, BuilderNode node) { - if (name.Contains(@"\\")) + if (name.IndexOfAny(Utilities.PathSeparators) >= 0) { throw new ArgumentException("Single level of path must be provided", nameof(name)); } diff --git a/Library/DiscUtils.SquashFs/SquashFileSystemBuilder.cs b/Library/DiscUtils.SquashFs/SquashFileSystemBuilder.cs index 82b9c7540..a65c28418 100644 --- a/Library/DiscUtils.SquashFs/SquashFileSystemBuilder.cs +++ b/Library/DiscUtils.SquashFs/SquashFileSystemBuilder.cs @@ -1,5 +1,5 @@ // -// Copyright (c) 2008-2024, Kenneth Bell, Olof Lagerkvist +// Copyright (c) 2008-2024, Kenneth Bell, Olof Lagerkvist and contributors // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), @@ -45,6 +45,23 @@ public sealed class SquashFileSystemBuilder : StreamBuilder, IFileSystemBuilder private BuilderDirectory _rootDir; + // Progress reporting event + public event EventHandler ProgressChanged; + + private ProgressEventArgs progressEventArgs; + + // Method for updating progress + private void AddProgress(int newFiles, int newItems) + { + if (ProgressChanged is not null) + { + progressEventArgs ??= new(); + progressEventArgs.TotalFiles += newFiles; + progressEventArgs.TotalItems += newItems; + ProgressChanged(this, progressEventArgs); + } + } + /// /// Initializes a new instance of the SquashFileSystemBuilder class. /// @@ -155,7 +172,10 @@ public void AddFile(string path, Stream content, int user, int group, UnixFilePe user, group, DefaultDirectoryPermissions); + dirNode.AddChild(Utilities.GetFileFromPath(path), file); + + AddProgress(newFiles: 1, newItems: 1); } /// @@ -187,7 +207,10 @@ public void AddFile(string path, byte[] content, int user, int group, UnixFilePe user, group, DefaultDirectoryPermissions); + dirNode.AddChild(Utilities.GetFileFromPath(path), file); + + AddProgress(newFiles: 1, newItems: 1); } /// @@ -219,7 +242,10 @@ public void AddFile(string path, string contentPath, int user, int group, UnixFi user, group, DefaultDirectoryPermissions); + dirNode.AddChild(Utilities.GetFileFromPath(path), file); + + AddProgress(newFiles: 1, newItems: 1); } /// @@ -266,6 +292,7 @@ public void AddDirectory(string path, int user, int group, UnixFilePermissions p user, group, permissions); + parentDir.AddChild(Utilities.GetFileFromPath(path), dir); } @@ -535,6 +562,8 @@ private BuilderDirectory CreateDirectory(string path, int user, int group, UnixF }; currentDir.AddChild(elems[i], nextDir); + + AddProgress(newFiles: 0, newItems: 1); } else if (nextDir == null) { diff --git a/Library/DiscUtils.VirtualFileSystem/TarFileSystemBuilder.cs b/Library/DiscUtils.VirtualFileSystem/TarFileSystemBuilder.cs index 94af2c905..5ad13aa49 100644 --- a/Library/DiscUtils.VirtualFileSystem/TarFileSystemBuilder.cs +++ b/Library/DiscUtils.VirtualFileSystem/TarFileSystemBuilder.cs @@ -4,10 +4,31 @@ using DiscUtils.Archives; using DiscUtils.Internal; using System.IO; +using System.Collections.Specialized; +using System.Linq; +using LTRData.Extensions.Buffers; namespace DiscUtils.VirtualFileSystem; public class TarFileSystemBuilder : TarFileBuilder, IFileSystemBuilder { + // Progress reporting event + public event EventHandler ProgressChanged; + + private ProgressEventArgs progressEventArgs; + + protected override void AddFile(UnixBuildFileRecord file) + { + base.AddFile(file); + + if (ProgressChanged is not null) + { + progressEventArgs ??= new(); + progressEventArgs.TotalFiles += file.Name.EndsWith('/') ? 0 : 1; + progressEventArgs.TotalItems = FileCount; + ProgressChanged(this, progressEventArgs); + } + } + public string VolumeIdentifier { get; set; } public IFileSystem GenerateFileSystem() => new TarFileSystem(Build(), VolumeIdentifier, ownsStream: true); diff --git a/Library/DiscUtils.VirtualFileSystem/VirtualFileSystem.cs b/Library/DiscUtils.VirtualFileSystem/VirtualFileSystem.cs index 2bd9efff5..f29fec53d 100644 --- a/Library/DiscUtils.VirtualFileSystem/VirtualFileSystem.cs +++ b/Library/DiscUtils.VirtualFileSystem/VirtualFileSystem.cs @@ -12,6 +12,23 @@ public partial class VirtualFileSystem : DiscFileSystem, IWindowsFileSystem, IUn { public delegate Stream FileOpenDelegate(FileMode mode, FileAccess access); + // Progress reporting event + public event EventHandler ProgressChanged; + + private ProgressEventArgs progressEventArgs; + + // Method for updating progress + internal void AddProgress(int newFiles, int newItems) + { + if (ProgressChanged is not null) + { + progressEventArgs ??= new(); + progressEventArgs.TotalFiles += newFiles; + progressEventArgs.TotalItems += newItems; + ProgressChanged(this, progressEventArgs); + } + } + public static string GetPathDirectoryName(string path) { if (string.IsNullOrEmpty(path)) diff --git a/Library/DiscUtils.VirtualFileSystem/VirtualFileSystemDirectoryEntry.cs b/Library/DiscUtils.VirtualFileSystem/VirtualFileSystemDirectoryEntry.cs index a480ed82a..47ec0f1e4 100644 --- a/Library/DiscUtils.VirtualFileSystem/VirtualFileSystemDirectoryEntry.cs +++ b/Library/DiscUtils.VirtualFileSystem/VirtualFileSystemDirectoryEntry.cs @@ -43,8 +43,11 @@ internal VirtualFileSystemDirectoryEntry(VirtualFileSystem fileSystem) internal VirtualFileSystemDirectoryEntry(VirtualFileSystemDirectory parent, string name) { - Parent = parent ?? throw new ArgumentNullException(nameof(parent)); - FileSystem = parent.FileSystem ?? throw new ArgumentException("FileSystem property is null", nameof(parent)); + Parent = parent + ?? throw new ArgumentNullException(nameof(parent)); + + FileSystem = parent.FileSystem + ?? throw new ArgumentException("FileSystem property is null", nameof(parent)); if (string.IsNullOrEmpty(name)) { @@ -52,6 +55,8 @@ internal VirtualFileSystemDirectoryEntry(VirtualFileSystemDirectory parent, stri } parent.AddEntry(name, this); + + FileSystem.AddProgress(newFiles: (this is VirtualFileSystemFile) ? 1 : 0, newItems: 1); } public WindowsFileInformation GetStandardInformation() => new()