summaryrefslogtreecommitdiffstats
path: root/firmware/common/file_internal.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/common/file_internal.c')
-rw-r--r--firmware/common/file_internal.c120
1 files changed, 44 insertions, 76 deletions
diff --git a/firmware/common/file_internal.c b/firmware/common/file_internal.c
index fe18f90056..a73d9beaa2 100644
--- a/firmware/common/file_internal.c
+++ b/firmware/common/file_internal.c
@@ -26,12 +26,18 @@
#include "pathfuncs.h"
#include "disk_cache.h"
#include "fileobj_mgr.h"
-#include "dir.h"
-#include "dircache_redirect.h"
-#include "dircache.h"
+#include "rb_namespace.h"
#include "string-extra.h"
#include "rbunicode.h"
+/* Define LOGF_ENABLE to enable logf output in this file */
+//#define LOGF_ENABLE
+#ifdef LOGF_ENABLE
+#include "logf.h"
+#undef DEBUGF
+#define DEBUGF logf
+#endif
+
/** Internal common filesystem service functions **/
/* for internal functions' scanning use to save quite a bit of stack space -
@@ -75,21 +81,23 @@ void file_cache_alloc(struct filestr_cache *cachep)
/* free resources attached to the cache */
void file_cache_free(struct filestr_cache *cachep)
{
- if (cachep && cachep->buffer)
+ if (cachep)
{
- dc_release_buffer(cachep->buffer);
- cachep->buffer = NULL;
+ if(cachep->buffer)
+ {
+ dc_release_buffer(cachep->buffer);
+ cachep->buffer = NULL;
+ }
+ file_cache_reset(cachep);
}
-
- file_cache_reset(cachep);
}
/** Stream base APIs **/
-static inline void filestr_clear(struct filestr_base *stream)
+static inline void filestr_clear(struct filestr_base *stream, unsigned int flags)
{
- stream->flags = 0;
+ stream->flags = flags;
stream->bindp = NULL;
#if 0
stream->mtx = NULL;
@@ -153,7 +161,7 @@ void filestr_discard_cache(struct filestr_base *stream)
/* Initialize the base descriptor */
void filestr_base_init(struct filestr_base *stream)
{
- filestr_clear(stream);
+ filestr_clear(stream, FD_VALID);
file_cache_init(&stream->cache);
stream->cachep = &stream->cache;
}
@@ -161,7 +169,7 @@ void filestr_base_init(struct filestr_base *stream)
/* free base descriptor resources */
void filestr_base_destroy(struct filestr_base *stream)
{
- filestr_clear(stream);
+ filestr_clear(stream, 0);
filestr_free_cache(stream);
}
@@ -219,6 +227,7 @@ void iso_decode_d_name(char *d_name)
return;
char shortname[13];
+ /* this only gets called in the case of DOS (8.3) filenames */
size_t len = strlcpy(shortname, d_name, sizeof (shortname));
/* This MUST be the default codepage thus not something that could be
loaded on call */
@@ -227,7 +236,7 @@ void iso_decode_d_name(char *d_name)
#ifdef HAVE_DIRCACHE
/* nullify all the fields of the struct dirent */
-void empty_dirent(struct dirent *entry)
+void empty_dirent(struct DIRENT *entry)
{
entry->d_name[0] = '\0';
entry->info.attr = 0;
@@ -249,7 +258,7 @@ void fill_dirinfo_native(struct dirinfo_native *dinp)
int uncached_readdir_dirent(struct filestr_base *stream,
struct dirscan_info *scanp,
- struct dirent *entry)
+ struct DIRENT *entry)
{
struct fat_direntry fatent;
int rc = fat_readdir(&stream->fatstr, &scanp->fatscan,
@@ -293,7 +302,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/volume root */
+#define WALK_RC_FOUND_ROOT 2 /* found and opened sys root */
#define WALK_RC_CONT_AT_ROOT 3 /* continue at root level */
/* return another struct pathwalk_component from the pool, or NULL if the
@@ -397,10 +406,9 @@ 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))
+ if (!(callflags & (FF_PROBE|FF_NOFS)))
fileop_onopen_internal(stream, &compp->info, callflags);
-
- return compp->nextp ? WALK_RC_FOUND : WALK_RC_FOUND_ROOT;
+ return compp->attr == ATTR_SYSTEM_ROOT ? WALK_RC_FOUND_ROOT : WALK_RC_FOUND;
}
/* check the component against the prefix test info */
@@ -507,6 +515,10 @@ 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] == '.')
{
@@ -575,7 +587,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;
@@ -585,80 +597,36 @@ 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)
{
- 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;
- }
-
- 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 = ns_parse_root(walk.path, &rootp->name, &rootp->length);
+ if (rc < 0)
+ break;
- rc = fat_open_rootdir(IF_MV(volume,) &rootp->info.fatfile);
+ rc = ns_open_root(IF_MV(rc,) &walk.callflags, &rootp->info, &rootp->attr);
if (rc < 0)
- {
- /* not mounted */
- DEBUGF("No such device or address: %d\n", IF_MV_VOL(volume));
- rc = -ENXIO;
break;
- }
- get_rootinfo_internal(&rootp->info);
+ walk.path = rootp->name + rootp->length;
+
rc = walk_path(&walk, rootp, stream);
if (rc != WALK_RC_CONT_AT_ROOT)
break;
}
- switch (rc)
+ if (rc >= 0)
{
- 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 (callflags & FF_PROBE)
+ if (walk.callflags & FF_PROBE)
filestr_base_destroy(stream);
-
- break;
-
- default: /* utter, abject failure :`( */
+ }
+ else
+ {
+ /* utter, abject failure :`( */
DEBUGF("Open failed: rc=%d, errno=%d\n", rc, errno);
filestr_base_destroy(stream);
- FILE_ERROR(-rc, -3);
+ FILE_ERROR(-rc, -1);
}
file_error: