summaryrefslogtreecommitdiffstats
path: root/src/file.c
diff options
context:
space:
mode:
authorRichard W.M. Jones <rjones@redhat.com>2012-08-17 13:10:53 +0100
committerRichard W.M. Jones <rjones@redhat.com>2012-08-17 16:08:13 +0100
commit8ee51907685d6db92031e84d249ea3bb4cdc2d67 (patch)
tree9fe65ebb3e25172e7ebc172e0b61298af762d37e /src/file.c
parentdc66dd32c214db99467341caea0be517d2dd736f (diff)
downloadlibguestfs-8ee51907685d6db92031e84d249ea3bb4cdc2d67.tar.gz
libguestfs-8ee51907685d6db92031e84d249ea3bb4cdc2d67.tar.xz
libguestfs-8ee51907685d6db92031e84d249ea3bb4cdc2d67.zip
guestfs_readlinklist: Reimplement to avoid protocol limits.
Diffstat (limited to 'src/file.c')
-rw-r--r--src/file.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/src/file.c b/src/file.c
index dabd1b21..71b208d3 100644
--- a/src/file.c
+++ b/src/file.c
@@ -494,3 +494,44 @@ guestfs__lxattrlist (guestfs_h *g, const char *dir, char *const *names)
return ret;
}
+
+#define READLINK_MAX 1000
+
+char **
+guestfs__readlinklist (guestfs_h *g, const char *dir, char *const *names)
+{
+ size_t len = count_strings (names);
+ char **first;
+ size_t old_len, ret_len = 0;
+ char **ret = NULL, **links;
+
+ while (len > 0) {
+ first = take_strings (g, names, READLINK_MAX, &names);
+ len = len <= READLINK_MAX ? 0 : len - READLINK_MAX;
+
+ links = guestfs_internal_readlinklist (g, dir, first);
+ /* Note we don't need to free up the strings because take_strings
+ * does not do a deep copy.
+ */
+ free (first);
+
+ if (links == NULL) {
+ guestfs___free_string_list (ret);
+ return NULL;
+ }
+
+ /* Append links to ret. */
+ old_len = ret_len;
+ ret_len += count_strings (links);
+ ret = safe_realloc (g, ret, ret_len * sizeof (char *));
+ memcpy (&ret[old_len], links, (ret_len-old_len) * sizeof (char *));
+
+ free (links);
+ }
+
+ /* NULL-terminate the list. */
+ ret = safe_realloc (g, ret, (ret_len+1) * sizeof (char *));
+ ret[ret_len] = NULL;
+
+ return ret;
+}