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.c100
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
92static inline void filestr_clear(struct filestr_base *stream) 90static 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 */
156void filestr_base_init(struct filestr_base *stream) 154void 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 */
164void filestr_base_destroy(struct filestr_base *stream) 162void 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 */
232void empty_dirent(struct dirent *entry) 230void 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
252int uncached_readdir_dirent(struct filestr_base *stream, 250int 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
667file_error: 623file_error: