Compare commits

...

248 Commits

Author SHA1 Message Date
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
392 changed files with 52409 additions and 34896 deletions

27
.gitignore vendored
View File

@@ -96,17 +96,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
@@ -160,8 +160,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
@@ -319,6 +320,7 @@ Makefile.in
/po-docs/po4a.conf
/po-docs/*/*.pod
/po-docs/*/stamp-update-po
/podwrapper.1
/podwrapper.pl
/po/*.gmo
/python/bindtests.py
@@ -344,6 +346,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
@@ -358,16 +361,19 @@ Makefile.in
/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
@@ -398,12 +404,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
@@ -423,6 +431,7 @@ Makefile.in
/tests/data/test.iso
/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/guest-aux/fedora-name.db
@@ -431,9 +440,11 @@ Makefile.in
/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
/test-tool/libguestfs-test-tool
/test-tool/libguestfs-test-tool.1

View File

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

157
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-02-25
This contains a local list of the bugs that are open against
libguestfs. Bugs are tracked in the Red Hat Bugzilla database
@@ -149,9 +149,6 @@ Bugs in NEW or ASSIGNED state are open and waiting for someone to fix.
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
@@ -164,9 +161,6 @@ Bugs in NEW or ASSIGNED state are open and waiting for someone to fix.
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 +170,90 @@ 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
503134 ASSIGNED https://bugzilla.redhat.com/show_bug.cgi?id=503134
guestfish's list splitting does not recognize internal quoting
@@ -194,50 +272,35 @@ 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)
912499 ASSIGNED https://bugzilla.redhat.com/show_bug.cgi?id=912499
Security context on image file gets reset
(85 bugs)
--------------------------------------------------
Bugs in MODIFIED, POST or ON_QA state are fixed.
You can help by testing the fixes.
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
889537 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=889537
Libguestfs live support should be disabled in RHEL 7 packages
889538 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=889538
libguestfs can not be installed with recent iptables
909573 MODIFIED https://bugzilla.redhat.com/show_bug.cgi?id=909573
patch libguestfs to use 'supermin' instead of 'febootstrap' in RHEL 7
(4 bugs)
--------------------------------------------------
These bugs are in the VERIFIED state.
801640 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=801640
[RFE] the error reported by resize2fs-M need to be more clear
865923 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=865923
Check that new qemu -machine option doesn't break libguestfs.
816839 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=816839
data overflow error when debug progress -1
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
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
883338 VERIFIED https://bugzilla.redhat.com/show_bug.cgi?id=883338
Missing #include <locale.h> in fuse/guestmount.c
(13 bugs)
(1 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
@@ -43,6 +43,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
@@ -288,11 +289,22 @@ 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
@@ -346,9 +358,8 @@ 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
@@ -368,25 +379,44 @@ check-with-upstream-libvirt:
$(LIBVIRTDIR)/run $(MAKE) check || exit $$?; \
fi
# 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-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
@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]"

304
README
View File

@@ -41,134 +41,183 @@ 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 attach-method 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.
+--------------+-------------+---+-----------------------------------------+
| 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. |
+--------------+-------------+---+-----------------------------------------+
| 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. |
+==============+=============+===+=========================================+
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,6 +235,10 @@ 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.
make help
lists all 'make' targets.
If everything works, you can install the library and tools by running
this command as root:
@@ -204,8 +257,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 +341,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 +376,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 +395,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

2
TODO
View File

@@ -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

View File

@@ -39,12 +39,15 @@ virt_alignment_scan_SOURCES = \
scan.c \
scan.h
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)/fish \
-I$(srcdir)/../gnulib/lib -I../gnulib/lib \
-DLOCALEBASEDIR=\""$(datadir)/locale"\" \
-DLOCALEBASEDIR=\""$(datadir)/locale"\"
virt_alignment_scan_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
$(GPROF_CFLAGS) $(GCOV_CFLAGS) \
$(LIBCONFIG_CFLAGS) \
@@ -52,9 +55,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.

View File

@@ -30,10 +30,6 @@
#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"
@@ -267,7 +263,7 @@ add_domain (virDomainPtr dom)
domain->uuid = NULL;
domain->disks = NULL;
int n = guestfs___for_each_disk (g, dom, add_disk, domain);
int n = guestfs___for_each_disk (g, dom, add_disk, domain, NULL);
if (n == -1)
exit (EXIT_FAILURE);
domain->nr_disks = n;

View File

@@ -53,12 +53,6 @@ int inspector = 0;
static int quiet = 0; /* --quiet */
static inline char *
bad_cast (char const *s)
{
return (char *) s;
}
static void __attribute__((noreturn))
usage (int status)
{
@@ -130,7 +124,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);
@@ -245,27 +239,26 @@ main (int argc, char *argv[])
void
scan (size_t *worst_alignment, const char *prefix)
{
char **devices, *p;
size_t i, j;
size_t alignment;
uint64_t start;
struct guestfs_partition_list *parts;
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) {
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);
/* Canonicalize the name of the device for printing. */
p = guestfs_canonical_device_name (g, devices[i]);
if (p == NULL)
name = guestfs_canonical_device_name (g, devices[i]);
if (name == NULL)
exit (EXIT_FAILURE);
free (devices[i]);
devices[i] = p;
for (j = 0; j < parts->len; ++j) {
/* Start offset of the partition in bytes. */
@@ -276,7 +269,7 @@ scan (size_t *worst_alignment, const char *prefix)
printf ("%s:", prefix);
printf ("%s%d %12" PRIu64 " ",
devices[i], (int) parts->val[j].part_num, start);
name, (int) parts->val[j].part_num, start);
}
/* What's the alignment? */
@@ -309,9 +302,5 @@ scan (size_t *worst_alignment, const char *prefix)
printf ("ok\n");
}
}
guestfs_free_partition_list (parts);
free (devices[i]);
}
free (devices);
}

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

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

View File

@@ -35,12 +35,14 @@
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
systemd /* for /sbin/reboot and udevd */
@@ -62,7 +64,9 @@
hfsplus
iproute
libaugeas0
libcap2
libhivex0
libpcre3
libyajl2
linux-image
nilfs-tools
@@ -70,6 +74,7 @@
ntfsprogs
openssh-client
reiserfsprogs
sysvinit /* for /sbin/reboot */
ufsutils
vim-tiny
xz-utils
@@ -86,11 +91,13 @@
hivex
iproute2
iputils
libcap
linux
lrzip
nilfs-utils
ntfsprogs
ntfs-3g
pcre
reiserfsprogs
systemd
vim
@@ -111,6 +118,7 @@ dosfstools
file
findutils
gawk
gdisk
grep
gzip
jfsutils

View File

@@ -38,6 +38,8 @@ gnulib_tool=$GNULIB_SRCDIR/gnulib-tool
modules='
accept4
areadlink
areadlinkat
arpa_inet
byteswap
c-ctype

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)
{
@@ -114,6 +109,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 +118,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);
@@ -240,24 +236,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 +275,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)
{
@@ -197,7 +191,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);
@@ -379,9 +373,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 +429,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 +489,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 +531,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 +561,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 +596,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 +609,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 +628,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 +636,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 +665,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 +709,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 +751,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 +773,6 @@ parents_of_md (char *device)
ret[stats->len] = NULL;
guestfs_free_mdstat_list (stats);
return ret;
}
@@ -861,15 +804,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 +843,6 @@ parents_of_vg (char *vg)
ret[i] = NULL;
free_strings (pvuuids);
return ret;
}
@@ -941,7 +881,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 +929,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 +1097,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)
{
@@ -191,7 +183,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);
@@ -408,18 +400,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 +415,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 +428,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 +456,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 +465,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 +506,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 +516,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 +525,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 +578,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 +650,6 @@ show_file (const char *dir, const char *name,
output_end_line ();
free (path);
free (csum);
free (link);
return 0;
}
@@ -966,14 +929,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

@@ -510,4 +510,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 \
@@ -197,14 +189,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

@@ -84,7 +84,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 +92,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;
}

View File

@@ -177,48 +177,37 @@ int
do_copy_device_to_file (const char *src, const char *dest,
int64_t srcoffset, int64_t destoffset, int64_t size)
{
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);
}
int
do_copy_file_to_device (const char *src, const char *dest,
int64_t srcoffset, int64_t destoffset, int64_t size)
{
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);
}
int
do_copy_file_to_file (const char *src, const char *dest,
int64_t srcoffset, int64_t destoffset, int64_t size)
{
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 +218,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);
}

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,7 @@ 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 void deliberately_cause_a_segfault (void);
static struct cmd cmds[] = {
{ "help", debug_help },
@@ -209,13 +211,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 +223,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 +262,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 +276,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 +318,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 +333,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 +346,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 +364,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 +372,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 +387,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 +397,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 +414,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 +424,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 +438,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;
@@ -589,12 +598,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 +616,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 +683,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,17 +491,15 @@ 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);
@@ -520,7 +515,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 +539,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,83 @@ 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)
{
mountable->type = MOUNTABLE_BTRFSVOL;
char *device = desc;
if (strncmp (device, "/dev/", strlen("/dev/")) == -1)
return -1;
char *volume = NULL;
char *slash = device + strlen("/dev/") - 1;
while ((slash = strchr (slash + 1, '/'))) {
*slash = '\0';
struct stat statbuf;
if (stat (device, &statbuf) == -1) {
perror (device);
return -1;
}
if (!S_ISDIR (statbuf.st_mode) &&
!is_root_device_stat(&statbuf) &&
device_name_translation (device) == 0)
{
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 +1325,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.
*/

41
daemon/rename.c Normal file
View File

@@ -0,0 +1,41 @@
/* 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
* 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 "daemon.h"
#include "actions.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);

View File

@@ -31,7 +31,7 @@ char **
do_strings_e (const char *encoding, const char *path)
{
int fd, flags, r;
char *out, *err;
CLEANUP_FREE char *out = NULL, *err = NULL;
char **lines;
if (strlen (encoding) != 1 ||
@@ -53,17 +53,11 @@ do_strings_e (const char *encoding, const char *path)
r = commandf (&out, &err, flags, "strings", "-e", encoding, NULL);
if (r == -1) {
reply_with_error ("%s: %s", path, err);
free (err);
free (out);
return NULL;
}
free (err);
/* Now convert the output to a list of lines. */
lines = split_lines (out);
free (out);
if (lines == NULL)
return NULL;

View File

@@ -44,7 +44,7 @@ GUESTFSD_EXT_CMD(str_swapoff, swapoff);
int
optgroup_linuxfsuuid_available (void)
{
char *err;
CLEANUP_FREE char *err = NULL;
int av;
/* Upstream util-linux have been gradually changing '--help' to go
@@ -56,7 +56,6 @@ optgroup_linuxfsuuid_available (void)
str_mkswap, "--help", NULL));
av = strstr (err, "-U") != NULL;
free (err);
return av;
}
@@ -68,7 +67,7 @@ do_mkswap (const char *device, const char *label, const char *uuid)
const char *argv[MAX_ARGS];
size_t i = 0;
int r;
char *err;
CLEANUP_FREE char *err = NULL;
ADD_ARG (argv, i, str_mkswap);
ADD_ARG (argv, i, "-f");
@@ -92,15 +91,14 @@ do_mkswap (const char *device, const char *label, const char *uuid)
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", device, err);
free (err);
return -1;
}
free (err);
udev_settle ();
return 0;
@@ -123,8 +121,7 @@ do_mkswap_U (const char *uuid, const char *device)
int
do_mkswap_file (const char *path)
{
char *buf;
char *err;
CLEANUP_FREE char *buf = NULL, *err = NULL;
int r;
buf = sysroot_path (path);
@@ -134,23 +131,19 @@ do_mkswap_file (const char *path)
}
r = command (NULL, &err, str_mkswap, "-f", buf, NULL);
free (buf);
if (r == -1) {
reply_with_error ("%s: %s", path, err);
free (err);
return -1;
}
free (err);
return r;
}
static int
swaponoff (const char *cmd, const char *flag, const char *value)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
if (!flag)
@@ -160,12 +153,9 @@ swaponoff (const char *cmd, const char *flag, const char *value)
if (r == -1) {
reply_with_error ("%s: %s", value, err);
free (err);
return -1;
}
free (err);
/* Possible fix for RHBZ#516096. It probably doesn't hurt to do
* this in any case.
*/
@@ -189,8 +179,7 @@ do_swapoff_device (const char *device)
int
do_swapon_file (const char *path)
{
char *buf;
int r;
CLEANUP_FREE char *buf = NULL;
buf = sysroot_path (path);
if (!buf) {
@@ -198,16 +187,13 @@ do_swapon_file (const char *path)
return -1;
}
r = swaponoff (str_swapon, NULL, buf);
free (buf);
return r;
return swaponoff (str_swapon, NULL, buf);
}
int
do_swapoff_file (const char *path)
{
char *buf;
int r;
CLEANUP_FREE char *buf = NULL;
buf = sysroot_path (path);
if (!buf) {
@@ -215,9 +201,7 @@ do_swapoff_file (const char *path)
return -1;
}
r = swaponoff (str_swapoff, NULL, buf);
free (buf);
return r;
return swaponoff (str_swapoff, NULL, buf);
}
int

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
@@ -134,7 +134,7 @@ fsync_devices (void)
/* Close the directory handle */
if (closedir (dir) == -1)
perror ("closedir");
perror ("closedir: /sys/block");
}
#endif /* HAVE_FSYNC */

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
@@ -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 "read-file.h"
@@ -122,7 +125,7 @@ do_tar_in (const char *dir, const char *compress)
const char *filter;
int err, r;
FILE *fp;
char *cmd;
CLEANUP_FREE char *cmd = NULL;
char error_file[] = "/tmp/tarXXXXXX";
int fd, chown_supported;
@@ -180,10 +183,8 @@ do_tar_in (const char *dir, const char *compress)
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.
@@ -193,9 +194,8 @@ do_tar_in (const char *dir, const char *compress)
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 directory: %s: %s", dir, errstr);
free (errstr);
unlink (error_file);
pclose (fp);
return -1;
@@ -211,10 +211,9 @@ do_tar_in (const char *dir, const char *compress)
}
if (pclose (fp) != 0) {
char *errstr = read_error_file (error_file);
CLEANUP_FREE char *errstr = read_error_file (error_file);
reply_with_error ("tar subcommand failed on directory: %s: %s",
dir, errstr);
free (errstr);
unlink (error_file);
return -1;
}
@@ -283,12 +282,14 @@ int
do_tar_out (const char *dir, const char *compress, int numericowner,
char *const *excludes)
{
CLEANUP_FREE char *buf = NULL;
struct stat statbuf;
const char *filter;
int r;
FILE *fp;
char *excludes_args;
char *cmd;
char buf[GUESTFS_MAX_CHUNK_SIZE];
CLEANUP_FREE char *excludes_args = NULL;
CLEANUP_FREE char *cmd = NULL;
char buffer[GUESTFS_MAX_CHUNK_SIZE];
if ((optargs_bitmask & GUESTFS_TAR_OUT_COMPRESS_BITMASK)) {
if (STREQ (compress, "compress"))
@@ -323,17 +324,32 @@ do_tar_out (const char *dir, const char *compress, int numericowner,
}
}
/* Check the filename exists and is a directory (RHBZ#908322). */
buf = sysroot_path (dir);
if (buf == NULL) {
reply_with_perror ("malloc");
return -1;
}
if (stat (buf, &statbuf) == -1) {
reply_with_perror ("stat: %s", dir);
return -1;
}
if (! S_ISDIR (statbuf.st_mode)) {
reply_with_error ("%s: not a directory", dir);
return -1;
}
/* "tar -C /sysroot%s -cf - ." but we have to quote the dir. */
if (asprintf_nowarn (&cmd, "%s -C %R%s%s%s -cf - .",
if (asprintf_nowarn (&cmd, "%s -C %s%s%s%s -cf - .",
str_tar,
dir, filter,
buf, filter,
numericowner ? " --numeric-owner" : "",
excludes_args) == -1) {
reply_with_perror ("asprintf");
free (excludes_args);
return -1;
}
free (excludes_args);
if (verbose)
fprintf (stderr, "%s\n", cmd);
@@ -341,10 +357,8 @@ do_tar_out (const char *dir, const char *compress, int numericowner,
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
@@ -352,22 +366,22 @@ do_tar_out (const char *dir, const char *compress, int numericowner,
*/
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 (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

@@ -1,5 +1,5 @@
/* libguestfs - the guestfsd daemon
* Copyright (C) 2009 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
@@ -129,6 +129,24 @@ do_upload_offset (const char *filename, int64_t offset)
return upload (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_CLOEXEC, offset);
}
/* Extra check to prevent RHBZ#908321. */
static int
check_not_directory (const char *filename, int fd)
{
struct stat statbuf;
if (fstat (fd, &statbuf) == -1) {
reply_with_perror ("fstat: %s", filename);
return -1;
}
if (S_ISDIR (statbuf.st_mode)) {
reply_with_error ("%s: is a directory", filename);
return -1;
}
return 0;
}
/* Has one FileOut parameter. */
int
do_download (const char *filename)
@@ -146,6 +164,11 @@ do_download (const char *filename)
return -1;
}
if (check_not_directory (filename, fd) == -1) {
close (fd);
return -1;
}
/* Calculate the size of the file or device for notification messages. */
uint64_t total, sent = 0;
if (!is_dev) {
@@ -183,14 +206,14 @@ do_download (const char *filename)
}
if (r == -1) {
perror (filename);
fprintf (stderr, "read: %s: %m\n", filename);
send_file_end (1); /* Cancel. */
close (fd);
return -1;
}
if (close (fd) == -1) {
perror (filename);
fprintf (stderr, "close: %s: %m\n", filename);
send_file_end (1); /* Cancel. */
return -1;
}
@@ -229,6 +252,11 @@ do_download_offset (const char *filename, int64_t offset, int64_t size)
return -1;
}
if (check_not_directory (filename, fd) == -1) {
close (fd);
return -1;
}
if (offset) {
if (lseek (fd, offset, SEEK_SET) == -1) {
reply_with_perror ("lseek: %s", filename);
@@ -248,7 +276,7 @@ do_download_offset (const char *filename, int64_t offset, int64_t size)
while (usize > 0) {
r = read (fd, buf, usize > sizeof buf ? sizeof buf : usize);
if (r == -1) {
perror (filename);
fprintf (stderr, "read: %s: %m\n", filename);
send_file_end (1); /* Cancel. */
close (fd);
return -1;
@@ -271,7 +299,7 @@ do_download_offset (const char *filename, int64_t offset, int64_t size)
}
if (close (fd) == -1) {
perror (filename);
fprintf (stderr, "close: %s: %m\n", filename);
send_file_end (1); /* Cancel. */
return -1;
}

View File

@@ -31,7 +31,7 @@
static int
wc (const char *flag, const char *path)
{
char *out, *err;
CLEANUP_FREE char *out = NULL, *err = NULL;
int fd, flags, r;
CHROOT_IN;
@@ -47,13 +47,9 @@ wc (const char *flag, const char *path)
r = commandf (&out, &err, flags, "wc", flag, NULL);
if (r == -1) {
reply_with_error ("wc %s: %s", flag, err);
free (out);
free (err);
return -1;
}
free (err);
#if 0
/* Split it at the first whitespace. */
len = strcspn (out, " \t\n");
@@ -63,11 +59,9 @@ wc (const char *flag, const char *path)
/* Parse the number. */
if (sscanf (out, "%d", &r) != 1) {
reply_with_error ("cannot parse number: %s", out);
free (out);
return -1;
}
free (out);
return r;
}

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
@@ -120,7 +120,7 @@ getxattrs (const char *path,
void *value, size_t size))
{
ssize_t len, vlen;
char *buf = NULL;
CLEANUP_FREE char *buf = NULL;
size_t i, j;
guestfs_int_xattr_list *r = NULL;
@@ -202,12 +202,9 @@ getxattrs (const char *path,
}
}
free (buf);
return r;
error:
free (buf);
if (r) {
if (r->guestfs_int_xattr_list_val) {
size_t k;
@@ -266,23 +263,11 @@ guestfs_int_xattr_list *
do_internal_lxattrlist (const char *path, char *const *names)
{
#if defined(HAVE_LLISTXATTR) && defined(HAVE_LGETXATTR)
/* XXX This would be easier if the kernel had lgetxattrat. In the
* meantime we use this buffer to store the whole path name.
*/
char pathname[PATH_MAX];
size_t path_len = strlen (path);
guestfs_int_xattr_list *ret = NULL;
size_t i, j;
size_t k, m, nr_attrs;
ssize_t len, vlen;
char *buf = NULL;
if (path_len >= PATH_MAX) {
reply_with_perror ("path longer than PATH_MAX");
goto error;
}
strcpy (pathname, path);
CLEANUP_FREE char *buf = NULL;
ret = malloc (sizeof (*ret));
if (ret == NULL) {
@@ -294,22 +279,28 @@ do_internal_lxattrlist (const char *path, char *const *names)
ret->guestfs_int_xattr_list_val = NULL;
for (k = 0; names[k] != NULL; ++k) {
/* Be careful in here about which errors cause the whole call
void *newptr;
CLEANUP_FREE char *pathname;
/* Be careful in this loop about which errors cause the whole call
* to abort, and which errors allow us to continue processing
* the call, recording a special "error attribute" in the
* outgoing struct list.
*/
if (path_len + strlen (names[k]) + 2 > PATH_MAX) {
reply_with_perror ("path and name longer than PATH_MAX");
/* XXX This would be easier if the kernel had lgetxattrat. In the
* meantime we use the 'pathname' buffer to store the whole path
* name.
*/
if (asprintf (&pathname, "%s/%s", path, names[k]) == -1) {
reply_with_perror ("asprintf");
goto error;
}
pathname[path_len] = '/';
strcpy (&pathname[path_len+1], names[k]);
/* Reserve space for the special attribute. */
void *newptr =
realloc (ret->guestfs_int_xattr_list_val,
(ret->guestfs_int_xattr_list_len+1)*sizeof (guestfs_int_xattr));
newptr = realloc (ret->guestfs_int_xattr_list_val,
(ret->guestfs_int_xattr_list_len+1) *
sizeof (guestfs_int_xattr));
if (newptr == NULL) {
reply_with_perror ("realloc");
goto error;
@@ -409,8 +400,6 @@ do_internal_lxattrlist (const char *path, char *const *names)
}
}
free (buf); buf = NULL;
char num[16];
snprintf (num, sizeof num, "%zu", nr_attrs);
entry[0].attrval.attrval_len = strlen (num) + 1;
@@ -425,7 +414,6 @@ do_internal_lxattrlist (const char *path, char *const *names)
return ret;
error:
free (buf);
if (ret) {
if (ret->guestfs_int_xattr_list_val) {
for (k = 0; k < ret->guestfs_int_xattr_list_len; ++k) {

View File

@@ -106,7 +106,7 @@ static guestfs_int_xfsinfo *
parse_xfs_info (char **lines)
{
guestfs_int_xfsinfo *ret;
char *buf = NULL, *p;
char *p;
size_t i;
ret = malloc (sizeof *ret);
@@ -150,149 +150,128 @@ parse_xfs_info (char **lines)
if (ret->xfs_mntpoint == NULL) goto error;
}
if ((p = strstr (lines[i], "isize="))) {
buf = split_strdup (p + 6);
CLEANUP_FREE char *buf = split_strdup (p + 6);
if (buf == NULL) goto error;
if (parse_uint32 (&ret->xfs_inodesize, buf) == -1)
goto error;
free (buf); buf = NULL;
}
if ((p = strstr (lines[i], "agcount="))) {
buf = split_strdup (p + 8);
CLEANUP_FREE char *buf = split_strdup (p + 8);
if (buf == NULL) goto error;
if (parse_uint32 (&ret->xfs_agcount, buf) == -1)
goto error;
free (buf); buf = NULL;
}
if ((p = strstr (lines[i], "agsize="))) {
buf = split_strdup (p + 7);
CLEANUP_FREE char *buf = split_strdup (p + 7);
if (buf == NULL) goto error;
if (parse_uint32 (&ret->xfs_agsize, buf) == -1)
goto error;
free (buf); buf = NULL;
}
if ((p = strstr (lines[i], "sectsz="))) {
buf = split_strdup (p + 7);
CLEANUP_FREE char *buf = split_strdup (p + 7);
if (buf == NULL) goto error;
if (i == 1) {
if (parse_uint32 (&ret->xfs_sectsize, buf) == -1)
goto error;
free (buf); buf = NULL;
} else if (i == 6) {
if (parse_uint32 (&ret->xfs_logsectsize, buf) == -1)
goto error;
free (buf); buf = NULL;
} else goto error;
}
if ((p = strstr (lines[i], "attr="))) {
buf = split_strdup (p + 5);
CLEANUP_FREE char *buf = split_strdup (p + 5);
if (buf == NULL) goto error;
if (parse_uint32 (&ret->xfs_attr, buf) == -1)
goto error;
free (buf); buf = NULL;
}
if ((p = strstr (lines[i], "bsize="))) {
buf = split_strdup (p + 6);
CLEANUP_FREE char *buf = split_strdup (p + 6);
if (buf == NULL) goto error;
if (i == 2) {
if (parse_uint32 (&ret->xfs_blocksize, buf) == -1)
goto error;
free (buf); buf = NULL;
} else if (i == 4) {
if (parse_uint32 (&ret->xfs_dirblocksize, buf) == -1)
goto error;
free (buf); buf = NULL;
} else if (i == 5) {
if (parse_uint32 (&ret->xfs_logblocksize, buf) == -1)
goto error;
free (buf); buf = NULL;
} else goto error;
}
if ((p = strstr (lines[i], "blocks="))) {
buf = split_strdup (p + 7);
CLEANUP_FREE char *buf = split_strdup (p + 7);
if (buf == NULL) goto error;
if (i == 2) {
if (parse_uint64 (&ret->xfs_datablocks, buf) == -1)
goto error;
free (buf); buf = NULL;
} else if (i == 5) {
if (parse_uint32 (&ret->xfs_logblocks, buf) == -1)
goto error;
free (buf); buf = NULL;
} else if (i == 7) {
if (parse_uint64 (&ret->xfs_rtblocks, buf) == -1)
goto error;
free (buf); buf = NULL;
} else goto error;
}
if ((p = strstr (lines[i], "imaxpct="))) {
buf = split_strdup (p + 8);
CLEANUP_FREE char *buf = split_strdup (p + 8);
if (buf == NULL) goto error;
if (parse_uint32 (&ret->xfs_imaxpct, buf) == -1)
goto error;
free (buf); buf = NULL;
}
if ((p = strstr (lines[i], "sunit="))) {
buf = split_strdup (p + 6);
CLEANUP_FREE char *buf = split_strdup (p + 6);
if (buf == NULL) goto error;
if (i == 3) {
if (parse_uint32 (&ret->xfs_sunit, buf) == -1)
goto error;
free (buf); buf = NULL;
} else if (i == 6) {
if (parse_uint32 (&ret->xfs_logsunit, buf) == -1)
goto error;
free (buf); buf = NULL;
} else goto error;
}
if ((p = strstr (lines[i], "swidth="))) {
buf = split_strdup (p + 7);
CLEANUP_FREE char *buf = split_strdup (p + 7);
if (buf == NULL) goto error;
if (parse_uint32 (&ret->xfs_swidth, buf) == -1)
goto error;
free (buf); buf = NULL;
}
if ((p = strstr (lines[i], "naming =version "))) {
buf = split_strdup (p + 18);
CLEANUP_FREE char *buf = split_strdup (p + 18);
if (buf == NULL) goto error;
if (parse_uint32 (&ret->xfs_dirversion, buf) == -1)
goto error;
free (buf); buf = NULL;
}
if ((p = strstr (lines[i], "ascii-ci="))) {
buf = split_strdup (p + 9);
CLEANUP_FREE char *buf = split_strdup (p + 9);
if (buf == NULL) goto error;
if (parse_uint32 (&ret->xfs_cimode, buf) == -1)
goto error;
free (buf); buf = NULL;
}
if ((p = strstr (lines[i], "log ="))) {
ret->xfs_logname = split_strdup (p + 10);
if (ret->xfs_logname == NULL) goto error;
}
if ((p = strstr (lines[i], "version="))) {
buf = split_strdup (p + 8);
CLEANUP_FREE char *buf = split_strdup (p + 8);
if (buf == NULL) goto error;
if (parse_uint32 (&ret->xfs_logversion, buf) == -1)
goto error;
free (buf); buf = NULL;
}
if ((p = strstr (lines[i], "lazy-count="))) {
buf = split_strdup (p + 11);
CLEANUP_FREE char *buf = split_strdup (p + 11);
if (buf == NULL) goto error;
if (parse_uint32 (&ret->xfs_lazycount, buf) == -1)
goto error;
free (buf); buf = NULL;
}
if ((p = strstr (lines[i], "realtime ="))) {
ret->xfs_rtname = split_strdup (p + 10);
if (ret->xfs_rtname == NULL) goto error;
}
if ((p = strstr (lines[i], "rtextents="))) {
buf = split_strdup (p + 10);
CLEANUP_FREE char *buf = split_strdup (p + 10);
if (buf == NULL) goto error;
if (parse_uint64 (&ret->xfs_rtextents, buf) == -1)
goto error;
free (buf); buf = NULL;
}
}
@@ -312,7 +291,6 @@ parse_xfs_info (char **lines)
return ret;
error:
free (buf);
free (ret->xfs_mntpoint);
free (ret->xfs_logname);
free (ret->xfs_rtname);
@@ -324,10 +302,9 @@ guestfs_int_xfsinfo *
do_xfs_info (const char *pathordevice)
{
int r;
char *buf;
char *out = NULL, *err = NULL;
char **lines = NULL;
guestfs_int_xfsinfo *ret = NULL;
CLEANUP_FREE char *buf = NULL;
CLEANUP_FREE char *out = NULL, *err = NULL;
CLEANUP_FREE_STRING_LIST char **lines = NULL;
int is_dev;
is_dev = STREQLEN (pathordevice, "/dev/", 5);
@@ -339,24 +316,16 @@ do_xfs_info (const char *pathordevice)
}
r = command (&out, &err, str_xfs_info, buf, NULL);
free (buf);
if (r == -1) {
reply_with_error ("%s", err);
goto error;
return NULL;
}
lines = split_lines (out);
if (lines == NULL)
goto error;
return NULL;
ret = parse_xfs_info (lines);
error:
free (err);
free (out);
if (lines)
free_strings (lines);
return ret;
return parse_xfs_info (lines);
}
int
@@ -366,8 +335,7 @@ do_xfs_growfs (const char *path,
int64_t rtextsize, int32_t maxpct)
{
int r;
char *buf;
char *err = NULL;
CLEANUP_FREE char *buf = NULL, *err = NULL;
const char *argv[MAX_ARGS];
char datasize_s[64];
char logsize_s[64];
@@ -402,7 +370,7 @@ do_xfs_growfs (const char *path,
if (optargs_bitmask & GUESTFS_XFS_GROWFS_DATASIZE_BITMASK) {
if (datasize < 0) {
reply_with_error ("datasize must be >= 0");
goto error;
return -1;
}
snprintf (datasize_s, sizeof datasize_s, "%" PRIi64, datasize);
ADD_ARG (argv, i, "-D");
@@ -412,7 +380,7 @@ do_xfs_growfs (const char *path,
if (optargs_bitmask & GUESTFS_XFS_GROWFS_LOGSIZE_BITMASK) {
if (logsize < 0) {
reply_with_error ("logsize must be >= 0");
goto error;
return -1;
}
snprintf(logsize_s, sizeof logsize_s, "%" PRIi64, logsize);
ADD_ARG (argv, i, "-L");
@@ -422,7 +390,7 @@ do_xfs_growfs (const char *path,
if (optargs_bitmask & GUESTFS_XFS_GROWFS_RTSIZE_BITMASK) {
if (rtsize < 0) {
reply_with_error ("rtsize must be >= 0");
goto error;
return -1;
}
snprintf(rtsize_s, sizeof rtsize_s, "%" PRIi64, rtsize);
ADD_ARG (argv, i, "-R");
@@ -432,7 +400,7 @@ do_xfs_growfs (const char *path,
if (optargs_bitmask & GUESTFS_XFS_GROWFS_RTEXTSIZE_BITMASK) {
if (rtextsize < 0) {
reply_with_error ("rtextsize must be >= 0");
goto error;
return -1;
}
snprintf(rtextsize_s, sizeof rtextsize_s, "%" PRIi64, rtextsize);
ADD_ARG (argv, i, "-e");
@@ -442,7 +410,7 @@ do_xfs_growfs (const char *path,
if (optargs_bitmask & GUESTFS_XFS_GROWFS_MAXPCT_BITMASK) {
if (maxpct < 0) {
reply_with_error ("maxpct must be >= 0");
goto error;
return -1;
}
snprintf(maxpct_s, sizeof maxpct_s, "%" PRIi32, maxpct);
ADD_ARG (argv, i, "-m");
@@ -453,19 +421,12 @@ do_xfs_growfs (const char *path,
ADD_ARG (argv, i, NULL);
r = commandv (NULL, &err, argv);
free (buf);
if (r == -1) {
reply_with_error ("%s: %s", path, err);
goto error;
return -1;
}
free (err);
return 0;
error:
free (buf);
free (err);
return -1;
}
int
@@ -475,7 +436,7 @@ do_xfs_admin (const char *device,
int lazycounter, const char *label, const char *uuid)
{
int r;
char *err = NULL;
CLEANUP_FREE char *err = NULL;
const char *argv[MAX_ARGS];
size_t i = 0;
@@ -526,15 +487,10 @@ do_xfs_admin (const char *device,
r = commandv (NULL, &err, argv);
if (r == -1) {
reply_with_error ("%s: %s", device, err);
goto error;
return -1;
}
free (err);
return 0;
error:
free (err);
return -1;
}
int
@@ -546,9 +502,8 @@ do_xfs_repair (const char *device,
const char *logdev, const char *rtdev)
{
int r;
char *err = NULL;
CLEANUP_FREE char *err = NULL, *buf = NULL;
const char *argv[MAX_ARGS];
char *buf = NULL;
char maxmem_s[64];
char ihashsize_s[70];
char bhashsize_s[70];
@@ -581,7 +536,7 @@ do_xfs_repair (const char *device,
if (optargs_bitmask & GUESTFS_XFS_REPAIR_MAXMEM_BITMASK) {
if (maxmem < 0) {
reply_with_error ("maxmem must be >= 0");
goto error;
return -1;
}
snprintf(maxmem_s, sizeof maxmem_s, "%" PRIi64, maxmem);
ADD_ARG (argv, i, "-m");
@@ -591,7 +546,7 @@ do_xfs_repair (const char *device,
if (optargs_bitmask & GUESTFS_XFS_REPAIR_IHASHSIZE_BITMASK) {
if (ihashsize < 0) {
reply_with_error ("ihashsize must be >= 0");
goto error;
return -1;
}
snprintf(ihashsize_s, sizeof ihashsize_s, "ihash=" "%" PRIi64, ihashsize);
ADD_ARG (argv, i, "-o");
@@ -601,7 +556,7 @@ do_xfs_repair (const char *device,
if (optargs_bitmask & GUESTFS_XFS_REPAIR_BHASHSIZE_BITMASK) {
if (bhashsize < 0) {
reply_with_error ("bhashsize must be >= 0");
goto error;
return -1;
}
snprintf(bhashsize_s, sizeof bhashsize_s, "bhash=" "%" PRIi64, bhashsize);
ADD_ARG (argv, i, "-o");
@@ -611,7 +566,7 @@ do_xfs_repair (const char *device,
if (optargs_bitmask & GUESTFS_XFS_REPAIR_AGSTRIDE_BITMASK) {
if (agstride < 0) {
reply_with_error ("agstride must be >= 0");
goto error;
return -1;
}
snprintf(agstride_s, sizeof agstride_s, "ag_stride=" "%" PRIi64, agstride);
ADD_ARG (argv, i, "-o");
@@ -634,7 +589,7 @@ do_xfs_repair (const char *device,
buf = sysroot_path (device);
if (buf == NULL) {
reply_with_perror ("malloc");
goto error;
return -1;
}
ADD_ARG (argv, i, "-f");
ADD_ARG (argv, i, buf);
@@ -645,16 +600,10 @@ do_xfs_repair (const char *device,
ADD_ARG (argv, i, NULL);
r = commandrv (NULL, &err, argv);
free (buf);
if (r == -1) {
reply_with_error ("%s: %s", device, err);
goto error;
return -1;
}
free (err);
return r;
error:
free (err);
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
@@ -88,19 +88,15 @@ wipefs_has_force_option (void)
{
static int flag = -1;
int r;
char *out, *err;
CLEANUP_FREE char *out = NULL, *err = NULL;
if (flag == -1) {
r = command (&out, &err, "wipefs", "--help", NULL);
if (r == -1) {
reply_with_error ("%s", err);
free (out);
free (err);
return -1;
}
free (err);
flag = strstr (out, "--force") != NULL;
free (out);
}
return flag;
@@ -111,7 +107,7 @@ do_wipefs (const char *device)
{
int force;
int r;
char *err = NULL;
CLEANUP_FREE char *err = NULL;
const size_t MAX_ARGS = 16;
const char *argv[MAX_ARGS];
size_t i = 0;
@@ -130,11 +126,9 @@ do_wipefs (const char *device)
r = commandv (NULL, &err, argv);
if (r == -1) {
reply_with_error ("%s", err);
free (err);
return -1;
}
free (err);
return 0;
}
@@ -343,3 +337,32 @@ do_zero_free_space (const char *dir)
return 0;
}
/* Internal function used to wipe disks before we do 'mkfs'-type
* operations on them. For the rationale see RHBZ#889888 and
* RHBZ#907554.
*
* Note this is really destructive, so only call it just before doing
* the 'mkfs' operation (ie. after doing as much pre-checking as
* possible). Otherwise you could end up with a 'mkfs' operation
* failing with an error but still wiping data.
*/
void
wipe_device_before_mkfs (const char *device)
{
int r;
r = command (NULL, NULL, "wipefs", "-a", "--force", device, NULL);
if (r == 0)
return;
r = command (NULL, NULL, "wipefs", "-a", device, NULL);
if (r == 0)
return;
/* XXX We could fall back to overwriting bits of disk here, but if
* they don't have working wipefs, it seems unlikely they are using
* btrfs which is what mostly causes this problem. See:
* http://www.spinics.net/lists/linux-btrfs/msg21197.html
*/
}

View File

@@ -39,17 +39,14 @@ optgroup_zerofree_available (void)
int
do_zerofree (const char *device)
{
char *err;
CLEANUP_FREE char *err = NULL;
int r;
r = command (NULL, &err, str_zerofree, device, NULL);
if (r == -1) {
reply_with_error ("%s: %s", device, err);
free (err);
return -1;
}
free (err);
return 0;
}

View File

@@ -42,12 +42,15 @@ virt_df_SOURCES = \
main.c \
output.c
virt_df_CFLAGS = \
virt_df_CPPFLAGS = \
-DGUESTFS_WARN_DEPRECATED=1 \
-DGUESTFS_PRIVATE=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_df_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
$(GPROF_CFLAGS) $(GCOV_CFLAGS) \
$(LIBCONFIG_CFLAGS) \
@@ -55,9 +58,11 @@ virt_df_CFLAGS = \
virt_df_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.

14
df/df.c
View File

@@ -48,7 +48,7 @@ df_on_handle (const char *name, const char *uuid, char **devices, int offset)
{
int ret = -1;
size_t i;
char **fses = NULL;
CLEANUP_FREE_STRING_LIST char **fses = NULL;
int free_devices = 0, is_lv;
if (verbose) {
@@ -101,12 +101,6 @@ df_on_handle (const char *name, const char *uuid, char **devices, int offset)
ret = 0;
cleanup:
if (fses) {
for (i = 0; fses[i] != NULL; ++i)
free (fses[i]);
free (fses);
}
if (free_devices) {
for (i = 0; devices[i] != NULL; ++i)
free (devices[i]);
@@ -163,7 +157,7 @@ static void
try_df (const char *name, const char *uuid,
const char *dev, int offset)
{
struct guestfs_statvfs *stat = NULL;
CLEANUP_FREE_STATVFS struct guestfs_statvfs *stat = NULL;
if (verbose)
fprintf (stderr, "try_df %s %s %d\n", name, dev, offset);
@@ -180,8 +174,6 @@ try_df (const char *name, const char *uuid,
guestfs_pop_error_handler (g);
if (stat) {
if (stat)
print_stat (name, uuid, dev, offset, stat);
guestfs_free_statvfs (stat);
}
}

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