guestfs_readlinklist: Reimplement to avoid protocol limits.

This commit is contained in:
Richard W.M. Jones
2012-08-17 13:10:53 +01:00
parent dc66dd32c2
commit 8ee5190768
4 changed files with 67 additions and 4 deletions

2
TODO
View File

@@ -564,5 +564,3 @@ These would be changed from daemon_functions to non_daemon_functions,
with the non-daemon versions implemented using guestfs_upload and
guestfs_download (and others). This change should be transparent from
the p.o.v of the API and ABI.
- guestfs_readlinklist

View File

@@ -53,7 +53,7 @@ do_readlink (const char *path)
}
char **
do_readlinklist (const char *path, char *const *names)
do_internal_readlinklist (const char *path, char *const *names)
{
int fd_cwd;
size_t i;

View File

@@ -2196,6 +2196,29 @@ list a directory contents without making many round-trips.
See also C<guestfs_lstatlist> for a similarly efficient call
for getting standard stats." };
{ defaults with
name = "readlinklist";
style = RStringList "links", [Pathname "path"; StringList "names"], [];
shortdesc = "readlink on multiple files";
longdesc = "\
This call allows you to do a C<readlink> operation
on multiple files, where all files are in the directory C<path>.
C<names> is the list of files from this directory.
On return you get a list of strings, with a one-to-one
correspondence to the C<names> list. Each string is the
value of the symbolic link.
If the C<readlink(2)> operation fails on any name, then
the corresponding result string is the empty string C<\"\">.
However the whole operation is completed even if there
were C<readlink(2)> errors, and so you can call this
function with names where you don't know if they are
symbolic links already (albeit slightly less efficient).
This call is intended for programs that want to efficiently
list a directory contents without making many round-trips." };
]
(* daemon_functions are any functions which cause some action
@@ -6379,9 +6402,10 @@ this call to fail. The caller must split up such requests
into smaller groups of names." };
{ defaults with
name = "readlinklist";
name = "internal_readlinklist";
style = RStringList "links", [Pathname "path"; StringList "names"], [];
proc_nr = Some 206;
in_docs = false; in_fish = false;
shortdesc = "readlink on multiple files";
longdesc = "\
This call allows you to do a C<readlink> operation

View File

@@ -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;
}