fish: New command 'sparse', like 'alloc' but to generate sparse files.
authorRichard Jones <rjones@redhat.com>
Wed, 4 Nov 2009 17:42:03 +0000 (17:42 +0000)
committerRichard Jones <rjones@redhat.com>
Wed, 4 Nov 2009 17:42:03 +0000 (17:42 +0000)
With sparse you can make sparse files, which is fun because you
can experiment with really large devices:

  ><fs> sparse /tmp/test.img 100G
  ><fs> run
  ><fs> sfdiskM /dev/vda ,
  ><fs> mkfs ext2 /dev/vda1    # very long pause here ...
  ><fs> mount /dev/vda1 /

To see the real (ie. allocated) size of the sparse file, use the du
command, eg:

  ><fs> !du -h /tmp/test.img
  1.6G -rw-rw-r-- 1 rjones rjones 100G 2009-11-04 17:40 /tmp/test.img

fish/alloc.c
fish/fish.c
fish/fish.h
guestfish.pod

index a7d115a..e35c02f 100644 (file)
@@ -75,6 +75,60 @@ do_alloc (const char *cmd, int argc, char *argv[])
   return 0;
 }
 
+int
+do_sparse (const char *cmd, int argc, char *argv[])
+{
+  off_t size;
+  int fd;
+  char c = 0;
+
+  if (argc != 2) {
+    fprintf (stderr, _("use 'sparse file size' to create a sparse image\n"));
+    return -1;
+  }
+
+  if (parse_size (argv[1], &size) == -1)
+    return -1;
+
+  if (!guestfs_is_config (g)) {
+    fprintf (stderr, _("can't allocate or add disks after launching\n"));
+    return -1;
+  }
+
+  fd = open (argv[0], O_WRONLY|O_CREAT|O_NOCTTY|O_TRUNC, 0666);
+  if (fd == -1) {
+    perror (argv[0]);
+    return -1;
+  }
+
+  if (lseek (fd, size-1, SEEK_SET) == (off_t) -1) {
+    perror ("lseek");
+    close (fd);
+    unlink (argv[0]);
+    return -1;
+  }
+
+  if (write (fd, &c, 1) != 1) {
+    perror ("write");
+    close (fd);
+    unlink (argv[0]);
+    return -1;
+  }
+
+  if (close (fd) == -1) {
+    perror (argv[0]);
+    unlink (argv[0]);
+    return -1;
+  }
+
+  if (guestfs_add_drive (g, argv[0]) == -1) {
+    unlink (argv[0]);
+    return -1;
+  }
+
+  return 0;
+}
+
 static int
 parse_size (const char *str, off_t *size_rtn)
 {
index f699603..2dfdfb9 100644 (file)
@@ -874,6 +874,8 @@ issue_command (const char *cmd, char *argv[], const char *pipecmd)
     r = do_more (cmd, argc, argv);
   else if (strcasecmp (cmd, "reopen") == 0)
     r = do_reopen (cmd, argc, argv);
+  else if (strcasecmp (cmd, "sparse") == 0)
+    r = do_sparse (cmd, argc, argv);
   else if (strcasecmp (cmd, "time") == 0)
     r = do_time (cmd, argc, argv);
   else
@@ -927,6 +929,8 @@ list_builtin_commands (void)
   printf ("%-20s %s\n",
           "reopen", _("close and reopen libguestfs handle"));
   printf ("%-20s %s\n",
+          "sparse", _("allocate a sparse image file"));
+  printf ("%-20s %s\n",
           "time", _("measure time taken to run command"));
 
   /* actions are printed after this (see list_commands) */
@@ -1020,6 +1024,30 @@ display_builtin_command (const char *cmd)
               "Close and reopen the libguestfs handle.  It is not necessary to use\n"
               "this normally, because the handle is closed properly when guestfish\n"
               "exits.  However this is occasionally useful for testing.\n"));
+  else if (strcasecmp (cmd, "sparse") == 0)
+    printf (_("sparse - allocate a sparse image file\n"
+              "     sparse <filename> <size>\n"
+              "\n"
+              "    This creates an empty sparse file of the given size,\n"
+              "    and then adds so it can be further examined.\n"
+              "\n"
+              "    In all respects it works the same as the 'alloc'\n"
+              "    command, except that the image file is allocated\n"
+              "    sparsely, which means that disk blocks are not assigned\n"
+              "    to the file until they are needed.  Sparse disk files\n"
+              "    only use space when written to, but they are slower\n"
+              "    and there is a danger you could run out of real disk\n"
+              "    space during a write operation.\n"
+              "\n"
+              "    For more advanced image creation, see qemu-img utility.\n"
+              "\n"
+              "    Size can be specified (where <nn> means a number):\n"
+              "    <nn>             number of kilobytes\n"
+              "      eg: 1440       standard 3.5\" floppy\n"
+              "    <nn>K or <nn>KB  number of kilobytes\n"
+              "    <nn>M or <nn>MB  number of megabytes\n"
+              "    <nn>G or <nn>GB  number of gigabytes\n"
+              "    <nn>sects        number of 512 byte sectors\n"));
   else if (strcasecmp (cmd, "time") == 0)
     printf (_("time - measure time taken to run command\n"
               "    time <command> [<args> ...]\n"
index 8c5dba1..cdb3d63 100644 (file)
@@ -62,6 +62,7 @@ extern char *complete_dest_paths_generator (const char *text, int state);
 
 /* in alloc.c */
 extern int do_alloc (const char *cmd, int argc, char *argv[]);
+extern int do_sparse (const char *cmd, int argc, char *argv[]);
 
 /* in echo.c */
 extern int do_echo (const char *cmd, int argc, char *argv[]);
index b635419..7755cc6 100644 (file)
@@ -531,6 +531,43 @@ Close and reopen the libguestfs handle.  It is not necessary to use
 this normally, because the handle is closed properly when guestfish
 exits.  However this is occasionally useful for testing.
 
+=head2 sparse
+
+ sparse filename size
+
+This creates an empty sparse file of the given size, and then adds
+so it can be further examined.
+
+In all respects it works the same as the C<alloc> command, except that
+the image file is allocated sparsely, which means that disk blocks are
+not assigned to the file until they are needed.  Sparse disk files
+only use space when written to, but they are slower and there is a
+danger you could run out of real disk space during a write operation.
+
+For more advanced image creation, see L<qemu-img(1)> utility.
+
+Size can be specified (where C<nn> means a number):
+
+=over 4
+
+=item C<nn> or C<nn>K or C<nn>KB
+
+number of kilobytes, eg: C<1440> = standard 3.5in floppy
+
+=item C<nn>M or C<nn>MB
+
+number of megabytes
+
+=item C<nn>G or C<nn>GB
+
+number of gigabytes
+
+=item C<nn>sects
+
+number of 512 byte sectors
+
+=back
+
 =head2 time
 
  time command args...