diff --git a/source/filesys/fsutil.c b/source/filesys/fsutil.c index d79aea7..686da53 100644 --- a/source/filesys/fsutil.c +++ b/source/filesys/fsutil.c @@ -666,6 +666,11 @@ bool PathRename(const char* path, const char* newname) { return (f_rename(path, npath) == FR_OK); } +bool PathAttr(const char* path, u8 attr, u8 mask) { + if (!CheckDirWritePermissions(path)) return false; + return (f_chmod(path, attr, mask) == FR_OK); +} + bool FileSelector(char* result, const char* text, const char* path, const char* pattern, bool hide_ext, bool no_dirs) { DirStruct* contents = (DirStruct*) (void*) TEMP_BUFFER; char path_local[256]; diff --git a/source/filesys/fsutil.h b/source/filesys/fsutil.h index 80ae171..e350ce3 100644 --- a/source/filesys/fsutil.h +++ b/source/filesys/fsutil.h @@ -70,6 +70,9 @@ bool PathDelete(const char* path); /** Rename file / folder in path to new name **/ bool PathRename(const char* path, const char* newname); +/** Change the attributes on a file/directory **/ +bool PathAttr(const char* path, u8 attr, u8 mask); + /** Select a file **/ bool FileSelector(char* result, const char* text, const char* path, const char* pattern, bool hide_ext, bool no_dirs); diff --git a/source/godmode.c b/source/godmode.c index c44713f..5e42cfe 100644 --- a/source/godmode.c +++ b/source/godmode.c @@ -835,6 +835,79 @@ u32 BootFirmHandler(const char* bootpath, bool verbose, bool delete) { return 1; } +u32 FileAttrMenu(const char* file_path) { + FILINFO fno; + if (fvx_stat(file_path, &fno) != FR_OK) { + char pathstr[32 + 1]; + TruncateString(pathstr, file_path, 32, 8); + ShowPrompt(false, "%s\nFile info failed!", pathstr); + return 1; + } + + char namestr[32]; + char sizestr[32]; + TruncateString(namestr, fno.fname, 32, 8); + FormatNumber(sizestr, fno.fsize); + const bool vrt = (fno.fattrib & AM_VRT); + u8 new_attrib = fno.fattrib; + + while (true) { + ShowString( + "%s\n" + " \n" + "filesize: %s byte\n" + "modified: %04lu-%02lu-%02lu %02lu:%02lu:%02lu\n" + " \n" + "[%c] %sread-only [%c] %shidden\n" + "[%c] %ssystem [%c] %sarchive\n" + "[%c] %svirtual\n" + " \n" + "%s" + "%s", + namestr, sizestr, + 1980 + ((fno.fdate >> 9) & 0x7F), (fno.fdate >> 5) & 0x0F, (fno.fdate >> 0) & 0x1F, + (fno.ftime >> 11) & 0x1F, (fno.ftime >> 5) & 0x3F, ((fno.ftime >> 0) & 0x1F) << 1, + (new_attrib & AM_RDO) ? 'X' : ' ', (vrt ? "" : "\x18 "), + (new_attrib & AM_HID) ? 'X' : ' ', (vrt ? "" : "\x19 "), + (new_attrib & AM_SYS) ? 'X' : ' ', (vrt ? "" : "\x1A "), + (new_attrib & AM_ARC) ? 'X' : ' ', (vrt ? "" : "\x1B "), + vrt ? 'X' : ' ', (vrt ? "" : " "), + vrt ? "" : "(\x18\x19\x1A\x1B to change attributes)\n", + (vrt || (new_attrib == fno.fattrib)) ? "( to continue)" : "( to apply, to cancel)"); + + while (true) { + u32 pad_state = InputWait(0); + if (pad_state & (BUTTON_A | BUTTON_B)) { + bool apply = !vrt && (new_attrib != fno.fattrib) && (pad_state & BUTTON_A); + const u8 mask = (AM_RDO | AM_HID | AM_SYS | AM_ARC); + if (apply && !PathAttr(file_path, new_attrib & mask, mask)) { + ShowPrompt(false, "%s\nFailed to set attributes!", namestr); + } + ClearScreenF(true, false, COLOR_STD_BG); + return 0; + } else if (vrt) continue; + + switch (pad_state) { + case BUTTON_UP: + new_attrib ^= AM_RDO; + break; + case BUTTON_DOWN: + new_attrib ^= AM_HID; + break; + case BUTTON_RIGHT: + new_attrib ^= AM_SYS; + break; + case BUTTON_LEFT: + new_attrib ^= AM_ARC; + break; + default: + continue; + } + break; + } + } +} + u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pane) { const char* file_path = (&(current_dir->entry[*cursor]))->path; const char* optionstr[16]; @@ -1005,21 +1078,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan return FileHandlerMenu(current_path, cursor, scroll, pane); } else if (user_select == fileinfo) { // -> show file info - FILINFO fno; - if (fvx_stat(file_path, &fno) != FR_OK) { - ShowPrompt(false, "%s\nFile info failed!", pathstr); - return 0; - }; - char sizestr[32]; - char namestr[32]; - FormatNumber(sizestr, fno.fsize); - TruncateString(namestr, fno.fname, 32, 8); - ShowPrompt(false, "%s\n \nfilesize: %s byte\nmodified: %04lu-%02lu-%02lu %02lu:%02lu:%02lu\n \n[%c] read-only [%c] hidden\n[%c] system [%c] archive\n[%c] virtual", - namestr, sizestr, - 1980 + ((fno.fdate >> 9) & 0x7F), (fno.fdate >> 5) & 0x0F, (fno.fdate >> 0) & 0x1F, - (fno.ftime >> 11) & 0x1F, (fno.ftime >> 5) & 0x3F, ((fno.ftime >> 0) & 0x1F) << 1, - (fno.fattrib & AM_RDO) ? 'X' : ' ', (fno.fattrib & AM_HID) ? 'X' : ' ', (fno.fattrib & AM_SYS) ? 'X' : ' ' , - (fno.fattrib & AM_ARC) ? 'X' : ' ', (fno.fattrib & AM_VRT) ? 'X' : ' '); + FileAttrMenu(file_path); return 0; } else if (user_select == copystd) { // -> copy to OUTPUT_PATH