Browse ISOs

This commit is contained in:
2023-09-04 15:19:20 +02:00
parent 38979d8572
commit a323edafd3
29 changed files with 555 additions and 60 deletions

View File

@@ -0,0 +1,220 @@
using System.Collections.ObjectModel;
using DiscUtils;
using DiscUtils.Iso9660;
using DiscUtils.Udf;
using FileTime.Core.ContentAccess;
using FileTime.Core.Enums;
using FileTime.Core.Models;
using FileTime.Core.Timeline;
using FileTime.Tools.VirtualDiskSources.Abstractions;
namespace FileTime.Tools.VirtualDiskSources;
public class VirtualDiskSubContentProvider : IVirtualDiskSubContentProvider
{
private readonly IContentAccessorFactory _contentAccessorFactory;
private readonly ITimelessContentProvider _timelessContentProvider;
public VirtualDiskSubContentProvider(
IContentAccessorFactory contentAccessorFactory,
ITimelessContentProvider timelessContentProvider
)
{
_contentAccessorFactory = contentAccessorFactory;
_timelessContentProvider = timelessContentProvider;
}
public Task<bool> CanHandleAsync(IElement parentElement)
=> Task.FromResult(parentElement.NativePath?.Path.EndsWith(".iso", StringComparison.OrdinalIgnoreCase) ?? false);
public async Task<IItem?> GetItemByFullNameAsync(
IElement parentElement,
FullName itemPath,
PointInTime pointInTime,
AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown,
ItemInitializationSettings itemInitializationSettings = default)
{
var contentReaderFactory = _contentAccessorFactory.GetContentReaderFactory(parentElement.Provider);
var reader = await contentReaderFactory.CreateContentReaderAsync(parentElement);
await using var readerStream = reader.AsStream();
var discReader = new UdfReader(readerStream);
if (itemPath.Path.Length == 0 || itemPath.Path == Constants.SubContentProviderRootContainer)
{
var rootFullNameBase = parentElement.FullName!.Path + Constants.SeparatorChar + Constants.SubContentProviderRootContainer;
var rootNativePathBase = parentElement.NativePath!.Path + Constants.SeparatorChar + Constants.SubContentProviderRootContainer;
var rootFullName = new FullName(rootFullNameBase);
var rootNativePath = new NativePath(rootNativePathBase);
return CreateContainer(discReader.Root,
rootFullName,
rootNativePath,
parentElement.Provider,
parentElement.Parent!,
parentElement.PointInTime,
itemInitializationSettings);
}
return ResolveNonRootChild(discReader, parentElement, itemPath, pointInTime, itemInitializationSettings);
}
private IItem? ResolveNonRootChild(
UdfReader discReader,
IElement parentElement,
FullName itemPath,
PointInTime pointInTime,
ItemInitializationSettings itemInitializationSettings = default)
{
var pathParts = itemPath.Path.Split(Constants.SeparatorChar);
var childFullNameBase = parentElement.FullName!.Path + Constants.SeparatorChar + itemPath.Path;
var childNativePathBase = parentElement.NativePath!.Path + Constants.SeparatorChar + itemPath.Path;
var childFullName = new FullName(childFullNameBase);
var childNativePath = new NativePath(childNativePathBase);
var parent = new AbsolutePath(_timelessContentProvider, pointInTime, childFullName.GetParent()!, AbsolutePathType.Container);
var container = discReader.Root;
for (var i = 1; i < pathParts.Length - 1; i++)
{
if (container is null) break;
container = container.GetDirectories().FirstOrDefault(d => d.Name == pathParts[i]);
}
if (container is null) return null;
if (container.GetDirectories().FirstOrDefault(d => d.Name == pathParts[^1]) is { } childContainer)
{
return CreateContainer(
childContainer,
childFullName,
childNativePath,
parentElement.Provider,
parent,
pointInTime,
itemInitializationSettings
);
}
if (container.GetFiles().FirstOrDefault(d => d.Name == pathParts[^1]) is { } childElement)
{
return CreateElement(
childElement,
childFullName,
childNativePath,
parentElement.Provider,
parent,
pointInTime
);
}
return null;
}
private IContainer CreateContainer(
DiscDirectoryInfo sourceContainer,
FullName fullname,
NativePath nativePath,
IContentProvider parentContentProvider,
AbsolutePath parent,
PointInTime pointInTime,
ItemInitializationSettings initializationSettings)
{
var children = new ObservableCollection<AbsolutePath>();
var exceptions = new ObservableCollection<Exception>();
var container = new Container(
sourceContainer.Name,
sourceContainer.Name,
fullname,
nativePath,
parent,
true,
true,
sourceContainer.CreationTime,
sourceContainer.LastWriteTime,
SupportsDelete.False,
false,
FormatAttributes(sourceContainer.Attributes),
new VirtualDiskContentProvider(parentContentProvider, _timelessContentProvider),
false,
pointInTime,
exceptions,
new ReadOnlyExtensionCollection(new ExtensionCollection()),
children
);
if (!initializationSettings.SkipChildInitialization)
{
ThreadPool.QueueUserWorkItem(_ => LoadChildren(container, sourceContainer, children, pointInTime, exceptions));
}
return container;
}
private void LoadChildren(
Container container,
DiscDirectoryInfo sourceContainer,
ObservableCollection<AbsolutePath> children,
PointInTime pointInTime,
ObservableCollection<Exception> exceptions
)
{
foreach (var discDirectoryInfo in sourceContainer.GetDirectories())
{
children.Add(new AbsolutePath(
_timelessContentProvider,
pointInTime,
container.FullName.GetChild(discDirectoryInfo.Name),
AbsolutePathType.Container)
);
}
foreach (var fileInfo in sourceContainer.GetFiles())
{
children.Add(new AbsolutePath(
_timelessContentProvider,
pointInTime,
container.FullName.GetChild(fileInfo.Name),
AbsolutePathType.Element)
);
}
}
private IElement CreateElement(DiscFileInfo childElement,
FullName fullname,
NativePath nativePath,
IContentProvider parentContentProvider,
AbsolutePath parent,
PointInTime pointInTime)
{
var element = new Element(
childElement.Name,
childElement.Name,
fullname,
nativePath,
parent,
true,
true,
childElement.CreationTime,
childElement.LastWriteTime,
SupportsDelete.False,
false,
FormatAttributes(childElement.Attributes),
childElement.Length,
new VirtualDiskContentProvider(parentContentProvider, _timelessContentProvider),
pointInTime,
new ObservableCollection<Exception>(),
new ReadOnlyExtensionCollection(new ExtensionCollection())
);
return element;
}
private string FormatAttributes(FileAttributes attributes)
{
return "";
}
}