feature.c 3.9 KB

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