guestfs man page

guestfs — Library for accessing and modifying virtual machine images


 #include <guestfs.h>
 guestfs_h *g = guestfs_create ();
 guestfs_add_drive (g, "guest.img");
 guestfs_launch (g);
 guestfs_mount (g, "/dev/sda1", "/");
 guestfs_touch (g, "/hello");
 guestfs_umount (g, "/");
 guestfs_shutdown (g);
 guestfs_close (g);

 cc prog.c -o prog -lguestfs
 cc prog.c -o prog `pkg-config libguestfs --cflags --libs`


Libguestfs is a library for accessing and modifying disk images and virtual machines.

This manual page documents the C API.

If you are looking for an introduction to libguestfs, see the web site:

Each virt tool has its own man page (for a full list, go to "See Also" at the end of this file).

Other libguestfs manual pages:


Frequently Asked Questions (FAQ).


Examples of using the API from C.  For examples in other languages, see "Using Libguestfs with Other Programming Languages" below.


Tips and recipes.


Performance tips and solutions.


Help testing libguestfs.


How to build libguestfs from source.


Contribute code to libguestfs.


How libguestfs works.


Security information, including CVEs affecting libguestfs.

API Overview

This section provides a gentler overview of the libguestfs API.  We also try to group API calls together, where that may not be obvious from reading about the individual calls in the main section of this manual.


Before you can use libguestfs calls, you have to create a handle. Then you must add at least one disk image to the handle, followed by launching the handle, then performing whatever operations you want, and finally closing the handle.  By convention we use the single letter "g" for the name of the handle variable, although of course you can use any name you want.

The general structure of all libguestfs-using programs looks like this:

 guestfs_h *g = guestfs_create ();
 /* Call guestfs_add_drive additional times if there are
  * multiple disk images.
 guestfs_add_drive (g, "guest.img");
 /* Most manipulation calls won't work until you've launched
  * the handle 'g'.  You have to do this _after_ adding drives
  * and _before_ other commands.
 guestfs_launch (g);
 /* Either: examine what partitions, LVs etc are available: */
 char **partitions = guestfs_list_partitions (g);
 char **logvols = guestfs_lvs (g);
 /* Or: ask libguestfs to find filesystems for you: */
 char **filesystems = guestfs_list_filesystems (g);
 /* Or: use inspection (see INSPECTION section below). */
 /* To access a filesystem in the image, you must mount it. */
 guestfs_mount (g, "/dev/sda1", "/");
 /* Now you can perform filesystem actions on the guest
  * disk image.
 guestfs_touch (g, "/hello");
 /* Synchronize the disk.  This is the opposite of guestfs_launch. */
 guestfs_shutdown (g);
 /* Close and free the handle 'g'. */
 guestfs_close (g);

The code above doesn't include any error checking.  In real code you should check return values carefully for errors.  In general all functions that return integers return "-1" on error, and all functions that return pointers return "NULL" on error.  See section "Error Handling" below for how to handle errors, and consult the documentation for each function call below to see precisely how they return error indications.

The code above does not free(3) the strings and arrays returned from functions.  Consult the documentation for each function to find out how to free the return value.

See guestfs-examples(3) for fully worked examples.

Disk Images

The image filename ("guest.img" in the example above) could be a disk image from a virtual machine, a dd(1) copy of a physical hard disk, an actual block device, or simply an empty file of zeroes that you have created through posix_fallocate(3).  Libguestfs lets you do useful things to all of these.

The call you should use in modern code for adding drives is "guestfs_add_drive_opts".  To add a disk image, allowing writes, and specifying that the format is raw, do:

 guestfs_add_drive_opts (g, filename,
                         GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",

You can add a disk read-only using:

 guestfs_add_drive_opts (g, filename,
                         GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
                         GUESTFS_ADD_DRIVE_OPTS_READONLY, 1,

or by calling the older function "guestfs_add_drive_ro".  If you use the readonly flag, libguestfs won't modify the file. (See also "Disk Image Formats" below).

Be extremely cautious if the disk image is in use, eg. if it is being used by a virtual machine.  Adding it read-write will almost certainly cause disk corruption, but adding it read-only is safe.

You should usually add at least one disk image, and you may add multiple disk images.  If adding multiple disk images, they usually have to be "related", ie. from the same guest.  In the API, the disk images are usually referred to as /dev/sda (for the first one you added), /dev/sdb (for the second one you added), etc.

Once "guestfs_launch" has been called you cannot add any more images. You can call "guestfs_list_devices" to get a list of the device names, in the order that you added them. See also "Block Device Naming" below.

There are slightly different rules when hotplugging disks (in libguestfs ≥ 1.20).  See "Hotplugging" below.


Before you can read or write files, create directories and so on in a disk image that contains filesystems, you have to mount those filesystems using "guestfs_mount" or "guestfs_mount_ro". If you already know that a disk image contains (for example) one partition with a filesystem on that partition, then you can mount it directly:

 guestfs_mount (g, "/dev/sda1", "/");

where /dev/sda1 means literally the first partition (1) of the first disk image that we added (/dev/sda).  If the disk contains Linux LVM2 logical volumes you could refer to those instead (eg. /dev/VG/LV).  Note that these are libguestfs virtual devices, and are nothing to do with host devices.

If you are given a disk image and you don’t know what it contains then you have to find out.  Libguestfs can do that too: use "guestfs_list_partitions" and "guestfs_lvs" to list possible partitions and LVs, and either try mounting each to see what is mountable, or else examine them with "guestfs_vfs_type" or "guestfs_file".  To list just filesystems, use "guestfs_list_filesystems".

Libguestfs also has a set of APIs for inspection of unknown disk images (see "Inspection" below).  You might also want to look at higher level programs built on top of libguestfs, in particular virt-inspector(1).

To mount a filesystem read-only, use "guestfs_mount_ro".  There are several other variations of the "guestfs_mount_*" call.

Filesystem Access and Modification

The majority of the libguestfs API consists of fairly low-level calls for accessing and modifying the files, directories, symlinks etc on mounted filesystems.  There are over a hundred such calls which you can find listed in detail below in this man page, and we don't even pretend to cover them all in this overview.

Specify filenames as full paths, starting with "/" and including the mount point.

For example, if you mounted a filesystem at "/" and you want to read the file called "etc/passwd" then you could do:

 char *data = guestfs_cat (g, "/etc/passwd");

This would return "data" as a newly allocated buffer containing the full content of that file (with some conditions: see also "Downloading" below), or "NULL" if there was an error.

As another example, to create a top-level directory on that filesystem called "var" you would do:

 guestfs_mkdir (g, "/var");

To create a symlink you could do:

 guestfs_ln_s (g, "/etc/init.d/portmap",

Libguestfs will reject attempts to use relative paths and there is no concept of a current working directory.

Libguestfs can return errors in many situations: for example if the filesystem isn't writable, or if a file or directory that you requested doesn't exist.  If you are using the C API (documented here) you have to check for those error conditions after each call.  (Other language bindings turn these errors into exceptions).

File writes are affected by the per-handle umask, set by calling "guestfs_umask" and defaulting to 022.  See "Umask".

Since libguestfs 1.18, it is possible to mount the libguestfs filesystem on a local directory, subject to some restrictions.  See "Mount Local" below.


Libguestfs contains API calls to read, create and modify partition tables on disk images.

In the common case where you want to create a single partition covering the whole disk, you should use the "guestfs_part_disk" call:

 const char *parttype = "mbr";
 if (disk_is_larger_than_2TB)
   parttype = "gpt";
 guestfs_part_disk (g, "/dev/sda", parttype);

Obviously this effectively wipes anything that was on that disk image before.


Libguestfs provides access to a large part of the LVM2 API, such as "guestfs_lvcreate" and "guestfs_vgremove".  It won't make much sense unless you familiarize yourself with the concepts of physical volumes, volume groups and logical volumes.

This author strongly recommends reading the LVM HOWTO, online at


Use "guestfs_cat" to download small, text only files.  This call cannot handle files containing any ASCII NUL ("\0") characters. However the API is very simple to use.

"guestfs_read_file" can be used to read files which contain arbitrary 8 bit data, since it returns a (pointer, size) pair.

"guestfs_download" can be used to download any file, with no limits on content or size.

To download multiple files, see "guestfs_tar_out" and "guestfs_tgz_out".


To write a small file with fixed content, use "guestfs_write".  To create a file of all zeroes, use "guestfs_truncate_size" (sparse) or "guestfs_fallocate64" (with all disk blocks allocated).  There are a variety of other functions for creating test files, for example "guestfs_fill" and "guestfs_fill_pattern".

To upload a single file, use "guestfs_upload".  This call has no limits on file content or size.

To upload multiple files, see "guestfs_tar_in" and "guestfs_tgz_in".

However the fastest way to upload large numbers of arbitrary files is to turn them into a squashfs or CD ISO (see mksquashfs(8) and mkisofs(8)), then attach this using "guestfs_add_drive_ro".  If you add the drive in a predictable way (eg. adding it last after all other drives) then you can get the device name from "guestfs_list_devices" and mount it directly using "guestfs_mount_ro".  Note that squashfs images are sometimes non-portable between kernel versions, and they don't support labels or UUIDs.  If you want to pre-build an image or you need to mount it using a label or UUID, use an ISO image instead.


There are various different commands for copying between files and devices and in and out of the guest filesystem.  These are summarised in the table below.

file to file

Use "guestfs_cp" to copy a single file, or "guestfs_cp_a" to copy directories recursively.

To copy part of a file (offset and size) use "guestfs_copy_file_to_file".

file to device
device to file
device to device

Use "guestfs_copy_file_to_device", "guestfs_copy_device_to_file", or "guestfs_copy_device_to_device".

Example: duplicate the contents of an LV:

 guestfs_copy_device_to_device (g,
         "/dev/VG/Original", "/dev/VG/Copy",
         /* -1 marks the end of the list of optional parameters */

The destination (/dev/VG/Copy) must be at least as large as the source (/dev/VG/Original).  To copy less than the whole source device, use the optional "size" parameter:

 guestfs_copy_device_to_device (g,
         "/dev/VG/Original", "/dev/VG/Copy",
file on the host to file or device

Use "guestfs_upload".  See "Uploading" above.

file or device to file on the host

Use "guestfs_download".  See "Downloading" above.

Uploading and Downloading to Pipes and File Descriptors

Calls like "guestfs_upload", "guestfs_download", "guestfs_tar_in", "guestfs_tar_out" etc appear to only take filenames as arguments, so it appears you can only upload and download to files.  However many Un*x-like hosts let you use the special device files /dev/stdin, /dev/stdout, /dev/stderr and /dev/fd/N to read and write from stdin, stdout, stderr, and arbitrary file descriptor N.

For example, virt-cat(1) writes its output to stdout by doing:

 guestfs_download (g, filename, "/dev/stdout");

and you can write tar output to a file descriptor "fd" by doing:

 char devfd[64];
 snprintf (devfd, sizeof devfd, "/dev/fd/%d", fd);
 guestfs_tar_out (g, "/", devfd);

Listing Files

"guestfs_ll" is just designed for humans to read (mainly when using the guestfish(1)-equivalent command "ll").

"guestfs_ls" is a quick way to get a list of files in a directory from programs, as a flat list of strings.

"guestfs_readdir" is a programmatic way to get a list of files in a directory, plus additional information about each one.  It is more equivalent to using the readdir(3) call on a local filesystem.

"guestfs_find" and "guestfs_find0" can be used to recursively list files.

Running Commands

Although libguestfs is primarily an API for manipulating files inside guest images, we also provide some limited facilities for running commands inside guests.

There are many limitations to this:

  • The kernel version that the command runs under will be different from what it expects.
  • If the command needs to communicate with daemons, then most likely they won't be running.
  • The command will be running in limited memory.
  • The network may not be available unless you enable it (see "guestfs_set_network").
  • Only supports Linux guests (not Windows, BSD, etc).
  • Architecture limitations (eg. won’t work for a PPC guest on an X86 host).
  • For SELinux guests, you may need to relabel the guest after creating new files.  See "Selinux" below.
  • Security: It is not safe to run commands from untrusted, possibly malicious guests.  These commands may attempt to exploit your program by sending unexpected output.  They could also try to exploit the Linux kernel or qemu provided by the libguestfs appliance.  They could use the network provided by the libguestfs appliance to bypass ordinary network partitions and firewalls.  They could use the elevated privileges or different SELinux context of your program to their advantage.

    A secure alternative is to use libguestfs to install a "firstboot" script (a script which runs when the guest next boots normally), and to have this script run the commands you want in the normal context of the running guest, network security and so on.  For information about other security issues, see guestfs-security(1).

The two main API calls to run commands are "guestfs_command" and "guestfs_sh" (there are also variations).

The difference is that "guestfs_sh" runs commands using the shell, so any shell globs, redirections, etc will work.

Configuration Files

To read and write configuration files in Linux guest filesystems, we strongly recommend using Augeas.  For example, Augeas understands how to read and write, say, a Linux shadow password file or configuration file, and so avoids you having to write that code.

The main Augeas calls are bound through the "guestfs_aug_*" APIs.  We don't document Augeas itself here because there is excellent documentation on the website.

If you don’t want to use Augeas (you fool!) then try calling "guestfs_read_lines" to get the file as a list of lines which you can iterate over.

Systemd Journal Files

To read the systemd journal from a Linux guest, use the "guestfs_journal_*" APIs starting with "guestfs_journal_open".

Consult the journal documentation here: sd-journal(3), sd_journal_open(3).


We support SELinux guests.  However it is not possible to load the SELinux policy of the guest into the appliance kernel.  Therefore the strategy for dealing with SELinux guests is to relabel them after making changes.

In libguestfs ≥ 1.34 there is a new API, "guestfs_setfiles", which can be used for this.  To properly use this API you have to parse the guest SELinux configuration.  See the virt-customize(1) module customize/ for how to do this.

A simpler but slower alternative is to touch /.autorelabel in the guest, which means that the guest will relabel itself at next boot.

Libguestfs ≤ 1.32 had APIs "guestfs_set_selinux", "guestfs_get_selinux", "guestfs_setcon" and "guestfs_getcon". These did not work properly, are deprecated, and should not be used in new code.


Certain calls are affected by the current file mode creation mask (the "umask").  In particular ones which create files or directories, such as "guestfs_touch", "guestfs_mknod" or "guestfs_mkdir".  This affects either the default mode that the file is created with or modifies the mode that you supply.

The default umask is 022, so files are created with modes such as 0644 and directories with 0755.

There are two ways to avoid being affected by umask.  Either set umask to 0 (call "guestfs_umask (g, 0)" early after launching).  Or call "guestfs_chmod" after creating each file or directory.

For more information about umask, see umask(2).

Labels and Uuids

Many filesystems, devices and logical volumes support either labels (short strings like "BOOT" which might not be unique) and/or UUIDs (globally unique IDs).

For filesystems, use "guestfs_vfs_label" or "guestfs_vfs_uuid" to read the label or UUID.  Some filesystems let you call "guestfs_set_label" or "guestfs_set_uuid" to change the label or UUID.

You can locate a filesystem by its label or UUID using "guestfs_findfs_label" or "guestfs_findfs_uuid".

For LVM2 (which supports only UUIDs), there is a rich set of APIs for fetching UUIDs, fetching UUIDs of the contained objects, and changing UUIDs.  See: "guestfs_lvuuid", "guestfs_vguuid", "guestfs_pvuuid", "guestfs_vglvuuids", "guestfs_vgpvuuids", "guestfs_vgchange_uuid", "guestfs_vgchange_uuid_all", "guestfs_pvchange_uuid", "guestfs_pvchange_uuid_all".

Note when cloning a filesystem, device or whole guest, it is a good idea to set new randomly generated UUIDs on the copy.

Encrypted Disks

Libguestfs allows you to access Linux guests which have been encrypted using whole disk encryption that conforms to the Linux Unified Key Setup (LUKS) standard.  This includes nearly all whole disk encryption systems used by modern Linux guests.

Use "guestfs_vfs_type" to identify LUKS-encrypted block devices (it returns the string "crypto_LUKS").

Then open these devices by calling "guestfs_luks_open". Obviously you will require the passphrase!

Opening a LUKS device creates a new device mapper device called /dev/mapper/mapname (where "mapname" is the string you supply to "guestfs_luks_open"). Reads and writes to this mapper device are decrypted from and encrypted to the underlying block device respectively.

LVM volume groups on the device can be made visible by calling "guestfs_vgscan" followed by "guestfs_vg_activate_all". The logical volume(s) can now be mounted in the usual way.

Use the reverse process to close a LUKS device.  Unmount any logical volumes on it, deactivate the volume groups by calling "guestfs_vg_activate (g, 0, ["/dev/VG"])". Then close the mapper device by calling "guestfs_luks_close" on the /dev/mapper/mapname device (not the underlying encrypted block device).

Mount Local

In libguestfs ≥ 1.18, it is possible to mount the libguestfs filesystem on a local directory and access it using ordinary POSIX calls and programs.

Availability of this is subject to a number of restrictions: it requires FUSE (the Filesystem in USErspace), and libfuse must also have been available when libguestfs was compiled.  FUSE may require that a kernel module is loaded, and it may be necessary to add the current user to a special "fuse" group.  See the documentation for your distribution and for further information.

The call to mount the libguestfs filesystem on a local directory is "guestfs_mount_local" (q.v.) followed by "guestfs_mount_local_run". The latter does not return until you unmount the filesystem. The reason is that the call enters the FUSE main loop and processes kernel requests, turning them into libguestfs calls.  An alternative design would have been to create a background thread to do this, but libguestfs doesn't require pthreads.  This way is also more flexible: for example the user can create another thread for "guestfs_mount_local_run".

"guestfs_mount_local" needs a certain amount of time to set up the mountpoint.  The mountpoint is not ready to use until the call returns.  At this point, accesses to the filesystem will block until the main loop is entered (ie. "guestfs_mount_local_run"). So if you need to start another process to access the filesystem, put the fork between "guestfs_mount_local" and "guestfs_mount_local_run".


Since local mounting was only added in libguestfs 1.18, and may not be available even in these builds, you should consider writing code so that it doesn't depend on this feature, and can fall back to using libguestfs file system calls.

If libguestfs was compiled without support for "guestfs_mount_local" then calling it will return an error with errno set to "ENOTSUP" (see "guestfs_last_errno").


Libguestfs on top of FUSE performs quite poorly.  For best performance do not use it.  Use ordinary libguestfs filesystem calls, upload, download etc. instead.


In libguestfs ≥ 1.20, you may add drives and remove after calling "guestfs_launch".  There are some restrictions, see below.  This is called hotplugging.

Only a subset of the backends support hotplugging (currently only the libvirt backend has support).  It also requires that you use libvirt ≥ 0.10.3 and qemu ≥ 1.2.

To hot-add a disk, simply call "guestfs_add_drive_opts" after "guestfs_launch".  It is mandatory to specify the "label" parameter so that the newly added disk has a predictable name.  For example:

 if (guestfs_launch (g) == -1)
   error ("launch failed");
 if (guestfs_add_drive_opts (g, filename,
                             GUESTFS_ADD_DRIVE_OPTS_LABEL, "newdisk",
                             -1) == -1)
   error ("hot-add of disk failed");
 if (guestfs_part_disk ("/dev/disk/guestfs/newdisk", "mbr") == -1)
   error ("partitioning of hot-added disk failed");

To hot-remove a disk, call "guestfs_remove_drive".  You can call this before or after "guestfs_launch".  You can only remove disks that were previously added with a label.

Backends that support hotplugging do not require that you add ≥ 1 disk before calling launch.  When hotplugging is supported you don't need to add any disks.

Remote Storage


Libguestfs can access Ceph (librbd/RBD) disks.

To do this, set the optional "protocol" and "server" parameters of "guestfs_add_drive_opts" like this:

 char **servers = { "", /* ... */, NULL };
 guestfs_add_drive_opts (g, "pool/image",
                         GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
                         GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "rbd",
                         GUESTFS_ADD_DRIVE_OPTS_SERVER, servers,
                         GUESTFS_ADD_DRIVE_OPTS_USERNAME, "rbduser",

"servers" (the "server" parameter) is a list of one or more Ceph servers.  The server string is documented in "guestfs_add_drive_opts". The "username" and "secret" parameters are also optional, and if not given, then no authentication will be used.


Libguestfs can access remote disks over FTP, FTPS, HTTP, HTTPS or TFTP protocols.

To do this, set the optional "protocol" and "server" parameters of "guestfs_add_drive_opts" like this:

 char **servers = { "", NULL };
 guestfs_add_drive_opts (g, "/disk.img",
                         GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
                         GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "http",
                         GUESTFS_ADD_DRIVE_OPTS_SERVER, servers,

The "protocol" can be one of "ftp", "ftps", "http", "https" or "tftp".

"servers" (the "server" parameter) is a list which must have a single element.  The single element is a string defining the web, FTP or TFTP server.  The format of this string is documented in "guestfs_add_drive_opts".


Libguestfs can access Gluster disks.

To do this, set the optional "protocol" and "server" parameters of "guestfs_add_drive_opts" like this:

 char **servers = { "", NULL };
 guestfs_add_drive_opts (g, "volname/image",
                         GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
                         GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "gluster",
                         GUESTFS_ADD_DRIVE_OPTS_SERVER, servers,

"servers" (the "server" parameter) is a list which must have a single element.  The single element is a string defining the Gluster server.  The format of this string is documented in "guestfs_add_drive_opts".

Note that gluster usually requires the client process (ie. libguestfs) to run as root and will give unfathomable errors if it is not (eg. "No data available").


Libguestfs can access iSCSI disks remotely.

To do this, set the optional "protocol" and "server" parameters like this:

 char **server = { "", NULL };
 guestfs_add_drive_opts (g, "target-iqn-name/lun",
                         GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
                         GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "iscsi",
                         GUESTFS_ADD_DRIVE_OPTS_SERVER, server,

The "server" parameter is a list which must have a single element. The single element is a string defining the iSCSI server.  The format of this string is documented in "guestfs_add_drive_opts".


Libguestfs can access Network Block Device (NBD) disks remotely.

To do this, set the optional "protocol" and "server" parameters of "guestfs_add_drive_opts" like this:

 char **server = { "", NULL };
 guestfs_add_drive_opts (g, "" /* export name - see below */,
                         GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
                         GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "nbd",
                         GUESTFS_ADD_DRIVE_OPTS_SERVER, server,


  • "server" is in fact a list of servers.  For NBD you must always supply a list with a single element.  (Other remote protocols require zero or more than one server, hence the requirement for this parameter to be a list).
  • The "server" string is documented in "guestfs_add_drive_opts".  To connect to a local qemu-nbd instance over a Unix domain socket, use "unix:/path/to/socket".
  • The "filename" parameter is the NBD export name.  Use an empty string to mean the default export.  Many NBD servers, including qemu-nbd, do not support export names.
  • If using qemu-nbd as your server, you should always specify the "-t" option.  The reason is that libguestfs may open several connections to the server.
  • The libvirt backend requires that you set the "format" parameter of "guestfs_add_drive_opts" accurately when you use writable NBD disks.
  • The libvirt backend has a bug that stops Unix domain socket connections from working:
  • The direct backend does not support readonly connections because of a bug in qemu:


Libguestfs can access Sheepdog disks.

To do this, set the optional "protocol" and "server" parameters of "guestfs_add_drive_opts" like this:

 char **servers = { /* optional servers ... */ NULL };
 guestfs_add_drive_opts (g, "volume",
                         GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
                         GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "sheepdog",
                         GUESTFS_ADD_DRIVE_OPTS_SERVER, servers,

The optional list of "servers" may be zero or more server addresses ("hostname:port").  The format of the server strings is documented in "guestfs_add_drive_opts".


Libguestfs can access disks over a Secure Shell (SSH) connection.

To do this, set the "protocol" and "server" and (optionally) "username" parameters of "guestfs_add_drive_opts" like this:

 char **server = { "", NULL };
 guestfs_add_drive_opts (g, "/path/to/disk.img",
                         GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
                         GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "ssh",
                         GUESTFS_ADD_DRIVE_OPTS_SERVER, server,
                         GUESTFS_ADD_DRIVE_OPTS_USERNAME, "remoteuser",

The format of the server string is documented in "guestfs_add_drive_opts".


Libguestfs has APIs for inspecting an unknown disk image to find out if it contains operating systems, an install CD or a live CD.

Add all disks belonging to the unknown virtual machine and call "guestfs_launch" in the usual way.

Then call "guestfs_inspect_os".  This function uses other libguestfs calls and certain heuristics, and returns a list of operating systems that were found.  An empty list means none were found.  A single element is the root filesystem of the operating system.  For dual- or multi-boot guests, multiple roots can be returned, each one corresponding to a separate operating system.  (Multi-boot virtual machines are extremely rare in the world of virtualization, but since this scenario can happen, we have built libguestfs to deal with it.)

For each root, you can then call various "guestfs_inspect_get_*" functions to get additional details about that operating system.  For example, call "guestfs_inspect_get_type" to return the string "windows" or "linux" for Windows and Linux-based operating systems respectively.

Un*x-like and Linux-based operating systems usually consist of several filesystems which are mounted at boot time (for example, a separate boot partition mounted on /boot).  The inspection rules are able to detect how filesystems correspond to mount points.  Call "guestfs_inspect_get_mountpoints" to get this mapping.  It might return a hash table like this example:

 /boot => /dev/sda1
 /     => /dev/vg_guest/lv_root
 /usr  => /dev/vg_guest/lv_usr

The caller can then make calls to "guestfs_mount" to mount the filesystems as suggested.

Be careful to mount filesystems in the right order (eg. / before /usr).  Sorting the keys of the hash by length, shortest first, should work.

Inspection currently only works for some common operating systems. Contributors are welcome to send patches for other operating systems that we currently cannot detect.

Encrypted disks must be opened before inspection.  See "Encrypted Disks" for more details.  The "guestfs_inspect_os" function just ignores any encrypted devices.

A note on the implementation: The call "guestfs_inspect_os" performs inspection and caches the results in the guest handle.  Subsequent calls to "guestfs_inspect_get_*" return this cached information, but do not re-read the disks.  If you change the content of the guest disks, you can redo inspection by calling "guestfs_inspect_os" again.  ("guestfs_inspect_list_applications2" works a little differently from the other calls and does read the disks.  See documentation for that function for details).


Libguestfs (since 1.9.4) can detect some install disks, install CDs, live CDs and more.

Further information is available about the operating system that can be installed using the regular inspection APIs like "guestfs_inspect_get_product_name", "guestfs_inspect_get_major_version" etc.

Special Considerations for Windows Guests

Libguestfs can mount NTFS partitions.  It does this using the driver.


DOS and Windows still use drive letters, and the filesystems are always treated as case insensitive by Windows itself, and therefore you might find a Windows configuration file referring to a path like "c:\windows\system32".  When the filesystem is mounted in libguestfs, that directory might be referred to as /WINDOWS/System32.

Drive letter mappings can be found using inspection (see "Inspection" and "guestfs_inspect_get_drive_mappings")

Dealing with separator characters (backslash vs forward slash) is outside the scope of libguestfs, but usually a simple character replacement will work.

To resolve the case insensitivity of paths, call "guestfs_case_sensitive_path".


NTFS supports filenames up to 255 characters long.  "Character" means a 2 byte UTF-16 codepoint which can encode the most common Unicode codepoints.

Most Linux filesystems support filenames up to 255 bytes. This means you may get an error:

 File name too long

when you copy a file from NTFS to a Linux filesystem if the name, when reencoded as UTF-8, would exceed 255 bytes in length.

This will most often happen when using non-ASCII names that are longer than ~127 characters (eg. Greek, Cyrillic) or longer than ~85 characters (Asian languages).

A workaround is not to try to store such long filenames on Linux native filesystems.  Since the tar(1) format can store unlimited length filenames, keep the files in a tarball.


Libguestfs also provides some help for decoding Windows Registry "hive" files, through a separate C library called hivex(3).

Before libguestfs 1.19.35 you had to download the hive file, operate on it locally using hivex, and upload it again.  Since this version, we have included the major hivex APIs directly in the libguestfs API (see "guestfs_hivex_open").  This means that if you have opened a Windows guest, you can read and write the registry directly.

See also virt-win-reg(1).


Ntfs-3g tries to rewrite "Junction Points" and NTFS "symbolic links" to provide something which looks like a Linux symlink.  The way it tries to do the rewriting is described here:

The essential problem is that ntfs-3g simply does not have enough information to do a correct job.  NTFS links can contain drive letters and references to external device GUIDs that ntfs-3g has no way of resolving.  It is almost certainly the case that libguestfs callers should ignore what ntfs-3g does (ie. don't use "guestfs_readlink" on NTFS volumes).

Instead if you encounter a symbolic link on an ntfs-3g filesystem, use "guestfs_lgetxattr" to read the "system.ntfs_reparse_data" extended attribute, and read the raw reparse data from that (you can find the format documented in various places around the web).


There are other useful extended attributes that can be read from ntfs-3g filesystems (using "guestfs_getxattr").  See:


Windows guests which have been hibernated (instead of fully shut down) cannot be mounted.  This is a limitation of ntfs-3g.  You will see an error like this:

 The disk contains an unclean file system (0, 0).
 Metadata kept in Windows cache, refused to mount.
 Failed to mount '/dev/sda2': Operation not permitted
 The NTFS partition is in an unsafe state. Please resume
 and shutdown Windows fully (no hibernation or fast
 restarting), or mount the volume read-only with the
 'ro' mount option.

In Windows 8, the shutdown button does not shut down the guest at all. Instead it usually hibernates the guest.  This is known as "fast startup".

Some suggested workarounds are:

  • Mount read-only (eg. "guestfs_mount_ro").
  • On Windows 8, turn off fast startup.  It is in the Control Panel → Power Options → Choose what the power buttons do → Change settings that are currently unavailable → Turn on fast startup.
  • On Windows 7 and earlier, shut the guest off properly instead of hibernating it.

Resize2fs Errors

The "guestfs_resize2fs", "guestfs_resize2fs_size" and "guestfs_resize2fs_M" calls are used to resize ext2/3/4 filesystems.

The underlying program (resize2fs(8)) requires that the filesystem is clean and recently fsck'd before you can resize it.  Also, if the resize operation fails for some reason, then you had to call fsck the filesystem again to fix it.

In libguestfs "lt" 1.17.14, you usually had to call "guestfs_e2fsck_f" before the resize.  However, in "ge" 1.17.14, e2fsck(8) is called automatically before the resize, so you no longer need to do this.

The resize2fs(8) program can still fail, in which case it prints an error message similar to:

 Please run 'e2fsck -fy <device>' to fix the filesystem
 after the aborted resize operation.

You can do this by calling "guestfs_e2fsck" with the "forceall" option.  However in the context of disk images, it is usually better to avoid this situation, eg. by rolling back to an earlier snapshot, or by copying and resizing and on failure going back to the original.

Using Libguestfs with Other Programming Languages

Although we don’t want to discourage you from using the C API, we will mention here that the same API is also available in other languages.

The API is broadly identical in all supported languages.  This means that the C call "guestfs_add_drive_ro(g,file)" is "$g->add_drive_ro($file)" in Perl, "g.add_drive_ro(file)" in Python, and "g#add_drive_ro file" in OCaml.  In other words, a straightforward, predictable isomorphism between each language.

Error messages are automatically transformed into exceptions if the language supports it.

We don’t try to "object orientify" parts of the API in OO languages, although contributors are welcome to write higher level APIs above what we provide in their favourite languages if they wish.


You can use the guestfs.h header file from C++ programs.  The C++ API is identical to the C API.  C++ classes and exceptions are not used.


The C# bindings are highly experimental.  Please read the warnings at the top of csharp/Libguestfs.cs.


See guestfs-erlang(3).


Experimental GObject bindings (with GObject Introspection support) are available.

See guestfs-gobject(3).


See guestfs-golang(3).


This language binding is working but incomplete:

  • Functions with optional arguments are not bound.  Implementing optional arguments in Haskell seems to be very complex.
  • Events are not bound.
  • Functions with the following return types are not bound:

    • Any function returning a struct.
    • Any function returning a list of structs.
    • A few functions that return fixed length buffers (specifically ones declared "RBufferOut" in the generator).
    • A tiny number of obscure functions that return constant strings (specifically ones declared "RConstOptString" in the generator).

Full documentation is contained in the Javadoc which is distributed with libguestfs.  For examples, see guestfs-java(3).


See guestfs-lua(3).


See guestfs-ocaml(3).


See guestfs-perl(3) and Sys::Guestfs(3).


For documentation see "README-PHP" supplied with libguestfs sources or in the php-libguestfs package for your distribution.

The PHP binding only works correctly on 64 bit machines.


See guestfs-python(3).


See guestfs-ruby(3).

For JRuby, use the Java bindings.

shell scripts

See guestfish(1).

Libguestfs Gotchas "A feature of a system [...] that works in the way it is documented but is counterintuitive and almost invites mistakes."

Since we developed libguestfs and the associated tools, there are several things we would have designed differently, but are now stuck with for backwards compatibility or other reasons.  If there is ever a libguestfs 2.0 release, you can expect these to change.  Beware of them.

Read-only should be the default.

In guestfish(3), --ro should be the default, and you should have to specify --rw if you want to make changes to the image.

This would reduce the potential to corrupt live VM images.

Note that many filesystems change the disk when you just mount and unmount, even if you didn't perform any writes.  You need to use "guestfs_add_drive_ro" to guarantee that the disk is not changed.

guestfish command line is hard to use.

guestfish disk.img doesn't do what people expect (open disk.img for examination).  It tries to run a guestfish command disk.img which doesn't exist, so it fails.  In earlier versions of guestfish the error message was also unintuitive, but we have corrected this since.  Like the Bourne shell, we should have used "guestfish -c command" to run commands.

guestfish megabyte modifiers don’t work right on all commands

In recent guestfish you can use "1M" to mean 1 megabyte (and similarly for other modifiers).  What guestfish actually does is to multiply the number part by the modifier part and pass the result to the C API.  However this doesn't work for a few APIs which aren't expecting bytes, but are already expecting some other unit (eg. megabytes).

The most common is "guestfs_lvcreate".  The guestfish command:

 lvcreate LV VG 100M

does not do what you might expect.  Instead because "guestfs_lvcreate" is already expecting megabytes, this tries to create a 100 terabyte (100 megabytes * megabytes) logical volume. The error message you get from this is also a little obscure.

This could be fixed in the generator by specially marking parameters and return values which take bytes or other units.

Ambiguity between devices and paths

There is a subtle ambiguity in the API between a device name (eg. /dev/sdb2) and a similar pathname.  A file might just happen to be called "sdb2" in the directory /dev (consider some non-Unix VM image).

In the current API we usually resolve this ambiguity by having two separate calls, for example "guestfs_checksum" and "guestfs_checksum_device".  Some API calls are ambiguous and (incorrectly) resolve the problem by detecting if the path supplied begins with /dev/.

To avoid both the ambiguity and the need to duplicate some calls, we could make paths/devices into structured names.  One way to do this would be to use a notation like grub ("hd(0,0)"), although nobody really likes this aspect of grub.  Another way would be to use a structured type, equivalent to this OCaml type:

 type path = Path of string | Device of int | Partition of int * int

which would allow you to pass arguments like:

 Path "/foo/bar"
 Device 1            (* /dev/sdb, or perhaps /dev/sda *)
 Partition (1, 2)    (* /dev/sdb2 (or is it /dev/sda2 or /dev/sdb3?) *)
 Path "/dev/sdb2"    (* not a device *)

As you can see there are still problems to resolve even with this representation.  Also consider how it might work in guestfish.

Keys and Passphrases

Certain libguestfs calls take a parameter that contains sensitive key material, passed in as a C string.

In the future we would hope to change the libguestfs implementation so that keys are mlock(2)-ed into physical RAM, and thus can never end up in swap.  However this is not done at the moment, because of the complexity of such an implementation.

Therefore you should be aware that any key parameter you pass to libguestfs might end up being written out to the swap partition.  If this is a concern, scrub the swap partition or don't use libguestfs on encrypted devices.

Multiple Handles and Multiple Threads

All high-level libguestfs actions are synchronous.  If you want to use libguestfs asynchronously then you must create a thread.

Threads in libguestfs ≥ 1.38

In libguestfs ≥ 1.38, each handle ("guestfs_h") contains a lock which is acquired automatically when you call a libguestfs function. The practical effect of this is you can call libguestfs functions with the same handle from multiple threads without needing to do any locking.

Also in libguestfs ≥ 1.38, the last error on the handle ("guestfs_last_error", "guestfs_last_errno") is stored in thread-local storage, so it is safe to write code like:

 if (guestfs_add_drive_ro (g, drive) == -1)
   fprintf (stderr, "error was: %s\n", guestfs_last_error (g));

even when other threads may be concurrently using the same handle "g".

Threads in libguestfs < 1.38

In libguestfs < 1.38, you must use the handle only from a single thread.  Either use the handle exclusively from one thread, or provide your own mutex so that two threads cannot issue calls on the same handle at the same time.  Even apparently innocent functions like "guestfs_get_trace" are not safe to be called from multiple threads without a mutex in libguestfs < 1.38.

Use "guestfs_set_identifier" to make it simpler to identify threads in trace output.


Libguestfs needs a supermin appliance, which it finds by looking along an internal path.

By default it looks for these in the directory "$libdir/guestfs" (eg. /usr/local/lib/guestfs or /usr/lib64/guestfs).

Use "guestfs_set_path" or set the environment variable "LIBGUESTFS_PATH" to change the directories that libguestfs will search in.  The value is a colon-separated list of paths.  The current directory is not searched unless the path contains an empty element or ".".  For example "LIBGUESTFS_PATH=:/usr/lib/guestfs" would search the current directory and then /usr/lib/guestfs.

Qemu Wrappers

If you want to compile your own qemu, run qemu from a non-standard location, or pass extra arguments to qemu, then you can write a shell-script wrapper around qemu.

There is one important rule to remember: you must "exec qemu" as the last command in the shell script (so that qemu replaces the shell and becomes the direct child of the libguestfs-using program).  If you don't do this, then the qemu process won't be cleaned up correctly.

Here is an example of a wrapper, where I have built my own copy of qemu from source:

 #!/bin/sh -
 exec $qemudir/x86_64-softmmu/qemu-system-x86_64 -L $qemudir/pc-bios "$@"

Save this script as /tmp/qemu.wrapper (or wherever), "chmod +x", and then use it by setting the LIBGUESTFS_HV environment variable. For example:

 LIBGUESTFS_HV=/tmp/qemu.wrapper guestfish

Note that libguestfs also calls qemu with the -help and -version options in order to determine features.

Wrappers can also be used to edit the options passed to qemu.  In the following example, the "-machine ..." option ("-machine" and the following argument) are removed from the command line and replaced with "-machine pc,accel=tcg".  The while loop iterates over the options until it finds the right one to remove, putting the remaining options into the "args" array.

 #!/bin/bash -
 while [ $# -gt 0 ]; do
     case "$1" in
         shift 2;;
         (( i++ ))
         shift ;;
 exec qemu-kvm -machine pc,accel=tcg "${args[@]}"


The backend (previously known as the "attach method") controls how libguestfs creates and/or connects to the backend daemon, eg. by starting qemu directly, or using libvirt to manage an appliance, running User-Mode Linux, or connecting to an already running daemon.

You can set the backend by calling "guestfs_set_backend", or by setting the environment variable "LIBGUESTFS_BACKEND".

Possible backends are described below:


Run qemu directly to launch an appliance.

"direct" and "appliance" are synonyms.

This is the ordinary method and normally the default, but see the note below.


Use libvirt to launch and manage the appliance.

"libvirt" causes libguestfs to choose a suitable URI for creating session guests.  If using the libvirt backend, you almost always should use this.

"libvirt:null" causes libguestfs to use the "NULL" connection URI, which causes libvirt to try to guess what the user meant.  You probably don't want to use this.

"libvirt:URI" uses URI as the libvirt connection URI (see  The typical libvirt backend with a URI would be "libvirt:qemu:///session"

The libvirt backend supports more features, including hotplugging (see "Hotplugging") and sVirt.


Run the User-Mode Linux kernel.  The location of the kernel is set using $LIBGUESTFS_HV or using the "guestfs_set_qemu" API (note that qemu is not involved, we just reuse the same variable in the handle for convenience).

User-Mode Linux can be much faster, simpler and more lightweight than using a full-blown virtual machine, but it also has some shortcomings. See "User-Mode Linux Backend" below.


Connect to the Unix domain socket path.

This method lets you connect to an existing daemon or (using virtio-serial) to a live guest.  For more information, see "Attaching to Running Daemons".

"direct" is usually the default backend.  However since libguestfs ≥ 1.19.24, libguestfs can be built with a different default by doing:

 ./configure --with-default-backend=...

To find out if libguestfs was compiled with a different default backend, do:

 guestfish get-backend

Backend Settings

Each backend can be configured by passing a list of strings.  You can either call "guestfs_set_backend_settings" with a list of strings, or set the "LIBGUESTFS_BACKEND_SETTINGS" environment variable to a colon-separated list of strings (before creating the handle).




will force the direct and libvirt backends to use TCG (software emulation) instead of KVM (hardware accelerated virtualization).


The direct backend supports:


When this is set, qemu will not start running the appliance immediately.  It will wait for you to connect to it using gdb:

 $ gdb
 (gdb) symbol-file /path/to/vmlinux
 (gdb) target remote tcp::1234
 (gdb) cont

You can then debug the appliance kernel, which is useful to debug boot failures (especially ones where there are no debug messages printed - tip: look in the kernel "log_buf").

On Fedora, install "kernel-debuginfo" for the "vmlinux" file (containing symbols).  Make sure the symbols precisely match the kernel being used.


The libvirt backend supports:

 export LIBGUESTFS_BACKEND_SETTINGS=network_bridge=virbrX

This allows you to override the bridge that is connected to when the network is enabled.  The default is "virbr0".  See also "guestfs_set_network".

Attaching to Running Daemons

Note (1): This is highly experimental and has a tendency to eat babies.  Use with caution.

Note (2): This section explains how to attach to a running daemon from a low level perspective.  For most users, simply using virt tools such as guestfish(1) with the --live option will "just work".

Using guestfs_set_backend

By calling "guestfs_set_backend" you can change how the library connects to the "guestfsd" daemon in "guestfs_launch" (read "ARCHITECTURE" in guestfs-internals(1) for some background).

The normal backend is "direct", where a small appliance is created containing the daemon, and then the library connects to this. "libvirt" or "libvirt:URI" are alternatives that use libvirt to start the appliance.

Setting the backend to "unix:path" (where path is the path of a Unix domain socket) causes "guestfs_launch" to connect to an existing daemon over the Unix domain socket.

The normal use for this is to connect to a running virtual machine that contains a "guestfsd" daemon, and send commands so you can read and write files inside the live virtual machine.

Using guestfs_add_domain with live flag

"guestfs_add_domain" provides some help for getting the correct backend.  If you pass the "live" option to this function, then (if the virtual machine is running) it will examine the libvirt XML looking for a virtio-serial channel to connect to:

     <channel type='unix'>
       <source mode='bind' path='/path/to/socket'/>
       <target type='virtio' name=''/>

"guestfs_add_domain" extracts /path/to/socket and sets the backend to "unix:/path/to/socket".

Some of the libguestfs tools (including guestfish) support a --live option which is passed through to "guestfs_add_domain" thus allowing you to attach to and modify live virtual machines.

The virtual machine needs to have been set up beforehand so that it has the virtio-serial channel and so that guestfsd is running inside it.

User-Mode Linux Backend

Setting the following environment variables (or the equivalent in the API) selects the User-Mode Linux backend:

 export LIBGUESTFS_HV=/path/to/vmlinux

"vmlinux" (or it may be called "linux") is the Linux binary, compiled to run as a userspace process.  Note that we reuse the qemu variable in the handle for convenience; qemu is not involved.

User-Mode Linux can be faster and more lightweight than running a full-blown virtual machine as the backend (especially if you are already running libguestfs in a virtual machine or cloud instance), but it also has some shortcomings compared to the usual qemu/KVM-based backend.


Your Linux distro may provide UML in which case you can ignore this section.

These instructions are adapted from:

1. Check out Linux sources

Clone the Linux git repository or download the Linux source tarball.

2. Configure the kernel

Note: All ‘make’ commands must have "ARCH=um" added.

 make menuconfig ARCH=um

Make sure any filesystem drivers that you need are compiled into the kernel.

Currently, it needs a large amount of extra work to get modules working.  It’s recommended that you disable module support in the kernel configuration, which will cause everything to be compiled into the image.

3. Build the kernel
 make ARCH=um

This will leave a file called "linux" or "vmlinux" in the top-level directory.  This is the UML kernel.  You should set "LIBGUESTFS_HV" to point to this file.


UML only supports raw-format images

Only plain raw-format images will work.  No qcow2, no backing files.

UML does not support any remote drives

No NBD, etc.

UML only works on ix86 and x86-64
UML is experimental

In particular, support for UML in libguestfs depends on support for UML in the upstream kernel.  If UML was ever removed from the upstream Linux kernel, then we might remove it from libguestfs too.

Abi Guarantee

We guarantee the libguestfs ABI (binary interface), for public, high-level actions as outlined in this section.  Although we will deprecate some actions, for example if they get replaced by newer calls, we will keep the old actions forever.  This allows you the developer to program in confidence against the libguestfs API.

Block Device Naming

Libguestfs defines /dev/sd* as the standard naming scheme for devices passed to API calls.  So /dev/sda means "the first device added by "guestfs_add_drive_opts"", and /dev/sdb3 means "the third partition on the second device".

Internally device names are sometimes translated, but this should not be visible at the API level.


In libguestfs ≥ 1.20, you can give a label to a disk when you add it, using the optional "label" parameter to "guestfs_add_drive_opts". (Note that disk labels are different from and not related to filesystem labels).

Not all versions of libguestfs support setting a disk label, and when it is supported, it is limited to 20 ASCII characters "[a-zA-Z]".

When you add a disk with a label, it can either be addressed using /dev/sd*, or using /dev/disk/guestfs/label. Partitions on the disk can be addressed using /dev/disk/guestfs/labelpartnum.

Listing devices ("guestfs_list_devices") and partitions ("guestfs_list_partitions") returns the block device names.  However you can use "guestfs_list_disk_labels" to map disk labels to block device and partition names.

Null Disks

When adding a disk using, eg., "guestfs_add_drive", you can set the filename to "/dev/null".  This string is treated specially by libguestfs, causing it to add a "null disk".

A null disk has the following properties:

  • A null disk will appear as a normal device, eg. in calls to "guestfs_list_devices".
  • You may add "/dev/null" multiple times.
  • You should not try to access a null disk in any way.  For example, you shouldn't try to read it or mount it.

Null disks are used for three main purposes:


Performance testing of libguestfs (see guestfs-performance(1)).


The internal test suite.


If you want to use libguestfs APIs that don’t refer to disks, since libguestfs requires that at least one disk is added, you should add a null disk.

For example, to test if a feature is available, use code like this:

 guestfs_h *g;
 char **groups = [ "btrfs", NULL ];
 g = guestfs_create ();
 guestfs_add_drive (g, "/dev/null");
 guestfs_launch (g);
 if (guestfs_available (g, groups) == 0) {
   // group(s) are available
 } else {
   // group(s) are not available
 guestfs_close (g);

Disk Image Formats

Virtual disks come in a variety of formats.  Some common formats are listed below.

Note that libguestfs itself is not responsible for handling the disk format: this is done using qemu(1).  If support for a particular format is missing or broken, this has to be fixed in qemu.



Raw format is simply a dump of the sequential bytes of the virtual hard disk.  There is no header, container, compression or processing of any sort.

Since raw format requires no translation to read or write, it is both fast and very well supported by qemu and all o