From e19765445de0dcb1271ef20e3b4a0e6e7e606acc Mon Sep 17 00:00:00 2001 From: SciresM Date: Fri, 9 Nov 2018 19:03:47 -0800 Subject: [PATCH] fs: Add fsFsQueryEntry (and fsFsSetArchiveBit helper) (#202) * fs: Add fsFsSetArchiveBit * Add fsdevSetArchiveBit wrapper --- nx/include/switch/runtime/devices/fs_dev.h | 3 ++ nx/include/switch/services/fs.h | 10 +++++ nx/source/runtime/devices/fs_dev.c | 10 +++++ nx/source/services/fs.c | 47 ++++++++++++++++++++++ 4 files changed, 70 insertions(+) diff --git a/nx/include/switch/runtime/devices/fs_dev.h b/nx/include/switch/runtime/devices/fs_dev.h index b80467db..da17640b 100644 --- a/nx/include/switch/runtime/devices/fs_dev.h +++ b/nx/include/switch/runtime/devices/fs_dev.h @@ -42,5 +42,8 @@ FsFileSystem* fsdevGetDeviceFileSystem(const char *name); /// Returns the FsFileSystem for the default device (SD card), if mounted. Used internally by romfs_dev. FsFileSystem* fsdevGetDefaultFileSystem(void); +/// This calls fsFsSetArchiveBit on the filesystem specified by the input absolute path. +Result fsdevSetArchiveBit(const char *path); + /// Unmounts all devices and cleans up any resources used by the FS driver. Result fsdevUnmountAll(void); diff --git a/nx/include/switch/services/fs.h b/nx/include/switch/services/fs.h index dfa14822..ce2341b5 100644 --- a/nx/include/switch/services/fs.h +++ b/nx/include/switch/services/fs.h @@ -178,6 +178,11 @@ typedef enum FsFileSystemType_ApplicationPackage = 7 } FsFileSystemType; +typedef enum +{ + FsFileSystemQueryType_SetArchiveBit = 0, +} FsFileSystemQueryType; + /// Mount requested filesystem type from content file Result fsOpenFileSystem(FsFileSystem* out, FsFileSystemType fsType, const char* contentPath); /// same as calling fsOpenFileSystemWithId with 0 as titleId Result fsOpenFileSystemWithId(FsFileSystem* out, u64 titleId, FsFileSystemType fsType, const char* contentPath); /// works on all firmwares, titleId is ignored on 1.0.0 @@ -197,8 +202,13 @@ Result fsFsCommit(FsFileSystem* fs); Result fsFsGetFreeSpace(FsFileSystem* fs, const char* path, u64* out); Result fsFsGetTotalSpace(FsFileSystem* fs, const char* path, u64* out); Result fsFsCleanDirectoryRecursively(FsFileSystem* fs, const char* path); +Result fsFsQueryEntry(FsFileSystem* fs, void *out, size_t out_size, const void *in, size_t in_size, const char* path, FsFileSystemQueryType query_type); void fsFsClose(FsFileSystem* fs); +/// Uses fsFsQueryEntry to set the archive bit on the specified absolute directory path. +/// This will cause HOS to treat the directory as if it were a file containing the directory's concatenated contents. +Result fsFsSetArchiveBit(FsFileSystem* fs, const char *path); + // IFile Result fsFileRead(FsFile* f, u64 off, void* buf, size_t len, size_t* out); Result fsFileWrite(FsFile* f, u64 off, const void* buf, size_t len); diff --git a/nx/source/runtime/devices/fs_dev.c b/nx/source/runtime/devices/fs_dev.c index 69064419..aed1ec3e 100644 --- a/nx/source/runtime/devices/fs_dev.c +++ b/nx/source/runtime/devices/fs_dev.c @@ -368,6 +368,16 @@ Result fsdevCommitDevice(const char *name) return fsFsCommit(&device->fs); } +Result fsdevSetArchiveBit(const char *path) { + char fs_path[FS_MAX_PATH]; + fsdev_fsdevice *device = NULL; + + if(fsdev_getfspath(_REENT, path, &device, fs_path)==-1) + return MAKERESULT(Module_Libnx, LibnxError_NotFound); + + return fsFsSetArchiveBit(&device->fs, fs_path); +} + /*! Initialize SDMC device */ Result fsdevMountSdmc(void) { diff --git a/nx/source/services/fs.c b/nx/source/services/fs.c index 2967b0c4..5ef5a941 100644 --- a/nx/source/services/fs.c +++ b/nx/source/services/fs.c @@ -1007,6 +1007,53 @@ Result fsFsCleanDirectoryRecursively(FsFileSystem* fs, const char* path) { return rc; } +Result fsFsQueryEntry(FsFileSystem* fs, void *out, size_t out_size, const void *in, size_t in_size, const char* path, FsFileSystemQueryType query_type) { + if (!kernelAbove400()) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + char send_path[FS_MAX_PATH] = {0}; + strncpy(send_path, path, sizeof(send_path)-1); + + IpcCommand c; + ipcInitialize(&c); + ipcAddSendStatic(&c, send_path, sizeof(send_path), 0); + ipcAddSendBuffer(&c, in, in_size, BufferType_Type1); + ipcAddRecvBuffer(&c, out, out_size, BufferType_Type1); + + struct { + u64 magic; + u64 cmd_id; + u32 query_type; + } *raw; + + raw = serviceIpcPrepareHeader(&fs->s, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 15; + raw->query_type = query_type; + + Result rc = serviceIpcDispatch(&fs->s); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(&fs->s, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result fsFsSetArchiveBit(FsFileSystem* fs, const char *path) { + return fsFsQueryEntry(fs, NULL, 0, NULL, 0, path, FsFileSystemQueryType_SetArchiveBit); +} + void fsFsClose(FsFileSystem* fs) { serviceClose(&fs->s); }