/// <summary> /// Function to return all the parents up to the root directory. /// </summary> /// <returns>A list of all the parents, up to and including the root.</returns> /// <remarks> /// If this value is empty, then there is no parent for this directory. This indicates that the current directory is the root directory for the file system. /// </remarks> public IEnumerable <IGorgonVirtualDirectory> GetParents() { IGorgonVirtualDirectory parent = Parent; while (parent != null) { yield return(parent); parent = parent.Parent; } }
/// <summary> /// Function to locate the associated texture codec and file for a sprite. /// </summary> /// <param name="fileSystem">The file system to evaluate.</param> /// <param name="localDir">The local directory for the sprite file.</param> /// <param name="renderer">The renderer used for resource look up.</param> /// <param name="textureName">The name of the texture.</param> /// <param name="codecs">The list of available image codecs to use when determining texture type.</param> /// <returns>A tuple containing the codec, the texture file, and a flag to indicate that the texture was previously loaded into memory.</returns> private static (IGorgonImageCodec codec, IGorgonVirtualFile file, bool alreadyLoaded) LocateTextureCodecAndFile( IGorgonFileSystem fileSystem, IGorgonVirtualDirectory localDir, Gorgon2D renderer, string textureName, IEnumerable <IGorgonImageCodec> codecs) { // First, attempt to locate the resource by its name. If it's already loaded, we should not load it again. GorgonTexture2D texture = renderer.Graphics .LocateResourcesByName <GorgonTexture2D>(textureName) .FirstOrDefault(); if (texture != null) { return(null, null, true); } IGorgonImageCodec codec; // We couldn't find the texture in our loaded resources, so try to locate it on the file system. // First, check the local directory. IEnumerable <IGorgonVirtualFile> files = fileSystem.FindFiles(localDir.FullPath, $"{textureName}.*", false); foreach (IGorgonVirtualFile file in files) { codec = FindTextureCodec(file, codecs); if (codec != null) { return(codec, file, false); } } // Check to see if the name has path information for the texture in the name. // The GorgonEditor from v2 does this. if (!textureName.Contains("/")) { // It is not. We cannot load the texture. return(null, null, false); } IGorgonVirtualFile textureFile = fileSystem.GetFile(textureName); if (textureFile == null) { return(null, null, false); } // Try to find a codec for the image file. codec = FindTextureCodec(textureFile, codecs); return(codec == null ? (null, null, false) : (codec, textureFile, false)); }
/// <summary> /// Function to enumerate the files and directories from a physical location and map it to a virtual location. /// </summary> /// <param name="physicalLocation">The physical location containing files and directories to enumerate.</param> /// <param name="mountPoint">A <see cref="IGorgonVirtualDirectory"/> that the directories and files from the physical file system will be mounted into.</param> /// <returns>A <see cref="GorgonPhysicalFileSystemData"/> object containing information about the directories and files contained within the physical file system.</returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="physicalLocation"/>, or the <paramref name="mountPoint"/> parameters are <b>null</b>.</exception> /// <exception cref="ArgumentEmptyException">Thrown when the <paramref name="physicalLocation"/> parameter is empty.</exception> /// <remarks> /// <para> /// This will return a <see cref="GorgonPhysicalFileSystemData"/> representing the paths to directories and <see cref="IGorgonPhysicalFileInfo"/> objects under the virtual file system. Each file /// system file and directory is mapped from its <paramref name="physicalLocation"/> on the physical file system to a <paramref name="mountPoint"/> on the virtual file system. For example, if the /// mount point is set to <c>/MyMount/</c>, and the physical location of a file is <c>c:\SourceFileSystem\MyDirectory\MyTextFile.txt</c>, then the returned value should be /// <c>/MyMount/MyDirectory/MyTextFile.txt</c>. /// </para> /// <para> /// Implementors of a <see cref="GorgonFileSystemProvider"/> plug in can override this method to read the list of files from another type of file system, like a Zip file. /// </para> /// </remarks> public GorgonPhysicalFileSystemData Enumerate(string physicalLocation, IGorgonVirtualDirectory mountPoint) { if (physicalLocation == null) { throw new ArgumentNullException(nameof(physicalLocation)); } if (mountPoint == null) { throw new ArgumentNullException(nameof(mountPoint)); } if (string.IsNullOrWhiteSpace(physicalLocation)) { throw new ArgumentEmptyException(nameof(physicalLocation)); } return(OnEnumerate(physicalLocation, mountPoint)); }
/// <summary> /// Function to enumerate the available directories stored in the packed file. /// </summary> /// <param name="index">The XML file containing the index of files and directories.</param> /// <param name="mountPoint">The mount point to map into.</param> /// <returns>A read only list of directory paths mapped to the virtual file system.</returns> private static IReadOnlyList <string> EnumerateDirectories(XDocument index, IGorgonVirtualDirectory mountPoint) { var result = new List <string>(); IEnumerable <XElement> directories = index.Descendants("Path"); foreach (XElement directoryNode in directories) { XAttribute pathAttrib = directoryNode.Attribute("FullPath"); if (string.IsNullOrWhiteSpace(pathAttrib?.Value)) { throw new FileLoadException(Resources.GORFS_GORPACK_ERR_FILEINDEX_CORRUPT); } // Add the directory. result.Add((mountPoint.FullPath + pathAttrib.Value).FormatDirectory('/')); } return(result); }
/// <summary> /// Initializes a new instance of the <see cref="ZipPhysicalFileInfo" /> class. /// </summary> /// <param name="entry">The entry.</param> /// <param name="physicalLocation">The physical location of the zip file.</param> /// <param name="mountPoint">Mount point path.</param> public ZipPhysicalFileInfo(ZipEntry entry, string physicalLocation, IGorgonVirtualDirectory mountPoint) { string directory = Path.GetDirectoryName(entry.Name); directory = mountPoint.FullPath + directory; if (string.IsNullOrWhiteSpace(directory)) { directory = "/"; } directory = directory.FormatDirectory('/'); CompressedLength = entry.CompressedSize; CreateDate = entry.DateTime; FullPath = physicalLocation + "::/" + entry.Name; Length = entry.Size; Offset = entry.Offset; Name = Path.GetFileName(entry.Name).FormatFileName(); VirtualPath = directory + Name; }
/// <summary> /// Function to fill the file system tree view. /// </summary> /// <param name="directory">Parent directory to fill, or <b>null</b> to fill the root directory.</param> private void FillTree(IGorgonVirtualDirectory directory) { TreeNodeCollection nodes; TreeNode parentNode; if (directory == null) { directory = _fileSystem.RootDirectory; nodes = treeFileSystem.Nodes; // Set root node. parentNode = new TreeNode("/") { Name = "/" }; parentNode.SelectedImageIndex = parentNode.ImageIndex = 0; } else { // Find the node with the directory. TreeNode[] searchNodes = treeFileSystem.Nodes.Find(directory.FullPath, true); if (searchNodes.Length > 0) { parentNode = searchNodes[0]; nodes = parentNode.Nodes; } else { GorgonDialogs.ErrorBox(this, "Could not find the virtual directory '" + directory.FullPath + "'"); return; } } parentNode.Tag = directory; // Turn off the expand event. treeFileSystem.BeforeExpand -= TreeFileSystem_BeforeExpand; try { // Clean up the tree node. treeFileSystem.BeginUpdate(); nodes.Clear(); // Add the root node if necessary. if (parentNode.Tag == _fileSystem.RootDirectory) { nodes.Add(parentNode); } // Enumerate the data. For the purposed of this example, we will filter out known binary files from our file system. IOrderedEnumerable <IGorgonVirtualDirectory> directories = directory.Directories.OrderBy(item => item.Name); IEnumerable <IGorgonVirtualFile> files = directory.Files.OrderBy(item => item.Name).Where(item => item.Extension != ".gorSprite" && item.Extension != ".gal"); // Get directories. foreach (IGorgonVirtualDirectory subDirectory in directories) { var directoryNode = new TreeNode(subDirectory.Name) { Name = subDirectory.FullPath, Tag = subDirectory }; // Put a special icon on the zip file so we have a visual representation // of where it is in our VFS. // The VFS does not care if the data is in a zip file or folder, and Gorgon // does very little to differentiate it. After all, the whole point of // have a unified file system is to abstract away the differences. if (subDirectory.Name != "ZipFile") { directoryNode.SelectedImageIndex = directoryNode.ImageIndex = 0; } else { directoryNode.SelectedImageIndex = directoryNode.ImageIndex = 2; } // Add a dummy node if there are files or sub directories. if ((subDirectory.Directories.Count > 0) || (subDirectory.Files.Count(item => item.Extension != ".gorSprite" && item.Extension != ".gal") > 0)) { directoryNode.Nodes.Add(new TreeNode("This is a dummy node.")); } parentNode.Nodes.Add(directoryNode); } // Get files. foreach (IGorgonVirtualFile file in files) { if (file.Extension == ".gorSprite") { continue; } var fileNode = new TreeNode(file.Name) { Name = file.FullPath, Tag = file }; fileNode.SelectedImageIndex = fileNode.ImageIndex = 1; parentNode.Nodes.Add(fileNode); } parentNode.Expand(); } finally { treeFileSystem.EndUpdate(); treeFileSystem.BeforeExpand += TreeFileSystem_BeforeExpand; } }
/// <summary> /// Function to enumerate the files and directories from a physical location and map it to a virtual location. /// </summary> /// <param name="physicalLocation">The physical location containing files and directories to enumerate.</param> /// <param name="mountPoint">A <see cref="IGorgonVirtualDirectory"/> that the directories and files from the physical file system will be mounted into.</param> /// <returns>A <see cref="GorgonPhysicalFileSystemData"/> object containing information about the directories and files contained within the physical file system.</returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="physicalLocation"/>, or the <paramref name="mountPoint"/> parameters are <b>null</b>.</exception> /// <exception cref="ArgumentEmptyException">Thrown when the <paramref name="physicalLocation"/> parameter is empty.</exception> /// <remarks> /// <para> /// This will return a <see cref="GorgonPhysicalFileSystemData"/> representing the paths to directories and <see cref="IGorgonPhysicalFileInfo"/> objects under the virtual file system. Each file /// system file and directory is mapped from its <paramref name="physicalLocation"/> on the physical file system to a <paramref name="mountPoint"/> on the virtual file system. For example, if the /// mount point is set to <c>/MyMount/</c>, and the physical location of a file is <c>c:\SourceFileSystem\MyDirectory\MyTextFile.txt</c>, then the returned value should be /// <c>/MyMount/MyDirectory/MyTextFile.txt</c>. /// </para> /// <para> /// Implementors of a <see cref="GorgonFileSystemProvider"/> plug in can override this method to read the list of files from another type of file system, like a Zip file. /// </para> /// <para> /// Implementors of a <see cref="GorgonFileSystemProvider"/> should override this method to read the list of directories and files from another type of file system, like a Zip file. /// The default functionality will only enumerate directories and files from the operating system file system. /// </para> /// </remarks> protected virtual GorgonPhysicalFileSystemData OnEnumerate(string physicalLocation, IGorgonVirtualDirectory mountPoint) => new GorgonPhysicalFileSystemData(EnumerateDirectories(physicalLocation, mountPoint), EnumerateFiles(physicalLocation, mountPoint));
/// <summary> /// Function to enumerate the files and directories from a physical location and map it to a virtual location. /// </summary> /// <param name="physicalLocation">The physical location containing files and directories to enumerate.</param> /// <param name="mountPoint">A <see cref="IGorgonVirtualDirectory"/> that the directories and files from the physical file system will be mounted into.</param> /// <returns>A <see cref="GorgonPhysicalFileSystemData"/> object containing information about the directories and files contained within the physical file system.</returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="physicalLocation"/>, or the <paramref name="mountPoint"/> parameters are <b>null</b>.</exception> /// <exception cref="ArgumentEmptyException">Thrown when the <paramref name="physicalLocation"/> parameter is empty.</exception> /// <remarks> /// Since this provider holds data in its own block of memory, there's nothing to enumerate when the provider is loaded. Thus, this will always return empty data. /// </remarks> public GorgonPhysicalFileSystemData Enumerate(string physicalLocation, IGorgonVirtualDirectory mountPoint) => OnEnumerate(physicalLocation, mountPoint);
/// <summary> /// Function to enumerate files from the file system. /// </summary> /// <param name="physicalLocation">The physical file system location to enumerate.</param> /// <param name="mountPoint">The mount point to remap the file paths to.</param> /// <returns>A read only list of <see cref="IGorgonPhysicalFileInfo"/> entries.</returns> private static IReadOnlyList <IGorgonPhysicalFileInfo> EnumerateFiles(string physicalLocation, IGorgonVirtualDirectory mountPoint) { var directoryInfo = new DirectoryInfo(physicalLocation); IEnumerable <FileInfo> files = directoryInfo.GetFiles("*", SearchOption.AllDirectories) .Where(item => (item.Attributes & FileAttributes.Hidden) != FileAttributes.Hidden && (item.Attributes & FileAttributes.System) != FileAttributes.System && (item.Attributes & FileAttributes.Compressed) != FileAttributes.Compressed && (item.Attributes & FileAttributes.Encrypted) != FileAttributes.Encrypted && (item.Attributes & FileAttributes.Device) != FileAttributes.Device); return(files.Select(file => new PhysicalFileInfo(file, MapToVirtualPath(file.DirectoryName.FormatDirectory(Path.DirectorySeparatorChar) + file.Name, physicalLocation, mountPoint.FullPath))) .Cast <IGorgonPhysicalFileInfo>() .ToArray()); }
/// <summary> /// Function to enumerate directories from the file system. /// </summary> /// <param name="physicalLocation">The physical file system location to enumerate.</param> /// <param name="mountPoint">The mount point to remap the directory paths to.</param> /// <returns>A read only list of <see cref="string"/> values representing the mapped directory entries.</returns> private static IReadOnlyList <string> EnumerateDirectories(string physicalLocation, IGorgonVirtualDirectory mountPoint) { var directoryInfo = new DirectoryInfo(physicalLocation); IEnumerable <DirectoryInfo> directories = directoryInfo.GetDirectories("*", SearchOption.AllDirectories) .Where( item => (item.Attributes & FileAttributes.Hidden) != FileAttributes.Hidden && (item.Attributes & FileAttributes.System) != FileAttributes.System); return(directories.Select(item => MapToVirtualPath(item.FullName.FormatDirectory(Path.DirectorySeparatorChar), physicalLocation, mountPoint.FullPath)) .ToArray()); }
/// <summary> /// Function to locate specific types of editor content files contained within the file system. /// </summary> /// <param name="fileSystem">The file system containing the content items.</param> /// <param name="path">Path to the directory containing the files to evaluate.</param> /// <param name="contentType">The type of content to locate.</param> /// <param name="searchMask">[Optional] A mask for filtering the search by file name.</param> /// <param name="recursive">[Optional] <b>true</b> to recursively search, <b>false</b> to only search the specified path.</param> /// <returns>A list of <see cref="IGorgonVirtualFile"/> items for each content item.</returns> /// <remarks> /// <para> /// Applications can use this to locate specific types of content files within a file system. If <b>null</b> is passed to the <paramref name="contentType"/>, then all content files with /// no content type associated will be returned. /// </para> /// </remarks> public static IReadOnlyList <IGorgonVirtualFile> GetContentItems(this IGorgonFileSystem fileSystem, string path, string contentType, string searchMask = "*", bool recursive = false) { var result = new List <IGorgonVirtualFile>(); if (fileSystem == null) { throw new ArgumentNullException(nameof(fileSystem)); } if (path == null) { throw new ArgumentNullException(nameof(path)); } if (string.IsNullOrWhiteSpace(path)) { throw new ArgumentEmptyException(nameof(path)); } IProjectMetadata metaData = fileSystem.GetMetadata(); if (metaData == null) { return(result); } // We passed in a file name, extract it for a seach pattern. if (string.IsNullOrWhiteSpace(searchMask)) { searchMask = "*"; } path = path.FormatDirectory('/'); IGorgonVirtualDirectory directory = fileSystem.GetDirectory(path); if (directory == null) { throw new DirectoryNotFoundException(); } IEnumerable <IGorgonVirtualFile> files = fileSystem.FindFiles(directory.FullPath, searchMask, recursive); // Handle the unassociated files. if (string.IsNullOrWhiteSpace(contentType)) { foreach (IGorgonVirtualFile file in files) { if (!metaData.ProjectItems.TryGetValue(file.FullPath, out ProjectItemMetadata metaDataItem)) { continue; } IReadOnlyDictionary <string, string> attributes = metaDataItem.Attributes; if ((attributes != null) && (attributes.Count > 0) && (attributes.TryGetValue(CommonEditorConstants.ContentTypeAttr, out string type))) { continue; } result.Add(file); } return(result); } // Filter the list based on the content type we ask for. foreach (IGorgonVirtualFile file in files) { if (!metaData.ProjectItems.TryGetValue(file.FullPath, out ProjectItemMetadata metaDataItem)) { continue; } IReadOnlyDictionary <string, string> attributes = metaDataItem.Attributes; if ((attributes == null) || (attributes.Count == 0) || (!attributes.TryGetValue(CommonEditorConstants.ContentTypeAttr, out string type)) || (!string.Equals(contentType, type, StringComparison.OrdinalIgnoreCase))) { continue; } result.Add(file); } return(result); }
/// <summary> /// Function to enumerate the files and directories from a physical location and map it to a virtual location. /// </summary> /// <param name="physicalLocation">The physical location containing files and directories to enumerate.</param> /// <param name="mountPoint">A <see cref="IGorgonVirtualDirectory"/> that the directories and files from the physical file system will be mounted into.</param> /// <returns>A <see cref="GorgonPhysicalFileSystemData"/> object containing information about the directories and files contained within the physical file system.</returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="physicalLocation"/>, or the <paramref name="mountPoint"/> parameters are <b>null</b>.</exception> /// <exception cref="ArgumentEmptyException">Thrown when the <paramref name="physicalLocation"/> parameter is empty.</exception> /// <remarks> /// <para> /// This will return a <see cref="GorgonPhysicalFileSystemData"/> representing the paths to directories and <see cref="IGorgonPhysicalFileInfo"/> objects under the virtual file system. Each file /// system file and directory is mapped from its <paramref name="physicalLocation"/> on the physical file system to a <paramref name="mountPoint"/> on the virtual file system. For example, if the /// mount point is set to <c>/MyMount/</c>, and the physical location of a file is <c>c:\SourceFileSystem\MyDirectory\MyTextFile.txt</c>, then the returned value should be /// <c>/MyMount/MyDirectory/MyTextFile.txt</c>. /// </para> /// <para> /// Implementors of a <see cref="GorgonFileSystemProvider"/> plug in can override this method to read the list of files from another type of file system, like a Zip file. /// </para> /// <para> /// Implementors of a <see cref="GorgonFileSystemProvider"/> should override this method to read the list of directories and files from another type of file system, like a Zip file. /// The default functionality will only enumerate directories and files from the operating system file system. /// </para> /// </remarks> protected override GorgonPhysicalFileSystemData OnEnumerate(string physicalLocation, IGorgonVirtualDirectory mountPoint) { var directories = new List <string>(); var files = new List <IGorgonPhysicalFileInfo>(); using (var zipStream = new ZipInputStream(File.Open(physicalLocation, FileMode.Open, FileAccess.Read, FileShare.Read))) { ZipEntry entry; while ((entry = zipStream.GetNextEntry()) != null) { if (!entry.IsDirectory) { string directoryName = Path.GetDirectoryName(entry.Name).FormatDirectory('/'); directoryName = mountPoint.FullPath + directoryName; if (string.IsNullOrWhiteSpace(directoryName)) { directoryName = "/"; } if (!directories.Contains(directoryName)) { directories.Add(directoryName); } files.Add(new ZipPhysicalFileInfo(entry, physicalLocation, mountPoint)); } else { directories.Add((mountPoint.FullPath + entry.Name).FormatDirectory('/')); } } } return(new GorgonPhysicalFileSystemData(directories, files)); }
/// <summary> /// The main entry point for the application. /// </summary> private static void Main() { _log = new GorgonLog("FolderFileSystem", "Tape_Worm"); _log.LogStart(); try { Console.WindowHeight = 26.Max(Console.WindowHeight); Console.BufferHeight = Console.WindowHeight; // Create a new file system. _fileSystem = new GorgonFileSystem(_log); // Set the following directory as root on the virtual file system. // To mount a directory we need to put in the trailing slash. // // If we wanted to, we could mount a directory as a sub directory of // the root of the virtual file system. For example, mounting the // directory D:\Dir with Mount(@"D:\Dir", "/VFSDir"); would mount the // contents of the D:\Dir directory under /VFSDir. // // It's also important to point out that the old Gorgon "file system" // would load files from the system into memory when mounting a // directory. While this version only loads directory and file // information when mounting. This is considerably more efficient. string physicalPath = GetResourcePath(@"FolderSystem\"); _fileSystem.Mount(physicalPath); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("This example will mount a physical file system directory as the root of a"); Console.WriteLine("virtual file system. The virtual file system is capable of mounting various"); Console.WriteLine("types of data such as a zip file, a file system folder, etc... as the root or a"); Console.WriteLine("sub directory. You can even mount a zip file as the root, and a physical file"); Console.WriteLine("system directory as a virtual sub directory in the same virtual file system and"); Console.WriteLine("access them as a single unified file system."); Console.Write("\nMounted: "); Console.ForegroundColor = ConsoleColor.Cyan; Console.Write("'{0}'", physicalPath.Ellipses(Console.WindowWidth - 20, true)); Console.ForegroundColor = ConsoleColor.White; Console.Write(" as "); Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine("'/'\n"); Console.ForegroundColor = ConsoleColor.White; // Get a count of all sub directories and files under the root directory. IGorgonVirtualDirectory[] directoryList = _fileSystem.FindDirectories("*").ToArray(); // Display directories. Console.WriteLine("Virtual file system contents:"); for (int i = -1; i < directoryList.Length; i++) { IGorgonVirtualDirectory directory = _fileSystem.RootDirectory; // Go into the sub directories under root. if (i > -1) { directory = directoryList[i]; } Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine("{0}", directory.FullPath); Console.ForegroundColor = ConsoleColor.Yellow; foreach (IGorgonVirtualFile file in directory.Files) { Console.Write(" {0}", file.Name); // Align the size to the same place. Console.CursorLeft = 65; Console.WriteLine("{0}", file.Size.FormatMemory()); } } Console.ResetColor(); Console.WriteLine("\nPress any key to close."); Console.ReadKey(); } catch (Exception ex) { ex.Catch(_ => { Console.Clear(); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Exception:\n{0}\n\nStack Trace:{1}", _.Message, _.StackTrace); Console.ResetColor(); #if DEBUG Console.ReadKey(); #endif }, _log); } finally { _log.LogEnd(); } }
/// <summary> /// Function to enumerate the files and directories from a physical location and map it to a virtual location. /// </summary> /// <param name="physicalLocation">The physical location containing files and directories to enumerate.</param> /// <param name="mountPoint">A <see cref="IGorgonVirtualDirectory"/> that the directories and files from the physical file system will be mounted into.</param> /// <returns>A <see cref="GorgonPhysicalFileSystemData"/> object containing information about the directories and files contained within the physical file system.</returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="physicalLocation"/>, or the <paramref name="mountPoint"/> parameters are <b>null</b>.</exception> /// <exception cref="ArgumentEmptyException">Thrown when the <paramref name="physicalLocation"/> parameter is empty.</exception> /// <remarks> /// Since this provider holds data in its own block of memory, there's nothing to enumerate when the provider is loaded. Thus, this will always return empty data. /// </remarks> protected virtual GorgonPhysicalFileSystemData OnEnumerate(string physicalLocation, IGorgonVirtualDirectory mountPoint) => new GorgonPhysicalFileSystemData(FileData.GetDirectories(), FileData.GetFileInfos() .Select(item => new PhysicalFileInfo(Prefix + "::" + item.FullPath, item.CreateDate, item.Size, item.FullPath, 0, item.LastModified)) .ToArray());
/// <summary> /// Function to enumerate the available files stored in the packed file. /// </summary> /// <param name="index">The XML file containing the index of files and directories.</param> /// <param name="offset">The offset into the physical file.</param> /// <param name="physicalLocation">Physical location of the packed file.</param> /// <param name="mountPoint">The mount point to map into.</param> /// <returns>A read only list of <see cref="IGorgonPhysicalFileInfo"/> objects mapped to the virtual file system.</returns> private static IReadOnlyList <IGorgonPhysicalFileInfo> EnumerateFiles(XDocument index, long offset, string physicalLocation, IGorgonVirtualDirectory mountPoint) { IEnumerable <XElement> files = index.Descendants("File"); var result = new List <IGorgonPhysicalFileInfo>(); foreach (XElement file in files) { XElement fileNameNode = file.Element("Filename"); XElement fileExtensionNode = file.Element("Extension"); XElement fileOffsetNode = file.Element("Offset"); XElement fileCompressedSizeNode = file.Element("CompressedSize"); XElement fileSizeNode = file.Element("Size"); XElement fileDateNode = file.Element("FileDate"); XElement fileLastModNode = file.Element("LastModDate"); string parentDirectoryPath = file.Parent?.Attribute("FullPath")?.Value; // We need these nodes. if ((fileNameNode == null) || (fileOffsetNode == null) || (fileSizeNode == null) || (fileDateNode == null) || ((string.IsNullOrWhiteSpace(fileNameNode.Value)) && (string.IsNullOrWhiteSpace(fileExtensionNode.Value))) || (string.IsNullOrWhiteSpace(fileDateNode.Value)) || (string.IsNullOrWhiteSpace(parentDirectoryPath))) { throw new FileLoadException(Resources.GORFS_GORPACK_ERR_FILEINDEX_CORRUPT); } parentDirectoryPath = (mountPoint.FullPath + parentDirectoryPath).FormatDirectory('/'); string fileName = fileNameNode.Value; long? compressedSize = null; // If we don't have a creation date, then don't allow the file to be processed. if (!DateTime.TryParse(fileDateNode.Value, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime fileDate)) { throw new FileLoadException(Resources.GORFS_GORPACK_ERR_FILEINDEX_CORRUPT); } if ((fileLastModNode == null) || (!DateTime.TryParse(fileLastModNode.Value, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime lastModDate))) { lastModDate = fileDate; } if (!long.TryParse(fileOffsetNode.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out long fileOffset)) { throw new FileLoadException(Resources.GORFS_GORPACK_ERR_FILEINDEX_CORRUPT); } fileOffset += offset; if (!long.TryParse(fileSizeNode.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out long fileSize)) { throw new FileLoadException(Resources.GORFS_GORPACK_ERR_FILEINDEX_CORRUPT); } string fileExtension = fileExtensionNode.Value ?? string.Empty; if (!string.IsNullOrWhiteSpace(fileName)) { fileName += fileExtension; } else { fileName = fileExtension; } // If the file is compressed, then add it to a special list. if (fileCompressedSizeNode != null) { if (!long.TryParse(fileCompressedSizeNode.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out long compressed)) { throw new FileLoadException(Resources.GORFS_GORPACK_ERR_FILEINDEX_CORRUPT); } if (compressed > 0) { compressedSize = compressed; } } result.Add(new GorPackPhysicalFileInfo(physicalLocation + "::/" + parentDirectoryPath + fileName, fileName, fileDate, lastModDate, fileOffset, fileSize, parentDirectoryPath + fileName, compressedSize)); } return(result); }
/// <summary> /// The main entry point for the application. /// </summary> private static void Main() { _log = new GorgonLog("ZipFileSystem", "Tape_Worm"); _log.LogStart(); // Create the plugin assembly cache. _pluginAssemblies = new GorgonMefPlugInCache(_log); // Create the plugin service. _pluginService = new GorgonMefPlugInService(_pluginAssemblies); try { Console.WindowHeight = 28; Console.BufferHeight = Console.WindowHeight; Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("This example will mount a zip file as the root of a virtual file system. The"); Console.WriteLine("virtual file system is capable of mounting various types of data such as a zip,"); Console.WriteLine("a file system folder, etc... as the root or a sub directory. You can even"); Console.WriteLine("mount a zip file as the root, and a physical file system directory as a virtual"); Console.WriteLine("sub directory in the same virtual file system and access them as a single"); Console.WriteLine("unified file system."); // Unlike the folder file system example, we need to load // a provider to handle zip files before trying to mount // one. if (!LoadZipProviderPlugIn()) { return; } // Set the following zip file as root on the virtual file system. // // If we wanted to, we could mount a zip file as a sub directory of // the root of the virtual file system. For example, mounting the // directory D:\Dir\zipFile.zip with Mount(@"D:\Dir", "/VFSDir"); would mount // the contents of the D:\Dir\zipFile.zip directory under /VFSDir. // // It's also important to point out that the old Gorgon "file system" // would load files from the system into memory when mounting a // directory. While this version only loads directory and file // information when mounting. This is considerably more efficient. string physicalPath = GetResourcePath(@"FileSystem.zip"); _fileSystem.Mount(physicalPath); Console.Write("\nMounted: "); Console.ForegroundColor = ConsoleColor.Cyan; Console.Write("'{0}'", physicalPath.Ellipses(Console.WindowWidth - 20, true)); Console.ForegroundColor = ConsoleColor.White; Console.Write(" as "); Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine("'/'\n"); Console.ForegroundColor = ConsoleColor.White; // Get a count of all sub directories and files under the root directory. IGorgonVirtualDirectory[] directoryList = _fileSystem.FindDirectories("*").ToArray(); // Display directories. Console.WriteLine("Virtual file system contents:"); for (int i = -1; i < directoryList.Length; i++) { IGorgonVirtualDirectory directory = _fileSystem.RootDirectory; // Go into the sub directories under root. if (i > -1) { directory = directoryList[i]; } Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine("{0}", directory.FullPath); Console.ForegroundColor = ConsoleColor.Yellow; foreach (IGorgonVirtualFile file in directory.Files) { Console.Write(" {0}", file.Name); // Align the size to the same place. Console.CursorLeft = 65; Console.WriteLine("{0}", file.Size.FormatMemory()); } } Console.ResetColor(); Console.WriteLine("\nPress any key to close."); Console.ReadKey(); } catch (Exception ex) { ex.Catch(_ => { Console.Clear(); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Exception:\n{0}\n\nStack Trace:{1}", _.Message, _.StackTrace); Console.ResetColor(); #if DEBUG Console.ReadKey(); #endif }); } finally { // Always dispose the cache to clean up the temporary app domain it creates. _pluginAssemblies.Dispose(); _log.LogEnd(); } }
/// <summary> /// Function to enumerate the files and directories from a physical location and map it to a virtual location. /// </summary> /// <param name="physicalLocation">The physical location containing files and directories to enumerate.</param> /// <param name="mountPoint">A <see cref="IGorgonVirtualDirectory"/> that the directories and files from the physical file system will be mounted into.</param> /// <returns>A <see cref="GorgonPhysicalFileSystemData"/> object containing information about the directories and files contained within the physical file system.</returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="physicalLocation"/>, or the <paramref name="mountPoint"/> parameters are <b>null</b>.</exception> /// <exception cref="ArgumentEmptyException">Thrown when the <paramref name="physicalLocation"/> parameter is empty.</exception> /// <remarks> /// <para> /// This will return a <see cref="GorgonPhysicalFileSystemData"/> representing the paths to directories and <see cref="IGorgonPhysicalFileInfo"/> objects under the virtual file system. Each file /// system file and directory is mapped from its <paramref name="physicalLocation"/> on the physical file system to a <paramref name="mountPoint"/> on the virtual file system. For example, if the /// mount point is set to <c>/MyMount/</c>, and the physical location of a file is <c>c:\SourceFileSystem\MyDirectory\MyTextFile.txt</c>, then the returned value should be /// <c>/MyMount/MyDirectory/MyTextFile.txt</c>. /// </para> /// <para> /// Implementors of a <see cref="GorgonFileSystemProvider"/> plug in can override this method to read the list of files from another type of file system, like a Zip file. /// </para> /// <para> /// Implementors of a <see cref="GorgonFileSystemProvider"/> should override this method to read the list of directories and files from another type of file system, like a Zip file. /// The default functionality will only enumerate directories and files from the operating system file system. /// </para> /// </remarks> protected override GorgonPhysicalFileSystemData OnEnumerate(string physicalLocation, IGorgonVirtualDirectory mountPoint) { using (var reader = new GorgonBinaryReader(File.Open(physicalLocation, FileMode.Open, FileAccess.Read, FileShare.Read))) { // Skip the header. reader.ReadString(); int indexLength = reader.ReadInt32(); byte[] indexData = Decompress(reader.ReadBytes(indexLength)); string xmlData = Encoding.UTF8.GetString(indexData); var index = XDocument.Parse(xmlData, LoadOptions.None); return(new GorgonPhysicalFileSystemData(EnumerateDirectories(index, mountPoint), EnumerateFiles(index, reader.BaseStream.Position, physicalLocation, mountPoint))); } }