feature.c revision 3542ba0d37fe58eba91b1b42f20de0fdbfb2ac43
1/* 2 * feature.c --- convert between features and strings 3 * 4 * Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu> 5 * 6 * This file can be redistributed under the terms of the GNU Library General 7 * Public License 8 * 9 */ 10 11#include <stdio.h> 12#include <stdlib.h> 13#include <string.h> 14#include <ctype.h> 15#include <errno.h> 16 17#include "e2p.h" 18 19struct feature { 20 int compat; 21 unsigned int mask; 22 const char *string; 23}; 24 25static struct feature feature_list[] = { 26 { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_PREALLOC, 27 "dir_prealloc" }, 28 { E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL, 29 "has_journal" }, 30 { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_IMAGIC_INODES, 31 "imagic_inodes" }, 32 { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_EXT_ATTR, 33 "ext_attr" }, 34 { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_INDEX, 35 "dir_index" }, 36 { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_RESIZE_INODE, 37 "resize_inode" }, 38 { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_LAZY_BG, 39 "lazy_bg" }, 40 41 { E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER, 42 "sparse_super" }, 43 { E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_LARGE_FILE, 44 "large_file" }, 45 { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_HUGE_FILE, 46 "huge_file" }, 47 { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_GDT_CSUM, 48 "uninit_groups" }, 49 { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_DIR_NLINK, 50 "dir_nlink" }, 51 { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE, 52 "extra_isize" }, 53 54 { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_COMPRESSION, 55 "compression" }, 56 { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_FILETYPE, 57 "filetype" }, 58 { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_RECOVER, 59 "needs_recovery" }, 60 { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV, 61 "journal_dev" }, 62 { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS, 63 "extents" }, 64 { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_META_BG, 65 "meta_bg" }, 66 { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS, 67 "extent" }, 68 { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_64BIT, 69 "64bit" }, 70 { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_FLEX_BG, 71 "flex_bg"}, 72 { 0, 0, 0 }, 73}; 74 75const char *e2p_feature2string(int compat, unsigned int mask) 76{ 77 struct feature *f; 78 static char buf[20]; 79 char fchar; 80 int fnum; 81 82 for (f = feature_list; f->string; f++) { 83 if ((compat == f->compat) && 84 (mask == f->mask)) 85 return f->string; 86 } 87 switch (compat) { 88 case E2P_FEATURE_COMPAT: 89 fchar = 'C'; 90 break; 91 case E2P_FEATURE_INCOMPAT: 92 fchar = 'I'; 93 break; 94 case E2P_FEATURE_RO_INCOMPAT: 95 fchar = 'R'; 96 break; 97 default: 98 fchar = '?'; 99 break; 100 } 101 for (fnum = 0; mask >>= 1; fnum++); 102 sprintf(buf, "FEATURE_%c%d", fchar, fnum); 103 return buf; 104} 105 106int e2p_string2feature(char *string, int *compat_type, unsigned int *mask) 107{ 108 struct feature *f; 109 char *eptr; 110 int num; 111 112 for (f = feature_list; f->string; f++) { 113 if (!strcasecmp(string, f->string)) { 114 *compat_type = f->compat; 115 *mask = f->mask; 116 return 0; 117 } 118 } 119 if (strncasecmp(string, "FEATURE_", 8)) 120 return 1; 121 122 switch (string[8]) { 123 case 'c': 124 case 'C': 125 *compat_type = E2P_FEATURE_COMPAT; 126 break; 127 case 'i': 128 case 'I': 129 *compat_type = E2P_FEATURE_INCOMPAT; 130 break; 131 case 'r': 132 case 'R': 133 *compat_type = E2P_FEATURE_RO_INCOMPAT; 134 break; 135 default: 136 return 1; 137 } 138 if (string[9] == 0) 139 return 1; 140 num = strtol(string+9, &eptr, 10); 141 if (num > 32 || num < 0) 142 return 1; 143 if (*eptr) 144 return 1; 145 *mask = 1 << num; 146 return 0; 147} 148 149static char *skip_over_blanks(char *cp) 150{ 151 while (*cp && isspace(*cp)) 152 cp++; 153 return cp; 154} 155 156static char *skip_over_word(char *cp) 157{ 158 while (*cp && !isspace(*cp) && *cp != ',') 159 cp++; 160 return cp; 161} 162 163/* 164 * Edit a feature set array as requested by the user. The ok_array, 165 * if set, allows the application to limit what features the user is 166 * allowed to set or clear using this function. If clear_ok_array is set, 167 * then use it tell whether or not it is OK to clear a filesystem feature. 168 */ 169int e2p_edit_feature2(const char *str, __u32 *compat_array, __u32 *ok_array, 170 __u32 *clear_ok_array, int *type_err, 171 unsigned int *mask_err) 172{ 173 char *cp, *buf, *next; 174 int neg; 175 unsigned int mask; 176 int compat_type; 177 int rc = 0; 178 179 if (!clear_ok_array) 180 clear_ok_array = ok_array; 181 182 if (type_err) 183 *type_err = 0; 184 if (mask_err) 185 *mask_err = 0; 186 187 buf = malloc(strlen(str)+1); 188 if (!buf) 189 return 1; 190 strcpy(buf, str); 191 for (cp = buf; cp && *cp; cp = next ? next+1 : 0) { 192 neg = 0; 193 cp = skip_over_blanks(cp); 194 next = skip_over_word(cp); 195 196 if (*next == 0) 197 next = 0; 198 else 199 *next = 0; 200 201 if ((strcasecmp(cp, "none") == 0) || 202 (strcasecmp(cp, "clear") == 0)) { 203 compat_array[0] = 0; 204 compat_array[1] = 0; 205 compat_array[2] = 0; 206 continue; 207 } 208 209 switch (*cp) { 210 case '-': 211 case '^': 212 neg++; 213 case '+': 214 cp++; 215 break; 216 } 217 if (e2p_string2feature(cp, &compat_type, &mask)) { 218 rc = 1; 219 break; 220 } 221 if (neg) { 222 if (clear_ok_array && 223 !(clear_ok_array[compat_type] & mask)) { 224 rc = 1; 225 if (type_err) 226 *type_err = (compat_type | 227 E2P_FEATURE_NEGATE_FLAG); 228 if (mask_err) 229 *mask_err = mask; 230 break; 231 } 232 compat_array[compat_type] &= ~mask; 233 } else { 234 if (ok_array && !(ok_array[compat_type] & mask)) { 235 rc = 1; 236 if (type_err) 237 *type_err = compat_type; 238 if (mask_err) 239 *mask_err = mask; 240 break; 241 } 242 compat_array[compat_type] |= mask; 243 } 244 } 245 free(buf); 246 return rc; 247} 248 249int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array) 250{ 251 return e2p_edit_feature2(str, compat_array, ok_array, 0, 0, 0); 252} 253