df: Add --uuid option to print guest UUIDs instead of names (RHBZ#646821).
[libguestfs.git] / daemon / link.c
index 9129b5c..3766d8c 100644 (file)
@@ -21,6 +21,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <fcntl.h>
 #include <unistd.h>
 #include <limits.h>
 
 #include "actions.h"
 
 char *
-do_readlink (char *path)
+do_readlink (const char *path)
 {
   ssize_t r;
   char *ret;
   char link[PATH_MAX];
 
-  NEED_ROOT (return NULL);
-  ABS_PATH (path, return NULL);
-
   CHROOT_IN;
   r = readlink (path, link, sizeof link);
   CHROOT_OUT;
@@ -54,6 +52,56 @@ do_readlink (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 ("open: %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)
 {
@@ -62,10 +110,6 @@ _link (const char *flag, int symbolic, const char *target, const char *linkname)
   char *buf_linkname;
   char *buf_target;
 
-  NEED_ROOT (return -1);
-  ABS_PATH (linkname, return -1);
-  /* but target does not need to be absolute */
-
   /* Prefix linkname with sysroot. */
   buf_linkname = sysroot_path (linkname);
   if (!buf_linkname) {
@@ -113,25 +157,25 @@ _link (const char *flag, int symbolic, const char *target, const char *linkname)
 }
 
 int
-do_ln (char *target, char *linkname)
+do_ln (const char *target, const char *linkname)
 {
   return _link (NULL, 0, target, linkname);
 }
 
 int
-do_ln_f (char *target, char *linkname)
+do_ln_f (const char *target, const char *linkname)
 {
   return _link ("-f", 0, target, linkname);
 }
 
 int
-do_ln_s (char *target, char *linkname)
+do_ln_s (const char *target, const char *linkname)
 {
   return _link ("-s", 1, target, linkname);
 }
 
 int
-do_ln_sf (char *target, char *linkname)
+do_ln_sf (const char *target, const char *linkname)
 {
   return _link ("-sf", 1, target, linkname);
 }