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];
37 * end of last successful read, equivalent to start of current
38 * malformated part of block
42 struct btrfs_send_ops
*ops
;
47 * Read len bytes to buf.
50 * < 0 - negative errno in case of error
51 * > 0 - no data read, EOF
53 static int read_buf(struct btrfs_send_stream
*sctx
, char *buf
, size_t len
)
61 rbytes
= read(sctx
->fd
, buf
+ pos
, len
- pos
);
64 error("read from stream failed: %s",
77 if (0 < pos
&& pos
< len
) {
78 error("short read from stream: expected %zu read %zu", len
, pos
);
81 sctx
->stream_pos
+= pos
;
89 * Reads a single command from kernel space and decodes the TLV's into
94 * < 0 - an error in the command
96 static int read_cmd(struct btrfs_send_stream
*sctx
)
106 memset(sctx
->cmd_attrs
, 0, sizeof(sctx
->cmd_attrs
));
108 ASSERT(sizeof(*sctx
->cmd_hdr
) <= sizeof(sctx
->read_buf
));
109 ret
= read_buf(sctx
, sctx
->read_buf
, sizeof(*sctx
->cmd_hdr
));
114 error("unexpected EOF in stream");
118 sctx
->cmd_hdr
= (struct btrfs_cmd_header
*)sctx
->read_buf
;
119 cmd
= le16_to_cpu(sctx
->cmd_hdr
->cmd
);
120 cmd_len
= le32_to_cpu(sctx
->cmd_hdr
->len
);
122 if (cmd_len
+ sizeof(*sctx
->cmd_hdr
) >= sizeof(sctx
->read_buf
)) {
124 error("command length %u too big for buffer %zu",
125 cmd_len
, sizeof(sctx
->read_buf
));
129 data
= sctx
->read_buf
+ sizeof(*sctx
->cmd_hdr
);
130 ret
= read_buf(sctx
, data
, cmd_len
);
135 error("unexpected EOF in stream");
139 crc
= le32_to_cpu(sctx
->cmd_hdr
->crc
);
140 sctx
->cmd_hdr
->crc
= 0;
142 crc2
= crc32c(0, (unsigned char*)sctx
->read_buf
,
143 sizeof(*sctx
->cmd_hdr
) + cmd_len
);
147 error("crc32 mismatch in command");
152 while (pos
< cmd_len
) {
153 struct btrfs_tlv_header
*tlv_hdr
;
157 tlv_hdr
= (struct btrfs_tlv_header
*)data
;
158 tlv_type
= le16_to_cpu(tlv_hdr
->tlv_type
);
159 tlv_len
= le16_to_cpu(tlv_hdr
->tlv_len
);
161 if (tlv_type
== 0 || tlv_type
> BTRFS_SEND_A_MAX
162 || tlv_len
> BTRFS_SEND_BUF_SIZE
) {
163 error("invalid tlv in cmd tlv_type = %hu, tlv_len = %hu",
169 sctx
->cmd_attrs
[tlv_type
] = tlv_hdr
;
171 data
+= sizeof(*tlv_hdr
) + tlv_len
;
172 pos
+= sizeof(*tlv_hdr
) + tlv_len
;
182 static int tlv_get(struct btrfs_send_stream
*sctx
, int attr
, void **data
, int *len
)
185 struct btrfs_tlv_header
*hdr
;
187 if (attr
<= 0 || attr
> BTRFS_SEND_A_MAX
) {
188 error("invalid attribute requested, attr = %d", attr
);
193 hdr
= sctx
->cmd_attrs
[attr
];
195 error("attribute %d requested but not present", attr
);
200 *len
= le16_to_cpu(hdr
->tlv_len
);
209 #define __TLV_GOTO_FAIL(expr) \
210 if ((ret = expr) < 0) \
213 #define __TLV_DO_WHILE_GOTO_FAIL(expr) \
215 __TLV_GOTO_FAIL(expr) \
219 #define TLV_GET(s, attr, data, len) \
220 __TLV_DO_WHILE_GOTO_FAIL(tlv_get(s, attr, data, len))
222 #define TLV_CHECK_LEN(expected, got) \
224 if (expected != got) { \
225 error("invalid size for attribute, " \
226 "expected = %d, got = %d", \
227 (int)expected, (int)got); \
229 goto tlv_get_failed; \
233 #define TLV_GET_INT(s, attr, bits, v) \
237 TLV_GET(s, attr, (void**)&__tmp, &__len); \
238 TLV_CHECK_LEN(sizeof(*__tmp), __len); \
239 *v = get_unaligned_le##bits(__tmp); \
242 #define TLV_GET_U8(s, attr, v) TLV_GET_INT(s, attr, 8, v)
243 #define TLV_GET_U16(s, attr, v) TLV_GET_INT(s, attr, 16, v)
244 #define TLV_GET_U32(s, attr, v) TLV_GET_INT(s, attr, 32, v)
245 #define TLV_GET_U64(s, attr, v) TLV_GET_INT(s, attr, 64, v)
247 static int tlv_get_string(struct btrfs_send_stream
*sctx
, int attr
, char **str
)
253 TLV_GET(sctx
, attr
, &data
, &len
);
255 *str
= malloc(len
+ 1);
259 memcpy(*str
, data
, len
);
266 #define TLV_GET_STRING(s, attr, str) \
267 __TLV_DO_WHILE_GOTO_FAIL(tlv_get_string(s, attr, str))
269 static int tlv_get_timespec(struct btrfs_send_stream
*sctx
,
270 int attr
, struct timespec
*ts
)
274 struct btrfs_timespec
*bts
;
276 TLV_GET(sctx
, attr
, (void**)&bts
, &len
);
277 TLV_CHECK_LEN(sizeof(*bts
), len
);
279 ts
->tv_sec
= le64_to_cpu(bts
->sec
);
280 ts
->tv_nsec
= le32_to_cpu(bts
->nsec
);
286 #define TLV_GET_TIMESPEC(s, attr, ts) \
287 __TLV_DO_WHILE_GOTO_FAIL(tlv_get_timespec(s, attr, ts))
289 static int tlv_get_uuid(struct btrfs_send_stream
*sctx
, int attr
, u8
*uuid
)
295 TLV_GET(sctx
, attr
, &data
, &len
);
296 TLV_CHECK_LEN(BTRFS_UUID_SIZE
, len
);
297 memcpy(uuid
, data
, BTRFS_UUID_SIZE
);
304 #define TLV_GET_UUID(s, attr, uuid) \
305 __TLV_DO_WHILE_GOTO_FAIL(tlv_get_uuid(s, attr, uuid))
307 static int read_and_process_cmd(struct btrfs_send_stream
*sctx
)
311 char *path_to
= NULL
;
312 char *clone_path
= NULL
;
313 char *xattr_name
= NULL
;
314 void *xattr_data
= NULL
;
319 u8 uuid
[BTRFS_UUID_SIZE
];
320 u8 clone_uuid
[BTRFS_UUID_SIZE
];
332 ret
= read_cmd(sctx
);
337 case BTRFS_SEND_C_SUBVOL
:
338 TLV_GET_STRING(sctx
, BTRFS_SEND_A_PATH
, &path
);
339 TLV_GET_UUID(sctx
, BTRFS_SEND_A_UUID
, uuid
);
340 TLV_GET_U64(sctx
, BTRFS_SEND_A_CTRANSID
, &ctransid
);
341 ret
= sctx
->ops
->subvol(path
, uuid
, ctransid
, sctx
->user
);
343 case BTRFS_SEND_C_SNAPSHOT
:
344 TLV_GET_STRING(sctx
, BTRFS_SEND_A_PATH
, &path
);
345 TLV_GET_UUID(sctx
, BTRFS_SEND_A_UUID
, uuid
);
346 TLV_GET_U64(sctx
, BTRFS_SEND_A_CTRANSID
, &ctransid
);
347 TLV_GET_UUID(sctx
, BTRFS_SEND_A_CLONE_UUID
, clone_uuid
);
348 TLV_GET_U64(sctx
, BTRFS_SEND_A_CLONE_CTRANSID
, &clone_ctransid
);
349 ret
= sctx
->ops
->snapshot(path
, uuid
, ctransid
, clone_uuid
,
350 clone_ctransid
, sctx
->user
);
352 case BTRFS_SEND_C_MKFILE
:
353 TLV_GET_STRING(sctx
, BTRFS_SEND_A_PATH
, &path
);
354 ret
= sctx
->ops
->mkfile(path
, sctx
->user
);
356 case BTRFS_SEND_C_MKDIR
:
357 TLV_GET_STRING(sctx
, BTRFS_SEND_A_PATH
, &path
);
358 ret
= sctx
->ops
->mkdir(path
, sctx
->user
);
360 case BTRFS_SEND_C_MKNOD
:
361 TLV_GET_STRING(sctx
, BTRFS_SEND_A_PATH
, &path
);
362 TLV_GET_U64(sctx
, BTRFS_SEND_A_MODE
, &mode
);
363 TLV_GET_U64(sctx
, BTRFS_SEND_A_RDEV
, &dev
);
364 ret
= sctx
->ops
->mknod(path
, mode
, dev
, sctx
->user
);
366 case BTRFS_SEND_C_MKFIFO
:
367 TLV_GET_STRING(sctx
, BTRFS_SEND_A_PATH
, &path
);
368 ret
= sctx
->ops
->mkfifo(path
, sctx
->user
);
370 case BTRFS_SEND_C_MKSOCK
:
371 TLV_GET_STRING(sctx
, BTRFS_SEND_A_PATH
, &path
);
372 ret
= sctx
->ops
->mksock(path
, sctx
->user
);
374 case BTRFS_SEND_C_SYMLINK
:
375 TLV_GET_STRING(sctx
, BTRFS_SEND_A_PATH
, &path
);
376 TLV_GET_STRING(sctx
, BTRFS_SEND_A_PATH_LINK
, &path_to
);
377 ret
= sctx
->ops
->symlink(path
, path_to
, sctx
->user
);
379 case BTRFS_SEND_C_RENAME
:
380 TLV_GET_STRING(sctx
, BTRFS_SEND_A_PATH
, &path
);
381 TLV_GET_STRING(sctx
, BTRFS_SEND_A_PATH_TO
, &path_to
);
382 ret
= sctx
->ops
->rename(path
, path_to
, sctx
->user
);
384 case BTRFS_SEND_C_LINK
:
385 TLV_GET_STRING(sctx
, BTRFS_SEND_A_PATH
, &path
);
386 TLV_GET_STRING(sctx
, BTRFS_SEND_A_PATH_LINK
, &path_to
);
387 ret
= sctx
->ops
->link(path
, path_to
, sctx
->user
);
389 case BTRFS_SEND_C_UNLINK
:
390 TLV_GET_STRING(sctx
, BTRFS_SEND_A_PATH
, &path
);
391 ret
= sctx
->ops
->unlink(path
, sctx
->user
);
393 case BTRFS_SEND_C_RMDIR
:
394 TLV_GET_STRING(sctx
, BTRFS_SEND_A_PATH
, &path
);
395 ret
= sctx
->ops
->rmdir(path
, sctx
->user
);
397 case BTRFS_SEND_C_WRITE
:
398 TLV_GET_STRING(sctx
, BTRFS_SEND_A_PATH
, &path
);
399 TLV_GET_U64(sctx
, BTRFS_SEND_A_FILE_OFFSET
, &offset
);
400 TLV_GET(sctx
, BTRFS_SEND_A_DATA
, &data
, &len
);
401 ret
= sctx
->ops
->write(path
, data
, offset
, len
, sctx
->user
);
403 case BTRFS_SEND_C_CLONE
:
404 TLV_GET_STRING(sctx
, BTRFS_SEND_A_PATH
, &path
);
405 TLV_GET_U64(sctx
, BTRFS_SEND_A_FILE_OFFSET
, &offset
);
406 TLV_GET_U64(sctx
, BTRFS_SEND_A_CLONE_LEN
, &len
);
407 TLV_GET_UUID(sctx
, BTRFS_SEND_A_CLONE_UUID
, clone_uuid
);
408 TLV_GET_U64(sctx
, BTRFS_SEND_A_CLONE_CTRANSID
, &clone_ctransid
);
409 TLV_GET_STRING(sctx
, BTRFS_SEND_A_CLONE_PATH
, &clone_path
);
410 TLV_GET_U64(sctx
, BTRFS_SEND_A_CLONE_OFFSET
, &clone_offset
);
411 ret
= sctx
->ops
->clone(path
, offset
, len
, clone_uuid
,
412 clone_ctransid
, clone_path
, clone_offset
,
415 case BTRFS_SEND_C_SET_XATTR
:
416 TLV_GET_STRING(sctx
, BTRFS_SEND_A_PATH
, &path
);
417 TLV_GET_STRING(sctx
, BTRFS_SEND_A_XATTR_NAME
, &xattr_name
);
418 TLV_GET(sctx
, BTRFS_SEND_A_XATTR_DATA
, &xattr_data
, &xattr_len
);
419 ret
= sctx
->ops
->set_xattr(path
, xattr_name
, xattr_data
,
420 xattr_len
, sctx
->user
);
422 case BTRFS_SEND_C_REMOVE_XATTR
:
423 TLV_GET_STRING(sctx
, BTRFS_SEND_A_PATH
, &path
);
424 TLV_GET_STRING(sctx
, BTRFS_SEND_A_XATTR_NAME
, &xattr_name
);
425 ret
= sctx
->ops
->remove_xattr(path
, xattr_name
, sctx
->user
);
427 case BTRFS_SEND_C_TRUNCATE
:
428 TLV_GET_STRING(sctx
, BTRFS_SEND_A_PATH
, &path
);
429 TLV_GET_U64(sctx
, BTRFS_SEND_A_SIZE
, &tmp
);
430 ret
= sctx
->ops
->truncate(path
, tmp
, sctx
->user
);
432 case BTRFS_SEND_C_CHMOD
:
433 TLV_GET_STRING(sctx
, BTRFS_SEND_A_PATH
, &path
);
434 TLV_GET_U64(sctx
, BTRFS_SEND_A_MODE
, &tmp
);
435 ret
= sctx
->ops
->chmod(path
, tmp
, sctx
->user
);
437 case BTRFS_SEND_C_CHOWN
:
438 TLV_GET_STRING(sctx
, BTRFS_SEND_A_PATH
, &path
);
439 TLV_GET_U64(sctx
, BTRFS_SEND_A_UID
, &tmp
);
440 TLV_GET_U64(sctx
, BTRFS_SEND_A_GID
, &tmp2
);
441 ret
= sctx
->ops
->chown(path
, tmp
, tmp2
, sctx
->user
);
443 case BTRFS_SEND_C_UTIMES
:
444 TLV_GET_STRING(sctx
, BTRFS_SEND_A_PATH
, &path
);
445 TLV_GET_TIMESPEC(sctx
, BTRFS_SEND_A_ATIME
, &at
);
446 TLV_GET_TIMESPEC(sctx
, BTRFS_SEND_A_MTIME
, &mt
);
447 TLV_GET_TIMESPEC(sctx
, BTRFS_SEND_A_CTIME
, &ct
);
448 ret
= sctx
->ops
->utimes(path
, &at
, &mt
, &ct
, sctx
->user
);
450 case BTRFS_SEND_C_UPDATE_EXTENT
:
451 TLV_GET_STRING(sctx
, BTRFS_SEND_A_PATH
, &path
);
452 TLV_GET_U64(sctx
, BTRFS_SEND_A_FILE_OFFSET
, &offset
);
453 TLV_GET_U64(sctx
, BTRFS_SEND_A_SIZE
, &tmp
);
454 ret
= sctx
->ops
->update_extent(path
, offset
, tmp
, sctx
->user
);
456 case BTRFS_SEND_C_END
:
471 * If max_errors is 0, then don't stop processing the stream if one of the
472 * callbacks in btrfs_send_ops structure returns an error. If greater than
473 * zero, stop after max_errors errors happened.
475 int btrfs_read_and_process_send_stream(int fd
,
476 struct btrfs_send_ops
*ops
, void *user
,
481 struct btrfs_send_stream sctx
;
482 struct btrfs_stream_header hdr
;
491 ret
= read_buf(&sctx
, (char*)&hdr
, sizeof(hdr
));
499 if (strcmp(hdr
.magic
, BTRFS_SEND_STREAM_MAGIC
)) {
501 error("unexpected header");
505 sctx
.version
= le32_to_cpu(hdr
.version
);
506 if (sctx
.version
> BTRFS_SEND_STREAM_VERSION
) {
508 error("stream version %d not supported, please use newer version",
514 ret
= read_and_process_cmd(&sctx
);
518 if (max_errors
> 0 && errors
>= max_errors
)
520 } else if (ret
> 0) {
528 if (last_err
&& !ret
)