summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2017-01-07 07:12:10 -0500
committerMichael Sevakis <jethead71@rockbox.org>2017-01-07 19:10:02 -0500
commit5c6ccb43b55d70350869429da25e2b54b45086d3 (patch)
treef06266c8ade82f36e7e3360ceca313c8b4adaf80
parent5a0a7b8b58a02192e5087077acf9e66fbdf1966e (diff)
downloadrockbox-5c6ccb4.tar.gz
rockbox-5c6ccb4.zip
Fix track formatting problems in playlist.c
Some changes in behavior were made with filesystem code commit for the sake of compatibility that changed expected behavior. * Restore substitution of drive spec in fully-qualified DOS paths with the playlists's volume spec (or root on univolume targets). Drive-relative paths of the form "c:foo" (no separator after ':') will be treated as purely relative. * Restore old behavior of preserving leading whitespace in the source path and trimming only trailing tabs and spaces. * Multivolume: Volume substition on fully-qualified UNIX/RB paths has NOT been reintroduced (and perhaps wasn't intended in the first place). They will not be modified because there is no ambiguity to resolve. Doing so would prevent a playlist on external storage from referencing a file on main storage without qualifying it with "/<0>...". * Plain relative paths are and always have been interpreted as relative to the location of the playlist. Change-Id: Ic0800cea79c59563b7bac20f8b08abb5051906c7
-rw-r--r--apps/playlist.c58
-rw-r--r--firmware/common/pathfuncs.c29
-rw-r--r--firmware/export/pathfuncs.h1
3 files changed, 47 insertions, 41 deletions
diff --git a/apps/playlist.c b/apps/playlist.c
index 173d445f8c..015e41ae0e 100644
--- a/apps/playlist.c
+++ b/apps/playlist.c
@@ -1712,23 +1712,59 @@ static int check_subdir_for_music(char *dir, const char *subdir, bool recurse)
static ssize_t format_track_path(char *dest, char *src, int buf_length,
const char *dir)
{
- size_t len;
+ size_t len = 0;
+
+ /* Look for the end of the string */
+ while (1)
+ {
+ int c = src[len];
+ if (c == '\n' || c == '\r' || c == '\0')
+ break;
+ len++;
+ }
+
+ /* Now work back killing white space */
+ while (len > 0)
+ {
+ int c = src[len - 1];
+ if (c != '\t' && c != ' ')
+ break;
+ len--;
+ }
- /* strip whitespace at beginning and end */
- len = path_trim_whitespace(src, (const char **)&src);
src[len] = '\0';
- /* replace backslashes with forward slashes */
+ /* Replace backslashes with forward slashes */
path_correct_separators(src, src);
- /* handle DOS style drive letter and parse non-greedily so that:
- * 1) "c:/foo" becomes "/foo" and the result is absolute
- * 2) "c:foo becomes "foo" and the result is relative
- * This is how Windows seems to handle it except drive letters are of no
- * meaning here. */
- path_strip_drive(src, (const char **)&src, false);
+ /* Drive letters have no meaning here; handle DOS style drive letter
+ * and parse greedily so that:
+ *
+ * 1) "c:/foo" is fully qualified, use directory volume only
+ * 2) "c:foo" is relative to current directory on C, use directory path
+ *
+ * Assume any volume on the beginning of the directory path is actually
+ * the volume on which it resides. This may not be the case if the dir
+ * param contains a path such as "/<1>/foo/../../<0>/bar", which refers
+ * to "/<0>/bar" (aka "/bar" at this time). *fingers crossed*
+ *
+ * If any stripped drive spec was absolute, prepend the playlist
+ * directory's volume spec, or root if none. Relative paths remain
+ * relative and the playlist's directory fully qualifies them. Absolute
+ * UNIX-style paths remain unaltered.
+ */
+ if (path_strip_drive(src, (const char **)&src, true) >= 0 &&
+ src[-1] == PATH_SEPCH)
+ {
+ #ifdef HAVE_MULTIVOLUME
+ const char *p;
+ path_strip_volume(dir, &p, false);
+ dir = strmemdupa(dir, p - dir); /* empty if no volspec on dir */
+ #else
+ dir = ""; /* only volume is root */
+ #endif
+ }
- /* prepends directory only if src is relative */
len = path_append(dest, *dir ? dir : PATH_ROOTSTR, src, buf_length);
if (len >= (size_t)buf_length)
return -1; /* buffer too small */
diff --git a/firmware/common/pathfuncs.c b/firmware/common/pathfuncs.c
index 1ee5fe9886..f5674983d9 100644
--- a/firmware/common/pathfuncs.c
+++ b/firmware/common/pathfuncs.c
@@ -197,35 +197,6 @@ int path_strip_drive(const char *name, const char **nameptr, bool greedy)
return -1;
}
-/* Strips leading and trailing whitespace from a path
- * " a/b \txyz" *nameptr->a, len=3: "a/b"
- */
-size_t path_trim_whitespace(const char *name, const char **nameptr)
-{
- /* NOTE: this won't currently treat DEL (0x7f) as non-printable */
- const unsigned char *p = name;
- int c;
-
- while ((c = *p) <= ' ' && c)
- ++p;
-
- const unsigned char *first = p;
- const unsigned char *last = p;
-
- while (1)
- {
- if (c < ' ')
- {
- *nameptr = first;
- return last - first;
- }
-
- while ((c = *++p) > ' ');
- last = p;
- while (c == ' ') c = *++p;
- }
-}
-
/* Strips directory components from the path
* "" *nameptr->NUL, len=0: ""
* "/" *nameptr->/, len=1: "/"
diff --git a/firmware/export/pathfuncs.h b/firmware/export/pathfuncs.h
index 26eb4a1067..92539c54c1 100644
--- a/firmware/export/pathfuncs.h
+++ b/firmware/export/pathfuncs.h
@@ -78,7 +78,6 @@ int get_volume_name(int volume, char *name);
#endif
int path_strip_drive(const char *name, const char **nameptr, bool greedy);
-size_t path_trim_whitespace(const char *name, const char **nameptr);
size_t path_basename(const char *name, const char **nameptr);
size_t path_dirname(const char *name, const char **nameptr);
size_t path_strip_trailing_separators(const char *name, const char **nameptr);