Richard W.M. Jones
2010-Jan-25 11:53 UTC
[Libguestfs] [PATCH version 2] guestfish: Use xstrtol to parse integers (RHBZ#557655).
-- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones New in Fedora 11: Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 70 libraries supprt'd http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw -------------- next part -------------->From 712adf306e22487cf8ec4bf508917dbb8ed5f357 Mon Sep 17 00:00:00 2001From: Richard Jones <rjones at redhat.com> Date: Fri, 22 Jan 2010 11:01:06 +0000 Subject: [PATCH] guestfish: Use xstrtol to parse integers (RHBZ#557655). Current code uses atoi to parse the generator Int type and atoll to parse the generator Int64 type. The problem with the ato* functions is that they don't cope with errors very well, and they cannot parse numbers that begin with 0.. or 0x.. for octal and hexadecimal respectively. This replaces the atoi call with a call to Gnulib xstrtol and the atoll call with a call to Gnulib xstrtoll. The generated code looks like this for all Int arguments: { strtol_error xerr; long r; xerr = xstrtol (argv[0], NULL, 0, &r, ""); if (xerr != LONGINT_OK) { fprintf (stderr, _("%s: %s: invalid integer parameter (%s returned %d)\n"), cmd, "memsize", "xstrtol", xerr); return -1; } /* The Int type in the generator is a signed 31 bit int. */ if (r < (-(2LL<<30)) || r > ((2LL<<30)-1)) { fprintf (stderr, _("%s: %s: integer out of range\n"), cmd, "memsize"); return -1; } /* The check above should ensure this assignment does not overflow. */ memsize = r; } and like this for all Int64 arguments (note we don't need the range check for these): { strtol_error xerr; long long r; xerr = xstrtoll (argv[1], NULL, 0, &r, ""); if (xerr != LONGINT_OK) { fprintf (stderr, _("%s: %s: invalid integer parameter (%s returned %d)\n"), cmd, "size", "xstrtoll", xerr); return -1; } size = r; } --- .gitignore | 1 + bootstrap | 2 + fish/guestfish.pod | 19 ++++++++ m4/.gitignore | 13 +++++ regressions/Makefile.am | 4 +- regressions/rhbz557655-expected.out | 22 +++++++++ regressions/rhbz557655.sh | 83 +++++++++++++++++++++++++++++++++++ src/generator.ml | 45 ++++++++++++++++++- 8 files changed, 185 insertions(+), 4 deletions(-) create mode 100644 regressions/rhbz557655-expected.out create mode 100755 regressions/rhbz557655.sh diff --git a/.gitignore b/.gitignore index 8fc9721..ee33343 100644 --- a/.gitignore +++ b/.gitignore @@ -204,6 +204,7 @@ python/guestfs.py python/guestfs-py.c python/guestfs.pyc regressions/test1.img +regressions/test.out ruby/bindtests.rb ruby/ext/guestfs/extconf.h ruby/ext/guestfs/_guestfs.c diff --git a/bootstrap b/bootstrap index 6007e59..bcb1f47 100755 --- a/bootstrap +++ b/bootstrap @@ -77,6 +77,8 @@ strndup vasprintf vc-list-files warnings +xstrtol +xstrtoll ' $gnulib_tool \ diff --git a/fish/guestfish.pod b/fish/guestfish.pod index 13a9fa7..1364545 100644 --- a/fish/guestfish.pod +++ b/fish/guestfish.pod @@ -296,6 +296,25 @@ must be escaped with a backslash. command "/bin/echo 'foo bar'" command "/bin/echo \'foo\'" +=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: + + 1234 decimal number 1234 + 02322 octal number, equivalent to decimal 1234 + 0x4d2 hexadecimal number, equivalent to decimal 1234 + +When using the C<chmod> command, you almost always want to specify an +octal number for the mode, and you must prefix it with C<0> (unlike +the Unix L<chmod(1)> program): + + chmod 0777 /public # OK + chmod 777 /public # WRONG! This is mode 777 decimal = 01411 octal. + +Commands that return numbers currently always print them in decimal. + =head1 WILDCARDS AND GLOBBING Neither guestfish nor the underlying guestfs API performs diff --git a/m4/.gitignore b/m4/.gitignore index 788ec87..01c8e2d 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -130,3 +130,16 @@ xsize.m4 /yield.m4 /fcntl-o.m4 /warn-on-use.m4 +/getopt.m4 +/stat.m4 +/symlink.m4 +/time_h.m4 +/xstrtol.m4 +/safe-read.m4 +/safe-write.m4 +/ssize_t.m4 +/write.m4 +/strtol.m4 +/strtoll.m4 +/strtoul.m4 +/strtoull.m4 diff --git a/regressions/Makefile.am b/regressions/Makefile.am index 7ceb0ce..3ce4b8d 100644 --- a/regressions/Makefile.am +++ b/regressions/Makefile.am @@ -26,6 +26,7 @@ include $(top_srcdir)/subdir-rules.mk TESTS = \ rhbz503169c10.sh \ rhbz503169c13.sh \ + rhbz557655.sh \ test-cancellation-download-librarycancels.sh \ test-cancellation-upload-daemoncancels.sh \ test-find0.sh \ @@ -55,4 +56,5 @@ TESTS_ENVIRONMENT = \ EXTRA_DIST = \ $(FAILING_TESTS) \ $(SKIPPED_TESTS) \ - $(TESTS) + $(TESTS) \ + rhbz557655-expected.out diff --git a/regressions/rhbz557655-expected.out b/regressions/rhbz557655-expected.out new file mode 100644 index 0000000..7d37e84 --- /dev/null +++ b/regressions/rhbz557655-expected.out @@ -0,0 +1,22 @@ +0 +16 +8 +-1073741824 +1073741823 +set-memsize: memsize: integer out of range +set-memsize: memsize: integer out of range +set-memsize: memsize: integer out of range +set-memsize: memsize: integer out of range +set-memsize: memsize: invalid integer parameter (xstrtol returned 4) +set-memsize: memsize: invalid integer parameter (xstrtol returned 2) +set-memsize: memsize: invalid integer parameter (xstrtol returned 2) +set-memsize: memsize: invalid integer parameter (xstrtol returned 2) +1234 +1234 +1234 +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) diff --git a/regressions/rhbz557655.sh b/regressions/rhbz557655.sh new file mode 100755 index 0000000..6ef0b70 --- /dev/null +++ b/regressions/rhbz557655.sh @@ -0,0 +1,83 @@ +#!/bin/bash - +# libguestfs +# Copyright (C) 2009 Red Hat Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +# Regression test for: +# https://bugzilla.redhat.com/show_bug.cgi?id=557655 +# "guestfish number parsing should not use atoi, should support '0...' for octal and '0x...' for hexadecimal" + +set -e +rm -f test.out +export LANG=C + +../fish/guestfish >> test.out 2>&1 <<EOF +# set-memsize is just a convenient non-daemon function that +# takes a single integer argument. +set-memsize 0 +get-memsize +set-memsize 0x10 +get-memsize +set-memsize 010 +get-memsize +set-memsize -1073741824 +get-memsize +set-memsize 1073741823 +get-memsize + +# the following should all provoke error messages: +-set-memsize -9000000000000000 +-set-memsize 9000000000000000 +-set-memsize 0x900000000000 +-set-memsize 07777770000000000000 +-set-memsize ABC +-set-memsize 09 +-set-memsize 123K +-set-memsize 123L +EOF + +../fish/guestfish >> test.out 2>&1 <<EOF +alloc test1.img 10M +run +part-disk /dev/sda mbr +mkfs ext2 /dev/sda1 +mount /dev/sda1 / + +touch /test + +# truncate-size takes an Int64 argument +truncate-size /test 1234 +filesize /test +truncate-size /test 0x4d2 +filesize /test +truncate-size /test 02322 +filesize /test + +# should parse OK, but underlying filesystem will reject it: +-truncate-size /test 0x7fffffffffffffff + +# larger than 64 bits, should be an error: +-truncate-size /test 0x10000000000000000 + +# these should all provoke parse errors: +-truncate-size /test ABC +-truncate-size /test 09 +-truncate-size /test 123K +-truncate-size /test 123L +EOF + +diff -u test.out rhbz557655-expected.out +rm test.out test1.img diff --git a/src/generator.ml b/src/generator.ml index e55b2b5..7827d1f 100755 --- a/src/generator.ml +++ b/src/generator.ml @@ -1326,7 +1326,11 @@ as necessary. This is like the C<mkdir -p> shell command."); "change file mode", "\ Change the mode (permissions) of C<path> to C<mode>. Only -numeric modes are supported."); +numeric modes are supported. + +I<Note>: When using this command from guestfish, C<mode> +by default would be decimal, unless you prefix it with +C<0> to get octal, ie. use C<0700> not C<700>."); ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [], [], (* XXX Need stat command to test *) @@ -6868,6 +6872,7 @@ and generate_fish_cmds () pr "\n"; pr "#include <guestfs.h>\n"; pr "#include \"c-ctype.h\"\n"; + pr "#include \"xstrtol.h\"\n"; pr "#include \"fish.h\"\n"; pr "\n"; @@ -7079,6 +7084,34 @@ and generate_fish_cmds () pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n"; pr " return -1;\n"; pr " }\n"; + + let parse_integer fn fntyp rtyp range name i + pr " {\n"; + pr " strtol_error xerr;\n"; + pr " %s r;\n" fntyp; + pr "\n"; + pr " xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i; + pr " if (xerr != LONGINT_OK) {\n"; + pr " fprintf (stderr,\n"; + pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n"; + pr " cmd, \"%s\", \"%s\", xerr);\n" name fn; + pr " return -1;\n"; + pr " }\n"; + (match range with + | None -> () + | Some (min, max, comment) -> + pr " /* %s */\n" comment; + pr " if (r < %s || r > %s) {\n" min max; + pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n" + name; + pr " return -1;\n"; + pr " }\n"; + pr " /* The check above should ensure this assignment does not overflow. */\n"; + ); + pr " %s = r;\n" name; + pr " }\n"; + in + iteri ( fun i -> function @@ -7104,9 +7137,15 @@ and generate_fish_cmds () | Bool name -> pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i | Int name -> - pr " %s = atoi (argv[%d]);\n" name i + let range + let min = "(-(2LL<<30))" + and max = "((2LL<<30)-1)" + and comment + "The Int type in the generator is a signed 31 bit int." in + Some (min, max, comment) in + parse_integer "xstrtol" "long" "int" range name i | Int64 name -> - pr " %s = atoll (argv[%d]);\n" name i + parse_integer "xstrtoll" "long long" "int64_t" None name i ) (snd style); (* Call C API function. *) -- 1.6.5.2
Jim Meyering
2010-Jan-25 12:05 UTC
[Libguestfs] [PATCH version 2] guestfish: Use xstrtol to parse integers (RHBZ#557655).
Richard W.M. Jones wrote:> Subject: [PATCH] guestfish: Use xstrtol to parse integers (RHBZ#557655). > > Current code uses atoi to parse the generator Int type and > atoll to parse the generator Int64 type. The problem with the > ato* functions is that they don't cope with errors very well, > and they cannot parse numbers that begin with 0.. or 0x.. > for octal and hexadecimal respectively. > > This replaces the atoi call with a call to Gnulib xstrtol > and the atoll call with a call to Gnulib xstrtoll. > > The generated code looks like this for all Int arguments:looks fine. ...> and like this for all Int64 arguments (note we don't need the > range check for these):... looks fine, too.> diff --git a/.gitignore b/.gitignore...> diff --git a/fish/guestfish.pod b/fish/guestfish.pod...> +=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: > + > + 1234 decimal number 1234 > + 02322 octal number, equivalent to decimal 1234 > + 0x4d2 hexadecimal number, equivalent to decimal 1234 > + > +When using the C<chmod> command, you almost always want to specify an > +octal number for the mode, and you must prefix it with C<0> (unlike > +the Unix L<chmod(1)> program): > + > + chmod 0777 /public # OK > + chmod 777 /public # WRONG! This is mode 777 decimal = 01411 octal.This strikes me as surprising enough that it would deserve to emit a warning when there is no leading 0. Doing anything else seems like just asking for trouble. ... Good test coverage. The rest looked fine, too.
Richard W.M. Jones
2010-Jan-25 12:10 UTC
[Libguestfs] [PATCH version 3] guestfish: Use xstrtol to parse integers (RHBZ#557655).
Updated again, includes a fix suggested by Jim Meyering, and another fix to handling of fwrite. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://et.redhat.com/~rjones/virt-df/ -------------- next part -------------->From 58abe782bf7137526b4a5c7e6d5d2b145e3b09d2 Mon Sep 17 00:00:00 2001From: Richard Jones <rjones at redhat.com> Date: Fri, 22 Jan 2010 11:01:06 +0000 Subject: [PATCH] guestfish: Use xstrtol to parse integers (RHBZ#557655). Current code uses atoi to parse the generator Int type and atoll to parse the generator Int64 type. The problem with the ato* functions is that they don't cope with errors very well, and they cannot parse numbers that begin with 0.. or 0x.. for octal and hexadecimal respectively. This replaces the atoi call with a call to Gnulib xstrtol and the atoll call with a call to Gnulib xstrtoll. The generated code looks like this for all Int arguments: { strtol_error xerr; long r; xerr = xstrtol (argv[0], NULL, 0, &r, ""); if (xerr != LONGINT_OK) { fprintf (stderr, _("%s: %s: invalid integer parameter (%s returned %d)\n"), cmd, "memsize", "xstrtol", xerr); return -1; } /* The Int type in the generator is a signed 31 bit int. */ if (r < (-(2LL<<30)) || r > ((2LL<<30)-1)) { fprintf (stderr, _("%s: %s: integer out of range\n"), cmd, "memsize"); return -1; } /* The check above should ensure this assignment does not overflow. */ memsize = r; } and like this for all Int64 arguments (note we don't need the range check for these): { strtol_error xerr; long long r; xerr = xstrtoll (argv[1], NULL, 0, &r, ""); if (xerr != LONGINT_OK) { fprintf (stderr, _("%s: %s: invalid integer parameter (%s returned %d)\n"), cmd, "size", "xstrtoll", xerr); return -1; } size = r; } Note this also fixes an unrelated bug in guestfish handling of RBufferOut. We were using 'fwrite' without checking the return value, and this could have caused silent failures, eg. in the case where there was not enough disk space to store the resulting file, or even if the program was interrupted (but continued) during the write. Replace this with Gnulib 'full-write', and check the return value and report errors. --- .gitignore | 1 + bootstrap | 3 + fish/guestfish.pod | 19 ++++++++ m4/.gitignore | 13 +++++ regressions/Makefile.am | 4 +- regressions/rhbz557655-expected.out | 22 +++++++++ regressions/rhbz557655.sh | 83 +++++++++++++++++++++++++++++++++++ src/generator.ml | 54 +++++++++++++++++++++-- 8 files changed, 194 insertions(+), 5 deletions(-) create mode 100644 regressions/rhbz557655-expected.out create mode 100755 regressions/rhbz557655.sh diff --git a/.gitignore b/.gitignore index 8fc9721..ee33343 100644 --- a/.gitignore +++ b/.gitignore @@ -204,6 +204,7 @@ python/guestfs.py python/guestfs-py.c python/guestfs.pyc regressions/test1.img +regressions/test.out ruby/bindtests.rb ruby/ext/guestfs/extconf.h ruby/ext/guestfs/_guestfs.c diff --git a/bootstrap b/bootstrap index 6007e59..7010eca 100755 --- a/bootstrap +++ b/bootstrap @@ -60,6 +60,7 @@ modules=' arpa_inet c-ctype closeout +full-write gitlog-to-changelog gnu-make gnumakefile @@ -77,6 +78,8 @@ strndup vasprintf vc-list-files warnings +xstrtol +xstrtoll ' $gnulib_tool \ diff --git a/fish/guestfish.pod b/fish/guestfish.pod index 13a9fa7..1364545 100644 --- a/fish/guestfish.pod +++ b/fish/guestfish.pod @@ -296,6 +296,25 @@ must be escaped with a backslash. command "/bin/echo 'foo bar'" command "/bin/echo \'foo\'" +=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: + + 1234 decimal number 1234 + 02322 octal number, equivalent to decimal 1234 + 0x4d2 hexadecimal number, equivalent to decimal 1234 + +When using the C<chmod> command, you almost always want to specify an +octal number for the mode, and you must prefix it with C<0> (unlike +the Unix L<chmod(1)> program): + + chmod 0777 /public # OK + chmod 777 /public # WRONG! This is mode 777 decimal = 01411 octal. + +Commands that return numbers currently always print them in decimal. + =head1 WILDCARDS AND GLOBBING Neither guestfish nor the underlying guestfs API performs diff --git a/m4/.gitignore b/m4/.gitignore index 788ec87..01c8e2d 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -130,3 +130,16 @@ xsize.m4 /yield.m4 /fcntl-o.m4 /warn-on-use.m4 +/getopt.m4 +/stat.m4 +/symlink.m4 +/time_h.m4 +/xstrtol.m4 +/safe-read.m4 +/safe-write.m4 +/ssize_t.m4 +/write.m4 +/strtol.m4 +/strtoll.m4 +/strtoul.m4 +/strtoull.m4 diff --git a/regressions/Makefile.am b/regressions/Makefile.am index 7ceb0ce..3ce4b8d 100644 --- a/regressions/Makefile.am +++ b/regressions/Makefile.am @@ -26,6 +26,7 @@ include $(top_srcdir)/subdir-rules.mk TESTS = \ rhbz503169c10.sh \ rhbz503169c13.sh \ + rhbz557655.sh \ test-cancellation-download-librarycancels.sh \ test-cancellation-upload-daemoncancels.sh \ test-find0.sh \ @@ -55,4 +56,5 @@ TESTS_ENVIRONMENT = \ EXTRA_DIST = \ $(FAILING_TESTS) \ $(SKIPPED_TESTS) \ - $(TESTS) + $(TESTS) \ + rhbz557655-expected.out diff --git a/regressions/rhbz557655-expected.out b/regressions/rhbz557655-expected.out new file mode 100644 index 0000000..7d37e84 --- /dev/null +++ b/regressions/rhbz557655-expected.out @@ -0,0 +1,22 @@ +0 +16 +8 +-1073741824 +1073741823 +set-memsize: memsize: integer out of range +set-memsize: memsize: integer out of range +set-memsize: memsize: integer out of range +set-memsize: memsize: integer out of range +set-memsize: memsize: invalid integer parameter (xstrtol returned 4) +set-memsize: memsize: invalid integer parameter (xstrtol returned 2) +set-memsize: memsize: invalid integer parameter (xstrtol returned 2) +set-memsize: memsize: invalid integer parameter (xstrtol returned 2) +1234 +1234 +1234 +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) diff --git a/regressions/rhbz557655.sh b/regressions/rhbz557655.sh new file mode 100755 index 0000000..6ef0b70 --- /dev/null +++ b/regressions/rhbz557655.sh @@ -0,0 +1,83 @@ +#!/bin/bash - +# libguestfs +# Copyright (C) 2009 Red Hat Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +# Regression test for: +# https://bugzilla.redhat.com/show_bug.cgi?id=557655 +# "guestfish number parsing should not use atoi, should support '0...' for octal and '0x...' for hexadecimal" + +set -e +rm -f test.out +export LANG=C + +../fish/guestfish >> test.out 2>&1 <<EOF +# set-memsize is just a convenient non-daemon function that +# takes a single integer argument. +set-memsize 0 +get-memsize +set-memsize 0x10 +get-memsize +set-memsize 010 +get-memsize +set-memsize -1073741824 +get-memsize +set-memsize 1073741823 +get-memsize + +# the following should all provoke error messages: +-set-memsize -9000000000000000 +-set-memsize 9000000000000000 +-set-memsize 0x900000000000 +-set-memsize 07777770000000000000 +-set-memsize ABC +-set-memsize 09 +-set-memsize 123K +-set-memsize 123L +EOF + +../fish/guestfish >> test.out 2>&1 <<EOF +alloc test1.img 10M +run +part-disk /dev/sda mbr +mkfs ext2 /dev/sda1 +mount /dev/sda1 / + +touch /test + +# truncate-size takes an Int64 argument +truncate-size /test 1234 +filesize /test +truncate-size /test 0x4d2 +filesize /test +truncate-size /test 02322 +filesize /test + +# should parse OK, but underlying filesystem will reject it: +-truncate-size /test 0x7fffffffffffffff + +# larger than 64 bits, should be an error: +-truncate-size /test 0x10000000000000000 + +# these should all provoke parse errors: +-truncate-size /test ABC +-truncate-size /test 09 +-truncate-size /test 123K +-truncate-size /test 123L +EOF + +diff -u test.out rhbz557655-expected.out +rm test.out test1.img diff --git a/src/generator.ml b/src/generator.ml index e55b2b5..58c39e6 100755 --- a/src/generator.ml +++ b/src/generator.ml @@ -1326,7 +1326,11 @@ as necessary. This is like the C<mkdir -p> shell command."); "change file mode", "\ Change the mode (permissions) of C<path> to C<mode>. Only -numeric modes are supported."); +numeric modes are supported. + +I<Note>: When using this command from guestfish, C<mode> +by default would be decimal, unless you prefix it with +C<0> to get octal, ie. use C<0700> not C<700>."); ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [], [], (* XXX Need stat command to test *) @@ -6861,6 +6865,8 @@ and generate_fish_cmds () fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags) ) all_functions_sorted in + pr "#include <config.h>\n"; + pr "\n"; pr "#include <stdio.h>\n"; pr "#include <stdlib.h>\n"; pr "#include <string.h>\n"; @@ -6868,6 +6874,8 @@ and generate_fish_cmds () pr "\n"; pr "#include <guestfs.h>\n"; pr "#include \"c-ctype.h\"\n"; + pr "#include \"full-write.h\"\n"; + pr "#include \"xstrtol.h\"\n"; pr "#include \"fish.h\"\n"; pr "\n"; @@ -7079,6 +7087,34 @@ and generate_fish_cmds () pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n"; pr " return -1;\n"; pr " }\n"; + + let parse_integer fn fntyp rtyp range name i + pr " {\n"; + pr " strtol_error xerr;\n"; + pr " %s r;\n" fntyp; + pr "\n"; + pr " xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i; + pr " if (xerr != LONGINT_OK) {\n"; + pr " fprintf (stderr,\n"; + pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n"; + pr " cmd, \"%s\", \"%s\", xerr);\n" name fn; + pr " return -1;\n"; + pr " }\n"; + (match range with + | None -> () + | Some (min, max, comment) -> + pr " /* %s */\n" comment; + pr " if (r < %s || r > %s) {\n" min max; + pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n" + name; + pr " return -1;\n"; + pr " }\n"; + pr " /* The check above should ensure this assignment does not overflow. */\n"; + ); + pr " %s = r;\n" name; + pr " }\n"; + in + iteri ( fun i -> function @@ -7104,9 +7140,15 @@ and generate_fish_cmds () | Bool name -> pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i | Int name -> - pr " %s = atoi (argv[%d]);\n" name i + let range + let min = "(-(2LL<<30))" + and max = "((2LL<<30)-1)" + and comment + "The Int type in the generator is a signed 31 bit int." in + Some (min, max, comment) in + parse_integer "xstrtol" "long" "int" range name i | Int64 name -> - pr " %s = atoll (argv[%d]);\n" name i + parse_integer "xstrtoll" "long long" "int64_t" None name i ) (snd style); (* Call C API function. *) @@ -7177,7 +7219,11 @@ and generate_fish_cmds () pr " return 0;\n" | RBufferOut _ -> pr " if (r == NULL) return -1;\n"; - pr " fwrite (r, size, 1, stdout);\n"; + pr " if (full_write (1, r, size) != size) {\n"; + pr " perror (\"write\");\n"; + pr " free (r);\n"; + pr " return -1;\n"; + pr " }\n"; pr " free (r);\n"; pr " return 0;\n" ); -- 1.6.5.2
Reasonably Related Threads
- [PATCH] guestfish: Use xstrtol to parse integers (RHBZ#557655).
- How Ogg mappings translate into the codecs parameter in Ogg media types
- [PATCHv3 0/2] Introduce vfs_min_size API to get minimum filesystem size.
- [PATCHv4 0/2] Introduce vfs_minimum_size API to get minimum filesystem size.
- [LLVMdev] linux/x86-64 codegen support