]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/storage/rsync.c
tree-wide: struct bdev -> struct lxc_storage
[mirror_lxc.git] / src / lxc / storage / rsync.c
CommitLineData
e9df7e1a
CB
1/*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Daniel Lezcano <daniel.lezcano at free.fr>
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#define _GNU_SOURCE
25#include <grp.h>
26#include <sched.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <stdint.h>
30#include <string.h>
31#include <unistd.h>
32#include <sys/types.h>
33#include <sys/mount.h>
34
e9df7e1a 35#include "log.h"
28d832c4
CB
36#include "rsync.h"
37#include "storage.h"
e9df7e1a
CB
38#include "utils.h"
39
10bc1861 40lxc_log_define(rsync, lxc);
e9df7e1a
CB
41
42/* the bulk of this needs to become a common helper */
43int do_rsync(const char *src, const char *dest)
44{
45 // call out to rsync
46 pid_t pid;
47 char *s;
48 size_t l;
49
50 pid = fork();
51 if (pid < 0)
52 return -1;
53 if (pid > 0)
54 return wait_for_pid(pid);
55
56 l = strlen(src) + 2;
57 s = malloc(l);
58 if (!s)
59 exit(1);
60 strcpy(s, src);
61 s[l-2] = '/';
62 s[l-1] = '\0';
63
4f142fad 64 execlp("rsync", "rsync", "-aHXS", "--delete", s, dest, (char *)NULL);
e9df7e1a
CB
65 exit(1);
66}
67
68int rsync_delta(struct rsync_data_char *data)
69{
70 if (setgid(0) < 0) {
71 ERROR("Failed to setgid to 0");
72 return -1;
73 }
74 if (setgroups(0, NULL) < 0)
75 WARN("Failed to clear groups");
76 if (setuid(0) < 0) {
77 ERROR("Failed to setuid to 0");
78 return -1;
79 }
80 if (do_rsync(data->src, data->dest) < 0) {
81 ERROR("rsyncing %s to %s", data->src, data->dest);
82 return -1;
83 }
84
85 return 0;
86}
87
88int rsync_delta_wrapper(void *data)
89{
90 struct rsync_data_char *arg = data;
91 return rsync_delta(arg);
92}
93
94int rsync_rootfs(struct rsync_data *data)
95{
10bc1861 96 struct lxc_storage *orig = data->orig, *new = data->new;
e9df7e1a
CB
97
98 if (unshare(CLONE_NEWNS) < 0) {
99 SYSERROR("unshare CLONE_NEWNS");
100 return -1;
101 }
102 if (detect_shared_rootfs()) {
103 if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) {
104 SYSERROR("Failed to make / rslave");
105 ERROR("Continuing...");
106 }
107 }
108
109 // If not a snapshot, copy the fs.
110 if (orig->ops->mount(orig) < 0) {
111 ERROR("failed mounting %s onto %s", orig->src, orig->dest);
112 return -1;
113 }
114 if (new->ops->mount(new) < 0) {
115 ERROR("failed mounting %s onto %s", new->src, new->dest);
116 return -1;
117 }
118 if (setgid(0) < 0) {
119 ERROR("Failed to setgid to 0");
120 return -1;
121 }
122 if (setgroups(0, NULL) < 0)
123 WARN("Failed to clear groups");
124 if (setuid(0) < 0) {
125 ERROR("Failed to setuid to 0");
126 return -1;
127 }
128 if (do_rsync(orig->dest, new->dest) < 0) {
129 ERROR("rsyncing %s to %s", orig->src, new->src);
130 return -1;
131 }
132
133 return 0;
134}
135
136int rsync_rootfs_wrapper(void *data)
137{
138 struct rsync_data *arg = data;
139 return rsync_rootfs(arg);
140}
301faec2
CB
141
142/* new helpers */
143int lxc_rsync_exec_wrapper(void *data)
144{
145 struct rsync_data *arg = data;
146 return lxc_rsync(arg);
147}
148
149int lxc_rsync_exec(const char *src, const char *dest)
150{
151 int ret;
152 size_t l;
153 char *s;
154
155 l = strlen(src) + 2;
156 s = malloc(l);
157 if (!s)
158 return -1;
159
160 ret = snprintf(s, l, "%s", src);
161 if (ret < 0 || (size_t)ret >= l)
162 return -1;
163
164 s[l - 2] = '/';
165 s[l - 1] = '\0';
166
167 execlp("rsync", "rsync", "-aHXS", "--delete", s, dest, (char *)NULL);
168 return -1;
169}
170
171int lxc_rsync(struct rsync_data *data)
172{
173 int ret;
10bc1861 174 struct lxc_storage *orig = data->orig, *new = data->new;
301faec2
CB
175 char *dest, *src;
176
177 ret = unshare(CLONE_NEWNS);
178 if (ret < 0) {
179 SYSERROR("Failed to unshare CLONE_NEWNS");
180 return -1;
181 }
182
183 ret = detect_shared_rootfs();
184 if (ret) {
185 ret = mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL);
186 if (ret < 0)
187 SYSERROR("Failed to make \"/\" a slave mount");
188 }
189
190 ret = orig->ops->mount(orig);
191 if (ret < 0) {
192 ERROR("Failed mounting \"%s\" on \"%s\"", orig->src, orig->dest);
193 return -1;
194 }
195
196 ret = new->ops->mount(new);
197 if (ret < 0) {
198 ERROR("Failed mounting \"%s\" onto \"%s\"", new->src, new->dest);
199 return -1;
200 }
201
202 ret = lxc_switch_uid_gid(0, 0);
203 if (ret < 0)
204 return -1;
205 ret = lxc_setgroups(0, NULL);
206 if (ret < 0)
207 return -1;
208
209 src = lxc_storage_get_path(orig->dest, orig->type);
210 dest = lxc_storage_get_path(new->dest, new->type);
211
212 ret = lxc_rsync_exec(src, dest);
213 if (ret < 0) {
214 ERROR("Failed to rsync from \"%s\" into \"%s\"", src, dest);
215 return -1;
216 }
217
218 return 0;
219}