diff options
| author | Thomas Martitz <kugel@rockbox.org> | 2011-06-20 20:12:10 +0000 |
|---|---|---|
| committer | Thomas Martitz <kugel@rockbox.org> | 2011-06-20 20:12:10 +0000 |
| commit | 38da400e58b78f0fd399bdb8e52e1ba63aca75a7 (patch) | |
| tree | 1646ffcf66ed7f7218a9486622eac41e2c11259a | |
| parent | 60e4f20c38853337c4f54a677eb96c0a4488486f (diff) | |
| download | rockbox-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.c | 56 |
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 --- */ |