summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2011-06-20 20:12:10 +0000
committerThomas Martitz <kugel@rockbox.org>2011-06-20 20:12:10 +0000
commit38da400e58b78f0fd399bdb8e52e1ba63aca75a7 (patch)
tree1646ffcf66ed7f7218a9486622eac41e2c11259a
parent60e4f20c38853337c4f54a677eb96c0a4488486f (diff)
downloadrockbox-38da400e58b78f0fd399bdb8e52e1ba63aca75a7.zip
rockbox-38da400e58b78f0fd399bdb8e52e1ba63aca75a7.tar.gz
rockbox-38da400e58b78f0fd399bdb8e52e1ba63aca75a7.tar.bz2
rockbox-38da400e58b78f0fd399bdb8e52e1ba63aca75a7.tar.xz
Dircache: Rework and simplify dircache_copy_path().
Use a recursive helper function with strlcat to build up the path backwards. This way the tree doesn't need to be walked twice and no extraneous size calculation is needed. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30033 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/common/dircache.c56
1 files changed, 28 insertions, 28 deletions
diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c
index 69e3f16..dc662bb 100644
--- a/firmware/common/dircache.c
+++ b/firmware/common/dircache.c
@@ -907,41 +907,41 @@ const struct dircache_entry *dircache_get_entry_ptr(const char *filename)
return dircache_get_entry(filename, false);
}
+/*
+ * build a path from an entry upto the root using recursion
+ *
+ * it appends '/' after strlcat, therefore buf[0] needs to be prepared with '/'
+ * and it will leave a trailing '/'
+ *
+ * returns the position of that trailing '/' so it can be deleted afterwards
+ * (or, in case of truncation, the position of the nul byte */
+static size_t copy_path_helper(const struct dircache_entry *entry, char *buf, size_t size)
+{
+ /* has parent? */
+ if (entry->up)
+ copy_path_helper(entry->up, buf, size);
+
+ size_t len = strlcat(buf, entry->d_name, size);
+ if (len < size)
+ {
+ buf[len++] = '/';
+ buf[len] = '\0';
+ }
+ return len-1;
+}
/**
* Function to copy the full absolute path from dircache to the given buffer
* using the given dircache_entry pointer.
*/
void dircache_copy_path(const struct dircache_entry *entry, char *buf, int size)
{
- int path_size = 0;
- int idx;
- const struct dircache_entry *temp = entry;
-
- if (size <= 0)
+ if (size <= 0 || !buf)
return ;
-
- /* first compute the necessary size */
- while(temp != NULL)
- {
- path_size += strlen(temp->d_name) + sizeof('/');
- temp = temp->up;
- }
-
- /* now copy the path */
- idx = path_size;
- while(entry != NULL)
- {
- idx -= strlen(entry->d_name);
- /* available size */
- int rem = size - idx;
-
- if(rem >= 1)
- {
- buf[idx] = '/';
- strlcpy(buf + idx + 1, entry->d_name, rem - 1);
- }
- entry = entry->up;
- }
+
+ buf[0] = '/';
+ size_t res = copy_path_helper(entry, buf, size);
+ /* fixup trailing '/' */
+ buf[res] = '\0';
}
/* --- Directory cache live updating functions --- */