From 46137ebd4d59d7a91d0b8d98d846a3fd2ec70f5c Mon Sep 17 00:00:00 2001 From: Thomas Martitz Date: Sat, 22 Feb 2014 23:17:16 +0100 Subject: simulator: Fully simulate external storage. The external storage will be created during make install, as simext folder in the build directory. Upon pressing the e key the sim will mount (virtually ) this into the root directory. It can be accessed in the same way as an sd/mmc card on real targets. This requires quite some path trickery in io.c. Change-Id: I2fa9070a3146101ec5655b5b4115ca349d1d4bf4 --- firmware/export/disk.h | 5 ---- firmware/export/mv.h | 6 +++++ tools/root.make | 10 ++++--- uisimulator/common/io.c | 72 ++++++++++++++++++++++++++++++++++++++++--------- 4 files changed, 72 insertions(+), 21 deletions(-) diff --git a/firmware/export/disk.h b/firmware/export/disk.h index b97ec11039..8d6b41b5bd 100644 --- a/firmware/export/disk.h +++ b/firmware/export/disk.h @@ -50,9 +50,4 @@ int disk_unmount(int drive); int disk_get_sector_multiplier(IF_MD_NONVOID(int drive)); #endif -#ifdef HAVE_HOTSWAP -bool volume_removable(int volume); -bool volume_present(int volume); -#endif - #endif diff --git a/firmware/export/mv.h b/firmware/export/mv.h index 0d98ed1211..05c9c6349f 100644 --- a/firmware/export/mv.h +++ b/firmware/export/mv.h @@ -56,6 +56,12 @@ #define VOL_NAMES "" #define VOL_ENUM_POS 3 #endif /* CONFIG_STORAGE */ + +#ifdef HAVE_HOTSWAP +bool volume_removable(int volume); +bool volume_present(int volume); +#endif + #else /* empty definitions if no multi-volume */ #define IF_MV(x...) #define IF_MV_NONVOID(x...) void diff --git a/tools/root.make b/tools/root.make index 20e1ce3b53..4d58e26e8e 100644 --- a/tools/root.make +++ b/tools/root.make @@ -355,19 +355,23 @@ voice: voicetools $(BUILDDIR)/apps/features endif ifeq (,$(findstring android, $(APP_TYPE))) + +simext: + $(SILENT)mkdir -p $@ + bininstall: $(BUILDDIR)/$(BINARY) @echo "Installing your rockbox binary in your '$(RBPREFIX)' dir" $(SILENT)cp $(BINARY) "$(RBPREFIX)/.rockbox/" -install: +install: simext @echo "Installing your build in your '$(RBPREFIX)' dir" $(SILENT)$(TOOLSDIR)/buildzip.pl $(VERBOSEOPT) --app=$(APPLICATION) -m "$(MODELNAME)" -i "$(TARGET_ID)" $(INSTALL) -z "zip -r0" -r "$(ROOTDIR)" --rbdir="$(RBDIR)" -f 0 $(TARGET) $(BINARY) -fullinstall: +fullinstall: simext @echo "Installing a full setup in your '$(RBPREFIX)' dir" $(SILENT)$(TOOLSDIR)/buildzip.pl $(VERBOSEOPT) --app=$(APPLICATION) -m "$(MODELNAME)" -i "$(TARGET_ID)" $(INSTALL) -z "zip -r0" -r "$(ROOTDIR)" --rbdir="$(RBDIR)" -f 2 $(TARGET) $(BINARY) -symlinkinstall: +symlinkinstall: simext @echo "Installing a full setup with links in your '$(RBPREFIX)' dir" $(SILENT)$(TOOLSDIR)/buildzip.pl $(VERBOSEOPT) --app=$(APPLICATION) -m "$(MODELNAME)" -i "$(TARGET_ID)" $(INSTALL) -z "zip -r0" -r "$(ROOTDIR)" --rbdir="$(RBDIR)" -f 2 $(TARGET) $(BINARY) -l endif diff --git a/uisimulator/common/io.c b/uisimulator/common/io.c index 9401f7d54a..179a919013 100644 --- a/uisimulator/common/io.c +++ b/uisimulator/common/io.c @@ -27,7 +27,9 @@ #include #include #include "config.h" +#include "system.h" #include "ata_idle_notify.h" +#include "mv.h" #define HAVE_STATVFS (!defined(WIN32)) #define HAVE_LSTAT (!defined(WIN32)) @@ -124,7 +126,8 @@ extern int _wrmdir(const wchar_t*); #define CLOSE(a) (close)(a) #define REMOVE(a) (_wremove)(UTF8_TO_OS(a)) #define RENAME(a,b) (_wrename)(UTF8_TO_OS(a),utf8_to_ucs2(b,convbuf2)) - +/* readlink isn't used in the sim yet (FIXME) */ +#define READLINK(a,b,c) ({ fprintf(stderr, "no readlink on windows yet"); abort(); }) #else /* !__MINGW32__ */ #define UTF8_TO_OS(a) (a) @@ -144,6 +147,7 @@ extern int _wrmdir(const wchar_t*); #define CLOSE(x) (close)(x) #define REMOVE(a) (remove)(a) #define RENAME(a,b) (rename)(a,b) +#define READLINK(a,b,c) (readlink)(a,b,c) #endif /* !__MINGW32__ */ @@ -183,6 +187,7 @@ struct dirstruct { struct mydir { DIR_T *dir; + IF_MV(int volumes_returned); char *name; }; @@ -323,6 +328,30 @@ ssize_t sim_write(int fd, const void *buf, size_t count) } #if !defined(APPLICATION) + +static const char *handle_special_links(const char* link) +{ + static char buffer[MAX_PATH]; /* sufficiently big */ + char vol_string[VOL_ENUM_POS + 8]; + int len = sprintf(vol_string, VOL_NAMES, 1); + + /* link might be passed with or without HOME_DIR expanded. To handle + * both perform substring matching (VOL_NAMES is unique enough) */ + const char *begin = strstr(link, vol_string); + if (begin) + { + /* begin now points to the start of vol_string within link, + * we want to copy the remainder of the paths, prefixed by + * the actual mount point (the remainder might be "") */ + snprintf(buffer, sizeof(buffer), "%s/../simext/%s", + sim_root_dir ?: SIMULATOR_DEFAULT_ROOT, begin + len); + return buffer; + } + else + return link; +} + + static const char *get_sim_pathname(const char *name) { static char buffer[MAX_PATH]; /* sufficiently big */ @@ -330,13 +359,14 @@ static const char *get_sim_pathname(const char *name) if(name[0] == '/') { snprintf(buffer, sizeof(buffer), "%s%s", - sim_root_dir != NULL ? sim_root_dir : SIMULATOR_DEFAULT_ROOT, name); - return buffer; + sim_root_dir ?: SIMULATOR_DEFAULT_ROOT, name); + return handle_special_links(buffer); } fprintf(stderr, "WARNING, bad file name lacks slash: %s\n", name); return name; } + MYDIR *sim_opendir(const char *name) { DIR_T *dir; @@ -348,6 +378,7 @@ MYDIR *sim_opendir(const char *name) my->dir = dir; my->name = (char *)malloc(strlen(name)+1); strcpy(my->name, name); + IF_MV(my->volumes_returned = 0); return my; } @@ -374,16 +405,34 @@ struct sim_dirent *sim_readdir(MYDIR *dir) #ifdef EOVERFLOW read_next: #endif - x11 = READDIR(dir->dir); - if(!x11) - return (struct sim_dirent *)0; +#define ATTR_LINK 0x80 /* see dir.h */ + + secret.info.attribute = 0; +#ifdef HAVE_MULTIVOLUME + if (dir->name[0] == '/' && dir->name[1] == '\0' + && dir->volumes_returned++ < (NUM_VOLUMES-1) + && volume_present(dir->volumes_returned)) + { + sprintf((char *)secret.d_name, VOL_NAMES, dir->volumes_returned); + secret.info.attribute = ATTR_LINK; + /* build file name for stat() which is the actual mount point */ + snprintf(buffer, sizeof(buffer), "%s/../simext", + sim_root_dir ?: SIMULATOR_DEFAULT_ROOT); + } + else +#endif + { + x11 = READDIR(dir->dir); - strcpy((char *)secret.d_name, OS_TO_UTF8(x11->d_name)); + if(!x11) + return (struct sim_dirent *)0; - /* build file name */ - snprintf(buffer, sizeof(buffer), "%s/%s", - get_sim_pathname(dir->name), secret.d_name); + strcpy((char *)secret.d_name, OS_TO_UTF8(x11->d_name)); + /* build file name for stat() */ + snprintf(buffer, sizeof(buffer), "%s/%s", + get_sim_pathname(dir->name), secret.d_name); + } if (STAT(buffer, &s)) /* get info */ { @@ -401,8 +450,6 @@ read_next: #define ATTR_DIRECTORY 0x10 - secret.info.attribute = 0; - if (S_ISDIR(s.st_mode)) secret.info.attribute = ATTR_DIRECTORY; @@ -418,7 +465,6 @@ read_next: (tm.tm_sec >> 1); #if HAVE_LSTAT -#define ATTR_LINK 0x80 if (!lstat(buffer, &s) && S_ISLNK(s.st_mode)) { secret.info.attribute |= ATTR_LINK; -- cgit v1.2.3