Files
kvmtool/builtin-setup.c
T
Sasha Levin d608029001 kvm tools: Link ld.so.conf to the file on the host
This enables the custom rootfs to run executables which have dylibs located
in non standard paths by taking these settings from the host.

Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2015-06-01 16:39:49 +01:00

243 lines
4.6 KiB
C

#include <kvm/util.h>
#include <kvm/kvm-cmd.h>
#include <kvm/builtin-setup.h>
#include <kvm/kvm.h>
#include <kvm/parse-options.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
static const char *instance_name;
static const char * const setup_usage[] = {
"kvm setup [name]",
NULL
};
static const struct option setup_options[] = {
OPT_END()
};
static void parse_setup_options(int argc, const char **argv)
{
while (argc != 0) {
argc = parse_options(argc, argv, setup_options, setup_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
if (argc != 0 && instance_name)
kvm_setup_help();
else
instance_name = argv[0];
argv++;
argc--;
}
}
void kvm_setup_help(void)
{
printf("\nkvm setup creates a new rootfs under %s.\n"
"This can be used later by the '-d' parameter of 'kvm run'.\n",
kvm__get_dir());
usage_with_options(setup_usage, setup_options);
}
static int copy_file(const char *from, const char *to)
{
int in_fd, out_fd;
void *src, *dst;
struct stat st;
int err = -1;
in_fd = open(from, O_RDONLY);
if (in_fd < 0)
return err;
if (fstat(in_fd, &st) < 0)
goto error_close_in;
out_fd = open(to, O_RDWR | O_CREAT | O_TRUNC, st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO));
if (out_fd < 0)
goto error_close_in;
src = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, in_fd, 0);
if (src == MAP_FAILED)
goto error_close_out;
if (ftruncate(out_fd, st.st_size) < 0)
goto error_munmap_src;
dst = mmap(NULL, st.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, out_fd, 0);
if (dst == MAP_FAILED)
goto error_munmap_src;
memcpy(dst, src, st.st_size);
if (fsync(out_fd) < 0)
goto error_munmap_dst;
err = 0;
error_munmap_dst:
munmap(dst, st.st_size);
error_munmap_src:
munmap(src, st.st_size);
error_close_out:
close(out_fd);
error_close_in:
close(in_fd);
return err;
}
static const char *guestfs_dirs[] = {
"/dev",
"/etc",
"/home",
"/host",
"/proc",
"/root",
"/sys",
"/tmp",
"/var",
"/var/lib",
"/virt",
};
static const char *guestfs_symlinks[] = {
"/bin",
"/lib",
"/lib64",
"/sbin",
"/usr",
"/etc/ld.so.conf",
};
static int copy_init(const char *guestfs_name)
{
char path[PATH_MAX];
snprintf(path, PATH_MAX, "%s%s/virt/init", kvm__get_dir(), guestfs_name);
return copy_file("guest/init", path);
}
static int copy_passwd(const char *guestfs_name)
{
char path[PATH_MAX];
snprintf(path, PATH_MAX, "%s%s/etc/passwd", kvm__get_dir(), guestfs_name);
return copy_file("guest/passwd", path);
}
static int make_guestfs_symlink(const char *guestfs_name, const char *path)
{
char target[PATH_MAX];
char name[PATH_MAX];
snprintf(name, PATH_MAX, "%s%s%s", kvm__get_dir(), guestfs_name, path);
snprintf(target, PATH_MAX, "/host%s", path);
return symlink(target, name);
}
static void make_root_dir(void)
{
char name[PATH_MAX];
snprintf(name, PATH_MAX, "%s", kvm__get_dir());
mkdir(name, 0777);
}
static int make_dir(const char *dir)
{
char name[PATH_MAX];
snprintf(name, PATH_MAX, "%s%s", kvm__get_dir(), dir);
return mkdir(name, 0777);
}
static void make_guestfs_dir(const char *guestfs_name, const char *dir)
{
char name[PATH_MAX];
snprintf(name, PATH_MAX, "%s%s", guestfs_name, dir);
make_dir(name);
}
void kvm_setup_resolv(const char *guestfs_name)
{
char path[PATH_MAX];
snprintf(path, PATH_MAX, "%s%s/etc/resolv.conf", kvm__get_dir(), guestfs_name);
copy_file("/etc/resolv.conf", path);
}
static int do_setup(const char *guestfs_name)
{
unsigned int i;
int ret;
make_root_dir();
ret = make_dir(guestfs_name);
if (ret < 0)
return ret;
for (i = 0; i < ARRAY_SIZE(guestfs_dirs); i++)
make_guestfs_dir(guestfs_name, guestfs_dirs[i]);
for (i = 0; i < ARRAY_SIZE(guestfs_symlinks); i++) {
make_guestfs_symlink(guestfs_name, guestfs_symlinks[i]);
}
ret = copy_init(guestfs_name);
if (ret < 0)
return ret;
return copy_passwd(guestfs_name);
}
int kvm_setup_create_new(const char *guestfs_name)
{
return do_setup(guestfs_name);
}
int kvm_cmd_setup(int argc, const char **argv, const char *prefix)
{
int r;
parse_setup_options(argc, argv);
if (instance_name == NULL)
kvm_setup_help();
r = do_setup(instance_name);
if (r == 0)
printf("A new rootfs '%s' has been created in '%s%s'.\n\n"
"You can now start it by running the following command:\n\n"
" kvm run -d %s\n",
instance_name, kvm__get_dir(), instance_name, instance_name);
else
printf("Unable to create rootfs in %s%s: %s\n",
kvm__get_dir(), instance_name, strerror(errno));
return r;
}