コード例 #1
0
        public static Result VerifyPath(U8Span path, int maxPathLength, int maxNameLength)
        {
            Debug.Assert(!path.IsNull());

            int nameLength = 0;

            for (int i = 0; i < path.Length && i <= maxPathLength && nameLength <= maxNameLength; i++)
            {
                byte c = path[i];

                if (IsNullTerminator(c))
                {
                    return(Result.Success);
                }

                // todo: Compare path based on their Unicode code points

                if (c == ':' || c == '*' || c == '?' || c == '<' || c == '>' || c == '|')
                {
                    return(ResultFs.InvalidCharacter.Log());
                }

                nameLength++;
                if (c == '\\' || c == '/')
                {
                    nameLength = 0;
                }
            }

            return(ResultFs.TooLongPath.Log());
        }
コード例 #2
0
        internal static Result FindFileSystem(this FileSystemClientImpl fs, out FileSystemAccessor fileSystem,
                                              out U8Span subPath, U8Span path)
        {
            UnsafeHelpers.SkipParamInit(out fileSystem);
            subPath = default;

            if (path.IsNull())
            {
                return(ResultFs.NullptrArgument.Log());
            }

            int hostMountNameLen = StringUtils.GetLength(CommonPaths.HostRootFileSystemMountName);

            if (StringUtils.Compare(path, CommonPaths.HostRootFileSystemMountName, hostMountNameLen) == 0)
            {
                return(ResultFs.NotMounted.Log());
            }

            Result rc = GetMountNameAndSubPath(out MountName mountName, out subPath, path);

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

            return(fs.Find(out fileSystem, new U8Span(mountName.Name)));
        }
コード例 #3
0
        internal Result FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, U8Span path)
        {
            fileSystem = default;
            subPath    = default;

            if (path.IsNull())
            {
                return(ResultFs.NullptrArgument.Log());
            }

            int hostMountNameLen = StringUtils.GetLength(CommonMountNames.HostRootFileSystemMountName);

            if (StringUtils.Compare(path, CommonMountNames.HostRootFileSystemMountName, hostMountNameLen) == 0)
            {
                return(ResultFs.NotMounted.Log());
            }

            Result rc = GetMountNameAndSubPath(out MountName mountName, out subPath, path);

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

            rc = MountTable.Find(StringUtils.Utf8ZToString(mountName.Name), out fileSystem);
            if (rc.IsFailure())
            {
                return(rc);
            }

            return(Result.Success);
        }
コード例 #4
0
ファイル: WindowsPath.cs プロジェクト: garoxas/LibHac
        public static bool IsWindowsDrive(U8Span path)
        {
            Assert.SdkRequires(!path.IsNull());

            return((uint)path.Length > 1 &&
                   IsWindowsDriveCharacter(path[0]) &&
                   path[1] == DriveSeparator);
        }
コード例 #5
0
        /// <summary>
        /// Performs a query on the specified file.
        /// </summary>
        /// <remarks>This method allows implementers of <see cref="IFileSystem"/> to accept queries and operations
        /// not included in the IFileSystem interface itself.</remarks>
        /// <param name="outBuffer">The buffer for receiving data from the query operation.
        /// May be unused depending on the query type.</param>
        /// <param name="inBuffer">The buffer for sending data to the query operation.
        /// May be unused depending on the query type.</param>
        /// <param name="queryId">The type of query to perform.</param>
        /// <param name="path">The full path of the file to query.</param>
        /// <returns>The <see cref="Result"/> of the requested operation.</returns>
        public Result QueryEntry(Span <byte> outBuffer, ReadOnlySpan <byte> inBuffer, QueryId queryId, U8Span path)
        {
            if (path.IsNull())
            {
                return(ResultFs.NullptrArgument.Log());
            }

            return(DoQueryEntry(outBuffer, inBuffer, queryId, path));
        }
コード例 #6
0
        public Result SetFileAttributes(U8Span path, NxFileAttributes attributes)
        {
            if (path.IsNull())
            {
                return(ResultFs.NullptrArgument.Log());
            }

            return(DoSetFileAttributes(path, attributes));
        }
コード例 #7
0
        public Result CreateDirectory(U8Span path, NxFileAttributes archiveAttribute)
        {
            if (path.IsNull())
            {
                return(ResultFs.NullptrArgument.Log());
            }

            return(DoCreateDirectory(path, archiveAttribute));
        }
コード例 #8
0
        /// <summary>
        /// Deletes any subdirectories and files in the specified directory.
        /// </summary>
        /// <param name="path">The full path of the directory to clean.</param>
        /// <returns>The <see cref="Result"/> of the requested operation.</returns>
        /// <remarks>
        /// The following <see cref="Result"/> codes may be returned under certain conditions:
        ///
        /// The specified path does not exist or is a file: <see cref="ResultFs.PathNotFound"/>
        /// </remarks>
        public Result CleanDirectoryRecursively(U8Span path)
        {
            if (path.IsNull())
            {
                return(ResultFs.NullptrArgument.Log());
            }

            return(DoCleanDirectoryRecursively(path));
        }
コード例 #9
0
        /// <summary>
        /// Creates all directories and subdirectories in the specified path unless they already exist.
        /// </summary>
        /// <param name="path">The full path of the directory to create.</param>
        /// <returns>The <see cref="Result"/> of the requested operation.</returns>
        /// <remarks>
        /// The following <see cref="Result"/> codes may be returned under certain conditions:
        ///
        /// The parent directory of the specified path does not exist: <see cref="ResultFs.PathNotFound"/>
        /// Specified path already exists as either a file or directory: <see cref="ResultFs.PathAlreadyExists"/>
        /// Insufficient free space to create the directory: <see cref="ResultFs.UsableSpaceNotEnough"/>
        /// </remarks>
        public Result CreateDirectory(U8Span path)
        {
            if (path.IsNull())
            {
                return(ResultFs.NullptrArgument.Log());
            }

            return(DoCreateDirectory(path));
        }
コード例 #10
0
        /// <summary>
        /// Deletes the specified file.
        /// </summary>
        /// <param name="path">The full path of the file to delete.</param>
        /// <returns>The <see cref="Result"/> of the requested operation.</returns>
        /// <remarks>
        /// The following <see cref="Result"/> codes may be returned under certain conditions:
        ///
        /// The specified path does not exist or is a directory: <see cref="ResultFs.PathNotFound"/>
        /// </remarks>
        public Result DeleteFile(U8Span path)
        {
            if (path.IsNull())
            {
                return(ResultFs.NullptrArgument.Log());
            }

            return(DoDeleteFile(path));
        }
コード例 #11
0
        /// <summary>
        /// Gets the creation, last accessed, and last modified timestamps of a file or directory.
        /// </summary>
        /// <param name="timeStamp">If the operation returns successfully, the timestamps for the specified file or directory.
        /// These value are expressed as Unix timestamps.</param>
        /// <param name="path">The path of the file or directory.</param>
        /// <returns>The <see cref="Result"/> of the requested operation.</returns>
        /// <remarks>
        /// The following <see cref="Result"/> codes may be returned under certain conditions:
        ///
        /// The specified path does not exist: <see cref="ResultFs.PathNotFound"/>
        /// </remarks>
        public Result GetFileTimeStampRaw(out FileTimeStampRaw timeStamp, U8Span path)
        {
            if (path.IsNull())
            {
                UnsafeHelpers.SkipParamInit(out timeStamp);
                return(ResultFs.NullptrArgument.Log());
            }

            return(DoGetFileTimeStampRaw(out timeStamp, path));
        }
コード例 #12
0
ファイル: IFileSystem.cs プロジェクト: leo60228/LibHac
        /// <summary>
        /// Gets the creation, last accessed, and last modified timestamps of a file or directory.
        /// </summary>
        /// <param name="timeStamp">If the operation returns successfully, the timestamps for the specified file or directory.
        /// These value are expressed as Unix timestamps.</param>
        /// <param name="path">The path of the file or directory.</param>
        /// <returns>The <see cref="Result"/> of the requested operation.</returns>
        /// <remarks>
        /// The following <see cref="Result"/> codes may be returned under certain conditions:
        ///
        /// The specified path does not exist: <see cref="ResultFs.PathNotFound"/>
        /// </remarks>
        public Result GetFileTimeStampRaw(out FileTimeStampRaw timeStamp, U8Span path)
        {
            if (path.IsNull())
            {
                timeStamp = default;
                return(ResultFs.NullptrArgument.Log());
            }

            return(DoGetFileTimeStampRaw(out timeStamp, path));
        }
コード例 #13
0
ファイル: IFileSystem.cs プロジェクト: leo60228/LibHac
        /// <summary>
        /// Determines whether the specified path is a file or directory, or does not exist.
        /// </summary>
        /// <param name="entryType">If the operation returns successfully, the <see cref="DirectoryEntryType"/> of the file.</param>
        /// <param name="path">The full path to check.</param>
        /// <returns>The <see cref="Result"/> of the requested operation.</returns>
        public Result GetEntryType(out DirectoryEntryType entryType, U8Span path)
        {
            if (path.IsNull())
            {
                entryType = default;
                return(ResultFs.NullptrArgument.Log());
            }

            return(DoGetEntryType(out entryType, path));
        }
コード例 #14
0
        public Result GetFileSize(out long fileSize, U8Span path)
        {
            if (path.IsNull())
            {
                fileSize = default;
                return(ResultFs.NullptrArgument.Log());
            }

            return(DoGetFileSize(out fileSize, path));
        }
コード例 #15
0
        public Result GetFileAttributes(out NxFileAttributes attributes, U8Span path)
        {
            if (path.IsNull())
            {
                attributes = default;
                return(ResultFs.NullptrArgument.Log());
            }

            return(DoGetFileAttributes(out attributes, path));
        }
コード例 #16
0
ファイル: IFileSystem.cs プロジェクト: leo60228/LibHac
        /// <summary>
        /// Gets the total size of storage space on a drive, in bytes.
        /// </summary>
        /// <param name="totalSpace">If the operation returns successfully, the total size of the drive, in bytes.</param>
        /// <param name="path">The path of the drive to query. Unused in almost all cases.</param>
        /// <returns>The <see cref="Result"/> of the requested operation.</returns>
        public Result GetTotalSpaceSize(out long totalSpace, U8Span path)
        {
            if (path.IsNull())
            {
                totalSpace = default;
                return(ResultFs.NullptrArgument.Log());
            }

            return(DoGetTotalSpaceSize(out totalSpace, path));
        }
コード例 #17
0
        // Todo: Make case sensitive
        public Result Create(out ReferenceCountedDisposable <IFileSystem> fileSystem, U8Span rootPath,
                             BisPartitionId partitionId, bool caseSensitive)
        {
            UnsafeHelpers.SkipParamInit(out fileSystem);

            if (!IsValidPartitionId(partitionId))
            {
                return(ResultFs.InvalidArgument.Log());
            }
            if (rootPath.IsNull())
            {
                return(ResultFs.NullptrArgument.Log());
            }

            if (Config.TryGetFileSystem(out IFileSystem fs, partitionId))
            {
                fileSystem = new ReferenceCountedDisposable <IFileSystem>(fs);
                return(Result.Success);
            }

            if (Config.RootFileSystem == null)
            {
                return(ResultFs.PreconditionViolation.Log());
            }

            var partitionPath = GetPartitionPath(partitionId).ToU8String();

            ReferenceCountedDisposable <IFileSystem> partitionFileSystem = null;
            ReferenceCountedDisposable <IFileSystem> sharedRootFs        = null;

            try
            {
                sharedRootFs = new ReferenceCountedDisposable <IFileSystem>(Config.RootFileSystem);

                Result rc = Utility.WrapSubDirectory(out partitionFileSystem, ref sharedRootFs, partitionPath, true);

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

                if (rootPath.IsEmpty())
                {
                    Shared.Move(out fileSystem, ref partitionFileSystem);
                    return(Result.Success);
                }

                return(Utility.CreateSubDirectoryFileSystem(out fileSystem, ref partitionFileSystem, rootPath));
            }
            finally
            {
                partitionFileSystem?.Dispose();
                sharedRootFs?.Dispose();
            }
        }
コード例 #18
0
        /// <summary>
        /// Determines whether the specified path is a file or directory, or does not exist.
        /// </summary>
        /// <param name="entryType">If the operation returns successfully, the <see cref="DirectoryEntryType"/> of the file.</param>
        /// <param name="path">The full path to check.</param>
        /// <returns>The <see cref="Result"/> of the requested operation.</returns>
        public Result GetEntryType(out DirectoryEntryType entryType, U8Span path)
        {
            UnsafeHelpers.SkipParamInit(out entryType);

            if (path.IsNull())
            {
                return(ResultFs.NullptrArgument.Log());
            }

            return(DoGetEntryType(out entryType, path));
        }
コード例 #19
0
        public Result GetFileSize(out long fileSize, U8Span path)
        {
            UnsafeHelpers.SkipParamInit(out fileSize);

            if (path.IsNull())
            {
                return(ResultFs.NullptrArgument.Log());
            }

            return(DoGetFileSize(out fileSize, path));
        }
コード例 #20
0
        public Result GetFileAttributes(out NxFileAttributes attributes, U8Span path)
        {
            UnsafeHelpers.SkipParamInit(out attributes);

            if (path.IsNull())
            {
                return(ResultFs.NullptrArgument.Log());
            }

            return(DoGetFileAttributes(out attributes, path));
        }
コード例 #21
0
ファイル: MountHelpers.cs プロジェクト: CaitSith2/libhac
        public static Result CheckMountNameAcceptingReservedMountName(U8Span name)
        {
            if (name.IsNull())
            {
                return(ResultFs.NullArgument.Log());
            }

            if (!CheckMountNameImpl(name))
            {
                return(ResultFs.InvalidMountName.Log());
            }

            return(Result.Success);
        }
コード例 #22
0
        /// <summary>
        /// Renames or moves a directory to a new location.
        /// </summary>
        /// <param name="oldPath">The full path of the directory to rename.</param>
        /// <param name="newPath">The new full path of the directory.</param>
        /// <returns>The <see cref="Result"/> of the requested operation.</returns>
        /// <remarks>
        /// If <paramref name="oldPath"/> and <paramref name="newPath"/> are the same, this function does nothing and returns <see cref="Result.Success"/>.
        /// The following <see cref="Result"/> codes may be returned under certain conditions:
        ///
        /// <paramref name="oldPath"/> does not exist or is a file: <see cref="ResultFs.PathNotFound"/>
        /// <paramref name="newPath"/>'s parent directory does not exist: <see cref="ResultFs.PathNotFound"/>
        /// <paramref name="newPath"/> already exists as either a file or directory: <see cref="ResultFs.PathAlreadyExists"/>
        /// Either <paramref name="oldPath"/> or <paramref name="newPath"/> is a subpath of the other: <see cref="ResultFs.DirectoryNotRenamable"/>
        /// </remarks>
        public Result RenameDirectory(U8Span oldPath, U8Span newPath)
        {
            if (oldPath.IsNull())
            {
                return(ResultFs.NullptrArgument.Log());
            }

            if (newPath.IsNull())
            {
                return(ResultFs.NullptrArgument.Log());
            }

            return(DoRenameDirectory(oldPath, newPath));
        }
コード例 #23
0
        public static Result CheckMountNameAcceptingReservedMountName(this FileSystemClientImpl fs, U8Span name)
        {
            if (name.IsNull())
            {
                return(ResultFs.NullptrArgument.Log());
            }

            if (!fs.IsValidMountName(name))
            {
                return(ResultFs.InvalidMountName.Log());
            }

            return(Result.Success);
        }
コード例 #24
0
        /// <summary>
        /// Creates or overwrites a file at the specified path.
        /// </summary>
        /// <param name="path">The full path of the file to create.</param>
        /// <param name="size">The initial size of the created file.
        /// Should usually be <see cref="CreateFileOptions.None"/></param>
        /// <returns>The <see cref="Result"/> of the requested operation.</returns>
        /// <remarks>
        /// The following <see cref="Result"/> codes may be returned under certain conditions:
        ///
        /// The parent directory of the specified path does not exist: <see cref="ResultFs.PathNotFound"/>
        /// Specified path already exists as either a file or directory: <see cref="ResultFs.PathAlreadyExists"/>
        /// Insufficient free space to create the file: <see cref="ResultFs.UsableSpaceNotEnough"/>
        /// </remarks>
        public Result CreateFile(U8Span path, long size)
        {
            if (path.IsNull())
            {
                return(ResultFs.NullptrArgument.Log());
            }

            if (size < 0)
            {
                return(ResultFs.OutOfRange.Log());
            }

            return(DoCreateFile(path, size, CreateFileOptions.None));
        }
コード例 #25
0
        public static Result ConvertToFsCommonPath(this FileSystemClient fs, U8SpanMutable commonPathBuffer,
                                                   U8Span path)
        {
            if (commonPathBuffer.IsNull())
            {
                return(ResultFs.NullptrArgument.Log());
            }

            if (path.IsNull())
            {
                return(ResultFs.NullptrArgument.Log());
            }

            Result rc = GetMountNameAndSubPath(out MountName mountName, out U8Span subPath, path);

            fs.Impl.AbortIfNeeded(rc);
            if (rc.IsFailure())
            {
                return(rc);
            }

            rc = fs.Impl.Find(out FileSystemAccessor fileSystem, new U8Span(mountName.Name));
            fs.Impl.AbortIfNeeded(rc);
            if (rc.IsFailure())
            {
                return(rc);
            }

            rc = fileSystem.GetCommonMountName(commonPathBuffer.Value);
            fs.Impl.AbortIfNeeded(rc);
            if (rc.IsFailure())
            {
                return(rc);
            }

            int mountNameLength  = StringUtils.GetLength(commonPathBuffer);
            int commonPathLength = StringUtils.GetLength(subPath);

            if (mountNameLength + commonPathLength > commonPathBuffer.Length)
            {
                return(ResultFs.TooLongPath.Log());
            }

            StringUtils.Copy(commonPathBuffer.Slice(commonPathLength), subPath);
            return(Result.Success);
        }
コード例 #26
0
ファイル: MountHelpers.cs プロジェクト: CaitSith2/libhac
        public static Result CheckMountName(U8Span name)
        {
            if (name.IsNull())
            {
                return(ResultFs.NullArgument.Log());
            }

            if (name.Length > 0 && name[0] == '@')
            {
                return(ResultFs.InvalidMountName.Log());
            }
            if (!CheckMountNameImpl(name))
            {
                return(ResultFs.InvalidMountName.Log());
            }

            return(Result.Success);
        }
コード例 #27
0
            static Result Mount(FileSystemClient fs, out CodeVerificationData verificationData,
                                U8Span mountName, U8Span path, ProgramId programId)
            {
                UnsafeHelpers.SkipParamInit(out verificationData);

                Result rc = fs.Impl.CheckMountName(mountName);

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

                if (path.IsNull())
                {
                    return(ResultFs.NullptrArgument.Log());
                }

                rc = FspPath.FromSpan(out FspPath fsPath, path);
                if (rc.IsFailure())
                {
                    return(rc);
                }

                using ReferenceCountedDisposable <IFileSystemProxyForLoader> fsProxy =
                          fs.Impl.GetFileSystemProxyForLoaderServiceObject();

                ReferenceCountedDisposable <IFileSystemSf> fileSystem = null;

                try
                {
                    rc = fsProxy.Target.OpenCodeFileSystem(out fileSystem, out verificationData, in fsPath, programId);
                    if (rc.IsFailure())
                    {
                        return(rc);
                    }

                    var fileSystemAdapter = new FileSystemServiceObjectAdapter(fileSystem);
                    return(fs.Register(mountName, fileSystemAdapter));
                }
                finally
                {
                    fileSystem?.Dispose();
                }
            }
コード例 #28
0
ファイル: Content.cs プロジェクト: garoxas/LibHac
        private static Result MountContentImpl(FileSystemClient fs, U8Span mountName, U8Span path, ulong id,
                                               ContentType contentType)
        {
            Result rc = fs.Impl.CheckMountNameAcceptingReservedMountName(mountName);

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

            FileSystemProxyType fsType = ConvertToFileSystemProxyType(contentType);

            if (path.IsNull())
            {
                return(ResultFs.NullptrArgument.Log());
            }

            rc = FspPath.FromSpan(out FspPath fsPath, path);
            if (rc.IsFailure())
            {
                return(rc);
            }

            using ReferenceCountedDisposable <IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();

            ReferenceCountedDisposable <IFileSystemSf> fileSystem = null;

            try
            {
                rc = fsProxy.Target.OpenFileSystemWithId(out fileSystem, in fsPath, id, fsType);
                if (rc.IsFailure())
                {
                    return(rc);
                }

                var fileSystemAdapter = new FileSystemServiceObjectAdapter(fileSystem);
                return(fs.Register(mountName, fileSystemAdapter));
            }
            finally
            {
                fileSystem?.Dispose();
            }
        }
コード例 #29
0
        /// <summary>
        /// Opens an <see cref="IFile"/> instance for the specified path.
        /// </summary>
        /// <param name="file">If the operation returns successfully,
        /// An <see cref="IFile"/> instance for the specified path.</param>
        /// <param name="path">The full path of the file to open.</param>
        /// <param name="mode">Specifies the access permissions of the created <see cref="IFile"/>.</param>
        /// <returns>The <see cref="Result"/> of the requested operation.</returns>
        /// <remarks>
        /// The following <see cref="Result"/> codes may be returned under certain conditions:
        ///
        /// The specified path does not exist or is a directory: <see cref="ResultFs.PathNotFound"/>
        /// </remarks>
        public Result OpenFile(out IFile file, U8Span path, OpenMode mode)
        {
            if (path.IsNull())
            {
                UnsafeHelpers.SkipParamInit(out file);
                return(ResultFs.NullptrArgument.Log());
            }

            if ((mode & OpenMode.ReadWrite) == 0)
            {
                UnsafeHelpers.SkipParamInit(out file);
                return(ResultFs.InvalidOpenMode.Log());
            }

            if ((mode & ~OpenMode.All) != 0)
            {
                UnsafeHelpers.SkipParamInit(out file);
                return(ResultFs.InvalidOpenMode.Log());
            }

            return(DoOpenFile(out file, path, mode));
        }
コード例 #30
0
        /// <summary>
        /// Creates an <see cref="IDirectory"/> instance for enumerating the specified directory.
        /// </summary>
        /// <param name="directory">If the operation returns successfully,
        /// An <see cref="IDirectory"/> instance for the specified directory.</param>
        /// <param name="path">The directory's full path.</param>
        /// <param name="mode">Specifies which sub-entries should be enumerated.</param>
        /// <returns>The <see cref="Result"/> of the requested operation.</returns>
        /// <remarks>
        /// The following <see cref="Result"/> codes may be returned under certain conditions:
        ///
        /// The specified path does not exist or is a file: <see cref="ResultFs.PathNotFound"/>
        /// </remarks>
        public Result OpenDirectory(out IDirectory directory, U8Span path, OpenDirectoryMode mode)
        {
            if (path.IsNull())
            {
                UnsafeHelpers.SkipParamInit(out directory);
                return(ResultFs.NullptrArgument.Log());
            }

            if ((mode & OpenDirectoryMode.All) == 0)
            {
                UnsafeHelpers.SkipParamInit(out directory);
                return(ResultFs.InvalidOpenMode.Log());
            }

            if ((mode & ~(OpenDirectoryMode.All | OpenDirectoryMode.NoFileSize)) != 0)
            {
                UnsafeHelpers.SkipParamInit(out directory);
                return(ResultFs.InvalidOpenMode.Log());
            }

            return(DoOpenDirectory(out directory, path, mode));
        }