extern char **do_aug_match (const char *path);
extern int do_aug_save (void);
extern int do_aug_load (void);
+extern char **do_aug_ls (const char *path);
reply (NULL, NULL);
}
+static void aug_ls_stub (XDR *xdr_in)
+{
+ char **r;
+ struct guestfs_aug_ls_args args;
+ const char *path;
+
+ memset (&args, 0, sizeof args);
+
+ if (!xdr_guestfs_aug_ls_args (xdr_in, &args)) {
+ reply_with_error ("%s: daemon failed to decode procedure arguments", "aug_ls");
+ return;
+ }
+ path = args.path;
+
+ r = do_aug_ls (path);
+ if (r == NULL)
+ /* do_aug_ls has already called reply_with_error, so just return */
+ return;
+
+ struct guestfs_aug_ls_ret ret;
+ ret.matches.matches_len = count_strings (r);
+ ret.matches.matches_val = r;
+ reply ((xdrproc_t) &xdr_guestfs_aug_ls_ret, (char *) &ret);
+ free_strings (r);
+}
+
void dispatch_incoming_message (XDR *xdr_in)
{
switch (proc_nr) {
case GUESTFS_PROC_AUG_LOAD:
aug_load_stub (xdr_in);
break;
+ case GUESTFS_PROC_AUG_LS:
+ aug_ls_stub (xdr_in);
+ break;
default:
reply_with_error ("dispatch_incoming_message: unknown procedure number %d", proc_nr);
}
printf ("%-20s %s\n", "aug-init", "create a new Augeas handle");
printf ("%-20s %s\n", "aug-insert", "insert a sibling Augeas node");
printf ("%-20s %s\n", "aug-load", "load files into the tree");
+ printf ("%-20s %s\n", "aug-ls", "list Augeas nodes under a path");
printf ("%-20s %s\n", "aug-match", "return Augeas nodes which match path");
printf ("%-20s %s\n", "aug-mv", "move Augeas node");
printf ("%-20s %s\n", "aug-rm", "remove an Augeas path");
if (strcasecmp (cmd, "aug_load") == 0 || strcasecmp (cmd, "aug-load") == 0)
pod2text ("aug-load - load files into the tree", " aug-load\n\nLoad files into the tree.\n\nSee C<aug_load> in the Augeas documentation for the full gory\ndetails.");
else
+ if (strcasecmp (cmd, "aug_ls") == 0 || strcasecmp (cmd, "aug-ls") == 0)
+ pod2text ("aug-ls - list Augeas nodes under a path", " aug-ls <path>\n\nThis is just a shortcut for listing C<aug_match>\nC<path/*> and sorting the files into alphabetical order.");
+ else
display_builtin_command (cmd);
}
return r;
}
+static int run_aug_ls (const char *cmd, int argc, char *argv[])
+{
+ char **r;
+ const char *path;
+ if (argc != 1) {
+ fprintf (stderr, "%s should have 1 parameter(s)\n", cmd);
+ fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+ return -1;
+ }
+ path = argv[0];
+ r = guestfs_aug_ls (g, path);
+ if (r == NULL) return -1;
+ print_strings (r);
+ free_strings (r);
+ return 0;
+}
+
int run_action (const char *cmd, int argc, char *argv[])
{
if (strcasecmp (cmd, "launch") == 0 || strcasecmp (cmd, "run") == 0)
if (strcasecmp (cmd, "aug_load") == 0 || strcasecmp (cmd, "aug-load") == 0)
return run_aug_load (cmd, argc, argv);
else
+ if (strcasecmp (cmd, "aug_ls") == 0 || strcasecmp (cmd, "aug-ls") == 0)
+ return run_aug_ls (cmd, argc, argv);
+ else
{
fprintf (stderr, "%s: unknown command\n", cmd);
return -1;
See C<aug_load> in the Augeas documentation for the full gory
details.
+=head2 aug-ls
+
+ aug-ls path
+
+This is just a shortcut for listing C<aug_match>
+C<path/*> and sorting the files into alphabetical order.
+
=head2 aug-match
aug-match path
This function returns 0 on success or -1 on error.
+=head2 guestfs_aug_ls
+
+ char **guestfs_aug_ls (guestfs_h *handle,
+ const char *path);
+
+This is just a shortcut for listing C<guestfs_aug_match>
+C<path/*> and sorting the files into alphabetical order.
+
+This function returns a NULL-terminated array of strings
+(like L<environ(3)>), or NULL if there was an error.
+I<The caller must free the strings and the array after use>.
+
=head2 guestfs_aug_match
char **guestfs_aug_match (guestfs_h *handle,
external aug_match : t -> string -> string array = "ocaml_guestfs_aug_match"
external aug_save : t -> unit = "ocaml_guestfs_aug_save"
external aug_load : t -> unit = "ocaml_guestfs_aug_load"
+external aug_ls : t -> string -> string array = "ocaml_guestfs_aug_ls"
val aug_load : t -> unit
(** load files into the tree *)
+val aug_ls : t -> string -> string array
+(** list Augeas nodes under a path *)
+
CAMLreturn (rv);
}
+CAMLprim value
+ocaml_guestfs_aug_ls (value gv, value pathv)
+{
+ CAMLparam2 (gv, pathv);
+ CAMLlocal1 (rv);
+
+ guestfs_h *g = Guestfs_val (gv);
+ if (g == NULL)
+ caml_failwith ("aug_ls: used handle after closing it");
+
+ const char *path = String_val (pathv);
+ int i;
+ char **r;
+
+ caml_enter_blocking_section ();
+ r = guestfs_aug_ls (g, path);
+ caml_leave_blocking_section ();
+ if (r == NULL)
+ ocaml_guestfs_raise_error (g, "aug_ls");
+
+ rv = caml_copy_string_array ((const char **) r);
+ for (i = 0; r[i] != NULL; ++i) free (r[i]);
+ free (r);
+ CAMLreturn (rv);
+}
+
if (guestfs_aug_load (g) == -1)
croak ("aug_load: %s", last_error);
+void
+aug_ls (g, path)
+ guestfs_h *g;
+ char *path;
+PREINIT:
+ char **matches;
+ int i, n;
+ PPCODE:
+ matches = guestfs_aug_ls (g, path);
+ if (matches == NULL)
+ croak ("aug_ls: %s", last_error);
+ for (n = 0; matches[n] != NULL; ++n) /**/;
+ EXTEND (SP, n);
+ for (i = 0; i < n; ++i) {
+ PUSHs (sv_2mortal (newSVpv (matches[i], 0)));
+ free (matches[i]);
+ }
+ free (matches);
+
See C<aug_load> in the Augeas documentation for the full gory
details.
+=item @matches = $h->aug_ls (path);
+
+This is just a shortcut for listing C<$h-E<gt>aug_match>
+C<path/*> and sorting the files into alphabetical order.
+
=item @matches = $h->aug_match (path);
Returns a list of paths which match the path expression C<path>.
return 0;
}
+struct aug_ls_rv {
+ int cb_done; /* flag to indicate callback was called */
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_aug_ls_ret ret;
+};
+
+static void aug_ls_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ struct aug_ls_rv *rv = (struct aug_ls_rv *) data;
+
+ if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+ error (g, "guestfs_aug_ls: failed to parse reply header");
+ return;
+ }
+ if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+ error (g, "guestfs_aug_ls: failed to parse reply error");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_aug_ls_ret (xdr, &rv->ret)) {
+ error (g, "guestfs_aug_ls: failed to parse reply");
+ return;
+ }
+ done:
+ rv->cb_done = 1;
+ main_loop.main_loop_quit (g);
+}
+
+char **guestfs_aug_ls (guestfs_h *g,
+ const char *path)
+{
+ struct guestfs_aug_ls_args args;
+ struct aug_ls_rv rv;
+ int serial;
+
+ if (g->state != READY) {
+ error (g, "guestfs_aug_ls called from the wrong state, %d != READY",
+ g->state);
+ return NULL;
+ }
+
+ memset (&rv, 0, sizeof rv);
+
+ args.path = (char *) path;
+ serial = dispatch (g, GUESTFS_PROC_AUG_LS,
+ (xdrproc_t) xdr_guestfs_aug_ls_args, (char *) &args);
+ if (serial == -1)
+ return NULL;
+
+ rv.cb_done = 0;
+ g->reply_cb_internal = aug_ls_cb;
+ g->reply_cb_internal_data = &rv;
+ main_loop.main_loop_run (g);
+ g->reply_cb_internal = NULL;
+ g->reply_cb_internal_data = NULL;
+ if (!rv.cb_done) {
+ error (g, "guestfs_aug_ls failed, see earlier error messages");
+ return NULL;
+ }
+
+ if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_AUG_LS, serial) == -1)
+ return NULL;
+
+ if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", rv.err.error);
+ return NULL;
+ }
+
+ /* caller will free this, but we need to add a NULL entry */
+ rv.ret.matches.matches_val = safe_realloc (g, rv.ret.matches.matches_val,
+ sizeof (char *) * (rv.ret.matches.matches_len + 1));
+ rv.ret.matches.matches_val[rv.ret.matches.matches_len] = NULL;
+ return rv.ret.matches.matches_val;
+}
+
extern char **guestfs_aug_match (guestfs_h *handle, const char *path);
extern int guestfs_aug_save (guestfs_h *handle);
extern int guestfs_aug_load (guestfs_h *handle);
+extern char **guestfs_aug_ls (guestfs_h *handle, const char *path);
}
bool_t
+xdr_guestfs_aug_ls_args (XDR *xdrs, guestfs_aug_ls_args *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_string (xdrs, &objp->path, ~0))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_aug_ls_ret (XDR *xdrs, guestfs_aug_ls_ret *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_array (xdrs, (char **)&objp->matches.matches_val, (u_int *) &objp->matches.matches_len, ~0,
+ sizeof (str), (xdrproc_t) xdr_str))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
xdr_guestfs_procedure (XDR *xdrs, guestfs_procedure *objp)
{
register int32_t *buf;
};
typedef struct guestfs_aug_match_ret guestfs_aug_match_ret;
+struct guestfs_aug_ls_args {
+ char *path;
+};
+typedef struct guestfs_aug_ls_args guestfs_aug_ls_args;
+
+struct guestfs_aug_ls_ret {
+ struct {
+ u_int matches_len;
+ str *matches_val;
+ } matches;
+};
+typedef struct guestfs_aug_ls_ret guestfs_aug_ls_ret;
+
enum guestfs_procedure {
GUESTFS_PROC_MOUNT = 1,
GUESTFS_PROC_SYNC = 2,
GUESTFS_PROC_AUG_MATCH = 24,
GUESTFS_PROC_AUG_SAVE = 25,
GUESTFS_PROC_AUG_LOAD = 27,
- GUESTFS_PROC_dummy = 27 + 1,
+ GUESTFS_PROC_AUG_LS = 28,
+ GUESTFS_PROC_dummy = 28 + 1,
};
typedef enum guestfs_procedure guestfs_procedure;
#define GUESTFS_MESSAGE_MAX 4194304
extern bool_t xdr_guestfs_aug_mv_args (XDR *, guestfs_aug_mv_args*);
extern bool_t xdr_guestfs_aug_match_args (XDR *, guestfs_aug_match_args*);
extern bool_t xdr_guestfs_aug_match_ret (XDR *, guestfs_aug_match_ret*);
+extern bool_t xdr_guestfs_aug_ls_args (XDR *, guestfs_aug_ls_args*);
+extern bool_t xdr_guestfs_aug_ls_ret (XDR *, guestfs_aug_ls_ret*);
extern bool_t xdr_guestfs_procedure (XDR *, guestfs_procedure*);
extern bool_t xdr_guestfs_message_direction (XDR *, guestfs_message_direction*);
extern bool_t xdr_guestfs_message_status (XDR *, guestfs_message_status*);
extern bool_t xdr_guestfs_aug_mv_args ();
extern bool_t xdr_guestfs_aug_match_args ();
extern bool_t xdr_guestfs_aug_match_ret ();
+extern bool_t xdr_guestfs_aug_ls_args ();
+extern bool_t xdr_guestfs_aug_ls_ret ();
extern bool_t xdr_guestfs_procedure ();
extern bool_t xdr_guestfs_message_direction ();
extern bool_t xdr_guestfs_message_status ();
str matches<>;
};
+struct guestfs_aug_ls_args {
+ string path<>;
+};
+
+struct guestfs_aug_ls_ret {
+ str matches<>;
+};
+
enum guestfs_procedure {
GUESTFS_PROC_MOUNT = 1,
GUESTFS_PROC_SYNC = 2,
GUESTFS_PROC_AUG_MATCH = 24,
GUESTFS_PROC_AUG_SAVE = 25,
GUESTFS_PROC_AUG_LOAD = 27,
+ GUESTFS_PROC_AUG_LS = 28,
GUESTFS_PROC_dummy
};