From f850bbbbc4b7345bebde241f651bad1c5c28df66 Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Thu, 20 Aug 2020 21:54:00 -0400 Subject: Revert root_redirect :( This reverts commit 31fc46ded69be7438cca2ba2c2b93c1f200165a6. Change-Id: Ia78618c0e8b25ca65f7c8ae0db1cb9c9b321bad9 --- apps/debug_menu.c | 19 +-- firmware/SOURCES | 1 - firmware/common/dir.c | 92 +++++++++-- firmware/common/dircache.c | 9 +- firmware/common/disk.c | 4 + firmware/common/file.c | 2 +- firmware/common/file_internal.c | 95 ++++++++---- firmware/common/fileobj_mgr.c | 114 ++++---------- firmware/common/pathfuncs.c | 43 ++---- firmware/common/rb_namespace.c | 289 ----------------------------------- firmware/export/mv.h | 4 - firmware/export/pathfuncs.h | 6 - firmware/export/rbpaths.h | 3 - firmware/include/dircache_redirect.h | 58 +------ firmware/include/file_internal.h | 22 ++- firmware/include/fileobj_mgr.h | 5 - firmware/include/fs_defines.h | 11 +- firmware/include/rb_namespace.h | 79 ---------- uisimulator/common/filesystem-sim.c | 2 - 19 files changed, 214 insertions(+), 644 deletions(-) delete mode 100644 firmware/common/rb_namespace.c delete mode 100644 firmware/include/rb_namespace.h diff --git a/apps/debug_menu.c b/apps/debug_menu.c index eae389d049..e75fce6d32 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c @@ -2453,21 +2453,16 @@ static bool dbg_boot_data(void) simplelist_set_line_count(0); crc = crc_32(boot_data.payload, boot_data.length, 0xffffffff); #if defined(HAVE_MULTIBOOT) - char rootpath[VOL_MAX_LEN+2] = RB_ROOT_CONTENTS_DIR; int boot_volume = 0; - if(crc == boot_data.crc) - { - boot_volume = boot_data.boot_volume; /* boot volume contained in uint8_t payload */ - get_redirect_dir(rootpath, sizeof(rootpath), boot_volume, "", ""); - rootpath[path_strip_trailing_separators(rootpath,NULL)] = '\0'; - } - simplelist_addline("Boot Volume: <%lu>", boot_volume); - simplelist_addline("Root:"); - simplelist_addline("%s", rootpath); - simplelist_addline(""); + if(crc == boot_data.crc) + { + boot_volume = boot_data.boot_volume; /* boot volume contained in uint8_t payload */ + } + simplelist_addline("Boot Volume: <%lu>", boot_volume); + simplelist_addline(""); #endif simplelist_addline("Bootdata RAW:"); - if (crc != boot_data.crc) + if (crc != boot_data.crc) simplelist_addline("Magic: %.8s", boot_data.magic); simplelist_addline("Length: %lu", boot_data.length); simplelist_addline("CRC: %lx", boot_data.crc); diff --git a/firmware/SOURCES b/firmware/SOURCES index f1c7621244..a68d10ec76 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -238,7 +238,6 @@ common/dircache.c common/pathfuncs.c common/fdprintf.c common/linked_list.c -common/rb_namespace.c common/strcasecmp.c common/strcasestr.c common/strnatcmp.c diff --git a/firmware/common/dir.c b/firmware/common/dir.c index 85e6ff316b..f89129ae34 100644 --- a/firmware/common/dir.c +++ b/firmware/common/dir.c @@ -27,14 +27,17 @@ #include "dir.h" #include "pathfuncs.h" #include "fileobj_mgr.h" -#include "rb_namespace.h" +#include "dircache_redirect.h" /* structure used for open directory streams */ static struct dirstr_desc { struct filestr_base stream; /* basic stream info (first!) */ - struct ns_scan_info scan; /* directory scan cursor */ + struct dirscan_info scan; /* directory scan cursor */ struct dirent entry; /* current parsed entry information */ +#ifdef HAVE_MULTIVOLUME + int volumecounter; /* counter for root volume entries */ +#endif } open_streams[MAX_OPEN_DIRS]; /* check and return a struct dirstr_desc* from a DIR* */ @@ -44,7 +47,7 @@ static struct dirstr_desc * get_dirstr(DIR *dirp) if (!PTR_IN_ARRAY(open_streams, dir, MAX_OPEN_DIRS)) dir = NULL; - else if (dir->stream.flags & (FDO_BUSY|FD_VALID)) + else if (dir->stream.flags & FDO_BUSY) return dir; int errnum; @@ -101,6 +104,49 @@ static struct dirstr_desc * alloc_dirstr(void) return NULL; } +#ifdef HAVE_MULTIVOLUME +static int readdir_volume_inner(struct dirstr_desc *dir, struct dirent *entry) +{ + /* Volumes (secondary file systems) get inserted into the system root + * directory. If the path specified volume 0, enumeration will not + * include other volumes, but just its own files and directories. + * + * Fake special directories, which don't really exist, that will get + * redirected upon opendir() + */ + while (++dir->volumecounter < NUM_VOLUMES) + { + /* on the system root */ + if (!fat_ismounted(dir->volumecounter)) + continue; + + get_volume_name(dir->volumecounter, entry->d_name); + dir->entry.info.attr = ATTR_MOUNT_POINT; + dir->entry.info.size = 0; + dir->entry.info.wrtdate = 0; + dir->entry.info.wrttime = 0; + return 1; + } + + /* do normal directory entry fetching */ + return 0; +} +#endif /* HAVE_MULTIVOLUME */ + +static inline int readdir_volume(struct dirstr_desc *dir, + struct dirent *entry) +{ +#ifdef HAVE_MULTIVOLUME + /* fetch virtual volume entries? */ + if (dir->volumecounter < NUM_VOLUMES) + return readdir_volume_inner(dir, entry); +#endif /* HAVE_MULTIVOLUME */ + + /* do normal directory entry fetching */ + return 0; + (void)dir; (void)entry; +} + /** POSIX interface **/ @@ -119,13 +165,21 @@ DIR * opendir(const char *dirname) if (!dir) FILE_ERROR(EMFILE, RC); - rc = ns_open_stream(dirname, FF_DIR, &dir->stream, &dir->scan); + rc = open_stream_internal(dirname, FF_DIR, &dir->stream, NULL); if (rc < 0) { DEBUGF("Open failed: %d\n", rc); FILE_ERROR(ERRNO, RC); } +#ifdef HAVE_MULTIVOLUME + /* volume counter is relevant only to the system root */ + dir->volumecounter = rc > 1 ? 0 : INT_MAX; +#endif /* HAVE_MULTIVOLUME */ + + fat_rewind(&dir->stream.fatstr); + rewinddir_dirent(&dir->scan); + dirp = (DIR *)dir; file_error: file_internal_unlock_WRITER(); @@ -150,7 +204,7 @@ int closedir(DIR *dirp) FILE_ERROR(EBADF, -2); } - rc = ns_close_stream(&dir->stream); + rc = close_stream_internal(&dir->stream); if (rc < 0) FILE_ERROR(ERRNO, rc * 10 - 3); @@ -168,11 +222,16 @@ struct dirent * readdir(DIR *dirp) struct dirent *res = NULL; - int rc = ns_readdir_dirent(&dir->stream, &dir->scan, &dir->entry); + int rc = readdir_volume(dir, &dir->entry); + if (rc == 0) + { + rc = readdir_dirent(&dir->stream, &dir->scan, &dir->entry); + if (rc < 0) + FILE_ERROR(EIO, RC); + } + if (rc > 0) res = &dir->entry; - else if (rc < 0) - FILE_ERROR(EIO, RC); file_error: RELEASE_DIRSTR(READER, dir); @@ -199,9 +258,13 @@ int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) if (!dir) FILE_ERROR_RETURN(ERRNO, -1); - int rc = ns_readdir_dirent(&dir->stream, &dir->scan, entry); - if (rc < 0) - FILE_ERROR(EIO, rc * 10 - 4); + int rc = readdir_volume(dir, entry); + if (rc == 0) + { + rc = readdir_dirent(&dir->stream, &dir->scan, entry); + if (rc < 0) + FILE_ERROR(EIO, rc * 10 - 4); + } file_error: RELEASE_DIRSTR(READER, dir); @@ -225,7 +288,12 @@ void rewinddir(DIR *dirp) if (!dir) FILE_ERROR_RETURN(ERRNO); - ns_dirscan_rewind(&dir->scan); + rewinddir_dirent(&dir->scan); + +#ifdef HAVE_MULTIVOLUME + if (dir->volumecounter != INT_MAX) + dir->volumecounter = 0; +#endif /* HAVE_MULTIVOLUME */ RELEASE_DIRSTR(READER, dir); } diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c index cc65d2d540..0cdaf1bd4a 100644 --- a/firmware/common/dircache.c +++ b/firmware/common/dircache.c @@ -2541,10 +2541,13 @@ static ssize_t get_path_sub(int idx, struct get_path_sub_data *data) cename = ""; #ifdef HAVE_MULTIVOLUME - /* prepend the volume specifier */ int volume = IF_MV_VOL(-idx - 1); - cename = alloca(VOL_MAX_LEN+1); - get_volume_name(volume, cename); + if (volume > 0) + { + /* prepend the volume specifier for volumes > 0 */ + cename = alloca(VOL_MAX_LEN+1); + get_volume_name(volume, cename); + } #endif /* HAVE_MULTIVOLUME */ data->serialhash = dc_hash_serialnum(get_idx_dcvolp(idx)->serialnum, diff --git a/firmware/common/disk.c b/firmware/common/disk.c index 49137286a3..51d033b678 100644 --- a/firmware/common/disk.c +++ b/firmware/common/disk.c @@ -30,6 +30,10 @@ #include "dircache_redirect.h" #include "disk.h" +#if defined(HAVE_BOOTDATA) && !defined(SIMULATOR) && !defined(BOOTLOADER) +#include "bootdata.h" +#include "crc32.h" +#endif #ifndef CONFIG_DEFAULT_PARTNUM #define CONFIG_DEFAULT_PARTNUM 0 diff --git a/firmware/common/file.c b/firmware/common/file.c index 893e475a32..cb918c6eab 100644 --- a/firmware/common/file.c +++ b/firmware/common/file.c @@ -28,7 +28,7 @@ #include "file.h" #include "fileobj_mgr.h" #include "disk_cache.h" -#include "rb_namespace.h" +#include "dircache_redirect.h" #include "string-extra.h" /** diff --git a/firmware/common/file_internal.c b/firmware/common/file_internal.c index 45f412e166..fe18f90056 100644 --- a/firmware/common/file_internal.c +++ b/firmware/common/file_internal.c @@ -26,7 +26,9 @@ #include "pathfuncs.h" #include "disk_cache.h" #include "fileobj_mgr.h" -#include "rb_namespace.h" +#include "dir.h" +#include "dircache_redirect.h" +#include "dircache.h" #include "string-extra.h" #include "rbunicode.h" @@ -85,10 +87,9 @@ void file_cache_free(struct filestr_cache *cachep) /** Stream base APIs **/ -static inline void filestr_clear(struct filestr_base *stream, - unsigned int flags) +static inline void filestr_clear(struct filestr_base *stream) { - stream->flags = flags; + stream->flags = 0; stream->bindp = NULL; #if 0 stream->mtx = NULL; @@ -152,7 +153,7 @@ void filestr_discard_cache(struct filestr_base *stream) /* Initialize the base descriptor */ void filestr_base_init(struct filestr_base *stream) { - filestr_clear(stream, FD_VALID); + filestr_clear(stream); file_cache_init(&stream->cache); stream->cachep = &stream->cache; } @@ -160,7 +161,7 @@ void filestr_base_init(struct filestr_base *stream) /* free base descriptor resources */ void filestr_base_destroy(struct filestr_base *stream) { - filestr_clear(stream, 0); + filestr_clear(stream); filestr_free_cache(stream); } @@ -292,7 +293,7 @@ struct pathwalk_component #define WALK_RC_NOT_FOUND 0 /* successfully not found (aid for file creation) */ #define WALK_RC_FOUND 1 /* found and opened */ -#define WALK_RC_FOUND_ROOT 2 /* found and opened sys root */ +#define WALK_RC_FOUND_ROOT 2 /* found and opened sys/volume root */ #define WALK_RC_CONT_AT_ROOT 3 /* continue at root level */ /* return another struct pathwalk_component from the pool, or NULL if the @@ -396,10 +397,10 @@ static int walk_open_info(struct pathwalk *walkp, /* make open official if not simply probing for presence - must do it here or compp->info on stack will get destroyed before it was copied */ - if (!(callflags & (FF_PROBE|FF_NOFS))) + if (!(callflags & FF_PROBE)) fileop_onopen_internal(stream, &compp->info, callflags); - return compp->attr == ATTR_SYSTEM_ROOT ? WALK_RC_FOUND_ROOT : WALK_RC_FOUND; + return compp->nextp ? WALK_RC_FOUND : WALK_RC_FOUND_ROOT; } /* check the component against the prefix test info */ @@ -506,10 +507,6 @@ walk_path(struct pathwalk *walkp, struct pathwalk_component *compp, if (len > MAX_COMPNAME) return -ENAMETOOLONG; - /* no filesystem is mounted here */ - if (walkp->callflags & FF_NOFS) - return -ENOENT; - /* check for "." and ".." */ if (name[0] == '.') { @@ -578,7 +575,7 @@ int open_stream_internal(const char *path, unsigned int callflags, callflags &= ~(FF_INFO | FF_PARENTINFO | FF_CHECKPREFIX); /* This lets it be passed quietly to directory scanning */ - stream->flags |= callflags & FF_MASK; + stream->flags = callflags & FF_MASK; struct pathwalk walk; walk.path = path; @@ -588,36 +585,80 @@ int open_stream_internal(const char *path, unsigned int callflags, struct pathwalk_component *rootp = pathwalk_comp_alloc(NULL); rootp->nextp = NULL; + rootp->attr = ATTR_SYSTEM_ROOT; + +#ifdef HAVE_MULTIVOLUME + int volume = 0, rootrc = WALK_RC_FOUND; +#endif /* HAVE_MULTIVOLUME */ while (1) { - rc = ns_parse_root(walk.path, &rootp->name, &rootp->length); - if (rc < 0) - break; + const char *pathptr = walk.path; + + #ifdef HAVE_MULTIVOLUME + /* this seamlessly integrates secondary filesystems into the + root namespace (e.g. "/<0>/../../<1>/../foo/." :<=> "/foo") */ + const char *p; + volume = path_strip_volume(pathptr, &p, false); + if (!CHECK_VOL(volume)) + { + DEBUGF("No such device or address: %d\n", volume); + FILE_ERROR(ENXIO, -2); + } + + if (p == pathptr) + { + /* the root of this subpath is the system root */ + rootp->attr = ATTR_SYSTEM_ROOT; + rootrc = WALK_RC_FOUND_ROOT; + } + else + { + /* this subpath specifies a mount point */ + rootp->attr = ATTR_MOUNT_POINT; + rootrc = WALK_RC_FOUND; + } - rc = ns_open_root(IF_MV(rc,) &walk.callflags, &rootp->info, &rootp->attr); + walk.path = p; + #endif /* HAVE_MULTIVOLUME */ + + /* set name to start at last leading separator; names of volume + specifiers will be returned as "/" */ + rootp->name = GOBBLE_PATH_SEPCH(pathptr) - 1; + rootp->length = + IF_MV( rootrc == WALK_RC_FOUND ? p - rootp->name : ) 1; + + rc = fat_open_rootdir(IF_MV(volume,) &rootp->info.fatfile); if (rc < 0) + { + /* not mounted */ + DEBUGF("No such device or address: %d\n", IF_MV_VOL(volume)); + rc = -ENXIO; break; + } - walk.path = rootp->name + rootp->length; - + get_rootinfo_internal(&rootp->info); rc = walk_path(&walk, rootp, stream); if (rc != WALK_RC_CONT_AT_ROOT) break; } - if (rc >= 0) + switch (rc) { + case WALK_RC_FOUND_ROOT: + IF_MV( rc = rootrc; ) + case WALK_RC_NOT_FOUND: + case WALK_RC_FOUND: /* FF_PROBE leaves nothing for caller to clean up */ - if (walk.callflags & FF_PROBE) + if (callflags & FF_PROBE) filestr_base_destroy(stream); - } - else - { - /* utter, abject failure :`( */ + + break; + + default: /* utter, abject failure :`( */ DEBUGF("Open failed: rc=%d, errno=%d\n", rc, errno); filestr_base_destroy(stream); - FILE_ERROR(-rc, -1); + FILE_ERROR(-rc, -3); } file_error: diff --git a/firmware/common/fileobj_mgr.c b/firmware/common/fileobj_mgr.c index 37452fbbe1..e34a460e10 100644 --- a/firmware/common/fileobj_mgr.c +++ b/firmware/common/fileobj_mgr.c @@ -20,13 +20,12 @@ ****************************************************************************/ #include "config.h" #include "system.h" -#include #include "debug.h" #include "file.h" #include "dir.h" #include "disk_cache.h" #include "fileobj_mgr.h" -#include "rb_namespace.h" +#include "dircache_redirect.h" /** * Manages file and directory streams on all volumes @@ -35,8 +34,8 @@ */ -/* there will always be enough of these for all user handles, thus most of - these functions don't return failure codes */ +/* there will always be enough of these for all user handles, thus these + functions don't return failure codes */ #define MAX_FILEOBJS (MAX_OPEN_HANDLES + AUX_FILEOBJS) /* describes the file as an image on the storage medium */ @@ -85,15 +84,6 @@ static struct ll_head busy_bindings[NUM_VOLUMES]; for (struct filestr_base *s = STREAM_##what(start); \ s; s = STREAM_NEXT(s)) -/* once a file/directory, always a file/directory; such a change - is a bug */ -#define CHECK_FO_DIRECTORY(callflags, fobp) \ - if (((callflags) ^ (fobp)->flags) & FO_DIRECTORY) \ - { \ - DEBUGF("%s - FO_DIRECTORY flag does not match: %p %u\n", \ - __func__, (fobp), (callflags)); \ - } - /* syncs information for the stream's old and new parent directory if any are currently opened */ @@ -106,10 +96,6 @@ static void fileobj_sync_parent(const struct file_base_info *infop[], continue; /* not directory or removed can't be parent of anything */ struct filestr_base *parentstrp = STREAM_FIRST(fobp); - - if (!parentstrp) - continue; - struct fat_file *parentfilep = &parentstrp->infop->fatfile; for (int i = 0; i < count; i++) @@ -125,7 +111,8 @@ static void fileobj_sync_parent(const struct file_base_info *infop[], } /* see if this file has open streams and return that fileobj_binding if so, - else grab a new one from the free list; returns true if this is new */ + else grab a new one from the free list; returns true if this stream is + the only open one */ static bool binding_assign(const struct file_base_info *srcinfop, struct fileobj_binding **fobpp) { @@ -136,7 +123,7 @@ static bool binding_assign(const struct file_base_info *srcinfop, if (fat_file_is_same(&srcinfop->fatfile, &fobp->bind.info.fatfile)) { - /* already has open streams/mounts */ + /* already has open streams */ *fobpp = fobp; return false; } @@ -156,23 +143,6 @@ static void binding_add_to_free_list(struct fileobj_binding *fobp) ll_insert_last(FREE_BINDINGS(), &fobp->bind.node); } -static void bind_source_info(const struct file_base_info *srcinfop, - struct fileobj_binding **fobpp) -{ - if (!binding_assign(srcinfop, fobpp)) - return; /* already in use */ - - /* is new */ - (*fobpp)->bind.info = *srcinfop; - fileobj_bind_file(&(*fobpp)->bind); -} - -static void release_binding(struct fileobj_binding *fobp) -{ - fileobj_unbind_file(&fobp->bind); - binding_add_to_free_list(fobp); -} - /** File and directory internal interface **/ void file_binding_insert_last(struct file_base_binding *bindp) @@ -199,41 +169,6 @@ void file_binding_remove_next(struct file_base_binding *prevp, } #endif /* HAVE_DIRCACHE */ -/* mounts a file object as a target from elsewhere */ -bool fileobj_mount(const struct file_base_info *srcinfop, - unsigned int callflags, - struct file_base_binding **bindpp) -{ - struct fileobj_binding *fobp; - bind_source_info(srcinfop, &fobp); - - CHECK_FO_DIRECTORY(callflags, fobp); - - if (fobp->flags & FO_MOUNTTARGET) - return false; /* already mounted */ - - fobp->flags |= FDO_BUSY | FO_MOUNTTARGET | - (callflags & FO_DIRECTORY); - - *bindpp = &fobp->bind; - - return true; -} - -/* unmounts the file object and frees it if now unusued */ -void fileobj_unmount(struct file_base_binding *bindp) -{ - struct fileobj_binding *fobp = (struct fileobj_binding *)bindp; - - if (!(fobp->flags & FO_MOUNTTARGET)) - return; /* not mounted */ - - if (STREAM_FIRST(fobp) == NULL) - release_binding(fobp); /* no longer in use */ - else - fobp->flags &= ~FO_MOUNTTARGET; -} - /* opens the file object for a new stream and sets up the caches; * the stream must already be opened at the FS driver level and *stream * initialized. @@ -245,14 +180,10 @@ void fileobj_fileop_open(struct filestr_base *stream, const struct file_base_info *srcinfop, unsigned int callflags) { - /* assign base file information */ struct fileobj_binding *fobp; - bind_source_info(srcinfop, &fobp); - - unsigned int foflags = fobp->flags; + bool first = binding_assign(srcinfop, &fobp); /* add stream to this file's list */ - bool first = STREAM_FIRST(fobp) == NULL; ll_insert_last(&fobp->list, &stream->node); /* initiate the new stream into the enclave */ @@ -266,16 +197,27 @@ void fileobj_fileop_open(struct filestr_base *stream, if (first) { /* first stream for file */ - fobp->flags = foflags | FDO_BUSY | FO_SINGLE | - (callflags & (FO_DIRECTORY|FO_TRUNC)); - fobp->writers = 0; - fobp->size = 0; + fobp->bind.info = *srcinfop; + fobp->flags = FDO_BUSY | FO_SINGLE | + (callflags & (FO_DIRECTORY|FO_TRUNC)); + fobp->writers = 0; + fobp->size = 0; + + fileobj_bind_file(&fobp->bind); } else { /* additional stream for file */ - fobp->flags = (foflags & ~FO_SINGLE) | (callflags & FO_TRUNC); - CHECK_FO_DIRECTORY(callflags, fobp); + fobp->flags &= ~FO_SINGLE; + fobp->flags |= callflags & FO_TRUNC; + + /* once a file/directory, always a file/directory; such a change + is a bug */ + if ((callflags ^ fobp->flags) & FO_DIRECTORY) + { + DEBUGF("%s - FO_DIRECTORY flag does not match: %p %u\n", + __func__, stream, callflags); + } } if ((callflags & FD_WRITE) && ++fobp->writers == 1) @@ -315,14 +257,12 @@ void fileobj_fileop_close(struct filestr_base *stream) if (foflags & FO_SINGLE) { /* last stream for file; close everything */ + fileobj_unbind_file(&fobp->bind); + if (fobp->writers) file_cache_free(&fobp->cache); - /* binding must stay valid if something is mounted to here */ - if (foflags & FO_MOUNTTARGET) - fobp->flags = foflags & (FDO_BUSY|FO_DIRECTORY|FO_MOUNTTARGET); - else - release_binding(fobp); + binding_add_to_free_list(fobp); } else { diff --git a/firmware/common/pathfuncs.c b/firmware/common/pathfuncs.c index 078c0b6938..0935a9a6e3 100644 --- a/firmware/common/pathfuncs.c +++ b/firmware/common/pathfuncs.c @@ -105,7 +105,7 @@ static const unsigned char storage_dec_indexes[STORAGE_NUM_TYPES+1] = */ int path_strip_volume(const char *name, const char **nameptr, bool greedy) { - int volume = ROOT_VOLUME; + int volume = 0; const char *t = name; int c, v = 0; @@ -114,16 +114,9 @@ int path_strip_volume(const char *name, const char **nameptr, bool greedy) * digits within the brackets is parsed as the volume number and of * those, only the last ones VOL_MUM_MAX allows. */ - t = GOBBLE_PATH_SEPCH(t); /* skip all leading slashes */ - if (t == name) - { - volume = -1; /* relative path; don't know */ - goto psv_out; - } - - c = *t; + c = *(t = GOBBLE_PATH_SEPCH(t)); /* skip all leading slashes */ if (c != VOL_START_TOK) /* missing start token? no volume */ - goto psv_out; + goto volume0; do { @@ -134,7 +127,7 @@ int path_strip_volume(const char *name, const char **nameptr, bool greedy) break; case '\0': case PATH_SEPCH: /* no closing bracket; no volume */ - goto psv_out; + goto volume0; default: /* something else; reset volume */ v = 0; } @@ -144,7 +137,7 @@ int path_strip_volume(const char *name, const char **nameptr, bool greedy) if (!(c = *++t)) /* no more path and no '/' is ok */ ; else if (c != PATH_SEPCH) /* more path and no separator after end */ - goto psv_out; + goto volume0; else if (greedy) t = GOBBLE_PATH_SEPCH(++t); /* strip remaining separators */ @@ -153,7 +146,7 @@ int path_strip_volume(const char *name, const char **nameptr, bool greedy) volume = v; name = t; -psv_out: +volume0: if (nameptr) *nameptr = name; return volume; @@ -164,14 +157,10 @@ psv_out: */ int get_volume_name(int volume, char *buffer) { - if (volume < 0 || volume == ROOT_VOLUME) + if (volume < 0) { - char *t = buffer; - if (volume == ROOT_VOLUME) - *t++ = PATH_ROOTCHR; - - *t = '\0'; - return t - buffer; + *buffer = '\0'; + return 0; } volume %= VOL_NUM_MAX; /* as path parser would have it */ @@ -184,20 +173,6 @@ int get_volume_name(int volume, char *buffer) return snprintf(buffer, VOL_MAX_LEN + 1, "%c%s%d%c", VOL_START_TOK, voldec, volume, VOL_END_TOK); } - -/* Returns volume name formatted with the root. Assumes buffer size is at - * least {VOL_MAX_LEN}+2 */ -int make_volume_root(int volume, char *buffer) -{ - char *t = buffer; - - if (volume >= 0 && volume != ROOT_VOLUME) - *t++ = PATH_ROOTCHR; - - t += get_volume_name(volume, t); - - return t - buffer; -} #endif /* HAVE_MULTIVOLUME */ /* Just like path_strip_volume() but strips a leading drive specifier and diff --git a/firmware/common/rb_namespace.c b/firmware/common/rb_namespace.c deleted file mode 100644 index 04f92e97af..0000000000 --- a/firmware/common/rb_namespace.c +++ /dev/null @@ -1,289 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2017 by Michael Sevakis - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "config.h" -#include -#include "fileobj_mgr.h" -#include "rb_namespace.h" - -#define ROOT_CONTENTS_INDEX (NUM_VOLUMES) -#define NUM_ROOT_ITEMS (NUM_VOLUMES+1) - -static uint8_t root_entry_flags[NUM_VOLUMES+1]; -static struct file_base_binding *root_bindp; - -static inline unsigned int get_root_item_state(int item) -{ - return root_entry_flags[item]; -} - -static inline void set_root_item_state(int item, unsigned int state) -{ - root_entry_flags[item] = state; -} - -static void get_mount_point_entry(IF_MV(int volume,) struct dirent *entry) -{ -#ifdef HAVE_MULTIVOLUME - get_volume_name(volume, entry->d_name); -#else /* */ - strcpy(entry->d_name, PATH_ROOTSTR); -#endif /* HAVE_MULTIVOLUME */ - - /* is dirinfo_native */ - entry->info.attr = ATTR_MOUNT_POINT; - entry->info.size = 0; - entry->info.wrtdate = 0; - entry->info.wrttime = 0; -} - -/* unmount the directory that enumerates into the root namespace */ -static void unmount_item(int item) -{ - unsigned int state = get_root_item_state(item); - if (!state) - return; - - if (state & NSITEM_CONTENTS) - { - fileobj_unmount(root_bindp); - root_bindp = NULL; - } - - set_root_item_state(item, 0); -} - -/* mount the directory that enumerates into the root namespace */ -int root_mount_path(const char *path, unsigned int flags) -{ -#ifdef HAVE_MULTIVOLUME - int volume = path_strip_volume(path, NULL, false); - if (volume == ROOT_VOLUME) - return -EINVAL; - - if (!CHECK_VOL(volume)) - return -ENOENT; -#else - if (!path_is_absolute(path)) - return -ENOENT; -#endif /* HAVE_MULTIVOLUME */ - - bool contents = flags & NSITEM_CONTENTS; - int item = contents ? ROOT_CONTENTS_INDEX : IF_MV_VOL(volume); - unsigned int state = get_root_item_state(item); - - if (state) - return -EBUSY; - - if (contents) - { - /* cache information about the target */ - struct filestr_base stream; - struct path_component_info compinfo; - - int e = errno; - int rc = open_stream_internal(path, FF_DIR | FF_PROBE | FF_INFO | - FF_DEVPATH, &stream, &compinfo); - if (rc <= 0) - { - rc = rc ? -errno : -ENOENT; - errno = e; - return rc; - } - - if (!fileobj_mount(&compinfo.info, FO_DIRECTORY, &root_bindp)) - return -EBUSY; - } - - state = NSITEM_MOUNTED | (flags & (NSITEM_HIDDEN|NSITEM_CONTENTS)); - set_root_item_state(item, state); - - return 0; -} - -/* inform root that an entire volume is being unmounted */ -void root_unmount_volume(IF_MV_NONVOID(int volume)) -{ - FOR_EACH_VOLUME(volume, item) - { - #ifdef HAVE_MULTIVOLUME - uint32_t state = get_root_item_state(item); - if (state && (volume < 0 || item == volume)) - #endif /* HAVE_MULTIVOLUME */ - unmount_item(item); - } - - /* if the volume unmounted contains the root directory contents then - the contents must also be unmounted */ -#ifdef HAVE_MULTIVOLUME - uint32_t state = get_root_item_state(ROOT_CONTENTS_INDEX); - if (state && (volume < 0 || BASEINFO_VOL(&root_bindp->info) == volume)) -#endif - unmount_item(ROOT_CONTENTS_INDEX); -} - -/* parse the root part of a path */ -int ns_parse_root(const char *path, const char **pathp, uint16_t *lenp) -{ - int volume = ROOT_VOLUME; - -#ifdef HAVE_MULTIVOLUME - /* this seamlessly integrates secondary filesystems into the - root namespace (e.g. "/<0>/../../<1>/../foo/." :<=> "/foo") */ - const char *p; - volume = path_strip_volume(path, &p, false); - if (volume != ROOT_VOLUME && !CHECK_VOL(volume)) - return -ENOENT; -#endif /* HAVE_MULTIVOLUME */ - - /* set name to start at last leading separator; name of root will - * be returned as "/", volume specifiers as "/" */ - *pathp = GOBBLE_PATH_SEPCH(path) - 1; - *lenp = IF_MV( volume < NUM_VOLUMES ? p - *pathp : ) 1; - -#ifdef HAVE_MULTIVOLUME - if (*lenp > MAX_COMPNAME+1) - return -ENAMETOOLONG; -#endif - - return volume; -} - -/* open one of the items in the root */ -int ns_open_root(IF_MV(int volume,) unsigned int *callflagsp, - struct file_base_info *infop, uint16_t *attrp) -{ - unsigned int callflags = *callflagsp; - bool devpath = !!(callflags & FF_DEVPATH); -#ifdef HAVE_MULTIVOLUME - bool sysroot = volume == ROOT_VOLUME; - if (devpath && sysroot) - return -ENOENT; /* devpath needs volume spec */ -#else - bool sysroot = !devpath; /* always sysroot unless devpath */ -#endif - - int item = sysroot ? ROOT_CONTENTS_INDEX : IF_MV_VOL(volume); - unsigned int state = get_root_item_state(item); - - if (sysroot) - { - *attrp = ATTR_SYSTEM_ROOT; - - if (state) - *infop = root_bindp->info; - else - *callflagsp = callflags | FF_NOFS; /* contents not mounted */ - } - else - { - *attrp = ATTR_MOUNT_POINT; - - if (!devpath && !state) - return -ENOENT; /* regular open requires having been mounted */ - - if (fat_open_rootdir(IF_MV(volume,) &infop->fatfile) < 0) - return -ENOENT; /* not mounted */ - - get_rootinfo_internal(infop); - } - - return 0; -} - -/* read root directory entries */ -int root_readdir_dirent(struct filestr_base *stream, - struct ns_scan_info *scanp, struct dirent *entry) -{ - int rc = 0; - - int item = scanp->item; - - /* skip any not-mounted or hidden items */ - unsigned int state; - while (1) - { - if (item >= NUM_ROOT_ITEMS) - goto file_eod; - - state = get_root_item_state(item); - if ((state & (NSITEM_MOUNTED|NSITEM_HIDDEN)) == NSITEM_MOUNTED) - break; - - item++; - } - - if (item == ROOT_CONTENTS_INDEX) - { - rc = readdir_dirent(stream, &scanp->scan, entry); - if (rc < 0) - FILE_ERROR(ERRNO, rc * 10 - 1); - - if (rc == 0) - item++; - } - else - { - get_mount_point_entry(IF_MV(item,) entry); - item++; - rc = 1; - } - - scanp->item = item; - -file_eod: - if (rc == 0) - empty_dirent(entry); - -file_error: - return rc; -} - -/* opens a stream to enumerate items in a namespace container */ -int ns_open_stream(const char *path, unsigned int callflags, - struct filestr_base *stream, struct ns_scan_info *scanp) -{ - /* stream still needs synchronization even if we don't have a stream */ - static struct mutex no_contents_mtx SHAREDBSS_ATTR; - - int rc = open_stream_internal(path, callflags, stream, NULL); - if (rc < 0) - FILE_ERROR(ERRNO, rc * 10 - 1); - - scanp->item = rc > 1 ? 0 : -1; - - if (stream->flags & FDO_BUSY) - { - /* root contents are mounted */ - fat_rewind(&stream->fatstr); - } - else - { - /* root contents not mounted */ - mutex_init(&no_contents_mtx); - stream->mtx = &no_contents_mtx; - } - - ns_dirscan_rewind(scanp); - - rc = 0; -file_error: - return rc; -} diff --git a/firmware/export/mv.h b/firmware/export/mv.h index 5aa0ff8b4d..ec7b2efdbd 100644 --- a/firmware/export/mv.h +++ b/firmware/export/mv.h @@ -84,10 +84,6 @@ #define VOL_MAX_LEN (1 + VOL_DEC_MAX_LEN + 2 + 1) #define VOL_NUM_MAX 100 -#ifndef ROOT_VOLUME -#define ROOT_VOLUME INT_MAX -#endif - #else /* empty definitions if no multi-volume */ #define IF_MV(x...) #define IF_MV_NONVOID(x...) void diff --git a/firmware/export/pathfuncs.h b/firmware/export/pathfuncs.h index 8858d85d24..92539c54c1 100644 --- a/firmware/export/pathfuncs.h +++ b/firmware/export/pathfuncs.h @@ -30,15 +30,10 @@ /* useful char constants that could be reconfigured if desired */ #define PATH_SEPCH '/' #define PATH_SEPSTR "/" -#define PATH_ROOTCHR '/' #define PATH_ROOTSTR "/" #define PATH_BADSEPCH '\\' #define PATH_DRVSEPCH ':' -#ifndef ROOT_VOLUME -#define ROOT_VOLUME INT_MAX -#endif - /* a nicer way to check for "." and ".." than two strcmp() calls */ static inline bool is_dotdir_name(const char *name) { @@ -80,7 +75,6 @@ static inline bool name_is_dot_dot(const char *name) #ifdef HAVE_MULTIVOLUME int path_strip_volume(const char *name, const char **nameptr, bool greedy); int get_volume_name(int volume, char *name); -int make_volume_root(int volume, char *dst); #endif int path_strip_drive(const char *name, const char **nameptr, bool greedy); diff --git a/firmware/export/rbpaths.h b/firmware/export/rbpaths.h index 458a070f92..de591f0ec1 100644 --- a/firmware/export/rbpaths.h +++ b/firmware/export/rbpaths.h @@ -64,9 +64,6 @@ #define PLUGIN_DIR ROCKBOX_DIR "/rocks" #define CODECS_DIR ROCKBOX_DIR "/codecs" -#define RB_ROOT_VOL_HIDDEN(v) (IF_MV_VOL(v) == 0) -#define RB_ROOT_CONTENTS_DIR "/" IF_MV("<0>") - #else /* APPLICATION */ #define HOME_DIR "" /* replaced at runtime */ diff --git a/firmware/include/dircache_redirect.h b/firmware/include/dircache_redirect.h index e8cf8dc8f5..9fae16b551 100644 --- a/firmware/include/dircache_redirect.h +++ b/firmware/include/dircache_redirect.h @@ -20,16 +20,7 @@ ****************************************************************************/ #ifndef _DIRCACHE_REDIRECT_H_ -#include "rbpaths.h" -#include "pathfuncs.h" #include "dir.h" -#include "dircache.h" - -#if defined(HAVE_MULTIBOOT) && !defined(SIMULATOR) -#include "rb-loader.h" -#include "bootdata.h" -#include "crc32.h" -#endif /*** ** Internal redirects that depend upon whether or not dircache is made @@ -132,56 +123,10 @@ static inline void fileop_onsync_internal(struct filestr_base *stream) static inline void volume_onmount_internal(IF_MV_NONVOID(int volume)) { -#ifdef HAVE_MULTIVOLUME - char path[VOL_MAX_LEN+2]; - make_volume_root(volume, path); -#else - const char *path = PATH_ROOTSTR; -#endif - -#if defined(HAVE_MULTIBOOT) && !defined(SIMULATOR) - static char rtpath[VOL_MAX_LEN+2] = RB_ROOT_CONTENTS_DIR; - static bool redirected = false; - int boot_volume = 0; - unsigned int crc = 0; - - crc = crc_32(boot_data.payload, boot_data.length, 0xffffffff); - if (crc == boot_data.crc) - { - root_mount_path(path, 0); /*root could be different folder don't hide*/ - boot_volume = boot_data.boot_volume; /* boot volume contained in uint8_t payload */ - //root_mount_path(path, volume == boot_volume ? NSITEM_HIDDEN : 0); - if (!redirected && volume == boot_volume) - { - if (get_redirect_dir(rtpath, sizeof(rtpath), volume, "", "") < 0) - { /* Error occurred, card removed? Set root to default */ - root_mount_path(RB_ROOT_CONTENTS_DIR, NSITEM_CONTENTS); - } - else - redirected = true; - } - if (redirected && volume == boot_volume) - root_mount_path(rtpath, NSITEM_CONTENTS); - } /*CRC OK*/ - else - { - root_mount_path(path, RB_ROOT_VOL_HIDDEN(volume) ? NSITEM_HIDDEN : 0); - if (volume == path_strip_volume(RB_ROOT_CONTENTS_DIR, NULL, false)) - root_mount_path(RB_ROOT_CONTENTS_DIR, NSITEM_CONTENTS); - } -#else - - root_mount_path(path, RB_ROOT_VOL_HIDDEN(volume) ? NSITEM_HIDDEN : 0); -#ifdef HAVE_MULTIVOLUME - if (volume == path_strip_volume(RB_ROOT_CONTENTS_DIR, NULL, false)) -#endif - root_mount_path(RB_ROOT_CONTENTS_DIR, NSITEM_CONTENTS); - -#endif /* HAVE_MULTIBOOT */ - #ifdef HAVE_DIRCACHE dircache_mount(); #endif + IF_MV( (void)volume; ) } static inline void volume_onunmount_internal(IF_MV_NONVOID(int volume)) @@ -190,7 +135,6 @@ static inline void volume_onunmount_internal(IF_MV_NONVOID(int volume)) /* First, to avoid update of something about to be destroyed anyway */ dircache_unmount(IF_MV(volume)); #endif - root_unmount_volume(IF_MV(volume)); fileobj_mgr_unmount(IF_MV(volume)); } diff --git a/firmware/include/file_internal.h b/firmware/include/file_internal.h index f4bd8bb8c2..d62b5a8541 100644 --- a/firmware/include/file_internal.h +++ b/firmware/include/file_internal.h @@ -72,18 +72,16 @@ enum fildes_and_obj_flags /* used in descriptor and common */ FDO_BUSY = 0x0001, /* descriptor/object is in use */ /* only used in individual stream descriptor */ - FD_VALID = 0x0002, /* descriptor is valid but not registered */ - FD_WRITE = 0x0004, /* descriptor has write mode */ - FD_WRONLY = 0x0008, /* descriptor is write mode only */ - FD_APPEND = 0x0010, /* descriptor is append mode */ + FD_WRITE = 0x0002, /* descriptor has write mode */ + FD_WRONLY = 0x0004, /* descriptor is write mode only */ + FD_APPEND = 0x0008, /* descriptor is append mode */ FD_NONEXIST = 0x8000, /* closed but not freed (uncombined) */ /* only used as common flags */ - FO_DIRECTORY = 0x0020, /* fileobj is a directory */ - FO_TRUNC = 0x0040, /* fileobj is opened to be truncated */ - FO_REMOVED = 0x0080, /* fileobj was deleted while open */ - FO_SINGLE = 0x0100, /* fileobj has only one stream open */ - FO_MOUNTTARGET = 0x0200, /* fileobj kept open as a mount target */ - FDO_MASK = 0x03ff, + FO_DIRECTORY = 0x0010, /* fileobj is a directory */ + FO_TRUNC = 0x0020, /* fileobj is opened to be truncated */ + FO_REMOVED = 0x0040, /* fileobj was deleted while open */ + FO_SINGLE = 0x0080, /* fileobj has only one stream open */ + FDO_MASK = 0x00ff, FDO_CHG_MASK = FO_TRUNC, /* fileobj permitted external change */ /* bitflags that instruct various 'open' functions how to behave; * saved in stream flags (only) but not used by manager */ @@ -97,9 +95,7 @@ enum fildes_and_obj_flags FF_CACHEONLY = 0x00200000, /* succeed only if in dircache */ FF_INFO = 0x00400000, /* return info on self */ FF_PARENTINFO = 0x00800000, /* return info on parent */ - FF_DEVPATH = 0x01000000, /* path is a device path, not root-based */ - FF_NOFS = 0x02000000, /* no filesystem mounted here */ - FF_MASK = 0x03ff0000, + FF_MASK = 0x00ff0000, }; /** Common data structures used throughout **/ diff --git a/firmware/include/fileobj_mgr.h b/firmware/include/fileobj_mgr.h index 0db3520d34..627d2df341 100644 --- a/firmware/include/fileobj_mgr.h +++ b/firmware/include/fileobj_mgr.h @@ -29,11 +29,6 @@ void file_binding_remove(struct file_base_binding *bindp); void file_binding_remove_next(struct file_base_binding *prevp, struct file_base_binding *bindp); -bool fileobj_mount(const struct file_base_info *srcinfop, - unsigned int callflags, - struct file_base_binding **bindpp); -void fileobj_unmount(struct file_base_binding *bindp); - void fileobj_fileop_open(struct filestr_base *stream, const struct file_base_info *srcinfop, unsigned int callflags); diff --git a/firmware/include/fs_defines.h b/firmware/include/fs_defines.h index aee6daff6a..538c4b36cd 100644 --- a/firmware/include/fs_defines.h +++ b/firmware/include/fs_defines.h @@ -51,19 +51,12 @@ /* internal functions open streams as well; make sure they don't fail if all user descs are busy; this needs to be at least the greatest quantity needed at once by all internal functions */ -/* internal functions open streams as well; make sure they don't fail if all - user descs are busy; this needs to be at least the greatest quantity needed - at once by all internal functions */ -#define MOUNT_AUX_FILEOBJS 1 - #ifdef HAVE_DIRCACHE -#define DIRCACHE_AUX_FILEOBJS 1 +#define AUX_FILEOBJS 3 #else -#define DIRCACHE_AUX_FILEOBJS 0 +#define AUX_FILEOBJS 2 #endif -#define AUX_FILEOBJS (2+DIRCACHE_AUX_FILEOBJS+MOUNT_AUX_FILEOBJS) - /* number of components statically allocated to handle the vast majority of path depths; should maybe be tuned for >= 90th percentile but for now, imma just guessing based on something like: diff --git a/firmware/include/rb_namespace.h b/firmware/include/rb_namespace.h deleted file mode 100644 index 4d7a125c7b..0000000000 --- a/firmware/include/rb_namespace.h +++ /dev/null @@ -1,79 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2017 by Michael Sevakis - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef RB_NAMESPACE_H -#define RB_NAMESPACE_H - -#include "file_internal.h" - -enum ns_item_flags -{ - NSITEM_MOUNTED = 0x01, /* item is mounted */ - NSITEM_HIDDEN = 0x02, /* item is not enumerated */ - NSITEM_CONTENTS = 0x04, /* contents enumerate */ -}; - -struct ns_scan_info -{ - struct dirscan_info scan; /* dirscan info - first! */ - int item; /* current item in parent */ -}; - -/* root functions */ -int root_mount_path(const char *path, unsigned int flags); -void root_unmount_volume(IF_MV_NONVOID(int volume)); -int root_readdir_dirent(struct filestr_base *stream, - struct ns_scan_info *scanp, - struct dirent *entry); - -/* namespace functions */ -int ns_parse_root(const char *path, const char **pathp, uint16_t *lenp); -int ns_open_root(IF_MV(int volume,) unsigned int *callflagsp, - struct file_base_info *infop, uint16_t *attrp); -int ns_open_stream(const char *path, unsigned int callflags, - struct filestr_base *stream, struct ns_scan_info *scanp); - -/* closes the namespace stream */ -static inline int ns_close_stream(struct filestr_base *stream) -{ - return close_stream_internal(stream); -} - -#include "dircache_redirect.h" - -static inline void ns_dirscan_rewind(struct ns_scan_info *scanp) -{ - rewinddir_dirent(&scanp->scan); - if (scanp->item != -1) - scanp->item = 0; -} - -static inline int ns_readdir_dirent(struct filestr_base *stream, - struct ns_scan_info *scanp, - struct dirent *entry) - -{ - if (scanp->item == -1) - return readdir_dirent(stream, &scanp->scan, entry); - else - return root_readdir_dirent(stream, scanp, entry); -} - -#endif /* RB_NAMESPACE_H */ diff --git a/uisimulator/common/filesystem-sim.c b/uisimulator/common/filesystem-sim.c index 45483b7172..766beb3fda 100644 --- a/uisimulator/common/filesystem-sim.c +++ b/uisimulator/common/filesystem-sim.c @@ -309,8 +309,6 @@ int sim_get_os_path(char *buffer, const char *path, size_t bufsize) const char *next; volume = path_strip_volume(p, &next, true); - if (volume == ROOT_VOLUME) - volume = 0; /* FIXME: root no longer implies volume 0 */ if (next > p) { -- cgit