X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lib%2Fe2p%2Ffeature.c;h=b7f6c1d26fe699ac149d0d2c4b95d60ddbbe12df;hb=35b459ffd7b8b60671debe7233d5c558db1afafd;hp=fc6052c18fd3c14e730a38352e2210094de90235;hpb=a49670e64e28ac3b15e36cb6bd0a8135d3ecdbbb;p=tools%2Fe2fsprogs.git diff --git a/lib/e2p/feature.c b/lib/e2p/feature.c index fc6052c..b7f6c1d 100644 --- a/lib/e2p/feature.c +++ b/lib/e2p/feature.c @@ -1,13 +1,15 @@ /* * feature.c --- convert between features and strings - * + * * Copyright (C) 1999 Theodore Ts'o - * - * This file can be redistributed under the terms of the GNU Library General - * Public License - * + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% */ +#include "config.h" #include #include #include @@ -15,6 +17,8 @@ #include #include "e2p.h" +#include +#include struct feature { int compat; @@ -37,6 +41,10 @@ static struct feature feature_list[] = { "resize_inode" }, { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_LAZY_BG, "lazy_bg" }, + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP, + "snapshot_bitmap" }, + { E2P_FEATURE_COMPAT, EXT4_FEATURE_COMPAT_SPARSE_SUPER2, + "sparse_super2" }, { E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER, "sparse_super" }, @@ -45,11 +53,25 @@ static struct feature feature_list[] = { { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_HUGE_FILE, "huge_file" }, { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_GDT_CSUM, - "gdt_checksum" }, + "uninit_bg" }, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_GDT_CSUM, + "uninit_groups" }, { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_DIR_NLINK, "dir_nlink" }, { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE, "extra_isize" }, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_QUOTA, + "quota" }, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_BIGALLOC, + "bigalloc"}, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_METADATA_CSUM, + "metadata_csum"}, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_REPLICA, + "replica" }, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_READONLY, + "read-only" }, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_PROJECT, + "project"}, { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_COMPRESSION, "compression" }, @@ -60,18 +82,49 @@ static struct feature feature_list[] = { { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV, "journal_dev" }, { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS, + "extent" }, + { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS, "extents" }, { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_META_BG, "meta_bg" }, - { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS, - "extent" }, { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_64BIT, "64bit" }, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_MMP, + "mmp" }, { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_FLEX_BG, - "flex_bg"}, + "flex_bg"}, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_EA_INODE, + "ea_inode"}, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_DIRDATA, + "dirdata"}, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_CSUM_SEED, + "metadata_csum_seed"}, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_LARGEDIR, + "large_dir"}, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_INLINE_DATA, + "inline_data"}, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_ENCRYPT, + "encrypt"}, { 0, 0, 0 }, }; +static struct feature jrnl_feature_list[] = { + { E2P_FEATURE_COMPAT, JFS_FEATURE_COMPAT_CHECKSUM, + "journal_checksum" }, + + { E2P_FEATURE_INCOMPAT, JFS_FEATURE_INCOMPAT_REVOKE, + "journal_incompat_revoke" }, + { E2P_FEATURE_INCOMPAT, JFS_FEATURE_INCOMPAT_64BIT, + "journal_64bit" }, + { E2P_FEATURE_INCOMPAT, JFS_FEATURE_INCOMPAT_ASYNC_COMMIT, + "journal_async_commit" }, + { E2P_FEATURE_INCOMPAT, JFS_FEATURE_INCOMPAT_CSUM_V2, + "journal_checksum_v2" }, + { E2P_FEATURE_INCOMPAT, JFS_FEATURE_INCOMPAT_CSUM_V3, + "journal_checksum_v3" }, + { 0, 0, 0 }, +}; + const char *e2p_feature2string(int compat, unsigned int mask) { struct feature *f; @@ -138,7 +191,7 @@ int e2p_string2feature(char *string, int *compat_type, unsigned int *mask) if (string[9] == 0) return 1; num = strtol(string+9, &eptr, 10); - if (num > 32 || num < 0) + if (num > 31 || num < 0) return 1; if (*eptr) return 1; @@ -146,6 +199,79 @@ int e2p_string2feature(char *string, int *compat_type, unsigned int *mask) return 0; } +const char *e2p_jrnl_feature2string(int compat, unsigned int mask) +{ + struct feature *f; + static char buf[20]; + char fchar; + int fnum; + + for (f = jrnl_feature_list; f->string; f++) { + if ((compat == f->compat) && + (mask == f->mask)) + return f->string; + } + switch (compat) { + case E2P_FEATURE_COMPAT: + fchar = 'C'; + break; + case E2P_FEATURE_INCOMPAT: + fchar = 'I'; + break; + case E2P_FEATURE_RO_INCOMPAT: + fchar = 'R'; + break; + default: + fchar = '?'; + break; + } + for (fnum = 0; mask >>= 1; fnum++); + sprintf(buf, "FEATURE_%c%d", fchar, fnum); + return buf; +} + +int e2p_jrnl_string2feature(char *string, int *compat_type, unsigned int *mask) +{ + struct feature *f; + char *eptr; + int num; + + for (f = jrnl_feature_list; f->string; f++) { + if (!strcasecmp(string, f->string)) { + *compat_type = f->compat; + *mask = f->mask; + return 0; + } + } + if (strncasecmp(string, "FEATURE_", 8)) + return 1; + + switch (string[8]) { + case 'c': + case 'C': + *compat_type = E2P_FEATURE_COMPAT; + break; + case 'i': + case 'I': + *compat_type = E2P_FEATURE_INCOMPAT; + break; + case 'r': + case 'R': + *compat_type = E2P_FEATURE_RO_INCOMPAT; + break; + default: + return 1; + } + if (string[9] == 0) + return 1; + num = strtol(string+9, &eptr, 10); + if (num > 31 || num < 0) + return 1; + if (*eptr) + return 1; + *mask = 1 << num; + return 0; +} static char *skip_over_blanks(char *cp) { while (*cp && isspace(*cp)) @@ -163,11 +289,11 @@ static char *skip_over_word(char *cp) /* * Edit a feature set array as requested by the user. The ok_array, * if set, allows the application to limit what features the user is - * allowed to set or clear using this function. If clear_ok_array is set, + * allowed to set or clear using this function. If clear_ok_array is set, * then use it tell whether or not it is OK to clear a filesystem feature. */ int e2p_edit_feature2(const char *str, __u32 *compat_array, __u32 *ok_array, - __u32 *clear_ok_array, int *type_err, + __u32 *clear_ok_array, int *type_err, unsigned int *mask_err) { char *cp, *buf, *next; @@ -192,7 +318,7 @@ int e2p_edit_feature2(const char *str, __u32 *compat_array, __u32 *ok_array, neg = 0; cp = skip_over_blanks(cp); next = skip_over_word(cp); - + if (*next == 0) next = 0; else @@ -210,6 +336,7 @@ int e2p_edit_feature2(const char *str, __u32 *compat_array, __u32 *ok_array, case '-': case '^': neg++; + /* fallthrough */ case '+': cp++; break; @@ -219,11 +346,11 @@ int e2p_edit_feature2(const char *str, __u32 *compat_array, __u32 *ok_array, break; } if (neg) { - if (clear_ok_array && + if (clear_ok_array && !(clear_ok_array[compat_type] & mask)) { rc = 1; if (type_err) - *type_err = (compat_type | + *type_err = (compat_type | E2P_FEATURE_NEGATE_FLAG); if (mask_err) *mask_err = mask; @@ -250,3 +377,47 @@ int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array) { return e2p_edit_feature2(str, compat_array, ok_array, 0, 0, 0); } + +#ifdef TEST_PROGRAM +int main(int argc, char **argv) +{ + int compat, compat2, i; + unsigned int mask, mask2; + const char *str; + struct feature *f; + + for (i = 0; i < 2; i++) { + if (i == 0) { + f = feature_list; + printf("Feature list:\n"); + } else { + printf("\nJournal feature list:\n"); + f = jrnl_feature_list; + } + for (; f->string; f++) { + if (i == 0) { + e2p_string2feature((char *)f->string, &compat, + &mask); + str = e2p_feature2string(compat, mask); + } else { + e2p_jrnl_string2feature((char *)f->string, + &compat, &mask); + str = e2p_jrnl_feature2string(compat, mask); + } + + printf("\tCompat = %d, Mask = %u, %s\n", + compat, mask, f->string); + if (strcmp(f->string, str)) { + if (e2p_string2feature((char *) str, &compat2, + &mask2) || + (compat2 != compat) || + (mask2 != mask)) { + fprintf(stderr, "Failure!\n"); + exit(1); + } + } + } + } + exit(0); +} +#endif