summaryrefslogtreecommitdiffstats
path: root/firmware/common
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/common')
-rw-r--r--firmware/common/dir.c92
-rw-r--r--firmware/common/dircache.c9
-rw-r--r--firmware/common/disk.c4
-rw-r--r--firmware/common/file.c2
-rw-r--r--firmware/common/file_internal.c95
-rw-r--r--firmware/common/fileobj_mgr.c114
-rw-r--r--firmware/common/pathfuncs.c43
-rw-r--r--firmware/common/rb_namespace.c289
8 files changed, 195 insertions, 453 deletions
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 "/<fooN>" */
+ 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 <errno.h>
#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 <errno.h>
-#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 "/<fooN>" */
- *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;
-}