Don't stash strings in the handle.
[libguestfs.git] / fish / cmds.c
index f0da329..1e442d8 100644 (file)
@@ -63,10 +63,17 @@ void list_commands (void)
   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", "cp", "copy a file");
+  printf ("%-20s %s\n", "cp-a", "copy a file or directory recursively");
   printf ("%-20s %s\n", "debug", "debugging and internals");
+  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");
+  printf ("%-20s %s\n", "get-append", "get the additional kernel options");
   printf ("%-20s %s\n", "get-autosync", "get autosync mode");
   printf ("%-20s %s\n", "get-e2label", "get the ext2/3/4 filesystem label");
   printf ("%-20s %s\n", "get-e2uuid", "get the ext2/3/4 filesystem UUID");
@@ -74,6 +81,8 @@ void list_commands (void)
   printf ("%-20s %s\n", "get-qemu", "get the qemu binary");
   printf ("%-20s %s\n", "get-state", "get the current state");
   printf ("%-20s %s\n", "get-verbose", "get verbose mode");
+  printf ("%-20s %s\n", "grub-install", "install GRUB");
+  printf ("%-20s %s\n", "hexdump", "dump a file in hexadecimal");
   printf ("%-20s %s\n", "is-busy", "is busy processing a command");
   printf ("%-20s %s\n", "is-config", "is in configuration state");
   printf ("%-20s %s\n", "is-dir", "test if file exists");
@@ -100,6 +109,8 @@ void list_commands (void)
   printf ("%-20s %s\n", "mount-ro", "mount a guest disk, read-only");
   printf ("%-20s %s\n", "mount-vfs", "mount a guest disk with mount options and vfstype");
   printf ("%-20s %s\n", "mounts", "show mounted filesystems");
+  printf ("%-20s %s\n", "mv", "move a file");
+  printf ("%-20s %s\n", "ping-daemon", "ping the guest daemon");
   printf ("%-20s %s\n", "pvcreate", "create an LVM physical volume");
   printf ("%-20s %s\n", "pvremove", "remove an LVM physical volume");
   printf ("%-20s %s\n", "pvs", "list the LVM physical volumes (PVs)");
@@ -108,6 +119,7 @@ void list_commands (void)
   printf ("%-20s %s\n", "rm", "remove a file");
   printf ("%-20s %s\n", "rm-rf", "remove a file or directory recursively");
   printf ("%-20s %s\n", "rmdir", "remove a directory");
+  printf ("%-20s %s\n", "set-append", "add options to kernel command line");
   printf ("%-20s %s\n", "set-autosync", "set autosync mode");
   printf ("%-20s %s\n", "set-e2label", "set the ext2/3/4 filesystem label");
   printf ("%-20s %s\n", "set-e2uuid", "set the ext2/3/4 filesystem UUID");
@@ -117,6 +129,8 @@ void list_commands (void)
   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", "strings", "print the printable strings in a file");
+  printf ("%-20s %s\n", "strings-e", "print the printable strings in a file");
   printf ("%-20s %s\n", "sync", "sync disks, writes are flushed through to the disk image");
   printf ("%-20s %s\n", "tar-in", "unpack tarfile to directory");
   printf ("%-20s %s\n", "tar-out", "pack directory into tarfile");
@@ -132,6 +146,7 @@ void list_commands (void)
   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", "zero", "write zeroes to the device");
   printf ("    Use -h <cmd> / help <cmd> to show detailed help for a command.\n");
 }
 
@@ -153,19 +168,25 @@ void display_command (const char *cmd)
     pod2text ("config - add qemu parameters", " config <qemuparam> <qemuvalue>\n\nThis can be used to add arbitrary qemu command line parameters\nof the form C<-param value>.  Actually it's not quite arbitrary - we\nprevent you from setting some parameters which would interfere with\nparameters that we use.\n\nThe first character of C<param> string must be a C<-> (dash).\n\nC<value> can be NULL.");
   else
   if (strcasecmp (cmd, "set_qemu") == 0 || strcasecmp (cmd, "set-qemu") == 0 || strcasecmp (cmd, "qemu") == 0)
-    pod2text ("set-qemu - set the qemu binary", " set-qemu <qemu>\n\nSet the qemu binary that we will use.\n\nThe default is chosen when the library was compiled by the\nconfigure script.\n\nYou can also override this by setting the C<LIBGUESTFS_QEMU>\nenvironment variable.\n\nThe string C<qemu> is stashed in the libguestfs handle, so the caller\nmust make sure it remains valid for the lifetime of the handle.\n\nSetting C<qemu> to C<NULL> restores the default qemu binary.\n\nYou can use 'qemu' as an alias for this command.");
+    pod2text ("set-qemu - set the qemu binary", " set-qemu <qemu>\n\nSet the qemu binary that we will use.\n\nThe default is chosen when the library was compiled by the\nconfigure script.\n\nYou can also override this by setting the C<LIBGUESTFS_QEMU>\nenvironment variable.\n\nSetting C<qemu> to C<NULL> restores the default qemu binary.\n\nYou can use 'qemu' as an alias for this command.");
   else
   if (strcasecmp (cmd, "get_qemu") == 0 || strcasecmp (cmd, "get-qemu") == 0)
     pod2text ("get-qemu - get the qemu binary", " get-qemu\n\nReturn the current qemu binary.\n\nThis is always non-NULL.  If it wasn't set already, then this will\nreturn the default qemu binary name.");
   else
   if (strcasecmp (cmd, "set_path") == 0 || strcasecmp (cmd, "set-path") == 0 || strcasecmp (cmd, "path") == 0)
-    pod2text ("set-path - set the search path", " set-path <path>\n\nSet the path that libguestfs searches for kernel and initrd.img.\n\nThe default is C<$libdir/guestfs> unless overridden by setting\nC<LIBGUESTFS_PATH> environment variable.\n\nThe string C<path> is stashed in the libguestfs handle, so the caller\nmust make sure it remains valid for the lifetime of the handle.\n\nSetting C<path> to C<NULL> restores the default path.\n\nYou can use 'path' as an alias for this command.");
+    pod2text ("set-path - set the search path", " set-path <path>\n\nSet the path that libguestfs searches for kernel and initrd.img.\n\nThe default is C<$libdir/guestfs> unless overridden by setting\nC<LIBGUESTFS_PATH> environment variable.\n\nSetting C<path> to C<NULL> restores the default path.\n\nYou can use 'path' as an alias for this command.");
   else
   if (strcasecmp (cmd, "get_path") == 0 || strcasecmp (cmd, "get-path") == 0)
     pod2text ("get-path - get the search path", " get-path\n\nReturn the current search path.\n\nThis is always non-NULL.  If it wasn't set already, then this will\nreturn the default path.");
   else
+  if (strcasecmp (cmd, "set_append") == 0 || strcasecmp (cmd, "set-append") == 0 || strcasecmp (cmd, "append") == 0)
+    pod2text ("set-append - add options to kernel command line", " set-append <append>\n\nThis function is used to add additional options to the\nguest kernel command line.\n\nThe default is C<NULL> unless overridden by setting\nC<LIBGUESTFS_APPEND> environment variable.\n\nSetting C<append> to C<NULL> means I<no> additional options\nare passed (libguestfs always adds a few of its own).\n\nYou can use 'append' as an alias for this command.");
+  else
+  if (strcasecmp (cmd, "get_append") == 0 || strcasecmp (cmd, "get-append") == 0)
+    pod2text ("get-append - get the additional kernel options", " get-append\n\nReturn the additional kernel options which are added to the\nguest kernel command line.\n\nIf C<NULL> then no options are added.");
+  else
   if (strcasecmp (cmd, "set_autosync") == 0 || strcasecmp (cmd, "set-autosync") == 0 || strcasecmp (cmd, "autosync") == 0)
-    pod2text ("set-autosync - set autosync mode", " set-autosync <autosync>\n\nIf C<autosync> is true, this enables autosync.  Libguestfs will make a\nbest effort attempt to run C<sync> when the handle is closed\n(also if the program exits without closing handles).\n\nYou can use 'autosync' as an alias for this command.");
+    pod2text ("set-autosync - set autosync mode", " set-autosync <autosync>\n\nIf C<autosync> is true, this enables autosync.  Libguestfs will make a\nbest effort attempt to run C<umount_all> followed by\nC<sync> when the handle is closed\n(also if the program exits without closing handles).\n\nThis is disabled by default (except in guestfish where it is\nenabled by default).\n\nYou can use 'autosync' as an alias for this command.");
   else
   if (strcasecmp (cmd, "get_autosync") == 0 || strcasecmp (cmd, "get-autosync") == 0)
     pod2text ("get-autosync - get autosync mode", " get-autosync\n\nGet the autosync flag.");
@@ -315,13 +336,13 @@ void display_command (const char *cmd)
     pod2text ("lvcreate - create an LVM volume group", " lvcreate <logvol> <volgroup> <mbytes>\n\nThis creates an LVM volume group called C<logvol>\non the volume group C<volgroup>, with C<size> megabytes.");
   else
   if (strcasecmp (cmd, "mkfs") == 0)
-    pod2text ("mkfs - make a filesystem", " mkfs <fstype> <device>\n\nThis creates a filesystem on C<device> (usually a partition\nof LVM logical volume).  The filesystem type is C<fstype>, for\nexample C<ext3>.");
+    pod2text ("mkfs - make a filesystem", " mkfs <fstype> <device>\n\nThis creates a filesystem on C<device> (usually a partition\nor LVM logical volume).  The filesystem type is C<fstype>, for\nexample C<ext3>.");
   else
   if (strcasecmp (cmd, "sfdisk") == 0)
     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\nI<NB.> Owing to a bug, writing content containing ASCII NUL\ncharacters does I<not> work, even if the length is specified.\nWe hope to resolve this bug in a future version.  In the meantime\nuse C<upload>.\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.");
@@ -339,10 +360,10 @@ void display_command (const char *cmd)
     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.");
+    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 return value is anything printed to I<stdout> by\nthe command.\n\nIf the command returns a non-zero exit status, then\nthis function returns an error message.  The error message\nstring is the content of I<stderr> from the command.\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.\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, "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.");
+    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.\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, "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.");
@@ -440,6 +461,45 @@ void display_command (const char *cmd)
   if (strcasecmp (cmd, "get_e2uuid") == 0 || strcasecmp (cmd, "get-e2uuid") == 0)
     pod2text ("get-e2uuid - get the ext2/3/4 filesystem UUID", " get-e2uuid <device>\n\nThis returns the ext2/3/4 filesystem UUID of the filesystem on\nC<device>.");
   else
+  if (strcasecmp (cmd, "fsck") == 0)
+    pod2text ("fsck - run the filesystem checker", " fsck <fstype> <device>\n\nThis runs the filesystem checker (fsck) on C<device> which\nshould have filesystem type C<fstype>.\n\nThe returned integer is the status.  See L<fsck(8)> for the\nlist of status codes from C<fsck>.\n\nNotes:\n\n=over 4\n\n=item *\n\nMultiple status codes can be summed together.\n\n=item *\n\nA non-zero return code can mean \"success\", for example if\nerrors have been corrected on the filesystem.\n\n=item *\n\nChecking or repairing NTFS volumes is not supported\n(by linux-ntfs).\n\n=back\n\nThis command is entirely equivalent to running C<fsck -a -t fstype device>.");
+  else
+  if (strcasecmp (cmd, "zero") == 0)
+    pod2text ("zero - write zeroes to the device", " zero <device>\n\nThis command writes zeroes over the first few blocks of C<device>.\n\nHow many blocks are zeroed isn't specified (but it's I<not> enough\nto securely wipe the device).  It should be sufficient to remove\nany partition tables, filesystem superblocks and so on.");
+  else
+  if (strcasecmp (cmd, "grub_install") == 0 || strcasecmp (cmd, "grub-install") == 0)
+    pod2text ("grub-install - install GRUB", " grub-install <root> <device>\n\nThis command installs GRUB (the Grand Unified Bootloader) on\nC<device>, with the root directory being C<root>.");
+  else
+  if (strcasecmp (cmd, "cp") == 0)
+    pod2text ("cp - copy a file", " cp <src> <dest>\n\nThis copies a file from C<src> to C<dest> where C<dest> is\neither a destination filename or destination directory.");
+  else
+  if (strcasecmp (cmd, "cp_a") == 0 || strcasecmp (cmd, "cp-a") == 0)
+    pod2text ("cp-a - copy a file or directory recursively", " cp-a <src> <dest>\n\nThis copies a file or directory from C<src> to C<dest>\nrecursively using the C<cp -a> command.");
+  else
+  if (strcasecmp (cmd, "mv") == 0)
+    pod2text ("mv - move a file", " mv <src> <dest>\n\nThis moves a file from C<src> to C<dest> where C<dest> is\neither a destination filename or destination directory.");
+  else
+  if (strcasecmp (cmd, "drop_caches") == 0 || strcasecmp (cmd, "drop-caches") == 0)
+    pod2text ("drop-caches - drop kernel page cache, dentries and inodes", " drop-caches <whattodrop>\n\nThis instructs the guest kernel to drop its page cache,\nand/or dentries and inode caches.  The parameter C<whattodrop>\ntells the kernel what precisely to drop, see\nL<http://linux-mm.org/Drop_Caches>\n\nSetting C<whattodrop> to 3 should drop everything.\n\nThis automatically calls L<sync(2)> before the operation,\nso that the maximum guest memory is freed.");
+  else
+  if (strcasecmp (cmd, "dmesg") == 0)
+    pod2text ("dmesg - return kernel messages", " dmesg\n\nThis returns the kernel messages (C<dmesg> output) from\nthe guest kernel.  This is sometimes useful for extended\ndebugging of problems.\n\nAnother way to get the same information is to enable\nverbose messages with C<set_verbose> or by setting\nthe environment variable C<LIBGUESTFS_DEBUG=1> before\nrunning the program.");
+  else
+  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
+  if (strcasecmp (cmd, "strings") == 0)
+    pod2text ("strings - print the printable strings in a file", " strings <path>\n\nThis runs the L<strings(1)> command on a file and returns\nthe list of printable strings found.\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, "strings_e") == 0 || strcasecmp (cmd, "strings-e") == 0)
+    pod2text ("strings-e - print the printable strings in a file", " strings-e <encoding> <path>\n\nThis is like the C<strings> command, but allows you to\nspecify the encoding.\n\nSee the L<strings(1)> manpage for the full list of encodings.\n\nCommonly useful encodings are C<l> (lower case L) which will\nshow strings inside Windows/x86 files.\n\nThe returned strings are transcoded to UTF-8.\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, "hexdump") == 0)
+    pod2text ("hexdump - dump a file in hexadecimal", " hexdump <path>\n\nThis runs C<hexdump -C> on the given C<path>.  The result is\nthe human-readable, canonical hex dump of the file.\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
     display_builtin_command (cmd);
 }
 
@@ -701,6 +761,34 @@ static int run_get_path (const char *cmd, int argc, char *argv[])
   return 0;
 }
 
+static int run_set_append (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  const char *append;
+  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;
+  }
+  append = argv[0];
+  r = guestfs_set_append (g, append);
+  return r;
+}
+
+static int run_get_append (const char *cmd, int argc, char *argv[])
+{
+  const char *r;
+  if (argc != 0) {
+    fprintf (stderr, "%s should have 0 parameter(s)\n", cmd);
+    fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+    return -1;
+  }
+  r = guestfs_get_append (g);
+  if (r == NULL) return -1;
+  printf ("%s\n", r);
+  return 0;
+}
+
 static int run_set_autosync (const char *cmd, int argc, char *argv[])
 {
   int r;
@@ -2142,6 +2230,214 @@ static int run_get_e2uuid (const char *cmd, int argc, char *argv[])
   return 0;
 }
 
+static int run_fsck (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  const char *fstype;
+  const char *device;
+  if (argc != 2) {
+    fprintf (stderr, "%s should have 2 parameter(s)\n", cmd);
+    fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+    return -1;
+  }
+  fstype = argv[0];
+  device = argv[1];
+  r = guestfs_fsck (g, fstype, device);
+  if (r == -1) return -1;
+  printf ("%d\n", r);
+  return 0;
+}
+
+static int run_zero (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_zero (g, device);
+  return r;
+}
+
+static int run_grub_install (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  const char *root;
+  const char *device;
+  if (argc != 2) {
+    fprintf (stderr, "%s should have 2 parameter(s)\n", cmd);
+    fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+    return -1;
+  }
+  root = argv[0];
+  device = argv[1];
+  r = guestfs_grub_install (g, root, device);
+  return r;
+}
+
+static int run_cp (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  const char *src;
+  const char *dest;
+  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;
+  }
+  src = argv[0];
+  dest = argv[1];
+  r = guestfs_cp (g, src, dest);
+  return r;
+}
+
+static int run_cp_a (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  const char *src;
+  const char *dest;
+  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;
+  }
+  src = argv[0];
+  dest = argv[1];
+  r = guestfs_cp_a (g, src, dest);
+  return r;
+}
+
+static int run_mv (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  const char *src;
+  const char *dest;
+  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;
+  }
+  src = argv[0];
+  dest = argv[1];
+  r = guestfs_mv (g, src, dest);
+  return r;
+}
+
+static int run_drop_caches (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  int whattodrop;
+  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;
+  }
+  whattodrop = atoi (argv[0]);
+  r = guestfs_drop_caches (g, whattodrop);
+  return r;
+}
+
+static int run_dmesg (const char *cmd, int argc, char *argv[])
+{
+  char *r;
+  if (argc != 0) {
+    fprintf (stderr, "%s should have 0 parameter(s)\n", cmd);
+    fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+    return -1;
+  }
+  r = guestfs_dmesg (g);
+  if (r == NULL) return -1;
+  printf ("%s\n", r);
+  free (r);
+  return 0;
+}
+
+static int run_ping_daemon (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  if (argc != 0) {
+    fprintf (stderr, "%s should have 0 parameter(s)\n", cmd);
+    fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+    return -1;
+  }
+  r = guestfs_ping_daemon (g);
+  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;
+}
+
+static int run_strings (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_strings (g, path);
+  if (r == NULL) return -1;
+  print_strings (r);
+  free_strings (r);
+  return 0;
+}
+
+static int run_strings_e (const char *cmd, int argc, char *argv[])
+{
+  char **r;
+  const char *encoding;
+  const char *path;
+  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;
+  }
+  encoding = argv[0];
+  path = argv[1];
+  r = guestfs_strings_e (g, encoding, path);
+  if (r == NULL) return -1;
+  print_strings (r);
+  free_strings (r);
+  return 0;
+}
+
+static int run_hexdump (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_hexdump (g, path);
+  if (r == NULL) return -1;
+  printf ("%s\n", r);
+  free (r);
+  return 0;
+}
+
 int run_action (const char *cmd, int argc, char *argv[])
 {
   if (strcasecmp (cmd, "launch") == 0 || strcasecmp (cmd, "run") == 0)
@@ -2171,6 +2467,12 @@ int run_action (const char *cmd, int argc, char *argv[])
   if (strcasecmp (cmd, "get_path") == 0 || strcasecmp (cmd, "get-path") == 0)
     return run_get_path (cmd, argc, argv);
   else
+  if (strcasecmp (cmd, "set_append") == 0 || strcasecmp (cmd, "set-append") == 0 || strcasecmp (cmd, "append") == 0)
+    return run_set_append (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "get_append") == 0 || strcasecmp (cmd, "get-append") == 0)
+    return run_get_append (cmd, argc, argv);
+  else
   if (strcasecmp (cmd, "set_autosync") == 0 || strcasecmp (cmd, "set-autosync") == 0 || strcasecmp (cmd, "autosync") == 0)
     return run_set_autosync (cmd, argc, argv);
   else
@@ -2447,6 +2749,45 @@ int run_action (const char *cmd, int argc, char *argv[])
   if (strcasecmp (cmd, "get_e2uuid") == 0 || strcasecmp (cmd, "get-e2uuid") == 0)
     return run_get_e2uuid (cmd, argc, argv);
   else
+  if (strcasecmp (cmd, "fsck") == 0)
+    return run_fsck (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "zero") == 0)
+    return run_zero (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "grub_install") == 0 || strcasecmp (cmd, "grub-install") == 0)
+    return run_grub_install (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "cp") == 0)
+    return run_cp (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "cp_a") == 0 || strcasecmp (cmd, "cp-a") == 0)
+    return run_cp_a (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "mv") == 0)
+    return run_mv (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "drop_caches") == 0 || strcasecmp (cmd, "drop-caches") == 0)
+    return run_drop_caches (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "dmesg") == 0)
+    return run_dmesg (cmd, argc, argv);
+  else
+  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
+  if (strcasecmp (cmd, "strings") == 0)
+    return run_strings (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "strings_e") == 0 || strcasecmp (cmd, "strings-e") == 0)
+    return run_strings_e (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "hexdump") == 0)
+    return run_hexdump (cmd, argc, argv);
+  else
     {
       fprintf (stderr, "%s: unknown command\n", cmd);
       return -1;