-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathbrowse.c
153 lines (125 loc) · 3.72 KB
/
browse.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include "browse.h"
#include "fatfs/ff.h"
#include "malloc.h"
#include "log.h"
#include "powerpc_elf.h"
char *browse_menu_entries[CONSOLE_LINES-HELP_LINES-HEAD_LINES-2];
int browse_menu_entries_count = 0;
char browse_current_path[4096];
// used by FatFS
PARTITION VolToPart[FF_VOLUMES] = {
{0, 1}, /* "0:" ==> Physical drive 0, 1st partition */
{0, 2}, /* "1:" ==> Physical drive 0, 2nd partition */
{0, 3}, /* "2:" ==> Physical drive 0, 3rd partition */
{0, 4} /* "3:" ==> Physical drive 0, 4th partition */
};
static void browse_append(const char *name, int is_directory) {
// stop ingurgitating menu entries
if (browse_menu_entries_count == sizeof(browse_menu_entries))
return;
if (!is_directory)
browse_menu_entries[browse_menu_entries_count++] = strdup(name);
else
browse_menu_entries[browse_menu_entries_count++] = strcat(name, "/");
}
static void menu_browse_leave(void) {
menu_selection = old_menu_selection;
menu_clear_entries();
menu_draw_entries_and_help();
}
int menu_browse() {
DIR dirs;
FILINFO Fno;
//NOTE: menu entries must have already been free'd on entry
FRESULT res = f_opendir(&dirs, browse_current_path);
if (res != FR_OK) {
log_printf("failed to open directory '%s': %d\n", browse_current_path, res);
sleep(4);
menu_browse_leave();
return (int)res;
}
// add first entry to go back one level
browse_append("..", 0);
while (((res = f_readdir(&dirs, &Fno)) == FR_OK) && Fno.fname[0]) {
if (Fno.fattrib & AM_DIR) {
browse_append(Fno.fname, 1);
} else {
browse_append(Fno.fname, 0);
}
}
if (res != FR_OK) {
log_printf("failed to read directory '%s': %d\n", browse_current_path, res);
sleep(3);
}
// add an extra entry to go back - it uses DISP_LEFT character code point
browse_append("\x1b Back to menu", 0);
// draw the new menu
menu_selection = 0;
menu_clear_entries();
menu_draw_entries_and_help();
// return non-zero so that input loop continues
return 1;
}
static void free_browse_menu() {
int i;
// free all browse menu entries
for(i=0;i<browse_menu_entries_count;i++) {
free(browse_menu_entries[i]);
}
browse_menu_entries_count = 0;
}
int menu_browse_activate(void) {
// shall we go back? handles first and last menu entries
if ((menu_selection == 0) || (menu_selection == browse_menu_entries_count-1)) {
// "0:" for example, or the "go back to menu" entry
if ((strlen(browse_current_path)<=2) || (menu_selection == browse_menu_entries_count-1)) {
free_browse_menu();
// end of line: go back
menu_browse_leave();
// return non-zero so that input loop continues
return 1;
}
free_browse_menu();
// find before-last slash in the current path
// length is above 3 thanks to criteria above
char *pos = browse_current_path+3, *last_pos = NULL;
while (1) {
pos = strchr(pos, '/');
if (pos)
last_pos = pos;
else
break;
}
if (last_pos) {
// cut here
*last_pos = 0;
} else
// truncate to root directory
browse_current_path[2] = 0;
return menu_browse();
}
// a file was selected, try too boot it
int cur_len = strlen(browse_current_path);
char *label = browse_menu_entries[menu_selection];
int l = strlen(label);
// is the selection a subdirectory?
if (label[l-1] == '/') {
// append subdirectory to the current path
browse_current_path[cur_len] = '/';
cur_len++;
l--;
memcpy(browse_current_path+cur_len, label, l);
browse_current_path[cur_len + l] = 0;
free_browse_menu();
return menu_browse();
}
// previous length + 1 slash + filename + delimiter
char *elf_fn = malloc(cur_len+l+2);
memcpy(elf_fn, browse_current_path, cur_len);
elf_fn[cur_len]='/';
cur_len++;
memcpy(elf_fn+cur_len, label, l+1);
int err = try_boot_file(elf_fn, "");
free(elf_fn);
return err;
}