summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRichard Jones <rjones@redhat.com>2009-04-07 06:50:31 +0100
committerRichard Jones <rjones@redhat.com>2009-04-07 09:14:17 +0100
commit73d6932ab2dd3f9120a1f4a532621c07cb174705 (patch)
tree8c24e36ca7c776611bc2278954b20b59143784b1 /src
parent8e570870f577ff0c3db074f88924633b559af5d4 (diff)
downloadlibguestfs-73d6932ab2dd3f9120a1f4a532621c07cb174705.tar.gz
libguestfs-73d6932ab2dd3f9120a1f4a532621c07cb174705.tar.xz
libguestfs-73d6932ab2dd3f9120a1f4a532621c07cb174705.zip
pvs/vgs/lvs commands working now.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rwxr-xr-xsrc/generator.ml509
-rw-r--r--src/guestfs-actions.c213
-rw-r--r--src/guestfs-actions.h3
-rw-r--r--src/guestfs-structs.h94
-rw-r--r--src/guestfs.c61
-rw-r--r--src/guestfs.h5
-rw-r--r--src/guestfs_protocol.c188
-rw-r--r--src/guestfs_protocol.h114
-rw-r--r--src/guestfs_protocol.x85
10 files changed, 1259 insertions, 15 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 566fa410..7a4e360a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -23,7 +23,7 @@ EXTRA_DIST += guestfs_protocol.x \
guestfs_protocol.c \
guestfs_protocol.h
-include_HEADERS = guestfs.h guestfs-actions.h
+include_HEADERS = guestfs.h guestfs-actions.h guestfs-structs.h
lib_LTLIBRARIES = libguestfs.la
diff --git a/src/generator.ml b/src/generator.ml
index 12c51fc8..8d1dc046 100755
--- a/src/generator.ml
+++ b/src/generator.ml
@@ -1,4 +1,4 @@
-#!/usr/bin/ocamlrun ocaml
+#!/usr/bin/env ocaml
(* libguestfs
* Copyright (C) 2009 Red Hat Inc.
*
@@ -37,6 +37,10 @@ and ret =
*)
| RString of string
| RStringList of string
+ (* LVM PVs, VGs and LVs. *)
+ | RPVList of string
+ | RVGList of string
+ | RLVList of string
and args =
(* 0 arguments, 1 argument, etc. The guestfs_h param is implicit. *)
| P0
@@ -130,6 +134,87 @@ The full partition device names are returned, eg. C</dev/sda1>
This does not return logical volumes. For that you will need to
call C<guestfs_lvs>.");
+
+ ("pvs", (RPVList "physvols", P0), 9, [],
+ "list the LVM physical volumes (PVs)",
+ "\
+List all the physical volumes detected. This is the equivalent
+of the L<pvs(8)> command.");
+
+ ("vgs", (RVGList "volgroups", P0), 10, [],
+ "list the LVM volume groups (VGs)",
+ "\
+List all the volumes groups detected. This is the equivalent
+of the L<vgs(8)> command.");
+
+ ("lvs", (RLVList "logvols", P0), 11, [],
+ "list the LVM logical volumes (LVs)",
+ "\
+List all the logical volumes detected. This is the equivalent
+of the L<lvs(8)> command.");
+]
+
+(* Column names and types from LVM PVs/VGs/LVs. *)
+let pv_cols = [
+ "pv_name", `String;
+ "pv_uuid", `UUID;
+ "pv_fmt", `String;
+ "pv_size", `Bytes;
+ "dev_size", `Bytes;
+ "pv_free", `Bytes;
+ "pv_used", `Bytes;
+ "pv_attr", `String (* XXX *);
+ "pv_pe_count", `Int;
+ "pv_pe_alloc_count", `Int;
+ "pv_tags", `String;
+ "pe_start", `Bytes;
+ "pv_mda_count", `Int;
+ "pv_mda_free", `Bytes;
+(* Not in Fedora 10:
+ "pv_mda_size", `Bytes;
+*)
+]
+let vg_cols = [
+ "vg_name", `String;
+ "vg_uuid", `UUID;
+ "vg_fmt", `String;
+ "vg_attr", `String (* XXX *);
+ "vg_size", `Bytes;
+ "vg_free", `Bytes;
+ "vg_sysid", `String;
+ "vg_extent_size", `Bytes;
+ "vg_extent_count", `Int;
+ "vg_free_count", `Int;
+ "max_lv", `Int;
+ "max_pv", `Int;
+ "pv_count", `Int;
+ "lv_count", `Int;
+ "snap_count", `Int;
+ "vg_seqno", `Int;
+ "vg_tags", `String;
+ "vg_mda_count", `Int;
+ "vg_mda_free", `Bytes;
+(* Not in Fedora 10:
+ "vg_mda_size", `Bytes;
+*)
+]
+let lv_cols = [
+ "lv_name", `String;
+ "lv_uuid", `UUID;
+ "lv_attr", `String (* XXX *);
+ "lv_major", `Int;
+ "lv_minor", `Int;
+ "lv_kernel_major", `Int;
+ "lv_kernel_minor", `Int;
+ "lv_size", `Bytes;
+ "seg_count", `Int;
+ "origin", `String;
+ "snap_percent", `OptPercent;
+ "copy_percent", `OptPercent;
+ "move_pv", `String;
+ "lv_tags", `String;
+ "mirror_log", `String;
+ "modules", `String;
]
(* In some places we want the functions to be displayed sorted
@@ -250,7 +335,7 @@ let rec generate_header comment license =
pr "\n"
(* Generate the pod documentation for the C API. *)
-and generate_pod () =
+and generate_actions_pod () =
List.iter (
fun (shortname, style, _, flags, _, longdesc) ->
let name = "guestfs_" ^ shortname in
@@ -269,6 +354,15 @@ I<The caller must free the returned string after use>.\n\n"
pr "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>.\n\n"
+ | RPVList _ ->
+ pr "This function returns a C<struct guestfs_lvm_pv_list>.
+I<The caller must call C<guestfs_free_lvm_pv_list> after use.>.\n\n"
+ | RVGList _ ->
+ pr "This function returns a C<struct guestfs_lvm_vg_list>.
+I<The caller must call C<guestfs_free_lvm_vg_list> after use.>.\n\n"
+ | RLVList _ ->
+ pr "This function returns a C<struct guestfs_lvm_lv_list>.
+I<The caller must call C<guestfs_free_lvm_lv_list> after use.>.\n\n"
);
if List.mem ProtocolLimitWarning flags then
pr "Because of the message protocol, there is a transfer limit
@@ -276,7 +370,43 @@ of somewhere between 2MB and 4MB. To transfer large files you should use
FTP.\n\n";
) sorted_functions
-(* Generate the protocol (XDR) file. *)
+and generate_structs_pod () =
+ (* LVM structs documentation. *)
+ List.iter (
+ fun (typ, cols) ->
+ pr "=head2 guestfs_lvm_%s\n" typ;
+ pr "\n";
+ pr " struct guestfs_lvm_%s {\n" typ;
+ List.iter (
+ function
+ | name, `String -> pr " char *%s;\n" name
+ | name, `UUID ->
+ pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
+ pr " char %s[32];\n" name
+ | name, `Bytes -> pr " uint64_t %s;\n" name
+ | name, `Int -> pr " int64_t %s;\n" name
+ | name, `OptPercent ->
+ pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
+ pr " float %s;\n" name
+ ) cols;
+ pr " \n";
+ pr " struct guestfs_lvm_%s_list {\n" typ;
+ pr " uint32_t len; /* Number of elements in list. */\n";
+ pr " struct guestfs_lvm_%s *val; /* Elements. */\n" typ;
+ pr " };\n";
+ pr " \n";
+ pr " void guestfs_free_lvm_%s_list (struct guestfs_free_lvm_%s_list *);\n"
+ typ typ;
+ pr "\n"
+ ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols]
+
+(* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
+ * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'. We
+ * have to use an underscore instead of a dash because otherwise
+ * rpcgen generates incorrect code.
+ *
+ * This header is NOT exported to clients, but see also generate_structs_h.
+ *)
and generate_xdr () =
generate_header CStyle LGPLv2;
@@ -284,6 +414,24 @@ and generate_xdr () =
pr "typedef string str<>;\n";
pr "\n";
+ (* LVM internal structures. *)
+ List.iter (
+ function
+ | typ, cols ->
+ pr "struct guestfs_lvm_int_%s {\n" typ;
+ List.iter (function
+ | name, `String -> pr " string %s<>;\n" name
+ | name, `UUID -> pr " opaque %s[32];\n" name
+ | name, `Bytes -> pr " hyper %s;\n" name
+ | name, `Int -> pr " hyper %s;\n" name
+ | name, `OptPercent -> pr " float %s;\n" name
+ ) cols;
+ pr "};\n";
+ pr "\n";
+ pr "typedef struct guestfs_lvm_int_%s guestfs_lvm_int_%s_list<>;\n" typ typ;
+ pr "\n";
+ ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols];
+
List.iter (
fun (shortname, style, _, _, _, _) ->
let name = "guestfs_" ^ shortname in
@@ -308,6 +456,18 @@ and generate_xdr () =
pr "struct %s_ret {\n" name;
pr " str %s<>;\n" n;
pr "};\n\n"
+ | RPVList n ->
+ pr "struct %s_ret {\n" name;
+ pr " guestfs_lvm_int_pv_list %s;\n" n;
+ pr "};\n\n"
+ | RVGList n ->
+ pr "struct %s_ret {\n" name;
+ pr " guestfs_lvm_int_vg_list %s;\n" n;
+ pr "};\n\n"
+ | RLVList n ->
+ pr "struct %s_ret {\n" name;
+ pr " guestfs_lvm_int_lv_list %s;\n" n;
+ pr "};\n\n"
);
) functions;
@@ -361,6 +521,46 @@ struct guestfs_message_header {
};
"
+(* Generate the guestfs-structs.h file. *)
+and generate_structs_h () =
+ generate_header CStyle LGPLv2;
+
+ (* This is a public exported header file containing various
+ * structures. The structures are carefully written to have
+ * exactly the same in-memory format as the XDR structures that
+ * we use on the wire to the daemon. The reason for creating
+ * copies of these structures here is just so we don't have to
+ * export the whole of guestfs_protocol.h (which includes much
+ * unrelated and XDR-dependent stuff that we don't want to be
+ * public, or required by clients).
+ *
+ * To reiterate, we will pass these structures to and from the
+ * client with a simple assignment or memcpy, so the format
+ * must be identical to what rpcgen / the RFC defines.
+ *)
+
+ (* LVM public structures. *)
+ List.iter (
+ function
+ | typ, cols ->
+ pr "struct guestfs_lvm_%s {\n" typ;
+ List.iter (
+ function
+ | name, `String -> pr " char *%s;\n" name
+ | name, `UUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
+ | name, `Bytes -> pr " uint64_t %s;\n" name
+ | name, `Int -> pr " int64_t %s;\n" name
+ | name, `OptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
+ ) cols;
+ pr "};\n";
+ pr "\n";
+ pr "struct guestfs_lvm_%s_list {\n" typ;
+ pr " uint32_t len;\n";
+ pr " struct guestfs_lvm_%s *val;\n" typ;
+ pr "};\n";
+ pr "\n"
+ ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols]
+
(* Generate the guestfs-actions.h file. *)
and generate_actions_h () =
generate_header CStyle LGPLv2;
@@ -374,6 +574,8 @@ and generate_actions_h () =
(* Generate the client-side dispatch stubs. *)
and generate_client_actions () =
generate_header CStyle LGPLv2;
+
+ (* Client-side stubs for each function. *)
List.iter (
fun (shortname, style, _, _, _, _) ->
let name = "guestfs_" ^ shortname in
@@ -385,7 +587,8 @@ and generate_client_actions () =
pr " struct guestfs_message_error err;\n";
(match fst style with
| Err -> ()
- | RString _ | RStringList _ -> pr " struct %s_ret ret;\n" name;
+ | RString _ | RStringList _ | RPVList _ | RVGList _ | RLVList _ ->
+ pr " struct %s_ret ret;\n" name
);
pr "};\n\n";
@@ -408,7 +611,7 @@ and generate_client_actions () =
(match fst style with
| Err -> ()
- | RString _ | RStringList _ ->
+ | RString _ | RStringList _ | RPVList _ | RVGList _ | RLVList _ ->
pr " if (!xdr_%s_ret (xdr, &rv->ret)) {\n" name;
pr " error (g, \"%s: failed to parse reply\");\n" name;
pr " return;\n";
@@ -427,7 +630,8 @@ and generate_client_actions () =
let error_code =
match fst style with
| Err -> "-1"
- | RString _ | RStringList _ -> "NULL" in
+ | RString _ | RStringList _ | RPVList _ | RVGList _ | RLVList _ ->
+ "NULL" in
pr "{\n";
@@ -499,6 +703,15 @@ and generate_client_actions () =
pr " rv.ret.%s.%s_val = safe_realloc (g, rv.ret.%s.%s_val, rv.ret.%s.%s_len + 1);\n" n n n n n n;
pr " rv.ret.%s.%s_val[rv.ret.%s.%s_len] = NULL;\n" n n n n;
pr " return rv.ret.%s.%s_val;\n" n n
+ | RPVList n ->
+ pr " /* caller will free this */\n";
+ pr " return safe_memdup (g, &rv.ret.%s, sizeof (rv.ret.%s));\n" n n
+ | RVGList n ->
+ pr " /* caller will free this */\n";
+ pr " return safe_memdup (g, &rv.ret.%s, sizeof (rv.ret.%s));\n" n n
+ | RLVList n ->
+ pr " /* caller will free this */\n";
+ pr " return safe_memdup (g, &rv.ret.%s, sizeof (rv.ret.%s));\n" n n
);
pr "}\n\n"
@@ -507,17 +720,30 @@ and generate_client_actions () =
(* Generate daemon/actions.h. *)
and generate_daemon_actions_h () =
generate_header CStyle GPLv2;
+
+ pr "#include \"../src/guestfs_protocol.h\"\n";
+ pr "\n";
+
List.iter (
fun (name, style, _, _, _, _) ->
- generate_prototype ~single_line:true ~newline:true ("do_" ^ name) style;
+ generate_prototype
+ ~single_line:true ~newline:true ~in_daemon:true ("do_" ^ name) style;
) functions
(* Generate the server-side stubs. *)
and generate_daemon_actions () =
generate_header CStyle GPLv2;
+ pr "#define _GNU_SOURCE // for strchrnul\n";
+ pr "\n";
+ pr "#include <stdio.h>\n";
+ pr "#include <stdlib.h>\n";
+ pr "#include <string.h>\n";
+ pr "#include <inttypes.h>\n";
+ pr "#include <ctype.h>\n";
pr "#include <rpc/types.h>\n";
pr "#include <rpc/xdr.h>\n";
+ pr "\n";
pr "#include \"daemon.h\"\n";
pr "#include \"../src/guestfs_protocol.h\"\n";
pr "#include \"actions.h\"\n";
@@ -532,7 +758,11 @@ and generate_daemon_actions () =
match fst style with
| Err -> pr " int r;\n"; "-1"
| RString _ -> pr " char *r;\n"; "NULL"
- | RStringList _ -> pr " char **r;\n"; "NULL" in
+ | RStringList _ -> pr " char **r;\n"; "NULL"
+ | RPVList _ -> pr " guestfs_lvm_int_pv_list *r;\n"; "NULL"
+ | RVGList _ -> pr " guestfs_lvm_int_vg_list *r;\n"; "NULL"
+ | RLVList _ -> pr " guestfs_lvm_int_lv_list *r;\n"; "NULL" in
+
(match snd style with
| P0 -> ()
| args ->
@@ -582,6 +812,21 @@ and generate_daemon_actions () =
pr " ret.%s.%s_val = r;\n" n n;
pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n" name;
pr " free_strings (r);\n"
+ | RPVList n ->
+ pr " struct guestfs_%s_ret ret;\n" name;
+ pr " ret.%s = *r;\n" n;
+ pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n" name;
+ pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n" name
+ | RVGList n ->
+ pr " struct guestfs_%s_ret ret;\n" name;
+ pr " ret.%s = *r;\n" n;
+ pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n" name;
+ pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n" name
+ | RLVList n ->
+ pr " struct guestfs_%s_ret ret;\n" name;
+ pr " ret.%s = *r;\n" n;
+ pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n" name;
+ pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n" name
);
pr "}\n\n";
@@ -602,7 +847,173 @@ and generate_daemon_actions () =
pr " default:\n";
pr " reply_with_error (\"dispatch_incoming_message: unknown procedure number %%d\", proc_nr);\n";
pr " }\n";
- pr "}\n"
+ pr "}\n";
+ pr "\n";
+
+ (* LVM columns and tokenization functions. *)
+ (* XXX This generates crap code. We should rethink how we
+ * do this parsing.
+ *)
+ List.iter (
+ function
+ | typ, cols ->
+ pr "static const char *lvm_%s_cols = \"%s\";\n"
+ typ (String.concat "," (List.map fst cols));
+ pr "\n";
+
+ pr "static int lvm_tokenize_%s (char *str, struct guestfs_lvm_int_%s *r)\n" typ typ;
+ pr "{\n";
+ pr " char *tok, *p, *next;\n";
+ pr " int i, j;\n";
+ pr "\n";
+ (*
+ pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
+ pr "\n";
+ *)
+ pr " if (!str) {\n";
+ pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
+ pr " return -1;\n";
+ pr " }\n";
+ pr " if (!*str || isspace (*str)) {\n";
+ pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
+ pr " return -1;\n";
+ pr " }\n";
+ pr " tok = str;\n";
+ List.iter (
+ fun (name, coltype) ->
+ pr " if (!tok) {\n";
+ pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
+ pr " return -1;\n";
+ pr " }\n";
+ pr " p = strchrnul (tok, ',');\n";
+ pr " if (*p) next = p+1; else next = NULL;\n";
+ pr " *p = '\\0';\n";
+ (match coltype with
+ | `String ->
+ pr " r->%s = strdup (tok);\n" name;
+ pr " if (r->%s == NULL) {\n" name;
+ pr " perror (\"strdup\");\n";
+ pr " return -1;\n";
+ pr " }\n"
+ | `UUID ->
+ pr " for (i = j = 0; i < 32; ++j) {\n";
+ pr " if (tok[j] == '\\0') {\n";
+ pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
+ pr " return -1;\n";
+ pr " } else if (tok[j] != '-')\n";
+ pr " r->%s[i++] = tok[j];\n" name;
+ pr " }\n";
+ | `Bytes ->
+ pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
+ pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
+ pr " return -1;\n";
+ pr " }\n";
+ | `Int ->
+ pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
+ pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
+ pr " return -1;\n";
+ pr " }\n";
+ | `OptPercent ->
+ pr " if (tok[0] == '\\0')\n";
+ pr " r->%s = -1;\n" name;
+ pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
+ pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
+ pr " return -1;\n";
+ pr " }\n";
+ );
+ pr " tok = next;\n";
+ ) cols;
+
+ pr " if (tok != NULL) {\n";
+ pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
+ pr " return -1;\n";
+ pr " }\n";
+ pr " return 0;\n";
+ pr "}\n";
+ pr "\n";
+
+ pr "guestfs_lvm_int_%s_list *\n" typ;
+ pr "parse_command_line_%ss (void)\n" typ;
+ pr "{\n";
+ pr " char *out, *err;\n";
+ pr " char *p, *pend;\n";
+ pr " int r, i;\n";
+ pr " guestfs_lvm_int_%s_list *ret;\n" typ;
+ pr " void *newp;\n";
+ pr "\n";
+ pr " ret = malloc (sizeof *ret);\n";
+ pr " if (!ret) {\n";
+ pr " reply_with_perror (\"malloc\");\n";
+ pr " return NULL;\n";
+ pr " }\n";
+ pr "\n";
+ pr " ret->guestfs_lvm_int_%s_list_len = 0;\n" typ;
+ pr " ret->guestfs_lvm_int_%s_list_val = NULL;\n" typ;
+ pr "\n";
+ pr " r = command (&out, &err,\n";
+ pr " \"/sbin/lvm\", \"%ss\",\n" typ;
+ pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
+ pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
+ pr " if (r == -1) {\n";
+ pr " reply_with_error (\"%%s\", err);\n";
+ pr " free (out);\n";
+ pr " free (err);\n";
+ pr " return NULL;\n";
+ pr " }\n";
+ pr "\n";
+ pr " free (err);\n";
+ pr "\n";
+ pr " /* Tokenize each line of the output. */\n";
+ pr " p = out;\n";
+ pr " i = 0;\n";
+ pr " while (p) {\n";
+ pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
+ pr " if (pend) {\n";
+ pr " *pend = '\\0';\n";
+ pr " pend++;\n";
+ pr " }\n";
+ pr "\n";
+ pr " while (*p && isspace (*p)) /* Skip any leading whitespace. */\n";
+ pr " p++;\n";
+ pr "\n";
+ pr " if (!*p) { /* Empty line? Skip it. */\n";
+ pr " p = pend;\n";
+ pr " continue;\n";
+ pr " }\n";
+ pr "\n";
+ pr " /* Allocate some space to store this next entry. */\n";
+ pr " newp = realloc (ret->guestfs_lvm_int_%s_list_val,\n" typ;
+ pr " sizeof (guestfs_lvm_int_%s) * (i+1));\n" typ;
+ pr " if (newp == NULL) {\n";
+ pr " reply_with_perror (\"realloc\");\n";
+ pr " free (ret->guestfs_lvm_int_%s_list_val);\n" typ;
+ pr " free (ret);\n";
+ pr " free (out);\n";
+ pr " return NULL;\n";
+ pr " }\n";
+ pr " ret->guestfs_lvm_int_%s_list_val = newp;\n" typ;
+ pr "\n";
+ pr " /* Tokenize the next entry. */\n";
+ pr " r = lvm_tokenize_%s (p, &ret->guestfs_lvm_int_%s_list_val[i]);\n" typ typ;
+ pr " if (r == -1) {\n";
+ pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
+ pr " free (ret->guestfs_lvm_int_%s_list_val);\n" typ;
+ pr " free (ret);\n";
+ pr " free (out);\n";
+ pr " return NULL;\n";
+ pr " }\n";
+ pr "\n";
+ pr " ++i;\n";
+ pr " p = pend;\n";
+ pr " }\n";
+ pr "\n";
+ pr " ret->guestfs_lvm_int_%s_list_len = i;\n" typ;
+ pr "\n";
+ pr " free (out);\n";
+ pr " return ret;\n";
+ pr "}\n"
+
+ ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols]
(* Generate a lot of different functions for guestfish. *)
and generate_fish_cmds () =
@@ -611,7 +1022,9 @@ and generate_fish_cmds () =
pr "#include <stdio.h>\n";
pr "#include <stdlib.h>\n";
pr "#include <string.h>\n";
+ pr "#include <inttypes.h>\n";
pr "\n";
+ pr "#include <guestfs.h>\n";
pr "#include \"fish.h\"\n";
pr "\n";
@@ -669,6 +1082,45 @@ FTP."
pr "}\n";
pr "\n";
+ (* print_{pv,vg,lv}_list functions *)
+ List.iter (
+ function
+ | typ, cols ->
+ pr "static void print_%s (struct guestfs_lvm_%s *%s)\n" typ typ typ;
+ pr "{\n";
+ pr " int i;\n";
+ pr "\n";
+ List.iter (
+ function
+ | name, `String ->
+ pr " printf (\"%s: %%s\\n\", %s->%s);\n" name typ name
+ | name, `UUID ->
+ pr " printf (\"%s: \");\n" name;
+ pr " for (i = 0; i < 32; ++i)\n";
+ pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
+ pr " printf (\"\\n\");\n"
+ | name, `Bytes ->
+ pr " printf (\"%s: %%\" PRIu64 \"\\n\", %s->%s);\n" name typ name
+ | name, `Int ->
+ pr " printf (\"%s: %%\" PRIi64 \"\\n\", %s->%s);\n" name typ name
+ | name, `OptPercent ->
+ pr " if (%s->%s >= 0) printf (\"%s: %%g %%%%\\n\", %s->%s);\n"
+ typ name name typ name;
+ pr " else printf (\"%s: \\n\");\n" name
+ ) cols;
+ pr "}\n";
+ pr "\n";
+ pr "static void print_%s_list (struct guestfs_lvm_%s_list *%ss)\n"
+ typ typ typ;
+ pr "{\n";
+ pr " int i;\n";
+ pr "\n";
+ pr " for (i = 0; i < %ss->len; ++i)\n" typ;
+ pr " print_%s (&%ss->val[i]);\n" typ typ;
+ pr "}\n";
+ pr "\n";
+ ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols];
+
(* run_<action> actions *)
List.iter (
fun (name, style, _, _, _, _) ->
@@ -678,6 +1130,9 @@ FTP."
| Err -> pr " int r;\n"
| RString _ -> pr " char *r;\n"
| RStringList _ -> pr " char **r;\n"
+ | RPVList _ -> pr " struct guestfs_lvm_pv_list *r;\n"
+ | RVGList _ -> pr " struct guestfs_lvm_vg_list *r;\n"
+ | RLVList _ -> pr " struct guestfs_lvm_lv_list *r;\n"
);
iter_args (
function
@@ -716,6 +1171,21 @@ FTP."
pr " print_strings (r);\n";
pr " free_strings (r);\n";
pr " return 0;\n"
+ | RPVList _ ->
+ pr " if (r == NULL) return -1;\n";
+ pr " print_pv_list (r);\n";
+ pr " guestfs_free_lvm_pv_list (r);\n";
+ pr " return 0;\n"
+ | RVGList _ ->
+ pr " if (r == NULL) return -1;\n";
+ pr " print_vg_list (r);\n";
+ pr " guestfs_free_lvm_vg_list (r);\n";
+ pr " return 0;\n"
+ | RLVList _ ->
+ pr " if (r == NULL) return -1;\n";
+ pr " print_lv_list (r);\n";
+ pr " guestfs_free_lvm_lv_list (r);\n";
+ pr " return 0;\n"
);
pr "}\n";
pr "\n"
@@ -745,7 +1215,7 @@ FTP."
(* Generate a C function prototype. *)
and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
- ?(single_line = false) ?(newline = false)
+ ?(single_line = false) ?(newline = false) ?(in_daemon = false)
?handle name style =
if extern then pr "extern ";
if static then pr "static ";
@@ -753,6 +1223,15 @@ and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
| Err -> pr "int "
| RString _ -> pr "char *"
| RStringList _ -> pr "char **"
+ | RPVList _ ->
+ if not in_daemon then pr "struct guestfs_lvm_pv_list *"
+ else pr "guestfs_lvm_int_pv_list *"
+ | RVGList _ ->
+ if not in_daemon then pr "struct guestfs_lvm_vg_list *"
+ else pr "guestfs_lvm_int_vg_list *"
+ | RLVList _ ->
+ if not in_daemon then pr "struct guestfs_lvm_lv_list *"
+ else pr "guestfs_lvm_int_lv_list *"
);
pr "%s (" name;
let comma = ref false in
@@ -810,6 +1289,10 @@ let () =
generate_xdr ();
close ();
+ let close = output_to "src/guestfs-structs.h" in
+ generate_structs_h ();
+ close ();
+
let close = output_to "src/guestfs-actions.h" in
generate_actions_h ();
close ();
@@ -830,6 +1313,10 @@ let () =
generate_fish_cmds ();
close ();
+ let close = output_to "guestfs-structs.pod" in
+ generate_structs_pod ();
+ close ();
+
let close = output_to "guestfs-actions.pod" in
- generate_pod ();
+ generate_actions_pod ();
close ()
diff --git a/src/guestfs-actions.c b/src/guestfs-actions.c
index d2ec0c76..83f5ec15 100644
--- a/src/guestfs-actions.c
+++ b/src/guestfs-actions.c
@@ -595,3 +595,216 @@ char **guestfs_list_partitions (guestfs_h *g)
return rv.ret.partitions.partitions_val;
}
+struct pvs_rv {
+ int cb_done; /* flag to indicate callback was called */
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_pvs_ret ret;
+};
+
+static void pvs_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ struct pvs_rv *rv = (struct pvs_rv *) data;
+
+ if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+ error (g, "guestfs_pvs: failed to parse reply header");
+ return;
+ }
+ if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+ error (g, "guestfs_pvs: failed to parse reply error");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_pvs_ret (xdr, &rv->ret)) {
+ error (g, "guestfs_pvs: failed to parse reply");
+ return;
+ }
+ done:
+ rv->cb_done = 1;
+ main_loop.main_loop_quit (g);
+}
+
+struct guestfs_lvm_pv_list *guestfs_pvs (guestfs_h *g)
+{
+ struct pvs_rv rv;
+ int serial;
+
+ if (g->state != READY) {
+ error (g, "guestfs_pvs called from the wrong state, %d != READY",
+ g->state);
+ return NULL;
+ }
+
+ memset (&rv, 0, sizeof rv);
+
+ serial = dispatch (g, GUESTFS_PROC_PVS, NULL, NULL);
+ if (serial == -1)
+ return NULL;
+
+ rv.cb_done = 0;
+ g->reply_cb_internal = pvs_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_pvs failed, see earlier error messages");
+ return NULL;
+ }
+
+ if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_PVS, serial) == -1)
+ return NULL;
+
+ if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", rv.err.error);
+ return NULL;
+ }
+
+ /* caller will free this */
+ return safe_memdup (g, &rv.ret.physvols, sizeof (rv.ret.physvols));
+}
+
+struct vgs_rv {
+ int cb_done; /* flag to indicate callback was called */
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_vgs_ret ret;
+};
+
+static void vgs_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ struct vgs_rv *rv = (struct vgs_rv *) data;
+
+ if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+ error (g, "guestfs_vgs: failed to parse reply header");
+ return;
+ }
+ if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+ error (g, "guestfs_vgs: failed to parse reply error");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_vgs_ret (xdr, &rv->ret)) {
+ error (g, "guestfs_vgs: failed to parse reply");
+ return;
+ }
+ done:
+ rv->cb_done = 1;
+ main_loop.main_loop_quit (g);
+}
+
+struct guestfs_lvm_vg_list *guestfs_vgs (guestfs_h *g)
+{
+ struct vgs_rv rv;
+ int serial;
+
+ if (g->state != READY) {
+ error (g, "guestfs_vgs called from the wrong state, %d != READY",
+ g->state);
+ return NULL;
+ }
+
+ memset (&rv, 0, sizeof rv);
+
+ serial = dispatch (g, GUESTFS_PROC_VGS, NULL, NULL);
+ if (serial == -1)
+ return NULL;
+
+ rv.cb_done = 0;
+ g->reply_cb_internal = vgs_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_vgs failed, see earlier error messages");
+ return NULL;
+ }
+
+ if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_VGS, serial) == -1)
+ return NULL;
+
+ if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", rv.err.error);
+ return NULL;
+ }
+
+ /* caller will free this */
+ return safe_memdup (g, &rv.ret.volgroups, sizeof (rv.ret.volgroups));
+}
+
+struct lvs_rv {
+ int cb_done; /* flag to indicate callback was called */
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_lvs_ret ret;
+};
+
+static void lvs_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ struct lvs_rv *rv = (struct lvs_rv *) data;
+
+ if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
+ error (g, "guestfs_lvs: failed to parse reply header");
+ return;
+ }
+ if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &rv->err)) {
+ error (g, "guestfs_lvs: failed to parse reply error");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_lvs_ret (xdr, &rv->ret)) {
+ error (g, "guestfs_lvs: failed to parse reply");
+ return;
+ }
+ done:
+ rv->cb_done = 1;
+ main_loop.main_loop_quit (g);
+}
+
+struct guestfs_lvm_lv_list *guestfs_lvs (guestfs_h *g)
+{
+ struct lvs_rv rv;
+ int serial;
+
+ if (g->state != READY) {
+ error (g, "guestfs_lvs called from the wrong state, %d != READY",
+ g->state);
+ return NULL;
+ }
+
+ memset (&rv, 0, sizeof rv);
+
+ serial = dispatch (g, GUESTFS_PROC_LVS, NULL, NULL);
+ if (serial == -1)
+ return NULL;
+
+ rv.cb_done = 0;
+ g->reply_cb_internal = lvs_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_lvs failed, see earlier error messages");
+ return NULL;
+ }
+
+ if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_LVS, serial) == -1)
+ return NULL;
+
+ if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", rv.err.error);
+ return NULL;
+ }
+
+ /* caller will free this */
+ return safe_memdup (g, &rv.ret.logvols, sizeof (rv.ret.logvols));
+}
+
diff --git a/src/guestfs-actions.h b/src/guestfs-actions.h
index 7019d988..d48cd9bf 100644
--- a/src/guestfs-actions.h
+++ b/src/guestfs-actions.h
@@ -27,3 +27,6 @@ extern char *guestfs_ll (guestfs_h *handle, const char *directory);
extern char **guestfs_ls (guestfs_h *handle, const char *directory);
extern char **guestfs_list_devices (guestfs_h *handle);
extern char **guestfs_list_partitions (guestfs_h *handle);
+extern struct guestfs_lvm_pv_list *guestfs_pvs (guestfs_h *handle);
+extern struct guestfs_lvm_vg_list *guestfs_vgs (guestfs_h *handle);
+extern struct guestfs_lvm_lv_list *guestfs_lvs (guestfs_h *handle);
diff --git a/src/guestfs-structs.h b/src/guestfs-structs.h
new file mode 100644
index 00000000..45ce1316
--- /dev/null
+++ b/src/guestfs-structs.h
@@ -0,0 +1,94 @@
+/* libguestfs generated file
+ * WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.
+ * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+struct guestfs_lvm_pv {
+ char *pv_name;
+ char pv_uuid[32]; /* this is NOT nul-terminated, be careful when printing */
+ char *pv_fmt;
+ uint64_t pv_size;
+ uint64_t dev_size;
+ uint64_t pv_free;
+ uint64_t pv_used;
+ char *pv_attr;
+ int64_t pv_pe_count;
+ int64_t pv_pe_alloc_count;
+ char *pv_tags;
+ uint64_t pe_start;
+ int64_t pv_mda_count;
+ uint64_t pv_mda_free;
+};
+
+struct guestfs_lvm_pv_list {
+ uint32_t len;
+ struct guestfs_lvm_pv *val;
+};
+
+struct guestfs_lvm_vg {
+ char *vg_name;
+ char vg_uuid[32]; /* this is NOT nul-terminated, be careful when printing */
+ char *vg_fmt;
+ char *vg_attr;
+ uint64_t vg_size;
+ uint64_t vg_free;
+ char *vg_sysid;
+ uint64_t vg_extent_size;
+ int64_t vg_extent_count;
+ int64_t vg_free_count;
+ int64_t max_lv;
+ int64_t max_pv;
+ int64_t pv_count;
+ int64_t lv_count;
+ int64_t snap_count;
+ int64_t vg_seqno;
+ char *vg_tags;
+ int64_t vg_mda_count;
+ uint64_t vg_mda_free;
+};
+
+struct guestfs_lvm_vg_list {
+ uint32_t len;
+ struct guestfs_lvm_vg *val;
+};
+
+struct guestfs_lvm_lv {
+ char *lv_name;
+ char lv_uuid[32]; /* this is NOT nul-terminated, be careful when printing */
+ char *lv_attr;
+ int64_t lv_major;
+ int64_t lv_minor;
+ int64_t lv_kernel_major;
+ int64_t lv_kernel_minor;
+ uint64_t lv_size;
+ int64_t seg_count;
+ char *origin;
+ float snap_percent; /* [0..100] or -1 */
+ float copy_percent; /* [0..100] or -1 */
+ char *move_pv;
+ char *lv_tags;
+ char *mirror_log;
+ char *modules;
+};
+
+struct guestfs_lvm_lv_list {
+ uint32_t len;
+ struct guestfs_lvm_lv *val;
+};
+
diff --git a/src/guestfs.c b/src/guestfs.c
index 3492c624..092e405e 100644
--- a/src/guestfs.c
+++ b/src/guestfs.c
@@ -58,9 +58,10 @@
static void error (guestfs_h *g, const char *fs, ...);
static void perrorf (guestfs_h *g, const char *fs, ...);
-static void *safe_malloc (guestfs_h *g, int nbytes);
+static void *safe_malloc (guestfs_h *g, size_t nbytes);
static void *safe_realloc (guestfs_h *g, void *ptr, int nbytes);
static char *safe_strdup (guestfs_h *g, const char *str);
+static void *safe_memdup (guestfs_h *g, void *ptr, size_t size);
static void default_error_cb (guestfs_h *g, void *data, const char *msg);
static void stdout_event (void *data, int watch, int fd, int events);
@@ -328,7 +329,7 @@ perrorf (guestfs_h *g, const char *fs, ...)
}
static void *
-safe_malloc (guestfs_h *g, int nbytes)
+safe_malloc (guestfs_h *g, size_t nbytes)
{
void *ptr = malloc (nbytes);
if (!ptr) g->abort_cb ();
@@ -351,6 +352,15 @@ safe_strdup (guestfs_h *g, const char *str)
return s;
}
+static void *
+safe_memdup (guestfs_h *g, void *ptr, size_t size)
+{
+ void *p = malloc (size);
+ if (!p) g->abort_cb ();
+ memcpy (p, ptr, size);
+ return p;
+}
+
void
guestfs_set_out_of_memory_handler (guestfs_h *g, guestfs_abort_cb cb)
{
@@ -1019,6 +1029,28 @@ sock_read_event (void *data, int watch, int fd, int events)
goto cleanup;
}
+ /* Got the full message, begin processing it. */
+ if (g->verbose) {
+ int i, j;
+
+ for (i = 0; i < g->msg_in_size; i += 16) {
+ printf ("%04x: ", i);
+ for (j = i; j < MIN (i+16, g->msg_in_size); ++j)
+ printf ("%02x ", (unsigned char) g->msg_in[j]);
+ for (; j < i+16; ++j)
+ printf (" ");
+ printf ("|");
+ for (j = i; j < MIN (i+16, g->msg_in_size); ++j)
+ if (isprint (g->msg_in[j]))
+ printf ("%c", g->msg_in[j]);
+ else
+ printf (".");
+ for (; j < i+16; ++j)
+ printf (" ");
+ printf ("|\n");
+ }
+ }
+
/* Not in the expected state. */
if (g->state != BUSY)
error (g, "state %d != BUSY", g->state);
@@ -1231,6 +1263,31 @@ check_reply_header (guestfs_h *g,
*/
#include "guestfs-actions.c"
+/* Structure-freeing functions. These rely on the fact that the
+ * structure format is identical to the XDR format. See note in
+ * generator.ml.
+ */
+void
+guestfs_free_lvm_pv_list (struct guestfs_lvm_pv_list *x)
+{
+ xdr_free ((xdrproc_t) xdr_guestfs_lvm_int_pv_list, (char *) x);
+ free (x);
+}
+
+void
+guestfs_free_lvm_vg_list (struct guestfs_lvm_vg_list *x)
+{
+ xdr_free ((xdrproc_t) xdr_guestfs_lvm_int_vg_list, (char *) x);
+ free (x);
+}
+
+void
+guestfs_free_lvm_lv_list (struct guestfs_lvm_lv_list *x)
+{
+ xdr_free ((xdrproc_t) xdr_guestfs_lvm_int_lv_list, (char *) x);
+ free (x);
+}
+
/* This is the default main loop implementation, using select(2). */
struct handle_cb_data {
diff --git a/src/guestfs.h b/src/guestfs.h
index 575e0c72..cbe2c82c 100644
--- a/src/guestfs.h
+++ b/src/guestfs.h
@@ -59,8 +59,13 @@ extern int guestfs_get_autosync (guestfs_h *g);
extern void guestfs_set_path (guestfs_h *g, const char *path);
extern const char *guestfs_get_path (guestfs_h *g);
+#include <guestfs-structs.h>
#include <guestfs-actions.h>
+extern void guestfs_free_lvm_pv_list (struct guestfs_lvm_pv_list *);
+extern void guestfs_free_lvm_vg_list (struct guestfs_lvm_vg_list *);
+extern void guestfs_free_lvm_lv_list (struct guestfs_lvm_lv_list *);
+
/* Low-level event API. */
typedef void (*guestfs_reply_cb) (guestfs_h *g, void *data, XDR *xdr);
typedef void (*guestfs_log_message_cb) (guestfs_h *g, void *data, char *buf, int len);
diff --git a/src/guestfs_protocol.c b/src/guestfs_protocol.c
index 80f618b1..dfdd0d8b 100644
--- a/src/guestfs_protocol.c
+++ b/src/guestfs_protocol.c
@@ -16,6 +16,164 @@ xdr_str (XDR *xdrs, str *objp)
}
bool_t
+xdr_guestfs_lvm_int_pv (XDR *xdrs, guestfs_lvm_int_pv *objp)
+{
+ register int32_t *buf;
+
+ int i;
+ if (!xdr_string (xdrs, &objp->pv_name, ~0))
+ return FALSE;
+ if (!xdr_opaque (xdrs, objp->pv_uuid, 32))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->pv_fmt, ~0))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->pv_size))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->dev_size))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->pv_free))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->pv_used))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->pv_attr, ~0))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->pv_pe_count))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->pv_pe_alloc_count))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->pv_tags, ~0))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->pe_start))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->pv_mda_count))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->pv_mda_free))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_lvm_int_pv_list (XDR *xdrs, guestfs_lvm_int_pv_list *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_array (xdrs, (char **)&objp->guestfs_lvm_int_pv_list_val, (u_int *) &objp->guestfs_lvm_int_pv_list_len, ~0,
+ sizeof (guestfs_lvm_int_pv), (xdrproc_t) xdr_guestfs_lvm_int_pv))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_lvm_int_vg (XDR *xdrs, guestfs_lvm_int_vg *objp)
+{
+ register int32_t *buf;
+
+ int i;
+ if (!xdr_string (xdrs, &objp->vg_name, ~0))
+ return FALSE;
+ if (!xdr_opaque (xdrs, objp->vg_uuid, 32))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->vg_fmt, ~0))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->vg_attr, ~0))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->vg_size))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->vg_free))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->vg_sysid, ~0))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->vg_extent_size))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->vg_extent_count))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->vg_free_count))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->max_lv))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->max_pv))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->pv_count))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->lv_count))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->snap_count))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->vg_seqno))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->vg_tags, ~0))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->vg_mda_count))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->vg_mda_free))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_lvm_int_vg_list (XDR *xdrs, guestfs_lvm_int_vg_list *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_array (xdrs, (char **)&objp->guestfs_lvm_int_vg_list_val, (u_int *) &objp->guestfs_lvm_int_vg_list_len, ~0,
+ sizeof (guestfs_lvm_int_vg), (xdrproc_t) xdr_guestfs_lvm_int_vg))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_lvm_int_lv (XDR *xdrs, guestfs_lvm_int_lv *objp)
+{
+ register int32_t *buf;
+
+ int i;
+ if (!xdr_string (xdrs, &objp->lv_name, ~0))
+ return FALSE;
+ if (!xdr_opaque (xdrs, objp->lv_uuid, 32))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->lv_attr, ~0))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->lv_major))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->lv_minor))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->lv_kernel_major))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->lv_kernel_minor))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->lv_size))
+ return FALSE;
+ if (!xdr_quad_t (xdrs, &objp->seg_count))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->origin, ~0))
+ return FALSE;
+ if (!xdr_float (xdrs, &objp->snap_percent))
+ return FALSE;
+ if (!xdr_float (xdrs, &objp->copy_percent))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->move_pv, ~0))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->lv_tags, ~0))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->mirror_log, ~0))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->modules, ~0))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_lvm_int_lv_list (XDR *xdrs, guestfs_lvm_int_lv_list *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_array (xdrs, (char **)&objp->guestfs_lvm_int_lv_list_val, (u_int *) &objp->guestfs_lvm_int_lv_list_len, ~0,
+ sizeof (guestfs_lvm_int_lv), (xdrproc_t) xdr_guestfs_lvm_int_lv))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
xdr_guestfs_mount_args (XDR *xdrs, guestfs_mount_args *objp)
{
register int32_t *buf;
@@ -121,6 +279,36 @@ xdr_guestfs_list_partitions_ret (XDR *xdrs, guestfs_list_partitions_ret *objp)
}
bool_t
+xdr_guestfs_pvs_ret (XDR *xdrs, guestfs_pvs_ret *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_guestfs_lvm_int_pv_list (xdrs, &objp->physvols))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_vgs_ret (XDR *xdrs, guestfs_vgs_ret *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_guestfs_lvm_int_vg_list (xdrs, &objp->volgroups))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_lvs_ret (XDR *xdrs, guestfs_lvs_ret *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_guestfs_lvm_int_lv_list (xdrs, &objp->logvols))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
xdr_guestfs_procedure (XDR *xdrs, guestfs_procedure *objp)
{
register int32_t *buf;
diff --git a/src/guestfs_protocol.h b/src/guestfs_protocol.h
index 3e192127..a168e43a 100644
--- a/src/guestfs_protocol.h
+++ b/src/guestfs_protocol.h
@@ -16,6 +16,82 @@ extern "C" {
typedef char *str;
+struct guestfs_lvm_int_pv {
+ char *pv_name;
+ char pv_uuid[32];
+ char *pv_fmt;
+ quad_t pv_size;
+ quad_t dev_size;
+ quad_t pv_free;
+ quad_t pv_used;
+ char *pv_attr;
+ quad_t pv_pe_count;
+ quad_t pv_pe_alloc_count;
+ char *pv_tags;
+ quad_t pe_start;
+ quad_t pv_mda_count;
+ quad_t pv_mda_free;
+};
+typedef struct guestfs_lvm_int_pv guestfs_lvm_int_pv;
+
+typedef struct {
+ u_int guestfs_lvm_int_pv_list_len;
+ guestfs_lvm_int_pv *guestfs_lvm_int_pv_list_val;
+} guestfs_lvm_int_pv_list;
+
+struct guestfs_lvm_int_vg {
+ char *vg_name;
+ char vg_uuid[32];
+ char *vg_fmt;
+ char *vg_attr;
+ quad_t vg_size;
+ quad_t vg_free;
+ char *vg_sysid;
+ quad_t vg_extent_size;
+ quad_t vg_extent_count;
+ quad_t vg_free_count;
+ quad_t max_lv;
+ quad_t max_pv;
+ quad_t pv_count;
+ quad_t lv_count;
+ quad_t snap_count;
+ quad_t vg_seqno;
+ char *vg_tags;
+ quad_t vg_mda_count;
+ quad_t vg_mda_free;
+};
+typedef struct guestfs_lvm_int_vg guestfs_lvm_int_vg;
+
+typedef struct {
+ u_int guestfs_lvm_int_vg_list_len;
+ guestfs_lvm_int_vg *guestfs_lvm_int_vg_list_val;
+} guestfs_lvm_int_vg_list;
+
+struct guestfs_lvm_int_lv {
+ char *lv_name;
+ char lv_uuid[32];
+ char *lv_attr;
+ quad_t lv_major;
+ quad_t lv_minor;
+ quad_t lv_kernel_major;
+ quad_t lv_kernel_minor;
+ quad_t lv_size;
+ quad_t seg_count;
+ char *origin;
+ float snap_percent;
+ float copy_percent;
+ char *move_pv;
+ char *lv_tags;
+ char *mirror_log;
+ char *modules;
+};
+typedef struct guestfs_lvm_int_lv guestfs_lvm_int_lv;
+
+typedef struct {
+ u_int guestfs_lvm_int_lv_list_len;
+ guestfs_lvm_int_lv *guestfs_lvm_int_lv_list_val;
+} guestfs_lvm_int_lv_list;
+
struct guestfs_mount_args {
char *device;
char *mountpoint;
@@ -76,6 +152,21 @@ struct guestfs_list_partitions_ret {
};
typedef struct guestfs_list_partitions_ret guestfs_list_partitions_ret;
+struct guestfs_pvs_ret {
+ guestfs_lvm_int_pv_list physvols;
+};
+typedef struct guestfs_pvs_ret guestfs_pvs_ret;
+
+struct guestfs_vgs_ret {
+ guestfs_lvm_int_vg_list volgroups;
+};
+typedef struct guestfs_vgs_ret guestfs_vgs_ret;
+
+struct guestfs_lvs_ret {
+ guestfs_lvm_int_lv_list logvols;
+};
+typedef struct guestfs_lvs_ret guestfs_lvs_ret;
+
enum guestfs_procedure {
GUESTFS_PROC_MOUNT = 1,
GUESTFS_PROC_SYNC = 2,
@@ -85,7 +176,10 @@ enum guestfs_procedure {
GUESTFS_PROC_LS = 6,
GUESTFS_PROC_LIST_DEVICES = 7,
GUESTFS_PROC_LIST_PARTITIONS = 8,
- GUESTFS_PROC_dummy = 8 + 1,
+ GUESTFS_PROC_PVS = 9,
+ GUESTFS_PROC_VGS = 10,
+ GUESTFS_PROC_LVS = 11,
+ GUESTFS_PROC_dummy = 11 + 1,
};
typedef enum guestfs_procedure guestfs_procedure;
#define GUESTFS_MESSAGE_MAX 4194304
@@ -124,6 +218,12 @@ typedef struct guestfs_message_header guestfs_message_header;
#if defined(__STDC__) || defined(__cplusplus)
extern bool_t xdr_str (XDR *, str*);
+extern bool_t xdr_guestfs_lvm_int_pv (XDR *, guestfs_lvm_int_pv*);
+extern bool_t xdr_guestfs_lvm_int_pv_list (XDR *, guestfs_lvm_int_pv_list*);
+extern bool_t xdr_guestfs_lvm_int_vg (XDR *, guestfs_lvm_int_vg*);
+extern bool_t xdr_guestfs_lvm_int_vg_list (XDR *, guestfs_lvm_int_vg_list*);
+extern bool_t xdr_guestfs_lvm_int_lv (XDR *, guestfs_lvm_int_lv*);
+extern bool_t xdr_guestfs_lvm_int_lv_list (XDR *, guestfs_lvm_int_lv_list*);
extern bool_t xdr_guestfs_mount_args (XDR *, guestfs_mount_args*);
extern bool_t xdr_guestfs_touch_args (XDR *, guestfs_touch_args*);
extern bool_t xdr_guestfs_cat_args (XDR *, guestfs_cat_args*);
@@ -134,6 +234,9 @@ extern bool_t xdr_guestfs_ls_args (XDR *, guestfs_ls_args*);
extern bool_t xdr_guestfs_ls_ret (XDR *, guestfs_ls_ret*);
extern bool_t xdr_guestfs_list_devices_ret (XDR *, guestfs_list_devices_ret*);
extern bool_t xdr_guestfs_list_partitions_ret (XDR *, guestfs_list_partitions_ret*);
+extern bool_t xdr_guestfs_pvs_ret (XDR *, guestfs_pvs_ret*);
+extern bool_t xdr_guestfs_vgs_ret (XDR *, guestfs_vgs_ret*);
+extern bool_t xdr_guestfs_lvs_ret (XDR *, guestfs_lvs_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*);
@@ -142,6 +245,12 @@ extern bool_t xdr_guestfs_message_header (XDR *, guestfs_message_header*);
#else /* K&R C */
extern bool_t xdr_str ();
+extern bool_t xdr_guestfs_lvm_int_pv ();
+extern bool_t xdr_guestfs_lvm_int_pv_list ();
+extern bool_t xdr_guestfs_lvm_int_vg ();
+extern bool_t xdr_guestfs_lvm_int_vg_list ();
+extern bool_t xdr_guestfs_lvm_int_lv ();
+extern bool_t xdr_guestfs_lvm_int_lv_list ();
extern bool_t xdr_guestfs_mount_args ();
extern bool_t xdr_guestfs_touch_args ();
extern bool_t xdr_guestfs_cat_args ();
@@ -152,6 +261,9 @@ extern bool_t xdr_guestfs_ls_args ();
extern bool_t xdr_guestfs_ls_ret ();
extern bool_t xdr_guestfs_list_devices_ret ();
extern bool_t xdr_guestfs_list_partitions_ret ();
+extern bool_t xdr_guestfs_pvs_ret ();
+extern bool_t xdr_guestfs_vgs_ret ();
+extern bool_t xdr_guestfs_lvs_ret ();
extern bool_t xdr_guestfs_procedure ();
extern bool_t xdr_guestfs_message_direction ();
extern bool_t xdr_guestfs_message_status ();
diff --git a/src/guestfs_protocol.x b/src/guestfs_protocol.x
index be0efdbb..fedc6f2d 100644
--- a/src/guestfs_protocol.x
+++ b/src/guestfs_protocol.x
@@ -21,6 +21,70 @@
typedef string str<>;
+struct guestfs_lvm_int_pv {
+ string pv_name<>;
+ opaque pv_uuid[32];
+ string pv_fmt<>;
+ hyper pv_size;
+ hyper dev_size;
+ hyper pv_free;
+ hyper pv_used;
+ string pv_attr<>;
+ hyper pv_pe_count;
+ hyper pv_pe_alloc_count;
+ string pv_tags<>;
+ hyper pe_start;
+ hyper pv_mda_count;
+ hyper pv_mda_free;
+};
+
+typedef struct guestfs_lvm_int_pv guestfs_lvm_int_pv_list<>;
+
+struct guestfs_lvm_int_vg {
+ string vg_name<>;
+ opaque vg_uuid[32];
+ string vg_fmt<>;
+ string vg_attr<>;
+ hyper vg_size;
+ hyper vg_free;
+ string vg_sysid<>;
+ hyper vg_extent_size;
+ hyper vg_extent_count;
+ hyper vg_free_count;
+ hyper max_lv;
+ hyper max_pv;
+ hyper pv_count;
+ hyper lv_count;
+ hyper snap_count;
+ hyper vg_seqno;
+ string vg_tags<>;
+ hyper vg_mda_count;
+ hyper vg_mda_free;
+};
+
+typedef struct guestfs_lvm_int_vg guestfs_lvm_int_vg_list<>;
+
+struct guestfs_lvm_int_lv {
+ string lv_name<>;
+ opaque lv_uuid[32];
+ string lv_attr<>;
+ hyper lv_major;
+ hyper lv_minor;
+ hyper lv_kernel_major;
+ hyper lv_kernel_minor;
+ hyper lv_size;
+ hyper seg_count;
+ string origin<>;
+ float snap_percent;
+ float copy_percent;
+ string move_pv<>;
+ string lv_tags<>;
+ string mirror_log<>;
+ string modules<>;
+};
+
+typedef struct guestfs_lvm_int_lv guestfs_lvm_int_lv_list<>;
+
/* guestfs_mount */
struct guestfs_mount_args {
@@ -78,6 +142,24 @@ struct guestfs_list_partitions_ret {
str partitions<>;
};
+/* guestfs_pvs */
+
+struct guestfs_pvs_ret {
+ guestfs_lvm_int_pv_list physvols;
+};
+
+/* guestfs_vgs */
+
+struct guestfs_vgs_ret {
+ guestfs_lvm_int_vg_list volgroups;
+};
+
+/* guestfs_lvs */
+
+struct guestfs_lvs_ret {
+ guestfs_lvm_int_lv_list logvols;
+};
+
enum guestfs_procedure {
GUESTFS_PROC_MOUNT = 1,
GUESTFS_PROC_SYNC = 2,
@@ -87,6 +169,9 @@ enum guestfs_procedure {
GUESTFS_PROC_LS = 6,
GUESTFS_PROC_LIST_DEVICES = 7,
GUESTFS_PROC_LIST_PARTITIONS = 8,
+ GUESTFS_PROC_PVS = 9,
+ GUESTFS_PROC_VGS = 10,
+ GUESTFS_PROC_LVS = 11,
GUESTFS_PROC_dummy
};