summaryrefslogtreecommitdiff
path: root/firmware/common/file_internal.c
diff options
context:
space:
mode:
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: