summaryrefslogtreecommitdiff
path: root/firmware/common/file_internal.c
diff options
context:
space:
mode:
authorWilliam Wilgus <wilgus.william@gmail.com>2022-03-03 07:37:03 -0500
committerWilliam Wilgus <wilgus.william@gmail.com>2022-03-03 18:58:07 -0500
commit9daacabd658508d2607a64b288c9bce7a635fb15 (patch)
treece96538ea82a4176f00f8eb9531711db7dea5750 /firmware/common/file_internal.c
parentf88ea12bacf381ad4f39ba2328c806e772c0dda8 (diff)
downloadrockbox-9daacabd658508d2607a64b288c9bce7a635fb15.tar.gz
rockbox-9daacabd658508d2607a64b288c9bce7a635fb15.zip
[RESTORED!] Allow mounting of any directory as the root directory.
Provide definitions for the macros: * RB_ROOT_VOL_HIDDEN(v) to exclude certain items from the root. * RB_ROOT_CONTENTS to return a string with the name of the directory to mount in the root. Defaults are in export/rbpaths.h It's a bit much for those that don't need the full functionality. Some conditional define can cut it back a lot to cut out things only needed if alternate root mounts are required. I'm just not bothering yet. The basic concept would be applied to all targets to keep file code from forking too much. Change-Id: I3b5a14c530ff4b10d97f67636237d96875eb8969 Author: Michael Sevakis
Diffstat (limited to 'firmware/common/file_internal.c')
-rw-r--r--firmware/common/file_internal.c100
1 files changed, 28 insertions, 72 deletions
diff --git a/firmware/common/file_internal.c b/firmware/common/file_internal.c
index b92c4ea115..14db247347 100644
--- a/firmware/common/file_internal.c
+++ b/firmware/common/file_internal.c
@@ -26,9 +26,7 @@
26#include "pathfuncs.h" 26#include "pathfuncs.h"
27#include "disk_cache.h" 27#include "disk_cache.h"
28#include "fileobj_mgr.h" 28#include "fileobj_mgr.h"
29#include "dir.h" 29#include "rb_namespace.h"
30#include "dircache_redirect.h"
31#include "dircache.h"
32#include "string-extra.h" 30#include "string-extra.h"
33#include "rbunicode.h" 31#include "rbunicode.h"
34 32
@@ -89,9 +87,9 @@ void file_cache_free(struct filestr_cache *cachep)
89 87
90/** Stream base APIs **/ 88/** Stream base APIs **/
91 89
92static inline void filestr_clear(struct filestr_base *stream) 90static inline void filestr_clear(struct filestr_base *stream, unsigned int flags)
93{ 91{
94 stream->flags = 0; 92 stream->flags = flags;
95 stream->bindp = NULL; 93 stream->bindp = NULL;
96#if 0 94#if 0
97 stream->mtx = NULL; 95 stream->mtx = NULL;
@@ -155,7 +153,7 @@ void filestr_discard_cache(struct filestr_base *stream)
155/* Initialize the base descriptor */ 153/* Initialize the base descriptor */
156void filestr_base_init(struct filestr_base *stream) 154void filestr_base_init(struct filestr_base *stream)
157{ 155{
158 filestr_clear(stream); 156 filestr_clear(stream, FD_VALID);
159 file_cache_init(&stream->cache); 157 file_cache_init(&stream->cache);
160 stream->cachep = &stream->cache; 158 stream->cachep = &stream->cache;
161} 159}
@@ -163,7 +161,7 @@ void filestr_base_init(struct filestr_base *stream)
163/* free base descriptor resources */ 161/* free base descriptor resources */
164void filestr_base_destroy(struct filestr_base *stream) 162void filestr_base_destroy(struct filestr_base *stream)
165{ 163{
166 filestr_clear(stream); 164 filestr_clear(stream, 0);
167 filestr_free_cache(stream); 165 filestr_free_cache(stream);
168} 166}
169 167
@@ -229,7 +227,7 @@ void iso_decode_d_name(char *d_name)
229 227
230#ifdef HAVE_DIRCACHE 228#ifdef HAVE_DIRCACHE
231/* nullify all the fields of the struct dirent */ 229/* nullify all the fields of the struct dirent */
232void empty_dirent(struct dirent *entry) 230void empty_dirent(struct DIRENT *entry)
233{ 231{
234 entry->d_name[0] = '\0'; 232 entry->d_name[0] = '\0';
235 entry->info.attr = 0; 233 entry->info.attr = 0;
@@ -251,7 +249,7 @@ void fill_dirinfo_native(struct dirinfo_native *dinp)
251 249
252int uncached_readdir_dirent(struct filestr_base *stream, 250int uncached_readdir_dirent(struct filestr_base *stream,
253 struct dirscan_info *scanp, 251 struct dirscan_info *scanp,
254 struct dirent *entry) 252 struct DIRENT *entry)
255{ 253{
256 struct fat_direntry fatent; 254 struct fat_direntry fatent;
257 int rc = fat_readdir(&stream->fatstr, &scanp->fatscan, 255 int rc = fat_readdir(&stream->fatstr, &scanp->fatscan,
@@ -295,7 +293,7 @@ struct pathwalk_component
295 293
296#define WALK_RC_NOT_FOUND 0 /* successfully not found (aid for file creation) */ 294#define WALK_RC_NOT_FOUND 0 /* successfully not found (aid for file creation) */
297#define WALK_RC_FOUND 1 /* found and opened */ 295#define WALK_RC_FOUND 1 /* found and opened */
298#define WALK_RC_FOUND_ROOT 2 /* found and opened sys/volume root */ 296#define WALK_RC_FOUND_ROOT 2 /* found and opened sys root */
299#define WALK_RC_CONT_AT_ROOT 3 /* continue at root level */ 297#define WALK_RC_CONT_AT_ROOT 3 /* continue at root level */
300 298
301/* return another struct pathwalk_component from the pool, or NULL if the 299/* return another struct pathwalk_component from the pool, or NULL if the
@@ -399,10 +397,9 @@ static int walk_open_info(struct pathwalk *walkp,
399 397
400 /* make open official if not simply probing for presence - must do it here 398 /* make open official if not simply probing for presence - must do it here
401 or compp->info on stack will get destroyed before it was copied */ 399 or compp->info on stack will get destroyed before it was copied */
402 if (!(callflags & FF_PROBE)) 400 if (!(callflags & (FF_PROBE|FF_NOFS)))
403 fileop_onopen_internal(stream, &compp->info, callflags); 401 fileop_onopen_internal(stream, &compp->info, callflags);
404 402 return compp->attr == ATTR_SYSTEM_ROOT ? WALK_RC_FOUND_ROOT : WALK_RC_FOUND;
405 return compp->nextp ? WALK_RC_FOUND : WALK_RC_FOUND_ROOT;
406} 403}
407 404
408/* check the component against the prefix test info */ 405/* check the component against the prefix test info */
@@ -509,6 +506,10 @@ walk_path(struct pathwalk *walkp, struct pathwalk_component *compp,
509 if (len > MAX_COMPNAME) 506 if (len > MAX_COMPNAME)
510 return -ENAMETOOLONG; 507 return -ENAMETOOLONG;
511 508
509 /* no filesystem is mounted here */
510 if (walkp->callflags & FF_NOFS)
511 return -ENOENT;
512
512 /* check for "." and ".." */ 513 /* check for "." and ".." */
513 if (name[0] == '.') 514 if (name[0] == '.')
514 { 515 {
@@ -577,7 +578,7 @@ int open_stream_internal(const char *path, unsigned int callflags,
577 callflags &= ~(FF_INFO | FF_PARENTINFO | FF_CHECKPREFIX); 578 callflags &= ~(FF_INFO | FF_PARENTINFO | FF_CHECKPREFIX);
578 579
579 /* This lets it be passed quietly to directory scanning */ 580 /* This lets it be passed quietly to directory scanning */
580 stream->flags = callflags & FF_MASK; 581 stream->flags |= callflags & FF_MASK;
581 582
582 struct pathwalk walk; 583 struct pathwalk walk;
583 walk.path = path; 584 walk.path = path;
@@ -587,81 +588,36 @@ int open_stream_internal(const char *path, unsigned int callflags,
587 588
588 struct pathwalk_component *rootp = pathwalk_comp_alloc(NULL); 589 struct pathwalk_component *rootp = pathwalk_comp_alloc(NULL);
589 rootp->nextp = NULL; 590 rootp->nextp = NULL;
590 rootp->attr = ATTR_SYSTEM_ROOT;
591
592#ifdef HAVE_MULTIVOLUME
593 int volume = 0, rootrc = WALK_RC_FOUND;
594#endif /* HAVE_MULTIVOLUME */
595 591
596 while (1) 592 while (1)
597 { 593 {
598 const char *pathptr = walk.path; 594 rc = ns_parse_root(walk.path, &rootp->name, &rootp->length);
599 595 if (rc < 0)
600 #ifdef HAVE_MULTIVOLUME 596 break;
601 /* this seamlessly integrates secondary filesystems into the
602 root namespace (e.g. "/<0>/../../<1>/../foo/." :<=> "/foo") */
603 const char *p;
604 volume = path_strip_volume(pathptr, &p, false);
605 if (!CHECK_VOL(volume))
606 {
607 DEBUGF("No such device or address: %d\n", volume);
608 FILE_ERROR(ENXIO, -2);
609 }
610
611 if (p == pathptr)
612 {
613 /* the root of this subpath is the system root */
614 rootp->attr = ATTR_SYSTEM_ROOT;
615 rootrc = WALK_RC_FOUND_ROOT;
616 }
617 else
618 {
619 /* this subpath specifies a mount point */
620 rootp->attr = ATTR_MOUNT_POINT;
621 rootrc = WALK_RC_FOUND;
622 }
623
624 walk.path = p;
625 #endif /* HAVE_MULTIVOLUME */
626
627 /* set name to start at last leading separator; names of volume
628 specifiers will be returned as "/<fooN>" */
629 rootp->name = GOBBLE_PATH_SEPCH(pathptr) - 1;
630 rootp->length =
631 IF_MV( rootrc == WALK_RC_FOUND ? p - rootp->name : ) 1;
632 597
633 rc = fat_open_rootdir(IF_MV(volume,) &rootp->info.fatfile); 598 rc = ns_open_root(IF_MV(rc,) &walk.callflags, &rootp->info, &rootp->attr);
634 if (rc < 0) 599 if (rc < 0)
635 {
636 /* not mounted */
637 DEBUGF("No such device or address: %d\n", IF_MV_VOL(volume));
638 rc = -ENXIO;
639 break; 600 break;
640 }
641 601
642 get_rootinfo_internal(&rootp->info); 602 walk.path = rootp->name + rootp->length;
603
643 rc = walk_path(&walk, rootp, stream); 604 rc = walk_path(&walk, rootp, stream);
644 if (rc != WALK_RC_CONT_AT_ROOT) 605 if (rc != WALK_RC_CONT_AT_ROOT)
645 break; 606 break;
646 } 607 }
647 608
648 switch (rc) 609 if (rc >= 0)
649 { 610 {
650 case WALK_RC_FOUND_ROOT:
651 IF_MV( rc = rootrc; )
652 /* fallthrough */
653 case WALK_RC_NOT_FOUND:
654 case WALK_RC_FOUND:
655 /* FF_PROBE leaves nothing for caller to clean up */ 611 /* FF_PROBE leaves nothing for caller to clean up */
656 if (callflags & FF_PROBE) 612 if (walk.callflags & FF_PROBE)
657 filestr_base_destroy(stream); 613 filestr_base_destroy(stream);
658 614 }
659 break; 615 else
660 616 {
661 default: /* utter, abject failure :`( */ 617 /* utter, abject failure :`( */
662 DEBUGF("Open failed: rc=%d, errno=%d\n", rc, errno); 618 DEBUGF("Open failed: rc=%d, errno=%d\n", rc, errno);
663 filestr_base_destroy(stream); 619 filestr_base_destroy(stream);
664 FILE_ERROR(-rc, -3); 620 FILE_ERROR(-rc, -1);
665 } 621 }
666 622
667file_error: 623file_error: