diff options
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | daemon/link.c | 2 | ||||
-rw-r--r-- | generator/generator_actions.ml | 26 | ||||
-rw-r--r-- | src/file.c | 41 |
4 files changed, 67 insertions, 4 deletions
@@ -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 diff --git a/daemon/link.c b/daemon/link.c index c4cdfe1d..4536f007 100644 --- a/daemon/link.c +++ b/daemon/link.c @@ -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; diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml index 5e776519..9c45a663 100644 --- a/generator/generator_actions.ml +++ b/generator/generator_actions.ml @@ -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 @@ -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; +} |