#include <sys/ioctl.h>
#include <errno.h>
#include <sys/stat.h>
+#include <sys/vfs.h>
#include <libgen.h>
#include <limits.h>
#include <getopt.h>
#include <uuid/uuid.h>
+#include <linux/magic.h>
#include "kerncompat.h"
#include "ioctl.h"
retval = 1; /* failure */
res = test_isdir(dst);
+ if (res < 0 && res != -ENOENT) {
+ error("cannot access %s: %s", dst, strerror(-res));
+ goto out;
+ }
if (res >= 0) {
error("target path already exists: %s", dst);
goto out;
}
/*
- * test if path is a subvolume:
- * this function return
- * 0-> path exists but it is not a subvolume
- * 1-> path exists and it is a subvolume
- * -1 -> path is unaccessible
+ * Test if path is a subvolume
+ * Returns:
+ * 0 - path exists but it is not a subvolume
+ * 1 - path exists and it is a subvolume
+ * < 0 - error
*/
-int test_issubvolume(char *path)
+int test_issubvolume(const char *path)
{
struct stat st;
+ struct statfs stfs;
int res;
res = stat(path, &st);
- if(res < 0 )
- return -1;
+ if (res < 0)
+ return -errno;
+
+ if (st.st_ino != BTRFS_FIRST_FREE_OBJECTID || !S_ISDIR(st.st_mode))
+ return 0;
- return (st.st_ino == 256) && S_ISDIR(st.st_mode);
+ res = statfs(path, &stfs);
+ if (res < 0)
+ return -errno;
+
+ return (int)stfs.f_type == BTRFS_SUPER_MAGIC;
}
static int wait_for_commit(int fd)
res = test_issubvolume(path);
if (res < 0) {
- error("cannot access subvolume %s", path);
+ error("cannot access subvolume %s: %s", path, strerror(-res));
ret = 1;
goto out;
}
retval = 1; /* failure */
res = test_issubvolume(subvol);
if (res < 0) {
- error("cannot access subvolume %s", subvol);
+ error("cannot access subvolume %s: %s", subvol, strerror(-res));
goto out;
}
if (!res) {
}
res = test_isdir(dst);
+ if (res < 0 && res != -ENOENT) {
+ error("cannot access %s: %s", dst, strerror(-res));
+ goto out;
+ }
if (res == 0) {
error("'%s' exists and it is not a directory", dst);
goto out;
u64 default_id;
DIR *dirstream = NULL;
- if (check_argc_exact(argc, 2))
+ clean_args_no_options(argc, argv, cmd_subvol_get_default_usage);
+
+ if (check_argc_exact(argc - optind, 2))
usage(cmd_subvol_get_default_usage);
subvol = argv[1];
char *subvolid;
DIR *dirstream = NULL;
- if (check_argc_exact(argc, 3))
+ clean_args_no_options(argc, argv, cmd_subvol_set_default_usage);
+
+ if (check_argc_exact(argc - optind, 2))
usage(cmd_subvol_set_default_usage);
- subvolid = argv[1];
- path = argv[2];
+ subvolid = argv[optind];
+ path = argv[optind + 1];
objectid = arg_strtou64(subvolid);
u64 last_gen;
DIR *dirstream = NULL;
- if (check_argc_exact(argc, 3))
+ clean_args_no_options(argc, argv, cmd_subvol_find_new_usage);
+
+ if (check_argc_exact(argc - optind, 2))
usage(cmd_subvol_find_new_usage);
- subvol = argv[1];
- last_gen = arg_strtou64(argv[2]);
+ subvol = argv[optind];
+ last_gen = arg_strtou64(argv[optind + 1]);
ret = test_issubvolume(subvol);
if (ret < 0) {
- error("cannot access subvolume %s", subvol);
+ error("cannot access subvolume %s: %s", subvol, strerror(-ret));
return 1;
}
if (!ret) {
int ret = 1;
DIR *dirstream1 = NULL, *dirstream2 = NULL;
- if (check_argc_exact(argc, 2))
+ clean_args_no_options(argc, argv, cmd_subvol_show_usage);
+
+ if (check_argc_exact(argc - optind, 1))
usage(cmd_subvol_show_usage);
- fullpath = realpath(argv[1], NULL);
+ fullpath = realpath(argv[optind], NULL);
if (!fullpath) {
error("cannot find real path for '%s': %s",
- argv[1], strerror(errno));
+ argv[optind], strerror(errno));
goto out;
}
ret = test_issubvolume(fullpath);
if (ret < 0) {
- error("cannot access subvolume %s", fullpath);
+ error("cannot access subvolume %s: %s", fullpath,
+ strerror(-ret));
goto out;
}
if (!ret) {