summaryrefslogtreecommitdiffstats
path: root/daemon/link.c
diff options
context:
space:
mode:
authorRichard Jones <rjones@redhat.com>2009-10-31 13:41:18 +0000
committerRichard Jones <rjones@redhat.com>2009-11-02 17:48:35 +0000
commit55a7427b7679e25134cd43488a9f74cb542416ea (patch)
tree87922387a4fa25c80aba484f3f7cba1a89621796 /daemon/link.c
parent2eb19f526164a978c373a760deb30854d56b62ce (diff)
downloadlibguestfs-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.c51
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)
{