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;
 }
 
   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)
 {
 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);
     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
   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",
   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) */
           "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"));
               "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"
   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[]);
 
 /* 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[]);
 
 /* 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.
 
 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...
 =head2 time
 
  time command args...