btrfs-progs: dump-super: check array_size in print_sys_chunk_array
[platform/upstream/btrfs-progs.git] / utils.c
diff --git a/utils.c b/utils.c
index 9de1ca2..d2489e7 100644 (file)
--- a/utils.c
+++ b/utils.c
@@ -37,8 +37,7 @@
 #include <sys/vfs.h>
 #include <sys/statfs.h>
 #include <linux/magic.h>
-#include <sys/utsname.h>
-#include <linux/version.h>
+#include <getopt.h>
 
 #include "kerncompat.h"
 #include "radix-tree.h"
@@ -50,7 +49,7 @@
 #include "volumes.h"
 #include "ioctl.h"
 #include "commands.h"
-#include "fsfeatures.h"
+#include "mkfs/common.h"
 
 #ifndef BLKDISCARD
 #define BLKDISCARD     _IO(0x12,119)
@@ -124,210 +123,6 @@ int test_uuid_unique(char *fs_uuid)
        return unique;
 }
 
-/*
- * Insert a root item for temporary tree root
- *
- * Only used in make_btrfs_v2().
- */
-#define VERSION_TO_STRING3(a,b,c)      #a "." #b "." #c, KERNEL_VERSION(a,b,c)
-#define VERSION_TO_STRING2(a,b)                #a "." #b, KERNEL_VERSION(a,b,0)
-
-/*
- * Feature stability status and versions: compat <= safe <= default
- */
-static const struct btrfs_fs_feature {
-       const char *name;
-       u64 flag;
-       const char *sysfs_name;
-       /*
-        * Compatibility with kernel of given version. Filesystem can be
-        * mounted.
-        */
-       const char *compat_str;
-       u32 compat_ver;
-       /*
-        * Considered safe for use, but is not on by default, even if the
-        * kernel supports the feature.
-        */
-       const char *safe_str;
-       u32 safe_ver;
-       /*
-        * Considered safe for use and will be turned on by default if
-        * supported by the running kernel.
-        */
-       const char *default_str;
-       u32 default_ver;
-       const char *desc;
-} mkfs_features[] = {
-       { "mixed-bg", BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS,
-               "mixed_groups",
-               VERSION_TO_STRING3(2,6,37),
-               VERSION_TO_STRING3(2,6,37),
-               NULL, 0,
-               "mixed data and metadata block groups" },
-       { "extref", BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF,
-               "extended_iref",
-               VERSION_TO_STRING2(3,7),
-               VERSION_TO_STRING2(3,12),
-               VERSION_TO_STRING2(3,12),
-               "increased hardlink limit per file to 65536" },
-       { "raid56", BTRFS_FEATURE_INCOMPAT_RAID56,
-               "raid56",
-               VERSION_TO_STRING2(3,9),
-               NULL, 0,
-               NULL, 0,
-               "raid56 extended format" },
-       { "skinny-metadata", BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA,
-               "skinny_metadata",
-               VERSION_TO_STRING2(3,10),
-               VERSION_TO_STRING2(3,18),
-               VERSION_TO_STRING2(3,18),
-               "reduced-size metadata extent refs" },
-       { "no-holes", BTRFS_FEATURE_INCOMPAT_NO_HOLES,
-               "no_holes",
-               VERSION_TO_STRING2(3,14),
-               VERSION_TO_STRING2(4,0),
-               NULL, 0,
-               "no explicit hole extents for files" },
-       /* Keep this one last */
-       { "list-all", BTRFS_FEATURE_LIST_ALL, NULL }
-};
-
-static int parse_one_fs_feature(const char *name, u64 *flags)
-{
-       int i;
-       int found = 0;
-
-       for (i = 0; i < ARRAY_SIZE(mkfs_features); i++) {
-               if (name[0] == '^' &&
-                       !strcmp(mkfs_features[i].name, name + 1)) {
-                       *flags &= ~ mkfs_features[i].flag;
-                       found = 1;
-               } else if (!strcmp(mkfs_features[i].name, name)) {
-                       *flags |= mkfs_features[i].flag;
-                       found = 1;
-               }
-       }
-
-       return !found;
-}
-
-void btrfs_parse_features_to_string(char *buf, u64 flags)
-{
-       int i;
-
-       buf[0] = 0;
-
-       for (i = 0; i < ARRAY_SIZE(mkfs_features); i++) {
-               if (flags & mkfs_features[i].flag) {
-                       if (*buf)
-                               strcat(buf, ", ");
-                       strcat(buf, mkfs_features[i].name);
-               }
-       }
-}
-
-void btrfs_process_fs_features(u64 flags)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(mkfs_features); i++) {
-               if (flags & mkfs_features[i].flag) {
-                       printf("Turning ON incompat feature '%s': %s\n",
-                               mkfs_features[i].name,
-                               mkfs_features[i].desc);
-               }
-       }
-}
-
-void btrfs_list_all_fs_features(u64 mask_disallowed)
-{
-       int i;
-
-       fprintf(stderr, "Filesystem features available:\n");
-       for (i = 0; i < ARRAY_SIZE(mkfs_features) - 1; i++) {
-               const struct btrfs_fs_feature *feat = &mkfs_features[i];
-
-               if (feat->flag & mask_disallowed)
-                       continue;
-               fprintf(stderr, "%-20s- %s (0x%llx", feat->name, feat->desc,
-                               feat->flag);
-               if (feat->compat_ver)
-                       fprintf(stderr, ", compat=%s", feat->compat_str);
-               if (feat->safe_ver)
-                       fprintf(stderr, ", safe=%s", feat->safe_str);
-               if (feat->default_ver)
-                       fprintf(stderr, ", default=%s", feat->default_str);
-               fprintf(stderr, ")\n");
-       }
-}
-
-/*
- * Return NULL if all features were parsed fine, otherwise return the name of
- * the first unparsed.
- */
-char* btrfs_parse_fs_features(char *namelist, u64 *flags)
-{
-       char *this_char;
-       char *save_ptr = NULL; /* Satisfy static checkers */
-
-       for (this_char = strtok_r(namelist, ",", &save_ptr);
-            this_char != NULL;
-            this_char = strtok_r(NULL, ",", &save_ptr)) {
-               if (parse_one_fs_feature(this_char, flags))
-                       return this_char;
-       }
-
-       return NULL;
-}
-
-void print_kernel_version(FILE *stream, u32 version)
-{
-       u32 v[3];
-
-       v[0] = version & 0xFF;
-       v[1] = (version >> 8) & 0xFF;
-       v[2] = version >> 16;
-       fprintf(stream, "%u.%u", v[2], v[1]);
-       if (v[0])
-               fprintf(stream, ".%u", v[0]);
-}
-
-u32 get_running_kernel_version(void)
-{
-       struct utsname utsbuf;
-       char *tmp;
-       char *saveptr = NULL;
-       u32 version;
-
-       uname(&utsbuf);
-       if (strcmp(utsbuf.sysname, "Linux") != 0) {
-               error("unsupported system: %s", utsbuf.sysname);
-               exit(1);
-       }
-       /* 1.2.3-4-name */
-       tmp = strchr(utsbuf.release, '-');
-       if (tmp)
-               *tmp = 0;
-
-       tmp = strtok_r(utsbuf.release, ".", &saveptr);
-       if (!string_is_numerical(tmp))
-               return (u32)-1;
-       version = atoi(tmp) << 16;
-       tmp = strtok_r(NULL, ".", &saveptr);
-       if (!string_is_numerical(tmp))
-               return (u32)-1;
-       version |= atoi(tmp) << 8;
-       tmp = strtok_r(NULL, ".", &saveptr);
-       if (tmp) {
-               if (!string_is_numerical(tmp))
-                       return (u32)-1;
-               version |= atoi(tmp);
-       }
-
-       return version;
-}
-
 u64 btrfs_device_size(int fd, struct stat *st)
 {
        u64 size;
@@ -1951,159 +1746,6 @@ out:
        return ret;
 }
 
-#define isoctal(c)     (((c) & ~7) == '0')
-
-static inline void translate(char *f, char *t)
-{
-       while (*f != '\0') {
-               if (*f == '\\' &&
-                   isoctal(f[1]) && isoctal(f[2]) && isoctal(f[3])) {
-                       *t++ = 64*(f[1] & 7) + 8*(f[2] & 7) + (f[3] & 7);
-                       f += 4;
-               } else
-                       *t++ = *f++;
-       }
-       *t = '\0';
-       return;
-}
-
-/*
- * Checks if the swap device.
- * Returns 1 if swap device, < 0 on error or 0 if not swap device.
- */
-static int is_swap_device(const char *file)
-{
-       FILE    *f;
-       struct stat     st_buf;
-       dev_t   dev;
-       ino_t   ino = 0;
-       char    tmp[PATH_MAX];
-       char    buf[PATH_MAX];
-       char    *cp;
-       int     ret = 0;
-
-       if (stat(file, &st_buf) < 0)
-               return -errno;
-       if (S_ISBLK(st_buf.st_mode))
-               dev = st_buf.st_rdev;
-       else if (S_ISREG(st_buf.st_mode)) {
-               dev = st_buf.st_dev;
-               ino = st_buf.st_ino;
-       } else
-               return 0;
-
-       if ((f = fopen("/proc/swaps", "r")) == NULL)
-               return 0;
-
-       /* skip the first line */
-       if (fgets(tmp, sizeof(tmp), f) == NULL)
-               goto out;
-
-       while (fgets(tmp, sizeof(tmp), f) != NULL) {
-               if ((cp = strchr(tmp, ' ')) != NULL)
-                       *cp = '\0';
-               if ((cp = strchr(tmp, '\t')) != NULL)
-                       *cp = '\0';
-               translate(tmp, buf);
-               if (stat(buf, &st_buf) != 0)
-                       continue;
-               if (S_ISBLK(st_buf.st_mode)) {
-                       if (dev == st_buf.st_rdev) {
-                               ret = 1;
-                               break;
-                       }
-               } else if (S_ISREG(st_buf.st_mode)) {
-                       if (dev == st_buf.st_dev && ino == st_buf.st_ino) {
-                               ret = 1;
-                               break;
-                       }
-               }
-       }
-
-out:
-       fclose(f);
-
-       return ret;
-}
-
-/*
- * Check for existing filesystem or partition table on device.
- * Returns:
- *      1 for existing fs or partition
- *      0 for nothing found
- *     -1 for internal error
- */
-static int check_overwrite(const char *device)
-{
-       const char      *type;
-       blkid_probe     pr = NULL;
-       int             ret;
-       blkid_loff_t    size;
-
-       if (!device || !*device)
-               return 0;
-
-       ret = -1; /* will reset on success of all setup calls */
-
-       pr = blkid_new_probe_from_filename(device);
-       if (!pr)
-               goto out;
-
-       size = blkid_probe_get_size(pr);
-       if (size < 0)
-               goto out;
-
-       /* nothing to overwrite on a 0-length device */
-       if (size == 0) {
-               ret = 0;
-               goto out;
-       }
-
-       ret = blkid_probe_enable_partitions(pr, 1);
-       if (ret < 0)
-               goto out;
-
-       ret = blkid_do_fullprobe(pr);
-       if (ret < 0)
-               goto out;
-
-       /*
-        * Blkid returns 1 for nothing found and 0 when it finds a signature,
-        * but we want the exact opposite, so reverse the return value here.
-        *
-        * In addition print some useful diagnostics about what actually is
-        * on the device.
-        */
-       if (ret) {
-               ret = 0;
-               goto out;
-       }
-
-       if (!blkid_probe_lookup_value(pr, "TYPE", &type, NULL)) {
-               fprintf(stderr,
-                       "%s appears to contain an existing "
-                       "filesystem (%s).\n", device, type);
-       } else if (!blkid_probe_lookup_value(pr, "PTTYPE", &type, NULL)) {
-               fprintf(stderr,
-                       "%s appears to contain a partition "
-                       "table (%s).\n", device, type);
-       } else {
-               fprintf(stderr,
-                       "%s appears to contain something weird "
-                       "according to blkid\n", device);
-       }
-       ret = 1;
-
-out:
-       if (pr)
-               blkid_free_probe(pr);
-       if (ret == -1)
-               fprintf(stderr,
-                       "probe of %s failed, cannot detect "
-                         "existing filesystem.\n", device);
-       return ret;
-}
-
 static int group_profile_devs_min(u64 flag)
 {
        switch (flag & BTRFS_BLOCK_GROUP_PROFILE_MASK) {
@@ -2192,63 +1834,6 @@ int group_profile_max_safe_loss(u64 flags)
        }
 }
 
-/*
- * Check if a device is suitable for btrfs
- * returns:
- *  1: something is wrong, an error is printed
- *  0: all is fine
- */
-int test_dev_for_mkfs(const char *file, int force_overwrite)
-{
-       int ret, fd;
-       struct stat st;
-
-       ret = is_swap_device(file);
-       if (ret < 0) {
-               error("checking status of %s: %s", file, strerror(-ret));
-               return 1;
-       }
-       if (ret == 1) {
-               error("%s is a swap device", file);
-               return 1;
-       }
-       if (!force_overwrite) {
-               if (check_overwrite(file)) {
-                       error("use the -f option to force overwrite of %s",
-                                       file);
-                       return 1;
-               }
-       }
-       ret = check_mounted(file);
-       if (ret < 0) {
-               error("cannot check mount status of %s: %s", file,
-                               strerror(-ret));
-               return 1;
-       }
-       if (ret == 1) {
-               error("%s is mounted", file);
-               return 1;
-       }
-       /* check if the device is busy */
-       fd = open(file, O_RDWR|O_EXCL);
-       if (fd < 0) {
-               error("unable to open %s: %s", file, strerror(errno));
-               return 1;
-       }
-       if (fstat(fd, &st)) {
-               error("unable to stat %s: %s", file, strerror(errno));
-               close(fd);
-               return 1;
-       }
-       if (!S_ISBLK(st.st_mode)) {
-               error("%s is not a block device", file);
-               close(fd);
-               return 1;
-       }
-       close(fd);
-       return 0;
-}
-
 int btrfs_scan_devices(void)
 {
        int fd = -1;
@@ -2301,35 +1886,6 @@ int btrfs_scan_devices(void)
        return 0;
 }
 
-int is_vol_small(const char *file)
-{
-       int fd = -1;
-       int e;
-       struct stat st;
-       u64 size;
-
-       fd = open(file, O_RDONLY);
-       if (fd < 0)
-               return -errno;
-       if (fstat(fd, &st) < 0) {
-               e = -errno;
-               close(fd);
-               return e;
-       }
-       size = btrfs_device_size(fd, &st);
-       if (size == 0) {
-               close(fd);
-               return -1;
-       }
-       if (size < BTRFS_MKFS_SMALL_VOLUME_SIZE) {
-               close(fd);
-               return 1;
-       } else {
-               close(fd);
-               return 0;
-       }
-}
-
 /*
  * This reads a line from the stdin and only returns non-zero if the
  * first whitespace delimited token is a case insensitive match with yes
@@ -2403,27 +1959,6 @@ int find_mount_root(const char *path, char **mount_root)
        return ret;
 }
 
-int test_minimum_size(const char *file, u32 nodesize)
-{
-       int fd;
-       struct stat statbuf;
-
-       fd = open(file, O_RDONLY);
-       if (fd < 0)
-               return -errno;
-       if (stat(file, &statbuf) < 0) {
-               close(fd);
-               return -errno;
-       }
-       if (btrfs_device_size(fd, &statbuf) < btrfs_min_dev_size(nodesize)) {
-               close(fd);
-               return 1;
-       }
-       close(fd);
-       return 0;
-}
-
-
 /*
  * Test if path is a directory
  * Returns:
@@ -2731,6 +2266,32 @@ unsigned int get_unit_mode_from_arg(int *argc, char *argv[], int df_mode)
        return unit_mode;
 }
 
+u64 div_factor(u64 num, int factor)
+{
+       if (factor == 10)
+               return num;
+       num *= factor;
+       num /= 10;
+       return num;
+}
+/*
+ * Get the length of the string converted from a u64 number.
+ *
+ * Result is equal to log10(num) + 1, but without the use of math library.
+ */
+int count_digits(u64 num)
+{
+       int ret = 0;
+
+       if (num == 0)
+               return 1;
+       while (num > 0) {
+               ret++;
+               num /= 10;
+       }
+       return ret;
+}
+
 int string_is_numerical(const char *str)
 {
        if (!str)
@@ -2744,6 +2305,15 @@ int string_is_numerical(const char *str)
        return 1;
 }
 
+int prefixcmp(const char *str, const char *prefix)
+{
+       for (; ; str++, prefix++)
+               if (!*prefix)
+                       return 0;
+               else if (*str != *prefix)
+                       return (unsigned char)*prefix - (unsigned char)*str;
+}
+
 /* Subvolume helper functions */
 /*
  * test if name is a correct subvolume name
@@ -2862,6 +2432,7 @@ out:
        return ret;
 }
 
+/* Set the seed manually */
 void init_rand_seed(u64 seed)
 {
        int i;
@@ -2911,6 +2482,7 @@ u32 rand_u32(void)
        return (u32)jrand48(rand_seed);
 }
 
+/* Return random number in range [0, upper) */
 unsigned int rand_range(unsigned int upper)
 {
        __init_seed();
@@ -2921,6 +2493,31 @@ unsigned int rand_range(unsigned int upper)
        return (unsigned int)(jrand48(rand_seed) % upper);
 }
 
+int rand_int(void)
+{
+       return (int)(rand_u32());
+}
+
+u64 rand_u64(void)
+{
+       u64 ret = 0;
+
+       ret += rand_u32();
+       ret <<= 32;
+       ret += rand_u32();
+       return ret;
+}
+
+u16 rand_u16(void)
+{
+       return (u16)(rand_u32());
+}
+
+u8 rand_u8(void)
+{
+       return (u8)(rand_u32());
+}
+
 void btrfs_config_init(void)
 {
 }