Scripting: 'fill' and 'fdummy' commands

This commit is contained in:
d0k3 2018-01-02 02:26:49 +01:00
parent c7d60879ae
commit 93f966e1da
4 changed files with 93 additions and 2 deletions

View File

@ -198,6 +198,23 @@ set ERRORMSG "SHA check failed (this was expected)"
sha -o $[RENPATH] $[TESTPATH].sha
set ERRORMSG ""
# 'fdummy' COMMAND
# This command creates a dummy file of the specified size (size in hex)
# Contents of the dummy file are undefined and existing files won't be overwritten
set DUMMY 0:/testdir/dummy.bin
fdummy $[DUMMY] 400
# 'fill' COMMAND
# This command fills (a portition of) a file with the specified byte value
# The syntax is: fill destination@x:y fillbyte
# x: destination offset (in hex)
# y: destination size, starting at x (in hex)
# If x is not given, the full file size, starting from offset 0, is overwritten
# If y is not given, everything starting from offset x is overwritten
# -n / --no_cancel prevents user cancels (useful on critical operations)
fill $[DUMMY]@100:100 FF
fill $[DUMMY]@300 80
# 'fixcmac' COMMAND
# Use this to fix the CMACs for a file or a whole folder (recursively)
# This will count as success if a file does not contain a CMAC

View File

@ -270,10 +270,55 @@ bool FileInjectFile(const char* dest, const char* orig, u64 off_dest, u64 off_or
return ret;
}
bool FileSetByte(const char* dest, u64 offset, u64 size, u8 fillbyte, u32* flags) {
FIL dfile;
bool allow_expand = (flags && (*flags & ALLOW_EXPAND));
if (!CheckWritePermissions(dest)) return false;
// open destination
if (fvx_open(&dfile, dest, FA_WRITE | ((allow_expand) ? FA_OPEN_ALWAYS : FA_OPEN_EXISTING)) != FR_OK)
return false;
fvx_lseek(&dfile, offset);
if (!size && (offset < fvx_size(&dfile)))
size = fvx_size(&dfile) - offset;
// check file limits
if (!allow_expand && (offset + size > fvx_size(&dfile))) {
ShowPrompt(false, "Operation would write beyond end of file");
fvx_close(&dfile);
return false;
}
bool ret = true;
memset(MAIN_BUFFER, fillbyte, size);
ShowProgress(0, 0, dest);
for (u64 pos = 0; (pos < size) && ret; pos += MAIN_BUFFER_SIZE) {
UINT write_bytes = min(MAIN_BUFFER_SIZE, size - pos);
UINT bytes_written = write_bytes;
if ((fvx_write(&dfile, MAIN_BUFFER, write_bytes, &bytes_written) != FR_OK) ||
(write_bytes != bytes_written))
ret = false;
if (ret && !ShowProgress(pos + bytes_written, size, dest)) {
if (flags && (*flags & NO_CANCEL)) {
ShowPrompt(false, "Cancel is not allowed here");
} else ret = !ShowPrompt(true, "B button detected. Cancel?");
ShowProgress(0, 0, dest);
ShowProgress(pos + bytes_written, size, dest);
}
}
ShowProgress(1, 1, dest);
fvx_close(&dfile);
return ret;
}
bool FileCreateDummy(const char* cpath, const char* filename, u64 size) {
char npath[256]; // 256 is the maximum length of a full path
if (!CheckWritePermissions(cpath)) return false;
snprintf(npath, 255, "%s/%s", cpath, filename);
if (filename) snprintf(npath, 255, "%s/%s", cpath, filename);
else snprintf(npath, 255, "%s", cpath);
// create dummy file (fail if already existing)
// then, expand the file size via cluster preallocation

View File

@ -43,6 +43,9 @@ u32 FileFindData(const char* path, u8* data, u32 size_data, u32 offset_file);
/** Inject file into file @offset **/
bool FileInjectFile(const char* dest, const char* orig, u64 off_dest, u64 off_orig, u64 size, u32* flags);
/** Fill (a portion of) a file with a fillbyte **/
bool FileSetByte(const char* dest, u64 offset, u64 size, u8 fillbyte, u32* flags);
/** Create a dummy file at dest **/
bool FileCreateDummy(const char* cpath, const char* filename, u64 size);

View File

@ -78,6 +78,8 @@ typedef enum {
CMD_ID_CP,
CMD_ID_MV,
CMD_ID_INJECT,
CMD_ID_FILL,
CMD_ID_FDUMMY,
CMD_ID_RM,
CMD_ID_MKDIR,
CMD_ID_MOUNT,
@ -133,6 +135,8 @@ Gm9ScriptCmd cmd_list[] = {
{ CMD_ID_CP , "cp" , 2, _FLG('h') | _FLG('w') | _FLG('k') | _FLG('s') | _FLG('n')},
{ CMD_ID_MV , "mv" , 2, _FLG('w') | _FLG('k') | _FLG('s') | _FLG('n') },
{ CMD_ID_INJECT , "inject" , 2, _FLG('n') },
{ CMD_ID_FILL , "fill" , 2, 0 },
{ CMD_ID_FDUMMY , "fdummy" , 2, 0 },
{ CMD_ID_RM , "rm" , 1, 0 },
{ CMD_ID_MKDIR , "mkdir" , 1, 0 },
{ CMD_ID_MOUNT , "imgmount", 1, 0 },
@ -661,7 +665,7 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) {
// process arg0 @string
u64 at_org = 0;
u64 sz_org = 0;
if ((id == CMD_ID_SHA) || (id == CMD_ID_SHAGET) || (id == CMD_ID_INJECT)) {
if ((id == CMD_ID_SHA) || (id == CMD_ID_SHAGET) || (id == CMD_ID_INJECT) || (id == CMD_ID_FILL)) {
char* atstr_org = strrchr(argv[0], '@');
if (atstr_org) {
*(atstr_org++) = '\0';
@ -910,6 +914,28 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) {
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");
}
else if (id == CMD_ID_FILL) {
u32 flags_ext = ALLOW_EXPAND;
u8 fillbyte = 0;
if ((strnlen(argv[1], _ARG_MAX_LEN) != 2) || !strntohex(argv[1], &fillbyte, 1)) {
ret = false;
if (err_str) snprintf(err_str, _ERR_STR_LEN, "fillbyte fail");
} else {
if (flags & _FLG('n')) flags_ext |= NO_CANCEL;
ret = FileSetByte(argv[0], at_org, sz_org, fillbyte, &flags_ext);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "fill fail");
}
}
else if (id == CMD_ID_FDUMMY) {
u32 fsize;
if (sscanf(argv[1], "%lX", &fsize) != 1) {
ret = false;
if (err_str) snprintf(err_str, _ERR_STR_LEN, "bad filesize");
} else {
ret = FileCreateDummy(argv[0], NULL, fsize);
if (err_str) snprintf(err_str, _ERR_STR_LEN, "create dummy fail");
}
}
else if (id == CMD_ID_RM) {
char pathstr[_ERR_STR_LEN];
TruncateString(pathstr, argv[0], 24, 8);