diff options
author | Richard Jones <rjones@redhat.com> | 2009-10-31 13:41:18 +0000 |
---|---|---|
committer | Richard Jones <rjones@redhat.com> | 2009-11-02 17:48:35 +0000 |
commit | 55a7427b7679e25134cd43488a9f74cb542416ea (patch) | |
tree | 87922387a4fa25c80aba484f3f7cba1a89621796 /daemon/link.c | |
parent | 2eb19f526164a978c373a760deb30854d56b62ce (diff) | |
download | libguestfs-55a7427b7679e25134cd43488a9f74cb542416ea.tar.gz libguestfs-55a7427b7679e25134cd43488a9f74cb542416ea.tar.xz libguestfs-55a7427b7679e25134cd43488a9f74cb542416ea.zip |
New API calls: lstatlist, lxattrlist, readlinklist.
These three functions are very specifically designed for FUSE
support, so we can list directories efficiently. Instead of
making lots of lstat, lgetxattr and readlink calls, we can make just
three calls per directory to grab all the attributes (which we
then cache briefly).
Diffstat (limited to 'daemon/link.c')
-rw-r--r-- | daemon/link.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/daemon/link.c b/daemon/link.c index a77c2e8a..5ea0d39d 100644 --- a/daemon/link.c +++ b/daemon/link.c @@ -21,6 +21,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <fcntl.h> #include <unistd.h> #include <limits.h> @@ -51,6 +52,56 @@ do_readlink (const char *path) return ret; /* caller frees */ } +char ** +do_readlinklist (const char *path, char *const *names) +{ + int fd_cwd; + size_t i; + ssize_t r; + char link[PATH_MAX]; + const char *str; + char **ret = NULL; + int size = 0, alloc = 0; + + CHROOT_IN; + fd_cwd = open (path, O_RDONLY | O_DIRECTORY); + CHROOT_OUT; + + if (fd_cwd == -1) { + reply_with_perror ("readlinklist: %s", path); + return NULL; + } + + for (i = 0; names[i] != NULL; ++i) { + r = readlinkat (fd_cwd, names[i], link, sizeof link); + if (r >= PATH_MAX) { + reply_with_perror ("readlinkat: returned link is too long"); + free_strings (ret); + close (fd_cwd); + return NULL; + } + /* Because of the way this function is intended to be used, + * we actually expect to see errors here, and they are not fatal. + */ + if (r >= 0) { + link[r] = '\0'; + str = link; + } else + str = ""; + if (add_string (&ret, &size, &alloc, str) == -1) { + close (fd_cwd); + return NULL; + } + } + + close (fd_cwd); + + if (add_string (&ret, &size, &alloc, NULL) == -1) + return NULL; + + return ret; +} + static int _link (const char *flag, int symbolic, const char *target, const char *linkname) { |