Add packaging
[platform/upstream/btrfs-progs.git] / send-stream.c
1 /*
2  * Copyright (C) 2012 Alexander Block.  All rights reserved.
3  *
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.
7  *
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.
12  *
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.
17  */
18
19 #include <uuid/uuid.h>
20 #include <unistd.h>
21
22 #include "send.h"
23 #include "send-stream.h"
24 #include "crc32c.h"
25 #include "utils.h"
26
27 struct btrfs_send_stream {
28         int fd;
29         char read_buf[BTRFS_SEND_BUF_SIZE];
30
31         int cmd;
32         struct btrfs_cmd_header *cmd_hdr;
33         struct btrfs_tlv_header *cmd_attrs[BTRFS_SEND_A_MAX + 1];
34         u32 version;
35
36         /*
37          * end of last successful read, equivalent to start of current
38          * malformated part of block
39          */
40         size_t stream_pos;
41
42         struct btrfs_send_ops *ops;
43         void *user;
44 };
45
46 /*
47  * Read len bytes to buf.
48  * Return:
49  *   0 - success
50  * < 0 - negative errno in case of error
51  * > 0 - no data read, EOF
52  */
53 static int read_buf(struct btrfs_send_stream *sctx, char *buf, size_t len)
54 {
55         int ret;
56         size_t pos = 0;
57
58         while (pos < len) {
59                 ssize_t rbytes;
60
61                 rbytes = read(sctx->fd, buf + pos, len - pos);
62                 if (rbytes < 0) {
63                         ret = -errno;
64                         error("read from stream failed: %s",
65                                         strerror(-ret));
66                         goto out;
67                 }
68                 if (rbytes == 0) {
69                         ret = 1;
70                         goto out_eof;
71                 }
72                 pos += rbytes;
73         }
74         ret = 0;
75
76 out_eof:
77         if (0 < pos && pos < len) {
78                 error("short read from stream: expected %zu read %zu", len, pos);
79                 ret = -EIO;
80         } else {
81                 sctx->stream_pos += pos;
82         }
83
84 out:
85         return ret;
86 }
87
88 /*
89  * Reads a single command from kernel space and decodes the TLV's into
90  * sctx->cmd_attrs
91  *
92  * Returns:
93  *   0 - success
94  * < 0 - an error in the command
95  */
96 static int read_cmd(struct btrfs_send_stream *sctx)
97 {
98         int ret;
99         u16 cmd;
100         u32 cmd_len;
101         char *data;
102         u32 pos;
103         u32 crc;
104         u32 crc2;
105
106         memset(sctx->cmd_attrs, 0, sizeof(sctx->cmd_attrs));
107
108         ASSERT(sizeof(*sctx->cmd_hdr) <= sizeof(sctx->read_buf));
109         ret = read_buf(sctx, sctx->read_buf, sizeof(*sctx->cmd_hdr));
110         if (ret < 0)
111                 goto out;
112         if (ret) {
113                 ret = -EINVAL;
114                 error("unexpected EOF in stream");
115                 goto out;
116         }
117
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);
121
122         if (cmd_len + sizeof(*sctx->cmd_hdr) >= sizeof(sctx->read_buf)) {
123                 ret = -EINVAL;
124                 error("command length %u too big for buffer %zu",
125                                 cmd_len, sizeof(sctx->read_buf));
126                 goto out;
127         }
128
129         data = sctx->read_buf + sizeof(*sctx->cmd_hdr);
130         ret = read_buf(sctx, data, cmd_len);
131         if (ret < 0)
132                 goto out;
133         if (ret) {
134                 ret = -EINVAL;
135                 error("unexpected EOF in stream");
136                 goto out;
137         }
138
139         crc = le32_to_cpu(sctx->cmd_hdr->crc);
140         sctx->cmd_hdr->crc = 0;
141
142         crc2 = crc32c(0, (unsigned char*)sctx->read_buf,
143                         sizeof(*sctx->cmd_hdr) + cmd_len);
144
145         if (crc != crc2) {
146                 ret = -EINVAL;
147                 error("crc32 mismatch in command");
148                 goto out;
149         }
150
151         pos = 0;
152         while (pos < cmd_len) {
153                 struct btrfs_tlv_header *tlv_hdr;
154                 u16 tlv_type;
155                 u16 tlv_len;
156
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);
160
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",
164                                         tlv_type, tlv_len);
165                         ret = -EINVAL;
166                         goto out;
167                 }
168
169                 sctx->cmd_attrs[tlv_type] = tlv_hdr;
170
171                 data += sizeof(*tlv_hdr) + tlv_len;
172                 pos += sizeof(*tlv_hdr) + tlv_len;
173         }
174
175         sctx->cmd = cmd;
176         ret = 0;
177
178 out:
179         return ret;
180 }
181
182 static int tlv_get(struct btrfs_send_stream *sctx, int attr, void **data, int *len)
183 {
184         int ret;
185         struct btrfs_tlv_header *hdr;
186
187         if (attr <= 0 || attr > BTRFS_SEND_A_MAX) {
188                 error("invalid attribute requested, attr = %d", attr);
189                 ret = -EINVAL;
190                 goto out;
191         }
192
193         hdr = sctx->cmd_attrs[attr];
194         if (!hdr) {
195                 error("attribute %d requested but not present", attr);
196                 ret = -ENOENT;
197                 goto out;
198         }
199
200         *len = le16_to_cpu(hdr->tlv_len);
201         *data = hdr + 1;
202
203         ret = 0;
204
205 out:
206         return ret;
207 }
208
209 #define __TLV_GOTO_FAIL(expr) \
210         if ((ret = expr) < 0) \
211                 goto tlv_get_failed;
212
213 #define __TLV_DO_WHILE_GOTO_FAIL(expr) \
214         do { \
215                 __TLV_GOTO_FAIL(expr) \
216         } while (0)
217
218
219 #define TLV_GET(s, attr, data, len) \
220         __TLV_DO_WHILE_GOTO_FAIL(tlv_get(s, attr, data, len))
221
222 #define TLV_CHECK_LEN(expected, got) \
223         do { \
224                 if (expected != got) { \
225                         error("invalid size for attribute, " \
226                                         "expected = %d, got = %d", \
227                                         (int)expected, (int)got); \
228                         ret = -EINVAL; \
229                         goto tlv_get_failed; \
230                 } \
231         } while (0)
232
233 #define TLV_GET_INT(s, attr, bits, v) \
234         do { \
235                 __le##bits *__tmp; \
236                 int __len; \
237                 TLV_GET(s, attr, (void**)&__tmp, &__len); \
238                 TLV_CHECK_LEN(sizeof(*__tmp), __len); \
239                 *v = get_unaligned_le##bits(__tmp); \
240         } while (0)
241
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)
246
247 static int tlv_get_string(struct btrfs_send_stream *sctx, int attr, char **str)
248 {
249         int ret;
250         void *data;
251         int len = 0;
252
253         TLV_GET(sctx, attr, &data, &len);
254
255         *str = malloc(len + 1);
256         if (!*str)
257                 return -ENOMEM;
258
259         memcpy(*str, data, len);
260         (*str)[len] = 0;
261         ret = 0;
262
263 tlv_get_failed:
264         return ret;
265 }
266 #define TLV_GET_STRING(s, attr, str) \
267         __TLV_DO_WHILE_GOTO_FAIL(tlv_get_string(s, attr, str))
268
269 static int tlv_get_timespec(struct btrfs_send_stream *sctx,
270                             int attr, struct timespec *ts)
271 {
272         int ret;
273         int len;
274         struct btrfs_timespec *bts;
275
276         TLV_GET(sctx, attr, (void**)&bts, &len);
277         TLV_CHECK_LEN(sizeof(*bts), len);
278
279         ts->tv_sec = le64_to_cpu(bts->sec);
280         ts->tv_nsec = le32_to_cpu(bts->nsec);
281         ret = 0;
282
283 tlv_get_failed:
284         return ret;
285 }
286 #define TLV_GET_TIMESPEC(s, attr, ts) \
287         __TLV_DO_WHILE_GOTO_FAIL(tlv_get_timespec(s, attr, ts))
288
289 static int tlv_get_uuid(struct btrfs_send_stream *sctx, int attr, u8 *uuid)
290 {
291         int ret;
292         int len;
293         void *data;
294
295         TLV_GET(sctx, attr, &data, &len);
296         TLV_CHECK_LEN(BTRFS_UUID_SIZE, len);
297         memcpy(uuid, data, BTRFS_UUID_SIZE);
298
299         ret = 0;
300
301 tlv_get_failed:
302         return ret;
303 }
304 #define TLV_GET_UUID(s, attr, uuid) \
305         __TLV_DO_WHILE_GOTO_FAIL(tlv_get_uuid(s, attr, uuid))
306
307 static int read_and_process_cmd(struct btrfs_send_stream *sctx)
308 {
309         int ret;
310         char *path = NULL;
311         char *path_to = NULL;
312         char *clone_path = NULL;
313         char *xattr_name = NULL;
314         void *xattr_data = NULL;
315         void *data = NULL;
316         struct timespec at;
317         struct timespec ct;
318         struct timespec mt;
319         u8 uuid[BTRFS_UUID_SIZE];
320         u8 clone_uuid[BTRFS_UUID_SIZE];
321         u64 tmp;
322         u64 tmp2;
323         u64 ctransid;
324         u64 clone_ctransid;
325         u64 mode;
326         u64 dev;
327         u64 clone_offset;
328         u64 offset;
329         int len;
330         int xattr_len;
331
332         ret = read_cmd(sctx);
333         if (ret)
334                 goto out;
335
336         switch (sctx->cmd) {
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);
342                 break;
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);
351                 break;
352         case BTRFS_SEND_C_MKFILE:
353                 TLV_GET_STRING(sctx, BTRFS_SEND_A_PATH, &path);
354                 ret = sctx->ops->mkfile(path, sctx->user);
355                 break;
356         case BTRFS_SEND_C_MKDIR:
357                 TLV_GET_STRING(sctx, BTRFS_SEND_A_PATH, &path);
358                 ret = sctx->ops->mkdir(path, sctx->user);
359                 break;
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);
365                 break;
366         case BTRFS_SEND_C_MKFIFO:
367                 TLV_GET_STRING(sctx, BTRFS_SEND_A_PATH, &path);
368                 ret = sctx->ops->mkfifo(path, sctx->user);
369                 break;
370         case BTRFS_SEND_C_MKSOCK:
371                 TLV_GET_STRING(sctx, BTRFS_SEND_A_PATH, &path);
372                 ret = sctx->ops->mksock(path, sctx->user);
373                 break;
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);
378                 break;
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);
383                 break;
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);
388                 break;
389         case BTRFS_SEND_C_UNLINK:
390                 TLV_GET_STRING(sctx, BTRFS_SEND_A_PATH, &path);
391                 ret = sctx->ops->unlink(path, sctx->user);
392                 break;
393         case BTRFS_SEND_C_RMDIR:
394                 TLV_GET_STRING(sctx, BTRFS_SEND_A_PATH, &path);
395                 ret = sctx->ops->rmdir(path, sctx->user);
396                 break;
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);
402                 break;
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,
413                                 sctx->user);
414                 break;
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);
421                 break;
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);
426                 break;
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);
431                 break;
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);
436                 break;
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);
442                 break;
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);
449                 break;
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);
455                 break;
456         case BTRFS_SEND_C_END:
457                 ret = 1;
458                 break;
459         }
460
461 tlv_get_failed:
462 out:
463         free(path);
464         free(path_to);
465         free(clone_path);
466         free(xattr_name);
467         return ret;
468 }
469
470 /*
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.
474  */
475 int btrfs_read_and_process_send_stream(int fd,
476                                        struct btrfs_send_ops *ops, void *user,
477                                        int honor_end_cmd,
478                                        u64 max_errors)
479 {
480         int ret;
481         struct btrfs_send_stream sctx;
482         struct btrfs_stream_header hdr;
483         u64 errors = 0;
484         int last_err = 0;
485
486         sctx.fd = fd;
487         sctx.ops = ops;
488         sctx.user = user;
489         sctx.stream_pos = 0;
490
491         ret = read_buf(&sctx, (char*)&hdr, sizeof(hdr));
492         if (ret < 0)
493                 goto out;
494         if (ret) {
495                 ret = -ENODATA;
496                 goto out;
497         }
498
499         if (strcmp(hdr.magic, BTRFS_SEND_STREAM_MAGIC)) {
500                 ret = -EINVAL;
501                 error("unexpected header");
502                 goto out;
503         }
504
505         sctx.version = le32_to_cpu(hdr.version);
506         if (sctx.version > BTRFS_SEND_STREAM_VERSION) {
507                 ret = -EINVAL;
508                 error("stream version %d not supported, please use newer version",
509                                 sctx.version);
510                 goto out;
511         }
512
513         while (1) {
514                 ret = read_and_process_cmd(&sctx);
515                 if (ret < 0) {
516                         last_err = ret;
517                         errors++;
518                         if (max_errors > 0 && errors >= max_errors)
519                                 goto out;
520                 } else if (ret > 0) {
521                         if (!honor_end_cmd)
522                                 ret = 0;
523                         goto out;
524                 }
525         }
526
527 out:
528         if (last_err && !ret)
529                 ret = last_err;
530
531         return ret;
532 }