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 static const char *instance_name; 23 24 static const char * const setup_usage[] = { 25 "kvm setup [name]", 26 NULL 27 }; 28 29 static const struct option setup_options[] = { 30 OPT_END() 31 }; 32 33 static void parse_setup_options(int argc, const char **argv) 34 { 35 while (argc != 0) { 36 argc = parse_options(argc, argv, setup_options, setup_usage, 37 PARSE_OPT_STOP_AT_NON_OPTION); 38 if (argc != 0 && instance_name) 39 kvm_setup_help(); 40 else 41 instance_name = argv[0]; 42 argv++; 43 argc--; 44 } 45 } 46 47 void kvm_setup_help(void) 48 { 49 printf("\nkvm setup creates a new rootfs and stores it under ~/.kvm-tools/ .\n" 50 "This can be used later by the '-d' parameter of 'kvm run'.\n"); 51 usage_with_options(setup_usage, setup_options); 52 } 53 54 static int copy_file(const char *from, const char *to) 55 { 56 int in_fd, out_fd; 57 void *src, *dst; 58 struct stat st; 59 int err = -1; 60 61 in_fd = open(from, O_RDONLY); 62 if (in_fd < 0) 63 return err; 64 65 if (fstat(in_fd, &st) < 0) 66 goto error_close_in; 67 68 out_fd = open(to, O_RDWR | O_CREAT | O_TRUNC, st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)); 69 if (out_fd < 0) 70 goto error_close_in; 71 72 src = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, in_fd, 0); 73 if (src == MAP_FAILED) 74 goto error_close_out; 75 76 if (ftruncate(out_fd, st.st_size) < 0) 77 goto error_munmap_src; 78 79 dst = mmap(NULL, st.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, out_fd, 0); 80 if (dst == MAP_FAILED) 81 goto error_munmap_src; 82 83 memcpy(dst, src, st.st_size); 84 85 if (fsync(out_fd) < 0) 86 goto error_munmap_dst; 87 88 err = 0; 89 90 error_munmap_dst: 91 munmap(dst, st.st_size); 92 error_munmap_src: 93 munmap(src, st.st_size); 94 error_close_out: 95 close(out_fd); 96 error_close_in: 97 close(in_fd); 98 99 return err; 100 } 101 102 static const char *guestfs_dirs[] = { 103 "/dev", 104 "/etc", 105 "/home", 106 "/host", 107 "/proc", 108 "/root", 109 "/sys", 110 "/tmp", 111 "/var", 112 "/var/lib", 113 "/virt", 114 }; 115 116 static const char *guestfs_symlinks[] = { 117 "/bin", 118 "/lib", 119 "/lib64", 120 "/sbin", 121 "/usr", 122 }; 123 124 static int copy_init(const char *guestfs_name) 125 { 126 char path[PATH_MAX]; 127 128 snprintf(path, PATH_MAX, "%s%s/virt/init", kvm__get_dir(), guestfs_name); 129 130 return copy_file("guest/init", path); 131 } 132 133 static int make_guestfs_symlink(const char *guestfs_name, const char *path) 134 { 135 char target[PATH_MAX]; 136 char name[PATH_MAX]; 137 138 snprintf(name, PATH_MAX, "%s%s%s", kvm__get_dir(), guestfs_name, path); 139 140 snprintf(target, PATH_MAX, "/host%s", path); 141 142 return symlink(target, name); 143 } 144 145 static void make_root_dir(void) 146 { 147 char name[PATH_MAX]; 148 149 snprintf(name, PATH_MAX, "%s", kvm__get_dir()); 150 151 mkdir(name, 0777); 152 } 153 154 static int make_dir(const char *dir) 155 { 156 char name[PATH_MAX]; 157 158 snprintf(name, PATH_MAX, "%s%s", kvm__get_dir(), dir); 159 160 return mkdir(name, 0777); 161 } 162 163 static void make_guestfs_dir(const char *guestfs_name, const char *dir) 164 { 165 char name[PATH_MAX]; 166 167 snprintf(name, PATH_MAX, "%s%s", guestfs_name, dir); 168 169 make_dir(name); 170 } 171 172 void kvm_setup_resolv(const char *guestfs_name) 173 { 174 char path[PATH_MAX]; 175 176 snprintf(path, PATH_MAX, "%s%s/etc/resolv.conf", kvm__get_dir(), guestfs_name); 177 178 copy_file("/etc/resolv.conf", path); 179 } 180 181 static int do_setup(const char *guestfs_name) 182 { 183 unsigned int i; 184 int ret; 185 186 make_root_dir(); 187 188 ret = make_dir(guestfs_name); 189 if (ret < 0) 190 return ret; 191 192 for (i = 0; i < ARRAY_SIZE(guestfs_dirs); i++) 193 make_guestfs_dir(guestfs_name, guestfs_dirs[i]); 194 195 for (i = 0; i < ARRAY_SIZE(guestfs_symlinks); i++) { 196 make_guestfs_symlink(guestfs_name, guestfs_symlinks[i]); 197 } 198 199 return copy_init(guestfs_name); 200 } 201 202 int kvm_setup_create_new(const char *guestfs_name) 203 { 204 return do_setup(guestfs_name); 205 } 206 207 int kvm_cmd_setup(int argc, const char **argv, const char *prefix) 208 { 209 int r; 210 211 parse_setup_options(argc, argv); 212 213 if (instance_name == NULL) 214 kvm_setup_help(); 215 216 r = do_setup(instance_name); 217 if (r == 0) 218 pr_info("Your new rootfs named %s has been created.\n" 219 "You can now start it by running 'kvm run -d %s'\n", 220 instance_name, instance_name); 221 else 222 perror("Error creating rootfs"); 223 224 return r; 225 } 226