diff --git a/apps/misc.c b/apps/misc.c index 1410d47..171d01f 100644 --- a/apps/misc.c +++ b/apps/misc.c @@ -1207,15 +1207,14 @@ void format_time(char* buf, int buf_size, long t) } } +#define BOM_SIZE 3 +static const unsigned char BOM[BOM_SIZE] = { 0xef, 0xbb, 0xbf }; /** Open a UTF-8 file and set file descriptor to first byte after BOM. * If no BOM is present this behaves like open(). * If the file is opened for writing and O_TRUNC is set, write a BOM to * the opened file and leave the file pointer set after the BOM. */ -#define BOM "\xef\xbb\xbf" -#define BOM_SIZE 3 - int open_utf8(const char* pathname, int flags) { int fd; @@ -1239,6 +1238,46 @@ int open_utf8(const char* pathname, int flags) return fd; } +/* Seek a UTF-8 file. + * When the resulting offset location is the beginning of the file, + * if the file starts BOM, then lseek_utf8() returns BOM_SIZE. + */ +off_t lseek_utf8(int fd, off_t offset, int whence) +{ + unsigned char bom[BOM_SIZE]; + off_t res = lseek(fd, offset, whence); + + if (res != 0) + return res; + + read(fd, bom, BOM_SIZE); + /* check for BOM */ + if(memcmp(bom, BOM, BOM_SIZE)) + res = lseek(fd, 0, SEEK_SET); + else + res = BOM_SIZE; + + return res; +} + +/* Get a UTF-8 file size. + * If the file starts BOM, then filesize_utf8() returns filesize() - BOM_SIZE. + */ +off_t filesize_utf8(int fd) +{ + unsigned char bom[BOM_SIZE]; + off_t sz = filesize(fd); + off_t cur = lseek(fd, 0, SEEK_CUR); + + lseek(fd, 0, SEEK_SET); + read(fd, bom, BOM_SIZE); + /* check for BOM */ + if(!memcmp(bom, BOM, BOM_SIZE)) + sz -= BOM_SIZE; + lseek(fd, cur, SEEK_SET); + + return sz; +} #ifdef HAVE_LCD_COLOR /* diff --git a/apps/misc.h b/apps/misc.h index 807f231..0211813 100644 --- a/apps/misc.h +++ b/apps/misc.h @@ -23,6 +23,7 @@ #include #include +#include /* Format a large-range value for output, using the appropriate unit so that * the displayed value is in the range 1 <= display < 1000 (1024 for "binary" @@ -108,6 +109,8 @@ int get_replaygain_mode(bool have_track_gain, bool have_album_gain); #endif int open_utf8(const char* pathname, int flags); +off_t lseek_utf8(int fd, off_t offset, int whence); +off_t filesize_utf8(int fd); #ifdef BOOTFILE #if !defined(USB_NONE) && !defined(USB_IPODSTYLE) diff --git a/apps/plugin.c b/apps/plugin.c index a19a08b..038a9c1 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -260,15 +260,18 @@ static const struct plugin_api rockbox_api = { /* file */ (open_func)PREFIX(open), + open_utf8, PREFIX(close), (read_func)PREFIX(read), PREFIX(lseek), + lseek_utf8, (creat_func)PREFIX(creat), (write_func)PREFIX(write), PREFIX(remove), PREFIX(rename), PREFIX(ftruncate), PREFIX(filesize), + filesize_utf8, fdprintf, read_line, settings_parseline, diff --git a/apps/plugin.h b/apps/plugin.h old mode 100644 new mode 100755 index 992012b..0901152 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -126,12 +126,12 @@ void* plugin_get_buffer(size_t *buffer_size); #define PLUGIN_MAGIC 0x526F634B /* RocK */ /* increase this every time the api struct changes */ -#define PLUGIN_API_VERSION 137 +#define PLUGIN_API_VERSION 138 /* update this to latest version if a change to the api struct breaks backwards compatibility (and please take the opportunity to sort in any new function which are "waiting" at the end of the function table) */ -#define PLUGIN_MIN_API_VERSION 137 +#define PLUGIN_MIN_API_VERSION 138 /* plugin return codes */ enum plugin_status { @@ -364,15 +364,18 @@ struct plugin_api { /* file */ int (*open)(const char* pathname, int flags); + int (*open_utf8)(const char* pathname, int flags); int (*close)(int fd); ssize_t (*read)(int fd, void* buf, size_t count); off_t (*lseek)(int fd, off_t offset, int whence); + off_t (*lseek_utf8)(int fd, off_t offset, int whence); int (*creat)(const char *pathname); ssize_t (*write)(int fd, const void* buf, size_t count); int (*remove)(const char* pathname); int (*rename)(const char* path, const char* newname); int (*ftruncate)(int fd, off_t length); off_t (*filesize)(int fd); + off_t (*filesize_utf8)(int fd); int (*fdprintf)(int fd, const char *fmt, ...) ATTRIBUTE_PRINTF(2, 3); int (*read_line)(int fd, char* buffer, int buffer_size); bool (*settings_parseline)(char* line, char** name, char** value); diff --git a/apps/plugins/viewer.c b/apps/plugins/viewer.c index 7e03c55..da7902d 100644 --- a/apps/plugins/viewer.c +++ b/apps/plugins/viewer.c @@ -716,7 +716,7 @@ static void fill_buffer(long pos, unsigned char* buf, unsigned size) unsigned numread, i; bool found_CR = false; - rb->lseek(fd, pos, SEEK_SET); + rb->lseek_utf8(fd, pos, SEEK_SET); numread = rb->read(fd, buf, size); rb->button_clear_queue(); /* clear button queue */ @@ -1152,11 +1152,11 @@ static bool viewer_init(void) par_indent_spaces = 2; #endif - fd = rb->open(file_name, O_RDONLY); + fd = rb->open_utf8(file_name, O_RDONLY); if (fd==-1) return false; - file_size = rb->filesize(fd); + file_size = rb->filesize_utf8(fd); if (file_size==-1) return false;