mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-22 07:03:38 +00:00
Automated using this command: perl -pi.bak -e 's/(20[012][0-9])-20[12][01234]/$1-2025/g' `git ls-files`
842 lines
32 KiB
C
842 lines
32 KiB
C
/* libguestfs
|
|
* Copyright (C) 2009-2025 Red Hat Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
/**
|
|
* This header file is included in the libguestfs library (F<lib/>)
|
|
* only.
|
|
*
|
|
* See also F<lib/guestfs-internal-all.h>.
|
|
*/
|
|
|
|
#ifndef GUESTFS_INTERNAL_H_
|
|
#define GUESTFS_INTERNAL_H_
|
|
|
|
#ifdef __APPLE__
|
|
#include <crt_externs.h>
|
|
#define environ (*_NSGetEnviron())
|
|
#endif // __APPLE__
|
|
|
|
#include <stdbool.h>
|
|
#include <assert.h>
|
|
|
|
#include <rpc/types.h> /* Needed on libc's different than glibc. */
|
|
#include <rpc/xdr.h>
|
|
|
|
#define PCRE2_CODE_UNIT_WIDTH 8
|
|
#include <pcre2.h>
|
|
|
|
#include <pthread.h>
|
|
|
|
#include "guestfs-utils.h"
|
|
|
|
/* Defined in gnulib "hash.h", but we explicitly define it here to
|
|
* avoid having to include that header everywhere.
|
|
*/
|
|
typedef struct hash_table Hash_table;
|
|
|
|
#ifdef HAVE_LIBVIRT
|
|
#include <libvirt/libvirt.h>
|
|
#endif
|
|
|
|
/* https://stackoverflow.com/a/1597129 */
|
|
#define XXUNIQUE_VAR(name, line) name ## line
|
|
#define XUNIQUE_VAR(name, line) XXUNIQUE_VAR (name, line)
|
|
#define UNIQUE_VAR(name) XUNIQUE_VAR (name, __LINE__)
|
|
|
|
/* Acquire and release the per-handle lock. Note the release happens
|
|
* in an __attribute__((cleanup)) handler, making it simple to write
|
|
* bug-free code.
|
|
*/
|
|
#define ACQUIRE_LOCK_FOR_CURRENT_SCOPE(mutex) \
|
|
CLEANUP_MUTEX_UNLOCK pthread_mutex_t *UNIQUE_VAR(_lock) = mutex; \
|
|
do { \
|
|
int _r = pthread_mutex_lock (UNIQUE_VAR(_lock)); \
|
|
assert (!_r); \
|
|
} while (0)
|
|
|
|
#define CLEANUP_MUTEX_UNLOCK __attribute__((cleanup (cleanup_mutex_unlock)))
|
|
|
|
static inline void
|
|
cleanup_mutex_unlock (pthread_mutex_t **ptr)
|
|
{
|
|
int r = pthread_mutex_unlock (*ptr);
|
|
assert (!r);
|
|
}
|
|
|
|
/* Default and minimum appliance memory size. */
|
|
|
|
/* Needs to be larger on ppc64 because of the larger page size (64K).
|
|
* For example, test-max-disks won't pass unless we increase the
|
|
* default memory size since the system runs out of memory when
|
|
* creating device nodes.
|
|
*/
|
|
#ifdef __powerpc__
|
|
# define DEFAULT_MEMSIZE 1280
|
|
#endif
|
|
|
|
/* Kernel 3.19 is unable to uncompress the initramfs on aarch64 unless
|
|
* we have > 500 MB of space. This looks like a kernel bug (earlier
|
|
* kernels have no problems). However since 64 KB pages are also
|
|
* common on aarch64, treat this like the ppc case above.
|
|
*/
|
|
#ifdef __aarch64__
|
|
# define DEFAULT_MEMSIZE 1280
|
|
#endif
|
|
|
|
/* The default and minimum memory size for most users. */
|
|
#ifndef DEFAULT_MEMSIZE
|
|
# define DEFAULT_MEMSIZE 1280
|
|
#endif
|
|
#ifndef MIN_MEMSIZE
|
|
# define MIN_MEMSIZE 256
|
|
#endif
|
|
|
|
/* Timeout waiting for appliance to come up (seconds).
|
|
*
|
|
* XXX This is just a large timeout for now. Should make this
|
|
* configurable. Also it interacts with libguestfs-test-tool -t
|
|
* option.
|
|
*/
|
|
#define APPLIANCE_TIMEOUT (20*60) /* 20 mins */
|
|
|
|
/* Maximum size of Windows explorer.exe. 2.6MB on Windows 7. */
|
|
#define MAX_WINDOWS_EXPLORER_SIZE (4 * 1000 * 1000)
|
|
|
|
/* Machine types. */
|
|
#if defined(__x86_64__)
|
|
#define MACHINE_TYPE "q35"
|
|
#endif
|
|
#ifdef __arm__
|
|
#define MACHINE_TYPE "virt"
|
|
#endif
|
|
#ifdef __aarch64__
|
|
#define MACHINE_TYPE "virt"
|
|
#endif
|
|
#ifdef __powerpc__
|
|
#define MACHINE_TYPE "pseries"
|
|
#endif
|
|
#ifdef __riscv
|
|
#define MACHINE_TYPE "virt"
|
|
#endif
|
|
|
|
/* Differences in qemu device names on ARMv7 (virtio-mmio), s/390x
|
|
* (CCW) vs normal hardware with PCI.
|
|
*/
|
|
#if defined(__arm__)
|
|
#define VIRTIO_DEVICE_NAME(type) type "-device"
|
|
#elif defined(__s390x__)
|
|
#define VIRTIO_DEVICE_NAME(type) type "-ccw"
|
|
#else
|
|
#define VIRTIO_DEVICE_NAME(type) type "-pci"
|
|
#endif
|
|
|
|
/* Place the virtio-net controller in slot 0x1e on the root bus, on normal
|
|
* hardware with PCI. Necessary only before libvirt 3.8.0. Refer to
|
|
* RHBZ#2034160.
|
|
*/
|
|
#ifdef HAVE_LIBVIRT
|
|
#if defined(__arm__) || defined(__s390x__)
|
|
#define VIRTIO_NET_PCI_ADDR ""
|
|
#else
|
|
#define VIRTIO_NET_PCI_ADDR ",addr=1e.0"
|
|
#endif
|
|
#endif
|
|
|
|
/* Network address and network mask (expressed as address prefix) that the
|
|
* appliance will see (if networking is enabled).
|
|
*/
|
|
#define NETWORK_ADDRESS "169.254.2.15"
|
|
#define NETWORK_PREFIX "16"
|
|
|
|
/* The IP address and the MAC address of the host, as seen from the appliance.
|
|
*
|
|
* NETWORK_GW_IP should be the same as NETWORK_ADDRESS, only replacing ".15" in
|
|
* the rightmost octet with ".2". NETWORK_GW_MAC cannot be changed. These
|
|
* restrictions are a consequence of the following landscape:
|
|
*
|
|
* libguestfs backend userspace network stack restrictions
|
|
* ------------------ ----------------------- --------------------------------
|
|
* direct passt None; both NETWORK_GW_IP and
|
|
* NETWORK_GW_MAC can be set on the
|
|
* passt command line.
|
|
*
|
|
* direct SLIRP SLIRP hard-codes NETWORK_GW_MAC.
|
|
*
|
|
* libvirt passt The domain XML does not expose
|
|
* either knob (RHBZ#2222766), even
|
|
* though passt could accept both.
|
|
*
|
|
* libvirt SLIRP The domain XML does not expose
|
|
* either knob (RHBZ#2222766), and
|
|
* SLIRP hard-codes NETWORK_GW_MAC
|
|
* anyway.
|
|
*/
|
|
#define NETWORK_GW_IP "169.254.2.2"
|
|
#define NETWORK_GW_MAC "52:56:00:00:00:02"
|
|
|
|
/* Guestfs handle and associated structures. */
|
|
|
|
/* State. */
|
|
enum state { CONFIG = 0, LAUNCHING = 1, READY = 2,
|
|
NO_HANDLE = 0xebadebad };
|
|
|
|
/**
|
|
* This struct is used to maintain a list of events registered
|
|
* against the handle. See C<g-E<gt>events> in the handle.
|
|
*/
|
|
struct event {
|
|
uint64_t event_bitmask;
|
|
guestfs_event_callback cb;
|
|
void *opaque;
|
|
|
|
/* opaque2 is not exposed through the API, but is used internally to
|
|
* emulate the old-style callback API.
|
|
*/
|
|
void *opaque2;
|
|
};
|
|
|
|
/* Drives added to the handle. */
|
|
enum drive_protocol {
|
|
drive_protocol_file,
|
|
drive_protocol_ftp,
|
|
drive_protocol_ftps,
|
|
drive_protocol_http,
|
|
drive_protocol_https,
|
|
drive_protocol_iscsi,
|
|
drive_protocol_nbd,
|
|
drive_protocol_rbd,
|
|
drive_protocol_ssh,
|
|
};
|
|
|
|
enum drive_transport {
|
|
drive_transport_none = 0, /* no transport specified */
|
|
drive_transport_tcp, /* +tcp */
|
|
drive_transport_unix, /* +unix */
|
|
};
|
|
|
|
struct drive_server {
|
|
enum drive_transport transport;
|
|
|
|
/* This field is always non-NULL. */
|
|
union {
|
|
char *hostname; /* hostname or IP address as a string */
|
|
char *socket; /* Unix domain socket */
|
|
} u;
|
|
|
|
int port; /* port number */
|
|
};
|
|
|
|
struct drive_source {
|
|
enum drive_protocol protocol;
|
|
|
|
/* Format (eg. raw, qcow2). NULL = autodetect. */
|
|
char *format;
|
|
|
|
/* This field is always non-NULL. It may be an empty string. */
|
|
union {
|
|
char *path; /* path to file (file) */
|
|
char *exportname; /* name of export (nbd) */
|
|
} u;
|
|
|
|
/* For network transports, zero or more servers can be specified here.
|
|
*
|
|
* - for protocol "nbd": exactly one server
|
|
*/
|
|
size_t nr_servers;
|
|
struct drive_server *servers;
|
|
|
|
/* Optional username (may be NULL if not specified). */
|
|
char *username;
|
|
/* Optional secret (may be NULL if not specified). */
|
|
char *secret;
|
|
};
|
|
|
|
enum discard {
|
|
discard_disable = 0,
|
|
discard_enable,
|
|
discard_besteffort,
|
|
};
|
|
|
|
/**
|
|
* There is one C<struct drive> per drive.
|
|
*/
|
|
struct drive {
|
|
/* Original source of the drive, eg. file:..., http:... */
|
|
struct drive_source src;
|
|
|
|
/* If the drive is readonly, then an overlay [a local file] is
|
|
* created before launch to protect the original drive content, and
|
|
* the filename is stored here. Backends should open this file if
|
|
* it is non-NULL, else consult the original source above.
|
|
*
|
|
* Note that the overlay is in a backend-specific format, probably
|
|
* different from the source format. eg. qcow2
|
|
*/
|
|
char *overlay;
|
|
|
|
/* Various per-drive flags. */
|
|
bool readonly;
|
|
char *name;
|
|
char *disk_label;
|
|
char *cachemode;
|
|
enum discard discard;
|
|
bool copyonread;
|
|
int blocksize;
|
|
};
|
|
|
|
/* Extra hv parameters (from guestfs_config). */
|
|
struct hv_param {
|
|
struct hv_param *next;
|
|
|
|
char *hv_param;
|
|
char *hv_value; /* May be NULL. */
|
|
};
|
|
|
|
/**
|
|
* Backend operations.
|
|
*
|
|
* Each backend (eg. libvirt, direct) defines some functions which get
|
|
* run at various places in the handle lifecycle (eg. at launch,
|
|
* shutdown). The backend defines this struct pointing to those
|
|
* functions.
|
|
*/
|
|
struct backend_ops {
|
|
/* Size (in bytes) of the per-handle data structure needed by this
|
|
* backend. The data pointer is allocated and freed by libguestfs
|
|
* and passed to the functions in the 'void *data' parameter.
|
|
* Inside the data structure is opaque to libguestfs. Any strings
|
|
* etc pointed to by it must be freed by the backend during
|
|
* shutdown.
|
|
*/
|
|
size_t data_size;
|
|
|
|
/* Create a COW overlay on top of a drive. This must be a local
|
|
* file, created in the temporary directory. This is called when
|
|
* the drive is added to the handle.
|
|
*/
|
|
char *(*create_cow_overlay) (guestfs_h *g, void *data, struct drive *drv);
|
|
|
|
/* Launch and shut down. */
|
|
int (*launch) (guestfs_h *g, void *data, const char *arg);
|
|
int (*shutdown) (guestfs_h *g, void *data, int check_for_errors);
|
|
|
|
/* Miscellaneous. */
|
|
int (*get_pid) (guestfs_h *g, void *data);
|
|
int (*max_disks) (guestfs_h *g, void *data);
|
|
};
|
|
|
|
/**
|
|
* Connection module.
|
|
*
|
|
* A C<connection> represents the appliance console connection plus
|
|
* the daemon connection. It hides the underlying representation
|
|
* (POSIX sockets, C<virStreamPtr>).
|
|
*/
|
|
struct connection {
|
|
const struct connection_ops *ops;
|
|
|
|
/* In the real struct, private data used by each connection module
|
|
* follows here.
|
|
*/
|
|
};
|
|
|
|
struct connection_ops {
|
|
/* Close everything and free the connection struct and any internal data. */
|
|
void (*free_connection) (guestfs_h *g, struct connection *);
|
|
|
|
/* Accept the connection (back to us) from the daemon.
|
|
* There is an implicit timeout (APPLIANCE_TIMEOUT defined above).
|
|
*
|
|
* Returns: 1 = accepted, 0 = appliance closed connection, -1 = error
|
|
*/
|
|
int (*accept_connection) (guestfs_h *g, struct connection *);
|
|
|
|
/* Read/write the given buffer from/to the daemon. The whole buffer is
|
|
* read or written. Partial reads/writes are automatically completed
|
|
* if possible, and if this wasn't possible it returns an error.
|
|
*
|
|
* These functions also monitor the console socket and deliver log
|
|
* messages up as events. This is entirely transparent to the caller.
|
|
*
|
|
* Normal return is number of bytes read/written. Both functions
|
|
* return 0 to mean that the appliance closed the connection or
|
|
* otherwise went away. -1 means there's an error.
|
|
*/
|
|
ssize_t (*read_data) (guestfs_h *g, struct connection *, void *buf, size_t len);
|
|
ssize_t (*write_data) (guestfs_h *g, struct connection *, const void *buf, size_t len);
|
|
|
|
/* Test if data is available to read on the daemon socket, without blocking.
|
|
* Returns: 1 = yes, 0 = no, -1 = error
|
|
*/
|
|
int (*can_read_data) (guestfs_h *g, struct connection *);
|
|
|
|
/* Get the console socket (to support virt-rescue). */
|
|
int (*get_console_sock) (guestfs_h *g, struct connection *);
|
|
};
|
|
|
|
/**
|
|
* Cache of queried features.
|
|
*
|
|
* Used to cache the appliance features (see F<lib/available.c>).
|
|
*/
|
|
struct cached_feature {
|
|
char *group;
|
|
int result;
|
|
};
|
|
|
|
/**
|
|
* The libguestfs handle.
|
|
*/
|
|
struct guestfs_h {
|
|
struct guestfs_h *next; /* Linked list of open handles. */
|
|
enum state state; /* See the state machine diagram in guestfs(3)*/
|
|
|
|
/* Lock acquired when entering any public guestfs_* function to
|
|
* protect the handle.
|
|
*/
|
|
pthread_mutex_t lock;
|
|
|
|
/**** Configuration of the handle. ****/
|
|
bool verbose; /* Debugging. */
|
|
bool trace; /* Trace calls. */
|
|
bool autosync; /* Autosync. */
|
|
bool direct_mode; /* Direct mode. */
|
|
bool recovery_proc; /* Create a recovery process. */
|
|
bool enable_network; /* Enable the network. */
|
|
bool selinux; /* selinux enabled? */
|
|
bool pgroup; /* Create process group for children? */
|
|
bool close_on_exit; /* Is this handle on the atexit list? */
|
|
|
|
int smp; /* If > 1, -smp flag passed to hv. */
|
|
int memsize; /* Size of RAM (megabytes). */
|
|
|
|
char *path; /* Path to the appliance. */
|
|
char *hv; /* Hypervisor (HV) binary. */
|
|
char *append; /* Append to kernel command line. */
|
|
|
|
struct hv_param *hv_params; /* Extra hv parameters. */
|
|
|
|
char *program; /* Program name. */
|
|
char *identifier; /* Handle identifier. */
|
|
|
|
/* Array of drives added by add-drive* APIs.
|
|
*
|
|
* Before launch this list can be empty or contain some drives.
|
|
*
|
|
* During launch, a dummy slot may be added which represents the
|
|
* slot taken up by the appliance drive.
|
|
*
|
|
* During shutdown, this list is deleted, so that each launch gets a
|
|
* fresh set of drives (however callers: don't do this, create a new
|
|
* handle each time).
|
|
*
|
|
* Always use ITER_DRIVES macro to iterate over this list!
|
|
*/
|
|
struct drive **drives;
|
|
size_t nr_drives;
|
|
|
|
#define ITER_DRIVES(g,i,drv) \
|
|
for (i = 0; i < (g)->nr_drives; ++i) \
|
|
if (((drv) = (g)->drives[i]) != NULL)
|
|
|
|
/* Backend. NB: Use guestfs_int_set_backend to change the backend. */
|
|
char *backend; /* The full string, always non-NULL. */
|
|
char *backend_arg; /* Pointer to the argument part. */
|
|
const struct backend_ops *backend_ops;
|
|
void *backend_data; /* Per-handle data. */
|
|
char **backend_settings; /* Backend settings (can be NULL). */
|
|
|
|
/**** Runtime information. ****/
|
|
/* Temporary and cache directories. */
|
|
/* The actual temporary directory - this is not created with the
|
|
* handle, you have to call guestfs_int_lazy_make_tmpdir.
|
|
*/
|
|
char *tmpdir;
|
|
char *sockdir;
|
|
/* Environment variables that affect tmpdir/cachedir/sockdir locations. */
|
|
char *env_tmpdir; /* $TMPDIR (NULL if not set) */
|
|
char *env_runtimedir; /* $XDG_RUNTIME_DIR (NULL if not set)*/
|
|
char *int_tmpdir; /* $LIBGUESTFS_TMPDIR or guestfs_set_tmpdir or NULL */
|
|
char *int_cachedir; /* $LIBGUESTFS_CACHEDIR or guestfs_set_cachedir or NULL */
|
|
|
|
/* Error handler, plus stack of old error handlers. */
|
|
pthread_key_t error_data;
|
|
|
|
/* Linked list of error_data structures allocated for this handle,
|
|
* plus a mutex to protect the linked list.
|
|
*/
|
|
pthread_mutex_t error_data_list_lock;
|
|
struct error_data *error_data_list;
|
|
|
|
/* Out of memory error handler. */
|
|
guestfs_abort_cb abort_cb;
|
|
|
|
/* Events. */
|
|
struct event *events;
|
|
size_t nr_events;
|
|
|
|
/* Private data area. */
|
|
struct hash_table *pda;
|
|
struct pda_entry *pda_next;
|
|
|
|
/* User cancelled transfer. Not signal-atomic, but it doesn't
|
|
* matter for this case because we only care if it is != 0.
|
|
*/
|
|
int user_cancel;
|
|
|
|
struct timeval launch_t; /* The time that we called guestfs_launch. */
|
|
|
|
/* Used by bindtests. */
|
|
FILE *test_fp;
|
|
|
|
/* Used to generate unique numbers, eg for temp files. To use this,
|
|
* '++g->unique'. Note these are only unique per-handle, not
|
|
* globally unique.
|
|
*/
|
|
int unique;
|
|
|
|
/*** Protocol. ***/
|
|
struct connection *conn; /* Connection to appliance. */
|
|
int msg_next_serial;
|
|
|
|
#if HAVE_FUSE
|
|
/**** Used by the mount-local APIs. ****/
|
|
char *localmountpoint;
|
|
struct fuse *fuse; /* FUSE handle. */
|
|
int ml_dir_cache_timeout; /* Directory cache timeout. */
|
|
Hash_table *lsc_ht, *xac_ht, *rlc_ht; /* Directory cache. */
|
|
int ml_read_only; /* If mounted read-only. */
|
|
int ml_debug_calls; /* Extra debug info on each FUSE call. */
|
|
#endif
|
|
|
|
#ifdef HAVE_LIBVIRT
|
|
/* Used by lib/libvirt-auth.c. */
|
|
#define NR_CREDENTIAL_TYPES 9
|
|
unsigned int nr_supported_credentials;
|
|
int supported_credentials[NR_CREDENTIAL_TYPES];
|
|
const char *saved_libvirt_uri; /* Doesn't need to be freed. */
|
|
bool wrapper_warning_done;
|
|
unsigned int nr_requested_credentials;
|
|
virConnectCredentialPtr requested_credentials;
|
|
#endif
|
|
|
|
/* Cached features. */
|
|
struct cached_feature *features;
|
|
size_t nr_features;
|
|
|
|
/* Used by lib/info.c. -1 = not tested or error; else 0 or 1. */
|
|
int qemu_img_supports_U_option;
|
|
};
|
|
|
|
/**
|
|
* Used for storing major.minor.micro version numbers.
|
|
* See F<lib/version.c> for more information.
|
|
*/
|
|
struct version {
|
|
int v_major;
|
|
int v_minor;
|
|
int v_micro;
|
|
};
|
|
|
|
struct guestfs_message_header;
|
|
struct guestfs_message_error;
|
|
struct guestfs_progress;
|
|
|
|
/* handle.c */
|
|
extern int guestfs_int_get_backend_setting_bool (guestfs_h *g, const char *name);
|
|
|
|
/* alloc.c */
|
|
extern void *guestfs_int_safe_malloc (guestfs_h *g, size_t nbytes);
|
|
extern void *guestfs_int_safe_calloc (guestfs_h *g, size_t n, size_t s);
|
|
extern char *guestfs_int_safe_strdup (guestfs_h *g, const char *str);
|
|
extern void *guestfs_int_safe_memdup (guestfs_h *g, const void *ptr, size_t size);
|
|
extern void *guestfs_int_safe_realloc (guestfs_h *g, void *ptr, size_t nbytes);
|
|
extern char *guestfs_int_safe_strdup (guestfs_h *g, const char *str);
|
|
extern char *guestfs_int_safe_strndup (guestfs_h *g, const char *str, size_t n);
|
|
extern void *guestfs_int_safe_memdup (guestfs_h *g, const void *ptr, size_t size);
|
|
extern char *guestfs_int_safe_asprintf (guestfs_h *g, const char *fs, ...)
|
|
__attribute__((format (printf,2,3)));
|
|
|
|
#define safe_calloc guestfs_int_safe_calloc
|
|
#define safe_malloc guestfs_int_safe_malloc
|
|
#define safe_realloc guestfs_int_safe_realloc
|
|
#define safe_strdup guestfs_int_safe_strdup
|
|
#define safe_strndup guestfs_int_safe_strndup
|
|
#define safe_memdup guestfs_int_safe_memdup
|
|
#define safe_asprintf guestfs_int_safe_asprintf
|
|
|
|
/* errors.c */
|
|
extern void guestfs_int_free_error_data_list (guestfs_h *g);
|
|
|
|
extern void guestfs_int_error_errno (guestfs_h *g, int errnum, const char *fs, ...)
|
|
__attribute__((format (printf,3,4)));
|
|
extern void guestfs_int_perrorf (guestfs_h *g, const char *fs, ...)
|
|
__attribute__((format (printf,2,3)));
|
|
|
|
extern void guestfs_int_warning (guestfs_h *g, const char *fs, ...)
|
|
__attribute__((format (printf,2,3)));
|
|
extern void guestfs_int_debug (guestfs_h *g, const char *fs, ...)
|
|
__attribute__((format (printf,2,3)));
|
|
extern void guestfs_int_trace (guestfs_h *g, const char *fs, ...)
|
|
__attribute__((format (printf,2,3)));
|
|
|
|
extern void guestfs_int_print_BufferIn (FILE *out, const char *buf, size_t buf_size);
|
|
extern void guestfs_int_print_BufferOut (FILE *out, const char *buf, size_t buf_size);
|
|
|
|
#define error(g,...) guestfs_int_error_errno((g),0,__VA_ARGS__)
|
|
#define perrorf guestfs_int_perrorf
|
|
#define warning(g,...) guestfs_int_warning((g),__VA_ARGS__)
|
|
#define debug(g,...) \
|
|
do { if ((g)->verbose) guestfs_int_debug ((g),__VA_ARGS__); } while (0)
|
|
|
|
#define NOT_SUPPORTED(g,errcode,...) \
|
|
do { \
|
|
guestfs_int_error_errno ((g), ENOTSUP, __VA_ARGS__); \
|
|
return (errcode); \
|
|
} \
|
|
while (0)
|
|
|
|
extern void guestfs_int_launch_failed_error (guestfs_h *g);
|
|
extern void guestfs_int_unexpected_close_error (guestfs_h *g);
|
|
extern void guestfs_int_launch_timeout (guestfs_h *g);
|
|
extern void guestfs_int_external_command_failed (guestfs_h *g, int status, const char *cmd_name, const char *extra);
|
|
|
|
/* actions-support.c */
|
|
struct trace_buffer {
|
|
FILE *fp;
|
|
char *buf;
|
|
size_t len;
|
|
bool opened;
|
|
};
|
|
|
|
extern int guestfs_int_check_reply_header (guestfs_h *g, const struct guestfs_message_header *hdr, unsigned int proc_nr, unsigned int serial);
|
|
extern int guestfs_int_check_appliance_up (guestfs_h *g, const char *caller);
|
|
extern void guestfs_int_trace_open (struct trace_buffer *tb);
|
|
extern void guestfs_int_trace_send_line (guestfs_h *g, struct trace_buffer *tb);
|
|
|
|
/* match.c */
|
|
extern int guestfs_int_match (guestfs_h *g, const char *str, const pcre2_code *re);
|
|
extern char *guestfs_int_match1 (guestfs_h *g, const char *str, const pcre2_code *re);
|
|
extern int guestfs_int_match2 (guestfs_h *g, const char *str, const pcre2_code *re, char **ret1, char **ret2);
|
|
extern int guestfs_int_match3 (guestfs_h *g, const char *str, const pcre2_code *re, char **ret1, char **ret2, char **ret3);
|
|
extern int guestfs_int_match4 (guestfs_h *g, const char *str, const pcre2_code *re, char **ret1, char **ret2, char **ret3, char **ret4);
|
|
extern int guestfs_int_match6 (guestfs_h *g, const char *str, const pcre2_code *re, char **ret1, char **ret2, char **ret3, char **ret4, char **ret5, char **ret6);
|
|
|
|
#define match guestfs_int_match
|
|
#define match1 guestfs_int_match1
|
|
#define match2 guestfs_int_match2
|
|
#define match3 guestfs_int_match3
|
|
#define match4 guestfs_int_match4
|
|
#define match6 guestfs_int_match6
|
|
|
|
/* stringsbuf.c */
|
|
struct stringsbuf {
|
|
char **argv;
|
|
size_t size;
|
|
size_t alloc;
|
|
};
|
|
#define DECLARE_STRINGSBUF(v) \
|
|
struct stringsbuf (v) = { .argv = NULL, .size = 0, .alloc = 0 }
|
|
|
|
extern void guestfs_int_add_string_nodup (guestfs_h *g, struct stringsbuf *sb, char *str);
|
|
extern void guestfs_int_add_string (guestfs_h *g, struct stringsbuf *sb, const char *str);
|
|
extern void guestfs_int_add_sprintf (guestfs_h *g, struct stringsbuf *sb, const char *fs, ...)
|
|
__attribute__((format (printf,3,4)));
|
|
extern void guestfs_int_end_stringsbuf (guestfs_h *g, struct stringsbuf *sb);
|
|
|
|
extern void guestfs_int_free_stringsbuf (struct stringsbuf *sb);
|
|
|
|
#define CLEANUP_FREE_STRINGSBUF __attribute__((cleanup(guestfs_int_cleanup_free_stringsbuf)))
|
|
extern void guestfs_int_cleanup_free_stringsbuf (struct stringsbuf *sb);
|
|
|
|
/* proto.c */
|
|
extern int guestfs_int_send (guestfs_h *g, int proc_nr, uint64_t progress_hint, uint64_t optargs_bitmask, xdrproc_t xdrp, char *args);
|
|
extern int guestfs_int_recv (guestfs_h *g, const char *fn, struct guestfs_message_header *hdr, struct guestfs_message_error *err, xdrproc_t xdrp, char *ret);
|
|
extern int guestfs_int_recv_discard (guestfs_h *g, const char *fn);
|
|
extern int guestfs_int_send_file (guestfs_h *g, const char *filename);
|
|
extern int guestfs_int_recv_file (guestfs_h *g, const char *filename);
|
|
extern int guestfs_int_recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn);
|
|
extern void guestfs_int_progress_message_callback (guestfs_h *g, const struct guestfs_progress *message);
|
|
extern void guestfs_int_log_message_callback (guestfs_h *g, const char *buf, size_t len);
|
|
|
|
/* conn-socket.c */
|
|
extern struct connection *guestfs_int_new_conn_socket_listening (guestfs_h *g, int daemon_accept_sock, int console_sock);
|
|
extern struct connection *guestfs_int_new_conn_socket_connected (guestfs_h *g, int daemon_sock, int console_sock);
|
|
|
|
/* events.c */
|
|
extern void guestfs_int_call_callbacks_void (guestfs_h *g, uint64_t event);
|
|
extern void guestfs_int_call_callbacks_message (guestfs_h *g, uint64_t event, const char *buf, size_t buf_len);
|
|
extern void guestfs_int_call_callbacks_array (guestfs_h *g, uint64_t event, const uint64_t *array, size_t array_len);
|
|
|
|
/* tmpdirs.c */
|
|
extern int guestfs_int_set_env_tmpdir (guestfs_h *g, const char *envname, const char *tmpdir);
|
|
extern int guestfs_int_set_env_runtimedir (guestfs_h *g, const char *envname, const char *runtimedir);
|
|
extern int guestfs_int_lazy_make_tmpdir (guestfs_h *g);
|
|
extern int guestfs_int_lazy_make_sockdir (guestfs_h *g);
|
|
extern char *guestfs_int_make_temp_path (guestfs_h *g, const char *name, const char *extension);
|
|
extern int guestfs_int_create_socketname (guestfs_h *g, const char *filename, char (*sockname)[UNIX_PATH_MAX]);
|
|
extern char *guestfs_int_make_pid_path (guestfs_h *g, const char *name);
|
|
extern char *guestfs_int_lazy_make_supermin_appliance_dir (guestfs_h *g);
|
|
extern void guestfs_int_remove_tmpdir (guestfs_h *g);
|
|
extern void guestfs_int_remove_sockdir (guestfs_h *g);
|
|
extern void guestfs_int_recursive_remove_dir (guestfs_h *g, const char *dir);
|
|
|
|
/* whole-file.c */
|
|
extern int guestfs_int_read_whole_file (guestfs_h *g, const char *filename, char **data_r, size_t *size_r);
|
|
|
|
/* drives.c */
|
|
extern size_t guestfs_int_checkpoint_drives (guestfs_h *g);
|
|
extern void guestfs_int_rollback_drives (guestfs_h *g, size_t);
|
|
extern void guestfs_int_add_dummy_appliance_drive (guestfs_h *g);
|
|
extern void guestfs_int_free_drives (guestfs_h *g);
|
|
extern const char *guestfs_int_drive_protocol_to_string (enum drive_protocol protocol);
|
|
|
|
/* appliance.c */
|
|
extern int guestfs_int_build_appliance (guestfs_h *g, char **kernel, char **initrd, char **appliance);
|
|
|
|
/* appliance-cpu.c */
|
|
const char *guestfs_int_get_cpu_model (int kvm);
|
|
|
|
/* appliance-kcmdline.c */
|
|
extern char *guestfs_int_appliance_command_line (guestfs_h *g, const char *appliance, int flags);
|
|
#define APPLIANCE_COMMAND_LINE_IS_TCG 1
|
|
|
|
/* appliance-uefi.c */
|
|
extern int guestfs_int_get_uefi (guestfs_h *g, char *const *firmwares, const char **firmware, char **code, char **vars, int *flags);
|
|
|
|
/* launch.c */
|
|
extern int64_t guestfs_int_timeval_diff (const struct timeval *x, const struct timeval *y);
|
|
extern void guestfs_int_launch_send_progress (guestfs_h *g, int perdozen);
|
|
extern void guestfs_int_unblock_sigterm (void);
|
|
extern void guestfs_int_register_backend (const char *name, const struct backend_ops *);
|
|
extern int guestfs_int_set_backend (guestfs_h *g, const char *method);
|
|
extern bool guestfs_int_passt_runnable (guestfs_h *g);
|
|
|
|
/* Close all file descriptors matching the condition. */
|
|
#define close_file_descriptors(cond) do { \
|
|
int max_fd = sysconf (_SC_OPEN_MAX); \
|
|
int fd; \
|
|
if (max_fd == -1) \
|
|
max_fd = 1024; \
|
|
if (max_fd > 65536) \
|
|
max_fd = 65536; /* bound the amount of work we do here */ \
|
|
for (fd = 0; fd < max_fd; ++fd) { \
|
|
if (cond) \
|
|
close (fd); \
|
|
} \
|
|
} while (0)
|
|
|
|
/* inspect.c */
|
|
extern char *guestfs_int_download_to_tmp (guestfs_h *g, const char *filename, const char *extension, uint64_t max_size);
|
|
|
|
/* lpj.c */
|
|
extern int guestfs_int_get_lpj (guestfs_h *g);
|
|
|
|
/* fuse.c */
|
|
#if HAVE_FUSE
|
|
extern void guestfs_int_free_fuse (guestfs_h *g);
|
|
#endif
|
|
|
|
/* libvirt-auth.c */
|
|
#ifdef HAVE_LIBVIRT
|
|
extern virConnectPtr guestfs_int_open_libvirt_connection (guestfs_h *g, const char *uri, unsigned int flags);
|
|
#endif
|
|
|
|
/* command.c */
|
|
struct command;
|
|
typedef void (*cmd_stdout_callback) (guestfs_h *g, void *data, const char *line, size_t len);
|
|
typedef int (*cmd_child_callback) (guestfs_h *g, void *data);
|
|
extern struct command *guestfs_int_new_command (guestfs_h *g);
|
|
extern void guestfs_int_cmd_add_arg (struct command *, const char *arg);
|
|
extern void guestfs_int_cmd_add_arg_format (struct command *, const char *fs, ...)
|
|
__attribute__((format (printf,2,3)));
|
|
extern void guestfs_int_cmd_add_string_unquoted (struct command *, const char *str);
|
|
extern void guestfs_int_cmd_add_string_quoted (struct command *, const char *str);
|
|
extern void guestfs_int_cmd_set_stdout_callback (struct command *, cmd_stdout_callback stdout_callback, void *data, unsigned flags);
|
|
#define CMD_STDOUT_FLAG_LINE_BUFFER 0
|
|
#define CMD_STDOUT_FLAG_UNBUFFERED 1
|
|
#define CMD_STDOUT_FLAG_WHOLE_BUFFER 2
|
|
extern void guestfs_int_cmd_set_stderr_to_stdout (struct command *);
|
|
extern void guestfs_int_cmd_set_child_rlimit (struct command *, int resource, long limit);
|
|
extern void guestfs_int_cmd_clear_capture_errors (struct command *);
|
|
extern void guestfs_int_cmd_set_child_callback (struct command *, cmd_child_callback child_callback, void *data);
|
|
extern int guestfs_int_cmd_run (struct command *);
|
|
extern void guestfs_int_cmd_close (struct command *);
|
|
extern int guestfs_int_cmd_pipe_run (struct command *cmd, const char *mode);
|
|
extern int guestfs_int_cmd_pipe_wait (struct command *cmd);
|
|
extern char *guestfs_int_cmd_get_pipe_errors (struct command *cmd);
|
|
|
|
#define CLEANUP_CMD_CLOSE __attribute__((cleanup(guestfs_int_cleanup_cmd_close)))
|
|
extern void guestfs_int_cleanup_cmd_close (struct command **);
|
|
|
|
/* launch-*.c constructors */
|
|
void guestfs_int_init_direct_backend (void) __attribute__((constructor));
|
|
#ifdef HAVE_LIBVIRT
|
|
void guestfs_int_init_libvirt_backend (void) __attribute__((constructor));
|
|
#endif
|
|
|
|
/* qemu.c */
|
|
struct qemu_data;
|
|
extern struct qemu_data *guestfs_int_test_qemu (guestfs_h *g);
|
|
extern struct version guestfs_int_qemu_version (guestfs_h *g, struct qemu_data *);
|
|
extern int guestfs_int_qemu_supports (guestfs_h *g, const struct qemu_data *, const char *option);
|
|
extern int guestfs_int_qemu_supports_device (guestfs_h *g, const struct qemu_data *, const char *device_name);
|
|
extern bool guestfs_int_platform_has_kvm (guestfs_h *g, const struct qemu_data *data);
|
|
extern char *guestfs_int_drive_source_qemu_param (guestfs_h *g, const struct drive_source *src);
|
|
extern bool guestfs_int_discard_possible (guestfs_h *g, struct drive *drv, const struct version *qemu_version);
|
|
extern char *guestfs_int_qemu_escape_param (guestfs_h *g, const char *param);
|
|
extern void guestfs_int_free_qemu_data (struct qemu_data *);
|
|
|
|
/* guid.c */
|
|
extern int guestfs_int_validate_guid (const char *);
|
|
|
|
/* umask.c */
|
|
extern int guestfs_int_getumask (guestfs_h *g);
|
|
|
|
/* wait.c */
|
|
extern int guestfs_int_waitpid (guestfs_h *g, pid_t pid, int *status, const char *errmsg);
|
|
extern void guestfs_int_waitpid_noerror (pid_t pid);
|
|
struct rusage;
|
|
extern int guestfs_int_wait4 (guestfs_h *g, pid_t pid, int *status, struct rusage *rusage, const char *errmsg);
|
|
|
|
/* version.c */
|
|
extern void guestfs_int_version_from_libvirt (struct version *v, int vernum);
|
|
extern void guestfs_int_version_from_values (struct version *v, int maj, int min, int mic);
|
|
extern int guestfs_int_version_from_x_y (guestfs_h *g, struct version *v, const char *str);
|
|
extern int guestfs_int_version_from_x_y_re (guestfs_h *g, struct version *v, const char *str, const pcre2_code *re);
|
|
extern int guestfs_int_version_from_x_y_or_x (guestfs_h *g, struct version *v, const char *str);
|
|
extern bool guestfs_int_version_ge (const struct version *v, int maj, int min, int mic);
|
|
extern bool guestfs_int_version_cmp_ge (const struct version *a, const struct version *b);
|
|
extern int guestfs_int_parse_unsigned_int (guestfs_h *g, const char *str);
|
|
#define version_init_null(v) guestfs_int_version_from_values (v, 0, 0, 0)
|
|
#define version_is_null(v) ((v)->v_major == 0 && (v)->v_minor == 0 && (v)->v_micro == 0)
|
|
|
|
/* uefi.c */
|
|
struct uefi_firmware {
|
|
const char *code; /* code file (NULL = end of list) */
|
|
const char *code_debug; /* code file with debugging msgs (may be NULL)*/
|
|
const char *vars; /* vars template file */
|
|
int flags; /* various flags, see below */
|
|
#define UEFI_FLAG_SECURE_BOOT_REQUIRED 1 /* secure boot (see RHBZ#1367615) */
|
|
};
|
|
extern struct uefi_firmware guestfs_int_uefi_i386_firmware[];
|
|
extern struct uefi_firmware guestfs_int_uefi_x86_64_firmware[];
|
|
extern struct uefi_firmware guestfs_int_uefi_aarch64_firmware[];
|
|
|
|
#endif /* GUESTFS_INTERNAL_H_ */
|