1*282113fdSPekka Enberg #include <kvm/util.h> 2*282113fdSPekka Enberg #include <kvm/kvm-cmd.h> 3*282113fdSPekka Enberg #include <kvm/builtin-setup.h> 4*282113fdSPekka Enberg #include <kvm/kvm.h> 5*282113fdSPekka Enberg #include <kvm/parse-options.h> 6*282113fdSPekka Enberg 7*282113fdSPekka Enberg #include <sys/types.h> 8*282113fdSPekka Enberg #include <sys/stat.h> 9*282113fdSPekka Enberg #include <limits.h> 10*282113fdSPekka Enberg #include <signal.h> 11*282113fdSPekka Enberg #include <stdlib.h> 12*282113fdSPekka Enberg #include <string.h> 13*282113fdSPekka Enberg #include <unistd.h> 14*282113fdSPekka Enberg #include <stdio.h> 15*282113fdSPekka Enberg #include <sys/types.h> 16*282113fdSPekka Enberg #include <sys/mman.h> 17*282113fdSPekka Enberg #include <sys/stat.h> 18*282113fdSPekka Enberg #include <string.h> 19*282113fdSPekka Enberg #include <unistd.h> 20*282113fdSPekka Enberg #include <fcntl.h> 21*282113fdSPekka Enberg 22*282113fdSPekka Enberg #define KVM_PID_FILE_PATH "/.kvm-tools/" 23*282113fdSPekka Enberg #define HOME_DIR getenv("HOME") 24*282113fdSPekka Enberg 25*282113fdSPekka Enberg static const char *instance_name; 26*282113fdSPekka Enberg 27*282113fdSPekka Enberg static const char * const setup_usage[] = { 28*282113fdSPekka Enberg "kvm setup [-n name]", 29*282113fdSPekka Enberg NULL 30*282113fdSPekka Enberg }; 31*282113fdSPekka Enberg 32*282113fdSPekka Enberg static const struct option setup_options[] = { 33*282113fdSPekka Enberg OPT_GROUP("General options:"), 34*282113fdSPekka Enberg OPT_STRING('n', "name", &instance_name, "name", "Instance name"), 35*282113fdSPekka Enberg OPT_END() 36*282113fdSPekka Enberg }; 37*282113fdSPekka Enberg 38*282113fdSPekka Enberg static void parse_setup_options(int argc, const char **argv) 39*282113fdSPekka Enberg { 40*282113fdSPekka Enberg while (argc != 0) { 41*282113fdSPekka Enberg argc = parse_options(argc, argv, setup_options, setup_usage, 42*282113fdSPekka Enberg PARSE_OPT_STOP_AT_NON_OPTION); 43*282113fdSPekka Enberg if (argc != 0) 44*282113fdSPekka Enberg kvm_setup_help(); 45*282113fdSPekka Enberg } 46*282113fdSPekka Enberg } 47*282113fdSPekka Enberg 48*282113fdSPekka Enberg void kvm_setup_help(void) 49*282113fdSPekka Enberg { 50*282113fdSPekka Enberg usage_with_options(setup_usage, setup_options); 51*282113fdSPekka Enberg } 52*282113fdSPekka Enberg 53*282113fdSPekka Enberg static int copy_file(const char *from, const char *to) 54*282113fdSPekka Enberg { 55*282113fdSPekka Enberg int in_fd, out_fd; 56*282113fdSPekka Enberg void *src, *dst; 57*282113fdSPekka Enberg struct stat st; 58*282113fdSPekka Enberg int err = -1; 59*282113fdSPekka Enberg 60*282113fdSPekka Enberg in_fd = open(from, O_RDONLY); 61*282113fdSPekka Enberg if (in_fd < 0) 62*282113fdSPekka Enberg return err; 63*282113fdSPekka Enberg 64*282113fdSPekka Enberg if (fstat(in_fd, &st) < 0) 65*282113fdSPekka Enberg goto error_close_in; 66*282113fdSPekka Enberg 67*282113fdSPekka Enberg out_fd = open(to, O_RDWR | O_CREAT | O_TRUNC, st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)); 68*282113fdSPekka Enberg if (out_fd < 0) 69*282113fdSPekka Enberg goto error_close_in; 70*282113fdSPekka Enberg 71*282113fdSPekka Enberg src = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, in_fd, 0); 72*282113fdSPekka Enberg if (src == MAP_FAILED) 73*282113fdSPekka Enberg goto error_close_out; 74*282113fdSPekka Enberg 75*282113fdSPekka Enberg if (ftruncate(out_fd, st.st_size) < 0) 76*282113fdSPekka Enberg goto error_munmap_src; 77*282113fdSPekka Enberg 78*282113fdSPekka Enberg dst = mmap(NULL, st.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, out_fd, 0); 79*282113fdSPekka Enberg if (dst == MAP_FAILED) 80*282113fdSPekka Enberg goto error_munmap_src; 81*282113fdSPekka Enberg 82*282113fdSPekka Enberg memcpy(dst, src, st.st_size); 83*282113fdSPekka Enberg 84*282113fdSPekka Enberg if (fsync(out_fd) < 0) 85*282113fdSPekka Enberg goto error_munmap_dst; 86*282113fdSPekka Enberg 87*282113fdSPekka Enberg err = 0; 88*282113fdSPekka Enberg 89*282113fdSPekka Enberg error_munmap_dst: 90*282113fdSPekka Enberg munmap(dst, st.st_size); 91*282113fdSPekka Enberg error_munmap_src: 92*282113fdSPekka Enberg munmap(src, st.st_size); 93*282113fdSPekka Enberg error_close_out: 94*282113fdSPekka Enberg close(out_fd); 95*282113fdSPekka Enberg error_close_in: 96*282113fdSPekka Enberg close(in_fd); 97*282113fdSPekka Enberg 98*282113fdSPekka Enberg return err; 99*282113fdSPekka Enberg } 100*282113fdSPekka Enberg 101*282113fdSPekka Enberg static const char *guestfs_dirs[] = { 102*282113fdSPekka Enberg "/dev", 103*282113fdSPekka Enberg "/etc", 104*282113fdSPekka Enberg "/home", 105*282113fdSPekka Enberg "/host", 106*282113fdSPekka Enberg "/proc", 107*282113fdSPekka Enberg "/root", 108*282113fdSPekka Enberg "/sys", 109*282113fdSPekka Enberg "/var", 110*282113fdSPekka Enberg "/var/lib", 111*282113fdSPekka Enberg "/virt", 112*282113fdSPekka Enberg }; 113*282113fdSPekka Enberg 114*282113fdSPekka Enberg static const char *guestfs_symlinks[] = { 115*282113fdSPekka Enberg "/bin", 116*282113fdSPekka Enberg "/lib", 117*282113fdSPekka Enberg "/lib64", 118*282113fdSPekka Enberg "/sbin", 119*282113fdSPekka Enberg "/usr", 120*282113fdSPekka Enberg }; 121*282113fdSPekka Enberg 122*282113fdSPekka Enberg static int copy_init(const char *guestfs_name) 123*282113fdSPekka Enberg { 124*282113fdSPekka Enberg char path[PATH_MAX]; 125*282113fdSPekka Enberg 126*282113fdSPekka Enberg snprintf(path, PATH_MAX, "%s%s%s/virt/init", HOME_DIR, KVM_PID_FILE_PATH, guestfs_name); 127*282113fdSPekka Enberg 128*282113fdSPekka Enberg return copy_file("guest/init", path); 129*282113fdSPekka Enberg } 130*282113fdSPekka Enberg 131*282113fdSPekka Enberg static int make_guestfs_symlink(const char *guestfs_name, const char *path) 132*282113fdSPekka Enberg { 133*282113fdSPekka Enberg char target[PATH_MAX]; 134*282113fdSPekka Enberg char name[PATH_MAX]; 135*282113fdSPekka Enberg 136*282113fdSPekka Enberg snprintf(name, PATH_MAX, "%s%s%s%s", HOME_DIR, KVM_PID_FILE_PATH, guestfs_name, path); 137*282113fdSPekka Enberg 138*282113fdSPekka Enberg snprintf(target, PATH_MAX, "/host%s", path); 139*282113fdSPekka Enberg 140*282113fdSPekka Enberg return symlink(target, name); 141*282113fdSPekka Enberg } 142*282113fdSPekka Enberg 143*282113fdSPekka Enberg static void make_dir(const char *dir) 144*282113fdSPekka Enberg { 145*282113fdSPekka Enberg char name[PATH_MAX]; 146*282113fdSPekka Enberg 147*282113fdSPekka Enberg snprintf(name, PATH_MAX, "%s%s%s", HOME_DIR, KVM_PID_FILE_PATH, dir); 148*282113fdSPekka Enberg 149*282113fdSPekka Enberg mkdir(name, 0777); 150*282113fdSPekka Enberg } 151*282113fdSPekka Enberg 152*282113fdSPekka Enberg static void make_guestfs_dir(const char *guestfs_name, const char *dir) 153*282113fdSPekka Enberg { 154*282113fdSPekka Enberg char name[PATH_MAX]; 155*282113fdSPekka Enberg 156*282113fdSPekka Enberg snprintf(name, PATH_MAX, "%s%s", guestfs_name, dir); 157*282113fdSPekka Enberg 158*282113fdSPekka Enberg make_dir(name); 159*282113fdSPekka Enberg } 160*282113fdSPekka Enberg 161*282113fdSPekka Enberg static int do_setup(const char *guestfs_name) 162*282113fdSPekka Enberg { 163*282113fdSPekka Enberg unsigned int i; 164*282113fdSPekka Enberg 165*282113fdSPekka Enberg make_dir(guestfs_name); 166*282113fdSPekka Enberg 167*282113fdSPekka Enberg for (i = 0; i < ARRAY_SIZE(guestfs_dirs); i++) 168*282113fdSPekka Enberg make_guestfs_dir(guestfs_name, guestfs_dirs[i]); 169*282113fdSPekka Enberg 170*282113fdSPekka Enberg for (i = 0; i < ARRAY_SIZE(guestfs_symlinks); i++) { 171*282113fdSPekka Enberg make_guestfs_symlink(guestfs_name, guestfs_symlinks[i]); 172*282113fdSPekka Enberg } 173*282113fdSPekka Enberg 174*282113fdSPekka Enberg return copy_init(guestfs_name); 175*282113fdSPekka Enberg } 176*282113fdSPekka Enberg 177*282113fdSPekka Enberg int kvm_cmd_setup(int argc, const char **argv, const char *prefix) 178*282113fdSPekka Enberg { 179*282113fdSPekka Enberg parse_setup_options(argc, argv); 180*282113fdSPekka Enberg 181*282113fdSPekka Enberg if (instance_name == NULL) 182*282113fdSPekka Enberg kvm_setup_help(); 183*282113fdSPekka Enberg 184*282113fdSPekka Enberg return do_setup(instance_name); 185*282113fdSPekka Enberg } 186