Rewrite of main loop impl, start of FileIn/FileOut support.
[libguestfs.git] / fish / cmds.c
index 1ab9ea0..c197ece 100644 (file)
@@ -46,11 +46,24 @@ void list_commands (void)
   printf ("%-20s %s\n", "aug-rm", "remove an Augeas path");
   printf ("%-20s %s\n", "aug-save", "write all pending Augeas changes to disk");
   printf ("%-20s %s\n", "aug-set", "set Augeas path to value");
+  printf ("%-20s %s\n", "blockdev-flushbufs", "flush device buffers");
+  printf ("%-20s %s\n", "blockdev-getbsz", "get blocksize of block device");
+  printf ("%-20s %s\n", "blockdev-getro", "is block device set to read-only");
+  printf ("%-20s %s\n", "blockdev-getsize64", "get total size of device in bytes");
+  printf ("%-20s %s\n", "blockdev-getss", "get sectorsize of block device");
+  printf ("%-20s %s\n", "blockdev-getsz", "get total size of device in 512-byte sectors");
+  printf ("%-20s %s\n", "blockdev-rereadpt", "reread partition table");
+  printf ("%-20s %s\n", "blockdev-setbsz", "set blocksize of block device");
+  printf ("%-20s %s\n", "blockdev-setro", "set block device to read-only");
+  printf ("%-20s %s\n", "blockdev-setrw", "set block device to read-write");
   printf ("%-20s %s\n", "cat", "list the contents of a file");
   printf ("%-20s %s\n", "chmod", "change file mode");
   printf ("%-20s %s\n", "chown", "change file owner and group");
+  printf ("%-20s %s\n", "command", "run a command from the guest filesystem");
+  printf ("%-20s %s\n", "command-lines", "run a command, returning lines");
   printf ("%-20s %s\n", "config", "add qemu parameters");
   printf ("%-20s %s\n", "exists", "test if file or directory exists");
+  printf ("%-20s %s\n", "file", "determine file type");
   printf ("%-20s %s\n", "get-autosync", "get autosync mode");
   printf ("%-20s %s\n", "get-path", "get the search path");
   printf ("%-20s %s\n", "get-verbose", "get verbose mode");
@@ -62,6 +75,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)");
@@ -82,14 +96,17 @@ 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", "tune2fs-l", "get ext2/ext3 superblock details");
   printf ("%-20s %s\n", "umount", "unmount a filesystem");
   printf ("%-20s %s\n", "umount-all", "unmount all filesystems");
   printf ("%-20s %s\n", "vgcreate", "create an LVM volume group");
   printf ("%-20s %s\n", "vgs", "list the LVM volume groups (VGs)");
   printf ("%-20s %s\n", "vgs-full", "list the LVM volume groups (VGs)");
-  printf ("%-20s %s\n", "write-file", "Create a file");
+  printf ("%-20s %s\n", "write-file", "create a file");
   printf ("    Use -h <cmd> / help <cmd> to show detailed help for a command.\n");
 }
 
@@ -138,7 +155,7 @@ void display_command (const char *cmd)
     pod2text ("touch - update file timestamps or create a new file", " touch <path>\n\nTouch acts like the L<touch(1)> command.  It can be used to\nupdate the timestamps on a file, or, if the file does not exist,\nto create a new zero-length file.");
   else
   if (strcasecmp (cmd, "cat") == 0)
-    pod2text ("cat - list the contents of a file", " cat <path>\n\nReturn the contents of the file named C<path>.\n\nNote that this function cannot correctly handle binary files\n(specifically, files containing C<\\0> character which is treated\nas end of string).  For those you need to use the C<read_file>\nfunction which has a more complex interface.\n\nBecause of the message protocol, there is a transfer limit \nof somewhere between 2MB and 4MB.  To transfer large files you should use\nFTP.");
+    pod2text ("cat - list the contents of a file", " cat <path>\n\nReturn the contents of the file named C<path>.\n\nNote that this function cannot correctly handle binary files\n(specifically, files containing C<\\0> character which is treated\nas end of string).  For those you need to use the C<download>\nfunction which has a more complex interface.\n\nBecause of the message protocol, there is a transfer limit \nof somewhere between 2MB and 4MB.  To transfer large files you should use\nFTP.");
   else
   if (strcasecmp (cmd, "ll") == 0)
     pod2text ("ll - list the files in a directory (long format)", " ll <directory>\n\nList the files in C<directory> (relative to the root directory,\nthere is no cwd) in the format of 'ls -la'.\n\nThis command is mostly useful for interactive sessions.  It\nis I<not> intended that you try to parse the output string.");
@@ -258,7 +275,7 @@ void display_command (const char *cmd)
     pod2text ("sfdisk - create partitions on a block device", " sfdisk <device> <cyls> <heads> <sectors> <lines>\n\nThis is a direct interface to the L<sfdisk(8)> program for creating\npartitions on block devices.\n\nC<device> should be a block device, for example C</dev/sda>.\n\nC<cyls>, C<heads> and C<sectors> are the number of cylinders, heads\nand sectors on the device, which are passed directly to sfdisk as\nthe I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any\nof these, then the corresponding parameter is omitted.  Usually for\n'large' disks, you can just pass C<0> for these, but for small\n(floppy-sized) disks, sfdisk (or rather, the kernel) cannot work\nout the right geometry and you will need to tell it.\n\nC<lines> is a list of lines that we feed to C<sfdisk>.  For more\ninformation refer to the L<sfdisk(8)> manpage.\n\nTo create a single partition occupying the whole disk, you would\npass C<lines> as a single element list, when the single element being\nthe string C<,> (comma).\n\nB<This command is dangerous.  Without careful use you\ncan easily destroy all your data>.");
   else
   if (strcasecmp (cmd, "write_file") == 0 || strcasecmp (cmd, "write-file") == 0)
-    pod2text ("write-file - Create a file", " write-file <path> <content> <size>\n\nThis call creates a file called C<path>.  The contents of the\nfile is the string C<content> (which can contain any 8 bit data),\nwith length C<size>.\n\nAs a special case, if C<size> is C<0>\nthen the length is calculated using C<strlen> (so in this case\nthe content cannot contain embedded ASCII NULs).\n\nBecause of the message protocol, there is a transfer limit \nof somewhere between 2MB and 4MB.  To transfer large files you should use\nFTP.");
+    pod2text ("write-file - create a file", " write-file <path> <content> <size>\n\nThis call creates a file called C<path>.  The contents of the\nfile is the string C<content> (which can contain any 8 bit data),\nwith length C<size>.\n\nAs a special case, if C<size> is C<0>\nthen the length is calculated using C<strlen> (so in this case\nthe content cannot contain embedded ASCII NULs).\n\nBecause of the message protocol, there is a transfer limit \nof somewhere between 2MB and 4MB.  To transfer large files you should use\nFTP.");
   else
   if (strcasecmp (cmd, "umount") == 0 || strcasecmp (cmd, "unmount") == 0)
     pod2text ("umount - unmount a filesystem", " umount <pathordevice>\n\nThis unmounts the given filesystem.  The filesystem may be\nspecified either by its mountpoint (path) or the device which\ncontains the filesystem.\n\nYou can use 'unmount' as an alias for this command.");
@@ -272,6 +289,57 @@ void display_command (const char *cmd)
   if (strcasecmp (cmd, "lvm_remove_all") == 0 || strcasecmp (cmd, "lvm-remove-all") == 0)
     pod2text ("lvm-remove-all - remove all LVM LVs, VGs and PVs", " lvm-remove-all\n\nThis command removes all LVM logical volumes, volume groups\nand physical volumes.\n\nB<This command is dangerous.  Without careful use you\ncan easily destroy all your data>.");
   else
+  if (strcasecmp (cmd, "file") == 0)
+    pod2text ("file - determine file type", " file <path>\n\nThis call uses the standard L<file(1)> command to determine\nthe type or contents of the file.  This also works on devices,\nfor example to find out whether a partition contains a filesystem.\n\nThe exact command which runs is C<file -bsL path>.  Note in\nparticular that the filename is not prepended to the output\n(the C<-b> option).");
+  else
+  if (strcasecmp (cmd, "command") == 0)
+    pod2text ("command - run a command from the guest filesystem", " command <arguments>\n\nThis call runs a command from the guest filesystem.  The\nfilesystem must be mounted, and must contain a compatible\noperating system (ie. something Linux, with the same\nor compatible processor architecture).\n\nThe single parameter is an argv-style list of arguments.\nThe first element is the name of the program to run.\nSubsequent elements are parameters.  The list must be\nnon-empty (ie. must contain a program name).\n\nThe C<$PATH> environment variable will contain at least\nC</usr/bin> and C</bin>.  If you require a program from\nanother location, you should provide the full path in the\nfirst parameter.\n\nShared libraries and data files required by the program\nmust be available on filesystems which are mounted in the\ncorrect places.  It is the caller's responsibility to ensure\nall filesystems that are needed are mounted at the right\nlocations.");
+  else
+  if (strcasecmp (cmd, "command_lines") == 0 || strcasecmp (cmd, "command-lines") == 0)
+    pod2text ("command-lines - run a command, returning lines", " command-lines <arguments>\n\nThis is the same as C<command>, but splits the\nresult into a list of lines.");
+  else
+  if (strcasecmp (cmd, "stat") == 0)
+    pod2text ("stat - get file information", " stat <path>\n\nReturns file information for the given C<path>.\n\nThis is the same as the C<stat(2)> system call.");
+  else
+  if (strcasecmp (cmd, "lstat") == 0)
+    pod2text ("lstat - get file information for a symbolic link", " lstat <path>\n\nReturns file information for the given C<path>.\n\nThis is the same as C<stat> except that if C<path>\nis a symbolic link, then the link is stat-ed, not the file it\nrefers to.\n\nThis is the same as the C<lstat(2)> system call.");
+  else
+  if (strcasecmp (cmd, "statvfs") == 0)
+    pod2text ("statvfs - get file system statistics", " statvfs <path>\n\nReturns file system statistics for any mounted file system.\nC<path> 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<statvfs(2)> system call.");
+  else
+  if (strcasecmp (cmd, "tune2fs_l") == 0 || strcasecmp (cmd, "tune2fs-l") == 0)
+    pod2text ("tune2fs-l - get ext2/ext3 superblock details", " tune2fs-l <device>\n\nThis returns the contents of the ext2 or ext3 filesystem superblock\non C<device>.\n\nIt is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>\nmanpage for more details.  The list of fields returned isn't\nclearly defined, and depends on both the version of C<tune2fs>\nthat libguestfs was built against, and the filesystem itself.");
+  else
+  if (strcasecmp (cmd, "blockdev_setro") == 0 || strcasecmp (cmd, "blockdev-setro") == 0)
+    pod2text ("blockdev-setro - set block device to read-only", " blockdev-setro <device>\n\nSets the block device named C<device> to read-only.\n\nThis uses the L<blockdev(8)> command.");
+  else
+  if (strcasecmp (cmd, "blockdev_setrw") == 0 || strcasecmp (cmd, "blockdev-setrw") == 0)
+    pod2text ("blockdev-setrw - set block device to read-write", " blockdev-setrw <device>\n\nSets the block device named C<device> to read-write.\n\nThis uses the L<blockdev(8)> command.");
+  else
+  if (strcasecmp (cmd, "blockdev_getro") == 0 || strcasecmp (cmd, "blockdev-getro") == 0)
+    pod2text ("blockdev-getro - is block device set to read-only", " blockdev-getro <device>\n\nReturns a boolean indicating if the block device is read-only\n(true if read-only, false if not).\n\nThis uses the L<blockdev(8)> command.");
+  else
+  if (strcasecmp (cmd, "blockdev_getss") == 0 || strcasecmp (cmd, "blockdev-getss") == 0)
+    pod2text ("blockdev-getss - get sectorsize of block device", " blockdev-getss <device>\n\nThis returns the size of sectors on a block device.\nUsually 512, but can be larger for modern devices.\n\n(Note, this is not the size in sectors, use C<blockdev_getsz>\nfor that).\n\nThis uses the L<blockdev(8)> command.");
+  else
+  if (strcasecmp (cmd, "blockdev_getbsz") == 0 || strcasecmp (cmd, "blockdev-getbsz") == 0)
+    pod2text ("blockdev-getbsz - get blocksize of block device", " blockdev-getbsz <device>\n\nThis returns the block size of a device.\n\n(Note this is different from both I<size in blocks> and\nI<filesystem block size>).\n\nThis uses the L<blockdev(8)> command.");
+  else
+  if (strcasecmp (cmd, "blockdev_setbsz") == 0 || strcasecmp (cmd, "blockdev-setbsz") == 0)
+    pod2text ("blockdev-setbsz - set blocksize of block device", " blockdev-setbsz <device> <blocksize>\n\nThis sets the block size of a device.\n\n(Note this is different from both I<size in blocks> and\nI<filesystem block size>).\n\nThis uses the L<blockdev(8)> command.");
+  else
+  if (strcasecmp (cmd, "blockdev_getsz") == 0 || strcasecmp (cmd, "blockdev-getsz") == 0)
+    pod2text ("blockdev-getsz - get total size of device in 512-byte sectors", " blockdev-getsz <device>\n\nThis returns the size of the device in units of 512-byte sectors\n(even if the sectorsize isn't 512 bytes ... weird).\n\nSee also C<blockdev_getss> for the real sector size of\nthe device, and C<blockdev_getsize64> for the more\nuseful I<size in bytes>.\n\nThis uses the L<blockdev(8)> command.");
+  else
+  if (strcasecmp (cmd, "blockdev_getsize64") == 0 || strcasecmp (cmd, "blockdev-getsize64") == 0)
+    pod2text ("blockdev-getsize64 - get total size of device in bytes", " blockdev-getsize64 <device>\n\nThis returns the size of the device in bytes.\n\nSee also C<blockdev_getsz>.\n\nThis uses the L<blockdev(8)> command.");
+  else
+  if (strcasecmp (cmd, "blockdev_flushbufs") == 0 || strcasecmp (cmd, "blockdev-flushbufs") == 0)
+    pod2text ("blockdev-flushbufs - flush device buffers", " blockdev-flushbufs <device>\n\nThis tells the kernel to flush internal buffers associated\nwith C<device>.\n\nThis uses the L<blockdev(8)> command.");
+  else
+  if (strcasecmp (cmd, "blockdev_rereadpt") == 0 || strcasecmp (cmd, "blockdev-rereadpt") == 0)
+    pod2text ("blockdev-rereadpt - reread partition table", " blockdev-rereadpt <device>\n\nReread the partition table on C<device>.\n\nThis uses the L<blockdev(8)> command.");
+  else
     display_builtin_command (cmd);
 }
 
@@ -377,6 +445,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;
@@ -801,7 +901,7 @@ static int run_aug_defvar (const char *cmd, int argc, char *argv[])
   expr = strcmp (argv[1], "") != 0 ? argv[1] : NULL;
   r = guestfs_aug_defvar (g, name, expr);
   if (r == -1) return -1;
-  if (r) printf ("%d\n", r);
+  printf ("%d\n", r);
   return 0;
 }
 
@@ -890,7 +990,7 @@ static int run_aug_rm (const char *cmd, int argc, char *argv[])
   path = argv[0];
   r = guestfs_aug_rm (g, path);
   if (r == -1) return -1;
-  if (r) printf ("%d\n", r);
+  printf ("%d\n", r);
   return 0;
 }
 
@@ -1277,6 +1377,277 @@ static int run_lvm_remove_all (const char *cmd, int argc, char *argv[])
   return r;
 }
 
+static int run_file (const char *cmd, int argc, char *argv[])
+{
+  char *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_file (g, path);
+  if (r == NULL) return -1;
+  printf ("%s\n", r);
+  free (r);
+  return 0;
+}
+
+static int run_command (const char *cmd, int argc, char *argv[])
+{
+  char *r;
+  char **arguments;
+  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;
+  }
+  arguments = parse_string_list (argv[0]);
+  r = guestfs_command (g, arguments);
+  if (r == NULL) return -1;
+  printf ("%s\n", r);
+  free (r);
+  return 0;
+}
+
+static int run_command_lines (const char *cmd, int argc, char *argv[])
+{
+  char **r;
+  char **arguments;
+  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;
+  }
+  arguments = parse_string_list (argv[0]);
+  r = guestfs_command_lines (g, arguments);
+  if (r == NULL) return -1;
+  print_strings (r);
+  free_strings (r);
+  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;
+}
+
+static int run_tune2fs_l (const char *cmd, int argc, char *argv[])
+{
+  char **r;
+  const char *device;
+  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;
+  }
+  device = argv[0];
+  r = guestfs_tune2fs_l (g, device);
+  if (r == NULL) return -1;
+  print_table (r);
+  free_strings (r);
+  return 0;
+}
+
+static int run_blockdev_setro (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  const char *device;
+  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;
+  }
+  device = argv[0];
+  r = guestfs_blockdev_setro (g, device);
+  return r;
+}
+
+static int run_blockdev_setrw (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  const char *device;
+  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;
+  }
+  device = argv[0];
+  r = guestfs_blockdev_setrw (g, device);
+  return r;
+}
+
+static int run_blockdev_getro (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  const char *device;
+  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;
+  }
+  device = argv[0];
+  r = guestfs_blockdev_getro (g, device);
+  if (r == -1) return -1;
+  if (r) printf ("true\n"); else printf ("false\n");
+  return 0;
+}
+
+static int run_blockdev_getss (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  const char *device;
+  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;
+  }
+  device = argv[0];
+  r = guestfs_blockdev_getss (g, device);
+  if (r == -1) return -1;
+  printf ("%d\n", r);
+  return 0;
+}
+
+static int run_blockdev_getbsz (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  const char *device;
+  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;
+  }
+  device = argv[0];
+  r = guestfs_blockdev_getbsz (g, device);
+  if (r == -1) return -1;
+  printf ("%d\n", r);
+  return 0;
+}
+
+static int run_blockdev_setbsz (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  const char *device;
+  int blocksize;
+  if (argc != 2) {
+    fprintf (stderr, "%s should have 2 parameter(s)\n", cmd);
+    fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+    return -1;
+  }
+  device = argv[0];
+  blocksize = atoi (argv[1]);
+  r = guestfs_blockdev_setbsz (g, device, blocksize);
+  return r;
+}
+
+static int run_blockdev_getsz (const char *cmd, int argc, char *argv[])
+{
+  int64_t r;
+  const char *device;
+  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;
+  }
+  device = argv[0];
+  r = guestfs_blockdev_getsz (g, device);
+  if (r == -1) return -1;
+  printf ("%" PRIi64 "\n", r);
+  return 0;
+}
+
+static int run_blockdev_getsize64 (const char *cmd, int argc, char *argv[])
+{
+  int64_t r;
+  const char *device;
+  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;
+  }
+  device = argv[0];
+  r = guestfs_blockdev_getsize64 (g, device);
+  if (r == -1) return -1;
+  printf ("%" PRIi64 "\n", r);
+  return 0;
+}
+
+static int run_blockdev_flushbufs (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  const char *device;
+  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;
+  }
+  device = argv[0];
+  r = guestfs_blockdev_flushbufs (g, device);
+  return r;
+}
+
+static int run_blockdev_rereadpt (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  const char *device;
+  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;
+  }
+  device = argv[0];
+  r = guestfs_blockdev_rereadpt (g, device);
+  return r;
+}
+
 int run_action (const char *cmd, int argc, char *argv[])
 {
   if (strcasecmp (cmd, "launch") == 0 || strcasecmp (cmd, "run") == 0)
@@ -1456,6 +1827,57 @@ int run_action (const char *cmd, int argc, char *argv[])
   if (strcasecmp (cmd, "lvm_remove_all") == 0 || strcasecmp (cmd, "lvm-remove-all") == 0)
     return run_lvm_remove_all (cmd, argc, argv);
   else
+  if (strcasecmp (cmd, "file") == 0)
+    return run_file (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "command") == 0)
+    return run_command (cmd, argc, argv);
+  else
+  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
+  if (strcasecmp (cmd, "tune2fs_l") == 0 || strcasecmp (cmd, "tune2fs-l") == 0)
+    return run_tune2fs_l (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "blockdev_setro") == 0 || strcasecmp (cmd, "blockdev-setro") == 0)
+    return run_blockdev_setro (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "blockdev_setrw") == 0 || strcasecmp (cmd, "blockdev-setrw") == 0)
+    return run_blockdev_setrw (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "blockdev_getro") == 0 || strcasecmp (cmd, "blockdev-getro") == 0)
+    return run_blockdev_getro (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "blockdev_getss") == 0 || strcasecmp (cmd, "blockdev-getss") == 0)
+    return run_blockdev_getss (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "blockdev_getbsz") == 0 || strcasecmp (cmd, "blockdev-getbsz") == 0)
+    return run_blockdev_getbsz (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "blockdev_setbsz") == 0 || strcasecmp (cmd, "blockdev-setbsz") == 0)
+    return run_blockdev_setbsz (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "blockdev_getsz") == 0 || strcasecmp (cmd, "blockdev-getsz") == 0)
+    return run_blockdev_getsz (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "blockdev_getsize64") == 0 || strcasecmp (cmd, "blockdev-getsize64") == 0)
+    return run_blockdev_getsize64 (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "blockdev_flushbufs") == 0 || strcasecmp (cmd, "blockdev-flushbufs") == 0)
+    return run_blockdev_flushbufs (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "blockdev_rereadpt") == 0 || strcasecmp (cmd, "blockdev-rereadpt") == 0)
+    return run_blockdev_rereadpt (cmd, argc, argv);
+  else
     {
       fprintf (stderr, "%s: unknown command\n", cmd);
       return -1;