[PATCH] doc: add missing ms-dos fs section in set_label
by Chen Hanxiao
Signed-off-by: Chen Hanxiao <chenhanxiao(a)cn.fujitsu.com>
---
generator/actions.ml | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/generator/actions.ml b/generator/actions.ml
index 92f80d2..35f30d5 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -9919,7 +9919,7 @@ Set the filesystem label on C<mountable> to C<label>.
Only some filesystem types support labels, and libguestfs supports
setting labels on only a subset of these.
-=over 4
+=over 5
=item ext2, ext3, ext4
@@ -9941,6 +9941,9 @@ not allowed. Setting the label on a btrfs subvolume will set the
label on its parent filesystem. The filesystem must not be mounted
when trying to set the label.
+=item fat
+The label is limited to 11 bytes.
+
=back
To read the label on a filesystem, call C<guestfs_vfs_label>." };
--
2.1.0
9 years, 4 months
[PATCH] uuids: return ENOTSUP if could not set UUID for specific fs
by Chen Hanxiao
Signed-off-by: Chen Hanxiao <chenhanxiao(a)cn.fujitsu.com>
---
daemon/uuids.c | 6 ++----
generator/actions.ml | 3 +++
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/daemon/uuids.c b/daemon/uuids.c
index 20eabe3..00c47d8 100644
--- a/daemon/uuids.c
+++ b/daemon/uuids.c
@@ -77,11 +77,9 @@ do_set_uuid (const char *device, const char *uuid)
else if (STREQ (vfs_type, "btrfs"))
r = btrfs_set_uuid (device, uuid);
- else {
- reply_with_error ("don't know how to set the UUID for '%s' filesystems",
+ else
+ NOT_SUPPORTED(-1, "don't know how to set the UUID for '%s' filesystems",
vfs_type);
- r = -1;
- }
return r;
}
diff --git a/generator/actions.ml b/generator/actions.ml
index 92f80d2..7ecaf98 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -11804,6 +11804,9 @@ parameter. In future we may allow other flags to be adjusted." };
shortdesc = "set the filesystem UUID";
longdesc = "\
Set the filesystem UUID on C<device> to C<uuid>.
+If this fails and the errno is ENOTSUP,
+means that there is no support for changing the UUID
+for the type of the specified filesystem.
Only some filesystem types support setting UUIDs.
--
2.1.0
9 years, 4 months
[PATCH v6] New API: set_uuid_random
by Chen Hanxiao
Signed-off-by: Chen Hanxiao <chenhanxiao(a)cn.fujitsu.com>
---
v6: rename ext_set_e2uuid_random to ext_set_uuid_random
improve longdesc of set_uuid_random
v5: 1. improve testcases
2. rename set_uuid_random to ext_set_uuid_random
3. drop swap_set_uuid_random,
call swap_set_uuid + get_random_uuid
daemon/btrfs.c | 19 +++++++++++++++++++
daemon/daemon.h | 3 +++
daemon/ext2.c | 6 ++++++
daemon/uuids.c | 32 ++++++++++++++++++++++++++++++++
daemon/xfs.c | 7 +++++++
generator/actions.ml | 19 +++++++++++++++++++
src/MAX_PROC_NR | 2 +-
tests/btrfs/test-btrfs-misc.pl | 14 ++++++++++++++
8 files changed, 101 insertions(+), 1 deletion(-)
diff --git a/daemon/btrfs.c b/daemon/btrfs.c
index 28a48cf..8fcfd81 100644
--- a/daemon/btrfs.c
+++ b/daemon/btrfs.c
@@ -872,6 +872,25 @@ btrfs_set_uuid (const char *device, const char *uuid)
return 0;
}
+int
+btrfs_set_uuid_random (const char *device)
+{
+ CLEANUP_FREE char *err = NULL;
+ int r;
+ int has_uuid_opts = test_btrfstune_uuid_opt();
+
+ if (has_uuid_opts <= 0)
+ NOT_SUPPORTED(-1, "btrfs filesystems' UUID cannot be changed");
+
+ r = commandr (NULL, &err, str_btrfstune, "-f", "-u", device, NULL);
+ if (r == -1) {
+ reply_with_error ("%s: %s", device, err);
+ return -1;
+ }
+
+ return 0;
+}
+
/* Takes optional arguments, consult optargs_bitmask. */
int
do_btrfs_fsck (const char *device, int64_t superblock, int repair)
diff --git a/daemon/daemon.h b/daemon/daemon.h
index f8441d1..a4a4361 100644
--- a/daemon/daemon.h
+++ b/daemon/daemon.h
@@ -223,6 +223,7 @@ extern int sync_disks (void);
/* Confirmed this is true up to ext4 from the Linux sources. */
#define EXT2_LABEL_MAX 16
extern int fstype_is_extfs (const char *fstype);
+extern int ext_set_uuid_random (const char *device);
/*-- in blkid.c --*/
extern char *get_blkid_tag (const char *device, const char *tag);
@@ -265,6 +266,7 @@ extern int copy_xattrs (const char *src, const char *dest);
/* Documented in xfs_admin(8). */
#define XFS_LABEL_MAX 12
extern int xfs_set_uuid (const char *device, const char *uuid);
+extern int xfs_set_uuid_random (const char *device);
/*-- debug-bmap.c --*/
extern char *debug_bmap (const char *subcmd, size_t argc, char *const *const argv);
@@ -274,6 +276,7 @@ extern char *debug_bmap_device (const char *subcmd, size_t argc, char *const *co
/*-- in btrfs.c --*/
extern char *btrfs_get_label (const char *device);
extern int btrfs_set_uuid (const char *device, const char *uuid);
+extern int btrfs_set_uuid_random (const char *device);
/*-- in ntfs.c --*/
extern char *ntfs_get_label (const char *device);
diff --git a/daemon/ext2.c b/daemon/ext2.c
index 8ef6d5f..93b530b 100644
--- a/daemon/ext2.c
+++ b/daemon/ext2.c
@@ -159,6 +159,12 @@ do_set_e2uuid (const char *device, const char *uuid)
return 0;
}
+int
+ext_set_uuid_random (const char *device)
+{
+ return do_set_e2uuid (device, "random");
+}
+
char *
do_get_e2uuid (const char *device)
{
diff --git a/daemon/uuids.c b/daemon/uuids.c
index 5238f3e..20eabe3 100644
--- a/daemon/uuids.c
+++ b/daemon/uuids.c
@@ -85,3 +85,35 @@ do_set_uuid (const char *device, const char *uuid)
return r;
}
+
+int
+do_set_uuid_random (const char *device)
+{
+ int r;
+
+ /* How we set the UUID depends on the filesystem type. */
+ CLEANUP_FREE char *vfs_type = get_blkid_tag (device, "TYPE");
+ if (vfs_type == NULL)
+ return -1;
+
+ CLEANUP_FREE char *uuid_random = get_random_uuid ();
+ if (uuid_random == NULL)
+ return -1;
+
+ if (fstype_is_extfs (vfs_type))
+ r = ext_set_uuid_random (device);
+
+ else if (STREQ (vfs_type, "xfs"))
+ r = xfs_set_uuid_random (device);
+
+ else if (STREQ (vfs_type, "swap"))
+ r = swap_set_uuid (device, uuid_random);
+
+ else if (STREQ (vfs_type, "btrfs"))
+ r = btrfs_set_uuid_random (device);
+
+ else
+ NOT_SUPPORTED(-1, "don't know how to set the random UUID for '%s' filesystems",
+ vfs_type);
+ return r;
+}
diff --git a/daemon/xfs.c b/daemon/xfs.c
index fb7acb4..2c93311 100644
--- a/daemon/xfs.c
+++ b/daemon/xfs.c
@@ -463,6 +463,13 @@ xfs_set_uuid (const char *device, const char *uuid)
}
int
+xfs_set_uuid_random (const char *device)
+{
+ optargs_bitmask = GUESTFS_XFS_ADMIN_UUID_BITMASK;
+ return do_xfs_admin (device, 0, 0, 0, 0, 0, NULL, "generate");
+}
+
+int
do_xfs_admin (const char *device,
int extunwritten, int imgfile, int v2log,
int projid32bit,
diff --git a/generator/actions.ml b/generator/actions.ml
index b1865e0..fb4a174 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -12636,6 +12636,25 @@ 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>." };
+ { defaults with
+ name = "set_uuid_random"; added = (1, 29, 48);
+ style = RErr, [Device "device"], [];
+ proc_nr = Some 456;
+ tests = [
+ InitBasicFS, Always, TestRun (
+ [["set_uuid_random"; "/dev/sda1"]]), [];
+ ];
+ shortdesc = "set a random UUID for the filesystem";
+ longdesc = "\
+Set the filesystem UUID on C<device> to a random UUID.
+If this fails and the errno is ENOTSUP,
+means that there is no support for changing the UUID
+for the type of the specified filesystem.
+
+Only some filesystem types support setting UUIDs.
+
+To read the UUID on a filesystem, call C<guestfs_vfs_uuid>." };
+
]
(* Non-API meta-commands available only in guestfish.
diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR
index 4930863..8d38505 100644
--- a/src/MAX_PROC_NR
+++ b/src/MAX_PROC_NR
@@ -1 +1 @@
-455
+456
diff --git a/tests/btrfs/test-btrfs-misc.pl b/tests/btrfs/test-btrfs-misc.pl
index b637b17..0a8e942 100755
--- a/tests/btrfs/test-btrfs-misc.pl
+++ b/tests/btrfs/test-btrfs-misc.pl
@@ -67,5 +67,19 @@ if ($@) {
unless $uuid eq "12345678-1234-1234-1234-123456789012";
}
+# Setting btrfs random UUID.
+eval {
+ $g->set_uuid_random ("/dev/sda1")
+};
+
+if ($@) {
+ my $err = $g->last_errno ();
+ if ($err == Errno::ENOTSUP()) {
+ warn "$0: skipping test for btrfs UUID change feature is not available";
+ } else {
+ die $@;
+ }
+}
+
$g->shutdown ();
$g->close ();
--
2.1.0
9 years, 4 months
libguestfs error: need help troubleshooting
by Deepti Navale
Hi,
I'm trying to manually create a rhel7 image using the qemu-img and virt-install commands. I'm re-testing a procedure I previously wrote with the new grub commands that a customer suggested we add in. This procedure is available at: http://file.bne.redhat.com/dnavale/docs/review/RH-guides/AG-020715/#sect-...
As in the procedure, I'm able to run all steps successfully until step 12. When I run the virt-sysprep command, I get the following errors:
--------------
➜ RHEL7 sudo virt-sysprep -d rhel7 --format qcow2
[ 0.0] Examining the guest ...
Fatal error: exception Guestfs.Error("qemu-img: /tmp/libguestfsStQSH1/overlay1: qemu-img exited with error status 1.
To see full error messages you may need to enable debugging.
See http://libguestfs.org/guestfs-faq.1.html#debugging-libguestfs")
--------------
Then I updated the qemu-img package and started getting this error:
--------------
➜ RHEL7 sudo virt-sysprep -d rhel7
[ 0.0] Examining the guest ...
Fatal error: exception Guestfs.Error("/usr/bin/supermin exited with error status 1.
To see full error messages you may need to enable debugging.
See http://libguestfs.org/guestfs-faq.1.html#debugging-libguestfs")
--------------
I'm using the following packages: libguestfs-tools-c-1.26.10-1.fc20.x86_64, libguestfs-1.26.10-1.fc20.x86_64 on a Fedora20 machine. And I used 'yum install -y libguestfs-tools-c' command to install the package.
The complete, unedited output of the libguestfs-test-tool command is as below:
➜ RHEL7 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=/home/deepti/bin:/usr/lib64/qt-3.3/bin:/usr/local/bin:/usr/bin:/bin:/usr/games:/home/deepti/bin:/usr/local/sbin:/usr/sbin
SELinux: Enforcing
libguestfs: trace: add_drive_scratch 104857600
libguestfs: trace: get_tmpdir
libguestfs: trace: get_tmpdir = "/tmp"
libguestfs: trace: disk_create "/tmp/libguestfss2QPvp/scratch.1" "raw" 104857600
libguestfs: trace: disk_create = 0
libguestfs: trace: add_drive "/tmp/libguestfss2QPvp/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-kvm"
guestfs_get_hv: /usr/bin/qemu-kvm
libguestfs: trace: get_memsize
libguestfs: trace: get_memsize = 500
guestfs_get_memsize: 500
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: x86_64
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.26.10fedora=20,release=1.fc20,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/libguestfss2QPvp
libguestfs: launch: umask=0002
libguestfs: launch: euid=1000
libguestfs: libvirt version = 1001003 (1.1.3)
libguestfs: guest random name = guestfs-5v6jdpn1di0f0280
libguestfs: [00000ms] connect to libvirt
libguestfs: opening libvirt handle: URI = qemu:///session, auth = default+wrapper, flags = 0
libguestfs: successfully opened libvirt handle: conn = 0x7f7fa5839a20
libguestfs: qemu version (reported by libvirt) = 1006002 (1.6.2)
libguestfs: [00393ms] get libvirt capabilities
libguestfs: [00401ms] parsing capabilities XML
libguestfs: [00401ms] build appliance
libguestfs: trace: get_cachedir
libguestfs: trace: get_cachedir = "/var/tmp"
libguestfs: [00402ms] begin building supermin appliance
libguestfs: [00402ms] run supermin
libguestfs: command: run: /usr/bin/supermin
libguestfs: command: run: \ --build
libguestfs: command: run: \ --verbose
libguestfs: command: run: \ --if-newer
libguestfs: command: run: \ --lock /var/tmp/.guestfs-1000/lock
libguestfs: command: run: \ --copy-kernel
libguestfs: command: run: \ -f ext2
libguestfs: command: run: \ --host-cpu x86_64
libguestfs: command: run: \ /usr/lib64/guestfs/supermin.d
libguestfs: command: run: \ -o /var/tmp/.guestfs-1000/appliance.d
supermin: version: 5.1.9
supermin: rpm: detected RPM version 4.11
supermin: package handler: fedora/rpm
supermin: acquiring lock on /var/tmp/.guestfs-1000/lock
supermin: build: /usr/lib64/guestfs/supermin.d
supermin: build: visiting /usr/lib64/guestfs/supermin.d/base.tar.gz type gzip base image (tar)
tar: ./etc/tcsd.conf: Cannot write: No space left on device
tar: ./etc/aliases: Cannot write: No space left on device
tar: ./etc/bashrc: Cannot write: No space left on device
tar: ./etc/csh.cshrc: Cannot write: No space left on device
tar: ./etc/csh.login: Cannot write: No space left on device
tar: ./etc/filesystems: Cannot write: No space left on device
tar: ./etc/group: Cannot write: No space left on device
tar: ./etc/host.conf: Cannot write: No space left on device
tar: ./etc/hosts: Cannot write: No space left on device
tar: ./etc/hosts.allow: Cannot write: No space left on device
tar: ./etc/hosts.deny: Cannot write: No space left on device
tar: ./etc/inputrc: Cannot write: No space left on device
tar: ./etc/passwd: Cannot write: No space left on device
tar: ./etc/printcap: Cannot write: No space left on device
tar: ./etc/profile: Cannot write: No space left on device
tar: ./etc/protocols: Cannot write: No space left on device
tar: ./etc/securetty: Cannot write: No space left on device
tar: ./etc/services: Cannot write: No space left on device
tar: ./etc/shells: Cannot write: No space left on device
tar: ./etc/pki/nssdb/cert8.db: Cannot write: No space left on device
tar: ./etc/pki/nssdb/cert9.db: Cannot write: No space left on device
tar: ./etc/pki/nssdb/key3.db: Cannot write: No space left on device
tar: ./etc/pki/nssdb/key4.db: Cannot write: No space left on device
tar: ./etc/pki/nssdb/pkcs11.txt: Cannot write: No space left on device
tar: ./etc/pki/nssdb/secmod.db: Cannot write: No space left on device
tar: ./etc/selinux/semanage.conf: Cannot write: No space left on device
tar: ./etc/pki/ca-trust/ca-legacy.conf: Cannot write: No space left on device
tar: ./etc/default/useradd: Cannot write: No space left on device
tar: ./etc/login.defs: Cannot write: No space left on device
tar: ./etc/pam.d/config-util: Cannot write: No space left on device
tar: ./etc/pam.d/fingerprint-auth: Cannot write: No space left on device
tar: ./etc/pam.d/other: Cannot write: No space left on device
tar: ./etc/pam.d/password-auth: Cannot write: No space left on device
tar: ./etc/pam.d/postlogin: Cannot write: No space left on device
tar: ./etc/pam.d/smartcard-auth: Cannot write: No space left on device
tar: ./etc/pam.d/system-auth: Cannot write: No space left on device
tar: ./etc/security/access.conf: Cannot write: No space left on device
tar: ./etc/security/chroot.conf: Cannot write: No space left on device
tar: ./etc/security/console.handlers: Cannot write: No space left on device
tar: ./etc/security/console.perms: Cannot write: No space left on device
tar: ./etc/security/group.conf: Cannot write: No space left on device
tar: ./etc/security/limits.conf: Cannot write: No space left on device
tar: ./etc/security/limits.d/90-nproc.conf: Cannot write: No space left on device
tar: ./etc/security/namespace.conf: Cannot write: No space left on device
tar: ./etc/security/namespace.init: Cannot write: No space left on device
tar: ./etc/security/pam_env.conf: Cannot write: No space left on device
tar: ./etc/security/sepermit.conf: Cannot write: No space left on device
tar: ./etc/security/time.conf: Cannot write: No space left on device
tar: ./etc/pki/tls/openssl.cnf: Cannot write: No space left on device
tar: ./etc/ssh/moduli: Cannot write: No space left on device
tar: ./etc/openldap/ldap.conf: Cannot write: No space left on device
tar: ./etc/mtools.conf: Cannot write: No space left on device
tar: ./etc/libuser.conf: Cannot write: No space left on device
tar: ./etc/security/pwquality.conf: Cannot write: No space left on device
tar: ./etc/krb5.conf: Cannot write: No space left on device
tar: ./etc/sysconfig/ip6tables-config: Cannot write: No space left on device
tar: ./etc/sysconfig/iptables-config: Cannot write: No space left on device
tar: ./etc/xtables/connlabel.conf: Cannot write: No space left on device
tar: ./usr/share/info/dir: Cannot write: No space left on device
tar: ./etc/groff/site-tmac/man.local: Cannot write: No space left on device
tar: ./etc/groff/site-tmac/mdoc.local: Cannot write: No space left on device
tar: ./etc/default/nss: Cannot write: No space left on device
tar: ./etc/ld.so.conf: Cannot write: No space left on device
tar: ./etc/nsswitch.conf: Cannot write: No space left on device
tar: ./etc/rpc: Cannot write: No space left on device
tar: ./usr/lib64/gconv/gconv-modules: Cannot write: No space left on device
tar: ./etc/fuse.conf: Cannot write: No space left on device
tar: ./etc/dracut.conf: Cannot write: No space left on device
tar: ./etc/dbus-1/session.conf: Cannot write: No space left on device
tar: ./etc/dbus-1/system.conf: Cannot write: No space left on device
tar: ./etc/libaudit.conf: Cannot write: No space left on device
tar: ./etc/pam.d/chfn: Cannot write: No space left on device
tar: ./etc/pam.d/chsh: Cannot write: No space left on device
tar: ./etc/pam.d/login: Cannot write: No space left on device
tar: ./etc/pam.d/remote: Cannot write: No space left on device
tar: ./etc/pam.d/runuser: Cannot write: No space left on device
tar: ./etc/pam.d/runuser-l: Cannot write: No space left on device
tar: ./etc/pam.d/su: Cannot write: No space left on device
tar: ./etc/pam.d/su-l: Cannot write: No space left on device
tar: ./usr/lib/udev/rules.d/60-raw.rules: Cannot write: No space left on device
tar: ./etc/rsyncd.conf: Cannot write: No space left on device
tar: ./etc/sysconfig/rsyncd: Cannot write: No space left on device
tar: ./etc/cron.d/raid-check: Cannot write: No space left on device
tar: ./etc/sysconfig/raid-check: Cannot write: No space left on device
tar: ./usr/lib/tmpfiles.d/mdadm.conf: Cannot write: No space left on device
tar: ./etc/lvm/lvm.conf: Cannot write: No space left on device
tar: ./etc/GREP_COLORS: Cannot write: No space left on device
tar: ./etc/profile.d/colorgrep.csh: Cannot write: No space left on device
tar: ./etc/profile.d/colorgrep.sh: Cannot write: No space left on device
tar: ./etc/magic: Cannot write: No space left on device
tar: ./etc/DIR_COLORS: Cannot write: No space left on device
tar: ./etc/DIR_COLORS.256color: Cannot write: No space left on device
tar: ./etc/DIR_COLORS.lightbgcolor: Cannot write: No space left on device
tar: ./etc/profile.d/colorls.csh: Cannot write: No space left on device
tar: ./etc/profile.d/colorls.sh: Cannot write: No space left on device
tar: ./etc/skel/.bash_logout: Cannot write: No space left on device
tar: ./etc/skel/.bash_profile: Cannot write: No space left on device
tar: ./etc/skel/.bashrc: Cannot write: No space left on device
tar: ./etc/sysconfig/zfs-fuse: Cannot write: No space left on device
tar: ./etc/virc: Cannot write: No space left on device
tar: ./etc/dbus-1/system.d/org.freedesktop.hostname1.conf: Cannot write: No space left on device
tar: ./etc/dbus-1/system.d/org.freedesktop.locale1.conf: Cannot write: No space left on device
tar: ./etc/dbus-1/system.d/org.freedesktop.login1.conf: Cannot write: No space left on device
tar: ./etc/dbus-1/system.d/org.freedesktop.machine1.conf: Cannot write: No space left on device
tar: ./etc/dbus-1/system.d/org.freedesktop.systemd1.conf: Cannot write: No space left on device
tar: ./etc/dbus-1/system.d/org.freedesktop.timedate1.conf: Cannot write: No space left on device
tar: ./etc/pam.d/systemd-user: Cannot write: No space left on device
tar: ./etc/rsyslog.d/listen.conf: Cannot write: No space left on device
tar: ./etc/systemd/bootchart.conf: Cannot write: No space left on device
tar: ./etc/systemd/journald.conf: Cannot write: No space left on device
tar: ./etc/systemd/logind.conf: Cannot write: No space left on device
tar: ./etc/systemd/system.conf: Cannot write: No space left on device
tar: ./etc/systemd/user.conf: Cannot write: No space left on device
tar: ./etc/udev/udev.conf: Cannot write: No space left on device
tar: ./etc/yum/protected.d/systemd.conf: Cannot write: No space left on device
tar: ./etc/ssh/ssh_config: Cannot write: No space left on device
tar: ./etc/nilfs_cleanerd.conf: Cannot write: No space left on device
tar: ./etc/sysconfig/rdisc: Cannot write: No space left on device
tar: ./etc/iproute2/ematch_map: Cannot write: No space left on device
tar: ./etc/iproute2/group: Cannot write: No space left on device
tar: ./etc/iproute2/rt_dsfield: Cannot write: No space left on device
tar: ./etc/iproute2/rt_protos: Cannot write: No space left on device
tar: ./etc/iproute2/rt_realms: Cannot write: No space left on device
tar: ./etc/iproute2/rt_scopes: Cannot write: No space left on device
tar: ./etc/iproute2/rt_tables: Cannot write: No space left on device
tar: ./etc/sysconfig/cbq/avpkt: Cannot write: No space left on device
tar: ./etc/sysconfig/cbq/cbq-0000.example: Cannot write: No space left on device
tar: ./etc/e2fsck.conf: Cannot write: No space left on device
tar: ./etc/mke2fs.conf: Cannot write: No space left on device
tar: Exiting with failure status due to previous errors
supermin: zcat '/usr/lib64/guestfs/supermin.d/base.tar.gz' | tar -C '/tmp/superminef2565.tmpdir/base.d' -xf -: command failed, see earlier errors
libguestfs: error: /usr/bin/supermin 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 0x7f7fa5839320 (state 0)
libguestfs: command: run: rm
libguestfs: command: run: \ -rf /tmp/libguestfss2QPvp
Please help me resolve this issue and get a compatible rhel7 image that I can upload to OpenStack and create an instance from.
Thanks in advance,
Deepti
9 years, 4 months
[PATCH v2] Fix various -Wformat problems.
by Richard W.M. Jones
Updating gnulib has caused -Wformat-signedness to be enabled. This
has revealed many problems in C format strings. The fixes here fall
into the following main categories:
- Using %d with an unsigned parameter.
- %x and %o expect an unsigned argument.
- uid_t and gid_t are unsigned on Linux. The safe way to print these
is to cast them to uintmax_t and then print them using the %ju
modifier (see http://stackoverflow.com/a/1401581).
- Using %d to print an enum. Since enums may be either char or int,
I fixed this by casting the enum to int.
- strtol_error & lzma_ret are both unsigned types.
---
builder/pxzcat-c.c | 24 ++++++++++++------------
cat/filesystems.c | 2 +-
cat/ls.c | 5 +++--
daemon/ext2.c | 7 ++++++-
daemon/file.c | 2 +-
daemon/guestfsd.c | 3 ++-
daemon/parted.c | 5 +++--
daemon/proto.c | 14 ++++++++------
daemon/umask.c | 2 +-
daemon/zero.c | 2 +-
diff/diff.c | 7 ++++---
fish/alloc.c | 2 +-
fish/rc.c | 8 ++++----
generator/bindtests.ml | 2 +-
generator/daemon.ml | 4 ++--
generator/fish.ml | 17 +++++++++--------
make-fs/make-fs.c | 2 +-
p2v/main.c | 5 +++--
src/actions-support.c | 10 +++++-----
src/appliance.c | 6 +++---
src/fuse.c | 14 +++++++-------
src/handle.c | 2 +-
src/launch-libvirt.c | 3 ++-
src/launch.c | 2 +-
src/proto.c | 2 +-
test-tool/test-tool.c | 2 +-
26 files changed, 84 insertions(+), 70 deletions(-)
diff --git a/builder/pxzcat-c.c b/builder/pxzcat-c.c
index fb1a865..0c4a4be 100644
--- a/builder/pxzcat-c.c
+++ b/builder/pxzcat-c.c
@@ -298,7 +298,7 @@ parse_indexes (value filenamev, int fd)
/* Does the stream footer look reasonable? */
r = lzma_stream_footer_decode (&footer_flags, footer);
if (r != LZMA_OK) {
- fprintf (stderr, "invalid stream footer - error %d\n", r);
+ fprintf (stderr, "invalid stream footer - error %u\n", r);
caml_invalid_argument ("invalid stream footer");
}
@@ -317,7 +317,7 @@ parse_indexes (value filenamev, int fd)
/* Decode the index. */
r = lzma_index_decoder (&strm, &this_index, UINT64_MAX);
if (r != LZMA_OK) {
- fprintf (stderr, "invalid stream index - error %d\n", r);
+ fprintf (stderr, "invalid stream index - error %u\n", r);
caml_invalid_argument ("invalid stream index");
}
@@ -339,7 +339,7 @@ parse_indexes (value filenamev, int fd)
} while (r == LZMA_OK);
if (r != LZMA_STREAM_END) {
- fprintf (stderr, "could not parse index - error %d\n", r);
+ fprintf (stderr, "could not parse index - error %u\n", r);
caml_invalid_argument ("could not parse index");
}
@@ -356,14 +356,14 @@ parse_indexes (value filenamev, int fd)
r = lzma_stream_header_decode (&header_flags, header);
if (r != LZMA_OK) {
- fprintf (stderr, "invalid stream header - error %d\n", r);
+ fprintf (stderr, "invalid stream header - error %u\n", r);
caml_invalid_argument ("invalid stream header");
}
/* Header and footer of the stream should be equal. */
r = lzma_stream_flags_compare (&header_flags, &footer_flags);
if (r != LZMA_OK) {
- fprintf (stderr, "header and footer of stream are not equal - error %d\n",
+ fprintf (stderr, "header and footer of stream are not equal - error %u\n",
r);
caml_invalid_argument ("header and footer of stream are not equal");
}
@@ -371,7 +371,7 @@ parse_indexes (value filenamev, int fd)
/* Store the decoded stream flags in this_index. */
r = lzma_index_stream_flags (this_index, &footer_flags);
if (r != LZMA_OK) {
- fprintf (stderr, "cannot read stream_flags from index - error %d\n", r);
+ fprintf (stderr, "cannot read stream_flags from index - error %u\n", r);
caml_invalid_argument ("cannot read stream_flags from index");
}
@@ -380,14 +380,14 @@ parse_indexes (value filenamev, int fd)
*/
r = lzma_index_stream_padding (this_index, stream_padding);
if (r != LZMA_OK) {
- fprintf (stderr, "cannot set stream_padding in index - error %d\n", r);
+ fprintf (stderr, "cannot set stream_padding in index - error %u\n", r);
caml_invalid_argument ("cannot set stream_padding in index");
}
if (combined_index != NULL) {
r = lzma_index_cat (this_index, combined_index, NULL);
if (r != LZMA_OK) {
- fprintf (stderr, "cannot combine indexes - error %d\n", r);
+ fprintf (stderr, "cannot combine indexes - error %u\n", r);
caml_invalid_argument ("cannot combine indexes");
}
}
@@ -613,7 +613,7 @@ worker_thread (void *vp)
r = lzma_block_header_decode (&block, NULL, header);
if (r != LZMA_OK) {
- fprintf (stderr, "%s: invalid block header (error %d)\n",
+ fprintf (stderr, "%s: invalid block header (error %u)\n",
global->filename, r);
return &state->status;
}
@@ -624,7 +624,7 @@ worker_thread (void *vp)
r = lzma_block_compressed_size (&block, iter.block.unpadded_size);
if (r != LZMA_OK) {
fprintf (stderr,
- "%s: cannot calculate compressed size (error %d)\n",
+ "%s: cannot calculate compressed size (error %u)\n",
global->filename, r);
return &state->status;
}
@@ -635,7 +635,7 @@ worker_thread (void *vp)
/* Read the block data and uncompress it. */
r = lzma_block_decoder (&strm, &block);
if (r != LZMA_OK) {
- fprintf (stderr, "%s: invalid block (error %d)\n", global->filename, r);
+ fprintf (stderr, "%s: invalid block (error %u)\n", global->filename, r);
return &state->status;
}
@@ -684,7 +684,7 @@ worker_thread (void *vp)
break;
if (r != LZMA_OK) {
fprintf (stderr,
- "%s: could not parse block data (error %d)\n",
+ "%s: could not parse block data (error %u)\n",
global->filename, r);
return &state->status;
}
diff --git a/cat/filesystems.c b/cat/filesystems.c
index 44defe0..0e64e00 100644
--- a/cat/filesystems.c
+++ b/cat/filesystems.c
@@ -868,7 +868,7 @@ write_row (const char *name, const char *type,
strings[len++] = vfs_label;
if ((columns & COLUMN_MBR)) {
if (mbr_id >= 0) {
- snprintf (mbr_id_str, sizeof mbr_id_str, "%02x", mbr_id);
+ snprintf (mbr_id_str, sizeof mbr_id_str, "%02x", (unsigned) mbr_id);
strings[len++] = mbr_id_str;
} else
strings[len++] = NULL;
diff --git a/cat/ls.c b/cat/ls.c
index 3bced54..987dcef 100644
--- a/cat/ls.c
+++ b/cat/ls.c
@@ -702,7 +702,7 @@ output_int64_perms (int64_t i)
{
next_field ();
/* csv doesn't need escaping */
- if (printf ("%04" PRIo64, i) < 0) {
+ if (printf ("%04" PRIo64, (uint64_t) i) < 0) {
perror ("printf");
exit (EXIT_FAILURE);
}
@@ -774,7 +774,8 @@ output_int64_dev (int64_t i)
next_field ();
/* csv doesn't need escaping */
- if (printf ("%d:%d", major (dev), minor (dev)) < 0) {
+ if (printf ("%ju:%ju",
+ (uintmax_t) major (dev), (uintmax_t) minor (dev)) < 0) {
perror ("printf");
exit (EXIT_FAILURE);
}
diff --git a/daemon/ext2.c b/daemon/ext2.c
index 8ef6d5f..9142a38 100644
--- a/daemon/ext2.c
+++ b/daemon/ext2.c
@@ -780,11 +780,16 @@ do_get_e2generation (const char *filename)
return -1;
}
- if (sscanf (out, "%" SCNu64, &ret) != 1) {
+ if (sscanf (out, "%" SCNi64, &ret) != 1) {
reply_with_error ("cannot parse output from '%s' command: %s",
"lsattr", out);
return -1;
}
+ if (ret < 0) {
+ reply_with_error ("unexpected negative number from '%s' command: %s",
+ "lsattr", out);
+ return -1;
+ }
return ret;
}
diff --git a/daemon/file.c b/daemon/file.c
index bb3b3c1..c609a01 100644
--- a/daemon/file.c
+++ b/daemon/file.c
@@ -140,7 +140,7 @@ do_chmod (int mode, const char *path)
CHROOT_OUT;
if (r == -1) {
- reply_with_perror ("%s: 0%o", path, mode);
+ reply_with_perror ("%s: 0%o", path, (unsigned) mode);
return -1;
}
diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c
index 7f4b2f2..ee0aa43 100644
--- a/daemon/guestfsd.c
+++ b/daemon/guestfsd.c
@@ -224,7 +224,8 @@ main (int argc, char *argv[])
exit (EXIT_SUCCESS);
default:
- fprintf (stderr, "guestfsd: unexpected command line option 0x%x\n", c);
+ fprintf (stderr, "guestfsd: unexpected command line option 0x%x\n",
+ (unsigned) c);
exit (EXIT_FAILURE);
}
}
diff --git a/daemon/parted.c b/daemon/parted.c
index b516067..cb6c486 100644
--- a/daemon/parted.c
+++ b/daemon/parted.c
@@ -752,7 +752,7 @@ do_part_get_mbr_id (const char *device, int partnum)
udev_settle ();
/* It's printed in hex ... */
- int id;
+ unsigned id;
if (sscanf (out, "%x", &id) != 1) {
reply_with_error ("sfdisk --print-id: cannot parse output: %s", out);
return -1;
@@ -775,7 +775,8 @@ do_part_set_mbr_id (const char *device, int partnum, int idbyte)
snprintf (partnum_str, sizeof partnum_str, "%d", partnum);
char idbyte_str[16];
- snprintf (idbyte_str, sizeof partnum_str, "%x", idbyte); /* NB: hex */
+ /* NB: hex */
+ snprintf (idbyte_str, sizeof partnum_str, "%x", (unsigned) idbyte);
CLEANUP_FREE char *err = NULL;
int r;
diff --git a/daemon/proto.c b/daemon/proto.c
index 7ae8c66..df63bfd 100644
--- a/daemon/proto.c
+++ b/daemon/proto.c
@@ -157,19 +157,20 @@ main_loop (int _sock)
/* Check the version etc. */
if (hdr.prog != GUESTFS_PROGRAM) {
- reply_with_error ("wrong program (%d)", hdr.prog);
+ reply_with_error ("wrong program (%u)", hdr.prog);
goto cont;
}
if (hdr.vers != GUESTFS_PROTOCOL_VERSION) {
- reply_with_error ("wrong protocol version (%d)", hdr.vers);
+ reply_with_error ("wrong protocol version (%u)", hdr.vers);
goto cont;
}
if (hdr.direction != GUESTFS_DIRECTION_CALL) {
- reply_with_error ("unexpected message direction (%d)", hdr.direction);
+ reply_with_error ("unexpected message direction (%d)",
+ (int) hdr.direction);
goto cont;
}
if (hdr.status != GUESTFS_STATUS_OK) {
- reply_with_error ("unexpected message status (%d)", hdr.status);
+ reply_with_error ("unexpected message status (%d)", (int) hdr.status);
goto cont;
}
@@ -444,8 +445,9 @@ receive_file (receive_cb cb, void *opaque)
if (verbose)
fprintf (stderr,
- "guestfsd: receive_file: got chunk: cancel = 0x%x, len = %d, buf = %p\n",
- chunk.cancel, chunk.data.data_len, chunk.data.data_val);
+ "guestfsd: receive_file: got chunk: cancel = 0x%x, len = %u, buf = %p\n",
+ (unsigned) chunk.cancel,
+ chunk.data.data_len, chunk.data.data_val);
if (chunk.cancel != 0 && chunk.cancel != 1) {
fprintf (stderr,
diff --git a/daemon/umask.c b/daemon/umask.c
index 52e854e..475c820 100644
--- a/daemon/umask.c
+++ b/daemon/umask.c
@@ -36,7 +36,7 @@ do_umask (int mask)
int r;
if (mask < 0 || mask > 0777) {
- reply_with_error ("0%o: mask negative or out of range", mask);
+ reply_with_error ("0%o: mask negative or out of range", (unsigned) mask);
return -1;
}
diff --git a/daemon/zero.c b/daemon/zero.c
index 505c4bb..d152210 100644
--- a/daemon/zero.c
+++ b/daemon/zero.c
@@ -172,7 +172,7 @@ do_zero_device (const char *device)
if (!is_zero (buf, sizeof buf)) {
r = pwrite (fd, zero_buf, n, pos);
if (r == -1) {
- reply_with_perror ("pwrite: %s (with %" PRId64 " bytes left to write)",
+ reply_with_perror ("pwrite: %s (with %" PRIu64 " bytes left to write)",
device, size);
close (fd);
return -1;
diff --git a/diff/diff.c b/diff/diff.c
index 13ecca1..1261439 100644
--- a/diff/diff.c
+++ b/diff/diff.c
@@ -994,7 +994,7 @@ output_binary (const char *s, size_t len)
exit (EXIT_FAILURE);
}
} else {
- if (printf ("\\x%2x", s[i]) < 0) {
+ if (printf ("\\x%2x", (unsigned) s[i]) < 0) {
perror ("printf");
exit (EXIT_FAILURE);
}
@@ -1054,7 +1054,7 @@ output_int64_perms (int64_t i)
{
next_field ();
/* csv doesn't need escaping */
- if (printf ("%04" PRIo64, i) < 0) {
+ if (printf ("%04" PRIo64, (uint64_t) i) < 0) {
perror ("printf");
exit (EXIT_FAILURE);
}
@@ -1126,7 +1126,8 @@ output_int64_dev (int64_t i)
next_field ();
/* csv doesn't need escaping */
- if (printf ("%d:%d", major (dev), minor (dev)) < 0) {
+ if (printf ("%ju:%ju",
+ (uintmax_t) major (dev), (uintmax_t) minor (dev)) < 0) {
perror ("printf");
exit (EXIT_FAILURE);
}
diff --git a/fish/alloc.c b/fish/alloc.c
index b40284a..9f41915 100644
--- a/fish/alloc.c
+++ b/fish/alloc.c
@@ -97,7 +97,7 @@ parse_size (const char *str, off_t *size_rtn)
xerr = xstrtoull (str, NULL, 0, &size, "0kKMGTPEZY");
if (xerr != LONGINT_OK) {
fprintf (stderr,
- _("%s: invalid integer parameter (%s returned %d)\n"),
+ _("%s: invalid integer parameter (%s returned %u)\n"),
"parse_size", "xstrtoull", xerr);
return -1;
}
diff --git a/fish/rc.c b/fish/rc.c
index 9ccd5f3..9b0c9c5 100644
--- a/fish/rc.c
+++ b/fish/rc.c
@@ -40,8 +40,8 @@
/* Because this is a Unix domain socket, the total path length must be
* under 108 bytes.
*/
-#define SOCKET_DIR "/tmp/.guestfish-%d" /* euid */
-#define SOCKET_PATH "/tmp/.guestfish-%d/socket-%d" /* euid, pid */
+#define SOCKET_DIR "/tmp/.guestfish-%ju" /* euid */
+#define SOCKET_PATH "/tmp/.guestfish-%ju/socket-%ju" /* euid, pid */
static void
create_sockdir (void)
@@ -52,7 +52,7 @@ create_sockdir (void)
struct stat statbuf;
/* Create the directory, and ensure it is owned by the user. */
- snprintf (dir, sizeof dir, SOCKET_DIR, euid);
+ snprintf (dir, sizeof dir, SOCKET_DIR, (uintmax_t) euid);
r = mkdir (dir, 0700);
if (r == -1 && errno != EEXIST) {
error:
@@ -79,7 +79,7 @@ create_sockpath (pid_t pid, char *sockpath, size_t len,
create_sockdir ();
- snprintf (sockpath, len, SOCKET_PATH, euid, pid);
+ snprintf (sockpath, len, SOCKET_PATH, (uintmax_t) euid, (uintmax_t) pid);
addr->sun_family = AF_UNIX;
strcpy (addr->sun_path, sockpath);
diff --git a/generator/bindtests.ml b/generator/bindtests.ml
index 9558a74..5358ff1 100644
--- a/generator/bindtests.ml
+++ b/generator/bindtests.ml
@@ -159,7 +159,7 @@ fill_lvm_pv (guestfs_h *g, struct guestfs_lvm_pv *pv, size_t i)
pr " {\n";
pr " size_t i;\n";
pr " for (i = 0; i < %s_size; ++i)\n" n;
- pr " fprintf (fp, \"<%%02x>\", %s[i]);\n" n;
+ pr " fprintf (fp, \"<%%02x>\", (unsigned) %s[i]);\n" n;
pr " fprintf (fp, \"\\n\");\n";
pr " }\n";
| OptString n -> pr " fprintf (fp, \"%%s\\n\", %s ? %s : \"null\");\n" n n
diff --git a/generator/daemon.ml b/generator/daemon.ml
index 0c98d14..1825de4 100644
--- a/generator/daemon.ml
+++ b/generator/daemon.ml
@@ -564,12 +564,12 @@ cleanup_free_mountable (mountable_t *mountable)
pr " r->%s[i++] = tok[j];\n" name;
pr " }\n";
| FBytes ->
- pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
+ pr " if (sscanf (tok, \"%%\" SCNi64, &r->%s) != 1) {\n" name;
pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
pr " return -1;\n";
pr " }\n";
| FInt64 ->
- pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
+ pr " if (sscanf (tok, \"%%\" SCNi64, &r->%s) != 1) {\n" name;
pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
pr " return -1;\n";
pr " }\n";
diff --git a/generator/fish.ml b/generator/fish.ml
index 05bbdad..6f68e65 100644
--- a/generator/fish.ml
+++ b/generator/fish.ml
@@ -249,10 +249,10 @@ Guestfish will prompt for these separately."
pr "print_%s_list (struct guestfs_%s_list *%ss)\n"
typ typ typ;
pr "{\n";
- pr " unsigned int i;\n";
+ pr " size_t i;\n";
pr "\n";
pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
- pr " printf (\"[%%d] = {\\n\", i);\n";
+ pr " printf (\"[%%zu] = {\\n\", i);\n";
pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
pr " printf (\"}\\n\");\n";
pr " }\n";
@@ -270,7 +270,7 @@ Guestfish will prompt for these separately."
pr "print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
pr "{\n";
if needs_i then (
- pr " unsigned int i;\n";
+ pr " size_t i;\n";
pr "\n"
);
List.iter (
@@ -288,7 +288,8 @@ Guestfish will prompt for these separately."
pr " if (c_isprint (%s->%s[i]))\n" typ name;
pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
pr " else\n";
- pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
+ pr " printf (\"\\\\x%%02x\", (unsigned) %s->%s[i]);\n"
+ typ name;
pr " printf (\"\\n\");\n"
| name, (FUInt64|FBytes) ->
pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
@@ -422,7 +423,7 @@ Guestfish will prompt for these separately."
indent fn expr;
pr "%s if (xerr != LONGINT_OK) {\n" indent;
pr "%s fprintf (stderr,\n" indent;
- pr "%s _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n" indent;
+ pr "%s _(\"%%s: %%s: invalid integer parameter (%%s returned %%u)\\n\"),\n" indent;
pr "%s cmd, \"%s\", \"%s\", xerr);\n" indent name fn;
pr "%s goto %s;\n" indent out;
pr "%s }\n" indent;
@@ -585,9 +586,9 @@ Guestfish will prompt for these separately."
| None ->
pr " printf (\"%%d\\n\", r);\n";
| Some FishOutputOctal ->
- pr " printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
+ pr " printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", (unsigned) r);\n";
| Some FishOutputHexadecimal ->
- pr " printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n"
+ pr " printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", (unsigned) r);\n"
)
| RInt64 _ ->
pr " if (r == -1) goto out;\n";
@@ -598,7 +599,7 @@ Guestfish will prompt for these separately."
| Some FishOutputOctal ->
pr " printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
| Some FishOutputHexadecimal ->
- pr " printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n"
+ pr " printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", (uint64_t) r);\n"
)
| RBool _ ->
pr " if (r == -1) goto out;\n";
diff --git a/make-fs/make-fs.c b/make-fs/make-fs.c
index cbf49d9..980bfeb 100644
--- a/make-fs/make-fs.c
+++ b/make-fs/make-fs.c
@@ -620,7 +620,7 @@ parse_size (const char *str, uint64_t estimate, uint64_t *size_rtn)
xerr = xstrtoull (str, NULL, 0, &size, "0kKMGTPEZY");
if (xerr != LONGINT_OK) {
fprintf (stderr,
- _("%s: %s: invalid size parameter '%s' (%s returned %d)\n"),
+ _("%s: %s: invalid size parameter '%s' (%s returned %u)\n"),
guestfs_int_program_name, "parse_size", str, "xstrtoull", xerr);
return -1;
}
diff --git a/p2v/main.c b/p2v/main.c
index 666faf1..be32e4b 100644
--- a/p2v/main.c
+++ b/p2v/main.c
@@ -312,8 +312,9 @@ partition_parent (dev_t part_dev)
size_t len = 0;
unsigned parent_major, parent_minor;
- if (asprintf (&path, "/sys/dev/block/%d:%d/../dev",
- major (part_dev), minor (part_dev)) == -1) {
+ if (asprintf (&path, "/sys/dev/block/%ju:%ju/../dev",
+ (uintmax_t) major (part_dev),
+ (uintmax_t) minor (part_dev)) == -1) {
perror ("asprintf");
exit (EXIT_FAILURE);
}
diff --git a/src/actions-support.c b/src/actions-support.c
index e671ed8..23b9ba7 100644
--- a/src/actions-support.c
+++ b/src/actions-support.c
@@ -38,25 +38,25 @@ guestfs_int_check_reply_header (guestfs_h *g,
unsigned int proc_nr, unsigned int serial)
{
if (hdr->prog != GUESTFS_PROGRAM) {
- error (g, "wrong program (%d/%d)", hdr->prog, GUESTFS_PROGRAM);
+ error (g, "wrong program (%u/%d)", hdr->prog, GUESTFS_PROGRAM);
return -1;
}
if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
- error (g, "wrong protocol version (%d/%d)",
+ error (g, "wrong protocol version (%u/%d)",
hdr->vers, GUESTFS_PROTOCOL_VERSION);
return -1;
}
if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
error (g, "unexpected message direction (%d/%d)",
- hdr->direction, GUESTFS_DIRECTION_REPLY);
+ (int) hdr->direction, GUESTFS_DIRECTION_REPLY);
return -1;
}
if (hdr->proc != proc_nr) {
- error (g, "unexpected procedure number (%d/%d)", hdr->proc, proc_nr);
+ error (g, "unexpected procedure number (%d/%u)", (int) hdr->proc, proc_nr);
return -1;
}
if (hdr->serial != serial) {
- error (g, "unexpected serial (%d/%d)", hdr->serial, serial);
+ error (g, "unexpected serial (%u/%u)", hdr->serial, serial);
return -1;
}
diff --git a/src/appliance.c b/src/appliance.c
index 2167ac3..2645cca 100644
--- a/src/appliance.c
+++ b/src/appliance.c
@@ -229,7 +229,7 @@ build_supermin_appliance (guestfs_h *g,
*/
len = strlen (tmpdir) + 128;
char cachedir[len];
- snprintf (cachedir, len, "%s/.guestfs-%d", tmpdir, uid);
+ snprintf (cachedir, len, "%s/.guestfs-%ju", tmpdir, (uintmax_t) uid);
char lockfile[len];
snprintf (lockfile, len, "%s/lock", cachedir);
char appliancedir[len];
@@ -244,8 +244,8 @@ build_supermin_appliance (guestfs_h *g,
if (lstat (cachedir, &statbuf) == -1)
return 0;
if (statbuf.st_uid != uid) {
- error (g, _("security: cached appliance %s is not owned by UID %d"),
- cachedir, uid);
+ error (g, _("security: cached appliance %s is not owned by UID %ju"),
+ cachedir, (uintmax_t) uid);
return -1;
}
if (!S_ISDIR (statbuf.st_mode)) {
diff --git a/src/fuse.c b/src/fuse.c
index 3fdb1d4..332c1be 100644
--- a/src/fuse.c
+++ b/src/fuse.c
@@ -345,8 +345,8 @@ mount_local_access (const char *path, int mask)
debug (g, "%s: "
"testing access mask%s%s%s%s: "
- "caller UID:GID = %d:%d, "
- "file UID:GID = %d:%d, "
+ "caller UID:GID = %ju:%ju, "
+ "file UID:GID = %ju:%ju, "
"file mode = %o, "
"result = %s",
path,
@@ -354,8 +354,8 @@ mount_local_access (const char *path, int mask)
mask & W_OK ? " W_OK" : "",
mask & X_OK ? " X_OK" : "",
mask == 0 ? " 0" : "",
- fuse->uid, fuse->gid,
- statbuf.st_uid, statbuf.st_gid,
+ (uintmax_t) fuse->uid, (uintmax_t) fuse->gid,
+ (uintmax_t) statbuf.st_uid, (uintmax_t) statbuf.st_gid,
statbuf.st_mode,
ok ? "OK" : "EACCESS");
@@ -402,7 +402,7 @@ mount_local_mknod (const char *path, mode_t mode, dev_t rdev)
{
int r;
DECL_G ();
- DEBUG_CALL ("%s, 0%o, 0x%lx", path, mode, (long) rdev);
+ DEBUG_CALL ("%s, 0%o, 0x%jx", path, mode, (uintmax_t) rdev);
if (g->ml_read_only) return -EROFS;
@@ -548,7 +548,7 @@ mount_local_chown (const char *path, uid_t uid, gid_t gid)
{
int r;
DECL_G ();
- DEBUG_CALL ("%s, %ld, %ld", path, (long) uid, (long) gid);
+ DEBUG_CALL ("%s, %ju, %ju", path, (uintmax_t) uid, (uintmax_t) gid);
if (g->ml_read_only) return -EROFS;
@@ -630,7 +630,7 @@ mount_local_open (const char *path, struct fuse_file_info *fi)
{
int flags = fi->flags & O_ACCMODE;
DECL_G ();
- DEBUG_CALL ("%s, 0%o", path, fi->flags);
+ DEBUG_CALL ("%s, 0%o", path, (unsigned) fi->flags);
if (g->ml_read_only && flags != O_RDONLY)
return -EROFS;
diff --git a/src/handle.c b/src/handle.c
index 51b9572..12c1fb2 100644
--- a/src/handle.c
+++ b/src/handle.c
@@ -336,7 +336,7 @@ guestfs_close (guestfs_h *g)
trace_msg, strlen (trace_msg));
}
- debug (g, "closing guestfs handle %p (state %d)", g, g->state);
+ debug (g, "closing guestfs handle %p (state %d)", g, (int) g->state);
if (g->state != CONFIG)
shutdown_backend (g, 0);
diff --git a/src/launch-libvirt.c b/src/launch-libvirt.c
index f46782c..1c0bfac 100644
--- a/src/launch-libvirt.c
+++ b/src/launch-libvirt.c
@@ -857,7 +857,8 @@ debug_appliance_permissions (guestfs_h *g)
CLEANUP_FREE char *cachedir = guestfs_get_cachedir (g);
CLEANUP_FREE char *appliance = NULL;
- appliance = safe_asprintf (g, "%s/.guestfs-%d", cachedir, geteuid ());
+ appliance = safe_asprintf (g, "%s/.guestfs-%ju",
+ cachedir, (uintmax_t) geteuid ());
guestfs_int_cmd_add_arg (cmd, "ls");
guestfs_int_cmd_add_arg (cmd, "-a");
diff --git a/src/launch.c b/src/launch.c
index fd5479e..343f4ea 100644
--- a/src/launch.c
+++ b/src/launch.c
@@ -86,7 +86,7 @@ guestfs_impl_launch (guestfs_h *g)
debug (g, "launch: tmpdir=%s", g->tmpdir);
debug (g, "launch: umask=0%03o", get_umask (g));
- debug (g, "launch: euid=%d", geteuid ());
+ debug (g, "launch: euid=%ju", (uintmax_t) geteuid ());
}
/* Launch the appliance. */
diff --git a/src/proto.c b/src/proto.c
index 4ddd164..815a4d2 100644
--- a/src/proto.c
+++ b/src/proto.c
@@ -527,7 +527,7 @@ recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn)
if (*size_rtn == GUESTFS_LAUNCH_FLAG) {
if (g->state != LAUNCHING)
error (g, _("received magic signature from guestfsd, but in state %d"),
- g->state);
+ (int) g->state);
else {
g->state = READY;
guestfs_int_call_callbacks_void (g, GUESTFS_EVENT_LAUNCH_DONE);
diff --git a/test-tool/test-tool.c b/test-tool/test-tool.c
index f41b8fd..627bdf1 100644
--- a/test-tool/test-tool.c
+++ b/test-tool/test-tool.c
@@ -151,7 +151,7 @@ main (int argc, char *argv[])
default:
fprintf (stderr,
- _("libguestfs-test-tool: unexpected command line option 0x%x\n"),
+ _("libguestfs-test-tool: unexpected command line option %d\n"),
c);
exit (EXIT_FAILURE);
}
--
2.3.1
9 years, 4 months
[PATCH] Fix various -Wformat problems.
by Richard W.M. Jones
Updating gnulib has caused -Wformat-signedness to be enabled. This
has revealed many problems in C format strings. The fixes here fall
into the following main categories:
- Using %d with an unsigned parameter.
- %x and %o expect an unsigned argument.
- uid_t and gid_t are unsigned on Linux. The safe way to print these
is to cast them to uintmax_t and then print then using the %ju
modifier (see http://stackoverflow.com/a/1401581).
- Using %d to print an enum. Since enums may be either char or int,
I fixed this by casting the enum to int.
- strtol_error & lzma_ret are both unsigned types.
---
builder/pxzcat-c.c | 24 ++++++++++++------------
cat/filesystems.c | 2 +-
cat/ls.c | 5 +++--
daemon/ext2.c | 7 ++++++-
daemon/file.c | 2 +-
daemon/guestfsd.c | 3 ++-
daemon/parted.c | 5 +++--
daemon/proto.c | 14 ++++++++------
daemon/umask.c | 2 +-
daemon/zero.c | 2 +-
diff/diff.c | 7 ++++---
fish/alloc.c | 2 +-
fish/rc.c | 8 ++++----
generator/bindtests.ml | 2 +-
generator/daemon.ml | 4 ++--
generator/fish.ml | 17 +++++++++--------
make-fs/make-fs.c | 2 +-
p2v/main.c | 5 +++--
src/actions-support.c | 10 +++++-----
src/appliance.c | 6 +++---
src/fuse.c | 14 +++++++-------
src/handle.c | 2 +-
src/launch-libvirt.c | 3 ++-
src/launch.c | 2 +-
src/proto.c | 2 +-
test-tool/test-tool.c | 2 +-
26 files changed, 84 insertions(+), 70 deletions(-)
diff --git a/builder/pxzcat-c.c b/builder/pxzcat-c.c
index fb1a865..0c4a4be 100644
--- a/builder/pxzcat-c.c
+++ b/builder/pxzcat-c.c
@@ -298,7 +298,7 @@ parse_indexes (value filenamev, int fd)
/* Does the stream footer look reasonable? */
r = lzma_stream_footer_decode (&footer_flags, footer);
if (r != LZMA_OK) {
- fprintf (stderr, "invalid stream footer - error %d\n", r);
+ fprintf (stderr, "invalid stream footer - error %u\n", r);
caml_invalid_argument ("invalid stream footer");
}
@@ -317,7 +317,7 @@ parse_indexes (value filenamev, int fd)
/* Decode the index. */
r = lzma_index_decoder (&strm, &this_index, UINT64_MAX);
if (r != LZMA_OK) {
- fprintf (stderr, "invalid stream index - error %d\n", r);
+ fprintf (stderr, "invalid stream index - error %u\n", r);
caml_invalid_argument ("invalid stream index");
}
@@ -339,7 +339,7 @@ parse_indexes (value filenamev, int fd)
} while (r == LZMA_OK);
if (r != LZMA_STREAM_END) {
- fprintf (stderr, "could not parse index - error %d\n", r);
+ fprintf (stderr, "could not parse index - error %u\n", r);
caml_invalid_argument ("could not parse index");
}
@@ -356,14 +356,14 @@ parse_indexes (value filenamev, int fd)
r = lzma_stream_header_decode (&header_flags, header);
if (r != LZMA_OK) {
- fprintf (stderr, "invalid stream header - error %d\n", r);
+ fprintf (stderr, "invalid stream header - error %u\n", r);
caml_invalid_argument ("invalid stream header");
}
/* Header and footer of the stream should be equal. */
r = lzma_stream_flags_compare (&header_flags, &footer_flags);
if (r != LZMA_OK) {
- fprintf (stderr, "header and footer of stream are not equal - error %d\n",
+ fprintf (stderr, "header and footer of stream are not equal - error %u\n",
r);
caml_invalid_argument ("header and footer of stream are not equal");
}
@@ -371,7 +371,7 @@ parse_indexes (value filenamev, int fd)
/* Store the decoded stream flags in this_index. */
r = lzma_index_stream_flags (this_index, &footer_flags);
if (r != LZMA_OK) {
- fprintf (stderr, "cannot read stream_flags from index - error %d\n", r);
+ fprintf (stderr, "cannot read stream_flags from index - error %u\n", r);
caml_invalid_argument ("cannot read stream_flags from index");
}
@@ -380,14 +380,14 @@ parse_indexes (value filenamev, int fd)
*/
r = lzma_index_stream_padding (this_index, stream_padding);
if (r != LZMA_OK) {
- fprintf (stderr, "cannot set stream_padding in index - error %d\n", r);
+ fprintf (stderr, "cannot set stream_padding in index - error %u\n", r);
caml_invalid_argument ("cannot set stream_padding in index");
}
if (combined_index != NULL) {
r = lzma_index_cat (this_index, combined_index, NULL);
if (r != LZMA_OK) {
- fprintf (stderr, "cannot combine indexes - error %d\n", r);
+ fprintf (stderr, "cannot combine indexes - error %u\n", r);
caml_invalid_argument ("cannot combine indexes");
}
}
@@ -613,7 +613,7 @@ worker_thread (void *vp)
r = lzma_block_header_decode (&block, NULL, header);
if (r != LZMA_OK) {
- fprintf (stderr, "%s: invalid block header (error %d)\n",
+ fprintf (stderr, "%s: invalid block header (error %u)\n",
global->filename, r);
return &state->status;
}
@@ -624,7 +624,7 @@ worker_thread (void *vp)
r = lzma_block_compressed_size (&block, iter.block.unpadded_size);
if (r != LZMA_OK) {
fprintf (stderr,
- "%s: cannot calculate compressed size (error %d)\n",
+ "%s: cannot calculate compressed size (error %u)\n",
global->filename, r);
return &state->status;
}
@@ -635,7 +635,7 @@ worker_thread (void *vp)
/* Read the block data and uncompress it. */
r = lzma_block_decoder (&strm, &block);
if (r != LZMA_OK) {
- fprintf (stderr, "%s: invalid block (error %d)\n", global->filename, r);
+ fprintf (stderr, "%s: invalid block (error %u)\n", global->filename, r);
return &state->status;
}
@@ -684,7 +684,7 @@ worker_thread (void *vp)
break;
if (r != LZMA_OK) {
fprintf (stderr,
- "%s: could not parse block data (error %d)\n",
+ "%s: could not parse block data (error %u)\n",
global->filename, r);
return &state->status;
}
diff --git a/cat/filesystems.c b/cat/filesystems.c
index 44defe0..0e64e00 100644
--- a/cat/filesystems.c
+++ b/cat/filesystems.c
@@ -868,7 +868,7 @@ write_row (const char *name, const char *type,
strings[len++] = vfs_label;
if ((columns & COLUMN_MBR)) {
if (mbr_id >= 0) {
- snprintf (mbr_id_str, sizeof mbr_id_str, "%02x", mbr_id);
+ snprintf (mbr_id_str, sizeof mbr_id_str, "%02x", (unsigned) mbr_id);
strings[len++] = mbr_id_str;
} else
strings[len++] = NULL;
diff --git a/cat/ls.c b/cat/ls.c
index 3bced54..987dcef 100644
--- a/cat/ls.c
+++ b/cat/ls.c
@@ -702,7 +702,7 @@ output_int64_perms (int64_t i)
{
next_field ();
/* csv doesn't need escaping */
- if (printf ("%04" PRIo64, i) < 0) {
+ if (printf ("%04" PRIo64, (uint64_t) i) < 0) {
perror ("printf");
exit (EXIT_FAILURE);
}
@@ -774,7 +774,8 @@ output_int64_dev (int64_t i)
next_field ();
/* csv doesn't need escaping */
- if (printf ("%d:%d", major (dev), minor (dev)) < 0) {
+ if (printf ("%ju:%ju",
+ (uintmax_t) major (dev), (uintmax_t) minor (dev)) < 0) {
perror ("printf");
exit (EXIT_FAILURE);
}
diff --git a/daemon/ext2.c b/daemon/ext2.c
index 8ef6d5f..9142a38 100644
--- a/daemon/ext2.c
+++ b/daemon/ext2.c
@@ -780,11 +780,16 @@ do_get_e2generation (const char *filename)
return -1;
}
- if (sscanf (out, "%" SCNu64, &ret) != 1) {
+ if (sscanf (out, "%" SCNi64, &ret) != 1) {
reply_with_error ("cannot parse output from '%s' command: %s",
"lsattr", out);
return -1;
}
+ if (ret < 0) {
+ reply_with_error ("unexpected negative number from '%s' command: %s",
+ "lsattr", out);
+ return -1;
+ }
return ret;
}
diff --git a/daemon/file.c b/daemon/file.c
index bb3b3c1..c609a01 100644
--- a/daemon/file.c
+++ b/daemon/file.c
@@ -140,7 +140,7 @@ do_chmod (int mode, const char *path)
CHROOT_OUT;
if (r == -1) {
- reply_with_perror ("%s: 0%o", path, mode);
+ reply_with_perror ("%s: 0%o", path, (unsigned) mode);
return -1;
}
diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c
index 7f4b2f2..ee0aa43 100644
--- a/daemon/guestfsd.c
+++ b/daemon/guestfsd.c
@@ -224,7 +224,8 @@ main (int argc, char *argv[])
exit (EXIT_SUCCESS);
default:
- fprintf (stderr, "guestfsd: unexpected command line option 0x%x\n", c);
+ fprintf (stderr, "guestfsd: unexpected command line option 0x%x\n",
+ (unsigned) c);
exit (EXIT_FAILURE);
}
}
diff --git a/daemon/parted.c b/daemon/parted.c
index b516067..cb6c486 100644
--- a/daemon/parted.c
+++ b/daemon/parted.c
@@ -752,7 +752,7 @@ do_part_get_mbr_id (const char *device, int partnum)
udev_settle ();
/* It's printed in hex ... */
- int id;
+ unsigned id;
if (sscanf (out, "%x", &id) != 1) {
reply_with_error ("sfdisk --print-id: cannot parse output: %s", out);
return -1;
@@ -775,7 +775,8 @@ do_part_set_mbr_id (const char *device, int partnum, int idbyte)
snprintf (partnum_str, sizeof partnum_str, "%d", partnum);
char idbyte_str[16];
- snprintf (idbyte_str, sizeof partnum_str, "%x", idbyte); /* NB: hex */
+ /* NB: hex */
+ snprintf (idbyte_str, sizeof partnum_str, "%x", (unsigned) idbyte);
CLEANUP_FREE char *err = NULL;
int r;
diff --git a/daemon/proto.c b/daemon/proto.c
index 7ae8c66..df63bfd 100644
--- a/daemon/proto.c
+++ b/daemon/proto.c
@@ -157,19 +157,20 @@ main_loop (int _sock)
/* Check the version etc. */
if (hdr.prog != GUESTFS_PROGRAM) {
- reply_with_error ("wrong program (%d)", hdr.prog);
+ reply_with_error ("wrong program (%u)", hdr.prog);
goto cont;
}
if (hdr.vers != GUESTFS_PROTOCOL_VERSION) {
- reply_with_error ("wrong protocol version (%d)", hdr.vers);
+ reply_with_error ("wrong protocol version (%u)", hdr.vers);
goto cont;
}
if (hdr.direction != GUESTFS_DIRECTION_CALL) {
- reply_with_error ("unexpected message direction (%d)", hdr.direction);
+ reply_with_error ("unexpected message direction (%d)",
+ (int) hdr.direction);
goto cont;
}
if (hdr.status != GUESTFS_STATUS_OK) {
- reply_with_error ("unexpected message status (%d)", hdr.status);
+ reply_with_error ("unexpected message status (%d)", (int) hdr.status);
goto cont;
}
@@ -444,8 +445,9 @@ receive_file (receive_cb cb, void *opaque)
if (verbose)
fprintf (stderr,
- "guestfsd: receive_file: got chunk: cancel = 0x%x, len = %d, buf = %p\n",
- chunk.cancel, chunk.data.data_len, chunk.data.data_val);
+ "guestfsd: receive_file: got chunk: cancel = 0x%x, len = %u, buf = %p\n",
+ (unsigned) chunk.cancel,
+ chunk.data.data_len, chunk.data.data_val);
if (chunk.cancel != 0 && chunk.cancel != 1) {
fprintf (stderr,
diff --git a/daemon/umask.c b/daemon/umask.c
index 52e854e..475c820 100644
--- a/daemon/umask.c
+++ b/daemon/umask.c
@@ -36,7 +36,7 @@ do_umask (int mask)
int r;
if (mask < 0 || mask > 0777) {
- reply_with_error ("0%o: mask negative or out of range", mask);
+ reply_with_error ("0%o: mask negative or out of range", (unsigned) mask);
return -1;
}
diff --git a/daemon/zero.c b/daemon/zero.c
index 505c4bb..d152210 100644
--- a/daemon/zero.c
+++ b/daemon/zero.c
@@ -172,7 +172,7 @@ do_zero_device (const char *device)
if (!is_zero (buf, sizeof buf)) {
r = pwrite (fd, zero_buf, n, pos);
if (r == -1) {
- reply_with_perror ("pwrite: %s (with %" PRId64 " bytes left to write)",
+ reply_with_perror ("pwrite: %s (with %" PRIu64 " bytes left to write)",
device, size);
close (fd);
return -1;
diff --git a/diff/diff.c b/diff/diff.c
index 13ecca1..1261439 100644
--- a/diff/diff.c
+++ b/diff/diff.c
@@ -994,7 +994,7 @@ output_binary (const char *s, size_t len)
exit (EXIT_FAILURE);
}
} else {
- if (printf ("\\x%2x", s[i]) < 0) {
+ if (printf ("\\x%2x", (unsigned) s[i]) < 0) {
perror ("printf");
exit (EXIT_FAILURE);
}
@@ -1054,7 +1054,7 @@ output_int64_perms (int64_t i)
{
next_field ();
/* csv doesn't need escaping */
- if (printf ("%04" PRIo64, i) < 0) {
+ if (printf ("%04" PRIo64, (uint64_t) i) < 0) {
perror ("printf");
exit (EXIT_FAILURE);
}
@@ -1126,7 +1126,8 @@ output_int64_dev (int64_t i)
next_field ();
/* csv doesn't need escaping */
- if (printf ("%d:%d", major (dev), minor (dev)) < 0) {
+ if (printf ("%ju:%ju",
+ (uintmax_t) major (dev), (uintmax_t) minor (dev)) < 0) {
perror ("printf");
exit (EXIT_FAILURE);
}
diff --git a/fish/alloc.c b/fish/alloc.c
index b40284a..9f41915 100644
--- a/fish/alloc.c
+++ b/fish/alloc.c
@@ -97,7 +97,7 @@ parse_size (const char *str, off_t *size_rtn)
xerr = xstrtoull (str, NULL, 0, &size, "0kKMGTPEZY");
if (xerr != LONGINT_OK) {
fprintf (stderr,
- _("%s: invalid integer parameter (%s returned %d)\n"),
+ _("%s: invalid integer parameter (%s returned %u)\n"),
"parse_size", "xstrtoull", xerr);
return -1;
}
diff --git a/fish/rc.c b/fish/rc.c
index 9ccd5f3..9b0c9c5 100644
--- a/fish/rc.c
+++ b/fish/rc.c
@@ -40,8 +40,8 @@
/* Because this is a Unix domain socket, the total path length must be
* under 108 bytes.
*/
-#define SOCKET_DIR "/tmp/.guestfish-%d" /* euid */
-#define SOCKET_PATH "/tmp/.guestfish-%d/socket-%d" /* euid, pid */
+#define SOCKET_DIR "/tmp/.guestfish-%ju" /* euid */
+#define SOCKET_PATH "/tmp/.guestfish-%ju/socket-%ju" /* euid, pid */
static void
create_sockdir (void)
@@ -52,7 +52,7 @@ create_sockdir (void)
struct stat statbuf;
/* Create the directory, and ensure it is owned by the user. */
- snprintf (dir, sizeof dir, SOCKET_DIR, euid);
+ snprintf (dir, sizeof dir, SOCKET_DIR, (uintmax_t) euid);
r = mkdir (dir, 0700);
if (r == -1 && errno != EEXIST) {
error:
@@ -79,7 +79,7 @@ create_sockpath (pid_t pid, char *sockpath, size_t len,
create_sockdir ();
- snprintf (sockpath, len, SOCKET_PATH, euid, pid);
+ snprintf (sockpath, len, SOCKET_PATH, (uintmax_t) euid, (uintmax_t) pid);
addr->sun_family = AF_UNIX;
strcpy (addr->sun_path, sockpath);
diff --git a/generator/bindtests.ml b/generator/bindtests.ml
index 9558a74..5358ff1 100644
--- a/generator/bindtests.ml
+++ b/generator/bindtests.ml
@@ -159,7 +159,7 @@ fill_lvm_pv (guestfs_h *g, struct guestfs_lvm_pv *pv, size_t i)
pr " {\n";
pr " size_t i;\n";
pr " for (i = 0; i < %s_size; ++i)\n" n;
- pr " fprintf (fp, \"<%%02x>\", %s[i]);\n" n;
+ pr " fprintf (fp, \"<%%02x>\", (unsigned) %s[i]);\n" n;
pr " fprintf (fp, \"\\n\");\n";
pr " }\n";
| OptString n -> pr " fprintf (fp, \"%%s\\n\", %s ? %s : \"null\");\n" n n
diff --git a/generator/daemon.ml b/generator/daemon.ml
index 0c98d14..1825de4 100644
--- a/generator/daemon.ml
+++ b/generator/daemon.ml
@@ -564,12 +564,12 @@ cleanup_free_mountable (mountable_t *mountable)
pr " r->%s[i++] = tok[j];\n" name;
pr " }\n";
| FBytes ->
- pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
+ pr " if (sscanf (tok, \"%%\" SCNi64, &r->%s) != 1) {\n" name;
pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
pr " return -1;\n";
pr " }\n";
| FInt64 ->
- pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
+ pr " if (sscanf (tok, \"%%\" SCNi64, &r->%s) != 1) {\n" name;
pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
pr " return -1;\n";
pr " }\n";
diff --git a/generator/fish.ml b/generator/fish.ml
index 05bbdad..6f68e65 100644
--- a/generator/fish.ml
+++ b/generator/fish.ml
@@ -249,10 +249,10 @@ Guestfish will prompt for these separately."
pr "print_%s_list (struct guestfs_%s_list *%ss)\n"
typ typ typ;
pr "{\n";
- pr " unsigned int i;\n";
+ pr " size_t i;\n";
pr "\n";
pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
- pr " printf (\"[%%d] = {\\n\", i);\n";
+ pr " printf (\"[%%zu] = {\\n\", i);\n";
pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
pr " printf (\"}\\n\");\n";
pr " }\n";
@@ -270,7 +270,7 @@ Guestfish will prompt for these separately."
pr "print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
pr "{\n";
if needs_i then (
- pr " unsigned int i;\n";
+ pr " size_t i;\n";
pr "\n"
);
List.iter (
@@ -288,7 +288,8 @@ Guestfish will prompt for these separately."
pr " if (c_isprint (%s->%s[i]))\n" typ name;
pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
pr " else\n";
- pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
+ pr " printf (\"\\\\x%%02x\", (unsigned) %s->%s[i]);\n"
+ typ name;
pr " printf (\"\\n\");\n"
| name, (FUInt64|FBytes) ->
pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
@@ -422,7 +423,7 @@ Guestfish will prompt for these separately."
indent fn expr;
pr "%s if (xerr != LONGINT_OK) {\n" indent;
pr "%s fprintf (stderr,\n" indent;
- pr "%s _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n" indent;
+ pr "%s _(\"%%s: %%s: invalid integer parameter (%%s returned %%u)\\n\"),\n" indent;
pr "%s cmd, \"%s\", \"%s\", xerr);\n" indent name fn;
pr "%s goto %s;\n" indent out;
pr "%s }\n" indent;
@@ -585,9 +586,9 @@ Guestfish will prompt for these separately."
| None ->
pr " printf (\"%%d\\n\", r);\n";
| Some FishOutputOctal ->
- pr " printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
+ pr " printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", (unsigned) r);\n";
| Some FishOutputHexadecimal ->
- pr " printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n"
+ pr " printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", (unsigned) r);\n"
)
| RInt64 _ ->
pr " if (r == -1) goto out;\n";
@@ -598,7 +599,7 @@ Guestfish will prompt for these separately."
| Some FishOutputOctal ->
pr " printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
| Some FishOutputHexadecimal ->
- pr " printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n"
+ pr " printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", (uint64_t) r);\n"
)
| RBool _ ->
pr " if (r == -1) goto out;\n";
diff --git a/make-fs/make-fs.c b/make-fs/make-fs.c
index cbf49d9..980bfeb 100644
--- a/make-fs/make-fs.c
+++ b/make-fs/make-fs.c
@@ -620,7 +620,7 @@ parse_size (const char *str, uint64_t estimate, uint64_t *size_rtn)
xerr = xstrtoull (str, NULL, 0, &size, "0kKMGTPEZY");
if (xerr != LONGINT_OK) {
fprintf (stderr,
- _("%s: %s: invalid size parameter '%s' (%s returned %d)\n"),
+ _("%s: %s: invalid size parameter '%s' (%s returned %u)\n"),
guestfs_int_program_name, "parse_size", str, "xstrtoull", xerr);
return -1;
}
diff --git a/p2v/main.c b/p2v/main.c
index 666faf1..be32e4b 100644
--- a/p2v/main.c
+++ b/p2v/main.c
@@ -312,8 +312,9 @@ partition_parent (dev_t part_dev)
size_t len = 0;
unsigned parent_major, parent_minor;
- if (asprintf (&path, "/sys/dev/block/%d:%d/../dev",
- major (part_dev), minor (part_dev)) == -1) {
+ if (asprintf (&path, "/sys/dev/block/%ju:%ju/../dev",
+ (uintmax_t) major (part_dev),
+ (uintmax_t) minor (part_dev)) == -1) {
perror ("asprintf");
exit (EXIT_FAILURE);
}
diff --git a/src/actions-support.c b/src/actions-support.c
index e671ed8..23b9ba7 100644
--- a/src/actions-support.c
+++ b/src/actions-support.c
@@ -38,25 +38,25 @@ guestfs_int_check_reply_header (guestfs_h *g,
unsigned int proc_nr, unsigned int serial)
{
if (hdr->prog != GUESTFS_PROGRAM) {
- error (g, "wrong program (%d/%d)", hdr->prog, GUESTFS_PROGRAM);
+ error (g, "wrong program (%u/%d)", hdr->prog, GUESTFS_PROGRAM);
return -1;
}
if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
- error (g, "wrong protocol version (%d/%d)",
+ error (g, "wrong protocol version (%u/%d)",
hdr->vers, GUESTFS_PROTOCOL_VERSION);
return -1;
}
if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
error (g, "unexpected message direction (%d/%d)",
- hdr->direction, GUESTFS_DIRECTION_REPLY);
+ (int) hdr->direction, GUESTFS_DIRECTION_REPLY);
return -1;
}
if (hdr->proc != proc_nr) {
- error (g, "unexpected procedure number (%d/%d)", hdr->proc, proc_nr);
+ error (g, "unexpected procedure number (%d/%u)", (int) hdr->proc, proc_nr);
return -1;
}
if (hdr->serial != serial) {
- error (g, "unexpected serial (%d/%d)", hdr->serial, serial);
+ error (g, "unexpected serial (%u/%u)", hdr->serial, serial);
return -1;
}
diff --git a/src/appliance.c b/src/appliance.c
index 2167ac3..2645cca 100644
--- a/src/appliance.c
+++ b/src/appliance.c
@@ -229,7 +229,7 @@ build_supermin_appliance (guestfs_h *g,
*/
len = strlen (tmpdir) + 128;
char cachedir[len];
- snprintf (cachedir, len, "%s/.guestfs-%d", tmpdir, uid);
+ snprintf (cachedir, len, "%s/.guestfs-%ju", tmpdir, (uintmax_t) uid);
char lockfile[len];
snprintf (lockfile, len, "%s/lock", cachedir);
char appliancedir[len];
@@ -244,8 +244,8 @@ build_supermin_appliance (guestfs_h *g,
if (lstat (cachedir, &statbuf) == -1)
return 0;
if (statbuf.st_uid != uid) {
- error (g, _("security: cached appliance %s is not owned by UID %d"),
- cachedir, uid);
+ error (g, _("security: cached appliance %s is not owned by UID %ju"),
+ cachedir, (uintmax_t) uid);
return -1;
}
if (!S_ISDIR (statbuf.st_mode)) {
diff --git a/src/fuse.c b/src/fuse.c
index 3fdb1d4..332c1be 100644
--- a/src/fuse.c
+++ b/src/fuse.c
@@ -345,8 +345,8 @@ mount_local_access (const char *path, int mask)
debug (g, "%s: "
"testing access mask%s%s%s%s: "
- "caller UID:GID = %d:%d, "
- "file UID:GID = %d:%d, "
+ "caller UID:GID = %ju:%ju, "
+ "file UID:GID = %ju:%ju, "
"file mode = %o, "
"result = %s",
path,
@@ -354,8 +354,8 @@ mount_local_access (const char *path, int mask)
mask & W_OK ? " W_OK" : "",
mask & X_OK ? " X_OK" : "",
mask == 0 ? " 0" : "",
- fuse->uid, fuse->gid,
- statbuf.st_uid, statbuf.st_gid,
+ (uintmax_t) fuse->uid, (uintmax_t) fuse->gid,
+ (uintmax_t) statbuf.st_uid, (uintmax_t) statbuf.st_gid,
statbuf.st_mode,
ok ? "OK" : "EACCESS");
@@ -402,7 +402,7 @@ mount_local_mknod (const char *path, mode_t mode, dev_t rdev)
{
int r;
DECL_G ();
- DEBUG_CALL ("%s, 0%o, 0x%lx", path, mode, (long) rdev);
+ DEBUG_CALL ("%s, 0%o, 0x%jx", path, mode, (uintmax_t) rdev);
if (g->ml_read_only) return -EROFS;
@@ -548,7 +548,7 @@ mount_local_chown (const char *path, uid_t uid, gid_t gid)
{
int r;
DECL_G ();
- DEBUG_CALL ("%s, %ld, %ld", path, (long) uid, (long) gid);
+ DEBUG_CALL ("%s, %ju, %ju", path, (uintmax_t) uid, (uintmax_t) gid);
if (g->ml_read_only) return -EROFS;
@@ -630,7 +630,7 @@ mount_local_open (const char *path, struct fuse_file_info *fi)
{
int flags = fi->flags & O_ACCMODE;
DECL_G ();
- DEBUG_CALL ("%s, 0%o", path, fi->flags);
+ DEBUG_CALL ("%s, 0%o", path, (unsigned) fi->flags);
if (g->ml_read_only && flags != O_RDONLY)
return -EROFS;
diff --git a/src/handle.c b/src/handle.c
index 51b9572..12c1fb2 100644
--- a/src/handle.c
+++ b/src/handle.c
@@ -336,7 +336,7 @@ guestfs_close (guestfs_h *g)
trace_msg, strlen (trace_msg));
}
- debug (g, "closing guestfs handle %p (state %d)", g, g->state);
+ debug (g, "closing guestfs handle %p (state %d)", g, (int) g->state);
if (g->state != CONFIG)
shutdown_backend (g, 0);
diff --git a/src/launch-libvirt.c b/src/launch-libvirt.c
index f46782c..1c0bfac 100644
--- a/src/launch-libvirt.c
+++ b/src/launch-libvirt.c
@@ -857,7 +857,8 @@ debug_appliance_permissions (guestfs_h *g)
CLEANUP_FREE char *cachedir = guestfs_get_cachedir (g);
CLEANUP_FREE char *appliance = NULL;
- appliance = safe_asprintf (g, "%s/.guestfs-%d", cachedir, geteuid ());
+ appliance = safe_asprintf (g, "%s/.guestfs-%ju",
+ cachedir, (uintmax_t) geteuid ());
guestfs_int_cmd_add_arg (cmd, "ls");
guestfs_int_cmd_add_arg (cmd, "-a");
diff --git a/src/launch.c b/src/launch.c
index fd5479e..343f4ea 100644
--- a/src/launch.c
+++ b/src/launch.c
@@ -86,7 +86,7 @@ guestfs_impl_launch (guestfs_h *g)
debug (g, "launch: tmpdir=%s", g->tmpdir);
debug (g, "launch: umask=0%03o", get_umask (g));
- debug (g, "launch: euid=%d", geteuid ());
+ debug (g, "launch: euid=%ju", (uintmax_t) geteuid ());
}
/* Launch the appliance. */
diff --git a/src/proto.c b/src/proto.c
index 4ddd164..815a4d2 100644
--- a/src/proto.c
+++ b/src/proto.c
@@ -527,7 +527,7 @@ recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn)
if (*size_rtn == GUESTFS_LAUNCH_FLAG) {
if (g->state != LAUNCHING)
error (g, _("received magic signature from guestfsd, but in state %d"),
- g->state);
+ (int) g->state);
else {
g->state = READY;
guestfs_int_call_callbacks_void (g, GUESTFS_EVENT_LAUNCH_DONE);
diff --git a/test-tool/test-tool.c b/test-tool/test-tool.c
index f41b8fd..def21e2 100644
--- a/test-tool/test-tool.c
+++ b/test-tool/test-tool.c
@@ -151,7 +151,7 @@ main (int argc, char *argv[])
default:
fprintf (stderr,
- _("libguestfs-test-tool: unexpected command line option 0x%x\n"),
+ _("libguestfs-test-tool: unexpected command line option 0x%d\n"),
c);
exit (EXIT_FAILURE);
}
--
2.3.1
9 years, 4 months
[PATCH v5 0/3] uuid: add btrfs uuid change support and set_uuid_random
by Chen Hanxiao
- Btrfs-progs v4.1 introduced new feature of changing
uuid of btrfs partition.
This patch add support of this.
- Introduce set_uuid_random
- uuids.c did a lot of deplicated work for changing uuid
of fs. Use existing functions.
v5: use NOT_SUPPORTED macro
improve testcases
v4: introduce get_random_uuid
improve testcases
squash internal API patches
v3.1: fix typos
v3: set errno if feature is not available.
Chen Hanxiao (3):
uuid: add support to change uuid of btrfs partition
uuid: use newly introduced swap_set_uuid
New API: set_uuid_random
daemon/btrfs.c | 77 ++++++++++++++++++++++++++++++++++++++++++
daemon/daemon.h | 8 +++++
daemon/ext2.c | 6 ++++
daemon/swap.c | 16 +++++++++
daemon/uuids.c | 56 ++++++++++++++++++------------
daemon/xfs.c | 7 ++++
generator/actions.ml | 16 +++++++++
src/MAX_PROC_NR | 2 +-
tests/btrfs/test-btrfs-misc.pl | 35 +++++++++++++++++++
9 files changed, 201 insertions(+), 22 deletions(-)
--
2.1.0
9 years, 4 months
URI Handling Patch
by Gabriel Hartmann
I have written a patch (please see attached) which fixes both of these bugs:
https://bugzilla.redhat.com/show_bug.cgi?id=1092583
https://bugzilla.redhat.com/show_bug.cgi?id=1232477
By default, when saving a URI using xmlSaveUri it escapes everything in the
URI. QEMU doesn't want anything escaped, so now I unescape everything
after the URI is generated. Unfortunately there's no flag to change the
default behavior.
The other problem was that only the "path" portion of the URI struct was
being used to indicate the path. That's natural enough, but that practice
is what was dropping the query string. The query string is kept separately
from the path. I now concat the query string back onto the URI with a
separating '?'.
I've successfully mounted remote vhds in Azure with this new code, and the
basic set of tests pass. If there's anything else I can do by way of
verification, please let me know.
-- Gabriel
9 years, 4 months
[PATCH v4] RFC: New tool: virt-dib
by Pino Toscano
virt-dib is a new tool to run the elements of diskimage-builder using
libguestfs.
---
I would like to have it reviewed at this point, so it can be used.
Documentation and code can be improved and polished following feedback.
.gitignore | 5 +
Makefile.am | 3 +-
appliance/packagelist.in | 7 +
configure.ac | 1 +
dib/Makefile.am | 144 ++++++++
dib/cmdline.ml | 242 +++++++++++++
dib/dib.ml | 917 +++++++++++++++++++++++++++++++++++++++++++++++
dib/elements.ml | 187 ++++++++++
dib/utils.ml | 134 +++++++
dib/virt-dib.pod | 628 ++++++++++++++++++++++++++++++++
po-docs/podfiles | 1 +
po/POTFILES-ml | 4 +
run.in | 1 +
src/guestfs.pod | 4 +
14 files changed, 2277 insertions(+), 1 deletion(-)
create mode 100644 dib/Makefile.am
create mode 100644 dib/cmdline.ml
create mode 100644 dib/dib.ml
create mode 100644 dib/elements.ml
create mode 100644 dib/utils.ml
create mode 100644 dib/virt-dib.pod
diff --git a/.gitignore b/.gitignore
index 6f14915..697e5cd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -118,6 +118,10 @@ Makefile.in
/df/stamp-virt-df.pod
/df/virt-df
/df/virt-df.1
+/dib/.depend
+/dib/stamp-virt-dib.pod
+/dib/virt-dib
+/dib/virt-dib.1
/diff/stamp-virt-diff.pod
/diff/virt-diff
/diff/virt-diff.1
@@ -245,6 +249,7 @@ Makefile.in
/html/virt-copy-out.1.html
/html/virt-customize.1.html
/html/virt-df.1.html
+/html/virt-dib.1.html
/html/virt-diff.1.html
/html/virt-edit.1.html
/html/virt-filesystems.1.html
diff --git a/Makefile.am b/Makefile.am
index ad6d9d3..b51a3eb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -133,6 +133,7 @@ SUBDIRS += \
mllib \
customize \
builder builder/website \
+ dib \
get-kernel \
resize \
sparsify \
@@ -354,7 +355,7 @@ all-local:
grep -v -E '^python/utils.c$$' | \
LC_ALL=C sort > po/POTFILES
cd $(srcdir); \
- find builder customize get-kernel mllib resize sparsify sysprep v2v -name '*.ml' | \
+ find builder customize dib get-kernel mllib resize sparsify sysprep v2v -name '*.ml' | \
LC_ALL=C sort > po/POTFILES-ml
# Try to stop people using 'make install' without 'DESTDIR'.
diff --git a/appliance/packagelist.in b/appliance/packagelist.in
index 76c7293..a4f814b 100644
--- a/appliance/packagelist.in
+++ b/appliance/packagelist.in
@@ -255,5 +255,12 @@ zerofree
ifelse(VALGRIND_DAEMON,1,valgrind)
+dnl tools needed by virt-dib
+curl
+qemu-img
+debootstrap
+apt
+which
+
dnl Define this by doing: ./configure --with-extra-packages="..."
EXTRA_PACKAGES
diff --git a/configure.ac b/configure.ac
index e0da1ad..9356566 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1740,6 +1740,7 @@ AC_CONFIG_FILES([Makefile
customize/Makefile
daemon/Makefile
df/Makefile
+ dib/Makefile
diff/Makefile
edit/Makefile
erlang/Makefile
diff --git a/dib/Makefile.am b/dib/Makefile.am
new file mode 100644
index 0000000..8932e64
--- /dev/null
+++ b/dib/Makefile.am
@@ -0,0 +1,144 @@
+# libguestfs virt-dib tool
+# Copyright (C) 2015 Red Hat Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+include $(top_srcdir)/subdir-rules.mk
+
+EXTRA_DIST = \
+ $(SOURCES_ML) $(SOURCES_C) \
+ virt-dib.pod
+
+CLEANFILES = *~ *.annot *.cmi *.cmo *.cmx *.cmxa *.o virt-dib
+
+SOURCES_ML = \
+ utils.ml \
+ cmdline.ml \
+ elements.ml \
+ dib.ml
+
+SOURCES_C = \
+ $(top_srcdir)/mllib/mkdtemp-c.c
+
+bin_PROGRAMS =
+
+if HAVE_OCAML
+
+bin_PROGRAMS += virt-dib
+
+virt_dib_SOURCES = $(SOURCES_C)
+virt_dib_CPPFLAGS = \
+ -I. \
+ -I$(top_builddir) \
+ -I$(top_srcdir)/gnulib/lib -I$(top_builddir)/gnulib/lib \
+ -I$(shell $(OCAMLC) -where) \
+ -I$(top_srcdir)/gnulib/lib \
+ -I$(top_srcdir)/src
+virt_dib_CFLAGS = \
+ -pthread \
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
+
+BOBJECTS = \
+ $(top_builddir)/mllib/libdir.cmo \
+ $(top_builddir)/mllib/config.cmo \
+ $(top_builddir)/mllib/common_gettext.cmo \
+ $(top_builddir)/mllib/common_utils.cmo \
+ $(top_builddir)/mllib/mkdtemp.cmo \
+ $(SOURCES_ML:.ml=.cmo)
+XOBJECTS = $(BOBJECTS:.cmo=.cmx)
+
+# -I $(top_builddir)/src/.libs is a hack which forces corresponding -L
+# option to be passed to gcc, so we don't try linking against an
+# installed copy of libguestfs.
+OCAMLPACKAGES = \
+ -package str,unix \
+ -I $(top_builddir)/src/.libs \
+ -I $(top_builddir)/gnulib/lib/.libs \
+ -I $(top_builddir)/ocaml \
+ -I $(top_builddir)/mllib
+if HAVE_OCAML_PKG_GETTEXT
+OCAMLPACKAGES += -package gettext-stub
+endif
+
+OCAMLCLIBS = \
+ -pthread -lpthread \
+ -lutils \
+ $(LIBINTL) \
+ -lgnu
+
+OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR)
+
+if !HAVE_OCAMLOPT
+OBJECTS = $(BOBJECTS)
+BEST = c
+OCAMLLINKFLAGS = mlguestfs.cma -custom
+else
+OBJECTS = $(XOBJECTS)
+BEST = opt
+OCAMLLINKFLAGS = mlguestfs.cmxa
+endif
+
+virt_dib_DEPENDENCIES = $(OBJECTS) $(top_srcdir)/ocaml-link.sh
+virt_dib_LINK = \
+ $(top_srcdir)/ocaml-link.sh -cclib '$(OCAMLCLIBS)' -- \
+ $(OCAMLFIND) $(BEST) $(OCAMLFLAGS) $(OCAMLPACKAGES) $(OCAMLLINKFLAGS) \
+ $(OBJECTS) -o $@
+
+.mli.cmi:
+ $(OCAMLFIND) ocamlc $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@
+.ml.cmo:
+ $(OCAMLFIND) ocamlc $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@
+if HAVE_OCAMLOPT
+.ml.cmx:
+ $(OCAMLFIND) ocamlopt $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@
+endif
+
+# Manual pages and HTML files for the website.
+
+man_MANS = virt-dib.1
+
+noinst_DATA = $(top_builddir)/html/virt-dib.1.html
+
+virt-dib.1 $(top_builddir)/html/virt-dib.1.html: stamp-virt-dib.pod
+
+stamp-virt-dib.pod: virt-dib.pod
+ $(PODWRAPPER) \
+ --man virt-dib.1 \
+ --html $(top_builddir)/html/virt-dib.1.html \
+ --license GPLv2+ \
+ $<
+ touch $@
+
+CLEANFILES += stamp-virt-dib.pod
+
+# Dependencies.
+depend: .depend
+
+.depend: $(wildcard $(abs_srcdir)/*.mli) $(wildcard $(abs_srcdir)/*.ml)
+ rm -f $@ $@-t
+ $(OCAMLFIND) ocamldep -I ../ocaml -I $(abs_srcdir) -I $(abs_top_builddir)/mllib $^ | \
+ $(SED) 's/ *$$//' | \
+ $(SED) -e :a -e '/ *\\$$/N; s/ *\\\n */ /; ta' | \
+ $(SED) -e 's,$(abs_srcdir)/,$(builddir)/,g' | \
+ sort > $@-t
+ mv $@-t $@
+
+-include .depend
+
+endif
+
+DISTCLEANFILES = .depend
+
+.PHONY: depend docs
diff --git a/dib/cmdline.ml b/dib/cmdline.ml
new file mode 100644
index 0000000..2fe77da
--- /dev/null
+++ b/dib/cmdline.ml
@@ -0,0 +1,242 @@
+(* virt-dib
+ * Copyright (C) 2015 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.
+ *)
+
+(* Command line argument parsing. *)
+
+open Common_gettext.Gettext
+open Common_utils
+
+open Utils
+
+open Printf
+
+let parse_args () =
+ let usage_msg =
+ sprintf (f_"\
+%s: run diskimage-builder elements to generate images
+
+ virt-dib -B DIB-LIB -p ELEMENTS-PATH elements...
+
+A short summary of the options is given below. For detailed help please
+read the man page virt-dib(1).
+")
+ prog in
+
+ let elements = ref [] in
+ let append_element element =
+ elements := element :: !elements in
+
+ let excluded_elements = ref [] in
+ let append_excluded_element element =
+ excluded_elements := element :: !excluded_elements in
+
+ let element_paths = ref [] in
+ let append_element_path arg =
+ element_paths := arg :: !element_paths in
+
+ let excluded_scripts = ref [] in
+ let append_excluded_script arg =
+ excluded_scripts := arg :: !excluded_scripts in
+
+ let debug = ref 0 in
+ let set_debug arg =
+ if arg < 0 then
+ error (f_"--debug parameter must be >= 0");
+ debug := arg in
+
+ let basepath = ref "" in
+
+ let image_name = ref "image" in
+
+ let fs_type = ref "ext4" in
+
+ let size = ref (unit_GB 5) in
+ let set_size arg = size := parse_size arg in
+
+ let memsize = ref None in
+ let set_memsize arg = memsize := Some arg in
+
+ let network = ref true in
+
+ let smp = ref None in
+ let set_smp arg = smp := Some arg in
+
+ let formats = ref ["qcow2"] in
+ let set_format arg =
+ let fmts = remove_dups (string_nsplit "," arg) in
+ List.iter (
+ function
+ | "qcow2" | "tar" | "raw" | "vhd" -> ()
+ | fmt ->
+ error (f_"invalid format '%s' in --formats") fmt
+ ) fmts;
+ formats := fmts in
+
+ let envvars = ref [] in
+ let append_envvar arg =
+ envvars := arg :: !envvars in
+
+ let use_base = ref true in
+
+ let arch = ref "" in
+
+ let drive = ref None in
+ let set_drive arg = drive := Some arg in
+
+ let root_label = ref None in
+ let set_root_label arg = root_label := Some arg in
+
+ let install_type = ref "source" in
+
+ let image_cache = ref None in
+ let set_image_cache arg = image_cache := Some arg in
+
+ let compressed = ref true in
+
+ let delete_on_failure = ref true in
+
+ let is_ramdisk = ref false in
+ let ramdisk_element = ref "ramdisk" in
+
+ let qemu_img_options = ref None in
+ let set_qemu_img_options arg = qemu_img_options := Some arg in
+
+ let mkfs_options = ref None in
+ let set_mkfs_options arg = mkfs_options := Some arg in
+
+ let machine_readable = ref false in
+
+ let extra_packages = ref [] in
+ let append_extra_packages arg =
+ extra_packages := List.rev (string_nsplit "," arg) @ !extra_packages in
+
+ let argspec = [
+ "--short-options", Arg.Unit display_short_options, " " ^ s_"List short options";
+ "--long-options", Arg.Unit display_long_options, " " ^ s_"List long options";
+
+ "-p", Arg.String append_element_path, "path" ^ " " ^ s_"Add new a elements location";
+ "--element-path", Arg.String append_element_path, "path" ^ " " ^ s_"Add new a elements location";
+ "--exclude-element", Arg.String append_excluded_element,
+ "element" ^ " " ^ s_"Exclude the specified element";
+ "--exclude-script", Arg.String append_excluded_script,
+ "script" ^ " " ^ s_"Exclude the specified script";
+ "--envvar", Arg.String append_envvar, "envvar[=value]" ^ " " ^ s_"Carry/set this environment variable";
+ "--skip-base", Arg.Clear use_base, " " ^ s_"Skip the inclusion of the 'base' element";
+ "--root-label", Arg.String set_root_label, "label" ^ " " ^ s_"Label for the root fs";
+ "--install-type", Arg.Set_string install_type, "type" ^ " " ^ s_"Installation type";
+ "--image-cache", Arg.String set_image_cache, "directory" ^ " " ^ s_"Location for cached images";
+ "-u", Arg.Clear compressed, " " ^ "Do not compress the qcow2 image";
+ "--qemu-img-options", Arg.String set_qemu_img_options,
+ "option" ^ " " ^ s_"Add qemu-img options";
+ "--mkfs-options", Arg.String set_mkfs_options,
+ "option" ^ " " ^ s_"Add mkfs options";
+ "--extra-packages", Arg.String append_extra_packages,
+ "pkg,..." ^ " " ^ s_"Add extra packages to install";
+
+ "--ramdisk", Arg.Set is_ramdisk, " " ^ "Switch to a ramdisk build";
+ "--ramdisk-element", Arg.Set_string ramdisk_element, "name" ^ " " ^ s_"Main element for building ramdisks";
+
+ "--name", Arg.Set_string image_name, "name" ^ " " ^ s_"Name of the image";
+ "--fs-type", Arg.Set_string fs_type, "fs" ^ " " ^ s_"Filesystem for the image";
+ "--size", Arg.String set_size, "size" ^ " " ^ s_"Set output disk size";
+ "--formats", Arg.String set_format, "qcow2,tgz,..." ^ " " ^ s_"Output formats";
+ "--arch", Arg.Set_string arch, "arch" ^ " " ^ s_"Output architecture";
+ "--drive", Arg.String set_drive, "path" ^ " " ^ s_"Optional drive for caches";
+
+ "-m", Arg.Int set_memsize, "mb" ^ " " ^ s_"Set memory size";
+ "--memsize", Arg.Int set_memsize, "mb" ^ " " ^ s_"Set memory size";
+ "--network", Arg.Set network, " " ^ s_"Enable appliance network (default)";
+ "--no-network", Arg.Clear network, " " ^ s_"Disable appliance network";
+ "--smp", Arg.Int set_smp, "vcpus" ^ " " ^ s_"Set number of vCPUs";
+ "--no-delete-on-failure", Arg.Clear delete_on_failure,
+ " " ^ s_"Don't delete output file on failure";
+ "--machine-readable", Arg.Set machine_readable, " " ^ s_"Make output machine readable";
+
+ "-V", Arg.Unit print_version_and_exit, " " ^ s_"Display version and exit";
+ "--version", Arg.Unit print_version_and_exit, " " ^ s_"Display version and exit";
+ "-v", Arg.Unit set_verbose, " " ^ s_"Enable libguestfs debugging messages";
+ "--verbose", Arg.Unit set_verbose, " " ^ s_"Enable libguestfs debugging messages";
+ "-x", Arg.Unit set_trace, " " ^ s_"Enable tracing of libguestfs calls";
+ "--debug", Arg.Int set_debug, "level" ^ " " ^ s_"Set debug level";
+ "-B", Arg.Set_string basepath, "path" ^ " " ^ s_"Base path of diskimage-builder library";
+ ] in
+
+ let argspec =
+ let cmp (arg1, _, _) (arg2, _, _) =
+ let arg1 = skip_dashes arg1 and arg2 = skip_dashes arg2 in
+ compare (String.lowercase arg1) (String.lowercase arg2)
+ in
+ List.sort cmp argspec in
+ let argspec = Arg.align argspec in
+ long_options := argspec;
+
+ Arg.parse argspec append_element usage_msg;
+
+ let debug = !debug in
+ let basepath = !basepath in
+ let elements = List.rev !elements in
+ let excluded_elements = List.rev !excluded_elements in
+ let element_paths = List.rev !element_paths in
+ let excluded_scripts = List.rev !excluded_scripts in
+ let image_name = !image_name in
+ let fs_type = !fs_type in
+ let size = !size in
+ let memsize = !memsize in
+ let network = !network in
+ let smp = !smp in
+ let formats = !formats in
+ let envvars = !envvars in
+ let use_base = !use_base in
+ let arch = !arch in
+ let drive = !drive in
+ let root_label = !root_label in
+ let install_type = !install_type in
+ let image_cache = !image_cache in
+ let compressed = !compressed in
+ let delete_on_failure = !delete_on_failure in
+ let is_ramdisk = !is_ramdisk in
+ let ramdisk_element = !ramdisk_element in
+ let qemu_img_options = !qemu_img_options in
+ let mkfs_options = !mkfs_options in
+ let machine_readable = !machine_readable in
+ let extra_packages = List.rev !extra_packages in
+
+ (* No elements and machine-readable mode? Print some facts. *)
+ if elements = [] && machine_readable then (
+ printf "virt-dib\n";
+ printf "output:qcow2\n";
+ printf "output:tar\n";
+ printf "output:raw\n";
+ printf "output:vhd\n";
+ exit 0
+ );
+
+ if basepath = "" then
+ error (f_"-B must be specified");
+
+ if formats = [] then
+ error (f_"the list of output formats cannot be empty");
+
+ if elements = [] then
+ error (f_"at least one distribution root element must be specified");
+
+ debug, basepath, elements, excluded_elements, element_paths,
+ excluded_scripts, use_base, drive,
+ image_name, fs_type, size, root_label, install_type, image_cache, compressed,
+ qemu_img_options, mkfs_options, is_ramdisk, ramdisk_element, extra_packages,
+ memsize, network, smp, delete_on_failure, formats, arch, envvars
diff --git a/dib/dib.ml b/dib/dib.ml
new file mode 100644
index 0000000..b9c0588
--- /dev/null
+++ b/dib/dib.ml
@@ -0,0 +1,917 @@
+(* virt-dib
+ * Copyright (C) 2015 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.
+ *)
+
+open Common_gettext.Gettext
+open Common_utils
+
+open Cmdline
+open Utils
+open Elements
+
+open Printf
+
+module G = Guestfs
+
+let exclude_elements elements = function
+ | [] ->
+ (* No elements to filter out, so just don't bother iterating through
+ * the elements. *)
+ elements
+ | excl -> StringSet.filter (not_in_list excl) elements
+
+let read_envvars envvars =
+ filter_map (
+ fun var ->
+ let i = string_find var "=" in
+ if i = -1 then (
+ try Some (var, Sys.getenv var)
+ with Not_found -> None
+ ) else (
+ let len = String.length var in
+ Some (String.sub var 0 i, String.sub var (i + 1) (len - i - 1))
+ )
+ ) envvars
+
+let read_dib_envvars () =
+ let vars = Array.to_list (Unix.environment ()) in
+ let vars = List.filter (fun x -> string_prefix x "DIB_") vars in
+ let vars = List.map (fun x -> x ^ "\n") vars in
+ String.concat "" vars
+
+let make_dib_args args =
+ let args = Array.to_list args in
+ let rec quote_args = function
+ | [] -> ""
+ | x :: xs -> " " ^ (quote x) ^ quote_args xs
+ in
+ match args with
+ | [] -> ""
+ | app :: xs -> app ^ quote_args xs
+
+let write_script fn text =
+ let oc = open_out fn in
+ output_string oc text;
+ flush oc;
+ close_out oc;
+ Unix.chmod fn 0o755
+
+let prepare_external ~dib_args ~dib_vars ~out_name ~root_label ~rootfs_uuid
+ ~image_cache ~arch ~network ~debug
+ destdir libdir hooksdir tmpdir fakebindir all_elements element_paths =
+ let network_string = if network then "" else "1" in
+
+ let run_extra = sprintf "\
+#!/bin/bash
+%s
+target_dir=$1
+shift
+script=$1
+shift
+
+export PATH=%s:$PATH
+
+# d-i-b variables
+export TMP_MOUNT_PATH=%s
+export DIB_OFFLINE=%s
+export IMAGE_NAME=\"%s\"
+export DIB_ROOT_LABEL=\"%s\"
+export DIB_IMAGE_ROOT_FS_UUID=%s
+export DIB_IMAGE_CACHE=\"%s\"
+export _LIB=%s
+export ARCH=%s
+export TMP_HOOKS_PATH=%s
+export DIB_ARGS=\"%s\"
+export IMAGE_ELEMENT=\"%s\"
+export ELEMENTS_PATH=\"%s\"
+export DIB_ENV=%s
+export TMPDIR=\"${TMP_MOUNT_PATH}/tmp\"
+export TMP_DIR=\"${TMPDIR}\"
+export DIB_DEBUG_TRACE=%d
+
+ENVIRONMENT_D_DIR=$target_dir/../environment.d
+
+if [ -d $ENVIRONMENT_D_DIR ] ; then
+ env_files=$(find $ENVIRONMENT_D_DIR -maxdepth 1 -xtype f | \
+ grep -E \"/[0-9A-Za-z_\\.-]+$\" | \
+ LANG=C sort -n)
+ for env_file in $env_files ; do
+ source $env_file
+ done
+fi
+
+$target_dir/$script
+"
+ (if debug >= 1 then "set -x\n" else "")
+ fakebindir
+ (quote tmpdir)
+ network_string
+ out_name
+ root_label
+ rootfs_uuid
+ image_cache
+ (quote libdir)
+ arch
+ (quote hooksdir)
+ dib_args
+ (String.concat " " (StringSet.elements all_elements))
+ (String.concat ":" element_paths)
+ (quote dib_vars)
+ debug in
+ write_script (destdir // "run-part-extra.sh") run_extra;
+
+ (* Needed as TMPDIR for the extra-data hooks *)
+ do_mkdir (tmpdir // "tmp")
+
+let prepare_aux ~envvars ~dib_args ~dib_vars ~log_file ~out_name ~rootfs_uuid
+ ~arch ~network ~root_label ~install_type ~debug ~extra_packages
+ destdir all_elements =
+ let envvars_string = List.map (
+ fun (var, value) ->
+ sprintf "export %s=%s" var (quote value)
+ ) envvars in
+ let network_string = if network then "" else "1" in
+
+ let script_run_part = sprintf "\
+#!/bin/bash
+%s
+sysroot=$1
+shift
+mysysroot=$1
+shift
+blockdev=$1
+shift
+target_dir=$1
+shift
+new_wd=$1
+shift
+script=$1
+shift
+
+# user variables
+%s
+
+# system variables
+export HOME=$mysysroot/tmp/aux/perm/home
+export PATH=$mysysroot/tmp/aux/hooks/bin:$PATH
+export TMP=$mysysroot/tmp
+export TMPDIR=$TMP
+export TMP_DIR=$TMP
+
+# d-i-b variables
+export TMP_MOUNT_PATH=$sysroot
+export TARGET_ROOT=$sysroot
+export DIB_OFFLINE=%s
+export IMAGE_NAME=\"%s\"
+export DIB_IMAGE_ROOT_FS_UUID=%s
+export DIB_IMAGE_CACHE=$HOME/.cache/image-create
+export DIB_ROOT_LABEL=\"%s\"
+export _LIB=$mysysroot/tmp/aux/lib
+export _PREFIX=$mysysroot/tmp/aux/elements
+export ARCH=%s
+export TMP_HOOKS_PATH=$mysysroot/tmp/aux/hooks
+export DIB_ARGS=\"%s\"
+export DIB_MANIFEST_SAVE_DIR=\"$mysysroot/tmp/aux/out/${IMAGE_NAME}.d\"
+export IMAGE_BLOCK_DEVICE=$blockdev
+export IMAGE_ELEMENT=\"%s\"
+export DIB_ENV=%s
+export DIB_DEBUG_TRACE=%d
+export DIB_NO_TMPFS=1
+
+export TMP_BUILD_DIR=$mysysroot/tmp/aux
+export TMP_IMAGE_DIR=$mysysroot/tmp/aux
+
+if [ -n \"$mysysroot\" ]; then
+ export PATH=$mysysroot/tmp/aux/fake-bin:$PATH
+else
+ export PATH=\"$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"
+fi
+
+ENVIRONMENT_D_DIR=$target_dir/../environment.d
+
+if [ -d $ENVIRONMENT_D_DIR ] ; then
+ env_files=$(find $ENVIRONMENT_D_DIR -maxdepth 1 -xtype f | \
+ grep -E \"/[0-9A-Za-z_\\.-]+$\" | \
+ LANG=C sort -n)
+ for env_file in $env_files ; do
+ source $env_file
+ done
+fi
+
+if [ -n \"$new_wd\" ]; then
+ cd \"$mysysroot/$new_wd\"
+fi
+
+$target_dir/$script
+"
+ (if debug >= 1 then "set -x\n" else "")
+ (String.concat "\n" envvars_string)
+ network_string
+ out_name
+ rootfs_uuid
+ root_label
+ arch
+ dib_args
+ (String.concat " " (StringSet.elements all_elements))
+ (quote dib_vars)
+ debug in
+ write_script (destdir // "run-part.sh") script_run_part;
+ let script_run_and_log = "\
+#!/bin/bash
+logfile=$1
+shift
+exec 3>&1
+exit `( ( ( $(dirname $0)/run-part.sh \"$@\" ) 2>&1 3>&-; echo $? >&4) | tee -a $logfile >&3 >&2) 4>&1`
+" in
+ write_script (destdir // "run-and-log.sh") script_run_and_log;
+
+ (* Create the fake sudo support. *)
+ do_mkdir (destdir // "fake-bin");
+ let fake_sudo = "\
+#!/bin/bash
+
+SCRIPTNAME=fake-sudo
+
+ARGS_SHORT=\"EHiu:\"
+ARGS_LONG=\"\"
+TEMP=`POSIXLY_CORRECT=1 getopt ${ARGS_SHORT:+-o $ARGS_SHORT} ${ARGS_LONG:+--long $ARGS_LONG} \
+ -n \"$SCRIPTNAME\" -- \"$@\"`
+if [ $? != 0 ]; then echo \"$SCRIPTNAME: terminating...\" >&2 ; exit 1 ; fi
+eval set -- \"$TEMP\"
+
+preserve_env=
+set_home=
+login_shell=
+user=
+
+while true; do
+ case \"$1\" in
+ -E) preserve_env=1; shift;;
+ -H) set_home=1; shift;;
+ -i) login_shell=1; shift;;
+ -u) user=$2; shift 2;;
+ --) shift; break;;
+ *) echo \"$SCRIPTNAME: internal arguments error\"; exit 1;;
+ esac
+done
+
+if [ -n \"$user\" ]; then
+ if [ $user != root -a $user != `whoami` ]; then
+ echo \"$SCRIPTNAME: cannot use the sudo user $user, only root and $(whoami) handled\" >&2
+ exit 1
+ fi
+fi
+
+if [ -z \"$preserve_env\" ]; then
+ for envvar in `env | grep '^\\w' | cut -d= -f1`; do
+ case \"$envvar\" in
+ PATH | USER | USERNAME | HOSTNAME | TERM | LANG | HOME | SHELL | LOGNAME ) ;;
+ *) unset $envvar ;;
+ esac
+ done
+fi
+
+cmd=$1
+shift
+$cmd \"$@\"
+" in
+ write_script (destdir // "fake-bin" // "sudo") fake_sudo;
+ (* Pick dib-run-parts from the host, if available, otherwise put
+ * a fake executable which will error out if used.
+ *)
+ (try
+ let loc = which "dib-run-parts" in
+ do_cp loc (destdir // "fake-bin")
+ with Tool_not_found _ ->
+ let fake_dib_run_parts = "\
+#!/bin/sh
+echo \"Please install dib-run-parts on the host\"
+exit 1
+" in
+ write_script (destdir // "fake-bin" // "dib-run-parts") fake_dib_run_parts;
+ );
+
+ (* Write the custom hooks. *)
+ let script_install_type_env = sprintf "\
+export DIB_DEFAULT_INSTALLTYPE=${DIB_DEFAULT_INSTALLTYPE:-\"%s\"}
+"
+ install_type in
+ write_script (destdir // "hooks" // "environment.d" // "11-dib-install-type.bash") script_install_type_env;
+
+ (* Write install-packages.sh if needed. *)
+ if extra_packages <> [] then (
+ let script_install_packages = sprintf "\
+#!/bin/bash
+install-packages %s
+"
+ (String.concat " " extra_packages) in
+ write_script (destdir // "install-packages.sh") script_install_packages;
+ );
+
+ do_mkdir (destdir // "perm")
+
+let timing_output ~target_name entries timings =
+ let buf = Buffer.create 4096 in
+ Buffer.add_string buf "----------------------- PROFILING -----------------------\n";
+ Buffer.add_char buf '\n';
+ bprintf buf "Target: %s\n" target_name;
+ Buffer.add_char buf '\n';
+ bprintf buf "%-40s %9s\n" "Script" "Seconds";
+ bprintf buf "%-40s %9s\n" "---------------------------------------" "----------";
+ Buffer.add_char buf '\n';
+ List.iter (
+ fun x ->
+ bprintf buf "%-40s %10.3f\n" x (Hashtbl.find timings x);
+ ) entries;
+ Buffer.add_char buf '\n';
+ Buffer.add_string buf "--------------------- END PROFILING ---------------------\n";
+ Buffer.contents buf
+
+type sysroot_type =
+ | In
+ | Out
+ | Subroot
+
+let timed_run fn =
+ let time_before = Unix.gettimeofday () in
+ fn ();
+ let time_after = Unix.gettimeofday () in
+ time_after -. time_before
+
+let run_parts ~debug ~sysroot ~blockdev ~log_file ?(new_wd = "")
+ (g : Guestfs.guestfs) hook_name scripts =
+ let hook_dir = "/tmp/aux/hooks/" ^ hook_name in
+ let scripts = List.sort digit_prefix_compare scripts in
+ let outbuf = Buffer.create 16384 in
+ let timings = Hashtbl.create 13 in
+ let new_wd =
+ match sysroot, new_wd with
+ | (Out|Subroot), "" -> "''"
+ | _, dir -> dir in
+ List.iter (
+ fun x ->
+ message (f_"Running: %s/%s") hook_name x;
+ g#write_append log_file (sprintf "Running %s/%s...\n" hook_name x);
+ let out = ref "" in
+ let run () =
+ let outstr =
+ match sysroot with
+ | In ->
+ g#sh (sprintf "/tmp/aux/run-and-log.sh '%s' '' '' '%s' '%s' '%s' '%s'" log_file blockdev hook_dir new_wd x)
+ | Out ->
+ g#debug "sh" [| "/sysroot/tmp/aux/run-and-log.sh"; "/sysroot" ^ log_file; "/sysroot"; "/sysroot"; blockdev; "/sysroot" ^ hook_dir; new_wd; x |]
+ | Subroot ->
+ g#debug "sh" [| "/sysroot/tmp/aux/run-and-log.sh"; "/sysroot" ^ log_file; "/sysroot/subroot"; "/sysroot"; blockdev; "/sysroot" ^ hook_dir; new_wd; x |] in
+ out := outstr;
+ Buffer.add_string outbuf outstr in
+ let delta_t = timed_run run in
+ Buffer.add_char outbuf '\n';
+ out := ensure_trailing_newline !out;
+ printf "%s%!" !out;
+ if debug >= 1 then (
+ printf "%s completed after %.3f s\n" x delta_t
+ );
+ Hashtbl.add timings x delta_t;
+ ) scripts;
+ g#write_append log_file (timing_output ~target_name:hook_name scripts timings);
+ flush_all ();
+ Buffer.contents outbuf
+
+let run_parts_host ~debug hooks_dir hook_name scripts run_script =
+ let hook_dir = hooks_dir // hook_name in
+ let scripts = List.sort digit_prefix_compare scripts in
+ let timings = Hashtbl.create 13 in
+ List.iter (
+ fun x ->
+ message (f_"Running: %s/%s") hook_name x;
+ let cmd = sprintf "%s %s %s" (quote run_script) (quote hook_dir) (quote x) in
+ let run () =
+ run_command cmd in
+ let delta_t = timed_run run in
+ if debug >= 1 then (
+ printf "\n";
+ printf "%s completed after %.3f s\n" x delta_t
+ );
+ Hashtbl.add timings x delta_t;
+ ) scripts;
+ if debug >= 1 then (
+ print_string (timing_output ~target_name:hook_name scripts timings)
+ );
+ flush_all ()
+
+let run_install_packages ~debug ~blockdev ~log_file
+ (g : Guestfs.guestfs) packages =
+ let pkgs_string = String.concat " " packages in
+ message (f_"Installing: %s") pkgs_string;
+ g#write_append log_file (sprintf "Installing %s...\n" pkgs_string);
+ let out = g#sh (sprintf "/tmp/aux/run-and-log.sh '%s' '' '' '%s' '/tmp/aux' '' 'install-packages.sh'" log_file blockdev) in
+ let out = ensure_trailing_newline out in
+ if debug >= 1 then (
+ printf "%s%!" out;
+ printf "package installation completed\n";
+ );
+ flush_all ();
+ out
+
+let main () =
+ let debug, basepath, elements, excluded_elements, element_paths,
+ excluded_scripts, use_base, drive,
+ image_name, fs_type, size, root_label, install_type, image_cache, compressed,
+ qemu_img_options, mkfs_options, is_ramdisk, ramdisk_element, extra_packages,
+ memsize, network, smp, delete_on_failure, formats, arch, envvars =
+ parse_args () in
+
+ (* Check that the specified base directory of diskimage-builder
+ * has the "die" script in it, so we know the directory is the
+ * right one (hopefully so, at least).
+ *)
+ if not (Sys.file_exists (basepath // "die")) then
+ error (f_"the specified base path is not the diskimage-builder library");
+
+ (* Check for required tools. *)
+ require_tool "uuidgen";
+ if List.mem "qcow2" formats then
+ require_tool "qemu-img";
+ if List.mem "vhd" formats then
+ require_tool "vhd-util";
+
+ let image_name_d = image_name ^ ".d" in
+
+ let tmpdir = Mkdtemp.temp_dir "dib." "" in
+ rmdir_on_exit tmpdir;
+ let auxtmpdir = tmpdir // "aux" in
+ do_mkdir auxtmpdir;
+ let hookstmpdir = auxtmpdir // "hooks" in
+ do_mkdir (hookstmpdir // "environment.d"); (* Just like d-i-b does. *)
+ let extradatatmpdir = tmpdir // "extra-data" in
+ do_mkdir extradatatmpdir;
+ do_mkdir (auxtmpdir // "out" // image_name_d);
+ let elements = if use_base then ["base"] @ elements else elements in
+ let elements = if is_ramdisk then [ramdisk_element] @ elements else elements in
+ message (f_"Elements: %s") (String.concat " " elements);
+ if debug >= 1 then (
+ printf "tmpdir: %s\n" tmpdir;
+ printf "element paths: %s\n" (String.concat ":" element_paths);
+ );
+
+ let loaded_elements = load_elements ~debug element_paths in
+ if debug >= 1 then (
+ printf "loaded elements:\n";
+ Hashtbl.iter (
+ fun k v ->
+ printf " %s => %s\n" k v.directory;
+ Hashtbl.iter (
+ fun k v ->
+ printf "\t%-20s %s\n" k (String.concat " " (List.sort compare v))
+ ) v.hooks;
+ ) loaded_elements;
+ printf "\n";
+ );
+ let all_elements = load_dependencies elements loaded_elements in
+ let all_elements = exclude_elements all_elements
+ (excluded_elements @ builtin_elements_blacklist) in
+
+ message (f_"Expanded elements: %s") (String.concat " " (StringSet.elements all_elements));
+
+ let envvars = read_envvars envvars in
+ message (f_"Carried environment variables: %s") (String.concat " " (List.map fst envvars));
+ if debug >= 1 then (
+ printf "carried over envvars:\n";
+ if envvars <> [] then
+ List.iter (
+ fun (var, value) ->
+ printf " %s=%s\n" var value
+ ) envvars
+ else
+ printf " (none)\n";
+ printf "\n";
+ );
+ let dib_args = make_dib_args Sys.argv in
+ let dib_vars = read_dib_envvars () in
+ if debug >= 1 then (
+ printf "DIB args:\n%s\n" dib_args;
+ printf "DIB envvars:\n%s\n" dib_vars
+ );
+
+ message (f_"Preparing auxiliary data");
+
+ copy_elements all_elements loaded_elements
+ (excluded_scripts @ builtin_scripts_blacklist) hookstmpdir;
+
+ (* Re-read the hook scripts from the hooks dir, as d-i-b (and we too)
+ * has basically copied over anything found in elements.
+ *)
+ let final_hooks = load_hooks ~debug hookstmpdir in
+
+ let log_file = "/tmp/aux/perm/" ^ (log_filename ()) in
+
+ let arch =
+ match arch with
+ | "" -> current_arch ()
+ | arch -> arch in
+
+ let root_label =
+ match root_label with
+ | None ->
+ (* XFS has a limit of 12 characters for filesystem labels.
+ * Not changing the default for other filesystems to maintain
+ * backwards compatibility.
+ *)
+ (match fs_type with
+ | "xfs" -> "img-rootfs"
+ | _ -> "cloudimg-rootfs")
+ | Some label -> label in
+
+ let image_cache =
+ match image_cache with
+ | None -> Sys.getenv "HOME" // ".cache" // "image-create"
+ | Some dir -> dir in
+ do_mkdir image_cache;
+
+ let rootfs_uuid = uuidgen () in
+
+ let formats_img, formats_archive = List.partition (
+ function
+ | "qcow2" | "raw" | "vhd" -> true
+ | _ -> false
+ ) formats in
+ let formats_img_nonraw = List.filter ((<>) "raw") formats_img in
+
+ prepare_aux ~envvars ~dib_args ~dib_vars ~log_file ~out_name:image_name
+ ~rootfs_uuid ~arch ~network ~root_label ~install_type ~debug
+ ~extra_packages
+ auxtmpdir all_elements;
+
+ let delete_output_file = ref delete_on_failure in
+ let delete_file () =
+ if !delete_output_file then (
+ List.iter (
+ fun fmt ->
+ try Unix.unlink (output_filename image_name fmt) with _ -> ()
+ ) formats
+ )
+ in
+ at_exit delete_file;
+
+ prepare_external ~dib_args ~dib_vars ~out_name:image_name ~root_label
+ ~rootfs_uuid ~image_cache ~arch ~network ~debug
+ tmpdir basepath hookstmpdir extradatatmpdir (auxtmpdir // "fake-bin")
+ all_elements element_paths;
+
+ let run_hook_host hook =
+ try
+ let scripts = Hashtbl.find final_hooks hook in
+ if debug >= 1 then (
+ printf "Running hooks for %s...\n%!" hook;
+ );
+ run_parts_host ~debug hookstmpdir hook scripts
+ (tmpdir // "run-part-extra.sh")
+ with Not_found -> ()
+ and run_hook ~blockdev ~sysroot ?(new_wd = "") (g : Guestfs.guestfs) hook =
+ try
+ let scripts = Hashtbl.find final_hooks hook in
+ if debug >= 1 then (
+ printf "Running hooks for %s...\n%!" hook;
+ );
+ run_parts ~debug ~sysroot ~blockdev ~log_file ~new_wd g hook scripts
+ with Not_found -> "" in
+
+ run_hook_host "extra-data.d";
+
+ let copy_in (g : Guestfs.guestfs) srcdir destdir =
+ let desttar = Filename.temp_file ~temp_dir:tmpdir "virt-dib." ".tar.gz" in
+ let cmd = sprintf "tar czf %s -C %s --owner=root --group=root ."
+ (quote desttar) (quote srcdir) in
+ run_command cmd;
+ g#mkdir_p destdir;
+ g#tar_in ~compress:"gzip" desttar destdir;
+ Sys.remove desttar in
+
+ let copy_preserve_in (g : Guestfs.guestfs) srcdir destdir =
+ let desttar = Filename.temp_file ~temp_dir:tmpdir "virt-dib." ".tar.gz" in
+ let remotetar = "/tmp/aux/" ^ (Filename.basename desttar) in
+ let cmd = sprintf "tar czf %s -C %s --owner=root --group=root ."
+ (quote desttar) (quote srcdir) in
+ run_command cmd;
+ g#upload desttar remotetar;
+ let verbose_flag = if debug > 0 then "v" else "" in
+ ignore (g#debug "sh" [| "tar"; "-C"; "/sysroot" ^ destdir; "--no-overwrite-dir"; "-x" ^ verbose_flag ^ "zf"; "/sysroot" ^ remotetar |]);
+ Sys.remove desttar;
+ g#rm remotetar in
+
+ if debug >= 1 then
+ ignore (Sys.command (sprintf "tree -ps %s" (quote tmpdir)));
+
+ message (f_"Opening the disks");
+
+ let is_ramdisk_build = is_ramdisk || StringSet.mem "ironic-agent" all_elements in
+
+ let g, tmpdisk, tmpdiskfmt, drive_partition =
+ let g = new G.guestfs () in
+ if verbose () then g#set_verbose true;
+ if trace () then g#set_trace true;
+
+ (match memsize with None -> () | Some memsize -> g#set_memsize memsize);
+ (match smp with None -> () | Some smp -> g#set_smp smp);
+ g#set_network network;
+
+ (* Make sure to turn SELinux off to avoid awkward interactions
+ * between the appliance kernel and applications/libraries interacting
+ * with SELinux xattrs.
+ *)
+ g#set_selinux false;
+
+ (* Main disk with the built image. *)
+ let fmt = "raw" in
+ let fn =
+ (* If "raw" is among the selected outputs, use it as main backing
+ * disk, otherwise create a temporary disk.
+ *)
+ if not is_ramdisk_build && List.mem "raw" formats_img then image_name
+ else Filename.temp_file ~temp_dir:tmpdir "image." "" in
+ let fn = output_filename fn fmt in
+ (* Produce the output image. *)
+ g#disk_create fn fmt size;
+ g#add_drive ~readonly:false ~format:fmt fn;
+
+ (* Helper drive for elements and binaries. *)
+ g#add_drive_scratch (unit_GB 5);
+
+ (match drive with
+ | None ->
+ g#add_drive_scratch (unit_GB 5)
+ | Some drive ->
+ g#add_drive drive;
+ );
+
+ g#launch ();
+
+ (* Prepare the /aux partition. *)
+ g#mkfs "ext2" "/dev/sdb";
+ g#mount "/dev/sdb" "/";
+
+ copy_in g auxtmpdir "/";
+ copy_in g basepath "/lib";
+ g#umount "/";
+
+ (* Prepare the /aux/perm partition. *)
+ let drive_partition =
+ match drive with
+ | None ->
+ g#mkfs "ext2" "/dev/sdc";
+ "/dev/sdc"
+ | Some _ ->
+ let partitions = Array.to_list (g#list_partitions ()) in
+ (match partitions with
+ | [] -> "/dev/sdc"
+ | p ->
+ let p = List.filter (fun x -> string_prefix x "/dev/sdc") p in
+ if p = [] then
+ error (f_"no partitions found in the helper drive");
+ List.hd p
+ ) in
+ g#mount drive_partition "/";
+ g#mkdir_p "/home/.cache/image-create";
+ g#umount "/";
+
+ g, fn, fmt, drive_partition in
+
+ let mount_aux () =
+ g#mkmountpoint "/tmp/aux";
+ g#mount "/dev/sdb" "/tmp/aux";
+ g#mount drive_partition "/tmp/aux/perm" in
+
+ (* Small kludge: try to umount all first: if that fails, use lsof and fuser
+ * to find out what might have caused the failure, run udevadm to try
+ * to settle things down (udev, you never know), and try umount all again.
+ *)
+ let checked_umount_all () =
+ try g#umount_all ()
+ with G.Error _ ->
+ if debug >= 1 then (
+ (try printf "lsof:\n%s\nEND\n" (g#debug "sh" [| "lsof"; "/sysroot"; |]) with _ -> ());
+ (try printf "fuser:\n%s\nEND\n" (g#debug "sh" [| "fuser"; "-v"; "-m"; "/sysroot"; |]) with _ -> ());
+ (try printf "losetup:\n%s\nEND\n" (g#debug "sh" [| "losetup"; "--list"; "--all" |]) with _ -> ());
+ );
+ ignore (g#debug "sh" [| "udevadm"; "--debug"; "settle" |]);
+ g#umount_all () in
+
+ g#mkmountpoint "/tmp";
+ mount_aux ();
+
+ let blockdev =
+ (* Setup a loopback device, just like d-i-b would tie an image in the host
+ * environment.
+ *)
+ let run_losetup device =
+ let lines = g#debug "sh" [| "losetup"; "--show"; "-f"; device |] in
+ let lines = string_nsplit "\n" lines in
+ let lines = List.filter ((<>) "") lines in
+ (match lines with
+ | [] -> device
+ | x :: _ -> x
+ ) in
+ let blockdev = run_losetup "/dev/sda" in
+
+ let run_hook_out_eval hook envvar =
+ let lines = run_hook ~sysroot:Out ~blockdev g hook in
+ let lines = string_nsplit "\n" lines in
+ let lines = List.filter ((<>) "") lines in
+ if lines = [] then None
+ else (try Some (var_from_lines envvar lines) with _ -> None) in
+
+ (match run_hook_out_eval "block-device.d" "IMAGE_BLOCK_DEVICE" with
+ | None -> blockdev
+ | Some x -> x
+ ) in
+
+ let rec run_hook_out ?(new_wd = "") hook =
+ do_run_hooks_noout ~sysroot:Out ~new_wd hook
+ and run_hook_in hook =
+ do_run_hooks_noout ~sysroot:In hook
+ and run_hook_subroot hook =
+ do_run_hooks_noout ~sysroot:Subroot hook
+ and do_run_hooks_noout ~sysroot ?(new_wd = "") hook =
+ ignore (run_hook ~sysroot ~blockdev ~new_wd g hook) in
+
+ g#sync ();
+ checked_umount_all ();
+ flush_all ();
+
+ message (f_"Setting up the destination root");
+
+ (* Create and mount the target filesystem. *)
+ let mkfs_options =
+ match mkfs_options with
+ | None -> []
+ | Some o -> [ o ] in
+ let mkfs_options =
+ (match fs_type with
+ | "ext4" ->
+ (* Very conservative to handle images being resized a lot
+ * Without -J option specified, default journal size will be set to 32M
+ * and online resize will be failed with error of needs too many credits.
+ *)
+ [ "-i"; "4096"; "-J"; "size=64" ]
+ | _ -> []
+ ) @ mkfs_options @ [ "-t"; fs_type; blockdev ] in
+ ignore (g#debug "sh" (Array.of_list ([ "mkfs" ] @ mkfs_options)));
+ g#set_label blockdev root_label;
+ (match fs_type with
+ | x when string_prefix x "ext" -> g#set_uuid blockdev rootfs_uuid
+ | _ -> ());
+ g#mount blockdev "/";
+ g#mkmountpoint "/tmp";
+ mount_aux ();
+ g#mkdir "/subroot";
+
+ run_hook_subroot "root.d";
+
+ g#sync ();
+ g#umount "/tmp/aux/perm";
+ g#umount "/tmp/aux";
+ g#rm_rf "/tmp";
+ let subroot_items =
+ let l = Array.to_list (g#ls "/subroot") in
+ let l_lost_plus_found, l = List.partition ((=) "lost+found") l in
+ if l_lost_plus_found <> [] then (
+ g#rm_rf "/subroot/lost+found";
+ );
+ l in
+ List.iter (fun x -> g#mv ("/subroot/" ^ x) ("/" ^ x)) subroot_items;
+ g#rmdir "/subroot";
+ (* Check /tmp exists already. *)
+ ignore (g#is_dir "/tmp");
+ mount_aux ();
+ g#ln_s "aux/hooks" "/tmp/in_target.d";
+
+ copy_preserve_in g extradatatmpdir "/";
+
+ run_hook_in "pre-install.d";
+
+ if extra_packages <> [] then
+ ignore (run_install_packages ~debug ~blockdev ~log_file g extra_packages);
+
+ run_hook_in "install.d";
+
+ run_hook_in "post-install.d";
+
+ (* Unmount and remount the image, as d-i-b does at this point too. *)
+ g#sync ();
+ checked_umount_all ();
+ flush_all ();
+ g#mount blockdev "/";
+ (* Check /tmp/aux still exists. *)
+ ignore (g#is_dir "/tmp/aux");
+ g#mount "/dev/sdb" "/tmp/aux";
+ g#mount drive_partition "/tmp/aux/perm";
+
+ run_hook_in "finalise.d";
+
+ let out_dir = "/tmp/aux/out/" ^ image_name_d in
+
+ run_hook_out ~new_wd:out_dir "cleanup.d";
+
+ g#sync ();
+
+ if g#ls out_dir <> [||] then (
+ message (f_"Extracting data out of the image");
+ do_mkdir image_name_d;
+ g#copy_out out_dir ".";
+ );
+
+ (* Unmount everything, and remount only the root to cleanup
+ * its /tmp; this way we should be pretty sure that there is
+ * nothing left mounted over /tmp, so it is safe to empty it.
+ *)
+ checked_umount_all ();
+ flush_all ();
+ g#mount blockdev "/";
+ Array.iter (fun x -> g#rm_rf ("/tmp/" ^ x)) (g#ls "/tmp");
+
+ flush_all ();
+
+ List.iter (
+ fun fmt ->
+ let fn = output_filename image_name fmt in
+ match fmt with
+ | "tar" ->
+ message (f_"Compressing the image as tar");
+ g#tar_out ~excludes:[| "./sys/*"; "./proc/*" |] "/" fn
+ | _ as fmt -> error "unhandled format: %s" fmt
+ ) formats_archive;
+
+ message (f_"Umounting the disks");
+
+ (* Now that we've finished the build, don't delete the output file on
+ * exit.
+ *)
+ delete_output_file := false;
+
+ g#sync ();
+ checked_umount_all ();
+ g#shutdown ();
+ g#close ();
+
+ flush_all ();
+
+ (* Don't produce images as output when doing a ramdisk build. *)
+ if not is_ramdisk_build then (
+ List.iter (
+ fun fmt ->
+ let fn = output_filename image_name fmt in
+ message (f_"Converting to %s") fmt;
+ match fmt with
+ | "qcow2" ->
+ let cmd =
+ sprintf "qemu-img convert%s -f %s %s -O %s%s %s"
+ (if compressed then " -c" else "")
+ tmpdiskfmt
+ (quote tmpdisk)
+ fmt
+ (match qemu_img_options with
+ | None -> ""
+ | Some opt -> " -o " ^ quote opt)
+ (quote (qemu_input_filename fn)) in
+ if debug >= 1 then
+ printf "%s\n%!" cmd;
+ run_command cmd
+ | "vhd" ->
+ let fn_intermediate = Filename.temp_file ~temp_dir:tmpdir "vhd-intermediate." "" in
+ let cmd =
+ sprintf "vhd-util convert -s 0 -t 1 -i %s -o %s"
+ (quote tmpdisk)
+ (quote fn_intermediate) in
+ if debug >= 1 then
+ printf "%s\n%!" cmd;
+ run_command cmd;
+ let cmd =
+ sprintf "vhd-util convert -s 1 -t 2 -i %s -o %s"
+ (quote fn_intermediate)
+ (quote fn) in
+ if debug >= 1 then
+ printf "%s\n%!" cmd;
+ run_command cmd;
+ if not (Sys.file_exists fn) then
+ error (f_"VHD output not produced, most probably vhd-util is old or not patched for 'convert'")
+ | _ as fmt -> error "unhandled format: %s" fmt
+ ) formats_img_nonraw;
+ );
+
+ message (f_"Done")
+
+let () = run_main_and_handle_errors main
diff --git a/dib/elements.ml b/dib/elements.ml
new file mode 100644
index 0000000..216a5f6
--- /dev/null
+++ b/dib/elements.ml
@@ -0,0 +1,187 @@
+(* virt-dib
+ * Copyright (C) 2015 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.
+ *)
+
+(* Parsing and handling of elements. *)
+
+open Common_gettext.Gettext
+open Common_utils
+
+open Utils
+
+open Printf
+
+module StringSet = Set.Make (String)
+
+type element = {
+ directory : string;
+ hooks : hooks_map;
+}
+and hooks_map = (string, string list) Hashtbl.t (* hook name, scripts *)
+
+exception Duplicate_script of string * string (* hook, script *)
+
+(* These are the elements which we don't ever try to use. *)
+let builtin_elements_blacklist = [
+]
+
+(* These are the scripts which we don't ever try to run.
+ * Usual reason could be that they are not compatible the way virt-dib works:
+ * e.g. they expect the tree of elements outside the chroot, which is not
+ * available in the appliance. *)
+let builtin_scripts_blacklist = [
+ "01-sahara-version"; (* Gets the Git commit ID of the d-i-b and
+ * sahara-image-elements repositories. *)
+]
+
+let valid_script_name n =
+ let is_char_valid = function
+ | 'A'..'Z' | 'a'..'z' | '0'..'9' | '_' | '-' -> true
+ | _ -> false in
+ try ignore (string_index_fn (fun c -> not (is_char_valid c)) n); false
+ with Not_found -> true
+
+let stringset_of_list l =
+ List.fold_left (fun acc x -> StringSet.add x acc) StringSet.empty l
+
+let load_hooks ~debug path =
+ let hooks = Hashtbl.create 13 in
+ let entries = Array.to_list (Sys.readdir path) in
+ let entries = List.filter (fun x -> Filename.check_suffix x ".d") entries in
+ let entries = List.map (fun x -> (x, path // x)) entries in
+ let entries = List.filter (fun (_, x) -> is_directory x) entries in
+ List.iter (
+ fun (hook, p) ->
+ let listing = Array.to_list (Sys.readdir p) in
+ let scripts = List.filter valid_script_name listing in
+ let scripts = List.filter (
+ fun x ->
+ try
+ let s = Unix.stat (p // x) in
+ s.Unix.st_kind = Unix.S_REG && s.Unix.st_perm land 0o111 > 0
+ with Unix.Unix_error _ -> false
+ ) scripts in
+ if scripts <> [] then
+ Hashtbl.add hooks hook scripts
+ ) entries;
+ hooks
+
+let load_elements ~debug paths =
+ let loaded_elements = Hashtbl.create 13 in
+ let paths = List.filter is_directory paths in
+ List.iter (
+ fun path ->
+ let listing = Array.to_list (Sys.readdir path) in
+ let listing = List.map (fun x -> (x, path // x)) listing in
+ let listing = List.filter (fun (_, x) -> is_directory x) listing in
+ List.iter (
+ fun (p, dir) ->
+ if not (Hashtbl.mem loaded_elements p) then (
+ let elem = { directory = dir; hooks = load_hooks ~debug dir } in
+ Hashtbl.add loaded_elements p elem
+ ) else if debug >= 1 then (
+ printf "element %s (in %s) already present" p path;
+ )
+ ) listing
+ ) paths;
+ loaded_elements
+
+let load_dependencies elements loaded_elements =
+ let get filename element =
+ try
+ let path = (Hashtbl.find loaded_elements element).directory in
+ let path = path // filename in
+ if Sys.file_exists path then (
+ let lines = read_whole_file path in
+ let lines = string_nsplit "\n" lines in
+ let lines = List.filter ((<>) "") lines in
+ stringset_of_list lines
+ ) else
+ StringSet.empty
+ with Not_found ->
+ error (f_"element %s not found") element in
+ let get_deps = get "element-deps" in
+ let get_provides = get "element-provides" in
+
+ let queue = Queue.create () in
+ let final = ref StringSet.empty in
+ let provided = ref StringSet.empty in
+ List.iter (fun x -> Queue.push x queue) elements;
+ final := stringset_of_list elements;
+ while not (Queue.is_empty queue) do
+ let elem = Queue.pop queue in
+ if StringSet.mem elem !provided <> true then (
+ let deps = get_deps elem in
+ provided := StringSet.union !provided (get_provides elem);
+ StringSet.iter (fun x -> Queue.push x queue)
+ (StringSet.diff deps (StringSet.union !final !provided));
+ final := StringSet.union !final deps
+ )
+ done;
+ let conflicts = StringSet.inter (stringset_of_list elements) !provided in
+ if not (StringSet.is_empty conflicts) then
+ error (f_"following elements were explicitly required but are provided by other included elements: %s")
+ (String.concat "," (StringSet.elements conflicts));
+ if not (StringSet.mem "operating-system" !provided) then
+ error (f_"please include an operating system element");
+ StringSet.diff !final !provided
+
+let copy_element element destdir blacklist =
+ let entries = Array.to_list (Sys.readdir element.directory) in
+ let entries = List.filter ((<>) "tests") entries in
+ let entries = List.filter ((<>) "test-elements") entries in
+ let dirs, nondirs = List.partition is_directory entries in
+ let dirs = List.map (fun x -> (x, element.directory // x, destdir // x)) dirs in
+ let nondirs = List.map (fun x -> element.directory // x) nondirs in
+ let is_regular_file file =
+ try (Unix.stat file).Unix.st_kind = Unix.S_REG
+ with Unix.Unix_error _ -> false in
+ List.iter (
+ fun (e, path, destpath) ->
+ do_mkdir destpath;
+ let subentries = Array.to_list (Sys.readdir path) in
+ let subentries = List.filter (not_in_list blacklist) subentries in
+ List.iter (
+ fun sube ->
+ if is_regular_file (destpath // sube) then (
+ raise (Duplicate_script (e, sube))
+ ) else
+ do_cp (path // sube) destpath
+ ) subentries;
+ ) dirs;
+ List.iter (
+ fun path ->
+ do_cp path destdir
+ ) nondirs
+
+let copy_elements elements loaded_elements blacklist destdir =
+ do_mkdir destdir;
+ StringSet.iter (
+ fun element ->
+ try
+ copy_element (Hashtbl.find loaded_elements element) destdir blacklist
+ with
+ | Duplicate_script (hook, script) ->
+ let element_has_script e =
+ try
+ let s = Hashtbl.find (Hashtbl.find loaded_elements e).hooks hook in
+ List.exists ((=) script) s
+ with Not_found -> false in
+ let dups = StringSet.filter element_has_script elements in
+ error (f_"There is a duplicated script in your elements:\n%s/%s in: %s")
+ hook script (String.concat " " (StringSet.elements dups))
+ ) elements
diff --git a/dib/utils.ml b/dib/utils.ml
new file mode 100644
index 0000000..d20f7b3
--- /dev/null
+++ b/dib/utils.ml
@@ -0,0 +1,134 @@
+(* virt-dib
+ * Copyright (C) 2015 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.
+ *)
+
+open Common_gettext.Gettext
+open Common_utils
+
+open Printf
+
+exception Tool_not_found of string (* tool *)
+
+let quote = Filename.quote
+
+let unit_GB howmany =
+ (Int64.of_int howmany) *^ 1024_L *^ 1024_L *^ 1024_L
+
+let current_arch () =
+ (* Turn a CPU into the dpkg architecture naming. *)
+ match Config.host_cpu with
+ | "amd64" | "x86_64" -> "amd64"
+ | "i386" | "i486" | "i586" | "i686" -> "i386"
+ | arch when string_prefix arch "armv" -> "armhf"
+ | arch -> arch
+
+let output_filename image_name = function
+ | fmt -> image_name ^ "." ^ fmt
+
+let log_filename () =
+ let tm = Unix.gmtime (Unix.time ()) in
+ sprintf "%s-%d%02d%02d-%02d%02d%02d.log"
+ prog (tm.Unix.tm_year + 1900) (tm.Unix.tm_mon + 1) tm.Unix.tm_mday
+ tm.Unix.tm_hour tm.Unix.tm_min tm.Unix.tm_sec
+
+let var_from_lines var lines =
+ let var_with_equal = var ^ "=" in
+ let var_lines = List.filter (fun x -> string_prefix x var_with_equal) lines in
+ match var_lines with
+ | [] ->
+ error (f_"variable '%s' not found in lines:\n%s")
+ var (String.concat "\n" lines)
+ | [x] -> snd (string_split "=" x)
+ | _ ->
+ error (f_"variable '%s' has more than one occurrency in lines:\n%s")
+ var (String.concat "\n" lines)
+
+let string_index_fn fn str =
+ let len = String.length str in
+ let rec loop i =
+ if i = len then raise Not_found
+ else if fn str.[i] then i
+ else loop (i + 1) in
+ loop 0
+
+let digit_prefix_compare a b =
+ let myint str =
+ try int_of_string str
+ with _ -> 0 in
+ let mylength str =
+ match String.length str with
+ | 0 -> max_int
+ | x -> x in
+ let split_prefix str =
+ let len = String.length str in
+ let digits =
+ let isdigit = function
+ | '0'..'9' -> true
+ | _ -> false in
+ try string_index_fn (fun x -> not (isdigit x)) str
+ with Not_found -> len in
+ match digits with
+ | 0 -> "", str
+ | x when x = len -> str, ""
+ | _ -> String.sub str 0 digits, String.sub str digits (len - digits) in
+
+ let pref_a, rest_a = split_prefix a in
+ let pref_b, rest_b = split_prefix b in
+ match mylength pref_a, mylength pref_b, compare (myint pref_a) (myint pref_b) with
+ | x, y, 0 when x = y -> compare rest_a rest_b
+ | x, y, 0 -> x - y
+ | _, _, x -> x
+
+let do_mkdir dir =
+ mkdir_p dir 0o755
+
+let rec remove_dups = function
+ | [] -> []
+ | x :: xs -> x :: (remove_dups (List.filter ((<>) x) xs))
+
+let which tool =
+ (* XXX ugly but effective *)
+ let lines = external_command (sprintf "sh -c \"which %s 2>/dev/null || true\"" tool) in
+ let lines = List.filter ((<>) "") lines in
+ match lines with
+ | [] -> raise (Tool_not_found tool)
+ | [x] -> x
+ | x :: _ ->
+ error (f_"output of `which %s` contains more than one line:\n%s")
+ tool (String.concat "\n" lines)
+
+let run_command cmd =
+ ignore (external_command cmd)
+
+let check_tool tool =
+ try ignore (which tool); true
+ with Tool_not_found _ -> false
+
+let require_tool tool =
+ try ignore (which tool)
+ with Tool_not_found tool ->
+ error (f_"%s needed but not found") tool
+
+let do_cp src destdir =
+ run_command (sprintf "cp -t %s -a %s" (quote destdir) (quote src))
+
+let ensure_trailing_newline str =
+ if String.length str > 0 && str.[String.length str - 1] <> '\n' then str ^ "\n"
+ else str
+
+let not_in_list l e =
+ not (List.mem e l)
diff --git a/dib/virt-dib.pod b/dib/virt-dib.pod
new file mode 100644
index 0000000..8951cd4
--- /dev/null
+++ b/dib/virt-dib.pod
@@ -0,0 +1,628 @@
+=head1 NAME
+
+virt-dib - Run diskimage-builder elements
+
+=head1 SYNOPSIS
+
+ virt-dib -B DIB-LIB [options] elements...
+
+=head1 DESCRIPTION
+
+Virt-dib is a tool for using the elements of C<diskimage-builder>
+to build a new disk image, generate new ramdisks, etc.
+
+Virt-dib is intended as safe replacement for C<diskimage-builder>
+and its C<ramdisk-image-create> mode, see
+L</COMPARISON WITH DISKIMAGE-BUILDER> for a quick comparison with
+usage of C<diskimage-builder>.
+
+C<diskimage-builder> is part of the TripleO OpenStack project:
+L<https://wiki.openstack.org/wiki/TripleO>.
+
+=head1 EXAMPLES
+
+=head2 Build simple images of distributions
+
+ virt-dib \
+ -B /path/to/diskimage-builder/lib \
+ -p /path/to/diskimage-builder/elements \
+ --envvar DIB_RELEASE=jessie \
+ --name debian-jessie \
+ debian vm
+
+This builds a Debian Jessie (8.x) disk image, suitable for running
+as virtual machine, saved as F<debian-jessie.qcow2>.
+
+=head2 Build ramdisks
+
+ virt-dib \
+ -B /path/to/diskimage-builder/lib \
+ -p /path/to/diskimage-builder/elements \
+ --ramdisk \
+ --name ramdisk \
+ ubuntu deploy-ironic
+
+This builds a ramdisk for the Ironic OpenStack component based
+on the Ubuntu distribution.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<--help>
+
+Display help.
+
+=item B<-B> PATH
+
+Set the path to the library directory of C<diskimage-builder>. This is
+usually the F<lib> subdirectory in the sources and when installed,
+and F</usr/share/diskimage-builder/lib> when installed in F</usr>.
+
+This parameter is B<mandatory>, as virt-dib needs to provide it for
+the elements (as some of them might use scripts in it).
+Virt-dib itself does not make use of the library directory.
+
+=item B<--arch> ARCHITECURE
+
+Use the specified architecture for the output image. The default
+value is the same as the host running virt-dib.
+
+Right now this option does nothing more than setting the C<ARCH>
+environment variable for the elements, and it's up to them to
+produce an image for the requested architecture.
+
+=item B<--debug> LEVEL
+
+Set the debug level to C<LEVEL>, which is a non-negative integer
+number. The default is C<0>.
+
+This debug level is different than what I<-x> and I<-v> set,
+and it increases the debugging information printed out.
+Specifically, this sets the C<DIB_DEBUG_TRACE>, and any value
+E<gt> C<0> enables tracing in the scripts executed.
+
+=item B<--drive> DISK
+
+Add the specified disk to be used as helper drive where to cache
+files of the elements, like disk images, distribution packages, etc.
+
+See L</HELPER DRIVE>.
+
+=item B<-p> PATH
+
+=item B<--element-path> PATH
+
+Add a new path with elements. Paths are used in the same order as the
+I<-p> parameters appear, so a path specified first is looked first,
+and so on.
+
+Obviously, it is recommended to add the path to the own elements of
+C<diskimage-builder>, as most of the other elements will rely on them.
+
+=item B<--extra-packages> PACKAGE,...
+
+Install additional packages in the image being built.
+
+This relies on the C<install-packages> binary provided by the
+package management elements.
+
+This option can be specified multiple times, each time with multiple
+packages separated by comma.
+
+=item B<--envvar> VARIABLE
+
+=item B<--envvar> VARIABLE=VALUE
+
+Carry or set an environment variable for the elements.
+
+See L</ENVIRONMENT VARIABLES> below for more information on the
+interaction and usage of environment variables.
+
+This option can be used in two ways:
+
+=over 4
+
+=item B<--envvar> VARIABLE
+
+Carry the environment variable C<VARIABLE>. If it is not set, nothing
+is exported to the elements.
+
+=item B<--envvar> VARIABLE=VALUE
+
+Set the environment variable C<VARIABLE> with value C<VALUE> for the
+elements, regardless whether an environment variable with the same
+name exists.
+
+This can be useful to pass environment variable without exporting
+them in the environment where virt-dib runs.
+
+=back
+
+=item B<--exclude-element> ELEMENT
+
+Ignore the specified element.
+
+=item B<--exclude-script> SCRIPT
+
+Ignore any element script named C<SCRIPT>, whichever element it is in.
+
+This can be useful in case some script does not run well with
+virt-dib, for example when they really need C<diskimage-builder>'s
+environment.
+
+=item B<--formats> FORMAT,...
+
+Set the list of output formats, separating them with comma.
+
+Supported formats are:
+
+=over 4
+
+=item C<qcow2> (enabled by default)
+
+QEMU's qcow2.
+
+=item C<raw>
+
+Raw disk format.
+
+=item C<tar>
+
+An uncompressed tarball.
+
+=item C<vhd>
+
+C<Virtual Hard Disk> disk image. This output format requires
+the C<vhd-util> tool.
+
+Please note that the version of C<vhd-util> tool needs to be patched
+to support the C<convert> subcommand, and to be bootable.
+The patch is available here:
+L<https://github.com/emonty/vhd-util/blob/master/debian/patches/citrix>.
+
+=back
+
+=item B<--fs-type> FILESYSTEM
+
+Set the filesystem type to use for the root filesystem. The default
+is C<ext4>.
+
+See also L<guestfs(3)/guestfs_filesystem_available>.
+
+=item B<--image-cache> DIRECTORY
+
+Set the path in the host where cache the resources used by the
+elements of the C<extra-data.d> phase. The default is
+F<~/.cache/image-create>.
+
+Please note that most of the resources fetched after C<extra-data>
+will be cached in the helper drive specified with I<--drive>;
+see also L</HELPER DRIVE>.
+
+=item B<--install-type> TYPE
+
+Specify the default installation type. Defaults to C<source>.
+
+Set to C<package> to use package based installations by default.
+
+=item B<--machine-readable>
+
+This option is used to make the output more machine friendly
+when being parsed by other programs. See
+L</MACHINE READABLE OUTPUT> below.
+
+=item B<-m> MB
+
+=item B<--memsize> MB
+
+Change the amount of memory allocated to the appliance. Increase
+this if you find that the virt-dib execution runs out of memory.
+
+The default can be found with this command:
+
+ guestfish get-memsize
+
+=item B<--mkfs-options> C<OPTION STRING>
+
+Add the specified options to L<mkfs(1)>, to be able to fine-tune
+the root filesystem creation. Note that this is not possible
+to override the filesystem type.
+
+You should use I<--mkfs-options> at most once. To pass multiple
+options, separate them with space, eg:
+
+ virt-dib ... --mkfs-options '-O someopt -I foo'
+
+=item B<--network>
+
+=item B<--no-network>
+
+Enable or disable network access from the guest during the
+installation.
+
+Enabled is the default. Use I<--no-network> to disable access.
+
+The network only allows outgoing connections and has other minor
+limitations. See L<virt-rescue(1)/NETWORK>.
+
+This does not affect whether the guest can access the network once it
+has been booted, because that is controlled by your hypervisor or
+cloud environment and has nothing to do with virt-dib.
+
+If you use I<--no-network>, then the environment variable
+C<DIB_OFFLINE> is set to C<1>, signaling the elements that they
+should use only cached resources when available. Note also that,
+unlike with C<diskimage-builder> where elements may still be able
+to access to the network even with C<DIB_OFFLINE=>, under virt-dib
+network will be fully unaccessible.
+
+=item B<--name> NAME
+
+Set the name of the output image file. The default is C<image>.
+
+According to the chosen name, there will be the following in the
+current directory:
+
+=over 4
+
+=item F<$NAME.ext>
+
+For each output format, a disk image named after the outout image
+with the extension depending on the format; for example:
+F<$NAME.qcow2>, F<$NAME.raw>, etc.
+
+Not applicable in ramdisk mode, see L</RAMDISK BUILDING>.
+
+=item F<$NAME.d>
+
+A directory containing any files created by the elements, for example
+F<dib-manifests> directory (created by the C<manifests> element),
+ramdisks and kernels in ramdisk mode, and so on.
+
+=back
+
+=item B<--no-delete-on-failure>
+
+Don't delete the output files on failure to build. You can use this
+to debug failures to run scripts.
+
+The default is to delete the output file if virt-dib fails (or,
+for example, some script that it runs fails).
+
+=item B<--qemu-img-options> option[,option,...]
+
+Pass I<--qemu-img-options> option(s) to the L<qemu-img(1)> command
+to fine-tune the output format. Options available depend on
+the output format (see I<--formats>) and the installed version
+of the qemu-img program.
+
+You should use I<--qemu-img-options> at most once. To pass multiple
+options, separate them with commas, eg:
+
+ virt-dib ... --qemu-img-options cluster_size=512,preallocation=metadata ...
+
+=item B<--ramdisk>
+
+Set the ramdisk building mode.
+
+See L</RAMDISK BUILDING>.
+
+=item B<--ramdisk-element> NAME
+
+Set the name for the additional element added in ramdisk building
+mode. The default is C<ramdisk>.
+
+See L</RAMDISK BUILDING>.
+
+=item B<--root-label> LABEL
+
+Set the label for the root filesystem in the created image.
+
+Please note that some filesystems have different restrictions on
+the length of their labels; for example, on C<ext2/3/4> filesystems
+labels cannot be longer than 16 characters, while on C<xfs> they have
+at most 12 characters.
+
+The default depends on the actual filesystem for the root partition
+(see I<--fs-type>): on C<xfs> is C<img-rootfs>, while
+C<cloudimg-rootfs> on any other filesystem.
+
+=item B<--size> SIZE
+
+Select the size of the output disk, where the size can be specified
+using common names such as C<32G> (32 gigabytes) etc.
+The default size is C<5G>.
+
+To specify size in bytes, the number must be followed by the lowercase
+letter I<b>, eg: S<C<--size 10737418240b>>.
+
+See also L<virt-resize(1)> for resizing partitions of an existing
+disk image.
+
+=item B<--skip-base>
+
+Skip the inclusion of the C<base> element.
+
+=item B<--smp> N
+
+Enable N E<ge> 2 virtual CPUs for scripts to use.
+
+=item B<-u>
+
+Do not compress resulting qcow2 images. The default is
+to compressed them.
+
+=item B<-v>
+
+=item B<--verbose>
+
+Enable debugging messages.
+
+=item B<-V>
+
+=item B<--version>
+
+Display version number and exit.
+
+=item B<-x>
+
+Enable tracing of libguestfs API calls.
+
+=back
+
+=head1 ENVIRONMENT VARIABLES
+
+Unlike with C<diskimage-builder>, the environment of the host is
+B<not> inherited in the appliance when running most of the elements
+(i.e. all the ones different than C<extra-data.d>).
+
+To set environment for the elements being run, it is necessary to tell
+virt-dib to use them, with the option I<--envvar>. Such option
+allows to selectively export environment variables when running the
+elements, and it is the preferred way to pass environment variables
+to the elements.
+
+To recap: if you want the environment variable C<MYVAR>
+(and its content) to be available to the elements, you can do either
+
+ export MYVAR # whichever is its value
+ virt-dib ... --envvar MYVAR ...
+
+or
+
+ virt-dib ... --envvar MYVAR=value_of_it ...
+
+=head1 HELPER DRIVE
+
+Virt-dib runs most of the element in its own appliance, and thus not
+on the host. Because of this, there is no possibility for elements
+to cache resources directly on the host.
+
+To solve this issue, virt-dib allows the usage of an helper drive
+where to store cached resources, like disk images,
+distribution packages, etc. While this means that there is a smaller
+space available for caching, at least it allows to limit the space
+on the host for caches, without assuming that elements will do that
+by themselves.
+
+Currently this disk is either required to have a single partition
+on it, or the first partition on it will be used. A disk with
+the latter configuration can be easily created with L<guestfish(1)>
+like the following:
+
+ guestfish -N filename.img=fs:ext4:10G
+
+The above will create a disk image called F<filename.img>, 10G big,
+with a single partition of type ext4;
+see L<guestfish(1)/PREPARED DISK IMAGES>.
+
+It is recommended for it to be E<ge> 10G or even more, as elements
+will cache disk images, distribution packages, etc. As with any disk
+image, the helper disk can be easily resized using L<virt-resize(1)>
+if more space in it is needed.
+
+The drive can be accessed like any other disk image, for example using
+other tools of libguestfs such as L<guestfish(1)>:
+
+ guestfish -a filename.img -m /dev/sda1
+
+If no helper drive is specified with I<--drive>, all the resources
+cached during a virt-dib run will be discarded.
+
+=head2 RESOURCES INSIDE THE DRIVE
+
+Inside the helper drive, it is possible to find the following
+resources:
+
+=over 4
+
+=item F</home>
+
+This directory is set as C<HOME> environment variable during the
+build. It contains mostly the image cache (saved as
+F</home/.cache/image-create>), and whichever other resource is
+cached in the home directory of the user running the various tools.
+
+=item F</virt-dib-*.log>
+
+These are the logs of the elements being run within the libguestfs
+appliance, which means all the hooks except C<extra-data.d>.
+
+=back
+
+=head1 RAMDISK BUILDING
+
+Virt-dib can emulate also C<ramdisk-image-create>, which is a
+secondary operation mode of C<diskimage-builder>. Instead of being
+a different tool name, virt-dib provides easy access to this mode
+using the I<--ramdisk> switch.
+
+In this mode:
+
+=over 4
+
+=item
+
+there is an additional ramdisk element added (see
+I<--ramdisk-element>)
+
+=item
+
+no image is produced (so I<--formats> is ignored)
+
+=item
+
+F<$NAME.d> (see I<--name>) will contain initrd, kernel, etc
+
+=back
+
+=head1 TEMPORARY DIRECTORY
+
+Virt-dib uses the standard temporary directory used by libguestfs,
+see L<guestfs(3)/ENVIRONMENT VARIABLES>.
+
+By default this location is F</tmp> (default value for C<TMPDIR>),
+which on some systems may be on a tmpfs filesystem, and thus
+defaulting to a maximum size of I<half> of physical RAM.
+If virt-dib exceeds this, it may hang or exit early with an error.
+The solution is to point C<TMPDIR> to a permanent location used
+as temporary location, for example:
+
+ mkdir local-tmp
+ env TMPDIR=$PWD/local-tmp virt-dib ...
+ rm -rf local-tmp
+
+=head1 COMPARISON WITH DISKIMAGE-BUILDER
+
+Virt-dib is intended as safe replacement for C<diskimage-builder>
+and its C<ramdisk-image-create> mode; the user-notable differences
+consist in:
+
+=over 4
+
+=item
+
+the command line arguments; some of the arguments are the same as
+available in C<diskimage-builder>, while some have different names:
+
+ disk-image-create virt-dib
+ ----------------- --------
+ -a ARCH --arch ARCH
+ --image-size SIZE --size SIZE
+ --max-online-resize SIZE doable using --mkfs-options
+ -n --skip-base
+ -o IMAGENAME --name IMAGENAME
+ -p PACKAGE(S) --extra-packages PACKAGE(S)
+ -t FORMAT(S) --formats FORMAT(S)
+ -x --debug N
+
+=item
+
+the location of non-image output files (like ramdisks and kernels)
+
+=item
+
+the way some of the cached resources are saved: using an helper drive,
+not directly on the disk where virt-dib is run
+
+=item
+
+the need to specify a target size for the output disk, as opposed
+to C<diskimage-builder> calculating an optimal one
+
+=item
+
+the handling of environment variables, see L</ENVIRONMENT VARIABLES>.
+
+Furthermore, other than the libguestfs own environment variables
+(see L<guestfs(3)/ENVIRONMENT VARIABLES>), virt-dib does not read
+any other environment variable: this means that all the options
+and behaviour changes are specified solely using command line
+arguments
+
+=item
+
+C<extra-data.d> scripts run in the host environment, before all the
+other ones (even C<root.d>); this means that, depending on the
+configuration for the elements, some of them may fail due to missing
+content (usually directories) in C<TMP_HOOKS_PATH>.
+
+Workarounds for this may be either:
+
+=over 4
+
+=item
+
+fix the C<extra-data.d> scripts to create the missing directories
+
+=item
+
+create (and use) a simple element with a C<extra-data.d> script
+named e.g. F<00-create-missing-dirs> to create the missing
+directories
+
+=back
+
+=back
+
+Elements themselves should notice no difference in they way
+they are run; behaviour differences may due to wrong assumptions in
+elements, or not correct virt-dib emulation.
+
+Known issues at the moment:
+
+=over 4
+
+=item
+
+(none)
+
+=back
+
+=head1 MACHINE READABLE OUTPUT
+
+The I<--machine-readable> option can be used to make the output more
+machine friendly, which is useful when calling virt-dib from other
+programs, GUIs etc.
+
+Use the option on its own to query the capabilities of the
+virt-dib binary. Typical output looks like this:
+
+ $ virt-dib --machine-readable
+ virt-dib
+ output:qcow2
+ output:tar
+ output:raw
+ output:vhd
+
+A list of features is printed, one per line, and the program exits
+with status 0.
+
+=head1 TESTING
+
+Virt-dib has been tested with C<diskimage-builder> (and its elements)
+E<ge> 0.1.43; from time to time also with C<tripleo-image-elements>
+and C<sahara-image-elements>.
+
+Previous versions may work, but it is not guaranteed.
+
+=head1 EXIT STATUS
+
+This program returns 0 if successful, or non-zero if there was an
+error.
+
+=head1 SEE ALSO
+
+L<guestfs(3)>,
+L<guestfish(1)>,
+L<virt-resize(1)>,
+L<http://libguestfs.org/>.
+
+=head1 AUTHOR
+
+Pino Toscano (C<ptoscano at redhat dot com>)
+
+=head1 COPYRIGHT
+
+Copyright (C) 2015 Red Hat Inc.
diff --git a/po-docs/podfiles b/po-docs/podfiles
index c76f1b1..26bd880 100644
--- a/po-docs/podfiles
+++ b/po-docs/podfiles
@@ -11,6 +11,7 @@
../customize/virt-customize.pod
../daemon/guestfsd.pod
../df/virt-df.pod
+../dib/virt-dib.pod
../diff/virt-diff.pod
../edit/virt-edit.pod
../erlang/examples/guestfs-erlang.pod
diff --git a/po/POTFILES-ml b/po/POTFILES-ml
index 8725385..cddd02f 100644
--- a/po/POTFILES-ml
+++ b/po/POTFILES-ml
@@ -25,6 +25,10 @@ customize/random_seed.ml
customize/ssh_key.ml
customize/timezone.ml
customize/urandom.ml
+dib/cmdline.ml
+dib/dib.ml
+dib/elements.ml
+dib/utils.ml
get-kernel/get_kernel.ml
mllib/JSON.ml
mllib/JSON_tests.ml
diff --git a/run.in b/run.in
index 6709cdd..42f8cc8 100755
--- a/run.in
+++ b/run.in
@@ -86,6 +86,7 @@ prepend PATH "$b/builder"
prepend PATH "$b/cat"
prepend PATH "$b/customize"
prepend PATH "$b/df"
+prepend PATH "$b/dib"
prepend PATH "$b/diff"
prepend PATH "$b/edit"
prepend PATH "$b/erlang"
diff --git a/src/guestfs.pod b/src/guestfs.pod
index fa04c86..739110e 100644
--- a/src/guestfs.pod
+++ b/src/guestfs.pod
@@ -4353,6 +4353,10 @@ actions.
L<virt-df(1)> command and documentation.
+=item F<dib>
+
+L<virt-dib(1)> command and documentation.
+
=item F<diff>
L<virt-diff(1)> command and documentation.
--
2.1.0
9 years, 4 months