Implement list-devices and list-partitions.

This commit is contained in:
Richard Jones
2009-04-06 12:55:26 +01:00
parent 1cf85b1e60
commit 8e570870f5
15 changed files with 849 additions and 307 deletions

View File

@@ -21,6 +21,7 @@ noinst_PROGRAMS = guestfsd
guestfsd_SOURCES = \
actions.h \
daemon.h \
devsparts.c \
file.c \
guestfsd.c \
ls.c \

View File

@@ -19,9 +19,11 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
extern char *do_cat (const char *path);
extern char *do_ll (const char *directory);
extern char **do_ls (const char *directory);
extern int do_mount (const char *device, const char *mountpoint);
extern int do_sync ();
extern int do_touch (const char *path);
extern char *do_cat (const char *path);
extern char *do_ll (const char *directory);
extern char **do_ls (const char *directory);
extern char **do_list_devices ();
extern char **do_list_partitions ();

View File

@@ -29,7 +29,9 @@ extern void xread (int sock, void *buf, size_t len);
extern int add_string (char ***argv, int *size, int *alloc, const char *str);
extern int count_strings (char **argv);
extern void sort_strings (char **argv, int len);
extern void free_strings (char **argv);
extern void free_stringslen (char **argv, int len);
extern int command (char **stdoutput, char **stderror, const char *name, ...);

133
daemon/devsparts.c Normal file
View File

@@ -0,0 +1,133 @@
/* libguestfs - the guestfsd daemon
* Copyright (C) 2009 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/stat.h>
#include "daemon.h"
#include "actions.h"
char **
do_list_devices (void)
{
char **r = NULL;
int size = 0, alloc = 0;
DIR *dir;
struct dirent *d;
char buf[256];
dir = opendir ("/sys/block");
if (!dir) {
reply_with_perror ("opendir: /sys/block");
return NULL;
}
while ((d = readdir (dir)) != NULL) {
if (strncmp (d->d_name, "sd", 2) == 0) {
snprintf (buf, sizeof buf, "/dev/%s", d->d_name);
if (add_string (&r, &size, &alloc, buf) == -1) {
closedir (dir);
return NULL;
}
}
}
if (add_string (&r, &size, &alloc, NULL) == -1) {
closedir (dir);
return NULL;
}
if (closedir (dir) == -1) {
reply_with_perror ("closedir: /sys/block");
free_strings (r);
return NULL;
}
sort_strings (r, size-1);
return r;
}
char **
do_list_partitions (void)
{
char **r = NULL;
int size = 0, alloc = 0;
DIR *dir, *dir2;
struct dirent *d;
char buf[256], devname[256];
dir = opendir ("/sys/block");
if (!dir) {
reply_with_perror ("opendir: /sys/block");
return NULL;
}
while ((d = readdir (dir)) != NULL) {
if (strncmp (d->d_name, "sd", 2) == 0) {
strncpy (devname, d->d_name, sizeof devname);
devname[sizeof devname - 1] = '\0';
snprintf (buf, sizeof buf, "/sys/block/%s", devname);
dir2 = opendir (buf);
if (!dir2) {
reply_with_perror ("opendir: %s", buf);
free_stringslen (r, size);
return NULL;
}
while ((d = readdir (dir2)) != NULL) {
if (strncmp (d->d_name, devname, strlen (devname)) == 0) {
snprintf (buf, sizeof buf, "/dev/%s", d->d_name);
if (add_string (&r, &size, &alloc, buf) == -1) {
closedir (dir2);
closedir (dir);
return NULL;
}
}
}
if (closedir (dir2) == -1) {
reply_with_perror ("closedir: /sys/block/%s", devname);
free_stringslen (r, size);
return NULL;
}
}
}
if (add_string (&r, &size, &alloc, NULL) == -1) {
closedir (dir);
return NULL;
}
if (closedir (dir) == -1) {
reply_with_perror ("closedir: /sys/block");
free_strings (r);
return NULL;
}
sort_strings (r, size-1);
return r;
}

View File

@@ -272,6 +272,20 @@ count_strings (char **argv)
return argc;
}
static int
compare (const void *vp1, const void *vp2)
{
char * const *p1 = (char * const *) vp1;
char * const *p2 = (char * const *) vp2;
return strcmp (*p1, *p2);
}
void
sort_strings (char **argv, int len)
{
qsort (argv, len, sizeof (char *), compare);
}
void
free_strings (char **argv)
{
@@ -282,6 +296,16 @@ free_strings (char **argv)
free (argv);
}
void
free_stringslen (char **argv, int len)
{
int i;
for (i = 0; i < len; ++i)
free (argv[i]);
free (argv);
}
/* This is a more sane version of 'system(3)' for running external
* commands. It uses fork/execvp, so we don't need to worry about
* quoting of parameters, and it allows us to capture any error

View File

@@ -29,14 +29,6 @@
#include "daemon.h"
#include "actions.h"
static int
compare (const void *vp1, const void *vp2)
{
char * const *p1 = (char * const *) vp1;
char * const *p2 = (char * const *) vp2;
return strcmp (*p1, *p2);
}
char **
do_ls (const char *path)
{
@@ -78,7 +70,7 @@ do_ls (const char *path)
return NULL;
}
qsort (r, size-1, sizeof (char *), compare);
sort_strings (r, size-1);
return r;
}

View File

@@ -25,6 +25,64 @@
#include "../src/guestfs_protocol.h"
#include "actions.h"
static void mount_stub (XDR *xdr_in)
{
int r;
struct guestfs_mount_args args;
const char *device;
const char *mountpoint;
memset (&args, 0, sizeof args);
if (!xdr_guestfs_mount_args (xdr_in, &args)) {
reply_with_error ("mount: daemon failed to decode procedure arguments");
return;
}
device = args.device;
mountpoint = args.mountpoint;
r = do_mount (device, mountpoint);
if (r == -1)
/* do_mount has already called reply_with_error, so just return */
return;
reply (NULL, NULL);
}
static void sync_stub (XDR *xdr_in)
{
int r;
r = do_sync ();
if (r == -1)
/* do_sync has already called reply_with_error, so just return */
return;
reply (NULL, NULL);
}
static void touch_stub (XDR *xdr_in)
{
int r;
struct guestfs_touch_args args;
const char *path;
memset (&args, 0, sizeof args);
if (!xdr_guestfs_touch_args (xdr_in, &args)) {
reply_with_error ("touch: daemon failed to decode procedure arguments");
return;
}
path = args.path;
r = do_touch (path);
if (r == -1)
/* do_touch has already called reply_with_error, so just return */
return;
reply (NULL, NULL);
}
static void cat_stub (XDR *xdr_in)
{
char *r;
@@ -101,76 +159,41 @@ static void ls_stub (XDR *xdr_in)
free_strings (r);
}
static void mount_stub (XDR *xdr_in)
static void list_devices_stub (XDR *xdr_in)
{
int r;
struct guestfs_mount_args args;
const char *device;
const char *mountpoint;
char **r;
memset (&args, 0, sizeof args);
if (!xdr_guestfs_mount_args (xdr_in, &args)) {
reply_with_error ("mount: daemon failed to decode procedure arguments");
return;
}
device = args.device;
mountpoint = args.mountpoint;
r = do_mount (device, mountpoint);
if (r == -1)
/* do_mount has already called reply_with_error, so just return */
r = do_list_devices ();
if (r == NULL)
/* do_list_devices has already called reply_with_error, so just return */
return;
reply (NULL, NULL);
struct guestfs_list_devices_ret ret;
ret.devices.devices_len = count_strings (r);
ret.devices.devices_val = r;
reply ((xdrproc_t) &xdr_guestfs_list_devices_ret, (char *) &ret);
free_strings (r);
}
static void sync_stub (XDR *xdr_in)
static void list_partitions_stub (XDR *xdr_in)
{
int r;
char **r;
r = do_sync ();
if (r == -1)
/* do_sync has already called reply_with_error, so just return */
r = do_list_partitions ();
if (r == NULL)
/* do_list_partitions has already called reply_with_error, so just return */
return;
reply (NULL, NULL);
}
static void touch_stub (XDR *xdr_in)
{
int r;
struct guestfs_touch_args args;
const char *path;
memset (&args, 0, sizeof args);
if (!xdr_guestfs_touch_args (xdr_in, &args)) {
reply_with_error ("touch: daemon failed to decode procedure arguments");
return;
}
path = args.path;
r = do_touch (path);
if (r == -1)
/* do_touch has already called reply_with_error, so just return */
return;
reply (NULL, NULL);
struct guestfs_list_partitions_ret ret;
ret.partitions.partitions_len = count_strings (r);
ret.partitions.partitions_val = r;
reply ((xdrproc_t) &xdr_guestfs_list_partitions_ret, (char *) &ret);
free_strings (r);
}
void dispatch_incoming_message (XDR *xdr_in)
{
switch (proc_nr) {
case GUESTFS_PROC_CAT:
cat_stub (xdr_in);
break;
case GUESTFS_PROC_LL:
ll_stub (xdr_in);
break;
case GUESTFS_PROC_LS:
ls_stub (xdr_in);
break;
case GUESTFS_PROC_MOUNT:
mount_stub (xdr_in);
break;
@@ -180,6 +203,21 @@ void dispatch_incoming_message (XDR *xdr_in)
case GUESTFS_PROC_TOUCH:
touch_stub (xdr_in);
break;
case GUESTFS_PROC_CAT:
cat_stub (xdr_in);
break;
case GUESTFS_PROC_LL:
ll_stub (xdr_in);
break;
case GUESTFS_PROC_LS:
ls_stub (xdr_in);
break;
case GUESTFS_PROC_LIST_DEVICES:
list_devices_stub (xdr_in);
break;
case GUESTFS_PROC_LIST_PARTITIONS:
list_partitions_stub (xdr_in);
break;
default:
reply_with_error ("dispatch_incoming_message: unknown procedure number %d", proc_nr);
}

View File

@@ -30,6 +30,8 @@ void list_commands (void)
printf (" %-16s %s\n", "Command", "Description");
list_builtin_commands ();
printf ("%-20s %s\n", "cat", "list the contents of a file");
printf ("%-20s %s\n", "list-devices", "list the block devices");
printf ("%-20s %s\n", "list-partitions", "list the partitions");
printf ("%-20s %s\n", "ll", "list the files in a directory (long format)");
printf ("%-20s %s\n", "ls", "list the files in a directory");
printf ("%-20s %s\n", "mount", "mount a guest disk at a position in the filesystem");
@@ -40,15 +42,6 @@ void list_commands (void)
void display_command (const char *cmd)
{
if (strcasecmp (cmd, "cat") == 0)
pod2text ("cat - list the contents of a file", " cat <path>\n\nReturn the contents of the file named C<path>.\n\nNote that this function cannot correctly handle binary files\n(specifically, files containing C<\\0> character which is treated\nas end of string). For those you need to use the C<guestfs_read>\nfunction which has a more complex interface.\n\nBecause of the message protocol, there is a transfer limit \nof somewhere between 2MB and 4MB. To transfer large files you should use\nFTP.");
else
if (strcasecmp (cmd, "ll") == 0)
pod2text ("ll - list the files in a directory (long format)", " ll <directory>\n\nList the files in C<directory> (relative to the root directory,\nthere is no cwd) in the format of 'ls -la'.\n\nThis command is mostly useful for interactive sessions. It\nis I<not> intended that you try to parse the output string.");
else
if (strcasecmp (cmd, "ls") == 0)
pod2text ("ls - list the files in a directory", " ls <directory>\n\nList the files in C<directory> (relative to the root directory,\nthere is no cwd). The '.' and '..' entries are not returned, but\nhidden files are shown.\n\nThis command is mostly useful for interactive sessions. Programs\nshould probably use C<guestfs_readdir> instead.");
else
if (strcasecmp (cmd, "mount") == 0)
pod2text ("mount - mount a guest disk at a position in the filesystem", " mount <device> <mountpoint>\n\nMount a guest disk at a position in the filesystem. Block devices\nare named C</dev/sda>, C</dev/sdb> and so on, as they were added to\nthe guest. If those block devices contain partitions, they will have\nthe usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style\nnames can be used.\n\nThe rules are the same as for L<mount(2)>: A filesystem must\nfirst be mounted on C</> before others can be mounted. Other\nfilesystems can only be mounted on directories which already\nexist.\n\nThe mounted filesystem is writable, if we have sufficient permissions\non the underlying device.\n\nThe filesystem options C<sync> and C<noatime> are set with this\ncall, in order to improve reliability.");
else
@@ -57,10 +50,67 @@ void display_command (const char *cmd)
else
if (strcasecmp (cmd, "touch") == 0)
pod2text ("touch - update file timestamps or create a new file", " touch <path>\n\nTouch acts like the L<touch(1)> command. It can be used to\nupdate the timestamps on a file, or, if the file does not exist,\nto create a new zero-length file.");
else
if (strcasecmp (cmd, "cat") == 0)
pod2text ("cat - list the contents of a file", " cat <path>\n\nReturn the contents of the file named C<path>.\n\nNote that this function cannot correctly handle binary files\n(specifically, files containing C<\\0> character which is treated\nas end of string). For those you need to use the C<guestfs_read_file>\nfunction which has a more complex interface.\n\nBecause of the message protocol, there is a transfer limit \nof somewhere between 2MB and 4MB. To transfer large files you should use\nFTP.");
else
if (strcasecmp (cmd, "ll") == 0)
pod2text ("ll - list the files in a directory (long format)", " ll <directory>\n\nList the files in C<directory> (relative to the root directory,\nthere is no cwd) in the format of 'ls -la'.\n\nThis command is mostly useful for interactive sessions. It\nis I<not> intended that you try to parse the output string.");
else
if (strcasecmp (cmd, "ls") == 0)
pod2text ("ls - list the files in a directory", " ls <directory>\n\nList the files in C<directory> (relative to the root directory,\nthere is no cwd). The '.' and '..' entries are not returned, but\nhidden files are shown.\n\nThis command is mostly useful for interactive sessions. Programs\nshould probably use C<guestfs_readdir> instead.");
else
if (strcasecmp (cmd, "list_devices") == 0 || strcasecmp (cmd, "list-devices") == 0)
pod2text ("list-devices - list the block devices", " list-devices\n\nList all the block devices.\n\nThe full block device names are returned, eg. C</dev/sda>\n");
else
if (strcasecmp (cmd, "list_partitions") == 0 || strcasecmp (cmd, "list-partitions") == 0)
pod2text ("list-partitions - list the partitions", " list-partitions\n\nList all the partitions detected on all block devices.\n\nThe full partition device names are returned, eg. C</dev/sda1>\n\nThis does not return logical volumes. For that you will need to\ncall C<guestfs_lvs>.");
else
display_builtin_command (cmd);
}
static int run_mount (const char *cmd, int argc, char *argv[])
{
int r;
const char *device;
const char *mountpoint;
if (argc != 2) {
fprintf (stderr, "%s should have 2 parameter(s)\n", cmd);
fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
return -1;
}
device = argv[0];
mountpoint = argv[1];
r = guestfs_mount (g, device, mountpoint);
return r;
}
static int run_sync (const char *cmd, int argc, char *argv[])
{
int r;
if (argc != 0) {
fprintf (stderr, "%s should have 0 parameter(s)\n", cmd);
fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
return -1;
}
r = guestfs_sync (g);
return r;
}
static int run_touch (const char *cmd, int argc, char *argv[])
{
int 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_touch (g, path);
return r;
}
static int run_cat (const char *cmd, int argc, char *argv[])
{
char *r;
@@ -112,59 +162,38 @@ static int run_ls (const char *cmd, int argc, char *argv[])
return 0;
}
static int run_mount (const char *cmd, int argc, char *argv[])
static int run_list_devices (const char *cmd, int argc, char *argv[])
{
int r;
const char *device;
const char *mountpoint;
if (argc != 2) {
fprintf (stderr, "%s should have 2 parameter(s)\n", cmd);
fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
return -1;
}
device = argv[0];
mountpoint = argv[1];
r = guestfs_mount (g, device, mountpoint);
return r;
}
static int run_sync (const char *cmd, int argc, char *argv[])
{
int r;
char **r;
if (argc != 0) {
fprintf (stderr, "%s should have 0 parameter(s)\n", cmd);
fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
return -1;
}
r = guestfs_sync (g);
return r;
r = guestfs_list_devices (g);
if (r == NULL) return -1;
print_strings (r);
free_strings (r);
return 0;
}
static int run_touch (const char *cmd, int argc, char *argv[])
static int run_list_partitions (const char *cmd, int argc, char *argv[])
{
int r;
const char *path;
if (argc != 1) {
fprintf (stderr, "%s should have 1 parameter(s)\n", cmd);
char **r;
if (argc != 0) {
fprintf (stderr, "%s should have 0 parameter(s)\n", cmd);
fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
return -1;
}
path = argv[0];
r = guestfs_touch (g, path);
return r;
r = guestfs_list_partitions (g);
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, "cat") == 0)
return run_cat (cmd, argc, argv);
else
if (strcasecmp (cmd, "ll") == 0)
return run_ll (cmd, argc, argv);
else
if (strcasecmp (cmd, "ls") == 0)
return run_ls (cmd, argc, argv);
else
if (strcasecmp (cmd, "mount") == 0)
return run_mount (cmd, argc, argv);
else
@@ -173,6 +202,21 @@ int run_action (const char *cmd, int argc, char *argv[])
else
if (strcasecmp (cmd, "touch") == 0)
return run_touch (cmd, argc, argv);
else
if (strcasecmp (cmd, "cat") == 0)
return run_cat (cmd, argc, argv);
else
if (strcasecmp (cmd, "ll") == 0)
return run_ll (cmd, argc, argv);
else
if (strcasecmp (cmd, "ls") == 0)
return run_ls (cmd, argc, argv);
else
if (strcasecmp (cmd, "list_devices") == 0 || strcasecmp (cmd, "list-devices") == 0)
return run_list_devices (cmd, argc, argv);
else
if (strcasecmp (cmd, "list_partitions") == 0 || strcasecmp (cmd, "list-partitions") == 0)
return run_list_partitions (cmd, argc, argv);
else
{
fprintf (stderr, "%s: unknown command\n", cmd);

View File

@@ -7,16 +7,44 @@ Return the contents of the file named C<path>.
Note that this function cannot correctly handle binary files
(specifically, files containing C<\0> character which is treated
as end of string). For those you need to use the C<guestfs_read>
as end of string). For those you need to use the C<guestfs_read_file>
function which has a more complex interface.
This function returns a string or NULL on error. The caller
must free the returned string after use.
This function returns a string or NULL on error.
I<The caller must free the returned string after use>.
Because of the message protocol, there is a transfer limit
of somewhere between 2MB and 4MB. To transfer large files you should use
FTP.
=head2 guestfs_list_devices
char **guestfs_list_devices (guestfs_h *handle);
List all the block devices.
The full block device names are returned, eg. C</dev/sda>
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_list_partitions
char **guestfs_list_partitions (guestfs_h *handle);
List all the partitions detected on all block devices.
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>.
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_ll
char *guestfs_ll (guestfs_h *handle,
@@ -28,8 +56,8 @@ there is no cwd) in the format of 'ls -la'.
This command is mostly useful for interactive sessions. It
is I<not> intended that you try to parse the output string.
This function returns a string or NULL on error. The caller
must free the returned string after use.
This function returns a string or NULL on error.
I<The caller must free the returned string after use>.
=head2 guestfs_ls
@@ -45,8 +73,7 @@ should probably use C<guestfs_readdir> instead.
This function returns a NULL-terminated array of strings
(like L<environ(3)>), or NULL if there was an error.
The caller must free the strings I<and> the array after use.
I<The caller must free the strings and the array after use>.
=head2 guestfs_mount

View File

@@ -48,35 +48,6 @@ and argt =
type flags = ProtocolLimitWarning
let functions = [
("cat", (RString "content", P1 (String "path")), 4, [ProtocolLimitWarning],
"list the contents of a file",
"\
Return the contents of the file named C<path>.
Note that this function cannot correctly handle binary files
(specifically, files containing C<\\0> character which is treated
as end of string). For those you need to use the C<guestfs_read>
function which has a more complex interface.");
("ll", (RString "listing", P1 (String "directory")), 5, [],
"list the files in a directory (long format)",
"\
List the files in C<directory> (relative to the root directory,
there is no cwd) in the format of 'ls -la'.
This command is mostly useful for interactive sessions. It
is I<not> intended that you try to parse the output string.");
("ls", (RStringList "listing", P1 (String "directory")), 6, [],
"list the files in a directory",
"\
List the files in C<directory> (relative to the root directory,
there is no cwd). The '.' and '..' entries are not returned, but
hidden files are shown.
This command is mostly useful for interactive sessions. Programs
should probably use C<guestfs_readdir> instead.");
("mount", (Err, P2 (String "device", String "mountpoint")), 1, [],
"mount a guest disk at a position in the filesystem",
"\
@@ -112,8 +83,74 @@ calling C<guestfs_close>.");
Touch acts like the L<touch(1)> command. It can be used to
update the timestamps on a file, or, if the file does not exist,
to create a new zero-length file.");
("cat", (RString "content", P1 (String "path")), 4, [ProtocolLimitWarning],
"list the contents of a file",
"\
Return the contents of the file named C<path>.
Note that this function cannot correctly handle binary files
(specifically, files containing C<\\0> character which is treated
as end of string). For those you need to use the C<guestfs_read_file>
function which has a more complex interface.");
("ll", (RString "listing", P1 (String "directory")), 5, [],
"list the files in a directory (long format)",
"\
List the files in C<directory> (relative to the root directory,
there is no cwd) in the format of 'ls -la'.
This command is mostly useful for interactive sessions. It
is I<not> intended that you try to parse the output string.");
("ls", (RStringList "listing", P1 (String "directory")), 6, [],
"list the files in a directory",
"\
List the files in C<directory> (relative to the root directory,
there is no cwd). The '.' and '..' entries are not returned, but
hidden files are shown.
This command is mostly useful for interactive sessions. Programs
should probably use C<guestfs_readdir> instead.");
("list_devices", (RStringList "devices", P0), 7, [],
"list the block devices",
"\
List all the block devices.
The full block device names are returned, eg. C</dev/sda>
");
("list_partitions", (RStringList "partitions", P0), 8, [],
"list the partitions",
"\
List all the partitions detected on all block devices.
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>.");
]
(* In some places we want the functions to be displayed sorted
* alphabetically, so this is useful:
*)
let sorted_functions =
List.sort (fun (n1,_,_,_,_,_) (n2,_,_,_,_,_) -> compare n1 n2) functions
(* Useful functions. *)
let failwithf fs = ksprintf failwith fs
let replace s c1 c2 =
let s2 = String.copy s in
let r = ref false in
for i = 0 to String.length s2 - 1 do
if String.unsafe_get s2 i = c1 then (
String.unsafe_set s2 i c2;
r := true
)
done;
if not !r then s else s2
(* 'pr' prints to the current output file. *)
let chan = ref stdout
let pr fs = ksprintf (output_string !chan) fs
@@ -135,6 +172,30 @@ let map_args f = function
let nr_args = function | P0 -> 0 | P1 _ -> 1 | P2 _ -> 2
(* Check function names etc. for consistency. *)
let check_functions () =
List.iter (
fun (name, _, _, _, _, _) ->
if String.contains name '-' then
failwithf "Function name '%s' should not contain '-', use '_' instead."
name
) functions;
let proc_nrs =
List.map (fun (name, _, proc_nr, _, _, _) -> name, proc_nr) functions in
let proc_nrs =
List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
let rec loop = function
| [] -> ()
| [_] -> ()
| (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
loop rest
| (name1,nr1) :: (name2,nr2) :: _ ->
failwithf "'%s' and '%s' have conflicting procedure numbers (%d, %d)"
name1 name2 nr1 nr2
in
loop proc_nrs
type comment_style = CStyle | HashStyle | OCamlStyle
type license = GPLv2 | LGPLv2
@@ -202,19 +263,18 @@ and generate_pod () =
| Err ->
pr "This function returns 0 on success or -1 on error.\n\n"
| RString _ ->
pr "This function returns a string or NULL on error. The caller
must free the returned string after use.\n\n"
pr "This function returns a string or NULL on error.
I<The caller must free the returned string after use>.\n\n"
| RStringList _ ->
pr "This function returns a NULL-terminated array of strings
(like L<environ(3)>), or NULL if there was an error.
The caller must free the strings I<and> the array after use.\n\n"
I<The caller must free the strings and the array after use>.\n\n"
);
if List.mem ProtocolLimitWarning flags then
pr "Because of the message protocol, there is a transfer limit
of somewhere between 2MB and 4MB. To transfer large files you should use
FTP.\n\n";
) functions
) sorted_functions
(* Generate the protocol (XDR) file. *)
and generate_xdr () =
@@ -562,9 +622,10 @@ and generate_fish_cmds () =
pr " list_builtin_commands ();\n";
List.iter (
fun (name, _, _, _, shortdesc, _) ->
let name = replace name '_' '-' in
pr " printf (\"%%-20s %%s\\n\", \"%s\", \"%s\");\n"
name shortdesc
) functions;
) sorted_functions;
pr " printf (\" Use -h <cmd> / help <cmd> to show detailed help for a command.\\n\");\n";
pr "}\n";
pr "\n";
@@ -574,12 +635,13 @@ and generate_fish_cmds () =
pr "{\n";
List.iter (
fun (name, style, _, flags, shortdesc, longdesc) ->
let name2 = replace name '_' '-' in
let synopsis =
match snd style with
| P0 -> name
| P0 -> name2
| args ->
sprintf "%s <%s>"
name (
name2 (
String.concat "> <" (
map_args (function
| String n -> n) args
@@ -593,9 +655,13 @@ of somewhere between 2MB and 4MB. To transfer large files you should use
FTP."
else "" in
pr " if (strcasecmp (cmd, \"%s\") == 0)\n" name;
pr " if (";
pr "strcasecmp (cmd, \"%s\") == 0" name;
if name <> name2 then
pr " || strcasecmp (cmd, \"%s\") == 0" name2;
pr ")\n";
pr " pod2text (\"%s - %s\", %S);\n"
name shortdesc
name2 shortdesc
(" " ^ synopsis ^ "\n\n" ^ longdesc ^ warnings);
pr " else\n"
) functions;
@@ -660,7 +726,12 @@ FTP."
pr "{\n";
List.iter (
fun (name, _, _, _, _, _) ->
pr " if (strcasecmp (cmd, \"%s\") == 0)\n" name;
let name2 = replace name '_' '-' in
pr " if (";
pr "strcasecmp (cmd, \"%s\") == 0" name;
if name <> name2 then
pr " || strcasecmp (cmd, \"%s\") == 0" name2;
pr ")\n";
pr " return run_%s (cmd, argc, argv);\n" name;
pr " else\n";
) functions;
@@ -733,6 +804,8 @@ let output_to filename =
(* Main program. *)
let () =
check_functions ();
let close = output_to "src/guestfs_protocol.x" in
generate_xdr ();
close ();

View File

@@ -19,6 +19,211 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
struct mount_rv {
int cb_done; /* flag to indicate callback was called */
struct guestfs_message_header hdr;
struct guestfs_message_error err;
};
static void mount_cb (guestfs_h *g, void *data, XDR *xdr)
{
struct mount_rv *rv = (struct mount_rv *) data;
if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
error (g, "guestfs_mount: failed to parse reply header");
return;
}
if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
if (!xdr_guestfs_message_error (xdr, &rv->err)) {
error (g, "guestfs_mount: failed to parse reply error");
return;
}
goto done;
}
done:
rv->cb_done = 1;
main_loop.main_loop_quit (g);
}
int guestfs_mount (guestfs_h *g,
const char *device,
const char *mountpoint)
{
struct guestfs_mount_args args;
struct mount_rv rv;
int serial;
if (g->state != READY) {
error (g, "guestfs_mount called from the wrong state, %d != READY",
g->state);
return -1;
}
memset (&rv, 0, sizeof rv);
args.device = (char *) device;
args.mountpoint = (char *) mountpoint;
serial = dispatch (g, GUESTFS_PROC_MOUNT,
(xdrproc_t) xdr_guestfs_mount_args, (char *) &args);
if (serial == -1)
return -1;
rv.cb_done = 0;
g->reply_cb_internal = mount_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_mount failed, see earlier error messages");
return -1;
}
if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_MOUNT, serial) == -1)
return -1;
if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
error (g, "%s", rv.err.error);
return -1;
}
return 0;
}
struct sync_rv {
int cb_done; /* flag to indicate callback was called */
struct guestfs_message_header hdr;
struct guestfs_message_error err;
};
static void sync_cb (guestfs_h *g, void *data, XDR *xdr)
{
struct sync_rv *rv = (struct sync_rv *) data;
if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
error (g, "guestfs_sync: failed to parse reply header");
return;
}
if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
if (!xdr_guestfs_message_error (xdr, &rv->err)) {
error (g, "guestfs_sync: failed to parse reply error");
return;
}
goto done;
}
done:
rv->cb_done = 1;
main_loop.main_loop_quit (g);
}
int guestfs_sync (guestfs_h *g)
{
struct sync_rv rv;
int serial;
if (g->state != READY) {
error (g, "guestfs_sync called from the wrong state, %d != READY",
g->state);
return -1;
}
memset (&rv, 0, sizeof rv);
serial = dispatch (g, GUESTFS_PROC_SYNC, NULL, NULL);
if (serial == -1)
return -1;
rv.cb_done = 0;
g->reply_cb_internal = sync_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_sync failed, see earlier error messages");
return -1;
}
if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_SYNC, serial) == -1)
return -1;
if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
error (g, "%s", rv.err.error);
return -1;
}
return 0;
}
struct touch_rv {
int cb_done; /* flag to indicate callback was called */
struct guestfs_message_header hdr;
struct guestfs_message_error err;
};
static void touch_cb (guestfs_h *g, void *data, XDR *xdr)
{
struct touch_rv *rv = (struct touch_rv *) data;
if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
error (g, "guestfs_touch: failed to parse reply header");
return;
}
if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
if (!xdr_guestfs_message_error (xdr, &rv->err)) {
error (g, "guestfs_touch: failed to parse reply error");
return;
}
goto done;
}
done:
rv->cb_done = 1;
main_loop.main_loop_quit (g);
}
int guestfs_touch (guestfs_h *g,
const char *path)
{
struct guestfs_touch_args args;
struct touch_rv rv;
int serial;
if (g->state != READY) {
error (g, "guestfs_touch called from the wrong state, %d != READY",
g->state);
return -1;
}
memset (&rv, 0, sizeof rv);
args.path = (char *) path;
serial = dispatch (g, GUESTFS_PROC_TOUCH,
(xdrproc_t) xdr_guestfs_touch_args, (char *) &args);
if (serial == -1)
return -1;
rv.cb_done = 0;
g->reply_cb_internal = touch_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_touch failed, see earlier error messages");
return -1;
}
if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_TOUCH, serial) == -1)
return -1;
if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
error (g, "%s", rv.err.error);
return -1;
}
return 0;
}
struct cat_rv {
int cb_done; /* flag to indicate callback was called */
struct guestfs_message_header hdr;
@@ -244,208 +449,149 @@ char **guestfs_ls (guestfs_h *g,
return rv.ret.listing.listing_val;
}
struct mount_rv {
struct list_devices_rv {
int cb_done; /* flag to indicate callback was called */
struct guestfs_message_header hdr;
struct guestfs_message_error err;
struct guestfs_list_devices_ret ret;
};
static void mount_cb (guestfs_h *g, void *data, XDR *xdr)
static void list_devices_cb (guestfs_h *g, void *data, XDR *xdr)
{
struct mount_rv *rv = (struct mount_rv *) data;
struct list_devices_rv *rv = (struct list_devices_rv *) data;
if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
error (g, "guestfs_mount: failed to parse reply header");
error (g, "guestfs_list_devices: failed to parse reply header");
return;
}
if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
if (!xdr_guestfs_message_error (xdr, &rv->err)) {
error (g, "guestfs_mount: failed to parse reply error");
error (g, "guestfs_list_devices: failed to parse reply error");
return;
}
goto done;
}
if (!xdr_guestfs_list_devices_ret (xdr, &rv->ret)) {
error (g, "guestfs_list_devices: failed to parse reply");
return;
}
done:
rv->cb_done = 1;
main_loop.main_loop_quit (g);
}
int guestfs_mount (guestfs_h *g,
const char *device,
const char *mountpoint)
char **guestfs_list_devices (guestfs_h *g)
{
struct guestfs_mount_args args;
struct mount_rv rv;
struct list_devices_rv rv;
int serial;
if (g->state != READY) {
error (g, "guestfs_mount called from the wrong state, %d != READY",
error (g, "guestfs_list_devices called from the wrong state, %d != READY",
g->state);
return -1;
return NULL;
}
memset (&rv, 0, sizeof rv);
args.device = (char *) device;
args.mountpoint = (char *) mountpoint;
serial = dispatch (g, GUESTFS_PROC_MOUNT,
(xdrproc_t) xdr_guestfs_mount_args, (char *) &args);
serial = dispatch (g, GUESTFS_PROC_LIST_DEVICES, NULL, NULL);
if (serial == -1)
return -1;
return NULL;
rv.cb_done = 0;
g->reply_cb_internal = mount_cb;
g->reply_cb_internal = list_devices_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_mount failed, see earlier error messages");
return -1;
error (g, "guestfs_list_devices failed, see earlier error messages");
return NULL;
}
if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_MOUNT, serial) == -1)
return -1;
if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_LIST_DEVICES, serial) == -1)
return NULL;
if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
error (g, "%s", rv.err.error);
return -1;
return NULL;
}
return 0;
/* caller will free this, but we need to add a NULL entry */
rv.ret.devices.devices_val = safe_realloc (g, rv.ret.devices.devices_val, rv.ret.devices.devices_len + 1);
rv.ret.devices.devices_val[rv.ret.devices.devices_len] = NULL;
return rv.ret.devices.devices_val;
}
struct sync_rv {
struct list_partitions_rv {
int cb_done; /* flag to indicate callback was called */
struct guestfs_message_header hdr;
struct guestfs_message_error err;
struct guestfs_list_partitions_ret ret;
};
static void sync_cb (guestfs_h *g, void *data, XDR *xdr)
static void list_partitions_cb (guestfs_h *g, void *data, XDR *xdr)
{
struct sync_rv *rv = (struct sync_rv *) data;
struct list_partitions_rv *rv = (struct list_partitions_rv *) data;
if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
error (g, "guestfs_sync: failed to parse reply header");
error (g, "guestfs_list_partitions: failed to parse reply header");
return;
}
if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
if (!xdr_guestfs_message_error (xdr, &rv->err)) {
error (g, "guestfs_sync: failed to parse reply error");
error (g, "guestfs_list_partitions: failed to parse reply error");
return;
}
goto done;
}
if (!xdr_guestfs_list_partitions_ret (xdr, &rv->ret)) {
error (g, "guestfs_list_partitions: failed to parse reply");
return;
}
done:
rv->cb_done = 1;
main_loop.main_loop_quit (g);
}
int guestfs_sync (guestfs_h *g)
char **guestfs_list_partitions (guestfs_h *g)
{
struct sync_rv rv;
struct list_partitions_rv rv;
int serial;
if (g->state != READY) {
error (g, "guestfs_sync called from the wrong state, %d != READY",
error (g, "guestfs_list_partitions called from the wrong state, %d != READY",
g->state);
return -1;
return NULL;
}
memset (&rv, 0, sizeof rv);
serial = dispatch (g, GUESTFS_PROC_SYNC, NULL, NULL);
serial = dispatch (g, GUESTFS_PROC_LIST_PARTITIONS, NULL, NULL);
if (serial == -1)
return -1;
return NULL;
rv.cb_done = 0;
g->reply_cb_internal = sync_cb;
g->reply_cb_internal = list_partitions_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_sync failed, see earlier error messages");
return -1;
error (g, "guestfs_list_partitions failed, see earlier error messages");
return NULL;
}
if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_SYNC, serial) == -1)
return -1;
if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_LIST_PARTITIONS, serial) == -1)
return NULL;
if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
error (g, "%s", rv.err.error);
return -1;
return NULL;
}
return 0;
}
struct touch_rv {
int cb_done; /* flag to indicate callback was called */
struct guestfs_message_header hdr;
struct guestfs_message_error err;
};
static void touch_cb (guestfs_h *g, void *data, XDR *xdr)
{
struct touch_rv *rv = (struct touch_rv *) data;
if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {
error (g, "guestfs_touch: failed to parse reply header");
return;
}
if (rv->hdr.status == GUESTFS_STATUS_ERROR) {
if (!xdr_guestfs_message_error (xdr, &rv->err)) {
error (g, "guestfs_touch: failed to parse reply error");
return;
}
goto done;
}
done:
rv->cb_done = 1;
main_loop.main_loop_quit (g);
}
int guestfs_touch (guestfs_h *g,
const char *path)
{
struct guestfs_touch_args args;
struct touch_rv rv;
int serial;
if (g->state != READY) {
error (g, "guestfs_touch called from the wrong state, %d != READY",
g->state);
return -1;
}
memset (&rv, 0, sizeof rv);
args.path = (char *) path;
serial = dispatch (g, GUESTFS_PROC_TOUCH,
(xdrproc_t) xdr_guestfs_touch_args, (char *) &args);
if (serial == -1)
return -1;
rv.cb_done = 0;
g->reply_cb_internal = touch_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_touch failed, see earlier error messages");
return -1;
}
if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_TOUCH, serial) == -1)
return -1;
if (rv.hdr.status == GUESTFS_STATUS_ERROR) {
error (g, "%s", rv.err.error);
return -1;
}
return 0;
/* caller will free this, but we need to add a NULL entry */
rv.ret.partitions.partitions_val = safe_realloc (g, rv.ret.partitions.partitions_val, rv.ret.partitions.partitions_len + 1);
rv.ret.partitions.partitions_val[rv.ret.partitions.partitions_len] = NULL;
return rv.ret.partitions.partitions_val;
}

View File

@@ -19,9 +19,11 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
extern char *guestfs_cat (guestfs_h *handle, const char *path);
extern char *guestfs_ll (guestfs_h *handle, const char *directory);
extern char **guestfs_ls (guestfs_h *handle, const char *directory);
extern int guestfs_mount (guestfs_h *handle, const char *device, const char *mountpoint);
extern int guestfs_sync (guestfs_h *handle);
extern int guestfs_touch (guestfs_h *handle, const char *path);
extern char *guestfs_cat (guestfs_h *handle, const char *path);
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);

View File

@@ -15,6 +15,28 @@ xdr_str (XDR *xdrs, str *objp)
return TRUE;
}
bool_t
xdr_guestfs_mount_args (XDR *xdrs, guestfs_mount_args *objp)
{
register int32_t *buf;
if (!xdr_string (xdrs, &objp->device, ~0))
return FALSE;
if (!xdr_string (xdrs, &objp->mountpoint, ~0))
return FALSE;
return TRUE;
}
bool_t
xdr_guestfs_touch_args (XDR *xdrs, guestfs_touch_args *objp)
{
register int32_t *buf;
if (!xdr_string (xdrs, &objp->path, ~0))
return FALSE;
return TRUE;
}
bool_t
xdr_guestfs_cat_args (XDR *xdrs, guestfs_cat_args *objp)
{
@@ -77,23 +99,23 @@ xdr_guestfs_ls_ret (XDR *xdrs, guestfs_ls_ret *objp)
}
bool_t
xdr_guestfs_mount_args (XDR *xdrs, guestfs_mount_args *objp)
xdr_guestfs_list_devices_ret (XDR *xdrs, guestfs_list_devices_ret *objp)
{
register int32_t *buf;
if (!xdr_string (xdrs, &objp->device, ~0))
return FALSE;
if (!xdr_string (xdrs, &objp->mountpoint, ~0))
if (!xdr_array (xdrs, (char **)&objp->devices.devices_val, (u_int *) &objp->devices.devices_len, ~0,
sizeof (str), (xdrproc_t) xdr_str))
return FALSE;
return TRUE;
}
bool_t
xdr_guestfs_touch_args (XDR *xdrs, guestfs_touch_args *objp)
xdr_guestfs_list_partitions_ret (XDR *xdrs, guestfs_list_partitions_ret *objp)
{
register int32_t *buf;
if (!xdr_string (xdrs, &objp->path, ~0))
if (!xdr_array (xdrs, (char **)&objp->partitions.partitions_val, (u_int *) &objp->partitions.partitions_len, ~0,
sizeof (str), (xdrproc_t) xdr_str))
return FALSE;
return TRUE;
}

View File

@@ -16,6 +16,17 @@ extern "C" {
typedef char *str;
struct guestfs_mount_args {
char *device;
char *mountpoint;
};
typedef struct guestfs_mount_args guestfs_mount_args;
struct guestfs_touch_args {
char *path;
};
typedef struct guestfs_touch_args guestfs_touch_args;
struct guestfs_cat_args {
char *path;
};
@@ -49,25 +60,32 @@ struct guestfs_ls_ret {
};
typedef struct guestfs_ls_ret guestfs_ls_ret;
struct guestfs_mount_args {
char *device;
char *mountpoint;
struct guestfs_list_devices_ret {
struct {
u_int devices_len;
str *devices_val;
} devices;
};
typedef struct guestfs_mount_args guestfs_mount_args;
typedef struct guestfs_list_devices_ret guestfs_list_devices_ret;
struct guestfs_touch_args {
char *path;
struct guestfs_list_partitions_ret {
struct {
u_int partitions_len;
str *partitions_val;
} partitions;
};
typedef struct guestfs_touch_args guestfs_touch_args;
typedef struct guestfs_list_partitions_ret guestfs_list_partitions_ret;
enum guestfs_procedure {
GUESTFS_PROC_CAT = 4,
GUESTFS_PROC_LL = 5,
GUESTFS_PROC_LS = 6,
GUESTFS_PROC_MOUNT = 1,
GUESTFS_PROC_SYNC = 2,
GUESTFS_PROC_TOUCH = 3,
GUESTFS_PROC_dummy = 3 + 1,
GUESTFS_PROC_CAT = 4,
GUESTFS_PROC_LL = 5,
GUESTFS_PROC_LS = 6,
GUESTFS_PROC_LIST_DEVICES = 7,
GUESTFS_PROC_LIST_PARTITIONS = 8,
GUESTFS_PROC_dummy = 8 + 1,
};
typedef enum guestfs_procedure guestfs_procedure;
#define GUESTFS_MESSAGE_MAX 4194304
@@ -106,14 +124,16 @@ 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_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*);
extern bool_t xdr_guestfs_cat_ret (XDR *, guestfs_cat_ret*);
extern bool_t xdr_guestfs_ll_args (XDR *, guestfs_ll_args*);
extern bool_t xdr_guestfs_ll_ret (XDR *, guestfs_ll_ret*);
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_mount_args (XDR *, guestfs_mount_args*);
extern bool_t xdr_guestfs_touch_args (XDR *, guestfs_touch_args*);
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_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*);
@@ -122,14 +142,16 @@ 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_mount_args ();
extern bool_t xdr_guestfs_touch_args ();
extern bool_t xdr_guestfs_cat_args ();
extern bool_t xdr_guestfs_cat_ret ();
extern bool_t xdr_guestfs_ll_args ();
extern bool_t xdr_guestfs_ll_ret ();
extern bool_t xdr_guestfs_ls_args ();
extern bool_t xdr_guestfs_ls_ret ();
extern bool_t xdr_guestfs_mount_args ();
extern bool_t xdr_guestfs_touch_args ();
extern bool_t xdr_guestfs_list_devices_ret ();
extern bool_t xdr_guestfs_list_partitions_ret ();
extern bool_t xdr_guestfs_procedure ();
extern bool_t xdr_guestfs_message_direction ();
extern bool_t xdr_guestfs_message_status ();

View File

@@ -21,6 +21,21 @@
typedef string str<>;
/* guestfs_mount */
struct guestfs_mount_args {
string device<>;
string mountpoint<>;
};
/* guestfs_sync */
/* guestfs_touch */
struct guestfs_touch_args {
string path<>;
};
/* guestfs_cat */
struct guestfs_cat_args {
@@ -51,28 +66,27 @@ struct guestfs_ls_ret {
str listing<>;
};
/* guestfs_mount */
/* guestfs_list_devices */
struct guestfs_mount_args {
string device<>;
string mountpoint<>;
struct guestfs_list_devices_ret {
str devices<>;
};
/* guestfs_sync */
/* guestfs_list_partitions */
/* guestfs_touch */
struct guestfs_touch_args {
string path<>;
struct guestfs_list_partitions_ret {
str partitions<>;
};
enum guestfs_procedure {
GUESTFS_PROC_CAT = 4,
GUESTFS_PROC_LL = 5,
GUESTFS_PROC_LS = 6,
GUESTFS_PROC_MOUNT = 1,
GUESTFS_PROC_SYNC = 2,
GUESTFS_PROC_TOUCH = 3,
GUESTFS_PROC_CAT = 4,
GUESTFS_PROC_LL = 5,
GUESTFS_PROC_LS = 6,
GUESTFS_PROC_LIST_DEVICES = 7,
GUESTFS_PROC_LIST_PARTITIONS = 8,
GUESTFS_PROC_dummy
};