2 * Copyright (C) 2012 Alexander Block. All rights reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 021110-1307, USA.
19 #include <uuid/uuid.h>
23 #include "send-stream.h"
27 struct btrfs_send_stream {
29 char read_buf[BTRFS_SEND_BUF_SIZE];
32 struct btrfs_cmd_header *cmd_hdr;
33 struct btrfs_tlv_header *cmd_attrs[BTRFS_SEND_A_MAX + 1];
36 struct btrfs_send_ops *ops;
40 static int read_buf(struct btrfs_send_stream *s, void *buf, int len)
46 ret = read(s->fd, (char*)buf + pos, len - pos);
49 error("read from stream failed: %s",
67 * Reads a single command from kernel space and decodes the TLV's into
70 static int read_cmd(struct btrfs_send_stream *s)
79 struct btrfs_tlv_header *tlv_hdr;
83 memset(s->cmd_attrs, 0, sizeof(s->cmd_attrs));
85 ret = read_buf(s, s->read_buf, sizeof(*s->cmd_hdr));
90 error("unexpected EOF in stream");
94 s->cmd_hdr = (struct btrfs_cmd_header *)s->read_buf;
95 cmd = le16_to_cpu(s->cmd_hdr->cmd);
96 cmd_len = le32_to_cpu(s->cmd_hdr->len);
98 data = s->read_buf + sizeof(*s->cmd_hdr);
99 ret = read_buf(s, data, cmd_len);
104 error("unexpected EOF in stream");
108 crc = le32_to_cpu(s->cmd_hdr->crc);
111 crc2 = crc32c(0, (unsigned char*)s->read_buf,
112 sizeof(*s->cmd_hdr) + cmd_len);
116 error("crc32 mismatch in command");
121 while (pos < cmd_len) {
122 tlv_hdr = (struct btrfs_tlv_header *)data;
123 tlv_type = le16_to_cpu(tlv_hdr->tlv_type);
124 tlv_len = le16_to_cpu(tlv_hdr->tlv_len);
126 if (tlv_type <= 0 || tlv_type > BTRFS_SEND_A_MAX ||
127 tlv_len < 0 || tlv_len > BTRFS_SEND_BUF_SIZE) {
128 error("invalid tlv in cmd tlv_type = %d, tlv_len = %d",
134 s->cmd_attrs[tlv_type] = tlv_hdr;
136 data += sizeof(*tlv_hdr) + tlv_len;
137 pos += sizeof(*tlv_hdr) + tlv_len;
147 static int tlv_get(struct btrfs_send_stream *s, int attr, void **data, int *len)
150 struct btrfs_tlv_header *h;
152 if (attr <= 0 || attr > BTRFS_SEND_A_MAX) {
153 error("invalid attribute requested, attr = %d", attr);
158 h = s->cmd_attrs[attr];
160 error("attribute %d requested but not present", attr);
165 *len = le16_to_cpu(h->tlv_len);
174 #define __TLV_GOTO_FAIL(expr) \
175 if ((ret = expr) < 0) \
178 #define __TLV_DO_WHILE_GOTO_FAIL(expr) \
180 __TLV_GOTO_FAIL(expr) \
184 #define TLV_GET(s, attr, data, len) \
185 __TLV_DO_WHILE_GOTO_FAIL(tlv_get(s, attr, data, len))
187 #define TLV_CHECK_LEN(expected, got) \
189 if (expected != got) { \
190 error("invalid size for attribute, " \
191 "expected = %d, got = %d", \
192 (int)expected, (int)got); \
194 goto tlv_get_failed; \
198 #define TLV_GET_INT(s, attr, bits, v) \
202 TLV_GET(s, attr, (void**)&__tmp, &__len); \
203 TLV_CHECK_LEN(sizeof(*__tmp), __len); \
204 *v = get_unaligned_le##bits(__tmp); \
207 #define TLV_GET_U8(s, attr, v) TLV_GET_INT(s, attr, 8, v)
208 #define TLV_GET_U16(s, attr, v) TLV_GET_INT(s, attr, 16, v)
209 #define TLV_GET_U32(s, attr, v) TLV_GET_INT(s, attr, 32, v)
210 #define TLV_GET_U64(s, attr, v) TLV_GET_INT(s, attr, 64, v)
212 static int tlv_get_string(struct btrfs_send_stream *s, int attr, char **str)
218 TLV_GET(s, attr, &data, &len);
220 *str = malloc(len + 1);
224 memcpy(*str, data, len);
231 #define TLV_GET_STRING(s, attr, str) \
232 __TLV_DO_WHILE_GOTO_FAIL(tlv_get_string(s, attr, str))
234 static int tlv_get_timespec(struct btrfs_send_stream *s,
235 int attr, struct timespec *ts)
239 struct btrfs_timespec *bts;
241 TLV_GET(s, attr, (void**)&bts, &len);
242 TLV_CHECK_LEN(sizeof(*bts), len);
244 ts->tv_sec = le64_to_cpu(bts->sec);
245 ts->tv_nsec = le32_to_cpu(bts->nsec);
251 #define TLV_GET_TIMESPEC(s, attr, ts) \
252 __TLV_DO_WHILE_GOTO_FAIL(tlv_get_timespec(s, attr, ts))
254 static int tlv_get_uuid(struct btrfs_send_stream *s, int attr, u8 *uuid)
260 TLV_GET(s, attr, &data, &len);
261 TLV_CHECK_LEN(BTRFS_UUID_SIZE, len);
262 memcpy(uuid, data, BTRFS_UUID_SIZE);
269 #define TLV_GET_UUID(s, attr, uuid) \
270 __TLV_DO_WHILE_GOTO_FAIL(tlv_get_uuid(s, attr, uuid))
272 static int read_and_process_cmd(struct btrfs_send_stream *s)
276 char *path_to = NULL;
277 char *clone_path = NULL;
278 char *xattr_name = NULL;
279 void *xattr_data = NULL;
284 u8 uuid[BTRFS_UUID_SIZE];
285 u8 clone_uuid[BTRFS_UUID_SIZE];
302 case BTRFS_SEND_C_SUBVOL:
303 TLV_GET_STRING(s, BTRFS_SEND_A_PATH, &path);
304 TLV_GET_UUID(s, BTRFS_SEND_A_UUID, uuid);
305 TLV_GET_U64(s, BTRFS_SEND_A_CTRANSID, &ctransid);
306 ret = s->ops->subvol(path, uuid, ctransid, s->user);
308 case BTRFS_SEND_C_SNAPSHOT:
309 TLV_GET_STRING(s, BTRFS_SEND_A_PATH, &path);
310 TLV_GET_UUID(s, BTRFS_SEND_A_UUID, uuid);
311 TLV_GET_U64(s, BTRFS_SEND_A_CTRANSID, &ctransid);
312 TLV_GET_UUID(s, BTRFS_SEND_A_CLONE_UUID, clone_uuid);
313 TLV_GET_U64(s, BTRFS_SEND_A_CLONE_CTRANSID, &clone_ctransid);
314 ret = s->ops->snapshot(path, uuid, ctransid, clone_uuid,
315 clone_ctransid, s->user);
317 case BTRFS_SEND_C_MKFILE:
318 TLV_GET_STRING(s, BTRFS_SEND_A_PATH, &path);
319 ret = s->ops->mkfile(path, s->user);
321 case BTRFS_SEND_C_MKDIR:
322 TLV_GET_STRING(s, BTRFS_SEND_A_PATH, &path);
323 ret = s->ops->mkdir(path, s->user);
325 case BTRFS_SEND_C_MKNOD:
326 TLV_GET_STRING(s, BTRFS_SEND_A_PATH, &path);
327 TLV_GET_U64(s, BTRFS_SEND_A_MODE, &mode);
328 TLV_GET_U64(s, BTRFS_SEND_A_RDEV, &dev);
329 ret = s->ops->mknod(path, mode, dev, s->user);
331 case BTRFS_SEND_C_MKFIFO:
332 TLV_GET_STRING(s, BTRFS_SEND_A_PATH, &path);
333 ret = s->ops->mkfifo(path, s->user);
335 case BTRFS_SEND_C_MKSOCK:
336 TLV_GET_STRING(s, BTRFS_SEND_A_PATH, &path);
337 ret = s->ops->mksock(path, s->user);
339 case BTRFS_SEND_C_SYMLINK:
340 TLV_GET_STRING(s, BTRFS_SEND_A_PATH, &path);
341 TLV_GET_STRING(s, BTRFS_SEND_A_PATH_LINK, &path_to);
342 ret = s->ops->symlink(path, path_to, s->user);
344 case BTRFS_SEND_C_RENAME:
345 TLV_GET_STRING(s, BTRFS_SEND_A_PATH, &path);
346 TLV_GET_STRING(s, BTRFS_SEND_A_PATH_TO, &path_to);
347 ret = s->ops->rename(path, path_to, s->user);
349 case BTRFS_SEND_C_LINK:
350 TLV_GET_STRING(s, BTRFS_SEND_A_PATH, &path);
351 TLV_GET_STRING(s, BTRFS_SEND_A_PATH_LINK, &path_to);
352 ret = s->ops->link(path, path_to, s->user);
354 case BTRFS_SEND_C_UNLINK:
355 TLV_GET_STRING(s, BTRFS_SEND_A_PATH, &path);
356 ret = s->ops->unlink(path, s->user);
358 case BTRFS_SEND_C_RMDIR:
359 TLV_GET_STRING(s, BTRFS_SEND_A_PATH, &path);
360 ret = s->ops->rmdir(path, s->user);
362 case BTRFS_SEND_C_WRITE:
363 TLV_GET_STRING(s, BTRFS_SEND_A_PATH, &path);
364 TLV_GET_U64(s, BTRFS_SEND_A_FILE_OFFSET, &offset);
365 TLV_GET(s, BTRFS_SEND_A_DATA, &data, &len);
366 ret = s->ops->write(path, data, offset, len, s->user);
368 case BTRFS_SEND_C_CLONE:
369 TLV_GET_STRING(s, BTRFS_SEND_A_PATH, &path);
370 TLV_GET_U64(s, BTRFS_SEND_A_FILE_OFFSET, &offset);
371 TLV_GET_U64(s, BTRFS_SEND_A_CLONE_LEN, &len);
372 TLV_GET_UUID(s, BTRFS_SEND_A_CLONE_UUID, clone_uuid);
373 TLV_GET_U64(s, BTRFS_SEND_A_CLONE_CTRANSID, &clone_ctransid);
374 TLV_GET_STRING(s, BTRFS_SEND_A_CLONE_PATH, &clone_path);
375 TLV_GET_U64(s, BTRFS_SEND_A_CLONE_OFFSET, &clone_offset);
376 ret = s->ops->clone(path, offset, len, clone_uuid,
377 clone_ctransid, clone_path, clone_offset,
380 case BTRFS_SEND_C_SET_XATTR:
381 TLV_GET_STRING(s, BTRFS_SEND_A_PATH, &path);
382 TLV_GET_STRING(s, BTRFS_SEND_A_XATTR_NAME, &xattr_name);
383 TLV_GET(s, BTRFS_SEND_A_XATTR_DATA, &xattr_data, &xattr_len);
384 ret = s->ops->set_xattr(path, xattr_name, xattr_data,
387 case BTRFS_SEND_C_REMOVE_XATTR:
388 TLV_GET_STRING(s, BTRFS_SEND_A_PATH, &path);
389 TLV_GET_STRING(s, BTRFS_SEND_A_XATTR_NAME, &xattr_name);
390 ret = s->ops->remove_xattr(path, xattr_name, s->user);
392 case BTRFS_SEND_C_TRUNCATE:
393 TLV_GET_STRING(s, BTRFS_SEND_A_PATH, &path);
394 TLV_GET_U64(s, BTRFS_SEND_A_SIZE, &tmp);
395 ret = s->ops->truncate(path, tmp, s->user);
397 case BTRFS_SEND_C_CHMOD:
398 TLV_GET_STRING(s, BTRFS_SEND_A_PATH, &path);
399 TLV_GET_U64(s, BTRFS_SEND_A_MODE, &tmp);
400 ret = s->ops->chmod(path, tmp, s->user);
402 case BTRFS_SEND_C_CHOWN:
403 TLV_GET_STRING(s, BTRFS_SEND_A_PATH, &path);
404 TLV_GET_U64(s, BTRFS_SEND_A_UID, &tmp);
405 TLV_GET_U64(s, BTRFS_SEND_A_GID, &tmp2);
406 ret = s->ops->chown(path, tmp, tmp2, s->user);
408 case BTRFS_SEND_C_UTIMES:
409 TLV_GET_STRING(s, BTRFS_SEND_A_PATH, &path);
410 TLV_GET_TIMESPEC(s, BTRFS_SEND_A_ATIME, &at);
411 TLV_GET_TIMESPEC(s, BTRFS_SEND_A_MTIME, &mt);
412 TLV_GET_TIMESPEC(s, BTRFS_SEND_A_CTIME, &ct);
413 ret = s->ops->utimes(path, &at, &mt, &ct, s->user);
415 case BTRFS_SEND_C_UPDATE_EXTENT:
416 TLV_GET_STRING(s, BTRFS_SEND_A_PATH, &path);
417 TLV_GET_U64(s, BTRFS_SEND_A_FILE_OFFSET, &offset);
418 TLV_GET_U64(s, BTRFS_SEND_A_SIZE, &tmp);
419 ret = s->ops->update_extent(path, offset, tmp, s->user);
421 case BTRFS_SEND_C_END:
436 * If max_errors is 0, then don't stop processing the stream if one of the
437 * callbacks in btrfs_send_ops structure returns an error. If greater than
438 * zero, stop after max_errors errors happened.
440 int btrfs_read_and_process_send_stream(int fd,
441 struct btrfs_send_ops *ops, void *user,
446 struct btrfs_send_stream s;
447 struct btrfs_stream_header hdr;
455 ret = read_buf(&s, &hdr, sizeof(hdr));
463 if (strcmp(hdr.magic, BTRFS_SEND_STREAM_MAGIC)) {
465 error("unexpected header");
469 s.version = le32_to_cpu(hdr.version);
470 if (s.version > BTRFS_SEND_STREAM_VERSION) {
472 error("stream version %d not supported, please use newer version",
478 ret = read_and_process_cmd(&s);
482 if (max_errors > 0 && errors >= max_errors)
484 } else if (ret > 0) {
492 if (last_err && !ret)