diff options
author | William Wilgus <wilgus.william@gmail.com> | 2022-03-03 07:37:03 -0500 |
---|---|---|
committer | William Wilgus <wilgus.william@gmail.com> | 2022-03-03 18:58:07 -0500 |
commit | 9daacabd658508d2607a64b288c9bce7a635fb15 (patch) | |
tree | ce96538ea82a4176f00f8eb9531711db7dea5750 /firmware/common/file_internal.c | |
parent | f88ea12bacf381ad4f39ba2328c806e772c0dda8 (diff) | |
download | rockbox-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.c | 100 |
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 | ||
92 | static inline void filestr_clear(struct filestr_base *stream) | 90 | static 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 */ |
156 | void filestr_base_init(struct filestr_base *stream) | 154 | void 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 */ |
164 | void filestr_base_destroy(struct filestr_base *stream) | 162 | void 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 */ |
232 | void empty_dirent(struct dirent *entry) | 230 | void 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 | ||
252 | int uncached_readdir_dirent(struct filestr_base *stream, | 250 | int 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 | ||
667 | file_error: | 623 | file_error: |