mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
LIBGUESTFS_PATH implementation.
This commit is contained in:
10
configure.ac
10
configure.ac
@@ -50,10 +50,9 @@ AC_CHECK_PROG([POD2TEXT],[pod2text],[pod2text],[no])
|
||||
test "x$POD2TEXT" = "xno" &&
|
||||
AC_MSG_ERROR([pod2text must be installed])
|
||||
|
||||
dnl Check for QEMU. We only check for the basic 'qemu' program here
|
||||
dnl (ie. the i386 full system qemu). But at runtime we might choose
|
||||
dnl a different qemu to run, eg. qemu-system-ppc.
|
||||
AC_PATH_PROG([QEMU],[qemu],[no],
|
||||
dnl Check for QEMU for running binaries on this $host_cpu, fall
|
||||
dnl back to basic 'qemu'.
|
||||
AC_PATH_PROGS([QEMU],[qemu-system-$host_cpu qemu],[no],
|
||||
[$PATH$PATH_SEPARATOR/usr/sbin$PATH_SEPARATOR/sbin])
|
||||
test "x$QEMU" = "xno" && AC_MSG_ERROR([qemu must be installed])
|
||||
AC_DEFINE_UNQUOTED([QEMU],["$QEMU"],[Location of qemu binary.])
|
||||
@@ -84,6 +83,9 @@ AC_ARG_WITH([repo],
|
||||
[with_repo=fedora-10])
|
||||
REPO="$with_repo"
|
||||
AC_SUBST(REPO)
|
||||
AC_DEFINE_UNQUOTED([REPO],["$REPO"],[Name of Fedora repository.])
|
||||
|
||||
AC_DEFINE_UNQUOTED([host_cpu],["$host_cpu"],[Host architecture.])
|
||||
|
||||
dnl --with-mirror to specify a local Fedora mirror.
|
||||
AC_ARG_WITH([mirror],
|
||||
|
||||
@@ -21,5 +21,7 @@ guestfish_SOURCES = \
|
||||
cmds.c \
|
||||
fish.c \
|
||||
fish.h
|
||||
guestfish_CFLAGS = -I$(top_builddir)/src -Wall
|
||||
guestfish_CFLAGS = \
|
||||
-I$(top_builddir)/src -Wall \
|
||||
-DGUESTFS_DEFAULT_PATH='"$(libdir)/guestfs"'
|
||||
guestfish_LDADD = $(top_builddir)/src/libguestfs.la
|
||||
|
||||
@@ -117,6 +117,14 @@ main (int argc, char *argv[])
|
||||
|
||||
guestfs_set_autosync (g, 1);
|
||||
|
||||
/* If developing, add . to the path. Note that libtools interferes
|
||||
* with this because uninstalled guestfish is a shell script that runs
|
||||
* the real program with an absolute path. Detect that too.
|
||||
*/
|
||||
if (argv[0] &&
|
||||
(argv[0][0] != '/' || strstr (argv[0], "/.libs/lt-") != NULL))
|
||||
guestfs_set_path (g, ".:" GUESTFS_DEFAULT_PATH);
|
||||
|
||||
for (;;) {
|
||||
c = getopt_long (argc, argv, options, long_options, NULL);
|
||||
if (c == -1) break;
|
||||
|
||||
63
guestfs.pod
63
guestfs.pod
@@ -237,6 +237,44 @@ situations.
|
||||
|
||||
This returns the current out of memory handler.
|
||||
|
||||
=head1 PATH
|
||||
|
||||
Libguestfs needs a kernel and initrd.img, which it finds by looking
|
||||
along an internal path.
|
||||
|
||||
By default it looks for these in the directory C<$libdir/guestfs>
|
||||
(eg. C</usr/local/lib/guestfs> or C</usr/lib64/guestfs>).
|
||||
|
||||
Use C<guestfs_set_path> or set the environment variable
|
||||
C<LIBGUESTFS_PATH> to change the directories that libguestfs will
|
||||
search in. The value is a colon-separated list of paths. The current
|
||||
directory is I<not> searched unless the path contains an empty element
|
||||
or C<.>. For example C<LIBGUESTFS_PATH=:/usr/lib/guestfs> would
|
||||
search the current directory and then C</usr/lib/guestfs>.
|
||||
|
||||
=head2 guestfs_set_path
|
||||
|
||||
void guestfs_set_path (guestfs_h *handle, const char *path);
|
||||
|
||||
Set the path that libguestfs searches for kernel and initrd.img.
|
||||
|
||||
The default is C<$libdir/guestfs> unless overridden by setting
|
||||
C<LIBGUESTFS_PATH> environment variable.
|
||||
|
||||
The string C<path> is stashed in the libguestfs handle, so the caller
|
||||
must make sure it remains valid for the lifetime of the handle.
|
||||
|
||||
Setting C<path> to C<NULL> restores the default path.
|
||||
|
||||
=head2 guestfs_get_path
|
||||
|
||||
const char *guestfs_get_path (guestfs_h *handle);
|
||||
|
||||
Return the current search path.
|
||||
|
||||
This is always non-NULL. If it wasn't set already, then this will
|
||||
return the default path.
|
||||
|
||||
=head1 AUTOSYNC
|
||||
|
||||
=head2 guestfs_set_autosync
|
||||
@@ -550,13 +588,28 @@ function, eg. C<g_main_loop_quit>. In those cases, ignore this call.
|
||||
This isn't documented. Please see the libguestfs-select and
|
||||
libguestfs-glib implementations.
|
||||
|
||||
=head1 ENVIRONMENT VARIABLES
|
||||
|
||||
=over 4
|
||||
|
||||
=item LIBGUESTFS_DEBUG
|
||||
|
||||
Set C<LIBGUESTFS_DEBUG=1> to enable verbose messages. This
|
||||
has the same effect as calling C<guestfs_set_verbose (handle, 1)>.
|
||||
|
||||
=item LIBGUESTFS_PATH
|
||||
|
||||
Set the path that libguestfs uses to search for kernel and initrd.img.
|
||||
See the discussion of paths in C<guestfs_set_path> above.
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<qemu(1)>
|
||||
|
||||
|
||||
|
||||
|
||||
L<guestfish(1)>,
|
||||
L<qemu(1)>,
|
||||
L<febootstrap(1)>,
|
||||
L<http://et.redhat.com/~rjones/libguestfs>.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
|
||||
@@ -109,6 +109,8 @@ rm -rf $RPM_BUILD_ROOT
|
||||
%doc HACKING README examples
|
||||
%{_libdir}/libguestfs.so
|
||||
%{_mandir}/man3/guestfs.3*
|
||||
%{_includedir}/guestfs.h
|
||||
%{_includedir}/guestfs-actions.h
|
||||
|
||||
|
||||
%files -n guestfish
|
||||
|
||||
@@ -23,6 +23,8 @@ EXTRA_DIST += guestfs_protocol.x \
|
||||
guestfs_protocol.c \
|
||||
guestfs_protocol.h
|
||||
|
||||
include_HEADERS = guestfs.h guestfs-actions.h
|
||||
|
||||
lib_LTLIBRARIES = libguestfs.la
|
||||
|
||||
libguestfs_la_LDFLAGS = -version-info 0:0:0
|
||||
@@ -33,7 +35,7 @@ libguestfs_la_SOURCES = \
|
||||
guestfs_protocol.h \
|
||||
guestfs-actions.h
|
||||
|
||||
libguestfs_la_CFLAGS = -Wall
|
||||
libguestfs_la_CFLAGS = -Wall -DGUESTFS_DEFAULT_PATH='"$(libdir)/guestfs"'
|
||||
|
||||
if RPCGEN
|
||||
guestfs_protocol.c: guestfs_protocol.x
|
||||
|
||||
102
src/guestfs.c
102
src/guestfs.c
@@ -19,7 +19,7 @@
|
||||
#include <config.h>
|
||||
|
||||
#define _BSD_SOURCE /* for mkdtemp, usleep */
|
||||
#define _GNU_SOURCE /* for vasprintf, GNU strerror_r */
|
||||
#define _GNU_SOURCE /* for vasprintf, GNU strerror_r, strchrnul */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -118,6 +118,8 @@ struct guestfs_h
|
||||
int verbose;
|
||||
int autosync;
|
||||
|
||||
const char *path;
|
||||
|
||||
/* Callbacks. */
|
||||
guestfs_abort_cb abort_cb;
|
||||
guestfs_error_handler_cb error_cb;
|
||||
@@ -178,6 +180,10 @@ guestfs_create (void)
|
||||
str = getenv ("LIBGUESTFS_DEBUG");
|
||||
g->verbose = str != NULL && strcmp (str, "1") == 0;
|
||||
|
||||
str = getenv ("LIBGUESTFS_PATH");
|
||||
g->path = str != NULL ? str : GUESTFS_DEFAULT_PATH;
|
||||
/* XXX We should probably make QEMU configurable as well. */
|
||||
|
||||
/* Start with large serial numbers so they are easy to spot
|
||||
* inside the protocol.
|
||||
*/
|
||||
@@ -395,6 +401,21 @@ guestfs_get_autosync (guestfs_h *g)
|
||||
return g->autosync;
|
||||
}
|
||||
|
||||
void
|
||||
guestfs_set_path (guestfs_h *g, const char *path)
|
||||
{
|
||||
if (path == NULL)
|
||||
g->path = GUESTFS_DEFAULT_PATH;
|
||||
else
|
||||
g->path = path;
|
||||
}
|
||||
|
||||
const char *
|
||||
guestfs_get_path (guestfs_h *g)
|
||||
{
|
||||
return g->path;
|
||||
}
|
||||
|
||||
/* Add a string to the current command line. */
|
||||
static void
|
||||
incr_cmdline_size (guestfs_h *g)
|
||||
@@ -487,19 +508,16 @@ int
|
||||
guestfs_launch (guestfs_h *g)
|
||||
{
|
||||
static const char *dir_template = "/tmp/libguestfsXXXXXX";
|
||||
int r, i;
|
||||
int r, i, len;
|
||||
int wfd[2], rfd[2];
|
||||
int tries;
|
||||
/*const char *qemu = QEMU;*/ /* XXX */
|
||||
const char *qemu = "/usr/bin/qemu-system-x86_64";
|
||||
const char *kernel = "vmlinuz.fedora-10.x86_64";
|
||||
const char *initrd = "initramfs.fedora-10.x86_64.img";
|
||||
const char *kernel_name = "vmlinuz." REPO "." host_cpu;
|
||||
const char *initrd_name = "initramfs." REPO "." host_cpu ".img";
|
||||
char *path, *pelem, *pend;
|
||||
char *kernel = NULL, *initrd = NULL;
|
||||
char unixsock[256];
|
||||
struct sockaddr_un addr;
|
||||
|
||||
/* XXX Choose which qemu to run. */
|
||||
/* XXX Choose initrd, etc. */
|
||||
|
||||
/* Configured? */
|
||||
if (!g->cmdline) {
|
||||
error (g, "you must call guestfs_add_drive before guestfs_launch");
|
||||
@@ -511,12 +529,58 @@ guestfs_launch (guestfs_h *g)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Search g->path for the kernel and initrd. */
|
||||
pelem = path = safe_strdup (g, g->path);
|
||||
do {
|
||||
pend = strchrnul (pelem, ':');
|
||||
*pend = '\0';
|
||||
len = pend - pelem;
|
||||
|
||||
/* Empty element or "." means cwd. */
|
||||
if (len == 0 || (len == 1 && *pelem == '.')) {
|
||||
if (g->verbose)
|
||||
fprintf (stderr,
|
||||
"looking for kernel and initrd in current directory\n");
|
||||
if (access (kernel_name, F_OK) == 0 && access (initrd_name, F_OK) == 0) {
|
||||
kernel = safe_strdup (g, kernel_name);
|
||||
initrd = safe_strdup (g, initrd_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Look at <path>/kernel etc. */
|
||||
else {
|
||||
kernel = safe_malloc (g, len + strlen (kernel_name) + 2);
|
||||
initrd = safe_malloc (g, len + strlen (initrd_name) + 2);
|
||||
sprintf (kernel, "%s/%s", pelem, kernel_name);
|
||||
sprintf (initrd, "%s/%s", pelem, initrd_name);
|
||||
|
||||
if (g->verbose)
|
||||
fprintf (stderr, "looking for %s and %s\n", kernel, initrd);
|
||||
|
||||
if (access (kernel, F_OK) == 0 && access (initrd, F_OK) == 0)
|
||||
break;
|
||||
free (kernel);
|
||||
free (initrd);
|
||||
kernel = initrd = NULL;
|
||||
}
|
||||
|
||||
pelem = pend;
|
||||
} while (*pelem++ != '\0');
|
||||
|
||||
free (path);
|
||||
|
||||
if (kernel == NULL || initrd == NULL) {
|
||||
error (g, "cannot find %s or %s on LIBGUESTFS_PATH (current path = %s)",
|
||||
kernel_name, initrd_name, g->path);
|
||||
goto cleanup0;
|
||||
}
|
||||
|
||||
/* Make the temporary directory containing the socket. */
|
||||
if (!g->tmpdir) {
|
||||
g->tmpdir = safe_strdup (g, dir_template);
|
||||
if (mkdtemp (g->tmpdir) == NULL) {
|
||||
perrorf (g, "%s: cannot create temporary directory", dir_template);
|
||||
return -1;
|
||||
goto cleanup0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -525,7 +589,7 @@ guestfs_launch (guestfs_h *g)
|
||||
|
||||
if (pipe (wfd) == -1 || pipe (rfd) == -1) {
|
||||
perrorf (g, "pipe");
|
||||
return -1;
|
||||
goto cleanup0;
|
||||
}
|
||||
|
||||
r = fork ();
|
||||
@@ -535,7 +599,7 @@ guestfs_launch (guestfs_h *g)
|
||||
close (wfd[1]);
|
||||
close (rfd[0]);
|
||||
close (rfd[1]);
|
||||
return -1;
|
||||
goto cleanup0;
|
||||
}
|
||||
|
||||
if (r == 0) { /* Child (qemu). */
|
||||
@@ -545,7 +609,7 @@ guestfs_launch (guestfs_h *g)
|
||||
/* Set up the full command line. Do this in the subprocess so we
|
||||
* don't need to worry about cleaning up.
|
||||
*/
|
||||
g->cmdline[0] = (char *) qemu;
|
||||
g->cmdline[0] = (char *) QEMU;
|
||||
|
||||
/* Construct the -net channel parameter for qemu. */
|
||||
snprintf (vmchannel, sizeof vmchannel,
|
||||
@@ -578,7 +642,7 @@ guestfs_launch (guestfs_h *g)
|
||||
g->cmdline[g->cmdline_size-1] = NULL;
|
||||
|
||||
if (g->verbose) {
|
||||
fprintf (stderr, "%s", qemu);
|
||||
fprintf (stderr, "%s", QEMU);
|
||||
for (i = 0; g->cmdline[i]; ++i)
|
||||
fprintf (stderr, " %s", g->cmdline[i]);
|
||||
fprintf (stderr, "\n");
|
||||
@@ -601,8 +665,8 @@ guestfs_launch (guestfs_h *g)
|
||||
setpgid (0, 0);
|
||||
#endif
|
||||
|
||||
execv (qemu, g->cmdline); /* Run qemu. */
|
||||
perror (qemu);
|
||||
execv (QEMU, g->cmdline); /* Run qemu. */
|
||||
perror (QEMU);
|
||||
_exit (1);
|
||||
}
|
||||
|
||||
@@ -719,6 +783,10 @@ guestfs_launch (guestfs_h *g)
|
||||
g->start_t = 0;
|
||||
g->stdout_watch = -1;
|
||||
g->sock_watch = -1;
|
||||
|
||||
cleanup0:
|
||||
free (kernel);
|
||||
free (initrd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -779,7 +847,7 @@ guestfs_kill_subprocess (guestfs_h *g)
|
||||
}
|
||||
|
||||
if (g->verbose)
|
||||
fprintf (stderr, "sending SIGTERM to process group %d\n", g->pid);
|
||||
fprintf (stderr, "sending SIGTERM to process %d\n", g->pid);
|
||||
|
||||
kill (g->pid, SIGTERM);
|
||||
|
||||
|
||||
@@ -56,6 +56,8 @@ extern void guestfs_set_verbose (guestfs_h *g, int verbose);
|
||||
extern int guestfs_get_verbose (guestfs_h *g);
|
||||
extern void guestfs_set_autosync (guestfs_h *g, int a);
|
||||
extern int guestfs_get_autosync (guestfs_h *g);
|
||||
extern void guestfs_set_path (guestfs_h *g, const char *path);
|
||||
extern const char *guestfs_get_path (guestfs_h *g);
|
||||
|
||||
#include <guestfs-actions.h>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user