]>
Commit | Line | Data |
---|---|---|
e3642c43 DL |
1 | /* |
2 | * lxc: linux Container library | |
3 | * | |
4 | * (C) Copyright IBM Corp. 2007, 2008 | |
5 | * | |
6 | * Authors: | |
7 | * Daniel Lezcano <dlezcano at fr.ibm.com> | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
22 | */ | |
23 | ||
d983b93c | 24 | #define _GNU_SOURCE |
e3642c43 DL |
25 | #include <errno.h> |
26 | #include <unistd.h> | |
d983b93c MN |
27 | #include <stdlib.h> |
28 | #include <stddef.h> | |
e3642c43 DL |
29 | #include <sys/types.h> |
30 | #include <sys/stat.h> | |
31 | #include <sys/mman.h> | |
d983b93c | 32 | #include <sys/param.h> |
6e4bb2e0 | 33 | #include <sys/mount.h> |
d983b93c MN |
34 | #include <dirent.h> |
35 | #include <fcntl.h> | |
1b09f2c0 | 36 | #include <libgen.h> |
e3642c43 DL |
37 | |
38 | #include "log.h" | |
39 | ||
40 | lxc_log_define(lxc_utils, lxc); | |
41 | ||
42 | int lxc_copy_file(const char *srcfile, const char *dstfile) | |
43 | { | |
44 | void *srcaddr = NULL, *dstaddr; | |
45 | struct stat stat; | |
46 | int srcfd, dstfd, ret = -1; | |
47 | char c = '\0'; | |
48 | ||
49 | dstfd = open(dstfile, O_CREAT | O_EXCL | O_RDWR, 0600); | |
50 | if (dstfd < 0) { | |
51 | SYSERROR("failed to creat '%s'", dstfile); | |
52 | goto out; | |
53 | } | |
54 | ||
55 | srcfd = open(srcfile, O_RDONLY); | |
56 | if (srcfd < 0) { | |
57 | SYSERROR("failed to open '%s'", srcfile); | |
58 | goto err; | |
59 | } | |
60 | ||
61 | if (fstat(srcfd, &stat)) { | |
62 | SYSERROR("failed to stat '%s'", srcfile); | |
63 | goto err; | |
64 | } | |
65 | ||
66 | if (!stat.st_size) { | |
67 | INFO("copy '%s' which is an empty file", srcfile); | |
68 | ret = 0; | |
69 | goto out_close; | |
70 | } | |
71 | ||
72 | if (lseek(dstfd, stat.st_size - 1, SEEK_SET) < 0) { | |
73 | SYSERROR("failed to seek dest file '%s'", dstfile); | |
74 | goto err; | |
75 | } | |
76 | ||
77 | /* fixup length */ | |
78 | if (write(dstfd, &c, 1) < 0) { | |
79 | SYSERROR("failed to write to '%s'", dstfile); | |
80 | goto err; | |
81 | } | |
82 | ||
83 | srcaddr = mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, srcfd, 0L); | |
84 | if (srcaddr == MAP_FAILED) { | |
85 | SYSERROR("failed to mmap '%s'", srcfile); | |
86 | goto err; | |
87 | } | |
88 | ||
89 | dstaddr = mmap(NULL, stat.st_size, PROT_WRITE, MAP_SHARED, dstfd, 0L); | |
90 | if (dstaddr == MAP_FAILED) { | |
91 | SYSERROR("failed to mmap '%s'", dstfile); | |
92 | goto err; | |
93 | } | |
94 | ||
95 | ret = 0; | |
96 | ||
97 | memcpy(dstaddr, srcaddr, stat.st_size); | |
98 | ||
99 | munmap(dstaddr, stat.st_size); | |
100 | out_mmap: | |
101 | if (srcaddr) | |
102 | munmap(srcaddr, stat.st_size); | |
103 | out_close: | |
104 | close(dstfd); | |
105 | close(srcfd); | |
106 | out: | |
107 | return ret; | |
108 | err: | |
109 | unlink(dstfile); | |
110 | goto out_mmap; | |
111 | } | |
d983b93c | 112 | |
6e4bb2e0 MN |
113 | static int mount_fs(const char *source, const char *target, const char *type) |
114 | { | |
115 | /* the umount may fail */ | |
116 | if (umount(target)) | |
117 | WARN("failed to unmount %s : %s", target, strerror(errno)); | |
118 | ||
119 | if (mount(source, target, type, 0, NULL)) { | |
120 | ERROR("failed to mount %s : %s", target, strerror(errno)); | |
121 | return -1; | |
122 | } | |
123 | ||
124 | DEBUG("'%s' mounted on '%s'", source, target); | |
125 | ||
126 | return 0; | |
127 | } | |
128 | ||
129 | extern int lxc_setup_fs(void) | |
130 | { | |
131 | if (mount_fs("proc", "/proc", "proc")) | |
132 | return -1; | |
133 | ||
721d262c | 134 | /* if we can't mount /dev/shm, continue anyway */ |
6e4bb2e0 | 135 | if (mount_fs("shmfs", "/dev/shm", "tmpfs")) |
3283db09 | 136 | INFO("failed to mount /dev/shm"); |
6e4bb2e0 MN |
137 | |
138 | /* If we were able to mount /dev/shm, then /dev exists */ | |
b91b1cd7 | 139 | /* Sure, but it's read-only per config :) */ |
6e4bb2e0 | 140 | if (access("/dev/mqueue", F_OK) && mkdir("/dev/mqueue", 0666)) { |
b91b1cd7 SH |
141 | DEBUG("failed to create '/dev/mqueue'"); |
142 | return 0; | |
6e4bb2e0 MN |
143 | } |
144 | ||
145 | if (mount_fs("mqueue", "/dev/mqueue", "mqueue")) | |
146 | return -1; | |
147 | ||
148 | return 0; | |
149 | } | |
9ddaf3bf JHS |
150 | |
151 | /* borrowed from iproute2 */ | |
7c11d57a | 152 | extern int get_u16(unsigned short *val, const char *arg, int base) |
9ddaf3bf JHS |
153 | { |
154 | unsigned long res; | |
155 | char *ptr; | |
156 | ||
157 | if (!arg || !*arg) | |
158 | return -1; | |
159 | ||
160 | res = strtoul(arg, &ptr, base); | |
161 | if (!ptr || ptr == arg || *ptr || res > 0xFFFF) | |
162 | return -1; | |
163 | ||
164 | *val = res; | |
165 | ||
166 | return 0; | |
167 | } | |
168 | ||
1b09f2c0 DL |
169 | extern int mkdir_p(char *dir, mode_t mode) |
170 | { | |
171 | int ret; | |
172 | char *d; | |
173 | ||
174 | if (!strcmp(dir, "/")) | |
175 | return 0; | |
176 | ||
177 | d = strdup(dir); | |
178 | if (!d) | |
179 | return -1; | |
180 | ||
181 | ret = mkdir_p(dirname(d), mode); | |
182 | free(d); | |
183 | if (ret) | |
184 | return -1; | |
185 | ||
186 | if (!access(dir, F_OK)) | |
187 | return 0; | |
188 | ||
189 | if (mkdir(dir, mode)) { | |
190 | SYSERROR("failed to create directory '%s'\n", dir); | |
191 | return -1; | |
192 | } | |
193 | ||
194 | return 0; | |
195 | } | |
2a59a681 SH |
196 | |
197 | static char *copypath(char *p) | |
198 | { | |
199 | int len = strlen(p); | |
200 | char *retbuf; | |
201 | ||
202 | if (len < 1) | |
203 | return NULL; | |
204 | if (p[len-1] == '\n') { | |
205 | p[len-1] = '\0'; | |
206 | len--; | |
207 | } | |
208 | retbuf = malloc(len+1); | |
209 | if (!retbuf) | |
210 | return NULL; | |
211 | strcpy(retbuf, p); | |
212 | return retbuf; | |
213 | } | |
214 | ||
67e571de SG |
215 | char *default_lxcpath; |
216 | ||
217 | const char *default_lxc_path(void) | |
2a59a681 | 218 | { |
67e571de | 219 | char buf[1024], *p; |
2a59a681 SH |
220 | FILE *fin; |
221 | ||
67e571de SG |
222 | if (default_lxcpath) |
223 | return default_lxcpath; | |
224 | ||
2a59a681 SH |
225 | fin = fopen(LXC_GLOBAL_CONF, "r"); |
226 | if (fin) { | |
227 | while (fgets(buf, 1024, fin)) { | |
228 | if (buf[0] == '#') | |
229 | continue; | |
230 | p = strstr(buf, "lxcpath"); | |
231 | if (!p) | |
232 | continue; | |
233 | p = strchr(p, '='); | |
234 | if (!p) | |
235 | continue; | |
236 | p++; | |
237 | while (*p && (*p == ' ' || *p == '\t')) p++; | |
238 | if (!*p) | |
239 | continue; | |
67e571de | 240 | default_lxcpath = copypath(p); |
2a59a681 SH |
241 | goto out; |
242 | } | |
243 | } | |
244 | /* we couldn't open the file, or didn't find a lxcpath | |
245 | * entry there. Return @LXCPATH@ */ | |
67e571de | 246 | default_lxcpath = LXCPATH; |
2a59a681 SH |
247 | |
248 | out: | |
249 | if (fin) | |
250 | fclose(fin); | |
67e571de | 251 | return default_lxcpath; |
2a59a681 | 252 | } |