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