diff options
-rw-r--r-- | apps/filetree.c | 85 | ||||
-rw-r--r-- | apps/filetree.h | 2 | ||||
-rw-r--r-- | apps/tagcache.c | 47 | ||||
-rw-r--r-- | apps/tree.c | 11 | ||||
-rw-r--r-- | firmware/common/dir.c | 6 | ||||
-rw-r--r-- | firmware/common/rb_namespace.c | 74 | ||||
-rw-r--r-- | firmware/include/dir.h | 6 | ||||
-rw-r--r-- | firmware/include/dircache_redirect.h | 5 | ||||
-rw-r--r-- | firmware/include/rb_namespace.h | 3 | ||||
-rw-r--r-- | firmware/target/hosted/filesystem-app.c | 5 | ||||
-rw-r--r-- | uisimulator/common/filesystem-sim.c | 5 |
11 files changed, 198 insertions, 51 deletions
diff --git a/apps/filetree.c b/apps/filetree.c index eb429c83e3..4f59804686 100644 --- a/apps/filetree.c +++ b/apps/filetree.c | |||
@@ -46,6 +46,10 @@ | |||
46 | #include "strnatcmp.h" | 46 | #include "strnatcmp.h" |
47 | #include "keyboard.h" | 47 | #include "keyboard.h" |
48 | 48 | ||
49 | #ifdef HAVE_MULTIVOLUME | ||
50 | #include "mv.h" | ||
51 | #endif | ||
52 | |||
49 | #if CONFIG_TUNER | 53 | #if CONFIG_TUNER |
50 | #include "radio.h" | 54 | #include "radio.h" |
51 | #endif | 55 | #endif |
@@ -471,6 +475,45 @@ static void ft_apply_skin_file(char *buf, char *file, const int maxlen) | |||
471 | settings_apply_skins(); | 475 | settings_apply_skins(); |
472 | } | 476 | } |
473 | 477 | ||
478 | int ft_assemble_path(char *buf, size_t bufsz, const char* currdir, const char* filename) | ||
479 | { | ||
480 | int len; | ||
481 | if (!filename) | ||
482 | filename = ""; | ||
483 | #ifdef HAVE_MULTIVOLUME | ||
484 | if (currdir && currdir[0] && currdir[1]) /* Not in / */ | ||
485 | { | ||
486 | if (currdir[1] != VOL_START_TOK) | ||
487 | { | ||
488 | len = snprintf(buf, bufsz, "%s%s/%s", root_realpath(), currdir, filename); | ||
489 | } | ||
490 | else | ||
491 | len = snprintf(buf, bufsz, "%s/%s", currdir, filename); | ||
492 | } | ||
493 | else /* In / */ | ||
494 | { | ||
495 | if (filename[0] != VOL_START_TOK) | ||
496 | { | ||
497 | len = snprintf(buf, bufsz, "%s/%s",root_realpath(), filename); | ||
498 | } | ||
499 | else | ||
500 | len = snprintf(buf, bufsz, "/%s", filename); | ||
501 | } | ||
502 | #else | ||
503 | if (currdir && currdir[0] && currdir[1]) /* Not in / */ | ||
504 | { | ||
505 | len = snprintf(buf, bufsz, "%s%s/%s", root_realpath(), currdir, filename); | ||
506 | } | ||
507 | else /* In / */ | ||
508 | { | ||
509 | len = snprintf(buf, bufsz, "%s/%s",root_realpath(), filename); | ||
510 | } | ||
511 | #endif | ||
512 | if ((unsigned) len > bufsz) | ||
513 | splash(HZ, ID2P(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR)); | ||
514 | return len; | ||
515 | } | ||
516 | |||
474 | int ft_enter(struct tree_context* c) | 517 | int ft_enter(struct tree_context* c) |
475 | { | 518 | { |
476 | int rc = GO_TO_PREVIOUS; | 519 | int rc = GO_TO_PREVIOUS; |
@@ -484,16 +527,7 @@ int ft_enter(struct tree_context* c) | |||
484 | } | 527 | } |
485 | 528 | ||
486 | int file_attr = file->attr; | 529 | int file_attr = file->attr; |
487 | int len; | 530 | ft_assemble_path(buf, sizeof(buf), c->currdir, file->name); |
488 | |||
489 | if (c->currdir[1]) | ||
490 | { | ||
491 | len = snprintf(buf,sizeof(buf),"%s/%s",c->currdir, file->name); | ||
492 | if ((unsigned) len > sizeof(buf)) | ||
493 | splash(HZ, ID2P(LANG_PLAYLIST_ACCESS_ERROR)); | ||
494 | } | ||
495 | else | ||
496 | snprintf(buf,sizeof(buf),"/%s",file->name); | ||
497 | 531 | ||
498 | if (file_attr & ATTR_DIRECTORY) { | 532 | if (file_attr & ATTR_DIRECTORY) { |
499 | memcpy(c->currdir, buf, sizeof(c->currdir)); | 533 | memcpy(c->currdir, buf, sizeof(c->currdir)); |
@@ -537,22 +571,27 @@ int ft_enter(struct tree_context* c) | |||
537 | PLAYLIST_INSERT_LAST, true, true); | 571 | PLAYLIST_INSERT_LAST, true, true); |
538 | splash(HZ, ID2P(LANG_QUEUE_LAST)); | 572 | splash(HZ, ID2P(LANG_QUEUE_LAST)); |
539 | } | 573 | } |
540 | else if (playlist_create(c->currdir, NULL) != -1) | 574 | else |
541 | { | 575 | { |
542 | start_index = ft_build_playlist(c, c->selected_item); | 576 | /* use the assembled path sans filename */ |
543 | if (global_settings.playlist_shuffle) | 577 | char * fp = strrchr(buf, PATH_SEPCH); |
578 | if (fp) | ||
579 | *fp = '\0'; | ||
580 | if (playlist_create(buf, NULL) != -1) | ||
544 | { | 581 | { |
545 | start_index = playlist_shuffle(seed, start_index); | 582 | start_index = ft_build_playlist(c, c->selected_item); |
546 | 583 | if (global_settings.playlist_shuffle) | |
547 | /* when shuffling dir.: play all files | 584 | { |
548 | even if the file selected by user is | 585 | start_index = playlist_shuffle(seed, start_index); |
549 | not the first one */ | 586 | /* when shuffling dir.: play all files |
550 | if (!global_settings.play_selected) | 587 | even if the file selected by user is |
551 | start_index = 0; | 588 | not the first one */ |
589 | if (!global_settings.play_selected) | ||
590 | start_index = 0; | ||
591 | } | ||
592 | playlist_start(start_index, 0, 0); | ||
593 | play = true; | ||
552 | } | 594 | } |
553 | |||
554 | playlist_start(start_index, 0, 0); | ||
555 | play = true; | ||
556 | } | 595 | } |
557 | break; | 596 | break; |
558 | } | 597 | } |
diff --git a/apps/filetree.h b/apps/filetree.h index 7931c3c454..3ec7846d2c 100644 --- a/apps/filetree.h +++ b/apps/filetree.h | |||
@@ -25,6 +25,8 @@ | |||
25 | int ft_load(struct tree_context* c, const char* tempdir); | 25 | int ft_load(struct tree_context* c, const char* tempdir); |
26 | int ft_enter(struct tree_context* c); | 26 | int ft_enter(struct tree_context* c); |
27 | int ft_exit(struct tree_context* c); | 27 | int ft_exit(struct tree_context* c); |
28 | int ft_assemble_path(char *buf, size_t bufsz, | ||
29 | const char* currdir, const char* filename); | ||
28 | int ft_build_playlist(struct tree_context* c, int start_index); | 30 | int ft_build_playlist(struct tree_context* c, int start_index); |
29 | bool ft_play_playlist(char* pathname, char* dirname, | 31 | bool ft_play_playlist(char* pathname, char* dirname, |
30 | char* filename, bool skip_warn_and_bookmarks); | 32 | char* filename, bool skip_warn_and_bookmarks); |
diff --git a/apps/tagcache.c b/apps/tagcache.c index 40f9c28c33..c8900f5c38 100644 --- a/apps/tagcache.c +++ b/apps/tagcache.c | |||
@@ -4990,10 +4990,56 @@ void do_tagcache_build(const char *path[]) | |||
4990 | 4990 | ||
4991 | roots_ll[0].path = path[0]; | 4991 | roots_ll[0].path = path[0]; |
4992 | roots_ll[0].next = NULL; | 4992 | roots_ll[0].next = NULL; |
4993 | |||
4994 | #if defined HAVE_MULTIVOLUME && !defined(SIMULATOR) && !defined(__PCTOOL__) | ||
4995 | extern bool ns_volume_is_visible(int volume); /*rb_namespace.c*/ | ||
4996 | /* i is for the path vector, j for the roots_ll array */ | ||
4997 | int i = 1, j = 1; | ||
4998 | bool added = false; | ||
4999 | char volnamebuf[NUM_VOLUMES][VOL_MAX_LEN + 1]; | ||
5000 | /* we can just parse the root directory ('/') and get to any mounted | ||
5001 | * volume but we can also enumerate a volume in the root directory | ||
5002 | * when this occurs it leads to multiple entries since the files can | ||
5003 | * be reached through multiple paths ex, /Foo could also be /SD1/Foo | ||
5004 | * we used to hide the volume that was mapped but then when you switch | ||
5005 | * from the sd to the internal the paths don't map to the right volume | ||
5006 | * instead we will attempt to rewrite the root with any non-hidden volumes | ||
5007 | * failing that just leave the paths alone */ | ||
5008 | if (!strcmp(PATH_ROOTSTR, path[0])) | ||
5009 | { | ||
5010 | i = 0; | ||
5011 | j = 0; | ||
5012 | } | ||
5013 | /* path can be skipped , but root_ll entries can't */ | ||
5014 | for(; path[i] && j < MAX_STATIC_ROOTS; i++) | ||
5015 | { | ||
5016 | /* check if the link target is inside of an existing search root | ||
5017 | * don't add if target is inside, we'll scan it later */ | ||
5018 | if (!added && !strcmp(PATH_ROOTSTR, path[i])) | ||
5019 | { | ||
5020 | for (int v = 0; v < NUM_VOLUMES; v++) | ||
5021 | { | ||
5022 | if (ns_volume_is_visible(v)) | ||
5023 | { | ||
5024 | make_volume_root(v, volnamebuf[v]); | ||
5025 | roots_ll[j].path = volnamebuf[v]; | ||
5026 | if (j > 0) | ||
5027 | roots_ll[j-1].next = &roots_ll[j]; | ||
5028 | j++; | ||
5029 | added = true; | ||
5030 | } | ||
5031 | } | ||
5032 | if(!added) | ||
5033 | j = 1; | ||
5034 | added = true; | ||
5035 | continue; | ||
5036 | } | ||
5037 | #else | ||
4993 | /* i is for the path vector, j for the roots_ll array | 5038 | /* i is for the path vector, j for the roots_ll array |
4994 | * path can be skipped , but root_ll entries can't */ | 5039 | * path can be skipped , but root_ll entries can't */ |
4995 | for(int i = 1, j = 1; path[i] && j < MAX_STATIC_ROOTS; i++) | 5040 | for(int i = 1, j = 1; path[i] && j < MAX_STATIC_ROOTS; i++) |
4996 | { | 5041 | { |
5042 | #endif /*def HAVE_MULTIVOLUME*/ | ||
4997 | if (search_root_exists(path[i])) /* skip this path */ | 5043 | if (search_root_exists(path[i])) /* skip this path */ |
4998 | continue; | 5044 | continue; |
4999 | 5045 | ||
@@ -5006,6 +5052,7 @@ void do_tagcache_build(const char *path[]) | |||
5006 | /* check_dir might add new roots */ | 5052 | /* check_dir might add new roots */ |
5007 | for(this = &roots_ll[0]; this; this = this->next) | 5053 | for(this = &roots_ll[0]; this; this = this->next) |
5008 | { | 5054 | { |
5055 | logf("Search root %s", this->path); | ||
5009 | strmemccpy(curpath, this->path, sizeof(curpath)); | 5056 | strmemccpy(curpath, this->path, sizeof(curpath)); |
5010 | ret = ret && check_dir(this->path, true); | 5057 | ret = ret && check_dir(this->path, true); |
5011 | } | 5058 | } |
diff --git a/apps/tree.c b/apps/tree.c index 7563c1ef6e..ea2ef23e71 100644 --- a/apps/tree.c +++ b/apps/tree.c | |||
@@ -646,7 +646,6 @@ static int dirbrowse(void) | |||
646 | { | 646 | { |
647 | int numentries=0; | 647 | int numentries=0; |
648 | char buf[MAX_PATH]; | 648 | char buf[MAX_PATH]; |
649 | int len; | ||
650 | int button; | 649 | int button; |
651 | int oldbutton; | 650 | int oldbutton; |
652 | bool reload_root = false; | 651 | bool reload_root = false; |
@@ -857,16 +856,8 @@ static int dirbrowse(void) | |||
857 | 856 | ||
858 | attr = entry->attr; | 857 | attr = entry->attr; |
859 | 858 | ||
860 | if (currdir[1]) /* Not in / */ | 859 | ft_assemble_path(buf, sizeof(buf), currdir, entry->name); |
861 | { | ||
862 | len = snprintf(buf, sizeof buf, "%s/%s", | ||
863 | currdir, entry->name); | ||
864 | 860 | ||
865 | if ((unsigned) len > sizeof(buf)) | ||
866 | splash(HZ, ID2P(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR)); | ||
867 | } | ||
868 | else /* In / */ | ||
869 | snprintf(buf, sizeof buf, "/%s", entry->name); | ||
870 | } | 861 | } |
871 | onplay_result = onplay(buf, attr, curr_context, hotkey); | 862 | onplay_result = onplay(buf, attr, curr_context, hotkey); |
872 | } | 863 | } |
diff --git a/firmware/common/dir.c b/firmware/common/dir.c index 45749b8474..9a78d910a7 100644 --- a/firmware/common/dir.c +++ b/firmware/common/dir.c | |||
@@ -344,3 +344,9 @@ struct dirinfo dir_get_info(DIR *dirp, struct dirent *entry) | |||
344 | file_error: | 344 | file_error: |
345 | return (struct dirinfo){ .attribute = 0 }; | 345 | return (struct dirinfo){ .attribute = 0 }; |
346 | } | 346 | } |
347 | |||
348 | const char* root_realpath(void) | ||
349 | { | ||
350 | /* Native only, for APP and SIM see respective filesystem-.c files */ | ||
351 | return root_get_realpath(); /* rb_namespace.c */ | ||
352 | } | ||
diff --git a/firmware/common/rb_namespace.c b/firmware/common/rb_namespace.c index ff5ad0f6db..52b2205f40 100644 --- a/firmware/common/rb_namespace.c +++ b/firmware/common/rb_namespace.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include "fileobj_mgr.h" | 23 | #include "fileobj_mgr.h" |
24 | #include "rb_namespace.h" | 24 | #include "rb_namespace.h" |
25 | #include "file_internal.h" | 25 | #include "file_internal.h" |
26 | #include <stdio.h> /*snprintf*/ | ||
26 | 27 | ||
27 | /* Define LOGF_ENABLE to enable logf output in this file */ | 28 | /* Define LOGF_ENABLE to enable logf output in this file */ |
28 | //#define LOGF_ENABLE | 29 | //#define LOGF_ENABLE |
@@ -82,39 +83,48 @@ static void unmount_item(int item) | |||
82 | set_root_item_state(item, 0); | 83 | set_root_item_state(item, 0); |
83 | } | 84 | } |
84 | 85 | ||
86 | static char *root_realpath_internal(void) | ||
87 | { | ||
88 | static char root_realpath[ROOT_MAX_REALPATH]; | ||
89 | return root_realpath; | ||
90 | } | ||
91 | const char* root_get_realpath(void) | ||
92 | { | ||
93 | return root_realpath_internal(); | ||
94 | } | ||
95 | |||
85 | /* mount the directory that enumerates into the root namespace */ | 96 | /* mount the directory that enumerates into the root namespace */ |
86 | int root_mount_path(const char *path, unsigned int flags) | 97 | int root_mount_path(const char *path, unsigned int flags) |
87 | { | 98 | { |
99 | const char *folder = NULL; /* is a folder enumerated in the root? */ | ||
88 | #ifdef HAVE_MULTIVOLUME | 100 | #ifdef HAVE_MULTIVOLUME |
89 | int volume = path_strip_volume(path, NULL, false); | 101 | int volume = path_strip_volume(path, &folder, false); |
90 | if (volume == ROOT_VOLUME) | 102 | if (volume == ROOT_VOLUME) |
91 | return -EINVAL; | 103 | return -EINVAL; |
92 | |||
93 | if (!CHECK_VOL(volume)) | 104 | if (!CHECK_VOL(volume)) |
94 | return -ENOENT; | 105 | return -ENOENT; |
106 | char volname[VOL_MAX_LEN+2]; | ||
107 | make_volume_root(volume, volname); | ||
95 | #else | 108 | #else |
109 | const char volname = PATH_ROOTSTR; | ||
96 | if (!path_is_absolute(path)) | 110 | if (!path_is_absolute(path)) |
97 | { | 111 | { |
98 | logf("Path not absolute %s", path); | 112 | logf("Path not absolute %s", path); |
99 | return -ENOENT; | 113 | return -ENOENT; |
100 | } | 114 | } |
115 | path_dirname(path, &folder); | ||
101 | #endif /* HAVE_MULTIVOLUME */ | 116 | #endif /* HAVE_MULTIVOLUME */ |
102 | |||
103 | bool contents = flags & NSITEM_CONTENTS; | 117 | bool contents = flags & NSITEM_CONTENTS; |
104 | int item = contents ? ROOT_CONTENTS_INDEX : IF_MV_VOL(volume); | 118 | int item = IF_MV_VOL(volume); |
105 | unsigned int state = get_root_item_state(item); | 119 | unsigned int state = get_root_item_state(item); |
106 | |||
107 | logf("%s: item:%d, st:%u, %s", __func__, item, state, path); | 120 | logf("%s: item:%d, st:%u, %s", __func__, item, state, path); |
108 | 121 | if (contents && state) /* volume must be mounted to enumerate into the root namespace */ | |
109 | if (state) | ||
110 | return -EBUSY; | ||
111 | |||
112 | if (contents) | ||
113 | { | 122 | { |
123 | if (get_root_item_state(ROOT_CONTENTS_INDEX)) | ||
124 | return -EBUSY; /* error something is already enumerated */ | ||
114 | /* cache information about the target */ | 125 | /* cache information about the target */ |
115 | struct filestr_base stream; | 126 | struct filestr_base stream; |
116 | struct path_component_info compinfo; | 127 | struct path_component_info compinfo; |
117 | |||
118 | int e = errno; | 128 | int e = errno; |
119 | int rc = open_stream_internal(path, FF_DIR | FF_PROBE | FF_INFO | | 129 | int rc = open_stream_internal(path, FF_DIR | FF_PROBE | FF_INFO | |
120 | FF_DEVPATH, &stream, &compinfo); | 130 | FF_DEVPATH, &stream, &compinfo); |
@@ -124,17 +134,41 @@ int root_mount_path(const char *path, unsigned int flags) | |||
124 | errno = e; | 134 | errno = e; |
125 | return rc; | 135 | return rc; |
126 | } | 136 | } |
127 | |||
128 | if (!fileobj_mount(&compinfo.info, FO_DIRECTORY, &root_bindp)) | 137 | if (!fileobj_mount(&compinfo.info, FO_DIRECTORY, &root_bindp)) |
129 | return -EBUSY; | 138 | return -EBUSY; |
130 | } | 139 | int root_state = NSITEM_MOUNTED | (flags & (NSITEM_HIDDEN|NSITEM_CONTENTS)); |
140 | set_root_item_state(ROOT_CONTENTS_INDEX, root_state); | ||
141 | flags |= state; /* preserve the state of the mounted volume */ | ||
142 | if (!folder) | ||
143 | { | ||
144 | folder = ""; | ||
145 | } | ||
146 | else | ||
147 | { | ||
148 | /*if a folder has been enumerated don't mark the whole volume */ | ||
149 | if (folder[0] != '\0' && folder[1] != '\0') | ||
150 | flags &= ~NSITEM_CONTENTS; | ||
131 | 151 | ||
152 | } | ||
153 | snprintf(root_realpath_internal(), ROOT_MAX_REALPATH,"%s%s", volname, folder); | ||
154 | } | ||
155 | else if (state) /* error volume already mounted */ | ||
156 | return -EBUSY; | ||
132 | state = NSITEM_MOUNTED | (flags & (NSITEM_HIDDEN|NSITEM_CONTENTS)); | 157 | state = NSITEM_MOUNTED | (flags & (NSITEM_HIDDEN|NSITEM_CONTENTS)); |
133 | set_root_item_state(item, state); | 158 | set_root_item_state(item, state); |
134 | |||
135 | return 0; | 159 | return 0; |
136 | } | 160 | } |
137 | 161 | ||
162 | /* check if volume in path is mounted in the root namespace */ | ||
163 | bool ns_volume_is_visible(IF_MV_NONVOID(int volume)) | ||
164 | { | ||
165 | int item = IF_MV_VOL(volume); | ||
166 | if ((item == ROOT_VOLUME) || !CHECK_VOL(item)) | ||
167 | return false; | ||
168 | unsigned int state = get_root_item_state(item); | ||
169 | return state && (((state & NSITEM_HIDDEN) == 0) || (state & NSITEM_CONTENTS)); | ||
170 | } | ||
171 | |||
138 | /* inform root that an entire volume is being unmounted */ | 172 | /* inform root that an entire volume is being unmounted */ |
139 | void root_unmount_volume(IF_MV_NONVOID(int volume)) | 173 | void root_unmount_volume(IF_MV_NONVOID(int volume)) |
140 | { | 174 | { |
@@ -154,7 +188,10 @@ void root_unmount_volume(IF_MV_NONVOID(int volume)) | |||
154 | uint32_t state = get_root_item_state(ROOT_CONTENTS_INDEX); | 188 | uint32_t state = get_root_item_state(ROOT_CONTENTS_INDEX); |
155 | if (state && (volume < 0 || BASEINFO_VOL(&root_bindp->info) == volume)) | 189 | if (state && (volume < 0 || BASEINFO_VOL(&root_bindp->info) == volume)) |
156 | #endif | 190 | #endif |
191 | { | ||
157 | unmount_item(ROOT_CONTENTS_INDEX); | 192 | unmount_item(ROOT_CONTENTS_INDEX); |
193 | root_realpath_internal()[0] = '\0'; | ||
194 | } | ||
158 | } | 195 | } |
159 | 196 | ||
160 | /* parse the root part of a path */ | 197 | /* parse the root part of a path */ |
@@ -268,8 +305,13 @@ int root_readdir_dirent(struct filestr_base *stream, | |||
268 | state = get_root_item_state(item); | 305 | state = get_root_item_state(item); |
269 | if ((state & (NSITEM_MOUNTED|NSITEM_HIDDEN)) == NSITEM_MOUNTED) | 306 | if ((state & (NSITEM_MOUNTED|NSITEM_HIDDEN)) == NSITEM_MOUNTED) |
270 | { | 307 | { |
271 | logf("Found mounted item: %d %s", item, entry->d_name); | 308 | #if 1 /* hide the volume enumerated into the root namespace */ |
272 | break; | 309 | if (item == ROOT_CONTENTS_INDEX || (state & NSITEM_CONTENTS) == 0) |
310 | { | ||
311 | logf("Found mounted item: %d %s", item, entry->d_name); | ||
312 | break; | ||
313 | } | ||
314 | #endif | ||
273 | } | 315 | } |
274 | 316 | ||
275 | item++; | 317 | item++; |
diff --git a/firmware/include/dir.h b/firmware/include/dir.h index 2f78b11cf5..4599877ede 100644 --- a/firmware/include/dir.h +++ b/firmware/include/dir.h | |||
@@ -63,6 +63,9 @@ | |||
63 | #ifndef dir_exists | 63 | #ifndef dir_exists |
64 | #define dir_exists FS_PREFIX(dir_exists) | 64 | #define dir_exists FS_PREFIX(dir_exists) |
65 | #endif | 65 | #endif |
66 | #ifndef root_realpath | ||
67 | #define root_realpath FS_PREFIX(root_realpath) | ||
68 | #endif | ||
66 | #endif /* !DIRFUNCTIONS_DEFINED */ | 69 | #endif /* !DIRFUNCTIONS_DEFINED */ |
67 | 70 | ||
68 | #ifndef DIRENT_DEFINED | 71 | #ifndef DIRENT_DEFINED |
@@ -83,6 +86,9 @@ struct dirinfo | |||
83 | #ifndef DIRFUNCTIONS_DECLARED | 86 | #ifndef DIRFUNCTIONS_DECLARED |
84 | /* TIP: set errno to zero before calling to see if anything failed */ | 87 | /* TIP: set errno to zero before calling to see if anything failed */ |
85 | struct dirinfo dir_get_info(DIR *dirp, struct DIRENT *entry); | 88 | struct dirinfo dir_get_info(DIR *dirp, struct DIRENT *entry); |
89 | const char* root_realpath(void); | ||
86 | #endif /* !DIRFUNCTIONS_DECLARED */ | 90 | #endif /* !DIRFUNCTIONS_DECLARED */ |
87 | 91 | ||
92 | |||
93 | |||
88 | #endif /* _DIR_H_ */ | 94 | #endif /* _DIR_H_ */ |
diff --git a/firmware/include/dircache_redirect.h b/firmware/include/dircache_redirect.h index f51ce70690..36f68b7251 100644 --- a/firmware/include/dircache_redirect.h +++ b/firmware/include/dircache_redirect.h | |||
@@ -139,8 +139,10 @@ static inline void fileop_onsync_internal(struct filestr_base *stream) | |||
139 | 139 | ||
140 | static inline void volume_onmount_internal(IF_MV_NONVOID(int volume)) | 140 | static inline void volume_onmount_internal(IF_MV_NONVOID(int volume)) |
141 | { | 141 | { |
142 | #if defined(HAVE_MULTIBOOT) && !defined(SIMULATOR) && !defined(BOOTLOADER) | 142 | #if (defined(HAVE_MULTIVOLUME) || (defined(HAVE_MULTIBOOT) && !defined(BOOTLOADER))) |
143 | char path[VOL_MAX_LEN+2]; | 143 | char path[VOL_MAX_LEN+2]; |
144 | #endif | ||
145 | #if defined(HAVE_MULTIBOOT) && !defined(SIMULATOR) && !defined(BOOTLOADER) | ||
144 | char rtpath[MAX_PATH / 2]; | 146 | char rtpath[MAX_PATH / 2]; |
145 | make_volume_root(volume, path); | 147 | make_volume_root(volume, path); |
146 | 148 | ||
@@ -183,7 +185,6 @@ standard_redirect: | |||
183 | root_mount_path(RB_ROOT_CONTENTS_DIR, NSITEM_CONTENTS); | 185 | root_mount_path(RB_ROOT_CONTENTS_DIR, NSITEM_CONTENTS); |
184 | } | 186 | } |
185 | #elif defined(HAVE_MULTIVOLUME) | 187 | #elif defined(HAVE_MULTIVOLUME) |
186 | char path[VOL_MAX_LEN+2]; | ||
187 | make_volume_root(volume, path); | 188 | make_volume_root(volume, path); |
188 | root_mount_path(path, RB_ROOT_VOL_HIDDEN(volume) ? NSITEM_HIDDEN : 0); | 189 | root_mount_path(path, RB_ROOT_VOL_HIDDEN(volume) ? NSITEM_HIDDEN : 0); |
189 | if (volume == path_strip_volume(RB_ROOT_CONTENTS_DIR, NULL, false)) | 190 | if (volume == path_strip_volume(RB_ROOT_CONTENTS_DIR, NULL, false)) |
diff --git a/firmware/include/rb_namespace.h b/firmware/include/rb_namespace.h index 7bc711b5a6..5cd8c2dd29 100644 --- a/firmware/include/rb_namespace.h +++ b/firmware/include/rb_namespace.h | |||
@@ -37,6 +37,8 @@ struct ns_scan_info | |||
37 | }; | 37 | }; |
38 | 38 | ||
39 | /* root functions */ | 39 | /* root functions */ |
40 | #define ROOT_MAX_REALPATH 80 | ||
41 | const char* root_get_realpath(void); | ||
40 | int root_mount_path(const char *path, unsigned int flags); | 42 | int root_mount_path(const char *path, unsigned int flags); |
41 | void root_unmount_volume(IF_MV_NONVOID(int volume)); | 43 | void root_unmount_volume(IF_MV_NONVOID(int volume)); |
42 | int root_readdir_dirent(struct filestr_base *stream, | 44 | int root_readdir_dirent(struct filestr_base *stream, |
@@ -49,6 +51,7 @@ int ns_open_root(IF_MV(int volume,) unsigned int *callflagsp, | |||
49 | struct file_base_info *infop, uint16_t *attrp); | 51 | struct file_base_info *infop, uint16_t *attrp); |
50 | int ns_open_stream(const char *path, unsigned int callflags, | 52 | int ns_open_stream(const char *path, unsigned int callflags, |
51 | struct filestr_base *stream, struct ns_scan_info *scanp); | 53 | struct filestr_base *stream, struct ns_scan_info *scanp); |
54 | bool ns_volume_is_visible(IF_MV_NONVOID(int volume)); | ||
52 | 55 | ||
53 | /* closes the namespace stream */ | 56 | /* closes the namespace stream */ |
54 | static inline int ns_close_stream(struct filestr_base *stream) | 57 | static inline int ns_close_stream(struct filestr_base *stream) |
diff --git a/firmware/target/hosted/filesystem-app.c b/firmware/target/hosted/filesystem-app.c index cfe4e65fe9..09b3365a9e 100644 --- a/firmware/target/hosted/filesystem-app.c +++ b/firmware/target/hosted/filesystem-app.c | |||
@@ -600,3 +600,8 @@ int os_volume_path(IF_MV(int volume, ) char *buffer, size_t bufsize) | |||
600 | 600 | ||
601 | return 0; | 601 | return 0; |
602 | } | 602 | } |
603 | |||
604 | const char* app_root_realpath(void) | ||
605 | { | ||
606 | return PATH_ROOTSTR; | ||
607 | } | ||
diff --git a/uisimulator/common/filesystem-sim.c b/uisimulator/common/filesystem-sim.c index 0a5df0c742..f4f6321b7d 100644 --- a/uisimulator/common/filesystem-sim.c +++ b/uisimulator/common/filesystem-sim.c | |||
@@ -843,3 +843,8 @@ int os_volume_path(IF_MV(int volume, ) char *buffer, size_t bufsize) | |||
843 | 843 | ||
844 | return sim_get_os_path(buffer, tmpbuf, bufsize); | 844 | return sim_get_os_path(buffer, tmpbuf, bufsize); |
845 | } | 845 | } |
846 | |||
847 | const char* sim_root_realpath(void) | ||
848 | { | ||
849 | return PATH_ROOTSTR; | ||
850 | } | ||