summaryrefslogtreecommitdiff
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)
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);