Working file copying routines

This commit is contained in:
d0k3 2016-03-02 17:22:44 +01:00
parent 2a53ee0a5b
commit df82754a6a
4 changed files with 54 additions and 37 deletions

View File

@ -264,22 +264,31 @@ bool ShowUnlockSequence(u32 seqlvl, const char *format, ...) {
return (lvl >= len); return (lvl >= len);
} }
void ShowProgress(u64 current, u64 total, const char* opstr, bool clearscreen) bool ShowProgress(u64 current, u64 total, const char* opstr)
{ {
static u32 last_prog_width = 0;
const u32 bar_width = 240; const u32 bar_width = 240;
const u32 bar_height = 12; const u32 bar_height = 12;
const u32 bar_pos_x = (SCREEN_WIDTH_TOP - bar_width) / 2; const u32 bar_pos_x = (SCREEN_WIDTH_TOP - bar_width) / 2;
const u32 bar_pos_y = (SCREEN_HEIGHT / 2) - bar_height - 2; const u32 bar_pos_y = (SCREEN_HEIGHT / 2) - bar_height - 2 - 10;
const u32 text_pos_y = (SCREEN_HEIGHT / 2); const u32 text_pos_y = bar_pos_y + bar_height + 2;
u32 prog_width = ((total > 0) && (current <= total)) ? (current * (bar_width-4)) / total : 0; u32 prog_width = ((total > 0) && (current <= total)) ? (current * (bar_width-4)) / total : 0;
char tempstr[64]; char tempstr[64];
if (clearscreen) ClearScreenF(true, false, COLOR_STD_BG); if (!current || last_prog_width > prog_width) {
DrawRectangleF(true, bar_pos_x, bar_pos_y, bar_width, bar_height, COLOR_DARKGREY); ClearScreenF(true, false, COLOR_STD_BG);
DrawRectangleF(true, bar_pos_x + 1, bar_pos_y + 1, bar_width - 2, bar_height - 2, COLOR_STD_BG); DrawRectangleF(true, bar_pos_x, bar_pos_y, bar_width, bar_height, COLOR_STD_FONT);
DrawRectangleF(true, bar_pos_x + 1, bar_pos_y + 1, bar_width - 2, bar_height - 2, COLOR_STD_BG);
}
DrawRectangleF(true, bar_pos_x + 2, bar_pos_y + 2, prog_width, bar_height - 4, COLOR_STD_FONT); DrawRectangleF(true, bar_pos_x + 2, bar_pos_y + 2, prog_width, bar_height - 4, COLOR_STD_FONT);
ResizeString(tempstr, opstr, 28, 8, false); ResizeString(tempstr, opstr, 28, 8, false);
DrawString(TOP_SCREEN0, tempstr, bar_pos_x, text_pos_y, COLOR_STD_FONT, COLOR_STD_BG); DrawString(TOP_SCREEN0, tempstr, bar_pos_x, text_pos_y, COLOR_STD_FONT, COLOR_STD_BG);
DrawString(TOP_SCREEN1, tempstr, bar_pos_x, text_pos_y, COLOR_STD_FONT, COLOR_STD_BG); DrawString(TOP_SCREEN1, tempstr, bar_pos_x, text_pos_y, COLOR_STD_FONT, COLOR_STD_BG);
DrawString(TOP_SCREEN0, "(hold B to cancel)", bar_pos_x + 2, text_pos_y + 14, COLOR_STD_FONT, COLOR_STD_BG);
DrawString(TOP_SCREEN1, "(hold B to cancel)", bar_pos_x + 2, text_pos_y + 14, COLOR_STD_FONT, COLOR_STD_BG);
last_prog_width = prog_width;
return !(~HID_STATE & BUTTON_B);
} }

View File

@ -70,4 +70,4 @@ void FormatBytes(char* str, u64 bytes);
bool ShowPrompt(bool ask, const char *format, ...); bool ShowPrompt(bool ask, const char *format, ...);
bool ShowUnlockSequence(u32 seqlvl, const char *format, ...); bool ShowUnlockSequence(u32 seqlvl, const char *format, ...);
void ShowProgress(u64 current, u64 total, const char* opstr, bool clearscreen); bool ShowProgress(u64 current, u64 total, const char* opstr);

View File

@ -8,7 +8,7 @@ static FATFS* fs = (FATFS*)0x20316000;
// this is the main buffer // this is the main buffer
static u8* main_buffer = (u8*)0x21100000; static u8* main_buffer = (u8*)0x21100000;
// this is the main buffer size // this is the main buffer size
static size_t main_buffer_size = 128 * 1024; static size_t main_buffer_size = 1 * 1024 * 1024;
// write permission level - careful with this // write permission level - careful with this
static u32 write_permission_level = 1; static u32 write_permission_level = 1;
@ -24,7 +24,7 @@ bool InitFS() {
#endif #endif
for (numfs = 0; numfs < 7; numfs++) { for (numfs = 0; numfs < 7; numfs++) {
char fsname[8]; char fsname[8];
snprintf(fsname, 8, "%lu:", numfs); snprintf(fsname, 7, "%lu:", numfs);
int res = f_mount(fs + numfs, fsname, 1); int res = f_mount(fs + numfs, fsname, 1);
if (res != FR_OK) { if (res != FR_OK) {
if (numfs >= 4) break; if (numfs >= 4) break;
@ -115,35 +115,43 @@ bool FileCreate(const char* path, u8* data, u32 size) {
} }
bool PathCopyWorker(char* dest, char* orig) { bool PathCopyWorker(char* dest, char* orig) {
FILINFO fno; FILINFO fno = {.lfname = NULL};
bool ret = false; bool ret = false;
if (f_stat(dest, &fno) != FR_OK) return false; // destination directory does not exist if (f_stat(dest, &fno) != FR_OK) return false; // destination directory does not exist
if (!(fno.fattrib & AM_DIR)) return false; // destination is not a directory (must be at this point) if (!(fno.fattrib & AM_DIR)) return false; // destination is not a directory (must be at this point)
if (f_stat(orig, &fno) != FR_OK) return false; // origin does not exist if (f_stat(orig, &fno) != FR_OK) return false; // origin does not exist
// get filename, build full destination path // build full destination path (on top of destination directory)
char* oname = strrchr(orig, '/'); char* oname = strrchr(orig, '/');
char* dname = dest + strnlen(dest, 256); char* dname = dest + strnlen(dest, 255);
if (oname == NULL) return false; // not a proper origin path if (oname == NULL) return false; // not a proper origin path
oname++; oname++;
*(dname++) = '/'; *(dname++) = '/';
strncpy(dname, oname, 256 - (dname - dest)); strncpy(dname, oname, 256 - (dname - dest));
// check if destination is part of or equal origin
if (strncmp(dest, orig, strnlen(orig, 255)) == 0) {
if ((dest[strnlen(orig, 255)] == '/') || (dest[strnlen(orig, 255)] == '\0'))
return false;
}
// check if destination exists // check if destination exists
if (f_stat(dest, NULL) == FR_OK) { if (f_stat(dest, NULL) == FR_OK) {
char tempstr[40]; char namestr[40];
TruncateString(tempstr, dest, 36, 8); TruncateString(namestr, dest, 36, 8);
if (!ShowPrompt(true, "Destination already exists:\n%s\nOverwrite existing file(s)?")) if (!ShowPrompt(true, "Destination already exists:\n%s\nOverwrite existing file(s)?", namestr))
return false; return false;
} }
// the copy process takes place here // the copy process takes place here
ShowProgress(0, 0, orig, true); if (!ShowProgress(0, 0, orig)) return false;
if (fno.fattrib & AM_DIR) { // processing folders... if (fno.fattrib & AM_DIR) { // processing folders...
DIR pdir; DIR pdir;
char* fname = orig + strnlen(orig, 256); char* fname = orig + strnlen(orig, 256);
// create the destination folder if it does not already exist
if ((f_stat(dest, NULL) != FR_OK) && (f_mkdir(dest) != FR_OK)) if ((f_stat(dest, NULL) != FR_OK) && (f_mkdir(dest) != FR_OK))
return false; return false;
@ -153,9 +161,7 @@ bool PathCopyWorker(char* dest, char* orig) {
fno.lfname = fname; fno.lfname = fname;
fno.lfsize = 256 - (fname - orig); fno.lfsize = 256 - (fname - orig);
ShowPrompt(false, "Made:\n%s\n%s", orig, dest);
while (f_readdir(&pdir, &fno) == FR_OK) { while (f_readdir(&pdir, &fno) == FR_OK) {
ShowPrompt(false, "Trying:\n%s\n%s", orig, dest);
if ((strncmp(fno.fname, ".", 2) == 0) || (strncmp(fno.fname, "..", 3) == 0)) if ((strncmp(fno.fname, ".", 2) == 0) || (strncmp(fno.fname, "..", 3) == 0))
continue; // filter out virtual entries continue; // filter out virtual entries
if (fname[0] == 0) if (fname[0] == 0)
@ -164,7 +170,6 @@ bool PathCopyWorker(char* dest, char* orig) {
ret = true; ret = true;
break; break;
} else if (!PathCopyWorker(dest, orig)) { } else if (!PathCopyWorker(dest, orig)) {
ShowPrompt(false, "Failed:\n%s\n%s", orig, dest);
break; break;
} }
} }
@ -190,20 +195,24 @@ bool PathCopyWorker(char* dest, char* orig) {
for (size_t pos = 0; pos < fsize; pos += main_buffer_size) { for (size_t pos = 0; pos < fsize; pos += main_buffer_size) {
UINT bytes_read = 0; UINT bytes_read = 0;
UINT bytes_written = 0; UINT bytes_written = 0;
ShowProgress(pos, fsize, orig, false);
f_read(&ofile, main_buffer, main_buffer_size, &bytes_read); f_read(&ofile, main_buffer, main_buffer_size, &bytes_read);
if (!ShowProgress(pos + (bytes_read / 2), fsize, orig)) {
ret = false;
break;
}
f_write(&dfile, main_buffer, bytes_read, &bytes_written); f_write(&dfile, main_buffer, bytes_read, &bytes_written);
if (bytes_read != bytes_written) { if (bytes_read != bytes_written) {
ret = false; ret = false;
break; break;
} }
} }
ShowProgress(1, 1, orig, false); ShowProgress(1, 1, orig);
f_close(&ofile); f_close(&ofile);
f_close(&dfile); f_close(&dfile);
} }
*(--dname) = '\0';
return ret; return ret;
} }
@ -211,13 +220,13 @@ bool PathCopy(const char* destdir, const char* orig) {
char fdpath[256]; // 256 is the maximum length of a full path char fdpath[256]; // 256 is the maximum length of a full path
char fopath[256]; char fopath[256];
if (!CheckWritePermissions(destdir)) return false; if (!CheckWritePermissions(destdir)) return false;
strncpy(fdpath, destdir, 256); strncpy(fdpath, destdir, 255);
strncpy(fopath, orig, 256); strncpy(fopath, orig, 255);
return PathCopyWorker(fdpath, fopath); return PathCopyWorker(fdpath, fopath);
} }
bool PathDeleteWorker(char* fpath) { bool PathDeleteWorker(char* fpath) {
FILINFO fno; FILINFO fno = {.lfname = NULL};
// this code handles directory content deletion // this code handles directory content deletion
if (f_stat(fpath, &fno) != FR_OK) return false; // fpath does not exist if (f_stat(fpath, &fno) != FR_OK) return false; // fpath does not exist

View File

@ -85,6 +85,8 @@ void DrawUserInterface(const char* curr_path, DirEntry* curr_entry, DirStruct* c
void DrawDirContents(DirStruct* contents, u32 cursor) { void DrawDirContents(DirStruct* contents, u32 cursor) {
static u32 offset_disp = 0; static u32 offset_disp = 0;
const int str_width = 39; const int str_width = 39;
const u32 bar_height_min = 32;
const u32 bar_width = 2;
const u32 start_y = 2; const u32 start_y = 2;
const u32 stp_y = 12; const u32 stp_y = 12;
const u32 pos_x = 0; const u32 pos_x = 0;
@ -114,9 +116,6 @@ void DrawDirContents(DirStruct* contents, u32 cursor) {
} }
if (contents->n_entries > lines) { // draw position bar at the right if (contents->n_entries > lines) { // draw position bar at the right
const u32 bar_height_min = 32;
const u32 bar_width = 2;
u32 bar_height = (lines * SCREEN_HEIGHT) / contents->n_entries; u32 bar_height = (lines * SCREEN_HEIGHT) / contents->n_entries;
if (bar_height < bar_height_min) bar_height = bar_height_min; if (bar_height < bar_height_min) bar_height = bar_height_min;
u32 bar_pos = ((u64) offset_disp * (SCREEN_HEIGHT - bar_height)) / (contents->n_entries - lines); u32 bar_pos = ((u64) offset_disp * (SCREEN_HEIGHT - bar_height)) / (contents->n_entries - lines);
@ -124,7 +123,7 @@ void DrawDirContents(DirStruct* contents, u32 cursor) {
DrawRectangleF(false, SCREEN_WIDTH_BOT - bar_width, 0, bar_width, bar_pos, COLOR_STD_BG); DrawRectangleF(false, SCREEN_WIDTH_BOT - bar_width, 0, bar_width, bar_pos, COLOR_STD_BG);
DrawRectangleF(false, SCREEN_WIDTH_BOT - bar_width, bar_pos + bar_height, bar_width, SCREEN_WIDTH_BOT - (bar_pos + bar_height), COLOR_STD_BG); DrawRectangleF(false, SCREEN_WIDTH_BOT - bar_width, bar_pos + bar_height, bar_width, SCREEN_WIDTH_BOT - (bar_pos + bar_height), COLOR_STD_BG);
DrawRectangleF(false, SCREEN_WIDTH_BOT - bar_width, bar_pos, bar_width, bar_height, COLOR_SIDE_BAR); DrawRectangleF(false, SCREEN_WIDTH_BOT - bar_width, bar_pos, bar_width, bar_height, COLOR_SIDE_BAR);
} } else DrawRectangleF(false, SCREEN_WIDTH_BOT - bar_width, 0, bar_width, SCREEN_HEIGHT, COLOR_STD_BG);
} }
u32 GodMode() { u32 GodMode() {
@ -217,10 +216,10 @@ u32 GodMode() {
if (n_errors) ShowPrompt(false, "Failed deleting %u/%u path(s)", n_errors, n_marked); if (n_errors) ShowPrompt(false, "Failed deleting %u/%u path(s)", n_errors, n_marked);
} }
} else { } else {
char namestr[20+1]; char namestr[36+1];
TruncateString(namestr, current_dir->entry[cursor].name, 20, 12); TruncateString(namestr, current_dir->entry[cursor].name, 36, 12);
if ((ShowPrompt(true, "Delete \"%s\"?", namestr)) && !PathDelete(current_dir->entry[cursor].path)) if ((ShowPrompt(true, "Delete \"%s\"?", namestr)) && !PathDelete(current_dir->entry[cursor].path))
ShowPrompt(false, "Failed deleting \"%s\"", namestr); ShowPrompt(false, "Failed deleting:\n%s", namestr);
} }
GetDirContents(current_dir, current_path); GetDirContents(current_dir, current_path);
if (cursor >= current_dir->n_entries) if (cursor >= current_dir->n_entries)
@ -248,11 +247,11 @@ u32 GodMode() {
if (ShowPrompt(true, promptstr)) { if (ShowPrompt(true, promptstr)) {
for (u32 c = 0; c < clipboard->n_entries; c++) { for (u32 c = 0; c < clipboard->n_entries; c++) {
if (!PathCopy(current_path, clipboard->entry[c].path)) { if (!PathCopy(current_path, clipboard->entry[c].path)) {
char namestr[20+1]; char namestr[36+1];
TruncateString(namestr, clipboard->entry[c].name, 20, 12); TruncateString(namestr, clipboard->entry[c].name, 36, 12);
if (c + 1 < clipboard->n_entries) { if (c + 1 < clipboard->n_entries) {
if (!ShowPrompt(true, "Failed copying \"%s\"\nContinue?", namestr)) break; if (!ShowPrompt(true, "Failed copying path:\n%s\nProcess remaining?", namestr)) break;
} else ShowPrompt(false, "Failed copying \"%s\"\n", namestr); } else ShowPrompt(false, "Failed copying path:\n%s", namestr);
} }
} }
} }