diff options
author | Richard W.M. Jones <rjones@redhat.com> | 2009-05-01 12:16:08 +0100 |
---|---|---|
committer | Richard W.M. Jones <rjones@redhat.com> | 2009-05-01 12:16:08 +0100 |
commit | f47dafd23186938a22d41739d9bc695c7760b912 (patch) | |
tree | a6e5bf03a63cae2eeca269505724ae5c5ba11020 | |
parent | d9ea3e8d979c3ade1b21f27083788fd33fa3b1fa (diff) | |
download | libguestfs-f47dafd23186938a22d41739d9bc695c7760b912.tar.gz libguestfs-f47dafd23186938a22d41739d9bc695c7760b912.tar.xz libguestfs-f47dafd23186938a22d41739d9bc695c7760b912.zip |
Generated code for 'equal' command.
-rw-r--r-- | daemon/actions.h | 1 | ||||
-rw-r--r-- | daemon/stubs.c | 31 | ||||
-rw-r--r-- | fish/cmds.c | 25 | ||||
-rw-r--r-- | fish/completion.c | 1 | ||||
-rw-r--r-- | guestfish-actions.pod | 9 | ||||
-rw-r--r-- | guestfs-actions.pod | 13 | ||||
-rw-r--r-- | java/com/redhat/et/libguestfs/GuestFS.java | 21 | ||||
-rw-r--r-- | java/com_redhat_et_libguestfs_GuestFS.c | 21 | ||||
-rw-r--r-- | ocaml/guestfs.ml | 1 | ||||
-rw-r--r-- | ocaml/guestfs.mli | 3 | ||||
-rw-r--r-- | ocaml/guestfs_c_actions.c | 24 | ||||
-rw-r--r-- | perl/Guestfs.xs | 15 | ||||
-rw-r--r-- | perl/lib/Sys/Guestfs.pm | 7 | ||||
-rw-r--r-- | python/guestfs-py.c | 26 | ||||
-rw-r--r-- | python/guestfs.py | 9 | ||||
-rw-r--r-- | ruby/ext/guestfs/_guestfs.c | 27 | ||||
-rw-r--r-- | src/guestfs-actions.c | 93 | ||||
-rw-r--r-- | src/guestfs-actions.h | 1 | ||||
-rw-r--r-- | src/guestfs_protocol.c | 22 | ||||
-rw-r--r-- | src/guestfs_protocol.h | 18 | ||||
-rw-r--r-- | src/guestfs_protocol.x | 10 | ||||
-rw-r--r-- | tests.c | 215 |
22 files changed, 591 insertions, 2 deletions
diff --git a/daemon/actions.h b/daemon/actions.h index 2dc85376..ac57a126 100644 --- a/daemon/actions.h +++ b/daemon/actions.h @@ -113,3 +113,4 @@ extern int do_mv (const char *src, const char *dest); extern int do_drop_caches (int whattodrop); extern char *do_dmesg (void); extern int do_ping_daemon (void); +extern int do_equal (const char *file1, const char *file2); diff --git a/daemon/stubs.c b/daemon/stubs.c index f992bdf6..fd9c7eae 100644 --- a/daemon/stubs.c +++ b/daemon/stubs.c @@ -2284,6 +2284,34 @@ static void ping_daemon_stub (XDR *xdr_in) done: ; } +static void equal_stub (XDR *xdr_in) +{ + int r; + struct guestfs_equal_args args; + const char *file1; + const char *file2; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_equal_args (xdr_in, &args)) { + reply_with_error ("%s: daemon failed to decode procedure arguments", "equal"); + return; + } + file1 = args.file1; + file2 = args.file2; + + r = do_equal (file1, file2); + if (r == -1) + /* do_equal has already called reply_with_error */ + goto done; + + struct guestfs_equal_ret ret; + ret.equality = r; + reply ((xdrproc_t) &xdr_guestfs_equal_ret, (char *) &ret); +done: + xdr_free ((xdrproc_t) xdr_guestfs_equal_args, (char *) &args); +} + void dispatch_incoming_message (XDR *xdr_in) { switch (proc_nr) { @@ -2563,6 +2591,9 @@ void dispatch_incoming_message (XDR *xdr_in) case GUESTFS_PROC_PING_DAEMON: ping_daemon_stub (xdr_in); break; + case GUESTFS_PROC_EQUAL: + equal_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 7264e7dc..05977385 100644 --- a/fish/cmds.c +++ b/fish/cmds.c @@ -69,6 +69,7 @@ void list_commands (void) printf ("%-20s %s\n", "dmesg", "return kernel messages"); printf ("%-20s %s\n", "download", "download a file to the local machine"); printf ("%-20s %s\n", "drop-caches", "drop kernel page cache, dentries and inodes"); + printf ("%-20s %s\n", "equal", "test if two files have equal contents"); 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"); @@ -476,6 +477,9 @@ void display_command (const char *cmd) if (strcasecmp (cmd, "ping_daemon") == 0 || strcasecmp (cmd, "ping-daemon") == 0) pod2text ("ping-daemon - ping the guest daemon", " ping-daemon\n\nThis is a test probe into the guestfs daemon running inside\nthe qemu subprocess. Calling this function checks that the\ndaemon responds to the ping message, without affecting the daemon\nor attached block device(s) in any other way."); else + if (strcasecmp (cmd, "equal") == 0) + pod2text ("equal - test if two files have equal contents", " equal <file1> <file2>\n\nThis compares the two files C<file1> and C<file2> and returns\ntrue if their content is exactly equal, or false otherwise.\n\nThe external L<cmp(1)> program is used for the comparison."); + else display_builtin_command (cmd); } @@ -2315,6 +2319,24 @@ static int run_ping_daemon (const char *cmd, int argc, char *argv[]) return r; } +static int run_equal (const char *cmd, int argc, char *argv[]) +{ + int r; + const char *file1; + const char *file2; + 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; + } + file1 = argv[0]; + file2 = argv[1]; + r = guestfs_equal (g, file1, file2); + if (r == -1) return -1; + if (r) printf ("true\n"); else printf ("false\n"); + return 0; +} + int run_action (const char *cmd, int argc, char *argv[]) { if (strcasecmp (cmd, "launch") == 0 || strcasecmp (cmd, "run") == 0) @@ -2647,6 +2669,9 @@ int run_action (const char *cmd, int argc, char *argv[]) if (strcasecmp (cmd, "ping_daemon") == 0 || strcasecmp (cmd, "ping-daemon") == 0) return run_ping_daemon (cmd, argc, argv); else + if (strcasecmp (cmd, "equal") == 0) + return run_equal (cmd, argc, argv); + else { fprintf (stderr, "%s: unknown command\n", cmd); return -1; diff --git a/fish/completion.c b/fish/completion.c index 095a3351..640c3691 100644 --- a/fish/completion.c +++ b/fish/completion.c @@ -75,6 +75,7 @@ static const char *const commands[] = { "dmesg", "download", "drop-caches", + "equal", "exists", "file", "fsck", diff --git a/guestfish-actions.pod b/guestfish-actions.pod index 2d9c5e8d..f1b624b2 100644 --- a/guestfish-actions.pod +++ b/guestfish-actions.pod @@ -469,6 +469,15 @@ Setting C<whattodrop> to 3 should drop everything. This automatically calls L<sync(2)> before the operation, so that the maximum guest memory is freed. +=head2 equal + + equal file1 file2 + +This compares the two files C<file1> and C<file2> and returns +true if their content is exactly equal, or false otherwise. + +The external L<cmp(1)> program is used for the comparison. + =head2 exists exists path diff --git a/guestfs-actions.pod b/guestfs-actions.pod index 9d094c96..871ad3cf 100644 --- a/guestfs-actions.pod +++ b/guestfs-actions.pod @@ -609,6 +609,19 @@ so that the maximum guest memory is freed. This function returns 0 on success or -1 on error. +=head2 guestfs_equal + + int guestfs_equal (guestfs_h *handle, + const char *file1, + const char *file2); + +This compares the two files C<file1> and C<file2> and returns +true if their content is exactly equal, or false otherwise. + +The external L<cmp(1)> program is used for the comparison. + +This function returns a C truth value on success or -1 on error. + =head2 guestfs_exists int guestfs_exists (guestfs_h *handle, diff --git a/java/com/redhat/et/libguestfs/GuestFS.java b/java/com/redhat/et/libguestfs/GuestFS.java index 5ae2b106..07253176 100644 --- a/java/com/redhat/et/libguestfs/GuestFS.java +++ b/java/com/redhat/et/libguestfs/GuestFS.java @@ -2557,4 +2557,25 @@ public class GuestFS { private native void _ping_daemon (long g) throws LibGuestFSException; + /** + * test if two files have equal contents + * + * This compares the two files "file1" and "file2" and + * returns true if their content is exactly equal, or false + * otherwise. + * + * The external cmp(1) program is used for the comparison. + * + * @throws LibGuestFSException + */ + public boolean equal (String file1, String file2) + throws LibGuestFSException + { + if (g == 0) + throw new LibGuestFSException ("equal: handle is closed"); + return _equal (g, file1, file2); + } + private native boolean _equal (long g, String file1, String file2) + throws LibGuestFSException; + } diff --git a/java/com_redhat_et_libguestfs_GuestFS.c b/java/com_redhat_et_libguestfs_GuestFS.c index b689a6c4..da287b15 100644 --- a/java/com_redhat_et_libguestfs_GuestFS.c +++ b/java/com_redhat_et_libguestfs_GuestFS.c @@ -2565,3 +2565,24 @@ Java_com_redhat_et_libguestfs_GuestFS__1ping_1daemon } } +JNIEXPORT jboolean JNICALL +Java_com_redhat_et_libguestfs_GuestFS__1equal + (JNIEnv *env, jobject obj, jlong jg, jstring jfile1, jstring jfile2) +{ + guestfs_h *g = (guestfs_h *) (long) jg; + int r; + const char *file1; + const char *file2; + + file1 = (*env)->GetStringUTFChars (env, jfile1, NULL); + file2 = (*env)->GetStringUTFChars (env, jfile2, NULL); + r = guestfs_equal (g, file1, file2); + (*env)->ReleaseStringUTFChars (env, jfile1, file1); + (*env)->ReleaseStringUTFChars (env, jfile2, file2); + if (r == -1) { + throw_exception (env, guestfs_last_error (g)); + return 0; + } + return (jboolean) r; +} + diff --git a/ocaml/guestfs.ml b/ocaml/guestfs.ml index e4916b07..99d59037 100644 --- a/ocaml/guestfs.ml +++ b/ocaml/guestfs.ml @@ -228,3 +228,4 @@ external mv : t -> string -> string -> unit = "ocaml_guestfs_mv" external drop_caches : t -> int -> unit = "ocaml_guestfs_drop_caches" external dmesg : t -> string = "ocaml_guestfs_dmesg" external ping_daemon : t -> unit = "ocaml_guestfs_ping_daemon" +external equal : t -> string -> string -> bool = "ocaml_guestfs_equal" diff --git a/ocaml/guestfs.mli b/ocaml/guestfs.mli index 125fa979..40d1d2a4 100644 --- a/ocaml/guestfs.mli +++ b/ocaml/guestfs.mli @@ -463,3 +463,6 @@ val dmesg : t -> string val ping_daemon : t -> unit (** ping the guest daemon *) +val equal : t -> string -> string -> bool +(** test if two files have equal contents *) + diff --git a/ocaml/guestfs_c_actions.c b/ocaml/guestfs_c_actions.c index a640e0f3..7732e1c6 100644 --- a/ocaml/guestfs_c_actions.c +++ b/ocaml/guestfs_c_actions.c @@ -3010,3 +3010,27 @@ ocaml_guestfs_ping_daemon (value gv) CAMLreturn (rv); } +CAMLprim value +ocaml_guestfs_equal (value gv, value file1v, value file2v) +{ + CAMLparam3 (gv, file1v, file2v); + CAMLlocal1 (rv); + + guestfs_h *g = Guestfs_val (gv); + if (g == NULL) + caml_failwith ("equal: used handle after closing it"); + + const char *file1 = String_val (file1v); + const char *file2 = String_val (file2v); + int r; + + caml_enter_blocking_section (); + r = guestfs_equal (g, file1, file2); + caml_leave_blocking_section (); + if (r == -1) + ocaml_guestfs_raise_error (g, "equal"); + + rv = Val_bool (r); + CAMLreturn (rv); +} + diff --git a/perl/Guestfs.xs b/perl/Guestfs.xs index af543ec0..d29d5a08 100644 --- a/perl/Guestfs.xs +++ b/perl/Guestfs.xs @@ -1682,3 +1682,18 @@ PREINIT: if (r == -1) croak ("ping_daemon: %s", guestfs_last_error (g)); +SV * +equal (g, file1, file2) + guestfs_h *g; + char *file1; + char *file2; +PREINIT: + int equality; + CODE: + equality = guestfs_equal (g, file1, file2); + if (equality == -1) + croak ("equal: %s", guestfs_last_error (g)); + RETVAL = newSViv (equality); + OUTPUT: + RETVAL + diff --git a/perl/lib/Sys/Guestfs.pm b/perl/lib/Sys/Guestfs.pm index a13c4411..7331053e 100644 --- a/perl/lib/Sys/Guestfs.pm +++ b/perl/lib/Sys/Guestfs.pm @@ -484,6 +484,13 @@ Setting C<whattodrop> to 3 should drop everything. This automatically calls L<sync(2)> before the operation, so that the maximum guest memory is freed. +=item $equality = $h->equal ($file1, $file2); + +This compares the two files C<file1> and C<file2> and returns +true if their content is exactly equal, or false otherwise. + +The external L<cmp(1)> program is used for the comparison. + =item $existsflag = $h->exists ($path); This returns C<true> if and only if there is a file, directory diff --git a/python/guestfs-py.c b/python/guestfs-py.c index 6a807e3e..918e2ba0 100644 --- a/python/guestfs-py.c +++ b/python/guestfs-py.c @@ -3229,6 +3229,31 @@ py_guestfs_ping_daemon (PyObject *self, PyObject *args) return py_r; } +static PyObject * +py_guestfs_equal (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *file1; + const char *file2; + + if (!PyArg_ParseTuple (args, (char *) "Oss:guestfs_equal", + &py_g, &file1, &file2)) + return NULL; + g = get_handle (py_g); + + r = guestfs_equal (g, file1, file2); + 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 }, @@ -3345,6 +3370,7 @@ static PyMethodDef methods[] = { { (char *) "drop_caches", py_guestfs_drop_caches, METH_VARARGS, NULL }, { (char *) "dmesg", py_guestfs_dmesg, METH_VARARGS, NULL }, { (char *) "ping_daemon", py_guestfs_ping_daemon, METH_VARARGS, NULL }, + { (char *) "equal", py_guestfs_equal, METH_VARARGS, NULL }, { NULL, NULL, 0, NULL } }; diff --git a/python/guestfs.py b/python/guestfs.py index 1596bcdb..d03a7a9d 100644 --- a/python/guestfs.py +++ b/python/guestfs.py @@ -1242,3 +1242,12 @@ class GuestFS: """ return libguestfsmod.ping_daemon (self._o) + def equal (self, file1, file2): + u"""This compares the two files "file1" and "file2" and + returns true if their content is exactly equal, or false + otherwise. + + The external cmp(1) program is used for the comparison. + """ + return libguestfsmod.equal (self._o, file1, file2) + diff --git a/ruby/ext/guestfs/_guestfs.c b/ruby/ext/guestfs/_guestfs.c index eed0b80e..83486e75 100644 --- a/ruby/ext/guestfs/_guestfs.c +++ b/ruby/ext/guestfs/_guestfs.c @@ -2715,6 +2715,31 @@ static VALUE ruby_guestfs_ping_daemon (VALUE gv) return Qnil; } +static VALUE ruby_guestfs_equal (VALUE gv, VALUE file1v, VALUE file2v) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "equal"); + + const char *file1 = StringValueCStr (file1v); + if (!file1) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "file1", "equal"); + const char *file2 = StringValueCStr (file2v); + if (!file2) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "file2", "equal"); + + int r; + + r = guestfs_equal (g, file1, file2); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return INT2NUM (r); +} + /* Initialize the module. */ void Init__guestfs () { @@ -2951,4 +2976,6 @@ void Init__guestfs () ruby_guestfs_dmesg, 0); rb_define_method (c_guestfs, "ping_daemon", ruby_guestfs_ping_daemon, 0); + rb_define_method (c_guestfs, "equal", + ruby_guestfs_equal, 2); } diff --git a/src/guestfs-actions.c b/src/guestfs-actions.c index c0762dfa..3da1b42b 100644 --- a/src/guestfs-actions.c +++ b/src/guestfs-actions.c @@ -8335,3 +8335,96 @@ int guestfs_ping_daemon (guestfs_h *g) return 0; } +struct equal_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_equal_ret ret; +}; + +static void equal_reply_cb (guestfs_h *g, void *data, XDR *xdr) +{ + guestfs_main_loop *ml = guestfs_get_main_loop (g); + struct equal_ctx *ctx = (struct equal_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_equal"); + return; + } + + ml->main_loop_quit (ml, g); + + if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { + error (g, "%s: failed to parse reply header", "guestfs_equal"); + 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_equal"); + return; + } + goto done; + } + if (!xdr_guestfs_equal_ret (xdr, &ctx->ret)) { + error (g, "%s: failed to parse reply", "guestfs_equal"); + return; + } + done: + ctx->cb_sequence = 1; +} + +int guestfs_equal (guestfs_h *g, + const char *file1, + const char *file2) +{ + struct guestfs_equal_args args; + struct equal_ctx ctx; + guestfs_main_loop *ml = guestfs_get_main_loop (g); + int serial; + + if (check_state (g, "guestfs_equal") == -1) return -1; + guestfs_set_busy (g); + + memset (&ctx, 0, sizeof ctx); + + args.file1 = (char *) file1; + args.file2 = (char *) file2; + serial = guestfs__send_sync (g, GUESTFS_PROC_EQUAL, + (xdrproc_t) xdr_guestfs_equal_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, equal_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_equal"); + guestfs_set_ready (g); + return -1; + } + + if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_EQUAL, 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.equality; +} + diff --git a/src/guestfs-actions.h b/src/guestfs-actions.h index f2218f4e..05399818 100644 --- a/src/guestfs-actions.h +++ b/src/guestfs-actions.h @@ -132,3 +132,4 @@ extern int guestfs_mv (guestfs_h *handle, const char *src, const char *dest); extern int guestfs_drop_caches (guestfs_h *handle, int whattodrop); extern char *guestfs_dmesg (guestfs_h *handle); extern int guestfs_ping_daemon (guestfs_h *handle); +extern int guestfs_equal (guestfs_h *handle, const char *file1, const char *file2); diff --git a/src/guestfs_protocol.c b/src/guestfs_protocol.c index 7a40e14e..66889cc4 100644 --- a/src/guestfs_protocol.c +++ b/src/guestfs_protocol.c @@ -1528,6 +1528,28 @@ xdr_guestfs_dmesg_ret (XDR *xdrs, guestfs_dmesg_ret *objp) } bool_t +xdr_guestfs_equal_args (XDR *xdrs, guestfs_equal_args *objp) +{ + register int32_t *buf; + + if (!xdr_string (xdrs, &objp->file1, ~0)) + return FALSE; + if (!xdr_string (xdrs, &objp->file2, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_guestfs_equal_ret (XDR *xdrs, guestfs_equal_ret *objp) +{ + register int32_t *buf; + + if (!xdr_bool (xdrs, &objp->equality)) + 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 e4725247..06287c9e 100644 --- a/src/guestfs_protocol.h +++ b/src/guestfs_protocol.h @@ -789,6 +789,17 @@ struct guestfs_dmesg_ret { }; typedef struct guestfs_dmesg_ret guestfs_dmesg_ret; +struct guestfs_equal_args { + char *file1; + char *file2; +}; +typedef struct guestfs_equal_args guestfs_equal_args; + +struct guestfs_equal_ret { + bool_t equality; +}; +typedef struct guestfs_equal_ret guestfs_equal_ret; + enum guestfs_procedure { GUESTFS_PROC_MOUNT = 1, GUESTFS_PROC_SYNC = 2, @@ -882,7 +893,8 @@ enum guestfs_procedure { GUESTFS_PROC_DROP_CACHES = 90, GUESTFS_PROC_DMESG = 91, GUESTFS_PROC_PING_DAEMON = 92, - GUESTFS_PROC_NR_PROCS = 92 + 1, + GUESTFS_PROC_EQUAL = 93, + GUESTFS_PROC_NR_PROCS = 93 + 1, }; typedef enum guestfs_procedure guestfs_procedure; #define GUESTFS_MESSAGE_MAX 4194304 @@ -1056,6 +1068,8 @@ extern bool_t xdr_guestfs_cp_a_args (XDR *, guestfs_cp_a_args*); extern bool_t xdr_guestfs_mv_args (XDR *, guestfs_mv_args*); extern bool_t xdr_guestfs_drop_caches_args (XDR *, guestfs_drop_caches_args*); extern bool_t xdr_guestfs_dmesg_ret (XDR *, guestfs_dmesg_ret*); +extern bool_t xdr_guestfs_equal_args (XDR *, guestfs_equal_args*); +extern bool_t xdr_guestfs_equal_ret (XDR *, guestfs_equal_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*); @@ -1188,6 +1202,8 @@ extern bool_t xdr_guestfs_cp_a_args (); extern bool_t xdr_guestfs_mv_args (); extern bool_t xdr_guestfs_drop_caches_args (); extern bool_t xdr_guestfs_dmesg_ret (); +extern bool_t xdr_guestfs_equal_args (); +extern bool_t xdr_guestfs_equal_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 e61d3fb8..f6cab670 100644 --- a/src/guestfs_protocol.x +++ b/src/guestfs_protocol.x @@ -614,6 +614,15 @@ struct guestfs_dmesg_ret { string kmsgs<>; }; +struct guestfs_equal_args { + string file1<>; + string file2<>; +}; + +struct guestfs_equal_ret { + bool equality; +}; + enum guestfs_procedure { GUESTFS_PROC_MOUNT = 1, GUESTFS_PROC_SYNC = 2, @@ -707,6 +716,7 @@ enum guestfs_procedure { GUESTFS_PROC_DROP_CACHES = 90, GUESTFS_PROC_DMESG = 91, GUESTFS_PROC_PING_DAEMON = 92, + GUESTFS_PROC_EQUAL = 93, GUESTFS_PROC_NR_PROCS }; @@ -112,6 +112,201 @@ static void no_test_warnings (void) fprintf (stderr, "warning: \"guestfs_get_e2uuid\" has no tests\n"); } +static int test_equal_0 (void) +{ + /* InitBasicFS for equal (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; + } + /* TestOutputTrue for equal (0) */ + { + int r; + suppress_error = 0; + r = guestfs_write_file (g, "/file1", "contents of a file", 0); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_cp (g, "/file1", "/file2"); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_equal (g, "/file1", "/file2"); + if (r == -1) + return -1; + if (!r) { + fprintf (stderr, "test_equal_0: expected true, got false\n"); + return -1; + } + } + return 0; +} + +static int test_equal_1 (void) +{ + /* InitBasicFS for equal (1): 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; + } + /* TestOutputFalse for equal (1) */ + { + int r; + suppress_error = 0; + r = guestfs_write_file (g, "/file1", "contents of a file", 0); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_write_file (g, "/file2", "contents of another file", 0); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_equal (g, "/file1", "/file2"); + if (r == -1) + return -1; + if (r) { + fprintf (stderr, "test_equal_1: expected false, got true\n"); + return -1; + } + } + return 0; +} + +static int test_equal_2 (void) +{ + /* InitBasicFS for equal (2): 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; + } + /* TestLastFail for equal (2) */ + { + int r; + suppress_error = 1; + r = guestfs_equal (g, "/file1", "/file2"); + if (r != -1) + return -1; + } + return 0; +} + static int test_ping_daemon_0 (void) { /* InitEmpty for ping_daemon (0) */ @@ -7320,9 +7515,27 @@ int main (int argc, char *argv[]) exit (1); } - nr_tests = 104; + nr_tests = 107; test_num++; + printf ("%3d/%3d test_equal_0\n", test_num, nr_tests); + if (test_equal_0 () == -1) { + printf ("test_equal_0 FAILED\n"); + failed++; + } + test_num++; + printf ("%3d/%3d test_equal_1\n", test_num, nr_tests); + if (test_equal_1 () == -1) { + printf ("test_equal_1 FAILED\n"); + failed++; + } + test_num++; + printf ("%3d/%3d test_equal_2\n", test_num, nr_tests); + if (test_equal_2 () == -1) { + printf ("test_equal_2 FAILED\n"); + failed++; + } + test_num++; printf ("%3d/%3d test_ping_daemon_0\n", test_num, nr_tests); if (test_ping_daemon_0 () == -1) { printf ("test_ping_daemon_0 FAILED\n"); |