From 0703248d233744047515418893dac05ce013a642 Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Thu, 30 Apr 2009 18:57:07 +0100 Subject: [PATCH] Add generated code for 'fsck' command. --- daemon/actions.h | 1 + daemon/daemon.h | 3 + daemon/guestfsd.c | 65 +++++++++++++++++++-- daemon/stubs.c | 31 ++++++++++ fish/cmds.c | 25 ++++++++ fish/completion.c | 1 + guestfish-actions.pod | 15 +++++ guestfs-actions.pod | 19 ++++++ java/com/redhat/et/libguestfs/GuestFS.java | 26 +++++++++ java/com_redhat_et_libguestfs_GuestFS.c | 21 +++++++ ocaml/guestfs.ml | 1 + ocaml/guestfs.mli | 3 + ocaml/guestfs_c_actions.c | 24 ++++++++ perl/Guestfs.xs | 15 +++++ perl/lib/Sys/Guestfs.pm | 13 +++++ python/guestfs-py.c | 26 +++++++++ python/guestfs.py | 14 +++++ ruby/ext/guestfs/_guestfs.c | 27 +++++++++ src/guestfs-actions.c | 93 ++++++++++++++++++++++++++++++ src/guestfs-actions.h | 1 + src/guestfs_protocol.c | 22 +++++++ src/guestfs_protocol.h | 18 +++++- src/guestfs_protocol.x | 10 ++++ tests.c | 61 +++++++++++++++++++- 24 files changed, 529 insertions(+), 6 deletions(-) diff --git a/daemon/actions.h b/daemon/actions.h index 373e513..7455586 100644 --- a/daemon/actions.h +++ b/daemon/actions.h @@ -104,3 +104,4 @@ extern int do_set_e2label (const char *device, const char *label); extern char *do_get_e2label (const char *device); extern int do_set_e2uuid (const char *device, const char *uuid); extern char *do_get_e2uuid (const char *device); +extern int do_fsck (const char *fstype, const char *device); diff --git a/daemon/daemon.h b/daemon/daemon.h index 3f51056..001c703 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -41,8 +41,11 @@ extern void free_strings (char **argv); extern void free_stringslen (char **argv, int len); extern int command (char **stdoutput, char **stderror, const char *name, ...); +extern int commandr (char **stdoutput, char **stderror, const char *name, ...); extern int commandv (char **stdoutput, char **stderror, char * const* const argv); +extern int commandrv (char **stdoutput, char **stderror, + char * const* const argv); extern int shell_quote (char *out, int len, const char *in); diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c index ba4035e..99055a9 100644 --- a/daemon/guestfsd.c +++ b/daemon/guestfsd.c @@ -378,9 +378,69 @@ command (char **stdoutput, char **stderror, const char *name, ...) return r; } +/* Same as 'command', but we allow the status code from the + * subcommand to be non-zero, and return that status code. + * We still return -1 if there was some other error. + */ +int +commandr (char **stdoutput, char **stderror, const char *name, ...) +{ + va_list args; + char **argv, **p; + char *s; + int i, r; + + /* Collect the command line arguments into an array. */ + i = 2; + argv = malloc (sizeof (char *) * i); + if (argv == NULL) { + perror ("malloc"); + return -1; + } + argv[0] = (char *) name; + argv[1] = NULL; + + va_start (args, name); + + while ((s = va_arg (args, char *)) != NULL) { + p = realloc (argv, sizeof (char *) * (++i)); + if (p == NULL) { + perror ("realloc"); + free (argv); + va_end (args); + return -1; + } + argv = p; + argv[i-2] = s; + argv[i-1] = NULL; + } + + va_end (args); + + r = commandrv (stdoutput, stderror, argv); + + /* NB: Mustn't free the strings which are on the stack. */ + free (argv); + + return r; +} + +/* Same as 'command', but passing an argv. */ int commandv (char **stdoutput, char **stderror, char * const* const argv) { + int r; + + r = commandrv (stdoutput, stderror, argv); + if (r == 0) + return 0; + else + return -1; +} + +int +commandrv (char **stdoutput, char **stderror, char * const* const argv) +{ int so_size = 0, se_size = 0; int so_fd[2], se_fd[2]; int pid, r, quit, i; @@ -524,10 +584,7 @@ commandv (char **stdoutput, char **stderror, char * const* const argv) waitpid (pid, &r, 0); if (WIFEXITED (r)) { - if (WEXITSTATUS (r) == 0) - return 0; - else - return -1; + return WEXITSTATUS (r); } else return -1; } diff --git a/daemon/stubs.c b/daemon/stubs.c index 019e4fb..9e0ce55 100644 --- a/daemon/stubs.c +++ b/daemon/stubs.c @@ -2075,6 +2075,34 @@ done: xdr_free ((xdrproc_t) xdr_guestfs_get_e2uuid_args, (char *) &args); } +static void fsck_stub (XDR *xdr_in) +{ + int r; + struct guestfs_fsck_args args; + const char *fstype; + const char *device; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_fsck_args (xdr_in, &args)) { + reply_with_error ("%s: daemon failed to decode procedure arguments", "fsck"); + return; + } + fstype = args.fstype; + device = args.device; + + r = do_fsck (fstype, device); + if (r == -1) + /* do_fsck has already called reply_with_error */ + goto done; + + struct guestfs_fsck_ret ret; + ret.status = r; + reply ((xdrproc_t) &xdr_guestfs_fsck_ret, (char *) &ret); +done: + xdr_free ((xdrproc_t) xdr_guestfs_fsck_args, (char *) &args); +} + void dispatch_incoming_message (XDR *xdr_in) { switch (proc_nr) { @@ -2327,6 +2355,9 @@ void dispatch_incoming_message (XDR *xdr_in) case GUESTFS_PROC_GET_E2UUID: get_e2uuid_stub (xdr_in); break; + case GUESTFS_PROC_FSCK: + fsck_stub (xdr_in); + break; default: reply_with_error ("dispatch_incoming_message: unknown procedure number %d", proc_nr); } diff --git a/fish/cmds.c b/fish/cmds.c index 1e8cb30..e762521 100644 --- a/fish/cmds.c +++ b/fish/cmds.c @@ -67,6 +67,7 @@ void list_commands (void) printf ("%-20s %s\n", "download", "download a file to the local machine"); printf ("%-20s %s\n", "exists", "test if file or directory exists"); printf ("%-20s %s\n", "file", "determine file type"); + printf ("%-20s %s\n", "fsck", "run the filesystem checker"); printf ("%-20s %s\n", "get-autosync", "get autosync mode"); printf ("%-20s %s\n", "get-e2label", "get the ext2/3/4 filesystem label"); printf ("%-20s %s\n", "get-e2uuid", "get the ext2/3/4 filesystem UUID"); @@ -440,6 +441,9 @@ void display_command (const char *cmd) if (strcasecmp (cmd, "get_e2uuid") == 0 || strcasecmp (cmd, "get-e2uuid") == 0) pod2text ("get-e2uuid - get the ext2/3/4 filesystem UUID", " get-e2uuid \n\nThis returns the ext2/3/4 filesystem UUID of the filesystem on\nC."); else + if (strcasecmp (cmd, "fsck") == 0) + pod2text ("fsck - run the filesystem checker", " fsck \n\nThis runs the filesystem checker (fsck) on C which\nshould have filesystem type C.\n\nThe returned integer is the status. See L for the\nlist of status codes from C, and note that multiple\nstatus codes can be summed together.\n\nIt is entirely equivalent to running C.\nNote that checking or repairing NTFS volumes is not supported\n(by linux-ntfs)."); + else display_builtin_command (cmd); } @@ -2142,6 +2146,24 @@ static int run_get_e2uuid (const char *cmd, int argc, char *argv[]) return 0; } +static int run_fsck (const char *cmd, int argc, char *argv[]) +{ + int r; + const char *fstype; + const char *device; + 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; + } + fstype = argv[0]; + device = argv[1]; + r = guestfs_fsck (g, fstype, device); + if (r == -1) return -1; + printf ("%d\n", r); + return 0; +} + int run_action (const char *cmd, int argc, char *argv[]) { if (strcasecmp (cmd, "launch") == 0 || strcasecmp (cmd, "run") == 0) @@ -2447,6 +2469,9 @@ int run_action (const char *cmd, int argc, char *argv[]) if (strcasecmp (cmd, "get_e2uuid") == 0 || strcasecmp (cmd, "get-e2uuid") == 0) return run_get_e2uuid (cmd, argc, argv); else + if (strcasecmp (cmd, "fsck") == 0) + return run_fsck (cmd, argc, argv); + else { fprintf (stderr, "%s: unknown command\n", cmd); return -1; diff --git a/fish/completion.c b/fish/completion.c index e44c388..cafb84d 100644 --- a/fish/completion.c +++ b/fish/completion.c @@ -73,6 +73,7 @@ static const char *const commands[] = { "download", "exists", "file", + "fsck", "get-autosync", "get-e2label", "get-e2uuid", diff --git a/guestfish-actions.pod b/guestfish-actions.pod index fce1b31..c1981c5 100644 --- a/guestfish-actions.pod +++ b/guestfish-actions.pod @@ -449,6 +449,21 @@ The exact command which runs is C. Note in particular that the filename is not prepended to the output (the C<-b> option). +=head2 fsck + + fsck fstype device + +This runs the filesystem checker (fsck) on C which +should have filesystem type C. + +The returned integer is the status. See L for the +list of status codes from C, and note that multiple +status codes can be summed together. + +It is entirely equivalent to running C. +Note that checking or repairing NTFS volumes is not supported +(by linux-ntfs). + =head2 get-autosync get-autosync diff --git a/guestfs-actions.pod b/guestfs-actions.pod index 210e825..07b35af 100644 --- a/guestfs-actions.pod +++ b/guestfs-actions.pod @@ -582,6 +582,25 @@ particular that the filename is not prepended to the output This function returns a string, or NULL on error. I. +=head2 guestfs_fsck + + int guestfs_fsck (guestfs_h *handle, + const char *fstype, + const char *device); + +This runs the filesystem checker (fsck) on C which +should have filesystem type C. + +The returned integer is the status. See L for the +list of status codes from C, and note that multiple +status codes can be summed together. + +It is entirely equivalent to running C. +Note that checking or repairing NTFS volumes is not supported +(by linux-ntfs). + +On error this function returns -1. + =head2 guestfs_get_autosync int guestfs_get_autosync (guestfs_h *handle); diff --git a/java/com/redhat/et/libguestfs/GuestFS.java b/java/com/redhat/et/libguestfs/GuestFS.java index 7e7cd68..844c3b3 100644 --- a/java/com/redhat/et/libguestfs/GuestFS.java +++ b/java/com/redhat/et/libguestfs/GuestFS.java @@ -2356,4 +2356,30 @@ public class GuestFS { private native String _get_e2uuid (long g, String device) throws LibGuestFSException; + /** + * run the filesystem checker + * + * This runs the filesystem checker (fsck) on "device" + * which should have filesystem type "fstype". + * + * The returned integer is the status. See fsck(8) for the + * list of status codes from "fsck", and note that multiple + * status codes can be summed together. + * + * It is entirely equivalent to running "fsck -a -t fstype + * device". Note that checking or repairing NTFS volumes is + * not supported (by linux-ntfs). + * + * @throws LibGuestFSException + */ + public int fsck (String fstype, String device) + throws LibGuestFSException + { + if (g == 0) + throw new LibGuestFSException ("fsck: handle is closed"); + return _fsck (g, fstype, device); + } + private native int _fsck (long g, String fstype, String device) + throws LibGuestFSException; + } diff --git a/java/com_redhat_et_libguestfs_GuestFS.c b/java/com_redhat_et_libguestfs_GuestFS.c index f012a4b..1f5579e 100644 --- a/java/com_redhat_et_libguestfs_GuestFS.c +++ b/java/com_redhat_et_libguestfs_GuestFS.c @@ -2399,3 +2399,24 @@ Java_com_redhat_et_libguestfs_GuestFS__1get_1e2uuid return jr; } +JNIEXPORT jint JNICALL +Java_com_redhat_et_libguestfs_GuestFS__1fsck + (JNIEnv *env, jobject obj, jlong jg, jstring jfstype, jstring jdevice) +{ + guestfs_h *g = (guestfs_h *) (long) jg; + int r; + const char *fstype; + const char *device; + + fstype = (*env)->GetStringUTFChars (env, jfstype, NULL); + device = (*env)->GetStringUTFChars (env, jdevice, NULL); + r = guestfs_fsck (g, fstype, device); + (*env)->ReleaseStringUTFChars (env, jfstype, fstype); + (*env)->ReleaseStringUTFChars (env, jdevice, device); + if (r == -1) { + throw_exception (env, guestfs_last_error (g)); + return 0; + } + return (jint) r; +} + diff --git a/ocaml/guestfs.ml b/ocaml/guestfs.ml index b8511a4..32e2264 100644 --- a/ocaml/guestfs.ml +++ b/ocaml/guestfs.ml @@ -219,3 +219,4 @@ external set_e2label : t -> string -> string -> unit = "ocaml_guestfs_set_e2labe external get_e2label : t -> string -> string = "ocaml_guestfs_get_e2label" external set_e2uuid : t -> string -> string -> unit = "ocaml_guestfs_set_e2uuid" external get_e2uuid : t -> string -> string = "ocaml_guestfs_get_e2uuid" +external fsck : t -> string -> string -> int = "ocaml_guestfs_fsck" diff --git a/ocaml/guestfs.mli b/ocaml/guestfs.mli index 291f340..2cbd734 100644 --- a/ocaml/guestfs.mli +++ b/ocaml/guestfs.mli @@ -436,3 +436,6 @@ val set_e2uuid : t -> string -> string -> unit val get_e2uuid : t -> string -> string (** get the ext2/3/4 filesystem UUID *) +val fsck : t -> string -> string -> int +(** run the filesystem checker *) + diff --git a/ocaml/guestfs_c_actions.c b/ocaml/guestfs_c_actions.c index 9f860ba..22dc18f 100644 --- a/ocaml/guestfs_c_actions.c +++ b/ocaml/guestfs_c_actions.c @@ -2799,3 +2799,27 @@ ocaml_guestfs_get_e2uuid (value gv, value devicev) CAMLreturn (rv); } +CAMLprim value +ocaml_guestfs_fsck (value gv, value fstypev, value devicev) +{ + CAMLparam3 (gv, fstypev, devicev); + CAMLlocal1 (rv); + + guestfs_h *g = Guestfs_val (gv); + if (g == NULL) + caml_failwith ("fsck: used handle after closing it"); + + const char *fstype = String_val (fstypev); + const char *device = String_val (devicev); + int r; + + caml_enter_blocking_section (); + r = guestfs_fsck (g, fstype, device); + caml_leave_blocking_section (); + if (r == -1) + ocaml_guestfs_raise_error (g, "fsck"); + + rv = Val_int (r); + CAMLreturn (rv); +} + diff --git a/perl/Guestfs.xs b/perl/Guestfs.xs index 9d8a49c..38c60c2 100644 --- a/perl/Guestfs.xs +++ b/perl/Guestfs.xs @@ -1573,3 +1573,18 @@ PREINIT: OUTPUT: RETVAL +SV * +fsck (g, fstype, device) + guestfs_h *g; + char *fstype; + char *device; +PREINIT: + int status; + CODE: + status = guestfs_fsck (g, fstype, device); + if (status == -1) + croak ("fsck: %s", guestfs_last_error (g)); + RETVAL = newSViv (status); + OUTPUT: + RETVAL + diff --git a/perl/lib/Sys/Guestfs.pm b/perl/lib/Sys/Guestfs.pm index efc2845..5b87b27 100644 --- a/perl/lib/Sys/Guestfs.pm +++ b/perl/lib/Sys/Guestfs.pm @@ -468,6 +468,19 @@ The exact command which runs is C. Note in particular that the filename is not prepended to the output (the C<-b> option). +=item $status = $h->fsck ($fstype, $device); + +This runs the filesystem checker (fsck) on C which +should have filesystem type C. + +The returned integer is the status. See L for the +list of status codes from C, and note that multiple +status codes can be summed together. + +It is entirely equivalent to running C. +Note that checking or repairing NTFS volumes is not supported +(by linux-ntfs). + =item $autosync = $h->get_autosync (); Get the autosync flag. diff --git a/python/guestfs-py.c b/python/guestfs-py.c index 3f3cb4d..6b93b27 100644 --- a/python/guestfs-py.c +++ b/python/guestfs-py.c @@ -3002,6 +3002,31 @@ py_guestfs_get_e2uuid (PyObject *self, PyObject *args) return py_r; } +static PyObject * +py_guestfs_fsck (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *fstype; + const char *device; + + if (!PyArg_ParseTuple (args, (char *) "Oss:guestfs_fsck", + &py_g, &fstype, &device)) + return NULL; + g = get_handle (py_g); + + r = guestfs_fsck (g, fstype, device); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = PyInt_FromLong ((long) r); + return py_r; +} + static PyMethodDef methods[] = { { (char *) "create", py_guestfs_create, METH_VARARGS, NULL }, { (char *) "close", py_guestfs_close, METH_VARARGS, NULL }, @@ -3109,6 +3134,7 @@ static PyMethodDef methods[] = { { (char *) "get_e2label", py_guestfs_get_e2label, METH_VARARGS, NULL }, { (char *) "set_e2uuid", py_guestfs_set_e2uuid, METH_VARARGS, NULL }, { (char *) "get_e2uuid", py_guestfs_get_e2uuid, METH_VARARGS, NULL }, + { (char *) "fsck", py_guestfs_fsck, METH_VARARGS, NULL }, { NULL, NULL, 0, NULL } }; diff --git a/python/guestfs.py b/python/guestfs.py index 2fced28..37dce2b 100644 --- a/python/guestfs.py +++ b/python/guestfs.py @@ -1149,3 +1149,17 @@ class GuestFS: """ return libguestfsmod.get_e2uuid (self._o, device) + def fsck (self, fstype, device): + u"""This runs the filesystem checker (fsck) on "device" + which should have filesystem type "fstype". + + The returned integer is the status. See fsck(8) for the + list of status codes from "fsck", and note that multiple + status codes can be summed together. + + It is entirely equivalent to running "fsck -a -t fstype + device". Note that checking or repairing NTFS volumes is + not supported (by linux-ntfs). + """ + return libguestfsmod.fsck (self._o, fstype, device) + diff --git a/ruby/ext/guestfs/_guestfs.c b/ruby/ext/guestfs/_guestfs.c index e6c4236..56b3f21 100644 --- a/ruby/ext/guestfs/_guestfs.c +++ b/ruby/ext/guestfs/_guestfs.c @@ -2515,6 +2515,31 @@ static VALUE ruby_guestfs_get_e2uuid (VALUE gv, VALUE devicev) return rv; } +static VALUE ruby_guestfs_fsck (VALUE gv, VALUE fstypev, VALUE devicev) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "fsck"); + + const char *fstype = StringValueCStr (fstypev); + if (!fstype) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "fstype", "fsck"); + const char *device = StringValueCStr (devicev); + if (!device) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "device", "fsck"); + + int r; + + r = guestfs_fsck (g, fstype, device); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return INT2NUM (r); +} + /* Initialize the module. */ void Init__guestfs () { @@ -2733,4 +2758,6 @@ void Init__guestfs () ruby_guestfs_set_e2uuid, 2); rb_define_method (c_guestfs, "get_e2uuid", ruby_guestfs_get_e2uuid, 1); + rb_define_method (c_guestfs, "fsck", + ruby_guestfs_fsck, 2); } diff --git a/src/guestfs-actions.c b/src/guestfs-actions.c index f39aa75..a075b80 100644 --- a/src/guestfs-actions.c +++ b/src/guestfs-actions.c @@ -7549,3 +7549,96 @@ char *guestfs_get_e2uuid (guestfs_h *g, return ctx.ret.uuid; /* caller will free */ } +struct fsck_ctx { + /* This flag is set by the callbacks, so we know we've done + * the callbacks as expected, and in the right sequence. + * 0 = not called, 1 = reply_cb called. + */ + int cb_sequence; + struct guestfs_message_header hdr; + struct guestfs_message_error err; + struct guestfs_fsck_ret ret; +}; + +static void fsck_reply_cb (guestfs_h *g, void *data, XDR *xdr) +{ + guestfs_main_loop *ml = guestfs_get_main_loop (g); + struct fsck_ctx *ctx = (struct fsck_ctx *) data; + + /* This should definitely not happen. */ + if (ctx->cb_sequence != 0) { + ctx->cb_sequence = 9999; + error (g, "%s: internal error: reply callback called twice", "guestfs_fsck"); + return; + } + + ml->main_loop_quit (ml, g); + + if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { + error (g, "%s: failed to parse reply header", "guestfs_fsck"); + return; + } + if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { + if (!xdr_guestfs_message_error (xdr, &ctx->err)) { + error (g, "%s: failed to parse reply error", "guestfs_fsck"); + return; + } + goto done; + } + if (!xdr_guestfs_fsck_ret (xdr, &ctx->ret)) { + error (g, "%s: failed to parse reply", "guestfs_fsck"); + return; + } + done: + ctx->cb_sequence = 1; +} + +int guestfs_fsck (guestfs_h *g, + const char *fstype, + const char *device) +{ + struct guestfs_fsck_args args; + struct fsck_ctx ctx; + guestfs_main_loop *ml = guestfs_get_main_loop (g); + int serial; + + if (check_state (g, "guestfs_fsck") == -1) return -1; + guestfs_set_busy (g); + + memset (&ctx, 0, sizeof ctx); + + args.fstype = (char *) fstype; + args.device = (char *) device; + serial = guestfs__send_sync (g, GUESTFS_PROC_FSCK, + (xdrproc_t) xdr_guestfs_fsck_args, (char *) &args); + if (serial == -1) { + guestfs_set_ready (g); + return -1; + } + + guestfs__switch_to_receiving (g); + ctx.cb_sequence = 0; + guestfs_set_reply_callback (g, fsck_reply_cb, &ctx); + (void) ml->main_loop_run (ml, g); + guestfs_set_reply_callback (g, NULL, NULL); + if (ctx.cb_sequence != 1) { + error (g, "%s reply failed, see earlier error messages", "guestfs_fsck"); + guestfs_set_ready (g); + return -1; + } + + if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_FSCK, serial) == -1) { + guestfs_set_ready (g); + return -1; + } + + if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { + error (g, "%s", ctx.err.error_message); + guestfs_set_ready (g); + return -1; + } + + guestfs_set_ready (g); + return ctx.ret.status; +} + diff --git a/src/guestfs-actions.h b/src/guestfs-actions.h index c8570b0..6e56099 100644 --- a/src/guestfs-actions.h +++ b/src/guestfs-actions.h @@ -123,3 +123,4 @@ extern int guestfs_set_e2label (guestfs_h *handle, const char *device, const cha extern char *guestfs_get_e2label (guestfs_h *handle, const char *device); extern int guestfs_set_e2uuid (guestfs_h *handle, const char *device, const char *uuid); extern char *guestfs_get_e2uuid (guestfs_h *handle, const char *device); +extern int guestfs_fsck (guestfs_h *handle, const char *fstype, const char *device); diff --git a/src/guestfs_protocol.c b/src/guestfs_protocol.c index c26d539..16e80f1 100644 --- a/src/guestfs_protocol.c +++ b/src/guestfs_protocol.c @@ -1428,6 +1428,28 @@ xdr_guestfs_get_e2uuid_ret (XDR *xdrs, guestfs_get_e2uuid_ret *objp) } bool_t +xdr_guestfs_fsck_args (XDR *xdrs, guestfs_fsck_args *objp) +{ + register int32_t *buf; + + if (!xdr_string (xdrs, &objp->fstype, ~0)) + return FALSE; + if (!xdr_string (xdrs, &objp->device, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_guestfs_fsck_ret (XDR *xdrs, guestfs_fsck_ret *objp) +{ + register int32_t *buf; + + if (!xdr_int (xdrs, &objp->status)) + 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 90b0ede..64e4b4d 100644 --- a/src/guestfs_protocol.h +++ b/src/guestfs_protocol.h @@ -739,6 +739,17 @@ struct guestfs_get_e2uuid_ret { }; typedef struct guestfs_get_e2uuid_ret guestfs_get_e2uuid_ret; +struct guestfs_fsck_args { + char *fstype; + char *device; +}; +typedef struct guestfs_fsck_args guestfs_fsck_args; + +struct guestfs_fsck_ret { + int status; +}; +typedef struct guestfs_fsck_ret guestfs_fsck_ret; + enum guestfs_procedure { GUESTFS_PROC_MOUNT = 1, GUESTFS_PROC_SYNC = 2, @@ -823,7 +834,8 @@ enum guestfs_procedure { GUESTFS_PROC_GET_E2LABEL = 81, GUESTFS_PROC_SET_E2UUID = 82, GUESTFS_PROC_GET_E2UUID = 83, - GUESTFS_PROC_NR_PROCS = 83 + 1, + GUESTFS_PROC_FSCK = 84, + GUESTFS_PROC_NR_PROCS = 84 + 1, }; typedef enum guestfs_procedure guestfs_procedure; #define GUESTFS_MESSAGE_MAX 4194304 @@ -988,6 +1000,8 @@ extern bool_t xdr_guestfs_get_e2label_ret (XDR *, guestfs_get_e2label_ret*); extern bool_t xdr_guestfs_set_e2uuid_args (XDR *, guestfs_set_e2uuid_args*); extern bool_t xdr_guestfs_get_e2uuid_args (XDR *, guestfs_get_e2uuid_args*); extern bool_t xdr_guestfs_get_e2uuid_ret (XDR *, guestfs_get_e2uuid_ret*); +extern bool_t xdr_guestfs_fsck_args (XDR *, guestfs_fsck_args*); +extern bool_t xdr_guestfs_fsck_ret (XDR *, guestfs_fsck_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*); @@ -1111,6 +1125,8 @@ extern bool_t xdr_guestfs_get_e2label_ret (); extern bool_t xdr_guestfs_set_e2uuid_args (); extern bool_t xdr_guestfs_get_e2uuid_args (); extern bool_t xdr_guestfs_get_e2uuid_ret (); +extern bool_t xdr_guestfs_fsck_args (); +extern bool_t xdr_guestfs_fsck_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 0cfb8ee..92dc8ea 100644 --- a/src/guestfs_protocol.x +++ b/src/guestfs_protocol.x @@ -573,6 +573,15 @@ struct guestfs_get_e2uuid_ret { string uuid<>; }; +struct guestfs_fsck_args { + string fstype<>; + string device<>; +}; + +struct guestfs_fsck_ret { + int status; +}; + enum guestfs_procedure { GUESTFS_PROC_MOUNT = 1, GUESTFS_PROC_SYNC = 2, @@ -657,6 +666,7 @@ enum guestfs_procedure { GUESTFS_PROC_GET_E2LABEL = 81, GUESTFS_PROC_SET_E2UUID = 82, GUESTFS_PROC_GET_E2UUID = 83, + GUESTFS_PROC_FSCK = 84, GUESTFS_PROC_NR_PROCS }; diff --git a/tests.c b/tests.c index 9a45cce..dddb971 100644 --- a/tests.c +++ b/tests.c @@ -112,6 +112,59 @@ static void no_test_warnings (void) fprintf (stderr, "warning: \"guestfs_get_e2uuid\" has no tests\n"); } +static int test_fsck_0 (void) +{ + /* InitBasicFS for fsck (0): create ext2 on /dev/sda1 */ + { + int r; + suppress_error = 0; + r = guestfs_umount_all (g); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvm_remove_all (g); + if (r == -1) + return -1; + } + { + char *lines[] = { + ",", + NULL + }; + int r; + suppress_error = 0; + r = guestfs_sfdisk (g, "/dev/sda", 0, 0, 0, lines); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_mkfs (g, "ext2", "/dev/sda1"); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_mount (g, "/dev/sda1", "/"); + if (r == -1) + return -1; + } + /* TestRun for fsck (0) */ + { + int r; + suppress_error = 0; + r = guestfs_fsck (g, "ext2", "/dev/sda1"); + if (r == -1) + return -1; + } + return 0; +} + static int test_set_e2uuid_0 (void) { /* InitBasicFS for set_e2uuid (0): create ext2 on /dev/sda1 */ @@ -6513,9 +6566,15 @@ int main (int argc, char *argv[]) exit (1); } - nr_tests = 91; + nr_tests = 92; test_num++; + printf ("%3d/%3d test_fsck_0\n", test_num, nr_tests); + if (test_fsck_0 () == -1) { + printf ("test_fsck_0 FAILED\n"); + failed++; + } + test_num++; printf ("%3d/%3d test_set_e2uuid_0\n", test_num, nr_tests); if (test_set_e2uuid_0 () == -1) { printf ("test_set_e2uuid_0 FAILED\n"); -- 1.8.3.1