summaryrefslogtreecommitdiff
path: root/firmware/common/file_internal.c
diff options
context:
space:
mode:
authorWilliam Wilgus <me.theuser@yahoo.com>2017-02-03 17:13:58 -0500
committerWilliam Wilgus <me.theuser@yahoo.com>2020-08-20 23:08:57 +0000
commit5ef28cccf92f5eada6d502fa4b0e16a13e94be5b (patch)
tree05f9d2f8bdf3c0cc54c5893159a7dcf07c7e3e55 /firmware/common/file_internal.c
parent31fc46ded69be7438cca2ba2c2b93c1f200165a6 (diff)
downloadrockbox-5ef28cccf92f5eada6d502fa4b0e16a13e94be5b.tar.gz
rockbox-5ef28cccf92f5eada6d502fa4b0e16a13e94be5b.zip
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: I90b5c0a1c949283d3102c16734b0b6ac73901a30
Diffstat (limited to 'firmware/common/file_internal.c')
-rw-r--r--firmware/common/file_internal.c95
1 files changed, 27 insertions, 68 deletions
diff --git a/firmware/common/file_internal.c b/firmware/common/file_internal.c
index fe18f90056..45f412e166 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
@@ -87,9 +85,10 @@ void file_cache_free(struct filestr_cache *cachep)
87 85
88/** Stream base APIs **/ 86/** Stream base APIs **/
89 87
90static inline void filestr_clear(struct filestr_base *stream) 88static inline void filestr_clear(struct filestr_base *stream,
89 unsigned int flags)
91{ 90{
92 stream->flags = 0; 91 stream->flags = flags;
93 stream->bindp = NULL; 92 stream->bindp = NULL;
94#if 0 93#if 0
95 stream->mtx = NULL; 94 stream->mtx = NULL;
@@ -153,7 +152,7 @@ void filestr_discard_cache(struct filestr_base *stream)
153/* Initialize the base descriptor */ 152/* Initialize the base descriptor */
154void filestr_base_init(struct filestr_base *stream) 153void filestr_base_init(struct filestr_base *stream)
155{ 154{
156 filestr_clear(stream); 155 filestr_clear(stream, FD_VALID);
157 file_cache_init(&stream->cache); 156 file_cache_init(&stream->cache);
158 stream->cachep = &stream->cache; 157 stream->cachep = &stream->cache;
159} 158}
@@ -161,7 +160,7 @@ void filestr_base_init(struct filestr_base *stream)
161/* free base descriptor resources */ 160/* free base descriptor resources */
162void filestr_base_destroy(struct filestr_base *stream) 161void filestr_base_destroy(struct filestr_base *stream)
163{ 162{
164 filestr_clear(stream); 163 filestr_clear(stream, 0);
165 filestr_free_cache(stream); 164 filestr_free_cache(stream);
166} 165}
167 166
@@ -293,7 +292,7 @@ struct pathwalk_component
293 292
294#define WALK_RC_NOT_FOUND 0 /* successfully not found (aid for file creation) */ 293#define WALK_RC_NOT_FOUND 0 /* successfully not found (aid for file creation) */
295#define WALK_RC_FOUND 1 /* found and opened */ 294#define WALK_RC_FOUND 1 /* found and opened */
296#define WALK_RC_FOUND_ROOT 2 /* found and opened sys/volume root */ 295#define WALK_RC_FOUND_ROOT 2 /* found and opened sys root */
297#define WALK_RC_CONT_AT_ROOT 3 /* continue at root level */ 296#define WALK_RC_CONT_AT_ROOT 3 /* continue at root level */
298 297
299/* return another struct pathwalk_component from the pool, or NULL if the 298/* return another struct pathwalk_component from the pool, or NULL if the
@@ -397,10 +396,10 @@ static int walk_open_info(struct pathwalk *walkp,
397 396
398 /* make open official if not simply probing for presence - must do it here 397 /* make open official if not simply probing for presence - must do it here
399 or compp->info on stack will get destroyed before it was copied */ 398 or compp->info on stack will get destroyed before it was copied */
400 if (!(callflags & FF_PROBE)) 399 if (!(callflags & (FF_PROBE|FF_NOFS)))
401 fileop_onopen_internal(stream, &compp->info, callflags); 400 fileop_onopen_internal(stream, &compp->info, callflags);
402 401
403 return compp->nextp ? WALK_RC_FOUND : WALK_RC_FOUND_ROOT; 402 return compp->attr == ATTR_SYSTEM_ROOT ? WALK_RC_FOUND_ROOT : WALK_RC_FOUND;
404} 403}
405 404
406/* check the component against the prefix test info */ 405/* check the component against the prefix test info */
@@ -507,6 +506,10 @@ walk_path(struct pathwalk *walkp, struct pathwalk_component *compp,
507 if (len > MAX_COMPNAME) 506 if (len > MAX_COMPNAME)
508 return -ENAMETOOLONG; 507 return -ENAMETOOLONG;
509 508
509 /* no filesystem is mounted here */
510 if (walkp->callflags & FF_NOFS)
511 return -ENOENT;
512
510 /* check for "." and ".." */ 513 /* check for "." and ".." */
511 if (name[0] == '.') 514 if (name[0] == '.')
512 { 515 {
@@ -575,7 +578,7 @@ int open_stream_internal(const char *path, unsigned int callflags,
575 callflags &= ~(FF_INFO | FF_PARENTINFO | FF_CHECKPREFIX); 578 callflags &= ~(FF_INFO | FF_PARENTINFO | FF_CHECKPREFIX);
576 579
577 /* This lets it be passed quietly to directory scanning */ 580 /* This lets it be passed quietly to directory scanning */
578 stream->flags = callflags & FF_MASK; 581 stream->flags |= callflags & FF_MASK;
579 582
580 struct pathwalk walk; 583 struct pathwalk walk;
581 walk.path = path; 584 walk.path = path;
@@ -585,80 +588,36 @@ int open_stream_internal(const char *path, unsigned int callflags,
585 588
586 struct pathwalk_component *rootp = pathwalk_comp_alloc(NULL); 589 struct pathwalk_component *rootp = pathwalk_comp_alloc(NULL);
587 rootp->nextp = NULL; 590 rootp->nextp = NULL;
588 rootp->attr = ATTR_SYSTEM_ROOT;
589
590#ifdef HAVE_MULTIVOLUME
591 int volume = 0, rootrc = WALK_RC_FOUND;
592#endif /* HAVE_MULTIVOLUME */
593 591
594 while (1) 592 while (1)
595 { 593 {
596 const char *pathptr = walk.path; 594 rc = ns_parse_root(walk.path, &rootp->name, &rootp->length);
597 595 if (rc < 0)
598 #ifdef HAVE_MULTIVOLUME 596 break;
599 /* this seamlessly integrates secondary filesystems into the
600 root namespace (e.g. "/<0>/../../<1>/../foo/." :<=> "/foo") */
601 const char *p;
602 volume = path_strip_volume(pathptr, &p, false);
603 if (!CHECK_VOL(volume))
604 {
605 DEBUGF("No such device or address: %d\n", volume);
606 FILE_ERROR(ENXIO, -2);
607 }
608
609 if (p == pathptr)
610 {
611 /* the root of this subpath is the system root */
612 rootp->attr = ATTR_SYSTEM_ROOT;
613 rootrc = WALK_RC_FOUND_ROOT;
614 }
615 else
616 {
617 /* this subpath specifies a mount point */
618 rootp->attr = ATTR_MOUNT_POINT;
619 rootrc = WALK_RC_FOUND;
620 }
621
622 walk.path = p;
623 #endif /* HAVE_MULTIVOLUME */
624
625 /* set name to start at last leading separator; names of volume
626 specifiers will be returned as "/<fooN>" */
627 rootp->name = GOBBLE_PATH_SEPCH(pathptr) - 1;
628 rootp->length =
629 IF_MV( rootrc == WALK_RC_FOUND ? p - rootp->name : ) 1;
630 597
631 rc = fat_open_rootdir(IF_MV(volume,) &rootp->info.fatfile); 598 rc = ns_open_root(IF_MV(rc,) &walk.callflags, &rootp->info, &rootp->attr);
632 if (rc < 0) 599 if (rc < 0)
633 {
634 /* not mounted */
635 DEBUGF("No such device or address: %d\n", IF_MV_VOL(volume));
636 rc = -ENXIO;
637 break; 600 break;
638 }
639 601
640 get_rootinfo_internal(&rootp->info); 602 walk.path = rootp->name + rootp->length;
603
641 rc = walk_path(&walk, rootp, stream); 604 rc = walk_path(&walk, rootp, stream);
642 if (rc != WALK_RC_CONT_AT_ROOT) 605 if (rc != WALK_RC_CONT_AT_ROOT)
643 break; 606 break;
644 } 607 }
645 608
646 switch (rc) 609 if (rc >= 0)
647 { 610 {
648 case WALK_RC_FOUND_ROOT:
649 IF_MV( rc = rootrc; )
650 case WALK_RC_NOT_FOUND:
651 case WALK_RC_FOUND:
652 /* FF_PROBE leaves nothing for caller to clean up */ 611 /* FF_PROBE leaves nothing for caller to clean up */
653 if (callflags & FF_PROBE) 612 if (walk.callflags & FF_PROBE)
654 filestr_base_destroy(stream); 613 filestr_base_destroy(stream);
655 614 }
656 break; 615 else
657 616 {
658 default: /* utter, abject failure :`( */ 617 /* utter, abject failure :`( */
659 DEBUGF("Open failed: rc=%d, errno=%d\n", rc, errno); 618 DEBUGF("Open failed: rc=%d, errno=%d\n", rc, errno);
660 filestr_base_destroy(stream); 619 filestr_base_destroy(stream);
661 FILE_ERROR(-rc, -3); 620 FILE_ERROR(-rc, -1);
662 } 621 }
663 622
664file_error: 623file_error: