Scripting: filesel command for selecting a file

Fixes #197, also includes run_cmd() code cleanup
This commit is contained in:
d0k3 2017-09-13 02:45:00 +02:00
parent b7d914d73f
commit ab557e6ae5
2 changed files with 83 additions and 27 deletions

View File

@ -56,6 +56,12 @@ set USERINPUT "Hello World"
input "Enter something please?" USERINPUT input "Enter something please?" USERINPUT
echo "You entered:\n$[USERINPUT]" echo "You entered:\n$[USERINPUT]"
# 'filesel' COMMAND
# The 'filesel' command allows the user to choose a file inside a directory
# The path is stored inside a variable, and the selection can be limited via wildcards
filesel "Please select a file" 0:/*.* SELFILE
echo "You selected $[SELFILE]\nWe'll do nothing with that :)."
# 'allow' COMMAND # 'allow' COMMAND
# typically used at the beginning of a script, prompts to allow writes to the location given in the argument # typically used at the beginning of a script, prompts to allow writes to the location given in the argument
# doing this from the beginning is preferable, so that no actions are taken unless all required write permissions are unlocked # doing this from the beginning is preferable, so that no actions are taken unless all required write permissions are unlocked

View File

@ -17,7 +17,7 @@
#include "hid.h" #include "hid.h"
#include "ui.h" #include "ui.h"
#define _MAX_ARGS 2 #define _MAX_ARGS 3
#define _VAR_CNT_LEN 256 #define _VAR_CNT_LEN 256
#define _VAR_NAME_LEN 32 #define _VAR_NAME_LEN 32
#define _ERR_STR_LEN 32 #define _ERR_STR_LEN 32
@ -51,6 +51,7 @@ typedef enum {
CMD_ID_ECHO, CMD_ID_ECHO,
CMD_ID_ASK, CMD_ID_ASK,
CMD_ID_INPUT, CMD_ID_INPUT,
CMD_ID_FILESEL,
CMD_ID_SET, CMD_ID_SET,
CMD_ID_ALLOW, CMD_ID_ALLOW,
CMD_ID_CP, CMD_ID_CP,
@ -92,6 +93,7 @@ Gm9ScriptCmd cmd_list[] = {
{ CMD_ID_ECHO , "echo" , 1, 0 }, { CMD_ID_ECHO , "echo" , 1, 0 },
{ CMD_ID_ASK , "ask" , 1, 0 }, { CMD_ID_ASK , "ask" , 1, 0 },
{ CMD_ID_INPUT , "input" , 2, 0 }, { CMD_ID_INPUT , "input" , 2, 0 },
{ CMD_ID_FILESEL , "filesel" , 3, 0 },
{ CMD_ID_SET , "set" , 2, 0 }, { CMD_ID_SET , "set" , 2, 0 },
{ CMD_ID_ALLOW , "allow" , 1, _FLG('a') }, { CMD_ID_ALLOW , "allow" , 1, _FLG('a') },
{ CMD_ID_CP , "cp" , 2, _FLG('h') | _FLG('w') | _FLG('k') | _FLG('s') | _FLG('n')}, { CMD_ID_CP , "cp" , 2, _FLG('h') | _FLG('w') | _FLG('k') | _FLG('s') | _FLG('n')},
@ -471,10 +473,12 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) {
// perform command // perform command
if (id == CMD_ID_ECHO) { if (id == CMD_ID_ECHO) {
ShowPrompt(false, argv[0]); ShowPrompt(false, argv[0]);
} else if (id == CMD_ID_ASK) { }
else if (id == CMD_ID_ASK) {
ret = ShowPrompt(true, argv[0]); ret = ShowPrompt(true, argv[0]);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "user abort"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "user abort");
} else if (id == CMD_ID_INPUT) { }
else if (id == CMD_ID_INPUT) {
char input[_VAR_CNT_LEN] = { 0 }; char input[_VAR_CNT_LEN] = { 0 };
char* var = get_var(argv[1], NULL); char* var = get_var(argv[1], NULL);
strncpy(input, var, _VAR_CNT_LEN); strncpy(input, var, _VAR_CNT_LEN);
@ -485,14 +489,39 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) {
ret = set_var(argv[1], input); ret = set_var(argv[1], input);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "var fail"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "var fail");
} }
} else if (id == CMD_ID_SET) { }
else if (id == CMD_ID_FILESEL) {
char choice[_VAR_CNT_LEN] = { 0 };
char* var = get_var(argv[2], NULL);
strncpy(choice, var, _VAR_CNT_LEN);
char path[_VAR_CNT_LEN];
strncpy(path, argv[1], _VAR_CNT_LEN);
char* npattern = strrchr(path, '/');
if (!npattern) {
ret = false;
if (err_str) snprintf(err_str, _ERR_STR_LEN, "invalid path");
} else {
*(npattern++) = '\0';
ret = FileSelector(choice, argv[0], path, npattern, false, true);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "fileselect abort");
}
if (ret) {
ret = set_var(argv[2], choice);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "var fail");
}
}
else if (id == CMD_ID_SET) {
ret = set_var(argv[0], argv[1]); ret = set_var(argv[0], argv[1]);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "set fail"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "set fail");
} else if (id == CMD_ID_ALLOW) { }
else if (id == CMD_ID_ALLOW) {
if (flags & _FLG('a')) ret = CheckDirWritePermissions(argv[0]); if (flags & _FLG('a')) ret = CheckDirWritePermissions(argv[0]);
else ret = CheckWritePermissions(argv[0]); else ret = CheckWritePermissions(argv[0]);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "permission fail"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "permission fail");
} else if (id == CMD_ID_CP) { }
else if (id == CMD_ID_CP) {
u32 flags_ext = BUILD_PATH; u32 flags_ext = BUILD_PATH;
if (flags & _FLG('h')) flags_ext |= CALC_SHA; if (flags & _FLG('h')) flags_ext |= CALC_SHA;
if (flags & _FLG('n')) flags_ext |= NO_CANCEL; if (flags & _FLG('n')) flags_ext |= NO_CANCEL;
@ -501,7 +530,8 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) {
else if (flags & _FLG('k')) flags_ext |= SKIP_ALL; else if (flags & _FLG('k')) flags_ext |= SKIP_ALL;
ret = PathMoveCopy(argv[1], argv[0], &flags_ext, false); ret = PathMoveCopy(argv[1], argv[0], &flags_ext, false);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "copy fail"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "copy fail");
} else if (id == CMD_ID_MV) { }
else if (id == CMD_ID_MV) {
u32 flags_ext = BUILD_PATH; u32 flags_ext = BUILD_PATH;
if (flags & _FLG('n')) flags_ext |= NO_CANCEL; if (flags & _FLG('n')) flags_ext |= NO_CANCEL;
if (flags & _FLG('s')) flags_ext |= SILENT; if (flags & _FLG('s')) flags_ext |= SILENT;
@ -509,7 +539,8 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) {
else if (flags & _FLG('k')) flags_ext |= SKIP_ALL; else if (flags & _FLG('k')) flags_ext |= SKIP_ALL;
ret = PathMoveCopy(argv[1], argv[0], &flags_ext, true); ret = PathMoveCopy(argv[1], argv[0], &flags_ext, true);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "move fail"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "move fail");
} else if (id == CMD_ID_INJECT) { }
else if (id == CMD_ID_INJECT) {
char* atstr_dst = strrchr(argv[1], '@'); char* atstr_dst = strrchr(argv[1], '@');
u64 at_dst = 0; u64 at_dst = 0;
if (atstr_dst) { if (atstr_dst) {
@ -520,21 +551,26 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) {
if (flags & _FLG('n')) flags_ext |= NO_CANCEL; if (flags & _FLG('n')) flags_ext |= NO_CANCEL;
ret = FileInjectFile(argv[1], argv[0], at_dst, at_org, sz_org, &flags_ext); ret = FileInjectFile(argv[1], argv[0], at_dst, at_org, sz_org, &flags_ext);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "inject fail"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "inject fail");
} else if (id == CMD_ID_RM) { }
else if (id == CMD_ID_RM) {
char pathstr[_ERR_STR_LEN]; char pathstr[_ERR_STR_LEN];
TruncateString(pathstr, argv[0], 24, 8); TruncateString(pathstr, argv[0], 24, 8);
ShowString("Deleting %s...", pathstr); ShowString("Deleting %s...", pathstr);
ret = PathDelete(argv[0]); ret = PathDelete(argv[0]);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "remove fail"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "remove fail");
} else if (id == CMD_ID_MKDIR) { }
else if (id == CMD_ID_MKDIR) {
ret = (CheckWritePermissions(argv[0])) && (fvx_rmkdir(argv[0]) == FR_OK); ret = (CheckWritePermissions(argv[0])) && (fvx_rmkdir(argv[0]) == FR_OK);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "makedir fail"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "makedir fail");
} else if (id == CMD_ID_MOUNT) { }
else if (id == CMD_ID_MOUNT) {
ret = InitImgFS(argv[0]); ret = InitImgFS(argv[0]);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "mount fail"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "mount fail");
} else if (id == CMD_ID_UMOUNT) { }
else if (id == CMD_ID_UMOUNT) {
InitImgFS(NULL); InitImgFS(NULL);
} else if (id == CMD_ID_FIND) { }
else if (id == CMD_ID_FIND) {
char path[_VAR_CNT_LEN]; char path[_VAR_CNT_LEN];
u8 mode = (flags & _FLG('f')) ? FN_LOWEST : FN_HIGHEST; u8 mode = (flags & _FLG('f')) ? FN_LOWEST : FN_HIGHEST;
ret = (fvx_findpath(path, argv[0], mode) == FR_OK); ret = (fvx_findpath(path, argv[0], mode) == FR_OK);
@ -543,7 +579,8 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) {
ret = set_var(argv[1], path); ret = set_var(argv[1], path);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "var fail"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "var fail");
} }
} else if (id == CMD_ID_FINDNOT) { }
else if (id == CMD_ID_FINDNOT) {
char path[_VAR_CNT_LEN]; char path[_VAR_CNT_LEN];
ret = (fvx_findnopath(path, argv[0]) == FR_OK); ret = (fvx_findnopath(path, argv[0]) == FR_OK);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "findnot fail"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "findnot fail");
@ -551,7 +588,8 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) {
ret = set_var(argv[1], path); ret = set_var(argv[1], path);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "var fail"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "var fail");
} }
} else if (id == CMD_ID_SHA) { }
else if (id == CMD_ID_SHA) {
u8 sha256_fil[0x20]; u8 sha256_fil[0x20];
u8 sha256_cmp[0x20]; u8 sha256_cmp[0x20];
if (!FileGetSha256(argv[0], sha256_fil, at_org, sz_org)) { if (!FileGetSha256(argv[0], sha256_fil, at_org, sz_org)) {
@ -564,36 +602,43 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) {
ret = (memcmp(sha256_fil, sha256_cmp, 0x20) == 0); ret = (memcmp(sha256_fil, sha256_cmp, 0x20) == 0);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "sha does not match"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "sha does not match");
} }
} else if (id == CMD_ID_SHAGET) { }
else if (id == CMD_ID_SHAGET) {
u8 sha256_fil[0x20]; u8 sha256_fil[0x20];
if (!(ret = FileGetSha256(argv[0], sha256_fil, at_org, sz_org))) { if (!(ret = FileGetSha256(argv[0], sha256_fil, at_org, sz_org))) {
if (err_str) snprintf(err_str, _ERR_STR_LEN, "sha arg0 fail"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "sha arg0 fail");
} else if (!(ret = FileSetData(argv[1], sha256_fil, 0x20, 0, true))) { } else if (!(ret = FileSetData(argv[1], sha256_fil, 0x20, 0, true))) {
if (err_str) snprintf(err_str, _ERR_STR_LEN, "sha write fail"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "sha write fail");
} }
} else if (id == CMD_ID_FIXCMAC) { }
else if (id == CMD_ID_FIXCMAC) {
ShowString("Fixing CMACs..."); ShowString("Fixing CMACs...");
ret = (RecursiveFixFileCmac(argv[0]) == 0); ret = (RecursiveFixFileCmac(argv[0]) == 0);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "fixcmac failed"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "fixcmac failed");
} else if (id == CMD_ID_VERIFY) { }
else if (id == CMD_ID_VERIFY) {
u32 filetype = IdentifyFileType(argv[0]); u32 filetype = IdentifyFileType(argv[0]);
if (filetype & IMG_NAND) ret = (ValidateNandDump(argv[0]) == 0); if (filetype & IMG_NAND) ret = (ValidateNandDump(argv[0]) == 0);
else ret = (VerifyGameFile(argv[0]) == 0); else ret = (VerifyGameFile(argv[0]) == 0);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "verification failed"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "verification failed");
} else if (id == CMD_ID_DECRYPT) { }
else if (id == CMD_ID_DECRYPT) {
u32 filetype = IdentifyFileType(argv[0]); u32 filetype = IdentifyFileType(argv[0]);
if (filetype & BIN_KEYDB) ret = (CryptAesKeyDb(argv[0], true, false) == 0); if (filetype & BIN_KEYDB) ret = (CryptAesKeyDb(argv[0], true, false) == 0);
else ret = (CryptGameFile(argv[0], true, false) == 0); else ret = (CryptGameFile(argv[0], true, false) == 0);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "decrypt failed"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "decrypt failed");
} else if (id == CMD_ID_ENCRYPT) { }
else if (id == CMD_ID_ENCRYPT) {
u32 filetype = IdentifyFileType(argv[0]); u32 filetype = IdentifyFileType(argv[0]);
if (filetype & BIN_KEYDB) ret = (CryptAesKeyDb(argv[0], true, true) == 0); if (filetype & BIN_KEYDB) ret = (CryptAesKeyDb(argv[0], true, true) == 0);
else ret = (CryptGameFile(argv[0], true, true) == 0); else ret = (CryptGameFile(argv[0], true, true) == 0);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "encrypt failed"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "encrypt failed");
} else if (id == CMD_ID_BUILDCIA) { }
else if (id == CMD_ID_BUILDCIA) {
ret = (BuildCiaFromGameFile(argv[0], (flags & _FLG('n'))) == 0); ret = (BuildCiaFromGameFile(argv[0], (flags & _FLG('n'))) == 0);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "build CIA failed"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "build CIA failed");
} else if (id == CMD_ID_EXTRCODE) { }
else if (id == CMD_ID_EXTRCODE) {
u32 filetype = IdentifyFileType(argv[0]); u32 filetype = IdentifyFileType(argv[0]);
if ((filetype&(GAME_NCCH|FLAG_CXI)) != (GAME_NCCH|FLAG_CXI)) { if ((filetype&(GAME_NCCH|FLAG_CXI)) != (GAME_NCCH|FLAG_CXI)) {
ret = false; ret = false;
@ -603,7 +648,8 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) {
ret = (ExtractCodeFromCxiFile(argv[0], argv[1]) == 0); ret = (ExtractCodeFromCxiFile(argv[0], argv[1]) == 0);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "extract .code failed"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "extract .code failed");
} }
} else if (id == CMD_ID_BOOT) { }
else if (id == CMD_ID_BOOT) {
size_t firm_size = FileGetData(argv[0], TEMP_BUFFER, TEMP_BUFFER_SIZE, 0); size_t firm_size = FileGetData(argv[0], TEMP_BUFFER, TEMP_BUFFER_SIZE, 0);
ret = firm_size && (firm_size < TEMP_BUFFER_SIZE) && ret = firm_size && (firm_size < TEMP_BUFFER_SIZE) &&
(ValidateFirm(TEMP_BUFFER, firm_size, false) == 0); (ValidateFirm(TEMP_BUFFER, firm_size, false) == 0);
@ -615,7 +661,8 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) {
BootFirm((FirmHeader*)(void*)TEMP_BUFFER, fixpath); BootFirm((FirmHeader*)(void*)TEMP_BUFFER, fixpath);
while(1); while(1);
} else if (err_str) snprintf(err_str, _ERR_STR_LEN, "not a bootable firm"); } else if (err_str) snprintf(err_str, _ERR_STR_LEN, "not a bootable firm");
} else if (id == CMD_ID_SWITCHSD) { }
else if (id == CMD_ID_SWITCHSD) {
DeinitExtFS(); DeinitExtFS();
if (!(ret = CheckSDMountState())) { if (!(ret = CheckSDMountState())) {
if (err_str) snprintf(err_str, _ERR_STR_LEN, "SD not mounted"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "SD not mounted");
@ -636,15 +683,18 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) {
InitSDCardFS(); InitSDCardFS();
AutoEmuNandBase(true); AutoEmuNandBase(true);
InitExtFS(); InitExtFS();
} else if (id == CMD_ID_REBOOT) { }
else if (id == CMD_ID_REBOOT) {
DeinitExtFS(); DeinitExtFS();
DeinitSDCardFS(); DeinitSDCardFS();
Reboot(); Reboot();
} else if (id == CMD_ID_POWEROFF) { }
else if (id == CMD_ID_POWEROFF) {
DeinitExtFS(); DeinitExtFS();
DeinitSDCardFS(); DeinitSDCardFS();
PowerOff(); PowerOff();
} else { // command not recognized / bad number of arguments }
else { // command not recognized / bad number of arguments
ret = false; ret = false;
if (err_str) snprintf(err_str, _ERR_STR_LEN, "unknown error"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "unknown error");
} }