fish: handle some out-of-memory conditions
[libguestfs.git] / fish / cmds.c
index ed59804..fe59737 100644 (file)
@@ -83,6 +83,7 @@ void list_commands (void)
   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");
+  printf ("%-20s %s\n", "get-memsize", "get memory allocated to the qemu subprocess");
   printf ("%-20s %s\n", "get-path", "get the search path");
   printf ("%-20s %s\n", "get-qemu", "get the qemu binary");
   printf ("%-20s %s\n", "get-state", "get the current state");
@@ -115,8 +116,16 @@ void list_commands (void)
   printf ("%-20s %s\n", "mkdir", "create a directory");
   printf ("%-20s %s\n", "mkdir-p", "create a directory and parents");
   printf ("%-20s %s\n", "mkdtemp", "create a temporary directory");
+  printf ("%-20s %s\n", "mkfifo", "make FIFO (named pipe)");
   printf ("%-20s %s\n", "mkfs", "make a filesystem");
+  printf ("%-20s %s\n", "mknod", "make block, character or FIFO devices");
+  printf ("%-20s %s\n", "mknod-b", "make block device node");
+  printf ("%-20s %s\n", "mknod-c", "make char device node");
+  printf ("%-20s %s\n", "mkswap", "create a swap partition");
+  printf ("%-20s %s\n", "mkswap-L", "create a swap partition with a label");
+  printf ("%-20s %s\n", "mkswap-U", "create a swap partition with an explicit UUID");
   printf ("%-20s %s\n", "mount", "mount a guest disk at a position in the filesystem");
+  printf ("%-20s %s\n", "mount-loop", "mount a file using the loop device");
   printf ("%-20s %s\n", "mount-options", "mount a guest disk with mount options");
   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");
@@ -141,6 +150,7 @@ void list_commands (void)
   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");
+  printf ("%-20s %s\n", "set-memsize", "set memory allocated to the qemu subprocess");
   printf ("%-20s %s\n", "set-path", "set the search path");
   printf ("%-20s %s\n", "set-qemu", "set the qemu binary");
   printf ("%-20s %s\n", "set-verbose", "set verbose mode");
@@ -165,6 +175,7 @@ void list_commands (void)
   printf ("%-20s %s\n", "tgz-out", "pack directory into compressed tarball");
   printf ("%-20s %s\n", "touch", "update file timestamps or create a new file");
   printf ("%-20s %s\n", "tune2fs-l", "get ext2/ext3/ext4 superblock details");
+  printf ("%-20s %s\n", "umask", "set file mode creation mask (umask)");
   printf ("%-20s %s\n", "umount", "unmount a filesystem");
   printf ("%-20s %s\n", "umount-all", "unmount all filesystems");
   printf ("%-20s %s\n", "upload", "upload a file from the local machine");
@@ -192,13 +203,13 @@ void display_command (const char *cmd)
     pod2text ("kill-subprocess - kill the qemu subprocess", " kill-subprocess\n\nThis kills the qemu subprocess.  You should never need to call this.");
   else
   if (strcasecmp (cmd, "add_drive") == 0 || strcasecmp (cmd, "add-drive") == 0 || strcasecmp (cmd, "add") == 0)
-    pod2text ("add-drive - add an image to examine or modify", " add-drive <filename>\n\nThis function adds a virtual machine disk image C<filename> to the\nguest.  The first time you call this function, the disk appears as IDE\ndisk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and\nso on.\n\nYou don't necessarily need to be root when using libguestfs.  However\nyou obviously do need sufficient permissions to access the filename\nfor whatever operations you want to perform (ie. read access if you\njust want to read the image or write access if you want to modify the\nimage).\n\nThis is equivalent to the qemu parameter C<-drive file=filename,cache=off>.\n\nNote that this call checks for the existence of C<filename>.  This\nstops you from specifying other types of drive which are supported\nby qemu such as C<nbd:> and C<http:> URLs.  To specify those, use\nthe general C<config> call instead.\n\nYou can use 'add' as an alias for this command.");
+    pod2text ("add-drive - add an image to examine or modify", " add-drive <filename>\n\nThis function adds a virtual machine disk image C<filename> to the\nguest.  The first time you call this function, the disk appears as IDE\ndisk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and\nso on.\n\nYou don't necessarily need to be root when using libguestfs.  However\nyou obviously do need sufficient permissions to access the filename\nfor whatever operations you want to perform (ie. read access if you\njust want to read the image or write access if you want to modify the\nimage).\n\nThis is equivalent to the qemu parameter\nC<-drive file=filename,cache=off,if=virtio>.\n\nNote that this call checks for the existence of C<filename>.  This\nstops you from specifying other types of drive which are supported\nby qemu such as C<nbd:> and C<http:> URLs.  To specify those, use\nthe general C<config> call instead.\n\nYou can use 'add' as an alias for this command.");
   else
   if (strcasecmp (cmd, "add_cdrom") == 0 || strcasecmp (cmd, "add-cdrom") == 0 || strcasecmp (cmd, "cdrom") == 0)
     pod2text ("add-cdrom - add a CD-ROM disk image to examine", " add-cdrom <filename>\n\nThis function adds a virtual CD-ROM disk image to the guest.\n\nThis is equivalent to the qemu parameter C<-cdrom filename>.\n\nNote that this call checks for the existence of C<filename>.  This\nstops you from specifying other types of drive which are supported\nby qemu such as C<nbd:> and C<http:> URLs.  To specify those, use\nthe general C<config> call instead.\n\nYou can use 'cdrom' as an alias for this command.");
   else
   if (strcasecmp (cmd, "add_drive_ro") == 0 || strcasecmp (cmd, "add-drive-ro") == 0 || strcasecmp (cmd, "add-ro") == 0)
-    pod2text ("add-drive-ro - add a drive in snapshot mode (read-only)", " add-drive-ro <filename>\n\nThis adds a drive in snapshot mode, making it effectively\nread-only.\n\nNote that writes to the device are allowed, and will be seen for\nthe duration of the guestfs handle, but they are written\nto a temporary file which is discarded as soon as the guestfs\nhandle is closed.  We don't currently have any method to enable\nchanges to be committed, although qemu can support this.\n\nThis is equivalent to the qemu parameter\nC<-drive file=filename,snapshot=on>.\n\nNote that this call checks for the existence of C<filename>.  This\nstops you from specifying other types of drive which are supported\nby qemu such as C<nbd:> and C<http:> URLs.  To specify those, use\nthe general C<config> call instead.\n\nYou can use 'add-ro' as an alias for this command.");
+    pod2text ("add-drive-ro - add a drive in snapshot mode (read-only)", " add-drive-ro <filename>\n\nThis adds a drive in snapshot mode, making it effectively\nread-only.\n\nNote that writes to the device are allowed, and will be seen for\nthe duration of the guestfs handle, but they are written\nto a temporary file which is discarded as soon as the guestfs\nhandle is closed.  We don't currently have any method to enable\nchanges to be committed, although qemu can support this.\n\nThis is equivalent to the qemu parameter\nC<-drive file=filename,snapshot=on,if=virtio>.\n\nNote that this call checks for the existence of C<filename>.  This\nstops you from specifying other types of drive which are supported\nby qemu such as C<nbd:> and C<http:> URLs.  To specify those, use\nthe general C<config> call instead.\n\nYou can use 'add-ro' as an alias for this command.");
   else
   if (strcasecmp (cmd, "config") == 0)
     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.");
@@ -248,6 +259,12 @@ void display_command (const char *cmd)
   if (strcasecmp (cmd, "get_state") == 0 || strcasecmp (cmd, "get-state") == 0)
     pod2text ("get-state - get the current state", " get-state\n\nThis returns the current state as an opaque integer.  This is\nonly useful for printing debug and internal error messages.\n\nFor more information on states, see L<guestfs(3)>.");
   else
+  if (strcasecmp (cmd, "set_memsize") == 0 || strcasecmp (cmd, "set-memsize") == 0 || strcasecmp (cmd, "memsize") == 0)
+    pod2text ("set-memsize - set memory allocated to the qemu subprocess", " set-memsize <memsize>\n\nThis sets the memory size in megabytes allocated to the\nqemu subprocess.  This only has any effect if called before\nC<launch>.\n\nYou can also change this by setting the environment\nvariable C<LIBGUESTFS_MEMSIZE> before the handle is\ncreated.\n\nFor more information on the architecture of libguestfs,\nsee L<guestfs(3)>.\n\nYou can use 'memsize' as an alias for this command.");
+  else
+  if (strcasecmp (cmd, "get_memsize") == 0 || strcasecmp (cmd, "get-memsize") == 0)
+    pod2text ("get-memsize - get memory allocated to the qemu subprocess", " get-memsize\n\nThis gets the memory size in megabytes allocated to the\nqemu subprocess.\n\nIf C<set_memsize> was not called\non this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,\nthen this returns the compiled-in default value for memsize.\n\nFor more information on the architecture of libguestfs,\nsee L<guestfs(3)>.");
+  else
   if (strcasecmp (cmd, "mount") == 0)
     pod2text ("mount - mount a guest disk at a position in the filesystem", " mount <device> <mountpoint>\n\nMount a guest disk at a position in the filesystem.  Block devices\nare named C</dev/sda>, C</dev/sdb> and so on, as they were added to\nthe guest.  If those block devices contain partitions, they will have\nthe usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style\nnames can be used.\n\nThe rules are the same as for L<mount(2)>:  A filesystem must\nfirst be mounted on C</> before others can be mounted.  Other\nfilesystems can only be mounted on directories which already\nexist.\n\nThe mounted filesystem is writable, if we have sufficient permissions\non the underlying device.\n\nThe filesystem options C<sync> and C<noatime> are set with this\ncall, in order to improve reliability.");
   else
@@ -632,6 +649,33 @@ void display_command (const char *cmd)
   if (strcasecmp (cmd, "initrd_list") == 0 || strcasecmp (cmd, "initrd-list") == 0)
     pod2text ("initrd-list - list files in an initrd", " initrd-list <path>\n\nThis command lists out files contained in an initrd.\n\nThe files are listed without any initial C</> character.  The\nfiles are listed in the order they appear (not necessarily\nalphabetical).  Directory names are listed as separate items.\n\nOld Linux kernels (2.4 and earlier) used a compressed ext2\nfilesystem as initrd.  We I<only> support the newer initramfs\nformat (compressed cpio files).");
   else
+  if (strcasecmp (cmd, "mount_loop") == 0 || strcasecmp (cmd, "mount-loop") == 0)
+    pod2text ("mount-loop - mount a file using the loop device", " mount-loop <file> <mountpoint>\n\nThis command lets you mount C<file> (a filesystem image\nin a file) on a mount point.  It is entirely equivalent to\nthe command C<mount -o loop file mountpoint>.");
+  else
+  if (strcasecmp (cmd, "mkswap") == 0)
+    pod2text ("mkswap - create a swap partition", " mkswap <device>\n\nCreate a swap partition on C<device>.");
+  else
+  if (strcasecmp (cmd, "mkswap_L") == 0 || strcasecmp (cmd, "mkswap-L") == 0)
+    pod2text ("mkswap-L - create a swap partition with a label", " mkswap-L <label> <device>\n\nCreate a swap partition on C<device> with label C<label>.");
+  else
+  if (strcasecmp (cmd, "mkswap_U") == 0 || strcasecmp (cmd, "mkswap-U") == 0)
+    pod2text ("mkswap-U - create a swap partition with an explicit UUID", " mkswap-U <uuid> <device>\n\nCreate a swap partition on C<device> with UUID C<uuid>.");
+  else
+  if (strcasecmp (cmd, "mknod") == 0)
+    pod2text ("mknod - make block, character or FIFO devices", " mknod <mode> <devmajor> <devminor> <path>\n\nThis call creates block or character special devices, or\nnamed pipes (FIFOs).\n\nThe C<mode> parameter should be the mode, using the standard\nconstants.  C<devmajor> and C<devminor> are the\ndevice major and minor numbers, only used when creating block\nand character special devices.");
+  else
+  if (strcasecmp (cmd, "mkfifo") == 0)
+    pod2text ("mkfifo - make FIFO (named pipe)", " mkfifo <mode> <path>\n\nThis call creates a FIFO (named pipe) called C<path> with\nmode C<mode>.  It is just a convenient wrapper around\nC<mknod>.");
+  else
+  if (strcasecmp (cmd, "mknod_b") == 0 || strcasecmp (cmd, "mknod-b") == 0)
+    pod2text ("mknod-b - make block device node", " mknod-b <mode> <devmajor> <devminor> <path>\n\nThis call creates a block device node called C<path> with\nmode C<mode> and device major/minor C<devmajor> and C<devminor>.\nIt is just a convenient wrapper around C<mknod>.");
+  else
+  if (strcasecmp (cmd, "mknod_c") == 0 || strcasecmp (cmd, "mknod-c") == 0)
+    pod2text ("mknod-c - make char device node", " mknod-c <mode> <devmajor> <devminor> <path>\n\nThis call creates a char device node called C<path> with\nmode C<mode> and device major/minor C<devmajor> and C<devminor>.\nIt is just a convenient wrapper around C<mknod>.");
+  else
+  if (strcasecmp (cmd, "umask") == 0)
+    pod2text ("umask - set file mode creation mask (umask)", " umask <mask>\n\nThis function sets the mask used for creating new files and\ndevice nodes to C<mask & 0777>.\n\nTypical umask values would be C<022> which creates new files\nwith permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and\nC<002> which creates new files with permissions like\n\"-rw-rw-r--\" or \"-rwxrwxr-x\".\n\nThe default umask is C<022>.  This is important because it\nmeans that directories and device nodes will be created with\nC<0644> or C<0755> mode even if you specify C<0777>.\n\nSee also L<umask(2)>, C<mknod>, C<mkdir>.\n\nThis call returns the previous umask.");
+  else
     display_builtin_command (cmd);
 }
 
@@ -1061,6 +1105,34 @@ static int run_get_state (const char *cmd, int argc, char *argv[])
   return 0;
 }
 
+static int run_set_memsize (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  int memsize;
+  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;
+  }
+  memsize = atoi (argv[0]);
+  r = guestfs_set_memsize (g, memsize);
+  return r;
+}
+
+static int run_get_memsize (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_get_memsize (g);
+  if (r == -1) return -1;
+  printf ("%d\n", r);
+  return 0;
+}
+
 static int run_mount (const char *cmd, int argc, char *argv[])
 {
   int r;
@@ -3103,6 +3175,160 @@ static int run_initrd_list (const char *cmd, int argc, char *argv[])
   return 0;
 }
 
+static int run_mount_loop (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  const char *file;
+  const char *mountpoint;
+  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;
+  }
+  file = argv[0];
+  mountpoint = argv[1];
+  r = guestfs_mount_loop (g, file, mountpoint);
+  return r;
+}
+
+static int run_mkswap (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_mkswap (g, device);
+  return r;
+}
+
+static int run_mkswap_L (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  const char *label;
+  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;
+  }
+  label = argv[0];
+  device = argv[1];
+  r = guestfs_mkswap_L (g, label, device);
+  return r;
+}
+
+static int run_mkswap_U (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  const char *uuid;
+  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;
+  }
+  uuid = argv[0];
+  device = argv[1];
+  r = guestfs_mkswap_U (g, uuid, device);
+  return r;
+}
+
+static int run_mknod (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  int mode;
+  int devmajor;
+  int devminor;
+  const char *path;
+  if (argc != 4) {
+    fprintf (stderr, "%s should have 4 parameter(s)\n", cmd);
+    fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+    return -1;
+  }
+  mode = atoi (argv[0]);
+  devmajor = atoi (argv[1]);
+  devminor = atoi (argv[2]);
+  path = argv[3];
+  r = guestfs_mknod (g, mode, devmajor, devminor, path);
+  return r;
+}
+
+static int run_mkfifo (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  int mode;
+  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;
+  }
+  mode = atoi (argv[0]);
+  path = argv[1];
+  r = guestfs_mkfifo (g, mode, path);
+  return r;
+}
+
+static int run_mknod_b (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  int mode;
+  int devmajor;
+  int devminor;
+  const char *path;
+  if (argc != 4) {
+    fprintf (stderr, "%s should have 4 parameter(s)\n", cmd);
+    fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+    return -1;
+  }
+  mode = atoi (argv[0]);
+  devmajor = atoi (argv[1]);
+  devminor = atoi (argv[2]);
+  path = argv[3];
+  r = guestfs_mknod_b (g, mode, devmajor, devminor, path);
+  return r;
+}
+
+static int run_mknod_c (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  int mode;
+  int devmajor;
+  int devminor;
+  const char *path;
+  if (argc != 4) {
+    fprintf (stderr, "%s should have 4 parameter(s)\n", cmd);
+    fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+    return -1;
+  }
+  mode = atoi (argv[0]);
+  devmajor = atoi (argv[1]);
+  devminor = atoi (argv[2]);
+  path = argv[3];
+  r = guestfs_mknod_c (g, mode, devmajor, devminor, path);
+  return r;
+}
+
+static int run_umask (const char *cmd, int argc, char *argv[])
+{
+  int r;
+  int mask;
+  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;
+  }
+  mask = atoi (argv[0]);
+  r = guestfs_umask (g, mask);
+  if (r == -1) return -1;
+  printf ("%d\n", r);
+  return 0;
+}
+
 int run_action (const char *cmd, int argc, char *argv[])
 {
   if (strcasecmp (cmd, "launch") == 0 || strcasecmp (cmd, "run") == 0)
@@ -3168,6 +3394,12 @@ int run_action (const char *cmd, int argc, char *argv[])
   if (strcasecmp (cmd, "get_state") == 0 || strcasecmp (cmd, "get-state") == 0)
     return run_get_state (cmd, argc, argv);
   else
+  if (strcasecmp (cmd, "set_memsize") == 0 || strcasecmp (cmd, "set-memsize") == 0 || strcasecmp (cmd, "memsize") == 0)
+    return run_set_memsize (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "get_memsize") == 0 || strcasecmp (cmd, "get-memsize") == 0)
+    return run_get_memsize (cmd, argc, argv);
+  else
   if (strcasecmp (cmd, "mount") == 0)
     return run_mount (cmd, argc, argv);
   else
@@ -3552,6 +3784,33 @@ int run_action (const char *cmd, int argc, char *argv[])
   if (strcasecmp (cmd, "initrd_list") == 0 || strcasecmp (cmd, "initrd-list") == 0)
     return run_initrd_list (cmd, argc, argv);
   else
+  if (strcasecmp (cmd, "mount_loop") == 0 || strcasecmp (cmd, "mount-loop") == 0)
+    return run_mount_loop (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "mkswap") == 0)
+    return run_mkswap (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "mkswap_L") == 0 || strcasecmp (cmd, "mkswap-L") == 0)
+    return run_mkswap_L (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "mkswap_U") == 0 || strcasecmp (cmd, "mkswap-U") == 0)
+    return run_mkswap_U (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "mknod") == 0)
+    return run_mknod (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "mkfifo") == 0)
+    return run_mkfifo (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "mknod_b") == 0 || strcasecmp (cmd, "mknod-b") == 0)
+    return run_mknod_b (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "mknod_c") == 0 || strcasecmp (cmd, "mknod-c") == 0)
+    return run_mknod_c (cmd, argc, argv);
+  else
+  if (strcasecmp (cmd, "umask") == 0)
+    return run_umask (cmd, argc, argv);
+  else
     {
       fprintf (stderr, "%s: unknown command\n", cmd);
       return -1;