diff options
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: |