btrfs-progs: reorder extent buffer members for better packing
[platform/upstream/btrfs-progs.git] / cmds-property.c
index 6699e61..03bafa0 100644 (file)
 #include "commands.h"
 #include "props.h"
 #include "ctree.h"
+#include "utils.h"
+#include "help.h"
 
 static const char * const property_cmd_group_usage[] = {
        "btrfs property get/set/list [-t <type>] <object> [<name>] [value]",
        NULL
 };
 
-static const char * const cmd_get_usage[] = {
-       "btrfs property get [-t <type>] <object> [<name>]",
-       "Gets a property from a btrfs object.",
-       "If no name is specified, all properties for the given object are",
-       "printed.",
-       "A filesystem object can be a the filesystem itself, a subvolume,",
-       "an inode or a device. The '-t <type>' option can be used to explicitly",
-       "specify what type of object you meant. This is only needed when a",
-       "property could be set for more then one object type. Possible types",
-       "are s[ubvol], f[ilesystem], i[node] and d[evice].",
-       NULL
-};
-
-static const char * const cmd_set_usage[] = {
-       "btrfs property set [-t <type>] <object> <name> <value>",
-       "Sets a property on a btrfs object.",
-       "Please see the help of 'btrfs property get' for a description of",
-       "objects and object types.",
-       NULL
-};
-
-static const char * const cmd_list_usage[] = {
-       "btrfs property list [-t <type>] <object>",
-       "Lists available properties with their descriptions for the given object.",
-       "Please see the help of 'btrfs property get' for a description of",
-       "objects and object types.",
-       NULL
-};
-
 static int parse_prop(const char *arg, const struct prop_handler *props,
                      const struct prop_handler **prop_ret)
 {
@@ -75,41 +48,12 @@ static int parse_prop(const char *arg, const struct prop_handler *props,
        return -1;
 }
 
-static int get_fsid(const char *path, u8 *fsid)
-{
-       int ret;
-       int fd;
-       struct btrfs_ioctl_fs_info_args args;
-
-       fd = open(path, O_RDONLY);
-       if (fd < 0) {
-               ret = -errno;
-               fprintf(stderr, "ERROR: open %s failed. %s\n", path,
-                               strerror(-ret));
-               goto out;
-       }
-
-       ret = ioctl(fd, BTRFS_IOC_FS_INFO, &args);
-       if (ret < 0) {
-               ret = -errno;
-               goto out;
-       }
-
-       memcpy(fsid, args.fsid, BTRFS_FSID_SIZE);
-       ret = 0;
-
-out:
-       if (fd != -1)
-               close(fd);
-       return ret;
-}
-
 static int check_btrfs_object(const char *object)
 {
        int ret;
        u8 fsid[BTRFS_FSID_SIZE];
 
-       ret = get_fsid(object, fsid);
+       ret = get_fsid(object, fsid, 0);
        if (ret < 0)
                ret = 0;
        else
@@ -122,7 +66,18 @@ static int check_is_root(const char *object)
        int ret;
        u8 fsid[BTRFS_FSID_SIZE];
        u8 fsid2[BTRFS_FSID_SIZE];
-       char *tmp;
+       char *tmp = NULL;
+       char *rp;
+
+       rp = realpath(object, NULL);
+       if (!rp) {
+               ret = -errno;
+               goto out;
+       }
+       if (!strcmp(rp, "/")) {
+               ret = 0;
+               goto out;
+       }
 
        tmp = malloc(strlen(object) + 5);
        if (!tmp) {
@@ -134,20 +89,25 @@ static int check_is_root(const char *object)
                strcat(tmp, "/");
        strcat(tmp, "..");
 
-       ret = get_fsid(object, fsid);
+       ret = get_fsid(object, fsid, 0);
        if (ret < 0) {
-               fprintf(stderr, "ERROR: get_fsid for %s failed. %s\n", object,
-                               strerror(-ret));
+               error("get_fsid for %s failed: %s", object, strerror(-ret));
                goto out;
        }
 
-       ret = get_fsid(tmp, fsid2);
-       if (ret < 0) {
+       ret = get_fsid(tmp, fsid2, 1);
+       if (ret == -ENOTTY) {
                ret = 0;
                goto out;
+       } else if (ret == -ENOTDIR) {
+               ret = 1;
+               goto out;
+       } else if (ret < 0) {
+               error("get_fsid for %s failed: %s", tmp, strerror(-ret));
+               goto out;
        }
 
-       if (!memcmp(fsid, fsid2, BTRFS_FSID_SIZE)) {
+       if (memcmp(fsid, fsid2, BTRFS_FSID_SIZE)) {
                ret = 0;
                goto out;
        }
@@ -156,6 +116,7 @@ static int check_is_root(const char *object)
 
 out:
        free(tmp);
+       free(rp);
        return ret;
 }
 
@@ -195,7 +156,7 @@ static int autodetect_object_types(const char *object, int *types_out)
                ret = check_is_root(object);
                if (ret < 0)
                        goto out;
-               if (ret)
+               if (!ret)
                        types |= prop_object_root;
        }
 
@@ -209,12 +170,6 @@ out:
        return ret;
 }
 
-static int print_prop_help(const struct prop_handler *prop)
-{
-       fprintf(stdout, "%-20s%s\n", prop->name, prop->desc);
-       return 0;
-}
-
 static int dump_prop(const struct prop_handler *prop,
                     const char *object,
                     int types,
@@ -227,7 +182,7 @@ static int dump_prop(const struct prop_handler *prop,
                if (!name_and_help)
                        ret = prop->handler(type, object, prop->name, NULL);
                else
-                       ret = print_prop_help(prop);
+                       printf("%-20s%s\n", prop->name, prop->desc);
        }
        return ret;
 }
@@ -264,32 +219,26 @@ static int setget_prop(int types, const char *object,
 
        ret = parse_prop(name, prop_handlers, &prop);
        if (ret == -1) {
-               fprintf(stderr, "ERROR: property is unknown\n");
+               error("unknown property: %s", name);
                ret = 40;
                goto out;
-       } else if (ret) {
-               fprintf(stderr, "ERROR: parse_prop reported unknown error\n");
-               ret = 42;
-               goto out;
        }
 
        types &= prop->types;
        if (!types) {
-               fprintf(stderr,
-                       "ERROR: object is not compatible with property\n");
+               error("object is not compatible with property: %s", prop->name);
                ret = 47;
                goto out;
        }
 
        if (count_bits(types) > 1) {
-               fprintf(stderr,
-                       "ERROR: type of object is ambiguous. Please specify a type by hand.\n");
+               error("type of object is ambiguous, please use option -t");
                ret = 48;
                goto out;
        }
 
        if (value && prop->read_only) {
-               fprintf(stderr, "ERROR: %s is a read-only property.\n",
+               error("property is read-only property: %s",
                                prop->name);
                ret = 51;
                goto out;
@@ -310,10 +259,11 @@ out:
 static void parse_args(int argc, char **argv,
                       const char * const *usage_str,
                       int *types, char **object,
-                      char **name, char **value)
+                      char **name, char **value, int min_nonopt_args)
 {
        int ret;
        char *type_str = NULL;
+       int max_nonopt_args = 1;
 
        optind = 1;
        while (1) {
@@ -327,10 +277,18 @@ static void parse_args(int argc, char **argv,
                        break;
                default:
                        usage(usage_str);
-                       break;
                }
        }
 
+       if (name)
+               max_nonopt_args++;
+       if (value)
+               max_nonopt_args++;
+
+       if (check_argc_min(argc - optind, min_nonopt_args) ||
+           check_argc_max(argc - optind, max_nonopt_args))
+               usage(usage_str);
+
        *types = 0;
        if (type_str) {
                if (!strcmp(type_str, "s") || !strcmp(type_str, "subvol")) {
@@ -345,54 +303,53 @@ static void parse_args(int argc, char **argv,
                           !strcmp(type_str, "device")) {
                        *types = prop_object_dev;
                } else {
-                       fprintf(stderr, "ERROR: invalid object type.\n");
+                       error("invalid object type: %s", type_str);
                        usage(usage_str);
                }
        }
 
-       if (object && optind < argc)
-               *object = argv[optind++];
-       if (name && optind < argc)
+       *object = argv[optind++];
+       if (optind < argc)
                *name = argv[optind++];
-       if (value && optind < argc)
+       if (optind < argc)
                *value = argv[optind++];
 
-       if (optind != argc) {
-               fprintf(stderr, "ERROR: invalid arguments.\n");
-               usage(usage_str);
-       }
-
-       if (!*types && object && *object) {
+       if (!*types) {
                ret = autodetect_object_types(*object, types);
                if (ret < 0) {
-                       fprintf(stderr,
-                               "ERROR: failed to detect object type. %s\n",
+                       error("failed to detect object type: %s",
                                strerror(-ret));
                        usage(usage_str);
                }
                if (!*types) {
-                       fprintf(stderr,
-                               "ERROR: object is not a btrfs object.\n");
+                       error("object is not a btrfs object: %s", *object);
                        usage(usage_str);
                }
        }
 }
 
-static int cmd_get(int argc, char **argv)
+static const char * const cmd_property_get_usage[] = {
+       "btrfs property get [-t <type>] <object> [<name>]",
+       "Gets a property from a btrfs object.",
+       "If no name is specified, all properties for the given object are",
+       "printed.",
+       "A filesystem object can be a the filesystem itself, a subvolume,",
+       "an inode or a device. The '-t <type>' option can be used to explicitly",
+       "specify what type of object you meant. This is only needed when a",
+       "property could be set for more then one object type. Possible types",
+       "are s[ubvol], f[ilesystem], i[node] and d[evice].",
+       NULL
+};
+
+static int cmd_property_get(int argc, char **argv)
 {
        int ret;
-       char *object;
+       char *object = NULL;
        char *name = NULL;
        int types = 0;
 
-       if (check_argc_min(argc, 2) || check_argc_max(argc, 4))
-               usage(cmd_get_usage);
-
-       parse_args(argc, argv, cmd_get_usage, &types, &object, &name, NULL);
-       if (!object) {
-               fprintf(stderr, "ERROR: invalid arguments.\n");
-               usage(cmd_set_usage);
-       }
+       parse_args(argc, argv, cmd_property_get_usage, &types, &object, &name,
+                  NULL, 1);
 
        if (name)
                ret = setget_prop(types, object, name, NULL);
@@ -402,54 +359,64 @@ static int cmd_get(int argc, char **argv)
        return ret;
 }
 
-static int cmd_set(int argc, char **argv)
+static const char * const cmd_property_set_usage[] = {
+       "btrfs property set [-t <type>] <object> <name> <value>",
+       "Sets a property on a btrfs object.",
+       "Please see the help of 'btrfs property get' for a description of",
+       "objects and object types.",
+       NULL
+};
+
+static int cmd_property_set(int argc, char **argv)
 {
        int ret;
-       char *object;
-       char *name;
-       char *value;
+       char *object = NULL;
+       char *name = NULL;
+       char *value = NULL;
        int types = 0;
 
-       if (check_argc_min(argc, 4) || check_argc_max(argc, 5))
-               usage(cmd_set_usage);
-
-       parse_args(argc, argv, cmd_set_usage, &types, &object, &name, &value);
-       if (!object || !name || !value) {
-               fprintf(stderr, "ERROR: invalid arguments.\n");
-               usage(cmd_set_usage);
-       }
+       parse_args(argc, argv, cmd_property_set_usage, &types,
+                  &object, &name, &value, 3);
 
        ret = setget_prop(types, object, name, value);
 
        return ret;
 }
 
-static int cmd_list(int argc, char **argv)
+static const char * const cmd_property_list_usage[] = {
+       "btrfs property list [-t <type>] <object>",
+       "Lists available properties with their descriptions for the given object.",
+       "Please see the help of 'btrfs property get' for a description of",
+       "objects and object types.",
+       NULL
+};
+
+static int cmd_property_list(int argc, char **argv)
 {
        int ret;
        char *object = NULL;
        int types = 0;
 
-       if (check_argc_min(argc, 2) || check_argc_max(argc, 3))
-               usage(cmd_list_usage);
-
-       parse_args(argc, argv, cmd_list_usage, &types, &object, NULL, NULL);
-       if (!object) {
-               fprintf(stderr, "ERROR: invalid arguments.\n");
-               usage(cmd_set_usage);
-       }
+       parse_args(argc, argv, cmd_property_list_usage,
+                  &types, &object, NULL, NULL, 1);
 
        ret = dump_props(types, object, 1);
 
        return ret;
 }
 
+static const char property_cmd_group_info[] =
+"modify properties of filesystem objects";
+
 const struct cmd_group property_cmd_group = {
-       property_cmd_group_usage, NULL, {
-               { "get", cmd_get, cmd_get_usage, NULL, 0 },
-               { "set", cmd_set, cmd_set_usage, NULL, 0 },
-               { "list", cmd_list, cmd_list_usage, NULL, 0 },
-               { 0, 0, 0, 0, 0 },
+       property_cmd_group_usage, property_cmd_group_info, {
+               { "get", cmd_property_get,
+                       cmd_property_get_usage, NULL, 0 },
+               { "set", cmd_property_set,
+                       cmd_property_set_usage, NULL, 0 },
+               { "list", cmd_property_list,
+                       cmd_property_list_usage, NULL, 0 },
+               NULL_CMD_STRUCT
        }
 };