diff options
author | William Wilgus <wilgus.william@gmail.com> | 2024-03-21 18:27:23 -0400 |
---|---|---|
committer | William Wilgus <wilgus.william@gmail.com> | 2024-03-23 01:03:33 -0400 |
commit | fdc3668a6a4d85fa6dde890ced7e9b850233bc0d (patch) | |
tree | 5b686359a60acaf753a66f2d09078607b9b11b45 /firmware/common/rb_namespace.c | |
parent | ae01ea7fd93d4ed3e1a97f9c9b25ca072ebbc431 (diff) | |
download | rockbox-fdc3668a6a4d85fa6dde890ced7e9b850233bc0d.tar.gz rockbox-fdc3668a6a4d85fa6dde890ced7e9b850233bc0d.zip |
[BugFix] Multiboot Database duplicate files
When the sd card is mounted into the root namespace the database
picks up files through both paths
previously we hid the mounted drive but this causes issues with users
databases when the drive letter changes
Adds a way to keep track of volumes mounted in the root namespace
Hides the enumerated volume in root
Database:
we can just parse the root directory ('/') and get to any mounted
volume but we can also enumerate a volume in the root directory
when this occurs it leads to multiple entries since the files can
be reached through multiple paths ex, /Foo could also be /SD1/Foo
Instead we will attempt to rewrite the root with any non-hidden volumes
failing that just leave the paths alone
Change-Id: I7bdba8cfaf63902d2a3852d28484bcf8ca317ebd
Diffstat (limited to 'firmware/common/rb_namespace.c')
-rw-r--r-- | firmware/common/rb_namespace.c | 74 |
1 files changed, 58 insertions, 16 deletions
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++; |