btrfs-progs: configure: check if xmlto exists at configure time
[platform/upstream/btrfs-progs.git] / cmds-receive.c
index df86c03..68123a3 100644 (file)
@@ -315,8 +315,8 @@ static int process_snapshot(const char *path, const u8 *uuid, u64 ctransid,
                sub_len = strlen(parent_subvol->path);
 
                /* First make sure the parent subvol is actually in our path */
-               if (sub_len < root_len ||
-                   strstr(parent_subvol->path, rctx->full_root_path) == NULL) {
+               if (strstr(parent_subvol->path, rctx->full_root_path) != parent_subvol->path ||
+                   (sub_len > root_len && parent_subvol->path[root_len] != '/')) {
                        error(
                "parent subvol is not reachable from inside the root subvol");
                        ret = -ENOENT;
@@ -324,7 +324,7 @@ static int process_snapshot(const char *path, const u8 *uuid, u64 ctransid,
                }
 
                if (sub_len == root_len) {
-                       parent_subvol->path[0] = '/';
+                       parent_subvol->path[0] = '.';
                        parent_subvol->path[1] = '\0';
                } else {
                        /*
@@ -783,7 +783,24 @@ static int process_clone(const char *path, u64 offset, u64 len,
                                                r->subvol_parent_name);
                        }
                }*/
-               subvol_path = strdup(si->path);
+
+               /* strip the subvolume that we are receiving to from the start of subvol_path */
+               if (rctx->full_root_path) {
+                       size_t root_len = strlen(rctx->full_root_path);
+                       size_t sub_len = strlen(si->path);
+
+                       if (sub_len > root_len &&
+                           strstr(si->path, rctx->full_root_path) == si->path &&
+                           si->path[root_len] == '/') {
+                               subvol_path = strdup(si->path + root_len + 1);
+                       } else {
+                               error("clone: source subvol path %s unreachable from %s",
+                                       si->path, rctx->full_root_path);
+                               goto out;
+                       }
+               } else {
+                       subvol_path = strdup(si->path);
+               }
        }
 
        ret = path_cat_out(full_clone_path, subvol_path, clone_path);
@@ -1074,7 +1091,7 @@ static int do_receive(struct btrfs_receive *rctx, const char *tomnt,
        char *dest_dir_full_path;
        char root_subvol_path[PATH_MAX];
        int end = 0;
-       int count;
+       int iterations = 0;
 
        dest_dir_full_path = realpath(tomnt, NULL);
        if (!dest_dir_full_path) {
@@ -1169,7 +1186,6 @@ static int do_receive(struct btrfs_receive *rctx, const char *tomnt,
        if (ret < 0)
                goto out;
 
-       count = 0;
        while (!end) {
                if (rctx->cached_capabilities_len) {
                        if (g_verbose >= 3)
@@ -1183,22 +1199,28 @@ static int do_receive(struct btrfs_receive *rctx, const char *tomnt,
                                                         rctx,
                                                         rctx->honor_end_cmd,
                                                         max_errors);
-               if (ret < 0)
-                       goto out;
-               /* Empty stream is invalid */
-               if (ret && count == 0) {
-                       error("empty stream is not considered valid");
-                       ret = -EINVAL;
-                       goto out;
+               if (ret < 0) {
+                       if (ret != -ENODATA)
+                               goto out;
+
+                       /* Empty stream is invalid */
+                       if (iterations == 0) {
+                               error("empty stream is not considered valid");
+                               ret = -EINVAL;
+                               goto out;
+                       }
+
+                       ret = 1;
                }
-               count++;
-               if (ret)
+               if (ret > 0)
                        end = 1;
 
                close_inode_for_write(rctx);
                ret = finish_subvol(rctx);
                if (ret < 0)
                        goto out;
+
+               iterations++;
        }
        ret = 0;
 
@@ -1255,7 +1277,7 @@ int cmd_receive(int argc, char **argv)
                        { NULL, 0, NULL, 0 }
                };
 
-               c = getopt_long(argc, argv, "Cevf:m:", long_opts, NULL);
+               c = getopt_long(argc, argv, "Cevf:m:E:", long_opts, NULL);
                if (c < 0)
                        break;
 
@@ -1308,7 +1330,7 @@ int cmd_receive(int argc, char **argv)
        if (fromfile[0]) {
                receive_fd = open(fromfile, O_RDONLY | O_NOATIME);
                if (receive_fd < 0) {
-                       error("cannot open %s: %s", fromfile, strerror(errno));
+                       error("cannot open %s: %m", fromfile);
                        goto out;
                }
        }