busybox/e2fsprogs/old_e2fsprogs/e2p/feature.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * feature.c --- convert between features and strings
   4 *
   5 * Copyright (C) 1999  Theodore Ts'o <tytso@mit.edu>
   6 *
   7 * This file can be redistributed under the terms of the GNU Library General
   8 * Public License
   9 *
  10 */
  11
  12#include <stdio.h>
  13#include <stdlib.h>
  14#include <string.h>
  15#include <ctype.h>
  16#include <errno.h>
  17
  18#include "e2p.h"
  19
  20struct feature {
  21        int             compat;
  22        unsigned int    mask;
  23        const char      *string;
  24};
  25
  26static const struct feature feature_list[] = {
  27        {       E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_PREALLOC,
  28                        "dir_prealloc" },
  29        {       E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL,
  30                        "has_journal" },
  31        {       E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_IMAGIC_INODES,
  32                        "imagic_inodes" },
  33        {       E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_EXT_ATTR,
  34                        "ext_attr" },
  35        {       E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_INDEX,
  36                        "dir_index" },
  37        {       E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_RESIZE_INODE,
  38                        "resize_inode" },
  39        {       E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER,
  40                        "sparse_super" },
  41        {       E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_LARGE_FILE,
  42                        "large_file" },
  43        {       E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_COMPRESSION,
  44                        "compression" },
  45        {       E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_FILETYPE,
  46                        "filetype" },
  47        {       E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_RECOVER,
  48                        "needs_recovery" },
  49        {       E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV,
  50                        "journal_dev" },
  51        {       E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS,
  52                        "extents" },
  53        {       E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_META_BG,
  54                        "meta_bg" },
  55        {       0, 0, 0 },
  56};
  57
  58const char *e2p_feature2string(int compat, unsigned int mask)
  59{
  60        const struct feature *f;
  61        static char buf[20];
  62        char fchar;
  63        int fnum;
  64
  65        for (f = feature_list; f->string; f++) {
  66                if ((compat == f->compat) &&
  67                    (mask == f->mask))
  68                        return f->string;
  69        }
  70        switch (compat) {
  71        case E2P_FEATURE_COMPAT:
  72                fchar = 'C';
  73                break;
  74        case E2P_FEATURE_INCOMPAT:
  75                fchar = 'I';
  76                break;
  77        case E2P_FEATURE_RO_INCOMPAT:
  78                fchar = 'R';
  79                break;
  80        default:
  81                fchar = '?';
  82                break;
  83        }
  84        for (fnum = 0; mask >>= 1; fnum++);
  85                sprintf(buf, "FEATURE_%c%d", fchar, fnum);
  86        return buf;
  87}
  88
  89int e2p_string2feature(char *string, int *compat_type, unsigned int *mask)
  90{
  91        const struct feature *f;
  92        char *eptr;
  93        int num;
  94
  95        for (f = feature_list; f->string; f++) {
  96                if (!strcasecmp(string, f->string)) {
  97                        *compat_type = f->compat;
  98                        *mask = f->mask;
  99                        return 0;
 100                }
 101        }
 102        if (strncasecmp(string, "FEATURE_", 8))
 103                return 1;
 104
 105        switch (string[8]) {
 106        case 'c':
 107        case 'C':
 108                *compat_type = E2P_FEATURE_COMPAT;
 109                break;
 110        case 'i':
 111        case 'I':
 112                *compat_type = E2P_FEATURE_INCOMPAT;
 113                break;
 114        case 'r':
 115        case 'R':
 116                *compat_type = E2P_FEATURE_RO_INCOMPAT;
 117                break;
 118        default:
 119                return 1;
 120        }
 121        if (string[9] == 0)
 122                return 1;
 123        num = strtol(string+9, &eptr, 10);
 124        if (num > 32 || num < 0)
 125                return 1;
 126        if (*eptr)
 127                return 1;
 128        *mask = 1 << num;
 129        return 0;
 130}
 131
 132static inline char *skip_over_blanks(char *cp)
 133{
 134        while (*cp && isspace(*cp))
 135                cp++;
 136        return cp;
 137}
 138
 139static inline char *skip_over_word(char *cp)
 140{
 141        while (*cp && !isspace(*cp) && *cp != ',')
 142                cp++;
 143        return cp;
 144}
 145
 146/*
 147 * Edit a feature set array as requested by the user.  The ok_array,
 148 * if set, allows the application to limit what features the user is
 149 * allowed to set or clear using this function.
 150 */
 151int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array)
 152{
 153        char    *cp, *buf, *next;
 154        int     neg;
 155        unsigned int    mask;
 156        int             compat_type;
 157
 158        buf = xstrdup(str);
 159        cp = buf;
 160        while (cp && *cp) {
 161                neg = 0;
 162                cp = skip_over_blanks(cp);
 163                next = skip_over_word(cp);
 164                if (*next == 0)
 165                        next = 0;
 166                else
 167                        *next = 0;
 168                switch (*cp) {
 169                case '-':
 170                case '^':
 171                        neg++;
 172                case '+':
 173                        cp++;
 174                        break;
 175                }
 176                if (e2p_string2feature(cp, &compat_type, &mask))
 177                        return 1;
 178                if (ok_array && !(ok_array[compat_type] & mask))
 179                        return 1;
 180                if (neg)
 181                        compat_array[compat_type] &= ~mask;
 182                else
 183                        compat_array[compat_type] |= mask;
 184                cp = next ? next+1 : 0;
 185        }
 186        return 0;
 187}
 188