diff options
author | Richard W.M. Jones <rjones@redhat.com> | 2012-08-17 12:21:37 +0100 |
---|---|---|
committer | Richard W.M. Jones <rjones@redhat.com> | 2012-08-17 16:08:13 +0100 |
commit | dc66dd32c214db99467341caea0be517d2dd736f (patch) | |
tree | 82de6e3d7b60aa78095892d7152bc8e38acadab4 /cat | |
parent | 118932fbeac606919f8b96c81184f4f3e0910508 (diff) | |
download | libguestfs-dc66dd32c214db99467341caea0be517d2dd736f.tar.gz libguestfs-dc66dd32c214db99467341caea0be517d2dd736f.tar.xz libguestfs-dc66dd32c214db99467341caea0be517d2dd736f.zip |
guestfs_lstatlist, guestfs_lxattrlist: Reimplement to avoid protocol limits.
Note that the code to do this was already in virt-ls, so this is
change is mostly just moving the code into the core library.
Diffstat (limited to 'cat')
-rw-r--r-- | cat/virt-ls.c | 175 |
1 files changed, 8 insertions, 167 deletions
diff --git a/cat/virt-ls.c b/cat/virt-ls.c index 771148c3..9e64e240 100644 --- a/cat/virt-ls.c +++ b/cat/virt-ls.c @@ -86,9 +86,7 @@ static int is_fifo (int64_t mode); static int is_lnk (int64_t mode); static int is_sock (int64_t mode); -static size_t count_strings (char **); static void free_strings (char **); -static char **take_strings (char **, size_t n, char ***); static inline char * bad_cast (char const *s) @@ -467,8 +465,6 @@ do_ls_R (const char *dir) https://rwmj.wordpress.com/2010/12/15/tip-audit-virtual-machine-for-setuid-files/ */ static char *full_path (const char *dir, const char *name); -static struct guestfs_stat_list *lstatlist (const char *dir, char **names); -static struct guestfs_xattr_list *lxattrlist (const char *dir, char **names); static int show_file (const char *dir, const char *name, const struct guestfs_stat *stat, const struct guestfs_xattr_list *xattrs); typedef int (*visitor_function) (const char *dir, const char *name, const struct guestfs_stat *stat, const struct guestfs_xattr_list *xattrs); @@ -514,11 +510,11 @@ visit (int depth, const char *dir, visitor_function f) if (names == NULL) goto out; - stats = lstatlist (dir, names); + stats = guestfs_lstatlist (g, dir, names); if (stats == NULL) goto out; - xattrs = lxattrlist (dir, names); + xattrs = guestfs_lxattrlist (g, dir, names); if (xattrs == NULL) goto out; @@ -538,8 +534,12 @@ visit (int depth, const char *dir, visitor_function f) program_name, dir, names[i]); goto out; } - /* lxattrlist function made sure attrval was \0-terminated, so we can do */ - if (sscanf (xattrs->val[xattrp].attrval, "%zu", &nr_xattrs) != 1) { + /* attrval is not \0-terminated. */ + char attrval[xattrs->val[xattrp].attrval_len+1]; + memcpy (attrval, xattrs->val[xattrp].attrval, + xattrs->val[xattrp].attrval_len); + attrval[xattrs->val[xattrp].attrval_len] = '\0'; + if (sscanf (attrval, "%zu", &nr_xattrs) != 1) { fprintf (stderr, _("%s: error: cannot parse xattr count for %s %s\n"), program_name, dir, names[i]); goto out; @@ -596,129 +596,6 @@ full_path (const char *dir, const char *name) return path; } -/* This calls guestfs_lstatlist, but it splits the names list up so that we - * don't overrun the libguestfs protocol limit. - */ -#define LSTATLIST_MAX 1000 - -static struct guestfs_stat_list * -lstatlist (const char *dir, char **names) -{ - size_t len = count_strings (names); - char **first; - size_t old_len; - struct guestfs_stat_list *ret, *stats; - - ret = malloc (sizeof *ret); - if (ret == NULL) { - perror ("malloc"); - exit (EXIT_FAILURE); - } - ret->len = 0; - ret->val = NULL; - - while (len > 0) { - first = take_strings (names, LSTATLIST_MAX, &names); - len = len <= LSTATLIST_MAX ? 0 : len - LSTATLIST_MAX; - - stats = guestfs_lstatlist (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 (stats == NULL) { - free (ret); - return NULL; - } - - /* Append stats to ret. */ - old_len = ret->len; - ret->len += stats->len; - ret->val = realloc (ret->val, ret->len * sizeof (struct guestfs_stat)); - if (ret->val == NULL) { - perror ("realloc"); - exit (EXIT_FAILURE); - } - memcpy (&ret->val[old_len], stats->val, - stats->len * sizeof (struct guestfs_stat)); - - guestfs_free_stat_list (stats); - } - - return ret; -} - -/* Same as above, for lxattrlist. Note the rather peculiar format - * used to return the list of extended attributes (see - * guestfs_lxattrlist documentation). - */ -#define LXATTRLIST_MAX 1000 - -static struct guestfs_xattr_list * -lxattrlist (const char *dir, char **names) -{ - size_t len = count_strings (names); - char **first; - size_t i, old_len; - struct guestfs_xattr_list *ret, *xattrs; - - ret = malloc (sizeof *ret); - if (ret == NULL) { - perror ("malloc"); - exit (EXIT_FAILURE); - } - ret->len = 0; - ret->val = NULL; - - while (len > 0) { - first = take_strings (names, LXATTRLIST_MAX, &names); - len = len <= LXATTRLIST_MAX ? 0 : len - LXATTRLIST_MAX; - - xattrs = guestfs_lxattrlist (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 (xattrs == NULL) { - free (ret); - return NULL; - } - - /* Append xattrs to ret. */ - old_len = ret->len; - ret->len += xattrs->len; - ret->val = realloc (ret->val, ret->len * sizeof (struct guestfs_xattr)); - if (ret->val == NULL) { - perror ("realloc"); - exit (EXIT_FAILURE); - } - for (i = 0; i < xattrs->len; ++i, ++old_len) { - /* We have to make a deep copy of the attribute name and value. - * The attrval contains 8 bit data. However make sure also that - * it is \0-terminated, because that makes the calling code - * simpler. - */ - ret->val[old_len].attrname = strdup (xattrs->val[i].attrname); - ret->val[old_len].attrval = malloc (xattrs->val[i].attrval_len + 1); - if (ret->val[old_len].attrname == NULL || - ret->val[old_len].attrval == NULL) { - perror ("malloc"); - exit (EXIT_FAILURE); - } - ret->val[old_len].attrval_len = xattrs->val[i].attrval_len; - memcpy (ret->val[old_len].attrval, xattrs->val[i].attrval, - xattrs->val[i].attrval_len); - ret->val[i].attrval[ret->val[i].attrval_len] = '\0'; - } - - guestfs_free_xattr_list (xattrs); - } - - return ret; -} - static int do_ls_lR (const char *dir) { @@ -1095,16 +972,6 @@ is_sock (int64_t mode) } /* String functions. */ -static size_t -count_strings (char **names) -{ - size_t ret = 0; - - while (names[ret] != NULL) - ret++; - return ret; -} - static void free_strings (char **names) { @@ -1114,29 +981,3 @@ free_strings (char **names) free (names[i]); free (names); } - -/* Take the first 'n' names, returning a newly allocated list. The - * strings themselves are not duplicated. If 'lastp' is not NULL, - * then it is updated with the pointer to the list of remaining names. - */ -static char ** -take_strings (char **names, size_t n, char ***lastp) -{ - size_t i; - - char **ret = malloc ((n+1) * sizeof (char *)); - if (ret == NULL) { - perror ("malloc"); - exit (EXIT_FAILURE); - } - - for (i = 0; names[i] != NULL && i < n; ++i) - ret[i] = names[i]; - - ret[i] = NULL; - - if (lastp) - *lastp = &names[i]; - - return ret; -} |