[PATCH] launch: rework handling of --enable-valgrind-daemon
by Pino Toscano
Instead of forcing valgrind to be run when --enable-valgrind-daemon is
passed to configure, enable it only when the backend setting
"valgrind_daemon" is set. This allows developers to keep building with
--enable-valgrind-daemon, which unconditionally adds valgrind in the
appliance but using only when requested.
When --enable-valgrind-daemon is not passed (typical for release
builds), then no valgrind-related code is built at all, and
"valgrind_daemon" is ignored.
---
src/guestfs-internal.h | 1 +
src/launch-direct.c | 4 ++++
src/launch-libvirt.c | 4 ++++
src/launch-uml.c | 14 ++++++++------
src/launch.c | 12 +++++++++---
5 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h
index bbd7fb4..d07b61d 100644
--- a/src/guestfs-internal.h
+++ b/src/guestfs-internal.h
@@ -767,6 +767,7 @@ extern void guestfs_int_print_timestamped_message (guestfs_h *g, const char *fs,
extern void guestfs_int_launch_send_progress (guestfs_h *g, int perdozen);
extern char *guestfs_int_appliance_command_line (guestfs_h *g, const char *appliance_dev, int flags);
#define APPLIANCE_COMMAND_LINE_IS_TCG 1
+#define APPLIANCE_COMMAND_LINE_VALGRIND_DAEMON 2
const char *guestfs_int_get_cpu_model (int kvm);
extern void guestfs_int_register_backend (const char *name, const struct backend_ops *);
extern int guestfs_int_set_backend (guestfs_h *g, const char *method);
diff --git a/src/launch-direct.c b/src/launch-direct.c
index ea67ec9..f6e90da 100644
--- a/src/launch-direct.c
+++ b/src/launch-direct.c
@@ -630,6 +630,10 @@ launch_direct (guestfs_h *g, void *datav, const char *arg)
flags = 0;
if (!has_kvm || force_tcg)
flags |= APPLIANCE_COMMAND_LINE_IS_TCG;
+#ifdef VALGRIND_DAEMON
+ if (guestfs_int_get_backend_setting_bool (g, "valgrind_daemon") > 0)
+ flags |= APPLIANCE_COMMAND_LINE_VALGRIND_DAEMON;
+#endif
ADD_CMDLINE_STRING_NODUP (guestfs_int_appliance_command_line (g, appliance_dev,
flags));
diff --git a/src/launch-libvirt.c b/src/launch-libvirt.c
index f46782c..92f2922 100644
--- a/src/launch-libvirt.c
+++ b/src/launch-libvirt.c
@@ -1160,6 +1160,10 @@ construct_libvirt_xml_boot (guestfs_h *g,
flags = 0;
if (!params->data->is_kvm)
flags |= APPLIANCE_COMMAND_LINE_IS_TCG;
+#ifdef VALGRIND_DAEMON
+ if (guestfs_int_get_backend_setting_bool (g, "valgrind_daemon") > 0)
+ flags |= APPLIANCE_COMMAND_LINE_VALGRIND_DAEMON;
+#endif
cmdline = guestfs_int_appliance_command_line (g, params->appliance_dev, flags);
start_element ("os") {
diff --git a/src/launch-uml.c b/src/launch-uml.c
index 785548c..1d92b5e 100644
--- a/src/launch-uml.c
+++ b/src/launch-uml.c
@@ -269,12 +269,14 @@ launch_uml (guestfs_h *g, void *datav, const char *arg)
#if 0 /* XXX This could be made to work. */
#ifdef VALGRIND_DAEMON
- /* Set up virtio-serial channel for valgrind messages. */
- ADD_CMDLINE ("-chardev");
- ADD_CMDLINE_PRINTF ("file,path=%s/valgrind.log.%d,id=valgrind",
- VALGRIND_LOG_PATH, getpid ());
- ADD_CMDLINE ("-device");
- ADD_CMDLINE ("virtserialport,chardev=valgrind,name=org.libguestfs.valgrind");
+ if (guestfs_int_get_backend_setting_bool (g, "valgrind_daemon") > 0) {
+ /* Set up virtio-serial channel for valgrind messages. */
+ ADD_CMDLINE ("-chardev");
+ ADD_CMDLINE_PRINTF ("file,path=%s/valgrind.log.%d,id=valgrind",
+ VALGRIND_LOG_PATH, getpid ());
+ ADD_CMDLINE ("-device");
+ ADD_CMDLINE ("virtserialport,chardev=valgrind,name=org.libguestfs.valgrind");
+ }
#endif
#endif
diff --git a/src/launch.c b/src/launch.c
index fd5479e..bfc2dea 100644
--- a/src/launch.c
+++ b/src/launch.c
@@ -319,6 +319,9 @@ guestfs_int_appliance_command_line (guestfs_h *g, const char *appliance_dev,
char *ret;
bool tcg = flags & APPLIANCE_COMMAND_LINE_IS_TCG;
char lpj_s[64] = "";
+#ifdef VALGRIND_DAEMON
+ int valgrind_daemon = flags & APPLIANCE_COMMAND_LINE_VALGRIND_DAEMON;
+#endif
if (appliance_dev)
snprintf (root, sizeof root, " root=%s", appliance_dev);
@@ -335,9 +338,6 @@ guestfs_int_appliance_command_line (guestfs_h *g, const char *appliance_dev,
#ifdef __arm__
" mem=%dM"
#endif
-#ifdef VALGRIND_DAEMON
- " guestfs_valgrind_daemon=1"
-#endif
#ifdef __i386__
" noapic" /* workaround for RHBZ#857026 */
#endif
@@ -363,6 +363,9 @@ guestfs_int_appliance_command_line (guestfs_h *g, const char *appliance_dev,
" %s" /* selinux */
"%s" /* verbose */
"%s" /* network */
+#ifdef VALGRIND_DAEMON
+ "%s" /* valgrind */
+#endif
" TERM=%s" /* TERM environment variable */
"%s%s", /* append */
#ifdef __arm__
@@ -373,6 +376,9 @@ guestfs_int_appliance_command_line (guestfs_h *g, const char *appliance_dev,
g->selinux ? "selinux=1 enforcing=0" : "selinux=0",
g->verbose ? " guestfs_verbose=1" : "",
g->enable_network ? " guestfs_network=1" : "",
+#ifdef VALGRIND_DAEMON
+ valgrind_daemon ? " guestfs_valgrind_daemon=1" : "",
+#endif
term ? term : "linux",
g->append ? " " : "", g->append ? g->append : "");
--
2.1.0
9 years, 3 months
[PATCH v3] New API: btrfs_replace
by Cao jin
Signed-off-by: Cao jin <caoj.fnst(a)cn.fujitsu.com>
---
v3: modify test script, add content check while remove replace back.
Also fixed other defects as Pino T comment
daemon/btrfs.c | 36 +++++++++++++++++++++
generator/actions.ml | 16 ++++++++++
tests/btrfs/Makefile.am | 3 +-
tests/btrfs/test-btrfs-replace.sh | 66 +++++++++++++++++++++++++++++++++++++++
4 files changed, 120 insertions(+), 1 deletion(-)
create mode 100755 tests/btrfs/test-btrfs-replace.sh
diff --git a/daemon/btrfs.c b/daemon/btrfs.c
index 20e5e6b..509a323 100644
--- a/daemon/btrfs.c
+++ b/daemon/btrfs.c
@@ -2060,3 +2060,39 @@ do_btrfs_image (char *const *sources, const char *image,
return 0;
}
+
+int
+do_btrfs_replace (const char *srcdev, const char *targetdev,
+ const char* mntpoint)
+{
+ const size_t MAX_ARGS = 64;
+ const char *argv[MAX_ARGS];
+ size_t i = 0;
+ CLEANUP_FREE char *err = NULL;
+ CLEANUP_FREE char *path_buf = NULL;
+ int r;
+
+ path_buf = sysroot_path (mntpoint);
+ if (path_buf == NULL) {
+ reply_with_perror ("malloc");
+ return -1;
+ }
+
+ ADD_ARG (argv, i, str_btrfs);
+ ADD_ARG (argv, i, "replace");
+ ADD_ARG (argv, i, "start");
+ ADD_ARG (argv, i, srcdev);
+ ADD_ARG (argv, i, targetdev);
+ ADD_ARG (argv, i, path_buf);
+ ADD_ARG (argv, i, "-B");
+ ADD_ARG (argv, i, "-f");
+ ADD_ARG (argv, i, NULL);
+
+ r = commandv (NULL, &err, argv);
+ if (r == -1) {
+ reply_with_error ("%s: %s", mntpoint, err);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/generator/actions.ml b/generator/actions.ml
index d5e5ccf..442f49c 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -12593,6 +12593,22 @@ numbered C<partnum> on device C<device>.
It returns C<primary>, C<logical>, or C<extended>." };
+ { defaults with
+ name = "btrfs_replace"; added = (1, 29, 48);
+ style = RErr, [Device "srcdev"; Device "targetdev"; Pathname "mntpoint"], [];
+ proc_nr = Some 455;
+ optional = Some "btrfs"; camel_name = "BTRFSReplace";
+ test_excuse = "put the test in 'tests/btrfs' directory";
+ shortdesc = "replace a btrfs managed device with another device";
+ longdesc = "\
+Replace device of a btrfs filesystem. On a live filesystem, duplicate the data
+to the target device which is currently stored on the source device.
+After completion of the operation, the source device is wiped out and
+removed from the filesystem.
+
+The C<targetdev> needs to be same size or larger than the C<srcdev>. Devices
+which are currently mounted are never allowed to be used as the C<targetdev>." };
+
]
(* Non-API meta-commands available only in guestfish.
diff --git a/tests/btrfs/Makefile.am b/tests/btrfs/Makefile.am
index bf4d7ae..b6ef794 100644
--- a/tests/btrfs/Makefile.am
+++ b/tests/btrfs/Makefile.am
@@ -20,7 +20,8 @@ include $(top_srcdir)/subdir-rules.mk
TESTS = \
test-btrfs-misc.pl \
test-btrfs-devices.sh \
- test-btrfs-subvolume-default.pl
+ test-btrfs-subvolume-default.pl \
+ test-btrfs-replace.sh
TESTS_ENVIRONMENT = $(top_builddir)/run --test
diff --git a/tests/btrfs/test-btrfs-replace.sh b/tests/btrfs/test-btrfs-replace.sh
new file mode 100755
index 0000000..2bf6d6d
--- /dev/null
+++ b/tests/btrfs/test-btrfs-replace.sh
@@ -0,0 +1,66 @@
+#!/bin/bash -
+# libguestfs
+# Copyright (C) 2015 Fujitsu 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.
+
+# Test btrfs replace devices.
+
+set -e
+
+# Allow the test to be skipped since btrfs is often broken.
+if [ -n "$SKIP_TEST_BTRFS_REPLACE_SH" ]; then
+ echo "$0: skipping test because environment variable is set."
+ exit 77
+fi
+
+# If btrfs is not available, bail.
+if ! guestfish -a /dev/null run : available btrfs; then
+ echo "$0: skipping test because btrfs is not available"
+ exit 77
+fi
+
+rm -f test-btrfs-devices-{1,2}.img replace.output
+
+guestfish <<EOF > replace.output
+# Add 2 empty disks
+sparse test-btrfs-devices-1.img 1G
+sparse test-btrfs-devices-2.img 1G
+run
+
+mkfs-btrfs /dev/sda
+mount /dev/sda /
+
+mkdir /data
+copy-in $srcdir/../data/filesanddirs-10M.tar.xz /data
+
+# now, sda is btrfs while sdb is blank.
+btrfs-replace /dev/sda /dev/sdb /
+
+# after replace: sda is wiped out, while sdb has btrfs with data
+list-filesystems
+ls /data/
+
+EOF
+
+if [ "$(cat replace.output)" != "/dev/sda: unknown
+/dev/sdb: btrfs
+filesanddirs-10M.tar.xz" ]; then
+ echo "btrfs-repalce fail!"
+ cat replace.output
+ exit 1
+fi
+
+rm test-btrfs-devices-{1,2}.img replace.output
--
2.1.0
9 years, 3 months
[PATCH v4 00/11] virt-resize: add support for resizing MBR logical partitions
by Chen Hanxiao
In current virt-resize, only primary partitions(including
extended partition) are supported. They are collected in an
array for resize operations. Logical partitions are not
supported.
This series add support for resizing logical partitions.
v4:
rebase on upstream.
v3:
1) rewrite partitions/logical_partitions/extended_partition section
by the comments from Rich and Pino.
2) in 03/11 introduce logical_align for reserve enough space
when resizing logical/extended partitions.
v2:
1) Add 3 variables to describe relationship of logical and extended partitions:
- partitions
flat list of primary partitions (as now, the global 'partitions').
extended partitions is essentially primary partition
- logical_partitions
flat list of logical partitions
- extended_partition
one MBR extended partition
2) reserve enough size when resizing logical partitions
Original patches by Hu Tao at:
https://www.redhat.com/archives/libguestfs/2014-October/msg00238.html
Chen Hanxiao (11):
resize: move loop check from find_partitions
resize: add logical_partitions and extended_partition
resize: calculate max alignment of logical partitions
resize: add support for logical partitions for calculate_surplus
resize: handle resize of logical partitions
resize: add support for logical partitions of
calculate_target_partitions
resize: calculate_target_partitions for logical partitions
resize: parted and copy logical partitions
resize: more misc ops on logical partition
resize: add support resize extended partition
resize: test: add support for resizing extended and logical partitions
resize/resize.ml | 220 +++++++++++++++++++++++++++++++++++----------
resize/test-virt-resize.pl | 32 ++-----
2 files changed, 179 insertions(+), 73 deletions(-)
--
2.1.0
9 years, 3 months
The usage if libguestfs
by fu lirong
HI all:
my problem is :
I want to use libguestfs on other project.
if I just run a test C programm It works well
just run : cc prog.c -o prog -lguestfs -I
/usr/libguestfs/libguestfs-1.28.10/src/
I write a C programm in my project , after that I run make , it happend:
/usr/nitro/libvmi-master/libvmi/.libs/libvmi.so: undefined reference to
`guestfs_launch'
/usr/nitro/libvmi-master/libvmi/.libs/libvmi.so: undefined reference to
`guestfs_close'
/usr/nitro/libvmi-master/libvmi/.libs/libvmi.so: undefined reference to
`guestfs_inspect_os'
/usr/nitro/libvmi-master/libvmi/.libs/libvmi.so: undefined reference to
`guestfs_ls'
/usr/nitro/libvmi-master/libvmi/.libs/libvmi.so: undefined reference to
`guestfs_inspect_get_type'
/usr/nitro/libvmi-master/libvmi/.libs/libvmi.so: undefined reference to
`guestfs_inspect_get_mountpoints'
/usr/nitro/libvmi-master/libvmi/.libs/libvmi.so: undefined reference to
`guestfs_inspect_get_major_version'
/usr/nitro/libvmi-master/libvmi/.libs/libvmi.so: undefined reference to
`guestfs_inspect_get_product_name'
/usr/nitro/libvmi-master/libvmi/.libs/libvmi.so: undefined reference to
`guestfs_add_drive_opts'
I think It's owe to the lack of DLL, so I did some change in Makefile,
the change is :
- LIBS = -lvirt
-LDFLAGS =
+LDFLAGS = /usr/lib
+LIBS = -lguestfs -lvirt
but it didn't works!
so does anyone know what's the problem?
appreciate so much
9 years, 3 months
[PATCH] v2v: Increase the timeout of VMware curl connections (RHBZ#1146007).
by Richard W.M. Jones
On certain webservers these appear to go beyond even 600 seconds (10
minutes).
---
v2v/input_libvirt_vcenter_https.ml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/v2v/input_libvirt_vcenter_https.ml b/v2v/input_libvirt_vcenter_https.ml
index 01a6c89..c6b9a1f 100644
--- a/v2v/input_libvirt_vcenter_https.ml
+++ b/v2v/input_libvirt_vcenter_https.ml
@@ -250,7 +250,8 @@ let map_source_to_uri ?readahead password uri scheme server path =
let json_params = [
"file.driver", JSON.String "https";
"file.url", JSON.String url;
- "file.timeout", JSON.Int 600;
+ (* https://bugzilla.redhat.com/show_bug.cgi?id=1146007#c10 *)
+ "file.timeout", JSON.Int 2000;
] in
let json_params =
--
2.3.1
9 years, 3 months
Problem with supermin and symlink in ibm_powerkvm ppc64le distro
by Daniel Henrique Barboza
Hi,
I've found a problem with supermin code running in an ibm_powerkvm
ppc64le distro.
Output of libguestfs-test-tool:
$ libguestfs-test-tool
************************************************************
* IMPORTANT NOTICE
*
* When reporting bugs, include the COMPLETE, UNEDITED
* output below in your bug report.
*
************************************************************
libguestfs: trace: set_verbose true
libguestfs: trace: set_verbose = 0
libguestfs: trace: set_verbose true
libguestfs: trace: set_verbose = 0
LIBGUESTFS_DEBUG=1
LIBGUESTFS_TRACE=1
PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/danielhb/.local/bin:/home/danielhb/bin
SELinux: Enforcing
libguestfs: trace: add_drive_scratch 104857600
libguestfs: trace: get_tmpdir
libguestfs: trace: get_tmpdir = "/tmp"
libguestfs: trace: disk_create "/tmp/libguestfsgakCjw/scratch.1" "raw"
104857600
libguestfs: trace: disk_create = 0
libguestfs: trace: add_drive "/tmp/libguestfsgakCjw/scratch.1"
"format:raw" "cachemode:unsafe"
libguestfs: trace: add_drive = 0
libguestfs: trace: add_drive_scratch = 0
libguestfs: trace: get_append
libguestfs: trace: get_append = "NULL"
guestfs_get_append: (null)
libguestfs: trace: get_autosync
libguestfs: trace: get_autosync = 1
guestfs_get_autosync: 1
libguestfs: trace: get_backend
libguestfs: trace: get_backend = "libvirt"
guestfs_get_backend: libvirt
libguestfs: trace: get_backend_settings
libguestfs: trace: get_backend_settings = []
guestfs_get_backend_settings: []
libguestfs: trace: get_cachedir
libguestfs: trace: get_cachedir = "/var/tmp"
guestfs_get_cachedir: /var/tmp
libguestfs: trace: get_direct
libguestfs: trace: get_direct = 0
guestfs_get_direct: 0
libguestfs: trace: get_hv
libguestfs: trace: get_hv = "/usr/bin/qemu-system-ppc64"
guestfs_get_hv: /usr/bin/qemu-system-ppc64
libguestfs: trace: get_memsize
libguestfs: trace: get_memsize = 768
guestfs_get_memsize: 768
libguestfs: trace: get_network
libguestfs: trace: get_network = 0
guestfs_get_network: 0
libguestfs: trace: get_path
libguestfs: trace: get_path = "/usr/lib64/guestfs"
guestfs_get_path: /usr/lib64/guestfs
libguestfs: trace: get_pgroup
libguestfs: trace: get_pgroup = 0
guestfs_get_pgroup: 0
libguestfs: trace: get_program
libguestfs: trace: get_program = "libguestfs-test-tool"
guestfs_get_program: libguestfs-test-tool
libguestfs: trace: get_recovery_proc
libguestfs: trace: get_recovery_proc = 1
guestfs_get_recovery_proc: 1
libguestfs: trace: get_selinux
libguestfs: trace: get_selinux = 0
guestfs_get_selinux: 0
libguestfs: trace: get_smp
libguestfs: trace: get_smp = 1
guestfs_get_smp: 1
libguestfs: trace: get_tmpdir
libguestfs: trace: get_tmpdir = "/tmp"
guestfs_get_tmpdir: /tmp
libguestfs: trace: get_trace
libguestfs: trace: get_trace = 1
guestfs_get_trace: 1
libguestfs: trace: get_verbose
libguestfs: trace: get_verbose = 1
guestfs_get_verbose: 1
host_cpu: powerpc64le
Launching appliance, timeout set to 600 seconds.
libguestfs: trace: launch
libguestfs: trace: version
libguestfs: trace: version = <struct guestfs_version *>
libguestfs: trace: get_backend
libguestfs: trace: get_backend = "libvirt"
libguestfs: launch: program=libguestfs-test-tool
libguestfs: launch: version=1.28.1base=8,release=1.18.el7_1.ibm.3,libvirt
libguestfs: launch: backend registered: unix
libguestfs: launch: backend registered: uml
libguestfs: launch: backend registered: libvirt
libguestfs: launch: backend registered: direct
libguestfs: launch: backend=libvirt
libguestfs: launch: tmpdir=/tmp/libguestfsgakCjw
libguestfs: launch: umask=0002
libguestfs: launch: euid=1002
libguestfs: libvirt version = 1002014 (1.2.14)
libguestfs: guest random name = guestfs-umy4uvuxvi1sxbb9
libguestfs: [00000ms] connect to libvirt
libguestfs: opening libvirt handle: URI = qemu:///session, auth =
default+wrapper, flags = 0
libguestfs: successfully opened libvirt handle: conn = 0x3fff88a20a30
libguestfs: qemu version (reported by libvirt) = 2003000 (2.3.0)
libguestfs: [00534ms] get libvirt capabilities
libguestfs: [00552ms] parsing capabilities XML
libguestfs: trace: get_backend_setting "force_tcg"
libguestfs: trace: get_backend_setting = NULL (error)
libguestfs: trace: get_backend_setting "internal_libvirt_label"
libguestfs: trace: get_backend_setting = NULL (error)
libguestfs: trace: get_backend_setting "internal_libvirt_imagelabel"
libguestfs: trace: get_backend_setting = NULL (error)
libguestfs: trace: get_backend_setting "internal_libvirt_norelabel_disks"
libguestfs: trace: get_backend_setting = NULL (error)
libguestfs: [00552ms] build appliance
libguestfs: trace: get_cachedir
libguestfs: trace: get_cachedir = "/var/tmp"
libguestfs: [00552ms] begin building supermin appliance
libguestfs: [00553ms] run supermin
libguestfs: command: run: /usr/bin/supermin5
libguestfs: command: run: \ --build
libguestfs: command: run: \ --verbose
libguestfs: command: run: \ --if-newer
libguestfs: command: run: \ --lock /var/tmp/.guestfs-1002/lock
libguestfs: command: run: \ --copy-kernel
libguestfs: command: run: \ -f ext2
libguestfs: command: run: \ --host-cpu powerpc64le
libguestfs: command: run: \ /usr/lib64/guestfs/supermin.d
libguestfs: command: run: \ -o /var/tmp/.guestfs-1002/appliance.d
supermin: version: 5.1.10
supermin: rpm: detected RPM version 4.11
supermin: package handler: ibm_powerkvm/rpm
supermin: acquiring lock on /var/tmp/.guestfs-1002/lock
supermin: build: /usr/lib64/guestfs/supermin.d
supermin: build: visiting /usr/lib64/guestfs/supermin.d/base.tar.gz type
gzip base image (tar)
supermin: build: visiting /usr/lib64/guestfs/supermin.d/daemon.tar.gz
type gzip base image (tar)
supermin: build: visiting /usr/lib64/guestfs/supermin.d/excludefiles
type uncompressed excludefiles
supermin: build: visiting /usr/lib64/guestfs/supermin.d/hostfiles type
uncompressed hostfiles
supermin: build: visiting /usr/lib64/guestfs/supermin.d/init.tar.gz type
gzip base image (tar)
supermin: build: visiting /usr/lib64/guestfs/supermin.d/packages type
uncompressed packages
supermin: build: visiting
/usr/lib64/guestfs/supermin.d/udev-rules.tar.gz type gzip base image (tar)
supermin: build: 179 packages, including dependencies
supermin: build: 29714 files
supermin: build: 16530 files, after removing unreadable files
supermin: build: 8520 files, after matching excludefiles
supermin: build: 8525 files, after adding hostfiles
supermin: build: 8561 files, after munging
supermin: kernel: picked kernel vmlinuz-4.0.0
supermin: kernel: picked modules path /lib/modules/4.0.0
supermin: kernel: kernel_version 4.0.0
supermin: kernel: modules /lib/modules/4.0.0
supermin: ext2: creating empty ext2 filesystem
'/var/tmp/.guestfs-1002/appliance.d.fas3dshe/root'
supermin: ext2: populating from base image
supermin: ext2: copying files from host filesystem
supermin: open: /lib64/dbus-1/dbus-daemon-launch-helper: Permission denied
supermin: *** parent directory not found ***
supermin: When reporting this error:
supermin: please include ALL the debugging information below
supermin: AND tell us what system you are running this on.
src=/opt/ibm/powerkvm-licenses
dest=/opt/ibm/powerkvm-licenses
dirname=/opt/ibm
basename=powerkvm-licenses
supermin: ext2fs_namei: parent directory not found: /opt/ibm: File not
found by ext2_lookup
supermin: failure: ext2fs_namei: parent directory not found
libguestfs: error: /usr/bin/supermin5 exited with error status 1, see
debug messages above
libguestfs: trace: launch = -1 (error)
libguestfs-test-tool: failed to launch appliance
libguestfs: trace: close
libguestfs: closing guestfs handle 0x3fff88a20250 (state 0)
libguestfs: command: run: rm
libguestfs: command: run: \ -rf /tmp/libguestfsgakCjw
The same problem happens when running test/test-build-bash.sh with
current supermin
upstream code. The results of make check follows:
PASS: test-basic.sh
PASS: test-execstack.sh
FAIL: test-build-bash.sh
PASS: test-binaries-exist.sh
PASS: test-harder.sh
FAIL: test-build-bash-network.sh
PASS: test-binaries-exist-network.sh
PASS: test-harder-network.sh
make[4]: Entering directory `/home/danielhb/supermin/tests'
make[4]: Nothing to be done for `all'.
make[4]: Leaving directory `/home/danielhb/supermin/tests'
============================================================================
Testsuite summary for supermin 5.1.13
============================================================================
# TOTAL: 8
# PASS: 6
# SKIP: 0
# XFAIL: 0
# FAIL: 2
# XPASS: 0
# ERROR: 0
This is how the filesystem looks like. It seems that supermin tries to
copy the contents of
powerkvm-licenses, which is a link to /usr/share(...) and then it has
problems when returning
to the parent dir /opt/ibm .
$ cd /opt/ibm
$ ls -lah
total 16K
drwxr-xr-x. 4 root root 4.0K Jun 12 07:06 .
drwxr-xr-x. 3 root root 4.0K Mar 19 09:35 ..
drwxr-xr-x. 9 root root 4.0K May 7 14:33 powerkvm
lrwxrwxrwx. 1 root root 36 May 7 14:32 powerkvm-licenses ->
/usr/share/doc/pkvm/licenses
drwxr-xr-x. 6 root root 4.0K May 7 14:33 seprovider
I've tracked the problem down to the function 'ext2_copy_file' in
src/ext2fs-c.c
Thanks,
Daniel
9 years, 3 months
[PATCH v3 0/4] uuid: add btrfs uuid change support and some rework
by Chen Hanxiao
- Btrfs-progs v4.1 introduced new feature of changing
uuid of btrfs partition.
This patch add support of this.
- uuids.c did a lot of deplicated work for changing uuid
of fs. Use existing functions.
v3: set errno if feature is not available.
Chen Hanxiao (4):
uuid: add support to change uuid of btrfs partition
uuid: use existing function of ext2
uuid: use newly introduced xfs_set_uuid of xfs
uuid: use newly introduced swap_set_uuid
daemon/btrfs.c | 60 ++++++++++++++++++++++++++++++++++++++++++
daemon/daemon.h | 5 ++++
daemon/swap.c | 16 +++++++++++
daemon/uuids.c | 48 ++++-----------------------------
daemon/xfs.c | 7 +++++
tests/btrfs/test-btrfs-misc.pl | 17 ++++++++++++
6 files changed, 110 insertions(+), 43 deletions(-)
--
2.1.0
9 years, 3 months
[PATCH] v2v: Free XML objects in the correct order.
by Richard W.M. Jones
If you free an xmlDocPtr before any xmlXPathObjectPtr 's that
reference the doc, you'll get valgrind errors like this:
==7390== Invalid read of size 4
==7390== at 0x4EB8BC6: xmlXPathFreeNodeSet (xpath.c:4185)
==7390== by 0x4EB8CC5: xmlXPathFreeObject (xpath.c:5492)
==7390== by 0x400A56: main (in /tmp/test)
==7390== Address 0x60c0928 is 8 bytes inside a block of size 120 free'd
==7390== at 0x4C29D2A: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==7390== by 0x4E8784F: xmlFreeNodeList (tree.c:3683)
==7390== by 0x4E87605: xmlFreeDoc (tree.c:1242)
==7390== by 0x400A4A: main (in /tmp/test)
The following simple test program demonstrates the problem:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <libxml/xpath.h>
int
main (int argc, char *argv[])
{
xmlDocPtr doc;
xmlXPathContextPtr xpathctx;
xmlXPathObjectPtr xpathobj;
doc = xmlReadMemory ("<test/>", 7, NULL, NULL, XML_PARSE_NONET);
assert (doc);
xpathctx = xmlXPathNewContext (doc);
assert (xpathctx);
xpathobj = xmlXPathEvalExpression (BAD_CAST "/test", xpathctx);
assert (xpathobj);
xmlFreeDoc (doc);
xmlXPathFreeObject (xpathobj);
xmlXPathFreeContext (xpathctx);
exit (EXIT_SUCCESS);
}
In virt-v2v we were not freeing up objects in the correct order,
because we didn't express the dependency between objects at the C
level into the OCaml, where the OCaml garbage collector could see
those dependencies. For example code like:
let doc = ... in
let xpathctx = xpath_new_context doc in
let xpathobj = xpath_eval_expression xpathctx "/foo" in
might end up freeing the 'doc' (xmlDocPtr) if, say, there were no
further references to it in the code, before freeing the 'xpathobj'
(xmlXPathObjectPtr).
To avoid this, we change the OCaml-level representation of objects
like xpathobj so they contain a reference back to the higher-level
objects (xpathctx & doc). Therefore holding an xpathobj means that
the doc cannot be freed.
However that alone is not quite sufficient. There is a further
problem when the program calls Gc.full_major, Gc.compact etc., or even
just when xpathctx & doc happen to be freed at the same time. The GC
won't necessarily free them in the right order as it knows both need
to be freed but doesn't know that one must be freed before the other.
To solve this we have to move the finalisers into OCaml code, since
the OCaml Gc.finalise function comes with an explicit ordering
guarantee (that finalisers are always called in reverse order that
they were created), which the C-level finaliser does not.
---
v2v/input_libvirtxml.ml | 18 +++---
v2v/input_ova.ml | 10 ++--
v2v/output_libvirt.ml | 6 +-
v2v/test-harness/v2v_test_harness.ml | 2 +-
v2v/xml-c.c | 103 ++++++++++++++++++-----------------
v2v/xml.ml | 92 ++++++++++++++++++++-----------
v2v/xml.mli | 2 +-
7 files changed, 131 insertions(+), 102 deletions(-)
diff --git a/v2v/input_libvirtxml.ml b/v2v/input_libvirtxml.ml
index ba00d94..646346d 100644
--- a/v2v/input_libvirtxml.ml
+++ b/v2v/input_libvirtxml.ml
@@ -44,14 +44,14 @@ let parse_libvirt_xml ?conn xml =
let obj = Xml.xpath_eval_expression xpathctx expr in
if Xml.xpathobj_nr_nodes obj < 1 then default
else (
- let node = Xml.xpathobj_node doc obj 0 in
+ let node = Xml.xpathobj_node obj 0 in
Xml.node_as_string node
)
and xpath_to_int expr default =
let obj = Xml.xpath_eval_expression xpathctx expr in
if Xml.xpathobj_nr_nodes obj < 1 then default
else (
- let node = Xml.xpathobj_node doc obj 0 in
+ let node = Xml.xpathobj_node obj 0 in
let str = Xml.node_as_string node in
try int_of_string str
with Failure "int_of_string" ->
@@ -78,7 +78,7 @@ let parse_libvirt_xml ?conn xml =
let obj = Xml.xpath_eval_expression xpathctx "/domain/features/*" in
let nr_nodes = Xml.xpathobj_nr_nodes obj in
for i = 0 to nr_nodes-1 do
- let node = Xml.xpathobj_node doc obj i in
+ let node = Xml.xpathobj_node obj i in
features := Xml.node_name node :: !features
done;
!features in
@@ -89,7 +89,7 @@ let parse_libvirt_xml ?conn xml =
if nr_nodes < 1 then None
else (
(* Ignore everything except the first <graphics> device. *)
- let node = Xml.xpathobj_node doc obj 0 in
+ let node = Xml.xpathobj_node obj 0 in
Xml.xpathctx_set_current_context xpathctx node;
let keymap =
match xpath_to_string "@keymap" "" with "" -> None | k -> Some k in
@@ -150,7 +150,7 @@ let parse_libvirt_xml ?conn xml =
if nr_nodes < 1 then None
else (
(* Ignore everything except the first <sound> device. *)
- let node = Xml.xpathobj_node doc obj 0 in
+ let node = Xml.xpathobj_node obj 0 in
Xml.xpathctx_set_current_context xpathctx node;
match xpath_to_string "@model" "" with
@@ -189,7 +189,7 @@ let parse_libvirt_xml ?conn xml =
if nr_nodes < 1 then
error (f_"this guest has no non-removable disks");
for i = 0 to nr_nodes-1 do
- let node = Xml.xpathobj_node doc obj i in
+ let node = Xml.xpathobj_node obj i in
Xml.xpathctx_set_current_context xpathctx node;
let controller =
@@ -248,7 +248,7 @@ let parse_libvirt_xml ?conn xml =
let obj = Xml.xpath_eval_expression xpathctx expr in
if Xml.xpathobj_nr_nodes obj < 1 then default
else (
- let node = Xml.xpathobj_node doc obj 0 in
+ let node = Xml.xpathobj_node obj 0 in
Xml.node_as_string node
) in
@@ -279,7 +279,7 @@ let parse_libvirt_xml ?conn xml =
let nr_nodes = Xml.xpathobj_nr_nodes obj in
let disks = ref [] in
for i = 0 to nr_nodes-1 do
- let node = Xml.xpathobj_node doc obj i in
+ let node = Xml.xpathobj_node obj i in
Xml.xpathctx_set_current_context xpathctx node;
let controller =
@@ -309,7 +309,7 @@ let parse_libvirt_xml ?conn xml =
let nr_nodes = Xml.xpathobj_nr_nodes obj in
let nics = ref [] in
for i = 0 to nr_nodes-1 do
- let node = Xml.xpathobj_node doc obj i in
+ let node = Xml.xpathobj_node obj i in
Xml.xpathctx_set_current_context xpathctx node;
let mac = xpath_to_string "mac/@address" "" in
diff --git a/v2v/input_ova.ml b/v2v/input_ova.ml
index 066af73..0ef349d 100644
--- a/v2v/input_ova.ml
+++ b/v2v/input_ova.ml
@@ -184,14 +184,14 @@ object
let obj = Xml.xpath_eval_expression xpathctx expr in
if Xml.xpathobj_nr_nodes obj < 1 then default
else (
- let node = Xml.xpathobj_node doc obj 0 in
+ let node = Xml.xpathobj_node obj 0 in
Xml.node_as_string node
)
and xpath_to_int expr default =
let obj = Xml.xpath_eval_expression xpathctx expr in
if Xml.xpathobj_nr_nodes obj < 1 then default
else (
- let node = Xml.xpathobj_node doc obj 0 in
+ let node = Xml.xpathobj_node obj 0 in
let str = Xml.node_as_string node in
try int_of_string str
with Failure "int_of_string" ->
@@ -247,7 +247,7 @@ object
let obj = Xml.xpath_eval_expression xpathctx expr in
let nr_nodes = Xml.xpathobj_nr_nodes obj in
for i = 0 to nr_nodes-1 do
- let n = Xml.xpathobj_node doc obj i in
+ let n = Xml.xpathobj_node obj i in
Xml.xpathctx_set_current_context xpathctx n;
(* XXX We assume the OVF lists these in order.
@@ -316,7 +316,7 @@ object
let obj = Xml.xpath_eval_expression xpathctx expr in
let nr_nodes = Xml.xpathobj_nr_nodes obj in
for i = 0 to nr_nodes-1 do
- let n = Xml.xpathobj_node doc obj i in
+ let n = Xml.xpathobj_node obj i in
Xml.xpathctx_set_current_context xpathctx n;
let id = xpath_to_int "rasd:ResourceType/text()" 0 in
assert (id = 14 || id = 15 || id = 16);
@@ -350,7 +350,7 @@ object
let obj = Xml.xpath_eval_expression xpathctx "/ovf:Envelope/ovf:VirtualSystem/ovf:VirtualHardwareSection/ovf:Item[rasd:ResourceType/text()=10]" in
let nr_nodes = Xml.xpathobj_nr_nodes obj in
for i = 0 to nr_nodes-1 do
- let n = Xml.xpathobj_node doc obj i in
+ let n = Xml.xpathobj_node obj i in
Xml.xpathctx_set_current_context xpathctx n;
let vnet = xpath_to_string "rasd:ElementName/text()" (sprintf"eth%d" i) in
let nic = {
diff --git a/v2v/output_libvirt.ml b/v2v/output_libvirt.ml
index a4fa5fb..7f02e45 100644
--- a/v2v/output_libvirt.ml
+++ b/v2v/output_libvirt.ml
@@ -54,7 +54,7 @@ let target_features_of_capabilities_doc doc arch =
warning (f_"the target hypervisor does not support a %s KVM guest") arch;
[]
) else (
- let node (* first matching <guest> *) = Xml.xpathobj_node doc obj 0 in
+ let node (* first matching <guest> *) = Xml.xpathobj_node obj 0 in
Xml.xpathctx_set_current_context xpathctx node;
(* Get guest/features/* nodes. *)
@@ -62,7 +62,7 @@ let target_features_of_capabilities_doc doc arch =
let features = ref [] in
for i = 0 to Xml.xpathobj_nr_nodes obj - 1 do
- let feature_node = Xml.xpathobj_node doc obj i in
+ let feature_node = Xml.xpathobj_node obj i in
let feature_name = Xml.node_name feature_node in
features := feature_name :: !features
done;
@@ -355,7 +355,7 @@ class output_libvirt oc output_pool = object
let obj = Xml.xpath_eval_expression xpathctx expr in
if Xml.xpathobj_nr_nodes obj < 1 then default
else (
- let node = Xml.xpathobj_node doc obj 0 in
+ let node = Xml.xpathobj_node obj 0 in
Xml.node_as_string node
)
in
diff --git a/v2v/test-harness/v2v_test_harness.ml b/v2v/test-harness/v2v_test_harness.ml
index 9ab2de7..efbda7b 100644
--- a/v2v/test-harness/v2v_test_harness.ml
+++ b/v2v/test-harness/v2v_test_harness.ml
@@ -92,7 +92,7 @@ let run ~test ?input_disk ?input_xml ?(test_plan = default_plan) () =
let nodes_of_xpathobj doc xpathobj =
let nodes = ref [] in
for i = 0 to Xml.xpathobj_nr_nodes xpathobj - 1 do
- nodes := Xml.xpathobj_node doc xpathobj i :: !nodes
+ nodes := Xml.xpathobj_node xpathobj i :: !nodes
done;
List.rev !nodes
in
diff --git a/v2v/xml-c.c b/v2v/xml-c.c
index 2602766..13627e1 100644
--- a/v2v/xml-c.c
+++ b/v2v/xml-c.c
@@ -40,60 +40,53 @@
/* xmlDocPtr type */
#define Doc_val(v) (*((xmlDocPtr *)Data_custom_val(v)))
-static void
-doc_finalize (value docv)
-{
- xmlDocPtr doc = Doc_val (docv);
-
- if (doc)
- xmlFreeDoc (doc);
-}
-
static struct custom_operations doc_custom_operations = {
(char *) "doc_custom_operations",
- doc_finalize,
+ custom_finalize_default,
custom_compare_default,
custom_hash_default,
custom_serialize_default,
custom_deserialize_default
};
+value
+v2v_xml_free_doc (value docv)
+{
+ CAMLparam1 (docv);
+ xmlDocPtr doc = Doc_val (docv);
+
+ xmlFreeDoc (doc);
+ CAMLreturn (Val_unit);
+}
+
/* xmlXPathContextPtr type */
-#define Xpathctx_val(v) (*((xmlXPathContextPtr *)Data_custom_val(v)))
+#define Xpathctx_ptr_val(v) (*((xmlXPathContextPtr *)Data_custom_val(v)))
-static void
-xpathctx_finalize (value xpathctxv)
-{
- xmlXPathContextPtr xpathctx = Xpathctx_val (xpathctxv);
-
- if (xpathctx)
- xmlXPathFreeContext (xpathctx);
-}
-
-static struct custom_operations xpathctx_custom_operations = {
- (char *) "xpathctx_custom_operations",
- xpathctx_finalize,
+static struct custom_operations xpathctx_ptr_custom_operations = {
+ (char *) "xpathctx_ptr_custom_operations",
+ custom_finalize_default,
custom_compare_default,
custom_hash_default,
custom_serialize_default,
custom_deserialize_default
};
+value
+v2v_xml_xpathctx_ptr_free_context (value xpathctxv)
+{
+ CAMLparam1 (xpathctxv);
+ xmlXPathContextPtr xpathctx = Xpathctx_ptr_val (xpathctxv);
+
+ xmlXPathFreeContext (xpathctx);
+ CAMLreturn (Val_unit);
+}
+
/* xmlXPathObjectPtr type */
-#define Xpathobj_val(v) (*((xmlXPathObjectPtr *)Data_custom_val(v)))
+#define Xpathobj_ptr_val(v) (*((xmlXPathObjectPtr *)Data_custom_val(v)))
-static void
-xpathobj_finalize (value xpathobjv)
-{
- xmlXPathObjectPtr xpathobj = Xpathobj_val (xpathobjv);
-
- if (xpathobj)
- xmlXPathFreeObject (xpathobj);
-}
-
-static struct custom_operations xpathobj_custom_operations = {
- (char *) "xpathobj_custom_operations",
- xpathobj_finalize,
+static struct custom_operations xpathobj_ptr_custom_operations = {
+ (char *) "xpathobj_ptr_custom_operations",
+ custom_finalize_default,
custom_compare_default,
custom_hash_default,
custom_serialize_default,
@@ -101,6 +94,16 @@ static struct custom_operations xpathobj_custom_operations = {
};
value
+v2v_xml_xpathobj_ptr_free_object (value xpathobjv)
+{
+ CAMLparam1 (xpathobjv);
+ xmlXPathObjectPtr xpathobj = Xpathobj_ptr_val (xpathobjv);
+
+ xmlXPathFreeObject (xpathobj);
+ CAMLreturn (Val_unit);
+}
+
+value
v2v_xml_parse_memory (value xmlv)
{
CAMLparam1 (xmlv);
@@ -159,7 +162,7 @@ v2v_xml_to_string (value docv, value formatv)
}
value
-v2v_xml_xpath_new_context (value docv)
+v2v_xml_xpath_new_context_ptr (value docv)
{
CAMLparam1 (docv);
CAMLlocal1 (xpathctxv);
@@ -171,21 +174,21 @@ v2v_xml_xpath_new_context (value docv)
if (xpathctx == NULL)
caml_invalid_argument ("xpath_new_context: unable to create xmlXPathNewContext");
- xpathctxv = caml_alloc_custom (&xpathctx_custom_operations,
+ xpathctxv = caml_alloc_custom (&xpathctx_ptr_custom_operations,
sizeof (xmlXPathContextPtr), 0, 1);
- Xpathctx_val (xpathctxv) = xpathctx;
+ Xpathctx_ptr_val (xpathctxv) = xpathctx;
CAMLreturn (xpathctxv);
}
value
-v2v_xml_xpath_register_ns (value xpathctxv, value prefix, value uri)
+v2v_xml_xpathctx_ptr_register_ns (value xpathctxv, value prefix, value uri)
{
CAMLparam3 (xpathctxv, prefix, uri);
xmlXPathContextPtr xpathctx;
int r;
- xpathctx = Xpathctx_val (xpathctxv);
+ xpathctx = Xpathctx_ptr_val (xpathctxv);
r = xmlXPathRegisterNs (xpathctx, BAD_CAST String_val (prefix), BAD_CAST String_val (uri));
if (r == -1)
caml_invalid_argument ("xpath_register_ns: unable to register namespace");
@@ -194,30 +197,30 @@ v2v_xml_xpath_register_ns (value xpathctxv, value prefix, value uri)
}
value
-v2v_xml_xpath_eval_expression (value xpathctxv, value exprv)
+v2v_xml_xpathctx_ptr_eval_expression (value xpathctxv, value exprv)
{
CAMLparam2 (xpathctxv, exprv);
CAMLlocal1 (xpathobjv);
xmlXPathContextPtr xpathctx;
xmlXPathObjectPtr xpathobj;
- xpathctx = Xpathctx_val (xpathctxv);
+ xpathctx = Xpathctx_ptr_val (xpathctxv);
xpathobj = xmlXPathEvalExpression (BAD_CAST String_val (exprv), xpathctx);
if (xpathobj == NULL)
caml_invalid_argument ("xpath_eval_expression: unable to evaluate XPath expression");
- xpathobjv = caml_alloc_custom (&xpathobj_custom_operations,
+ xpathobjv = caml_alloc_custom (&xpathobj_ptr_custom_operations,
sizeof (xmlXPathObjectPtr), 0, 1);
- Xpathobj_val (xpathobjv) = xpathobj;
+ Xpathobj_ptr_val (xpathobjv) = xpathobj;
CAMLreturn (xpathobjv);
}
value
-v2v_xml_xpathobj_nr_nodes (value xpathobjv)
+v2v_xml_xpathobj_ptr_nr_nodes (value xpathobjv)
{
CAMLparam1 (xpathobjv);
- xmlXPathObjectPtr xpathobj = Xpathobj_val (xpathobjv);
+ xmlXPathObjectPtr xpathobj = Xpathobj_ptr_val (xpathobjv);
if (xpathobj->nodesetval == NULL)
CAMLreturn (Val_int (0));
@@ -226,10 +229,10 @@ v2v_xml_xpathobj_nr_nodes (value xpathobjv)
}
value
-v2v_xml_xpathobj_get_node_ptr (value xpathobjv, value iv)
+v2v_xml_xpathobj_ptr_get_node_ptr (value xpathobjv, value iv)
{
CAMLparam2 (xpathobjv, iv);
- xmlXPathObjectPtr xpathobj = Xpathobj_val (xpathobjv);
+ xmlXPathObjectPtr xpathobj = Xpathobj_ptr_val (xpathobjv);
int i = Int_val (iv);
if (i < 0 || i >= xpathobj->nodesetval->nodeNr)
@@ -250,7 +253,7 @@ value
v2v_xml_xpathctx_set_node_ptr (value xpathctxv, value nodev)
{
CAMLparam2 (xpathctxv, nodev);
- xmlXPathContextPtr xpathctx = Xpathctx_val (xpathctxv);
+ xmlXPathContextPtr xpathctx = Xpathctx_ptr_val (xpathctxv);
xmlNodePtr node = (xmlNodePtr) nodev;
xpathctx->node = node;
diff --git a/v2v/xml.ml b/v2v/xml.ml
index f521c03..9d37d92 100644
--- a/v2v/xml.ml
+++ b/v2v/xml.ml
@@ -20,59 +20,85 @@
type doc
type node_ptr
-type xpathctx
-type xpathobj
+type xpathctx_ptr
+type xpathobj_ptr
-(* Since node is owned by doc, we have to make that explicit to the
- * garbage collector.
+(* At the C level, various objects "own" other objects. We have to
+ * make that ownership explicit to the garbage collector, else we could
+ * end up freeing an object before all the C references to it are
+ * freed.
*)
+type xpathctx = doc * xpathctx_ptr
+type xpathobj = xpathctx * xpathobj_ptr
type node = doc * node_ptr
-external parse_memory : string -> doc = "v2v_xml_parse_memory"
-external copy_doc : doc -> recursive:bool -> doc = "v2v_xml_copy_doc"
+external free_doc : doc -> unit = "v2v_xml_free_doc"
+external _parse_memory : string -> doc = "v2v_xml_parse_memory"
+let parse_memory xml =
+ let doc = _parse_memory xml in
+ Gc.finalise free_doc doc;
+ doc
+external _copy_doc : doc -> recursive:bool -> doc = "v2v_xml_copy_doc"
+let copy_doc doc ~recursive =
+ let copy = _copy_doc doc ~recursive in
+ Gc.finalise free_doc copy;
+ copy
external to_string : doc -> format:bool -> string = "v2v_xml_to_string"
-external xpath_new_context : doc -> xpathctx = "v2v_xml_xpath_new_context"
-external xpath_eval_expression : xpathctx -> string -> xpathobj = "v2v_xml_xpath_eval_expression"
-external xpath_register_ns : xpathctx -> string -> string -> unit = "v2v_xml_xpath_register_ns"
+external xpathctx_ptr_free_context : xpathctx_ptr -> unit = "v2v_xml_xpathctx_ptr_free_context"
+external xpath_new_context_ptr : doc -> xpathctx_ptr = "v2v_xml_xpath_new_context_ptr"
+let xpath_new_context doc =
+ let xpathctx_ptr = xpath_new_context_ptr doc in
+ Gc.finalise xpathctx_ptr_free_context xpathctx_ptr;
+ doc, xpathctx_ptr
+external xpathctx_ptr_register_ns : xpathctx_ptr -> string -> string -> unit = "v2v_xml_xpathctx_ptr_register_ns"
+let xpath_register_ns (_, xpathctx_ptr) prefix uri =
+ xpathctx_ptr_register_ns xpathctx_ptr prefix uri
+external xpathobj_ptr_free_object : xpathobj_ptr -> unit = "v2v_xml_xpathobj_ptr_free_object"
+external xpathctx_ptr_eval_expression : xpathctx_ptr -> string -> xpathobj_ptr = "v2v_xml_xpathctx_ptr_eval_expression"
+let xpath_eval_expression ((_, xpathctx_ptr) as xpathctx) expr =
+ let xpathobj_ptr = xpathctx_ptr_eval_expression xpathctx_ptr expr in
+ Gc.finalise xpathobj_ptr_free_object xpathobj_ptr;
+ xpathctx, xpathobj_ptr
-external xpathobj_nr_nodes : xpathobj -> int = "v2v_xml_xpathobj_nr_nodes"
-external xpathobj_get_node_ptr : xpathobj -> int -> node_ptr = "v2v_xml_xpathobj_get_node_ptr"
-let xpathobj_node doc xpathobj i =
- let n = xpathobj_get_node_ptr xpathobj i in
- (doc, n)
+external xpathobj_ptr_nr_nodes : xpathobj_ptr -> int = "v2v_xml_xpathobj_ptr_nr_nodes"
+let xpathobj_nr_nodes (_, xpathobj_ptr) =
+ xpathobj_ptr_nr_nodes xpathobj_ptr
-external xpathctx_set_node_ptr : xpathctx -> node_ptr -> unit = "v2v_xml_xpathctx_set_node_ptr"
-let xpathctx_set_current_context xpathctx (_, node) =
- xpathctx_set_node_ptr xpathctx node
+external xpathobj_ptr_get_node_ptr : xpathobj_ptr -> int -> node_ptr = "v2v_xml_xpathobj_ptr_get_node_ptr"
+let xpathobj_node ((doc, _), xpathobj_ptr) i =
+ doc, xpathobj_ptr_get_node_ptr xpathobj_ptr i
+
+external xpathctx_ptr_set_node_ptr : xpathctx_ptr -> node_ptr -> unit = "v2v_xml_xpathctx_set_node_ptr"
+let xpathctx_set_current_context (_, xpathctx_ptr) (_, node_ptr) =
+ xpathctx_ptr_set_node_ptr xpathctx_ptr node_ptr
external node_ptr_name : node_ptr -> string = "v2v_xml_node_ptr_name"
-let node_name (_, node) = node_ptr_name node
+let node_name (_, node_ptr) = node_ptr_name node_ptr
external node_ptr_as_string : doc -> node_ptr -> string = "v2v_xml_node_ptr_as_string"
-let node_as_string (doc, node) =
- node_ptr_as_string doc node
+let node_as_string (doc, node_ptr) = node_ptr_as_string doc node_ptr
external node_ptr_set_content : node_ptr -> string -> unit = "v2v_xml_node_ptr_set_content"
-let node_set_content (doc, node) = node_ptr_set_content node
+let node_set_content (doc, node_ptr) = node_ptr_set_content node_ptr
external node_ptr_set_prop : node_ptr -> string -> string -> unit = "v2v_xml_node_ptr_set_prop"
-let set_prop (doc, node) = node_ptr_set_prop node
+let set_prop (doc, node_ptr) = node_ptr_set_prop node_ptr
external node_ptr_unlink_node : node_ptr -> unit = "v2v_xml_node_ptr_unlink_node"
-let unlink_node (doc, node) = node_ptr_unlink_node node
+let unlink_node (doc, node_ptr) = node_ptr_unlink_node node_ptr
type uri = {
- uri_scheme : string option;
- uri_opaque : string option;
- uri_authority : string option;
- uri_server : string option;
- uri_user : string option;
- uri_port : int;
- uri_path : string option;
- uri_fragment : string option;
- uri_query_raw : string option;
-}
+ uri_scheme : string option;
+ uri_opaque : string option;
+ uri_authority : string option;
+ uri_server : string option;
+ uri_user : string option;
+ uri_port : int;
+ uri_path : string option;
+ uri_fragment : string option;
+ uri_query_raw : string option;
+ }
external parse_uri : string -> uri = "v2v_xml_parse_uri"
diff --git a/v2v/xml.mli b/v2v/xml.mli
index 8029813..a3a9c01 100644
--- a/v2v/xml.mli
+++ b/v2v/xml.mli
@@ -40,7 +40,7 @@ val xpath_register_ns : xpathctx -> string -> string -> unit
val xpathobj_nr_nodes : xpathobj -> int
(** Get the number of nodes in the nodeset of the xmlXPathObjectPtr. *)
-val xpathobj_node : doc -> xpathobj -> int -> node
+val xpathobj_node : xpathobj -> int -> node
(** Get the i'th node in the nodeset of the xmlXPathObjectPtr. *)
val xpathctx_set_current_context : xpathctx -> node -> unit
--
2.3.1
9 years, 3 months