summaryrefslogtreecommitdiff
path: root/apps/plugin.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugin.c')
-rw-r--r--apps/plugin.c264
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 @@
18 * KIND, either express or implied. 18 * KIND, either express or implied.
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#define DIRFUNCTIONS_DEFINED
22#define FILEFUNCTIONS_DEFINED
21#include "plugin.h" 23#include "plugin.h"
22#include <ctype.h> 24#include <ctype.h>
23#include <string.h> 25#include <string.h>
@@ -40,8 +42,9 @@
40#include "pcmbuf.h" 42#include "pcmbuf.h"
41#include "errno.h" 43#include "errno.h"
42#include "diacritic.h" 44#include "diacritic.h"
43#include "filefuncs.h" 45#include "pathfuncs.h"
44#include "load_code.h" 46#include "load_code.h"
47#include "file.h"
45 48
46#if CONFIG_CHARGING 49#if CONFIG_CHARGING
47#include "power.h" 50#include "power.h"
@@ -58,80 +61,119 @@
58#include "usbstack/usb_hid.h" 61#include "usbstack/usb_hid.h"
59#endif 62#endif
60 63
61#if defined (SIMULATOR) 64#define WRAPPER(_x_) _x_ ## _wrapper
62#define PREFIX(_x_) sim_ ## _x_ 65
63#elif defined (APPLICATION) 66#if (CONFIG_PLATFORM & PLATFORM_HOSTED)
64#define PREFIX(_x_) app_ ## _x_ 67static unsigned char pluginbuf[PLUGIN_BUFFER_SIZE];
68void sim_lcd_ex_init(unsigned long (*getpixel)(int, int));
69void sim_lcd_ex_update_rect(int x, int y, int width, int height);
65#else 70#else
66#define PREFIX(_x_) _x_ 71extern unsigned char pluginbuf[];
72#include "bitswap.h"
67#endif 73#endif
68 74
69#if defined (APPLICATION) 75/* for actual plugins only, not for codecs */
70/* For symmetry reasons (we want app_ and sim_ to behave similarly), some 76static int plugin_size = 0;
71 * wrappers are needed */ 77static bool (*pfn_tsr_exit)(bool reenter) = NULL; /* TSR exit callback */
72static int app_close(int fd) 78static char current_plugin[MAX_PATH];
79/* NULL if no plugin is loaded, otherwise the handle that lc_open() returned */
80static void *current_plugin_handle;
81
82char *plugin_get_current_filename(void);
83
84static void* plugin_get_audio_buffer(size_t *buffer_size);
85static void plugin_release_audio_buffer(void);
86static void plugin_tsr(bool (*exit_callback)(bool));
87
88
89#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE
90/* File handle leak prophylaxis */
91#include "bitarray.h"
92#include "file_internal.h" /* for MAX_OPEN_FILES */
93
94#define PCOC_WRAPPER(_x_) WRAPPER(_x_)
95
96BITARRAY_TYPE_DECLARE(plugin_check_open_close_bitmap_t, open_files_bitmap,
97 MAX_OPEN_FILES)
98
99static plugin_check_open_close_bitmap_t open_files_bitmap;
100
101static void plugin_check_open_close__enter(void)
73{ 102{
74 return close(fd); 103 if (!current_plugin_handle)
104 open_files_bitmap_clear(&open_files_bitmap);
75} 105}
76 106
77static ssize_t app_read(int fd, void *buf, size_t count) 107static void plugin_check_open_close__open(int fildes)
78{ 108{
79 return read(fd,buf,count); 109 if (fildes >= 0)
110 open_files_bitmap_set_bit(&open_files_bitmap, fildes);
80} 111}
81 112
82static off_t app_lseek(int fd, off_t offset, int whence) 113static void plugin_check_open_close__close(int fildes)
83{ 114{
84 return lseek(fd,offset,whence); 115 if (fildes < 0)
116 return;
117
118 if (!open_files_bitmap_test_bit(&open_files_bitmap, fildes))
119 {
120 logf("double close from plugin");
121 }
122
123 open_files_bitmap_clear_bit(&open_files_bitmap, fildes);
85} 124}
86 125
87static ssize_t app_write(int fd, const void *buf, size_t count) 126static int WRAPPER(open)(const char *path, int oflag, ...)
88{ 127{
89 return write(fd,buf,count); 128 int fildes = FS_PREFIX(open)(path, oflag __OPEN_MODE_ARG);
129 plugin_check_open_close__open(fildes);
130 return fildes;
90} 131}
91 132
92static int app_ftruncate(int fd, off_t length) 133static int WRAPPER(creat)(const char *path, mode_t mode)
93{ 134{
94 return ftruncate(fd,length); 135 int fildes = FS_PREFIX(creat)(path __CREAT_MODE_ARG);
136 plugin_check_open_close__open(fildes);
137 return fildes;
138 (void)mode;
95} 139}
96#endif
97 140
98#if defined(HAVE_PLUGIN_CHECK_OPEN_CLOSE) && (MAX_OPEN_FILES>32) 141static int WRAPPER(close)(int fildes)
99#warning "MAX_OPEN_FILES>32, disabling plugin file open/close checking" 142{
100#undef HAVE_PLUGIN_CHECK_OPEN_CLOSE 143 int rc = FS_PREFIX(close)(fildes);
101#endif 144 if (rc >= 0)
145 plugin_check_open_close__close(fildes);
102 146
103#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE 147 return rc;
104static unsigned int open_files; 148}
105#endif
106 149
107#if (CONFIG_PLATFORM & PLATFORM_HOSTED) 150static void plugin_check_open_close__exit(void)
108static unsigned char pluginbuf[PLUGIN_BUFFER_SIZE]; 151{
109void sim_lcd_ex_init(unsigned long (*getpixel)(int, int)); 152 if (current_plugin_handle)
110void sim_lcd_ex_update_rect(int x, int y, int width, int height); 153 return;
111#else
112extern unsigned char pluginbuf[];
113#include "bitswap.h"
114#endif
115 154
116/* for actual plugins only, not for codecs */ 155 if (open_files_bitmap_is_clear(&open_files_bitmap))
117static int plugin_size = 0; 156 return;
118static bool (*pfn_tsr_exit)(bool reenter) = NULL; /* TSR exit callback */
119static char current_plugin[MAX_PATH];
120/* NULL if no plugin is loaded, otherwise the handle that lc_open() returned */
121static void *current_plugin_handle;
122 157
123char *plugin_get_current_filename(void); 158 logf("Plugin '%s' leaks file handles", plugin);
124 159
125/* Some wrappers used to monitor open and close and detect leaks*/ 160 static const char *lines[] =
126static int open_wrapper(const char* pathname, int flags, ...); 161 { ID2P(LANG_PLUGIN_ERROR), "#leak-file-handles" };
127#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE 162 static const struct text_message message = { lines, 2 };
128static int close_wrapper(int fd); 163 button_clear_queue(); /* Empty the keyboard buffer */
129static int creat_wrapper(const char *pathname, mode_t mode); 164 gui_syncyesno_run(&message, NULL, NULL);
130#endif
131 165
132static void* plugin_get_audio_buffer(size_t *buffer_size); 166 FOR_EACH_BITARRAY_SET_BIT(&open_files_bitmap, fildes)
133static void plugin_release_audio_buffer(void); 167 WRAPPER(close)(fildes);
134static void plugin_tsr(bool (*exit_callback)(bool)); 168}
169
170#else /* !HAVE_PLUGIN_CHECK_OPEN_CLOSE */
171
172#define PCOC_WRAPPER(_x_) FS_PREFIX(_x_)
173#define plugin_check_open_close__enter()
174#define plugin_check_open_close__exit()
175
176#endif /* HAVE_PLUGIN_CHECK_OPEN_CLOSE */
135 177
136static const struct plugin_api rockbox_api = { 178static const struct plugin_api rockbox_api = {
137 179
@@ -339,24 +381,16 @@ static const struct plugin_api rockbox_api = {
339 381
340 /* file */ 382 /* file */
341 open_utf8, 383 open_utf8,
342 (open_func)open_wrapper, 384 PCOC_WRAPPER(open),
343#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE 385 PCOC_WRAPPER(creat),
344 close_wrapper, 386 PCOC_WRAPPER(close),
345#else 387 FS_PREFIX(read),
346 PREFIX(close), 388 FS_PREFIX(lseek),
347#endif 389 FS_PREFIX(write),
348 (read_func)PREFIX(read), 390 FS_PREFIX(remove),
349 PREFIX(lseek), 391 FS_PREFIX(rename),
350#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE 392 FS_PREFIX(ftruncate),
351 (creat_func)creat_wrapper, 393 FS_PREFIX(filesize),
352#else
353 PREFIX(creat),
354#endif
355 (write_func)PREFIX(write),
356 PREFIX(remove),
357 PREFIX(rename),
358 PREFIX(ftruncate),
359 filesize,
360 fdprintf, 394 fdprintf,
361 read_line, 395 read_line,
362 settings_parseline, 396 settings_parseline,
@@ -369,18 +403,18 @@ static const struct plugin_api rockbox_api = {
369#endif /* USING_STORAGE_CALLBACK */ 403#endif /* USING_STORAGE_CALLBACK */
370 reload_directory, 404 reload_directory,
371 create_numbered_filename, 405 create_numbered_filename,
372 file_exists, 406 FS_PREFIX(file_exists),
373 strip_extension, 407 strip_extension,
374 crc_32, 408 crc_32,
375 filetype_get_attr, 409 filetype_get_attr,
376 410
377 /* dir */ 411 /* dir */
378 (opendir_func)opendir, 412 FS_PREFIX(opendir),
379 (closedir_func)closedir, 413 FS_PREFIX(closedir),
380 (readdir_func)readdir, 414 FS_PREFIX(readdir),
381 mkdir, 415 FS_PREFIX(mkdir),
382 rmdir, 416 FS_PREFIX(rmdir),
383 dir_exists, 417 FS_PREFIX(dir_exists),
384 dir_get_info, 418 dir_get_info,
385 419
386 /* browsing */ 420 /* browsing */
@@ -688,10 +722,11 @@ static const struct plugin_api rockbox_api = {
688#endif 722#endif
689 srand, 723 srand,
690 rand, 724 rand,
691 (qsort_func)qsort, 725 (void *)qsort,
692 kbd_input, 726 kbd_input,
693 get_time, 727 get_time,
694 set_time, 728 set_time,
729 gmtime_r,
695#if CONFIG_RTC 730#if CONFIG_RTC
696 mktime, 731 mktime,
697#endif 732#endif
@@ -891,9 +926,7 @@ int plugin_load(const char* plugin, const void* parameter)
891 /* allow voice to back off if the plugin needs lots of memory */ 926 /* allow voice to back off if the plugin needs lots of memory */
892 talk_buffer_set_policy(TALK_BUFFER_LOOSE); 927 talk_buffer_set_policy(TALK_BUFFER_LOOSE);
893 928
894#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE 929 plugin_check_open_close__enter();
895 open_files = 0;
896#endif
897 930
898 int rc = p_hdr->entry_point(parameter); 931 int rc = p_hdr->entry_point(parameter);
899 932
@@ -947,24 +980,7 @@ int plugin_load(const char* plugin, const void* parameter)
947 FOR_NB_SCREENS(i) 980 FOR_NB_SCREENS(i)
948 viewportmanager_theme_undo(i, true); 981 viewportmanager_theme_undo(i, true);
949 982
950#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE 983 plugin_check_open_close__exit();
951 if(open_files != 0 && !current_plugin_handle)
952 {
953 int fd;
954 logf("Plugin '%s' leaks file handles", plugin);
955
956 static const char *lines[] =
957 { ID2P(LANG_PLUGIN_ERROR),
958 "#leak-file-handles" };
959 static const struct text_message message={ lines, 2 };
960 button_clear_queue(); /* Empty the keyboard buffer */
961 gui_syncyesno_run(&message, NULL, NULL);
962
963 for(fd=0; fd < MAX_OPEN_FILES; fd++)
964 if(open_files & (1<<fd))
965 close_wrapper(fd);
966 }
967#endif
968 984
969 if (rc == PLUGIN_ERROR) 985 if (rc == PLUGIN_ERROR)
970 splash(HZ*2, str(LANG_PLUGIN_ERROR)); 986 splash(HZ*2, str(LANG_PLUGIN_ERROR));
@@ -1027,55 +1043,3 @@ char *plugin_get_current_filename(void)
1027{ 1043{
1028 return current_plugin; 1044 return current_plugin;
1029} 1045}
1030
1031static int open_wrapper(const char* pathname, int flags, ...)
1032{
1033/* we don't have an 'open' function. it's a define. and we need
1034 * the real file_open, hence PREFIX() doesn't work here */
1035 int fd;
1036#if (CONFIG_PLATFORM & PLATFORM_HOSTED)
1037 if (flags & O_CREAT)
1038 {
1039 va_list ap;
1040 va_start(ap, flags);
1041 fd = open(pathname, flags, va_arg(ap, unsigned int));
1042 va_end(ap);
1043 }
1044 else
1045 fd = open(pathname, flags);
1046#else
1047 fd = file_open(pathname,flags);
1048#endif
1049
1050#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE
1051 if(fd >= 0)
1052 open_files |= 1<<fd;
1053#endif
1054 return fd;
1055}
1056
1057#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE
1058static int close_wrapper(int fd)
1059{
1060 if((~open_files) & (1<<fd))
1061 {
1062 logf("double close from plugin");
1063 }
1064 if(fd >= 0)
1065 open_files &= (~(1<<fd));
1066
1067 return PREFIX(close)(fd);
1068}
1069
1070static int creat_wrapper(const char *pathname, mode_t mode)
1071{
1072 (void)mode;
1073
1074 int fd = PREFIX(creat)(pathname, mode);
1075
1076 if(fd >= 0)
1077 open_files |= (1<<fd);
1078
1079 return fd;
1080}
1081#endif /* HAVE_PLUGIN_CHECK_OPEN_CLOSE */