summaryrefslogtreecommitdiffstats
path: root/daemon/stat.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/stat.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/stat.c')
-rw-r--r--daemon/stat.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/daemon/stat.c b/daemon/stat.c
index 4ff27113..2441c9fe 100644
--- a/daemon/stat.c
+++ b/daemon/stat.c
@@ -24,6 +24,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
+#include <fcntl.h>
#include <unistd.h>
#include "../src/guestfs_protocol.h"
@@ -108,6 +109,73 @@ do_lstat (const char *path)
return ret;
}
+guestfs_int_stat_list *
+do_lstatlist (const char *path, char *const *names)
+{
+ int path_fd;
+ guestfs_int_stat_list *ret;
+ size_t i, nr_names;
+
+ nr_names = count_strings (names);
+
+ ret = malloc (sizeof *ret);
+ if (!ret) {
+ reply_with_perror ("malloc");
+ return NULL;
+ }
+ ret->guestfs_int_stat_list_len = nr_names;
+ ret->guestfs_int_stat_list_val = calloc (nr_names, sizeof (guestfs_int_stat));
+ if (ret->guestfs_int_stat_list_val == NULL) {
+ reply_with_perror ("malloc");
+ free (ret);
+ return NULL;
+ }
+
+ CHROOT_IN;
+ path_fd = open (path, O_RDONLY | O_DIRECTORY);
+ CHROOT_OUT;
+
+ if (path_fd == -1) {
+ reply_with_perror ("lstatlist: %s", path);
+ free (ret->guestfs_int_stat_list_val);
+ free (ret);
+ return NULL;
+ }
+
+ for (i = 0; names[i] != NULL; ++i) {
+ int r;
+ struct stat statbuf;
+
+ r = fstatat (path_fd, names[i], &statbuf, AT_SYMLINK_NOFOLLOW);
+ if (r == -1)
+ ret->guestfs_int_stat_list_val[i].ino = -1;
+ else {
+ ret->guestfs_int_stat_list_val[i].dev = statbuf.st_dev;
+ ret->guestfs_int_stat_list_val[i].ino = statbuf.st_ino;
+ ret->guestfs_int_stat_list_val[i].mode = statbuf.st_mode;
+ ret->guestfs_int_stat_list_val[i].nlink = statbuf.st_nlink;
+ ret->guestfs_int_stat_list_val[i].uid = statbuf.st_uid;
+ ret->guestfs_int_stat_list_val[i].gid = statbuf.st_gid;
+ ret->guestfs_int_stat_list_val[i].rdev = statbuf.st_rdev;
+ ret->guestfs_int_stat_list_val[i].size = statbuf.st_size;
+ ret->guestfs_int_stat_list_val[i].blksize = statbuf.st_blksize;
+ ret->guestfs_int_stat_list_val[i].blocks = statbuf.st_blocks;
+ ret->guestfs_int_stat_list_val[i].atime = statbuf.st_atime;
+ ret->guestfs_int_stat_list_val[i].mtime = statbuf.st_mtime;
+ ret->guestfs_int_stat_list_val[i].ctime = statbuf.st_ctime;
+ }
+ }
+
+ if (close (path_fd) == -1) {
+ reply_with_perror ("close: %s", path);
+ free (ret->guestfs_int_stat_list_val);
+ free (ret);
+ return NULL;
+ }
+
+ return ret;
+}
+
guestfs_int_statvfs *
do_statvfs (const char *path)
{