mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Implement UserFileSystem and mount registration
This commit is contained in:
parent
a11e84cc81
commit
0dc433d8a2
13 changed files with 1304 additions and 212 deletions
|
@ -533,6 +533,7 @@ Module,DescriptionStart,DescriptionEnd,Flags,Namespace,Name,Summary
|
|||
2,5307,,,,UnexpectedErrorInHostFileFlush,
|
||||
2,5308,,,,UnexpectedErrorInHostFileGetSize,
|
||||
2,5309,,,,UnknownHostFileSystemError,
|
||||
2,5319,,,,UnexpectedInMountUtilityA,
|
||||
2,5320,,,,InvalidNcaMountPoint,
|
||||
|
||||
2,6000,6499,,,PreconditionViolation,
|
||||
|
|
|
|
@ -435,5 +435,19 @@ namespace LibHac.Fs.Impl
|
|||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static ReadOnlySpan<byte> ConvertFromBoolToAccessLogBooleanValue(bool value)
|
||||
{
|
||||
return value ? LogTrue : LogFalse;
|
||||
}
|
||||
|
||||
private static ReadOnlySpan<byte> LogTrue => // "true"
|
||||
new[] { (byte)'t', (byte)'r', (byte)'u', (byte)'e' };
|
||||
|
||||
private static ReadOnlySpan<byte> LogFalse => // "false"
|
||||
new[]
|
||||
{
|
||||
(byte)'f', (byte)'a', (byte)'l', (byte)'s', (byte)'e'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ namespace LibHac.Fs
|
|||
filter.SetProgramId(applicationId);
|
||||
filter.SetSaveDataType(SaveDataType.Temporary);
|
||||
|
||||
Result rc = fs.FindSaveDataWithFilter(out _, SaveDataSpaceId.Temporary, ref filter);
|
||||
Result rc = fs.FindSaveDataWithFilter(out _, SaveDataSpaceId.Temporary, in filter);
|
||||
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
|
@ -176,7 +176,7 @@ namespace LibHac.Fs
|
|||
private static Result EnsureAndExtendSaveData(FileSystemClient fs, Func<Result> createFunc,
|
||||
ref long requiredSize, ref SaveDataFilter filter, long baseSize, long dataSize, long journalSize)
|
||||
{
|
||||
Result rc = fs.FindSaveDataWithFilter(out SaveDataInfo info, SaveDataSpaceId.User, ref filter);
|
||||
Result rc = fs.FindSaveDataWithFilter(out SaveDataInfo info, SaveDataSpaceId.User, in filter);
|
||||
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
|
@ -346,7 +346,7 @@ namespace LibHac.Fs
|
|||
filter.SetIndex(index);
|
||||
filter.SetSaveDataType(SaveDataType.Cache);
|
||||
|
||||
Result rc = fs.FindSaveDataWithFilter(out SaveDataInfo info, spaceId, ref filter);
|
||||
Result rc = fs.FindSaveDataWithFilter(out SaveDataInfo info, spaceId, in filter);
|
||||
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
|
@ -401,7 +401,7 @@ namespace LibHac.Fs
|
|||
|
||||
if (fs.IsSdCardAccessible())
|
||||
{
|
||||
Result rc = fs.FindSaveDataWithFilter(out _, SaveDataSpaceId.SdCache, ref filter);
|
||||
Result rc = fs.FindSaveDataWithFilter(out _, SaveDataSpaceId.SdCache, in filter);
|
||||
if (rc.IsFailure() && !ResultFs.TargetNotFound.Includes(rc)) return rc;
|
||||
|
||||
if (rc.IsSuccess())
|
||||
|
@ -413,7 +413,7 @@ namespace LibHac.Fs
|
|||
// Not on the SD card. Check it it's in NAND
|
||||
if (target == CacheStorageTargetMedia.None)
|
||||
{
|
||||
Result rc = fs.FindSaveDataWithFilter(out _, SaveDataSpaceId.User, ref filter);
|
||||
Result rc = fs.FindSaveDataWithFilter(out _, SaveDataSpaceId.User, in filter);
|
||||
if (rc.IsFailure() && !ResultFs.TargetNotFound.Includes(rc)) return rc;
|
||||
|
||||
if (rc.IsSuccess())
|
||||
|
@ -434,7 +434,7 @@ namespace LibHac.Fs
|
|||
|
||||
while (true)
|
||||
{
|
||||
rc = fs.FindSaveDataWithFilter(out SaveDataInfo saveInfo, SaveDataSpaceId.Temporary, ref filter);
|
||||
rc = fs.FindSaveDataWithFilter(out SaveDataInfo saveInfo, SaveDataSpaceId.Temporary, in filter);
|
||||
|
||||
if (rc.IsFailure()) break;
|
||||
|
||||
|
|
|
@ -177,9 +177,11 @@ namespace LibHac.Fs
|
|||
Restore = 1 << 4
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum CommitOptionFlag
|
||||
{
|
||||
None = 1,
|
||||
None = 0,
|
||||
ClearRestoreFlag = 1,
|
||||
SetRestoreFlag = 2
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Diag;
|
||||
using LibHac.Fs.Impl;
|
||||
using LibHac.FsSystem;
|
||||
using LibHac.Os;
|
||||
using LibHac.Util;
|
||||
|
||||
namespace LibHac.Fs.Fsa
|
||||
{
|
||||
|
@ -8,59 +13,260 @@ namespace LibHac.Fs.Fsa
|
|||
{
|
||||
internal static Result GetMountNameAndSubPath(out MountName mountName, out U8Span subPath, U8Span path)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Unsafe.SkipInit(out mountName);
|
||||
subPath = default;
|
||||
|
||||
int mountLen = 0;
|
||||
int maxMountLen = Math.Min(path.Length, PathTools.MountNameLengthMax);
|
||||
|
||||
if (PathUtility.IsWindowsDrive(path) || PathUtility.IsUnc(path))
|
||||
{
|
||||
StringUtils.Copy(mountName.Name, CommonPaths.HostRootFileSystemMountName);
|
||||
mountName.Name[PathTools.MountNameLengthMax] = StringTraits.NullTerminator;
|
||||
|
||||
subPath = path;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
for (int i = 0; i <= maxMountLen; i++)
|
||||
{
|
||||
if (path[i] == PathTools.MountSeparator)
|
||||
{
|
||||
mountLen = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mountLen == 0)
|
||||
return ResultFs.InvalidMountName.Log();
|
||||
|
||||
if (mountLen > maxMountLen)
|
||||
return ResultFs.InvalidMountName.Log();
|
||||
|
||||
if (mountLen <= 0)
|
||||
return ResultFs.InvalidMountName.Log();
|
||||
|
||||
U8Span subPathTemp = path.Slice(mountLen + 1);
|
||||
|
||||
if (subPathTemp.Length == 0 || !PathTool.IsAnySeparator(subPathTemp[0]))
|
||||
return ResultFs.InvalidPathFormat.Log();
|
||||
|
||||
path.Value.Slice(0, mountLen).CopyTo(mountName.Name);
|
||||
mountName.Name[mountLen] = StringTraits.NullTerminator;
|
||||
subPath = subPathTemp;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static bool IsValidMountName(this FileSystemClientImpl fs, U8Span name)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
if (name.IsEmpty())
|
||||
return false;
|
||||
|
||||
// Check for a single-letter mount name
|
||||
if ((name.Length <= 1 || name[1] == 0) &&
|
||||
('a' <= name[0] && name[0] <= 'z' || 'A' <= name[0] && name[0] <= 'Z'))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for mount or directory separators
|
||||
int length = 0;
|
||||
for (int i = 0; i < name.Length && name[i] != 0; i++)
|
||||
{
|
||||
if (PathTool.IsDriveSeparator(name[i]) || PathTool.IsSeparator(name[i]))
|
||||
return false;
|
||||
|
||||
if (++length > PathTools.MountNameLengthMax)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Todo: VerifyUtf8String
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool IsUsedReservedMountName(this FileSystemClientImpl fs, U8Span name)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return name.Length > 0 && name[0] == CommonPaths.ReservedMountNamePrefixCharacter;
|
||||
}
|
||||
|
||||
internal static Result FindFileSystem(this FileSystemClientImpl fs, out FileSystemAccessor fileSystem,
|
||||
out U8Span subPath, U8Span path)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
fileSystem = default;
|
||||
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));
|
||||
}
|
||||
|
||||
public static Result CheckMountName(this FileSystemClientImpl fs, U8Span name)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
if (name.IsNull())
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
|
||||
if (fs.IsUsedReservedMountName(name))
|
||||
return ResultFs.InvalidMountName.Log();
|
||||
|
||||
if (fs.IsValidMountName(name))
|
||||
return ResultFs.InvalidMountName.Log();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result CheckMountNameAcceptingReservedMountName(this FileSystemClientImpl fs, U8Span name)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
if (name.IsNull())
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
|
||||
if (fs.IsValidMountName(name))
|
||||
return ResultFs.InvalidMountName.Log();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result Unmount(this FileSystemClientImpl fs, U8Span mountName)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Result rc = fs.Find(out FileSystemAccessor fileSystem, mountName);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (fileSystem.IsFileDataCacheAttachable())
|
||||
{
|
||||
// Todo: Data cache purge
|
||||
}
|
||||
|
||||
fs.Unregister(mountName);
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result IsMounted(this FileSystemClientImpl fs, out bool isMounted, U8Span mountName)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Unsafe.SkipInit(out isMounted);
|
||||
|
||||
Result rc = fs.Find(out _, mountName);
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
if (!ResultFs.NotMounted.Includes(rc))
|
||||
return rc;
|
||||
|
||||
isMounted = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
isMounted = true;
|
||||
}
|
||||
|
||||
public static Result Unmount(this FileSystemClient fs, U8Span mountName)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result IsMounted(this FileSystemClient fs, out bool isMounted, U8Span mountName)
|
||||
public static void Unmount(this FileSystemClient fs, U8Span mountName)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Result rc;
|
||||
Span<byte> logBuffer = stackalloc byte[0x30];
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog() && fs.Impl.IsEnabledFileSystemAccessorAccessLog(mountName))
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fs.Impl.Unmount(mountName);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var sb = new U8StringBuilder(logBuffer, true);
|
||||
sb.Append(LogName).Append(mountName).Append((byte)'"');
|
||||
logBuffer = sb.Buffer;
|
||||
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fs.Impl.Unmount(mountName);
|
||||
}
|
||||
fs.Impl.LogErrorMessage(rc);
|
||||
Abort.DoAbortUnless(rc.IsSuccess());
|
||||
}
|
||||
|
||||
public static bool IsMounted(this FileSystemClient fs, U8Span mountName)
|
||||
{
|
||||
Result rc;
|
||||
bool isMounted;
|
||||
Span<byte> logBuffer = stackalloc byte[0x30];
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog() && fs.Impl.IsEnabledFileSystemAccessorAccessLog(mountName))
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fs.Impl.IsMounted(out isMounted, mountName);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var sb = new U8StringBuilder(logBuffer, true);
|
||||
ReadOnlySpan<byte> boolString = AccessLogImpl.ConvertFromBoolToAccessLogBooleanValue(isMounted);
|
||||
sb.Append(LogName).Append(mountName).Append(LogIsMounted).Append(boolString).Append((byte)'"');
|
||||
logBuffer = sb.Buffer;
|
||||
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fs.Impl.IsMounted(out isMounted, mountName);
|
||||
}
|
||||
fs.Impl.LogErrorMessage(rc);
|
||||
Abort.DoAbortUnless(rc.IsSuccess());
|
||||
|
||||
return isMounted;
|
||||
}
|
||||
|
||||
public static Result ConvertToFsCommonPath(this FileSystemClient fs, U8SpanMutable commonPathBuffer,
|
||||
U8Span path)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
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;
|
||||
}
|
||||
|
||||
private static ReadOnlySpan<byte> LogName => // ", name: ""
|
||||
new[]
|
||||
{
|
||||
(byte)',', (byte)' ', (byte)'n', (byte)'a', (byte)'m', (byte)'e', (byte)':', (byte)' ',
|
||||
(byte)'"'
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> LogIsMounted => // "", is_mounted: ""
|
||||
new[]
|
||||
{
|
||||
(byte)'"', (byte)',', (byte)' ', (byte)'i', (byte)'s', (byte)'_', (byte)'m', (byte)'o',
|
||||
(byte)'u', (byte)'n', (byte)'t', (byte)'e', (byte)'d', (byte)':', (byte)' ', (byte)'"'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Impl;
|
||||
|
||||
namespace LibHac.Fs.Fsa
|
||||
{
|
||||
|
@ -15,32 +16,47 @@ namespace LibHac.Fs.Fsa
|
|||
|
||||
internal static class Registrar
|
||||
{
|
||||
public static Result Register(U8Span name, IFileSystem fileSystem)
|
||||
public static Result Register(this FileSystemClient fs, U8Span name, IFileSystem fileSystem)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var accessor = new FileSystemAccessor(name, null, fileSystem, null, null);
|
||||
fs.Impl.Register(accessor);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result Register(U8Span name, IFileSystem fileSystem, ICommonMountNameGenerator mountNameGenerator)
|
||||
public static Result Register(this FileSystemClient fs, U8Span name, IFileSystem fileSystem,
|
||||
ICommonMountNameGenerator mountNameGenerator)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var accessor = new FileSystemAccessor(name, null, fileSystem, mountNameGenerator, null);
|
||||
fs.Impl.Register(accessor);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result Register(U8Span name, IMultiCommitTarget multiCommitTarget, IFileSystem fileSystem,
|
||||
ICommonMountNameGenerator mountNameGenerator, bool useDataCache, bool usePathCache)
|
||||
public static Result Register(this FileSystemClient fs, U8Span name, IMultiCommitTarget multiCommitTarget,
|
||||
IFileSystem fileSystem, ICommonMountNameGenerator mountNameGenerator, bool useDataCache, bool usePathCache)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return fs.Register(name, multiCommitTarget, fileSystem, mountNameGenerator, null, useDataCache,
|
||||
usePathCache);
|
||||
}
|
||||
|
||||
public static Result Register(U8Span name, IMultiCommitTarget multiCommitTarget, IFileSystem fileSystem,
|
||||
ICommonMountNameGenerator mountNameGenerator, ISaveDataAttributeGetter saveAttributeGetter,
|
||||
bool useDataCache, bool usePathCache)
|
||||
public static Result Register(this FileSystemClient fs, U8Span name, IMultiCommitTarget multiCommitTarget,
|
||||
IFileSystem fileSystem, ICommonMountNameGenerator mountNameGenerator,
|
||||
ISaveDataAttributeGetter saveAttributeGetter, bool useDataCache, bool usePathCache)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var accessor = new FileSystemAccessor(name, multiCommitTarget, fileSystem, mountNameGenerator,
|
||||
saveAttributeGetter);
|
||||
|
||||
accessor.SetFileDataCacheAttachable(useDataCache);
|
||||
accessor.SetPathBasedFileDataCacheAttachable(usePathCache);
|
||||
fs.Impl.Register(accessor);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static void Unregister(U8Span name)
|
||||
public static void Unregister(this FileSystemClient fs, U8Span name)
|
||||
{
|
||||
|
||||
fs.Impl.Unregister(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -210,7 +210,7 @@ namespace LibHac.Fs.Fsa
|
|||
Result rc = Get(handle).OperateRange(SpanHelpers.AsByteSpan(ref rangeInfo), OperationId.QueryRange, offset,
|
||||
size, ReadOnlySpan<byte>.Empty);
|
||||
|
||||
fs.Impl.IsAbortNeeded(rc);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -219,7 +219,7 @@ namespace LibHac.Fs.Fsa
|
|||
Result rc = Get(handle).OperateRange(Span<byte>.Empty, OperationId.InvalidateCache, offset, size,
|
||||
ReadOnlySpan<byte>.Empty);
|
||||
|
||||
fs.Impl.IsAbortNeeded(rc);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,101 +1,805 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Impl;
|
||||
using LibHac.Fs.Shim;
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.Os;
|
||||
using IFileSystemSf = LibHac.FsSrv.Sf.IFileSystem;
|
||||
|
||||
namespace LibHac.Fs.Fsa
|
||||
{
|
||||
[SkipLocalsInit]
|
||||
public static class UserFileSystem
|
||||
{
|
||||
public static Result CreateFile(this FileSystemClient fs, U8Span path, long size)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return fs.CreateFile(path, size, CreateFileOptions.None);
|
||||
}
|
||||
|
||||
public static Result DeleteFile(this FileSystemClient fs, U8Span path)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Result rc;
|
||||
U8Span subPath;
|
||||
FileSystemAccessor fileSystem;
|
||||
Span<byte> logBuffer = stackalloc byte[0x300];
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fs.Impl.FindFileSystem(out fileSystem, out subPath, path);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var sb = new U8StringBuilder(logBuffer, true);
|
||||
sb.Append(LogPath).Append(path).Append((byte)'"');
|
||||
logBuffer = sb.Buffer;
|
||||
|
||||
fs.Impl.OutputAccessLogUnlessResultSuccess(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fs.Impl.FindFileSystem(out fileSystem, out subPath, path);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog() && fileSystem.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fileSystem.DeleteFile(subPath);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.DeleteFile(subPath);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
public static Result CreateDirectory(this FileSystemClient fs, U8Span path)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Result rc;
|
||||
U8Span subPath;
|
||||
FileSystemAccessor fileSystem;
|
||||
Span<byte> logBuffer = stackalloc byte[0x300];
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fs.Impl.FindFileSystem(out fileSystem, out subPath, path);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var sb = new U8StringBuilder(logBuffer, true);
|
||||
sb.Append(LogPath).Append(path).Append((byte)'"');
|
||||
logBuffer = sb.Buffer;
|
||||
|
||||
fs.Impl.OutputAccessLogUnlessResultSuccess(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fs.Impl.FindFileSystem(out fileSystem, out subPath, path);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog() && fileSystem.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fileSystem.CreateDirectory(subPath);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.CreateDirectory(subPath);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
public static Result DeleteDirectory(this FileSystemClient fs, U8Span path)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Result rc;
|
||||
U8Span subPath;
|
||||
FileSystemAccessor fileSystem;
|
||||
Span<byte> logBuffer = stackalloc byte[0x300];
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fs.Impl.FindFileSystem(out fileSystem, out subPath, path);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var sb = new U8StringBuilder(logBuffer, true);
|
||||
sb.Append(LogPath).Append(path).Append((byte)'"');
|
||||
logBuffer = sb.Buffer;
|
||||
|
||||
fs.Impl.OutputAccessLogUnlessResultSuccess(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fs.Impl.FindFileSystem(out fileSystem, out subPath, path);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog() && fileSystem.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fileSystem.DeleteDirectory(subPath);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.DeleteDirectory(subPath);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
public static Result DeleteDirectoryRecursively(this FileSystemClient fs, U8Span path)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Result rc;
|
||||
U8Span subPath;
|
||||
FileSystemAccessor fileSystem;
|
||||
Span<byte> logBuffer = stackalloc byte[0x300];
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fs.Impl.FindFileSystem(out fileSystem, out subPath, path);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var sb = new U8StringBuilder(logBuffer, true);
|
||||
sb.Append(LogPath).Append(path).Append((byte)'"');
|
||||
logBuffer = sb.Buffer;
|
||||
|
||||
fs.Impl.OutputAccessLogUnlessResultSuccess(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fs.Impl.FindFileSystem(out fileSystem, out subPath, path);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog() && fileSystem.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fileSystem.DeleteDirectoryRecursively(subPath);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.DeleteDirectoryRecursively(subPath);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
public static Result CleanDirectoryRecursively(this FileSystemClient fs, U8Span path)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Result rc;
|
||||
U8Span subPath;
|
||||
FileSystemAccessor fileSystem;
|
||||
Span<byte> logBuffer = stackalloc byte[0x300];
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fs.Impl.FindFileSystem(out fileSystem, out subPath, path);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var sb = new U8StringBuilder(logBuffer, true);
|
||||
sb.Append(LogPath).Append(path).Append((byte)'"');
|
||||
logBuffer = sb.Buffer;
|
||||
|
||||
fs.Impl.OutputAccessLogUnlessResultSuccess(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fs.Impl.FindFileSystem(out fileSystem, out subPath, path);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog() && fileSystem.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fileSystem.CleanDirectoryRecursively(subPath);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.CleanDirectoryRecursively(subPath);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
public static Result RenameFile(this FileSystemClient fs, U8Span oldPath, U8Span newPath)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Result rc;
|
||||
U8Span currentSubPath, newSubPath;
|
||||
FileSystemAccessor currentFileSystem, newFileSystem;
|
||||
Span<byte> logBuffer = stackalloc byte[0x300];
|
||||
|
||||
// Get the file system accessor for the current path
|
||||
if (fs.Impl.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fs.Impl.FindFileSystem(out currentFileSystem, out currentSubPath, oldPath);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var sb = new U8StringBuilder(logBuffer, true);
|
||||
sb.Append(LogPath).Append(oldPath).Append(LogNewPath).Append(newPath).Append((byte)'"');
|
||||
logBuffer = sb.Buffer;
|
||||
|
||||
fs.Impl.OutputAccessLogUnlessResultSuccess(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fs.Impl.FindFileSystem(out currentFileSystem, out currentSubPath, oldPath);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
// Get the file system accessor for the new path
|
||||
if (fs.Impl.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fs.Impl.FindFileSystem(out newFileSystem, out newSubPath, newPath);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
fs.Impl.OutputAccessLogUnlessResultSuccess(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fs.Impl.FindFileSystem(out newFileSystem, out newSubPath, newPath);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
// Rename the file
|
||||
if (fs.Impl.IsEnabledAccessLog() && currentFileSystem.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
rc = currentFileSystem != newFileSystem
|
||||
? ResultFs.RenameToOtherFileSystem.Log()
|
||||
: currentFileSystem.RenameFile(currentSubPath, newSubPath);
|
||||
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = currentFileSystem != newFileSystem
|
||||
? ResultFs.RenameToOtherFileSystem.Log()
|
||||
: currentFileSystem.RenameFile(currentSubPath, newSubPath);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
public static Result RenameDirectory(this FileSystemClient fs, U8Span oldPath, U8Span newPath)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Result rc;
|
||||
U8Span currentSubPath, newSubPath;
|
||||
FileSystemAccessor currentFileSystem, newFileSystem;
|
||||
Span<byte> logBuffer = stackalloc byte[0x300];
|
||||
|
||||
// Get the file system accessor for the current path
|
||||
if (fs.Impl.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fs.Impl.FindFileSystem(out currentFileSystem, out currentSubPath, oldPath);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var sb = new U8StringBuilder(logBuffer, true);
|
||||
sb.Append(LogPath).Append(oldPath).Append(LogNewPath).Append(newPath).Append((byte)'"');
|
||||
logBuffer = sb.Buffer;
|
||||
|
||||
fs.Impl.OutputAccessLogUnlessResultSuccess(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fs.Impl.FindFileSystem(out currentFileSystem, out currentSubPath, oldPath);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
// Get the file system accessor for the new path
|
||||
if (fs.Impl.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fs.Impl.FindFileSystem(out newFileSystem, out newSubPath, newPath);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
fs.Impl.OutputAccessLogUnlessResultSuccess(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fs.Impl.FindFileSystem(out newFileSystem, out newSubPath, newPath);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
// Rename the directory
|
||||
if (fs.Impl.IsEnabledAccessLog() && currentFileSystem.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
rc = currentFileSystem != newFileSystem
|
||||
? ResultFs.RenameToOtherFileSystem.Log()
|
||||
: currentFileSystem.RenameDirectory(currentSubPath, newSubPath);
|
||||
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = currentFileSystem != newFileSystem
|
||||
? ResultFs.RenameToOtherFileSystem.Log()
|
||||
: currentFileSystem.RenameDirectory(currentSubPath, newSubPath);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
public static Result GetEntryType(this FileSystemClient fs, out DirectoryEntryType type, U8Span path)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Unsafe.SkipInit(out type);
|
||||
|
||||
Result rc;
|
||||
U8Span subPath;
|
||||
FileSystemAccessor fileSystem;
|
||||
Span<byte> logBuffer = stackalloc byte[0x300];
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fs.Impl.FindFileSystem(out fileSystem, out subPath, path);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var idString = new IdString();
|
||||
var sb = new U8StringBuilder(logBuffer, true);
|
||||
sb.Append(LogPath).Append(path).Append(LogEntryType)
|
||||
.Append(idString.ToString(AccessLogImpl.DereferenceOutValue(in type, rc)));
|
||||
logBuffer = sb.Buffer;
|
||||
|
||||
fs.Impl.OutputAccessLogUnlessResultSuccess(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fs.Impl.FindFileSystem(out fileSystem, out subPath, path);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog() && fileSystem.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fileSystem.GetEntryType(out type, subPath);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var idString = new IdString();
|
||||
var sb = new U8StringBuilder(logBuffer, true);
|
||||
sb.Append(LogPath).Append(path).Append(LogEntryType)
|
||||
.Append(idString.ToString(AccessLogImpl.DereferenceOutValue(in type, rc)));
|
||||
logBuffer = sb.Buffer;
|
||||
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.GetEntryType(out type, subPath);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
public static Result GetFreeSpaceSize(this FileSystemClient fs, out long freeSpace, U8Span path)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Unsafe.SkipInit(out freeSpace);
|
||||
|
||||
Result rc;
|
||||
var subPath = U8Span.Empty;
|
||||
FileSystemAccessor fileSystem;
|
||||
Span<byte> logBuffer = stackalloc byte[0x300];
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
if (fs.Impl.IsValidMountName(path))
|
||||
{
|
||||
rc = fs.Impl.Find(out fileSystem, path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fs.Impl.FindFileSystem(out fileSystem, out subPath, path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var sb = new U8StringBuilder(logBuffer, true);
|
||||
sb.Append(LogPath).Append(path).Append(LogSize)
|
||||
.AppendFormat(AccessLogImpl.DereferenceOutValue(in freeSpace, rc));
|
||||
logBuffer = sb.Buffer;
|
||||
|
||||
fs.Impl.OutputAccessLogUnlessResultSuccess(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fs.Impl.IsValidMountName(path))
|
||||
{
|
||||
rc = fs.Impl.Find(out fileSystem, path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fs.Impl.FindFileSystem(out fileSystem, out subPath, path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog() && fileSystem.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fileSystem.GetFreeSpaceSize(out freeSpace, subPath);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var sb = new U8StringBuilder(logBuffer, true);
|
||||
sb.Append(LogPath).Append(path).Append(LogSize)
|
||||
.AppendFormat(AccessLogImpl.DereferenceOutValue(in freeSpace, rc));
|
||||
logBuffer = sb.Buffer;
|
||||
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.GetFreeSpaceSize(out freeSpace, subPath);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
public static Result OpenFile(this FileSystemClient fs, out FileHandle2 handle, U8Span path, OpenMode mode)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
handle = default;
|
||||
|
||||
Result rc;
|
||||
U8Span subPath;
|
||||
FileSystemAccessor fileSystem;
|
||||
Span<byte> logBuffer = stackalloc byte[0x300];
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fs.Impl.FindFileSystem(out fileSystem, out subPath, path);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var sb = new U8StringBuilder(logBuffer, true);
|
||||
sb.Append(LogPath).Append(path).Append(LogOpenMode).AppendFormat((int)mode, 'X');
|
||||
logBuffer = sb.Buffer;
|
||||
|
||||
fs.Impl.OutputAccessLogUnlessResultSuccess(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fs.Impl.FindFileSystem(out fileSystem, out subPath, path);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
FileAccessor accessor;
|
||||
if (fs.Impl.IsEnabledAccessLog() && fileSystem.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fileSystem.OpenFile(out accessor, subPath, mode);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.OpenFile(out accessor, subPath, mode);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
handle = new FileHandle2(accessor);
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result OpenFile(this FileSystemClient fs, out FileHandle2 handle, IFile file, OpenMode mode)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var accessor = new FileAccessor(ref file, null, mode);
|
||||
handle = new FileHandle2(accessor);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result OpenDirectory(this FileSystemClient fs, out DirectoryHandle2 handle, U8Span path,
|
||||
OpenDirectoryMode mode)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
handle = default;
|
||||
|
||||
Result rc;
|
||||
U8Span subPath;
|
||||
FileSystemAccessor fileSystem;
|
||||
Span<byte> logBuffer = stackalloc byte[0x300];
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fs.Impl.FindFileSystem(out fileSystem, out subPath, path);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var sb = new U8StringBuilder(logBuffer, true);
|
||||
sb.Append(LogPath).Append(path).Append(LogOpenMode).AppendFormat((int)mode, 'X');
|
||||
logBuffer = sb.Buffer;
|
||||
|
||||
fs.Impl.OutputAccessLogUnlessResultSuccess(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fs.Impl.FindFileSystem(out fileSystem, out subPath, path);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
DirectoryAccessor accessor;
|
||||
if (fs.Impl.IsEnabledAccessLog() && fileSystem.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fileSystem.OpenDirectory(out accessor, subPath, mode);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.OpenDirectory(out accessor, subPath, mode);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
handle = new DirectoryHandle2(accessor);
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private static Result CommitImpl(FileSystemClient fs, U8Span mountName,
|
||||
[CallerMemberName] string functionName = "")
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Result rc;
|
||||
FileSystemAccessor fileSystem;
|
||||
Span<byte> logBuffer = stackalloc byte[0x30];
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fs.Impl.Find(out fileSystem, mountName);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var sb = new U8StringBuilder(logBuffer, true);
|
||||
sb.Append(LogName).Append(mountName).Append((byte)'"');
|
||||
logBuffer = sb.Buffer;
|
||||
|
||||
fs.Impl.OutputAccessLogUnlessResultSuccess(rc, start, end, null, new U8Span(logBuffer), functionName);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fs.Impl.Find(out fileSystem, mountName);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog() && fileSystem.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fileSystem.Commit();
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(logBuffer), functionName);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.Commit();
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
public static Result Commit(this FileSystemClient fs, ReadOnlySpan<U8String> mountNames)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
// Todo: Add access log
|
||||
|
||||
if (mountNames.Length > 10)
|
||||
return ResultFs.InvalidCommitNameCount.Log();
|
||||
|
||||
if (mountNames.Length == 0)
|
||||
return Result.Success;
|
||||
|
||||
ReferenceCountedDisposable<IMultiCommitManager> commitManager = null;
|
||||
ReferenceCountedDisposable<IFileSystemSf> fileSystem = null;
|
||||
try
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.OpenMultiCommitManager(out commitManager);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
for (int i = 0; i < mountNames.Length; i++)
|
||||
{
|
||||
rc = fs.Impl.Find(out FileSystemAccessor accessor, mountNames[i]);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
fileSystem = accessor.GetMultiCommitTarget();
|
||||
if (fileSystem is null)
|
||||
return ResultFs.UnsupportedCommitTarget.Log();
|
||||
|
||||
rc = commitManager.Target.Add(fileSystem);
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
|
||||
rc = commitManager.Target.Commit();
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
commitManager?.Dispose();
|
||||
fileSystem?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public static Result Commit(this FileSystemClient fs, U8Span mountName, CommitOption option)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Result rc;
|
||||
FileSystemAccessor fileSystem;
|
||||
Span<byte> logBuffer = stackalloc byte[0x40];
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fs.Impl.Find(out fileSystem, mountName);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var sb = new U8StringBuilder(logBuffer, true);
|
||||
sb.Append(LogName).Append(mountName).Append(LogCommitOption).AppendFormat((int)option.Flags, 'X');
|
||||
logBuffer = sb.Buffer;
|
||||
|
||||
fs.Impl.OutputAccessLogUnlessResultSuccess(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fs.Impl.Find(out fileSystem, mountName);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog() && fileSystem.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = RunCommit(fs, option, fileSystem);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = RunCommit(fs, option, fileSystem);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
|
||||
static Result RunCommit(FileSystemClient fs, CommitOption option, FileSystemAccessor fileSystem)
|
||||
{
|
||||
if ((option.Flags & (CommitOptionFlag.ClearRestoreFlag | CommitOptionFlag.SetRestoreFlag)) == 0)
|
||||
{
|
||||
return fileSystem.Commit();
|
||||
}
|
||||
|
||||
if (option.Flags != CommitOptionFlag.ClearRestoreFlag &&
|
||||
option.Flags != CommitOptionFlag.SetRestoreFlag)
|
||||
{
|
||||
return ResultFs.InvalidCommitOption.Log();
|
||||
}
|
||||
|
||||
Result rc = fileSystem.GetSaveDataAttribute(out SaveDataAttribute attribute);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (attribute.ProgramId == SaveData.InvalidProgramId)
|
||||
attribute.ProgramId = SaveData.AutoResolveCallerProgramId;
|
||||
|
||||
var extraDataMask = new SaveDataExtraData();
|
||||
extraDataMask.Flags = SaveDataFlags.Restore;
|
||||
|
||||
var extraData = new SaveDataExtraData();
|
||||
extraDataMask.Flags = option.Flags == CommitOptionFlag.SetRestoreFlag
|
||||
? SaveDataFlags.Restore
|
||||
: SaveDataFlags.None;
|
||||
|
||||
return fs.Impl.WriteSaveDataFileSystemExtraData(SaveDataSpaceId.User, in attribute, in extraData,
|
||||
in extraDataMask);
|
||||
}
|
||||
}
|
||||
|
||||
public static Result Commit(this FileSystemClient fs, U8Span mountName)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return CommitImpl(fs, mountName);
|
||||
}
|
||||
|
||||
public static Result CommitSaveData(this FileSystemClient fs, U8Span mountName)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return CommitImpl(fs, mountName);
|
||||
}
|
||||
|
||||
private static ReadOnlySpan<byte> LogPath => // ", path: ""
|
||||
new[]
|
||||
{
|
||||
(byte)',', (byte)' ', (byte)'p', (byte)'a', (byte)'t', (byte)'h', (byte)':', (byte)' ',
|
||||
(byte)'"'
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> LogNewPath => // "", new_path: ""
|
||||
new[]
|
||||
{
|
||||
(byte)'"', (byte)',', (byte)' ', (byte)'n', (byte)'e', (byte)'w', (byte)'_', (byte)'p',
|
||||
(byte)'a', (byte)'t', (byte)'h', (byte)':', (byte)' ', (byte)'"'
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> LogEntryType => // "", entry_type: "
|
||||
new[]
|
||||
{
|
||||
(byte)'"', (byte)',', (byte)' ', (byte)'e', (byte)'n', (byte)'t', (byte)'r', (byte)'y',
|
||||
(byte)'_', (byte)'t', (byte)'y', (byte)'p', (byte)'e', (byte)':', (byte)' '
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> LogSize => // "", size: "
|
||||
new[]
|
||||
{
|
||||
(byte)'"', (byte)',', (byte)' ', (byte)'s', (byte)'i', (byte)'z', (byte)'e', (byte)':',
|
||||
(byte)' '
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> LogOpenMode => // "", open_mode: 0x"
|
||||
new[]
|
||||
{
|
||||
(byte)'"', (byte)',', (byte)' ', (byte)'o', (byte)'p', (byte)'e', (byte)'n', (byte)'_',
|
||||
(byte)'m', (byte)'o', (byte)'d', (byte)'e', (byte)':', (byte)' ', (byte)'0', (byte)'x'
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> LogName => // ", name: ""
|
||||
new[]
|
||||
{
|
||||
(byte)',', (byte)' ', (byte)'n', (byte)'a', (byte)'m', (byte)'e', (byte)':', (byte)' ',
|
||||
(byte)'"'
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> LogCommitOption => // "", commit_option: 0x"
|
||||
new[]
|
||||
{
|
||||
(byte)'"', (byte)',', (byte)' ', (byte)'c', (byte)'o', (byte)'m', (byte)'m', (byte)'i',
|
||||
(byte)'t', (byte)'_', (byte)'o', (byte)'p', (byte)'t', (byte)'i', (byte)'o', (byte)'n',
|
||||
(byte)':', (byte)' ', (byte)'0', (byte)'x'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
95
src/LibHac/Fs/Fsa/UserFileSystemPrivate.cs
Normal file
95
src/LibHac/Fs/Fsa/UserFileSystemPrivate.cs
Normal file
|
@ -0,0 +1,95 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Impl;
|
||||
using LibHac.Os;
|
||||
|
||||
namespace LibHac.Fs.Fsa
|
||||
{
|
||||
public static class UserFileSystemPrivate
|
||||
{
|
||||
public static Result CreateFile(this FileSystemClient fs, U8Span path, long size, CreateFileOptions options)
|
||||
{
|
||||
Result rc;
|
||||
U8Span subPath;
|
||||
FileSystemAccessor fileSystem;
|
||||
Span<byte> logBuffer = stackalloc byte[0x300];
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fs.Impl.FindFileSystem(out fileSystem, out subPath, path);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var sb = new U8StringBuilder(logBuffer, true);
|
||||
sb.Append(LogPath).Append(path).Append((byte)'"');
|
||||
logBuffer = sb.Buffer;
|
||||
|
||||
fs.Impl.OutputAccessLogUnlessResultSuccess(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fs.Impl.FindFileSystem(out fileSystem, out subPath, path);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (fs.Impl.IsEnabledAccessLog() && fileSystem.IsEnabledAccessLog())
|
||||
{
|
||||
Tick start = fs.Hos.Os.GetSystemTick();
|
||||
rc = fileSystem.CreateFile(subPath, size, options);
|
||||
Tick end = fs.Hos.Os.GetSystemTick();
|
||||
|
||||
var sb = new U8StringBuilder(logBuffer, true);
|
||||
sb.Append(LogPath).Append(path).Append(LogSize).AppendFormat(size);
|
||||
logBuffer = sb.Buffer;
|
||||
|
||||
fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(logBuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = fileSystem.CreateFile(subPath, size, options);
|
||||
}
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
public static Result GetTotalSpaceSize(this FileSystemClient fs, out long totalSpace, U8Span path)
|
||||
{
|
||||
Unsafe.SkipInit(out totalSpace);
|
||||
|
||||
Result rc = fs.Impl.FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = fileSystem.GetFreeSpaceSize(out totalSpace, subPath);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
public static Result SetConcatenationFileAttribute(this FileSystemClient fs, U8Span path)
|
||||
{
|
||||
Result rc = fs.Impl.FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = fileSystem.QueryEntry(Span<byte>.Empty, ReadOnlySpan<byte>.Empty, QueryId.MakeConcatFile, subPath);
|
||||
fs.Impl.AbortIfNeeded(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
private static ReadOnlySpan<byte> LogPath => // ", path: ""
|
||||
new[]
|
||||
{
|
||||
(byte)',', (byte)' ', (byte)'p', (byte)'a', (byte)'t', (byte)'h', (byte)':', (byte)' ',
|
||||
(byte)'"'
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> LogSize => // "", size: "
|
||||
new[]
|
||||
{
|
||||
(byte)'"', (byte)',', (byte)' ', (byte)'s', (byte)'i', (byte)'z', (byte)'e', (byte)':',
|
||||
(byte)' '
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs.Impl;
|
||||
|
||||
namespace LibHac.Fs.Fsa
|
||||
|
@ -18,17 +17,17 @@ namespace LibHac.Fs.Fsa
|
|||
{
|
||||
public static Result Register(this FileSystemClientImpl fs, FileSystemAccessor fileSystem)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return fs.Globals.UserMountTable.MountTable.Mount(fileSystem);
|
||||
}
|
||||
|
||||
public static Result Find(this FileSystemClientImpl fs, out FileSystemAccessor fileSystem, U8Span name)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return fs.Globals.UserMountTable.MountTable.Find(out fileSystem, name);
|
||||
}
|
||||
|
||||
public static void Unregister(this FileSystemClientImpl fs, U8Span name)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
fs.Globals.UserMountTable.MountTable.Unmount(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -934,6 +934,8 @@ namespace LibHac.Fs
|
|||
public static Result.Base UnexpectedErrorInHostFileGetSize => new Result.Base(ModuleFs, 5308);
|
||||
/// <summary>Error code: 2002-5309; Inner value: 0x297a02</summary>
|
||||
public static Result.Base UnknownHostFileSystemError => new Result.Base(ModuleFs, 5309);
|
||||
/// <summary>Error code: 2002-5319; Inner value: 0x298e02</summary>
|
||||
public static Result.Base UnexpectedInMountUtilityA => new Result.Base(ModuleFs, 5319);
|
||||
/// <summary>Error code: 2002-5320; Inner value: 0x299002</summary>
|
||||
public static Result.Base InvalidNcaMountPoint => new Result.Base(ModuleFs, 5320);
|
||||
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
namespace LibHac.Fs
|
||||
using LibHac.Ncm;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
public static class SaveData
|
||||
{
|
||||
public const ulong SaveIndexerId = 0x8000000000000000;
|
||||
public static ProgramId InvalidProgramId => ProgramId.InvalidId;
|
||||
public static ProgramId AutoResolveCallerProgramId => new ProgramId(ulong.MaxValue - 1);
|
||||
}
|
||||
}
|
|
@ -10,6 +10,55 @@ namespace LibHac.Fs.Shim
|
|||
{
|
||||
public static class SaveDataManagement
|
||||
{
|
||||
internal static Result ReadSaveDataFileSystemExtraData(this FileSystemClientImpl fs,
|
||||
out SaveDataExtraData extraData, ulong saveDataId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal static Result ReadSaveDataFileSystemExtraData(this FileSystemClientImpl fs,
|
||||
out SaveDataExtraData extraData, SaveDataSpaceId spaceId, ulong saveDataId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal static Result ReadSaveDataFileSystemExtraData(this FileSystemClientImpl fs,
|
||||
out SaveDataExtraData extraData, SaveDataSpaceId spaceId, in SaveDataAttribute attribute)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal static Result ReadSaveDataFileSystemExtraData(this FileSystemClientImpl fs,
|
||||
out SaveDataExtraData extraData, SaveDataSpaceId spaceId, in SaveDataAttribute attribute,
|
||||
in SaveDataExtraData extraDataMask)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal static Result WriteSaveDataFileSystemExtraData(this FileSystemClientImpl fs, SaveDataSpaceId spaceId,
|
||||
ulong saveDataId, in SaveDataExtraData extraData)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal static Result WriteSaveDataFileSystemExtraData(this FileSystemClientImpl fs, SaveDataSpaceId spaceId,
|
||||
ulong saveDataId, in SaveDataExtraData extraData, in SaveDataExtraData extraDataMask)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal static Result WriteSaveDataFileSystemExtraData(this FileSystemClientImpl fs, SaveDataSpaceId spaceId,
|
||||
in SaveDataAttribute attribute, in SaveDataExtraData extraData, in SaveDataExtraData extraDataMask)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal static Result FindSaveDataWithFilter(this FileSystemClientImpl fs, out SaveDataInfo saveInfo,
|
||||
SaveDataSpaceId spaceId, in SaveDataFilter filter)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static Result CreateSaveData(this FileSystemClient fs, Ncm.ApplicationId applicationId, UserId userId,
|
||||
ulong ownerId, long size, long journalSize, SaveDataFlags flags)
|
||||
{
|
||||
|
@ -42,39 +91,6 @@ namespace LibHac.Fs.Shim
|
|||
$", applicationid: 0x{applicationId.Value:X}, userid: 0x{userId}, save_data_owner_id: 0x{ownerId:X}, save_data_size: {size}, save_data_journal_size: {journalSize}, save_data_flags: 0x{(int)flags:X8}");
|
||||
}
|
||||
|
||||
public static Result CreateSaveData(this FileSystemClient fs, Ncm.ApplicationId applicationId, UserId userId,
|
||||
ulong ownerId, long size, long journalSize, HashSalt hashSalt, SaveDataFlags flags)
|
||||
{
|
||||
return fs.RunOperationWithAccessLog(AccessLogTarget.System,
|
||||
() =>
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
var attribute = new SaveDataAttribute(applicationId, SaveDataType.Account, userId, 0);
|
||||
|
||||
var createInfo = new SaveDataCreationInfo
|
||||
{
|
||||
Size = size,
|
||||
JournalSize = journalSize,
|
||||
BlockSize = 0x4000,
|
||||
OwnerId = ownerId,
|
||||
Flags = flags,
|
||||
SpaceId = SaveDataSpaceId.User
|
||||
};
|
||||
|
||||
var metaInfo = new SaveDataMetaInfo
|
||||
{
|
||||
Type = SaveDataMetaType.Thumbnail,
|
||||
Size = 0x40060
|
||||
};
|
||||
|
||||
return fsProxy.Target.CreateSaveDataFileSystemWithHashSalt(in attribute, in createInfo, in metaInfo,
|
||||
in hashSalt);
|
||||
},
|
||||
() =>
|
||||
$", applicationid: 0x{applicationId.Value:X}, userid: 0x{userId}, save_data_owner_id: 0x{ownerId:X}, save_data_size: {size}, save_data_journal_size: {journalSize}, save_data_flags: 0x{(int)flags:X8}");
|
||||
}
|
||||
|
||||
public static Result CreateBcatSaveData(this FileSystemClient fs, Ncm.ApplicationId applicationId, long size)
|
||||
{
|
||||
return fs.RunOperationWithAccessLog(AccessLogTarget.System,
|
||||
|
@ -128,6 +144,159 @@ namespace LibHac.Fs.Shim
|
|||
() => $", applicationid: 0x{applicationId.Value:X}, save_data_owner_id: 0x{ownerId:X}, save_data_size: {size}, save_data_journal_size: {journalSize}, save_data_flags: 0x{(int)flags:X8}");
|
||||
}
|
||||
|
||||
public static Result DeleteSaveData(this FileSystemClient fs, ulong saveDataId)
|
||||
{
|
||||
return fs.RunOperationWithAccessLog(AccessLogTarget.System,
|
||||
() =>
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
return fsProxy.Target.DeleteSaveDataFileSystem(saveDataId);
|
||||
},
|
||||
() => $", savedataid: 0x{saveDataId:X}");
|
||||
}
|
||||
|
||||
public static Result DeleteSaveData(this FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId)
|
||||
{
|
||||
return fs.RunOperationWithAccessLog(AccessLogTarget.System,
|
||||
() =>
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
return fsProxy.Target.DeleteSaveDataFileSystemBySaveDataSpaceId(spaceId, saveDataId);
|
||||
},
|
||||
() => $", savedataspaceid: {spaceId}, savedataid: 0x{saveDataId:X}");
|
||||
}
|
||||
|
||||
public static Result OpenSaveDataIterator(this FileSystemClient fs, out SaveDataIterator iterator, SaveDataSpaceId spaceId)
|
||||
{
|
||||
var tempIterator = new SaveDataIterator();
|
||||
|
||||
try
|
||||
{
|
||||
Result result = fs.RunOperationWithAccessLog(AccessLogTarget.System,
|
||||
() =>
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.OpenSaveDataInfoReaderBySaveDataSpaceId(
|
||||
out ReferenceCountedDisposable<ISaveDataInfoReader> reader, spaceId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
tempIterator = new SaveDataIterator(fs, reader);
|
||||
|
||||
return Result.Success;
|
||||
},
|
||||
() => $", savedataspaceid: {spaceId}");
|
||||
|
||||
iterator = result.IsSuccess() ? tempIterator : default;
|
||||
tempIterator = default;
|
||||
|
||||
return result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
tempIterator.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public static Result OpenSaveDataIterator(this FileSystemClient fs, out SaveDataIterator iterator, SaveDataSpaceId spaceId, in SaveDataFilter filter)
|
||||
{
|
||||
ReferenceCountedDisposable<ISaveDataInfoReader> reader = null;
|
||||
var tempIterator = new SaveDataIterator();
|
||||
SaveDataFilter tempFilter = filter;
|
||||
|
||||
try
|
||||
{
|
||||
Result result = fs.RunOperationWithAccessLog(AccessLogTarget.System,
|
||||
() =>
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.OpenSaveDataInfoReaderWithFilter(out reader, spaceId, in tempFilter);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
tempIterator = new SaveDataIterator(fs, reader);
|
||||
|
||||
return Result.Success;
|
||||
},
|
||||
() => $", savedataspaceid: {spaceId}");
|
||||
|
||||
iterator = result.IsSuccess() ? tempIterator : default;
|
||||
|
||||
return result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
reader?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public static Result FindSaveDataWithFilter(this FileSystemClient fs, out SaveDataInfo info, SaveDataSpaceId spaceId,
|
||||
in SaveDataFilter filter)
|
||||
{
|
||||
info = default;
|
||||
|
||||
SaveDataFilter tempFilter = filter;
|
||||
var tempInfo = new SaveDataInfo();
|
||||
|
||||
Result result = fs.RunOperationWithAccessLog(AccessLogTarget.System,
|
||||
() =>
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
tempInfo = new SaveDataInfo();
|
||||
|
||||
Result rc = fsProxy.Target.FindSaveDataWithFilter(out long count,
|
||||
OutBuffer.FromStruct(ref tempInfo), spaceId, in tempFilter);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (count == 0)
|
||||
return ResultFs.TargetNotFound.Log();
|
||||
|
||||
return Result.Success;
|
||||
},
|
||||
() => $", savedataspaceid: {spaceId}");
|
||||
|
||||
if (result.IsSuccess())
|
||||
{
|
||||
info = tempInfo;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Result CreateSaveData(this FileSystemClient fs, Ncm.ApplicationId applicationId, UserId userId,
|
||||
ulong ownerId, long size, long journalSize, HashSalt hashSalt, SaveDataFlags flags)
|
||||
{
|
||||
return fs.RunOperationWithAccessLog(AccessLogTarget.System,
|
||||
() =>
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
var attribute = new SaveDataAttribute(applicationId, SaveDataType.Account, userId, 0);
|
||||
|
||||
var createInfo = new SaveDataCreationInfo
|
||||
{
|
||||
Size = size,
|
||||
JournalSize = journalSize,
|
||||
BlockSize = 0x4000,
|
||||
OwnerId = ownerId,
|
||||
Flags = flags,
|
||||
SpaceId = SaveDataSpaceId.User
|
||||
};
|
||||
|
||||
var metaInfo = new SaveDataMetaInfo
|
||||
{
|
||||
Type = SaveDataMetaType.Thumbnail,
|
||||
Size = 0x40060
|
||||
};
|
||||
|
||||
return fsProxy.Target.CreateSaveDataFileSystemWithHashSalt(in attribute, in createInfo, in metaInfo,
|
||||
in hashSalt);
|
||||
},
|
||||
() =>
|
||||
$", applicationid: 0x{applicationId.Value:X}, userid: 0x{userId}, save_data_owner_id: 0x{ownerId:X}, save_data_size: {size}, save_data_journal_size: {journalSize}, save_data_flags: 0x{(int)flags:X8}");
|
||||
}
|
||||
|
||||
public static Result CreateTemporaryStorage(this FileSystemClient fs, Ncm.ApplicationId applicationId, ulong ownerId, long size, SaveDataFlags flags)
|
||||
{
|
||||
return fs.RunOperationWithAccessLog(AccessLogTarget.System,
|
||||
|
@ -247,62 +416,6 @@ namespace LibHac.Fs.Shim
|
|||
return CreateSystemSaveData(fs, spaceId, saveDataId, UserId.InvalidId, ownerId, size, journalSize, flags);
|
||||
}
|
||||
|
||||
public static Result DeleteSaveData(this FileSystemClient fs, ulong saveDataId)
|
||||
{
|
||||
return fs.RunOperationWithAccessLog(AccessLogTarget.System,
|
||||
() =>
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
return fsProxy.Target.DeleteSaveDataFileSystem(saveDataId);
|
||||
},
|
||||
() => $", savedataid: 0x{saveDataId:X}");
|
||||
}
|
||||
|
||||
public static Result DeleteSaveData(this FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId)
|
||||
{
|
||||
return fs.RunOperationWithAccessLog(AccessLogTarget.System,
|
||||
() =>
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
return fsProxy.Target.DeleteSaveDataFileSystemBySaveDataSpaceId(spaceId, saveDataId);
|
||||
},
|
||||
() => $", savedataspaceid: {spaceId}, savedataid: 0x{saveDataId:X}");
|
||||
}
|
||||
|
||||
public static Result FindSaveDataWithFilter(this FileSystemClient fs, out SaveDataInfo info, SaveDataSpaceId spaceId,
|
||||
ref SaveDataFilter filter)
|
||||
{
|
||||
info = default;
|
||||
|
||||
SaveDataFilter tempFilter = filter;
|
||||
var tempInfo = new SaveDataInfo();
|
||||
|
||||
Result result = fs.RunOperationWithAccessLog(AccessLogTarget.System,
|
||||
() =>
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
tempInfo = new SaveDataInfo();
|
||||
|
||||
Result rc = fsProxy.Target.FindSaveDataWithFilter(out long count,
|
||||
OutBuffer.FromStruct(ref tempInfo), spaceId, in tempFilter);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (count == 0)
|
||||
return ResultFs.TargetNotFound.Log();
|
||||
|
||||
return Result.Success;
|
||||
},
|
||||
() => $", savedataspaceid: {spaceId}");
|
||||
|
||||
if (result.IsSuccess())
|
||||
{
|
||||
info = tempInfo;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Result QuerySaveDataTotalSize(this FileSystemClient fs, out long totalSize, long size, long journalSize)
|
||||
{
|
||||
totalSize = default;
|
||||
|
@ -326,70 +439,6 @@ namespace LibHac.Fs.Shim
|
|||
return result;
|
||||
}
|
||||
|
||||
public static Result OpenSaveDataIterator(this FileSystemClient fs, out SaveDataIterator iterator, SaveDataSpaceId spaceId)
|
||||
{
|
||||
var tempIterator = new SaveDataIterator();
|
||||
|
||||
try
|
||||
{
|
||||
Result result = fs.RunOperationWithAccessLog(AccessLogTarget.System,
|
||||
() =>
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.OpenSaveDataInfoReaderBySaveDataSpaceId(
|
||||
out ReferenceCountedDisposable<ISaveDataInfoReader> reader, spaceId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
tempIterator = new SaveDataIterator(fs, reader);
|
||||
|
||||
return Result.Success;
|
||||
},
|
||||
() => $", savedataspaceid: {spaceId}");
|
||||
|
||||
iterator = result.IsSuccess() ? tempIterator : default;
|
||||
tempIterator = default;
|
||||
|
||||
return result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
tempIterator.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public static Result OpenSaveDataIterator(this FileSystemClient fs, out SaveDataIterator iterator, SaveDataSpaceId spaceId, ref SaveDataFilter filter)
|
||||
{
|
||||
ReferenceCountedDisposable<ISaveDataInfoReader> reader = null;
|
||||
var tempIterator = new SaveDataIterator();
|
||||
SaveDataFilter tempFilter = filter;
|
||||
|
||||
try
|
||||
{
|
||||
Result result = fs.RunOperationWithAccessLog(AccessLogTarget.System,
|
||||
() =>
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fs.Impl.GetFileSystemProxyServiceObject();
|
||||
|
||||
Result rc = fsProxy.Target.OpenSaveDataInfoReaderWithFilter(out reader, spaceId, in tempFilter);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
tempIterator = new SaveDataIterator(fs, reader);
|
||||
|
||||
return Result.Success;
|
||||
},
|
||||
() => $", savedataspaceid: {spaceId}");
|
||||
|
||||
iterator = result.IsSuccess() ? tempIterator : default;
|
||||
|
||||
return result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
reader?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public static void DisableAutoSaveDataCreation(this FileSystemClient fsClient)
|
||||
{
|
||||
using ReferenceCountedDisposable<IFileSystemProxy> fsProxy = fsClient.Impl.GetFileSystemProxyServiceObject();
|
||||
|
|
Loading…
Reference in a new issue