diff options
Diffstat (limited to 'apps/plugin.c')
-rw-r--r-- | apps/plugin.c | 264 |
1 files changed, 114 insertions, 150 deletions
diff --git a/apps/plugin.c b/apps/plugin.c index 8edc773239..8a6c577f69 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -18,6 +18,8 @@ * KIND, either express or implied. * ****************************************************************************/ +#define DIRFUNCTIONS_DEFINED +#define FILEFUNCTIONS_DEFINED #include "plugin.h" #include <ctype.h> #include <string.h> @@ -40,8 +42,9 @@ #include "pcmbuf.h" #include "errno.h" #include "diacritic.h" -#include "filefuncs.h" +#include "pathfuncs.h" #include "load_code.h" +#include "file.h" #if CONFIG_CHARGING #include "power.h" @@ -58,80 +61,119 @@ #include "usbstack/usb_hid.h" #endif -#if defined (SIMULATOR) -#define PREFIX(_x_) sim_ ## _x_ -#elif defined (APPLICATION) -#define PREFIX(_x_) app_ ## _x_ +#define WRAPPER(_x_) _x_ ## _wrapper + +#if (CONFIG_PLATFORM & PLATFORM_HOSTED) +static unsigned char pluginbuf[PLUGIN_BUFFER_SIZE]; +void sim_lcd_ex_init(unsigned long (*getpixel)(int, int)); +void sim_lcd_ex_update_rect(int x, int y, int width, int height); #else -#define PREFIX(_x_) _x_ +extern unsigned char pluginbuf[]; +#include "bitswap.h" #endif -#if defined (APPLICATION) -/* For symmetry reasons (we want app_ and sim_ to behave similarly), some - * wrappers are needed */ -static int app_close(int fd) +/* for actual plugins only, not for codecs */ +static int plugin_size = 0; +static bool (*pfn_tsr_exit)(bool reenter) = NULL; /* TSR exit callback */ +static char current_plugin[MAX_PATH]; +/* NULL if no plugin is loaded, otherwise the handle that lc_open() returned */ +static void *current_plugin_handle; + +char *plugin_get_current_filename(void); + +static void* plugin_get_audio_buffer(size_t *buffer_size); +static void plugin_release_audio_buffer(void); +static void plugin_tsr(bool (*exit_callback)(bool)); + + +#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE +/* File handle leak prophylaxis */ +#include "bitarray.h" +#include "file_internal.h" /* for MAX_OPEN_FILES */ + +#define PCOC_WRAPPER(_x_) WRAPPER(_x_) + +BITARRAY_TYPE_DECLARE(plugin_check_open_close_bitmap_t, open_files_bitmap, + MAX_OPEN_FILES) + +static plugin_check_open_close_bitmap_t open_files_bitmap; + +static void plugin_check_open_close__enter(void) { - return close(fd); + if (!current_plugin_handle) + open_files_bitmap_clear(&open_files_bitmap); } -static ssize_t app_read(int fd, void *buf, size_t count) +static void plugin_check_open_close__open(int fildes) { - return read(fd,buf,count); + if (fildes >= 0) + open_files_bitmap_set_bit(&open_files_bitmap, fildes); } -static off_t app_lseek(int fd, off_t offset, int whence) +static void plugin_check_open_close__close(int fildes) { - return lseek(fd,offset,whence); + if (fildes < 0) + return; + + if (!open_files_bitmap_test_bit(&open_files_bitmap, fildes)) + { + logf("double close from plugin"); + } + + open_files_bitmap_clear_bit(&open_files_bitmap, fildes); } -static ssize_t app_write(int fd, const void *buf, size_t count) +static int WRAPPER(open)(const char *path, int oflag, ...) { - return write(fd,buf,count); + int fildes = FS_PREFIX(open)(path, oflag __OPEN_MODE_ARG); + plugin_check_open_close__open(fildes); + return fildes; } -static int app_ftruncate(int fd, off_t length) +static int WRAPPER(creat)(const char *path, mode_t mode) { - return ftruncate(fd,length); + int fildes = FS_PREFIX(creat)(path __CREAT_MODE_ARG); + plugin_check_open_close__open(fildes); + return fildes; + (void)mode; } -#endif -#if defined(HAVE_PLUGIN_CHECK_OPEN_CLOSE) && (MAX_OPEN_FILES>32) -#warning "MAX_OPEN_FILES>32, disabling plugin file open/close checking" -#undef HAVE_PLUGIN_CHECK_OPEN_CLOSE -#endif +static int WRAPPER(close)(int fildes) +{ + int rc = FS_PREFIX(close)(fildes); + if (rc >= 0) + plugin_check_open_close__close(fildes); -#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE -static unsigned int open_files; -#endif + return rc; +} -#if (CONFIG_PLATFORM & PLATFORM_HOSTED) -static unsigned char pluginbuf[PLUGIN_BUFFER_SIZE]; -void sim_lcd_ex_init(unsigned long (*getpixel)(int, int)); -void sim_lcd_ex_update_rect(int x, int y, int width, int height); -#else -extern unsigned char pluginbuf[]; -#include "bitswap.h" -#endif +static void plugin_check_open_close__exit(void) +{ + if (current_plugin_handle) + return; -/* for actual plugins only, not for codecs */ -static int plugin_size = 0; -static bool (*pfn_tsr_exit)(bool reenter) = NULL; /* TSR exit callback */ -static char current_plugin[MAX_PATH]; -/* NULL if no plugin is loaded, otherwise the handle that lc_open() returned */ -static void *current_plugin_handle; + if (open_files_bitmap_is_clear(&open_files_bitmap)) + return; -char *plugin_get_current_filename(void); + logf("Plugin '%s' leaks file handles", plugin); -/* Some wrappers used to monitor open and close and detect leaks*/ -static int open_wrapper(const char* pathname, int flags, ...); -#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE -static int close_wrapper(int fd); -static int creat_wrapper(const char *pathname, mode_t mode); -#endif + static const char *lines[] = + { ID2P(LANG_PLUGIN_ERROR), "#leak-file-handles" }; + static const struct text_message message = { lines, 2 }; + button_clear_queue(); /* Empty the keyboard buffer */ + gui_syncyesno_run(&message, NULL, NULL); -static void* plugin_get_audio_buffer(size_t *buffer_size); -static void plugin_release_audio_buffer(void); -static void plugin_tsr(bool (*exit_callback)(bool)); + FOR_EACH_BITARRAY_SET_BIT(&open_files_bitmap, fildes) + WRAPPER(close)(fildes); +} + +#else /* !HAVE_PLUGIN_CHECK_OPEN_CLOSE */ + +#define PCOC_WRAPPER(_x_) FS_PREFIX(_x_) +#define plugin_check_open_close__enter() +#define plugin_check_open_close__exit() + +#endif /* HAVE_PLUGIN_CHECK_OPEN_CLOSE */ static const struct plugin_api rockbox_api = { @@ -339,24 +381,16 @@ static const struct plugin_api rockbox_api = { /* file */ open_utf8, - (open_func)open_wrapper, -#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE - close_wrapper, -#else - PREFIX(close), -#endif - (read_func)PREFIX(read), - PREFIX(lseek), -#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE - (creat_func)creat_wrapper, -#else - PREFIX(creat), -#endif - (write_func)PREFIX(write), - PREFIX(remove), - PREFIX(rename), - PREFIX(ftruncate), - filesize, + PCOC_WRAPPER(open), + PCOC_WRAPPER(creat), + PCOC_WRAPPER(close), + FS_PREFIX(read), + FS_PREFIX(lseek), + FS_PREFIX(write), + FS_PREFIX(remove), + FS_PREFIX(rename), + FS_PREFIX(ftruncate), + FS_PREFIX(filesize), fdprintf, read_line, settings_parseline, @@ -369,18 +403,18 @@ static const struct plugin_api rockbox_api = { #endif /* USING_STORAGE_CALLBACK */ reload_directory, create_numbered_filename, - file_exists, + FS_PREFIX(file_exists), strip_extension, crc_32, filetype_get_attr, /* dir */ - (opendir_func)opendir, - (closedir_func)closedir, - (readdir_func)readdir, - mkdir, - rmdir, - dir_exists, + FS_PREFIX(opendir), + FS_PREFIX(closedir), + FS_PREFIX(readdir), + FS_PREFIX(mkdir), + FS_PREFIX(rmdir), + FS_PREFIX(dir_exists), dir_get_info, /* browsing */ @@ -688,10 +722,11 @@ static const struct plugin_api rockbox_api = { #endif srand, rand, - (qsort_func)qsort, + (void *)qsort, kbd_input, get_time, set_time, + gmtime_r, #if CONFIG_RTC mktime, #endif @@ -891,9 +926,7 @@ int plugin_load(const char* plugin, const void* parameter) /* allow voice to back off if the plugin needs lots of memory */ talk_buffer_set_policy(TALK_BUFFER_LOOSE); -#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE - open_files = 0; -#endif + plugin_check_open_close__enter(); int rc = p_hdr->entry_point(parameter); @@ -947,24 +980,7 @@ int plugin_load(const char* plugin, const void* parameter) FOR_NB_SCREENS(i) viewportmanager_theme_undo(i, true); -#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE - if(open_files != 0 && !current_plugin_handle) - { - int fd; - logf("Plugin '%s' leaks file handles", plugin); - - static const char *lines[] = - { ID2P(LANG_PLUGIN_ERROR), - "#leak-file-handles" }; - static const struct text_message message={ lines, 2 }; - button_clear_queue(); /* Empty the keyboard buffer */ - gui_syncyesno_run(&message, NULL, NULL); - - for(fd=0; fd < MAX_OPEN_FILES; fd++) - if(open_files & (1<<fd)) - close_wrapper(fd); - } -#endif + plugin_check_open_close__exit(); if (rc == PLUGIN_ERROR) splash(HZ*2, str(LANG_PLUGIN_ERROR)); @@ -1027,55 +1043,3 @@ char *plugin_get_current_filename(void) { return current_plugin; } - -static int open_wrapper(const char* pathname, int flags, ...) -{ -/* we don't have an 'open' function. it's a define. and we need - * the real file_open, hence PREFIX() doesn't work here */ - int fd; -#if (CONFIG_PLATFORM & PLATFORM_HOSTED) - if (flags & O_CREAT) - { - va_list ap; - va_start(ap, flags); - fd = open(pathname, flags, va_arg(ap, unsigned int)); - va_end(ap); - } - else - fd = open(pathname, flags); -#else - fd = file_open(pathname,flags); -#endif - -#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE - if(fd >= 0) - open_files |= 1<<fd; -#endif - return fd; -} - -#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE -static int close_wrapper(int fd) -{ - if((~open_files) & (1<<fd)) - { - logf("double close from plugin"); - } - if(fd >= 0) - open_files &= (~(1<<fd)); - - return PREFIX(close)(fd); -} - -static int creat_wrapper(const char *pathname, mode_t mode) -{ - (void)mode; - - int fd = PREFIX(creat)(pathname, mode); - - if(fd >= 0) - open_files |= (1<<fd); - - return fd; -} -#endif /* HAVE_PLUGIN_CHECK_OPEN_CLOSE */ |