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()); }
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))); }
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); }
public static bool IsWindowsDrive(U8Span path) { Assert.SdkRequires(!path.IsNull()); return((uint)path.Length > 1 && IsWindowsDriveCharacter(path[0]) && path[1] == DriveSeparator); }
/// <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)); }
public Result SetFileAttributes(U8Span path, NxFileAttributes attributes) { if (path.IsNull()) { return(ResultFs.NullptrArgument.Log()); } return(DoSetFileAttributes(path, attributes)); }
public Result CreateDirectory(U8Span path, NxFileAttributes archiveAttribute) { if (path.IsNull()) { return(ResultFs.NullptrArgument.Log()); } return(DoCreateDirectory(path, archiveAttribute)); }
/// <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)); }
/// <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)); }
/// <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)); }
/// <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)); }
/// <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)); }
/// <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)); }
public Result GetFileSize(out long fileSize, U8Span path) { if (path.IsNull()) { fileSize = default; return(ResultFs.NullptrArgument.Log()); } return(DoGetFileSize(out fileSize, path)); }
public Result GetFileAttributes(out NxFileAttributes attributes, U8Span path) { if (path.IsNull()) { attributes = default; return(ResultFs.NullptrArgument.Log()); } return(DoGetFileAttributes(out attributes, path)); }
/// <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)); }
// 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(); } }
/// <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)); }
public Result GetFileSize(out long fileSize, U8Span path) { UnsafeHelpers.SkipParamInit(out fileSize); if (path.IsNull()) { return(ResultFs.NullptrArgument.Log()); } return(DoGetFileSize(out fileSize, path)); }
public Result GetFileAttributes(out NxFileAttributes attributes, U8Span path) { UnsafeHelpers.SkipParamInit(out attributes); if (path.IsNull()) { return(ResultFs.NullptrArgument.Log()); } return(DoGetFileAttributes(out attributes, path)); }
public static Result CheckMountNameAcceptingReservedMountName(U8Span name) { if (name.IsNull()) { return(ResultFs.NullArgument.Log()); } if (!CheckMountNameImpl(name)) { return(ResultFs.InvalidMountName.Log()); } return(Result.Success); }
/// <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)); }
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); }
/// <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)); }
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); }
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); }
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(); } }
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(); } }
/// <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)); }
/// <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)); }