protected override Result RenameDirectoryImpl(string oldPath, string newPath)
        {
            oldPath = PathTools.Normalize(oldPath);
            newPath = PathTools.Normalize(newPath);

            if (IsConcatenationFile(oldPath))
            {
                return(ResultFs.PathNotFound.Log());
            }

            return(BaseFileSystem.RenameDirectory(oldPath, newPath));
        }
        protected override Result OpenFileImpl(out IFile file, U8Span path, OpenMode mode)
        {
            path = PathTools.Normalize(path.ToString()).TrimStart('/').ToU8Span();

            if (!FileDict.TryGetValue(path.ToString(), out PartitionFileEntry entry))
            {
                ThrowHelper.ThrowResult(ResultFs.PathNotFound.Value);
            }

            file = OpenFile(entry, mode);
            return(Result.Success);
        }
        protected override Result GetEntryTypeImpl(out DirectoryEntryType entryType, string path)
        {
            path = PathTools.Normalize(path);

            if (IsConcatenationFile(path))
            {
                entryType = DirectoryEntryType.File;
                return(Result.Success);
            }

            return(BaseFileSystem.GetEntryType(out entryType, path));
        }
Beispiel #4
0
        protected override Result DeleteFileImpl(string path)
        {
            string localPath = ResolveLocalPath(PathTools.Normalize(path));

            Result rc = GetFileInfo(out FileInfo file, localPath);

            if (rc.IsFailure())
            {
                return(rc);
            }

            return(DeleteFileInternal(file));
        }
Beispiel #5
0
        protected override Result CreateDirectoryImpl(string path)
        {
            path = PathTools.Normalize(path);
            string parent = PathTools.GetParentDirectory(path);

            if (IsConcatenationFile(parent))
            {
                // Cannot create a directory inside of a concatenation file
                return(ResultFs.PathNotFound.Log());
            }

            return(BaseFileSystem.CreateDirectory(path));
        }
Beispiel #6
0
        protected override Result DeleteDirectoryRecursivelyImpl(string path)
        {
            string localPath = ResolveLocalPath(PathTools.Normalize(path));

            Result rc = GetDirInfo(out DirectoryInfo dir, localPath);

            if (rc.IsFailure())
            {
                return(rc);
            }

            return(DeleteDirectoryInternal(dir, true));
        }
Beispiel #7
0
        protected override Result RenameFileImpl(string oldPath, string newPath)
        {
            oldPath = PathTools.Normalize(oldPath);
            newPath = PathTools.Normalize(newPath);

            if (IsConcatenationFile(oldPath))
            {
                return(BaseFileSystem.RenameDirectory(oldPath, newPath));
            }
            else
            {
                return(BaseFileSystem.RenameFile(oldPath, newPath));
            }
        }
        public static Result CopyDirectory(this IFileSystem sourceFs, IFileSystem destFs, string sourcePath, string destPath,
                                           IProgressReport logger = null, CreateFileOptions options = CreateFileOptions.None)
        {
            Result rc;

            foreach (DirectoryEntryEx entry in sourceFs.EnumerateEntries(sourcePath, "*", SearchOptions.Default))
            {
                string subSrcPath = PathTools.Normalize(PathTools.Combine(sourcePath, entry.Name));
                string subDstPath = PathTools.Normalize(PathTools.Combine(destPath, entry.Name));

                if (entry.Type == DirectoryEntryType.Directory)
                {
                    destFs.EnsureDirectoryExists(subDstPath);

                    rc = sourceFs.CopyDirectory(destFs, subSrcPath, subDstPath, logger, options);
                    if (rc.IsFailure())
                    {
                        return(rc);
                    }
                }

                if (entry.Type == DirectoryEntryType.File)
                {
                    destFs.CreateOrOverwriteFile(subDstPath, entry.Size, options);

                    rc = sourceFs.OpenFile(out IFile srcFile, subSrcPath.ToU8Span(), OpenMode.Read);
                    if (rc.IsFailure())
                    {
                        return(rc);
                    }

                    using (srcFile)
                    {
                        rc = destFs.OpenFile(out IFile dstFile, subDstPath.ToU8Span(), OpenMode.Write | OpenMode.AllowAppend);
                        if (rc.IsFailure())
                        {
                            return(rc);
                        }

                        using (dstFile)
                        {
                            logger?.LogMessage(subSrcPath);
                            srcFile.CopyTo(dstFile, logger);
                        }
                    }
                }
            }

            return(Result.Success);
        }
Beispiel #9
0
        protected override Result GetFileSizeImpl(out long fileSize, string path)
        {
            fileSize = default;
            string localPath = ResolveLocalPath(PathTools.Normalize(path));

            Result rc = GetFileInfo(out FileInfo info, localPath);

            if (rc.IsFailure())
            {
                return(rc);
            }

            return(GetSizeInternal(out fileSize, info));
        }
Beispiel #10
0
        public PartitionDirectory(PartitionFileSystem fs, string path, OpenDirectoryMode mode)
        {
            path = PathTools.Normalize(path);

            if (path != "/")
            {
                throw new DirectoryNotFoundException();
            }

            ParentFileSystem = fs;
            Mode             = mode;

            CurrentIndex = 0;
        }
Beispiel #11
0
        protected override Result OpenDirectoryImpl(out IDirectory directory, string path, OpenDirectoryMode mode)
        {
            directory = default;
            path      = PathTools.Normalize(path);

            Result rc = BaseFileSystem.OpenDirectory(out IDirectory baseDir, path, mode);

            if (rc.IsFailure())
            {
                return(rc);
            }

            directory = new AesXtsDirectory(BaseFileSystem, baseDir, path, mode);
            return(Result.Success);
        }
Beispiel #12
0
        protected override Result QueryEntryImpl(Span <byte> outBuffer, ReadOnlySpan <byte> inBuffer, QueryId queryId, string path)
        {
            path = PathTools.Normalize(path);

            foreach (IFileSystem fs in Sources)
            {
                Result getEntryResult = fs.GetEntryType(out DirectoryEntryType type, path);

                if (getEntryResult.IsSuccess() && type != DirectoryEntryType.NotFound)
                {
                    return(fs.QueryEntry(outBuffer, inBuffer, queryId, path));
                }
            }

            return(ResultFs.PathNotFound.Log());
        }
Beispiel #13
0
        protected override Result CreateFileImpl(string path, long size, CreateFileOptions options)
        {
            path = PathTools.Normalize(path);

            CreateFileOptions newOptions = options & ~CreateFileOptions.CreateConcatenationFile;

            if (!options.HasFlag(CreateFileOptions.CreateConcatenationFile))
            {
                return(BaseFileSystem.CreateFile(path, size, newOptions));
            }

            // A concatenation file directory can't contain normal files
            string parentDir = PathTools.GetParentDirectory(path);

            if (IsConcatenationFile(parentDir))
            {
                // Cannot create a file inside of a concatenation file
                return(ResultFs.PathNotFound.Log());
            }

            Result rc = BaseFileSystem.CreateDirectory(path, NxFileAttributes.Archive);

            if (rc.IsFailure())
            {
                return(rc);
            }

            long remaining = size;

            for (int i = 0; remaining > 0; i++)
            {
                long   fileSize = Math.Min(SubFileSize, remaining);
                string fileName = GetSubFilePath(path, i);

                Result createSubFileResult = BaseFileSystem.CreateFile(fileName, fileSize, CreateFileOptions.None);

                if (createSubFileResult.IsFailure())
                {
                    BaseFileSystem.DeleteDirectoryRecursively(path);
                    return(createSubFileResult);
                }

                remaining -= fileSize;
            }

            return(Result.Success);
        }
Beispiel #14
0
        protected override Result GetFileTimeStampRawImpl(out FileTimeStampRaw timeStamp, string path)
        {
            path = PathTools.Normalize(path);

            foreach (IFileSystem fs in Sources)
            {
                Result getEntryResult = fs.GetEntryType(out DirectoryEntryType type, path);

                if (getEntryResult.IsSuccess() && type != DirectoryEntryType.NotFound)
                {
                    return(fs.GetFileTimeStampRaw(out timeStamp, path));
                }
            }

            timeStamp = default;
            return(ResultFs.PathNotFound.Log());
        }
Beispiel #15
0
        protected override Result OpenFileImpl(out IFile file, string path, OpenMode mode)
        {
            file = default;
            path = PathTools.Normalize(path);

            Result rc = BaseFileSystem.OpenFile(out IFile baseFile, path, mode | OpenMode.Read);

            if (rc.IsFailure())
            {
                return(rc);
            }

            var xtsFile = new AesXtsFile(mode, baseFile, path, KekSource, ValidationKey, BlockSize);

            file = xtsFile;
            return(Result.Success);
        }
Beispiel #16
0
        public static Result EnsureDirectoryExists(this IFileSystem fs, string path)
        {
            path = PathTools.Normalize(path);
            if (fs.DirectoryExists(path))
            {
                return(Result.Success);
            }

            // Find the first subdirectory in the chain that doesn't exist
            int i;

            for (i = path.Length - 1; i > 0; i--)
            {
                if (path[i] == '/')
                {
                    string subPath = path.Substring(0, i);

                    if (fs.DirectoryExists(subPath))
                    {
                        break;
                    }
                }
            }

            // path[i] will be a '/', so skip that character
            i++;

            // loop until `path.Length - 1` so CreateDirectory won't be called multiple
            // times on path if the last character in the path is a '/'
            for (; i < path.Length - 1; i++)
            {
                if (path[i] == '/')
                {
                    string subPath = path.Substring(0, i);

                    Result rc = fs.CreateDirectory(subPath.ToU8Span());
                    if (rc.IsFailure())
                    {
                        return(rc);
                    }
                }
            }

            return(fs.CreateDirectory(path.ToU8Span()));
        }
Beispiel #17
0
        protected override Result GetEntryTypeImpl(out DirectoryEntryType entryType, string path)
        {
            path = PathTools.Normalize(path);

            foreach (IFileSystem fs in Sources)
            {
                Result getEntryResult = fs.GetEntryType(out DirectoryEntryType type, path);

                if (getEntryResult.IsSuccess() && type != DirectoryEntryType.NotFound)
                {
                    entryType = type;
                    return(Result.Success);
                }
            }

            entryType = DirectoryEntryType.NotFound;
            return(ResultFs.PathNotFound.Log());
        }
Beispiel #18
0
        protected override Result GetEntryTypeImpl(out DirectoryEntryType entryType, string path)
        {
            entryType = DirectoryEntryType.NotFound;
            path      = PathTools.Normalize(path);

            if (path == "/")
            {
                entryType = DirectoryEntryType.Directory;
                return(Result.Success);
            }

            if (FileDict.ContainsKey(path.TrimStart('/')))
            {
                entryType = DirectoryEntryType.File;
                return(Result.Success);
            }

            return(ResultFs.PathNotFound.Log());
        }
Beispiel #19
0
        protected override Result OpenDirectoryImpl(out IDirectory directory, string path, OpenDirectoryMode mode)
        {
            directory = default;
            path      = PathTools.Normalize(path);

            if (IsConcatenationFile(path))
            {
                return(ResultFs.PathNotFound.Log());
            }

            Result rc = BaseFileSystem.OpenDirectory(out IDirectory parentDir, path, OpenDirectoryMode.All);

            if (rc.IsFailure())
            {
                return(rc);
            }

            directory = new ConcatenationDirectory(this, BaseFileSystem, parentDir, mode, path);
            return(Result.Success);
        }
Beispiel #20
0
        protected override Result GetFileAttributesImpl(string path, out NxFileAttributes attributes)
        {
            attributes = default;

            string localPath = ResolveLocalPath(PathTools.Normalize(path));

            Result rc = GetFileInfo(out FileInfo info, localPath);

            if (rc.IsFailure())
            {
                return(rc);
            }

            if (info.Attributes == (FileAttributes)(-1))
            {
                attributes = default;
                return(ResultFs.PathNotFound.Log());
            }

            attributes = info.Attributes.ToNxAttributes();
            return(Result.Success);
        }
Beispiel #21
0
        protected override Result DeleteFileImpl(string path)
        {
            path = PathTools.Normalize(path);

            if (!IsConcatenationFile(path))
            {
                return(BaseFileSystem.DeleteFile(path));
            }

            int count = GetSubFileCount(path);

            for (int i = 0; i < count; i++)
            {
                Result rc = BaseFileSystem.DeleteFile(GetSubFilePath(path, i));
                if (rc.IsFailure())
                {
                    return(rc);
                }
            }

            return(BaseFileSystem.DeleteDirectory(path));
        }
Beispiel #22
0
        protected override Result OpenFileImpl(out IFile file, string path, OpenMode mode)
        {
            file = default;
            string fullPath = GetFullPath(PathTools.Normalize(path));

            lock (Locker)
            {
                Result rc = BaseFs.OpenFile(out IFile baseFile, fullPath, mode);
                if (rc.IsFailure())
                {
                    return(rc);
                }

                file = new DirectorySaveDataFile(this, baseFile, mode);

                if (mode.HasFlag(OpenMode.Write))
                {
                    OpenWritableFileCount++;
                }

                return(Result.Success);
            }
        }
Beispiel #23
0
        protected override Result CreateDirectoryImpl(string path, NxFileAttributes archiveAttribute)
        {
            string localPath = ResolveLocalPath(PathTools.Normalize(path));

            Result rc = GetDirInfo(out DirectoryInfo dir, localPath);

            if (rc.IsFailure())
            {
                return(rc);
            }

            if (dir.Exists)
            {
                return(ResultFs.PathAlreadyExists.Log());
            }

            if (dir.Parent?.Exists != true)
            {
                return(ResultFs.PathNotFound.Log());
            }

            return(CreateDirInternal(dir, archiveAttribute));
        }
Beispiel #24
0
        protected override Result GetFileTimeStampRawImpl(out FileTimeStampRaw timeStamp, string path)
        {
            timeStamp = default;
            string localPath = ResolveLocalPath(PathTools.Normalize(path));

            Result rc = GetFileInfo(out FileInfo file, localPath);

            if (rc.IsFailure())
            {
                return(rc);
            }

            if (!file.Exists)
            {
                return(ResultFs.PathNotFound.Log());
            }

            timeStamp.Created  = new DateTimeOffset(File.GetCreationTime(localPath)).ToUnixTimeSeconds();
            timeStamp.Accessed = new DateTimeOffset(File.GetLastAccessTime(localPath)).ToUnixTimeSeconds();
            timeStamp.Modified = new DateTimeOffset(File.GetLastWriteTime(localPath)).ToUnixTimeSeconds();

            return(Result.Success);
        }
Beispiel #25
0
        protected override Result RenameDirectoryImpl(string oldPath, string newPath)
        {
            oldPath = PathTools.Normalize(oldPath);
            newPath = PathTools.Normalize(newPath);

            // todo: Return proper result codes

            // Official code procedure:
            // Make sure all file headers can be decrypted
            // Rename directory to the new path
            // Reencrypt file headers with new path
            // If no errors, return
            // Reencrypt any modified file headers with the old path
            // Rename directory to the old path

            Result rc = BaseFileSystem.RenameDirectory(oldPath, newPath);

            if (rc.IsFailure())
            {
                return(rc);
            }

            try
            {
                RenameDirectoryImpl(oldPath, newPath, false);
            }
            catch (Exception)
            {
                RenameDirectoryImpl(oldPath, newPath, true);
                BaseFileSystem.RenameDirectory(oldPath, newPath);

                throw;
            }

            return(Result.Success);
        }
Beispiel #26
0
        protected override Result CleanDirectoryRecursivelyImpl(string path)
        {
            string localPath = ResolveLocalPath(PathTools.Normalize(path));

            foreach (string file in Directory.EnumerateFiles(localPath))
            {
                Result rc = GetFileInfo(out FileInfo fileInfo, file);
                if (rc.IsFailure())
                {
                    return(rc);
                }

                rc = DeleteFileInternal(fileInfo);
                if (rc.IsFailure())
                {
                    return(rc);
                }
            }

            foreach (string dir in Directory.EnumerateDirectories(localPath))
            {
                Result rc = GetDirInfo(out DirectoryInfo dirInfo, dir);
                if (rc.IsFailure())
                {
                    return(rc);
                }

                rc = DeleteDirectoryInternal(dirInfo, true);
                if (rc.IsFailure())
                {
                    return(rc);
                }
            }

            return(Result.Success);
        }
Beispiel #27
0
        protected override Result GetEntryTypeImpl(out DirectoryEntryType entryType, string path)
        {
            string fullPath = ResolveFullPath(PathTools.Normalize(path));

            return(ParentFileSystem.GetEntryType(out entryType, fullPath));
        }
Beispiel #28
0
        protected override Result OpenFileImpl(out IFile file, string path, OpenMode mode)
        {
            string fullPath = ResolveFullPath(PathTools.Normalize(path));

            return(ParentFileSystem.OpenFile(out file, fullPath, mode));
        }
Beispiel #29
0
        protected override Result OpenDirectoryImpl(out IDirectory directory, string path, OpenDirectoryMode mode)
        {
            string fullPath = ResolveFullPath(PathTools.Normalize(path));

            return(ParentFileSystem.OpenDirectory(out directory, fullPath, mode));
        }
Beispiel #30
0
        protected override Result DeleteFileImpl(string path)
        {
            string fullPath = ResolveFullPath(PathTools.Normalize(path));

            return(ParentFileSystem.DeleteFile(fullPath));
        }