Revert root_redirect :(
This reverts commit 31fc46ded6
.
Change-Id: Ia78618c0e8b25ca65f7c8ae0db1cb9c9b321bad9
This commit is contained in:
parent
bd744059cf
commit
f850bbbbc4
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
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 = 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;
|
||||
}
|
||||
|
||||
rc = ns_open_root(IF_MV(rc,) &walk.callflags, &rootp->info, &rootp->attr);
|
||||
if (rc < 0)
|
||||
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:
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 "<HOME>" /* replaced at runtime */
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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 **/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 */
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue