]> Chaos Git - corbenik/ctrulib.git/commitdiff
Separate information required to open an archive from the actual opened handle.
authorSteven Smith <Steveice10@gmail.com>
Fri, 29 Apr 2016 03:38:15 +0000 (20:38 -0700)
committerSteven Smith <Steveice10@gmail.com>
Fri, 6 May 2016 22:25:20 +0000 (15:25 -0700)
libctru/include/3ds/services/fs.h
libctru/source/internal.h
libctru/source/ndsp/ndsp.c
libctru/source/os-versionbin.c
libctru/source/romfs_dev.c
libctru/source/sdmc_dev.c
libctru/source/services/fs.c

index 2db8f818a7d5b64e162b3a00515e8f157d6b0a73..f1f118913874e669832e2c43ee47102deb3bee89 100644 (file)
@@ -226,7 +226,7 @@ typedef struct
        u8 encryptParameter[0x10]; ///< Encrypt parameter.
 } FS_DeviceMoveContext;
 
-/// FS path.
+/// Filesystem path data, detailing the specific target of an operation.
 typedef struct
 {
        FS_PathType type; ///< FS path type.
@@ -234,13 +234,8 @@ typedef struct
        const void* data; ///< Pointer to FS path data.
 } FS_Path;
 
-/// FS archive.
-typedef struct
-{
-       u32 id;          ///< Archive ID.
-       FS_Path lowPath; ///< FS path.
-       u64 handle;      ///< Handle.
-} FS_Archive;
+/// Filesystem archive handle, providing access to a filesystem's contents.
+typedef u64 FS_Archive;
 
 /// Initializes FS.
 Result fsInit(void);
@@ -251,13 +246,25 @@ void fsExit(void);
 /**
  * @brief Sets the FSUSER session to use in the current thread.
  * @param session The handle of the FSUSER session to use.
- * @param sdmc When true, SDMC archive commands are redirected to this session too. Otherwise the default session is used.
  */
-void fsUseSession(Handle session, bool sdmc);
+void fsUseSession(Handle session);
 
 /// Disables the FSUSER session override in the current thread.
 void fsEndUseSession(void);
 
+/**
+ * @brief Exempts an archive from using alternate FS session handles provided with @ref fsUseSession
+ * Instead, the archive will use the default FS session handle, opened with @ref srvGetSessionHandle
+ * @param archive Archive to exempt.
+ */
+void fsExemptFromSession(FS_Archive archive);
+
+/**
+ * @brief Unexempts an archive from using alternate FS session handles provided with @ref fsUseSession
+ * @param archive Archive to remove from the exemption list.
+ */
+void fsUnexemptFromSession(FS_Archive archive);
+
 /**
  * @brief Creates an FS_Path instance.
  * @param type Type of path.
@@ -299,14 +306,15 @@ Result FSUSER_Initialize(Handle session);
 Result FSUSER_OpenFile(Handle* out, FS_Archive archive, FS_Path path, u32 openFlags, u32 attributes);
 
 /**
- * @brief Opens a file directly.
+ * @brief Opens a file directly, bypassing the requirement of an opened archive handle.
  * @param out Pointer to output the file handle to.
- * @param archive Archive containing the file.
- * @param path Path of the file.
+ * @param archiveId ID of the archive containing the file.
+ * @param archivePath Path of the archive containing the file.
+ * @param filePath Path of the file.
  * @param openFlags Flags to open the file with.
  * @param attributes Attributes of the file.
  */
-Result FSUSER_OpenFileDirectly(Handle* out, FS_Archive archive, FS_Path path, u32 openFlags, u32 attributes);
+Result FSUSER_OpenFileDirectly(Handle* out, FS_ArchiveID archiveId, FS_Path archivePath, FS_Path filePath, u32 openFlags, u32 attributes);
 
 /**
  * @brief Deletes a file.
@@ -340,7 +348,7 @@ Result FSUSER_DeleteDirectoryRecursively(FS_Archive archive, FS_Path path);
 
 /**
  * @brief Creates a file.
- * @param archive Archive containing the file.
+ * @param archive Archive to create the file in.
  * @param path Path of the file.
  * @param attributes Attributes of the file.
  * @param fileSize Size of the file.
@@ -349,7 +357,7 @@ Result FSUSER_CreateFile(FS_Archive archive, FS_Path path, u32 attributes, u64 f
 
 /**
  * @brief Creates a directory
- * @param archive Archive containing the directory.
+ * @param archive Archive to create the directory in.
  * @param path Path of the directory.
  * @param attributes Attributes of the directory.
  */
@@ -374,9 +382,11 @@ Result FSUSER_OpenDirectory(Handle *out, FS_Archive archive, FS_Path path);
 
 /**
  * @brief Opens an archive.
- * @param archive Archive to open.
+ * @param archive Pointer to output the opened archive to.
+ * @param id ID of the archive.
+ * @param path Path of the archive.
  */
-Result FSUSER_OpenArchive(FS_Archive* archive);
+Result FSUSER_OpenArchive(FS_Archive* archive, FS_ArchiveID id, FS_Path path);
 
 /**
  * @brief Performs a control operation on an archive.
@@ -393,7 +403,7 @@ Result FSUSER_ControlArchive(FS_Archive archive, FS_ArchiveAction action, void*
  * @brief Closes an archive.
  * @param archive Archive to close.
  */
-Result FSUSER_CloseArchive(FS_Archive* archive);
+Result FSUSER_CloseArchive(FS_Archive archive);
 
 /**
  * @brief Gets the number of free bytes within an archive.
index 65ba9a6b629dc76e63b16201eaf6ae1b96fec8bd..09316d12f9750e33d2f6e1e3082c465dad10e43c 100644 (file)
@@ -26,7 +26,6 @@ typedef struct
        // FS session override
        u32    fs_magic;
        Handle fs_session;
-       bool   fs_sdmc;
 } ThreadVars;
 
 static inline ThreadVars* getThreadVars(void)
index 1b5fce12379a5c5be243ff2d798a84eed14453df..867eeb5aed348d2e71e686412d4c86e4f2ea8e1a 100644 (file)
@@ -398,10 +398,10 @@ static bool ndspFindAndLoadComponent(void)
        do
        {
                static const char dsp_filename[] = "/3ds/dspfirm.cdc";
-               FS_Archive arch = { ARCHIVE_SDMC, { PATH_EMPTY, 1, (u8*)"" }, 0 };
-               FS_Path path = { PATH_ASCII, sizeof(dsp_filename), (u8*)dsp_filename };
+               FS_Path archPath = { PATH_EMPTY, 1, (u8*)"" };
+               FS_Path filePath = { PATH_ASCII, sizeof(dsp_filename), (u8*)dsp_filename };
 
-               rc = FSUSER_OpenFileDirectly(&rsrc, arch, path, FS_OPEN_READ, 0);
+               rc = FSUSER_OpenFileDirectly(&rsrc, ARCHIVE_SDMC, archPath, filePath, FS_OPEN_READ, 0);
                if (R_FAILED(rc)) break;
 
                u64 size = 0;
index 464903d0ee34cba5b5c3b66d741990abd0a8a9c3..a7fe0a56a2d2b036a19804a789eebc1545cf0494 100644 (file)
@@ -36,13 +36,13 @@ static u32 __CVer_tidlow_regionarray[7] = {
 };
 
 
-static Result __read_versionbin(FS_Archive archive, FS_Path fileLowPath, OS_VersionBin *versionbin)
+static Result __read_versionbin(FS_ArchiveID archiveId, FS_Path archivePath, FS_Path fileLowPath, OS_VersionBin *versionbin)
 {
        Result ret = 0;
        Handle filehandle = 0;
        FILE *f = NULL;
 
-       ret = FSUSER_OpenFileDirectly(&filehandle, archive, fileLowPath, FS_OPEN_READ, 0x0);
+       ret = FSUSER_OpenFileDirectly(&filehandle, archiveId, archivePath, fileLowPath, FS_OPEN_READ, 0x0);
        if(R_FAILED(ret))return ret;
 
        ret = romfsInitFromFile(filehandle, 0x0);
@@ -72,16 +72,17 @@ Result osGetSystemVersionData(OS_VersionBin *nver_versionbin, OS_VersionBin *cve
        u32 archive_lowpath_data[0x10>>2];
        u32 file_lowpath_data[0x14>>2];
 
-       FS_Archive archive;
+       FS_ArchiveID archiveId;
+       FS_Path archivePath;
        FS_Path fileLowPath;
 
        memset(archive_lowpath_data, 0, sizeof(archive_lowpath_data));
        memset(file_lowpath_data,    0, sizeof(file_lowpath_data));
 
-       archive.id = 0x2345678a;
-       archive.lowPath.type = PATH_BINARY;
-       archive.lowPath.size = 0x10;
-       archive.lowPath.data = archive_lowpath_data;
+       archiveId = 0x2345678a;
+       archivePath.type = PATH_BINARY;
+       archivePath.size = 0x10;
+       archivePath.data = archive_lowpath_data;
 
        fileLowPath.type = PATH_BINARY;
        fileLowPath.size = 0x14;
@@ -100,11 +101,11 @@ Result osGetSystemVersionData(OS_VersionBin *nver_versionbin, OS_VersionBin *cve
        cfguExit();
 
        archive_lowpath_data[0] = __NVer_tidlow_regionarray[region];
-       ret = __read_versionbin(archive, fileLowPath, nver_versionbin);
+       ret = __read_versionbin(archiveId, archivePath, fileLowPath, nver_versionbin);
        if(R_FAILED(ret))return ret;
 
        archive_lowpath_data[0] = __CVer_tidlow_regionarray[region];
-       ret = __read_versionbin(archive, fileLowPath, cver_versionbin);
+       ret = __read_versionbin(archiveId, archivePath, fileLowPath, cver_versionbin);
        return ret;
 }
 
index 7006e713c1b01ea705472e7a5f64afe56891256d..a7d0e694b89a586717368275880149dfeb60362e 100644 (file)
@@ -121,7 +121,7 @@ typedef struct
 } _3DSX_Header;
 
 static Result romfsInitCommon(void);
-static void   romfsInitMtime(FS_Archive arch, FS_Path path);
+static void   romfsInitMtime(FS_ArchiveID archId, FS_Path archPath, FS_Path filePath);
 
 __attribute__((weak)) const char* __romfs_path = NULL;
 
@@ -152,13 +152,13 @@ Result romfsInit(void)
                if (units >= PATH_MAX) return 4;
                __utf16path[units] = 0;
 
-               FS_Archive arch = { ARCHIVE_SDMC, { PATH_EMPTY, 1, (u8*)"" }, 0 };
-               FS_Path path = { PATH_UTF16, (units+1)*2, (u8*)__utf16path };
+               FS_Path archPath = { PATH_EMPTY, 1, (u8*)"" };
+               FS_Path filePath = { PATH_UTF16, (units+1)*2, (u8*)__utf16path };
 
-               Result rc = FSUSER_OpenFileDirectly(&romFS_file, arch, path, FS_OPEN_READ, 0);
+               Result rc = FSUSER_OpenFileDirectly(&romFS_file, ARCHIVE_SDMC, archPath, filePath, FS_OPEN_READ, 0);
                if (R_FAILED(rc)) return rc;
 
-               romfsInitMtime(arch, path);
+               romfsInitMtime(ARCHIVE_SDMC, archPath, filePath);
 
                _3DSX_Header hdr;
                if (!_romfs_read_chk(0, &hdr, sizeof(hdr))) goto _fail0;
@@ -172,13 +172,13 @@ Result romfsInit(void)
                u8 zeros[0xC];
                memset(zeros, 0, sizeof(zeros));
 
-               FS_Archive arch = { ARCHIVE_ROMFS, { PATH_EMPTY, 1, (u8*)"" }, 0 };
-               FS_Path path = { PATH_BINARY, sizeof(zeros), zeros };
+               FS_Path archPath = { PATH_EMPTY, 1, (u8*)"" };
+               FS_Path filePath = { PATH_BINARY, sizeof(zeros), zeros };
 
-               Result rc = FSUSER_OpenFileDirectly(&romFS_file, arch, path, FS_OPEN_READ, 0);
+               Result rc = FSUSER_OpenFileDirectly(&romFS_file, ARCHIVE_ROMFS, archPath, filePath, FS_OPEN_READ, 0);
                if (R_FAILED(rc)) return rc;
 
-               romfsInitMtime(arch, path);
+               romfsInitMtime(ARCHIVE_ROMFS, archPath, filePath);
        }
 
        return romfsInitCommon();
@@ -237,20 +237,21 @@ _fail0:
        return 10;
 }
 
-static void romfsInitMtime(FS_Archive arch, FS_Path path)
+static void romfsInitMtime(FS_ArchiveID archId, FS_Path archPath, FS_Path filePath)
 {
        u64 mtime;
+       FS_Archive arch;
        Result rc;
 
        romFS_mtime = time(NULL);
-       rc = FSUSER_OpenArchive(&arch);
+       rc = FSUSER_OpenArchive(&arch, archId, archPath);
        if (R_FAILED(rc))
                return;
 
        rc = FSUSER_ControlArchive(arch, ARCHIVE_ACTION_GET_TIMESTAMP,
-                                  (void*)path.data, path.size,
+                                  (void*)filePath.data, filePath.size,
                                   &mtime, sizeof(mtime));
-       FSUSER_CloseArchive(&arch);
+       FSUSER_CloseArchive(arch);
        if (R_FAILED(rc))
                return;
 
index fa9af99a6754e205265f06ef19af2bb021221852..fbc6df89a1e765835114e15ac4d89975005e128f 100644 (file)
@@ -91,16 +91,7 @@ sdmc_devoptab =
 };
 
 /*! SDMC archive handle */
-static FS_Archive sdmcArchive =
-{
-  .id = ARCHIVE_SDMC,
-  .lowPath =
-  {
-    .type = PATH_EMPTY,
-    .size = 1,
-    .data = (u8*)"",
-  },
-};
+static FS_Archive sdmcArchive;
 
 /*! @endcond */
 
@@ -216,14 +207,17 @@ Result sdmcInit(void)
   ssize_t  units;
   uint32_t code;
   char     *p;
+  FS_Path sdmcPath = { PATH_EMPTY, 1, (u8*)"" };
   Result   rc = 0;
 
   if(sdmcInitialised)
     return rc;
 
-  rc = FSUSER_OpenArchive(&sdmcArchive);
+
+  rc = FSUSER_OpenArchive(&sdmcArchive, ARCHIVE_SDMC, sdmcPath);
   if(R_SUCCEEDED(rc))
   {
+    fsExemptFromSession(sdmcArchive);
 
     int dev = AddDevice(&sdmc_devoptab);
 
@@ -296,9 +290,10 @@ Result sdmcExit(void)
 
   if(!sdmcInitialised) return rc;
 
-  rc = FSUSER_CloseArchive(&sdmcArchive);
+  rc = FSUSER_CloseArchive(sdmcArchive);
   if(R_SUCCEEDED(rc))
   {
+    fsUnexemptFromSession(sdmcArchive);
     RemoveDevice("sdmc:");
     sdmcInitialised = false;
   }
index fb622f3b721e2d46ac2e800fc2dd60e46341e234..3470283320ec81c87dc63d98c57fe296dff013ea 100644 (file)
@@ -9,20 +9,30 @@
 #include <3ds/env.h>
 #include "../internal.h"
 
+#define FS_MAX_EXEMPT_ARCHIVE_HANDLES 16
+
 static Handle fsuHandle;
 static int fsuRefCount;
 
-static Handle fsSessionForArchive(FS_ArchiveID arch)
+static FS_Archive fsExemptArchives[FS_MAX_EXEMPT_ARCHIVE_HANDLES];
+
+static Handle fsSession(void)
 {
        ThreadVars* tv = getThreadVars();
-       if (tv->fs_magic == FS_OVERRIDE_MAGIC && (arch != ARCHIVE_SDMC || tv->fs_sdmc))
+       if (tv->fs_magic == FS_OVERRIDE_MAGIC)
                return tv->fs_session;
        return fsuHandle;
 }
 
-static Handle fsSession(void)
+static Handle fsSessionForArchive(FS_Archive archive)
 {
-       return fsSessionForArchive(0);
+       for (int i = 0; i < FS_MAX_EXEMPT_ARCHIVE_HANDLES; i++)
+       {
+               if (fsExemptArchives[i] == archive)
+                       return fsuHandle;
+       }
+
+       return fsSession();
 }
 
 Result fsInit(void)
@@ -48,12 +58,11 @@ void fsExit(void)
        svcCloseHandle(fsuHandle);
 }
 
-void fsUseSession(Handle session, bool sdmc)
+void fsUseSession(Handle session)
 {
        ThreadVars* tv = getThreadVars();
        tv->fs_magic   = FS_OVERRIDE_MAGIC;
        tv->fs_session = session;
-       tv->fs_sdmc    = sdmc;
 }
 
 void fsEndUseSession(void)
@@ -62,6 +71,34 @@ void fsEndUseSession(void)
        tv->fs_magic   = 0;
 }
 
+void fsExemptFromSession(FS_Archive archive)
+{
+       int freeIndex = -1;
+       for (int i = 0; i < FS_MAX_EXEMPT_ARCHIVE_HANDLES; i++)
+       {
+               if (fsExemptArchives[i] == archive)
+                       return;
+
+               if (freeIndex == -1 && fsExemptArchives[i] == 0)
+                       freeIndex = i;
+       }
+
+       if (freeIndex != -1)
+               fsExemptArchives[freeIndex] = archive;
+}
+
+void fsUnexemptFromSession(FS_Archive archive)
+{
+       for (int i = 0; i < FS_MAX_EXEMPT_ARCHIVE_HANDLES; i++)
+       {
+               if (fsExemptArchives[i] == archive)
+               {
+                       fsExemptArchives[i] = 0;
+                       break;
+               }
+       }
+}
+
 FS_Path fsMakePath(FS_PathType type, const void* path)
 {
        FS_Path p = { type, 0, path };
@@ -129,8 +166,8 @@ Result FSUSER_OpenFile(Handle* out, FS_Archive archive, FS_Path path, u32 openFl
 
        cmdbuf[0] = IPC_MakeHeader(0x802,7,2); // 0x80201C2
        cmdbuf[1] = 0;
-       cmdbuf[2] = (u32) archive.handle;
-       cmdbuf[3] = (u32) (archive.handle >> 32);
+       cmdbuf[2] = (u32) archive;
+       cmdbuf[3] = (u32) (archive >> 32);
        cmdbuf[4] = path.type;
        cmdbuf[5] = path.size;
        cmdbuf[6] = openFlags;
@@ -139,33 +176,33 @@ Result FSUSER_OpenFile(Handle* out, FS_Archive archive, FS_Path path, u32 openFl
        cmdbuf[9] = (u32) path.data;
 
        Result ret = 0;
-       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive.id)))) return ret;
+       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive)))) return ret;
 
        if(out) *out = cmdbuf[3];
 
        return cmdbuf[1];
 }
 
-Result FSUSER_OpenFileDirectly(Handle* out, FS_Archive archive, FS_Path path, u32 openFlags, u32 attributes)
+Result FSUSER_OpenFileDirectly(Handle* out, FS_ArchiveID archiveId, FS_Path archivePath, FS_Path filePath, u32 openFlags, u32 attributes)
 {
        u32 *cmdbuf = getThreadCommandBuffer();
 
        cmdbuf[0] = IPC_MakeHeader(0x803,8,4); // 0x8030204
        cmdbuf[1] = 0;
-       cmdbuf[2] = archive.id;
-       cmdbuf[3] = archive.lowPath.type;
-       cmdbuf[4] = archive.lowPath.size;
-       cmdbuf[5] = path.type;
-       cmdbuf[6] = path.size;
+       cmdbuf[2] = archiveId;
+       cmdbuf[3] = archivePath.type;
+       cmdbuf[4] = archivePath.size;
+       cmdbuf[5] = filePath.type;
+       cmdbuf[6] = filePath.size;
        cmdbuf[7] = openFlags;
        cmdbuf[8] = attributes;
-       cmdbuf[9] = IPC_Desc_StaticBuffer(archive.lowPath.size, 2);
-       cmdbuf[10] = (u32) archive.lowPath.data;
-       cmdbuf[11] = IPC_Desc_StaticBuffer(path.size, 0);
-       cmdbuf[12] = (u32) path.data;
+       cmdbuf[9] = IPC_Desc_StaticBuffer(archivePath.size, 2);
+       cmdbuf[10] = (u32) archivePath.data;
+       cmdbuf[11] = IPC_Desc_StaticBuffer(filePath.size, 0);
+       cmdbuf[12] = (u32) filePath.data;
 
        Result ret = 0;
-       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive.id)))) return ret;
+       if(R_FAILED(ret = svcSendSyncRequest(fsSession()))) return ret;
 
        if(out) *out = cmdbuf[3];
 
@@ -178,15 +215,15 @@ Result FSUSER_DeleteFile(FS_Archive archive, FS_Path path)
 
        cmdbuf[0] = IPC_MakeHeader(0x804,5,2); // 0x8040142
        cmdbuf[1] = 0;
-       cmdbuf[2] = (u32) archive.handle;
-       cmdbuf[3] = (u32) (archive.handle >> 32);
+       cmdbuf[2] = (u32) archive;
+       cmdbuf[3] = (u32) (archive >> 32);
        cmdbuf[4] = path.type;
        cmdbuf[5] = path.size;
        cmdbuf[6] = IPC_Desc_StaticBuffer(path.size, 0);
        cmdbuf[7] = (u32) path.data;
 
        Result ret = 0;
-       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive.id)))) return ret;
+       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive)))) return ret;
 
        return cmdbuf[1];
 }
@@ -197,12 +234,12 @@ Result FSUSER_RenameFile(FS_Archive srcArchive, FS_Path srcPath, FS_Archive dstA
 
        cmdbuf[0] = IPC_MakeHeader(0x805,9,4); // 0x8050244
        cmdbuf[1] = 0;
-       cmdbuf[2] = (u32) srcArchive.handle;
-       cmdbuf[3] = (u32) (srcArchive.handle >> 32);
+       cmdbuf[2] = (u32) srcArchive;
+       cmdbuf[3] = (u32) (srcArchive >> 32);
        cmdbuf[4] = srcPath.type;
        cmdbuf[5] = srcPath.size;
-       cmdbuf[6] = (u32) dstArchive.handle;
-       cmdbuf[7] = (u32) (dstArchive.handle >> 32);
+       cmdbuf[6] = (u32) dstArchive;
+       cmdbuf[7] = (u32) (dstArchive >> 32);
        cmdbuf[8] = dstPath.type;
        cmdbuf[9] = dstPath.size;
        cmdbuf[10] = IPC_Desc_StaticBuffer(srcPath.size, 1);
@@ -211,7 +248,7 @@ Result FSUSER_RenameFile(FS_Archive srcArchive, FS_Path srcPath, FS_Archive dstA
        cmdbuf[13] = (u32) dstPath.data;
 
        Result ret = 0;
-       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(srcArchive.id)))) return ret;
+       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(srcArchive)))) return ret;
 
        return cmdbuf[1];
 }
@@ -222,15 +259,15 @@ Result FSUSER_DeleteDirectory(FS_Archive archive, FS_Path path)
 
        cmdbuf[0] = IPC_MakeHeader(0x806,5,2); // 0x8060142
        cmdbuf[1] = 0;
-       cmdbuf[2] = (u32) archive.handle;
-       cmdbuf[3] = (u32) (archive.handle >> 32);
+       cmdbuf[2] = (u32) archive;
+       cmdbuf[3] = (u32) (archive >> 32);
        cmdbuf[4] = path.type;
        cmdbuf[5] = path.size;
        cmdbuf[6] = IPC_Desc_StaticBuffer(path.size, 0);
        cmdbuf[7] = (u32) path.data;
 
        Result ret = 0;
-       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive.id)))) return ret;
+       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive)))) return ret;
 
        return cmdbuf[1];
 }
@@ -241,15 +278,15 @@ Result FSUSER_DeleteDirectoryRecursively(FS_Archive archive, FS_Path path)
 
        cmdbuf[0] = IPC_MakeHeader(0x807,5,2); // 0x8070142
        cmdbuf[1] = 0;
-       cmdbuf[2] = (u32) archive.handle;
-       cmdbuf[3] = (u32) (archive.handle >> 32);
+       cmdbuf[2] = (u32) archive;
+       cmdbuf[3] = (u32) (archive >> 32);
        cmdbuf[4] = path.type;
        cmdbuf[5] = path.size;
        cmdbuf[6] = IPC_Desc_StaticBuffer(path.size, 0);
        cmdbuf[7] = (u32) path.data;
 
        Result ret = 0;
-       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive.id)))) return ret;
+       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive)))) return ret;
 
        return cmdbuf[1];
 }
@@ -260,8 +297,8 @@ Result FSUSER_CreateFile(FS_Archive archive, FS_Path path, u32 attributes, u64 f
 
        cmdbuf[0] = IPC_MakeHeader(0x808,8,2); // 0x8080202
        cmdbuf[1] = 0;
-       cmdbuf[2] = (u32) archive.handle;
-       cmdbuf[3] = (u32) (archive.handle >> 32);
+       cmdbuf[2] = (u32) archive;
+       cmdbuf[3] = (u32) (archive >> 32);
        cmdbuf[4] = path.type;
        cmdbuf[5] = path.size;
        cmdbuf[6] = attributes;
@@ -271,7 +308,7 @@ Result FSUSER_CreateFile(FS_Archive archive, FS_Path path, u32 attributes, u64 f
        cmdbuf[10] = (u32) path.data;
 
        Result ret = 0;
-       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive.id)))) return ret;
+       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive)))) return ret;
 
        return cmdbuf[1];
 }
@@ -282,8 +319,8 @@ Result FSUSER_CreateDirectory(FS_Archive archive, FS_Path path, u32 attributes)
 
        cmdbuf[0] = IPC_MakeHeader(0x809,6,2); // 0x8090182
        cmdbuf[1] = 0;
-       cmdbuf[2] = (u32) archive.handle;
-       cmdbuf[3] = (u32) (archive.handle >> 32);
+       cmdbuf[2] = (u32) archive;
+       cmdbuf[3] = (u32) (archive >> 32);
        cmdbuf[4] = path.type;
        cmdbuf[5] = path.size;
        cmdbuf[6] = attributes;
@@ -291,7 +328,7 @@ Result FSUSER_CreateDirectory(FS_Archive archive, FS_Path path, u32 attributes)
        cmdbuf[8] = (u32) path.data;
 
        Result ret = 0;
-       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive.id)))) return ret;
+       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive)))) return ret;
 
        return cmdbuf[1];
 }
@@ -302,12 +339,12 @@ Result FSUSER_RenameDirectory(FS_Archive srcArchive, FS_Path srcPath, FS_Archive
 
        cmdbuf[0] = IPC_MakeHeader(0x80A,9,4); // 0x80A0244
        cmdbuf[1] = 0;
-       cmdbuf[2] = (u32) srcArchive.handle;
-       cmdbuf[3] = (u32) (srcArchive.handle >> 32);
+       cmdbuf[2] = (u32) srcArchive;
+       cmdbuf[3] = (u32) (srcArchive >> 32);
        cmdbuf[4] = srcPath.type;
        cmdbuf[5] = srcPath.size;
-       cmdbuf[6] = (u32) dstArchive.handle;
-       cmdbuf[7] = (u32) (dstArchive.handle >> 32);
+       cmdbuf[6] = (u32) dstArchive;
+       cmdbuf[7] = (u32) (dstArchive >> 32);
        cmdbuf[8] = dstPath.type;
        cmdbuf[9] = dstPath.size;
        cmdbuf[10] = IPC_Desc_StaticBuffer(srcPath.size, 1);
@@ -316,7 +353,7 @@ Result FSUSER_RenameDirectory(FS_Archive srcArchive, FS_Path srcPath, FS_Archive
        cmdbuf[13] = (u32) dstPath.data;
 
        Result ret = 0;
-       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(srcArchive.id)))) return ret;
+       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(srcArchive)))) return ret;
 
        return cmdbuf[1];
 }
@@ -326,38 +363,38 @@ Result FSUSER_OpenDirectory(Handle* out, FS_Archive archive, FS_Path path)
        u32 *cmdbuf = getThreadCommandBuffer();
 
        cmdbuf[0] = IPC_MakeHeader(0x80B,4,2); // 0x80B0102
-       cmdbuf[1] = (u32) archive.handle;
-       cmdbuf[2] = (u32) (archive.handle >> 32);
+       cmdbuf[1] = (u32) archive;
+       cmdbuf[2] = (u32) (archive >> 32);
        cmdbuf[3] = path.type;
        cmdbuf[4] = path.size;
        cmdbuf[5] = IPC_Desc_StaticBuffer(path.size, 0);
        cmdbuf[6] = (u32) path.data;
 
        Result ret = 0;
-       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive.id)))) return ret;
+       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive)))) return ret;
 
        if(out) *out = cmdbuf[3];
 
        return cmdbuf[1];
 }
 
-Result FSUSER_OpenArchive(FS_Archive* archive)
+Result FSUSER_OpenArchive(FS_Archive* archive, FS_ArchiveID id, FS_Path path)
 {
        if(!archive) return -2;
 
        u32 *cmdbuf = getThreadCommandBuffer();
 
        cmdbuf[0] = IPC_MakeHeader(0x80C,3,2); // 0x80C00C2
-       cmdbuf[1] = archive->id;
-       cmdbuf[2] = archive->lowPath.type;
-       cmdbuf[3] = archive->lowPath.size;
-       cmdbuf[4] = IPC_Desc_StaticBuffer(archive->lowPath.size, 0);
-       cmdbuf[5] = (u32) archive->lowPath.data;
+       cmdbuf[1] = id;
+       cmdbuf[2] = path.type;
+       cmdbuf[3] = path.size;
+       cmdbuf[4] = IPC_Desc_StaticBuffer(path.size, 0);
+       cmdbuf[5] = (u32) path.data;
 
        Result ret = 0;
-       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive->id)))) return ret;
+       if(R_FAILED(ret = svcSendSyncRequest(fsSession()))) return ret;
 
-       archive->handle = cmdbuf[2] | ((u64) cmdbuf[3] << 32);
+       if(archive) *archive = cmdbuf[2] | ((u64) cmdbuf[3] << 32);
 
        return cmdbuf[1];
 }
@@ -367,8 +404,8 @@ Result FSUSER_ControlArchive(FS_Archive archive, FS_ArchiveAction action, void*
        u32 *cmdbuf = getThreadCommandBuffer();
 
        cmdbuf[0] = IPC_MakeHeader(0x80D,5,4); // 0x80D0144
-       cmdbuf[1] = (u32) archive.handle;
-       cmdbuf[2] = (u32) (archive.handle >> 32);
+       cmdbuf[1] = (u32) archive;
+       cmdbuf[2] = (u32) (archive >> 32);
        cmdbuf[3] = action;
        cmdbuf[4] = inputSize;
        cmdbuf[5] = outputSize;
@@ -378,23 +415,23 @@ Result FSUSER_ControlArchive(FS_Archive archive, FS_ArchiveAction action, void*
        cmdbuf[9] = (u32) output;
 
        Result ret = 0;
-       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive.id)))) return ret;
+       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive)))) return ret;
 
        return cmdbuf[1];
 }
 
-Result FSUSER_CloseArchive(FS_Archive* archive)
+Result FSUSER_CloseArchive(FS_Archive archive)
 {
        if(!archive) return -2;
 
        u32 *cmdbuf = getThreadCommandBuffer();
 
        cmdbuf[0] = IPC_MakeHeader(0x80E,2,0); // 0x80E0080
-       cmdbuf[1] = (u32) archive->handle;
-       cmdbuf[2] = (u32) (archive->handle >> 32);
+       cmdbuf[1] = (u32) archive;
+       cmdbuf[2] = (u32) (archive >> 32);
 
        Result ret = 0;
-       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive->id)))) return ret;
+       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive)))) return ret;
 
        return cmdbuf[1];
 }
@@ -404,11 +441,11 @@ Result FSUSER_GetFreeBytes(u64* freeBytes, FS_Archive archive)
        u32 *cmdbuf = getThreadCommandBuffer();
 
        cmdbuf[0] = IPC_MakeHeader(0x812,2,0); // 0x8120080
-       cmdbuf[1] = (u32) archive.handle;
-       cmdbuf[2] = (u32) (archive.handle >> 32);
+       cmdbuf[1] = (u32) archive;
+       cmdbuf[2] = (u32) (archive >> 32);
 
        Result ret = 0;
-       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive.id)))) return ret;
+       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive)))) return ret;
 
        if(freeBytes) *freeBytes = cmdbuf[2] | ((u64) cmdbuf[3] << 32);
 
@@ -436,7 +473,7 @@ Result FSUSER_GetSdmcArchiveResource(FS_ArchiveResource* archiveResource)
        cmdbuf[0] = IPC_MakeHeader(0x814,0,0); // 0x8140000
 
        Result ret = 0;
-       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(ARCHIVE_SDMC)))) return ret;
+       if(R_FAILED(ret = svcSendSyncRequest(fsSession()))) return ret;
 
        if(archiveResource) memcpy(archiveResource, &cmdbuf[2], sizeof(FS_ArchiveResource));
 
@@ -1037,7 +1074,7 @@ Result FSUSER_GetFormatInfo(u32* totalSize, u32* directories, u32* files, bool*
        cmdbuf[5] = (u32) path.data;
 
        Result ret = 0;
-       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archiveId)))) return ret;
+       if(R_FAILED(ret = svcSendSyncRequest(fsSession()))) return ret;
 
        if(totalSize) *totalSize = cmdbuf[2];
        if(directories) *directories = cmdbuf[3];
@@ -1353,12 +1390,12 @@ Result FSUSER_SetArchivePriority(FS_Archive archive, u32 priority)
        u32 *cmdbuf = getThreadCommandBuffer();
 
        cmdbuf[0] = IPC_MakeHeader(0x85A,3,0); // 0x85A00C0
-       cmdbuf[1] = (u32) archive.handle;
-       cmdbuf[2] = (u32) (archive.handle >> 32);
+       cmdbuf[1] = (u32) archive;
+       cmdbuf[2] = (u32) (archive >> 32);
        cmdbuf[3] = priority;
 
        Result ret = 0;
-       if(R_FAILED(ret = svcSendSyncRequest(fsSession()))) return ret;
+       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive)))) return ret;
 
        return cmdbuf[1];
 }
@@ -1368,11 +1405,11 @@ Result FSUSER_GetArchivePriority(u32* priority, FS_Archive archive)
        u32 *cmdbuf = getThreadCommandBuffer();
 
        cmdbuf[0] = IPC_MakeHeader(0x85B,2,0); // 0x85B0080
-       cmdbuf[1] = (u32) archive.handle;
-       cmdbuf[2] = (u32) (archive.handle >> 32);
+       cmdbuf[1] = (u32) archive;
+       cmdbuf[2] = (u32) (archive >> 32);
 
        Result ret = 0;
-       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive.id)))) return ret;
+       if(R_FAILED(ret = svcSendSyncRequest(fsSessionForArchive(archive)))) return ret;
 
        if(priority) *priority = cmdbuf[2];