diff --git a/Makefile b/Makefile index 1236f25..cafda8e 100644 --- a/Makefile +++ b/Makefile @@ -21,9 +21,9 @@ ifeq ($(MODE),safe) export TARGET := SafeMode9 endif BUILD := build -SOURCES := source source/crypto source/fatfs source/nand source/virtual source/game source/abstraction +SOURCES := source source/fs source/crypto source/fatfs source/nand source/virtual source/game source/abstraction DATA := data -INCLUDES := source source/font source/crypto source/fatfs source/nand source/virtual source/game +INCLUDES := source source/font source/fs source/crypto source/fatfs source/nand source/virtual source/game #--------------------------------------------------------------------------------- # options for code generation diff --git a/source/fs.h b/source/fs.h deleted file mode 100644 index cc6b352..0000000 --- a/source/fs.h +++ /dev/null @@ -1,125 +0,0 @@ -#pragma once - -#include "common.h" -#include "dir.h" - -// primary drive types -#define DRV_UNKNOWN (0<<0) -#define DRV_FAT (1<<0) -#define DRV_VIRTUAL (1<<1) -// secondary drive types -#define DRV_SDCARD (1<<2) -#define DRV_SYSNAND (1<<3) -#define DRV_EMUNAND (1<<4) -#define DRV_IMAGE (1<<5) -#define DRV_XORPAD (1<<6) -#define DRV_RAMDRIVE (1<<7) -#define DRV_MEMORY (1<<8) -#define DRV_GAME (1<<9) -#define DRV_ALIAS (1<<10) -#define DRV_SEARCH (1<<11) -#define DRV_STDFAT (1<<12) // standard FAT drive without limitations - -// permission types -#define PERM_SDCARD (1<<0) -#define PERM_RAMDRIVE (1<<1) -#define PERM_EMUNAND (1<<2) -#define PERM_SYSNAND (1<<3) -#define PERM_IMAGE (1<<4) -#define PERM_MEMORY (1<<5) -#define PERM_GAME (1<<6) // can't be enabled, placeholder -#define PERM_XORPAD (1<<7) // can't be enabled, placeholder -#define PERM_A9LH ((1<<8) | PERM_SYSNAND) -#define PERM_SDDATA ((1<<9) | PERM_SDCARD) -#define PERM_BASE (PERM_SDCARD | PERM_RAMDRIVE) -#define PERM_ALL (PERM_SDCARD | PERM_RAMDRIVE | PERM_EMUNAND | PERM_SYSNAND | PERM_IMAGE | PERM_MEMORY | PERM_SDDATA) - -// move / copy flags -#define ASK_ALL (1<<0) -#define SKIP_ALL (1<<1) -#define OVERWRITE_ALL (1<<2) - -bool InitSDCardFS(); -bool InitExtFS(); -bool InitImgFS(const char* path); -bool InitRamDriveFS(); -void DeinitExtFS(); -void DeinitSDCardFS(); - -/** Set search pattern / path for special Z: drive **/ -void SetFSSearch(const char* pattern, const char* path); - -/** Return total size of SD card **/ -uint64_t GetSDCardSize(); - -/** Format the SD card **/ -bool FormatSDCard(u64 hidden_mb, u32 cluster_size); - -/** Check if writing to this path is allowed **/ -bool CheckWritePermissions(const char* path); - -/** Set new write permissions */ -bool SetWritePermissions(u32 perm, bool add_perm); - -/** Get write permissions */ -u32 GetWritePermissions(); - -/** True if file exists and is not locked, false otherwise **/ -bool FileCheck(const char* path); - -/** Create / open file and write the provided data to it **/ -bool FileSetData(const char* path, const u8* data, size_t size, size_t foffset, bool create); - -/** Read data from file@offset **/ -size_t FileGetData(const char* path, u8* data, size_t size, size_t foffset); - -/** Get size of file **/ -size_t FileGetSize(const char* path); - -/** Get SHA-256 of file **/ -bool FileGetSha256(const char* path, u8* sha256); - -/** Find data in file **/ -u32 FileFindData(const char* path, u8* data, u32 size, u32 offset); - -/** Inject file into file @offset **/ -bool FileInjectFile(const char* dest, const char* orig, u32 offset); - -/** Recursively copy a file or directory **/ -bool PathCopy(const char* destdir, const char* orig, u32* flags); - -/** Recursively move a file or directory **/ -bool PathMove(const char* destdir, const char* orig, u32* flags); - -/** Recursively delete a file or directory **/ -bool PathDelete(const char* path); - -/** Rename file / folder in path to new name **/ -bool PathRename(const char* path, const char* newname); - -/** Create a new directory in cpath **/ -bool DirCreate(const char* cpath, const char* dirname); - -/** Create a screenshot of the current framebuffer **/ -void CreateScreenshot(); - -/** Search under a given path **/ -void SearchDirContents(DirStruct* contents, const char* path, const char* pattern, bool recursive); - -/** Get directory content under a given path **/ -void GetDirContents(DirStruct* contents, const char* path); - -/** Gets remaining space in filesystem in bytes */ -uint64_t GetFreeSpace(const char* path); - -/** Gets total spacein filesystem in bytes */ -uint64_t GetTotalSpace(const char* path); - -/** Return the offset - in sectors - of the FAT partition on the drive **/ -uint64_t GetPartitionOffsetSector(const char* path); - -/** Function to identify the type of a drive **/ -int DriveType(const char* path); - -/** Check for special search drive **/ -bool IsSearchDrive(const char* path); diff --git a/source/filetype.c b/source/fs/filetype.c similarity index 100% rename from source/filetype.c rename to source/fs/filetype.c diff --git a/source/filetype.h b/source/fs/filetype.h similarity index 100% rename from source/filetype.h rename to source/fs/filetype.h diff --git a/source/dir.c b/source/fs/fsdir.c similarity index 99% rename from source/dir.c rename to source/fs/fsdir.c index 9abd957..81f7b54 100644 --- a/source/dir.c +++ b/source/fs/fsdir.c @@ -1,4 +1,4 @@ -#include "dir.h" +#include "fsdir.h" void DirEntryCpy(DirEntry* dest, const DirEntry* orig) { memcpy(dest, orig, sizeof(DirEntry)); diff --git a/source/dir.h b/source/fs/fsdir.h similarity index 100% rename from source/dir.h rename to source/fs/fsdir.h diff --git a/source/fs/fsdrive.c b/source/fs/fsdrive.c new file mode 100644 index 0000000..03e76c4 --- /dev/null +++ b/source/fs/fsdrive.c @@ -0,0 +1,200 @@ +#include "fsdrive.h" +#include "fsinit.h" +#include "virtual.h" +#include "sddata.h" +#include "image.h" +#include "ui.h" +#include "ff.h" + +// last search pattern & path +static char search_pattern[256] = { 0 }; +static char search_path[256] = { 0 }; + +int DriveType(const char* path) { + int type = DRV_UNKNOWN; + int pdrv = GetMountedFSNum(path); + + if (CheckAliasDrive(path)) { + type = DRV_FAT | DRV_ALIAS; + } else if (*search_pattern && *search_path && (strncmp(path, "Z:", 3) == 0)) { + type = DRV_SEARCH; + } else if ((pdrv >= 0) && (pdrv < NORM_FS)) { + if (pdrv == 0) { + type = DRV_FAT | DRV_SDCARD | DRV_STDFAT; + } else if ((pdrv == 7) && (GetMountState() == IMG_RAMDRV)) { + type = DRV_FAT | DRV_RAMDRIVE | DRV_STDFAT; + } else if ((pdrv >= 1) && (pdrv <= 3)) { + type = DRV_FAT | DRV_SYSNAND | DRV_STDFAT; + } else if ((pdrv >= 4) && (pdrv <= 6)) { + type = DRV_FAT | DRV_EMUNAND | DRV_STDFAT; + } else if ((pdrv >= 7) && (pdrv <= 9) && + ((GetMountState() == IMG_FAT) || (GetMountState() == IMG_NAND))) { + type = DRV_FAT | DRV_IMAGE | DRV_STDFAT; + } + } else if (CheckVirtualDrive(path)) { + int vsrc = GetVirtualSource(path); + if (vsrc == VRT_SYSNAND) { + type = DRV_VIRTUAL | DRV_SYSNAND; + } else if (vsrc == VRT_EMUNAND) { + type = DRV_VIRTUAL | DRV_EMUNAND; + } else if (vsrc == VRT_IMGNAND) { + type = DRV_VIRTUAL | DRV_IMAGE; + } else if (vsrc == VRT_XORPAD) { + type = DRV_VIRTUAL | DRV_XORPAD; + } else if (vsrc == VRT_MEMORY) { + type = DRV_VIRTUAL | DRV_MEMORY; + } else if (vsrc == VRT_GAME) { + type = DRV_VIRTUAL | DRV_GAME | DRV_IMAGE; + } + } + + return type; +} + +void SetFSSearch(const char* pattern, const char* path) { + if (pattern && path) { + strncpy(search_pattern, pattern, 256); + strncpy(search_path, path, 256); + } else *search_pattern = *search_path = '\0'; +} + +bool GetRootDirContentsWorker(DirStruct* contents) { + static const char* drvname[] = { FS_DRVNAME }; + static const char* drvnum[] = { FS_DRVNUM }; + u32 n_entries = 0; + + // virtual root objects hacked in + for (u32 pdrv = 0; (pdrv < NORM_FS+VIRT_FS) && (n_entries < MAX_DIR_ENTRIES); pdrv++) { + DirEntry* entry = &(contents->entry[n_entries]); + if (!DriveType(drvnum[pdrv])) continue; // drive not available + memset(entry->path, 0x00, 64); + snprintf(entry->path + 0, 4, drvnum[pdrv]); + if ((pdrv == 7) && ((GetMountState() == IMG_FAT) || (GetMountState() == IMG_RAMDRV))) + snprintf(entry->path + 4, 32, "[%s] %s", drvnum[pdrv], // FAT image / RAM drive special handling + (GetMountState() == IMG_FAT) ? "FAT IMAGE" : "RAMDRIVE"); + else if (pdrv == 10) // Game drive special handling + snprintf(entry->path + 4, 32, "[%s] %s %s", drvnum[pdrv], + (GetMountState() == GAME_CIA ) ? "CIA" : + (GetMountState() == GAME_NCSD ) ? "NCSD" : + (GetMountState() == GAME_NCCH ) ? "NCCH" : + (GetMountState() == GAME_EXEFS) ? "EXEFS" : + (GetMountState() == GAME_ROMFS) ? "ROMFS" : "UNK", drvname[pdrv]); + else snprintf(entry->path + 4, 32, "[%s] %s", drvnum[pdrv], drvname[pdrv]); + entry->name = entry->path + 4; + entry->size = GetTotalSpace(entry->path); + entry->type = T_ROOT; + entry->marked = 0; + n_entries++; + } + contents->n_entries = n_entries; + + return contents->n_entries; +} + +bool GetDirContentsWorker(DirStruct* contents, char* fpath, int fnsize, const char* pattern, bool recursive) { + DIR pdir; + FILINFO fno; + char* fname = fpath + strnlen(fpath, fnsize - 1); + bool ret = false; + + if (fa_opendir(&pdir, fpath) != FR_OK) + return false; + (fname++)[0] = '/'; + + while (f_readdir(&pdir, &fno) == FR_OK) { + if ((strncmp(fno.fname, ".", 2) == 0) || (strncmp(fno.fname, "..", 3) == 0)) + continue; // filter out virtual entries + strncpy(fname, fno.fname, (fnsize - 1) - (fname - fpath)); + if (fno.fname[0] == 0) { + ret = true; + break; + } else if (!pattern || MatchName(pattern, fname)) { + DirEntry* entry = &(contents->entry[contents->n_entries]); + strncpy(entry->path, fpath, 256); + entry->name = entry->path + (fname - fpath); + if (fno.fattrib & AM_DIR) { + entry->type = T_DIR; + entry->size = 0; + } else { + entry->type = T_FILE; + entry->size = fno.fsize; + } + entry->marked = 0; + if (contents->n_entries >= MAX_DIR_ENTRIES) { + ret = true; // Too many entries, still okay + break; + } + contents->n_entries++; + } + if (recursive && (fno.fattrib & AM_DIR)) { + if (!GetDirContentsWorker(contents, fpath, fnsize, pattern, recursive)) + break; + } + } + f_closedir(&pdir); + + return ret; +} + +void SearchDirContents(DirStruct* contents, const char* path, const char* pattern, bool recursive) { + contents->n_entries = 0; + if (!(*path)) { // root directory + if (!GetRootDirContentsWorker(contents)) + contents->n_entries = 0; // not required, but so what? + } else { + // create virtual '..' entry + contents->entry->name = contents->entry->path + 8; + strncpy(contents->entry->path, "*?*?*", 8); + strncpy(contents->entry->name, "..", 4); + contents->entry->type = T_DOTDOT; + contents->entry->size = 0; + contents->n_entries = 1; + // search the path + char fpath[256]; // 256 is the maximum length of a full path + strncpy(fpath, path, 256); + if (DriveType(path) & DRV_VIRTUAL) { + if (!GetVirtualDirContents(contents, fpath, 256, pattern, recursive)) + contents->n_entries = 0; + } else { + if (!GetDirContentsWorker(contents, fpath, 256, pattern, recursive)) + contents->n_entries = 0; + } + SortDirStruct(contents); + } +} + +void GetDirContents(DirStruct* contents, const char* path) { + if (DriveType(path) & DRV_SEARCH) { + ShowString("Searching, please wait..."); + SearchDirContents(contents, search_path, search_pattern, true); + ClearScreenF(true, false, COLOR_STD_BG); + } else SearchDirContents(contents, path, NULL, false); +} + +uint64_t GetFreeSpace(const char* path) +{ + DWORD free_clusters; + FATFS* fsptr; + char fsname[4] = { '\0' }; + int pdrv = GetMountedFSNum(path); + FATFS* fsobj = GetMountedFSObject(path); + if ((pdrv < 0) || !fsobj) return 0; + + snprintf(fsname, 3, "%i:", pdrv); + if (f_getfree(fsname, &free_clusters, &fsptr) != FR_OK) + return 0; + + return (uint64_t) free_clusters * fsobj->csize * _MAX_SS; +} + +uint64_t GetTotalSpace(const char* path) +{ + FATFS* fsobj = GetMountedFSObject(path); + return (fsobj) ? ((uint64_t) (fsobj->n_fatent - 2) * fsobj->csize * _MAX_SS) : 0; +} + +uint64_t GetPartitionOffsetSector(const char* path) +{ + FATFS* fsobj = GetMountedFSObject(path); + return (fsobj) ? (uint64_t) fsobj->volbase : 0; +} diff --git a/source/fs/fsdrive.h b/source/fs/fsdrive.h new file mode 100644 index 0000000..3239a96 --- /dev/null +++ b/source/fs/fsdrive.h @@ -0,0 +1,58 @@ +#pragma once + +#include "common.h" +#include "fsdir.h" + +#define NORM_FS 10 +#define IMGN_FS 3 // image normal filesystems +#define VIRT_FS 9 + +// primary drive types +#define DRV_UNKNOWN (0<<0) +#define DRV_FAT (1<<0) +#define DRV_VIRTUAL (1<<1) +// secondary drive types +#define DRV_SDCARD (1<<2) +#define DRV_SYSNAND (1<<3) +#define DRV_EMUNAND (1<<4) +#define DRV_IMAGE (1<<5) +#define DRV_XORPAD (1<<6) +#define DRV_RAMDRIVE (1<<7) +#define DRV_MEMORY (1<<8) +#define DRV_GAME (1<<9) +#define DRV_ALIAS (1<<10) +#define DRV_SEARCH (1<<11) +#define DRV_STDFAT (1<<12) // standard FAT drive without limitations + +#define FS_DRVNAME \ + "SDCARD", \ + "SYSNAND CTRNAND", "SYSNAND TWLN", "SYSNAND TWLP", \ + "EMUNAND CTRNAND", "EMUNAND TWLN", "EMUNAND TWLP", \ + "IMGNAND CTRNAND", "IMGNAND TWLN", "IMGNAND TWLP", \ + "GAME IMAGE", \ + "SYSNAND SD", "EMUNAND SD", \ + "SYSNAND VIRTUAL", "EMUNAND VIRTUAL", "IMGNAND VIRTUAL", \ + "NAND XORPADS", \ + "MEMORY VIRTUAL", \ + "LAST SEARCH" \ + +#define FS_DRVNUM \ + "0:", "1:", "2:", "3:", "4:", "5:", "6:", "7:", "8:", "9:", "G:", "A:", "B:", "S:", "E:", "I:", "X:", "M:", "Z:" + +/** Function to identify the type of a drive **/ +int DriveType(const char* path); + +/** Set search pattern / path for special Z: drive **/ +void SetFSSearch(const char* pattern, const char* path); + +/** Get directory content under a given path **/ +void GetDirContents(DirStruct* contents, const char* path); + +/** Gets remaining space in filesystem in bytes */ +uint64_t GetFreeSpace(const char* path); + +/** Gets total spacein filesystem in bytes */ +uint64_t GetTotalSpace(const char* path); + +/** Return the offset - in sectors - of the FAT partition on the drive **/ +uint64_t GetPartitionOffsetSector(const char* path); diff --git a/source/fs/fsinit.c b/source/fs/fsinit.c new file mode 100644 index 0000000..04965c7 --- /dev/null +++ b/source/fs/fsinit.c @@ -0,0 +1,126 @@ +#include "fsinit.h" +#include "fsdrive.h" +#include "virtual.h" +#include "vgame.h" +#include "sddata.h" +#include "image.h" +#include "ff.h" + +// don't use this area for anything else! +static FATFS* fs = (FATFS*)0x20316000; + +// currently open file systems +static bool fs_mounted[NORM_FS] = { false }; + +bool InitSDCardFS() { + fs_mounted[0] = (f_mount(fs, "0:", 1) == FR_OK); + return fs_mounted[0]; +} + +bool InitExtFS() { + if (!fs_mounted[0]) + return false; + for (u32 i = 1; i < NORM_FS; i++) { + char fsname[8]; + snprintf(fsname, 7, "%lu:", i); + if (fs_mounted[i]) continue; + fs_mounted[i] = (f_mount(fs + i, fsname, 1) == FR_OK); + } + SetupNandSdDrive("A:", "0:", "1:/private/movable.sed", 0); + SetupNandSdDrive("B:", "0:", "4:/private/movable.sed", 1); + return true; +} + +bool InitImgFS(const char* path) { + // deinit image filesystem + for (u32 i = NORM_FS - 1; i >= NORM_FS - IMGN_FS; i--) { + char fsname[8]; + snprintf(fsname, 7, "%lu:", i); + if (!fs_mounted[i]) continue; + f_mount(NULL, fsname, 1); + fs_mounted[i] = false; + } + // (re)mount image, done if path == NULL + MountImage(path); + InitVGameDrive(); + if (!GetMountState()) return false; + // reinit image filesystem + for (u32 i = NORM_FS - IMGN_FS; i < NORM_FS; i++) { + char fsname[8]; + snprintf(fsname, 7, "%lu:", i); + fs_mounted[i] = (f_mount(fs + i, fsname, 1) == FR_OK); + } + return true; +} + +bool InitRamDriveFS() { + u32 pdrv = NORM_FS - IMGN_FS; + char fsname[8]; + snprintf(fsname, 7, "%lu:", pdrv); + + InitImgFS(NULL); + MountRamDrive(); + fs_mounted[pdrv] = (f_mount(fs + pdrv, fsname, 1) == FR_OK); + if (!fs_mounted[pdrv] && (GetMountState() == IMG_RAMDRV)) { + f_mkfs(fsname, FM_ANY, 0, MAIN_BUFFER, MAIN_BUFFER_SIZE); // format ramdrive if required + f_mount(NULL, fsname, 1); + fs_mounted[pdrv] = (f_mount(fs + pdrv, fsname, 1) == FR_OK); + } + + return true; +} + +void DeinitExtFS() { + SetupNandSdDrive(NULL, NULL, NULL, 0); + SetupNandSdDrive(NULL, NULL, NULL, 1); + for (u32 i = NORM_FS - 1; i > 0; i--) { + if (fs_mounted[i]) { + char fsname[8]; + snprintf(fsname, 7, "%lu:", i); + f_mount(NULL, fsname, 1); + fs_mounted[i] = false; + } + if ((i == NORM_FS - IMGN_FS) && (GetMountState() != IMG_RAMDRV)) { // unmount image + MountImage(NULL); + InitVGameDrive(); + } + } +} + +void DeinitSDCardFS() { + if (GetMountState() != IMG_RAMDRV) { + MountImage(NULL); + InitVGameDrive(); + } + if (fs_mounted[0]) { + f_mount(NULL, "0:", 1); + fs_mounted[0] = false; + } +} + +void DismountDriveType(u32 type) { // careful with this - no safety checks + if (type & DriveType(GetMountPath())) + InitImgFS(NULL); // image is mounted from type -> unmount image drive, too + for (u32 i = NORM_FS - 1; i > 0; i--) { + char fsname[8]; + snprintf(fsname, 7, "%lu:", i); + if (!fs_mounted[i] || !(type & DriveType(fsname))) + continue; + f_mount(NULL, fsname, 1); + fs_mounted[i] = false; + } +} + +int GetMountedFSNum(const char* path) { + char alias[256]; + dealias_path(alias, path); + int fsnum = *alias - (int) '0'; + if ((fsnum < 0) || (fsnum >= NORM_FS) || (alias[1] != ':') || !fs_mounted[fsnum]) + return -1; + return fsnum; +} + +FATFS* GetMountedFSObject(const char* path) { + int fsnum = GetMountedFSNum(path); + return (fsnum >= 0) ? fs + fsnum : NULL; +} diff --git a/source/fs/fsinit.h b/source/fs/fsinit.h new file mode 100644 index 0000000..6ef4d2b --- /dev/null +++ b/source/fs/fsinit.h @@ -0,0 +1,31 @@ +#pragma once + +#include "common.h" +#include "ff.h" + +// init SD card filesystem - required for everything else +bool InitSDCardFS(); + +// init fill external fileystem +bool InitExtFS(); + +// mount and init image file system +bool InitImgFS(const char* path); + +// init RAM drive filesystem (unmounts image) +bool InitRamDriveFS(); + +// deinitialize external filesystem +void DeinitExtFS(); + +// deinitialize SD card filesystem +void DeinitSDCardFS(); + +// dismount drives of a certain type +void DismountDriveType(u32 type); + +// get number of mounted file system (only for FATFS filesystems) +int GetMountedFSNum(const char* path); + +// get mounted file system object (only for FATFS filesystems) +FATFS* GetMountedFSObject(const char* path); diff --git a/source/fs/fsperm.c b/source/fs/fsperm.c new file mode 100644 index 0000000..7729d99 --- /dev/null +++ b/source/fs/fsperm.c @@ -0,0 +1,147 @@ +#include "fsperm.h" +#include "fsdrive.h" +#include "virtual.h" +#include "image.h" +#include "ui.h" + +// write permissions - careful with this +static u32 write_permissions = PERM_BASE; + +bool CheckWritePermissions(const char* path) { + char area_name[16]; + int drvtype = DriveType(path); + u32 perm; + + // check mounted image write permissions + if ((drvtype & DRV_IMAGE) && !CheckWritePermissions(GetMountPath())) + return false; // endless loop when mounted file inside image, but not possible + + // check drive type, get permission type + if (drvtype & DRV_SYSNAND) { + perm = PERM_SYSNAND; + snprintf(area_name, 16, "the SysNAND"); + // check virtual file flags (if any) + VirtualFile vfile; + if (GetVirtualFile(&vfile, path) && (vfile.flags & VFLAG_A9LH_AREA)) { + perm = PERM_A9LH; + snprintf(area_name, 16, "A9LH regions"); + } + } else if (drvtype & DRV_EMUNAND) { + perm = PERM_EMUNAND; + snprintf(area_name, 16, "the EmuNAND"); + } else if (drvtype & DRV_GAME) { + perm = PERM_GAME; + snprintf(area_name, 16, "game images"); + } else if (drvtype & DRV_XORPAD) { + perm = PERM_XORPAD; + snprintf(area_name, 16, "XORpads"); + } else if (drvtype & DRV_IMAGE) { + perm = PERM_IMAGE; + snprintf(area_name, 16, "images"); + } else if (drvtype & DRV_MEMORY) { + perm = PERM_MEMORY; + snprintf(area_name, 16, "memory areas"); + } else if ((drvtype & DRV_ALIAS) || (strncmp(path, "0:/Nintendo 3DS", 15) == 0)) { + perm = PERM_SDDATA; + snprintf(area_name, 16, "SD system data"); + } else if (drvtype & DRV_SDCARD) { + perm = PERM_SDCARD; + snprintf(area_name, 16, "the SD card"); + } else if (drvtype & DRV_RAMDRIVE) { + perm = PERM_RAMDRIVE; + snprintf(area_name, 16, "the RAM drive"); + } else { + return false; + } + + // check permission, return if already set + if ((write_permissions & perm) == perm) + return true; + + // ask the user + if (!ShowPrompt(true, "Writing to %s is locked!\nUnlock it now?", area_name)) + return false; + + return SetWritePermissions(perm, true); +} + +bool SetWritePermissions(u32 perm, bool add_perm) { + if ((write_permissions & perm) == perm) { // write permissions already given + if (!add_perm) write_permissions = perm; + return true; + } + + switch (perm) { + case PERM_BASE: + if (!ShowUnlockSequence(1, "You want to enable base\nwriting permissions.")) + return false; + break; + case PERM_SDCARD: + if (!ShowUnlockSequence(1, "You want to enable SD card\nwriting permissions.")) + return false; + break; + case PERM_RAMDRIVE: + if (!ShowUnlockSequence(1, "You want to enable RAM drive\nwriting permissions.")) + return false; + case PERM_EMUNAND: + if (!ShowUnlockSequence(2, "You want to enable EmuNAND\nwriting permissions.")) + return false; + break; + case PERM_IMAGE: + if (!ShowUnlockSequence(2, "You want to enable image\nwriting permissions.")) + return false; + break; + case PERM_GAME: + ShowPrompt(false, "Unlock write permission for\ngame images is not allowed."); + return false; + break; + case PERM_XORPAD: + ShowPrompt(false, "Unlock write permission for\nXORpad drive is not allowed."); + return false; + break; + #ifndef SAFEMODE + case PERM_SYSNAND: + if (!ShowUnlockSequence(3, "!Better be careful!\n \nYou want to enable SysNAND\nwriting permissions.\nThis enables you to do some\nreally dangerous stuff!")) + return false; + break; + case PERM_A9LH: + if (!ShowUnlockSequence(5, "!THIS IS YOUR ONLY WARNING!\n \nYou want to enable A9LH area\nwriting permissions.\nThis enables you to OVERWRITE\nyour A9LH installation!")) + return false; + break; + case PERM_MEMORY: + if (!ShowUnlockSequence(4, "!Better be careful!\n \nYou want to enable memory\nwriting permissions.\nWriting to certain areas may\nlead to unexpected results.")) + return false; + break; + case PERM_SDDATA: + if (!ShowUnlockSequence(2, "You want to enable SD data\nwriting permissions.")) + return false; + break; + case PERM_ALL: + if (!ShowUnlockSequence(3, "!Better be careful!\n \nYou want to enable ALL\nwriting permissions.\nThis enables you to do some\nreally dangerous stuff!")) + return false; + break; + default: + ShowPrompt(false, "Unlock write permission is not allowed."); + return false; + break; + #else + case PERM_ALL: + perm &= ~(PERM_SYSNAND|PERM_MEMORY); + if (!ShowUnlockSequence(2, "You want to enable EmuNAND &\nimage writing permissions.\nKeep backups, just in case.")) + return false; + break; + default: + ShowPrompt(false, "Can't unlock write permission.\nTry GodMode9 instead!"); + return false; + break; + #endif + } + + write_permissions = add_perm ? write_permissions | perm : perm; + + return true; +} + +u32 GetWritePermissions() { + return write_permissions; +} diff --git a/source/fs/fsperm.h b/source/fs/fsperm.h new file mode 100644 index 0000000..97524f6 --- /dev/null +++ b/source/fs/fsperm.h @@ -0,0 +1,26 @@ +#pragma once + +#include "common.h" + +// permission types +#define PERM_SDCARD (1<<0) +#define PERM_RAMDRIVE (1<<1) +#define PERM_EMUNAND (1<<2) +#define PERM_SYSNAND (1<<3) +#define PERM_IMAGE (1<<4) +#define PERM_MEMORY (1<<5) +#define PERM_GAME (1<<6) // can't be enabled, placeholder +#define PERM_XORPAD (1<<7) // can't be enabled, placeholder +#define PERM_A9LH ((1<<8) | PERM_SYSNAND) +#define PERM_SDDATA ((1<<9) | PERM_SDCARD) +#define PERM_BASE (PERM_SDCARD | PERM_RAMDRIVE) +#define PERM_ALL (PERM_SDCARD | PERM_RAMDRIVE | PERM_EMUNAND | PERM_SYSNAND | PERM_IMAGE | PERM_MEMORY | PERM_SDDATA) + +/** Check if writing to this path is allowed **/ +bool CheckWritePermissions(const char* path); + +/** Set new write permissions */ +bool SetWritePermissions(u32 perm, bool add_perm); + +/** Get write permissions */ +u32 GetWritePermissions(); diff --git a/source/fs.c b/source/fs/fsutil.c similarity index 63% rename from source/fs.c rename to source/fs/fsutil.c index 042c722..4f105c0 100644 --- a/source/fs.c +++ b/source/fs/fsutil.c @@ -1,16 +1,13 @@ -#include "ui.h" -#include "fs.h" -#include "virtual.h" -#include "vgame.h" +#include "fsutil.h" +#include "fsinit.h" +#include "fsdrive.h" +#include "fsperm.h" #include "sddata.h" -#include "image.h" +#include "virtual.h" #include "sha.h" #include "sdmmc.h" #include "ff.h" - -#define NORM_FS 10 -#define IMGN_FS 3 // image normal filesystems -#define VIRT_FS 9 +#include "ui.h" #define SKIP_CUR (1<<3) #define OVERWRITE_CUR (1<<4) @@ -21,191 +18,6 @@ PARTITION VolToPart[] = { {5, 0}, {6, 0}, {7, 0}, {8, 0}, {9, 0} }; -// don't use this area for anything else! -static FATFS* fs = (FATFS*)0x20316000; - -// write permissions - careful with this -static u32 write_permissions = PERM_BASE; - -// number of currently open file systems -static bool fs_mounted[NORM_FS] = { false }; - -// last search pattern & path -static char search_pattern[256] = { 0 }; -static char search_path[256] = { 0 }; - -bool InitSDCardFS() { - fs_mounted[0] = (f_mount(fs, "0:", 1) == FR_OK); - return fs_mounted[0]; -} - -bool InitExtFS() { - if (!fs_mounted[0]) - return false; - for (u32 i = 1; i < NORM_FS; i++) { - char fsname[8]; - snprintf(fsname, 7, "%lu:", i); - if (fs_mounted[i]) continue; - fs_mounted[i] = (f_mount(fs + i, fsname, 1) == FR_OK); - } - SetupNandSdDrive("A:", "0:", "1:/private/movable.sed", 0); - SetupNandSdDrive("B:", "0:", "4:/private/movable.sed", 1); - return true; -} - -bool InitImgFS(const char* path) { - // deinit image filesystem - for (u32 i = NORM_FS - 1; i >= NORM_FS - IMGN_FS; i--) { - char fsname[8]; - snprintf(fsname, 7, "%lu:", i); - if (!fs_mounted[i]) continue; - f_mount(NULL, fsname, 1); - fs_mounted[i] = false; - } - // (re)mount image, done if path == NULL - MountImage(path); - InitVGameDrive(); - if (!GetMountState()) return false; - // reinit image filesystem - for (u32 i = NORM_FS - IMGN_FS; i < NORM_FS; i++) { - char fsname[8]; - snprintf(fsname, 7, "%lu:", i); - fs_mounted[i] = (f_mount(fs + i, fsname, 1) == FR_OK); - } - return true; -} - -bool InitRamDriveFS() { - u32 pdrv = NORM_FS - IMGN_FS; - char fsname[8]; - snprintf(fsname, 7, "%lu:", pdrv); - - InitImgFS(NULL); - MountRamDrive(); - fs_mounted[pdrv] = (f_mount(fs + pdrv, fsname, 1) == FR_OK); - if (!fs_mounted[pdrv] && (GetMountState() == IMG_RAMDRV)) { - f_mkfs(fsname, FM_ANY, 0, MAIN_BUFFER, MAIN_BUFFER_SIZE); // format ramdrive if required - f_mount(NULL, fsname, 1); - fs_mounted[pdrv] = (f_mount(fs + pdrv, fsname, 1) == FR_OK); - } - - return true; -} - -void DeinitExtFS() { - SetupNandSdDrive(NULL, NULL, NULL, 0); - SetupNandSdDrive(NULL, NULL, NULL, 1); - for (u32 i = NORM_FS - 1; i > 0; i--) { - if (fs_mounted[i]) { - char fsname[8]; - snprintf(fsname, 7, "%lu:", i); - f_mount(NULL, fsname, 1); - fs_mounted[i] = false; - } - if ((i == NORM_FS - IMGN_FS) && (GetMountState() != IMG_RAMDRV)) { // unmount image - MountImage(NULL); - InitVGameDrive(); - } - } -} - -void DeinitSDCardFS() { - if (GetMountState() != IMG_RAMDRV) { - MountImage(NULL); - InitVGameDrive(); - } - if (fs_mounted[0]) { - f_mount(NULL, "0:", 1); - fs_mounted[0] = false; - } -} - -void DismountDriveType(u32 type) { // careful with this - no safety checks - if (type & DriveType(GetMountPath())) - InitImgFS(NULL); // image is mounted from type -> unmount image drive, too - for (u32 i = NORM_FS - 1; i > 0; i--) { - char fsname[8]; - snprintf(fsname, 7, "%lu:", i); - if (!fs_mounted[i] || !(type & DriveType(fsname))) - continue; - f_mount(NULL, fsname, 1); - fs_mounted[i] = false; - } -} - -void SetFSSearch(const char* pattern, const char* path) { - if (pattern && path) { - strncpy(search_pattern, pattern, 256); - strncpy(search_path, path, 256); - } else *search_pattern = *search_path = '\0'; -} - -int PathToNumFS(const char* path) { - int fsnum = *path - (int) '0'; - if ((fsnum < 0) || (fsnum >= NORM_FS) || (path[1] != ':')) { - // this check is not required - /* if (!GetVirtualSource(path) && - !CheckAliasDrive(path) && - !IsSearchDrive(path)) - ShowPrompt(false, "Invalid path (%s)", path); */ - return -1; - } - return fsnum; -} - -int PathToNumFSA(const char* path) { - char alias[256]; - dealias_path(alias, path); - return PathToNumFS(alias); -} - -bool IsSearchDrive(const char* path) { - return *search_pattern && *search_path && (strncmp(path, "Z:", 3) == 0); -} - -int DriveType(const char* path) { - int type = DRV_UNKNOWN; - int pdrv = PathToNumFS(path); - - if ((pdrv >= 0) && (pdrv < NORM_FS)) { - if (!fs_mounted[pdrv]) { - type = DRV_UNKNOWN; - } else if (pdrv == 0) { - type = DRV_FAT | DRV_SDCARD | DRV_STDFAT; - } else if ((pdrv == 7) && (GetMountState() == IMG_RAMDRV)) { - type = DRV_FAT | DRV_RAMDRIVE | DRV_STDFAT; - } else if ((pdrv >= 1) && (pdrv <= 3)) { - type = DRV_FAT | DRV_SYSNAND | DRV_STDFAT; - } else if ((pdrv >= 4) && (pdrv <= 6)) { - type = DRV_FAT | DRV_EMUNAND | DRV_STDFAT; - } else if ((pdrv >= 7) && (pdrv <= 9) && - ((GetMountState() == IMG_FAT) || (GetMountState() == IMG_NAND))) { - type = DRV_FAT | DRV_IMAGE | DRV_STDFAT; - } - } else if (CheckVirtualDrive(path)) { - int vsrc = GetVirtualSource(path); - if (vsrc == VRT_SYSNAND) { - type = DRV_VIRTUAL | DRV_SYSNAND; - } else if (vsrc == VRT_EMUNAND) { - type = DRV_VIRTUAL | DRV_EMUNAND; - } else if (vsrc == VRT_IMGNAND) { - type = DRV_VIRTUAL | DRV_IMAGE; - } else if (vsrc == VRT_XORPAD) { - type = DRV_VIRTUAL | DRV_XORPAD; - } else if (vsrc == VRT_MEMORY) { - type = DRV_VIRTUAL | DRV_MEMORY; - } else if (vsrc == VRT_GAME) { - type = DRV_VIRTUAL | DRV_GAME | DRV_IMAGE; - } - } else if (CheckAliasDrive(path)) { - type = DRV_FAT | DRV_ALIAS; - } else if (IsSearchDrive(path)) { - type = DRV_SEARCH; - } - - return type; -} - uint64_t GetSDCardSize() { if (sdmmc_sdcard_init() != 0) return 0; return (u64) getMMCDevice(1)->total_size * 512; @@ -255,156 +67,17 @@ bool FormatSDCard(u64 hidden_mb, u32 cluster_size) { } // format the SD card - f_mount(fs, "0:", 1); + InitSDCardFS(); UINT c_size = cluster_size; bool ret = (f_mkfs("0:", FM_FAT32, c_size, MAIN_BUFFER, MAIN_BUFFER_SIZE) == FR_OK) && (f_setlabel("0:GM9SD") == FR_OK); - f_mount(NULL, "0:", 1); + DeinitSDCardFS(); return ret; } -bool CheckWritePermissions(const char* path) { - char area_name[16]; - int drvtype = DriveType(path); - u32 perm; - - // check mounted image write permissions - if ((drvtype & DRV_IMAGE) && !CheckWritePermissions(GetMountPath())) - return false; // endless loop when mounted file inside image, but not possible - - // check drive type, get permission type - if (drvtype & DRV_SYSNAND) { - perm = PERM_SYSNAND; - snprintf(area_name, 16, "the SysNAND"); - // check virtual file flags (if any) - VirtualFile vfile; - if (GetVirtualFile(&vfile, path) && (vfile.flags & VFLAG_A9LH_AREA)) { - perm = PERM_A9LH; - snprintf(area_name, 16, "A9LH regions"); - } - } else if (drvtype & DRV_EMUNAND) { - perm = PERM_EMUNAND; - snprintf(area_name, 16, "the EmuNAND"); - } else if (drvtype & DRV_GAME) { - perm = PERM_GAME; - snprintf(area_name, 16, "game images"); - } else if (drvtype & DRV_XORPAD) { - perm = PERM_XORPAD; - snprintf(area_name, 16, "XORpads"); - } else if (drvtype & DRV_IMAGE) { - perm = PERM_IMAGE; - snprintf(area_name, 16, "images"); - } else if (drvtype & DRV_MEMORY) { - perm = PERM_MEMORY; - snprintf(area_name, 16, "memory areas"); - } else if ((drvtype & DRV_ALIAS) || (strncmp(path, "0:/Nintendo 3DS", 15) == 0)) { - perm = PERM_SDDATA; - snprintf(area_name, 16, "SD system data"); - } else if (drvtype & DRV_SDCARD) { - perm = PERM_SDCARD; - snprintf(area_name, 16, "the SD card"); - } else if (drvtype & DRV_RAMDRIVE) { - perm = PERM_RAMDRIVE; - snprintf(area_name, 16, "the RAM drive"); - } else { - return false; - } - - // check permission, return if already set - if ((write_permissions & perm) == perm) - return true; - - // ask the user - if (!ShowPrompt(true, "Writing to %s is locked!\nUnlock it now?", area_name)) - return false; - - return SetWritePermissions(perm, true); -} - -bool SetWritePermissions(u32 perm, bool add_perm) { - if ((write_permissions & perm) == perm) { // write permissions already given - if (!add_perm) write_permissions = perm; - return true; - } - - switch (perm) { - case PERM_BASE: - if (!ShowUnlockSequence(1, "You want to enable base\nwriting permissions.")) - return false; - break; - case PERM_SDCARD: - if (!ShowUnlockSequence(1, "You want to enable SD card\nwriting permissions.")) - return false; - break; - case PERM_RAMDRIVE: - if (!ShowUnlockSequence(1, "You want to enable RAM drive\nwriting permissions.")) - return false; - case PERM_EMUNAND: - if (!ShowUnlockSequence(2, "You want to enable EmuNAND\nwriting permissions.")) - return false; - break; - case PERM_IMAGE: - if (!ShowUnlockSequence(2, "You want to enable image\nwriting permissions.")) - return false; - break; - case PERM_GAME: - ShowPrompt(false, "Unlock write permission for\ngame images is not allowed."); - return false; - break; - case PERM_XORPAD: - ShowPrompt(false, "Unlock write permission for\nXORpad drive is not allowed."); - return false; - break; - #ifndef SAFEMODE - case PERM_SYSNAND: - if (!ShowUnlockSequence(3, "!Better be careful!\n \nYou want to enable SysNAND\nwriting permissions.\nThis enables you to do some\nreally dangerous stuff!")) - return false; - break; - case PERM_A9LH: - if (!ShowUnlockSequence(5, "!THIS IS YOUR ONLY WARNING!\n \nYou want to enable A9LH area\nwriting permissions.\nThis enables you to OVERWRITE\nyour A9LH installation!")) - return false; - break; - case PERM_MEMORY: - if (!ShowUnlockSequence(4, "!Better be careful!\n \nYou want to enable memory\nwriting permissions.\nWriting to certain areas may\nlead to unexpected results.")) - return false; - break; - case PERM_SDDATA: - if (!ShowUnlockSequence(2, "You want to enable SD data\nwriting permissions.")) - return false; - break; - case PERM_ALL: - if (!ShowUnlockSequence(3, "!Better be careful!\n \nYou want to enable ALL\nwriting permissions.\nThis enables you to do some\nreally dangerous stuff!")) - return false; - break; - default: - ShowPrompt(false, "Unlock write permission is not allowed."); - return false; - break; - #else - case PERM_ALL: - perm &= ~(PERM_SYSNAND|PERM_MEMORY); - if (!ShowUnlockSequence(2, "You want to enable EmuNAND &\nimage writing permissions.\nKeep backups, just in case.")) - return false; - break; - default: - ShowPrompt(false, "Can't unlock write permission.\nTry GodMode9 instead!"); - return false; - break; - #endif - } - - write_permissions = add_perm ? write_permissions | perm : perm; - - return true; -} - -u32 GetWritePermissions() { - return write_permissions; -} - bool FileCheck(const char* path) { FIL file; - if (PathToNumFSA(path) < 0) return true; + if (!(DriveType(path) & DRV_FAT)) return true; // can't really check this if (fx_open(&file, path, FA_READ | FA_OPEN_EXISTING) == FR_OK) { fx_close(&file); return true; @@ -1065,7 +738,7 @@ bool PathMove(const char* destdir, const char* orig, u32* flags) { char fopath[256]; strncpy(fdpath, destdir, 255); strncpy(fopath, orig, 255); - bool same_drv = (PathToNumFS(orig) == PathToNumFS(destdir)); + bool same_drv = (strncmp(orig, destdir, 2) == 0); bool res = PathCopyWorker(fdpath, fopath, flags, same_drv); if (res && (!flags || !(*flags&SKIP_CUR))) PathDelete(orig); return res; @@ -1157,160 +830,3 @@ void CreateScreenshot() { memcpy(buffer + (y*400 + x + 40) * 3, BOT_SCREEN + (x*240 + y) * 3, 3); FileSetData(filename, MAIN_BUFFER, 54 + (400 * 240 * 3 * 2), 0, true); } - -bool GetRootDirContentsWorker(DirStruct* contents) { - static const char* drvname[] = { - "SDCARD", - "SYSNAND CTRNAND", "SYSNAND TWLN", "SYSNAND TWLP", - "EMUNAND CTRNAND", "EMUNAND TWLN", "EMUNAND TWLP", - "IMGNAND CTRNAND", "IMGNAND TWLN", "IMGNAND TWLP", - "GAME IMAGE", - "SYSNAND SD", "EMUNAND SD", - "SYSNAND VIRTUAL", "EMUNAND VIRTUAL", "IMGNAND VIRTUAL", - "NAND XORPADS", - "MEMORY VIRTUAL", - "LAST SEARCH" - }; - static const char* drvnum[] = { - "0:", "1:", "2:", "3:", "4:", "5:", "6:", "7:", "8:", "9:", "G:", "A:", "B:", "S:", "E:", "I:", "X:", "M:", "Z:" - }; - u32 n_entries = 0; - - // virtual root objects hacked in - for (u32 pdrv = 0; (pdrv < NORM_FS+VIRT_FS) && (n_entries < MAX_DIR_ENTRIES); pdrv++) { - DirEntry* entry = &(contents->entry[n_entries]); - if (!DriveType(drvnum[pdrv])) continue; // drive not available - memset(entry->path, 0x00, 64); - snprintf(entry->path + 0, 4, drvnum[pdrv]); - if ((pdrv == 7) && ((GetMountState() == IMG_FAT) || (GetMountState() == IMG_RAMDRV))) - snprintf(entry->path + 4, 32, "[%s] %s", drvnum[pdrv], // FAT image / RAM drive special handling - (GetMountState() == IMG_FAT) ? "FAT IMAGE" : "RAMDRIVE"); - else if (pdrv == 10) // Game drive special handling - snprintf(entry->path + 4, 32, "[%s] %s %s", drvnum[pdrv], - (GetMountState() == GAME_CIA ) ? "CIA" : - (GetMountState() == GAME_NCSD ) ? "NCSD" : - (GetMountState() == GAME_NCCH ) ? "NCCH" : - (GetMountState() == GAME_EXEFS) ? "EXEFS" : - (GetMountState() == GAME_ROMFS) ? "ROMFS" : "UNK", drvname[pdrv]); - else snprintf(entry->path + 4, 32, "[%s] %s", drvnum[pdrv], drvname[pdrv]); - entry->name = entry->path + 4; - entry->size = GetTotalSpace(entry->path); - entry->type = T_ROOT; - entry->marked = 0; - n_entries++; - } - contents->n_entries = n_entries; - - return contents->n_entries; -} - -bool GetDirContentsWorker(DirStruct* contents, char* fpath, int fnsize, const char* pattern, bool recursive) { - DIR pdir; - FILINFO fno; - char* fname = fpath + strnlen(fpath, fnsize - 1); - bool ret = false; - - if (fa_opendir(&pdir, fpath) != FR_OK) - return false; - (fname++)[0] = '/'; - - while (f_readdir(&pdir, &fno) == FR_OK) { - if ((strncmp(fno.fname, ".", 2) == 0) || (strncmp(fno.fname, "..", 3) == 0)) - continue; // filter out virtual entries - strncpy(fname, fno.fname, (fnsize - 1) - (fname - fpath)); - if (fno.fname[0] == 0) { - ret = true; - break; - } else if (!pattern || MatchName(pattern, fname)) { - DirEntry* entry = &(contents->entry[contents->n_entries]); - strncpy(entry->path, fpath, 256); - entry->name = entry->path + (fname - fpath); - if (fno.fattrib & AM_DIR) { - entry->type = T_DIR; - entry->size = 0; - } else { - entry->type = T_FILE; - entry->size = fno.fsize; - } - entry->marked = 0; - if (contents->n_entries >= MAX_DIR_ENTRIES) { - ret = true; // Too many entries, still okay - break; - } - contents->n_entries++; - } - if (recursive && (fno.fattrib & AM_DIR)) { - if (!GetDirContentsWorker(contents, fpath, fnsize, pattern, recursive)) - break; - } - } - f_closedir(&pdir); - - return ret; -} - -void SearchDirContents(DirStruct* contents, const char* path, const char* pattern, bool recursive) { - contents->n_entries = 0; - if (!(*path)) { // root directory - if (!GetRootDirContentsWorker(contents)) - contents->n_entries = 0; // not required, but so what? - } else { - // create virtual '..' entry - contents->entry->name = contents->entry->path + 8; - strncpy(contents->entry->path, "*?*?*", 8); - strncpy(contents->entry->name, "..", 4); - contents->entry->type = T_DOTDOT; - contents->entry->size = 0; - contents->n_entries = 1; - // search the path - char fpath[256]; // 256 is the maximum length of a full path - strncpy(fpath, path, 256); - if (DriveType(path) & DRV_VIRTUAL) { - if (!GetVirtualDirContents(contents, fpath, 256, pattern, recursive)) - contents->n_entries = 0; - } else { - if (!GetDirContentsWorker(contents, fpath, 256, pattern, recursive)) - contents->n_entries = 0; - } - SortDirStruct(contents); - } -} - -void GetDirContents(DirStruct* contents, const char* path) { - if (IsSearchDrive(path)) { - ShowString("Searching, please wait..."); - SearchDirContents(contents, search_path, search_pattern, true); - ClearScreenF(true, false, COLOR_STD_BG); - } else SearchDirContents(contents, path, NULL, false); -} - -uint64_t GetFreeSpace(const char* path) -{ - DWORD free_clusters; - FATFS *fs_ptr; - char fsname[4] = { '\0' }; - int pdrv = PathToNumFSA(path); - if (pdrv < 0) return 0; - - snprintf(fsname, 3, "%i:", pdrv); - if (f_getfree(fsname, &free_clusters, &fs_ptr) != FR_OK) - return 0; - - return (uint64_t) free_clusters * fs[pdrv].csize * _MAX_SS; -} - -uint64_t GetTotalSpace(const char* path) -{ - int pdrv = PathToNumFSA(path); - if (pdrv < 0) return 0; - - return (uint64_t) (fs[pdrv].n_fatent - 2) * fs[pdrv].csize * _MAX_SS; -} - -uint64_t GetPartitionOffsetSector(const char* path) -{ - int pdrv = PathToNumFSA(path); - if (pdrv < 0) return -1; - - return (uint64_t) fs[pdrv].volbase; -} diff --git a/source/fs/fsutil.h b/source/fs/fsutil.h new file mode 100644 index 0000000..7a0935c --- /dev/null +++ b/source/fs/fsutil.h @@ -0,0 +1,57 @@ +#pragma once + +#include "common.h" +// temporary +// #include "fsinit.h" +// #include "fsdrive.h" +// #include "fsperm.h" + +// move / copy flags +#define ASK_ALL (1<<0) +#define SKIP_ALL (1<<1) +#define OVERWRITE_ALL (1<<2) + +/** Return total size of SD card **/ +uint64_t GetSDCardSize(); + +/** Format the SD card **/ +bool FormatSDCard(u64 hidden_mb, u32 cluster_size); + +/** True if file exists and is not locked, false otherwise **/ +bool FileCheck(const char* path); + +/** Create / open file and write the provided data to it **/ +bool FileSetData(const char* path, const u8* data, size_t size, size_t foffset, bool create); + +/** Read data from file@offset **/ +size_t FileGetData(const char* path, u8* data, size_t size, size_t foffset); + +/** Get size of file **/ +size_t FileGetSize(const char* path); + +/** Get SHA-256 of file **/ +bool FileGetSha256(const char* path, u8* sha256); + +/** Find data in file **/ +u32 FileFindData(const char* path, u8* data, u32 size, u32 offset); + +/** Inject file into file @offset **/ +bool FileInjectFile(const char* dest, const char* orig, u32 offset); + +/** Recursively copy a file or directory **/ +bool PathCopy(const char* destdir, const char* orig, u32* flags); + +/** Recursively move a file or directory **/ +bool PathMove(const char* destdir, const char* orig, u32* flags); + +/** Recursively delete a file or directory **/ +bool PathDelete(const char* path); + +/** Rename file / folder in path to new name **/ +bool PathRename(const char* path, const char* newname); + +/** Create a new directory in cpath **/ +bool DirCreate(const char* cpath, const char* dirname); + +/** Create a screenshot of the current framebuffer **/ +void CreateScreenshot(); diff --git a/source/virtual/sddata.c b/source/fs/sddata.c similarity index 100% rename from source/virtual/sddata.c rename to source/fs/sddata.c diff --git a/source/virtual/sddata.h b/source/fs/sddata.h similarity index 100% rename from source/virtual/sddata.h rename to source/fs/sddata.h diff --git a/source/godmode.c b/source/godmode.c index b1ebbe8..4ad7062 100644 --- a/source/godmode.c +++ b/source/godmode.c @@ -1,7 +1,10 @@ #include "godmode.h" #include "ui.h" #include "hid.h" -#include "fs.h" +#include "fsinit.h" +#include "fsdrive.h" +#include "fsutil.h" +#include "fsperm.h" #include "gameio.h" #include "platform.h" #include "nand.h" @@ -99,7 +102,7 @@ void DrawUserInterface(const char* curr_path, DirEntry* curr_entry, DirStruct* c } DrawStringF(TOP_SCREEN, 4, info_start + 12 + 10, color_current, COLOR_STD_BG, tempstr); // path of file (if in search results) - if (IsSearchDrive(curr_path) && strrchr(curr_entry->path, '/')) { + if ((DriveType(curr_path) & DRV_SEARCH) && strrchr(curr_entry->path, '/')) { char dirstr[256]; strncpy(dirstr, curr_entry->path, 256); *(strrchr(dirstr, '/')+1) = '\0'; @@ -625,7 +628,7 @@ u32 GodMode() { // basic navigation commands if ((pad_state & BUTTON_A) && (curr_entry->type != T_FILE) && (curr_entry->type != T_DOTDOT)) { // for dirs - if (switched && !IsSearchDrive(curr_entry->path)) { // search directory + if (switched && !(DriveType(curr_entry->path) & DRV_SEARCH)) { // search directory char searchstr[256]; char namestr[20+1]; snprintf(searchstr, 256, "*"); diff --git a/source/main.c b/source/main.c index 2955fe9..a9d6db4 100644 --- a/source/main.c +++ b/source/main.c @@ -1,7 +1,6 @@ #include "common.h" #include "godmode.h" #include "ui.h" -#include "fs.h" #include "i2c.h" void Reboot() diff --git a/source/nand/nand.c b/source/nand/nand.c index 50eb208..e7d685b 100644 --- a/source/nand/nand.c +++ b/source/nand/nand.c @@ -1,10 +1,11 @@ -#include "fs.h" +#include "nand.h" +#include "fsdrive.h" +#include "fsutil.h" #include "platform.h" #include "keydb.h" #include "aes.h" #include "sha.h" #include "sdmmc.h" -#include "nand.h" #include "image.h" #define NAND_MIN_SECTORS ((GetUnitPlatform() == PLATFORM_N3DS) ? 0x26C000 : 0x1D7800) diff --git a/source/virtual/virtual.h b/source/virtual/virtual.h index 0f4c8b9..0bf098e 100644 --- a/source/virtual/virtual.h +++ b/source/virtual/virtual.h @@ -1,7 +1,7 @@ #pragma once #include "common.h" -#include "dir.h" +#include "fsdir.h" #include "nand.h" #define VRT_SYSNAND NAND_SYSNAND