Merge branch 'akpm'
[linux-2.6/next.git] / tools / kvm / builtin-setup.c
blob75874760eb034b83afee6dc4a98a8256fab21879
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>
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>
22 #define KVM_PID_FILE_PATH "/.kvm-tools/"
23 #define HOME_DIR getenv("HOME")
25 static const char *instance_name;
27 static const char * const setup_usage[] = {
28 "kvm setup [-n name]",
29 NULL
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()
38 static void parse_setup_options(int argc, const char **argv)
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();
48 void kvm_setup_help(void)
50 usage_with_options(setup_usage, setup_options);
53 static int copy_file(const char *from, const char *to)
55 int in_fd, out_fd;
56 void *src, *dst;
57 struct stat st;
58 int err = -1;
60 in_fd = open(from, O_RDONLY);
61 if (in_fd < 0)
62 return err;
64 if (fstat(in_fd, &st) < 0)
65 goto error_close_in;
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;
71 src = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, in_fd, 0);
72 if (src == MAP_FAILED)
73 goto error_close_out;
75 if (ftruncate(out_fd, st.st_size) < 0)
76 goto error_munmap_src;
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;
82 memcpy(dst, src, st.st_size);
84 if (fsync(out_fd) < 0)
85 goto error_munmap_dst;
87 err = 0;
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);
98 return err;
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",
115 static const char *guestfs_symlinks[] = {
116 "/bin",
117 "/lib",
118 "/lib64",
119 "/sbin",
120 "/usr",
123 static int copy_init(const char *guestfs_name)
125 char path[PATH_MAX];
127 snprintf(path, PATH_MAX, "%s%s%s/virt/init", HOME_DIR, KVM_PID_FILE_PATH, guestfs_name);
129 return copy_file("guest/init", path);
132 static int make_guestfs_symlink(const char *guestfs_name, const char *path)
134 char target[PATH_MAX];
135 char name[PATH_MAX];
137 snprintf(name, PATH_MAX, "%s%s%s%s", HOME_DIR, KVM_PID_FILE_PATH, guestfs_name, path);
139 snprintf(target, PATH_MAX, "/host%s", path);
141 return symlink(target, name);
144 static void make_root_dir(void)
146 char name[PATH_MAX];
148 snprintf(name, PATH_MAX, "%s%s", HOME_DIR, KVM_PID_FILE_PATH);
150 mkdir(name, 0777);
153 static void make_dir(const char *dir)
155 char name[PATH_MAX];
157 snprintf(name, PATH_MAX, "%s%s%s", HOME_DIR, KVM_PID_FILE_PATH, dir);
159 mkdir(name, 0777);
162 static void make_guestfs_dir(const char *guestfs_name, const char *dir)
164 char name[PATH_MAX];
166 snprintf(name, PATH_MAX, "%s%s", guestfs_name, dir);
168 make_dir(name);
171 static int do_setup(const char *guestfs_name)
173 unsigned int i;
175 make_root_dir();
177 make_dir(guestfs_name);
179 for (i = 0; i < ARRAY_SIZE(guestfs_dirs); i++)
180 make_guestfs_dir(guestfs_name, guestfs_dirs[i]);
182 for (i = 0; i < ARRAY_SIZE(guestfs_symlinks); i++) {
183 make_guestfs_symlink(guestfs_name, guestfs_symlinks[i]);
186 return copy_init(guestfs_name);
189 int kvm_cmd_setup(int argc, const char **argv, const char *prefix)
191 parse_setup_options(argc, argv);
193 if (instance_name == NULL)
194 kvm_setup_help();
196 return do_setup(instance_name);