From 6bcbe54b5785cb8c911ccf4b724ae6abfdf53ce4 Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Wed, 15 Apr 2009 10:45:01 +0100 Subject: [PATCH] Generated code for stat/lstat/statvfs changes. --- daemon/actions.h | 3 + daemon/stubs.c | 90 +++++++ fish/cmds.c | 104 ++++++++ fish/completion.c | 3 + guestfish-actions.pod | 30 +++ guestfs-actions.pod | 63 ++++- ocaml/guestfs.ml | 33 +++ ocaml/guestfs.mli | 39 +++ ocaml/guestfs_c_actions.c | 140 +++++++++++ perl/Guestfs.xs | 76 ++++++ perl/lib/Sys/Guestfs.pm | 24 ++ python/guestfs-py.c | 144 +++++++++++ python/guestfs.py | 9 + src/guestfs-actions.c | 225 +++++++++++++++++ src/guestfs-actions.h | 3 + src/guestfs-structs.h | 30 +++ src/guestfs_protocol.c | 124 ++++++++++ src/guestfs_protocol.h | 83 ++++++- src/guestfs_protocol.x | 57 +++++ tests.c | 609 ++++++++++++++++++++-------------------------- 20 files changed, 1540 insertions(+), 349 deletions(-) diff --git a/daemon/actions.h b/daemon/actions.h index 90aeb8d..c0f41ce 100644 --- a/daemon/actions.h +++ b/daemon/actions.h @@ -72,3 +72,6 @@ extern int do_lvm_remove_all (void); extern char *do_file (const char *path); extern char *do_command (char * const* const arguments); extern char **do_command_lines (char * const* const arguments); +extern guestfs_int_stat *do_stat (const char *path); +extern guestfs_int_stat *do_lstat (const char *path); +extern guestfs_int_statvfs *do_statvfs (const char *path); diff --git a/daemon/stubs.c b/daemon/stubs.c index 9a0dc91..9662de8 100644 --- a/daemon/stubs.c +++ b/daemon/stubs.c @@ -1223,6 +1223,87 @@ done: xdr_free ((xdrproc_t) xdr_guestfs_command_lines_args, (char *) &args); } +static void stat_stub (XDR *xdr_in) +{ + guestfs_int_stat *r; + struct guestfs_stat_args args; + const char *path; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_stat_args (xdr_in, &args)) { + reply_with_error ("%s: daemon failed to decode procedure arguments", "stat"); + return; + } + path = args.path; + + r = do_stat (path); + if (r == NULL) + /* do_stat has already called reply_with_error */ + goto done; + + struct guestfs_stat_ret ret; + ret.statbuf = *r; + reply ((xdrproc_t) xdr_guestfs_stat_ret, (char *) &ret); + xdr_free ((xdrproc_t) xdr_guestfs_stat_ret, (char *) &ret); +done: + xdr_free ((xdrproc_t) xdr_guestfs_stat_args, (char *) &args); +} + +static void lstat_stub (XDR *xdr_in) +{ + guestfs_int_stat *r; + struct guestfs_lstat_args args; + const char *path; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_lstat_args (xdr_in, &args)) { + reply_with_error ("%s: daemon failed to decode procedure arguments", "lstat"); + return; + } + path = args.path; + + r = do_lstat (path); + if (r == NULL) + /* do_lstat has already called reply_with_error */ + goto done; + + struct guestfs_lstat_ret ret; + ret.statbuf = *r; + reply ((xdrproc_t) xdr_guestfs_lstat_ret, (char *) &ret); + xdr_free ((xdrproc_t) xdr_guestfs_lstat_ret, (char *) &ret); +done: + xdr_free ((xdrproc_t) xdr_guestfs_lstat_args, (char *) &args); +} + +static void statvfs_stub (XDR *xdr_in) +{ + guestfs_int_statvfs *r; + struct guestfs_statvfs_args args; + const char *path; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_statvfs_args (xdr_in, &args)) { + reply_with_error ("%s: daemon failed to decode procedure arguments", "statvfs"); + return; + } + path = args.path; + + r = do_statvfs (path); + if (r == NULL) + /* do_statvfs has already called reply_with_error */ + goto done; + + struct guestfs_statvfs_ret ret; + ret.statbuf = *r; + reply ((xdrproc_t) xdr_guestfs_statvfs_ret, (char *) &ret); + xdr_free ((xdrproc_t) xdr_guestfs_statvfs_ret, (char *) &ret); +done: + xdr_free ((xdrproc_t) xdr_guestfs_statvfs_args, (char *) &args); +} + void dispatch_incoming_message (XDR *xdr_in) { switch (proc_nr) { @@ -1379,6 +1460,15 @@ void dispatch_incoming_message (XDR *xdr_in) case GUESTFS_PROC_COMMAND_LINES: command_lines_stub (xdr_in); break; + case GUESTFS_PROC_STAT: + stat_stub (xdr_in); + break; + case GUESTFS_PROC_LSTAT: + lstat_stub (xdr_in); + break; + case GUESTFS_PROC_STATVFS: + statvfs_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 b658614..60aee8c 100644 --- a/fish/cmds.c +++ b/fish/cmds.c @@ -65,6 +65,7 @@ void list_commands (void) 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", "lstat", "get file information for a symbolic link"); printf ("%-20s %s\n", "lvcreate", "create an LVM volume group"); printf ("%-20s %s\n", "lvm-remove-all", "remove all LVM LVs, VGs and PVs"); printf ("%-20s %s\n", "lvs", "list the LVM logical volumes (LVs)"); @@ -85,6 +86,8 @@ void list_commands (void) printf ("%-20s %s\n", "set-path", "set the search path"); printf ("%-20s %s\n", "set-verbose", "set verbose mode"); printf ("%-20s %s\n", "sfdisk", "create partitions on a block device"); + printf ("%-20s %s\n", "stat", "get file information"); + printf ("%-20s %s\n", "statvfs", "get file system statistics"); printf ("%-20s %s\n", "sync", "sync disks, writes are flushed through to the disk image"); printf ("%-20s %s\n", "touch", "update file timestamps or create a new file"); printf ("%-20s %s\n", "umount", "unmount a filesystem"); @@ -284,6 +287,15 @@ void display_command (const char *cmd) if (strcasecmp (cmd, "command_lines") == 0 || strcasecmp (cmd, "command-lines") == 0) pod2text ("command-lines - run a command, returning lines", " command-lines \n\nThis is the same as C, but splits the\nresult into a list of lines."); else + if (strcasecmp (cmd, "stat") == 0) + pod2text ("stat - get file information", " stat \n\nReturns file information for the given C.\n\nThis is the same as the C system call."); + else + if (strcasecmp (cmd, "lstat") == 0) + pod2text ("lstat - get file information for a symbolic link", " lstat \n\nReturns file information for the given C.\n\nThis is the same as C except that if C\nis a symbolic link, then the link is stat-ed, not the file it\nrefers to.\n\nThis is the same as the C system call."); + else + if (strcasecmp (cmd, "statvfs") == 0) + pod2text ("statvfs - get file system statistics", " statvfs \n\nReturns file system statistics for any mounted file system.\nC should be a file or directory in the mounted file system\n(typically it is the mount point itself, but it doesn't need to be).\n\nThis is the same as the C system call."); + else display_builtin_command (cmd); } @@ -389,6 +401,38 @@ static void print_lv_list (struct guestfs_lvm_lv_list *lvs) print_lv (&lvs->val[i]); } +static void print_stat (struct guestfs_stat *stat) +{ + printf ("dev: %" PRIi64 "\n", stat->dev); + printf ("ino: %" PRIi64 "\n", stat->ino); + printf ("mode: %" PRIi64 "\n", stat->mode); + printf ("nlink: %" PRIi64 "\n", stat->nlink); + printf ("uid: %" PRIi64 "\n", stat->uid); + printf ("gid: %" PRIi64 "\n", stat->gid); + printf ("rdev: %" PRIi64 "\n", stat->rdev); + printf ("size: %" PRIi64 "\n", stat->size); + printf ("blksize: %" PRIi64 "\n", stat->blksize); + printf ("blocks: %" PRIi64 "\n", stat->blocks); + printf ("atime: %" PRIi64 "\n", stat->atime); + printf ("mtime: %" PRIi64 "\n", stat->mtime); + printf ("ctime: %" PRIi64 "\n", stat->ctime); +} + +static void print_statvfs (struct guestfs_statvfs *statvfs) +{ + printf ("bsize: %" PRIi64 "\n", statvfs->bsize); + printf ("frsize: %" PRIi64 "\n", statvfs->frsize); + printf ("blocks: %" PRIi64 "\n", statvfs->blocks); + printf ("bfree: %" PRIi64 "\n", statvfs->bfree); + printf ("bavail: %" PRIi64 "\n", statvfs->bavail); + printf ("files: %" PRIi64 "\n", statvfs->files); + printf ("ffree: %" PRIi64 "\n", statvfs->ffree); + printf ("favail: %" PRIi64 "\n", statvfs->favail); + printf ("fsid: %" PRIi64 "\n", statvfs->fsid); + printf ("flag: %" PRIi64 "\n", statvfs->flag); + printf ("namemax: %" PRIi64 "\n", statvfs->namemax); +} + static int run_launch (const char *cmd, int argc, char *argv[]) { int r; @@ -1340,6 +1384,57 @@ static int run_command_lines (const char *cmd, int argc, char *argv[]) return 0; } +static int run_stat (const char *cmd, int argc, char *argv[]) +{ + struct guestfs_stat *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_stat (g, path); + if (r == NULL) return -1; + print_stat (r); + free (r); + return 0; +} + +static int run_lstat (const char *cmd, int argc, char *argv[]) +{ + struct guestfs_stat *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_lstat (g, path); + if (r == NULL) return -1; + print_stat (r); + free (r); + return 0; +} + +static int run_statvfs (const char *cmd, int argc, char *argv[]) +{ + struct guestfs_statvfs *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_statvfs (g, path); + if (r == NULL) return -1; + print_statvfs (r); + free (r); + return 0; +} + int run_action (const char *cmd, int argc, char *argv[]) { if (strcasecmp (cmd, "launch") == 0 || strcasecmp (cmd, "run") == 0) @@ -1528,6 +1623,15 @@ int run_action (const char *cmd, int argc, char *argv[]) if (strcasecmp (cmd, "command_lines") == 0 || strcasecmp (cmd, "command-lines") == 0) return run_command_lines (cmd, argc, argv); else + if (strcasecmp (cmd, "stat") == 0) + return run_stat (cmd, argc, argv); + else + if (strcasecmp (cmd, "lstat") == 0) + return run_lstat (cmd, argc, argv); + else + if (strcasecmp (cmd, "statvfs") == 0) + return run_statvfs (cmd, argc, argv); + else { fprintf (stderr, "%s: unknown command\n", cmd); return -1; diff --git a/fish/completion.c b/fish/completion.c index 150b1aa..7b4f818 100644 --- a/fish/completion.c +++ b/fish/completion.c @@ -71,6 +71,7 @@ static const char *commands[] = { "list-partitions", "ll", "ls", + "lstat", "lvcreate", "lvm-remove-all", "lvs", @@ -93,6 +94,8 @@ static const char *commands[] = { "set-path", "set-verbose", "sfdisk", + "stat", + "statvfs", "sync", "touch", "umount", diff --git a/guestfish-actions.pod b/guestfish-actions.pod index fbf2f97..e240f49 100644 --- a/guestfish-actions.pod +++ b/guestfish-actions.pod @@ -377,6 +377,18 @@ hidden files are shown. This command is mostly useful for interactive sessions. Programs should probably use C instead. +=head2 lstat + + lstat path + +Returns file information for the given C. + +This is the same as C except that if C +is a symbolic link, then the link is stat-ed, not the file it +refers to. + +This is the same as the C system call. + =head2 lvcreate lvcreate logvol volgroup mbytes @@ -583,6 +595,24 @@ the string C<,> (comma). B. +=head2 stat + + stat path + +Returns file information for the given C. + +This is the same as the C system call. + +=head2 statvfs + + statvfs path + +Returns file system statistics for any mounted file system. +C should be a file or directory in the mounted file system +(typically it is the mount point itself, but it doesn't need to be). + +This is the same as the C system call. + =head2 sync sync diff --git a/guestfs-actions.pod b/guestfs-actions.pod index 5bd9628..03378e0 100644 --- a/guestfs-actions.pod +++ b/guestfs-actions.pod @@ -58,7 +58,8 @@ On success this returns a pair containing the number of nodes in the nodeset, and a boolean flag if a node was created. -This function returns a C. +This function returns a C, +or NULL if there was an error. I after use>. =head2 guestfs_aug_defvar @@ -500,6 +501,24 @@ This function returns a NULL-terminated array of strings (like L), or NULL if there was an error. I. +=head2 guestfs_lstat + + struct guestfs_stat *guestfs_lstat (guestfs_h *handle, + const char *path); + +Returns file information for the given C. + +This is the same as C except that if C +is a symbolic link, then the link is stat-ed, not the file it +refers to. + +This is the same as the C system call. + +This function returns a C +(see L and Eguestfs-structs.hE), +or NULL if there was an error. +I after use>. + =head2 guestfs_lvcreate int guestfs_lvcreate (guestfs_h *handle, @@ -547,7 +566,9 @@ I. List all the logical volumes detected. This is the equivalent of the L command. The "full" version includes all fields. -This function returns a C. +This function returns a C +(see Eguestfs-structs.hE), +or NULL if there was an error. I after use>. =head2 guestfs_mkdir @@ -653,7 +674,9 @@ I. List all the physical volumes detected. This is the equivalent of the L command. The "full" version includes all fields. -This function returns a C. +This function returns a C +(see Eguestfs-structs.hE), +or NULL if there was an error. I after use>. =head2 guestfs_read_lines @@ -778,6 +801,36 @@ This function returns 0 on success or -1 on error. B. +=head2 guestfs_stat + + struct guestfs_stat *guestfs_stat (guestfs_h *handle, + const char *path); + +Returns file information for the given C. + +This is the same as the C system call. + +This function returns a C +(see L and Eguestfs-structs.hE), +or NULL if there was an error. +I after use>. + +=head2 guestfs_statvfs + + struct guestfs_statvfs *guestfs_statvfs (guestfs_h *handle, + const char *path); + +Returns file system statistics for any mounted file system. +C should be a file or directory in the mounted file system +(typically it is the mount point itself, but it doesn't need to be). + +This is the same as the C system call. + +This function returns a C +(see L and Eguestfs-structs.hE), +or NULL if there was an error. +I after use>. + =head2 guestfs_sync int guestfs_sync (guestfs_h *handle); @@ -856,7 +909,9 @@ I. List all the volumes groups detected. This is the equivalent of the L command. The "full" version includes all fields. -This function returns a C. +This function returns a C +(see Eguestfs-structs.hE), +or NULL if there was an error. I after use>. =head2 guestfs_wait_ready diff --git a/ocaml/guestfs.ml b/ocaml/guestfs.ml index fa2e341..f0344ac 100644 --- a/ocaml/guestfs.ml +++ b/ocaml/guestfs.ml @@ -85,6 +85,36 @@ type lvm_lv = { modules : string; } +type stat = { + dev : int64; + ino : int64; + mode : int64; + nlink : int64; + uid : int64; + gid : int64; + rdev : int64; + size : int64; + blksize : int64; + blocks : int64; + atime : int64; + mtime : int64; + ctime : int64; +} + +type statvfs = { + bsize : int64; + frsize : int64; + blocks : int64; + bfree : int64; + bavail : int64; + files : int64; + ffree : int64; + favail : int64; + fsid : int64; + flag : int64; + namemax : int64; +} + external launch : t -> unit = "ocaml_guestfs_launch" external wait_ready : t -> unit = "ocaml_guestfs_wait_ready" external kill_subprocess : t -> unit = "ocaml_guestfs_kill_subprocess" @@ -148,3 +178,6 @@ external lvm_remove_all : t -> unit = "ocaml_guestfs_lvm_remove_all" external file : t -> string -> string = "ocaml_guestfs_file" external command : t -> string array -> string = "ocaml_guestfs_command" external command_lines : t -> string array -> string array = "ocaml_guestfs_command_lines" +external stat : t -> string -> stat = "ocaml_guestfs_stat" +external lstat : t -> string -> stat = "ocaml_guestfs_lstat" +external statvfs : t -> string -> statvfs = "ocaml_guestfs_statvfs" diff --git a/ocaml/guestfs.mli b/ocaml/guestfs.mli index 279ed4d..3062968 100644 --- a/ocaml/guestfs.mli +++ b/ocaml/guestfs.mli @@ -94,6 +94,36 @@ type lvm_lv = { modules : string; } +type stat = { + dev : int64; + ino : int64; + mode : int64; + nlink : int64; + uid : int64; + gid : int64; + rdev : int64; + size : int64; + blksize : int64; + blocks : int64; + atime : int64; + mtime : int64; + ctime : int64; +} + +type statvfs = { + bsize : int64; + frsize : int64; + blocks : int64; + bfree : int64; + bavail : int64; + files : int64; + ffree : int64; + favail : int64; + fsid : int64; + flag : int64; + namemax : int64; +} + val launch : t -> unit (** launch the qemu subprocess *) @@ -283,3 +313,12 @@ val command : t -> string array -> string val command_lines : t -> string array -> string array (** run a command, returning lines *) +val stat : t -> string -> stat +(** get file information *) + +val lstat : t -> string -> stat +(** get file information for a symbolic link *) + +val statvfs : t -> string -> statvfs +(** get file system statistics *) + diff --git a/ocaml/guestfs_c_actions.c b/ocaml/guestfs_c_actions.c index 356965d..01fbcb0 100644 --- a/ocaml/guestfs_c_actions.c +++ b/ocaml/guestfs_c_actions.c @@ -233,6 +233,74 @@ copy_lvm_lv_list (const struct guestfs_lvm_lv_list *lvs) } } +static CAMLprim value +copy_stat (const struct guestfs_stat *stat) +{ + CAMLparam0 (); + CAMLlocal2 (rv, v); + + rv = caml_alloc (13, 0); + v = caml_copy_int64 (stat->dev); + Store_field (rv, 0, v); + v = caml_copy_int64 (stat->ino); + Store_field (rv, 1, v); + v = caml_copy_int64 (stat->mode); + Store_field (rv, 2, v); + v = caml_copy_int64 (stat->nlink); + Store_field (rv, 3, v); + v = caml_copy_int64 (stat->uid); + Store_field (rv, 4, v); + v = caml_copy_int64 (stat->gid); + Store_field (rv, 5, v); + v = caml_copy_int64 (stat->rdev); + Store_field (rv, 6, v); + v = caml_copy_int64 (stat->size); + Store_field (rv, 7, v); + v = caml_copy_int64 (stat->blksize); + Store_field (rv, 8, v); + v = caml_copy_int64 (stat->blocks); + Store_field (rv, 9, v); + v = caml_copy_int64 (stat->atime); + Store_field (rv, 10, v); + v = caml_copy_int64 (stat->mtime); + Store_field (rv, 11, v); + v = caml_copy_int64 (stat->ctime); + Store_field (rv, 12, v); + CAMLreturn (rv); +} + +static CAMLprim value +copy_statvfs (const struct guestfs_statvfs *statvfs) +{ + CAMLparam0 (); + CAMLlocal2 (rv, v); + + rv = caml_alloc (11, 0); + v = caml_copy_int64 (statvfs->bsize); + Store_field (rv, 0, v); + v = caml_copy_int64 (statvfs->frsize); + Store_field (rv, 1, v); + v = caml_copy_int64 (statvfs->blocks); + Store_field (rv, 2, v); + v = caml_copy_int64 (statvfs->bfree); + Store_field (rv, 3, v); + v = caml_copy_int64 (statvfs->bavail); + Store_field (rv, 4, v); + v = caml_copy_int64 (statvfs->files); + Store_field (rv, 5, v); + v = caml_copy_int64 (statvfs->ffree); + Store_field (rv, 6, v); + v = caml_copy_int64 (statvfs->favail); + Store_field (rv, 7, v); + v = caml_copy_int64 (statvfs->fsid); + Store_field (rv, 8, v); + v = caml_copy_int64 (statvfs->flag); + Store_field (rv, 9, v); + v = caml_copy_int64 (statvfs->namemax); + Store_field (rv, 10, v); + CAMLreturn (rv); +} + CAMLprim value ocaml_guestfs_launch (value gv) { @@ -1741,3 +1809,75 @@ ocaml_guestfs_command_lines (value gv, value argumentsv) CAMLreturn (rv); } +CAMLprim value +ocaml_guestfs_stat (value gv, value pathv) +{ + CAMLparam2 (gv, pathv); + CAMLlocal1 (rv); + + guestfs_h *g = Guestfs_val (gv); + if (g == NULL) + caml_failwith ("stat: used handle after closing it"); + + const char *path = String_val (pathv); + struct guestfs_stat *r; + + caml_enter_blocking_section (); + r = guestfs_stat (g, path); + caml_leave_blocking_section (); + if (r == NULL) + ocaml_guestfs_raise_error (g, "stat"); + + rv = copy_stat (r); + free (r); + CAMLreturn (rv); +} + +CAMLprim value +ocaml_guestfs_lstat (value gv, value pathv) +{ + CAMLparam2 (gv, pathv); + CAMLlocal1 (rv); + + guestfs_h *g = Guestfs_val (gv); + if (g == NULL) + caml_failwith ("lstat: used handle after closing it"); + + const char *path = String_val (pathv); + struct guestfs_stat *r; + + caml_enter_blocking_section (); + r = guestfs_lstat (g, path); + caml_leave_blocking_section (); + if (r == NULL) + ocaml_guestfs_raise_error (g, "lstat"); + + rv = copy_stat (r); + free (r); + CAMLreturn (rv); +} + +CAMLprim value +ocaml_guestfs_statvfs (value gv, value pathv) +{ + CAMLparam2 (gv, pathv); + CAMLlocal1 (rv); + + guestfs_h *g = Guestfs_val (gv); + if (g == NULL) + caml_failwith ("statvfs: used handle after closing it"); + + const char *path = String_val (pathv); + struct guestfs_statvfs *r; + + caml_enter_blocking_section (); + r = guestfs_statvfs (g, path); + caml_leave_blocking_section (); + if (r == NULL) + ocaml_guestfs_raise_error (g, "statvfs"); + + rv = copy_statvfs (r); + free (r); + CAMLreturn (rv); +} + diff --git a/perl/Guestfs.xs b/perl/Guestfs.xs index c1eaa11..37a15e0 100644 --- a/perl/Guestfs.xs +++ b/perl/Guestfs.xs @@ -1011,3 +1011,79 @@ PREINIT: } free (lines); +void +stat (g, path) + guestfs_h *g; + char *path; +PREINIT: + struct guestfs_stat *statbuf; + PPCODE: + statbuf = guestfs_stat (g, path); + if (statbuf == NULL) + croak ("stat: %s", guestfs_last_error (g)); + EXTEND (SP, 13); + PUSHs (sv_2mortal (my_newSVll (statbuf->dev))); + PUSHs (sv_2mortal (my_newSVll (statbuf->ino))); + PUSHs (sv_2mortal (my_newSVll (statbuf->mode))); + PUSHs (sv_2mortal (my_newSVll (statbuf->nlink))); + PUSHs (sv_2mortal (my_newSVll (statbuf->uid))); + PUSHs (sv_2mortal (my_newSVll (statbuf->gid))); + PUSHs (sv_2mortal (my_newSVll (statbuf->rdev))); + PUSHs (sv_2mortal (my_newSVll (statbuf->size))); + PUSHs (sv_2mortal (my_newSVll (statbuf->blksize))); + PUSHs (sv_2mortal (my_newSVll (statbuf->blocks))); + PUSHs (sv_2mortal (my_newSVll (statbuf->atime))); + PUSHs (sv_2mortal (my_newSVll (statbuf->mtime))); + PUSHs (sv_2mortal (my_newSVll (statbuf->ctime))); + free (statbuf); + +void +lstat (g, path) + guestfs_h *g; + char *path; +PREINIT: + struct guestfs_stat *statbuf; + PPCODE: + statbuf = guestfs_lstat (g, path); + if (statbuf == NULL) + croak ("lstat: %s", guestfs_last_error (g)); + EXTEND (SP, 13); + PUSHs (sv_2mortal (my_newSVll (statbuf->dev))); + PUSHs (sv_2mortal (my_newSVll (statbuf->ino))); + PUSHs (sv_2mortal (my_newSVll (statbuf->mode))); + PUSHs (sv_2mortal (my_newSVll (statbuf->nlink))); + PUSHs (sv_2mortal (my_newSVll (statbuf->uid))); + PUSHs (sv_2mortal (my_newSVll (statbuf->gid))); + PUSHs (sv_2mortal (my_newSVll (statbuf->rdev))); + PUSHs (sv_2mortal (my_newSVll (statbuf->size))); + PUSHs (sv_2mortal (my_newSVll (statbuf->blksize))); + PUSHs (sv_2mortal (my_newSVll (statbuf->blocks))); + PUSHs (sv_2mortal (my_newSVll (statbuf->atime))); + PUSHs (sv_2mortal (my_newSVll (statbuf->mtime))); + PUSHs (sv_2mortal (my_newSVll (statbuf->ctime))); + free (statbuf); + +void +statvfs (g, path) + guestfs_h *g; + char *path; +PREINIT: + struct guestfs_statvfs *statbuf; + PPCODE: + statbuf = guestfs_statvfs (g, path); + if (statbuf == NULL) + croak ("statvfs: %s", guestfs_last_error (g)); + EXTEND (SP, 11); + PUSHs (sv_2mortal (my_newSVll (statbuf->bsize))); + PUSHs (sv_2mortal (my_newSVll (statbuf->frsize))); + PUSHs (sv_2mortal (my_newSVll (statbuf->blocks))); + PUSHs (sv_2mortal (my_newSVll (statbuf->bfree))); + PUSHs (sv_2mortal (my_newSVll (statbuf->bavail))); + PUSHs (sv_2mortal (my_newSVll (statbuf->files))); + PUSHs (sv_2mortal (my_newSVll (statbuf->ffree))); + PUSHs (sv_2mortal (my_newSVll (statbuf->favail))); + PUSHs (sv_2mortal (my_newSVll (statbuf->fsid))); + PUSHs (sv_2mortal (my_newSVll (statbuf->flag))); + PUSHs (sv_2mortal (my_newSVll (statbuf->namemax))); + free (statbuf); + diff --git a/perl/lib/Sys/Guestfs.pm b/perl/lib/Sys/Guestfs.pm index c9caf08..09663bc 100644 --- a/perl/lib/Sys/Guestfs.pm +++ b/perl/lib/Sys/Guestfs.pm @@ -402,6 +402,16 @@ hidden files are shown. This command is mostly useful for interactive sessions. Programs should probably use C<$h-Ereaddir> instead. +=item %statbuf = $h->lstat ($path); + +Returns file information for the given C. + +This is the same as C<$h-Estat> except that if C +is a symbolic link, then the link is stat-ed, not the file it +refers to. + +This is the same as the C system call. + =item $h->lvcreate ($logvol, $volgroup, $mbytes); This creates an LVM volume group called C @@ -568,6 +578,20 @@ the string C<,> (comma). B. +=item %statbuf = $h->stat ($path); + +Returns file information for the given C. + +This is the same as the C system call. + +=item %statbuf = $h->statvfs ($path); + +Returns file system statistics for any mounted file system. +C should be a file or directory in the mounted file system +(typically it is the mount point itself, but it doesn't need to be). + +This is the same as the C system call. + =item $h->sync (); This syncs the disk, so that any writes are flushed through to the diff --git a/python/guestfs-py.c b/python/guestfs-py.c index 8c7ad22..81c8798 100644 --- a/python/guestfs-py.c +++ b/python/guestfs-py.c @@ -303,6 +303,72 @@ put_lvm_lv_list (struct guestfs_lvm_lv_list *lvs) }; static PyObject * +put_stat (struct guestfs_stat *stat) +{ + PyObject *dict; + + dict = PyDict_New (); + PyDict_SetItemString (dict, "dev", + PyLong_FromLongLong (stat->dev)); + PyDict_SetItemString (dict, "ino", + PyLong_FromLongLong (stat->ino)); + PyDict_SetItemString (dict, "mode", + PyLong_FromLongLong (stat->mode)); + PyDict_SetItemString (dict, "nlink", + PyLong_FromLongLong (stat->nlink)); + PyDict_SetItemString (dict, "uid", + PyLong_FromLongLong (stat->uid)); + PyDict_SetItemString (dict, "gid", + PyLong_FromLongLong (stat->gid)); + PyDict_SetItemString (dict, "rdev", + PyLong_FromLongLong (stat->rdev)); + PyDict_SetItemString (dict, "size", + PyLong_FromLongLong (stat->size)); + PyDict_SetItemString (dict, "blksize", + PyLong_FromLongLong (stat->blksize)); + PyDict_SetItemString (dict, "blocks", + PyLong_FromLongLong (stat->blocks)); + PyDict_SetItemString (dict, "atime", + PyLong_FromLongLong (stat->atime)); + PyDict_SetItemString (dict, "mtime", + PyLong_FromLongLong (stat->mtime)); + PyDict_SetItemString (dict, "ctime", + PyLong_FromLongLong (stat->ctime)); + return dict; +}; + +static PyObject * +put_statvfs (struct guestfs_statvfs *statvfs) +{ + PyObject *dict; + + dict = PyDict_New (); + PyDict_SetItemString (dict, "bsize", + PyLong_FromLongLong (statvfs->bsize)); + PyDict_SetItemString (dict, "frsize", + PyLong_FromLongLong (statvfs->frsize)); + PyDict_SetItemString (dict, "blocks", + PyLong_FromLongLong (statvfs->blocks)); + PyDict_SetItemString (dict, "bfree", + PyLong_FromLongLong (statvfs->bfree)); + PyDict_SetItemString (dict, "bavail", + PyLong_FromLongLong (statvfs->bavail)); + PyDict_SetItemString (dict, "files", + PyLong_FromLongLong (statvfs->files)); + PyDict_SetItemString (dict, "ffree", + PyLong_FromLongLong (statvfs->ffree)); + PyDict_SetItemString (dict, "favail", + PyLong_FromLongLong (statvfs->favail)); + PyDict_SetItemString (dict, "fsid", + PyLong_FromLongLong (statvfs->fsid)); + PyDict_SetItemString (dict, "flag", + PyLong_FromLongLong (statvfs->flag)); + PyDict_SetItemString (dict, "namemax", + PyLong_FromLongLong (statvfs->namemax)); + return dict; +}; + +static PyObject * py_guestfs_launch (PyObject *self, PyObject *args) { PyObject *py_g; @@ -1889,6 +1955,81 @@ py_guestfs_command_lines (PyObject *self, PyObject *args) return py_r; } +static PyObject * +py_guestfs_stat (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + struct guestfs_stat *r; + const char *path; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_stat", + &py_g, &path)) + return NULL; + g = get_handle (py_g); + + r = guestfs_stat (g, path); + if (r == NULL) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = put_stat (r); + free (r); + return py_r; +} + +static PyObject * +py_guestfs_lstat (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + struct guestfs_stat *r; + const char *path; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_lstat", + &py_g, &path)) + return NULL; + g = get_handle (py_g); + + r = guestfs_lstat (g, path); + if (r == NULL) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = put_stat (r); + free (r); + return py_r; +} + +static PyObject * +py_guestfs_statvfs (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + struct guestfs_statvfs *r; + const char *path; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_statvfs", + &py_g, &path)) + return NULL; + g = get_handle (py_g); + + r = guestfs_statvfs (g, path); + if (r == NULL) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + py_r = put_statvfs (r); + free (r); + return py_r; +} + static PyMethodDef methods[] = { { (char *) "create", py_guestfs_create, METH_VARARGS, NULL }, { (char *) "close", py_guestfs_close, METH_VARARGS, NULL }, @@ -1955,6 +2096,9 @@ static PyMethodDef methods[] = { { (char *) "file", py_guestfs_file, METH_VARARGS, NULL }, { (char *) "command", py_guestfs_command, METH_VARARGS, NULL }, { (char *) "command_lines", py_guestfs_command_lines, METH_VARARGS, NULL }, + { (char *) "stat", py_guestfs_stat, METH_VARARGS, NULL }, + { (char *) "lstat", py_guestfs_lstat, METH_VARARGS, NULL }, + { (char *) "statvfs", py_guestfs_statvfs, METH_VARARGS, NULL }, { NULL, NULL, 0, NULL } }; diff --git a/python/guestfs.py b/python/guestfs.py index 6cf7e19..2e0be5c 100644 --- a/python/guestfs.py +++ b/python/guestfs.py @@ -216,3 +216,12 @@ class GuestFS: def command_lines (self, arguments): return libguestfsmod.command_lines (self._o, arguments) + def stat (self, path): + return libguestfsmod.stat (self._o, path) + + def lstat (self, path): + return libguestfsmod.lstat (self._o, path) + + def statvfs (self, path): + return libguestfsmod.statvfs (self._o, path) + diff --git a/src/guestfs-actions.c b/src/guestfs-actions.c index c6f574a..8f40102 100644 --- a/src/guestfs-actions.c +++ b/src/guestfs-actions.c @@ -3699,3 +3699,228 @@ char **guestfs_command_lines (guestfs_h *g, return rv.ret.lines.lines_val; } +struct stat_rv { + int cb_done; /* flag to indicate callback was called */ + struct guestfs_message_header hdr; + struct guestfs_message_error err; + struct guestfs_stat_ret ret; +}; + +static void stat_cb (guestfs_h *g, void *data, XDR *xdr) +{ + struct stat_rv *rv = (struct stat_rv *) data; + + if (!xdr_guestfs_message_header (xdr, &rv->hdr)) { + error (g, "guestfs_stat: failed to parse reply header"); + return; + } + if (rv->hdr.status == GUESTFS_STATUS_ERROR) { + if (!xdr_guestfs_message_error (xdr, &rv->err)) { + error (g, "guestfs_stat: failed to parse reply error"); + return; + } + goto done; + } + if (!xdr_guestfs_stat_ret (xdr, &rv->ret)) { + error (g, "guestfs_stat: failed to parse reply"); + return; + } + done: + rv->cb_done = 1; + main_loop.main_loop_quit (g); +} + +struct guestfs_stat *guestfs_stat (guestfs_h *g, + const char *path) +{ + struct guestfs_stat_args args; + struct stat_rv rv; + int serial; + + if (g->state != READY) { + error (g, "guestfs_stat called from the wrong state, %d != READY", + g->state); + return NULL; + } + + memset (&rv, 0, sizeof rv); + + args.path = (char *) path; + serial = dispatch (g, GUESTFS_PROC_STAT, + (xdrproc_t) xdr_guestfs_stat_args, (char *) &args); + if (serial == -1) + return NULL; + + rv.cb_done = 0; + g->reply_cb_internal = stat_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_stat failed, see earlier error messages"); + return NULL; + } + + if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_STAT, serial) == -1) + return NULL; + + if (rv.hdr.status == GUESTFS_STATUS_ERROR) { + error (g, "%s", rv.err.error); + return NULL; + } + + /* caller will free this */ + return safe_memdup (g, &rv.ret.statbuf, sizeof (rv.ret.statbuf)); +} + +struct lstat_rv { + int cb_done; /* flag to indicate callback was called */ + struct guestfs_message_header hdr; + struct guestfs_message_error err; + struct guestfs_lstat_ret ret; +}; + +static void lstat_cb (guestfs_h *g, void *data, XDR *xdr) +{ + struct lstat_rv *rv = (struct lstat_rv *) data; + + if (!xdr_guestfs_message_header (xdr, &rv->hdr)) { + error (g, "guestfs_lstat: failed to parse reply header"); + return; + } + if (rv->hdr.status == GUESTFS_STATUS_ERROR) { + if (!xdr_guestfs_message_error (xdr, &rv->err)) { + error (g, "guestfs_lstat: failed to parse reply error"); + return; + } + goto done; + } + if (!xdr_guestfs_lstat_ret (xdr, &rv->ret)) { + error (g, "guestfs_lstat: failed to parse reply"); + return; + } + done: + rv->cb_done = 1; + main_loop.main_loop_quit (g); +} + +struct guestfs_stat *guestfs_lstat (guestfs_h *g, + const char *path) +{ + struct guestfs_lstat_args args; + struct lstat_rv rv; + int serial; + + if (g->state != READY) { + error (g, "guestfs_lstat called from the wrong state, %d != READY", + g->state); + return NULL; + } + + memset (&rv, 0, sizeof rv); + + args.path = (char *) path; + serial = dispatch (g, GUESTFS_PROC_LSTAT, + (xdrproc_t) xdr_guestfs_lstat_args, (char *) &args); + if (serial == -1) + return NULL; + + rv.cb_done = 0; + g->reply_cb_internal = lstat_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_lstat failed, see earlier error messages"); + return NULL; + } + + if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_LSTAT, serial) == -1) + return NULL; + + if (rv.hdr.status == GUESTFS_STATUS_ERROR) { + error (g, "%s", rv.err.error); + return NULL; + } + + /* caller will free this */ + return safe_memdup (g, &rv.ret.statbuf, sizeof (rv.ret.statbuf)); +} + +struct statvfs_rv { + int cb_done; /* flag to indicate callback was called */ + struct guestfs_message_header hdr; + struct guestfs_message_error err; + struct guestfs_statvfs_ret ret; +}; + +static void statvfs_cb (guestfs_h *g, void *data, XDR *xdr) +{ + struct statvfs_rv *rv = (struct statvfs_rv *) data; + + if (!xdr_guestfs_message_header (xdr, &rv->hdr)) { + error (g, "guestfs_statvfs: failed to parse reply header"); + return; + } + if (rv->hdr.status == GUESTFS_STATUS_ERROR) { + if (!xdr_guestfs_message_error (xdr, &rv->err)) { + error (g, "guestfs_statvfs: failed to parse reply error"); + return; + } + goto done; + } + if (!xdr_guestfs_statvfs_ret (xdr, &rv->ret)) { + error (g, "guestfs_statvfs: failed to parse reply"); + return; + } + done: + rv->cb_done = 1; + main_loop.main_loop_quit (g); +} + +struct guestfs_statvfs *guestfs_statvfs (guestfs_h *g, + const char *path) +{ + struct guestfs_statvfs_args args; + struct statvfs_rv rv; + int serial; + + if (g->state != READY) { + error (g, "guestfs_statvfs called from the wrong state, %d != READY", + g->state); + return NULL; + } + + memset (&rv, 0, sizeof rv); + + args.path = (char *) path; + serial = dispatch (g, GUESTFS_PROC_STATVFS, + (xdrproc_t) xdr_guestfs_statvfs_args, (char *) &args); + if (serial == -1) + return NULL; + + rv.cb_done = 0; + g->reply_cb_internal = statvfs_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_statvfs failed, see earlier error messages"); + return NULL; + } + + if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_STATVFS, serial) == -1) + return NULL; + + if (rv.hdr.status == GUESTFS_STATUS_ERROR) { + error (g, "%s", rv.err.error); + return NULL; + } + + /* caller will free this */ + return safe_memdup (g, &rv.ret.statbuf, sizeof (rv.ret.statbuf)); +} + diff --git a/src/guestfs-actions.h b/src/guestfs-actions.h index 06efabf..a838a04 100644 --- a/src/guestfs-actions.h +++ b/src/guestfs-actions.h @@ -82,3 +82,6 @@ extern int guestfs_lvm_remove_all (guestfs_h *handle); extern char *guestfs_file (guestfs_h *handle, const char *path); extern char *guestfs_command (guestfs_h *handle, char * const* const arguments); extern char **guestfs_command_lines (guestfs_h *handle, char * const* const arguments); +extern struct guestfs_stat *guestfs_stat (guestfs_h *handle, const char *path); +extern struct guestfs_stat *guestfs_lstat (guestfs_h *handle, const char *path); +extern struct guestfs_statvfs *guestfs_statvfs (guestfs_h *handle, const char *path); diff --git a/src/guestfs-structs.h b/src/guestfs-structs.h index b3751cd..76ac819 100644 --- a/src/guestfs-structs.h +++ b/src/guestfs-structs.h @@ -97,3 +97,33 @@ struct guestfs_lvm_lv_list { struct guestfs_lvm_lv *val; }; +struct guestfs_stat { + int64_t dev; + int64_t ino; + int64_t mode; + int64_t nlink; + int64_t uid; + int64_t gid; + int64_t rdev; + int64_t size; + int64_t blksize; + int64_t blocks; + int64_t atime; + int64_t mtime; + int64_t ctime; +}; + +struct guestfs_statvfs { + int64_t bsize; + int64_t frsize; + int64_t blocks; + int64_t bfree; + int64_t bavail; + int64_t files; + int64_t ffree; + int64_t favail; + int64_t fsid; + int64_t flag; + int64_t namemax; +}; + diff --git a/src/guestfs_protocol.c b/src/guestfs_protocol.c index 0849f7a..99377b4 100644 --- a/src/guestfs_protocol.c +++ b/src/guestfs_protocol.c @@ -174,6 +174,70 @@ xdr_guestfs_lvm_int_lv_list (XDR *xdrs, guestfs_lvm_int_lv_list *objp) } bool_t +xdr_guestfs_int_stat (XDR *xdrs, guestfs_int_stat *objp) +{ + register int32_t *buf; + + if (!xdr_quad_t (xdrs, &objp->dev)) + return FALSE; + if (!xdr_quad_t (xdrs, &objp->ino)) + return FALSE; + if (!xdr_quad_t (xdrs, &objp->mode)) + return FALSE; + if (!xdr_quad_t (xdrs, &objp->nlink)) + return FALSE; + if (!xdr_quad_t (xdrs, &objp->uid)) + return FALSE; + if (!xdr_quad_t (xdrs, &objp->gid)) + return FALSE; + if (!xdr_quad_t (xdrs, &objp->rdev)) + return FALSE; + if (!xdr_quad_t (xdrs, &objp->size)) + return FALSE; + if (!xdr_quad_t (xdrs, &objp->blksize)) + return FALSE; + if (!xdr_quad_t (xdrs, &objp->blocks)) + return FALSE; + if (!xdr_quad_t (xdrs, &objp->atime)) + return FALSE; + if (!xdr_quad_t (xdrs, &objp->mtime)) + return FALSE; + if (!xdr_quad_t (xdrs, &objp->ctime)) + return FALSE; + return TRUE; +} + +bool_t +xdr_guestfs_int_statvfs (XDR *xdrs, guestfs_int_statvfs *objp) +{ + register int32_t *buf; + + if (!xdr_quad_t (xdrs, &objp->bsize)) + return FALSE; + if (!xdr_quad_t (xdrs, &objp->frsize)) + return FALSE; + if (!xdr_quad_t (xdrs, &objp->blocks)) + return FALSE; + if (!xdr_quad_t (xdrs, &objp->bfree)) + return FALSE; + if (!xdr_quad_t (xdrs, &objp->bavail)) + return FALSE; + if (!xdr_quad_t (xdrs, &objp->files)) + return FALSE; + if (!xdr_quad_t (xdrs, &objp->ffree)) + return FALSE; + if (!xdr_quad_t (xdrs, &objp->favail)) + return FALSE; + if (!xdr_quad_t (xdrs, &objp->fsid)) + return FALSE; + if (!xdr_quad_t (xdrs, &objp->flag)) + return FALSE; + if (!xdr_quad_t (xdrs, &objp->namemax)) + return FALSE; + return TRUE; +} + +bool_t xdr_guestfs_mount_args (XDR *xdrs, guestfs_mount_args *objp) { register int32_t *buf; @@ -890,6 +954,66 @@ xdr_guestfs_command_lines_ret (XDR *xdrs, guestfs_command_lines_ret *objp) } bool_t +xdr_guestfs_stat_args (XDR *xdrs, guestfs_stat_args *objp) +{ + register int32_t *buf; + + if (!xdr_string (xdrs, &objp->path, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_guestfs_stat_ret (XDR *xdrs, guestfs_stat_ret *objp) +{ + register int32_t *buf; + + if (!xdr_guestfs_int_stat (xdrs, &objp->statbuf)) + return FALSE; + return TRUE; +} + +bool_t +xdr_guestfs_lstat_args (XDR *xdrs, guestfs_lstat_args *objp) +{ + register int32_t *buf; + + if (!xdr_string (xdrs, &objp->path, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_guestfs_lstat_ret (XDR *xdrs, guestfs_lstat_ret *objp) +{ + register int32_t *buf; + + if (!xdr_guestfs_int_stat (xdrs, &objp->statbuf)) + return FALSE; + return TRUE; +} + +bool_t +xdr_guestfs_statvfs_args (XDR *xdrs, guestfs_statvfs_args *objp) +{ + register int32_t *buf; + + if (!xdr_string (xdrs, &objp->path, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_guestfs_statvfs_ret (XDR *xdrs, guestfs_statvfs_ret *objp) +{ + register int32_t *buf; + + if (!xdr_guestfs_int_statvfs (xdrs, &objp->statbuf)) + 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 4b31468..0720723 100644 --- a/src/guestfs_protocol.h +++ b/src/guestfs_protocol.h @@ -92,6 +92,38 @@ typedef struct { guestfs_lvm_int_lv *guestfs_lvm_int_lv_list_val; } guestfs_lvm_int_lv_list; +struct guestfs_int_stat { + quad_t dev; + quad_t ino; + quad_t mode; + quad_t nlink; + quad_t uid; + quad_t gid; + quad_t rdev; + quad_t size; + quad_t blksize; + quad_t blocks; + quad_t atime; + quad_t mtime; + quad_t ctime; +}; +typedef struct guestfs_int_stat guestfs_int_stat; + +struct guestfs_int_statvfs { + quad_t bsize; + quad_t frsize; + quad_t blocks; + quad_t bfree; + quad_t bavail; + quad_t files; + quad_t ffree; + quad_t favail; + quad_t fsid; + quad_t flag; + quad_t namemax; +}; +typedef struct guestfs_int_statvfs guestfs_int_statvfs; + struct guestfs_mount_args { char *device; char *mountpoint; @@ -465,6 +497,36 @@ struct guestfs_command_lines_ret { }; typedef struct guestfs_command_lines_ret guestfs_command_lines_ret; +struct guestfs_stat_args { + char *path; +}; +typedef struct guestfs_stat_args guestfs_stat_args; + +struct guestfs_stat_ret { + guestfs_int_stat statbuf; +}; +typedef struct guestfs_stat_ret guestfs_stat_ret; + +struct guestfs_lstat_args { + char *path; +}; +typedef struct guestfs_lstat_args guestfs_lstat_args; + +struct guestfs_lstat_ret { + guestfs_int_stat statbuf; +}; +typedef struct guestfs_lstat_ret guestfs_lstat_ret; + +struct guestfs_statvfs_args { + char *path; +}; +typedef struct guestfs_statvfs_args guestfs_statvfs_args; + +struct guestfs_statvfs_ret { + guestfs_int_statvfs statbuf; +}; +typedef struct guestfs_statvfs_ret guestfs_statvfs_ret; + enum guestfs_procedure { GUESTFS_PROC_MOUNT = 1, GUESTFS_PROC_SYNC = 2, @@ -517,7 +579,10 @@ enum guestfs_procedure { GUESTFS_PROC_FILE = 49, GUESTFS_PROC_COMMAND = 50, GUESTFS_PROC_COMMAND_LINES = 51, - GUESTFS_PROC_dummy = 51 + 1, + GUESTFS_PROC_STAT = 52, + GUESTFS_PROC_LSTAT = 53, + GUESTFS_PROC_STATVFS = 54, + GUESTFS_PROC_dummy = 54 + 1, }; typedef enum guestfs_procedure guestfs_procedure; #define GUESTFS_MESSAGE_MAX 4194304 @@ -562,6 +627,8 @@ extern bool_t xdr_guestfs_lvm_int_vg (XDR *, guestfs_lvm_int_vg*); extern bool_t xdr_guestfs_lvm_int_vg_list (XDR *, guestfs_lvm_int_vg_list*); extern bool_t xdr_guestfs_lvm_int_lv (XDR *, guestfs_lvm_int_lv*); extern bool_t xdr_guestfs_lvm_int_lv_list (XDR *, guestfs_lvm_int_lv_list*); +extern bool_t xdr_guestfs_int_stat (XDR *, guestfs_int_stat*); +extern bool_t xdr_guestfs_int_statvfs (XDR *, guestfs_int_statvfs*); 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*); @@ -623,6 +690,12 @@ extern bool_t xdr_guestfs_command_args (XDR *, guestfs_command_args*); extern bool_t xdr_guestfs_command_ret (XDR *, guestfs_command_ret*); extern bool_t xdr_guestfs_command_lines_args (XDR *, guestfs_command_lines_args*); extern bool_t xdr_guestfs_command_lines_ret (XDR *, guestfs_command_lines_ret*); +extern bool_t xdr_guestfs_stat_args (XDR *, guestfs_stat_args*); +extern bool_t xdr_guestfs_stat_ret (XDR *, guestfs_stat_ret*); +extern bool_t xdr_guestfs_lstat_args (XDR *, guestfs_lstat_args*); +extern bool_t xdr_guestfs_lstat_ret (XDR *, guestfs_lstat_ret*); +extern bool_t xdr_guestfs_statvfs_args (XDR *, guestfs_statvfs_args*); +extern bool_t xdr_guestfs_statvfs_ret (XDR *, guestfs_statvfs_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*); @@ -637,6 +710,8 @@ extern bool_t xdr_guestfs_lvm_int_vg (); extern bool_t xdr_guestfs_lvm_int_vg_list (); extern bool_t xdr_guestfs_lvm_int_lv (); extern bool_t xdr_guestfs_lvm_int_lv_list (); +extern bool_t xdr_guestfs_int_stat (); +extern bool_t xdr_guestfs_int_statvfs (); extern bool_t xdr_guestfs_mount_args (); extern bool_t xdr_guestfs_touch_args (); extern bool_t xdr_guestfs_cat_args (); @@ -698,6 +773,12 @@ extern bool_t xdr_guestfs_command_args (); extern bool_t xdr_guestfs_command_ret (); extern bool_t xdr_guestfs_command_lines_args (); extern bool_t xdr_guestfs_command_lines_ret (); +extern bool_t xdr_guestfs_stat_args (); +extern bool_t xdr_guestfs_stat_ret (); +extern bool_t xdr_guestfs_lstat_args (); +extern bool_t xdr_guestfs_lstat_ret (); +extern bool_t xdr_guestfs_statvfs_args (); +extern bool_t xdr_guestfs_statvfs_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 68362d6..e03aef6 100644 --- a/src/guestfs_protocol.x +++ b/src/guestfs_protocol.x @@ -85,6 +85,36 @@ struct guestfs_lvm_int_lv { typedef struct guestfs_lvm_int_lv guestfs_lvm_int_lv_list<>; +struct guestfs_int_stat { + hyper dev; + hyper ino; + hyper mode; + hyper nlink; + hyper uid; + hyper gid; + hyper rdev; + hyper size; + hyper blksize; + hyper blocks; + hyper atime; + hyper mtime; + hyper ctime; +}; + +struct guestfs_int_statvfs { + hyper bsize; + hyper frsize; + hyper blocks; + hyper bfree; + hyper bavail; + hyper files; + hyper ffree; + hyper favail; + hyper fsid; + hyper flag; + hyper namemax; +}; + struct guestfs_mount_args { string device<>; string mountpoint<>; @@ -352,6 +382,30 @@ struct guestfs_command_lines_ret { str lines<>; }; +struct guestfs_stat_args { + string path<>; +}; + +struct guestfs_stat_ret { + guestfs_int_stat statbuf; +}; + +struct guestfs_lstat_args { + string path<>; +}; + +struct guestfs_lstat_ret { + guestfs_int_stat statbuf; +}; + +struct guestfs_statvfs_args { + string path<>; +}; + +struct guestfs_statvfs_ret { + guestfs_int_statvfs statbuf; +}; + enum guestfs_procedure { GUESTFS_PROC_MOUNT = 1, GUESTFS_PROC_SYNC = 2, @@ -404,6 +458,9 @@ enum guestfs_procedure { GUESTFS_PROC_FILE = 49, GUESTFS_PROC_COMMAND = 50, GUESTFS_PROC_COMMAND_LINES = 51, + GUESTFS_PROC_STAT = 52, + GUESTFS_PROC_LSTAT = 53, + GUESTFS_PROC_STATVFS = 54, GUESTFS_PROC_dummy }; diff --git a/tests.c b/tests.c index b59192c..1c6676b 100644 --- a/tests.c +++ b/tests.c @@ -1238,288 +1238,6 @@ static int test_lvs_1 (void) return 0; } -static int test_pvs_full_0 (void) -{ - /* InitBasicFSonLVM for pvs_full (0): create ext2 on /dev/VG/LV */ - { - 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_pvcreate (g, "/dev/sda1"); - if (r == -1) - return -1; - } - { - char *physvols[] = { - "/dev/sda1", - NULL - }; - int r; - suppress_error = 0; - r = guestfs_vgcreate (g, "VG", physvols); - if (r == -1) - return -1; - } - { - int r; - suppress_error = 0; - r = guestfs_lvcreate (g, "LV", "VG", 8); - if (r == -1) - return -1; - } - { - int r; - suppress_error = 0; - r = guestfs_mkfs (g, "ext2", "/dev/VG/LV"); - if (r == -1) - return -1; - } - { - int r; - suppress_error = 0; - r = guestfs_mount (g, "/dev/VG/LV", "/"); - if (r == -1) - return -1; - } - /* TestOutputLength for pvs_full (0) */ - { - char **r; - int i; - suppress_error = 0; - r = guestfs_pvs (g); - if (r == NULL) - return -1; - int j; - for (j = 0; j < 1; ++j) - if (r[j] == NULL) { - fprintf (stderr, "test_pvs_full_0: short list returned\n"); - print_strings (r); - return -1; - } - if (r[j] != NULL) { - fprintf (stderr, "test_pvs_full_0: long list returned\n"); - print_strings (r); - return -1; - } - for (i = 0; r[i] != NULL; ++i) - free (r[i]); - free (r); - } - return 0; -} - -static int test_vgs_full_0 (void) -{ - /* InitBasicFSonLVM for vgs_full (0): create ext2 on /dev/VG/LV */ - { - 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_pvcreate (g, "/dev/sda1"); - if (r == -1) - return -1; - } - { - char *physvols[] = { - "/dev/sda1", - NULL - }; - int r; - suppress_error = 0; - r = guestfs_vgcreate (g, "VG", physvols); - if (r == -1) - return -1; - } - { - int r; - suppress_error = 0; - r = guestfs_lvcreate (g, "LV", "VG", 8); - if (r == -1) - return -1; - } - { - int r; - suppress_error = 0; - r = guestfs_mkfs (g, "ext2", "/dev/VG/LV"); - if (r == -1) - return -1; - } - { - int r; - suppress_error = 0; - r = guestfs_mount (g, "/dev/VG/LV", "/"); - if (r == -1) - return -1; - } - /* TestOutputLength for vgs_full (0) */ - { - char **r; - int i; - suppress_error = 0; - r = guestfs_pvs (g); - if (r == NULL) - return -1; - int j; - for (j = 0; j < 1; ++j) - if (r[j] == NULL) { - fprintf (stderr, "test_vgs_full_0: short list returned\n"); - print_strings (r); - return -1; - } - if (r[j] != NULL) { - fprintf (stderr, "test_vgs_full_0: long list returned\n"); - print_strings (r); - return -1; - } - for (i = 0; r[i] != NULL; ++i) - free (r[i]); - free (r); - } - return 0; -} - -static int test_lvs_full_0 (void) -{ - /* InitBasicFSonLVM for lvs_full (0): create ext2 on /dev/VG/LV */ - { - 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_pvcreate (g, "/dev/sda1"); - if (r == -1) - return -1; - } - { - char *physvols[] = { - "/dev/sda1", - NULL - }; - int r; - suppress_error = 0; - r = guestfs_vgcreate (g, "VG", physvols); - if (r == -1) - return -1; - } - { - int r; - suppress_error = 0; - r = guestfs_lvcreate (g, "LV", "VG", 8); - if (r == -1) - return -1; - } - { - int r; - suppress_error = 0; - r = guestfs_mkfs (g, "ext2", "/dev/VG/LV"); - if (r == -1) - return -1; - } - { - int r; - suppress_error = 0; - r = guestfs_mount (g, "/dev/VG/LV", "/"); - if (r == -1) - return -1; - } - /* TestOutputLength for lvs_full (0) */ - { - char **r; - int i; - suppress_error = 0; - r = guestfs_pvs (g); - if (r == NULL) - return -1; - int j; - for (j = 0; j < 1; ++j) - if (r[j] == NULL) { - fprintf (stderr, "test_lvs_full_0: short list returned\n"); - print_strings (r); - return -1; - } - if (r[j] != NULL) { - fprintf (stderr, "test_lvs_full_0: long list returned\n"); - print_strings (r); - return -1; - } - for (i = 0; r[i] != NULL; ++i) - free (r[i]); - free (r); - } - return 0; -} - static int test_read_lines_0 (void) { /* InitBasicFS for read_lines (0): create ext2 on /dev/sda1 */ @@ -3787,6 +3505,207 @@ static int test_file_2 (void) return 0; } +static int test_stat_0 (void) +{ + /* InitBasicFS for stat (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; + } + /* TestOutputStruct for stat (0) */ + { + int r; + suppress_error = 0; + r = guestfs_touch (g, "/new"); + if (r == -1) + return -1; + } + { + struct guestfs_stat *r; + suppress_error = 0; + r = guestfs_stat (g, "/new"); + if (r == NULL) + return -1; + if (r->size != 0) { + fprintf (stderr, "test_stat_0: size was %d, expected 0\n", + (int) r->size); + return -1; + } + free (r); + } + return 0; +} + +static int test_lstat_0 (void) +{ + /* InitBasicFS for lstat (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; + } + /* TestOutputStruct for lstat (0) */ + { + int r; + suppress_error = 0; + r = guestfs_touch (g, "/new"); + if (r == -1) + return -1; + } + { + struct guestfs_stat *r; + suppress_error = 0; + r = guestfs_lstat (g, "/new"); + if (r == NULL) + return -1; + if (r->size != 0) { + fprintf (stderr, "test_lstat_0: size was %d, expected 0\n", + (int) r->size); + return -1; + } + free (r); + } + return 0; +} + +static int test_statvfs_0 (void) +{ + /* InitBasicFS for statvfs (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; + } + /* TestOutputStruct for statvfs (0) */ + { + struct guestfs_statvfs *r; + suppress_error = 0; + r = guestfs_statvfs (g, "/"); + if (r == NULL) + return -1; + if (r->bfree != 487702) { + fprintf (stderr, "test_statvfs_0: bfree was %d, expected 487702\n", + (int) r->bfree); + return -1; + } + if (r->blocks != 490020) { + fprintf (stderr, "test_statvfs_0: blocks was %d, expected 490020\n", + (int) r->blocks); + return -1; + } + if (r->bsize != 1024) { + fprintf (stderr, "test_statvfs_0: bsize was %d, expected 1024\n", + (int) r->bsize); + return -1; + } + free (r); + } + return 0; +} + int main (int argc, char *argv[]) { char c = 0; @@ -3794,6 +3713,7 @@ int main (int argc, char *argv[]) const char *srcdir; int fd; char buf[256]; + int nr_tests; g = guestfs_create (); if (g == NULL) { @@ -3900,251 +3820,252 @@ int main (int argc, char *argv[]) exit (1); } - printf (" 1/ 49 test_mount_0\n"); + nr_tests = 49; + printf (" 1/%3d test_mount_0\n", nr_tests); if (test_mount_0 () == -1) { printf ("test_mount_0 FAILED\n"); failed++; } - printf (" 2/ 49 test_sync_0\n"); + printf (" 2/%3d test_sync_0\n", nr_tests); if (test_sync_0 () == -1) { printf ("test_sync_0 FAILED\n"); failed++; } - printf (" 3/ 49 test_touch_0\n"); + printf (" 3/%3d test_touch_0\n", nr_tests); if (test_touch_0 () == -1) { printf ("test_touch_0 FAILED\n"); failed++; } - printf (" 4/ 49 test_cat_0\n"); + printf (" 4/%3d test_cat_0\n", nr_tests); if (test_cat_0 () == -1) { printf ("test_cat_0 FAILED\n"); failed++; } - printf (" 5/ 49 test_ls_0\n"); + printf (" 5/%3d test_ls_0\n", nr_tests); if (test_ls_0 () == -1) { printf ("test_ls_0 FAILED\n"); failed++; } - printf (" 6/ 49 test_list_devices_0\n"); + printf (" 6/%3d test_list_devices_0\n", nr_tests); if (test_list_devices_0 () == -1) { printf ("test_list_devices_0 FAILED\n"); failed++; } - printf (" 7/ 49 test_list_partitions_0\n"); + printf (" 7/%3d test_list_partitions_0\n", nr_tests); if (test_list_partitions_0 () == -1) { printf ("test_list_partitions_0 FAILED\n"); failed++; } - printf (" 8/ 49 test_list_partitions_1\n"); + printf (" 8/%3d test_list_partitions_1\n", nr_tests); if (test_list_partitions_1 () == -1) { printf ("test_list_partitions_1 FAILED\n"); failed++; } - printf (" 9/ 49 test_pvs_0\n"); + printf (" 9/%3d test_pvs_0\n", nr_tests); if (test_pvs_0 () == -1) { printf ("test_pvs_0 FAILED\n"); failed++; } - printf (" 10/ 49 test_pvs_1\n"); + printf (" 10/%3d test_pvs_1\n", nr_tests); if (test_pvs_1 () == -1) { printf ("test_pvs_1 FAILED\n"); failed++; } - printf (" 11/ 49 test_vgs_0\n"); + printf (" 11/%3d test_vgs_0\n", nr_tests); if (test_vgs_0 () == -1) { printf ("test_vgs_0 FAILED\n"); failed++; } - printf (" 12/ 49 test_vgs_1\n"); + printf (" 12/%3d test_vgs_1\n", nr_tests); if (test_vgs_1 () == -1) { printf ("test_vgs_1 FAILED\n"); failed++; } - printf (" 13/ 49 test_lvs_0\n"); + printf (" 13/%3d test_lvs_0\n", nr_tests); if (test_lvs_0 () == -1) { printf ("test_lvs_0 FAILED\n"); failed++; } - printf (" 14/ 49 test_lvs_1\n"); + printf (" 14/%3d test_lvs_1\n", nr_tests); if (test_lvs_1 () == -1) { printf ("test_lvs_1 FAILED\n"); failed++; } - printf (" 15/ 49 test_pvs_full_0\n"); - if (test_pvs_full_0 () == -1) { - printf ("test_pvs_full_0 FAILED\n"); - failed++; - } - printf (" 16/ 49 test_vgs_full_0\n"); - if (test_vgs_full_0 () == -1) { - printf ("test_vgs_full_0 FAILED\n"); - failed++; - } - printf (" 17/ 49 test_lvs_full_0\n"); - if (test_lvs_full_0 () == -1) { - printf ("test_lvs_full_0 FAILED\n"); - failed++; - } - printf (" 18/ 49 test_read_lines_0\n"); + printf (" 15/%3d test_read_lines_0\n", nr_tests); if (test_read_lines_0 () == -1) { printf ("test_read_lines_0 FAILED\n"); failed++; } - printf (" 19/ 49 test_read_lines_1\n"); + printf (" 16/%3d test_read_lines_1\n", nr_tests); if (test_read_lines_1 () == -1) { printf ("test_read_lines_1 FAILED\n"); failed++; } - printf (" 20/ 49 test_rm_0\n"); + printf (" 17/%3d test_rm_0\n", nr_tests); if (test_rm_0 () == -1) { printf ("test_rm_0 FAILED\n"); failed++; } - printf (" 21/ 49 test_rm_1\n"); + printf (" 18/%3d test_rm_1\n", nr_tests); if (test_rm_1 () == -1) { printf ("test_rm_1 FAILED\n"); failed++; } - printf (" 22/ 49 test_rm_2\n"); + printf (" 19/%3d test_rm_2\n", nr_tests); if (test_rm_2 () == -1) { printf ("test_rm_2 FAILED\n"); failed++; } - printf (" 23/ 49 test_rmdir_0\n"); + printf (" 20/%3d test_rmdir_0\n", nr_tests); if (test_rmdir_0 () == -1) { printf ("test_rmdir_0 FAILED\n"); failed++; } - printf (" 24/ 49 test_rmdir_1\n"); + printf (" 21/%3d test_rmdir_1\n", nr_tests); if (test_rmdir_1 () == -1) { printf ("test_rmdir_1 FAILED\n"); failed++; } - printf (" 25/ 49 test_rmdir_2\n"); + printf (" 22/%3d test_rmdir_2\n", nr_tests); if (test_rmdir_2 () == -1) { printf ("test_rmdir_2 FAILED\n"); failed++; } - printf (" 26/ 49 test_rm_rf_0\n"); + printf (" 23/%3d test_rm_rf_0\n", nr_tests); if (test_rm_rf_0 () == -1) { printf ("test_rm_rf_0 FAILED\n"); failed++; } - printf (" 27/ 49 test_mkdir_0\n"); + printf (" 24/%3d test_mkdir_0\n", nr_tests); if (test_mkdir_0 () == -1) { printf ("test_mkdir_0 FAILED\n"); failed++; } - printf (" 28/ 49 test_mkdir_1\n"); + printf (" 25/%3d test_mkdir_1\n", nr_tests); if (test_mkdir_1 () == -1) { printf ("test_mkdir_1 FAILED\n"); failed++; } - printf (" 29/ 49 test_mkdir_p_0\n"); + printf (" 26/%3d test_mkdir_p_0\n", nr_tests); if (test_mkdir_p_0 () == -1) { printf ("test_mkdir_p_0 FAILED\n"); failed++; } - printf (" 30/ 49 test_mkdir_p_1\n"); + printf (" 27/%3d test_mkdir_p_1\n", nr_tests); if (test_mkdir_p_1 () == -1) { printf ("test_mkdir_p_1 FAILED\n"); failed++; } - printf (" 31/ 49 test_mkdir_p_2\n"); + printf (" 28/%3d test_mkdir_p_2\n", nr_tests); if (test_mkdir_p_2 () == -1) { printf ("test_mkdir_p_2 FAILED\n"); failed++; } - printf (" 32/ 49 test_exists_0\n"); + printf (" 29/%3d test_exists_0\n", nr_tests); if (test_exists_0 () == -1) { printf ("test_exists_0 FAILED\n"); failed++; } - printf (" 33/ 49 test_exists_1\n"); + printf (" 30/%3d test_exists_1\n", nr_tests); if (test_exists_1 () == -1) { printf ("test_exists_1 FAILED\n"); failed++; } - printf (" 34/ 49 test_is_file_0\n"); + printf (" 31/%3d test_is_file_0\n", nr_tests); if (test_is_file_0 () == -1) { printf ("test_is_file_0 FAILED\n"); failed++; } - printf (" 35/ 49 test_is_file_1\n"); + printf (" 32/%3d test_is_file_1\n", nr_tests); if (test_is_file_1 () == -1) { printf ("test_is_file_1 FAILED\n"); failed++; } - printf (" 36/ 49 test_is_dir_0\n"); + printf (" 33/%3d test_is_dir_0\n", nr_tests); if (test_is_dir_0 () == -1) { printf ("test_is_dir_0 FAILED\n"); failed++; } - printf (" 37/ 49 test_is_dir_1\n"); + printf (" 34/%3d test_is_dir_1\n", nr_tests); if (test_is_dir_1 () == -1) { printf ("test_is_dir_1 FAILED\n"); failed++; } - printf (" 38/ 49 test_pvcreate_0\n"); + printf (" 35/%3d test_pvcreate_0\n", nr_tests); if (test_pvcreate_0 () == -1) { printf ("test_pvcreate_0 FAILED\n"); failed++; } - printf (" 39/ 49 test_vgcreate_0\n"); + printf (" 36/%3d test_vgcreate_0\n", nr_tests); if (test_vgcreate_0 () == -1) { printf ("test_vgcreate_0 FAILED\n"); failed++; } - printf (" 40/ 49 test_lvcreate_0\n"); + printf (" 37/%3d test_lvcreate_0\n", nr_tests); if (test_lvcreate_0 () == -1) { printf ("test_lvcreate_0 FAILED\n"); failed++; } - printf (" 41/ 49 test_mkfs_0\n"); + printf (" 38/%3d test_mkfs_0\n", nr_tests); if (test_mkfs_0 () == -1) { printf ("test_mkfs_0 FAILED\n"); failed++; } - printf (" 42/ 49 test_write_file_0\n"); + printf (" 39/%3d test_write_file_0\n", nr_tests); if (test_write_file_0 () == -1) { printf ("test_write_file_0 FAILED\n"); failed++; } - printf (" 43/ 49 test_umount_0\n"); + printf (" 40/%3d test_umount_0\n", nr_tests); if (test_umount_0 () == -1) { printf ("test_umount_0 FAILED\n"); failed++; } - printf (" 44/ 49 test_umount_1\n"); + printf (" 41/%3d test_umount_1\n", nr_tests); if (test_umount_1 () == -1) { printf ("test_umount_1 FAILED\n"); failed++; } - printf (" 45/ 49 test_mounts_0\n"); + printf (" 42/%3d test_mounts_0\n", nr_tests); if (test_mounts_0 () == -1) { printf ("test_mounts_0 FAILED\n"); failed++; } - printf (" 46/ 49 test_umount_all_0\n"); + printf (" 43/%3d test_umount_all_0\n", nr_tests); if (test_umount_all_0 () == -1) { printf ("test_umount_all_0 FAILED\n"); failed++; } - printf (" 47/ 49 test_file_0\n"); + printf (" 44/%3d test_file_0\n", nr_tests); if (test_file_0 () == -1) { printf ("test_file_0 FAILED\n"); failed++; } - printf (" 48/ 49 test_file_1\n"); + printf (" 45/%3d test_file_1\n", nr_tests); if (test_file_1 () == -1) { printf ("test_file_1 FAILED\n"); failed++; } - printf (" 49/ 49 test_file_2\n"); + printf (" 46/%3d test_file_2\n", nr_tests); if (test_file_2 () == -1) { printf ("test_file_2 FAILED\n"); failed++; } + printf (" 47/%3d test_stat_0\n", nr_tests); + if (test_stat_0 () == -1) { + printf ("test_stat_0 FAILED\n"); + failed++; + } + printf (" 48/%3d test_lstat_0\n", nr_tests); + if (test_lstat_0 () == -1) { + printf ("test_lstat_0 FAILED\n"); + failed++; + } + printf (" 49/%3d test_statvfs_0\n", nr_tests); + if (test_statvfs_0 () == -1) { + printf ("test_statvfs_0 FAILED\n"); + failed++; + } guestfs_close (g); snprintf (buf, sizeof buf, "%s/test1.img", srcdir); @@ -4155,7 +4076,7 @@ int main (int argc, char *argv[]) unlink (buf); if (failed > 0) { - printf ("***** %d / 49 tests FAILED *****\n", failed); + printf ("***** %d / %d tests FAILED *****\n", failed, nr_tests); exit (1); } -- 1.8.3.1