#include "ioctl.h"
#include "commands.h"
#include "list.h"
+#include "utils.h"
#include "send.h"
#include "send-utils.h"
struct subvol_uuid_search sus;
};
-int find_mount_root(const char *path, char **mount_root)
-{
- FILE *mnttab;
- int fd;
- struct mntent *ent;
- int len;
- int ret;
- int longest_matchlen = 0;
- char *longest_match = NULL;
-
- fd = open(path, O_RDONLY | O_NOATIME);
- if (fd < 0)
- return -errno;
- close(fd);
-
- mnttab = setmntent("/proc/self/mounts", "r");
- if (!mnttab)
- return -errno;
-
- while ((ent = getmntent(mnttab))) {
- len = strlen(ent->mnt_dir);
- if (strncmp(ent->mnt_dir, path, len) == 0) {
- /* match found */
- if (longest_matchlen < len) {
- free(longest_match);
- longest_matchlen = len;
- longest_match = strdup(ent->mnt_dir);
- }
- }
- }
- endmntent(mnttab);
-
- if (!longest_match) {
- fprintf(stderr,
- "ERROR: Failed to find mount root for path %s.\n",
- path);
- return -ENOENT;
- }
-
- ret = 0;
- *mount_root = realpath(longest_match, NULL);
- if (!*mount_root)
- ret = -errno;
-
- free(longest_match);
- return ret;
-}
-
static int get_root_id(struct btrfs_send *s, const char *path, u64 *root_id)
{
struct subvol_info *si;
{
int ret;
pthread_t t_read;
- pthread_attr_t t_attr;
struct btrfs_ioctl_send_args io_send;
void *t_err = NULL;
int subvol_fd = -1;
goto out;
}
- ret = pthread_attr_init(&t_attr);
-
ret = pipe(pipefd);
if (ret < 0) {
ret = -errno;
send->send_fd = pipefd[0];
if (!ret)
- ret = pthread_create(&t_read, &t_attr, dump_thread,
+ ret = pthread_create(&t_read, NULL, dump_thread,
send);
if (ret) {
ret = -ret;
goto out;
}
- pthread_attr_destroy(&t_attr);
-
ret = 0;
out:
"root_id for %s\n", subvol);
goto out;
}
+
+ ret = is_subvol_ro(&send, subvol);
+ if (ret < 0)
+ goto out;
+ if (!ret) {
+ ret = -EINVAL;
+ fprintf(stderr,
+ "ERROR: cloned subvol %s is not read-only.\n",
+ subvol);
+ goto out;
+ }
+
add_clone_source(&send, root_id);
subvol_uuid_search_finit(&send.sus);
free(subvol);
"%s\n", optarg, strerror(-ret));
goto out;
}
+
+ ret = is_subvol_ro(&send, snapshot_parent);
+ if (ret < 0)
+ goto out;
+ if (!ret) {
+ ret = -EINVAL;
+ fprintf(stderr,
+ "ERROR: parent %s is not read-only.\n",
+ snapshot_parent);
+ goto out;
+ }
+
full_send = 0;
break;
case 'i':
}
}
- if (optind == argc) {
- fprintf(stderr, "ERROR: send needs path to snapshot\n");
- ret = 1;
- goto out;
- }
+ if (optind == argc)
+ usage(cmd_send_usage);
if (outname != NULL) {
send.dump_fd = creat(outname, 0600);
}
const char * const cmd_send_usage[] = {
- "btrfs send [-ve] [-p <parent>] [-c <clone-src>] [-f <outfile>] <subvol>",
- "Send the subvolume to stdout.",
- "Sends the subvolume specified by <subvol> to stdout.",
+ "btrfs send [-ve] [-p <parent>] [-c <clone-src>] [-f <outfile>] <subvol> [<subvol>...]",
+ "Send the subvolume(s) to stdout.",
+ "Sends the subvolume(s) specified by <subvol> to stdout.",
"By default, this will send the whole subvolume. To do an incremental",
"send, use '-p <parent>'. If you want to allow btrfs to clone from",
"any additional local snapshots, use '-c <clone-src>' (multiple times",