Cleanup and reorganize fs.c / fs.h

This commit is contained in:
d0k3 2016-12-10 15:32:03 +01:00
parent 4dc92abef6
commit 020b1b74b2
20 changed files with 668 additions and 629 deletions

View File

@ -21,9 +21,9 @@ ifeq ($(MODE),safe)
export TARGET := SafeMode9 export TARGET := SafeMode9
endif endif
BUILD := build 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 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 # options for code generation

View File

@ -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);

View File

@ -1,4 +1,4 @@
#include "dir.h" #include "fsdir.h"
void DirEntryCpy(DirEntry* dest, const DirEntry* orig) { void DirEntryCpy(DirEntry* dest, const DirEntry* orig) {
memcpy(dest, orig, sizeof(DirEntry)); memcpy(dest, orig, sizeof(DirEntry));

200
source/fs/fsdrive.c Normal file
View File

@ -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;
}

58
source/fs/fsdrive.h Normal file
View File

@ -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);

126
source/fs/fsinit.c Normal file
View File

@ -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;
}

31
source/fs/fsinit.h Normal file
View File

@ -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);

147
source/fs/fsperm.c Normal file
View File

@ -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;
}

26
source/fs/fsperm.h Normal file
View File

@ -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();

View File

@ -1,16 +1,13 @@
#include "ui.h" #include "fsutil.h"
#include "fs.h" #include "fsinit.h"
#include "virtual.h" #include "fsdrive.h"
#include "vgame.h" #include "fsperm.h"
#include "sddata.h" #include "sddata.h"
#include "image.h" #include "virtual.h"
#include "sha.h" #include "sha.h"
#include "sdmmc.h" #include "sdmmc.h"
#include "ff.h" #include "ff.h"
#include "ui.h"
#define NORM_FS 10
#define IMGN_FS 3 // image normal filesystems
#define VIRT_FS 9
#define SKIP_CUR (1<<3) #define SKIP_CUR (1<<3)
#define OVERWRITE_CUR (1<<4) #define OVERWRITE_CUR (1<<4)
@ -21,191 +18,6 @@ PARTITION VolToPart[] = {
{5, 0}, {6, 0}, {7, 0}, {8, 0}, {9, 0} {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() { uint64_t GetSDCardSize() {
if (sdmmc_sdcard_init() != 0) return 0; if (sdmmc_sdcard_init() != 0) return 0;
return (u64) getMMCDevice(1)->total_size * 512; return (u64) getMMCDevice(1)->total_size * 512;
@ -255,156 +67,17 @@ bool FormatSDCard(u64 hidden_mb, u32 cluster_size) {
} }
// format the SD card // format the SD card
f_mount(fs, "0:", 1); InitSDCardFS();
UINT c_size = cluster_size; 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); 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; 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) { bool FileCheck(const char* path) {
FIL file; 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) { if (fx_open(&file, path, FA_READ | FA_OPEN_EXISTING) == FR_OK) {
fx_close(&file); fx_close(&file);
return true; return true;
@ -1065,7 +738,7 @@ bool PathMove(const char* destdir, const char* orig, u32* flags) {
char fopath[256]; char fopath[256];
strncpy(fdpath, destdir, 255); strncpy(fdpath, destdir, 255);
strncpy(fopath, orig, 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); bool res = PathCopyWorker(fdpath, fopath, flags, same_drv);
if (res && (!flags || !(*flags&SKIP_CUR))) PathDelete(orig); if (res && (!flags || !(*flags&SKIP_CUR))) PathDelete(orig);
return res; return res;
@ -1157,160 +830,3 @@ void CreateScreenshot() {
memcpy(buffer + (y*400 + x + 40) * 3, BOT_SCREEN + (x*240 + y) * 3, 3); 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); 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;
}

57
source/fs/fsutil.h Normal file
View File

@ -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();

View File

@ -1,7 +1,10 @@
#include "godmode.h" #include "godmode.h"
#include "ui.h" #include "ui.h"
#include "hid.h" #include "hid.h"
#include "fs.h" #include "fsinit.h"
#include "fsdrive.h"
#include "fsutil.h"
#include "fsperm.h"
#include "gameio.h" #include "gameio.h"
#include "platform.h" #include "platform.h"
#include "nand.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); DrawStringF(TOP_SCREEN, 4, info_start + 12 + 10, color_current, COLOR_STD_BG, tempstr);
// path of file (if in search results) // 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]; char dirstr[256];
strncpy(dirstr, curr_entry->path, 256); strncpy(dirstr, curr_entry->path, 256);
*(strrchr(dirstr, '/')+1) = '\0'; *(strrchr(dirstr, '/')+1) = '\0';
@ -625,7 +628,7 @@ u32 GodMode() {
// basic navigation commands // basic navigation commands
if ((pad_state & BUTTON_A) && (curr_entry->type != T_FILE) && (curr_entry->type != T_DOTDOT)) { // for dirs 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 searchstr[256];
char namestr[20+1]; char namestr[20+1];
snprintf(searchstr, 256, "*"); snprintf(searchstr, 256, "*");

View File

@ -1,7 +1,6 @@
#include "common.h" #include "common.h"
#include "godmode.h" #include "godmode.h"
#include "ui.h" #include "ui.h"
#include "fs.h"
#include "i2c.h" #include "i2c.h"
void Reboot() void Reboot()

View File

@ -1,10 +1,11 @@
#include "fs.h" #include "nand.h"
#include "fsdrive.h"
#include "fsutil.h"
#include "platform.h" #include "platform.h"
#include "keydb.h" #include "keydb.h"
#include "aes.h" #include "aes.h"
#include "sha.h" #include "sha.h"
#include "sdmmc.h" #include "sdmmc.h"
#include "nand.h"
#include "image.h" #include "image.h"
#define NAND_MIN_SECTORS ((GetUnitPlatform() == PLATFORM_N3DS) ? 0x26C000 : 0x1D7800) #define NAND_MIN_SECTORS ((GetUnitPlatform() == PLATFORM_N3DS) ? 0x26C000 : 0x1D7800)

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "common.h" #include "common.h"
#include "dir.h" #include "fsdir.h"
#include "nand.h" #include "nand.h"
#define VRT_SYSNAND NAND_SYSNAND #define VRT_SYSNAND NAND_SYSNAND