diff options
Diffstat (limited to 'firmware/common/file_internal.c')
-rw-r--r-- | firmware/common/file_internal.c | 95 |
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 | ||
90 | static inline void filestr_clear(struct filestr_base *stream) | 88 | static 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 */ |
154 | void filestr_base_init(struct filestr_base *stream) | 153 | void 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 */ |
162 | void filestr_base_destroy(struct filestr_base *stream) | 161 | void 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 | ||
664 | file_error: | 623 | file_error: |