summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
authorRafaël Carré <rafael.carre@gmail.com>2011-12-14 04:38:30 +0000
committerRafaël Carré <rafael.carre@gmail.com>2011-12-14 04:38:30 +0000
commit1648441d6e2cfa2f5f8a7665d5c92bf9744399f9 (patch)
treeca9260bf6b14e5d37259f715b5c4094b2dec03c9 /apps/plugins
parent3b00460701f35edd99b8401c4edb2ddbcc8e1a11 (diff)
downloadrockbox-1648441d6e2cfa2f5f8a7665d5c92bf9744399f9.zip
rockbox-1648441d6e2cfa2f5f8a7665d5c92bf9744399f9.tar.gz
rockbox-1648441d6e2cfa2f5f8a7665d5c92bf9744399f9.tar.bz2
rockbox-1648441d6e2cfa2f5f8a7665d5c92bf9744399f9.tar.xz
disktidy: simplify
support filenames beginning with '#' by escaping them in config example: "\##MUSIC#: no" it is a limitation of settings_parseline to recognize comments git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31238 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/disktidy.c528
1 files changed, 163 insertions, 365 deletions
diff --git a/apps/plugins/disktidy.c b/apps/plugins/disktidy.c
index cedb117..f3717fd 100644
--- a/apps/plugins/disktidy.c
+++ b/apps/plugins/disktidy.c
@@ -23,25 +23,18 @@
static int removed = 0; /* number of items removed */
+static bool abort;
-/* function return values */
-enum tidy_return
-{
- TIDY_RETURN_OK = 0,
- TIDY_RETURN_ERROR = 1,
- TIDY_RETURN_USB = 2,
- TIDY_RETURN_ABORT = 3,
-};
-
-#define MAX_TYPES 64
struct tidy_type {
char filestring[64];
int pre;
int post;
bool directory;
bool remove;
-} tidy_types[MAX_TYPES];
-int tidy_type_count;
+} tidy_types[64];
+
+static size_t tidy_type_count;
+
bool tidy_loaded_and_changed = false;
#define DEFAULT_FILES PLUGIN_APPS_DATA_DIR "/disktidy.config"
@@ -49,8 +42,7 @@ bool tidy_loaded_and_changed = false;
static void add_item(const char* name, int index)
{
- char *a;
- struct tidy_type *entry = tidy_types + index;
+ struct tidy_type *entry = &tidy_types[index];
rb->strcpy(entry->filestring, name);
if (name[rb->strlen(name)-1] == '/')
{
@@ -59,7 +51,8 @@ static void add_item(const char* name, int index)
}
else
entry->directory = false;
- a = rb->strchr(entry->filestring, '*');
+
+ char *a = rb->strchr(entry->filestring, '*');
if (a)
{
entry->pre = a - entry->filestring;
@@ -75,7 +68,7 @@ static void add_item(const char* name, int index)
static int find_file_string(const char *file, char *last_group)
{
char temp[MAX_PATH];
- int i = 0, idx_last_group = -1;
+ int idx_last_group = -1;
bool folder = false;
rb->strcpy(temp, file);
if (temp[rb->strlen(temp)-1] == '/')
@@ -83,107 +76,89 @@ static int find_file_string(const char *file, char *last_group)
folder = true;
temp[rb->strlen(temp)-1] = '\0';
}
- while (i<tidy_type_count)
- {
- if (!rb->strcmp(tidy_types[i].filestring, temp) &&
- folder == tidy_types[i].directory)
+
+ for (unsigned i = 0; i < tidy_type_count; i++)
+ if (!rb->strcmp(tidy_types[i].filestring, temp) && folder == tidy_types[i].directory)
return i;
else if (!rb->strcmp(tidy_types[i].filestring, last_group))
idx_last_group = i;
- i++;
- }
+
+ if (file[0] == '<' || idx_last_group == -1)
+ return tidy_type_count;
+
+
/* not found, so insert it into its group */
- if (file[0] != '<' && idx_last_group != -1)
- {
- for (i=idx_last_group; i<tidy_type_count; i++)
+ for (unsigned i=idx_last_group; i<tidy_type_count; i++)
+ if (tidy_types[i].filestring[0] == '<')
{
- if (tidy_types[i].filestring[0] == '<')
- {
- idx_last_group = i;
- break;
- }
- }
- /* shift items up one */
- for (i=tidy_type_count;i>idx_last_group;i--)
- {
- rb->memcpy(&tidy_types[i], &tidy_types[i-1], sizeof(struct tidy_type));
+ idx_last_group = i;
+ break;
}
- tidy_type_count++;
- add_item(file, idx_last_group+1);
- return idx_last_group+1;
- }
- return i;
+
+ /* shift items up one */
+ for (int i=tidy_type_count;i>idx_last_group;i--)
+ rb->memcpy(&tidy_types[i], &tidy_types[i-1], sizeof(struct tidy_type));
+
+ tidy_type_count++;
+ add_item(file, idx_last_group+1);
+ return idx_last_group+1;
}
-static bool tidy_load_file(const char* file)
+static void tidy_load_file(const char* file)
{
- int fd = rb->open(file, O_RDONLY), i;
+ int fd = rb->open(file, O_RDONLY);
char buf[MAX_PATH], *str, *remove;
char last_group[MAX_PATH] = "";
- bool new;
if (fd < 0)
- return false;
- while ((tidy_type_count < MAX_TYPES) &&
- rb->read_line(fd, buf, MAX_PATH))
+ return;
+
+ while ((tidy_type_count < sizeof(tidy_types) / sizeof(tidy_types[0])) && rb->read_line(fd, buf, MAX_PATH))
{
- if (rb->settings_parseline(buf, &str, &remove))
+ if (!rb->settings_parseline(buf, &str, &remove))
+ continue;
+
+ if (*str == '\\') /* escape first character ? */
+ str++;
+ unsigned i = find_file_string(str, last_group);
+
+ tidy_types[i].remove = rb->strcmp(remove, "yes");
+
+ if (i >= tidy_type_count)
{
- i = find_file_string(str, last_group);
- new = (i >= tidy_type_count);
- if (!rb->strcmp(remove, "yes"))
- tidy_types[i].remove = true;
- else tidy_types[i].remove = false;
- if (new)
- {
- i = tidy_type_count;
- add_item(str, i);
- tidy_type_count++;
- }
- if (str[0] == '<')
- rb->strcpy(last_group, str);
+ i = tidy_type_count;
+ add_item(str, i);
+ tidy_type_count++;
}
+ if (str[0] == '<')
+ rb->strcpy(last_group, str);
}
rb->close(fd);
- return true;
}
-static bool match(struct tidy_type *tidy_type, char *string, int len)
+static bool match(struct tidy_type *tidy_type, const char *string, int len)
{
char *pattern = tidy_type->filestring;
- if (tidy_type->pre < 0)
- {
- /* no '*', just compare. */
- return (rb->strcmp(pattern, string) == 0);
- }
+
+ if (tidy_type->pre < 0) /* no '*', just compare. */
+ return !rb->strcmp(pattern, string);
+
/* pattern is too long for the string. avoid 'ab*bc' matching 'abc'. */
if (len < tidy_type->pre + tidy_type->post)
return false;
+
/* pattern has '*', compare former part of '*' to the begining of
the string and compare next part of '*' to the end of string. */
- return (rb->strncmp(pattern, string, tidy_type->pre) == 0 &&
- rb->strcmp(pattern + tidy_type->pre + 1,
- string + len - tidy_type->post) == 0);
+ return !rb->strncmp(pattern, string, tidy_type->pre) &&
+ !rb->strcmp(pattern + tidy_type->pre + 1, string + len - tidy_type->post);
}
-static bool tidy_remove_item(char *item, int attr)
+static bool tidy_remove_item(const char *item, int attr)
{
- int i;
- int len;
- bool ret = false;
- len = rb->strlen(item);
- for (i=0; ret == false && i < tidy_type_count; i++)
- {
- if (match(&tidy_types[i], item, len))
- {
- if (!tidy_types[i].remove)
- return false;
- if (attr&ATTR_DIRECTORY)
- ret = tidy_types[i].directory;
- else
- ret = !tidy_types[i].directory;
- }
- }
- return ret;
+ for (struct tidy_type *t = &tidy_types[0]; t < &tidy_types[tidy_type_count]; t++)
+ if (match(t, item, rb->strlen(item)))
+ return t->remove && ((!!(attr&ATTR_DIRECTORY)) == t->directory);
+
+ return false;
}
static void tidy_lcd_status(const char *name)
@@ -203,11 +178,11 @@ static int tidy_path_append_entry(char *path, struct dirent *entry, int *path_le
int name_len = rb->strlen(entry->d_name);
/* for the special case of path="/" this is one bigger but it's not a problem */
int new_length = *path_length + name_len + 1;
-
+
/* check overflow (keep space for trailing zero) */
if(new_length >= MAX_PATH)
return 0;
-
+
/* special case for path <> "/" */
if(rb->strcmp(path, "/") != 0)
{
@@ -216,10 +191,10 @@ static int tidy_path_append_entry(char *path, struct dirent *entry, int *path_le
}
/* strcat is unsafe but the previous check normally avoid any problem */
/* use path_length to optimise */
-
+
rb->strcat(path + *path_length, entry->d_name);
*path_length += name_len;
-
+
return 1;
}
@@ -229,200 +204,91 @@ static void tidy_path_remove_entry(char *path, int old_path_length, int *path_le
*path_length = old_path_length;
}
-/* Removes the directory specified by 'path'. This includes recursively
- removing all files and directories in that directory.
- path is assumed to be array of size MAX_PATH.
-*/
-static enum tidy_return tidy_removedir(char *path, int *path_length)
+/* path is assumed to be array of size MAX_PATH. */
+static enum plugin_status tidy_clean(char *path, int *path_length, bool rmdir)
{
- /* delete directory */
- struct dirent *entry;
- enum tidy_return status = TIDY_RETURN_OK;
- int button;
- DIR *dir;
int old_path_length = *path_length;
- /* display status text */
tidy_lcd_status(path);
- rb->yield();
+ DIR *dir = rb->opendir(path);
+ if (!dir)
+ return PLUGIN_ERROR;
- dir = rb->opendir(path);
- if (dir)
+ struct dirent *entry;
+ while ((entry = rb->readdir(dir)))
{
- while((status == TIDY_RETURN_OK) && ((entry = rb->readdir(dir)) != 0))
- /* walk directory */
+ /* check for user input and usb connect */
+ int button = rb->get_action(CONTEXT_STD, TIMEOUT_NOBLOCK);
+ if (button == ACTION_STD_CANCEL)
{
- /* check for user input and usb connect */
- button = rb->get_action(CONTEXT_STD, TIMEOUT_NOBLOCK);
- if (button == ACTION_STD_CANCEL)
- {
- rb->closedir(dir);
- return TIDY_RETURN_ABORT;
- }
- if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
- {
- rb->closedir(dir);
- return TIDY_RETURN_USB;
- }
-
- rb->yield();
-
- /* get absolute path */
- /* returns an error if path is too long */
- if(!tidy_path_append_entry(path, entry, path_length))
- /* silent error */
- continue;
-
- struct dirinfo info = rb->dir_get_info(dir, entry);
- if (info.attribute & ATTR_DIRECTORY)
- {
- /* dir ignore "." and ".." */
- if ((rb->strcmp(entry->d_name, ".") != 0) && \
- (rb->strcmp(entry->d_name, "..") != 0))
- {
- status = tidy_removedir(path, path_length);
- }
- }
- else
- {
- /* file */
- removed++;
- rb->remove(path);
- }
-
- /* restore path */
- tidy_path_remove_entry(path, old_path_length, path_length);
+ rb->closedir(dir);
+ abort = true;
+ return PLUGIN_OK;
+ }
+ if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
+ {
+ rb->closedir(dir);
+ return PLUGIN_USB_CONNECTED;
}
- rb->closedir(dir);
- /* rmdir */
- removed++;
- rb->rmdir(path);
- }
- else
- {
- status = TIDY_RETURN_ERROR;
- }
- return status;
-}
-/* path is assumed to be array of size MAX_PATH */
-static enum tidy_return tidy_clean(char *path, int *path_length)
-{
- /* deletes junk files and dirs left by system */
- struct dirent *entry;
- enum tidy_return status = TIDY_RETURN_OK;
- int button;
- DIR *dir;
- int old_path_length = *path_length;
+ rb->yield();
- /* display status text */
- tidy_lcd_status(path);
+ struct dirinfo info = rb->dir_get_info(dir, entry);
+ if (!rmdir && !tidy_remove_item(entry->d_name, info.attribute))
+ continue;
- rb->yield();
+ /* get absolute path, returns an error if path is too long */
+ if(!tidy_path_append_entry(path, entry, path_length))
+ continue; /* silent error */
- dir = rb->opendir(path);
- if (dir)
- {
- while((status == TIDY_RETURN_OK) && ((entry = rb->readdir(dir)) != 0))
- /* walk directory */
+ if (info.attribute & ATTR_DIRECTORY)
+ {
+ /* dir ignore "." and ".." */
+ if (rb->strcmp(entry->d_name, ".") && rb->strcmp(entry->d_name, ".."))
+ tidy_clean(path, path_length, true);
+ }
+ else
{
- struct dirinfo info = rb->dir_get_info(dir, entry);
- /* check for user input and usb connect */
- button = rb->get_action(CONTEXT_STD, TIMEOUT_NOBLOCK);
- if (button == ACTION_STD_CANCEL)
- {
- rb->closedir(dir);
- return TIDY_RETURN_ABORT;
- }
- if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
- {
- rb->closedir(dir);
- return TIDY_RETURN_USB;
- }
-
- rb->yield();
-
- if (info.attribute & ATTR_DIRECTORY)
- {
- /* directory ignore "." and ".." */
- if ((rb->strcmp(entry->d_name, ".") != 0) && \
- (rb->strcmp(entry->d_name, "..") != 0))
- {
- /* get absolute path */
- /* returns an error if path is too long */
- if(!tidy_path_append_entry(path, entry, path_length))
- /* silent error */
- continue;
-
- if (tidy_remove_item(entry->d_name, info.attribute))
- {
- /* delete dir */
- status = tidy_removedir(path, path_length);
- }
- else
- {
- /* dir not deleted so clean it */
- status = tidy_clean(path, path_length);
- }
-
- /* restore path */
- tidy_path_remove_entry(path, old_path_length, path_length);
- }
- }
- else
- {
- /* file */
- if (tidy_remove_item(entry->d_name, info.attribute))
- {
- /* get absolute path */
- /* returns an error if path is too long */
- if(!tidy_path_append_entry(path, entry, path_length))
- /* silent error */
- continue;
-
- removed++; /* increment removed files counter */
- /* delete file */
- if (rb->remove(path) != 0)
- DEBUGF("Could not delete file %s\n", path);
-
- /* restore path */
- tidy_path_remove_entry(path, old_path_length, path_length);
- }
- }
+ removed++;
+ rb->remove(path);
}
- rb->closedir(dir);
- return status;
+
+ /* restore path */
+ tidy_path_remove_entry(path, old_path_length, path_length);
}
- else
+ rb->closedir(dir);
+
+ if (rmdir)
{
- return TIDY_RETURN_ERROR;
+ removed++;
+ rb->rmdir(path);
}
+
+ return PLUGIN_OK;
}
-static enum tidy_return tidy_do(void)
+static enum plugin_status tidy_do(void)
{
/* clean disk and display num of items removed */
- enum tidy_return status;
char path[MAX_PATH];
- int path_length;
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
rb->cpu_boost(true);
#endif
rb->strcpy(path, "/");
- path_length = rb->strlen(path);
- status = tidy_clean(path, &path_length);
+ int path_length = rb->strlen(path);
+ enum plugin_status status = tidy_clean(path, &path_length, false);
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
rb->cpu_boost(false);
#endif
- if ((status == TIDY_RETURN_OK) || (status == TIDY_RETURN_ABORT))
+ if (status == PLUGIN_OK)
{
rb->lcd_clear_display();
- if (status == TIDY_RETURN_ABORT)
+ if (abort)
{
rb->splash(HZ, "User aborted");
rb->lcd_clear_display();
@@ -458,123 +324,80 @@ static const char* get_name(int selected_item, void * data,
static int list_action_callback(int action, struct gui_synclist *lists)
{
- if (action == ACTION_STD_OK)
+ if (action != ACTION_STD_OK)
+ return action;
+
+ unsigned selection = rb->gui_synclist_get_sel_pos(lists);
+ if (tidy_types[selection].filestring[0] == '<')
{
- int selection = rb->gui_synclist_get_sel_pos(lists);
- if (tidy_types[selection].filestring[0] == '<')
+ bool all = !rb->strcmp(tidy_types[selection].filestring, "< ALL >");
+ bool none= !rb->strcmp(tidy_types[selection].filestring, "< NONE >");
+
+ if (all || none)
{
- int i;
- if (!rb->strcmp(tidy_types[selection].filestring, "< ALL >"))
- {
- for (i=0; i<tidy_type_count; i++)
- {
- if (tidy_types[i].filestring[0] != '<')
- tidy_types[i].remove = true;
- }
- }
- else if (!rb->strcmp(tidy_types[selection].filestring, "< NONE >"))
- {
- for (i=0; i<tidy_type_count; i++)
- {
- if (tidy_types[i].filestring[0] != '<')
- tidy_types[i].remove = false;
- }
- }
- else /* toggle all untill the next <> */
- {
- selection++;
- while (selection < tidy_type_count &&
- tidy_types[selection].filestring[0] != '<')
- {
- tidy_types[selection].remove = !tidy_types[selection].remove;
- selection++;
- }
- }
+ for (unsigned i=0; i<tidy_type_count; i++)
+ if (tidy_types[i].filestring[0] != '<')
+ tidy_types[i].remove = all;
}
- else
- tidy_types[selection].remove = !tidy_types[selection].remove;
- tidy_loaded_and_changed = true;
- return ACTION_REDRAW;
+ else /* toggle all untill the next <> */
+ while (++selection < tidy_type_count && tidy_types[selection].filestring[0] != '<')
+ tidy_types[selection].remove = !tidy_types[selection].remove;
}
- return action;
+ else
+ tidy_types[selection].remove = !tidy_types[selection].remove;
+ tidy_loaded_and_changed = true;
+ return ACTION_REDRAW;
}
-static enum tidy_return tidy_lcd_menu(void)
+static void tidy_lcd_menu(void)
{
int selection = 0;
- enum tidy_return status = TIDY_RETURN_OK;
- bool menu_quit = false;
+ struct simplelist_info list;
- MENUITEM_STRINGLIST(menu, "Disktidy Menu", NULL,
- "Start Cleaning", "Files to Clean",
- "Quit");
+ MENUITEM_STRINGLIST(menu, "Disktidy Menu", NULL, "Start Cleaning",
+ "Files to Clean", "Quit");
- while (!menu_quit)
- {
+ for(;;)
switch(rb->do_menu(&menu, &selection, NULL, false))
{
- case 0:
- menu_quit = true; /* start cleaning */
- break;
-
- case 1:
- {
- struct simplelist_info list;
- rb->simplelist_info_init(&list, "Files to Clean",
- tidy_type_count, NULL);
- list.get_icon = get_icon;
- list.get_name = get_name;
- list.action_callback = list_action_callback;
- rb->simplelist_show_list(&list);
- }
+ default:
+ abort = true;
+ case 0:
+ return; /* start cleaning */
+
+ case 1:
+ rb->simplelist_info_init(&list, "Files to Clean", tidy_type_count, NULL);
+ list.get_icon = get_icon;
+ list.get_name = get_name;
+ list.action_callback = list_action_callback;
+ rb->simplelist_show_list(&list);
break;
-
- default:
- status = TIDY_RETURN_ABORT; /* exit plugin */
- menu_quit = true;
- break;
}
- }
- return status;
}
/* Creates a file and writes information about what files to
delete and what to keep to it.
- Returns true iff the file was successfully created.
*/
-static bool save_config(const char *file_name)
+static void save_config(void)
{
- int fd, i;
- bool result;
-
- fd = rb->creat(file_name, 0666);
- result = (fd >= 0);
+ int fd = rb->creat(CUSTOM_FILES, 0666);
+ if (fd < 0)
+ return;
- if (result)
- {
- for (i=0; i<tidy_type_count; i++)
- {
- rb->fdprintf(fd, "%s%s: %s\n", tidy_types[i].filestring,
+ for (unsigned i=0; i<tidy_type_count; i++)
+ rb->fdprintf(fd, "%s%s%s: %s\n",
+ tidy_types[i].filestring[0] == '#' ? "\\" : "",
+ tidy_types[i].filestring,
tidy_types[i].directory ? "/" : "",
tidy_types[i].remove ? "yes" : "no");
- }
- rb->close(fd);
- }
- else
- {
- DEBUGF("Could not create file %s\n", file_name);
- }
-
- return result;
+ rb->close(fd);
}
/* this is the plugin entry point */
enum plugin_status plugin_start(const void* parameter)
{
- enum tidy_return status;
(void)parameter;
- tidy_type_count = 0;
tidy_load_file(DEFAULT_FILES);
tidy_load_file(CUSTOM_FILES);
if (tidy_type_count == 0)
@@ -582,34 +405,9 @@ enum plugin_status plugin_start(const void* parameter)
rb->splash(3*HZ, "Missing disktidy.config file");
return PLUGIN_ERROR;
}
- status = tidy_lcd_menu();
+ tidy_lcd_menu();
if (tidy_loaded_and_changed)
- {
- save_config(CUSTOM_FILES);
- }
- if (status == TIDY_RETURN_ABORT)
- return PLUGIN_OK;
- while (true)
- {
- status = tidy_do();
-
- switch (status)
- {
- case TIDY_RETURN_OK:
- return PLUGIN_OK;
- case TIDY_RETURN_ERROR:
- return PLUGIN_ERROR;
- case TIDY_RETURN_USB:
- return PLUGIN_USB_CONNECTED;
- case TIDY_RETURN_ABORT:
- return PLUGIN_OK;
- }
- }
-
- if (rb->default_event_handler(rb->button_get(false)) == SYS_USB_CONNECTED)
- return PLUGIN_USB_CONNECTED;
+ save_config();
- rb->yield();
-
- return PLUGIN_OK;
+ return abort ? PLUGIN_OK : tidy_do();
}