Revert root_redirect :(

This reverts commit 31fc46ded6.

Change-Id: Ia78618c0e8b25ca65f7c8ae0db1cb9c9b321bad9
This commit is contained in:
William Wilgus 2020-08-20 21:54:00 -04:00
parent bd744059cf
commit f850bbbbc4
19 changed files with 215 additions and 645 deletions

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -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,

View File

@ -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

View File

@ -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"
/**

View File

@ -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:

View File

@ -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
{

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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 */

View File

@ -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));
}

View File

@ -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 **/

View File

@ -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);

View File

@ -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:

View File

@ -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 */

View File

@ -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)
{