Compare commits

...

420 Commits

Author SHA1 Message Date
Richard W.M. Jones
f9f3c7c5ac Version 1.21.27. 2013-04-04 21:04:32 +01:00
Richard W.M. Jones
dee1dd64c3 New APIs: Add support for syslinux and extlinux (bootloaders).
This also adds tests of SYSLINUX and EXTLINUX which create bootable
guests.
2013-04-04 18:31:41 +01:00
Richard W.M. Jones
e73cd348c8 Don't delete iconv locale data from the appliance.
- /usr/lib{,64}/gconv/*:

This is the iconv data, required for APIs like iconv_open to work.  In
particular, the mtools 'mcopy' program fails completely if it cannot
use iconv.  'mcopy' is used by SYSLINUX to copy files to the disk.

The error you would have seen is:

  Error converting to codepage 850 Invalid argument
  Cannot initialize 'S:'
  Bad target s:/ldlinux.sys

- /usr/bin/localedef and /usr/sbin/build-locale-archive:

These are not really needed, but both are simply small binaries so we
might as well not delete them.
2013-04-04 18:23:32 +01:00
Richard W.M. Jones
3cdca7616a daemon/copy: Ensure errno is preserved along error paths. 2013-04-04 14:58:32 +01:00
Richard W.M. Jones
33c087ea9c Add 'sparse' option to copy-{device,file}-to-{device,file} calls.
Setting the 'sparse' optional boolean causes writes to be omitted if
the block to be written contains all zero bytes.

This should help with sparse backing files (eg. raw, qcow2, dm-thin, etc).

Also, modify virt-resize to use this option by default when copying
devices.  The savings in virt-resize can be quite startling, eg
'du -sh' (ie. true size) of a resized disk image:

8.1G      /tmp/f15x32-resized.img    # before this change
3.2G      /tmp/f15x32-resized.img    # after this change
2013-04-04 14:58:32 +01:00
Richard W.M. Jones
289fd29f0b php: Fix segfault when function has an OStringList optional argument.
How this PHP/Zend stuff is supposed to work is not documented, but at
least with these changes it no longer segfaults.
2013-04-04 11:49:27 +01:00
Richard W.M. Jones
ba0199c487 python: Let RHashtable be returned as a Python dict.
The initial proposal was suggested by Matt Booth and discussed on the
mailing list here:

https://www.redhat.com/archives/libguestfs/2013-April/msg00007.html
2013-04-03 19:18:07 +01:00
Richard W.M. Jones
3dcb572bda Better error messages for FUSE and other things not supported.
The bare message "FUSE not supported" wasn't actionable.
2013-04-03 12:33:24 +01:00
Richard W.M. Jones
d0a8cca9a1 FAQ: In Fedora >= 19, the RPM detects if it can access the network when building. 2013-04-02 15:53:37 +01:00
Richard W.M. Jones
387b232126 Version 1.21.26. 2013-04-02 15:29:59 +01:00
Richard W.M. Jones
667482ca9a perl: Remove Sys::Guestfs::Lib.
See announcement on the mailing list for more details about this change:

https://www.redhat.com/archives/libguestfs/2013-April/msg00001.html
2013-04-02 15:26:05 +01:00
Richard W.M. Jones
2287b988ee perl: Remove use of Sys::Guestfs::Lib::open_guest function.
This obsolete function does all sorts of libvirt/XML things, which can
now be replaced by using ordinary API calls; especially $g->add_domain.
2013-04-02 13:30:19 +01:00
Richard W.M. Jones
ecda39bed4 tests/data: Update README and comments about initrd binary files.
These are used for testing the C, not Perl, file_architecture API.
2013-04-02 13:06:10 +01:00
Richard W.M. Jones
1cb38ab924 New API: feature-available.
This API is an easier to use version of the existing guestfs_available,
because the new API returns true/false instead of throwing an error
when a feature from the list is not available.

In truth we've had this implementation internally in the library
and several tools and in Sys::Guestfs::Lib for a long time.  This
change just turns it into a publicly consumable API.
2013-04-02 12:38:50 +01:00
Richard W.M. Jones
288b2b2d4f virt-ls, virt-edit: Remove references to Sys::Guestfs::Lib and other irrelevant Perl libraries. 2013-04-02 10:15:25 +01:00
Richard W.M. Jones
6fa1177b0a java: Make test cases depend on jar file.
This fixes parallel builds.  The error you would have seen was:

  error: error reading libguestfs-1.21.25.jar; zip file is empty
2013-04-01 20:29:17 +01:00
Richard W.M. Jones
1a2e03c323 java: 'make clean' should remove whole api/ directory.
This directory (containing HTML documentation) can be removed
completely when making clean.  CLEANFILES cannot recursively remove a
directory, so use a clean-local rule instead.
2013-04-01 20:28:16 +01:00
Richard W.M. Jones
ce49e1fdc0 build: Change various check rules so they implicitly act like 'make -k'.
Rules such as 'make check-valgrind' are implemented using a for-loop.
They would always exit after the first error, even if 'make -k' was
used at the top-level.  Since 'make -k'-style behaviour is generally
more useful, change these for-loops so they run all the tests, and
report errors at the end.
2013-04-01 13:32:15 +01:00
Richard W.M. Jones
599f5d7ddc make clean: Remove *~ (editor backup) files. 2013-04-01 13:32:15 +01:00
Richard W.M. Jones
5f5ce4f59f make clean: Clean contents of tmp directory. 2013-04-01 11:40:35 +01:00
Richard W.M. Jones
b050d7e4bf valgrind: Write separate log files in tmp/valgrind-<DATE>-<PID>.log
Current code wrote a single valgrind.log in the top-level directory.
This was overwritten with each valgrinded program, which wasn't much
use.  The new version writes multiple separate valgrind-*.log files
containing the date and PID (so each is unique).

It would nice if valgrind could delete log files that don't contain
errors, but this doesn't appear to be possible.
2013-04-01 11:35:26 +01:00
Richard W.M. Jones
68990840b6 "attach method" is from now on known as "backend".
This large, but mainly mechanical commit, renames "attach method"
everywhere to "backend".

Backwards compatibility of the API (guestfs_{set,get}_attach_method)
and environment (LIBGUESTFS_ATTACH_METHOD) is maintained, but in new
code use guestfs_{set,get}_backend and LIBGUESTFS_BACKEND instead.

The default backend (launching qemu directly) is now called 'direct'
instead of 'appliance', although you can still use 'appliance' as a
synonym.
2013-04-01 11:16:18 +01:00
Richard W.M. Jones
f2b1a01e76 build: Clarify output of 'make help'. 2013-04-01 11:16:18 +01:00
Richard W.M. Jones
72f5a6b004 Version 1.21.25. 2013-03-30 22:57:29 +00:00
Richard W.M. Jones
75f2fcd687 docs: Remove obsolete sections from libguestfs gotchas.
These refer to old behaviour in long-unsupported versions
of libguestfs.
2013-03-30 19:44:39 +00:00
Richard W.M. Jones
806289ec66 docs: Refresh API overview section. 2013-03-30 19:43:52 +00:00
Richard W.M. Jones
b2eef58571 docs: Alternate ways to list filesystems through the API. 2013-03-30 19:28:29 +00:00
Richard W.M. Jones
8e76cb4512 FAQ: Update distro support section. 2013-03-30 19:09:12 +00:00
Richard W.M. Jones
02a4e5ac6a debian: Allow test-virt-alignment-scan-guests.sh test to be skipped. 2013-03-30 18:17:09 +00:00
Richard W.M. Jones
2a090e0667 tests/guests: Add 'guests-all-good.xml{.in}' libvirt test guest set.
This differs from 'guests.xml' in that there are no guests with
missing disks, etc., so we can use this to test virt-alignment-scan
accurately.
2013-03-30 16:33:08 +00:00
Richard W.M. Jones
429ffda329 parallel: Propagate errors from worker threads and exit with error code.
In virt-df and virt-alignment-scan, ensure that errors that happen in
worker threads are propagated all the way up and result in
exit(EXIT_FAILURE).

Note that this makes the align/test-virt-alignment-scan-guests.sh test
fail (for a genuine reason).  This is fixed in the following commit.

This updates commit 8b90f55dc7.
2013-03-30 16:33:08 +00:00
Richard W.M. Jones
30702c7f54 Version 1.21.24. 2013-03-29 22:07:18 +00:00
Richard W.M. Jones
f55a2dbf29 java: Make bindtests depend on jar file so parallel builds work.
This fixes commit c36ced5e21.
2013-03-29 22:02:46 +00:00
Richard W.M. Jones
8b90f55dc7 virt-alignment-scan: Don't call exit(3) from this multi-threaded program.
For more information see:
https://bugzilla.redhat.com/show_bug.cgi?id=790837#c2
2013-03-29 21:28:49 +00:00
Richard W.M. Jones
d6ea2f5911 daemon: file: Remove extraneous space after output of 'file' command (RHBZ#928995). 2013-03-29 20:04:11 +00:00
Richard W.M. Jones
a9ad3088bf daemon: parse_btrfsvol: Perform device name translation before trying to stat the device.
If using (eg) virtio-blk, the canonical name won't work unless device
name translation is done first.

This fixes commit 47b929b7893b3a76ff22760d245cb80720ae6345..
2013-03-29 10:50:28 +00:00
Richard W.M. Jones
bb276e8a26 daemon: parse_btrfsvol: Move variable decls to top, whitespace fixes.
This fixes commit 47b929b789.
2013-03-28 23:30:51 +00:00
Richard W.M. Jones
a28a430b10 daemon: Fix parse_btrfsvol to use STRPREFIX instead of bogus strncmp.
This fixes commit 47b929b789.
2013-03-28 23:30:51 +00:00
Richard W.M. Jones
c50cde67cc java: Format CLEANFILES rule. 2013-03-28 20:24:25 +00:00
Richard W.M. Jones
c36ced5e21 java: Enable parallel builds.
This reverts commit 89404ec0ba.
2013-03-28 20:20:09 +00:00
Richard W.M. Jones
6185aa4e38 ocaml tools: Enable parallel builds.
In particular, building virt-sysprep is slow because there are so many
modules.  Enable parallel builds.  If it breaks, we should fix it, not
work around it.
2013-03-28 20:15:51 +00:00
Richard W.M. Jones
dce94f3e26 ocaml: Fix and enable parallel builds.
We only have to serialize the two calls to ocamlmklib, since both will
try to create a file called 'libmlguestfs.a'.  Apart from that,
parallel builds here should be fine.
2013-03-28 20:13:36 +00:00
Richard W.M. Jones
b13c935bbd ocaml: Break circular dependency of mlguestfs.cma{,x} <-> guestfs.cm{o,x} 2013-03-28 20:12:47 +00:00
Richard W.M. Jones
3c34db9808 Use new-style demand-loaded bash-completion scripts. 2013-03-28 18:46:06 +00:00
Richard W.M. Jones
df7f57a193 Version 1.21.23. 2013-03-28 15:18:43 +00:00
Richard W.M. Jones
924aa44c1f bash completion: Extend this script to work with other virt tools. 2013-03-28 15:15:45 +00:00
Richard W.M. Jones
6c9a7fe561 Add --long-options option to most tools.
For example:

$ guestfish --long-options
--add
--cmd-help
--connect
--csh
--domain
--echo-keys
[etc.]

The idea of this is to make it easier to write a bash completion
script that accurately expands --<TAB> options for each command.
2013-03-28 14:46:20 +00:00
Richard W.M. Jones
b98de580c9 fish: Better tab completion for guestfish. 2013-03-28 14:00:42 +00:00
Richard W.M. Jones
05ba393724 OCaml tools: Use Common_gettext and Common_utils modules.
Share these modules across all three tools virt-resize, virt-sparsify
and virt-sysprep.

This is mostly code motion.
2013-03-28 14:00:42 +00:00
Richard W.M. Jones
69e0f86cab osinfo: Fix declaration of guestfs___osinfo_map to work when libxml2 is not installed. 2013-03-23 18:57:39 +00:00
Richard W.M. Jones
186bb67c6e Add support for: Gluster, Ceph (rbd), Sheepdog.
These are not tested at all, and so probably won't work.  However the
code and infrastructure is in place so we can fix bugs easily as they
arise.
2013-03-19 12:39:51 +00:00
Richard W.M. Jones
97be29893e build: Add 'make check-valgrind-with-appliance'. 2013-03-19 12:24:40 +00:00
Richard W.M. Jones
62d940d2dd build: Small rearrangement of Makefile.am check-slow rule. 2013-03-19 12:24:40 +00:00
Richard W.M. Jones
55ce68784f build: Fix 'make extra-tests' to call 'check-valgrind' instead of rule that doesn't exist. 2013-03-19 12:24:40 +00:00
Richard W.M. Jones
71de9ef039 build: Turn off warning about overlength-strings.
ISO apparently specified a limit of 4096 bytes/characters for strings.
The description of the guestfish command 'add-drive' is now longer
than this limit, causing this warning.

Turn off this warning, since GCC has no problems with these strings.
2013-03-19 12:24:37 +00:00
Richard W.M. Jones
a535befbeb nbd: Update and clarify the documentation for NBD. 2013-03-18 22:35:43 +00:00
Richard W.M. Jones
66df6ae908 drives: Make parse_servers return an int (number of servers).
This is just a code refactoring.
2013-03-18 22:35:24 +00:00
Richard W.M. Jones
f8941b09e6 Version 1.21.22. 2013-03-18 19:46:24 +00:00
Richard W.M. Jones
dc4c959ce1 nbd: Allow 'unix' transport & socket to be specified.
This allows the server string to contain "unix:/path/to/socket",
thus using a Unix domain socket to connect to the NBD server.
2013-03-18 17:59:19 +00:00
Richard W.M. Jones
43b6d75a08 tests: nbd: Ensure qemu-nbd subprocess is always killed.
Even if the test fails/dies for some other reason.
2013-03-18 16:45:55 +00:00
Richard W.M. Jones
f750c3e72d drives: Factor out common code for making a file= qemu parameter. 2013-03-18 16:45:55 +00:00
Richard W.M. Jones
9c32c73afd drives: Allow multiple servers to be passed to add_drives.
This changes the existing (non-published-in-stable) API for
add_drives{_opt} so that instead of having separate 'server' and
'port' parameters, now we have a single 'server' parameter which is a
list of strings.

This is so we will be able to cope with protocols such as Ceph which
allows multiple servers, or Sheepdog which can use an implicit local
server (ie. zero servers specified).

NBD still requires exactly one server.
2013-03-18 16:45:55 +00:00
Richard W.M. Jones
766393d854 inspection: Remove unused #includes. 2013-03-18 15:47:34 +00:00
Richard W.M. Jones
6641758221 drives: Add a common guestfs___free_drive_source function.
This refactors the code to introduce a common function.
2013-03-18 14:58:50 +00:00
Richard W.M. Jones
612a3f06b4 drives: Whitespace change. 2013-03-18 14:58:36 +00:00
Richard W.M. Jones
cec0c55a35 drives: Change internal struct drive_source.
This is just code refactoring.
2013-03-18 12:04:24 +00:00
Richard W.M. Jones
856c2f6a47 nbd: Note that readonly connections are not supported by the appliance attach-method.
This documents the problem and links to the upstream bug.
2013-03-18 09:55:36 +00:00
Richard W.M. Jones
ae3011d518 lib: Remove -Wswitch-default.
This warning is actively dangerous.  Because it forces you to use a
'default:' case in every switch statement, it means you can no longer
detect missing cases in enums.
2013-03-16 21:22:03 +00:00
Richard W.M. Jones
bf1c3196b5 lib: Add missing cases in switch statements.
These were being hidden by misguided use of the dangerous
-Wswitch-default flag.
2013-03-16 20:23:14 +00:00
Richard W.M. Jones
2af946b3bf Version 1.21.21. 2013-03-15 22:42:38 +00:00
Richard W.M. Jones
af1c53d104 appliance: Make sure cachedir has mode 0755 (RHBZ#921292).
See https://bugzilla.redhat.com/show_bug.cgi?id=921292#c4
2013-03-15 22:40:06 +00:00
Richard W.M. Jones
e7c78881fc appliance: Use ignore_value() macro instead of casting return to (void). 2013-03-15 22:39:45 +00:00
Richard W.M. Jones
c83221a869 drives: add_drive was only called from one place, so inline it.
This is just code motion.
2013-03-15 20:47:55 +00:00
Richard W.M. Jones
694a091d3f lib: Add direct support for the NBD (Network Block Device) protocol.
You can now add remote NBD drives using:

 ><fs> add-drive "" format:raw protocol:nbd server:localhost

(Note that you also need to add port:NNNN if the server is running on
a non-standard port).

The corresponding qemu-nbd service can be started by doing:

 qemu-nbd disk.img -t

This commit also adds a test.
2013-03-15 20:47:54 +00:00
Richard W.M. Jones
e7e2b56569 drives: Make drv->readonly flag into a bool. 2013-03-14 22:34:56 +00:00
Richard W.M. Jones
b1df9a9df1 drives: Refactor code to separate 'struct drive' creation from adding drives. 2013-03-14 22:28:22 +00:00
Richard W.M. Jones
33ec3eca29 launch: Move code concerned with adding drives to 'src/drives.c'.
Apart from adding a few comments, this is entirely code motion.
2013-03-14 22:06:16 +00:00
Richard W.M. Jones
a2b88b8637 Add ./configure --with-extra-packages="..." option.
This adds extra packages to the appliance.  It's useful for adding
debugging packages.
2013-03-14 13:50:49 +00:00
Hilko Bengen
85dd52f470 Mount /run as tmpfs inside appliance (workaround for febootstrap's /init) 2013-03-14 13:01:07 +00:00
Richard W.M. Jones
e29a130d8f erlang: Use $(ERLANG_LIB_DIR) to get Erlang libdir.
Instead of previous custom hack which didn't work properly on Debian.

Thanks: Hilko Bengen.
2013-03-14 12:47:40 +00:00
Richard W.M. Jones
04acc32abf README: Discourage general users from doing 'make install'.
It causes plenty of problems with people have multiple parallel
versions of libguestfs installed, and there's no benefit because you
can easily run libguestfs and tools from the build directory.
2013-03-14 12:20:52 +00:00
Richard W.M. Jones
87c9ec881c ruby: Support 'make INSTALLDIRS=vendor install' for Ruby as well as Perl.
As with Perl, you can now set INSTALLDIRS to control where Ruby places
its files (ie. in the site dir, which is the default, or in the vendor
dir).

The difference in file layout between 'make install' and
'make INSTALLDIRS=vendor install' is shown below (for Fedora 18).

--- /tmp/site	2013-03-14 12:14:35.740015694 +0000
+++ /tmp/vendor	2013-03-14 12:14:13.668093944 +0000
@@ -119,21 +119,20 @@
 ./usr/lib64/ocaml/guestfs/mlguestfs.cmxa
 ./usr/lib64/ocaml/stublibs/dllmlguestfs.so
 ./usr/lib64/ocaml/stublibs/dllmlguestfs.so.owner
-./usr/lib64/perl5/auto/Sys/Guestfs/Guestfs.bs
-./usr/lib64/perl5/auto/Sys/Guestfs/Guestfs.so
-./usr/lib64/perl5/auto/Sys/Guestfs/.packlist
 ./usr/lib64/perl5/perllocal.pod
-./usr/lib64/perl5/Sys/bindtests.pl
-./usr/lib64/perl5/Sys/Guestfs/Lib.pm
-./usr/lib64/perl5/Sys/Guestfs.pm
+./usr/lib64/perl5/vendor_perl/auto/Sys/Guestfs/Guestfs.bs
+./usr/lib64/perl5/vendor_perl/auto/Sys/Guestfs/Guestfs.so
+./usr/lib64/perl5/vendor_perl/auto/Sys/Guestfs/.packlist
+./usr/lib64/perl5/vendor_perl/Sys/bindtests.pl
+./usr/lib64/perl5/vendor_perl/Sys/Guestfs/Lib.pm
+./usr/lib64/perl5/vendor_perl/Sys/Guestfs.pm
 ./usr/lib64/php/modules/guestfs_php.so
 ./usr/lib64/pkgconfig/libguestfs-gobject-1.0.pc
 ./usr/lib64/pkgconfig/libguestfs.pc
 ./usr/lib64/python2.7/site-packages/guestfs.py
 ./usr/lib64/python2.7/site-packages/libguestfsmod.la
 ./usr/lib64/python2.7/site-packages/libguestfsmod.so
-./usr/local/lib64/ruby/site_ruby/_guestfs.so
-./usr/local/share/ruby/site_ruby/guestfs.rb
+./usr/lib64/ruby/vendor_ruby/_guestfs.so
 ./usr/sbin/libguestfs-make-fixed-appliance
 ./usr/share/doc/libguestfs/example-debian-netinst-cd.xml
 ./usr/share/doc/libguestfs/example-debian.xml
@@ -406,3 +405,4 @@
 ./usr/share/man/uk/man3/guestfs-perl.3
 ./usr/share/man/uk/man3/guestfs-python.3
 ./usr/share/man/uk/man3/guestfs-ruby.3
+./usr/share/ruby/vendor_ruby/guestfs.rb

For prompting me to fix this, thanks: Hilko Bengen.
2013-03-14 12:19:22 +00:00
Richard W.M. Jones
0fd925da77 launch: Print attach-method, tmpdir, umask, euid when launching.
These are only printed when debugging is enabled, but should help
debugging hard-to-pin-down permissions problems.
2013-03-14 10:47:00 +00:00
Richard W.M. Jones
df656c9d5a tests: Make it easier to grep failures out of the log file. 2013-03-14 08:56:29 +00:00
Richard W.M. Jones
3e4d3f415c Version 1.21.20. 2013-03-13 18:45:30 +00:00
Richard W.M. Jones
1b644ad64e utils: Fix error messages for external commands that fail (RHBZ#921040).
This adds a common utility function (guestfs___exit_status_to_string)
and a common error function (guestfs___external_command_failed), and
uses them all over the library and tools when converting exit status
in error messages etc.
2013-03-13 18:34:17 +00:00
Richard W.M. Jones
50a3fa5f42 lib: Move common errors to src/errors.c.
This is just code motion.
2013-03-13 17:20:41 +00:00
Richard W.M. Jones
e9d3074294 rescue: Remove dead code.
This pty code was defended by #if 0 ... #endif and was dead code.
2013-03-13 17:20:41 +00:00
Richard W.M. Jones
368b4c6480 Ignore case when generating AUTHORS file. 2013-03-13 10:57:36 +00:00
infernix
b17c3a7eb3 launch: appliance: Add custom parameters last.
This allows custom parameters to modify parameters added by
libguestfs, eg. by doing:

  -set drive.hd0.file=rbd:foo/bar

[infernix adds the comment below:]

This works for recent versions of QEMU. The way to use this is:

guestfish
><fs> add-drive /dev/null
><fs> config -set drive.hd0.file=rbd:pool/volume
><fs> run

This will probably work for more types (sheepdog, iscsi et al), but
with the caveat that the libguestfs layers are bypassed so you'll
*always* end up directly accessing the disk in rw mode.
2013-03-12 17:58:32 +00:00
Richard W.M. Jones
0b285cd8a6 docs: Update documentation on attach-methods.
Add better instructions for getting the default attach-method.

Update libguestfs-test-tool(1) to show how to enable and disable
libvirt.
2013-03-12 13:19:26 +00:00
Richard W.M. Jones
6e4f9be492 php: Pass all libvirt environment variables down to PHP test scripts.
Including LIBVIRTD_* and VIRTLOCKD_*.

This updates commit cd40cf7139.
2013-03-12 12:35:17 +00:00
Richard W.M. Jones
49622ab63b Version 1.21.19. 2013-03-11 23:03:38 +00:00
Richard W.M. Jones
5e5026b730 qemu-img info: Use --output json and YAJL (JSON parser) to safely parse output (RHBZ#920225).
The old parser is still used if either YAJL is not available or
qemu-img info doesn't support the --output json option.
2013-03-11 19:10:04 +00:00
Richard W.M. Jones
2f8960f784 qemu-img info: Prefix parsing functions as old_parser_*.
Prefix functions in this file with old_parser_... to make it clear
this is the old / slightly unsafe human output parser, which is
shortly to be replaced by a safer JSON parser.

This is just code motion.
2013-03-11 16:27:13 +00:00
Richard W.M. Jones
cd40cf7139 php: Fix tests.
- Use ./run script to run the tests.
- Set environment variables correctly, including $PATH.
- Test the locally built, not installed, copy of libguestfs.
2013-03-11 16:04:17 +00:00
Richard W.M. Jones
becc4fecf4 php: Revise README-PHP documentation. 2013-03-11 14:29:13 +00:00
Richard W.M. Jones
c64e99782f docs: Note that $PATH affects libguestfs.
If $PATH is not set, libguestfs and/or libvirt tend to break.
2013-03-11 14:28:40 +00:00
Richard W.M. Jones
350c478d7b launch: libvirt: Unset $PATH can cause libvirt launch to fail.
Note this fact in the error message that is printed in this situation.
2013-03-11 14:27:56 +00:00
Richard W.M. Jones
02159e9aa8 launch: libvirt: Print proper dotted libvirt version. 2013-03-11 14:05:33 +00:00
Richard W.M. Jones
fe3798f366 php: Print libguestfs error string if test fails. 2013-03-11 13:44:50 +00:00
Richard W.M. Jones
d44752a110 php: Fix test, /dev/null format must be "raw". 2013-03-11 13:44:33 +00:00
Richard W.M. Jones
7a968beb46 lib: Give values for each state in 'enum state'.
The values of CONFIG, LAUNCHING and READY and (kind of) exposed
through the API so shouldn't change.

Use a bad sentinel for NO_HANDLE since that indicates a serious error.
2013-03-11 12:34:22 +00:00
Richard W.M. Jones
99e5ffd1de lib: Add comment for libguestfs handle. 2013-03-11 12:32:30 +00:00
Richard W.M. Jones
d9efcfb556 RHEL 5: tests/xml: Define O_CLOEXEC in LD_PRELOAD library. 2013-03-11 11:04:38 +00:00
Richard W.M. Jones
1b5b397da8 RHEL 5: tests: Use gnulib.
Gnulib defines O_CLOEXEC which is missing on RHEL 5.
2013-03-10 20:08:59 +00:00
Richard W.M. Jones
d16bb6b70c RHEL 5: Replacement for 'Unix.isatty stdout' for old OCaml versions.
Unix.isatty missing on RHEL 5-era OCaml 3.09.3.
2013-03-09 22:32:30 +00:00
Richard W.M. Jones
e73944faf4 RHEL 5: gnulib: Use module mkstemps.
RHEL 5 glibc doesn't have this function.
2013-03-09 18:53:51 +00:00
Richard W.M. Jones
bb0617859f RHEL 5: inspect: Add macro for be32toh if one is not defined in the header files. 2013-03-09 18:53:51 +00:00
Richard W.M. Jones
74297e6109 Add suppression for memory leak in libmagic. 2013-03-08 17:03:37 +00:00
Richard W.M. Jones
52c3edd5e0 filearch: Use a more logical way to construct the cpio command. 2013-03-08 14:02:19 +00:00
Richard W.M. Jones
801487f2a7 filearch: Don't print errno if cpio command fails, print command status instead.
errno is meaningless here.
2013-03-08 13:51:18 +00:00
Richard W.M. Jones
22d82d00b4 generator: Small fix for OCaml 3.12.1.
OCaml 3.12.1 (unlike 4.00.1) doesn't let you use printf formatters
in this way:

  printf (if foo then "&%s" else "%s") str
2013-03-08 13:17:45 +00:00
Hilko Bengen
0ee24ccf8a Move Ruby-related checks from autoconf to extconf.rb; add extra check for rb_alloc_func_t
Ruby ships its own config.h which may or may not define the same
relevant constants as our autoconf-generated config.h. Instead of
trying to specify the exact path to the wanted header file we may just
as well simply use Ruby's autoconf-inspired checks and macros.
2013-03-08 12:47:24 +00:00
Richard W.M. Jones
3a895ba794 df/parallel.c: Fix if libvirt is not available at compile time. 2013-03-07 23:29:21 +00:00
Richard W.M. Jones
ef33ea359d Version 1.21.18. 2013-03-07 21:53:16 +00:00
Hilko Bengen
6557d0c082 out-of-tree build: Fix link creation 2013-03-07 21:26:05 +00:00
Hilko Bengen
a568dec4cf Still build the libguestfs-specific parts when --disable-appliance is passed to configure 2013-03-07 21:26:03 +00:00
Hilko Bengen
43b37d02a1 out-of-tree build: Fix localized manpages 2013-03-07 21:17:30 +00:00
Hilko Bengen
0a50e64435 out-of-tree build: don't distribute extconf.rb.in template, use generated exconf.rb
Apparently, the file will only be autogenerated in $(builddir) if it
is not already present in $(srcdir).
2013-03-07 21:14:11 +00:00
Richard W.M. Jones
bb1f665d7f protocol: Handle log messages from connection layer centrally.
Previously described as a "gross hack and massive layering violation".
2013-03-07 18:23:45 +00:00
Richard W.M. Jones
ed41fcd75c protocol: Abstract out socket operations from protocol code.
This creates an abstract layer below the protocol code which handles
the socket operations.  This will make it easier to introduce libvirt
virSocketPtr operations in future.

In the handle, g->conn contains the connection to the appliance.
g->conn is NULL when we're not connected.

poll(2) is used instead of select(2).

All error messages about launch failing or the appliance unexpectedly
dying are handled by two common error message functions, and these
contain a better explanation of what to do.
2013-03-07 18:15:09 +00:00
Richard W.M. Jones
06b39b8098 protocol: Remove message_summary code.
Produces lots of output, and not very helpful.
2013-03-07 16:29:12 +00:00
Richard W.M. Jones
2c8e7ba9b4 launch: unix: Set g->daemon_sock = -1 after closing it.
This ensures we don't accidentally use the closed fd.
2013-03-07 11:40:44 +00:00
Richard W.M. Jones
9ae639948a lib: Rename g->fd to console_sock and g->sock to daemon_sock.
This just renames the fields in the handle to more descriptive names.
There is no functional change.
2013-03-07 11:39:44 +00:00
Richard W.M. Jones
f9381847f1 launch: appliance: Set FD_CLOEXEC flag on console socket.
The earlier (pipe-based) code never set this flag, but that was a bug,
potentially allowing the file descriptor to be leaked to subprocesses.

Set the FD_CLOEXEC flag, but also ensure it is cleared in the child
process just before qemu is exec'd (otherwise qemu would not have a
console).
2013-03-07 11:12:04 +00:00
Richard W.M. Jones
6e7cbb09a9 launch: appliance: Use socketpair instead of pipe for qemu stdin/stdout.
The libvirt backend already uses a Unix socket for the appliance
console, and so for the libvirt backend the fields g->fd[0] == g->fd[1].

Change the appliance backend to use a socketpair, so we need just a
single file descriptor for qemu stdin/stdout (ie. appliance console).

Consequently we can remove the array int fd[2] in the handle and
replace it with a single file descriptor.
2013-03-07 09:50:36 +00:00
Richard W.M. Jones
8136ca3719 proto: send_to_daemon is not an exported function.
This function is only used inside src/proto.c, so rename
it from guestfs___send_to_daemon to just send_to_daemon.
2013-03-06 21:13:14 +00:00
Richard W.M. Jones
7de25c2bca valgrind: Add suppression for memory leak found in libselinux. 2013-03-06 14:39:07 +00:00
Richard W.M. Jones
c44c5ee268 debug: Add command to generate lots of debug messages. 2013-03-06 11:18:14 +00:00
Richard W.M. Jones
ba08a51094 launch: libvirt: When debugging, print permissions of appliance and sockets.
When debugging is enabled, this prints out the permissions (ie.
ls -laZ) of the appliance and sockets directories.  This should be
helpful for debugging RHBZ#913774.
2013-03-05 17:03:21 +00:00
Richard W.M. Jones
59f01c4a70 launch: libvirt: Rename 'is_root' as 'current_proc_is_root', and documentation. 2013-03-05 16:49:46 +00:00
Richard W.M. Jones
ed354e8f8b launch: libvirt: When root, set socket permissions to 0660 (vs 0775).
Since qemu connects to both, there was no point at all in having these
sockets be readable by other, nor executable by anyone.

The sockets should now end up as:

  srw-rw---- root.qemu
2013-03-05 16:49:46 +00:00
Richard W.M. Jones
a4a2a181c2 fuse: tests: Set FD_CLOEXEC flag on file descriptor.
This is not required here, but it helps if the test code matches what
the documentations says you should do.
2013-03-05 15:26:41 +00:00
Richard W.M. Jones
f7789acdab Version 1.21.17. 2013-03-05 14:47:10 +00:00
Richard W.M. Jones
6039689344 guestmount: Add --no-fork flag.
This prevent guestmount from daemonizing.
2013-03-05 14:40:27 +00:00
Richard W.M. Jones
0120a087f4 Add guestunmount.1.html to the website.
This fixes commit 3e9e40aee3.
2013-03-05 14:05:35 +00:00
Richard W.M. Jones
3e9e40aee3 fuse: Add guestunmount program to handle unmounting (RHBZ#916780). 2013-03-05 13:12:25 +00:00
Richard W.M. Jones
09442d0588 fuse: guestfs_umount_local is not thread-safe.
Despite what the documentation may have said, it certainly was not
safe to call guestfs_umount_local from another thread.

guestfs_umount_local could generate events, call the error handler, or
access other fields in the handle, with no locking at all.

We should aim to make guestfs_umount_local thread-safe in future.

See also:
https://bugzilla.redhat.com/show_bug.cgi?id=917706
2013-03-04 15:31:41 +00:00
Richard W.M. Jones
d08f5ebd9a generator: Generate guestfs_user_cancel.
This function is now generated, so bindings in various languages
are made automatically.

Note that the function previously returned void, but now it returns
int (although always 0).  We don't believe that this is an ABI break
since existing programs will continue to work.
2013-03-04 15:24:26 +00:00
Richard W.M. Jones
ac2f6c4ef2 generator: Add 'wrapper' flag to control when wrapper is generated.
Non-daemon functions normally have a wrapper function called
eg. guestfs_name.  The "real" (ie. hand-written) function is called
eg. guestfs__name.  The wrapper deals with checking parameters and
doing trace messages.

This commit allows the wrapper function to be omitted.  The reason is
so that we can handle a few functions that have to be thread-safe
(currently just: guestfs_user_cancel).  The wrapper is not thread safe
because it can call events and/or the error handler.
2013-03-04 15:24:05 +00:00
Richard W.M. Jones
4236929fbb generator: Typo in comment: "Checking" -> "Check". 2013-03-04 15:07:50 +00:00
Richard W.M. Jones
9b7de52d58 threads: Note that even innocent-looking functions need a mutex.
RWMJ was caught out by this one ...
2013-03-04 15:07:50 +00:00
Richard W.M. Jones
66351f7494 trace: Put trace buffer on the stack instead of in the handle.
This makes more sense, and makes the code slightly closer to being
thread safe (although it's still NOT thread safe).
2013-03-04 15:07:50 +00:00
Richard W.M. Jones
8e2b920fe6 FAQ: Add question about running fsck on live filesystems. 2013-03-01 16:25:41 +00:00
Richard W.M. Jones
7d8b97559b Version 1.21.16. 2013-03-01 15:55:18 +00:00
Richard W.M. Jones
7f5bedd53b lib: Check calls to xmlXPathEvalExpression for nodesetval == NULL.
libxml2 xmlXPathEvalExpression can return an unusual nodeset:

  $1 = {type = XPATH_NODESET, nodesetval = 0x0, boolval = 0, floatval = 0,
    stringval = 0x0, user = 0x0, index = 0, user2 = 0x0, index2 = 0}

Note that the nodeset is non-NULL, but the nodesetval is NULL.

Check every call site and fix those that don't deal with this
correctly.
2013-03-01 14:44:51 +00:00
Richard W.M. Jones
3adb0d6d01 add-domain: Move 'connect_live' function.
This is just code motion.
2013-03-01 14:12:47 +00:00
Richard W.M. Jones
e78a2c5df3 add-domain: Pass SELinux label from guest to appliance (RHBZ#912499).
When adding a domain (ie. guestfs_add_domain), read the SELinux
<label/> and <imagelabel/> from the guest and use them for the
appliance.  The appliance is statically labelled the same as the
guest, so it is able to read its disks.

However tell libvirt not to try relabelling the disks, to prevent
libvirt from disturbing the existing labels on the disks (in
particular when the libvirt connection is closed, we don't want
libvirt to try to restore some other label on the disks).

Updated with feedback from Matthew Booth.
2013-03-01 14:12:33 +00:00
Richard W.M. Jones
26df366d3b launch: libvirt: Allow the SELinux label to be set on qcow2 overlay files.
When a disk is opened readonly, the libvirt attach-method privately
creates a qcow2 overlay on top.

This commit lets that overlay get an SELinux label, and sets it to the
imagelabel specified by guestfs_internal_set_libvirt_selinux_label.

The above only applies to the libvirt attach-method.
2013-02-28 15:49:28 +00:00
Richard W.M. Jones
b9ee8baa49 New internal API: internal_set_libvirt_selinux_norelabel_disks.
If set, this causes <seclabel model=selinux relabel=no> to be added to
the disk element in the libvirt XML.

It has no effect *except* on the libvirt attach method when SELinux
and sVirt is being used.
2013-02-28 15:49:27 +00:00
Richard W.M. Jones
617eb88c5e New internal API: internal_set_libvirt_selinux_label
This internal API sets two SELinux labels in the handle (the process
label and the image label -- they are closely related).

If using the libvirt attach-method with SELinux and sVirt, then this
will cause the following XML to be added to the appliance definition:

<seclabel type=static model=selinux relabel=yes>
  <label>[LABEL HERE]</label>
  <imagelabel>[IMAGELABEL HERE]</imagelabel>
</seclabel>

It is ignored by other attach-methods.
2013-02-28 15:49:27 +00:00
Richard W.M. Jones
a6a703253b add-domain: Refactor domain XML parsing code.
This is just code motion.
2013-02-28 15:49:27 +00:00
Richard W.M. Jones
d01ac17559 test-tool: Give an error if there are extra arguments on the command line. 2013-02-28 15:22:06 +00:00
Richard W.M. Jones
3f1e7f1078 launch: libvirt: Refactor SELinux warning code.
This is just code motion.
2013-02-28 13:38:25 +00:00
Richard W.M. Jones
93feaa4ae8 parallel: Don't access the global handle from multiple threads.
libguestfs handles are not thread safe, and it's not safe even to read
settings from the handle from multiple threads (eg. guestfs_get_trace).
Stop doing this in the parallel library.  This caused fairly
reproducible segfaults when you enabled '-x' and/or '-v'.

This fixes commit 34e77af1bf.
2013-02-28 13:38:25 +00:00
Richard W.M. Jones
ce7cffa85a libutils: Don't include "guestfs-internal.h".
This mini-library shouldn't access library-internal stuff.  It should
only use the "guestfs-internal-frontend.h" header.
2013-02-27 14:07:25 +00:00
Richard W.M. Jones
1ea7752e95 lib: Move 'for_each_disk' function back into libvirt-domain.c.
This function is no longer called from anywhere outside the library,
or even outside libvirt-domain.c.

This is just code motion, except for the size_t changes which are
required in order to avoid signed overflow optimization error:

  assuming signed overflow does not occur when simplifying conditional
  to constant [-Werror=strict-overflow]
2013-02-27 11:33:05 +00:00
Richard W.M. Jones
4c5c555eeb generator: Line up GUESTFS_EVENT_ALL. 2013-02-26 22:11:40 +00:00
Richard W.M. Jones
c29660588f generator: Remove "deprecated macros for internal functions".
No need for these since these are internal functions that only code
under our control should have been calling.
2013-02-26 22:08:53 +00:00
Richard W.M. Jones
1ea73f4bdf Version 1.21.15. 2013-02-26 18:48:15 +00:00
Richard W.M. Jones
db30fe0cb0 lib: Fix memory leak in guestfs_list_filesystems.
This fixes commit 6e7f052ef4.
2013-02-26 18:48:15 +00:00
Richard W.M. Jones
b6cbd980fb tests: Add tests of guests to virt-df and virt-alignment-scan. 2013-02-26 18:48:14 +00:00
Richard W.M. Jones
5ff3845d28 tests: guests: Add blank disks plus libvirt test:// XML.
You can now run virt-df and virt-alignment-scan on all of the test
guests by doing:

./run ./df/virt-df -c test:///path/to/tests/guests/guests.xml
./run ./align/virt-alignment-scan -c test:///path/to/tests/guests/guests.xml

which is kinda cool.
2013-02-26 18:48:14 +00:00
Richard W.M. Jones
fe939cf842 lib: Turn guestfs___for_each_disk back into an internal library function.
Since the refactoring of virt-df and virt-alignment-scan, those
tools no longer use this function.
2013-02-26 17:02:32 +00:00
Richard W.M. Jones
6e3aab2f0c Partial rewrite of virt-alignment-scan to use parallel threads.
See previous commit (virt-df equivalent change) for the rationale.
2013-02-26 17:02:32 +00:00
Richard W.M. Jones
34e77af1bf Partial rewrite of virt-df to use parallel threads instead of single appliance.
Previously when you asked virt-df to show stats for all your libvirt
guests, it used a single appliance and tried to attach as many disks
as possible to it, even disks from different guests.

However this has been problematic: Not only is the code to do this
horrendously complex, but it's also insecure, and it doesn't interact
well with sVirt labels (see RHBZ#912499 comment 7).

In the meantime we discovered that running parallel appliances gives
you most of the performance of using a single appliance, but with a
lot less complexity and better guest isolation (see the documentation
in commit 680450f3b4).

Therefore this is a partial rewrite of virt-df so that in this case it
now uses parallel appliances.

Notes:

The '--one-per-guest' option is now the default and only way to do
things; this option now does nothing.

By default, the amount of parallelism to use is controlled by the
amount of free memory seen when virt-df starts up (subject to some
minima and maxima).  The user can control this through new command
line option '-P'.
2013-02-26 17:02:32 +00:00
Richard W.M. Jones
76266be549 lib: Export guestfs___add_libvirt_dom for use by virt-df and virt-alignment-scan.
See the comment in guestfs-internal-frontend.h in this commit.
2013-02-26 17:02:32 +00:00
Richard W.M. Jones
556e109765 tools: Introduce a mini-library for estimating max threads based on free memory.
This mini-library runs the 'free -m' command and greps the output to
estimate the max. number of libguestfs appliances we could run in
parallel in the remaining free memory.
2013-02-26 17:02:23 +00:00
Richard W.M. Jones
f8b92c0668 df: Always have TESTS= line even if appliance is disabled. 2013-02-26 17:02:23 +00:00
Richard W.M. Jones
a885dd025d virt-alignment-scan: Set LANG=C in test. 2013-02-26 17:02:23 +00:00
Richard W.M. Jones
4a6c8021b5 lib: Add a global MIN macro to guestfs-internal-all.h. 2013-02-26 10:13:00 +00:00
Richard W.M. Jones
d02610853d Version 1.21.14. 2013-02-25 17:39:11 +00:00
Hilko Bengen
ff0269e80f out-of-tree build: fix test-tool
(Not entirely sure whether using Gnulib to replace standard functions
is a good idea at all.)

link with libgnu:
  CCLD   libguestfs-test-tool
libguestfs_test_tool-test-tool.o: In function `main':
/home/bengen/src/deb/pkg-libvirt/libguestfs/debian/build-default/test-tool/../../../test-tool/test-tool.c:103: undefined reference to `rpl_getopt_long'
/home/bengen/src/deb/pkg-libvirt/libguestfs/debian/build-default/test-tool/../../../test-tool/test-tool.c:113: undefined reference to `rpl_optarg'
/home/bengen/src/deb/pkg-libvirt/libguestfs/debian/build-default/test-tool/../../../test-tool/test-tool.c:125: undefined reference to `rpl_optarg'
/home/bengen/src/deb/pkg-libvirt/libguestfs/debian/build-default/test-tool/../../../test-tool/test-tool.c:126: undefined reference to `rpl_optarg'
/home/bengen/src/deb/pkg-libvirt/libguestfs/debian/build-default/test-tool/../../../test-tool/test-tool.c:109: undefined reference to `rpl_optarg'
libguestfs_test_tool-test-tool.o: In function `set_qemu':
/home/bengen/src/deb/pkg-libvirt/libguestfs/debian/build-default/test-tool/../../../test-tool/test-tool.c:382: undefined reference to `rpl_perror'
/home/bengen/src/deb/pkg-libvirt/libguestfs/debian/build-default/test-tool/../../../test-tool/test-tool.c:366: undefined reference to `rpl_perror'
libguestfs_test_tool-test-tool.o: In function `make_files':
/home/bengen/src/deb/pkg-libvirt/libguestfs/debian/build-default/test-tool/../../../test-tool/test-tool.c:416: undefined reference to `rpl_perror'
/home/bengen/src/deb/pkg-libvirt/libguestfs/debian/build-default/test-tool/../../../test-tool/test-tool.c:428: undefined reference to `rpl_perror'
2013-02-25 16:21:48 +00:00
Hilko Bengen
cd1558b89e out-of-tree build: fix daemon
CC     guestfsd-9p.o
In file included from ../../../daemon/9p.c:32:0:
../../../daemon/daemon.h:33:34: fatal error: guestfs-internal-all.h: No such file or directory
2013-02-25 16:21:48 +00:00
Richard W.M. Jones
680450f3b4 docs: Update guestfs-performance with parallel scaling numbers and test script. 2013-02-25 16:01:15 +00:00
Olaf Hering
ff80a54011 lib: avoid pragma usage in inspect-fs-windows
pragma GCC diagnostic is a gcc 4.6+ feature, compilation fails with
older compilers:

inspect-fs-windows.c: In function 'map_registry_disk_blob':
inspect-fs-windows.c:502: error: #pragma GCC diagnostic not allowed inside functions
inspect-fs-windows.c:503: error: #pragma GCC diagnostic not allowed inside functions
inspect-fs-windows.c:505: error: #pragma GCC diagnostic not allowed inside functions
make[3]: *** [libguestfs_la-inspect-fs-windows.lo] Error 1

Use memcpy instead of pragma to fix compile error.

Signed-off-by: Olaf Hering <olaf@aepfle.de>
2013-02-25 11:18:36 +00:00
Richard W.M. Jones
455d6b1845 recipes: Add example converting from one format/filesystem to another. 2013-02-23 20:59:26 +00:00
Richard W.M. Jones
fadec0687f daemon: protocol: Fix memory leak when receiving FileIn file (RHBZ#914934).
This fixes commit 950951c67d.
2013-02-23 20:32:33 +00:00
Richard W.M. Jones
4136850f3c tests: Add a regression test for RHBZ#914931.
This involves adding a new test API which crashes the appliance in the
middle of a simulated upload, then a test which uses that API to test
for the libguestfs (library-side) crash.
2013-02-23 20:23:51 +00:00
Richard W.M. Jones
7953128ca6 protocol: Don't segfault if appliance crashes during FileIn upload (RHBZ#914931).
Instead of the segfault you now get a more informative error:

*stdin*:0: libguestfs: error: connection to daemon was closed unexpectedly.
This usually means the libguestfs appliance crashed.  Please enable
debugging (LIBGUESTFS_DEBUG=1) and rerun the command, then look at the
debug messages output prior to this error.
libguestfs: error: /dev/stdout: write: Broken pipe
libguestfs: error: file receive cancelled by daemon
2013-02-23 20:23:39 +00:00
Richard W.M. Jones
d950e1a3bc run: Refer to README and correct documentation for linking to script.
Any link works, even a hard link.
2013-02-23 08:19:10 +00:00
Richard W.M. Jones
1ca842d98b run: Relicense as LGPLv2+.
To allow reuse in other projects and because of the equivalent change
made by Eric Blake to the libvirt 'run' script.
2013-02-23 08:15:23 +00:00
Richard W.M. Jones
37796d70bf Update API support. 2013-02-20 23:20:45 +00:00
Richard W.M. Jones
b49eefdb15 Version 1.21.13. 2013-02-20 22:23:20 +00:00
Richard W.M. Jones
9d6aa8b537 Use guestfs___count_strings instead of custom versions in various places. 2013-02-20 22:18:10 +00:00
Richard W.M. Jones
907fbfff53 python: Use guestfs___free_string_list instead of custom version. 2013-02-20 22:18:10 +00:00
Richard W.M. Jones
4ede94ab7b ocaml: Use guestfs___free_string_list instead of custom-coded one.
It should be possible to add the guestfs___free_string_list to
dllmlguestfs.so, but I cannot work out exactly how to do this.  As a
result we end up using src/utils.c directly.
2013-02-20 22:18:10 +00:00
Richard W.M. Jones
6ee164d47a ocaml: Missing #include <config.h> in generated file. 2013-02-20 22:18:10 +00:00
Richard W.M. Jones
27e6347b75 lua: Use guestfs___free_string_list instead of custom-coded version. 2013-02-20 22:18:09 +00:00
Richard W.M. Jones
0b7acf50b6 fish: Use guestfs___{free_string_list,count_strings} utility functions.
Instead of custom-coded versions.
2013-02-20 19:32:11 +00:00
Richard W.M. Jones
e27295c578 libutils: Add guestfs___count_strings utility function to common library. 2013-02-20 19:24:21 +00:00
Richard W.M. Jones
7ef461948e erlang: Use guestfs___free_string_list from libutils, instead of custom version. 2013-02-20 19:16:47 +00:00
Richard W.M. Jones
04723b4dd1 lib: Create libutils convenience library.
The libutils convenience library is a place for code shared between
the main library, language bindings and virt tools.  Note that the
code is statically linked into both the library, each binding and each
tool, but this is an improvement because (a) the source is shared and
(b) libguestfs.so can export fewer private functions.

Currently it contains the cleanup functions, and the functions
guestfs___free_string_list function and guestfs___for_each_disk.

guestfs___for_each_disk has changed so that it no longer
unconditionally sets the error in the guestfs handle.  Instead callers
can control error handling.
2013-02-20 19:15:05 +00:00
Richard W.M. Jones
a4953090e1 lib: Rename guestfs_error_errno as guestfs___error_errno, etc.
These are internal functions.  Very old versions of libguestfs used to
export them, but they haven't been (and shouldn't be) exported for a
long time.

Also remove the unused guestfs_error function.
2013-02-20 17:09:52 +00:00
Richard W.M. Jones
1a2465c187 build: Remove long and mostly irrelevant comment about libtool versioning. 2013-02-20 16:05:11 +00:00
Richard W.M. Jones
2101324965 build: Rearrange src/Makefile.am into a more logical order.
This is just code motion.
2013-02-20 16:03:14 +00:00
Richard W.M. Jones
6566621345 tests: Add valgrind suppression for libvirt 1.0.2 memory leak.
Leak reported as RHBZ#913145.
2013-02-20 14:20:08 +00:00
Richard W.M. Jones
b7ab6de628 tests: Add valgrind suppression variant for new manifestation of an old libvirt memory leak. 2013-02-20 14:19:37 +00:00
Richard W.M. Jones
61162bdce1 lib: Use CLEANUP_* macros to simplify XPath query code. 2013-02-20 13:50:43 +00:00
Richard W.M. Jones
b10a6cfe24 rescue: Improve error messages in the test script. 2013-02-20 11:28:50 +00:00
Richard W.M. Jones
175d6ba432 faq: Add section for developers, including how to send patches and propose features. 2013-02-20 10:30:44 +00:00
Richard W.M. Jones
065861ce6b docs: Rewrite security section (thanks Dan Berrange). 2013-02-20 10:08:21 +00:00
Richard W.M. Jones
8671cfa343 Version 1.21.12. 2013-02-19 19:19:29 +00:00
Richard W.M. Jones
a1c89bf03d build: Only add 'serial-tests' for automake >= 1.12 (thanks Hilko Bengen).
Earlier versions of automake complain if they get a configuration
parameter which they don't understand.  The error is:

configure.ac:27: error: option 'serial-tests' not recognized

Use some m4 hackery to work around this.
2013-02-19 19:19:22 +00:00
Richard W.M. Jones
c7ba91761c handle: Define DEFAULT_MEMSIZE, MIN_MEMSIZE constants.
This is just code motion.
2013-02-19 14:30:20 +00:00
Richard W.M. Jones
70514c7f7e ruby: Add binding for guestfs_event_to_string. 2013-02-19 13:41:58 +00:00
Richard W.M. Jones
0f849029d1 python: Add binding for guestfs_event_to_string. 2013-02-19 13:41:58 +00:00
Richard W.M. Jones
e9d83e94a2 perl: Add binding for guestfs_event_to_string. 2013-02-19 13:41:58 +00:00
Richard W.M. Jones
7e71c9fb34 java: Use guestfs_event_to_string instead of generated code. 2013-02-19 13:41:58 +00:00
Richard W.M. Jones
2a8de9001e fish: Use guestfs_event_to_string instead of guestfish-specific generated functions. 2013-02-19 13:41:57 +00:00
Richard W.M. Jones
5c513060b1 ocaml: Add binding for Guestfs.event_to_string and use it in events test. 2013-02-19 13:41:57 +00:00
Richard W.M. Jones
b793fafcb7 New C only API: guestfs_event_to_string. 2013-02-19 13:41:57 +00:00
Richard W.M. Jones
6902f093ff handle: Translatable string in guestfs_parse_environment. 2013-02-18 14:02:21 +00:00
Richard W.M. Jones
0e0eec76d9 generator: Whitespace changes. 2013-02-18 13:04:24 +00:00
Richard W.M. Jones
cbfa394bfc lib: Fix memory leak when the 'lpj' setting is read from dmesg.
It was failing to clean up and close the 'struct command' buffer,
because commit 94d90f03e2 added an
incomplete patch to use CLEANUP_CMD_CLOSE.

This fixes commit 94d90f03e2.
2013-02-15 14:44:22 +00:00
Richard W.M. Jones
5c6895bda1 java: Print a better error message when JVM version is too old.
This fixes commit 87d1f7714f.
2013-02-15 14:25:25 +00:00
Richard W.M. Jones
87d1f7714f java: Note that JVM >= 1.6 is now required. 2013-02-15 12:57:19 +00:00
Richard W.M. Jones
c598e14052 appliance: Use a glibc trick to try to display a stack trace if a program in the appliance segfaults. 2013-02-14 22:15:25 +00:00
Richard W.M. Jones
989d3c7691 Version 1.21.11. 2013-02-14 18:10:02 +00:00
Richard W.M. Jones
9021351c8e tests: mountable: Add test-mountable-inspect.sh to EXTRA_DIST.
This fixes commit 7d976657e6.
2013-02-14 16:33:29 +00:00
Matthew Booth
52b7418670 Fix API doc errors 2013-02-13 10:38:59 +00:00
Matthew Booth
f0f8d7ce78 gobject: Fix doc generation of L<guestfs(3)/CVE-2010-3851> 2013-02-13 10:30:51 +00:00
Richard W.M. Jones
23f8bd4fac daemon: Fix RESOLVE_MOUNTABLE, internal_parse_mountable.
- The mountable->volume field was not being initialized on the
  device path.

- XDR string fields cannot be NULL.

This fixes commit 7d976657e6.
2013-02-12 17:09:44 +00:00
Richard W.M. Jones
db554cf271 tests: mountable: Print error message if guestfs_create fails. 2013-02-12 17:02:33 +00:00
Richard W.M. Jones
4f7d1b3ae7 tests: Add Fedora btrfs phony guest to target list.
This fixes commit 754e819438.
2013-02-12 17:01:44 +00:00
Richard W.M. Jones
77c57ab843 tests: Reorder the tests so test guest is created before it's used by mountable test.
This fixes commit 7d976657e6.
2013-02-12 17:00:10 +00:00
Richard W.M. Jones
1399005d7e examples: Ensure each example program is documented. 2013-02-12 16:31:10 +00:00
Richard W.M. Jones
e84d6e6102 examples: Rename example programs, replacing '_' with '-'. 2013-02-12 16:31:10 +00:00
Matthew Booth
4215d0ca68 mountable: Test inspection of fedora image 2013-02-12 15:51:15 +00:00
Matthew Booth
7ba0e10501 inspect: Update inspect_os to use mountables
This fixes inspection of guests which use btrfs subvolumes.
2013-02-12 15:51:15 +00:00
Matthew Booth
7d976657e6 New internal API: internal_parse_mountable 2013-02-12 15:51:06 +00:00
Matthew Booth
b0abf10b9f build: Minor cleanup in daemon/Makefile.am 2013-02-12 15:29:19 +00:00
Matthew Booth
754e819438 btrfs: Make a stub Fedora btrfs guest for inspection testing 2013-02-12 13:49:26 +00:00
Matthew Booth
6e7f052ef4 mountable: Make list-filesystems return btrfsvols 2013-02-12 13:45:54 +00:00
Matthew Booth
bcb933a0c1 btrfs: Update btrfs_subvolume_list to take Mountable_or_Path
btrfs_subvolume_list can now take either the path of a mounted btrfs
filesystem, or a mountable describing the location of a btrfs
filesystem, or one of its volumes. In the latter case, the filesystem
will be automatically mounted outside of /sysroot before running the
btrfs tool, and unmounted afterwards.
2013-02-12 13:39:14 +00:00
Matthew Booth
72aaf56fed mount: Add mount_vfs_nochroot
This internal function allows mounting a mountable outside /sysroot.
2013-02-12 13:38:51 +00:00
Richard W.M. Jones
ec6a4de37a faq: Add common questions about virt-resize/virt-sparsify in place support. 2013-02-12 12:04:35 +00:00
Richard W.M. Jones
954e315d21 faq: Fix some small typos in section on virt-sparsify. 2013-02-12 11:56:16 +00:00
Richard W.M. Jones
6c5577e403 faq: Update RHEL information. 2013-02-12 11:55:45 +00:00
Richard W.M. Jones
cd47df1fe5 test-tool: Point to SELinux documentation for further information. 2013-02-12 10:55:26 +00:00
Richard W.M. Jones
0e79b9dd03 examples: Add all the C examples to the guestfs-examples(3) man page. 2013-02-11 21:44:39 +00:00
Richard W.M. Jones
09c4f94c9d build: Separate out *_CPPFLAGS from *_CFLAGS.
This is pretty pointless.
2013-02-11 21:36:27 +00:00
Richard W.M. Jones
bbb637f962 test-tool: Get rid of the "=== Test starts here ===" banner.
It confuses things, because that is not always the start
of the output.
2013-02-11 21:22:25 +00:00
Richard W.M. Jones
ee61d16e3e test-tool: Display SELinux status in output of libguestfs-test-tool. 2013-02-11 21:21:01 +00:00
Richard W.M. Jones
45b4271579 Version 1.21.10. 2013-02-11 19:38:55 +00:00
Richard W.M. Jones
05444da983 tests: Add a regression test for stack overflow in events (RHBZ#909624).
Note this is a check-slow test since generating 1,000,000 progress
events take a few minutes.
2013-02-11 18:15:48 +00:00
Richard W.M. Jones
b3cf5d1d96 proto: Fix stack overflow when there are many progress events (RHBZ#909624).
Thanks: Eric Blake.
2013-02-11 18:15:48 +00:00
Richard W.M. Jones
a43f88b1c5 daemon: Allow rate to be specified in 'debug progress'.
There are now two forms of the 'debug progress' command:

(1) debug progress <n> (the original form) generates ordinary
rate-limited progress messages for <n> seconds.

(2) debug progress <n> <rate> generates progress messages every <rate>
microseconds for <n> seconds.

The second form omit the usual rate-limiting, and so wouldn't
be generated like this from an ordinary API call.  However this
is useful for testing events (see RHBZ#909624).
2013-02-11 18:02:55 +00:00
Matthew Booth
942e139562 mountable: Implement Mountable_or_Path
A Mountable_or_Path argument is passed as a mountable_t. A new type is
added to mountable_t to handle already mounted paths.
2013-02-11 16:54:42 +00:00
Richard W.M. Jones
93d4fddaef lib: Add format attribute for GCC 4.8 in two places. 2013-02-11 16:10:17 +00:00
Richard W.M. Jones
984431a9ef daemon: Force disable -Wsuggest-attribute=format warning around asprintf_nowarn, for GCC 4.8. 2013-02-11 16:10:17 +00:00
Richard W.M. Jones
f226133c1a lib: Define GUESTFS_GCC_VERSION in the internal header.
Note that you have to use this as follows:

#if defined(__GNUC__) && GUESTFS_GCC_VERSION >= x0y0z /* gcc >= x.y.z */

since GUESTFS_GCC_VERSION is not defined unless it's GCC.
2013-02-11 16:10:17 +00:00
Matthew Booth
ef2276654e generator: Create Mountable_or_Path, initially identical to Dev_or_Path 2013-02-11 15:43:53 +00:00
Matthew Booth
47b929b789 mountable: Implement Mountable support for all apis which take it
A Mountable is passed from the library to the daemon as a string. The daemon
stub parses it into a mountable_t, which it passes to the implementation.

Update all implementations which now take a mountable_t.
2013-02-11 15:42:58 +00:00
Matthew Booth
d5817537fa generator: Convert relevant arguments from Device to Mountable
This change updates the api style of all apis which should take Mountable
descriptions rather than block devices. It also updates the documentation
accordingly, but doesn't implement any functional changes.
2013-02-11 15:39:31 +00:00
Richard W.M. Jones
007c2f236d test-tool: Document how to change SELinux settings. 2013-02-11 14:14:36 +00:00
Richard W.M. Jones
b1a89d3b1c test-tool: Document how to run with alternate libvirt. 2013-02-11 14:13:44 +00:00
Richard W.M. Jones
3877cab329 test-tool: exec qemu in the wrapper script.
This ensures that libvirt can control qemu directly, eg. being able to
send it signals.
2013-02-11 13:41:40 +00:00
Richard W.M. Jones
20fd81147d test-tool: On i386, upstream qemu program is now called 'qemu-system-i386'.
For a while, the upstream qemu i386 emulator has been called
'qemu-system-i386' (instead of just 'qemu').  Fix test-tool so it
calls the right program.
2013-02-11 13:21:51 +00:00
Richard W.M. Jones
df983d1994 test-tool: Don't call guestfs_set_qemu before guestfs handle is initialized (RHBZ#909836).
Because of evolution of the code, if the user used the --qemu or
--qemudir options, libguestfs-test-tool would segfault because
guestfs_set_qemu was being called before the guestfs handle was
opened.

Change the code so this doesn't happen, and also remove the global 'g'
variable to make the code a bit more robust.

Bug found by Amit Shah.
2013-02-11 13:21:51 +00:00
Richard W.M. Jones
e4495b24bc daemon: link: Remove use of PATH_MAX.
Replace readlink calls with gnulib areadlink function.
2013-02-11 13:21:51 +00:00
Richard W.M. Jones
c3afef3eec daemon: xattr: Remove use of PATH_MAX. 2013-02-11 13:21:51 +00:00
Richard W.M. Jones
09f3913734 daemon: realpath: Remove use of both PATH_MAX and NAME_MAX. 2013-02-11 13:21:51 +00:00
Richard W.M. Jones
9c9ceec6b7 daemon: initrd: Remove use of PATH_MAX and other cleanups.
- Move variables to the top.
- Rearrange comments to make more sense.
2013-02-11 13:21:51 +00:00
Richard W.M. Jones
1703c6841b daemon: find0: Remove use of PATH_MAX. 2013-02-11 13:21:51 +00:00
Richard W.M. Jones
e527aed895 getline: Rename &n parameter as &allocsize.
The second parameter passed into getline(3) is the size of the
allocated buffer, *NOT* the length of the returned line.  This can be
confusing, so rename this parameter as 'allocsize' consistently
throughout the code.

This is just code motion.
2013-02-11 13:21:51 +00:00
Richard W.M. Jones
e0a3a7c1e5 docs: Improve reasons for using libguestfs-make-fixed-appliance.
Thanks: Richard Harman.
2013-02-09 22:38:24 +00:00
Richard W.M. Jones
d6c0ff055d launch: libvirt: Make it clear that setsockcreatecon debug message is just a warning.
This was disturbing to some users, but other users saw the warning
when it was really something they should pay attention to.  Make it
clear that it's a warning, unless people are really using SELinux +
sVirt.

Thanks: Richard Harman.
2013-02-09 21:29:35 +00:00
Richard W.M. Jones
8ad8e1075b Version 1.21.9. 2013-02-09 21:02:11 +00:00
Richard W.M. Jones
d538af8a0a rescue: Count the mountable filesystems when displaying the 'suggest' message. 2013-02-09 20:53:18 +00:00
Richard W.M. Jones
4255db65e5 tools: Use CLEANUP_* macros in several C tools. 2013-02-09 20:37:03 +00:00
Richard W.M. Jones
20a562321c generator: Export libxml2 CLEANUP_* macros unconditionally.
These call abort() if libxml2 is not actually installed, but that
should never happen inside the library or tools.
2013-02-09 17:49:11 +00:00
Richard W.M. Jones
94d90f03e2 lib: Define CLEANUP_CMD_CLOSE macro and use it throughout the library. 2013-02-08 18:14:41 +00:00
Richard W.M. Jones
59b296fecc tools, tests: Use "guestfs-internal-frontend.h" header.
Instead of redefining STREQ, etc.
2013-02-08 16:15:25 +00:00
Richard W.M. Jones
30029b7ffb lib: Use CLEANUP_FREE_<struct>, CLEANUP_FREE_<struct>_LIST macros in a few places in the library. 2013-02-08 16:12:04 +00:00
Richard W.M. Jones
5f54da6fdf lib: Add CLEANUP_FREE_<struct>, CLEANUP_FREE_<struct>_LIST macros for API structs.
For example:

 {
   CLEANUP_FREE_STAT struct guestfs_stat *stat = guestfs_stat (g, "/foo");

   // stat is freed automatically when we leave the scope.
 }

The new header file "guestfs-internal-frontend-cleanups.h"
includes definitions for these.  It should not be included
directly.
2013-02-08 16:12:04 +00:00
Richard W.M. Jones
5e770c8f6a lib: Allow guestfs_free_* functions to be safely called with a NULL pointer.
This is so they work just like 'free'.
2013-02-08 16:12:04 +00:00
Richard W.M. Jones
7b7cfa62e3 lib: Remove explicit defines of _BSD_SOURCE.
An equivalent is defined already in <config.h>.
2013-02-08 16:12:04 +00:00
Richard W.M. Jones
cab1a0c1d9 generator: Add #ifndef defense around guestfs-internal-actions.h file. 2013-02-08 15:48:52 +00:00
Matthew Booth
8fb2306be4 generator: Add new Mountable argument type
This type is initially identical to Device.
2013-02-08 14:59:00 +00:00
Matthew Booth
6e7f95b669 inspect: Fix improperly ignored error in check_filesystem 2013-02-08 14:53:05 +00:00
Matthew Booth
7d6b5bb837 inspect: Don't re-implement list_filesystems in inspect_os 2013-02-08 14:42:37 +00:00
Matthew Booth
dd58db7329 Fix bogus partition number passed to guestfs___check_for_filesystem_on
Partition number was being passed to guestfs___check_for_filesystem_on
based on an index in list_partition. However, this ignores the
possibility of multiple block devices.

This change makes guestfs___check_for_filesystem_on examine the
passed-in device directly to determine if it is a whole device, or
what its partition number is.
2013-02-08 14:42:37 +00:00
Matthew Booth
a7d7e8176f New API: is_whole_device 2013-02-08 14:42:37 +00:00
Matthew Booth
3045c0cbaf btrfs: Fix btrfs_subvolume_list on F18 (RHBZ#903620).
The output of btrfs subvolume list has changed in F18 to include generation,
which breaks the parsing in btrfs_subvolume_list. This change replaces sscanf
with a more robust regular expression. The new regular expression should also
handle the addition of future unexpected columns.
2013-02-08 09:09:25 +00:00
Richard W.M. Jones
c78ec7e085 daemon: Check parameter of base64-out and tar-out before running external command (RHBZ#908322).
For base64-out, check the filename parameter exists and is not a
directory.

For tar-out, check the dir parameter exists and is a directory.
2013-02-06 14:56:56 +00:00
Matthew Booth
ca056d53bd generator: Add visibility to action struct
The visibility field in action replaces in_fish, in_docs and internal.
The defined types are:

VPublic:
  A public API. This is exported and documented in all language
  bindings, and in guestfish.

VStateTest:
  A public API which queries the library state machine. It is exported
  and documented in all language bindings, but not guestfish.

VBindTest:
  An internal API used only for testing language bindings. It is
  guarded by GUESTFS_PRIVATE in the C api, but exported by all other
  language bindings as it is required for testing. If language
  bindings offer any way to guard use of these apis, that mechanism
  should be used. It is not documented anywhere.

VDebug:
  A debugging API. It is exported by all language bindings, and in
  guestfish, but is not documented anywhere.

VInternal:
  An internal-only API. It is guarded by GUESTFS_PRIVATE in the C api,
  and not exported at all in any other language binding. It is not
  documented anywhere.
2013-02-06 13:53:28 +00:00
Richard W.M. Jones
f9bafde5e7 daemon: download: Add extra check that download file is not a directory (RHBZ#908321). 2013-02-06 13:27:26 +00:00
Richard W.M. Jones
f473a173b8 daemon: Add more information to certain calls to perror.
Replace selected calls to 'perror (filename)' with:

  fprintf (stderr, "syscall: %s: %m\n", filename);

so that more information is available about precisely which syscall
failed.

Note this is *not* reply_with_perror.  These messages are only printed
in verbose output, for the benefit of debugging.
2013-02-06 13:14:07 +00:00
Richard W.M. Jones
f631e84102 9p: Missing call to reply_with_perror. 2013-02-06 12:59:00 +00:00
Richard W.M. Jones
c98ef8d089 Version 1.21.8. 2013-02-05 20:27:25 +00:00
Richard W.M. Jones
a0a4ee5245 Use 'supermin' and 'supermin-helper' in preference to febootstrap.
Febootstrap has been renamed upstream to 'supermin':
https://www.redhat.com/archives/libguestfs/2013-February/msg00004.html

This commit changes libguestfs so it can use either program to build
the supermin appliance.
2013-02-05 15:31:05 +00:00
Richard W.M. Jones
72dd398679 daemon: Call wipefs before mkfs to work around pathological behaviour in btrfs.
See: RHBZ#907554, http://www.spinics.net/lists/linux-btrfs/msg21197.html
2013-02-04 21:54:15 +00:00
Richard W.M. Jones
7e25e0780e FAQ: Update section on sVirt. 2013-02-04 21:54:08 +00:00
Richard W.M. Jones
4075ed9247 build: Add src/guestfs-internal-{all,frontend}.h to EXTRA_DIST.
This fixes commit ec3b75e5ff.
2013-02-04 13:12:28 +00:00
Richard W.M. Jones
776ffbfaec Version 1.21.7. 2013-02-04 13:03:25 +00:00
Richard W.M. Jones
4940bd9a9e fish: Be stricter about boolean values.
Previously I noticed that bfan used this command without any error:

><fs> hivex-open /WINDOWS/system32/config/software write:ture
                                                   ^^^^^^^^^^

This was because the code allowed any string to be evaluated as a
boolean.

The new code is stricter.  It allows the following strings only case
insensitive (everything else is an error):

  1
  true
  t
  yes
  y
  on

  0
  false
  f
  no
  n
  off
2013-02-04 12:45:02 +00:00
Richard W.M. Jones
d012b729fa ruby: Include "guestfs-internal-frontend.h" in extension.
Also undefine '_' symbol defined by Ruby's internal headers.

This fixes commit ec3b75e5ff.
2013-02-04 12:17:52 +00:00
Richard W.M. Jones
9e27a1556c perl: Include "guestfs-internal-frontend.h" in XS file.
Also undefine '_' symbol defined by Perl's internal headers.

This fixes commit ec3b75e5ff.
2013-02-04 11:49:04 +00:00
Richard W.M. Jones
5e4f03ccf2 README: Format the list of requirements better. 2013-02-02 15:24:23 +00:00
Richard W.M. Jones
0d18a8b407 Update copyright dates for 2013. 2013-02-02 13:56:19 +00:00
Richard W.M. Jones
791ad3e9e6 fish: Use CLEANUP_* macros in a lot of places. 2013-02-01 16:18:42 +00:00
Richard W.M. Jones
6c1aca5ae2 fish: Use CLEANUP_FREE in parse_config. 2013-02-01 15:54:13 +00:00
Richard W.M. Jones
4b20a20d33 Remove TMP_TEMPLATE_ON_STACK macro. 2013-02-01 14:48:35 +00:00
Richard W.M. Jones
42bffcd00a Remove all occurrences of the bad_cast (lowercase) function.
Not to be confused with the libxml2 macro 'BAD_CAST' which converts
from 'signed char *' to 'unsigned char *'.

The 'bad_cast' function was defined and used all over the place as a
replacement for a '(char *)' cast.  I think it is better to make these
casts explicit, instead of hiding them in an obscure function.
2013-02-01 14:16:51 +00:00
Richard W.M. Jones
ec3b75e5ff Rearrange internal header files.
This commit rearranges the internal header files.

"src/guestfs-internal.h" is just for the library, as before.

"src/guestfs-internal-frontend.h" is for use by all library, bindings,
tools C code, but NOT the daemon.

"src/guestfs-internal-all.h" is for use by all C code including the
daemon.

This is just code motion, but it has some important consequences:

(1) We can use the CLEANUP_* macros in bindings and tools code.

(2) We can get rid of TMP_TEMPLATE_ON_STACK.

(3) We will (in future) be able to stop bindings and tools code from
using the safe_* allocation functions (which are NOT safe to use
outside the library alone).
2013-02-01 14:07:25 +00:00
Cole Robinson
63c324e6c4 tests: Handle changing QEMUDIR
qemu-wrapper isn't regenerated if QEMUDIR is changed, so just
delete it and force regeneration.

Additionally we can drop the silent binary check, since
check-with-upstream-qemu-1 already does a similar test with --version
that will actually report an error to the user.
2013-01-31 16:30:28 +00:00
Matthew Booth
27b995c841 Make internal-only functions and structures private
Certain functions are intended to be internal only, but we currently
export them anyway. This change moves them into a separate section of
guestfs.h protected by a GUESTFS_PRIVATE variable. This change also
enables private structs, but doesn't implement any.

This change only affects the C api. Language bindings aren't affected,
but probably should be in the future.
2013-01-30 17:27:01 +00:00
Matthew Booth
1dd9bf73b7 build: Fix haskell dependencies and parallel build
Without this change all the tests in the haskell bindings are rebuilt
every time. The primary motivation for this change is to fix this.

The fix for the above also allows parallel builds to be re-enabled.
2013-01-30 10:53:02 +00:00
Matthew Booth
63c50c7847 build: Add common rule for sources shared between daemon and library 2013-01-29 16:24:08 +00:00
Richard W.M. Jones
be4a3d77c4 daemon: hivex: Rewrite filename param of hivex_commit to include sysroot (RHBZ#905341). 2013-01-29 10:21:51 +00:00
Richard W.M. Jones
908c45567c Version 1.21.6. 2013-01-28 18:42:05 +00:00
Richard W.M. Jones
950951c67d daemon: Use the new CLEANUP_* macros to simplify code. 2013-01-28 18:01:43 +00:00
Richard W.M. Jones
233055974d daemon: Add CLEANUP_* macros which automatically free memory when leaving scope.
cf commit 98b64650c8
2013-01-28 18:01:39 +00:00
Richard W.M. Jones
071de5ccfb daemon: Allow free_strings (NULL) and free_stringslen (NULL, ..).
Equivalent to free (NULL).
2013-01-28 18:01:20 +00:00
Richard W.M. Jones
3a8a62c3e4 lib: Further use of CLEANUP_* macros. 2013-01-28 18:01:19 +00:00
Richard W.M. Jones
cd3b626a33 launch: libvirt: Use CLEANUP_* macros.
Also implement macros for cleaning up libxml2 objects.
2013-01-28 18:01:19 +00:00
Richard W.M. Jones
5a3da36626 inspect: Use CLEANUP_* macros in inspection code. 2013-01-28 18:01:19 +00:00
Richard W.M. Jones
98b64650c8 lib: Add CLEANUP_* macros which automatically free things when leaving scope.
Use the macro like this to create temporary variables which are
automatically cleaned up when the scope is exited:

  {
    CLEANUP_FREE char *foo = safe_strdup (bar);
    ...
    // no need to call free (foo)!
  }

The following code is also valid.  The initialization of foo as 'NULL'
prevents any chance of free being called on an uninitialized pointer.
It may not be required in all cases.

  {
    CLEANUP_FREE char *foo = NULL;
    ...
    foo = safe_malloc (100);
    ...
    // no need to call free (foo)!
  }

This is also valid:

  {
    CLEANUP_FREE char *foo = ..., *bar = ...;
    ...
    // no need to call free (foo) or free (bar)!
  }

The CLEANUP_FREE_STRING_LIST macro calls guestfs___free_string_list
on its argument.  The argument may be NULL.

The CLEANUP_HASH_FREE macro calls hash_free on its argument.  The
argument may be NULL.

Important implementation note:
------------------------------

On GCC and LLVM, this is implemented using __attribute__((cleanup(...))).

There is no known way to implement this macro on other C compilers, so
this construct will cause a resource leak.

Important note about close/fclose:
----------------------------------

We did NOT implement 'CLEANUP_CLOSE' or 'CLEANUP_FCLOSE' macros.  The
reason is that I am not convinced that these can be used safely.  It
would be OK to use these to collect file handles along failure paths,
but you would still want a regular call to 'close'/'fclose' since you
must test for errors, and so you end up having to do:

  if (close (fd) == -1) {
    // failure case
    // avoid double-close in cleanup handler:
    fd = -1;
    ...
  }
  // avoid double-close in cleanup handler:
  fd = -1;
  ...
2013-01-28 18:01:19 +00:00
Richard W.M. Jones
acb85dafb1 Allow guestfs___free_string_list (NULL).
Equivalent to free (NULL).
2013-01-28 18:01:19 +00:00
Richard W.M. Jones
aab796c608 perl, python, ruby: Add definition of EVENT_ALL in these languages. 2013-01-28 18:01:19 +00:00
Richard W.M. Jones
27c81f3175 generator: Define all_events_bitmask.
In the C bindings, use this more accurate mask instead of 'all bits
set'.

In the Java bindings, use this instead of open coding.
2013-01-28 18:01:19 +00:00
Richard W.M. Jones
ded72a96f0 header: Minor whitespace fix. 2013-01-28 18:01:19 +00:00
Richard W.M. Jones
f3976de591 header: Deprecate LIBGUESTFS_HAVE_* in favour of GUESTFS_HAVE_*. 2013-01-28 18:01:19 +00:00
Richard W.M. Jones
d3068a3aff header: Link to guestfs-examples(3) man page from header file. 2013-01-28 18:01:19 +00:00
Matthew Booth
a0d874725d Update vim line length to 70
Apparently this makes it the same as emacs or something.
2013-01-24 15:00:49 +00:00
Richard W.M. Jones
abb1d46636 python: Inherit from 'object' base class.
This fixes the following Debian bug:
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=698771

For an overview, see this question and the links from there:
http://stackoverflow.com/questions/4015417/python-class-inherits-object
2013-01-24 13:09:16 +00:00
Richard W.M. Jones
ec8939fd47 launch: libvirt: Add 'is_root' flag to the params struct.
This is just code motion, but it allows us to read this flag inside
the 'construct_libvirt_xml_seclabel' function in future (as a possible
way to fix RHBZ#890291).
2013-01-22 14:43:37 +00:00
Richard W.M. Jones
085b86a95a libvirt: Add debugging when opening libvirt handle.
When debugging is enabled, this produces output like below.  This is
useful when diagnosing what URI libguestfs is using.

libguestfs: opening libvirt handle: URI = NULL, auth = virConnectAuthPtrDefault, flags = 0
libguestfs: successfully opened libvirt handle: conn = 0xb05580
2013-01-22 13:50:57 +00:00
Richard W.M. Jones
875dc11364 launch: libvirt: Refactor seclabel code.
This is just code motion.
2013-01-22 13:45:11 +00:00
Richard W.M. Jones
ed5a083891 Version 1.21.5. 2013-01-21 22:16:07 +00:00
Richard W.M. Jones
4d8bdf0357 fuse: Use guestfs_rename to implement rename(2) syscall (RHBZ#895910). 2013-01-21 17:00:04 +00:00
Richard W.M. Jones
159e8f8c3a New API: rename: Rename file within the same filesystem (RHBZ#895910). 2013-01-21 17:00:04 +00:00
Matthew Booth
f956457b5d docs: Fix cut/paste error in pread_device 2013-01-21 15:57:23 +00:00
Richard W.M. Jones
28e34290ff fuse: If guestfs_last_errno returns 0, don't return no error to FUSE layer.
guestfs_last_errno (g) == 0 doesn't mean "no error".  It means the
errno was not captured.  In this case we have to substitute some sort
of errno, so choose EINVAL arbitrarily.
2013-01-21 14:42:48 +00:00
Richard W.M. Jones
533082e282 daemon: Change ln, ln-f (hard-link) APIs to use link(2) instead of external ln (RHBZ#895905).
The reasons to do this are twofold:

(a) It's probably a tiny bit faster.

(b) It lets us capture the real errno if the link(2) syscall fails.

The errno is also passed through guestmount, fixing RHBZ#895905:

+ guestmount -a test1.img -m /dev/sda1:/ -m /dev/sda2:/boot /tmp/mnt
+ touch /tmp/mnt/foo
+ cd /tmp/mnt
+ ln foo boot/foo
ln: failed to create hard link ‘boot/foo’ => ‘foo’: Invalid cross-device link
2013-01-21 14:23:07 +00:00
Richard W.M. Jones
ebc86ae6d7 Fix checksums-out command (RHBZ#895904).
This was broken by the earlier
commit 0306c98d31.

This commit also adds a regression test.
2013-01-21 11:14:56 +00:00
Richard W.M. Jones
e18e20793f tests: virt-make-fs: Allow btrfs to be skipped. 2013-01-21 08:15:54 +00:00
Richard W.M. Jones
2974b5d666 tests/qemu: Don't require LVM for these tests. 2013-01-18 17:23:43 +00:00
Richard W.M. Jones
64b229e8ff Version 1.21.4. 2013-01-18 08:18:24 +00:00
Richard W.M. Jones
d8f14591d1 daemon: lvm: Fix various paths relative to new lvm_system_dir.
This fixes commit 9fd41abd40.
2013-01-18 07:13:54 +00:00
Richard W.M. Jones
312d02afe4 tests: Don't construct the guests in parallel.
In automake 1.13, check_DATA is now built in parallel, resulting in it
trying to build 4 or 5 guests in parallel.
2013-01-18 07:13:53 +00:00
Hilko Bengen
aa83e7c7b8 Fix packagelist for current Debian-based systems 2013-01-18 07:02:15 +00:00
Hilko Bengen
111f444d69 inspector: Fix tests for out-of-tree builds 2013-01-18 07:01:09 +00:00
Hilko Bengen
9637bddc33 erlang: fix bindtests for out-of-tree build 2013-01-18 07:01:07 +00:00
Richard W.M. Jones
24c4178749 appliance: Add libcap to the appliance (thanks Skippy VonDrake). 2013-01-18 06:42:13 +00:00
Richard W.M. Jones
2c68aca9d7 automake: Force serial-tests.
automake 1.13 started to use stupid parallel tests by default,
breaking everything.
2013-01-17 18:21:20 +00:00
Richard W.M. Jones
9c8e47247b FAQ: Document "Could not allocate dynamic translator buffer" and how to fix it. 2013-01-17 18:10:14 +00:00
Matthew Booth
c61b589f9b gobject: Add pkg-config for gobject bindings 2013-01-17 15:06:09 +00:00
Olaf Hering
9fd41abd40 daemon: copy entire lvm directory
cp will fail if /etc/lvm is an empty directory. Copy the entire
directory and adjust environment variable.

Signed-off-by: Olaf Hering <olaf@aepfle.de>

RWMJ:
 - Fixed a couple of whitespace issues.
2013-01-17 14:13:03 +00:00
Richard W.M. Jones
a710c42f0f Version 1.21.3. 2013-01-17 09:43:59 +00:00
Richard W.M. Jones
a0e9d310d1 ruby: Use updated package names, but allow fallback to the old names (RHBZ#894545).
Thanks Dominic Cleal.
2013-01-16 14:33:49 +00:00
Richard W.M. Jones
d4763a2e24 daemon: Suppress two false positives from Coverity.
Using // coverity[...] or /* coverity[...] */ comments in the source
it is possible to suppress specific Coverity errors.  The suppressed
error should occur in the line following the comment.

In this case I have suppressed two false positives from Coverity:

(a) We deliberately assign to a NULL pointer in order to cause a
segfault, for testing how the library reacts when this happens.
Coverity flags this, but it is not an error in this case.

(b) Coverity does not model global variables (a known shortcoming).
Therefore the code 'errno = posix_memalign (...)' cannot be modelled
by Coverity, even though the code is correct.  Coverity raises a false
positive about this.

(Thanks Kamil Dudka, Coverity)
2013-01-16 11:30:07 +00:00
Richard W.M. Jones
ce828c6afc podwrapper: Refresh podwrapper man page.
This also adds a rule so you can do:

 make podwrapper.1

if you want to read the documentation as a man page.
2013-01-15 18:40:17 +00:00
Richard W.M. Jones
0d2d26d8e7 java: Implement the event API. 2013-01-15 18:40:17 +00:00
Richard W.M. Jones
3f08d50863 java: Use defined constants for flags in call to guestfs_create_flags. 2013-01-15 18:40:17 +00:00
Richard W.M. Jones
05a67bcc25 java: Change synopsis in man page to show use of add_drive. 2013-01-15 18:40:16 +00:00
Richard W.M. Jones
7d89baa3e9 java: Tidy up javadoc. 2013-01-15 18:40:16 +00:00
Richard W.M. Jones
f58b6c5953 Refresh README file. 2013-01-15 18:40:16 +00:00
Richard W.M. Jones
20e23ab2a3 Update copyright dates for 2013.
On generated files in git and README.
2013-01-15 18:40:16 +00:00
Richard W.M. Jones
e051b270a2 haskell: Use unused bogus data types. 2012-12-29 14:28:47 +00:00
Richard W.M. Jones
bff29314df haskell: Typo in man page, lists -> list. 2012-12-29 13:57:24 +00:00
Richard W.M. Jones
60d744e32f haskell: Implement 'head' and 'tail' by hiding the Prelude functions. 2012-12-29 13:38:13 +00:00
Richard W.M. Jones
406e372469 haskell: Use 'import Guestfs as G' in test code.
The code is equivalent but shorter.
2012-12-29 13:35:07 +00:00
Richard W.M. Jones
67d59d0153 haskell: Document current state of Haskell bindings. 2012-12-29 13:26:38 +00:00
Richard W.M. Jones
1881be1e56 haskell: Fix RHashtable in the generator. 2012-12-29 13:16:07 +00:00
Richard W.M. Jones
3a72944597 haskell: Use .NOTPARALLEL in this directory. 2012-12-29 13:16:07 +00:00
Richard W.M. Jones
7718cb5afe haskell: Fix RStringList in generator. 2012-12-28 21:36:07 +00:00
Richard W.M. Jones
5ede0b21b0 haskell: Add tests of config functions. 2012-12-28 20:44:36 +00:00
Richard W.M. Jones
c9e0ff8831 haskell: Allow non-appliance tests to run when !ENABLE_APPLIANCE. 2012-12-28 20:19:20 +00:00
Richard W.M. Jones
604f9a79db haskell: Renumber tests according to Perl scheme. 2012-12-28 20:17:31 +00:00
Richard W.M. Jones
3e7dcc384a haskell: Enable RString, RConstString in generator. 2012-12-28 20:11:23 +00:00
Richard W.M. Jones
beebade874 haskell: Enable RBool in generator. 2012-12-28 19:59:31 +00:00
Richard W.M. Jones
11e111ec01 haskell: Replace deprecated INCLUDE directive.
The INCLUDE directive is obsolete.  You must now put the name of the
include file before the C function name.
2012-12-28 19:55:01 +00:00
Richard W.M. Jones
9ae248e03f arm: Recomment vexpress-a15 instead of vexpress-a9.
Neither works (because of lack of PCI) but A15 emulation is probably
better than A9 emulation.
2012-12-27 20:02:31 +00:00
Richard W.M. Jones
6c9aaf394f launch: appliance: Fix parsing of QEMU_OPTIONS.
If there was no quoting character, the options could run off the end
of the string and into whatever string which happened to be following
in memory.

This bug was revealed when libguestfs was compiled on arm.
2012-12-27 20:01:15 +00:00
Richard W.M. Jones
bcdaa46313 launch: appliance: Small refactoring of virtio-scsi detection code.
This is just code motion.
2012-12-27 19:36:33 +00:00
Richard W.M. Jones
a9d70d1ae4 Fix whitespace in configure.ac.
Standardize on 4 spaces for indentation in configure.ac file.
This is just a change of whitespace.
2012-12-27 18:55:34 +00:00
Richard W.M. Jones
364ee94b8d arm: Prevent -Wcast-align warnings.
See link below for a general description of the problem:

f8b62e4cd2
2012-12-27 18:08:55 +00:00
Richard W.M. Jones
5af94b5692 arm: Only use -device sga if qemu supports this device.
qemu-system-arm does not have the sgabios device.
2012-12-27 15:57:15 +00:00
Richard W.M. Jones
741c8606db lib: Remove useless cast.
'strings' is declared as char **, so the return type of
this expression will already be char *.  The cast is both
useless and potentially hides errors.
2012-12-27 15:27:20 +00:00
Richard W.M. Jones
4a877452f5 build: Fix ./configure --with-febootstrap-yum-config option.
This fixes commit bfddae7cee.

Also tested that all variants actually work.
2012-12-24 09:48:41 +00:00
Richard W.M. Jones
4b5d27869f Version 1.21.2. 2012-12-22 22:42:29 +00:00
Richard W.M. Jones
bfddae7cee build: Change --with-febootstrap-yum-config to --with-febootstrap-packager-config
For the rationale behind this renaming, see:
b8cbe191d0

You can still, for the time being, use
./configure --with-febootstrap-yum-config
but it's preferred to switch to the new option.  The new option is
identical, just renamed.

Qe still pass the deprecated --yum-config option to febootstrap
itself, since both old and new febootstrap support this.
2012-12-22 17:28:10 +00:00
Richard W.M. Jones
e73cf67762 inspection: Set fs->device field on swap devices.
For some reason the fs->device field was not set for swap devices.

Apparently this did not matter before (this bug has existed since at
least libguestfs 1.16), but in commit 6ee80b8dac we started to depend
on the fs->device field being non-NULL.  This resulted in segfaults
when inspecting any guest which had a swap device, eg:

 #0  __strcmp_sse42 () at ../sysdeps/x86_64/multiarch/strcmp-sse42.S:164
 #1  0x00007ffff7d740cb in parent_device_already_probed (g=0x703a70,
                        partition=0x6f79b0 "/dev/vda4") at inspect.c:156
 #2  0x00007ffff7d73e00 in guestfs__inspect_os (g=0x703a70) at inspect.c:83
 #3  0x00007ffff7cee11d in guestfs_inspect_os (g=0x703a70) at actions-1.c:397

This commit sets fs->device to the device name.

(Thanks Matthew Booth for first noticing this problem.)
2012-12-20 15:36:36 +00:00
Richard W.M. Jones
6628cc7ef6 Pass noapic on i686 kernel command line.
qemu 1.2 i686 TCG is buggy and hangs when emulating APIC.
https://bugzilla.redhat.com/show_bug.cgi?id=857026
2012-12-20 12:09:49 +00:00
Richard W.M. Jones
eca01c3105 faq: Suggest 'approx' (apt proxy) to speed up Debian builds.
Thanks Hilko Bengen.
2012-12-18 20:39:46 +00:00
Richard W.M. Jones
d1ad89520e tests: Skip windows.img tests if it is zero-sized.
If ntfs-3g is not installed, then tests/guests creates a 'windows.img'
file which is zero-sized.

This is problematical because other tests which use this image will
fail at best, or hit RHBZ#847549 (qemu/virtio-scsi bug) at worst.

Change the tests which use windows.img so they skip if 'windows.img'
has zero size.
2012-12-18 17:35:51 +00:00
Richard W.M. Jones
a34072e25b build: Add 'make print-subdirs' rule, useful for selectively running tests.
If you want to selectively run tests, or if the test suite fails half
way through, use:

  make print-subdirs

to print the subdirectories, select the ones you want to run / the
remaining ones, and do:

  make check SUBDIRS="..."
2012-12-18 16:28:23 +00:00
Richard W.M. Jones
fa162417ed daemon: Make gdisk into an optional dependency and optgroup.
Also document that gdisk is a dependency at all.

This fixes commit 956e30effa.
2012-12-18 11:52:41 +00:00
Richard W.M. Jones
2434a86da4 lua: tests: If $LUA is not set, set it to 'lua' instead of '/usr/bin/lua'. 2012-12-18 08:55:06 +00:00
Richard W.M. Jones
3f88f88c80 lua: Fix misapplied patch.
This fixes commit 5b70120293.
2012-12-18 08:53:34 +00:00
Richard W.M. Jones
8be9743e74 ruby: Disable -Wstrict-prototypes warning for Ruby headers. 2012-12-18 08:43:52 +00:00
Richard W.M. Jones
034d393bb1 docs: Properly document attach methods in the guestfs(3) man page. 2012-12-17 23:01:56 +00:00
Richard W.M. Jones
62f98d64a5 lua: Fix Lua configure test on Fedora.
On Debian, the lua pkg-config file is called "lua5.1.pc" (etc)
whereas on Fedora it's called "lua.pc" for all versions.
2012-12-17 23:01:56 +00:00
Hilko Bengen
5b70120293 lua: Use correct binary for tests 2012-12-17 22:24:53 +01:00
Hilko Bengen
f07e89c5f9 lua: Add ifdefs for Lua 5.2 compatibility 2012-12-17 22:24:53 +01:00
Hilko Bengen
05103cc693 lua: Use pkg-config to determine Lua version, parameters 2012-12-17 22:24:52 +01:00
Richard W.M. Jones
8237ac89c5 daemon: Use pvcreate --force option (RHBZ#887971).
pvcreate fails if the partition contains a swap space signature.  Use
more force to stop it from complaining.
2012-12-17 19:27:12 +00:00
Richard W.M. Jones
4ad6b28d83 Version 1.21.1. 2012-12-17 12:49:32 +00:00
Richard W.M. Jones
eab324bbbb list-filesystems: Ignore MBR type 0x42 (Windows dynamic disks) (RHBZ#887520). 2012-12-17 12:39:55 +00:00
Richard W.M. Jones
6f02e33c6f sparsify: Document that virt-sparsify doesn't work well on multi-disk VMs.
See: http://bugzilla.redhat.com/887826
2012-12-17 12:24:29 +00:00
Richard W.M. Jones
79339798b3 launch: libvirt: Improve loop invariant from previous commit.
This fixes commit 11b6293d1b.
2012-12-16 21:29:35 +00:00
Richard W.M. Jones
11b6293d1b launch: libvirt: Parse capabilities XML and fail early if qemu/KVM not supported (RHBZ#886915). 2012-12-16 20:56:39 +00:00
Richard W.M. Jones
c4ad2c0ce3 daemon: Fold stdout on stderr when running e2fsck.
User Phill Bandelow noted that virt-resize fails with an e2fsck error
on a host where the system clock had been accidentally set in the
past.

Unfortunately this was hard to diagnose because guestfsd 'ate' the
stdout of the e2fsck program.  I have verified by code inspection that
e2fsck prints messages on stdout.

Thus this changes the daemon to fold stdout and stderr together so we
get to see all error messages from e2fsck when it fails.
2012-12-16 18:38:41 +00:00
Richard W.M. Jones
22fe98ad9f build: Improve 'make help' output description of 'make extra-tests'. 2012-12-15 20:20:38 +00:00
Richard W.M. Jones
eca2dd2e8c build: Better formatting for 'make help' output.
This is just whitespace changes.
2012-12-15 20:15:12 +00:00
Richard W.M. Jones
486efb002a build: Show 'make -k check' as a possibility in 'make help' output.
Thanks to Cole Robinson for this suggestion.
2012-12-15 20:10:25 +00:00
Richard W.M. Jones
448a02373d ruby: Enable C compiler warnings.
This has the desirable side effect that the correct CFLAGS get passed
to the C compiler when building the Ruby extension.
2012-12-15 19:42:02 +00:00
Richard W.M. Jones
1571aef9cc python: Enable C compiler warnings. 2012-12-15 19:42:02 +00:00
Richard W.M. Jones
62e775c350 Change the handling of private functions, safe_malloc etc.
Rename guestfs_safe_malloc et al to guestfs___safe_malloc etc.

To use the private functions, code now has to define
-DGUESTFS_PRIVATE_FUNCTIONS=1.  This will make it easier for us in
future to work out which programs are using these functions and to
minimize both the number of programs and the functions they are
calling.

Note that the Perl, Python, OCaml, Ruby and Java bindings use
guestfs_safe_* calls.  None of the other bindings do.  This is a bug
(in the bindings using those functions): these functions will call the
out of memory callback on failure.  This function defaults to abort(),
and since this happens from a language binding, there is no way to
change this default.
2012-12-15 19:41:29 +00:00
Richard W.M. Jones
27f6878e2a guestfs.h: Fix use of __attribute__ and GCC < 4.
I guess no one uses GCC 3 any more, because if they did, including
<guestfs.h> would not work since GUESTFS_DLL_PUBLIC would not have
been defined.

At the same time, ensure that __attribute__((noreturn)) is only used
when the compiler is GCC >= 3.1.
2012-12-15 17:03:11 +00:00
Richard W.M. Jones
95df8a7c0c inspection: Don't call guestfs_hivex_close if previous guestfs_hivex_open call failed.
(Thanks Skippy VonDrake)
2012-12-14 22:04:25 +00:00
Matthew Booth
a9051eb98e daemon: Add sentinel attribute to commandf and commandrf
Causes a compiler warning to be emitted if you omit the trailing NULL argument.
2012-12-14 16:58:05 +00:00
Matthew Booth
956e30effa Add support for getting and setting GPT partition type GUIDs
New APIs:
  part_set_gpt_type
  part_get_gpt_type
2012-12-14 16:58:05 +00:00
Matthew Booth
2aa731e7c4 daemon: Remove redundant fork in commandrvf
Currently the code is doing a redundant fork when passed the
COMMAND_FLAG_CHROOT_COPY_FILE_TO_STDIN flag. The additional
sub-process does a chroot() which has no effect because all file
handles are already open at that point, then simply copies its input
to its output.

This change simply replaces the above with a dup2 of the passed file
handle to STDIN of the command process.

RWMJ:
  Don't initialize 'pid' variable.
2012-12-14 16:21:58 +00:00
Richard W.M. Jones
d7a806ca1a configure: Change minor from .20 to .21 for new development branch. 2012-12-13 17:53:36 +00:00
Matthew Booth
e92f9666de daemon: NFC Use symbolic names in commandrvf
Improve readability of commandrvf() by replacing bare int values for
file descriptors with their symbolic names STD{IN,OUT,ERR}_FILENO.

Also add PIPE_READ and PIPE_WRITE for referencing relevant ends of a pipe.
2012-12-13 17:53:20 +00:00
Matthew Booth
52cd07a0ac daemon: fix directory outside current root when executing commands
When executing a command, we temporarily chroot, fork and exec the
command, then chroot back. We intentionally don't chdir in the parent
process so that we can 'jailbreak' the chroot later. However, this has
the effect that commands are executed with a current working directory
which is outside the current root.  This unusual state can cause
errors in executed commands which don't anticipate it.

This change does a chdir("/") before executing and command. This
happens inside the fork, so the jailbreak isn't affected in the
parent.
2012-12-13 17:15:01 +00:00
518 changed files with 89237 additions and 62364 deletions

55
.gitignore vendored
View File

@@ -45,6 +45,15 @@ Makefile.in
/appliance/stamp-supermin
/appliance/supermin.d
/autom4te.cache
/bash/virt-cat
/bash/virt-df
/bash/virt-edit
/bash/virt-filesystems
/bash/virt-format
/bash/virt-inspector
/bash/virt-ls
/bash/virt-sysprep
/bash/virt-sparsify
/build-aux
/cat/stamp-virt-*.pod
/cat/virt-cat
@@ -96,17 +105,17 @@ Makefile.in
/erlang/guestfs.beam
/erlang/guestfs.erl
/erlang/test.img
/examples/copy_over
/examples/create_disk
/examples/display_icon
/examples/copy-over
/examples/create-disk
/examples/display-icon
/examples/guestfs-examples.3
/examples/guestfs-faq.1
/examples/guestfs-performance.1
/examples/guestfs-recipes.1
/examples/guestfs-testing.1
/examples/inspect_vm
/examples/libvirt_auth
/examples/mount_local
/examples/inspect-vm
/examples/libvirt-auth
/examples/mount-local
/examples/stamp-guestfs-examples.pod
/examples/stamp-guestfs-faq.pod
/examples/stamp-guestfs-performance.pod
@@ -141,7 +150,11 @@ Makefile.in
/format/virt-format.1
/fuse/guestmount
/fuse/guestmount.1
/fuse/guestunmount
/fuse/guestunmount.1
/fuse/stamp-guestmount.pod
/fuse/stamp-guestunmount.pod
/fuse/test-guestunmount-fd
/generator/.depend
/generator/files-generated.txt
/generator/generator
@@ -160,8 +173,9 @@ Makefile.in
/guestfsd-in-wine.log
/haskell/Bindtests
/haskell/Bindtests.hs
/haskell/Guestfs005Load
/haskell/Guestfs010Basic
/haskell/Guestfs010Load
/haskell/Guestfs030Config
/haskell/Guestfs050LVCreate
/haskell/Guestfs.hs
/html/guestfish.1.html
/html/guestfs.3.html
@@ -180,6 +194,7 @@ Makefile.in
/html/guestfs-testing.1.html
/html/guestfsd.8.html
/html/guestmount.1.html
/html/guestunmount.1.html
/html/libguestfs-make-fixed-appliance.1.html
/html/libguestfs-test-tool.1.html
/html/virt-alignment-scan.1.html
@@ -251,6 +266,7 @@ Makefile.in
/ocaml/guestfs.mli
/ocamlinit-stamp
/ocaml/META
/ocaml/stamp-mlguestfs
/ocaml/t/guestfs_005_load.bc
/ocaml/t/guestfs_005_load.opt
/ocaml/t/guestfs_010_basic.bc
@@ -292,6 +308,7 @@ Makefile.in
/php/extension/config.sub
/php/extension/configure
/php/extension/configure.in
/php/extension/env
/php/extension/guestfs_php.c
/php/extension/guestfs_php_*.diff
/php/extension/guestfs_php_*.exp
@@ -319,6 +336,7 @@ Makefile.in
/po-docs/po4a.conf
/po-docs/*/*.pod
/po-docs/*/stamp-update-po
/podwrapper.1
/podwrapper.pl
/po/*.gmo
/python/bindtests.py
@@ -334,8 +352,8 @@ Makefile.in
/rescue/virt-rescue
/rescue/virt-rescue.1
/resize/.depend
/resize/resize_gettext.ml
/resize/resize_utils_tests
/resize/common_gettext.ml
/resize/common_utils_tests
/resize/stamp-virt-resize.pod
/resize/virt-resize
/resize/virt-resize.1
@@ -344,6 +362,7 @@ Makefile.in
/ruby/examples/guestfs-ruby.3
/ruby/examples/stamp-guestfs-ruby.pod
/ruby/ext/guestfs/extconf.h
/ruby/ext/guestfs/extconf.rb
/ruby/ext/guestfs/_guestfs.bundle
/ruby/ext/guestfs/_guestfs.c
/ruby/ext/guestfs/_guestfs.so
@@ -351,23 +370,25 @@ Makefile.in
/ruby/Rakefile
/run
/sparsify/.depend
/sparsify/sparsify_gettext.ml
/sparsify/stamp-virt-sparsify.pod
/sparsify/virt-sparsify
/sparsify/virt-sparsify.1
/src/actions-?.c
/src/actions-variants.c
/src/bindtests.c
/src/cleanup-structs.c
/src/errnostring.c
/src/errnostring-gperf.c
/src/errnostring-gperf.gperf
/src/errnostring.h
/src/event-string.c
/src/free-structs.c
/src/guestfs.3
/src/guestfs-actions.pod
/src/guestfs-availability.pod
/src/guestfs.h
/src/guestfs-internal-actions.h
/src/guestfs-internal-frontend-cleanups.h
/src/guestfs_protocol.c
/src/guestfs_protocol.h
/src/guestfs_protocol.x
@@ -383,7 +404,6 @@ Makefile.in
/sysprep/stamp-script2.sh
/sysprep/stamp-virt-sysprep.pod
/sysprep/sysprep-extra-options.pod
/sysprep/sysprep_gettext.ml
/sysprep/sysprep-operations.pod
/sysprep/virt-sysprep
/sysprep/virt-sysprep.1
@@ -398,12 +418,14 @@ Makefile.in
/tests/c-api/test-create-handle
/tests/c-api/test-debug-to-file
/tests/c-api/test-environment
/tests/c-api/test-event-string
/tests/c-api/test*.img
/tests/c-api/test-just-header
/tests/c-api/test-just-header-cxx
/tests/c-api/test-last-errno
/tests/c-api/test.log
/tests/c-api/test-private-data
/tests/c-api/test-pwd
/tests/c-api/tests
/tests/c-api/tests.c
/tests/c-api/test*.tmp
@@ -421,20 +443,28 @@ Makefile.in
/tests/data/initrd-x86_64.img.gz
/tests/data/test-grep.txt.gz
/tests/data/test.iso
/tests/guests/blank-*.img
/tests/guests/debian.img
/tests/guests/fedora.img
/tests/guests/fedora-btrfs.img
/tests/guests/fedora-md1.img
/tests/guests/fedora-md2.img
/tests/guests/guests.xml
/tests/guests/guests-all-good.xml
/tests/guests/guest-aux/fedora-name.db
/tests/guests/guest-aux/fedora-packages.db
/tests/guests/stamp-fedora-md.img
/tests/guests/ubuntu.img
/tests/guests/windows.img
/tests/mount-local/test-parallel-mount-local
/tests/mountable/test-internal-parse-mountable
/tests/parallel/test-parallel
/tests/regressions/rhbz501893
/tests/regressions/rhbz790721
/tests/regressions/rhbz914931
/tests/rsync/rsyncd.pid
/tests/syslinux/extlinux-guest.img
/tests/syslinux/syslinux-guest.img
/test-tool/libguestfs-test-tool
/test-tool/libguestfs-test-tool.1
/test-tool/libguestfs-test-tool-helper
@@ -442,4 +472,3 @@ Makefile.in
/tools/test.img
/tools/virt-*.1
/tools/virt-*.pl
/valgrind.log*

View File

@@ -5,5 +5,5 @@
set sw=2
set ts=2
set tw=80
set tw=70
set expandtab

View File

@@ -10,7 +10,9 @@ Erik Nolte <erik_nolte@acm.org>
Evaggelos Balaskas <ebalaskas@ebalaskas.gr>
Geert Warrink <geert.warrink@onsnet.nu>
Guido Günther <agx@sigxcpu.org>
Hilko Bengen <bengen@debian.org>
Hilko Bengen <bengen@hilluzination.de>
infernix <infernix@infernix.net>
Jaswinder Singh <jsingh@redhat.com>
Jim Meyering <meyering@redhat.com>
Jiri Popelka <jpopelka@redhat.com>

180
BUGS
View File

@@ -1,5 +1,5 @@
NOTE: This file is automatically generated from "update-bugs.sh".
Last updated: 2012-12-13
Last updated: 2013-04-04
This contains a local list of the bugs that are open against
libguestfs. Bugs are tracked in the Red Hat Bugzilla database
@@ -107,9 +107,6 @@ Bugs in NEW or ASSIGNED state are open and waiting for someone to fix.
806179 NEW https://bugzilla.redhat.com/show_bug.cgi?id=806179
RFE: support inspection of icon for more Windows guests
808193 NEW https://bugzilla.redhat.com/show_bug.cgi?id=808193
g.launch() crashes on RHEL 5
812970 NEW https://bugzilla.redhat.com/show_bug.cgi?id=812970
virt-rescue cannot set ><rescue> prompt, on Ubuntu 12.04
@@ -143,30 +140,15 @@ Bugs in NEW or ASSIGNED state are open and waiting for someone to fix.
837941 NEW https://bugzilla.redhat.com/show_bug.cgi?id=837941
Data loss when writing to qcow2-format disk files
838081 NEW https://bugzilla.redhat.com/show_bug.cgi?id=838081
ocaml/t/guestfs_500_parallel_mount_local crashes in caml_thread_reinitialize
845234 NEW https://bugzilla.redhat.com/show_bug.cgi?id=845234
RFE: virt-ls on Windows guest doesn't support drive letters
846676 NEW https://bugzilla.redhat.com/show_bug.cgi?id=846676
guestfs_launch() hangs with Debian qemu-kvm 1.1.0
848464 NEW https://bugzilla.redhat.com/show_bug.cgi?id=848464
gobject javascript bindings cannot use 64 bit integers
857763 NEW https://bugzilla.redhat.com/show_bug.cgi?id=857763
libguestfs 'file-architecture' returns 'ARM' for arm binaries
863696 NEW https://bugzilla.redhat.com/show_bug.cgi?id=863696
[F18] libguestfs fails to mount a disk image file(in this case qcow2) as 'root'
864871 NEW https://bugzilla.redhat.com/show_bug.cgi?id=864871
libvirt error: could not create appliance through libvirt: unable to set security context 'unconfined_u:object_r:svirt_image_t:s0:cXXX,cYYY' on '.../console.sock'
865923 NEW https://bugzilla.redhat.com/show_bug.cgi?id=865923
Check that new qemu -machine option doesn't break libguestfs.
866994 NEW https://bugzilla.redhat.com/show_bug.cgi?id=866994
tgz-out causes memory leak in guestfsd
@@ -176,6 +158,117 @@ Bugs in NEW or ASSIGNED state are open and waiting for someone to fix.
880806 NEW https://bugzilla.redhat.com/show_bug.cgi?id=880806
virt-df with two -a options displays incorrect disk image name
887826 NEW https://bugzilla.redhat.com/show_bug.cgi?id=887826
RFE: virt-sparsify cannot handle multi-disk virtual machines (eg. if they use LVM, MD, LDM, etc)
889089 NEW https://bugzilla.redhat.com/show_bug.cgi?id=889089
Block device /dev/sd* didn't translate to /dev/vd*
890027 NEW https://bugzilla.redhat.com/show_bug.cgi?id=890027
virt-sysprep: Setting the hostname on Fedora 18 is stupidly over-complicated
891909 NEW https://bugzilla.redhat.com/show_bug.cgi?id=891909
Can't make install with non-standard prefix as non-root
892271 NEW https://bugzilla.redhat.com/show_bug.cgi?id=892271
virt-format fail to format the same disk more than twice with lvm enable
892272 NEW https://bugzilla.redhat.com/show_bug.cgi?id=892272
Specify QEMU interface emulation will break libguestfs
892275 NEW https://bugzilla.redhat.com/show_bug.cgi?id=892275
checksums-out fail to compute the checksums of all regular files in directory
892291 NEW https://bugzilla.redhat.com/show_bug.cgi?id=892291
guestmount: link() incorrectly returns ENOENT, when it should be EXDEV
892834 NEW https://bugzilla.redhat.com/show_bug.cgi?id=892834
guestmount: rename() incorrectly follows symbolic links
895898 NEW https://bugzilla.redhat.com/show_bug.cgi?id=895898
RFE: Allow interface to be specified with libvirt attach-method
895946 NEW https://bugzilla.redhat.com/show_bug.cgi?id=895946
Got incorrect block count number when resize ntfs file system via "ntfsresize_opts"
903890 NEW https://bugzilla.redhat.com/show_bug.cgi?id=903890
scrub-freespace didn't remove the scrub file, cause the file system 100% full
903972 NEW https://bugzilla.redhat.com/show_bug.cgi?id=903972
Command "acl-set-file" is inconvenient to use
903987 NEW https://bugzilla.redhat.com/show_bug.cgi?id=903987
Command "acl-set-file" is inconvenient to use
905322 NEW https://bugzilla.redhat.com/show_bug.cgi?id=905322
"No such file or directory" when execute "hivex-commit"
906190 NEW https://bugzilla.redhat.com/show_bug.cgi?id=906190
Need add a line break behind the output of command "hivex-value-value"
906766 NEW https://bugzilla.redhat.com/show_bug.cgi?id=906766
virt-resize cannot resize RHEL 5 guest with GPT partition table type
906777 NEW https://bugzilla.redhat.com/show_bug.cgi?id=906777
In tests, set_label sometimes fails
908255 NEW https://bugzilla.redhat.com/show_bug.cgi?id=908255
error message didn't translate to user language
909666 NEW https://bugzilla.redhat.com/show_bug.cgi?id=909666
Unexpected non-tail recursion in recv_from_daemon results in stack overflow in very long-running API calls that send progress messages
909667 NEW https://bugzilla.redhat.com/show_bug.cgi?id=909667
Unexpected non-tail recursion in recv_from_daemon results in stack overflow in very long-running API calls that send progress messages
910115 NEW https://bugzilla.redhat.com/show_bug.cgi?id=910115
RFE: support ntfsresize --bad-sectors option in virt-resize
910269 NEW https://bugzilla.redhat.com/show_bug.cgi?id=910269
Tracker: Bugs in other packages that stop libguestfs working on current Rawhide
910270 NEW https://bugzilla.redhat.com/show_bug.cgi?id=910270
Tracker: Bugs in other packages that stop libguestfs working on Fedora 18
911674 NEW https://bugzilla.redhat.com/show_bug.cgi?id=911674
swapon label test fails (RHEL 7 only)
911678 NEW https://bugzilla.redhat.com/show_bug.cgi?id=911678
libguestfs: error: cpio command failed: Resource temporarily unavailable (RHEL 7 only)
913774 NEW https://bugzilla.redhat.com/show_bug.cgi?id=913774
libguestfs: could not create appliance through libvirt when URI is qemu:///system or running as root (which causes system to be used implicitly)
913815 NEW https://bugzilla.redhat.com/show_bug.cgi?id=913815
febootstrap: no ext2 root device found when running libguestfs-test-tools
916130 NEW https://bugzilla.redhat.com/show_bug.cgi?id=916130
libguestfs can't rebuild in mock
917706 NEW https://bugzilla.redhat.com/show_bug.cgi?id=917706
guestfs_umount_local is not thread safe
920617 NEW https://bugzilla.redhat.com/show_bug.cgi?id=920617
RFE: virt-inspector (or another tool) should produce OVF output for oVirt / RHEV
921299 NEW https://bugzilla.redhat.com/show_bug.cgi?id=921299
virt-p2v fails with permissions problem on kernel module.
921710 NEW https://bugzilla.redhat.com/show_bug.cgi?id=921710
9p support should be disabled in libguestfs in RHEL 7
922891 NEW https://bugzilla.redhat.com/show_bug.cgi?id=922891
Tracker: Bugs in other packages that stop libguestfs working on Fedora 19
923355 NEW https://bugzilla.redhat.com/show_bug.cgi?id=923355
guestfish prints literal "n" in error messages
927447 NEW https://bugzilla.redhat.com/show_bug.cgi?id=927447
[suse] virt tools hang on disk image, but libguestfs-test-tool runs OK
948324 NEW https://bugzilla.redhat.com/show_bug.cgi?id=948324
inspection fails if libosinfo is not installed
503134 ASSIGNED https://bugzilla.redhat.com/show_bug.cgi?id=503134
guestfish's list splitting does not recognize internal quoting
@@ -194,50 +287,27 @@ Bugs in NEW or ASSIGNED state are open and waiting for someone to fix.
803643 ASSIGNED https://bugzilla.redhat.com/show_bug.cgi?id=803643
inspect-is-multipart return false when inspection results should be true
(58 bugs)
(89 bugs)
--------------------------------------------------
These bugs are in the VERIFIED state.
Bugs in MODIFIED, POST or ON_QA state are fixed.
You can help by testing the fixes.
801640 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=801640
[RFE] the error reported by resize2fs-M need to be more clear
889536 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=889536
[RFE]It's better to emphasize "libguestfs-winsupport" in V2V manpage or error output
816839 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=816839
data overflow error when debug progress -1
889537 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=889537
Libguestfs live support should be disabled in RHEL 7 packages
822626 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=822626
virt-ls error: "libguestfs: error: checksum: path: parameter cannot be NULL"
830135 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=830135
libguestfs should support mount-local APIs in RHEL 6 (for OpenStack)
836501 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=836501
dependency on fuse suggested
837691 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=837691
Data loss when writing to qcow2-format disk files
838609 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=838609
guestmount + fusermount allows a race condition when unmounting and immediately using the disk image
853763 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=853763
virt-sparsify should use a more robust method to detect the input format
858126 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=858126
virt-inspector fail to work with some windows guests
858128 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=858128
libguestfs fail to list devices added by add-drive-ro-with-if twice
858648 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=858648
889538 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=889538
libguestfs can not be installed with recent iptables
880805 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=880805
virt-df with two -a options displays incorrect disk image name
909573 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=909573
patch libguestfs to use 'supermin' instead of 'febootstrap' in RHEL 7
883338 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=883338
Missing #include <locale.h> in fuse/guestmount.c
947438 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=947438
Some obsolete tools should be removed from libguestfs RHEL 7 package
(13 bugs)
(5 bugs)
End of BUGS file.

View File

@@ -1,5 +1,5 @@
# libguestfs
# Copyright (C) 2009-2012 Red Hat Inc.
# Copyright (C) 2009-2013 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
@@ -30,9 +30,7 @@ SUBDIRS += tests/data generator src examples po
if ENABLE_DAEMON
SUBDIRS += daemon
endif
if ENABLE_APPLIANCE
SUBDIRS += appliance
endif
# Tests - order is important.
if ENABLE_APPLIANCE
@@ -43,6 +41,7 @@ SUBDIRS += tests/tmpdirs
SUBDIRS += tests/protocol
SUBDIRS += tests/parallel
SUBDIRS += tests/disks
SUBDIRS += tests/mountable
SUBDIRS += tests/lvm
SUBDIRS += tests/luks
SUBDIRS += tests/md
@@ -57,6 +56,8 @@ SUBDIRS += tests/rsync
SUBDIRS += tests/bigdirs
SUBDIRS += tests/disk-labels
SUBDIRS += tests/hotplug
SUBDIRS += tests/nbd
SUBDIRS += tests/syslinux
SUBDIRS += tests/regressions
endif
@@ -69,6 +70,9 @@ SUBDIRS += fish
# virt-tools in C.
SUBDIRS += align cat df edit format inspector rescue
# bash-completion
SUBDIRS += bash
# Language bindings.
if HAVE_PERL
SUBDIRS += perl perl/examples
@@ -191,6 +195,7 @@ HTMLFILES = \
html/guestfsd.8.html \
html/guestfish.1.html \
html/guestmount.1.html \
html/guestunmount.1.html \
html/libguestfs-make-fixed-appliance.1.html \
html/libguestfs-test-tool.1.html \
html/virt-alignment-scan.1.html \
@@ -241,7 +246,7 @@ dist-hook:
$(top_srcdir)/update-bugs.sh > BUGS-t
mv BUGS-t BUGS
cp BUGS $(distdir)/BUGS
git shortlog -se | awk -F'\t' '{print $$2}' > AUTHORS-t
git shortlog -se | awk -F'\t' '{print $$2}' | sort -f > AUTHORS-t
mv AUTHORS-t AUTHORS
cp AUTHORS $(distdir)/AUTHORS
@@ -288,13 +293,31 @@ stamp-guestfs-release-notes.pod: guestfs-release-notes.pod
$<
touch $@
# NB. podwrapper is an internal tool, so the man page mustn't be installed.
noinst_MANS = podwrapper.1
podwrapper.1: podwrapper.pl
$(PODWRAPPER) \
--section 1 \
--man $@-t \
--license GPLv2+ \
$<
mv $@-t $@
# Make clean.
CLEANFILES = \
*~ \
html/*.html \
pod2htm?.tmp \
podwrapper.1 \
qemu-wrapper.sh \
stamp-guestfs-release-notes.pod
stamp-guestfs-release-notes.pod \
tmp/guestfs.* \
tmp/run-* \
tmp/valgrind-*.log
clean-local:
-rm -rf tmp/libguestfs??????
# If you don't want to run all of the tests ('make check') then this
# will just run libguestfs-test-tool for a quick check. Note this
@@ -307,48 +330,53 @@ quickcheck:
extra-tests:
$(MAKE) -j1 \
valgrind \
valgrind-local-guests \
check-with-appliance \
check-valgrind \
check-valgrind-local-guests \
check-direct \
check-valgrind-direct \
check-with-upstream-qemu \
check-with-upstream-libvirt \
check-slow
check-valgrind: build-test-guests
@for f in `grep -l '^$@:' $(SUBDIRS:%=%/Makefile.am)`; do \
@errors=0; \
for f in `grep -l '^$@:' $(SUBDIRS:%=%/Makefile.am)`; do \
echo $(MAKE) -C `dirname $$f` $@; \
$(MAKE) -C `dirname $$f` $@ || exit $$?; \
done
$(MAKE) -C `dirname $$f` $@ || (( errors++ )); \
done; \
exit $$(( $$errors ? 1 : 0 ))
check-valgrind-local-guests:
@GUESTS=`$(top_builddir)/run ./pick-guests.pl 5`; \
errors=0; \
for f in `grep -l '^$@:' $(SUBDIRS:%=%/Makefile.am)`; do \
echo $(MAKE) GUESTS="$$GUESTS" -C `dirname $$f` $@; \
$(MAKE) GUESTS="$$GUESTS" -C `dirname $$f` $@ || exit $$?; \
done
$(MAKE) GUESTS="$$GUESTS" -C `dirname $$f` $@ || (( errors++ )); \
done; \
exit $$(( $$errors ? 1 : 0 ))
check-slow: build-test-guests
for f in `grep -l '^$@:' $(SUBDIRS:%=%/Makefile.am)`; do \
echo $(MAKE) -C `dirname $$f` $@; \
$(MAKE) -C `dirname $$f` $@ || exit $$?; \
done
build-test-guests:
$(MAKE) -C tests/guests check
check-with-appliance:
@method=`$(top_builddir)/run ./fish/guestfish get-attach-method`; \
if [ "$$method" != "appliance" ]; then \
$(MAKE) LIBGUESTFS_ATTACH_METHOD=appliance check || exit $$?; \
check-direct:
@backend=`$(top_builddir)/run ./fish/guestfish get-backend`; \
if [ "$$backend" != "direct" ]; then \
$(MAKE) LIBGUESTFS_BACKEND=direct check || exit $$?; \
fi
check-with-appliance: check-direct
check-valgrind-direct:
@backend=`$(top_builddir)/run ./fish/guestfish get-backend`; \
if [ "$$backend" != "direct" ]; then \
$(MAKE) LIBGUESTFS_BACKEND=direct check-valgrind || exit $$?; \
fi
check-valgrind-with-appliance: check-valgrind-direct
QEMUDIR = $(HOME)/d/qemu
QEMUBINARY = $(QEMUDIR)/x86_64-softmmu/qemu-system-x86_64
check-with-upstream-qemu:
@if $(QEMUBINARY) --help >/dev/null 2>&1; then \
$(MAKE) check-with-upstream-qemu-1 || exit $$?; \
fi
rm -f $(top_builddir)/qemu-wrapper.sh
$(MAKE) check-with-upstream-qemu-1 || exit $$?
check-with-upstream-qemu-1: $(top_builddir)/qemu-wrapper.sh
$(QEMUBINARY) --version
@@ -363,30 +391,61 @@ $(top_builddir)/qemu-wrapper.sh: Makefile
LIBVIRTDIR = $(HOME)/d/libvirt
check-with-upstream-libvirt:
@method=`$(top_builddir)/run ./fish/guestfish get-attach-method`; \
if [ "$$method" = "libvirt" ] && [ -x "$(LIBVIRTDIR)/run" ]; then \
@backend=`$(top_builddir)/run ./fish/guestfish get-backend`; \
if [ "$$backend" = "libvirt" ] && [ -x "$(LIBVIRTDIR)/run" ]; then \
$(LIBVIRTDIR)/run $(MAKE) check || exit $$?; \
fi
check-slow: build-test-guests
@errors=0; \
for f in `grep -l '^$@:' $(SUBDIRS:%=%/Makefile.am)`; do \
echo $(MAKE) -C `dirname $$f` $@; \
$(MAKE) -C `dirname $$f` $@ || (( errors++ )); \
done; \
exit $$(( $$errors ? 1 : 0 ))
build-test-guests:
$(MAKE) -C tests/guests check
# Print subdirs.
#
# If you want to selectively run tests, or if the test suite fails half
# way through, use:
#
# make print-subdirs
#
# to print the subdirectories, select the ones you want to run / the
# remaining ones, and do:
#
# make check SUBDIRS="..."
print-subdirs:
@echo $(SUBDIRS)
# Provide help on common Makefile targets.
help:
@echo
@echo "make Build everything."
@echo "make Build everything."
@echo
@echo "make check Run the standard tests."
@echo "make check-valgrind Run a subset of the tests under valgrind."
@echo "make check-valgrind-local-guests Test under valgrind using local guests."
@echo "make check-with-appliance Test using appliance attach-method."
@echo "make check-with-upstream-qemu Test using upstream qemu."
@echo "make check-with-upstream-libvirt Test using upstream libvirt."
@echo "make check-slow Slow/long-running tests."
@echo "make extra-tests Same as check-* (but not 'make check')"
@echo "make syntax-check Check syntax and style problems in the code."
@echo "make check Run the standard tests"
@echo "make -k check ... and display all errors at once."
@echo
@echo "make install Install everything."
@echo "make extra-tests Runs all of the following tests:"
@echo " make check-valgrind Run a subset of the tests under valgrind."
@echo " make check-valgrind-local-guests Test under valgrind using local guests."
@echo " make check-direct Test using direct backend."
@echo " make check-valgrind-direct Test valgrind + direct backend."
@echo " make check-with-upstream-qemu Test using upstream qemu."
@echo " make check-with-upstream-libvirt Test using upstream libvirt."
@echo " make check-slow Slow/long-running tests."
@echo
@echo "make clean Clean everything."
@echo "make syntax-check Check syntax and style problems in the code."
@echo "make print-subdirs Print subdirectories."
@echo
@echo "make install Install everything."
@echo
@echo "make clean Clean everything."
@echo
@echo "To run programs without installing:"
@echo " ./run ./fish/guestfish [or any other program]"

318
README
View File

@@ -41,134 +41,188 @@ Debian/Ubuntu users:
The full requirements are described below.
For basic functionality and the C tools:
- look at appliance/packagelist.in and install as many of the packages
that apply to your distro as possible
- QEMU >= 1.1.0.
- kernel >= 2.6.34 with virtio-serial support enabled.
- virtio-block and virtio-net drivers should be compiled into your
host kernel (strictly speaking this is optional, but you will have
to make complex changes to the ./configure command line to get it
to work if you don't have virtio)
- febootstrap >= 3.20
Notes: (1) febootstrap 2.x WILL NOT WORK
(2) febootstrap 3.x is distro-independent, and is required on
Debian and other distros as well as Fedora
(3) that is the minimum version, but later versions are better
- XDR, rpcgen (on Linux these are provided by glibc)
- cpio
- gperf
- pcre (Perl Compatible Regular Expressions C library)
- genisoimage (NOT mkisofs any more)
- hivex >= 1.2.7 (http://libguestfs.org/download) (optional)
- libmagic (the library that corresponds to the 'file' command) (optional)
- libvirt (optional, >= 0.10.2 to use the libvirt launch method)
- libxml2 (optional)
- libconfig (optional)
- augeas >= 0.5.0 (http://augeas.net/) (optional)
- Berkeley DB 'db_dump' and 'db_load' utilities
(db4-utils or db4.X-util or similar) (optional)
- systemtap/DTrace userspace probes (optional)
http://sourceware.org/systemtap/wiki/AddingUserSpaceProbingToApps
- perl Pod::Man and Pod::Simple are required. These are used to
generate man pages and other documentation. Every recent Perl
distribution ought to include both.
- Readline to have nicer command-line editing in guestfish (optional)
- xmllint (part of libxml2) to validate virt-inspector
RELAX NG schema (optional)
- OCaml compiler. Optional when compiling from the tarball, but
mandatory if you compile from git.
- ocaml-gettext if you want to translate OCaml tools (optional)
- po4a for translating manpages and POD files.
This is optional when compiling from the tarball, but mandatory
if you compile from git.
- getfacl, getfattr libraries and programs (optional)
- Linux capabilities library (libcap) (optional)
- libldm and ldmtool (optional)
This is used to handle Windows dynamic disks.
- yajl >= 2 (optional)
JSON parser, needed to handle the output of ldmtool.
- netpbm, icoutils (optional)
These programs are used to render icons from guests.
- Perl Expect module (optional)
This is used to test virt-rescue.
To build FUSE support in the core library, and guestmount:
- FUSE libraries and kernel module (optional)
To build language bindings:
- OCaml compiler to build the OCaml bindings (optional, but see above)
- Perl if you want to build the perl bindings (optional)
- Python if you want to build the python bindings (optional)
- Ruby, rake if you want to build the ruby bindings (optional)
- Java, JNI, jpackage-utils if you want to build the java
bindings (optional)
- GHC if you want to build the Haskell bindings (optional)
- PHP, phpize if you want to build the PHP bindings (optional)
To build the Perl tools:
- Perl Sys::Virt module (optional)
- Perl Win::Hivex module (optional)
- Perl Pod::Usage module (optional)
- Perl Test::More module (from perl Test::Simple) (optional)
- Perl String::ShellQuote module (optional)
- perl-libintl for translating perl code (optional)
R = Required
O = Optional
+==============+=============+===+=========================================+
| Package name | Min.version | | Notes |
+==============+=============+===+=========================================+
| Install as many packages listed in appliance/packagelist.in as possible. |
| This installs the disk management tools required by the appliance. The |
| list below is *additional* packages needed on the host. |
+--------------+-------------+---+-----------------------------------------+
| qemu | 1.2.0 | R | 1.1 may work, but has broken virtio-scsi|
+--------------+-------------+---+-----------------------------------------+
| qemu-img | | R | |
+--------------+-------------+---+-----------------------------------------+
| kernel | 2.6.34 | R | Make sure the following are enabled |
| | | | compiled in or as a module: |
| | | | - virtio-pci |
| | | | - virtio-serial |
| | | | - virtio-block |
| | | | - virtio-net |
+--------------+-------------+---+-----------------------------------------+
| supermin | 4.1.0 | R | This is required on all distros. |
| febootstrap | 3.20 | | 'supermin' is the new name for |
| | | | 'febootstrap'. |
| | | | For alternatives, see: |
| | | | libguestfs.org/download/binaries/appliance/
| | | | febootstrap 2.x WILL NOT WORK |
+--------------+-------------+---+-----------------------------------------+
| glibc | | R | We use various glibc-isms. |
| | | | Also glibc provides XDR, rpcgen. |
+--------------+-------------+---+-----------------------------------------+
| GCC or LLVM | | R | We use __attribute__((cleanup)). |
+--------------+-------------+---+-----------------------------------------+
| Perl | | R | Various build and test programs need |
| | | | Perl. Not needed at runtime except if |
| | | | you need to run a handful of virt-* |
| | | | tools that are still written in Perl. |
+--------------+-------------+---+-----------------------------------------+
| Pod::Man | | R | Part of Perl core. |
+--------------+-------------+---+-----------------------------------------+
| Pod::Simple | | R | Part of Perl core. |
+--------------+-------------+---+-----------------------------------------+
| OCaml | |R/O| Required if compiling from git. |
| | | | Optional if compiling from tarball. |
| | | | To build generated files and OCaml bindings.
+--------------+-------------+---+-----------------------------------------+
| autotools | |R/O| Required if compiling from git. |
| | | | Optional if compiling from tarball. |
| | | | Autotools-based build system. |
+--------------+-------------+---+-----------------------------------------+
| cpio | | R | |
+--------------+-------------+---+-----------------------------------------+
| gperf | | R | |
+--------------+-------------+---+-----------------------------------------+
| PCRE | | R | Perl-compatible Regular Expression lib. |
+--------------+-------------+---+-----------------------------------------+
| genisoimage | | R | mkisofs may work. |
+--------------+-------------+---+-----------------------------------------+
| po4a | |R/O| Required if compiling from git. |
| | | | Optional if compiling from tarball. |
| | | | For localizing man pages. |
+--------------+-------------+---+-----------------------------------------+
| hivex | 1.2.7 | O | Windows Registry hive parser. |
+--------------+-------------+---+-----------------------------------------+
| libmagic | | O | The library used by the 'file' command. |
+--------------+-------------+---+-----------------------------------------+
| libvirt | | O | >= 0.10.2 is needed if you want to use |
| | | | libvirt to manage transient VMs. |
+--------------+-------------+---+-----------------------------------------+
| libxml2 | | O | Popular XML library. |
+--------------+-------------+---+-----------------------------------------+
| xmllint | | O | Part of libxml2. Used for tests only. |
+--------------+-------------+---+-----------------------------------------+
| libconfig | | O | Used to parse libguestfs's own config |
| | | | files eg. /etc/libguestfs-tools.conf. |
+--------------+-------------+---+-----------------------------------------+
| libselinux | | O | Used by the libvirt backend to securely |
| | | | confine the appliance (sVirt). |
+--------------+-------------+---+-----------------------------------------+
| augeas | 0.5.0 | O | To inspect configuration of Linux guests.
+--------------+-------------+---+-----------------------------------------+
| db utils | | O | db_dump, db_load etc. Usually found in |
| | | | a package called db-utils, db4-utils, |
| | | | db4.X-utils, Berkeley DB utils, etc. |
+--------------+-------------+---+-----------------------------------------+
| systemtap | | O | For userspace probes. |
+--------------+-------------+---+-----------------------------------------+
| readline | | O | For nicer command line in guestfish. |
+--------------+-------------+---+-----------------------------------------+
| acl | | O | Library (libacl) and programs for |
| | | | handling POSIX ACLs. |
+--------------+-------------+---+-----------------------------------------+
| libcap | | O | Library (libcap) and programs for |
| | | | handling Linux capabilities. |
+--------------+-------------+---+-----------------------------------------+
| libldm | | O | Library (libldm) and 'ldmtool' for |
| | | | handling Windows Dynamic Disks. |
+--------------+-------------+---+-----------------------------------------+
| yajl | 2 | O | JSON parser for parsing output of |
| | | | ldmtool and qemu-img info commands. |
+--------------+-------------+---+-----------------------------------------+
| gdisk | | O | GPT disk support. |
+--------------+-------------+---+-----------------------------------------+
| netpbm | | O | Render icons from guests. |
+--------------+-------------+---+-----------------------------------------+
| icoutils | | O | Render icons from Windows guests. |
+--------------+-------------+---+-----------------------------------------+
| Expect | | O | Perl module used to test virt-rescue. |
+--------------+-------------+---+-----------------------------------------+
| FUSE | | O | fusermount, libfuse, and kernel module |
| | | | are all needed if you want guestmount |
| | | | and/or 'mount-local' support. |
+--------------+-------------+---+-----------------------------------------+
| static glibc | | O | Used for testing only. |
+--------------+-------------+---+-----------------------------------------+
| qemu-nbd | | O | Used for testing only. |
+--------------+-------------+---+-----------------------------------------+
| findlib | | O | For the OCaml bindings. |
+--------------+-------------+---+-----------------------------------------+
| ocaml-gettext| | O | For localizing OCaml virt-* tools. |
+--------------+-------------+---+-----------------------------------------+
| Python | 2.2 | O | For the Python bindings. |
+--------------+-------------+---+-----------------------------------------+
| Ruby | | O | >= 1.9 is better than 1.8. |
+--------------+-------------+---+-----------------------------------------+
| rake | | O | For the Ruby bindings. |
+--------------+-------------+---+-----------------------------------------+
| rubygem-minitest | O | For the Ruby bindings. |
+--------------+-------------+---+-----------------------------------------+
| Java | 1.6 | O | Java + JNI + jpackage-utils are needed |
| | | | for the Java bindings. |
+--------------+-------------+---+-----------------------------------------+
| GHC | | O | For the Haskell bindings. |
+--------------+-------------+---+-----------------------------------------+
| PHP | | O | For the PHP bindings. |
+--------------+-------------+---+-----------------------------------------+
| phpize | | O | For the PHP bindings. |
+--------------+-------------+---+-----------------------------------------+
| glib2 | | O | For the GObject bindings. |
+--------------+-------------+---+-----------------------------------------+
| gobject-introspection | O | For the GObject bindings. |
+--------------+-------------+---+-----------------------------------------+
| gjs | | O | For testing the GObject bindings. |
+--------------+-------------+---+-----------------------------------------+
| LUA | | O | For the LUA bindings. |
+--------------+-------------+---+-----------------------------------------+
| Erlang | | O | For the Erlang bindings. |
+--------------+-------------+---+-----------------------------------------+
| erl_interface| | O | For the Erlang bindings. |
+--------------+-------------+---+-----------------------------------------+
| valgrind | | O | For testing for memory problems. |
+--------------+-------------+---+-----------------------------------------+
| Sys::Virt | | O | Perl bindings for libvirt. |
+--------------+-------------+---+-----------------------------------------+
| Win::Hivex | | O | Perl bindings for hivex. |
+--------------+-------------+---+-----------------------------------------+
| Pod::Usage | | O | Perl module used by tests. |
+--------------+-------------+---+-----------------------------------------+
| Test::More | | O | Perl module used by tests. |
+--------------+-------------+---+-----------------------------------------+
| String::Shellquote | O | Perl module used by some virt-* tools. |
+--------------+-------------+---+-----------------------------------------+
| XML::XPath | | O | Perl module used by some virt-* tools. |
+--------------+-------------+---+-----------------------------------------+
| XML::XPath::XMLParser | O | Perl module used by some virt-* tools. |
+--------------+-------------+---+-----------------------------------------+
| perl-libintl | | O | Perl module for localization. |
+--------------+-------------+---+-----------------------------------------+
| bash-completion | O | For tab-completion of commands in bash. |
+==============+=============+===+=========================================+
R = Required
O = Optional
Building
----------------------------------------------------------------------
Then make the daemon, library and root filesystem:
Build the daemon, library and root filesystem:
./configure
make
Finally run the tests:
Run the tests:
make check
@@ -186,11 +240,20 @@ some libvirt guests installed, that these guests' disks are accessible
by the current user, and these tests may fail for other reasons which
are not necessarily because of real problems.
If everything works, you can install the library and tools by running
this command as root:
make help
lists all 'make' targets.
You may install the library by running the following command as root.
However *most users should probably not do this*. Instead, './run'
the programs from the build directory as described below.
make install
Distro packagers should use this instead:
make INSTALLDIRS=vendor [DESTDIR=...] install
You can run guestfish, guestmount and the virt tools without needing
to install, using the "./run" script in the top directory. This
script sets up some environment variables. For example:
@@ -204,8 +267,7 @@ command will also work:
../run ./guestfish [...]
You can also make a symlink (note: NOT a hard link) from your $PATH to
the run script, eg:
You can also make a link from your $PATH to the run script, eg:
cd ~/bin
ln -s ~/libguestfs/run libguestfs-run
@@ -289,7 +351,7 @@ distributions. Non-Linux ports are trickier, but we will accept
patches if they aren't too invasive.
The main porting issues are with the dependencies needed to build the
appliance. You will need to port the febootstrap first
appliance. You will need to port febootstrap first
(http://people.redhat.com/~rjones/febootstrap/).
@@ -324,11 +386,11 @@ For example:
--with-qemu-options="-M versatilepb -cpu arm926"
./configure \
--with-qemu="qemu-system-arm" \
--with-qemu-options="-M vexpress-a9 -cpu cortex-a9"
--with-qemu-options="-M vexpress-a15 -cpu cortex-a15"
Note that since virtio is required by libguestfs, and virtio is a
PCI-based architecture, whatever architecture qemu emulates must
support PCI also.
PCI-based architecture, whatever architecture qemu emulates MUST
support PCI.
For PPC64 you will need to specify the IBM pSeries machine type:
@@ -343,7 +405,7 @@ attention to the qemu command line and kernel output.
Copyright and license information
----------------------------------------------------------------------
Copyright (C) 2009-2012 Red Hat Inc.
Copyright (C) 2009-2013 Red Hat Inc.
The library is distributed under the LGPLv2+. The programs are
distributed under the GPLv2+. Please see the files COPYING and

16
TODO
View File

@@ -361,14 +361,14 @@ Interactive disk creator
An interactive disk creator program.
Attach method for disconnected operation
----------------------------------------
Backend for disconnected operation
----------------------------------
http://libguestfs.org/guestfs.3.html#guestfs_set_attach_method
http://libguestfs.org/guestfs.3.html#guestfs_set_backend
"Librarian" has an idea that he should be able to attach to a regular
appliance, but disconnect from it and reconnect to it later. This
would be some sort of modified attach method (see link above).
would be some sort of modified backend (see link above).
The complexity here is that we would no longer have access to
stdin/stdout (or we'd have to direct that somewhere else).
@@ -427,7 +427,7 @@ Launch remote sessions over ssh
-------------------------------
We had an idea you could add a launch method that uses ssh, ie. all
febootstrap and qemu commands happen the same as now, but prefixed by
supermin and qemu commands happen the same as now, but prefixed by
ssh so it happens on a remote machine.
Note that proper remote support and integration with libvirt is
@@ -490,7 +490,7 @@ Optimize the appliance
Pass -cpu host. Anything else?
[The libvirt attach-method uses 'host-model' which is basically
[The libvirt backend uses 'host-model' which is basically
the same as this]
Sort out partitioning
@@ -534,8 +534,8 @@ as data is reliably written out when g.sync, g.shutdown or g.close
return. Also in libguestfs we effectively control the whole stack, so
we can ensure write barriers happen when we want.
libvirt attach-method
---------------------
libvirt backend
---------------
Since libguestfs 1.19.24 this mostly works. Here are some suggested
items to work on:

View File

@@ -19,6 +19,7 @@ include $(top_srcdir)/subdir-rules.mk
EXTRA_DIST = \
test-virt-alignment-scan.sh \
test-virt-alignment-scan-guests.sh \
virt-alignment-scan.pod
CLEANFILES = stamp-virt-alignment-scan.pod
@@ -26,6 +27,12 @@ CLEANFILES = stamp-virt-alignment-scan.pod
bin_PROGRAMS = virt-alignment-scan
SHARED_SOURCE_FILES = \
../df/domains.c \
../df/domains.h \
../df/estimate-max-threads.c \
../df/estimate-max-threads.h \
../df/parallel.c \
../df/parallel.h \
../fish/config.c \
../fish/domain.c \
../fish/inspect.c \
@@ -35,16 +42,19 @@ SHARED_SOURCE_FILES = \
virt_alignment_scan_SOURCES = \
$(SHARED_SOURCE_FILES) \
domains.c \
scan.c \
scan.h
scan.c
virt_alignment_scan_CFLAGS = \
virt_alignment_scan_CPPFLAGS = \
-DGUESTFS_WARN_DEPRECATED=1 \
-DGUESTFS_PRIVATE=1 \
-I$(top_srcdir)/src -I$(top_builddir)/src \
-I$(top_srcdir)/df \
-I$(top_srcdir)/fish \
-I$(srcdir)/../gnulib/lib -I../gnulib/lib \
-DLOCALEBASEDIR=\""$(datadir)/locale"\" \
-DLOCALEBASEDIR=\""$(datadir)/locale"\"
virt_alignment_scan_CFLAGS = \
-pthread \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
$(GPROF_CFLAGS) $(GCOV_CFLAGS) \
$(LIBCONFIG_CFLAGS) \
@@ -52,9 +62,11 @@ virt_alignment_scan_CFLAGS = \
virt_alignment_scan_LDADD = \
$(LIBCONFIG_LIBS) \
$(top_builddir)/src/libutils.la \
$(top_builddir)/src/libguestfs.la \
../gnulib/lib/libgnu.la \
$(LIBXML2_LIBS) \
$(LIBVIRT_LIBS) \
../gnulib/lib/libgnu.la \
-lm
# Manual pages and HTML files for the website.
@@ -79,7 +91,8 @@ TESTS =
if ENABLE_APPLIANCE
TESTS += \
test-virt-alignment-scan.sh
test-virt-alignment-scan.sh \
test-virt-alignment-scan-guests.sh
endif
check-valgrind:

View File

@@ -1,359 +0,0 @@
/* virt-alignment-scan
* Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libintl.h>
#ifdef HAVE_LIBVIRT
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
#endif
#include "progname.h"
#if defined(HAVE_LIBVIRT) && defined(HAVE_LIBXML2)
#define GUESTFS_PRIVATE_FOR_EACH_DISK 1
#endif
#include "guestfs.h"
#include "options.h"
#include "scan.h"
#if defined(HAVE_LIBVIRT) && defined(HAVE_LIBXML2)
/* The list of domains and disks that we build up in
* get_domains_from_libvirt.
*/
struct disk {
struct disk *next;
char *filename;
char *format; /* could be NULL */
};
struct domain {
char *name;
char *uuid;
struct disk *disks;
size_t nr_disks;
};
struct domain *domains = NULL;
size_t nr_domains;
static int
compare_domain_names (const void *p1, const void *p2)
{
const struct domain *d1 = p1;
const struct domain *d2 = p2;
return strcmp (d1->name, d2->name);
}
static void
free_domain (struct domain *domain)
{
struct disk *disk, *next;
for (disk = domain->disks; disk; disk = next) {
next = disk->next;
free (disk->filename);
free (disk->format);
free (disk);
}
free (domain->name);
free (domain->uuid);
}
static void add_domains_by_id (virConnectPtr conn, int *ids, size_t n);
static void add_domains_by_name (virConnectPtr conn, char **names, size_t n);
static void add_domain (virDomainPtr dom);
static int add_disk (guestfs_h *g, const char *filename, const char *format, int readonly, void *domain_vp);
static size_t add_disks_to_handle_reverse (struct disk *disk, size_t *errors_r);
static void reset_guestfs_handle (void);
void
get_domains_from_libvirt (int uuid, size_t *worst_alignment_ptr)
{
virErrorPtr err;
virConnectPtr conn;
int n;
size_t i, count, errors;
const char *prefix;
nr_domains = 0;
domains = NULL;
/* Get the list of all domains. */
conn = virConnectOpenReadOnly (libvirt_uri);
if (!conn) {
err = virGetLastError ();
fprintf (stderr,
_("%s: could not connect to libvirt (code %d, domain %d): %s\n"),
program_name, err->code, err->domain, err->message);
exit (EXIT_FAILURE);
}
n = virConnectNumOfDomains (conn);
if (n == -1) {
err = virGetLastError ();
fprintf (stderr,
_("%s: could not get number of running domains (code %d, domain %d): %s\n"),
program_name, err->code, err->domain, err->message);
exit (EXIT_FAILURE);
}
int ids[n];
n = virConnectListDomains (conn, ids, n);
if (n == -1) {
err = virGetLastError ();
fprintf (stderr,
_("%s: could not list running domains (code %d, domain %d): %s\n"),
program_name, err->code, err->domain, err->message);
exit (EXIT_FAILURE);
}
add_domains_by_id (conn, ids, n);
n = virConnectNumOfDefinedDomains (conn);
if (n == -1) {
err = virGetLastError ();
fprintf (stderr,
_("%s: could not get number of inactive domains (code %d, domain %d): %s\n"),
program_name, err->code, err->domain, err->message);
exit (EXIT_FAILURE);
}
char *names[n];
n = virConnectListDefinedDomains (conn, names, n);
if (n == -1) {
err = virGetLastError ();
fprintf (stderr,
_("%s: could not list inactive domains (code %d, domain %d): %s\n"),
program_name, err->code, err->domain, err->message);
exit (EXIT_FAILURE);
}
add_domains_by_name (conn, names, n);
/* You must free these even though the libvirt documentation doesn't
* mention it.
*/
for (i = 0; i < (size_t) n; ++i)
free (names[i]);
virConnectClose (conn);
/* No domains? */
if (nr_domains == 0)
return;
/* Sort the domains alphabetically by name for display. */
qsort (domains, nr_domains, sizeof (struct domain), compare_domain_names);
errors = 0;
for (i = 0; i < nr_domains; ++i) {
if (domains[i].disks == NULL)
continue;
count = add_disks_to_handle_reverse (domains[i].disks, &errors);
if (count == 0)
continue;
if (guestfs_launch (g) == -1)
exit (EXIT_FAILURE);
prefix = !uuid ? domains[i].name : domains[i].uuid;
/* Perform the scan. */
scan (worst_alignment_ptr, prefix);
if (i < nr_domains - 1)
reset_guestfs_handle ();
}
/* Free up domains structure. */
for (i = 0; i < nr_domains; ++i)
free_domain (&domains[i]);
free (domains);
if (errors > 0) {
fprintf (stderr, _("%s: failed to analyze a disk, see error(s) above\n"),
program_name);
exit (EXIT_FAILURE);
}
}
static void
add_domains_by_id (virConnectPtr conn, int *ids, size_t n)
{
size_t i;
virDomainPtr dom;
for (i = 0; i < n; ++i) {
if (ids[i] != 0) { /* RHBZ#538041 */
dom = virDomainLookupByID (conn, ids[i]);
if (dom) { /* transient errors are possible here, ignore them */
add_domain (dom);
virDomainFree (dom);
}
}
}
}
static void
add_domains_by_name (virConnectPtr conn, char **names, size_t n)
{
size_t i;
virDomainPtr dom;
for (i = 0; i < n; ++i) {
dom = virDomainLookupByName (conn, names[i]);
if (dom) { /* transient errors are possible here, ignore them */
add_domain (dom);
virDomainFree (dom);
}
}
}
static void
add_domain (virDomainPtr dom)
{
struct domain *domain;
domains = realloc (domains, (nr_domains + 1) * sizeof (struct domain));
if (domains == NULL) {
perror ("realloc");
exit (EXIT_FAILURE);
}
domain = &domains[nr_domains];
nr_domains++;
domain->name = strdup (virDomainGetName (dom));
if (domain->name == NULL) {
perror ("strdup");
exit (EXIT_FAILURE);
}
char uuid[VIR_UUID_STRING_BUFLEN];
if (virDomainGetUUIDString (dom, uuid) == 0) {
domain->uuid = strdup (uuid);
if (domain->uuid == NULL) {
perror ("strdup");
exit (EXIT_FAILURE);
}
}
else
domain->uuid = NULL;
domain->disks = NULL;
int n = guestfs___for_each_disk (g, dom, add_disk, domain);
if (n == -1)
exit (EXIT_FAILURE);
domain->nr_disks = n;
}
static int
add_disk (guestfs_h *g,
const char *filename, const char *format, int readonly,
void *domain_vp)
{
struct domain *domain = domain_vp;
struct disk *disk;
disk = malloc (sizeof *disk);
if (disk == NULL) {
perror ("malloc");
return -1;
}
disk->next = domain->disks;
domain->disks = disk;
disk->filename = strdup (filename);
if (disk->filename == NULL) {
perror ("malloc");
return -1;
}
if (format) {
disk->format = strdup (format);
if (disk->format == NULL) {
perror ("malloc");
return -1;
}
}
else
disk->format = NULL;
return 0;
}
static size_t
add_disks_to_handle_reverse (struct disk *disk, size_t *errors_r)
{
size_t nr_disks_added;
if (disk == NULL)
return 0;
nr_disks_added = add_disks_to_handle_reverse (disk->next, errors_r);
struct guestfs_add_drive_opts_argv optargs = { .bitmask = 0 };
optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_READONLY_BITMASK;
optargs.readonly = 1;
if (disk->format) {
optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_FORMAT_BITMASK;
optargs.format = disk->format;
}
if (guestfs_add_drive_opts_argv (g, disk->filename, &optargs) == -1) {
(*errors_r)++;
return nr_disks_added;
}
return nr_disks_added+1;
}
/* Close and reopen the libguestfs handle. */
static void
reset_guestfs_handle (void)
{
/* Copy the settings from the old handle. */
int verbose = guestfs_get_verbose (g);
int trace = guestfs_get_trace (g);
guestfs_close (g);
g = guestfs_create ();
if (g == NULL) {
fprintf (stderr, _("guestfs_create: failed to create handle\n"));
exit (EXIT_FAILURE);
}
guestfs_set_verbose (g, verbose);
guestfs_set_trace (g, trace);
}
#endif

View File

@@ -29,6 +29,8 @@
#include <assert.h>
#include <libintl.h>
#include <pthread.h>
#ifdef HAVE_LIBVIRT
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
@@ -38,7 +40,18 @@
#include "guestfs.h"
#include "options.h"
#include "scan.h"
#include "parallel.h"
#include "domains.h"
/* This just needs to be larger than any alignment we care about. */
static size_t worst_alignment = UINT_MAX;
static pthread_mutex_t worst_alignment_mutex = PTHREAD_MUTEX_INITIALIZER;
static int scan (guestfs_h *g, const char *prefix, FILE *fp);
#ifdef HAVE_LIBVIRT
static int scan_work (guestfs_h *g, size_t i, FILE *fp);
#endif
/* These globals are shared with options.c. */
guestfs_h *g;
@@ -52,12 +65,7 @@ const char *libvirt_uri = NULL;
int inspector = 0;
static int quiet = 0; /* --quiet */
static inline char *
bad_cast (char const *s)
{
return (char *) s;
}
static int uuid = 0; /* --uuid */
static void __attribute__((noreturn))
usage (int status)
@@ -78,6 +86,7 @@ usage (int status)
" -d|--domain guest Add disks from libvirt guest\n"
" --format[=raw|..] Force disk format for -a option\n"
" --help Display brief help\n"
" -P nr_threads Use at most nr_threads\n"
" -q|--quiet No output, just exit code\n"
" -v|--verbose Verbose messages\n"
" -V|--version Display version and exit\n"
@@ -101,13 +110,14 @@ main (int argc, char *argv[])
enum { HELP_OPTION = CHAR_MAX + 1 };
static const char *options = "a:c:d:qvVx";
static const char *options = "a:c:d:P:qvVx";
static const struct option long_options[] = {
{ "add", 1, 0, 'a' },
{ "connect", 1, 0, 'c' },
{ "domain", 1, 0, 'd' },
{ "format", 2, 0, 0 },
{ "help", 0, 0, HELP_OPTION },
{ "long-options", 0, 0, 0 },
{ "quiet", 0, 0, 'q' },
{ "uuid", 0, 0, 0, },
{ "verbose", 0, 0, 'v' },
@@ -119,10 +129,9 @@ main (int argc, char *argv[])
const char *format = NULL;
int c;
int option_index;
int uuid = 0;
/* This just needs to be larger than any alignment we care about. */
size_t worst_alignment = UINT_MAX;
int exit_code;
size_t max_threads = 0;
int r;
g = guestfs_create ();
if (g == NULL) {
@@ -130,7 +139,7 @@ main (int argc, char *argv[])
exit (EXIT_FAILURE);
}
argv[0] = bad_cast (program_name);
argv[0] = (char *) program_name;
for (;;) {
c = getopt_long (argc, argv, options, long_options, &option_index);
@@ -138,7 +147,9 @@ main (int argc, char *argv[])
switch (c) {
case 0: /* options which are long only */
if (STREQ (long_options[option_index].name, "format")) {
if (STREQ (long_options[option_index].name, "long-options"))
display_long_options (long_options);
else if (STREQ (long_options[option_index].name, "format")) {
if (!optarg || STREQ (optarg, ""))
format = NULL;
else
@@ -164,6 +175,13 @@ main (int argc, char *argv[])
OPTION_d;
break;
case 'P':
if (sscanf (optarg, "%zu", &max_threads) != 1) {
fprintf (stderr, _("%s: -P option is not numeric\n"), program_name);
exit (EXIT_FAILURE);
}
break;
case 'q':
quiet = 1;
break;
@@ -200,16 +218,25 @@ main (int argc, char *argv[])
if (optind != argc)
usage (EXIT_FAILURE);
/* The user didn't specify any drives to scan. */
/* virt-alignment-scan has two modes. If the user didn't specify
* any drives, then we do the scan on every libvirt guest. That's
* the if-clause below. If the user specified domains/drives, then
* we assume they belong to a single guest. That's the else-clause
* below.
*/
if (drvs == NULL) {
#if defined(HAVE_LIBVIRT) && defined(HAVE_LIBXML2)
get_domains_from_libvirt (uuid, &worst_alignment);
get_all_libvirt_domains (libvirt_uri);
r = start_threads (max_threads, g, scan_work);
free_domains ();
if (r == -1)
exit (EXIT_FAILURE);
#else
fprintf (stderr, _("%s: compiled without support for libvirt and/or libxml2.\n"),
program_name);
exit (EXIT_FAILURE);
#endif
} else {
} else { /* Single guest. */
if (uuid) {
fprintf (stderr, _("%s: --uuid option cannot be used with -a or -d\n"),
program_name);
@@ -226,9 +253,12 @@ main (int argc, char *argv[])
free_drives (drvs);
/* Perform the scan. */
scan (&worst_alignment, NULL);
r = scan (g, NULL, stdout);
guestfs_close (g);
if (r == -1)
exit (EXIT_FAILURE);
}
/* Decide on an appropriate exit code. */
@@ -242,30 +272,30 @@ main (int argc, char *argv[])
exit (exit_code);
}
void
scan (size_t *worst_alignment, const char *prefix)
static int
scan (guestfs_h *g, const char *prefix, FILE *fp)
{
char **devices, *p;
size_t i, j;
size_t alignment;
uint64_t start;
struct guestfs_partition_list *parts;
int err;
devices = guestfs_list_devices (g);
CLEANUP_FREE_STRING_LIST char **devices = guestfs_list_devices (g);
if (devices == NULL)
exit (EXIT_FAILURE);
return -1;
for (i = 0; devices[i] != NULL; ++i) {
parts = guestfs_part_list (g, devices[i]);
CLEANUP_FREE char *name = NULL;
CLEANUP_FREE_PARTITION_LIST struct guestfs_partition_list *parts =
guestfs_part_list (g, devices[i]);
if (parts == NULL)
exit (EXIT_FAILURE);
return -1;
/* Canonicalize the name of the device for printing. */
p = guestfs_canonical_device_name (g, devices[i]);
if (p == NULL)
exit (EXIT_FAILURE);
free (devices[i]);
devices[i] = p;
name = guestfs_canonical_device_name (g, devices[i]);
if (name == NULL)
return -1;
for (j = 0; j < parts->len; ++j) {
/* Start offset of the partition in bytes. */
@@ -273,10 +303,10 @@ scan (size_t *worst_alignment, const char *prefix)
if (!quiet) {
if (prefix)
printf ("%s:", prefix);
fprintf (fp, "%s:", prefix);
printf ("%s%d %12" PRIu64 " ",
devices[i], (int) parts->val[j].part_num, start);
fprintf (fp, "%s%d %12" PRIu64 " ",
name, (int) parts->val[j].part_num, start);
}
/* What's the alignment? */
@@ -288,30 +318,60 @@ scan (size_t *worst_alignment, const char *prefix)
if (!quiet) {
if (alignment < 10)
printf ("%12" PRIu64 " ", UINT64_C(1) << alignment);
fprintf (fp, "%12" PRIu64 " ", UINT64_C(1) << alignment);
else if (alignment < 64)
printf ("%12" PRIu64 "K ", UINT64_C(1) << (alignment - 10));
fprintf (fp, "%12" PRIu64 "K ", UINT64_C(1) << (alignment - 10));
else
printf ("- ");
fprintf (fp, "- ");
}
if (alignment < *worst_alignment)
*worst_alignment = alignment;
err = pthread_mutex_lock (&worst_alignment_mutex);
assert (err == 0);
if (alignment < worst_alignment)
worst_alignment = alignment;
err = pthread_mutex_unlock (&worst_alignment_mutex);
assert (err == 0);
if (alignment < 12) { /* Bad in general: < 4K alignment */
if (!quiet)
printf ("bad (%s)\n", _("alignment < 4K"));
fprintf (fp, "bad (%s)\n", _("alignment < 4K"));
} else if (alignment < 16) { /* Bad on NetApps: < 64K alignment */
if (!quiet)
printf ("bad (%s)\n", _("alignment < 64K"));
fprintf (fp, "bad (%s)\n", _("alignment < 64K"));
} else {
if (!quiet)
printf ("ok\n");
fprintf (fp, "ok\n");
}
}
guestfs_free_partition_list (parts);
free (devices[i]);
}
free (devices);
return 0;
}
#if defined(HAVE_LIBVIRT)
/* The multi-threaded version. This callback is called from the code
* in "parallel.c".
*/
static int
scan_work (guestfs_h *g, size_t i, FILE *fp)
{
struct guestfs___add_libvirt_dom_argv optargs;
optargs.bitmask =
GUESTFS___ADD_LIBVIRT_DOM_READONLY_BITMASK |
GUESTFS___ADD_LIBVIRT_DOM_READONLYDISK_BITMASK;
optargs.readonly = 1;
optargs.readonlydisk = "read";
if (guestfs___add_libvirt_dom (g, domains[i].dom, &optargs) == -1)
return -1;
if (guestfs_launch (g) == -1)
return -1;
return scan (g, !uuid ? domains[i].name : domains[i].uuid, fp);
}
#endif /* HAVE_LIBVIRT */

View File

@@ -0,0 +1,35 @@
#!/bin/bash -
# libguestfs
# Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
export LANG=C
if [ -n "$SKIP_TEST_VIRT_ALIGNMENT_SCAN_GUESTS_SH" ]; then
echo "$0: skipping test because SKIP_TEST_VIRT_ALIGNMENT_SCAN_GUESTS_SH is set."
exit 77
fi
guestsdir="$(cd ../tests/guests && pwd)"
libvirt_uri="test://$guestsdir/guests-all-good.xml"
$VG ./virt-alignment-scan -c "$libvirt_uri"
r=$?
# 0, 2 and 3 are reasonable non-error exit codes. Others are errors.
if [ $r -ne 0 -a $r -ne 2 -a $r -ne 3 ]; then
exit $r
fi

View File

@@ -16,6 +16,8 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
export LANG=C
$VG ./virt-alignment-scan -a ../tests/guests/fedora.img
r=$?

View File

@@ -158,6 +158,18 @@ If you have untrusted raw-format guest disk images, you should use
this option to specify the disk format. This avoids a possible
security problem with malicious guests (CVE-2010-3851).
=item B<-P> nr_threads
Since libguestfs 1.22, virt-alignment-scan is multithreaded and
examines guests in parallel. By default the number of threads to use
is chosen based on the amount of free memory available at the time
that virt-alignment-scan is started. You can force
virt-alignment-scan to use at most C<nr_threads> by using the I<-P>
option.
Note that I<-P 0> means to autodetect, and I<-P 1> means to use a
single thread.
=item B<-q>
=item B<--quiet>

View File

@@ -35,15 +35,23 @@ superminfsdir = $(libdir)/guestfs/supermin.d
fs_DATA =
superminfs_DATA = \
supermin.d/base.img \
supermin.d/daemon.img \
supermin.d/init.img \
supermin.d/hostfiles \
supermin.d/udev-rules.img
# This used to be a configure-generated file (as is update.sh still).
# However config.status always touches the destination file, which
# means the appliance got rebuilt too often.
if ENABLE_DAEMON
superminfs_DATA += \
supermin.d/daemon.img
endif
if ENABLE_APPLIANCE
superminfs_DATA += \
supermin.d/base.img \
supermin.d/hostfiles
endif
# This used to be a configure-generated file. However config.status
# always touches the destination file, which means the appliance got
# rebuilt too often.
make.sh: make.sh.in $(top_builddir)/config.log $(top_builddir)/config.status
cd $(top_builddir) && \
./config.status --file=appliance/$@-t:appliance/$<
@@ -51,7 +59,7 @@ make.sh: make.sh.in $(top_builddir)/config.log $(top_builddir)/config.status
cmp -s $@ $@-t || mv $@-t $@
rm -f $@-t
PACKAGELIST_CPP_FLAGS = -D$(DISTRO)=1
PACKAGELIST_CPP_FLAGS = -D$(DISTRO)=1 -DEXTRA_PACKAGES="$(EXTRA_PACKAGES)"
if VALGRIND_DAEMON
PACKAGELIST_CPP_FLAGS += -DVALGRIND_DAEMON=1
endif
@@ -100,7 +108,7 @@ supermin.d/udev-rules.img: 99-guestfs-serial.rules
rm -f $@ $@-t
rm -rf tmp-u
mkdir -p tmp-u/etc/udev/rules.d
for f in $^; do ln $$f tmp-u/etc/udev/rules.d/$$f; done
for f in $^; do ln $$f tmp-u/etc/udev/rules.d/$$(basename $$f); done
( cd tmp-u && find | cpio --quiet -o -H newc ) > $@-t
rm -rf tmp-u
mv $@-t $@

View File

@@ -10,6 +10,16 @@ RUNLEVEL=S
PREVLEVEL=N
export RUNLEVEL PREVLEVEL
# Try to print a stack trace for segfaults inside the appliance.
for d in /lib64 /lib; do
f=$d/libSegFault.so
if [ -f "$f" ]; then
LD_PRELOAD=$f
export LD_PRELOAD
break
fi
done
mkdir -p /sysroot
if [ ! -d /proc ]; then rm -f /proc; fi
@@ -18,6 +28,9 @@ mount -t proc /proc /proc
if [ ! -d /sys ]; then rm -f /sys; fi
mkdir -p /sys
mount -t sysfs /sys /sys
# taken from initramfs-tools/init --Hilko Bengen
mkdir -p /run
mount -t tmpfs -o "nosuid,size=20%,mode=0755" tmpfs /run
mkdir -p /run/lock
# devtmpfs is required since udev 176

View File

@@ -15,11 +15,33 @@ libguestfs-make-fixed-appliance - Make a "fixed appliance" for libguestfs
libguestfs-make-fixed-appliance lets you make a pre-built binary
appliance for libguestfs.
B<Note that ordinary users should not need to run this tool>. The
only reason to use it is if you want to make a self-contained
libguestfs appliance that can be copied to another machine or platform
that doesn't support L<febootstrap(8)>. To understand why you might
need to use this tool, read the section L</FIXED APPLIANCE> below.
B<Note that ordinary users should not need to run this tool>.
Some reasons why you I<might> want to use this include:
=over 4
=item *
You want to make a self-contained libguestfs appliance that can be
copied to another machine or platform that doesn't support
L<supermin(8)>.
=item *
You have multiple users on the same machine and want to avoid the
storage duplication and start-up overhead of having multiple cached
copies of the appliance.
=item *
You want to have very predictable performance from libguestfs (see
L<guestfs-performance(1)>).
=back
For deeper understanding of why you might need this tool, read the
section L</FIXED APPLIANCE> below.
Instead of running this tool, you can download fixed appliances from
L<http://libguestfs.org/download/binaries/appliance/>. These
@@ -107,21 +129,21 @@ looking for an appliance. The path is built into libguestfs, or can
be set using the C<LIBGUESTFS_PATH> environment variable.
Normally a supermin appliance is located on this path (see
L<febootstrap(8)/SUPERMIN APPLIANCE>). libguestfs reconstructs this
into a full appliance by running L<febootstrap-supermin-helper(8)>.
L<supermin(8)/SUPERMIN APPLIANCE>). libguestfs reconstructs this
into a full appliance by running L<supermin-helper(8)>.
However, a simpler "fixed appliance" can also be used. libguestfs
detects this by looking for a directory on the path containing four
files called C<kernel>, C<initrd>, C<root> and C<README.fixed> (note
the C<README.fixed> file must be present as well).
If the fixed appliance is found, libguestfs skips febootstrap entirely
If the fixed appliance is found, libguestfs skips supermin entirely
and just runs qemu with the kernel, initrd and root disk from the
fixed appliance.
Thus the fixed appliance can be used when a platform or Linux distro
does not support febootstrap. You build the fixed appliance on a
platform that does support febootstrap, and copy it over, and use that
does not support supermin. You build the fixed appliance on a
platform that does support supermin, and copy it over, and use that
to run libguestfs.
=head1 LICENSING
@@ -144,8 +166,8 @@ libguestfs, please see the L<guestfs(3)> manual page.
=head1 SEE ALSO
L<guestfs(3)>,
L<febootstrap(8)>,
L<febootstrap-supermin-helper(8)>,
L<supermin(8)>,
L<supermin-helper(8)>,
L<xz(1)>,
L<http://libguestfs.org/>,
L<http://qemu.org/>.
@@ -156,4 +178,4 @@ Richard W.M. Jones (C<rjones at redhat dot com>)
=head1 COPYRIGHT
Copyright (C) 2009-2012 Red Hat Inc.
Copyright (C) 2009-2013 Red Hat Inc.

View File

@@ -1,6 +1,6 @@
#!/bin/bash -
# @configure_input@
# Copyright (C) 2009-2012 Red Hat Inc.
# Copyright (C) 2009-2013 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
@@ -27,13 +27,15 @@ while read regexp <&5; do
done
exec 5<&-
# Run febootstrap on the package list.
if [ "x@FEBOOTSTRAP_YUM_CONFIG@" != "xno" ]; then
extra="--yum-config @FEBOOTSTRAP_YUM_CONFIG@"
# Run supermin on the package list.
# NB: Keep using --yum-config (deprecated alias) here since both old
# and new supermin still support it.
if [ "x@SUPERMIN_PACKAGER_CONFIG@" != "xno" ]; then
extra="--yum-config @SUPERMIN_PACKAGER_CONFIG@"
fi
echo @FEBOOTSTRAP@ -v -o supermin.d --names $(< packagelist ) $excludes $extra
@FEBOOTSTRAP@ -v -o supermin.d --names $(< packagelist ) $excludes $extra
echo @SUPERMIN@ -v -o supermin.d --names $(< packagelist ) $excludes $extra
@SUPERMIN@ -v -o supermin.d --names $(< packagelist ) $excludes $extra
# Remove some things that we don't want in the appliance. This is
# copied from the old febootstrap-minimize. However minimization is
@@ -41,10 +43,6 @@ echo @FEBOOTSTRAP@ -v -o supermin.d --names $(< packagelist ) $excludes $extra
< supermin.d/hostfiles \
grep -v '^/usr/lib/locale' |
grep -v '^/usr/share/locale' |
grep -v '^/usr/lib/gconv' |
grep -v '^/usr/lib64/gconv' |
grep -v '^/usr/bin/localedef' |
grep -v '^/usr/sbin/build-locale-archive' |
grep -v '^/usr/share/man/' |
grep -v '^/usr/share/doc/' |
grep -v '^/usr/share/info/' |

View File

@@ -11,6 +11,10 @@
*
* There is also a list of packages which are excluded if they appear
* as dependencies of the packages below. See: excludelist.in
*
* To add arbitrary extra packages, use:
*
* ./configure --with-extra-packages="gdb valgrind [etc]"
*/
/* Basically the same with a few minor tweaks. */
@@ -35,14 +39,17 @@
iproute
iputils
kernel
libcap
libldm /* only Fedora has this for now, but we should add it to others later*/
MAKEDEV
nilfs-utils
ntfsprogs
ntfs-3g
openssh-clients
pcre
reiserfs-utils
libselinux
syslinux-extlinux
systemd /* for /sbin/reboot and udevd */
vim-minimal
xz
@@ -55,6 +62,7 @@
btrfs-tools
cryptsetup
e2fsprogs
extlinux
genisoimage
gfs-tools
gfs2-tools
@@ -62,7 +70,9 @@
hfsplus
iproute
libaugeas0
libcap2
libhivex0
libpcre3
libyajl2
linux-image
nilfs-tools
@@ -70,6 +80,7 @@
ntfsprogs
openssh-client
reiserfsprogs
sysvinit /* for /sbin/reboot */
ufsutils
vim-tiny
xz-utils
@@ -86,11 +97,13 @@
hivex
iproute2
iputils
libcap
linux
lrzip
nilfs-utils
ntfsprogs
ntfs-3g
pcre
reiserfsprogs
systemd
vim
@@ -111,6 +124,7 @@ dosfstools
file
findutils
gawk
gdisk
grep
gzip
jfsutils
@@ -136,6 +150,7 @@ rsync
scrub
sed
strace
syslinux
tar
udev
util-linux
@@ -152,7 +167,5 @@ zerofree
valgrind
#endif
/* Enable this to add useful debugging tools to the appliance. */
#if 0
gdb
#endif
/* Define this by doing: ./configure --with-extra-packages="..." */
EXTRA_PACKAGES

68
bash/Makefile.am Normal file
View File

@@ -0,0 +1,68 @@
# libguestfs
# Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
include $(top_srcdir)/subdir-rules.mk
scripts = \
guestfish \
guestmount \
virt-alignment-scan \
virt-cat \
virt-df \
virt-edit \
virt-filesystems \
virt-format \
virt-inspector \
virt-ls \
virt-rescue \
virt-resize \
virt-sparsify \
virt-sysprep
EXTRA_DIST = \
README \
$(scripts)
# Some of the scripts are simply symbolic links.
virt-cat:
ln -sf virt-alignment-scan $@
virt-df:
ln -sf virt-alignment-scan $@
virt-edit:
ln -sf virt-alignment-scan $@
virt-filesystems:
ln -sf virt-alignment-scan $@
virt-format:
ln -sf virt-alignment-scan $@
virt-inspector:
ln -sf virt-alignment-scan $@
virt-ls:
ln -sf virt-alignment-scan $@
virt-sysprep:
ln -sf virt-alignment-scan $@
virt-sparsify:
ln -sf virt-resize $@
if HAVE_BASH_COMPLETION
# Bash completion script.
bashcompletiondir = $(BASH_COMPLETIONS_DIR)
bashcompletion_DATA = $(scripts)
endif

3
bash/README Normal file
View File

@@ -0,0 +1,3 @@
This directory contains the scripts for tab-completing commands in
bash. Note these new-style demand-loaded scripts require
'bash-completion' >= 1.99.

72
bash/guestfish Normal file
View File

@@ -0,0 +1,72 @@
# guestfish bash completion script -*- shell-script -*-
# Copyright (C) 2010-2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# List all local libvirt domains.
_guestfs_virsh_list ()
{
local flag_ro=$1 flags
if [ "$flag_ro" -eq 1 ]; then
flags="--all"
else
flags="--inactive"
fi
virsh list $flags | head -n -1 | tail -n +3 | awk '{print $2}'
}
_guestfish ()
{
local cur prev words cword split
local longopts flag_ro=0 c=1 word cmds doms
_init_completion -s || return
longopts="$(guestfish --long-options)"
# See if user has specified certain options anywhere on the
# command line before the current word.
while [ $c -lt $COMP_CWORD ]; do
word="${COMP_WORDS[c]}"
case "$word" in
-r|--ro) flag_ro=1 ;;
esac
c=$((++c))
done
case "$prev" in
-a|--add)
COMPREPLY=( $(compgen "$cur") )
return ;;
-d|--domain)
doms=$(_guestfs_virsh_list "$flag_ro")
COMPREPLY=( $(compgen -W "$doms" -- "$cur") )
return ;;
esac
case "$cur" in
--*)
# --options
COMPREPLY=( $(compgen -W "$longopts" -- "$cur") )
return ;;
*)
# Might be a guestfish command.
cmds=$(guestfish -h| head -n -1 | tail -n +2 | awk '{print $1}')
COMPREPLY=( $(compgen -W "$cmds" -- "$cur") )
return ;;
esac
} &&
complete -o default -F _guestfish guestfish

67
bash/guestmount Normal file
View File

@@ -0,0 +1,67 @@
# guestmount bash completion script -*- shell-script -*-
# Copyright (C) 2010-2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# List all local libvirt domains.
_guestfs_virsh_list ()
{
local flag_ro=$1 flags
if [ "$flag_ro" -eq 1 ]; then
flags="--all"
else
flags="--inactive"
fi
virsh list $flags | head -n -1 | tail -n +3 | awk '{print $2}'
}
_guestmount ()
{
local cur prev words cword split
local longopts flag_ro=0 c=1 word doms
_init_completion -s || return
longopts="$(guestmount --long-options)"
# See if user has specified certain options anywhere on the
# command line before the current word.
while [ $c -lt $COMP_CWORD ]; do
word="${COMP_WORDS[c]}"
case "$word" in
-r|--ro) flag_ro=1 ;;
esac
c=$((++c))
done
case "$prev" in
-d|--domain)
doms=$(_guestfs_virsh_list "$flag_ro")
COMPREPLY=( $(compgen -W "$doms" -- "$cur") )
return ;;
esac
case "$cur" in
--*)
# --options
COMPREPLY=( $(compgen -W "$longopts" -- "$cur") )
return ;;
*)
COMPREPLY=( $(compgen "$cur") )
return ;;
esac
} &&
complete -o default -F _guestmount guestmount

108
bash/virt-alignment-scan Normal file
View File

@@ -0,0 +1,108 @@
# virt-tools bash completion script -*- shell-script -*-
# Copyright (C) 2010-2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# List all local libvirt domains.
_guestfs_virsh_list ()
{
local flag_ro=$1 flags
if [ "$flag_ro" -eq 1 ]; then
flags="--all"
else
flags="--inactive"
fi
virsh list $flags | head -n -1 | tail -n +3 | awk '{print $2}'
}
_guestfs_virttools ()
{
local cur prev words cword split
local longopts="$1" flag_ro="$2" doms
_init_completion -s || return
case "$prev" in
-d|--domain)
doms=$(_guestfs_virsh_list "$flag_ro")
COMPREPLY=( $(compgen -W "$doms" -- "$cur") )
return ;;
esac
case "$cur" in
--*)
# --options
COMPREPLY=( $(compgen -W "$longopts" -- "$cur") )
return ;;
*)
COMPREPLY=( $(compgen "$cur") )
return ;;
esac
}
_virt_alignment_scan ()
{
_guestfs_virttools "$(virt-alignment-scan --long-options)" 1
} &&
complete -o default -F _virt_alignment_scan virt-alignment-scan
_virt_cat ()
{
_guestfs_virttools "$(virt-cat --long-options)" 1
} &&
complete -o default -F _virt_cat virt-cat
_virt_df ()
{
_guestfs_virttools "$(virt-df --long-options)" 1
} &&
complete -o default -F _virt_df virt-df
_virt_edit ()
{
_guestfs_virttools "$(virt-edit --long-options)" 0
} &&
complete -o default -F _virt_edit virt-edit
_virt_filesystems ()
{
_guestfs_virttools "$(virt-filesystems --long-options)" 1
} &&
complete -o default -F _virt_filesystems virt-filesystems
_virt_format ()
{
_guestfs_virttools "$(virt-format --long-options)" 0
} &&
complete -o default -F _virt_format virt-format
_virt_inspector ()
{
_guestfs_virttools "$(virt-inspector --long-options)" 1
} &&
complete -o default -F _virt_inspector virt-inspector
_virt_ls ()
{
_guestfs_virttools "$(virt-ls --long-options)" 1
} &&
complete -o default -F _virt_ls virt-ls
_virt_sysprep ()
{
_guestfs_virttools "$(virt-sysprep --long-options)" 0
} &&
complete -o default -F _virt_sysprep virt-sysprep

67
bash/virt-rescue Normal file
View File

@@ -0,0 +1,67 @@
# virt-rescue bash completion script -*- shell-script -*-
# Copyright (C) 2010-2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# List all local libvirt domains.
_guestfs_virsh_list ()
{
local flag_ro=$1 flags
if [ "$flag_ro" -eq 1 ]; then
flags="--all"
else
flags="--inactive"
fi
virsh list $flags | head -n -1 | tail -n +3 | awk '{print $2}'
}
_virt_rescue ()
{
local cur prev words cword split
local longopts flag_ro=0 c=1 word doms
_init_completion -s || return
longopts="$(virt-rescue --long-options)"
# See if user has specified certain options anywhere on the
# command line before the current word.
while [ $c -lt $COMP_CWORD ]; do
word="${COMP_WORDS[c]}"
case "$word" in
-r|--ro) flag_ro=1 ;;
esac
c=$((++c))
done
case "$prev" in
-d|--domain)
doms=$(_guestfs_virsh_list "$flag_ro")
COMPREPLY=( $(compgen -W "$doms" -- "$cur") )
return ;;
esac
case "$cur" in
--*)
# --options
COMPREPLY=( $(compgen -W "$longopts" -- "$cur") )
return ;;
*)
COMPREPLY=( $(compgen "$cur") )
return ;;
esac
} &&
complete -o default -F _virt_rescue virt-rescue

46
bash/virt-resize Normal file
View File

@@ -0,0 +1,46 @@
# virt-resize, virt-sparsify bash completion script -*- shell-script -*-
# Copyright (C) 2010-2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
_guestfs_options_only ()
{
local cur prev words cword split
local longopts="$1"
_init_completion -s || return
case "$cur" in
--*)
# --options
COMPREPLY=( $(compgen -W "$longopts" -- "$cur") )
return ;;
*)
COMPREPLY=( $(compgen "$cur") )
return ;;
esac
}
_virt_resize ()
{
_guestfs_options_only "$(virt-resize --long-options)"
} &&
complete -o default -F _virt_resize virt-resize
_virt_sparsify ()
{
_guestfs_options_only "$(virt-sparsify --long-options)"
} &&
complete -o default -F _virt_sparsify virt-sparsify

View File

@@ -38,6 +38,8 @@ gnulib_tool=$GNULIB_SRCDIR/gnulib-tool
modules='
accept4
areadlink
areadlinkat
arpa_inet
byteswap
c-ctype
@@ -68,6 +70,7 @@ maintainer-makefile
manywarnings
memmem
mkdtemp
mkstemps
netdb
netinet_in
openat

View File

@@ -1,6 +1,6 @@
#!/bin/bash -
# bugs-in-changelog.sh
# Copyright (C) 2009-2012 Red Hat Inc.
# Copyright (C) 2009-2013 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

View File

@@ -41,57 +41,72 @@ virt_cat_SOURCES = \
$(SHARED_SOURCE_FILES) \
virt-cat.c
virt_cat_CFLAGS = \
virt_cat_CPPFLAGS = \
-DGUESTFS_WARN_DEPRECATED=1 \
-DLOCALEBASEDIR=\""$(datadir)/locale"\" \
-I$(top_srcdir)/src -I$(top_builddir)/src \
-I$(top_srcdir)/fish \
-I$(srcdir)/../gnulib/lib -I../gnulib/lib \
-DLOCALEBASEDIR=\""$(datadir)/locale"\" \
-I$(srcdir)/../gnulib/lib -I../gnulib/lib
virt_cat_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
$(GPROF_CFLAGS) $(GCOV_CFLAGS) \
$(LIBCONFIG_CFLAGS)
virt_cat_LDADD = \
$(LIBCONFIG_LIBS) \
$(top_builddir)/src/libutils.la \
$(top_builddir)/src/libguestfs.la \
$(LIBXML2_LIBS) \
$(LIBVIRT_LIBS) \
../gnulib/lib/libgnu.la
virt_filesystems_SOURCES = \
$(SHARED_SOURCE_FILES) \
virt-filesystems.c
virt_filesystems_CFLAGS = \
virt_filesystems_CPPFLAGS = \
-DGUESTFS_WARN_DEPRECATED=1 \
-DLOCALEBASEDIR=\""$(datadir)/locale"\" \
-I$(top_srcdir)/src -I$(top_builddir)/src \
-I$(top_srcdir)/fish \
-I$(srcdir)/../gnulib/lib -I../gnulib/lib \
-DLOCALEBASEDIR=\""$(datadir)/locale"\" \
-I$(srcdir)/../gnulib/lib -I../gnulib/lib
virt_filesystems_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
$(GPROF_CFLAGS) $(GCOV_CFLAGS) \
$(LIBCONFIG_CFLAGS)
virt_filesystems_LDADD = \
$(LIBCONFIG_LIBS) \
$(top_builddir)/src/libutils.la \
$(top_builddir)/src/libguestfs.la \
$(LIBXML2_LIBS) \
$(LIBVIRT_LIBS) \
../gnulib/lib/libgnu.la
virt_ls_SOURCES = \
$(SHARED_SOURCE_FILES) \
virt-ls.c
virt_ls_CFLAGS = \
virt_ls_CPPFLAGS = \
-DGUESTFS_WARN_DEPRECATED=1 \
-DLOCALEBASEDIR=\""$(datadir)/locale"\" \
-I$(top_srcdir)/src -I$(top_builddir)/src \
-I$(top_srcdir)/fish \
-I$(srcdir)/../gnulib/lib -I../gnulib/lib \
-DLOCALEBASEDIR=\""$(datadir)/locale"\" \
-I$(srcdir)/../gnulib/lib -I../gnulib/lib
virt_ls_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
$(GPROF_CFLAGS) $(GCOV_CFLAGS) \
$(LIBCONFIG_CFLAGS)
virt_ls_LDADD = \
$(LIBCONFIG_LIBS) \
$(top_builddir)/src/libutils.la \
$(top_builddir)/src/libguestfs.la \
$(LIBXML2_LIBS) \
$(LIBVIRT_LIBS) \
../gnulib/lib/libgnu.la
# Manual pages and HTML files for the website.

View File

@@ -1,6 +1,6 @@
#!/bin/bash -
# libguestfs
# Copyright (C) 2009-2012 Red Hat Inc.
# Copyright (C) 2009-2013 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

View File

@@ -1,6 +1,6 @@
#!/bin/bash -
# libguestfs
# Copyright (C) 2009-2012 Red Hat Inc.
# Copyright (C) 2009-2013 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

View File

@@ -45,15 +45,10 @@ int echo_keys = 0;
const char *libvirt_uri = NULL;
int inspector = 1;
static int do_cat (int argc, char *argv[]);
static int is_windows (guestfs_h *g, const char *root);
static char *windows_path (guestfs_h *g, const char *root, const char *filename);
static inline char *
bad_cast (char const *s)
{
return (char *) s;
}
static void __attribute__((noreturn))
usage (int status)
{
@@ -106,6 +101,7 @@ main (int argc, char *argv[])
{ "format", 2, 0, 0 },
{ "help", 0, 0, HELP_OPTION },
{ "keys-from-stdin", 0, 0, 0 },
{ "long-options", 0, 0, 0 },
{ "verbose", 0, 0, 'v' },
{ "version", 0, 0, 'V' },
{ 0, 0, 0, 0 }
@@ -114,6 +110,7 @@ main (int argc, char *argv[])
struct drv *drv;
const char *format = NULL;
int c;
int r;
int option_index;
g = guestfs_create ();
@@ -122,7 +119,7 @@ main (int argc, char *argv[])
exit (EXIT_FAILURE);
}
argv[0] = bad_cast (program_name);
argv[0] = (char *) program_name;
for (;;) {
c = getopt_long (argc, argv, options, long_options, &option_index);
@@ -130,7 +127,9 @@ main (int argc, char *argv[])
switch (c) {
case 0: /* options which are long only */
if (STREQ (long_options[option_index].name, "keys-from-stdin")) {
if (STREQ (long_options[option_index].name, "long-options"))
display_long_options (long_options);
else if (STREQ (long_options[option_index].name, "keys-from-stdin")) {
keys_from_stdin = 1;
} else if (STREQ (long_options[option_index].name, "echo-keys")) {
echo_keys = 1;
@@ -240,24 +239,34 @@ main (int argc, char *argv[])
/* Free up data structures, no longer needed after this point. */
free_drives (drvs);
r = do_cat (argc - optind, &argv[optind]);
guestfs_close (g);
exit (r == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int
do_cat (int argc, char *argv[])
{
unsigned errors = 0;
int windows;
char *root, **roots;
int windows, i;
char *root;
/* Get root mountpoint. See: fish/inspect.c:inspect_mount */
roots = guestfs_inspect_get_roots (g);
CLEANUP_FREE_STRING_LIST char **roots = guestfs_inspect_get_roots (g);
assert (roots);
assert (roots[0] != NULL);
assert (roots[1] == NULL);
root = roots[0];
free (roots);
/* Windows? Special handling is required. */
windows = is_windows (g, root);
for (; optind < argc; optind++) {
char *filename_to_free = NULL;
const char *filename = argv[optind];
for (i = 0; i < argc; ++i) {
CLEANUP_FREE char *filename_to_free = NULL;
const char *filename = argv[i];
if (windows) {
filename = filename_to_free = windows_path (g, root, filename);
@@ -269,15 +278,9 @@ main (int argc, char *argv[])
if (guestfs_download (g, filename, "/dev/stdout") == -1)
errors++;
free (filename_to_free);
}
free (root);
guestfs_close (g);
exit (errors == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
return errors == 0 ? 0 : -1;
}
static int

View File

@@ -80,12 +80,6 @@ static void do_output_end (void);
static struct guestfs_lvm_pv_list *get_pvs (void);
static void free_pvs (void);
static inline char *
bad_cast (char const *s)
{
return (char *) s;
}
static void __attribute__((noreturn))
usage (int status)
{
@@ -162,9 +156,10 @@ main (int argc, char *argv[])
{ "help", 0, 0, HELP_OPTION },
{ "human-readable", 0, 0, 'h' },
{ "keys-from-stdin", 0, 0, 0 },
{ "long", 0, 0, 'l' },
{ "logical-volumes", 0, 0, 0 },
{ "logvols", 0, 0, 0 },
{ "long", 0, 0, 'l' },
{ "long-options", 0, 0, 0 },
{ "lvs", 0, 0, 0 },
{ "no-title", 0, 0, 0 },
{ "parts", 0, 0, 0 },
@@ -197,7 +192,7 @@ main (int argc, char *argv[])
exit (EXIT_FAILURE);
}
argv[0] = bad_cast (program_name);
argv[0] = (char *) program_name;
for (;;) {
c = getopt_long (argc, argv, options, long_options, &option_index);
@@ -205,7 +200,9 @@ main (int argc, char *argv[])
switch (c) {
case 0: /* options which are long only */
if (STREQ (long_options[option_index].name, "keys-from-stdin")) {
if (STREQ (long_options[option_index].name, "long-options"))
display_long_options (long_options);
else if (STREQ (long_options[option_index].name, "keys-from-stdin")) {
keys_from_stdin = 1;
} else if (STREQ (long_options[option_index].name, "echo-keys")) {
echo_keys = 1;
@@ -379,9 +376,6 @@ static int is_md (char *device);
static char **parents_of_md (char *device);
static char **parents_of_vg (char *vg);
static void free_strings (char **strings);
static size_t count_strings (char **strings);
static void
do_output_title (void)
{
@@ -438,22 +432,21 @@ do_output (void)
static void
do_output_filesystems (void)
{
char **fses;
size_t i;
fses = guestfs_list_filesystems (g);
CLEANUP_FREE_STRING_LIST char **fses = guestfs_list_filesystems (g);
if (fses == NULL)
exit (EXIT_FAILURE);
for (i = 0; fses[i] != NULL; i += 2) {
char *dev, *vfs_label = NULL, *vfs_uuid = NULL;
char **parents;
CLEANUP_FREE char *dev = NULL, *vfs_label = NULL, *vfs_uuid = NULL;
CLEANUP_FREE_STRING_LIST char **parents = NULL;
int64_t size = -1;
/* Skip swap and unknown, unless --extra flag was given. */
if (!(output & OUTPUT_FILESYSTEMS_EXTRA) &&
(STREQ (fses[i+1], "swap") || STREQ (fses[i+1], "unknown")))
goto next;
continue;
dev = guestfs_canonical_device_name (g, fses[i]);
if (dev == NULL)
@@ -499,32 +492,20 @@ do_output_filesystems (void)
write_row (dev, "filesystem",
fses[i+1], vfs_label, -1, size, parents, vfs_uuid);
free_strings (parents);
free (dev);
free (vfs_label);
free (vfs_uuid);
next:
free (fses[i]);
free (fses[i+1]);
}
free (fses);
}
static void
do_output_lvs (void)
{
char **lvs;
size_t i;
lvs = guestfs_lvs (g);
CLEANUP_FREE_STRING_LIST char **lvs = guestfs_lvs (g);
if (lvs == NULL)
exit (EXIT_FAILURE);
for (i = 0; lvs[i] != NULL; ++i) {
char *uuid = NULL, *parent_name = NULL;
CLEANUP_FREE char *uuid = NULL, *parent_name = NULL;
const char *parents[2];
int64_t size = -1;
@@ -553,29 +534,23 @@ do_output_lvs (void)
write_row (lvs[i], "lv",
NULL, NULL, -1, size, (char **) parents, uuid);
free (uuid);
free (parent_name);
free (lvs[i]);
}
free (lvs);
}
static void
do_output_vgs (void)
{
struct guestfs_lvm_vg_list *vgs;
size_t i;
vgs = guestfs_vgs_full (g);
CLEANUP_FREE_LVM_VG_LIST struct guestfs_lvm_vg_list *vgs =
guestfs_vgs_full (g);
if (vgs == NULL)
exit (EXIT_FAILURE);
for (i = 0; i < vgs->len; ++i) {
char *name;
CLEANUP_FREE char *name = NULL;
char uuid[33];
char **parents;
CLEANUP_FREE_STRING_LIST char **parents = NULL;
if (asprintf (&name, "/dev/%s", vgs->val[i].vg_name) == -1) {
perror ("asprintf");
@@ -589,12 +564,7 @@ do_output_vgs (void)
write_row (name, "vg",
NULL, NULL, -1, (int64_t) vgs->val[i].vg_size, parents, uuid);
free (name);
free_strings (parents);
}
guestfs_free_lvm_vg_list (vgs);
}
/* Cache the output of guestfs_pvs_full, since we use it in a few places. */
@@ -629,11 +599,11 @@ do_output_pvs (void)
struct guestfs_lvm_pv_list *pvs = get_pvs ();
for (i = 0; i < pvs->len; ++i) {
char *dev;
char uuid[33];
const char *parents[1] = { NULL };
dev = guestfs_canonical_device_name (g, pvs->val[i].pv_name);
CLEANUP_FREE char *dev =
guestfs_canonical_device_name (g, pvs->val[i].pv_name);
if (!dev)
exit (EXIT_FAILURE);
@@ -642,15 +612,13 @@ do_output_pvs (void)
write_row (dev, "pv",
NULL, NULL, -1, (int64_t) pvs->val[i].pv_size,
(char **) parents, uuid);
free (dev);
}
}
static int
get_mbr_id (const char *dev, const char *parent_name)
{
char *parttype = NULL;
CLEANUP_FREE char *parttype = NULL;
int mbr_id = -1, partnum;
guestfs_push_error_handler (g, NULL, NULL);
@@ -663,8 +631,6 @@ get_mbr_id (const char *dev, const char *parent_name)
mbr_id = guestfs_part_get_mbr_id (g, parent_name, partnum);
}
free (parttype);
guestfs_pop_error_handler (g);
return mbr_id;
@@ -673,15 +639,14 @@ get_mbr_id (const char *dev, const char *parent_name)
static void
do_output_partitions (void)
{
char **parts;
size_t i;
parts = guestfs_list_partitions (g);
CLEANUP_FREE_STRING_LIST char **parts = guestfs_list_partitions (g);
if (parts == NULL)
exit (EXIT_FAILURE);
for (i = 0; parts[i] != NULL; ++i) {
char *dev, *parent_name = NULL;
CLEANUP_FREE char *dev = NULL, *parent_name = NULL, *canonical_name = NULL;
const char *parents[2];
int64_t size = -1;
int mbr_id = -1;
@@ -703,41 +668,32 @@ do_output_partitions (void)
if ((columns & COLUMN_MBR))
mbr_id = get_mbr_id (parts[i], parent_name);
char *p = guestfs_canonical_device_name (g, parent_name);
if (!p)
canonical_name = guestfs_canonical_device_name (g, parent_name);
if (!canonical_name)
exit (EXIT_FAILURE);
free (parent_name);
parent_name = p;
parents[0] = parent_name;
parents[0] = canonical_name;
parents[1] = NULL;
}
write_row (dev, "partition",
NULL, NULL, mbr_id, size, (char **) parents, NULL);
free (dev);
free (parent_name);
free (parts[i]);
}
free (parts);
}
static void
do_output_blockdevs (void)
{
char **devices;
size_t i;
devices = guestfs_list_devices (g);
CLEANUP_FREE_STRING_LIST char **devices = guestfs_list_devices (g);
if (devices == NULL)
exit (EXIT_FAILURE);
for (i = 0; devices[i] != NULL; ++i) {
int64_t size = -1;
char *dev;
char **parents;
CLEANUP_FREE_STRING_LIST char **parents = NULL;
CLEANUP_FREE char *dev;
dev = guestfs_canonical_device_name (g, devices[i]);
if (!dev)
@@ -756,18 +712,10 @@ do_output_blockdevs (void)
write_row (dev, "device",
NULL, NULL, -1, size, parents, NULL);
free (dev);
free (devices[i]);
free_strings (parents);
}
free (devices);
}
/* Returns an empty list of parents. Note this must be freed using
* free_strings.
*/
/* Returns an empty list of parents. Note this must be freed. */
static char **
no_parents (void)
{
@@ -806,11 +754,11 @@ is_md (char *device)
static char **
parents_of_md (char *device)
{
struct guestfs_mdstat_list *stats;
char **ret;
size_t i;
stats = guestfs_md_stat (g, device);
CLEANUP_FREE_MDSTAT_LIST struct guestfs_mdstat_list *stats =
guestfs_md_stat (g, device);
if (!stats)
exit (EXIT_FAILURE);
@@ -828,8 +776,6 @@ parents_of_md (char *device)
ret[stats->len] = NULL;
guestfs_free_mdstat_list (stats);
return ret;
}
@@ -861,15 +807,14 @@ static char **
parents_of_vg (char *vg)
{
struct guestfs_lvm_pv_list *pvs = get_pvs ();
char **pvuuids;
char **ret;
size_t n, i, j;
pvuuids = guestfs_vgpvuuids (g, vg);
CLEANUP_FREE_STRING_LIST char **pvuuids = guestfs_vgpvuuids (g, vg);
if (!pvuuids)
exit (EXIT_FAILURE);
n = count_strings (pvuuids);
n = guestfs___count_strings (pvuuids);
ret = malloc ((n + 1) * sizeof (char *));
if (!ret) {
@@ -901,8 +846,6 @@ parents_of_vg (char *vg)
ret[i] = NULL;
free_strings (pvuuids);
return ret;
}
@@ -941,7 +884,7 @@ write_row (const char *name, const char *type,
int64_t size, char **parents, const char *uuid)
{
const char *strings[NR_COLUMNS];
char *parents_str = NULL;
CLEANUP_FREE char *parents_str = NULL;
size_t len = 0;
char hum[LONGEST_HUMAN_READABLE];
char num[256];
@@ -989,8 +932,6 @@ write_row (const char *name, const char *type,
assert (len <= NR_COLUMNS);
write_row_strings ((char **) strings, len);
free (parents_str);
}
static void add_row (char **strings, size_t len);
@@ -1159,23 +1100,3 @@ do_output_end (void)
}
free (rows);
}
static void
free_strings (char **strings)
{
size_t i;
for (i = 0; strings[i] != NULL; ++i)
free (strings[i]);
free (strings);
}
static size_t
count_strings (char **strings)
{
size_t i;
for (i = 0; strings[i] != NULL; ++i)
;
return i;
}

View File

@@ -82,14 +82,6 @@ static int is_fifo (int64_t mode);
static int is_lnk (int64_t mode);
static int is_sock (int64_t mode);
static void free_strings (char **);
static inline char *
bad_cast (char const *s)
{
return (char *) s;
}
static void __attribute__((noreturn))
usage (int status)
{
@@ -163,6 +155,7 @@ main (int argc, char *argv[])
{ "human-readable", 0, 0, 'h' },
{ "keys-from-stdin", 0, 0, 0 },
{ "long", 0, 0, 'l' },
{ "long-options", 0, 0, 0 },
{ "recursive", 0, 0, 'R' },
{ "time", 0, 0, 0 },
{ "times", 0, 0, 0 },
@@ -191,7 +184,7 @@ main (int argc, char *argv[])
exit (EXIT_FAILURE);
}
argv[0] = bad_cast (program_name);
argv[0] = (char *) program_name;
for (;;) {
c = getopt_long (argc, argv, options, long_options, &option_index);
@@ -199,7 +192,9 @@ main (int argc, char *argv[])
switch (c) {
case 0: /* options which are long only */
if (STREQ (long_options[option_index].name, "keys-from-stdin")) {
if (STREQ (long_options[option_index].name, "long-options"))
display_long_options (long_options);
else if (STREQ (long_options[option_index].name, "keys-from-stdin")) {
keys_from_stdin = 1;
} else if (STREQ (long_options[option_index].name, "echo-keys")) {
echo_keys = 1;
@@ -408,18 +403,14 @@ main (int argc, char *argv[])
static int
do_ls (const char *dir)
{
char **lines;
size_t i;
CLEANUP_FREE_STRING_LIST char **lines = guestfs_ls (g, dir);
if ((lines = guestfs_ls (g, dir)) == NULL) {
if (lines == NULL)
return -1;
}
for (i = 0; lines[i] != NULL; ++i) {
for (i = 0; lines[i] != NULL; ++i)
printf ("%s\n", lines[i]);
free (lines[i]);
}
free (lines);
return 0;
}
@@ -427,13 +418,12 @@ do_ls (const char *dir)
static int
do_ls_l (const char *dir)
{
char *out;
CLEANUP_FREE char *out = guestfs_ll (g, dir);
if ((out = guestfs_ll (g, dir)) == NULL)
if (out == NULL)
return -1;
printf ("%s", out);
free (out);
return 0;
}
@@ -441,18 +431,14 @@ do_ls_l (const char *dir)
static int
do_ls_R (const char *dir)
{
char **dirs;
size_t i;
CLEANUP_FREE_STRING_LIST char **dirs = guestfs_find (g, dir);
dirs = guestfs_find (g, dir);
if (dirs == NULL)
return -1;
for (i = 0; dirs[i] != NULL; ++i) {
for (i = 0; dirs[i] != NULL; ++i)
puts (dirs[i]);
free (dirs[i]);
}
free (dirs);
return 0;
}
@@ -473,8 +459,8 @@ visit (int depth, const char *dir, visitor_function f)
* case.
*/
if (depth == 0) {
struct guestfs_stat *stat;
struct guestfs_xattr_list *xattrs;
CLEANUP_FREE_STAT struct guestfs_stat *stat = NULL;
CLEANUP_FREE_XATTR_LIST struct guestfs_xattr_list *xattrs = NULL;
int r;
stat = guestfs_lstat (g, dir);
@@ -482,40 +468,35 @@ visit (int depth, const char *dir, visitor_function f)
return -1;
xattrs = guestfs_lgetxattrs (g, dir);
if (xattrs == NULL) {
guestfs_free_stat (stat);
if (xattrs == NULL)
return -1;
}
r = f (dir, NULL, stat, xattrs);
guestfs_free_stat (stat);
guestfs_free_xattr_list (xattrs);
if (r == -1)
return -1;
}
int ret = -1;
char **names = NULL;
char *path = NULL;
size_t i, xattrp;
struct guestfs_stat_list *stats = NULL;
struct guestfs_xattr_list *xattrs = NULL;
CLEANUP_FREE_STRING_LIST char **names = NULL;
CLEANUP_FREE_STAT_LIST struct guestfs_stat_list *stats = NULL;
CLEANUP_FREE_XATTR_LIST struct guestfs_xattr_list *xattrs = NULL;
names = guestfs_ls (g, dir);
if (names == NULL)
goto out;
return -1;
stats = guestfs_lstatlist (g, dir, names);
if (stats == NULL)
goto out;
return -1;
xattrs = guestfs_lxattrlist (g, dir, names);
if (xattrs == NULL)
goto out;
return -1;
/* Call function on everything in this directory. */
for (i = 0, xattrp = 0; names[i] != NULL; ++i, ++xattrp) {
CLEANUP_FREE char *path = NULL;
struct guestfs_xattr_list file_xattrs;
size_t nr_xattrs;
@@ -528,7 +509,7 @@ visit (int depth, const char *dir, visitor_function f)
if (xattrs->val[xattrp].attrval_len == 0) {
fprintf (stderr, _("%s: error getting extended attrs for %s %s\n"),
program_name, dir, names[i]);
goto out;
return -1;
}
/* attrval is not \0-terminated. */
char attrval[xattrs->val[xattrp].attrval_len+1];
@@ -538,7 +519,7 @@ visit (int depth, const char *dir, visitor_function f)
if (sscanf (attrval, "%zu", &nr_xattrs) != 1) {
fprintf (stderr, _("%s: error: cannot parse xattr count for %s %s\n"),
program_name, dir, names[i]);
goto out;
return -1;
}
file_xattrs.len = nr_xattrs;
@@ -547,28 +528,17 @@ visit (int depth, const char *dir, visitor_function f)
/* Call the function. */
if (f (dir, names[i], &stats->val[i], &file_xattrs) == -1)
goto out;
return -1;
/* Recursively call visit, but only on directories. */
if (is_dir (stats->val[i].mode)) {
path = full_path (dir, names[i]);
if (visit (depth + 1, path, f) == -1)
goto out;
free (path); path = NULL;
return -1;
}
}
ret = 0;
out:
free (path);
if (names)
free_strings (names);
if (stats)
guestfs_free_stat_list (stats);
if (xattrs)
guestfs_free_xattr_list (xattrs);
return ret;
return 0;
}
static char *
@@ -611,7 +581,7 @@ show_file (const char *dir, const char *name,
const struct guestfs_xattr_list *xattrs)
{
char filetype[2];
char *path, *csum = NULL, *link = NULL;
CLEANUP_FREE char *path = NULL, *csum = NULL, *link = NULL;
/* Display the basic fields. */
output_start_line ();
@@ -683,10 +653,6 @@ show_file (const char *dir, const char *name,
output_end_line ();
free (path);
free (csum);
free (link);
return 0;
}
@@ -966,14 +932,3 @@ is_sock (int64_t mode)
{
return (mode & 0170000) == 0140000;
}
/* String functions. */
static void
free_strings (char **names)
{
size_t i;
for (i = 0; names[i] != NULL; ++i)
free (names[i]);
free (names);
}

View File

@@ -499,9 +499,6 @@ L<guestfish(1)>,
L<virt-cat(1)>,
L<virt-copy-out(1)>,
L<virt-tar-out(1)>,
L<Sys::Guestfs(3)>,
L<Sys::Guestfs::Lib(3)>,
L<Sys::Virt(3)>,
L<http://libguestfs.org/>.
=head1 AUTHOR
@@ -510,4 +507,4 @@ Richard W.M. Jones L<http://people.redhat.com/~rjones/>
=head1 COPYRIGHT
Copyright (C) 2009-2012 Red Hat Inc.
Copyright (C) 2009-2013 Red Hat Inc.

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
#!/bin/bash -
# libguestfs autobuild script
# Copyright (C) 2009-2012 Red Hat Inc.
# Copyright (C) 2009-2013 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

View File

@@ -1,6 +1,6 @@
#!/usr/bin/perl -w
# libguestfs
# Copyright (C) 2009-2012 Red Hat Inc.
# Copyright (C) 2009-2013 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

View File

@@ -1,7 +1,7 @@
#!/usr/bin/ocamlrun /usr/bin/ocaml
(* Convert *.qtr (qemu block device trace) to Postscript.
* Copyright (C) 2009-2012 Red Hat Inc.
* Copyright (C) 2009-2013 Red Hat Inc.
* By Richard W.M. Jones <rjones@redhat.com>.
*
* This program is free software; you can redistribute it and/or modify

View File

@@ -48,8 +48,10 @@ do_list_9p (void)
dir = opendir (BUS_PATH);
if (!dir) {
perror ("opendir: " BUS_PATH);
if (errno != ENOENT)
if (errno != ENOENT) {
reply_with_perror ("opendir: " BUS_PATH);
return NULL;
}
/* If this directory doesn't exist, it probably means that
* the virtio driver isn't loaded. Don't return an error
@@ -75,17 +77,14 @@ do_list_9p (void)
* the mount tag length to be unlimited (or up to 65536 bytes).
* See: linux/include/linux/virtio_9p.h
*/
char *mount_tag = read_whole_file (mount_tag_path);
CLEANUP_FREE char *mount_tag = read_whole_file (mount_tag_path);
if (mount_tag == 0)
continue;
if (add_string (&r, mount_tag) == -1) {
free (mount_tag);
closedir (dir);
return NULL;
}
free (mount_tag);
}
}
@@ -148,7 +147,7 @@ read_whole_file (const char *filename)
*/
ssize_t n = read (fd, r + size, alloc - size - 1);
if (n == -1) {
perror (filename);
fprintf (stderr, "read: %s: %m\n", filename);
free (r);
close (fd);
return NULL;
@@ -159,7 +158,7 @@ read_whole_file (const char *filename)
}
if (close (fd) == -1) {
perror (filename);
fprintf (stderr, "close: %s: %m\n", filename);
free (r);
return NULL;
}
@@ -173,26 +172,26 @@ read_whole_file (const char *filename)
int
do_mount_9p (const char *mount_tag, const char *mountpoint, const char *options)
{
char *mp = NULL, *opts = NULL, *err = NULL;
CLEANUP_FREE char *mp = NULL, *opts = NULL, *err = NULL;
struct stat statbuf;
int r = -1;
int r;
ABS_PATH (mountpoint, , return -1);
mp = sysroot_path (mountpoint);
if (!mp) {
reply_with_perror ("malloc");
goto out;
return -1;
}
/* Check the mountpoint exists and is a directory. */
if (stat (mp, &statbuf) == -1) {
reply_with_perror ("%s", mountpoint);
goto out;
return -1;
}
if (!S_ISDIR (statbuf.st_mode)) {
reply_with_perror ("%s: mount point is not a directory", mountpoint);
goto out;
return -1;
}
/* Add trans=virtio to the options. */
@@ -200,14 +199,14 @@ do_mount_9p (const char *mount_tag, const char *mountpoint, const char *options)
STRNEQ (options, "")) {
if (asprintf (&opts, "trans=virtio,%s", options) == -1) {
reply_with_perror ("asprintf");
goto out;
return -1;
}
}
else {
opts = strdup ("trans=virtio");
if (opts == NULL) {
reply_with_perror ("strdup");
goto out;
return -1;
}
}
@@ -215,13 +214,8 @@ do_mount_9p (const char *mount_tag, const char *mountpoint, const char *options)
str_mount, "-o", opts, "-t", "9p", mount_tag, mp, NULL);
if (r == -1) {
reply_with_error ("%s on %s: %s", mount_tag, mountpoint, err);
goto out;
return -1;
}
r = 0;
out:
free (err);
free (opts);
free (mp);
return r;
return 0;
}

View File

@@ -19,26 +19,31 @@ include $(top_srcdir)/subdir-rules.mk
CLEANFILES = stamp-guestfsd.pod
libsrcdir = $(top_builddir)/src
generator_built = \
actions.h \
stubs.c \
names.c
BUILT_SOURCES = \
$(generator_built) \
shared_with_library = \
guestfs_protocol.c \
guestfs_protocol.h \
errnostring-gperf.c \
errnostring-gperf.gperf \
errnostring.c \
errnostring.h
BUILT_SOURCES = \
$(generator_built) \
$(shared_with_library) \
errnostring-gperf.c
EXTRA_DIST = \
$(BUILT_SOURCES) \
guestfsd.pod
$(shared_with_library): %: $(top_srcdir)/src/%
rm -f $@
ln $< $@
noinst_LIBRARIES = libprotocol.a
# This convenience library is solely to compile its generated sources with
@@ -46,16 +51,10 @@ noinst_LIBRARIES = libprotocol.a
libprotocol_a_SOURCES = guestfs_protocol.c guestfs_protocol.h
libprotocol_a_CFLAGS = -Wall -Wno-unused -fno-strict-aliasing
guestfs_protocol.c: $(libsrcdir)/guestfs_protocol.c
rm -f $@
ln $< $@
guestfs_protocol.h: $(libsrcdir)/guestfs_protocol.h
rm -f $@
ln $< $@
$(libsrcdir)/guestfs_protocol.c: force
$(MAKE) -C $(libsrcdir) guestfs_protocol.c
$(libsrcdir)/guestfs_protocol.h: force
$(MAKE) -C $(libsrcdir) guestfs_protocol.h
$(top_builddir)/src/guestfs_protocol.c: force
$(MAKE) -C $(top_builddir)/src guestfs_protocol.c
$(top_builddir)/src/guestfs_protocol.h: force
$(MAKE) -C $(top_builddir)/src guestfs_protocol.h
# Build the errnostring perfect hash code. The generated code has lots
# of warnings so we must compile it in a separate mini-library.
@@ -70,15 +69,6 @@ errnostring-gperf.c: errnostring-gperf.gperf
rm -f $@
$(GPERF) -t $< > $@-t
mv $@-t $@
errnostring-gperf.gperf: $(libsrcdir)/errnostring-gperf.gperf
rm -f $@
ln $< $@
errnostring.c: $(libsrcdir)/errnostring.c
rm -f $@
ln $< $@
errnostring.h: $(libsrcdir)/errnostring.h
rm -f $@
ln $< $@
if INSTALL_DAEMON
sbin_PROGRAMS = guestfsd
@@ -148,6 +138,7 @@ guestfsd_SOURCES = \
mktemp.c \
modprobe.c \
mount.c \
mountable.c \
names.c \
ntfs.c \
ntfsclone.c \
@@ -158,6 +149,7 @@ guestfsd_SOURCES = \
proto.c \
readdir.c \
realpath.c \
rename.c \
rsync.c \
scrub.c \
selinux.c \
@@ -169,6 +161,7 @@ guestfsd_SOURCES = \
stubs.c \
swap.c \
sync.c \
syslinux.c \
tar.c \
truncate.c \
umask.c \
@@ -197,14 +190,20 @@ guestfsd_LDADD = \
$(LIBSOCKET) \
$(LIB_CLOCK_GETTIME) \
$(LIBINTL) \
$(SERVENT_LIB)
$(SERVENT_LIB) \
$(PCRE_LIBS)
guestfsd_CPPFLAGS = -I$(top_srcdir)/gnulib/lib -I$(top_builddir)/gnulib/lib
guestfsd_CPPFLAGS = \
-I$(top_srcdir)/gnulib/lib \
-I$(top_builddir)/gnulib/lib \
-I$(top_srcdir)/src \
-I$(top_builddir)/src
guestfsd_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
$(AUGEAS_CFLAGS) \
$(HIVEX_CFLAGS) \
$(YAJL_CFLAGS)
$(YAJL_CFLAGS) \
$(PCRE_CFLAGS)
# Manual pages and HTML files for the website.
man_MANS = guestfsd.8

View File

@@ -68,7 +68,7 @@ optgroup_augeas_available (void)
int
do_aug_init (const char *root, int flags)
{
char *buf;
CLEANUP_FREE char *buf = NULL;
if (aug) {
aug_close (aug);
@@ -82,7 +82,6 @@ do_aug_init (const char *root, int flags)
}
aug = aug_init (buf, NULL, flags);
free (buf);
if (!aug) {
reply_with_error ("Augeas initialization failed");
@@ -338,7 +337,6 @@ char **
do_aug_ls (const char *path)
{
char **matches;
char *buf;
size_t len;
NEED_AUG (NULL);
@@ -358,6 +356,8 @@ do_aug_ls (const char *path)
if (STREQ (path, "/"))
matches = do_aug_match ("/*");
else {
CLEANUP_FREE char *buf;
len += 3; /* / * + terminating \0 */
buf = malloc (len);
if (buf == NULL) {
@@ -367,7 +367,6 @@ do_aug_ls (const char *path)
snprintf (buf, len, "%s/*", path);
matches = do_aug_match (buf);
free (buf);
}
if (matches == NULL)

View File

@@ -33,8 +33,8 @@
GUESTFSD_EXT_CMD(str_grep, grep);
GUESTFSD_EXT_CMD(str_modprobe, modprobe);
int
do_available (char *const *groups)
static int
available (char *const *groups, int error_on_unavailable)
{
int av;
size_t i, j;
@@ -44,8 +44,12 @@ do_available (char *const *groups)
if (STREQ (groups[i], optgroups[j].group)) {
av = optgroups[j].available ();
if (!av) {
reply_with_error ("%s: group not available", optgroups[j].group);
return -1;
if (error_on_unavailable) {
reply_with_error ("%s: group not available", optgroups[j].group);
return -1;
}
else
return 0;
}
break; /* out of for (j) loop */
}
@@ -58,6 +62,23 @@ do_available (char *const *groups)
}
}
/* All specified groups available. */
return 1;
}
int
do_feature_available (char *const *groups)
{
return available (groups, 0);
}
int
do_available (char *const *groups)
{
if (available (groups, 1) == -1)
return -1;
/* No error, so all groups available, just returns no error. */
return 0;
}
@@ -84,7 +105,7 @@ test_proc_filesystems (const char *filesystem)
{
size_t len = strlen (filesystem) + 32;
char regex[len];
char *err;
CLEANUP_FREE char *err = NULL;
int r;
snprintf (regex, len, "^[[:space:]]*%s$", filesystem);
@@ -92,10 +113,8 @@ test_proc_filesystems (const char *filesystem)
r = commandr (NULL, &err, str_grep, regex, "/proc/filesystems", NULL);
if (r == -1 || r >= 2) {
fprintf (stderr, "grep /proc/filesystems: %s", err);
free (err);
return -1;
}
free (err);
return r == 0;
}

View File

@@ -22,6 +22,9 @@
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "guestfs_protocol.h"
#include "daemon.h"
@@ -42,7 +45,7 @@ do_base64_in (const char *file)
{
int err, r;
FILE *fp;
char *cmd;
CLEANUP_FREE char *cmd = NULL;
if (asprintf_nowarn (&cmd, "%s -d -i > %R", str_base64, file) == -1) {
err = errno;
@@ -61,10 +64,8 @@ do_base64_in (const char *file)
cancel_receive ();
errno = err;
reply_with_perror ("%s", cmd);
free (cmd);
return -1;
}
free (cmd);
/* The semantics of fwrite are too undefined, so write to the
* file descriptor directly instead.
@@ -99,12 +100,32 @@ do_base64_in (const char *file)
int
do_base64_out (const char *file)
{
CLEANUP_FREE char *buf = NULL;
struct stat statbuf;
int r;
FILE *fp;
char *cmd;
char buf[GUESTFS_MAX_CHUNK_SIZE];
CLEANUP_FREE char *cmd = NULL;
char buffer[GUESTFS_MAX_CHUNK_SIZE];
if (asprintf_nowarn (&cmd, "%s %R", str_base64, file) == -1) {
/* Check the filename exists and is not a directory (RHBZ#908322). */
buf = sysroot_path (file);
if (buf == NULL) {
reply_with_perror ("malloc");
return -1;
}
if (stat (buf, &statbuf) == -1) {
reply_with_perror ("stat: %s", file);
return -1;
}
if (S_ISDIR (statbuf.st_mode)) {
reply_with_error ("%s: is a directory", file);
return -1;
}
/* Construct the command. */
if (asprintf_nowarn (&cmd, "%s %s", str_base64, buf) == -1) {
reply_with_perror ("asprintf");
return -1;
}
@@ -115,10 +136,8 @@ do_base64_out (const char *file)
fp = popen (cmd, "r");
if (fp == NULL) {
reply_with_perror ("%s", cmd);
free (cmd);
return -1;
}
free (cmd);
/* Now we must send the reply message, before the file contents. After
* this there is no opportunity in the protocol to send any error
@@ -126,22 +145,22 @@ do_base64_out (const char *file)
*/
reply (NULL, NULL);
while ((r = fread (buf, 1, sizeof buf, fp)) > 0) {
if (send_file_write (buf, r) < 0) {
while ((r = fread (buffer, 1, sizeof buffer, fp)) > 0) {
if (send_file_write (buffer, r) < 0) {
pclose (fp);
return -1;
}
}
if (ferror (fp)) {
perror (file);
fprintf (stderr, "fread: %s: %m\n", file);
send_file_end (1); /* Cancel. */
pclose (fp);
return -1;
}
if (pclose (fp) != 0) {
perror (file);
fprintf (stderr, "pclose: %s: %m\n", file);
send_file_end (1); /* Cancel. */
return -1;
}

View File

@@ -32,7 +32,8 @@ GUESTFSD_EXT_CMD(str_blkid, blkid);
static char *
get_blkid_tag (const char *device, const char *tag)
{
char *out, *err;
char *out;
CLEANUP_FREE char *err = NULL;
int r;
r = commandr (&out, &err,
@@ -46,12 +47,9 @@ get_blkid_tag (const char *device, const char *tag)
else
reply_with_error ("%s: %s", device, err);
free (out);
free (err);
return NULL;
}
free (err);
if (r == 2) { /* means UUID etc not found */
free (out);
out = strdup ("");
@@ -69,21 +67,21 @@ get_blkid_tag (const char *device, const char *tag)
}
char *
do_vfs_type (const char *device)
do_vfs_type (const mountable_t *mountable)
{
return get_blkid_tag (device, "TYPE");
return get_blkid_tag (mountable->device, "TYPE");
}
char *
do_vfs_label (const char *device)
do_vfs_label (const mountable_t *mountable)
{
return get_blkid_tag (device, "LABEL");
return get_blkid_tag (mountable->device, "LABEL");
}
char *
do_vfs_uuid (const char *device)
do_vfs_uuid (const mountable_t *mountable)
{
return get_blkid_tag (device, "UUID");
return get_blkid_tag (mountable->device, "UUID");
}
/* RHEL5 blkid doesn't have the -p (low-level probing) option and the
@@ -96,32 +94,27 @@ static int
test_blkid_p_i_opt (void)
{
int r;
char *err;
CLEANUP_FREE char *err = NULL, *err2 = NULL;
r = commandr (NULL, &err, str_blkid, "-p", "/dev/null", NULL);
if (r == -1) {
/* This means we couldn't run the blkid command at all. */
command_failed:
reply_with_error ("could not run 'blkid' command: %s", err);
free (err);
return -1;
}
if (strstr (err, "invalid option --")) {
free (err);
return 0;
}
free (err);
r = commandr (NULL, &err, str_blkid, "-i", NULL);
r = commandr (NULL, &err2, str_blkid, "-i", NULL);
if (r == -1)
goto command_failed;
if (strstr (err, "invalid option --")) {
free (err);
if (strstr (err2, "invalid option --")) {
return 0;
}
free (err);
/* We have both options. */
return 1;
@@ -132,8 +125,8 @@ blkid_with_p_i_opt (const char *device)
{
size_t i;
int r;
char *out = NULL, *err = NULL;
char **lines = NULL;
CLEANUP_FREE char *out = NULL, *err = NULL;
CLEANUP_FREE_STRING_LIST char **lines = NULL;
DECLARE_STRINGSBUF (ret);
r = command (&out, &err, str_blkid, "-c", "/dev/null",
@@ -184,17 +177,9 @@ blkid_with_p_i_opt (const char *device)
if (end_stringsbuf (&ret) == -1) goto error;
free (out);
free (err);
free_strings (lines);
return ret.argv;
error:
free (out);
free (err);
if (lines)
free_strings (lines);
if (ret.argv)
free_strings (ret.argv);

View File

@@ -38,7 +38,7 @@ call_blockdev (const char *device, const char *switc, int extraarg, int prints)
{
int r;
int64_t rv;
char *out, *err;
CLEANUP_FREE char *out = NULL, *err = NULL;
const char *argv[] = {
str_blockdev,
switc,
@@ -73,8 +73,6 @@ call_blockdev (const char *device, const char *switc, int extraarg, int prints)
if (r == -1) {
reply_with_error ("%s: %s", argv[0], err);
free (err);
free (out);
return -1;
}
@@ -83,15 +81,10 @@ call_blockdev (const char *device, const char *switc, int extraarg, int prints)
if (prints) {
if (sscanf (out, "%" SCNi64, &rv) != 1) {
reply_with_error ("%s: expected output, but got nothing", argv[0]);
free (out);
free (err);
return -1;
}
}
free (out);
free (err);
return rv;
}

View File

@@ -21,17 +21,20 @@
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <pcre.h>
#include <string.h>
#include <unistd.h>
#include "daemon.h"
#include "actions.h"
#include "optgroups.h"
#include "xstrtol.h"
GUESTFSD_EXT_CMD(str_btrfs, btrfs);
GUESTFSD_EXT_CMD(str_btrfstune, btrfstune);
GUESTFSD_EXT_CMD(str_btrfsck, btrfsck);
GUESTFSD_EXT_CMD(str_mkfs_btrfs, mkfs.btrfs);
GUESTFSD_EXT_CMD(str_umount, umount);
int
optgroup_btrfs_available (void)
@@ -44,8 +47,7 @@ int
do_btrfs_filesystem_resize (const char *filesystem, int64_t size)
{
const size_t MAX_ARGS = 64;
char *buf;
char *err;
CLEANUP_FREE char *buf = NULL, *err = NULL;
int r;
const char *argv[MAX_ARGS];
size_t i = 0;
@@ -77,15 +79,12 @@ do_btrfs_filesystem_resize (const char *filesystem, int64_t size)
ADD_ARG (argv, i, NULL);
r = commandv (NULL, &err, argv);
free (buf);
if (r == -1) {
reply_with_error ("%s: %s", filesystem, err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -107,7 +106,7 @@ do_mkfs_btrfs (char *const *devices,
const char *argv[MAX_ARGS];
size_t i = 0, j;
int r;
char *err;
CLEANUP_FREE char *err = NULL;
char allocstart_s[64];
char bytecount_s[64];
char leafsize_s[64];
@@ -197,14 +196,15 @@ do_mkfs_btrfs (char *const *devices,
ADD_ARG (argv, i, NULL);
for (j = 0; j < nr_devices; ++j)
wipe_device_before_mkfs (devices[j]);
r = commandv (NULL, &err, argv);
if (r == -1) {
reply_with_error ("%s: %s", devices[0], err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -214,8 +214,8 @@ do_btrfs_subvolume_snapshot (const char *source, const char *dest)
const size_t MAX_ARGS = 64;
const char *argv[MAX_ARGS];
size_t i = 0;
char *source_buf, *dest_buf;
char *err;
CLEANUP_FREE char *source_buf = NULL, *dest_buf = NULL;
CLEANUP_FREE char *err = NULL;
int r;
source_buf = sysroot_path (source);
@@ -226,7 +226,6 @@ do_btrfs_subvolume_snapshot (const char *source, const char *dest)
dest_buf = sysroot_path (dest);
if (dest_buf == NULL) {
reply_with_perror ("malloc");
free (source_buf);
return -1;
}
@@ -238,14 +237,10 @@ do_btrfs_subvolume_snapshot (const char *source, const char *dest)
ADD_ARG (argv, i, NULL);
r = commandv (NULL, &err, argv);
free (source_buf);
free (dest_buf);
if (r == -1) {
reply_with_error ("%s: %s: %s", source, dest, err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -256,8 +251,8 @@ do_btrfs_subvolume_delete (const char *subvolume)
const size_t MAX_ARGS = 64;
const char *argv[MAX_ARGS];
size_t i = 0;
char *subvolume_buf;
char *err;
CLEANUP_FREE char *subvolume_buf = NULL;
CLEANUP_FREE char *err = NULL;
int r;
subvolume_buf = sysroot_path (subvolume);
@@ -273,13 +268,10 @@ do_btrfs_subvolume_delete (const char *subvolume)
ADD_ARG (argv, i, NULL);
r = commandv (NULL, &err, argv);
free (subvolume_buf);
if (r == -1) {
reply_with_error ("%s: %s", subvolume, err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -290,8 +282,8 @@ do_btrfs_subvolume_create (const char *dest)
const size_t MAX_ARGS = 64;
const char *argv[MAX_ARGS];
size_t i = 0;
char *dest_buf;
char *err;
CLEANUP_FREE char *dest_buf = NULL;
CLEANUP_FREE char *err = NULL;
int r;
dest_buf = sysroot_path (dest);
@@ -307,111 +299,196 @@ do_btrfs_subvolume_create (const char *dest)
ADD_ARG (argv, i, NULL);
r = commandv (NULL, &err, argv);
free (dest_buf);
if (r == -1) {
reply_with_error ("%s: %s", dest, err);
free (err);
return -1;
}
free (err);
return 0;
}
guestfs_int_btrfssubvolume_list *
do_btrfs_subvolume_list (const char *fs)
do_btrfs_subvolume_list (const mountable_t *fs)
{
const size_t MAX_ARGS = 64;
guestfs_int_btrfssubvolume_list *ret;
char *fs_buf;
const char *argv[MAX_ARGS];
size_t i = 0;
char *out, *err, **lines, *pos;
size_t nr_subvolumes;
int r;
char **lines;
fs_buf = sysroot_path (fs);
if (fs_buf == NULL) {
reply_with_perror ("malloc");
return NULL;
/* Execute 'btrfs subvolume list <fs>', and split the output into lines */
{
CLEANUP_FREE char *fs_buf = NULL;
if (fs->type == MOUNTABLE_PATH) {
fs_buf = sysroot_path (fs->device);
if (fs_buf == NULL) {
reply_with_perror ("malloc");
cmderror:
if (fs->type != MOUNTABLE_PATH && fs_buf) {
CLEANUP_FREE char *err = NULL;
if (command (NULL, &err, str_umount, fs_buf, NULL) == -1)
fprintf (stderr, "%s\n", err);
if (rmdir (fs_buf) == -1 && errno != ENOENT)
fprintf (stderr, "rmdir: %m\n");
}
return NULL;
}
}
else {
fs_buf = strdup ("/tmp/btrfs.XXXXXX");
if (fs_buf == NULL) {
reply_with_perror ("strdup");
goto cmderror;
}
if (mkdtemp (fs_buf) == NULL) {
reply_with_perror ("mkdtemp");
goto cmderror;
}
if (mount_vfs_nochroot ("", NULL, fs, fs_buf, "<internal>") == -1) {
goto cmderror;
}
}
size_t i = 0;
const size_t MAX_ARGS = 64;
const char *argv[MAX_ARGS];
ADD_ARG (argv, i, str_btrfs);
ADD_ARG (argv, i, "subvolume");
ADD_ARG (argv, i, "list");
ADD_ARG (argv, i, fs_buf);
ADD_ARG (argv, i, NULL);
CLEANUP_FREE char *out = NULL, *errout = NULL;
int r = commandv (&out, &errout, argv);
if (fs->type != MOUNTABLE_PATH) {
CLEANUP_FREE char *err = NULL;
if (command (NULL, &err, str_umount, fs_buf, NULL) == -1) {
reply_with_error ("%s", err ? err : "malloc");
goto cmderror;
}
if (rmdir (fs_buf) == -1 && errno != ENOENT) {
reply_with_error ("rmdir: %m\n");
goto cmderror;
}
}
if (r == -1) {
CLEANUP_FREE char *fs_desc = mountable_to_string (fs);
if (fs_desc == NULL) {
fprintf (stderr, "malloc: %m");
}
reply_with_error ("%s: %s", fs_desc ? fs_desc : "malloc", errout);
goto cmderror;
}
lines = split_lines (out);
if (!lines) return NULL;
}
ADD_ARG (argv, i, str_btrfs);
ADD_ARG (argv, i, "subvolume");
ADD_ARG (argv, i, "list");
ADD_ARG (argv, i, fs_buf);
ADD_ARG (argv, i, NULL);
r = commandv (&out, &err, argv);
free (fs_buf);
if (r == -1) {
reply_with_error ("%s: %s", fs, err);
free (err);
return NULL;
}
free (err);
lines = split_lines (out);
free (out);
if (!lines)
return NULL;
/* Output is:
*
* ID 256 top level 5 path test1
* ID 257 top level 5 path dir/test2
* ID 258 top level 5 path test3
* ID 256 gen 30 top level 5 path test1
* ID 257 gen 30 top level 5 path dir/test2
* ID 258 gen 30 top level 5 path test3
*
* "ID <n>" is the subvolume ID. "top level <n>" is the top level
* subvolume ID. "path <str>" is the subvolume path, relative to
* the top of the filesystem.
* "ID <n>" is the subvolume ID.
* "gen <n>" is the generation when the root was created or last
* updated.
* "top level <n>" is the top level subvolume ID.
* "path <str>" is the subvolume path, relative to the top of the
* filesystem.
*
* Note that the order that each of the above is fixed, but
* different versions of btrfs may display different sets of data.
* Specifically, older versions of btrfs do not display gen.
*/
nr_subvolumes = count_strings (lines);
guestfs_int_btrfssubvolume_list *ret = NULL;
pcre *re = NULL;
size_t nr_subvolumes = count_strings (lines);
ret = malloc (sizeof *ret);
if (!ret) {
reply_with_perror ("malloc");
free_stringslen (lines, nr_subvolumes);
return NULL;
goto error;
}
ret->guestfs_int_btrfssubvolume_list_len = nr_subvolumes;
ret->guestfs_int_btrfssubvolume_list_val =
calloc (nr_subvolumes, sizeof (struct guestfs_int_btrfssubvolume));
if (ret->guestfs_int_btrfssubvolume_list_val == NULL) {
reply_with_perror ("malloc");
free (ret);
free_stringslen (lines, nr_subvolumes);
return NULL;
goto error;
}
for (i = 0; i < nr_subvolumes; ++i) {
const char *errptr;
int erroffset;
re = pcre_compile ("ID\\s+(\\d+).*\\s"
"top level\\s+(\\d+).*\\s"
"path\\s(.*)",
0, &errptr, &erroffset, NULL);
if (re == NULL) {
reply_with_error ("pcre_compile (%i): %s", erroffset, errptr);
goto error;
}
for (size_t i = 0; i < nr_subvolumes; ++i) {
/* To avoid allocations, reuse the 'line' buffer to store the
* path. Thus we don't need to free 'line', since it will be
* freed by the calling (XDR) code.
*/
char *line = lines[i];
#define N_MATCHES 4
int ovector[N_MATCHES * 3];
if (sscanf (line, "ID %" SCNu64 " top level %" SCNu64 " path ",
&ret->guestfs_int_btrfssubvolume_list_val[i].btrfssubvolume_id,
&ret->guestfs_int_btrfssubvolume_list_val[i].btrfssubvolume_top_level_id) != 2) {
if (pcre_exec (re, NULL, line, strlen (line), 0, 0,
ovector, N_MATCHES * 3) < 0)
#undef N_MATCHES
{
unexpected_output:
reply_with_error ("unexpected output from 'btrfs subvolume list' command: %s", line);
free_stringslen (lines, nr_subvolumes);
free (ret->guestfs_int_btrfssubvolume_list_val);
free (ret);
return NULL;
goto error;
}
pos = strstr (line, " path ");
if (pos == NULL)
goto unexpected_output;
pos += 6;
struct guestfs_int_btrfssubvolume *this =
&ret->guestfs_int_btrfssubvolume_list_val[i];
memmove (line, pos, strlen (pos) + 1);
ret->guestfs_int_btrfssubvolume_list_val[i].btrfssubvolume_path = line;
#if __WORDSIZE == 64
#define XSTRTOU64 xstrtoul
#else
#define XSTRTOU64 xstrtoull
#endif
if (XSTRTOU64 (line + ovector[2], NULL, 10,
&this->btrfssubvolume_id, NULL) != LONGINT_OK)
goto unexpected_output;
if (XSTRTOU64 (line + ovector[4], NULL, 10,
&this->btrfssubvolume_top_level_id, NULL) != LONGINT_OK)
goto unexpected_output;
#undef XSTRTOU64
memmove (line, line + ovector[6], ovector[7] + 1);
this->btrfssubvolume_path = line;
}
free (lines);
pcre_free (re);
return ret;
error:
free_stringslen (lines, nr_subvolumes);
if (ret) free (ret->guestfs_int_btrfssubvolume_list_val);
free (ret);
if (re) pcre_free (re);
return NULL;
}
int
@@ -420,9 +497,9 @@ do_btrfs_subvolume_set_default (int64_t id, const char *fs)
const size_t MAX_ARGS = 64;
const char *argv[MAX_ARGS];
size_t i = 0;
char *fs_buf;
CLEANUP_FREE char *fs_buf = NULL;
char buf[64];
char *err;
CLEANUP_FREE char *err = NULL;
int r;
snprintf (buf, sizeof buf, "%" PRIi64, id);
@@ -441,13 +518,10 @@ do_btrfs_subvolume_set_default (int64_t id, const char *fs)
ADD_ARG (argv, i, NULL);
r = commandv (NULL, &err, argv);
free (fs_buf);
if (r == -1) {
reply_with_error ("%s: %s", fs, err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -458,8 +532,8 @@ do_btrfs_filesystem_sync (const char *fs)
const size_t MAX_ARGS = 64;
const char *argv[MAX_ARGS];
size_t i = 0;
char *fs_buf;
char *err;
CLEANUP_FREE char *fs_buf = NULL;
CLEANUP_FREE char *err = NULL;
int r;
fs_buf = sysroot_path (fs);
@@ -475,13 +549,10 @@ do_btrfs_filesystem_sync (const char *fs)
ADD_ARG (argv, i, NULL);
r = commandv (NULL, &err, argv);
free (fs_buf);
if (r == -1) {
reply_with_error ("%s: %s", fs, err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -492,8 +563,8 @@ do_btrfs_filesystem_balance (const char *fs)
const size_t MAX_ARGS = 64;
const char *argv[MAX_ARGS];
size_t i = 0;
char *fs_buf;
char *err;
CLEANUP_FREE char *fs_buf = NULL;
CLEANUP_FREE char *err = NULL;
int r;
fs_buf = sysroot_path (fs);
@@ -509,13 +580,10 @@ do_btrfs_filesystem_balance (const char *fs)
ADD_ARG (argv, i, NULL);
r = commandv (NULL, &err, argv);
free (fs_buf);
if (r == -1) {
reply_with_error ("%s: %s", fs, err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -531,8 +599,8 @@ do_btrfs_device_add (char *const *devices, const char *fs)
size_t MAX_ARGS = nr_devices + 8;
const char *argv[MAX_ARGS];
size_t i = 0, j;
char *fs_buf;
char *err;
CLEANUP_FREE char *fs_buf = NULL;
CLEANUP_FREE char *err = NULL;
int r;
fs_buf = sysroot_path (fs);
@@ -552,13 +620,10 @@ do_btrfs_device_add (char *const *devices, const char *fs)
ADD_ARG (argv, i, NULL);
r = commandv (NULL, &err, argv);
free (fs_buf);
if (r == -1) {
reply_with_error ("%s: %s", fs, err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -574,8 +639,8 @@ do_btrfs_device_delete (char *const *devices, const char *fs)
size_t MAX_ARGS = nr_devices + 8;
const char *argv[MAX_ARGS];
size_t i = 0, j;
char *fs_buf;
char *err;
CLEANUP_FREE char *fs_buf = NULL;
CLEANUP_FREE char *err = NULL;
int r;
fs_buf = sysroot_path (fs);
@@ -595,13 +660,10 @@ do_btrfs_device_delete (char *const *devices, const char *fs)
ADD_ARG (argv, i, NULL);
r = commandv (NULL, &err, argv);
free (fs_buf);
if (r == -1) {
reply_with_error ("%s: %s", fs, err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -609,7 +671,7 @@ do_btrfs_device_delete (char *const *devices, const char *fs)
int
do_btrfs_set_seeding (const char *device, int svalue)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
const char *s_value = svalue ? "1" : "0";
@@ -617,11 +679,9 @@ do_btrfs_set_seeding (const char *device, int svalue)
r = commandr (NULL, &err, str_btrfstune, "-S", s_value, device, NULL);
if (r == -1) {
reply_with_error ("%s: %s", device, err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -629,7 +689,7 @@ do_btrfs_set_seeding (const char *device, int svalue)
int
do_btrfs_fsck (const char *device, int64_t superblock, int repair)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
size_t i = 0;
const size_t MAX_ARGS = 64;
@@ -661,10 +721,8 @@ do_btrfs_fsck (const char *device, int64_t superblock, int repair)
r = commandv (NULL, &err, argv);
if (r == -1) {
reply_with_error ("%s: %s", device, err);
free (err);
return -1;
}
free (err);
return 0;
}

View File

@@ -1,5 +1,5 @@
/* libguestfs - the guestfsd daemon
* Copyright (C) 2009-2012 Red Hat Inc.
* Copyright (C) 2009-2013 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
@@ -66,7 +66,8 @@ static char *
checksum (const char *csumtype, int fd)
{
const char *program;
char *out, *err;
char *out;
CLEANUP_FREE char *err = NULL;
int flags, r;
size_t len;
@@ -84,12 +85,9 @@ checksum (const char *csumtype, int fd)
pulse_mode_cancel ();
reply_with_error ("%s: %s", program, err);
free (out);
free (err);
return NULL;
}
free (err);
/* Split it at the first whitespace. */
len = strcspn (out, " \t\n");
out[len] = '\0';
@@ -141,7 +139,7 @@ do_checksums_out (const char *csumtype, const char *dir)
if (program == NULL)
return -1;
char *sysrootdir = sysroot_path (dir);
CLEANUP_FREE char *sysrootdir = sysroot_path (dir);
if (!sysrootdir) {
reply_with_perror ("malloc");
return -1;
@@ -150,24 +148,19 @@ do_checksums_out (const char *csumtype, const char *dir)
r = stat (sysrootdir, &statbuf);
if (r == -1) {
reply_with_perror ("%s", dir);
free (sysrootdir);
return -1;
}
if (!S_ISDIR (statbuf.st_mode)) {
reply_with_error ("%s: not a directory", dir);
free (sysrootdir);
return -1;
}
char *cmd;
CLEANUP_FREE char *cmd = NULL;
if (asprintf_nowarn (&cmd, "cd %Q && %s -type f -print0 | %s -0 %s",
str_find, str_xargs,
sysrootdir, program) == -1) {
sysrootdir, str_find, str_xargs, program) == -1) {
reply_with_perror ("asprintf");
free (sysrootdir);
return -1;
}
free (sysrootdir);
if (verbose)
fprintf (stderr, "%s\n", cmd);
@@ -175,10 +168,8 @@ do_checksums_out (const char *csumtype, const char *dir)
FILE *fp = popen (cmd, "r");
if (fp == NULL) {
reply_with_perror ("%s", cmd);
free (cmd);
return -1;
}
free (cmd);
/* Now we must send the reply message, before the file contents. After
* this there is no opportunity in the protocol to send any error
@@ -196,14 +187,14 @@ do_checksums_out (const char *csumtype, const char *dir)
}
if (ferror (fp)) {
perror (dir);
fprintf (stderr, "fread: %s: %m\n", dir);
send_file_end (1); /* Cancel. */
pclose (fp);
return -1;
}
if (pclose (fp) != 0) {
perror (dir);
fprintf (stderr, "pclose: %s: %m\n", dir);
send_file_end (1); /* Cancel. */
return -1;
}

View File

@@ -32,8 +32,8 @@ GUESTFSD_EXT_CMD(str_cmp, cmp);
int
do_equal (const char *file1, const char *file2)
{
char *file1buf, *file2buf;
char *err;
CLEANUP_FREE char *file1buf = NULL, *file2buf = NULL;
CLEANUP_FREE char *err = NULL;
int r;
file1buf = sysroot_path (file1);
@@ -45,22 +45,14 @@ do_equal (const char *file1, const char *file2)
file2buf = sysroot_path (file2);
if (file2buf == NULL) {
reply_with_perror ("malloc");
free (file1buf);
return -1;
}
r = commandr (NULL, &err, str_cmp, "-s", file1buf, file2buf, NULL);
free (file1buf);
free (file2buf);
if (r == -1 || r > 1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
return r == 0;
}

View File

@@ -40,10 +40,11 @@ umount_ignore_fail (const char *path)
char *
do_command (char *const *argv)
{
char *out, *err;
char *out;
CLEANUP_FREE char *err;
int r;
char *sysroot_dev, *sysroot_dev_pts, *sysroot_proc,
*sysroot_selinux, *sysroot_sys;
CLEANUP_FREE char *sysroot_dev = NULL, *sysroot_dev_pts = NULL,
*sysroot_proc = NULL, *sysroot_selinux = NULL, *sysroot_sys = NULL;
int dev_ok, dev_pts_ok, proc_ok, selinux_ok, sys_ok;
/* We need a root filesystem mounted to do this. */
@@ -76,11 +77,6 @@ do_command (char *const *argv)
sysroot_proc == NULL || sysroot_selinux == NULL ||
sysroot_sys == NULL) {
reply_with_perror ("malloc");
free (sysroot_dev);
free (sysroot_dev_pts);
free (sysroot_proc);
free (sysroot_selinux);
free (sysroot_sys);
return NULL;
}
@@ -105,28 +101,19 @@ do_command (char *const *argv)
if (dev_pts_ok) umount_ignore_fail (sysroot_dev_pts);
if (dev_ok) umount_ignore_fail (sysroot_dev);
free (sysroot_dev);
free (sysroot_dev_pts);
free (sysroot_proc);
free (sysroot_selinux);
free (sysroot_sys);
if (r == -1) {
reply_with_error ("%s", err);
free (out);
free (err);
return NULL;
}
free (err);
return out; /* Caller frees. */
}
char **
do_command_lines (char *const *argv)
{
char *out;
CLEANUP_FREE char *out = NULL;
char **lines;
out = do_command (argv);
@@ -134,7 +121,6 @@ do_command_lines (char *const *argv)
return NULL;
lines = split_lines (out);
free (out);
if (lines == NULL)
return NULL;

View File

@@ -39,7 +39,7 @@ do_compressX_out (const char *file, const char *filter, int is_device)
{
int r;
FILE *fp;
char *cmd;
CLEANUP_FREE char *cmd = NULL;
char buf[GUESTFS_MAX_CHUNK_SIZE];
/* The command will look something like:
@@ -71,10 +71,8 @@ do_compressX_out (const char *file, const char *filter, int is_device)
fp = popen (cmd, "r");
if (fp == NULL) {
reply_with_perror ("%s", cmd);
free (cmd);
return -1;
}
free (cmd);
/* Now we must send the reply message, before the file contents. After
* this there is no opportunity in the protocol to send any error
@@ -90,14 +88,14 @@ do_compressX_out (const char *file, const char *filter, int is_device)
}
if (ferror (fp)) {
perror (file);
fprintf (stderr, "fread: %s: %m\n", file);
send_file_end (1); /* Cancel. */
pclose (fp);
return -1;
}
if (pclose (fp) != 0) {
perror (file);
fprintf (stderr, "pclose: %s: %m\n", file);
send_file_end (1); /* Cancel. */
return -1;
}
@@ -111,7 +109,7 @@ do_compressX_out (const char *file, const char *filter, int is_device)
#define CHECK_SUPPORTED(prog) \
if (!prog_exists (prog)) \
/* note: substring "not supported" must appear in this error */ \
NOT_SUPPORTED (-1, "compression type %s is not supported", prog);
NOT_SUPPORTED (-1, "compression type %s is not supported, because external program '%s' is not available in the appliance", prog, prog);
static int
get_filter (const char *ctype, int level, char *ret, size_t n)

View File

@@ -42,13 +42,14 @@ static int
copy (const char *src, const char *src_display,
const char *dest, const char *dest_display,
int wrflags, int wrmode,
int64_t srcoffset, int64_t destoffset, int64_t size)
int64_t srcoffset, int64_t destoffset, int64_t size, int sparse)
{
int64_t saved_size = size;
int src_fd, dest_fd;
char buf[BUFSIZ];
size_t n;
ssize_t r;
int err;
if ((optargs_bitmask & GUESTFS_COPY_DEVICE_TO_DEVICE_SRCOFFSET_BITMASK)) {
if (srcoffset < 0) {
@@ -77,6 +78,9 @@ copy (const char *src, const char *src_display,
else
size = -1;
if (! (optargs_bitmask & GUESTFS_COPY_DEVICE_TO_DEVICE_SPARSE_BITMASK))
sparse = 0;
/* Open source and destination. */
src_fd = open (src, O_RDONLY|O_CLOEXEC);
if (src_fd == -1) {
@@ -116,8 +120,10 @@ copy (const char *src, const char *src_display,
r = read (src_fd, buf, n);
if (r == -1) {
err = errno;
if (size == -1)
pulse_mode_cancel ();
errno = err;
reply_with_perror ("read: %s", src_display);
close (src_fd);
close (dest_fd);
@@ -133,14 +139,31 @@ copy (const char *src, const char *src_display,
return -1;
}
if (sparse && is_zero (buf, r)) {
if (lseek (dest_fd, r, SEEK_CUR) == -1) {
err = errno;
if (size == -1)
pulse_mode_cancel ();
errno = err;
reply_with_perror ("%s: seek (because of sparse flag)", dest_display);
close (src_fd);
close (dest_fd);
return -1;
}
goto sparse_skip;
}
if (xwrite (dest_fd, buf, r) == -1) {
err = errno;
if (size == -1)
pulse_mode_cancel ();
errno = err;
reply_with_perror ("%s: write", dest_display);
close (src_fd);
close (dest_fd);
return -1;
}
sparse_skip:
if (size != -1) {
size -= r;
@@ -167,58 +190,51 @@ copy (const char *src, const char *src_display,
int
do_copy_device_to_device (const char *src, const char *dest,
int64_t srcoffset, int64_t destoffset, int64_t size)
int64_t srcoffset, int64_t destoffset, int64_t size,
int sparse)
{
return copy (src, src, dest, dest, DEST_DEVICE_FLAGS,
srcoffset, destoffset, size);
srcoffset, destoffset, size, sparse);
}
int
do_copy_device_to_file (const char *src, const char *dest,
int64_t srcoffset, int64_t destoffset, int64_t size)
int64_t srcoffset, int64_t destoffset, int64_t size,
int sparse)
{
char *dest_buf;
int r;
CLEANUP_FREE char *dest_buf = sysroot_path (dest);
dest_buf = sysroot_path (dest);
if (!dest_buf) {
reply_with_perror ("malloc");
return -1;
}
r = copy (src, src, dest_buf, dest, DEST_FILE_FLAGS,
srcoffset, destoffset, size);
free (dest_buf);
return r;
return copy (src, src, dest_buf, dest, DEST_FILE_FLAGS,
srcoffset, destoffset, size, sparse);
}
int
do_copy_file_to_device (const char *src, const char *dest,
int64_t srcoffset, int64_t destoffset, int64_t size)
int64_t srcoffset, int64_t destoffset, int64_t size,
int sparse)
{
char *src_buf;
int r;
CLEANUP_FREE char *src_buf = sysroot_path (src);
src_buf = sysroot_path (src);
if (!src_buf) {
reply_with_perror ("malloc");
return -1;
}
r = copy (src_buf, src, dest, dest, DEST_DEVICE_FLAGS,
srcoffset, destoffset, size);
free (src_buf);
return r;
return copy (src_buf, src, dest, dest, DEST_DEVICE_FLAGS,
srcoffset, destoffset, size, sparse);
}
int
do_copy_file_to_file (const char *src, const char *dest,
int64_t srcoffset, int64_t destoffset, int64_t size)
int64_t srcoffset, int64_t destoffset, int64_t size,
int sparse)
{
char *src_buf, *dest_buf;
int r;
CLEANUP_FREE char *src_buf = NULL, *dest_buf = NULL;
src_buf = sysroot_path (src);
if (!src_buf) {
@@ -229,14 +245,9 @@ do_copy_file_to_file (const char *src, const char *dest,
dest_buf = sysroot_path (dest);
if (!dest_buf) {
reply_with_perror ("malloc");
free (src_buf);
return -1;
}
r = copy (src_buf, src, dest_buf, dest, DEST_FILE_FLAGS,
srcoffset, destoffset, size);
free (src_buf);
free (dest_buf);
return r;
return copy (src_buf, src, dest_buf, dest, DEST_FILE_FLAGS,
srcoffset, destoffset, size, sparse);
}

View File

@@ -1,5 +1,5 @@
/* libguestfs - the guestfsd daemon
* Copyright (C) 2009-2012 Red Hat Inc.
* Copyright (C) 2009-2013 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
@@ -51,8 +51,8 @@ do_mv (const char *src, const char *dest)
static int
cpmv_cmd (const char *cmd, const char *flags, const char *src, const char *dest)
{
char *srcbuf, *destbuf;
char *err;
CLEANUP_FREE char *srcbuf = NULL, *destbuf = NULL;
CLEANUP_FREE char *err = NULL;
int r;
srcbuf = sysroot_path (src);
@@ -64,7 +64,6 @@ cpmv_cmd (const char *cmd, const char *flags, const char *src, const char *dest)
destbuf = sysroot_path (dest);
if (destbuf == NULL) {
reply_with_perror ("malloc");
free (srcbuf);
return -1;
}
@@ -75,16 +74,11 @@ cpmv_cmd (const char *cmd, const char *flags, const char *src, const char *dest)
else
r = command (NULL, &err, cmd, srcbuf, destbuf, NULL);
free (srcbuf);
free (destbuf);
if (r == -1) {
pulse_mode_cancel ();
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
pulse_mode_end ();

View File

@@ -1,5 +1,5 @@
/* libguestfs - the guestfsd daemon
* Copyright (C) 2009-2012 Red Hat Inc.
* Copyright (C) 2009-2013 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
@@ -30,6 +30,16 @@
#include "guestfs_protocol.h"
#include "guestfs-internal-all.h"
/* Mountables */
typedef struct {
mountable_type_t type;
const char *device;
const char *volume;
} mountable_t;
/*-- in guestfsd.c --*/
extern int verbose;
@@ -47,6 +57,14 @@ extern int xwrite (int sock, const void *buf, size_t len)
extern int xread (int sock, void *buf, size_t len)
__attribute__((__warn_unused_result__));
extern char *mountable_to_string (const mountable_t *mountable);
/*-- in mount.c --*/
extern int mount_vfs_nochroot (const char *options, const char *vfstype,
const mountable_t *mountable,
const char *mp, const char *user_mp);
/* Growable strings buffer. */
struct stringsbuf {
char **argv;
@@ -100,9 +118,9 @@ extern char **split_lines (char *str);
#define COMMAND_FLAG_CHROOT_COPY_FILE_TO_STDIN 2048
extern int commandf (char **stdoutput, char **stderror, int flags,
const char *name, ...);
const char *name, ...) __attribute__((sentinel));
extern int commandrf (char **stdoutput, char **stderror, int flags,
const char *name, ...);
const char *name, ...) __attribute__((sentinel));
extern int commandvf (char **stdoutput, char **stderror, int flags,
char const *const *argv);
extern int commandrvf (char **stdoutput, char **stderror, int flags,
@@ -114,6 +132,8 @@ extern void trim (char *str);
extern int device_name_translation (char *device);
extern int parse_btrfsvol (char *desc, mountable_t *mountable);
extern int prog_exists (const char *prog);
extern void udev_settle (void);
@@ -122,8 +142,13 @@ extern int random_name (char *template);
/* This just stops gcc from giving a warning about our custom printf
* formatters %Q and %R. See guestfs(3)/EXTENDING LIBGUESTFS for more
* info about these.
* info about these. In GCC 4.8.0 the warning is even harder to
* 'trick', hence the need for the #pragma directives.
*/
#if defined(__GNUC__) && GUESTFS_GCC_VERSION >= 40800 /* gcc >= 4.8.0 */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
#endif
static inline int
asprintf_nowarn (char **strp, const char *fmt, ...)
{
@@ -135,6 +160,14 @@ asprintf_nowarn (char **strp, const char *fmt, ...)
va_end (args);
return r;
}
#if defined(__GNUC__) && GUESTFS_GCC_VERSION >= 40800 /* gcc >= 4.8.0 */
#pragma GCC diagnostic pop
#endif
/* Use by the CLEANUP_* macros. */
extern void cleanup_free (void *ptr);
extern void cleanup_free_string_list (void *ptr);
extern void cleanup_unlink_free (void *ptr);
/*-- in names.c (auto-generated) --*/
extern const char *function_names[];
@@ -179,6 +212,9 @@ extern int lv_canonical (const char *device, char **ret);
/*-- in lvm-filter.c --*/
extern void copy_lvm (void);
/*-- in zero.c --*/
extern void wipe_device_before_mkfs (const char *device);
/*-- in proto.c --*/
extern void main_loop (int sock) __attribute__((noreturn));
@@ -237,6 +273,11 @@ extern void pulse_mode_start (void);
extern void pulse_mode_end (void);
extern void pulse_mode_cancel (void);
/* Send a progress message without rate-limiting. This is just
* for debugging - DON'T use it in regular code!
*/
extern void notify_progress_no_ratelimit (uint64_t position, uint64_t total, const struct timeval *now);
/* Return true iff the buffer is all zero bytes.
*
* Note that gcc is smart enough to optimize this properly:
@@ -320,6 +361,33 @@ is_zero (const char *buffer, size_t size)
} \
} while (0)
/* All functions that take a mountable argument must call this macro.
* It parses the mountable into a mountable_t, ensures any
* underlying device exists, and does device name translation
* (described in the guestfs(3) manpage).
*
* Note that the "string" argument may be modified.
*/
#define RESOLVE_MOUNTABLE(string,mountable,cancel_stmt,fail_stmt) \
do { \
if (STRPREFIX ((string), "btrfsvol:")) { \
if (parse_btrfsvol ((string) + strlen ("btrfsvol:"), &(mountable)) == -1)\
{ \
cancel_stmt; \
reply_with_error ("%s: %s: expecting a btrfs volume", \
__func__, (string)); \
fail_stmt; \
} \
} \
\
else { \
(mountable).type = MOUNTABLE_DEVICE; \
(mountable).device = (string); \
(mountable).volume = NULL; \
RESOLVE_DEVICE((string), cancel_stmt, fail_stmt); \
} \
} while (0)
/* Helper for functions which need either an absolute path in the
* mounted filesystem, OR a /dev/ device which exists.
*
@@ -340,6 +408,24 @@ is_zero (const char *buffer, size_t size)
} \
} while (0)
/* Helper for functions which need either an absolute path in the
* mounted filesystem, OR a valid mountable description.
*/
#define REQUIRE_ROOT_OR_RESOLVE_MOUNTABLE(string, mountable, \
cancel_stmt, fail_stmt) \
do { \
if (STREQLEN ((string), "/dev/", strlen ("/dev/")) || (string)[0] != '/') {\
RESOLVE_MOUNTABLE (string, mountable, cancel_stmt, fail_stmt); \
} \
\
else { \
NEED_ROOT (cancel_stmt, fail_stmt); \
(mountable).type = MOUNTABLE_PATH; \
(mountable).device = (string); \
} \
} while (0) \
/* NB:
* (1) You must match CHROOT_IN and CHROOT_OUT even along error paths.
* (2) You must not change directory! cwd must always be "/", otherwise
@@ -384,24 +470,15 @@ is_zero (const char *buffer, size_t size)
} \
while (0)
#ifndef __attribute__
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
# define __attribute__(x) /* empty */
# endif
#ifdef HAVE_ATTRIBUTE_CLEANUP
#define CLEANUP_FREE __attribute__((cleanup(cleanup_free)))
#define CLEANUP_FREE_STRING_LIST \
__attribute__((cleanup(cleanup_free_string_list)))
#define CLEANUP_UNLINK_FREE __attribute__((cleanup(cleanup_unlink_free)))
#else
#define CLEANUP_FREE
#define CLEANUP_FREE_STRING_LIST
#define CLEANUP_UNLINK_FREE
#endif
#ifndef ATTRIBUTE_UNUSED
# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
#endif
#define STREQ(a,b) (strcmp((a),(b)) == 0)
#define STRCASEEQ(a,b) (strcasecmp((a),(b)) == 0)
#define STRNEQ(a,b) (strcmp((a),(b)) != 0)
#define STRCASENEQ(a,b) (strcasecmp((a),(b)) != 0)
#define STREQLEN(a,b,n) (strncmp((a),(b),(n)) == 0)
#define STRCASEEQLEN(a,b,n) (strncasecmp((a),(b),(n)) == 0)
#define STRNEQLEN(a,b,n) (strncmp((a),(b),(n)) != 0)
#define STRCASENEQLEN(a,b,n) (strncasecmp((a),(b),(n)) != 0)
#define STRPREFIX(a,b) (strncmp((a),(b),strlen((b))) == 0)
#endif /* GUESTFSD_DAEMON_H */

View File

@@ -33,8 +33,8 @@ int
do_dd (const char *src, const char *dest)
{
int src_is_dev, dest_is_dev;
char *if_arg, *of_arg;
char *err;
CLEANUP_FREE char *if_arg = NULL, *of_arg = NULL;
CLEANUP_FREE char *err = NULL;
int r;
src_is_dev = STRPREFIX (src, "/dev/");
@@ -56,20 +56,14 @@ do_dd (const char *src, const char *dest)
r = asprintf (&of_arg, "of=%s%s", sysroot, dest);
if (r == -1) {
reply_with_perror ("asprintf");
free (if_arg);
return -1;
}
r = command (NULL, &err, str_dd, "bs=1024K", if_arg, of_arg, NULL);
free (if_arg);
free (of_arg);
if (r == -1) {
reply_with_error ("%s: %s: %s", src, dest, err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -77,19 +71,17 @@ do_dd (const char *src, const char *dest)
int
do_copy_size (const char *src, const char *dest, int64_t ssize)
{
char *buf;
int src_fd, dest_fd;
if (STRPREFIX (src, "/dev/"))
src_fd = open (src, O_RDONLY | O_CLOEXEC);
else {
buf = sysroot_path (src);
CLEANUP_FREE char *buf = sysroot_path (src);
if (!buf) {
reply_with_perror ("malloc");
return -1;
}
src_fd = open (buf, O_RDONLY | O_CLOEXEC);
free (buf);
}
if (src_fd == -1) {
reply_with_perror ("%s", src);
@@ -99,14 +91,13 @@ do_copy_size (const char *src, const char *dest, int64_t ssize)
if (STRPREFIX (dest, "/dev/"))
dest_fd = open (dest, O_WRONLY | O_CLOEXEC);
else {
buf = sysroot_path (dest);
CLEANUP_FREE char *buf = sysroot_path (dest);
if (!buf) {
reply_with_perror ("malloc");
close (src_fd);
return -1;
}
dest_fd = open (buf, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, 0666);
free (buf);
}
if (dest_fd == -1) {
reply_with_perror ("%s", dest);

View File

@@ -21,6 +21,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -72,6 +73,8 @@ static char *debug_qtrace (const char *subcmd, size_t argc, char *const *const a
static char *debug_segv (const char *subcmd, size_t argc, char *const *const argv);
static char *debug_setenv (const char *subcmd, size_t argc, char *const *const argv);
static char *debug_sh (const char *subcmd, size_t argc, char *const *const argv);
static char *debug_spew (const char *subcmd, size_t argc, char *const *const argv);
static void deliberately_cause_a_segfault (void);
static struct cmd cmds[] = {
{ "help", debug_help },
@@ -87,6 +90,7 @@ static struct cmd cmds[] = {
{ "segv", debug_segv },
{ "setenv", debug_setenv },
{ "sh", debug_sh },
{ "spew", debug_spew },
{ NULL, NULL }
};
@@ -209,13 +213,7 @@ debug_fds (const char *subcmd, size_t argc, char *const *const argv)
static char *
debug_segv (const char *subcmd, size_t argc, char *const *const argv)
{
/* http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html
* "Dereferencing a NULL Pointer: contrary to popular belief,
* dereferencing a null pointer in C is undefined. It is not defined
* to trap [...]"
*/
volatile int *ptr = NULL;
*ptr = 1;
deliberately_cause_a_segfault ();
return NULL;
}
@@ -227,7 +225,7 @@ debug_segv (const char *subcmd, size_t argc, char *const *const argv)
static char *
debug_sh (const char *subcmd, size_t argc, char *const *const argv)
{
char *cmd;
CLEANUP_FREE char *cmd = NULL;
size_t len, i, j;
if (argc < 1) {
@@ -266,8 +264,6 @@ debug_sh (const char *subcmd, size_t argc, char *const *const argv)
char *err;
int r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
"/bin/sh", "-c", cmd, NULL);
free (cmd);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
@@ -282,18 +278,16 @@ static char *
debug_env (const char *subcmd, size_t argc, char *const *const argv)
{
int r;
char *out, *err;
char *out;
CLEANUP_FREE char *err = NULL;
r = command (&out, &err, str_printenv, NULL);
if (r == -1) {
reply_with_error ("printenv: %s", err);
free (out);
free (err);
return NULL;
}
free (err);
return out;
}
@@ -326,7 +320,8 @@ static char *
debug_binaries (const char *subcmd, size_t argc, char *const *const argv)
{
int r;
char *out, *err;
char *out;
CLEANUP_FREE char *err;
char cmd[256];
snprintf (cmd, sizeof (cmd),
@@ -340,12 +335,9 @@ debug_binaries (const char *subcmd, size_t argc, char *const *const argv)
if (r == -1) {
reply_with_error ("find: %s", err);
free (out);
free (err);
return NULL;
}
free (err);
return out;
}
@@ -356,7 +348,8 @@ static char *
debug_ldd (const char *subcmd, size_t argc, char *const *const argv)
{
int r;
char *out, *err, *ret;
char *out, *ret;
CLEANUP_FREE char *err = NULL;
if (argc != 1) {
reply_with_error ("ldd: no file argument");
@@ -373,7 +366,6 @@ debug_ldd (const char *subcmd, size_t argc, char *const *const argv)
if (r == -1) {
reply_with_error ("ldd: %s: %s", argv[0], err);
free (out);
free (err);
return NULL;
}
@@ -382,12 +374,10 @@ debug_ldd (const char *subcmd, size_t argc, char *const *const argv)
if (ret == NULL) {
reply_with_perror ("realloc");
free (out);
free (err);
return NULL;
}
strcat (ret, err);
free (err);
return ret;
}
@@ -399,6 +389,9 @@ debug_ls (const char *subcmd, size_t argc, char *const *const argv)
size_t len = count_strings (argv);
const char *cargv[len+3];
size_t i;
int r;
char *out;
CLEANUP_FREE char *err;
cargv[0] = str_ls;
cargv[1] = "-a";
@@ -406,19 +399,13 @@ debug_ls (const char *subcmd, size_t argc, char *const *const argv)
cargv[2+i] = argv[i];
cargv[2+len] = NULL;
int r;
char *out, *err;
r = commandv (&out, &err, (void *) cargv);
if (r == -1) {
reply_with_error ("ls: %s", err);
free (out);
free (err);
return NULL;
}
free (err);
return out;
}
@@ -429,6 +416,9 @@ debug_ll (const char *subcmd, size_t argc, char *const *const argv)
size_t len = count_strings (argv);
const char *cargv[len+3];
size_t i;
int r;
char *out;
CLEANUP_FREE char *err;
cargv[0] = str_ls;
cargv[1] = "-la";
@@ -436,19 +426,13 @@ debug_ll (const char *subcmd, size_t argc, char *const *const argv)
cargv[2+i] = argv[i];
cargv[2+len] = NULL;
int r;
char *out, *err;
r = commandv (&out, &err, (void *) cargv);
if (r == -1) {
reply_with_error ("ll: %s", err);
free (out);
free (err);
return NULL;
}
free (err);
return out;
}
@@ -456,29 +440,56 @@ debug_ll (const char *subcmd, size_t argc, char *const *const argv)
static char *
debug_progress (const char *subcmd, size_t argc, char *const *const argv)
{
uint64_t secs, rate = 0;
char *ret;
if (argc < 1) {
error:
reply_with_error ("progress: expecting arg (time in seconds as string)");
reply_with_error ("progress: expecting one or more args: time in seconds [, rate in microseconds]");
return NULL;
}
char *secs_str = argv[0];
unsigned secs;
if (sscanf (secs_str, "%u", &secs) != 1)
if (sscanf (argv[0], "%" SCNu64, &secs) != 1)
goto error;
if (secs == 0 || secs > 1000000) { /* RHBZ#816839 */
reply_with_error ("progress: argument is 0, less than 0, or too large");
return NULL;
}
unsigned i;
unsigned tsecs = secs * 10; /* 1/10ths of seconds */
for (i = 1; i <= tsecs; ++i) {
usleep (100000);
notify_progress ((uint64_t) i, (uint64_t) tsecs);
if (argc >= 2) {
if (sscanf (argv[1], "%" SCNu64, &rate) != 1)
goto error;
if (rate == 0 || rate > 1000000) {
reply_with_error ("progress: rate is 0 or too large");
return NULL;
}
}
char *ret = strdup ("ok");
/* Note the inner loops go to '<= limit' because we want to ensure
* that the final 100% completed message is set.
*/
if (rate == 0) { /* Ordinary rate-limited progress messages. */
uint64_t tsecs = secs * 10; /* 1/10ths of seconds */
uint64_t i;
for (i = 1; i <= tsecs; ++i) {
usleep (100000);
notify_progress (i, tsecs);
}
}
else { /* Send messages at a given rate. */
uint64_t usecs = secs * 1000000; /* microseconds */
uint64_t i;
struct timeval now;
for (i = rate; i <= usecs; i += rate) {
usleep (rate);
gettimeofday (&now, NULL);
notify_progress_no_ratelimit (i, usecs, &now);
}
}
ret = strdup ("ok");
if (ret == NULL) {
reply_with_perror ("strdup");
return NULL;
@@ -538,6 +549,42 @@ debug_core_pattern (const char *subcmd, size_t argc, char *const *const argv)
return ret;
}
/* Generate lots of debug messages. Each line of output is 72
* characters long (plus '\n'), so the total size of the output in
* bytes is n*73.
*/
static char *
debug_spew (const char *subcmd, size_t argc, char *const *const argv)
{
size_t i, n;
char *ret;
if (argc != 1) {
reply_with_error ("spew: expecting number of lines <n>");
return NULL;
}
if (sscanf (argv[0], "%zu", &n) != 1) {
reply_with_error ("spew: could not parse number of lines '%s'", argv[0]);
return NULL;
}
for (i = 0; i < n; ++i)
fprintf (stderr,
"abcdefghijklmnopqrstuvwxyz" /* 26 */
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* 52 */
"01234567890123456789" /* 72 */
"\n");
ret = strdup ("ok");
if (!ret) {
reply_with_perror ("strdup");
return NULL;
}
return ret;
}
static int
write_cb (void *fd_ptr, const void *buf, size_t len)
{
@@ -589,12 +636,13 @@ debug_qtrace (const char *subcmd, size_t argc, char *const *const argv)
{ 2, 15, 21, 2, -1 }, /* disable trace */
{ 2, 21, 15, 2, -1 } /* enable trace */
};
void *buf;
CLEANUP_FREE void *buf = NULL;
size_t i;
/* For O_DIRECT, buffer must be aligned too (thanks Matt).
* Note posix_memalign has this strange errno behaviour.
*/
/* coverity[resource_leak] */
errno = posix_memalign (&buf, QTRACE_SIZE, QTRACE_SIZE);
if (errno != 0) {
reply_with_perror ("posix_memalign");
@@ -606,20 +654,17 @@ debug_qtrace (const char *subcmd, size_t argc, char *const *const argv)
if (lseek (fd, patterns[enable][i]*QTRACE_SIZE, SEEK_SET) == -1) {
reply_with_perror ("qtrace: %s: lseek", argv[0]);
close (fd);
free (buf);
return NULL;
}
if (read (fd, buf, QTRACE_SIZE) == -1) {
reply_with_perror ("qtrace: %s: read", argv[0]);
close (fd);
free (buf);
return NULL;
}
}
close (fd);
free (buf);
/* This does a sync and flushes all caches. */
if (do_drop_caches (3) == -1)
@@ -676,3 +721,64 @@ do_debug_upload (const char *filename, int mode)
return 0;
}
/* Internal function used only when testing
* https://bugzilla.redhat.com/show_bug.cgi?id=914931
*/
static int
crash_cb (void *countv, const void *buf, size_t len)
{
int *countp = countv;
(*countp)--;
sleep (1);
if (*countp == 0)
deliberately_cause_a_segfault ();
return 0;
}
/* Has one FileIn parameter. */
int
do_internal_rhbz914931 (int count)
{
int r;
if (count <= 0 || count > 1000) {
reply_with_error ("count out of range");
return -1;
}
r = receive_file (crash_cb, &count);
if (r == -1) { /* write error */
int err = errno;
cancel_receive ();
errno = err;
reply_with_error ("write error");
return -1;
}
if (r == -2) { /* cancellation from library */
/* This error is ignored by the library since it initiated the
* cancel. Nevertheless we must send an error reply here.
*/
reply_with_error ("file upload cancelled");
return -1;
}
return 0;
}
static void
deliberately_cause_a_segfault (void)
{
/* http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html
* "Dereferencing a NULL Pointer: contrary to popular belief,
* dereferencing a null pointer in C is undefined. It is not defined
* to trap [...]"
*/
volatile int *ptr = NULL;
/* coverity[var_deref_op] */
*ptr = 1;
}

View File

@@ -1,5 +1,5 @@
/* libguestfs - the guestfsd daemon
* Copyright (C) 2009-2012 Red Hat Inc.
* Copyright (C) 2009-2013 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
@@ -244,42 +244,62 @@ do_part_to_partnum (const char *part)
return r;
}
int
do_is_whole_device (const char *device)
{
/* A 'whole' block device will have a symlink to the device in its
* /sys/block directory */
CLEANUP_FREE char *devpath = NULL;
if (asprintf (&devpath, "/sys/block/%s/device",
device + strlen ("/dev/")) == -1)
{
reply_with_perror ("asprintf");
return -1;
}
struct stat statbuf;
if (stat (devpath, &statbuf) == -1) {
if (errno == ENOENT || errno == ENOTDIR) return 0;
reply_with_perror ("stat");
return -1;
}
return 1;
}
int
do_device_index (const char *device)
{
char **devices;
size_t i;
int ret = -1;
CLEANUP_FREE_STRING_LIST char **devices = do_list_devices ();
devices = do_list_devices ();
if (devices == NULL)
return -1;
for (i = 0; devices[i] != NULL; ++i) {
if (STREQ (device, devices[i]))
ret = (int) i;
free (devices[i]);
}
free (devices);
if (ret == -1)
reply_with_error ("device not found");
return ret;
}
int
do_nr_devices (void)
{
char **devices;
size_t i;
CLEANUP_FREE_STRING_LIST char **devices = do_list_devices ();
devices = do_list_devices ();
if (devices == NULL)
return -1;
for (i = 0; devices[i] != NULL; ++i)
free (devices[i]);
free (devices);
;
return (int) i;
}
@@ -291,7 +311,7 @@ do_list_disk_labels (void)
{
DIR *dir = NULL;
struct dirent *d;
char *path = NULL, *rawdev = NULL;
char *rawdev = NULL;
DECLARE_STRINGSBUF (ret);
dir = opendir (GUESTFSDIR);
@@ -302,6 +322,8 @@ do_list_disk_labels (void)
errno = 0;
while ((d = readdir (dir)) != NULL) {
CLEANUP_FREE char *path = NULL;
if (d->d_name[0] == '.')
continue;
@@ -318,9 +340,6 @@ do_list_disk_labels (void)
goto error;
}
free (path);
path = NULL;
if (add_string (&ret, d->d_name) == -1)
goto error;
@@ -354,7 +373,6 @@ do_list_disk_labels (void)
error:
if (dir)
closedir (dir);
free (path);
free (rawdev);
return NULL;
}

View File

@@ -33,7 +33,8 @@ char *
do_df (void)
{
int r;
char *out, *err;
char *out;
CLEANUP_FREE char *err = NULL;
NEED_ROOT (, return NULL);
@@ -41,12 +42,9 @@ do_df (void)
if (r == -1) {
reply_with_error ("%s", err);
free (out);
free (err);
return NULL;
}
free (err);
return out; /* Caller frees. */
}
@@ -54,7 +52,8 @@ char *
do_df_h (void)
{
int r;
char *out, *err;
char *out;
CLEANUP_FREE char *err = NULL;
NEED_ROOT (, return NULL);
@@ -62,11 +61,8 @@ do_df_h (void)
if (r == -1) {
reply_with_error ("%s", err);
free (out);
free (err);
return NULL;
}
free (err);
return out; /* Caller frees. */
}

View File

@@ -56,7 +56,7 @@ int
do_rm_rf (const char *path)
{
int r;
char *buf, *err;
CLEANUP_FREE char *buf = NULL, *err = NULL;
if (STREQ (path, "/")) {
reply_with_error ("cannot remove root directory");
@@ -70,17 +70,12 @@ do_rm_rf (const char *path)
}
r = command (NULL, &err, str_rm, "-rf", buf, NULL);
free (buf);
/* rm -rf is never supposed to fail. I/O errors perhaps? */
if (r == -1) {
reply_with_error ("%s: %s", path, err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -133,7 +128,7 @@ recursive_mkdir (const char *path)
{
int loop = 0;
int r;
char *ppath, *p;
char *p;
struct stat buf;
again:
@@ -153,14 +148,13 @@ recursive_mkdir (const char *path)
if (path[0] == '/' && path[1] == '\0') return -1;
/* Try to make the parent directory first. */
ppath = strdup (path);
CLEANUP_FREE char *ppath = strdup (path);
if (ppath == NULL) return -1;
p = strrchr (ppath, '/');
if (p) *p = '\0';
r = recursive_mkdir (ppath);
free (ppath);
if (r != 0) return r;

View File

@@ -32,17 +32,16 @@ GUESTFSD_EXT_CMD(str_dmesg, dmesg);
char *
do_dmesg (void)
{
char *out, *err;
char *out;
CLEANUP_FREE char *err = NULL;
int r;
r = command (&out, &err, str_dmesg, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (out);
free (err);
return NULL;
}
free (err);
return out; /* caller frees */
}

View File

@@ -1,5 +1,5 @@
/* libguestfs - the guestfsd daemon
* Copyright (C) 2009-2012 Red Hat Inc.
* Copyright (C) 2009-2013 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
@@ -35,8 +35,7 @@ do_du (const char *path)
{
int r;
int64_t rv;
char *out, *err;
char *buf;
CLEANUP_FREE char *out = NULL, *err = NULL, *buf = NULL;
/* Make the path relative to /sysroot. */
buf = sysroot_path (path);
@@ -48,26 +47,18 @@ do_du (const char *path)
pulse_mode_start ();
r = command (&out, &err, str_du, "-s", buf, NULL);
free (buf);
if (r == -1) {
pulse_mode_cancel ();
reply_with_error ("%s: %s", path, err);
free (out);
free (err);
return -1;
}
free (err);
if (sscanf (out, "%"SCNi64, &rv) != 1) {
pulse_mode_cancel ();
reply_with_error ("%s: could not read output: %s", path, out);
free (out);
return -1;
}
free (out);
pulse_mode_end ();
return rv;

View File

@@ -50,7 +50,7 @@ do_echo_daemon (char *const *argv)
char *out_new = realloc (out, out_len + 1);
if (NULL == out_new) {
reply_with_perror ("realloc");
free(out);
free (out);
return 0;
}
out = out_new;

View File

@@ -1,5 +1,5 @@
/* libguestfs - the guestfsd daemon
* Copyright (C) 2009-2012 Red Hat Inc.
* Copyright (C) 2009-2013 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
@@ -42,18 +42,15 @@ char **
do_tune2fs_l (const char *device)
{
int r;
char *out, *err;
CLEANUP_FREE char *out = NULL, *err = NULL;
char *p, *pend, *colon;
DECLARE_STRINGSBUF (ret);
r = command (&out, &err, str_tune2fs, "-l", device, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
free (out);
return NULL;
}
free (err);
p = out;
@@ -63,7 +60,6 @@ do_tune2fs_l (const char *device)
if (p) p++;
else {
reply_with_error ("truncated output");
free (out);
return NULL;
}
}
@@ -85,30 +81,25 @@ do_tune2fs_l (const char *device)
do { colon++; } while (*colon && c_isspace (*colon));
if (add_string (&ret, p) == -1) {
free (out);
return NULL;
}
if (STREQ (colon, "<none>") ||
STREQ (colon, "<not available>") ||
STREQ (colon, "(none)")) {
if (add_string (&ret, "") == -1) {
free (out);
return NULL;
}
} else {
if (add_string (&ret, colon) == -1) {
free (out);
return NULL;
}
}
}
else {
if (add_string (&ret, p) == -1) {
free (out);
return NULL;
}
if (add_string (&ret, "") == -1) {
free (out);
return NULL;
}
}
@@ -116,8 +107,6 @@ do_tune2fs_l (const char *device)
p = pend;
}
free (out);
if (end_stringsbuf (&ret) == -1)
return NULL;
@@ -127,43 +116,50 @@ do_tune2fs_l (const char *device)
int
do_set_e2label (const char *device, const char *label)
{
return do_set_label (device, label);
mountable_t mountable;
mountable.type = MOUNTABLE_DEVICE;
mountable.device = device;
return do_set_label (&mountable, label);
}
char *
do_get_e2label (const char *device)
{
return do_vfs_label (device);
mountable_t mountable;
mountable.type = MOUNTABLE_DEVICE;
mountable.device = device;
return do_vfs_label (&mountable);
}
int
do_set_e2uuid (const char *device, const char *uuid)
{
int r;
char *err;
CLEANUP_FREE char *err = NULL;
r = command (NULL, &err, str_tune2fs, "-U", uuid, device, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
return 0;
}
char *
do_get_e2uuid (const char *device)
{
return do_vfs_uuid (device);
mountable_t mountable;
mountable.type = MOUNTABLE_DEVICE;
mountable.device = device;
return do_vfs_uuid (&mountable);
}
/* If the filesystem is not mounted, run e2fsck -f on it unconditionally. */
static int
if_not_mounted_run_e2fsck (const char *device)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r, mounted;
mounted = is_device_mounted (device);
@@ -171,13 +167,13 @@ if_not_mounted_run_e2fsck (const char *device)
return -1;
if (!mounted) {
r = command (NULL, &err, str_e2fsck, "-fy", device, NULL);
r = commandf (NULL, &err,
COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
str_e2fsck, "-fy", device, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
}
return 0;
@@ -186,7 +182,7 @@ if_not_mounted_run_e2fsck (const char *device)
int
do_resize2fs (const char *device)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
if (if_not_mounted_run_e2fsck (device) == -1)
@@ -195,18 +191,16 @@ do_resize2fs (const char *device)
r = command (NULL, &err, str_resize2fs, device, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
return 0;
}
int
do_resize2fs_size (const char *device, int64_t size)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
/* resize2fs itself may impose additional limits. Since we are
@@ -229,18 +223,16 @@ do_resize2fs_size (const char *device, int64_t size)
r = command (NULL, &err, str_resize2fs, device, buf, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
return 0;
}
int
do_resize2fs_M (const char *device)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
if (if_not_mounted_run_e2fsck (device) == -1)
@@ -249,11 +241,9 @@ do_resize2fs_M (const char *device)
r = command (NULL, &err, str_resize2fs, "-M", device, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -264,7 +254,7 @@ do_e2fsck (const char *device,
int forceall)
{
const char *argv[MAX_ARGS];
char *err;
CLEANUP_FREE char *err = NULL;
size_t i = 0;
int r;
@@ -291,7 +281,9 @@ do_e2fsck (const char *device,
ADD_ARG (argv, i, device);
ADD_ARG (argv, i, NULL);
r = commandv (NULL, &err, argv);
r = commandvf (NULL, &err,
COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
argv);
/* 0 = no errors, 1 = errors corrected.
*
* >= 4 means uncorrected or other errors.
@@ -301,11 +293,9 @@ do_e2fsck (const char *device,
*/
if (r == -1 || r >= 2) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -319,29 +309,29 @@ do_e2fsck_f (const char *device)
int
do_mke2journal (int blocksize, const char *device)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
char blocksize_s[32];
snprintf (blocksize_s, sizeof blocksize_s, "%d", blocksize);
wipe_device_before_mkfs (device);
r = command (NULL, &err,
str_mke2fs, "-F", "-O", "journal_dev", "-b", blocksize_s,
device, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
return 0;
}
int
do_mke2journal_L (int blocksize, const char *label, const char *device)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
if (strlen (label) > EXT2_LABEL_MAX) {
@@ -353,40 +343,40 @@ do_mke2journal_L (int blocksize, const char *label, const char *device)
char blocksize_s[32];
snprintf (blocksize_s, sizeof blocksize_s, "%d", blocksize);
wipe_device_before_mkfs (device);
r = command (NULL, &err,
str_mke2fs, "-F", "-O", "journal_dev", "-b", blocksize_s,
"-L", label,
device, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
return 0;
}
int
do_mke2journal_U (int blocksize, const char *uuid, const char *device)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
char blocksize_s[32];
snprintf (blocksize_s, sizeof blocksize_s, "%d", blocksize);
wipe_device_before_mkfs (device);
r = command (NULL, &err,
str_mke2fs, "-F", "-O", "journal_dev", "-b", blocksize_s,
"-U", uuid,
device, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -394,7 +384,7 @@ int
do_mke2fs_J (const char *fstype, int blocksize, const char *device,
const char *journal)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
char blocksize_s[32];
@@ -404,16 +394,16 @@ do_mke2fs_J (const char *fstype, int blocksize, const char *device,
char jdev[len+32];
snprintf (jdev, len+32, "device=%s", journal);
wipe_device_before_mkfs (device);
r = command (NULL, &err,
str_mke2fs, "-F", "-t", fstype, "-J", jdev, "-b", blocksize_s,
device, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -421,7 +411,7 @@ int
do_mke2fs_JL (const char *fstype, int blocksize, const char *device,
const char *label)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
if (strlen (label) > EXT2_LABEL_MAX) {
@@ -437,16 +427,16 @@ do_mke2fs_JL (const char *fstype, int blocksize, const char *device,
char jdev[len+32];
snprintf (jdev, len+32, "device=LABEL=%s", label);
wipe_device_before_mkfs (device);
r = command (NULL, &err,
str_mke2fs, "-F", "-t", fstype, "-J", jdev, "-b", blocksize_s,
device, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -454,7 +444,7 @@ int
do_mke2fs_JU (const char *fstype, int blocksize, const char *device,
const char *uuid)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
char blocksize_s[32];
@@ -464,16 +454,16 @@ do_mke2fs_JU (const char *fstype, int blocksize, const char *device,
char jdev[len+32];
snprintf (jdev, len+32, "device=UUID=%s", uuid);
wipe_device_before_mkfs (device);
r = command (NULL, &err,
str_mke2fs, "-F", "-t", fstype, "-J", jdev, "-b", blocksize_s,
device, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -494,7 +484,7 @@ do_tune2fs (const char *device, /* only required parameter */
const char *argv[MAX_ARGS];
size_t i = 0;
int r;
char *err;
CLEANUP_FREE char *err = NULL;
char maxmountcount_s[64];
char mountcount_s[64];
char group_s[64];
@@ -612,11 +602,9 @@ do_tune2fs (const char *device, /* only required parameter */
r = commandv (NULL, &err, argv);
if (r == -1) {
reply_with_error ("%s: %s", device, err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -632,8 +620,9 @@ char *
do_get_e2attrs (const char *filename)
{
int r;
char *buf;
char *out, *err;
CLEANUP_FREE char *buf;
char *out;
CLEANUP_FREE char *err;
size_t i, j;
buf = sysroot_path (filename);
@@ -643,14 +632,11 @@ do_get_e2attrs (const char *filename)
}
r = command (&out, &err, str_lsattr, "-d", "--", buf, NULL);
free (buf);
if (r == -1) {
reply_with_error ("%s: %s: %s", "lsattr", filename, err);
free (err);
free (out);
return NULL;
}
free (err);
/* Output looks like:
* -------------e- filename
@@ -674,8 +660,8 @@ int
do_set_e2attrs (const char *filename, const char *attrs, int clear)
{
int r;
char *buf;
char *err;
CLEANUP_FREE char *buf = NULL;
CLEANUP_FREE char *err = NULL;
size_t i, j;
int lowers[26], uppers[26];
char attr_arg[26*2+1+1]; /* '+'/'-' + attrs + trailing '\0' */
@@ -737,13 +723,10 @@ do_set_e2attrs (const char *filename, const char *attrs, int clear)
}
r = command (NULL, &err, str_chattr, attr_arg, "--", buf, NULL);
free (buf);
if (r == -1) {
reply_with_error ("%s: %s: %s", "chattr", filename, err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -752,8 +735,7 @@ int64_t
do_get_e2generation (const char *filename)
{
int r;
char *buf;
char *out, *err;
CLEANUP_FREE char *buf = NULL, *out = NULL, *err = NULL;
int64_t ret;
buf = sysroot_path (filename);
@@ -763,22 +745,16 @@ do_get_e2generation (const char *filename)
}
r = command (&out, &err, str_lsattr, "-dv", "--", buf, NULL);
free (buf);
if (r == -1) {
reply_with_error ("%s: %s: %s", "lsattr", filename, err);
free (err);
free (out);
return -1;
}
free (err);
if (sscanf (out, "%" SCNu64, &ret) != 1) {
reply_with_error ("cannot parse output from '%s' command: %s",
"lsattr", out);
free (out);
return -1;
}
free (out);
return ret;
}
@@ -787,8 +763,7 @@ int
do_set_e2generation (const char *filename, int64_t generation)
{
int r;
char *buf;
char *err;
CLEANUP_FREE char *buf = NULL, *err = NULL;
char generation_str[64];
buf = sysroot_path (filename);
@@ -801,13 +776,10 @@ do_set_e2generation (const char *filename, int64_t generation)
"%" PRIu64, (uint64_t) generation);
r = command (NULL, &err, str_chattr, "-v", generation_str, "--", buf, NULL);
free (buf);
if (r == -1) {
reply_with_error ("%s: %s: %s", "chattr", filename, err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -854,7 +826,7 @@ do_mke2fs (const char *device, /* 0 */
int uninitbg)
{
int r;
char *err = NULL;
CLEANUP_FREE char *err = NULL;
const char *argv[MAX_ARGS];
char blockscount_s[64];
char blocksize_s[64];
@@ -864,7 +836,7 @@ do_mke2fs (const char *device, /* 0 */
char bytesperinode_s[64];
char inodesize_s[64];
char journalsize_s[64];
char *journaldevice_s = NULL;
CLEANUP_FREE char *journaldevice_s = NULL;
char reservedblockspercentage_s[64];
char numberofinodes_s[64];
char mmpupdateinterval_s[84];
@@ -878,7 +850,7 @@ do_mke2fs (const char *device, /* 0 */
if (optargs_bitmask & GUESTFS_MKE2FS_BLOCKSIZE_BITMASK) {
if (blocksize < 0) {
reply_with_error ("blocksize must be >= 0");
goto error;
return -1;
}
snprintf (blocksize_s, sizeof blocksize_s, "%" PRIi64, blocksize);
ADD_ARG (argv, i, "-b");
@@ -887,7 +859,7 @@ do_mke2fs (const char *device, /* 0 */
if (optargs_bitmask & GUESTFS_MKE2FS_FRAGSIZE_BITMASK) {
if (fragsize < 0) {
reply_with_error ("fragsize must be >= 0");
goto error;
return -1;
}
snprintf (fragsize_s, sizeof fragsize_s, "%" PRIi64, fragsize);
ADD_ARG (argv, i, "-f");
@@ -900,7 +872,7 @@ do_mke2fs (const char *device, /* 0 */
if (optargs_bitmask & GUESTFS_MKE2FS_BLOCKSPERGROUP_BITMASK) {
if (blockspergroup < 0) {
reply_with_error ("blockspergroup must be >= 0");
goto error;
return -1;
}
snprintf (blockspergroup_s, sizeof blockspergroup_s,
"%" PRIi64, blockspergroup);
@@ -910,7 +882,7 @@ do_mke2fs (const char *device, /* 0 */
if (optargs_bitmask & GUESTFS_MKE2FS_NUMBEROFGROUPS_BITMASK) {
if (numberofgroups < 0) {
reply_with_error ("numberofgroups must be >= 0");
goto error;
return -1;
}
snprintf (numberofgroups_s, sizeof numberofgroups_s,
"%" PRIi64, numberofgroups);
@@ -920,7 +892,7 @@ do_mke2fs (const char *device, /* 0 */
if (optargs_bitmask & GUESTFS_MKE2FS_BYTESPERINODE_BITMASK) {
if (bytesperinode < 0) {
reply_with_error ("bytesperinode must be >= 0");
goto error;
return -1;
}
snprintf (bytesperinode_s, sizeof bytesperinode_s, "%" PRIi64, bytesperinode);
ADD_ARG (argv, i, "-i");
@@ -929,7 +901,7 @@ do_mke2fs (const char *device, /* 0 */
if (optargs_bitmask & GUESTFS_MKE2FS_INODESIZE_BITMASK) {
if (inodesize < 0) {
reply_with_error ("inodesize must be >= 0");
goto error;
return -1;
}
snprintf (inodesize_s, sizeof inodesize_s, "%" PRIi64, inodesize);
ADD_ARG (argv, i, "-I");
@@ -938,7 +910,7 @@ do_mke2fs (const char *device, /* 0 */
if (optargs_bitmask & GUESTFS_MKE2FS_JOURNALSIZE_BITMASK) {
if (journalsize < 0) {
reply_with_error ("journalsize must be >= 0");
goto error;
return -1;
}
snprintf (journalsize_s, sizeof journalsize_s,
"size=" "%" PRIi64, journalsize);
@@ -954,12 +926,12 @@ do_mke2fs (const char *device, /* 0 */
journaldevice_s = malloc (strlen (journaldevice) + 8);
if (!journaldevice_s) {
reply_with_perror ("malloc");
goto error;
return -1;
}
sprintf (journaldevice_s, "device=%s", journaldevice);
if (STRPREFIX (&journaldevice_s[7], "/dev/"))
RESOLVE_DEVICE (&journaldevice_s[7], , goto error);
RESOLVE_DEVICE (&journaldevice_s[7], , return -1);
ADD_ARG (argv, i, "-J");
ADD_ARG (argv, i, journaldevice_s);
@@ -974,7 +946,7 @@ do_mke2fs (const char *device, /* 0 */
if (optargs_bitmask & GUESTFS_MKE2FS_RESERVEDBLOCKSPERCENTAGE_BITMASK) {
if (reservedblockspercentage < 0) {
reply_with_error ("reservedblockspercentage must be >= 0");
goto error;
return -1;
}
snprintf (reservedblockspercentage_s, sizeof reservedblockspercentage_s,
"%" PRIi32, reservedblockspercentage);
@@ -990,7 +962,7 @@ do_mke2fs (const char *device, /* 0 */
if (optargs_bitmask & GUESTFS_MKE2FS_NUMBEROFINODES_BITMASK) {
if (numberofinodes < 0) {
reply_with_error ("numberofinodes must be >= 0");
goto error;
return -1;
}
snprintf (numberofinodes_s, sizeof numberofinodes_s,
"%" PRIi64, numberofinodes);
@@ -1028,7 +1000,7 @@ do_mke2fs (const char *device, /* 0 */
if (optargs_bitmask & GUESTFS_MKE2FS_MMPUPDATEINTERVAL_BITMASK) {
if (mmpupdateinterval < 0) {
reply_with_error ("mmpupdateinterval must be >= 0");
goto error;
return -1;
}
snprintf (mmpupdateinterval_s, sizeof mmpupdateinterval_s,
"mmp_update_interval=" "%" PRIi32, mmpupdateinterval);
@@ -1038,7 +1010,7 @@ do_mke2fs (const char *device, /* 0 */
if (optargs_bitmask & GUESTFS_MKE2FS_STRIDESIZE_BITMASK) {
if (stridesize < 0) {
reply_with_error ("stridesize must be >= 0");
goto error;
return -1;
}
snprintf (stridesize_s, sizeof stridesize_s,
"stride=" "%" PRIi64, stridesize);
@@ -1048,7 +1020,7 @@ do_mke2fs (const char *device, /* 0 */
if (optargs_bitmask & GUESTFS_MKE2FS_STRIPEWIDTH_BITMASK) {
if (stripewidth< 0) {
reply_with_error ("stripewidth must be >= 0");
goto error;
return -1;
}
snprintf (stripewidth_s, sizeof stripewidth_s,
"stripe_width=" "%" PRIi64, stripewidth);
@@ -1058,7 +1030,7 @@ do_mke2fs (const char *device, /* 0 */
if (optargs_bitmask & GUESTFS_MKE2FS_MAXONLINERESIZE_BITMASK) {
if (maxonlineresize < 0) {
reply_with_error ("maxonlineresize must be >= 0");
goto error;
return -1;
}
snprintf (maxonlineresize_s, sizeof maxonlineresize_s,
"resize=" "%" PRIi64, maxonlineresize);
@@ -1169,7 +1141,7 @@ do_mke2fs (const char *device, /* 0 */
if (optargs_bitmask & GUESTFS_MKE2FS_BLOCKSCOUNT_BITMASK) {
if (blockscount < 0) {
reply_with_error ("blockscount must be >= 0");
goto error;
return -1;
}
snprintf (blockscount_s, sizeof blockscount_s, "%" PRIi64, blockscount);
ADD_ARG (argv, i, blockscount_s);
@@ -1177,26 +1149,21 @@ do_mke2fs (const char *device, /* 0 */
ADD_ARG (argv, i, NULL);
wipe_device_before_mkfs (device);
r = commandv (NULL, &err, argv);
if (r == -1) {
reply_with_error ("%s: %s", device, err);
goto error;
return -1;
}
free (journaldevice_s);
free (err);
return 0;
error:
free (journaldevice_s);
free (err);
return -1;
}
int
do_mklost_and_found (const char *mountpoint)
{
char *cmd;
CLEANUP_FREE char *cmd = NULL;
int r;
if (asprintf_nowarn (&cmd, "cd %R && mklost+found", mountpoint) == -1) {
@@ -1207,15 +1174,12 @@ do_mklost_and_found (const char *mountpoint)
r = system (cmd);
if (r == -1) {
reply_with_perror ("system");
free (cmd);
return -1;
}
if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) {
reply_with_error ("%s: command failed", cmd);
free (cmd);
return -1;
}
free (cmd);
return 0;
}

View File

@@ -1,5 +1,5 @@
/* libguestfs - the guestfsd daemon
* Copyright (C) 2009-2012 Red Hat Inc.
* Copyright (C) 2009-2013 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
@@ -440,7 +440,7 @@ do_pwrite_device (const char *device, const char *content, size_t size,
char *
do_file (const char *path)
{
char *buf = NULL;
CLEANUP_FREE char *buf = NULL;
const char *display_path = path;
int is_dev = STRPREFIX (path, "/dev/");
@@ -459,15 +459,12 @@ do_file (const char *path)
struct stat statbuf;
if (lstat (path, &statbuf) == -1) {
reply_with_perror ("lstat: %s", display_path);
free (buf);
return NULL;
}
if (! S_ISREG (statbuf.st_mode)) {
char *ret;
free (buf);
if (S_ISDIR (statbuf.st_mode))
ret = strdup ("directory");
else if (S_ISCHR (statbuf.st_mode))
@@ -494,22 +491,27 @@ do_file (const char *path)
*/
const char *flags = is_dev ? "-zbsL" : "-zb";
char *out, *err;
char *out;
CLEANUP_FREE char *err;
int r = command (&out, &err, str_file, flags, path, NULL);
free (buf);
if (r == -1) {
free (out);
reply_with_error ("%s: %s", display_path, err);
free (err);
return NULL;
}
free (err);
/* We need to remove the trailing \n from output of file(1). */
size_t len = strlen (out);
if (len > 0 && out[len-1] == '\n')
out[len-1] = '\0';
out[--len] = '\0';
/* Some upstream versions of file add a space at the end of the
* output. This is fixed in the Fedora version, but we might as
* well fix it here too. (RHBZ#928995).
*/
if (len > 0 && out[len-1] == ' ')
out[--len] = '\0';
return out; /* caller frees */
}
@@ -520,7 +522,7 @@ do_zfile (const char *method, const char *path)
{
size_t len;
const char *zcat;
char *cmd;
CLEANUP_FREE char *cmd = NULL;
FILE *fp;
char line[256];
@@ -544,12 +546,9 @@ do_zfile (const char *method, const char *path)
fp = popen (cmd, "r");
if (fp == NULL) {
reply_with_perror ("%s", cmd);
free (cmd);
return NULL;
}
free (cmd);
if (fgets (line, sizeof line, fp) == NULL) {
reply_with_perror ("fgets");
fclose (fp);

View File

@@ -1,5 +1,5 @@
/* libguestfs - the guestfsd daemon
* Copyright (C) 2009-2012 Red Hat Inc.
* Copyright (C) 2009-2013 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
@@ -51,14 +51,6 @@ input_to_nul (FILE *fp, char *buf, size_t maxlen)
return -1;
}
/* The code below assumes each path returned can fit into a protocol
* chunk. If this turns out not to be true at some point in the
* future then we'll need to modify the code a bit to handle it.
*/
#if PATH_MAX > GUESTFS_MAX_CHUNK_SIZE
#error "PATH_MAX > GUESTFS_MAX_CHUNK_SIZE"
#endif
/* Has one FileOut parameter. */
int
do_find0 (const char *dir)
@@ -66,9 +58,9 @@ do_find0 (const char *dir)
struct stat statbuf;
int r;
FILE *fp;
char *cmd;
char *sysrootdir;
size_t sysrootdirlen, len;
CLEANUP_FREE char *cmd = NULL;
CLEANUP_FREE char *sysrootdir = NULL;
size_t sysrootdirlen;
char str[GUESTFS_MAX_CHUNK_SIZE];
sysrootdir = sysroot_path (dir);
@@ -80,12 +72,10 @@ do_find0 (const char *dir)
r = stat (sysrootdir, &statbuf);
if (r == -1) {
reply_with_perror ("%s", dir);
free (sysrootdir);
return -1;
}
if (!S_ISDIR (statbuf.st_mode)) {
reply_with_error ("%s: not a directory", dir);
free (sysrootdir);
return -1;
}
@@ -93,10 +83,8 @@ do_find0 (const char *dir)
if (asprintf_nowarn (&cmd, "%s %Q -print0", str_find, sysrootdir) == -1) {
reply_with_perror ("asprintf");
free (sysrootdir);
return -1;
}
free (sysrootdir);
if (verbose)
fprintf (stderr, "%s\n", cmd);
@@ -104,10 +92,8 @@ do_find0 (const char *dir)
fp = popen (cmd, "r");
if (fp == NULL) {
reply_with_perror ("%s", cmd);
free (cmd);
return -1;
}
free (cmd);
/* Now we must send the reply message, before the file contents. After
* this there is no opportunity in the protocol to send any error
@@ -115,8 +101,13 @@ do_find0 (const char *dir)
*/
reply (NULL, NULL);
/* The code below assumes each path returned can fit into a protocol
* chunk (if not you'll get a runtime protocol error). If this
* turns out not to be a problem at some point in the future then
* we'll need to modify the code to handle it. XXX
*/
while ((r = input_to_nul (fp, str, GUESTFS_MAX_CHUNK_SIZE)) > 0) {
len = strlen (str);
size_t len = strlen (str);
if (len <= sysrootdirlen)
continue;
@@ -128,14 +119,14 @@ do_find0 (const char *dir)
}
if (ferror (fp)) {
perror (dir);
fprintf (stderr, "fgetc: %s: %m\n", dir);
send_file_end (1); /* Cancel. */
pclose (fp);
return -1;
}
if (pclose (fp) != 0) {
perror (dir);
fprintf (stderr, "pclose: %s: %m\n", dir);
send_file_end (1); /* Cancel. */
return -1;
}

View File

@@ -31,6 +31,10 @@ GUESTFSD_EXT_CMD(str_findfs, findfs);
static char *
findfs (const char *tag, const char *label_or_uuid)
{
char *out;
CLEANUP_FREE char *err = NULL;
int r;
/* Kill the cache file, forcing blkid to reread values from the
* original filesystems. In blkid there is a '-p' option which is
* supposed to do this, but (a) it doesn't work and (b) that option
@@ -43,17 +47,13 @@ findfs (const char *tag, const char *label_or_uuid)
char arg[len];
snprintf (arg, len, "%s=%s", tag, label_or_uuid);
char *out, *err;
int r = command (&out, &err, str_findfs, arg, NULL);
r = command (&out, &err, str_findfs, arg, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (out);
free (err);
return NULL;
}
free (err);
/* Trim trailing \n if present. */
len = strlen (out);
if (len > 0 && out[len-1] == '\n')

View File

@@ -31,16 +31,14 @@ GUESTFSD_EXT_CMD(str_fsck, fsck);
int
do_fsck (const char *fstype, const char *device)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
r = commandr (NULL, &err, str_fsck, "-a", "-t", fstype, device, NULL);
if (r == -1) {
reply_with_error ("%s: %s", device, err);
free (err);
return -1;
}
free (err);
return r;
}

View File

@@ -46,7 +46,7 @@ do_fstrim (const char *path,
const char *argv[MAX_ARGS];
size_t i = 0;
char offset_s[64], length_s[64], mfe_s[64];
char *err;
CLEANUP_FREE char *err = NULL;
int r;
ADD_ARG (argv, i, str_fstrim);
@@ -90,10 +90,8 @@ do_fstrim (const char *path,
r = commandv (NULL, &err, argv);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
return 0;
}

View File

@@ -36,7 +36,7 @@ grep (const char *regex, const char *path,
{
const char *argv[MAX_ARGS];
size_t i = 0;
char *out, *err;
CLEANUP_FREE char *out = NULL, *err = NULL;
int fd, flags, r;
char **lines;
@@ -78,15 +78,10 @@ grep (const char *regex, const char *path,
r = commandrvf (&out, &err, flags, argv);
if (r == -1 || r > 1) {
reply_with_error ("%s: %s", regex, err);
free (out);
free (err);
return NULL;
}
free (err);
lines = split_lines (out);
free (out);
if (lines == NULL) return NULL;
return lines;

View File

@@ -1,5 +1,5 @@
/* libguestfs - the guestfsd daemon
* Copyright (C) 2009-2012 Red Hat Inc.
* Copyright (C) 2009-2013 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
@@ -38,8 +38,7 @@ int
do_grub_install (const char *root, const char *device)
{
int r;
char *err;
char *buf;
CLEANUP_FREE char *err = NULL, *buf = NULL;
if (asprintf_nowarn (&buf, "--root-directory=%R", root) == -1) {
reply_with_perror ("asprintf");
@@ -47,14 +46,11 @@ do_grub_install (const char *root, const char *device)
}
r = command (NULL, &err, str_grub_install, buf, device, NULL);
free (buf);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
return 0;
}

View File

@@ -1,5 +1,5 @@
/* libguestfs - the guestfsd daemon
* Copyright (C) 2009-2012 Red Hat Inc.
* Copyright (C) 2009-2013 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
@@ -66,6 +66,10 @@ static char *read_cmdline (void);
# define O_CLOEXEC 0
#endif
/* For improved readability dealing with pipe arrays */
#define PIPE_READ 0
#define PIPE_WRITE 1
/* If root device is an ext2 filesystem, this is the major and minor.
* This is so we can ignore this device from the point of view of the
* user, eg. in guestfs_list_devices and many other places.
@@ -354,6 +358,13 @@ read_cmdline (void)
/* Return true iff device is the root device (and therefore should be
* ignored from the point of view of user calls).
*/
static int
is_root_device_stat (struct stat *statbuf)
{
if (statbuf->st_rdev == root_device) return 1;
return 0;
}
int
is_root_device (const char *device)
{
@@ -362,9 +373,8 @@ is_root_device (const char *device)
perror (device);
return 0;
}
if (statbuf.st_rdev == root_device)
return 1;
return 0;
return is_root_device_stat (&statbuf);
}
/* Turn "/path" into "/sysroot/path".
@@ -513,6 +523,9 @@ free_strings (char **argv)
{
size_t argc;
if (!argv)
return;
for (argc = 0; argv[argc] != NULL; ++argc)
free (argv[argc]);
free (argv);
@@ -523,6 +536,9 @@ free_stringslen (char **argv, size_t len)
{
size_t i;
if (!argv)
return;
for (i = 0; i < len; ++i)
free (argv[i]);
free (argv);
@@ -647,7 +663,8 @@ int
commandf (char **stdoutput, char **stderror, int flags, const char *name, ...)
{
va_list args;
const char **argv;
/* NB: Mustn't free the strings which are on the stack. */
CLEANUP_FREE const char **argv;
char *s;
size_t i;
int r;
@@ -668,7 +685,6 @@ commandf (char **stdoutput, char **stderror, int flags, const char *name, ...)
const char **p = realloc (argv, sizeof (char *) * (++i));
if (p == NULL) {
perror ("realloc");
free (argv);
va_end (args);
return -1;
}
@@ -681,9 +697,6 @@ commandf (char **stdoutput, char **stderror, int flags, const char *name, ...)
r = commandvf (stdoutput, stderror, flags, (const char * const*) argv);
/* NB: Mustn't free the strings which are on the stack. */
free (argv);
return r;
}
@@ -695,7 +708,7 @@ int
commandrf (char **stdoutput, char **stderror, int flags, const char *name, ...)
{
va_list args;
const char **argv;
CLEANUP_FREE const char **argv;
char *s;
int i, r;
@@ -715,7 +728,6 @@ commandrf (char **stdoutput, char **stderror, int flags, const char *name, ...)
const char **p = realloc (argv, sizeof (char *) * (++i));
if (p == NULL) {
perror ("realloc");
free (argv);
va_end (args);
return -1;
}
@@ -728,9 +740,6 @@ commandrf (char **stdoutput, char **stderror, int flags, const char *name, ...)
r = commandrvf (stdoutput, stderror, flags, argv);
/* NB: Mustn't free the strings which are on the stack. */
free (argv);
return r;
}
@@ -785,8 +794,8 @@ commandrvf (char **stdoutput, char **stderror, int flags,
size_t so_size = 0, se_size = 0;
int so_fd[2], se_fd[2];
int flag_copy_stdin = flags & COMMAND_FLAG_CHROOT_COPY_FILE_TO_STDIN;
int stdin_fd[2] = { -1, -1 };
pid_t pid, stdin_pid = -1;
int flag_copy_fd = flags & COMMAND_FLAG_FD_MASK;
pid_t pid;
int r, quit, i;
fd_set rset, rset2;
char buf[256];
@@ -816,13 +825,6 @@ commandrvf (char **stdoutput, char **stderror, int flags,
abort ();
}
if (flag_copy_stdin) {
if (pipe (stdin_fd) == -1) {
error (0, errno, "pipe");
abort ();
}
}
pid = fork ();
if (pid == -1) {
error (0, errno, "fork");
@@ -834,95 +836,42 @@ commandrvf (char **stdoutput, char **stderror, int flags,
signal (SIGPIPE, SIG_DFL);
close (0);
if (flag_copy_stdin) {
dup2 (stdin_fd[0], 0);
close (stdin_fd[0]);
close (stdin_fd[1]);
dup2 (flag_copy_fd, STDIN_FILENO);
} else {
/* Set stdin to /dev/null (ignore failure) */
ignore_value (open ("/dev/null", O_RDONLY|O_CLOEXEC));
}
close (so_fd[0]);
close (se_fd[0]);
close (so_fd[PIPE_READ]);
close (se_fd[PIPE_READ]);
if (!(flags & COMMAND_FLAG_FOLD_STDOUT_ON_STDERR))
dup2 (so_fd[1], 1);
dup2 (so_fd[PIPE_WRITE], STDOUT_FILENO);
else
dup2 (se_fd[1], 1);
dup2 (se_fd[1], 2);
close (so_fd[1]);
close (se_fd[1]);
dup2 (se_fd[PIPE_WRITE], STDOUT_FILENO);
dup2 (se_fd[PIPE_WRITE], STDERR_FILENO);
close (so_fd[PIPE_WRITE]);
close (se_fd[PIPE_WRITE]);
ignore_value (chdir ("/"));
execvp (argv[0], (void *) argv);
perror (argv[0]);
_exit (EXIT_FAILURE);
}
if (flag_copy_stdin) {
int fd = flags & COMMAND_FLAG_FD_MASK;
stdin_pid = fork ();
if (stdin_pid == -1) {
error (0, errno, "fork");
abort ();
}
if (stdin_pid == 0) { /* Child process copying stdin. */
close (so_fd[0]);
close (so_fd[1]);
close (se_fd[0]);
close (se_fd[1]);
close (1);
dup2 (stdin_fd[1], 1);
close (stdin_fd[0]);
close (stdin_fd[1]);
if (chroot (sysroot) == -1) {
perror ("chroot");
_exit (EXIT_FAILURE);
}
ssize_t n;
char buffer[BUFSIZ];
while ((n = read (fd, buffer, sizeof buffer)) > 0) {
if (xwrite (1, buffer, n) == -1)
/* EPIPE error indicates the command process has exited
* early. If the command process fails that will be caught
* by the daemon, and if not, then it's not an error.
*/
_exit (errno == EPIPE ? EXIT_SUCCESS : EXIT_FAILURE);
}
if (n == -1) {
perror ("read");
_exit (EXIT_FAILURE);
}
if (close (fd) == -1) {
perror ("close");
_exit (EXIT_FAILURE);
}
_exit (EXIT_SUCCESS);
}
close (fd);
close (stdin_fd[0]);
close (stdin_fd[1]);
}
/* Parent process. */
close (so_fd[1]);
close (se_fd[1]);
close (so_fd[PIPE_WRITE]);
close (se_fd[PIPE_WRITE]);
FD_ZERO (&rset);
FD_SET (so_fd[0], &rset);
FD_SET (se_fd[0], &rset);
FD_SET (so_fd[PIPE_READ], &rset);
FD_SET (se_fd[PIPE_READ], &rset);
quit = 0;
while (quit < 2) {
again:
rset2 = rset;
r = select (MAX (so_fd[0], se_fd[0]) + 1, &rset2, NULL, NULL, NULL);
r = select (MAX (so_fd[PIPE_READ], se_fd[PIPE_READ]) + 1, &rset2,
NULL, NULL, NULL);
if (r == -1) {
if (errno == EINTR)
goto again;
@@ -943,20 +892,20 @@ commandrvf (char **stdoutput, char **stderror, int flags,
*stderror = strdup ("error running external command, "
"see debug output for details");
}
close (so_fd[0]);
close (se_fd[0]);
close (so_fd[PIPE_READ]);
close (se_fd[PIPE_READ]);
if (flag_copy_stdin) close (flag_copy_fd);
waitpid (pid, NULL, 0);
if (stdin_pid >= 0) waitpid (stdin_pid, NULL, 0);
return -1;
}
if (FD_ISSET (so_fd[0], &rset2)) { /* something on stdout */
r = read (so_fd[0], buf, sizeof buf);
if (FD_ISSET (so_fd[PIPE_READ], &rset2)) { /* something on stdout */
r = read (so_fd[PIPE_READ], buf, sizeof buf);
if (r == -1) {
perror ("read");
goto quit;
}
if (r == 0) { FD_CLR (so_fd[0], &rset); quit++; }
if (r == 0) { FD_CLR (so_fd[PIPE_READ], &rset); quit++; }
if (r > 0 && stdoutput) {
so_size += r;
@@ -970,17 +919,17 @@ commandrvf (char **stdoutput, char **stderror, int flags,
}
}
if (FD_ISSET (se_fd[0], &rset2)) { /* something on stderr */
r = read (se_fd[0], buf, sizeof buf);
if (FD_ISSET (se_fd[PIPE_READ], &rset2)) { /* something on stderr */
r = read (se_fd[PIPE_READ], buf, sizeof buf);
if (r == -1) {
perror ("read");
goto quit;
}
if (r == 0) { FD_CLR (se_fd[0], &rset); quit++; }
if (r == 0) { FD_CLR (se_fd[PIPE_READ], &rset); quit++; }
if (r > 0) {
if (verbose)
ignore_value (write (2, buf, r));
ignore_value (write (STDERR_FILENO, buf, r));
if (stderror) {
se_size += r;
@@ -996,8 +945,8 @@ commandrvf (char **stdoutput, char **stderror, int flags,
}
}
close (so_fd[0]);
close (se_fd[0]);
close (so_fd[PIPE_READ]);
close (se_fd[PIPE_READ]);
/* Make sure the output buffers are \0-terminated. Also remove any
* trailing \n characters from the error buffer (not from stdout).
@@ -1028,21 +977,9 @@ commandrvf (char **stdoutput, char **stderror, int flags,
}
}
if (flag_copy_stdin) {
/* Check copy process didn't fail. */
if (waitpid (stdin_pid, &r, 0) != stdin_pid) {
perror ("waitpid");
kill (pid, 9);
waitpid (pid, NULL, 0);
return -1;
}
if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) {
fprintf (stderr, "failed copying from input file, see earlier messages (r = %d)\n", r);
kill (pid, 9);
waitpid (pid, NULL, 0);
return -1;
}
if (flag_copy_stdin && close (flag_copy_fd) == -1) {
perror ("close");
return -1;
}
/* Get the exit status of the command. */
@@ -1233,6 +1170,88 @@ device_name_translation (char *device)
return -1;
}
/* Parse the mountable descriptor for a btrfs subvolume. Don't call this
* directly - use the RESOLVE_MOUNTABLE macro.
*
* A btrfs subvolume is given as:
*
* btrfsvol:/dev/sda3/root
*
* where /dev/sda3 is a block device containing a btrfs filesystem, and root is
* the name of a subvolume on it. This function is passed the string following
* 'btrfsvol:'.
*/
int
parse_btrfsvol (char *desc, mountable_t *mountable)
{
char *device, *volume = NULL, *slash;
struct stat statbuf;
mountable->type = MOUNTABLE_BTRFSVOL;
device = desc;
if (! STRPREFIX (device, "/dev/"))
return -1;
slash = device + strlen ("/dev/") - 1;
while ((slash = strchr (slash + 1, '/'))) {
*slash = '\0';
if (device_name_translation (device) == -1) {
perror (device);
continue;
}
if (stat (device, &statbuf) == -1) {
perror (device);
return -1;
}
if (!S_ISDIR (statbuf.st_mode) &&
!is_root_device_stat (&statbuf))
{
volume = slash + 1;
break;
}
*slash = '/';
}
if (!volume) return -1;
mountable->device = device;
mountable->volume = volume;
return 0;
}
/* Convert a mountable_t back to its string representation
*
* This function can be used in an error path, and must not call
* reply_with_error().
*/
char *
mountable_to_string (const mountable_t *mountable)
{
char *desc;
switch (mountable->type) {
case MOUNTABLE_DEVICE:
case MOUNTABLE_PATH:
return strdup (mountable->device);
case MOUNTABLE_BTRFSVOL:
if (asprintf(&desc, "btrfsvol:%s/%s",
mountable->device, mountable->volume) == -1)
return NULL;
return desc;
default:
return NULL;
}
}
/* Check program exists and is executable on $PATH. Actually, we
* just assume PATH contains the default entries (see main() above).
*/
@@ -1311,3 +1330,27 @@ udev_settle (void)
{
(void) command (NULL, NULL, str_udevadm, "settle", NULL);
}
/* Use by the CLEANUP_* macros. Do not call these directly. */
void
cleanup_free (void *ptr)
{
free (* (void **) ptr);
}
void
cleanup_free_string_list (void *ptr)
{
free_strings (* (char ***) ptr);
}
void
cleanup_unlink_free (void *ptr)
{
char *filename = * (char **) ptr;
if (filename) {
unlink (filename);
free (filename);
}
}

View File

@@ -100,4 +100,4 @@ Richard W.M. Jones L<http://people.redhat.com/~rjones/>
=head1 COPYRIGHT
Copyright (C) 2009-2012 Red Hat Inc.
Copyright (C) 2009-2013 Red Hat Inc.

View File

@@ -31,7 +31,7 @@
static char **
headtail (const char *prog, const char *flag, const char *n, const char *path)
{
char *out, *err;
CLEANUP_FREE char *out = NULL, *err = NULL;
int fd, flags, r;
char **lines;
@@ -48,13 +48,9 @@ headtail (const char *prog, const char *flag, const char *n, const char *path)
r = commandf (&out, &err, flags, prog, flag, n, NULL);
if (r == -1) {
reply_with_error ("%s %s %s: %s", prog, flag, n, err);
free (out);
free (err);
return NULL;
}
free (err);
#if 0
/* Split it at the first whitespace. */
len = strcspn (out, " \t\n");
@@ -62,7 +58,6 @@ headtail (const char *prog, const char *flag, const char *n, const char *path)
#endif
lines = split_lines (out);
free (out);
if (lines == NULL) return NULL;
return lines;

View File

@@ -31,7 +31,8 @@ char *
do_hexdump (const char *path)
{
int fd, flags, r;
char *out, *err;
char *out;
CLEANUP_FREE char *err = NULL;
CHROOT_IN;
fd = open (path, O_RDONLY|O_CLOEXEC);
@@ -46,12 +47,9 @@ do_hexdump (const char *path)
r = commandf (&out, &err, flags, "hexdump", "-C", NULL);
if (r == -1) {
reply_with_error ("%s: %s", path, err);
free (err);
free (out);
return NULL;
}
free (err);
return out; /* caller frees */
}

View File

@@ -70,7 +70,7 @@ hivex_finalize (void)
int
do_hivex_open (const char *filename, int verbose, int debug, int write)
{
char *buf;
CLEANUP_FREE char *buf = NULL;
int flags = 0;
if (h) {
@@ -100,11 +100,9 @@ do_hivex_open (const char *filename, int verbose, int debug, int write)
h = hivex_open (buf, flags);
if (!h) {
reply_with_perror ("hivex failed to open %s", filename);
free (buf);
return -1;
}
free (buf);
return 0;
}
@@ -155,7 +153,7 @@ guestfs_int_hivex_node_list *
do_hivex_node_children (int64_t nodeh)
{
guestfs_int_hivex_node_list *ret;
hive_node_h *r;
CLEANUP_FREE hive_node_h *r = NULL;
size_t i, len;
NEED_HANDLE (NULL);
@@ -173,7 +171,6 @@ do_hivex_node_children (int64_t nodeh)
ret = malloc (sizeof *ret);
if (!ret) {
reply_with_perror ("malloc");
free (r);
return NULL;
}
@@ -183,15 +180,12 @@ do_hivex_node_children (int64_t nodeh)
if (ret->guestfs_int_hivex_node_list_val == NULL) {
reply_with_perror ("malloc");
free (ret);
free (r);
return NULL;
}
for (i = 0; i < len; ++i)
ret->guestfs_int_hivex_node_list_val[i].hivex_node_h = r[i];
free (r);
return ret;
}
@@ -232,7 +226,7 @@ guestfs_int_hivex_value_list *
do_hivex_node_values (int64_t nodeh)
{
guestfs_int_hivex_value_list *ret;
hive_value_h *r;
CLEANUP_FREE hive_value_h *r = NULL;
size_t i, len;
NEED_HANDLE (NULL);
@@ -250,7 +244,6 @@ do_hivex_node_values (int64_t nodeh)
ret = malloc (sizeof *ret);
if (!ret) {
reply_with_perror ("malloc");
free (r);
return NULL;
}
@@ -260,15 +253,12 @@ do_hivex_node_values (int64_t nodeh)
if (ret->guestfs_int_hivex_value_list_val == NULL) {
reply_with_perror ("malloc");
free (ret);
free (r);
return NULL;
}
for (i = 0; i < len; ++i)
ret->guestfs_int_hivex_value_list_val[i].hivex_value_h = (int64_t) r[i];
free (r);
return ret;
}
@@ -341,11 +331,30 @@ do_hivex_value_value (int64_t valueh, size_t *size_r)
int
do_hivex_commit (const char *filename)
{
CLEANUP_FREE char *buf = NULL;
NEED_HANDLE (-1);
if (hivex_commit (h, filename, 0) == -1) {
reply_with_perror ("failed");
return -1;
/* The 'filename' parameter is an optional string, and in most
* cases will be NULL.
*/
if (filename) {
buf = sysroot_path (filename);
if (!buf) {
reply_with_perror ("malloc");
return -1;
}
if (hivex_commit (h, buf, 0) == -1) {
reply_with_perror ("%s: commit failed", filename);
return -1;
}
}
else {
if (hivex_commit (h, NULL, 0) == -1) {
reply_with_perror ("commit failed");
return -1;
}
}
return 0;

View File

@@ -83,7 +83,7 @@ do_internal_hot_remove_drive_precheck (const char *label)
size_t len = strlen (label);
char path[len+64];
int r;
char *out, *err;
CLEANUP_FREE char *out = NULL, *err = NULL;
/* Ensure there are no requests in flight (thanks Paolo Bonzini). */
udev_settle ();
@@ -94,11 +94,8 @@ do_internal_hot_remove_drive_precheck (const char *label)
r = commandr (&out, &err, str_fuser, "-v", "-m", path, NULL);
if (r == -1) {
reply_with_error ("fuser: %s: %s", path, err);
free (out);
free (err);
return -1;
}
free (err);
/* "fuser returns a non-zero return code if none of the specified
* files is accessed or in case of a fatal error. If at least one
@@ -112,13 +109,9 @@ do_internal_hot_remove_drive_precheck (const char *label)
if (verbose)
fprintf (stderr, "%s\n", out);
free (out);
return -1;
}
free (out);
return 0;
}

View File

@@ -37,10 +37,11 @@ char **
do_initrd_list (const char *path)
{
FILE *fp;
char *cmd;
char filename[PATH_MAX];
CLEANUP_FREE char *cmd = NULL;
DECLARE_STRINGSBUF (filenames);
size_t len;
CLEANUP_FREE char *filename = NULL;
size_t allocsize;
ssize_t len;
/* "zcat /sysroot/<path> | cpio --quiet -it", but path must be quoted. */
if (asprintf_nowarn (&cmd, "%s %R | %s --quiet -it", str_zcat, path, str_cpio) == -1) {
@@ -54,16 +55,13 @@ do_initrd_list (const char *path)
fp = popen (cmd, "r");
if (fp == NULL) {
reply_with_perror ("popen: %s", cmd);
free (cmd);
return NULL;
}
free (cmd);
while (fgets (filename, sizeof filename, fp) != NULL) {
len = strlen (filename);
allocsize = 0;
while ((len = getline (&filename, &allocsize, fp)) != -1) {
if (len > 0 && filename[len-1] == '\n')
filename[len-1] = '\0';
if (add_string (&filenames, filename) == -1) {
pclose (fp);
return NULL;
@@ -88,33 +86,36 @@ char *
do_initrd_cat (const char *path, const char *filename, size_t *size_r)
{
char tmpdir[] = "/tmp/initrd-cat-XXXXXX";
CLEANUP_FREE char *cmd;
struct stat statbuf;
int fd, r;
char *ret = NULL;
CLEANUP_FREE char *fullpath = NULL;
if (mkdtemp (tmpdir) == NULL) {
reply_with_perror ("mkdtemp");
return NULL;
}
/* "zcat /sysroot/<path> | cpio --quiet -id file", but paths must be quoted */
char *cmd;
if (asprintf_nowarn (&cmd, "cd %Q && zcat %R | cpio --quiet -id %Q",
tmpdir, path, filename) == -1) {
reply_with_perror ("asprintf");
rmdir (tmpdir);
return NULL;
}
/* Extract file into temporary directory. This may create subdirs.
* It's also possible that this doesn't create anything at all
* (eg. if the named file does not exist in the cpio archive) --
* cpio is silent in this case.
*/
int r = system (cmd);
if (r == -1) {
reply_with_perror ("command failed: %s", cmd);
free (cmd);
/* "zcat /sysroot/<path> | cpio --quiet -id file", but paths must be quoted */
if (asprintf_nowarn (&cmd, "cd %Q && zcat %R | cpio --quiet -id %Q",
tmpdir, path, filename) == -1) {
reply_with_perror ("asprintf");
rmdir (tmpdir);
return NULL;
}
r = system (cmd);
if (r == -1) {
reply_with_perror ("command failed: %s", cmd);
rmdir (tmpdir);
return NULL;
}
free (cmd);
if (WEXITSTATUS (r) != 0) {
reply_with_perror ("command failed with return code %d",
WEXITSTATUS (r));
@@ -122,13 +123,14 @@ do_initrd_cat (const char *path, const char *filename, size_t *size_r)
return NULL;
}
/* Construct the expected name of the extracted file. */
if (asprintf (&fullpath, "%s/%s", tmpdir, filename) == -1) {
reply_with_perror ("asprintf");
rmdir (tmpdir);
return NULL;
}
/* See if we got a file. */
char fullpath[PATH_MAX];
snprintf (fullpath, sizeof fullpath, "%s/%s", tmpdir, filename);
struct stat statbuf;
int fd;
fd = open (fullpath, O_RDONLY|O_CLOEXEC);
if (fd == -1) {
reply_with_perror ("open: %s:%s", path, filename);
@@ -139,8 +141,6 @@ do_initrd_cat (const char *path, const char *filename, size_t *size_r)
/* From this point, we know the file exists, so we require full
* cleanup.
*/
char *ret = NULL;
if (fstat (fd, &statbuf) == -1) {
reply_with_perror ("fstat: %s:%s", path, filename);
goto cleanup;
@@ -189,8 +189,7 @@ do_initrd_cat (const char *path, const char *filename, size_t *size_r)
/* Remove the file. */
if (unlink (fullpath) == -1) {
fprintf (stderr, "unlink: ");
perror (fullpath);
fprintf (stderr, "unlink: %s: %m\n", fullpath);
/* non-fatal */
}
@@ -200,8 +199,7 @@ do_initrd_cat (const char *path, const char *filename, size_t *size_r)
if (!p) break;
*p = '\0';
if (rmdir (fullpath) == -1) {
fprintf (stderr, "rmdir: ");
perror (fullpath);
fprintf (stderr, "rmdir: %s: %m\n", fullpath);
/* non-fatal */
}
} while (STRNEQ (fullpath, tmpdir));

View File

@@ -1,5 +1,5 @@
/* libguestfs - the guestfsd daemon
* Copyright (C) 2009-2012 Red Hat Inc.
* Copyright (C) 2009-2013 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
@@ -43,6 +43,9 @@ static int inotify_fd = -1;
static char inotify_buf[64*1024*1024]; /* Event buffer, [0..posn-1] is valid */
static size_t inotify_posn = 0;
/* Because of use of arbitrary offsets within inotify_buf. */
#pragma GCC diagnostic ignored "-Wcast-align"
/* Clean up the inotify handle on daemon exit. */
static void inotify_finalize (void) __attribute__((destructor));
static void
@@ -151,7 +154,7 @@ int64_t
do_inotify_add_watch (const char *path, int mask)
{
int64_t r;
char *buf;
CLEANUP_FREE char *buf = NULL;
NEED_INOTIFY (-1);
@@ -162,7 +165,6 @@ do_inotify_add_watch (const char *path, int mask)
}
r = inotify_add_watch (inotify_fd, buf, mask);
free (buf);
if (r == -1) {
reply_with_perror ("%s", path);
return -1;

View File

@@ -239,10 +239,9 @@ parse_isoinfo (char **lines)
static guestfs_int_isoinfo *
isoinfo (const char *path)
{
char *out = NULL, *err = NULL;
int r;
char **lines = NULL;
guestfs_int_isoinfo *ret = NULL;
CLEANUP_FREE char *out = NULL, *err = NULL;
CLEANUP_FREE_STRING_LIST char **lines = NULL;
/* --debug is necessary to get additional fields, in particular
* the date & time fields.
@@ -250,24 +249,14 @@ isoinfo (const char *path)
r = command (&out, &err, str_isoinfo, "--debug", "-d", "-i", path, NULL);
if (r == -1) {
reply_with_error ("%s", err);
goto done;
return NULL;
}
lines = split_lines (out);
if (lines == NULL)
goto done;
return NULL;
ret = parse_isoinfo (lines);
if (ret == NULL)
goto done;
done:
free (out);
free (err);
if (lines)
free_strings (lines);
return ret;
return parse_isoinfo (lines);
}
guestfs_int_isoinfo *
@@ -279,17 +268,14 @@ do_isoinfo_device (const char *device)
guestfs_int_isoinfo *
do_isoinfo (const char *path)
{
char *buf;
guestfs_int_isoinfo *ret;
buf = sysroot_path (path);
CLEANUP_FREE char *buf = sysroot_path (path);
if (!buf) {
reply_with_perror ("malloc");
return NULL;
}
ret = isoinfo (buf);
free (buf);
return ret;
}

View File

@@ -34,7 +34,7 @@ static int
e2label (const char *device, const char *label)
{
int r;
char *err;
CLEANUP_FREE char *err = NULL;
if (strlen (label) > EXT2_LABEL_MAX) {
reply_with_error ("%s: ext2 labels are limited to %d bytes",
@@ -45,11 +45,9 @@ e2label (const char *device, const char *label)
r = command (NULL, &err, str_e2label, device, label, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -57,7 +55,7 @@ static int
ntfslabel (const char *device, const char *label)
{
int r;
char *err;
CLEANUP_FREE char *err = NULL;
/* XXX We should check if the label is longer than 128 unicode
* characters and return an error. This is not so easy since we
@@ -66,31 +64,28 @@ ntfslabel (const char *device, const char *label)
r = command (NULL, &err, str_ntfslabel, device, label, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
return 0;
}
int
do_set_label (const char *device, const char *label)
do_set_label (const mountable_t *mountable, const char *label)
{
char *vfs_type;
int r;
/* How we set the label depends on the filesystem type. */
vfs_type = do_vfs_type (device);
CLEANUP_FREE char *vfs_type = do_vfs_type (mountable);
if (vfs_type == NULL)
return -1;
if (STREQ (vfs_type, "ext2") || STREQ (vfs_type, "ext3")
|| STREQ (vfs_type, "ext4"))
r = e2label (device, label);
r = e2label (mountable->device, label);
else if (STREQ (vfs_type, "ntfs"))
r = ntfslabel (device, label);
r = ntfslabel (mountable->device, label);
else {
reply_with_error ("don't know how to set the label for '%s' filesystems",
@@ -98,6 +93,5 @@ do_set_label (const char *device, const char *label)
r = -1;
}
free (vfs_type);
return r;
}

View File

@@ -105,15 +105,13 @@ int
do_ldmtool_create_all (void)
{
int r;
char *err;
CLEANUP_FREE char *err = NULL;
r = command (NULL, &err, "ldmtool", "create", "all", NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -121,15 +119,13 @@ int
do_ldmtool_remove_all (void)
{
int r;
char *err;
CLEANUP_FREE char *err = NULL;
r = command (NULL, &err, "ldmtool", "remove", "all", NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -293,9 +289,9 @@ do_ldmtool_scan_devices (char * const * devices)
{
char **ret;
size_t i, nr_devices;
const char **argv;
CLEANUP_FREE_STRING_LIST const char **argv = NULL;
int r;
char *out, *err;
CLEANUP_FREE char *out = NULL, *err = NULL;
nr_devices = count_strings (devices);
argv = malloc ((3 + nr_devices) * sizeof (char *));
@@ -311,153 +307,113 @@ do_ldmtool_scan_devices (char * const * devices)
argv[2+i] = NULL;
r = commandv (&out, &err, argv);
free (argv);
if (r == -1) {
reply_with_error ("%s", err);
free (out);
free (err);
return NULL;
}
free (err);
ret = parse_json_get_string_list (out, __func__, "ldmtool scan");
free (out);
return ret;
}
char *
do_ldmtool_diskgroup_name (const char *diskgroup)
{
char *ret;
int r;
char *out, *err;
CLEANUP_FREE char *out = NULL, *err = NULL;
r = command (&out, &err, str_ldmtool, "show", "diskgroup", diskgroup, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (out);
free (err);
return NULL;
}
free (err);
ret = parse_json_get_object_string (out, "name", 0,
__func__, "ldmtool show diskgroup");
free (out);
return ret;
return parse_json_get_object_string (out, "name", 0,
__func__, "ldmtool show diskgroup");
}
char **
do_ldmtool_diskgroup_volumes (const char *diskgroup)
{
char **ret;
int r;
char *out, *err;
CLEANUP_FREE char *out = NULL, *err = NULL;
r = command (&out, &err, str_ldmtool, "show", "diskgroup", diskgroup, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (out);
free (err);
return NULL;
}
free (err);
ret = parse_json_get_object_string_list (out, "volumes",
__func__, "ldmtool show diskgroup");
free (out);
return ret;
return parse_json_get_object_string_list (out, "volumes",
__func__, "ldmtool show diskgroup");
}
char **
do_ldmtool_diskgroup_disks (const char *diskgroup)
{
char **ret;
int r;
char *out, *err;
CLEANUP_FREE char *out = NULL, *err = NULL;
r = command (&out, &err, str_ldmtool, "show", "diskgroup", diskgroup, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (out);
free (err);
return NULL;
}
free (err);
ret = parse_json_get_object_string_list (out, "disks",
__func__, "ldmtool show diskgroup");
free (out);
return ret;
return parse_json_get_object_string_list (out, "disks",
__func__, "ldmtool show diskgroup");
}
char *
do_ldmtool_volume_type (const char *diskgroup, const char *volume)
{
char *ret;
int r;
char *out, *err;
CLEANUP_FREE char *out = NULL, *err = NULL;
r = command (&out, &err,
str_ldmtool, "show", "volume", diskgroup, volume, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (out);
free (err);
return NULL;
}
free (err);
ret = parse_json_get_object_string (out, "type", 0,
__func__, "ldmtool show volume");
free (out);
return ret;
return parse_json_get_object_string (out, "type", 0,
__func__, "ldmtool show volume");
}
char *
do_ldmtool_volume_hint (const char *diskgroup, const char *volume)
{
char *ret;
int r;
char *out, *err;
CLEANUP_FREE char *out = NULL, *err = NULL;
r = command (&out, &err,
str_ldmtool, "show", "volume", diskgroup, volume, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (out);
free (err);
return NULL;
}
free (err);
ret = parse_json_get_object_string (out, "hint", GET_STRING_NULL_TO_EMPTY,
__func__, "ldmtool show volume");
free (out);
return ret;
return parse_json_get_object_string (out, "hint", GET_STRING_NULL_TO_EMPTY,
__func__, "ldmtool show volume");
}
char **
do_ldmtool_volume_partitions (const char *diskgroup, const char *volume)
{
char **ret;
int r;
char *out, *err;
CLEANUP_FREE char *out = NULL, *err = NULL;
r = command (&out, &err,
str_ldmtool, "show", "volume", diskgroup, volume, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (out);
free (err);
return NULL;
}
free (err);
ret = parse_json_get_object_string_list (out, "partitions",
__func__, "ldmtool show volume");
free (out);
return ret;
return parse_json_get_object_string_list (out, "partitions",
__func__, "ldmtool show volume");
}
#else /* !HAVE_YAJL */

View File

@@ -25,6 +25,8 @@
#include <unistd.h>
#include <limits.h>
#include "areadlink.h"
#include "daemon.h"
#include "actions.h"
@@ -33,25 +35,17 @@ GUESTFSD_EXT_CMD(str_ln, ln);
char *
do_readlink (const char *path)
{
ssize_t r;
char *ret;
char link[PATH_MAX];
char *link;
CHROOT_IN;
r = readlink (path, link, sizeof link);
link = areadlink (path);
CHROOT_OUT;
if (r == -1) {
if (link == NULL) {
reply_with_perror ("readlink");
return NULL;
}
ret = strndup (link, r);
if (ret == NULL) {
reply_with_perror ("strndup");
return NULL;
}
return ret; /* caller frees */
return link; /* caller frees */
}
char **
@@ -59,9 +53,6 @@ do_internal_readlinklist (const char *path, char *const *names)
{
int fd_cwd;
size_t i;
ssize_t r;
char link[PATH_MAX];
const char *str;
DECLARE_STRINGSBUF (ret);
CHROOT_IN;
@@ -74,23 +65,20 @@ do_internal_readlinklist (const char *path, char *const *names)
}
for (i = 0; names[i] != NULL; ++i) {
r = readlinkat (fd_cwd, names[i], link, sizeof link);
if (r >= PATH_MAX) {
reply_with_perror ("readlinkat: returned link is too long");
close (fd_cwd);
return NULL;
}
/* Because of the way this function is intended to be used,
* we actually expect to see errors here, and they are not fatal.
*/
if (r >= 0) {
link[r] = '\0';
str = link;
} else
str = "";
if (add_string (&ret, str) == -1) {
close (fd_cwd);
return NULL;
CLEANUP_FREE char *link = areadlinkat (fd_cwd, names[i]);
if (link != NULL) {
if (add_string (&ret, link) == -1) {
add_string_failed:
close (fd_cwd);
return NULL;
}
} else {
if (add_string (&ret, "") == -1)
goto add_string_failed;
}
}
@@ -102,13 +90,47 @@ do_internal_readlinklist (const char *path, char *const *names)
return ret.argv;
}
static int
_link (const char *flag, int symbolic, const char *target, const char *linkname)
int
do_ln (const char *target, const char *linkname)
{
int r;
char *err;
char *buf_linkname;
char *buf_target;
CHROOT_IN;
r = link (target, linkname);
CHROOT_OUT;
if (r == -1) {
reply_with_perror ("link: %s: %s", target, linkname);
return -1;
}
return 0;
}
int
do_ln_f (const char *target, const char *linkname)
{
int r;
CHROOT_IN;
unlink (linkname);
r = link (target, linkname);
CHROOT_OUT;
if (r == -1) {
reply_with_perror ("link: %s: %s", target, linkname);
return -1;
}
return 0;
}
static int
_symlink (const char *flag, const char *target, const char *linkname)
{
int r;
CLEANUP_FREE char *err = NULL;
CLEANUP_FREE char *buf_linkname = NULL;
/* Prefix linkname with sysroot. */
buf_linkname = sysroot_path (linkname);
@@ -117,65 +139,26 @@ _link (const char *flag, int symbolic, const char *target, const char *linkname)
return -1;
}
/* Only prefix target if it's _not_ a symbolic link, and if
* the target is absolute. Note that the resulting link will
* always be "broken" from the p.o.v. of the appliance, ie:
* /a -> /b but the path as seen here is /sysroot/b
*/
buf_target = NULL;
if (!symbolic && target[0] == '/') {
buf_target = sysroot_path (target);
if (!buf_target) {
reply_with_perror ("malloc");
free (buf_linkname);
return -1;
}
}
if (flag)
r = command (NULL, &err,
str_ln, flag, "--", /* target could begin with '-' */
buf_target ? : target, buf_linkname, NULL);
else
r = command (NULL, &err,
str_ln, "--",
buf_target ? : target, buf_linkname, NULL);
free (buf_linkname);
free (buf_target);
r = command (NULL, &err,
str_ln, flag, "--", /* target could begin with '-' */
target, buf_linkname, NULL);
if (r == -1) {
reply_with_error ("ln%s%s: %s: %s: %s",
flag ? " " : "",
flag ? : "",
target, linkname, err);
free (err);
reply_with_error ("ln %s: %s: %s: %s",
flag, target, linkname, err);
return -1;
}
free (err);
return 0;
}
int
do_ln (const char *target, const char *linkname)
{
return _link (NULL, 0, target, linkname);
}
int
do_ln_f (const char *target, const char *linkname)
{
return _link ("-f", 0, target, linkname);
}
int
do_ln_s (const char *target, const char *linkname)
{
return _link ("-s", 1, target, linkname);
return _symlink ("-s", target, linkname);
}
int
do_ln_sf (const char *target, const char *linkname)
{
return _link ("-sf", 1, target, linkname);
return _symlink ("-sf", target, linkname);
}

View File

@@ -77,14 +77,14 @@ do_ls0 (const char *path)
}
if (errno != 0) {
perror (path);
fprintf (stderr, "readdir: %s: %m\n", path);
send_file_end (1); /* Cancel. */
closedir (dir);
return -1;
}
if (closedir (dir) == -1) {
perror (path);
fprintf (stderr, "closedir: %s: %m\n", path);
send_file_end (1); /* Cancel. */
return -1;
}
@@ -105,8 +105,9 @@ char *
do_ll (const char *path)
{
int r;
char *out, *err;
char *spath;
char *out;
CLEANUP_FREE char *err = NULL;
CLEANUP_FREE char *spath = NULL;
spath = sysroot_path (path);
if (!spath) {
@@ -115,15 +116,12 @@ do_ll (const char *path)
}
r = command (&out, &err, str_ls, "-la", spath, NULL);
free (spath);
if (r == -1) {
reply_with_error ("%s", err);
free (out);
free (err);
return NULL;
}
free (err);
return out; /* caller frees */
}
@@ -131,8 +129,9 @@ char *
do_llz (const char *path)
{
int r;
char *out, *err;
char *spath;
char *out;
CLEANUP_FREE char *err = NULL;
CLEANUP_FREE char *spath;
spath = sysroot_path (path);
if (!spath) {
@@ -141,14 +140,11 @@ do_llz (const char *path)
}
r = command (&out, &err, str_ls, "-laZ", spath, NULL);
free (spath);
if (r == -1) {
reply_with_error ("%s", err);
free (out);
free (err);
return NULL;
}
free (err);
return out; /* caller frees */
}

View File

@@ -115,18 +115,15 @@ luks_open (const char *device, const char *key, const char *mapname,
ADD_ARG (argv, i, mapname);
ADD_ARG (argv, i, NULL);
char *err;
CLEANUP_FREE char *err = NULL;
int r = commandv (NULL, &err, (const char * const *) argv);
remove_temp (tempfile);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
udev_settle ();
return 0;
@@ -155,16 +152,13 @@ do_luks_close (const char *device)
const char *mapname = &device[12];
char *err;
CLEANUP_FREE char *err = NULL;
int r = command (NULL, &err, str_cryptsetup, "luksClose", mapname, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
udev_settle ();
return 0;
@@ -196,18 +190,15 @@ luks_format (const char *device, const char *key, int keyslot,
ADD_ARG (argv, i, tempfile);
ADD_ARG (argv, i, NULL);
char *err;
CLEANUP_FREE char *err = NULL;
int r = commandv (NULL, &err, (const char * const *) argv);
remove_temp (tempfile);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
udev_settle ();
return 0;
@@ -256,19 +247,16 @@ do_luks_add_key (const char *device, const char *key, const char *newkey,
ADD_ARG (argv, i, newkeyfile);
ADD_ARG (argv, i, NULL);
char *err;
CLEANUP_FREE char *err = NULL;
int r = commandv (NULL, &err, (const char * const *) argv);
remove_temp (keyfile);
remove_temp (newkeyfile);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -293,17 +281,14 @@ do_luks_kill_slot (const char *device, const char *key, int keyslot)
ADD_ARG (argv, i, keyslot_s);
ADD_ARG (argv, i, NULL);
char *err;
CLEANUP_FREE char *err = NULL;
int r = commandv (NULL, &err, (const char * const *) argv);
remove_temp (tempfile);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
return 0;
}

View File

@@ -37,7 +37,13 @@ GUESTFSD_EXT_CMD(str_rm, rm);
/* This runs during daemon start up and creates a complete copy of
* /etc/lvm so that we can modify it as we desire. We set
* LVM_SYSTEM_DIR to point to the copy.
* LVM_SYSTEM_DIR to point to the copy. Note that the final directory
* layout is:
* /tmp/lvmXXXXXX (lvm_system_dir set to this)
* /tmp/lvmXXXXXX/lvm ($LVM_SYSTEM_DIR set to this)
* /tmp/lvmXXXXXX/lvm/lvm.conf (configuration file)
* /tmp/lvmXXXXXX/lvm/cache
* etc.
*/
static char lvm_system_dir[] = "/tmp/lvmXXXXXX";
@@ -47,7 +53,7 @@ void
copy_lvm (void)
{
struct stat statbuf;
char cmd[64];
char cmd[64], env[64];
int r;
/* If /etc/lvm directory doesn't exist (or isn't a directory) assume
@@ -64,12 +70,12 @@ copy_lvm (void)
}
if (mkdtemp (lvm_system_dir) == NULL) {
perror (lvm_system_dir);
fprintf (stderr, "mkdtemp: %s: %m\n", lvm_system_dir);
exit (EXIT_FAILURE);
}
/* Hopefully no dotfiles in there ... XXX */
snprintf (cmd, sizeof cmd, "%s -a /etc/lvm/* %s", str_cp, lvm_system_dir);
/* Copy the entire directory */
snprintf (cmd, sizeof cmd, "%s -a /etc/lvm/ %s", str_cp, lvm_system_dir);
r = system (cmd);
if (r == -1) {
perror (cmd);
@@ -85,7 +91,8 @@ copy_lvm (void)
}
/* Set environment variable so we use the copy. */
setenv ("LVM_SYSTEM_DIR", lvm_system_dir, 1);
snprintf (env, sizeof env, "%s/lvm", lvm_system_dir);
setenv ("LVM_SYSTEM_DIR", env, 1);
/* Set a handler to remove the temporary directory at exit. */
atexit (rm_lvm_system_dir);
@@ -129,10 +136,11 @@ static int
set_filter (const char *filter)
{
char lvm_conf[64];
snprintf (lvm_conf, sizeof lvm_conf, "%s/lvm.conf", lvm_system_dir);
snprintf (lvm_conf, sizeof lvm_conf, "%s/lvm/lvm.conf", lvm_system_dir);
char lvm_conf_new[64];
snprintf (lvm_conf_new, sizeof lvm_conf, "%s/lvm.conf.new", lvm_system_dir);
snprintf (lvm_conf_new, sizeof lvm_conf, "%s/lvm/lvm.conf.new",
lvm_system_dir);
FILE *ifp = fopen (lvm_conf, "r");
if (ifp == NULL) {
@@ -146,9 +154,9 @@ set_filter (const char *filter)
return -1;
}
char *line = NULL;
size_t len = 0;
while (getline (&line, &len, ifp) != -1) {
CLEANUP_FREE char *line = NULL;
size_t allocsize = 0;
while (getline (&line, &allocsize, ifp) != -1) {
int r;
if (is_filter_line (line)) {
r = fprintf (ofp, " filter = [ %s ]\n", filter);
@@ -160,14 +168,11 @@ set_filter (const char *filter)
reply_with_error ("%s: write failed", lvm_conf_new);
fclose (ifp);
fclose (ofp);
free (line);
unlink (lvm_conf_new);
return -1;
}
}
free (line);
if (fclose (ifp) == EOF) {
reply_with_perror ("close: %s", lvm_conf);
unlink (lvm_conf_new);
@@ -192,15 +197,13 @@ set_filter (const char *filter)
static int
vgchange (const char *vgchange_flag)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r = command (NULL, &err, str_lvm, "vgchange", vgchange_flag, NULL);
if (r == -1) {
reply_with_error ("vgchange: %s", err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -223,19 +226,17 @@ static int
rescan (void)
{
char lvm_cache[64];
snprintf (lvm_cache, sizeof lvm_cache, "%s/cache/.cache", lvm_system_dir);
snprintf (lvm_cache, sizeof lvm_cache, "%s/lvm/cache/.cache", lvm_system_dir);
unlink (lvm_cache);
char *err;
CLEANUP_FREE char *err = NULL;
int r = command (NULL, &err, str_lvm, "vgscan", NULL);
if (r == -1) {
reply_with_error ("vgscan: %s", err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -287,17 +288,14 @@ make_filter_string (char *const *devices)
int
do_lvm_set_filter (char *const *devices)
{
char *filter = make_filter_string (devices);
CLEANUP_FREE char *filter = make_filter_string (devices);
if (filter == NULL)
return -1;
if (deactivate () == -1) {
free (filter);
if (deactivate () == -1)
return -1;
}
int r = set_filter (filter);
free (filter);
if (r == -1)
return -1;

View File

@@ -1,5 +1,5 @@
/* libguestfs - the guestfsd daemon
* Copyright (C) 2009-2012 Red Hat Inc.
* Copyright (C) 2009-2013 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
@@ -103,7 +103,8 @@ convert_lvm_output (char *out, const char *prefix)
char **
do_pvs (void)
{
char *out, *err;
char *out;
CLEANUP_FREE char *err = NULL;
int r;
r = command (&out, &err,
@@ -111,19 +112,17 @@ do_pvs (void)
if (r == -1) {
reply_with_error ("%s", err);
free (out);
free (err);
return NULL;
}
free (err);
return convert_lvm_output (out, NULL);
}
char **
do_vgs (void)
{
char *out, *err;
char *out;
CLEANUP_FREE char *err = NULL;
int r;
r = command (&out, &err,
@@ -131,19 +130,17 @@ do_vgs (void)
if (r == -1) {
reply_with_error ("%s", err);
free (out);
free (err);
return NULL;
}
free (err);
return convert_lvm_output (out, NULL);
}
char **
do_lvs (void)
{
char *out, *err;
char *out;
CLEANUP_FREE char *err = NULL;
int r;
r = command (&out, &err,
@@ -153,12 +150,9 @@ do_lvs (void)
if (r == -1) {
reply_with_error ("%s", err);
free (out);
free (err);
return NULL;
}
free (err);
return convert_lvm_output (out, "/dev/");
}
@@ -187,19 +181,16 @@ do_lvs_full (void)
int
do_pvcreate (const char *device)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
r = command (NULL, &err,
str_lvm, "pvcreate", device, NULL);
str_lvm, "pvcreate", "--force", device, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
udev_settle ();
return 0;
@@ -208,9 +199,9 @@ do_pvcreate (const char *device)
int
do_vgcreate (const char *volgroup, char *const *physvols)
{
char *err;
int r, argc, i;
const char **argv;
CLEANUP_FREE char *err = NULL;
CLEANUP_FREE const char **argv = NULL;
argc = count_strings (physvols) + 3;
argv = malloc (sizeof (char *) * (argc + 1));
@@ -227,14 +218,9 @@ do_vgcreate (const char *volgroup, char *const *physvols)
r = commandv (NULL, &err, (const char * const*) argv);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
free (argv);
return -1;
}
free (err);
free (argv);
udev_settle ();
return 0;
@@ -243,7 +229,7 @@ do_vgcreate (const char *volgroup, char *const *physvols)
int
do_lvcreate (const char *logvol, const char *volgroup, int mbytes)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
char size[64];
@@ -254,12 +240,9 @@ do_lvcreate (const char *logvol, const char *volgroup, int mbytes)
"-L", size, "-n", logvol, volgroup, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
udev_settle ();
return 0;
@@ -268,7 +251,7 @@ do_lvcreate (const char *logvol, const char *volgroup, int mbytes)
int
do_lvcreate_free (const char *logvol, const char *volgroup, int percent)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
if (percent < 0 || percent > 100) {
@@ -284,12 +267,9 @@ do_lvcreate_free (const char *logvol, const char *volgroup, int percent)
"-l", size, "-n", logvol, volgroup, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
udev_settle ();
return 0;
@@ -309,7 +289,7 @@ ignore_same_size_error (const char *err)
int
do_lvresize (const char *logvol, int mbytes)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
char size[64];
@@ -321,19 +301,17 @@ do_lvresize (const char *logvol, int mbytes)
if (r == -1) {
if (!ignore_same_size_error (err)) {
reply_with_error ("%s", err);
free (err);
return -1;
}
}
free (err);
return 0;
}
int
do_lvresize_free (const char *logvol, int percent)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
if (percent < 0 || percent > 100) {
@@ -349,12 +327,10 @@ do_lvresize_free (const char *logvol, int percent)
if (r == -1) {
if (!ignore_same_size_error (err)) {
reply_with_error ("%s", err);
free (err);
return -1;
}
}
free (err);
return 0;
}
@@ -364,71 +340,66 @@ do_lvresize_free (const char *logvol, int percent)
int
do_lvm_remove_all (void)
{
char **xs;
size_t i;
int r;
char *err;
/* Remove LVs. */
xs = do_lvs ();
if (xs == NULL)
return -1;
for (i = 0; xs[i] != NULL; ++i) {
/* Deactivate the LV first. On Ubuntu, lvremove '-f' option
* does not remove active LVs reliably.
*/
(void) command (NULL, NULL, str_lvm, "lvchange", "-an", xs[i], NULL);
udev_settle ();
r = command (NULL, &err, str_lvm, "lvremove", "-f", xs[i], NULL);
if (r == -1) {
reply_with_error ("lvremove: %s: %s", xs[i], err);
free (err);
free_strings (xs);
{
/* Remove LVs. */
CLEANUP_FREE char *err = NULL;
CLEANUP_FREE_STRING_LIST char **xs = do_lvs ();
if (xs == NULL)
return -1;
for (i = 0; xs[i] != NULL; ++i) {
/* Deactivate the LV first. On Ubuntu, lvremove '-f' option
* does not remove active LVs reliably.
*/
(void) command (NULL, NULL, str_lvm, "lvchange", "-an", xs[i], NULL);
udev_settle ();
r = command (NULL, &err, str_lvm, "lvremove", "-f", xs[i], NULL);
if (r == -1) {
reply_with_error ("lvremove: %s: %s", xs[i], err);
return -1;
}
}
free (err);
}
free_strings (xs);
/* Remove VGs. */
xs = do_vgs ();
if (xs == NULL)
return -1;
for (i = 0; xs[i] != NULL; ++i) {
/* Deactivate the VG first, see note above. */
(void) command (NULL, NULL, str_lvm, "vgchange", "-an", xs[i], NULL);
udev_settle ();
r = command (NULL, &err, str_lvm, "vgremove", "-f", xs[i], NULL);
if (r == -1) {
reply_with_error ("vgremove: %s: %s", xs[i], err);
free (err);
free_strings (xs);
{
/* Remove VGs. */
CLEANUP_FREE char *err = NULL;
CLEANUP_FREE_STRING_LIST char **xs = do_vgs ();
if (xs == NULL)
return -1;
}
free (err);
}
free_strings (xs);
for (i = 0; xs[i] != NULL; ++i) {
/* Deactivate the VG first, see note above. */
(void) command (NULL, NULL, str_lvm, "vgchange", "-an", xs[i], NULL);
udev_settle ();
r = command (NULL, &err, str_lvm, "vgremove", "-f", xs[i], NULL);
if (r == -1) {
reply_with_error ("vgremove: %s: %s", xs[i], err);
return -1;
}
}
}
{
/* Remove PVs. */
xs = do_pvs ();
if (xs == NULL)
return -1;
for (i = 0; xs[i] != NULL; ++i) {
r = command (NULL, &err, str_lvm, "pvremove", "-f", xs[i], NULL);
if (r == -1) {
reply_with_error ("pvremove: %s: %s", xs[i], err);
free (err);
free_strings (xs);
CLEANUP_FREE char *err = NULL;
CLEANUP_FREE_STRING_LIST char **xs = do_pvs ();
if (xs == NULL)
return -1;
for (i = 0; xs[i] != NULL; ++i) {
r = command (NULL, &err, str_lvm, "pvremove", "-f", xs[i], NULL);
if (r == -1) {
reply_with_error ("pvremove: %s: %s", xs[i], err);
return -1;
}
}
free (err);
}
free_strings (xs);
udev_settle ();
@@ -439,19 +410,16 @@ do_lvm_remove_all (void)
int
do_lvremove (const char *device)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
r = command (NULL, &err,
str_lvm, "lvremove", "-f", device, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
udev_settle ();
return 0;
@@ -460,19 +428,16 @@ do_lvremove (const char *device)
int
do_vgremove (const char *device)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
r = command (NULL, &err,
str_lvm, "vgremove", "-f", device, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
udev_settle ();
return 0;
@@ -481,19 +446,16 @@ do_vgremove (const char *device)
int
do_pvremove (const char *device)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
r = command (NULL, &err,
str_lvm, "pvremove", "-ff", device, NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
udev_settle ();
return 0;
@@ -502,25 +464,23 @@ do_pvremove (const char *device)
int
do_pvresize (const char *device)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
r = command (NULL, &err,
str_lvm, "pvresize", device, NULL);
if (r == -1) {
reply_with_error ("%s: %s", device, err);
free (err);
return -1;
}
free (err);
return 0;
}
int
do_pvresize_size (const char *device, int64_t size)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
char buf[32];
@@ -532,20 +492,18 @@ do_pvresize_size (const char *device, int64_t size)
device, NULL);
if (r == -1) {
reply_with_error ("%s: %s", device, err);
free (err);
return -1;
}
free (err);
return 0;
}
int
do_vg_activate (int activate, char *const *volgroups)
{
char *err;
int r, i, argc;
const char **argv;
CLEANUP_FREE char *err = NULL;
CLEANUP_FREE const char **argv = NULL;
argc = count_strings (volgroups) + 4;
argv = malloc (sizeof (char *) * (argc+1));
@@ -564,14 +522,9 @@ do_vg_activate (int activate, char *const *volgroups)
r = commandv (NULL, &err, (const char * const*) argv);
if (r == -1) {
reply_with_error ("vgchange: %s", err);
free (err);
free (argv);
return -1;
}
free (err);
free (argv);
udev_settle ();
return 0;
@@ -587,7 +540,7 @@ do_vg_activate_all (int activate)
int
do_lvrename (const char *logvol, const char *newlogvol)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
r = command (NULL, &err,
@@ -595,12 +548,9 @@ do_lvrename (const char *logvol, const char *newlogvol)
logvol, newlogvol, NULL);
if (r == -1) {
reply_with_error ("%s -> %s: %s", logvol, newlogvol, err);
free (err);
return -1;
}
free (err);
udev_settle ();
return 0;
@@ -609,7 +559,7 @@ do_lvrename (const char *logvol, const char *newlogvol)
int
do_vgrename (const char *volgroup, const char *newvolgroup)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
r = command (NULL, &err,
@@ -617,12 +567,9 @@ do_vgrename (const char *volgroup, const char *newvolgroup)
volgroup, newvolgroup, NULL);
if (r == -1) {
reply_with_error ("%s -> %s: %s", volgroup, newvolgroup, err);
free (err);
return -1;
}
free (err);
udev_settle ();
return 0;
@@ -632,7 +579,7 @@ static char *
get_lvm_field (const char *cmd, const char *field, const char *device)
{
char *out;
char *err;
CLEANUP_FREE char *err = NULL;
int r = command (&out, &err,
str_lvm, cmd,
"--unbuffered", "--noheadings", "-o", field,
@@ -640,12 +587,9 @@ get_lvm_field (const char *cmd, const char *field, const char *device)
if (r == -1) {
reply_with_error ("%s: %s", device, err);
free (out);
free (err);
return NULL;
}
free (err);
trim (out);
return out; /* Caller frees. */
}
@@ -671,23 +615,18 @@ do_lvuuid (const char *device)
static char **
get_lvm_fields (const char *cmd, const char *field, const char *device)
{
char *out;
char *err;
CLEANUP_FREE char *out = NULL, *err = NULL;
int r = command (&out, &err,
str_lvm, cmd,
"--unbuffered", "--noheadings", "-o", field,
device, NULL);
if (r == -1) {
reply_with_error ("%s: %s", device, err);
free (out);
free (err);
return NULL;
}
free (err);
char **ret = split_lines (out);
free (out);
if (ret == NULL)
return NULL;
@@ -714,18 +653,16 @@ do_vglvuuids (const char *vgname)
int
do_vgscan (void)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
r = command (NULL, &err,
str_lvm, "vgscan", NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -760,7 +697,7 @@ lv_canonical (const char *device, char **ret)
return -1;
}
char **lvs = do_lvs ();
CLEANUP_FREE_STRING_LIST char **lvs = do_lvs ();
if (lvs == NULL)
return -1;
@@ -769,7 +706,6 @@ lv_canonical (const char *device, char **ret)
r = stat (lvs[i], &stat2);
if (r == -1) {
reply_with_perror ("stat: %s", lvs[i]);
free_strings (lvs);
return -1;
}
if (stat1.st_rdev == stat2.st_rdev) { /* found it */
@@ -777,17 +713,14 @@ lv_canonical (const char *device, char **ret)
*ret = strdup (lvs[i]);
if (*ret == NULL) {
reply_with_perror ("strdup");
free_strings (lvs);
return -1;
}
}
free_strings (lvs);
return 1;
}
}
/* not found */
free_strings (lvs);
return 0;
}
@@ -894,7 +827,7 @@ do_list_dm_devices (void)
char *
do_vgmeta (const char *vg, size_t *size_r)
{
char *err;
CLEANUP_FREE char *err = NULL;
int fd, r;
char tmp[] = "/tmp/vgmetaXXXXXX";
size_t alloc, size, max;
@@ -913,10 +846,8 @@ do_vgmeta (const char *vg, size_t *size_r)
r = command (NULL, &err, str_lvm, "vgcfgbackup", "-f", tmp, vg, NULL);
if (r == -1) {
reply_with_error ("vgcfgbackup: %s", err);
free (err);
return NULL;
}
free (err);
/* Now read back the temporary file. */
fd = open (tmp, O_RDONLY|O_CLOEXEC);
@@ -981,19 +912,16 @@ do_vgmeta (const char *vg, size_t *size_r)
int
do_pvchange_uuid (const char *device)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
r = command (NULL, &err,
str_lvm, "pvchange", "-u", device, NULL);
if (r == -1) {
reply_with_error ("%s: %s", device, err);
free (err);
return -1;
}
free (err);
udev_settle ();
return 0;
@@ -1002,19 +930,16 @@ do_pvchange_uuid (const char *device)
int
do_pvchange_uuid_all (void)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
r = command (NULL, &err,
str_lvm, "pvchange", "-u", "-a", NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
udev_settle ();
return 0;
@@ -1023,19 +948,16 @@ do_pvchange_uuid_all (void)
int
do_vgchange_uuid (const char *vg)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
r = command (NULL, &err,
str_lvm, "vgchange", "-u", vg, NULL);
if (r == -1) {
reply_with_error ("%s: %s", vg, err);
free (err);
return -1;
}
free (err);
udev_settle ();
return 0;
@@ -1044,19 +966,16 @@ do_vgchange_uuid (const char *vg)
int
do_vgchange_uuid_all (void)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
r = command (NULL, &err,
str_lvm, "vgchange", "-u", NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
udev_settle ();
return 0;

View File

@@ -61,7 +61,7 @@ do_md_create (const char *name, char *const *devices,
char chunk_s[32];
size_t j;
int r;
char *err;
CLEANUP_FREE char *err = NULL;
uint64_t umissingbitmap = (uint64_t) missingbitmap;
/* Check the optional parameters and set defaults where appropriate. */
@@ -161,12 +161,9 @@ do_md_create (const char *name, char *const *devices,
r = commandv (NULL, &err, argv);
if (r == -1) {
reply_with_error ("mdadm: %s: %s", name, err);
free (err);
return -1;
}
free (err);
udev_settle ();
return 0;
@@ -241,8 +238,8 @@ do_md_detail(const char *md)
size_t i;
int r;
char *out = NULL, *err = NULL;
char **lines = NULL;
CLEANUP_FREE char *out = NULL, *err = NULL;
CLEANUP_FREE_STRING_LIST char **lines = NULL;
DECLARE_STRINGSBUF (ret);
@@ -295,20 +292,12 @@ do_md_detail(const char *md)
}
}
free (out);
free (err);
free_strings (lines);
if (end_stringsbuf (&ret) == -1)
return NULL;
return ret.argv;
error:
free (out);
free (err);
if (lines)
free_strings (lines);
if (ret.argv != NULL)
free_stringslen (ret.argv, ret.size);
@@ -319,16 +308,14 @@ int
do_md_stop(const char *md)
{
int r;
char *err = NULL;
CLEANUP_FREE char *err = NULL;
const char *mdadm[] = { str_mdadm, "--stop", md, NULL};
r = commandv(NULL, &err, mdadm);
if (r == -1) {
reply_with_error("%s", err);
free(err);
return -1;
}
free (err);
return 0;
}
@@ -454,8 +441,8 @@ do_md_stat (const char *md)
{
size_t mdlen;
FILE *fp;
char *line = NULL;
size_t len = 0;
CLEANUP_FREE char *line = NULL;
size_t allocsize = 0;
ssize_t n;
guestfs_int_mdstat_list *ret = NULL;
@@ -470,13 +457,12 @@ do_md_stat (const char *md)
}
/* Search for a line which begins with "<md> : ". */
while ((n = getline (&line, &len, fp)) != -1) {
while ((n = getline (&line, &allocsize, fp)) != -1) {
if (STRPREFIX (line, md) &&
line[mdlen] == ' ' && line[mdlen+1] == ':' && line[mdlen+2] == ' ') {
/* Found it. */
ret = parse_md_stat_line (&line[mdlen+3]);
if (!ret) {
free (line);
fclose (fp);
return NULL;
}
@@ -488,8 +474,6 @@ do_md_stat (const char *md)
}
}
free (line);
if (fclose (fp) == EOF) {
reply_with_perror ("fclose: %s", "/proc/mdstat");
xdr_free ((xdrproc_t) xdr_guestfs_int_mdstat_list, (char *) ret);

View File

@@ -1,5 +1,5 @@
/* libguestfs - the guestfsd daemon
* Copyright (C) 2009-2012 Red Hat Inc.
* Copyright (C) 2009-2013 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
@@ -44,7 +44,7 @@ do_mkfs (const char *fstype, const char *device, int blocksize,
char inode_str[32];
char sectorsize_str[32];
int r;
char *err;
CLEANUP_FREE char *err = NULL;
int extfs = 0;
if (STREQ (fstype, "ext2") || STREQ (fstype, "ext3") ||
@@ -184,14 +184,14 @@ do_mkfs (const char *fstype, const char *device, int blocksize,
ADD_ARG (argv, i, device);
ADD_ARG (argv, i, NULL);
wipe_device_before_mkfs (device);
r = commandv (NULL, &err, argv);
if (r == -1) {
reply_with_error ("%s: %s: %s", fstype, device, err);
free (err);
return -1;
}
free (err);
return 0;
}

View File

@@ -36,14 +36,13 @@ optgroup_linuxmodules_available (void)
int
do_modprobe (const char *module)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r = command (NULL, &err, str_modprobe, module, NULL);
if (r == -1) {
reply_with_error ("%s", err);
return -1;
}
free (err);
return r;
}

View File

@@ -50,7 +50,7 @@ is_root_mounted (void)
*/
fp = setmntent ("/proc/mounts", "r");
if (fp == NULL) {
perror ("/proc/mounts");
fprintf (stderr, "setmntent: %s: %m\n", "/proc/mounts");
exit (EXIT_FAILURE);
}
@@ -92,7 +92,7 @@ is_device_mounted (const char *device)
*/
fp = setmntent ("/proc/mounts", "r");
if (fp == NULL) {
perror ("/proc/mounts");
fprintf (stderr, "setmntent: %s: %m\n", "/proc/mounts");
exit (EXIT_FAILURE);
}
@@ -124,11 +124,9 @@ is_device_mounted (const char *device)
int
do_mount_vfs (const char *options, const char *vfstype,
const char *device, const char *mountpoint)
const mountable_t *mountable, const char *mountpoint)
{
int r;
char *mp;
char *error;
CLEANUP_FREE char *mp = NULL;
struct stat statbuf;
ABS_PATH (mountpoint, , return -1);
@@ -142,50 +140,77 @@ do_mount_vfs (const char *options, const char *vfstype,
/* Check the mountpoint exists and is a directory. */
if (stat (mp, &statbuf) == -1) {
reply_with_perror ("mount: %s", mountpoint);
free (mp);
return -1;
}
if (!S_ISDIR (statbuf.st_mode)) {
reply_with_perror ("mount: %s: mount point is not a directory", mountpoint);
free (mp);
return -1;
}
return mount_vfs_nochroot (options, vfstype, mountable, mp, mountpoint);
}
int
mount_vfs_nochroot (const char *options, const char *vfstype,
const mountable_t *mountable,
const char *mp, const char *user_mp)
{
CLEANUP_FREE char *options_plus = NULL;
const char *device = mountable->device;
if (mountable->type == MOUNTABLE_BTRFSVOL) {
if (options && strlen (options) > 0) {
if (asprintf (&options_plus, "subvol=%s,%s",
mountable->volume, options) == -1)
{
reply_with_perror ("asprintf");
return -1;
}
}
else {
if (asprintf (&options_plus, "subvol=%s", mountable->volume) == -1) {
reply_with_perror ("asprintf");
return -1;
}
}
}
CLEANUP_FREE char *error = NULL;
int r;
if (vfstype)
r = command (NULL, &error,
str_mount, "-o", options, "-t", vfstype, device, mp, NULL);
str_mount, "-o", options_plus ? options_plus : options,
"-t", vfstype, device, mp, NULL);
else
r = command (NULL, &error,
str_mount, "-o", options, device, mp, NULL);
free (mp);
str_mount, "-o", options_plus ? options_plus : options,
device, mp, NULL);
if (r == -1) {
reply_with_error ("%s on %s (options: '%s'): %s",
device, mountpoint, options, error);
free (error);
device, user_mp, options, error);
return -1;
}
free (error);
return 0;
}
int
do_mount (const char *device, const char *mountpoint)
do_mount (const mountable_t *mountable, const char *mountpoint)
{
return do_mount_vfs ("", NULL, device, mountpoint);
return do_mount_vfs ("", NULL, mountable, mountpoint);
}
int
do_mount_ro (const char *device, const char *mountpoint)
do_mount_ro (const mountable_t *mountable, const char *mountpoint)
{
return do_mount_vfs ("ro", NULL, device, mountpoint);
return do_mount_vfs ("ro", NULL, mountable, mountpoint);
}
int
do_mount_options (const char *options, const char *device,
do_mount_options (const char *options, const mountable_t *mountable,
const char *mountpoint)
{
return do_mount_vfs (options, NULL, device, mountpoint);
return do_mount_vfs (options, NULL, mountable, mountpoint);
}
/* Takes optional arguments, consult optargs_bitmask. */
@@ -194,8 +219,8 @@ do_umount (const char *pathordevice,
int force, int lazyunmount)
{
int r;
char *err;
char *buf;
CLEANUP_FREE char *err = NULL;
CLEANUP_FREE char *buf = NULL;
int is_dev;
const char *argv[MAX_ARGS];
size_t i = 0;
@@ -227,16 +252,12 @@ do_umount (const char *pathordevice,
ADD_ARG (argv, i, NULL);
r = commandv (NULL, &err, argv);
free (buf);
if (r == -1) {
reply_with_error ("%s: %s", pathordevice, err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -255,7 +276,7 @@ mounts_or_mountpoints (int mp)
*/
fp = setmntent ("/proc/mounts", "r");
if (fp == NULL) {
perror ("/proc/mounts");
fprintf (stderr, "setmntent: %s: %m\n", "/proc/mounts");
exit (EXIT_FAILURE);
}
@@ -348,7 +369,7 @@ do_umount_all (void)
FILE *fp;
struct mntent *m;
DECLARE_STRINGSBUF (mounts);
char *err;
CLEANUP_FREE char *err = NULL;
size_t i;
int r;
@@ -357,7 +378,7 @@ do_umount_all (void)
*/
fp = setmntent ("/proc/mounts", "r");
if (fp == NULL) {
perror ("/proc/mounts");
fprintf (stderr, "setmntent: %s: %m\n", "/proc/mounts");
exit (EXIT_FAILURE);
}
@@ -388,11 +409,9 @@ do_umount_all (void)
r = command (NULL, &err, str_umount, mounts.argv[i], NULL);
if (r == -1) {
reply_with_error ("umount: %s: %s", mounts.argv[i], err);
free (err);
free_stringslen (mounts.argv, mounts.size);
return -1;
}
free (err);
}
free_stringslen (mounts.argv, mounts.size);
@@ -408,8 +427,7 @@ int
do_mount_loop (const char *file, const char *mountpoint)
{
int r;
char *buf, *mp;
char *error;
CLEANUP_FREE char *buf = NULL, *mp = NULL, *error = NULL;
/* We have to prefix /sysroot on both the filename and the mountpoint. */
mp = sysroot_path (mountpoint);
@@ -421,20 +439,15 @@ do_mount_loop (const char *file, const char *mountpoint)
buf = sysroot_path (file);
if (!buf) {
reply_with_perror ("malloc");
free (mp);
return -1;
}
r = command (NULL, &error, str_mount, "-o", "loop", buf, mp, NULL);
free (mp);
free (buf);
if (r == -1) {
reply_with_error ("%s on %s: %s", file, mountpoint, error);
free (error);
return -1;
}
free (error);
return 0;
}

64
daemon/mountable.c Normal file
View File

@@ -0,0 +1,64 @@
/* libguestfs - the guestfsd daemon
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "daemon.h"
#include "actions.h"
#include "guestfs_protocol.h"
guestfs_int_internal_mountable *
do_internal_parse_mountable (const mountable_t *mountable)
{
guestfs_int_internal_mountable *ret = calloc (1, sizeof *ret);
if (ret == NULL) {
reply_with_perror ("calloc");
return NULL;
}
ret->im_type = mountable->type;
if (mountable->device)
ret->im_device = strdup (mountable->device);
else
ret->im_device = strdup ("");
if (!ret->im_device) {
reply_with_perror ("strdup");
free (ret);
return NULL;
}
if (mountable->volume)
ret->im_volume = strdup (mountable->volume);
else
ret->im_volume = strdup ("");
if (!ret->im_volume) {
reply_with_perror ("strdup");
free (ret->im_device);
free (ret);
return NULL;
}
return ret;
}

View File

@@ -1,5 +1,5 @@
/* libguestfs - the guestfsd daemon
* Copyright (C) 2009-2012 Red Hat Inc.
* Copyright (C) 2009-2013 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
@@ -49,7 +49,7 @@ optgroup_ntfsprogs_available (void)
int
do_ntfs_3g_probe (int rw, const char *device)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
const char *rw_flag;
@@ -58,11 +58,9 @@ do_ntfs_3g_probe (int rw, const char *device)
r = commandr (NULL, &err, str_ntfs3g_probe, rw_flag, device, NULL);
if (r == -1) {
reply_with_error ("%s: %s", device, err);
free (err);
return -1;
}
free (err);
return r;
}
@@ -70,7 +68,7 @@ do_ntfs_3g_probe (int rw, const char *device)
int
do_ntfsresize (const char *device, int64_t size, int force)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
const char *argv[MAX_ARGS];
size_t i = 0;
@@ -99,11 +97,9 @@ do_ntfsresize (const char *device, int64_t size, int force)
r = commandv (NULL, &err, argv);
if (r == -1) {
reply_with_error ("%s: %s", device, err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -121,7 +117,7 @@ do_ntfsfix (const char *device, int clearbadsectors)
const char *argv[MAX_ARGS];
size_t i = 0;
int r;
char *err;
CLEANUP_FREE char *err = NULL;
ADD_ARG (argv, i, str_ntfsfix);
@@ -135,10 +131,8 @@ do_ntfsfix (const char *device, int clearbadsectors)
r = commandv (NULL, &err, argv);
if (r == -1) {
reply_with_error ("%s: %s", device, err);
free (err);
return -1;
}
free (err);
return 0;
}

View File

@@ -1,5 +1,5 @@
/* libguestfs - the guestfsd daemon
* Copyright (C) 2009-2012 Red Hat Inc.
* Copyright (C) 2009-2013 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
@@ -69,7 +69,7 @@ do_ntfsclone_in (const char *device)
{
int err, r;
FILE *fp;
char *cmd;
CLEANUP_FREE char *cmd = NULL;
char error_file[] = "/tmp/ntfscloneXXXXXX";
int fd;
@@ -102,10 +102,8 @@ do_ntfsclone_in (const char *device)
errno = err;
reply_with_perror ("%s", cmd);
unlink (error_file);
free (cmd);
return -1;
}
free (cmd);
/* The semantics of fwrite are too undefined, so write to the
* file descriptor directly instead.
@@ -115,9 +113,8 @@ do_ntfsclone_in (const char *device)
r = receive_file (write_cb, &fd);
if (r == -1) { /* write error */
cancel_receive ();
char *errstr = read_error_file (error_file);
CLEANUP_FREE char *errstr = read_error_file (error_file);
reply_with_error ("write error on device: %s: %s", device, errstr);
free (errstr);
unlink (error_file);
pclose (fp);
return -1;
@@ -133,10 +130,9 @@ do_ntfsclone_in (const char *device)
}
if (pclose (fp) != 0) {
char *errstr = read_error_file (error_file);
CLEANUP_FREE char *errstr = read_error_file (error_file);
reply_with_error ("ntfsclone subcommand failed on device: %s: %s",
device, errstr);
free (errstr);
unlink (error_file);
return -1;
}
@@ -155,7 +151,7 @@ do_ntfsclone_out (const char *device,
{
int r;
FILE *fp;
char *cmd;
CLEANUP_FREE char *cmd = NULL;
char buf[GUESTFS_MAX_CHUNK_SIZE];
/* Construct the ntfsclone command. */
@@ -177,10 +173,8 @@ do_ntfsclone_out (const char *device,
fp = popen (cmd, "r");
if (fp == NULL) {
reply_with_perror ("%s", cmd);
free (cmd);
return -1;
}
free (cmd);
/* Now we must send the reply message, before the file contents. After
* this there is no opportunity in the protocol to send any error
@@ -196,14 +190,14 @@ do_ntfsclone_out (const char *device,
}
if (ferror (fp)) {
perror (device);
fprintf (stderr, "fread: %s: %m\n", device);
send_file_end (1); /* Cancel. */
pclose (fp);
return -1;
}
if (pclose (fp) != 0) {
perror (device);
fprintf (stderr, "pclose: %s: %m\n", device);
send_file_end (1); /* Cancel. */
return -1;
}

View File

@@ -1,5 +1,5 @@
/* libguestfs - the guestfsd daemon
* Copyright (C) 2009-2012 Red Hat Inc.
* Copyright (C) 2009-2013 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
@@ -27,9 +27,11 @@
#include "daemon.h"
#include "actions.h"
#include "optgroups.h"
GUESTFSD_EXT_CMD(str_parted, parted);
GUESTFSD_EXT_CMD(str_sfdisk, sfdisk);
GUESTFSD_EXT_CMD(str_sgdisk, sgdisk);
/* Notes:
*
@@ -74,7 +76,7 @@ int
do_part_init (const char *device, const char *parttype)
{
int r;
char *err;
CLEANUP_FREE char *err = NULL;
parttype = check_parttype (parttype);
if (!parttype) {
@@ -88,10 +90,8 @@ do_part_init (const char *device, const char *parttype)
str_parted, "-s", "--", device, "mklabel", parttype, NULL);
if (r == -1) {
reply_with_error ("parted: %s: %s", device, err);
free (err);
return -1;
}
free (err);
udev_settle ();
@@ -103,7 +103,7 @@ do_part_add (const char *device, const char *prlogex,
int64_t startsect, int64_t endsect)
{
int r;
char *err;
CLEANUP_FREE char *err = NULL;
char startstr[32];
char endstr[32];
@@ -144,10 +144,8 @@ do_part_add (const char *device, const char *prlogex,
device, "mkpart", prlogex, startstr, endstr, NULL);
if (r == -1) {
reply_with_error ("parted: %s: %s", device, err);
free (err);
return -1;
}
free (err);
udev_settle ();
@@ -158,7 +156,7 @@ int
do_part_del (const char *device, int partnum)
{
int r;
char *err;
CLEANUP_FREE char *err = NULL;
if (partnum <= 0) {
reply_with_error ("partition number must be >= 1");
@@ -174,10 +172,8 @@ do_part_del (const char *device, int partnum)
str_parted, "-s", "--", device, "rm", partnum_str, NULL);
if (r == -1) {
reply_with_error ("parted: %s: %s", device, err);
free (err);
return -1;
}
free (err);
udev_settle ();
@@ -188,7 +184,7 @@ int
do_part_disk (const char *device, const char *parttype)
{
int r;
char *err;
CLEANUP_FREE char *err = NULL;
parttype = check_parttype (parttype);
if (!parttype) {
@@ -220,10 +216,8 @@ do_part_disk (const char *device, const char *parttype)
startstr, endstr, NULL);
if (r == -1) {
reply_with_error ("parted: %s: %s", device, err);
free (err);
return -1;
}
free (err);
udev_settle ();
@@ -234,7 +228,7 @@ int
do_part_set_bootable (const char *device, int partnum, int bootable)
{
int r;
char *err;
CLEANUP_FREE char *err = NULL;
if (partnum <= 0) {
reply_with_error ("partition number must be >= 1");
@@ -252,10 +246,8 @@ do_part_set_bootable (const char *device, int partnum, int bootable)
device, "set", partstr, "boot", bootable ? "on" : "off", NULL);
if (r == -1) {
reply_with_error ("parted: %s: %s", device, err);
free (err);
return -1;
}
free (err);
udev_settle ();
@@ -266,7 +258,7 @@ int
do_part_set_name (const char *device, int partnum, const char *name)
{
int r;
char *err;
CLEANUP_FREE char *err = NULL;
if (partnum <= 0) {
reply_with_error ("partition number must be >= 1");
@@ -283,10 +275,8 @@ do_part_set_name (const char *device, int partnum, const char *name)
str_parted, "-s", "--", device, "name", partstr, name, NULL);
if (r == -1) {
reply_with_error ("parted: %s: %s", device, err);
free (err);
return -1;
}
free (err);
udev_settle ();
@@ -335,12 +325,11 @@ test_parted_m_opt (void)
if (result >= 0)
return result;
char *err = NULL;
CLEANUP_FREE char *err = NULL;
int r = commandr (NULL, &err, str_parted, "-s", "-m", "/dev/null", NULL);
if (r == -1) {
/* Test failed, eg. missing or completely unusable parted binary. */
reply_with_error ("could not run 'parted' command");
free (err);
return -1;
}
@@ -348,14 +337,14 @@ test_parted_m_opt (void)
result = 0;
else
result = 1;
free (err);
return result;
}
static char *
print_partition_table (const char *device, int parted_has_m_opt)
{
char *out, *err;
char *out;
CLEANUP_FREE char *err = NULL;
int r;
if (parted_has_m_opt)
@@ -371,10 +360,8 @@ print_partition_table (const char *device, int parted_has_m_opt)
/* Hack for parted 1.x which sends errors to stdout. */
*err ? err : out);
free (out);
free (err);
return NULL;
}
free (err);
return out;
}
@@ -386,7 +373,7 @@ do_part_get_parttype (const char *device)
if (parted_has_m_opt == -1)
return NULL;
char *out = print_partition_table (device, parted_has_m_opt);
CLEANUP_FREE char *out = print_partition_table (device, parted_has_m_opt);
if (!out)
return NULL;
@@ -394,8 +381,7 @@ do_part_get_parttype (const char *device)
/* New-style parsing using the "machine-readable" format from
* 'parted -m'.
*/
char **lines = split_lines (out);
free (out);
CLEANUP_FREE_STRING_LIST char **lines = split_lines (out);
if (!lines)
return NULL;
@@ -403,13 +389,11 @@ do_part_get_parttype (const char *device)
if (lines[0] == NULL || STRNEQ (lines[0], "BYT;")) {
reply_with_error ("unknown signature, expected \"BYT;\" as first line of the output: %s",
lines[0] ? lines[0] : "(signature was null)");
free_strings (lines);
return NULL;
}
if (lines[1] == NULL) {
reply_with_error ("parted didn't return a line describing the device");
free_strings (lines);
return NULL;
}
@@ -418,12 +402,9 @@ do_part_get_parttype (const char *device)
*/
char *r = get_table_field (lines[1], 5);
if (r == NULL) {
free_strings (lines);
return NULL;
}
free_strings (lines);
/* If "loop" return an error (RHBZ#634246). */
if (STREQ (r, "loop")) {
free (r);
@@ -438,7 +419,6 @@ do_part_get_parttype (const char *device)
char *p = strstr (out, "\nPartition Table: ");
if (!p) {
reply_with_error ("parted didn't return Partition Table line");
free (out);
return NULL;
}
@@ -446,14 +426,12 @@ do_part_get_parttype (const char *device)
char *q = strchr (p, '\n');
if (!q) {
reply_with_error ("parted Partition Table has no end of line char");
free (out);
return NULL;
}
*q = '\0';
p = strdup (p);
free (out);
if (!p) {
reply_with_perror ("strdup");
return NULL;
@@ -477,12 +455,11 @@ do_part_list (const char *device)
if (parted_has_m_opt == -1)
return NULL;
char *out = print_partition_table (device, parted_has_m_opt);
CLEANUP_FREE char *out = print_partition_table (device, parted_has_m_opt);
if (!out)
return NULL;
char **lines = split_lines (out);
free (out);
CLEANUP_FREE_STRING_LIST char **lines = split_lines (out);
if (!lines)
return NULL;
@@ -503,7 +480,7 @@ do_part_list (const char *device)
r = malloc (sizeof *r);
if (r == NULL) {
reply_with_perror ("malloc");
goto error1;
return NULL;
}
r->guestfs_int_partition_list_len = nr_rows;
r->guestfs_int_partition_list_val =
@@ -540,7 +517,7 @@ do_part_list (const char *device)
if (start == 0) {
reply_with_error ("parted output has no \"Number\" line");
goto error1;
return NULL;
}
for (row = start; lines[row] != NULL; ++row)
@@ -551,7 +528,7 @@ do_part_list (const char *device)
if (end == 0) {
reply_with_error ("parted output has no blank after end of table");
goto error1;
return NULL;
}
size_t nr_rows = end - start;
@@ -559,7 +536,7 @@ do_part_list (const char *device)
r = malloc (sizeof *r);
if (r == NULL) {
reply_with_perror ("malloc");
goto error1;
return NULL;
}
r->guestfs_int_partition_list_len = nr_rows;
r->guestfs_int_partition_list_val =
@@ -583,15 +560,12 @@ do_part_list (const char *device)
}
}
free_strings (lines);
return r;
error3:
free (r->guestfs_int_partition_list_val);
error2:
free (r);
error1:
free_strings (lines);
return NULL;
}
@@ -607,12 +581,11 @@ do_part_get_bootable (const char *device, int partnum)
if (parted_has_m_opt == -1)
return -1;
char *out = print_partition_table (device, parted_has_m_opt);
CLEANUP_FREE char *out = print_partition_table (device, parted_has_m_opt);
if (!out)
return -1;
char **lines = split_lines (out);
free (out);
CLEANUP_FREE_STRING_LIST char **lines = split_lines (out);
if (!lines)
return -1;
@@ -627,13 +600,11 @@ do_part_get_bootable (const char *device, int partnum)
if (lines[0] == NULL || STRNEQ (lines[0], "BYT;")) {
reply_with_error ("unknown signature, expected \"BYT;\" as first line of the output: %s",
lines[0] ? lines[0] : "(signature was null)");
free_strings (lines);
return -1;
}
if (lines[1] == NULL) {
reply_with_error ("parted didn't return a line describing the device");
free_strings (lines);
return -1;
}
@@ -642,7 +613,6 @@ do_part_get_bootable (const char *device, int partnum)
for (row = 2; lines[row] != NULL; ++row) {
if (sscanf (lines[row], "%d:", &pnum) != 1) {
reply_with_error ("could not parse row from output of parted print command: %s", lines[row]);
free_strings (lines);
return -1;
}
if (pnum == partnum)
@@ -651,22 +621,14 @@ do_part_get_bootable (const char *device, int partnum)
if (lines[row] == NULL) {
reply_with_error ("partition number %d not found", partnum);
free_strings (lines);
return -1;
}
char *boot = get_table_field (lines[row], 6);
if (boot == NULL) {
free_strings (lines);
CLEANUP_FREE char *boot = get_table_field (lines[row], 6);
if (boot == NULL)
return -1;
}
int r = STREQ (boot, "boot");
free (boot);
free_strings (lines);
return r;
return STREQ (boot, "boot");
}
else {
/* Old-style: First look for the line matching "^Number". */
@@ -681,7 +643,6 @@ do_part_get_bootable (const char *device, int partnum)
if (start == 0) {
reply_with_error ("parted output has no \"Number\" line");
free_strings (lines);
return -1;
}
@@ -694,7 +655,6 @@ do_part_get_bootable (const char *device, int partnum)
char *p = strstr (lines[header], "Flags");
if (!p) {
reply_with_error ("parted output has no \"Flags\" field");
free_strings (lines);
return -1;
}
size_t col = p - lines[header];
@@ -706,7 +666,6 @@ do_part_get_bootable (const char *device, int partnum)
for (row = start; lines[row] != NULL; ++row) {
if (sscanf (lines[row], " %d", &pnum) != 1) {
reply_with_error ("could not parse row from output of parted print command: %s", lines[row]);
free_strings (lines);
return -1;
}
if (pnum == partnum)
@@ -715,13 +674,10 @@ do_part_get_bootable (const char *device, int partnum)
if (lines[row] == NULL) {
reply_with_error ("partition number %d not found", partnum);
free_strings (lines);
return -1;
}
int r = STRPREFIX (&lines[row][col], "boot");
free_strings (lines);
return r;
return STRPREFIX (&lines[row][col], "boot");
}
}
@@ -742,7 +698,7 @@ do_part_get_mbr_id (const char *device, int partnum)
char partnum_str[16];
snprintf (partnum_str, sizeof partnum_str, "%d", partnum);
char *out, *err;
CLEANUP_FREE char *out = NULL, *err = NULL;
int r;
udev_settle ();
@@ -750,11 +706,8 @@ do_part_get_mbr_id (const char *device, int partnum)
r = command (&out, &err, str_sfdisk, "--print-id", device, partnum_str, NULL);
if (r == -1) {
reply_with_error ("sfdisk --print-id: %s", err);
free (out);
free (err);
return -1;
}
free (err);
udev_settle ();
@@ -762,11 +715,9 @@ do_part_get_mbr_id (const char *device, int partnum)
int id;
if (sscanf (out, "%x", &id) != 1) {
reply_with_error ("sfdisk --print-id: cannot parse output: %s", out);
free (out);
return -1;
}
free (out);
return id;
}
@@ -784,7 +735,7 @@ do_part_set_mbr_id (const char *device, int partnum, int idbyte)
char idbyte_str[16];
snprintf (idbyte_str, sizeof partnum_str, "%x", idbyte); /* NB: hex */
char *err;
CLEANUP_FREE char *err = NULL;
int r;
udev_settle ();
@@ -793,12 +744,130 @@ do_part_set_mbr_id (const char *device, int partnum, int idbyte)
"--change-id", device, partnum_str, idbyte_str, NULL);
if (r == -1) {
reply_with_error ("sfdisk --change-id: %s", err);
free (err);
return -1;
}
free (err);
udev_settle ();
return 0;
}
int
optgroup_gdisk_available (void)
{
return prog_exists (str_sgdisk);
}
int
do_part_set_gpt_type(const char *device, int partnum, const char *guid)
{
if (partnum <= 0) {
reply_with_error ("partition number must be >= 1");
return -1;
}
CLEANUP_FREE char *typecode = NULL;
if (asprintf (&typecode, "%i:%s", partnum, guid) == -1) {
reply_with_perror ("asprintf");
return -1;
}
CLEANUP_FREE char *err = NULL;
int r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
str_sgdisk, device, "-t", typecode, NULL);
if (r == -1) {
reply_with_error ("%s %s -t %s: %s", str_sgdisk, device, typecode, err);
return -1;
}
return 0;
}
char *
do_part_get_gpt_type(const char *device, int partnum)
{
if (partnum <= 0) {
reply_with_error ("partition number must be >= 1");
return NULL;
}
CLEANUP_FREE char *partnum_str = NULL;
if (asprintf (&partnum_str, "%i", partnum) == -1) {
reply_with_perror ("asprintf");
return NULL;
}
CLEANUP_FREE char *err = NULL;
int r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
str_sgdisk, device, "-i", partnum_str, NULL);
if (r == -1) {
reply_with_error ("%s %s -i %s: %s", str_sgdisk, device, partnum_str, err);
return NULL;
}
char **lines = split_lines (err);
if (lines == NULL) {
reply_with_error ("'%s %s -i %i' returned no output",
str_sgdisk, device, partnum);
return NULL;
}
/* Parse the output of sgdisk -i:
* Partition GUID code: 21686148-6449-6E6F-744E-656564454649 (BIOS boot partition)
* Partition unique GUID: 19AEC5FE-D63A-4A15-9D37-6FCBFB873DC0
* First sector: 2048 (at 1024.0 KiB)
* Last sector: 411647 (at 201.0 MiB)
* Partition size: 409600 sectors (200.0 MiB)
* Attribute flags: 0000000000000000
* Partition name: 'EFI System Partition'
*/
for (char **i = lines; *i != NULL; i++) {
char *line = *i;
/* Skip blank lines */
if (line[0] == '\0') continue;
/* Split the line in 2 at the colon */
char *colon = strchr (line, ':');
if (colon) {
#define SEARCH "Partition GUID code"
if (colon - line == strlen(SEARCH) &&
memcmp (line, SEARCH, strlen(SEARCH)) == 0)
{
#undef SEARCH
/* The value starts after the colon */
char *value = colon + 1;
/* Skip any leading whitespace */
value += strspn (value, " \t");
/* The value contains only valid GUID characters */
size_t value_len = strspn (value, "-0123456789ABCDEF");
char *ret = malloc (value_len + 1);
if (ret == NULL) {
reply_with_perror ("malloc");
return NULL;
}
memcpy (ret, value, value_len);
ret[value_len] = '\0';
return ret;
}
} else {
/* Ignore lines with no colon. Log to stderr so it will show up in
* LIBGUESTFS_DEBUG. */
if (verbose) {
fprintf (stderr, "get-gpt-type: unexpected sgdisk output ignored: %s\n",
line);
}
}
}
/* If we got here it means we didn't find the Partition GUID code */
reply_with_error ("sgdisk output did not contain Partition GUID code. "
"See LIBGUESTFS_DEBUG output for more details");
return NULL;
}

View File

@@ -1,5 +1,5 @@
/* libguestfs - the guestfsd daemon
* Copyright (C) 2009-2012 Red Hat Inc.
* Copyright (C) 2009-2013 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
@@ -363,12 +363,13 @@ receive_file (receive_cb cb, void *opaque)
{
guestfs_chunk chunk;
char lenbuf[4];
char *buf;
XDR xdr;
int r;
uint32_t len;
for (;;) {
CLEANUP_FREE char *buf = NULL;
if (verbose)
fprintf (stderr, "guestfsd: receive_file: reading length word\n");
@@ -402,11 +403,9 @@ receive_file (receive_cb cb, void *opaque)
memset (&chunk, 0, sizeof chunk);
if (!xdr_guestfs_chunk (&xdr, &chunk)) {
xdr_destroy (&xdr);
free (buf);
return -1;
}
xdr_destroy (&xdr);
free (buf);
if (verbose)
fprintf (stderr,
@@ -600,19 +599,22 @@ void
notify_progress (uint64_t position, uint64_t total)
{
struct timeval now_t;
int64_t last_us, now_us, elapsed_us;
gettimeofday (&now_t, NULL);
/* Always send a notification at 100%. This simplifies callers by
* allowing them to 'finish' the progress bar at 100% without
* needing special code.
*/
if (count_progress > 0 && position == total)
goto send;
if (count_progress > 0 && position == total) {
notify_progress_no_ratelimit (position, total, &now_t);
return;
}
/* Calculate time in microseconds since the last progress message
* was sent out (or since the start of the call).
*/
int64_t last_us, now_us, elapsed_us;
last_us =
(int64_t) last_progress_t.tv_sec * 1000000 + last_progress_t.tv_usec;
now_us = (int64_t) now_t.tv_sec * 1000000 + now_t.tv_usec;
@@ -623,16 +625,24 @@ notify_progress (uint64_t position, uint64_t total)
(count_progress > 0 && elapsed_us < NOTIFICATION_PERIOD))
return;
send:
/* We're going to send a message now ... */
count_progress++;
last_progress_t = now_t;
notify_progress_no_ratelimit (position, total, &now_t);
}
/* Send the header word. */
void
notify_progress_no_ratelimit (uint64_t position, uint64_t total,
const struct timeval *now_t)
{
XDR xdr;
char buf[128];
uint32_t i = GUESTFS_PROGRESS_FLAG;
uint32_t i;
size_t len;
guestfs_progress message;
count_progress++;
last_progress_t = *now_t;
/* Send the header word. */
i = GUESTFS_PROGRESS_FLAG;
xdrmem_create (&xdr, buf, 4, XDR_ENCODE);
xdr_u_int (&xdr, &i);
xdr_destroy (&xdr);
@@ -642,12 +652,10 @@ notify_progress (uint64_t position, uint64_t total)
exit (EXIT_FAILURE);
}
guestfs_progress message = {
.proc = proc_nr,
.serial = serial,
.position = position,
.total = total,
};
message.proc = proc_nr;
message.serial = serial;
message.position = position;
message.total = total;
xdrmem_create (&xdr, buf, sizeof buf, XDR_ENCODE);
if (!xdr_guestfs_progress (&xdr, &message)) {

View File

@@ -1,5 +1,5 @@
/* libguestfs - the guestfsd daemon
* Copyright (C) 2009-2012 Red Hat Inc.
* Copyright (C) 2009-2013 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
@@ -33,11 +33,6 @@
#include "optgroups.h"
#include "actions.h"
/* On Windows, NAME_MAX is not defined. */
#ifndef NAME_MAX
#define NAME_MAX FILENAME_MAX
#endif
#ifdef HAVE_REALPATH
int
@@ -68,17 +63,21 @@ OPTGROUP_REALPATH_NOT_AVAILABLE
#endif /* !HAVE_REALPATH */
static int find_path_element (int fd_cwd, int is_end, char *name, size_t *name_len_ret);
static int find_path_element (int fd_cwd, int is_end, const char *name, char **name_ret);
char *
do_case_sensitive_path (const char *path)
{
char ret[PATH_MAX+1] = "/";
char name[NAME_MAX+1];
size_t next = 1;
size_t next;
int fd_cwd, fd2, err, is_end;
size_t i;
char *retp;
char *ret;
ret = strdup ("/");
if (ret == NULL) {
reply_with_perror ("strdup");
return NULL;
}
next = 1; /* next position in 'ret' buffer */
/* 'fd_cwd' here is a surrogate for the current working directory, so
* that we don't have to actually call chdir(2).
@@ -86,13 +85,17 @@ do_case_sensitive_path (const char *path)
fd_cwd = open (sysroot, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
if (fd_cwd == -1) {
reply_with_perror ("%s", sysroot);
return NULL;
goto error;
}
/* First character is a '/'. Take each subsequent path element
* and follow it.
*/
while (*path) {
char *t;
size_t i, len;
CLEANUP_FREE char *name_in = NULL, *name_out = NULL;
i = strcspn (path, "/");
if (i == 0) {
path++;
@@ -104,14 +107,13 @@ do_case_sensitive_path (const char *path)
reply_with_error ("path contained . or .. elements");
goto error;
}
if (i > NAME_MAX) {
reply_with_error ("path element too long");
name_in = strndup (path, i);
if (name_in == NULL) {
reply_with_perror ("strdup");
goto error;
}
memcpy (name, path, i);
name[i] = '\0';
/* Skip to next element in path (for the next loop iteration). */
path += i;
is_end = *path == 0;
@@ -120,23 +122,26 @@ do_case_sensitive_path (const char *path)
* this element of the path. This replaces 'name' with the
* correct case version.
*/
if (find_path_element (fd_cwd, is_end, name, &i) == -1)
if (find_path_element (fd_cwd, is_end, name_in, &name_out) == -1)
goto error;
len = strlen (name_out);
/* Add the real name of this path element to the return value. */
if (next > 1)
ret[next++] = '/';
if (next + i >= PATH_MAX) {
reply_with_error ("final path too long");
t = realloc (ret, next+len+1);
if (t == NULL) {
reply_with_perror ("realloc");
goto error;
}
ret = t;
strcpy (&ret[next], name);
next += i;
strcpy (&ret[next], name_out);
next += len;
/* Is it a directory? Try going into it. */
fd2 = openat (fd_cwd, name, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
fd2 = openat (fd_cwd, name_out, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
err = errno;
close (fd_cwd);
fd_cwd = fd2;
@@ -146,7 +151,7 @@ do_case_sensitive_path (const char *path)
if (is_end && (errno == ENOTDIR || errno == ENOENT))
break;
reply_with_perror ("openat: %s", name);
reply_with_perror ("openat: %s", name_out);
goto error;
}
}
@@ -154,34 +159,28 @@ do_case_sensitive_path (const char *path)
if (fd_cwd >= 0)
close (fd_cwd);
ret[next] = '\0';
retp = strdup (ret);
if (retp == NULL) {
reply_with_perror ("strdup");
return NULL;
}
return retp; /* caller frees */
return ret; /* caller frees */
error:
if (fd_cwd >= 0)
close (fd_cwd);
free (ret);
return NULL;
}
/* 'fd_cwd' is a file descriptor pointing to an open directory.
* 'name' is a buffer of NAME_MAX+1 characters in size which initially
* contains the path element to search for. 'is_end' is a flag
* 'name' is the path element to search for. 'is_end' is a flag
* indicating if this is the last path element.
*
* We search the directory looking for a path element that case
* insensitively matches 'name' and update the 'name' buffer.
* insensitively matches 'name', returning the actual name in '*name_ret'.
*
* If this is successful, return 0. If it fails, reply with an error
* and return -1.
*/
static int
find_path_element (int fd_cwd, int is_end, char *name, size_t *name_len_ret)
find_path_element (int fd_cwd, int is_end, const char *name, char **name_ret)
{
int fd2;
DIR *dir;
@@ -219,6 +218,11 @@ find_path_element (int fd_cwd, int is_end, char *name, size_t *name_len_ret)
* create a new file or directory (RHBZ#840115).
*/
closedir (dir);
*name_ret = strdup (name);
if (*name_ret == NULL) {
reply_with_perror ("strdup");
return -1;
}
return 0;
}
@@ -228,17 +232,13 @@ find_path_element (int fd_cwd, int is_end, char *name, size_t *name_len_ret)
return -1;
}
*name_len_ret = strlen (d->d_name);
if (*name_len_ret > NAME_MAX) {
/* Should never happen? */
reply_with_error ("path element longer than NAME_MAX");
*name_ret = strdup (d->d_name);
if (*name_ret == NULL) {
reply_with_perror ("strdup");
closedir (dir);
return -1;
}
/* Safe because name is a buffer of NAME_MAX+1 characters. */
strcpy (name, d->d_name);
/* NB: closedir frees the structure associated with 'd', so we must
* do this last.
*/

View File

@@ -1,5 +1,5 @@
/* virt-alignment-scan
* Copyright (C) 2012 Red Hat Inc.
/* libguestfs - the guestfsd daemon
* Copyright (C) 2013 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
@@ -16,15 +16,26 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GUESTFS_VIRT_ALIGNMENT_SCAN_H_
#define GUESTFS_VIRT_ALIGNMENT_SCAN_H_
#include <config.h>
/* domains.c */
#if defined(HAVE_LIBVIRT) && defined(HAVE_LIBXML2)
extern void get_domains_from_libvirt (int uuid, size_t *worst_alignment);
#endif
#include <stdio.h>
/* scan.c */
extern void scan (size_t *worst_alignment, const char *prefix);
#include "daemon.h"
#include "actions.h"
#endif /* GUESTFS_VIRT_ALIGNMENT_SCAN_H_ */
int
do_rename (const char *oldpath, const char *newpath)
{
int r;
CHROOT_IN;
r = rename (oldpath, newpath);
CHROOT_OUT;
if (r == -1) {
reply_with_perror ("rename: %s: %s", oldpath, newpath);
return -1;
}
return 0;
}

View File

@@ -46,7 +46,7 @@ rsync (const char *src, const char *src_orig,
const char *argv[MAX_ARGS];
size_t i = 0;
int r;
char *err;
CLEANUP_FREE char *err = NULL;
ADD_ARG (argv, i, str_rsync);
@@ -63,12 +63,9 @@ rsync (const char *src, const char *src_orig,
r = commandv (NULL, &err, argv);
if (r == -1) {
reply_with_error ("'%s' to '%s': %s", src_orig, dest_orig, err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -77,14 +74,13 @@ int
do_rsync (const char *src_orig, const char *dest_orig,
int archive, int deletedest)
{
char *src = NULL, *dest = NULL;
int r = -1;
CLEANUP_FREE char *src = NULL, *dest = NULL;
src = sysroot_path (src_orig);
dest = sysroot_path (dest_orig);
if (!src || !dest) {
reply_with_perror ("malloc");
goto out;
return -1;
}
if (!(optargs_bitmask & GUESTFS_RSYNC_ARCHIVE_BITMASK))
@@ -92,12 +88,7 @@ do_rsync (const char *src_orig, const char *dest_orig,
if (!(optargs_bitmask & GUESTFS_RSYNC_DELETEDEST_BITMASK))
deletedest = 0;
r = rsync (src, src_orig, dest, dest_orig, archive, deletedest);
out:
free (src);
free (dest);
return r;
return rsync (src, src_orig, dest, dest_orig, archive, deletedest);
}
/* Takes optional arguments, consult optargs_bitmask. */
@@ -105,13 +96,12 @@ int
do_rsync_in (const char *remote, const char *dest_orig,
int archive, int deletedest)
{
char *dest = NULL;
int r = -1;
CLEANUP_FREE char *dest = NULL;
dest = sysroot_path (dest_orig);
if (!dest) {
reply_with_perror ("malloc");
goto out;
return -1;
}
if (!(optargs_bitmask & GUESTFS_RSYNC_IN_ARCHIVE_BITMASK))
@@ -119,11 +109,7 @@ do_rsync_in (const char *remote, const char *dest_orig,
if (!(optargs_bitmask & GUESTFS_RSYNC_IN_DELETEDEST_BITMASK))
deletedest = 0;
r = rsync (remote, remote, dest, dest_orig, archive, deletedest);
out:
free (dest);
return r;
return rsync (remote, remote, dest, dest_orig, archive, deletedest);
}
/* Takes optional arguments, consult optargs_bitmask. */
@@ -131,13 +117,12 @@ int
do_rsync_out (const char *src_orig, const char *remote,
int archive, int deletedest)
{
char *src = NULL;
int r = -1;
CLEANUP_FREE char *src = NULL;
src = sysroot_path (src_orig);
if (!src) {
reply_with_perror ("malloc");
goto out;
return -1;
}
if (!(optargs_bitmask & GUESTFS_RSYNC_OUT_ARCHIVE_BITMASK))
@@ -145,9 +130,5 @@ do_rsync_out (const char *src_orig, const char *remote,
if (!(optargs_bitmask & GUESTFS_RSYNC_OUT_DELETEDEST_BITMASK))
deletedest = 0;
r = rsync (src, src_orig, remote, remote, archive, deletedest);
out:
free (src);
return r;
return rsync (src, src_orig, remote, remote, archive, deletedest);
}

View File

@@ -39,26 +39,23 @@ optgroup_scrub_available (void)
int
do_scrub_device (const char *device)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
r = command (NULL, &err, str_scrub, device, NULL);
if (r == -1) {
reply_with_error ("%s: %s", device, err);
free (err);
return -1;
}
free (err);
return 0;
}
int
do_scrub_file (const char *file)
{
char *buf;
char *err;
CLEANUP_FREE char *buf = NULL;
CLEANUP_FREE char *err = NULL;
int r;
/* Make the path relative to /sysroot. */
@@ -69,23 +66,19 @@ do_scrub_file (const char *file)
}
r = command (NULL, &err, str_scrub, "-r", buf, NULL);
free (buf);
if (r == -1) {
reply_with_error ("%s: %s", file, err);
free (err);
return -1;
}
free (err);
return 0;
}
int
do_scrub_freespace (const char *dir)
{
char *buf;
char *err;
CLEANUP_FREE char *buf = NULL;
CLEANUP_FREE char *err = NULL;
int r;
/* Make the path relative to /sysroot. */
@@ -96,14 +89,10 @@ do_scrub_freespace (const char *dir)
}
r = command (NULL, &err, str_scrub, "-X", buf, NULL);
free (buf);
if (r == -1) {
reply_with_error ("%s: %s", dir, err);
free (err);
return -1;
}
free (err);
return 0;
}

View File

@@ -135,19 +135,17 @@ do_sfdiskM (const char *device, char *const *lines)
static char *
sfdisk_flag (const char *device, const char *flag)
{
char *out, *err;
char *out;
CLEANUP_FREE char *err = NULL;
int r;
r = command (&out, &err, str_sfdisk, flag, device, NULL);
if (r == -1) {
reply_with_error ("%s: %s", device, err);
free (out);
free (err);
return NULL;
}
free (err);
udev_settle ();
return out; /* caller frees */

View File

@@ -80,7 +80,7 @@ do_statvfs (const char *path)
#else /* !HAVE_STATVFS */
# if WIN32
char *disk;
CLEANUP_FREE char *disk = NULL;
guestfs_int_statvfs *ret;
ULONGLONG free_bytes_available; /* for user - similar to bavail */
ULONGLONG total_number_of_bytes;
@@ -97,10 +97,8 @@ do_statvfs (const char *path)
(PULARGE_INTEGER) &total_number_of_bytes,
(PULARGE_INTEGER) &total_number_of_free_bytes)) {
reply_with_perror ("GetDiskFreeSpaceEx");
free (disk);
return NULL;
}
free (disk);
ret = malloc (sizeof *ret);
if (ret == NULL) {
@@ -142,7 +140,7 @@ do_statvfs (const char *path)
# else /* !WIN32 */
char *disk;
CLEANUP_FREE char *disk = NULL;
int r;
guestfs_int_statvfs *ret;
struct fs_usage fsu;
@@ -154,7 +152,6 @@ do_statvfs (const char *path)
}
r = get_fs_usage (disk, disk, &fsu);
free (disk);
if (r == -1) {
reply_with_perror ("get_fs_usage: %s", path);

Some files were not shown because too many files have changed in this diff Show More