2 * Copyright (C) 2016 Fujitsu. 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.
22 #include <sys/types.h>
25 #include <sys/ioctl.h>
31 #include <asm/types.h>
32 #include <uuid/uuid.h>
35 #include "send-utils.h"
36 #include "send-stream.h"
37 #include "send-dump.h"
39 #define PATH_CAT_OR_RET(function_name, outpath, path1, path2, ret) \
41 ret = path_cat_out(outpath, path1, path2); \
43 error("%s: path invalid: %s\n", function_name, path2); \
49 * Underlying PRINT_DUMP, the only difference is how we handle
52 __attribute__ ((format (printf, 5, 6)))
53 static int __print_dump(int subvol, void *user, const char *path,
54 const char *title, const char *fmt, ...)
56 struct btrfs_dump_send_args *r = user;
57 char full_path[PATH_MAX] = {0};
63 PATH_CAT_OR_RET(title, r->full_subvol_path, r->root_path, path, ret);
64 out_path = r->full_subvol_path;
66 PATH_CAT_OR_RET(title, full_path, r->full_subvol_path, path, ret);
71 printf("%-16s%-32s", title, out_path);
73 /* Operation specified ones */
80 /* For subvolume/snapshot operation only */
81 #define PRINT_DUMP_SUBVOL(user, path, title, fmt, ...) \
82 __print_dump(1, user, path, title, fmt, ##__VA_ARGS__)
84 /* For other operations */
85 #define PRINT_DUMP(user, path, title, fmt, ...) \
86 __print_dump(0, user, path, title, fmt, ##__VA_ARGS__)
88 static int print_subvol(const char *path, const u8 *uuid, u64 ctransid,
91 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
93 uuid_unparse(uuid, uuid_str);
95 return PRINT_DUMP_SUBVOL(user, path, "subvol", "uuid=%s transid=%llu",
99 static int print_snapshot(const char *path, const u8 *uuid, u64 ctransid,
100 const u8 *parent_uuid, u64 parent_ctransid,
103 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
104 char parent_uuid_str[BTRFS_UUID_UNPARSED_SIZE];
107 uuid_unparse(uuid, uuid_str);
108 uuid_unparse(parent_uuid, parent_uuid_str);
110 ret = PRINT_DUMP_SUBVOL(user, path, "snapshot",
111 "uuid=%s transid=%llu parent_uuid=%s parent_transid=%llu",
112 uuid_str, ctransid, parent_uuid_str,
117 static int print_mkfile(const char *path, void *user)
119 return PRINT_DUMP(user, path, "mkfile", NULL);
122 static int print_mkdir(const char *path, void *user)
124 return PRINT_DUMP(user, path, "mkdir", NULL);
127 static int print_mknod(const char *path, u64 mode, u64 dev, void *user)
129 return PRINT_DUMP(user, path, "mknod", "mode=%llo dev=0x%llx", mode,
133 static int print_mkfifo(const char *path, void *user)
135 return PRINT_DUMP(user, path, "mkfifo", NULL);
138 static int print_mksock(const char *path, void *user)
140 return PRINT_DUMP(user, path, "mksock", NULL);
143 static int print_symlink(const char *path, const char *lnk, void *user)
145 return PRINT_DUMP(user, path, "symlink", "dest=%s", lnk);
148 static int print_rename(const char *from, const char *to, void *user)
150 struct btrfs_dump_send_args *r = user;
151 char full_to[PATH_MAX];
154 PATH_CAT_OR_RET("rename", full_to, r->full_subvol_path, to, ret);
155 return PRINT_DUMP(user, from, "rename", "dest=%s", full_to);
158 static int print_link(const char *path, const char *lnk, void *user)
160 return PRINT_DUMP(user, path, "link", "dest=%s", lnk);
163 static int print_unlink(const char *path, void *user)
165 return PRINT_DUMP(user, path, "unlink", NULL);
168 static int print_rmdir(const char *path, void *user)
170 return PRINT_DUMP(user, path, "rmdir", NULL);
173 static int print_write(const char *path, const void *data, u64 offset,
176 return PRINT_DUMP(user, path, "write", "offset=%llu len=%llu",
180 static int print_clone(const char *path, u64 offset, u64 len,
181 const u8 *clone_uuid, u64 clone_ctransid,
182 const char *clone_path, u64 clone_offset,
185 struct btrfs_dump_send_args *r = user;
186 char full_path[PATH_MAX];
189 PATH_CAT_OR_RET("clone", full_path, r->full_subvol_path, clone_path,
191 return PRINT_DUMP(user, path, "clone",
192 "offset=%llu len=%llu from=%s clone_offset=%llu",
193 offset, len, full_path, clone_offset);
196 static int print_set_xattr(const char *path, const char *name,
197 const void *data, int len, void *user)
199 return PRINT_DUMP(user, path, "set_xattr", "name=%s data=%.*s len=%d",
200 name, len, (char *)data, len);
203 static int print_remove_xattr(const char *path, const char *name, void *user)
206 return PRINT_DUMP(user, path, "remove_xattr", "name=%s", name);
209 static int print_truncate(const char *path, u64 size, void *user)
211 return PRINT_DUMP(user, path, "truncate", "size=%llu", size);
214 static int print_chmod(const char *path, u64 mode, void *user)
216 return PRINT_DUMP(user, path, "chmod", "mode=%llo", mode);
219 static int print_chown(const char *path, u64 uid, u64 gid, void *user)
221 return PRINT_DUMP(user, path, "chown", "gid=%llu uid=%llu", gid, uid);
224 static int sprintf_timespec(struct timespec *ts, char *dest, int max_size)
229 tm = localtime(&ts->tv_sec);
231 error("failed to convert time %lld.%.9ld to local time",
232 (long long)ts->tv_sec, ts->tv_nsec);
235 ret = strftime(dest, max_size, "%FT%T%z", tm);
238 "time %lld.%ld is too long to convert into readable string",
239 (long long)ts->tv_sec, ts->tv_nsec);
245 #define TIME_STRING_MAX 64
246 static int print_utimes(const char *path, struct timespec *at,
247 struct timespec *mt, struct timespec *ct,
250 char at_str[TIME_STRING_MAX];
251 char mt_str[TIME_STRING_MAX];
252 char ct_str[TIME_STRING_MAX];
254 if (sprintf_timespec(at, at_str, TIME_STRING_MAX - 1) < 0 ||
255 sprintf_timespec(mt, mt_str, TIME_STRING_MAX - 1) < 0 ||
256 sprintf_timespec(ct, ct_str, TIME_STRING_MAX - 1) < 0)
258 return PRINT_DUMP(user, path, "utimes", "atime=%s mtime=%s ctime=%s",
259 at_str, mt_str, ct_str);
262 static int print_update_extent(const char *path, u64 offset, u64 len,
265 return PRINT_DUMP(user, path, "update_extent", "offset=%llu len=%llu",
269 struct btrfs_send_ops btrfs_print_send_ops = {
270 .subvol = print_subvol,
271 .snapshot = print_snapshot,
272 .mkfile = print_mkfile,
273 .mkdir = print_mkdir,
274 .mknod = print_mknod,
275 .mkfifo = print_mkfifo,
276 .mksock = print_mksock,
277 .symlink = print_symlink,
278 .rename = print_rename,
280 .unlink = print_unlink,
281 .rmdir = print_rmdir,
282 .write = print_write,
283 .clone = print_clone,
284 .set_xattr = print_set_xattr,
285 .remove_xattr = print_remove_xattr,
286 .truncate = print_truncate,
287 .chmod = print_chmod,
288 .chown = print_chown,
289 .utimes = print_utimes,
290 .update_extent = print_update_extent