fish: Allow suffixes on number parameters (eg. 1M)
authorRichard Jones <rjones@redhat.com>
Fri, 21 May 2010 12:07:05 +0000 (13:07 +0100)
committerRichard Jones <rjones@redhat.com>
Fri, 21 May 2010 13:51:53 +0000 (14:51 +0100)
This small change uses the gnulib xstrtoll functionality to
enable suffixes on integer parameters in guestfish.  For example:

 truncate-size /file 1G

(previously you would have had to given the full number).

This also applies to the 'alloc' and 'sparse' commands (and
indirectly to the -N option).  The specification for these commands
has changed slightly, in that 'alloc foo 1MB' would now use SI
units, allocating 1000000 bytes instead of a true megabyte.  All
existing uses would use 'alloc foo 1M' which still allocates true
megabytes.

fish/alloc.c
fish/fish.c
fish/guestfish.pod
regressions/rhbz557655-expected.stderr
regressions/rhbz557655.sh
src/generator.ml

index f91c5bb..7533741 100644 (file)
@@ -26,6 +26,8 @@
 #include <inttypes.h>
 #include <errno.h>
 
+#include "xstrtol.h"
+
 #include "fish.h"
 
 int
@@ -145,30 +147,14 @@ alloc_disk (const char *filename, const char *size_str, int add, int sparse)
 static int
 parse_size (const char *str, off_t *size_rtn)
 {
-  uint64_t size;
-  char type;
-
-  /* Note that the parsing here is looser than what is specified in the
-   * help, but we may tighten it up in future so beware.
-   */
-  if (sscanf (str, "%"SCNu64"%c", &size, &type) == 2) {
-    switch (type) {
-    case 'k': case 'K': size *= 1024ULL; break;
-    case 'm': case 'M': size *= 1024ULL * 1024ULL; break;
-    case 'g': case 'G': size *= 1024ULL * 1024ULL * 1024ULL; break;
-    case 't': case 'T': size *= 1024ULL * 1024ULL * 1024ULL * 1024ULL; break;
-    case 'p': case 'P': size *= 1024ULL * 1024ULL * 1024ULL * 1024ULL * 1024ULL; break;
-    case 'e': case 'E': size *= 1024ULL * 1024ULL * 1024ULL * 1024ULL * 1024ULL * 1024ULL; break;
-    case 's': size *= 512; break;
-    default:
-      fprintf (stderr, _("could not parse size specification '%s'\n"), str);
-      return -1;
-    }
-  }
-  else if (sscanf (str, "%"SCNu64, &size) == 1)
-    size *= 1024ULL;
-  else {
-    fprintf (stderr, _("could not parse size specification '%s'\n"), str);
+  unsigned long long size;
+  strtol_error xerr;
+
+  xerr = xstrtoull (str, NULL, 0, &size, "0kKMGTPEZY");
+  if (xerr != LONGINT_OK) {
+    fprintf (stderr,
+             _("%s: invalid integer parameter (%s returned %d)\n"),
+             "alloc_disk", "xstrtoull", xerr);
     return -1;
   }
 
index a32ed4d..d38d1c1 100644 (file)
@@ -1069,16 +1069,8 @@ display_builtin_command (const char *cmd)
               "\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>T or <nn>TB  number of terabytes\n"
-              "    <nn>P or <nn>PB  number of petabytes\n"
-              "    <nn>E or <nn>EB  number of exabytes\n"
-              "    <nn>sects        number of 512 byte sectors\n"));
+              "    Size can be specified using standard suffixes, eg. '1M'.\n"
+              ));
   else if (STRCASEEQ (cmd, "echo"))
     printf (_("echo - display a line of text\n"
               "     echo [<params> ...]\n"
@@ -1168,16 +1160,8 @@ display_builtin_command (const char *cmd)
               "\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>T or <nn>TB  number of terabytes\n"
-              "    <nn>P or <nn>PB  number of petabytes\n"
-              "    <nn>E or <nn>EB  number of exabytes\n"
-              "    <nn>sects        number of 512 byte sectors\n"));
+              "    Size can be specified using standard suffixes, eg. '1M'.\n"
+              ));
   else if (STRCASEEQ (cmd, "time"))
     printf (_("time - measure time taken to run command\n"
               "    time <command> [<args> ...]\n"
index 274f1d4..a6d341e 100644 (file)
@@ -320,9 +320,97 @@ must be escaped with a backslash.
 
 =head1 NUMBERS
 
-Commands which take integers as parameters use the C convention which
-is to use C<0> to prefix an octal number or C<0x> to prefix a
-hexadecimal number.  For example:
+This section applies to all commands which can take integers
+as parameters.
+
+=head2 SIZE SUFFIX
+
+When the command takes a parameter measured in bytes, you can use one
+of the following suffixes to specify kilobytes, megabytes and larger
+sizes:
+
+=over 4
+
+=item B<k> or B<K> or B<KiB>
+
+The size in kilobytes (multiplied by 1024).
+
+=item B<KB>
+
+The size in SI 1000 byte units.
+
+=item B<M> or B<MiB>
+
+The size in megabytes (multiplied by 1048576).
+
+=item B<MB>
+
+The size in SI 1000000 byte units.
+
+=item B<G> or B<GiB>
+
+The size in gigabytes (multiplied by 2**30).
+
+=item B<GB>
+
+The size in SI 10**9 byte units.
+
+=item B<T> or B<TiB>
+
+The size in terabytes (multiplied by 2**40).
+
+=item B<TB>
+
+The size in SI 10**12 byte units.
+
+=item B<P> or B<PiB>
+
+The size in petabytes (multiplied by 2**50).
+
+=item B<PB>
+
+The size in SI 10**15 byte units.
+
+=item B<E> or B<EiB>
+
+The size in exabytes (multiplied by 2**60).
+
+=item B<EB>
+
+The size in SI 10**18 byte units.
+
+=item B<Z> or B<ZiB>
+
+The size in zettabytes (multiplied by 2**70).
+
+=item B<ZB>
+
+The size in SI 10**21 byte units.
+
+=item B<Y> or B<YiB>
+
+The size in yottabytes (multiplied by 2**80).
+
+=item B<YB>
+
+The size in SI 10**24 byte units.
+
+=back
+
+For example:
+
+ truncate-size /file 1G
+
+would truncate the file to 1 gigabyte.
+
+Be careful because a few commands take sizes in kilobytes or megabytes
+(eg. the parameter to L</memsize> is specified in megabytes already).
+Adding a suffix will probably not do what you expect.
+
+=head2 OCTAL AND HEXADECIMAL NUMBERS
+
+For specifying the radix (base) use the C convention: C<0> to prefix
+an octal number or C<0x> to prefix a hexadecimal number.  For example:
 
  1234      decimal number 1234
  02322     octal number, equivalent to decimal 1234
@@ -600,39 +688,7 @@ so it can be further examined.
 
 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>T or C<nn>TB
-
-number of terabytes
-
-=item C<nn>P or C<nn>PB
-
-number of petabytes
-
-=item C<nn>E or C<nn>EB
-
-number of exabytes
-
-=item C<nn>sects
-
-number of 512 byte sectors
-
-=back
+Size can be specified using standard suffixes, eg. C<1M>.
 
 =head2 echo
 
@@ -727,39 +783,7 @@ 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>T or C<nn>TB
-
-number of terabytes
-
-=item C<nn>P or C<nn>PB
-
-number of petabytes
-
-=item C<nn>E or C<nn>EB
-
-number of exabytes
-
-=item C<nn>sects
-
-number of 512 byte sectors
-
-=back
+Size can be specified using standard suffixes, eg. C<1M>.
 
 =head2 time
 
index c8e02f5..e570cf3 100644 (file)
@@ -5,10 +5,8 @@ set-memsize: memsize: integer out of range
 set-memsize: memsize: invalid integer parameter (xstrtoll returned 4)
 set-memsize: memsize: invalid integer parameter (xstrtoll returned 2)
 set-memsize: memsize: invalid integer parameter (xstrtoll returned 2)
-set-memsize: memsize: invalid integer parameter (xstrtoll returned 2)
 libguestfs: error: truncate_size: ftruncate: /test: File too large
 truncate-size: size: invalid integer parameter (xstrtoll returned 1)
 truncate-size: size: invalid integer parameter (xstrtoll returned 4)
 truncate-size: size: invalid integer parameter (xstrtoll returned 2)
 truncate-size: size: invalid integer parameter (xstrtoll returned 2)
-truncate-size: size: invalid integer parameter (xstrtoll returned 2)
index 228b498..2306147 100755 (executable)
@@ -45,7 +45,6 @@ get-memsize
 -set-memsize 07777770000000000000
 -set-memsize ABC
 -set-memsize 09
--set-memsize 123K
 -set-memsize 123L
 EOF
 
@@ -69,7 +68,6 @@ filesize /test
 # these should all provoke parse errors:
 -truncate-size /test ABC
 -truncate-size /test 09
--truncate-size /test 123K
 -truncate-size /test 123L
 EOF
 
@@ -82,6 +80,6 @@ grep -E 'set[-_]memsize|truncate[-_]size' test.err~ |
   grep -Ev 'proc 200' > test.err
 rm test.err~
 
-diff -u test.out rhbz557655-expected.stdout
-diff -u test.err rhbz557655-expected.stderr
+diff -u rhbz557655-expected.stdout test.out
+diff -u rhbz557655-expected.stderr test.err
 rm test.out test.err test1.img
index d4ef81a..aca56a8 100755 (executable)
@@ -7456,6 +7456,9 @@ and generate_fish_cmds () =
   pr "#include \"xstrtol.h\"\n";
   pr "#include \"fish.h\"\n";
   pr "\n";
+  pr "/* Valid suffixes allowed for numbers.  See Gnulib xstrtol function. */\n";
+  pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
+  pr "\n";
 
   (* list_commands function, which implements guestfish -h *)
   pr "void list_commands (void)\n";
@@ -7674,7 +7677,7 @@ and generate_fish_cmds () =
         pr "    strtol_error xerr;\n";
         pr "    %s r;\n" fntyp;
         pr "\n";
-        pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
+        pr "    xerr = %s (argv[%d], NULL, 0, &r, xstrtol_suffixes);\n" fn i;
         pr "    if (xerr != LONGINT_OK) {\n";
         pr "      fprintf (stderr,\n";
         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";