feature.c revision 39dc1c45cb41ce37a56d364103bb852d0b62c835
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_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER, 39 "sparse_super" }, 40 { E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_LARGE_FILE, 41 "large_file" }, 42 { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_COMPRESSION, 43 "compression" }, 44 { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_FILETYPE, 45 "filetype" }, 46 { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_RECOVER, 47 "needs_recovery" }, 48 { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV, 49 "journal_dev" }, 50 { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS, 51 "extents" }, 52 { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_META_BG, 53 "meta_bg" }, 54 { 0, 0, 0 }, 55}; 56 57const char *e2p_feature2string(int compat, unsigned int mask) 58{ 59 struct feature *f; 60 static char buf[20]; 61 char fchar; 62 int fnum; 63 64 for (f = feature_list; f->string; f++) { 65 if ((compat == f->compat) && 66 (mask == f->mask)) 67 return f->string; 68 } 69 switch (compat) { 70 case E2P_FEATURE_COMPAT: 71 fchar = 'C'; 72 break; 73 case E2P_FEATURE_INCOMPAT: 74 fchar = 'I'; 75 break; 76 case E2P_FEATURE_RO_INCOMPAT: 77 fchar = 'R'; 78 break; 79 default: 80 fchar = '?'; 81 break; 82 } 83 for (fnum = 0; mask >>= 1; fnum++); 84 sprintf(buf, "FEATURE_%c%d", fchar, fnum); 85 return buf; 86} 87 88int e2p_string2feature(char *string, int *compat_type, unsigned int *mask) 89{ 90 struct feature *f; 91 char *eptr; 92 int num; 93 94 for (f = feature_list; f->string; f++) { 95 if (!strcasecmp(string, f->string)) { 96 *compat_type = f->compat; 97 *mask = f->mask; 98 return 0; 99 } 100 } 101 if (strncasecmp(string, "FEATURE_", 8)) 102 return 1; 103 104 switch (string[8]) { 105 case 'c': 106 case 'C': 107 *compat_type = E2P_FEATURE_COMPAT; 108 break; 109 case 'i': 110 case 'I': 111 *compat_type = E2P_FEATURE_INCOMPAT; 112 break; 113 case 'r': 114 case 'R': 115 *compat_type = E2P_FEATURE_RO_INCOMPAT; 116 break; 117 default: 118 return 1; 119 } 120 if (string[9] == 0) 121 return 1; 122 num = strtol(string+9, &eptr, 10); 123 if (num > 32 || num < 0) 124 return 1; 125 if (*eptr) 126 return 1; 127 *mask = 1 << num; 128 return 0; 129} 130 131static char *skip_over_blanks(char *cp) 132{ 133 while (*cp && isspace(*cp)) 134 cp++; 135 return cp; 136} 137 138static char *skip_over_word(char *cp) 139{ 140 while (*cp && !isspace(*cp) && *cp != ',') 141 cp++; 142 return cp; 143} 144 145/* 146 * Edit a feature set array as requested by the user. The ok_array, 147 * if set, allows the application to limit what features the user is 148 * allowed to set or clear using this function. 149 */ 150int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array) 151{ 152 char *cp, *buf, *next; 153 int neg; 154 unsigned int mask; 155 int compat_type; 156 157 buf = malloc(strlen(str)+1); 158 if (!buf) 159 return 1; 160 strcpy(buf, str); 161 cp = buf; 162 while (cp && *cp) { 163 neg = 0; 164 cp = skip_over_blanks(cp); 165 next = skip_over_word(cp); 166 if (*next == 0) 167 next = 0; 168 else 169 *next = 0; 170 switch (*cp) { 171 case '-': 172 case '^': 173 neg++; 174 case '+': 175 cp++; 176 break; 177 } 178 if (e2p_string2feature(cp, &compat_type, &mask)) 179 return 1; 180 if (ok_array && !(ok_array[compat_type] & mask)) 181 return 1; 182 if (neg) 183 compat_array[compat_type] &= ~mask; 184 else 185 compat_array[compat_type] |= mask; 186 cp = next ? next+1 : 0; 187 } 188 return 0; 189} 190 191