Whamcloud - gitweb
[COVERITY] Fix memory leak in libe2p (e2p_edit_mntopts)
[tools/e2fsprogs.git] / lib / e2p / feature.c
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
19 struct feature {
20         int             compat;
21         unsigned int    mask;
22         const char      *string;
23 };
24
25 static 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                         "gdt_checksum" },
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         {       0, 0, 0 },
71 };
72
73 const char *e2p_feature2string(int compat, unsigned int mask)
74 {
75         struct feature  *f;
76         static char buf[20];
77         char    fchar;
78         int     fnum;
79
80         for (f = feature_list; f->string; f++) {
81                 if ((compat == f->compat) &&
82                     (mask == f->mask))
83                         return f->string;
84         }
85         switch (compat) {
86         case  E2P_FEATURE_COMPAT:
87                 fchar = 'C';
88                 break;
89         case E2P_FEATURE_INCOMPAT:
90                 fchar = 'I';
91                 break;
92         case E2P_FEATURE_RO_INCOMPAT:
93                 fchar = 'R';
94                 break;
95         default:
96                 fchar = '?';
97                 break;
98         }
99         for (fnum = 0; mask >>= 1; fnum++);
100         sprintf(buf, "FEATURE_%c%d", fchar, fnum);
101         return buf;
102 }
103
104 int e2p_string2feature(char *string, int *compat_type, unsigned int *mask)
105 {
106         struct feature  *f;
107         char            *eptr;
108         int             num;
109
110         for (f = feature_list; f->string; f++) {
111                 if (!strcasecmp(string, f->string)) {
112                         *compat_type = f->compat;
113                         *mask = f->mask;
114                         return 0;
115                 }
116         }
117         if (strncasecmp(string, "FEATURE_", 8))
118                 return 1;
119
120         switch (string[8]) {
121         case 'c':
122         case 'C':
123                 *compat_type = E2P_FEATURE_COMPAT;
124                 break;
125         case 'i':
126         case 'I':
127                 *compat_type = E2P_FEATURE_INCOMPAT;
128                 break;
129         case 'r':
130         case 'R':
131                 *compat_type = E2P_FEATURE_RO_INCOMPAT;
132                 break;
133         default:
134                 return 1;
135         }
136         if (string[9] == 0)
137                 return 1;
138         num = strtol(string+9, &eptr, 10);
139         if (num > 32 || num < 0)
140                 return 1;
141         if (*eptr)
142                 return 1;
143         *mask = 1 << num;
144         return 0;
145 }
146
147 static char *skip_over_blanks(char *cp)
148 {
149         while (*cp && isspace(*cp))
150                 cp++;
151         return cp;
152 }
153
154 static char *skip_over_word(char *cp)
155 {
156         while (*cp && !isspace(*cp) && *cp != ',')
157                 cp++;
158         return cp;
159 }
160
161 /*
162  * Edit a feature set array as requested by the user.  The ok_array,
163  * if set, allows the application to limit what features the user is
164  * allowed to set or clear using this function.
165  */
166 int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array)
167 {
168         char            *cp, *buf, *next;
169         int             neg;
170         unsigned int    mask;
171         int             compat_type;
172         int             rc = 0;
173
174         buf = malloc(strlen(str)+1);
175         if (!buf)
176                 return 1;
177         strcpy(buf, str);
178         for (cp = buf; cp && *cp; cp = next ? next+1 : 0) {
179                 neg = 0;
180                 cp = skip_over_blanks(cp);
181                 next = skip_over_word(cp);
182                 
183                 if (*next == 0)
184                         next = 0;
185                 else
186                         *next = 0;
187
188                 if ((strcasecmp(cp, "none") == 0) ||
189                     (strcasecmp(cp, "clear") == 0)) {
190                         compat_array[0] = 0;
191                         compat_array[1] = 0;
192                         compat_array[2] = 0;
193                         continue;
194                 }
195
196                 switch (*cp) {
197                 case '-':
198                 case '^':
199                         neg++;
200                 case '+':
201                         cp++;
202                         break;
203                 }
204                 if (e2p_string2feature(cp, &compat_type, &mask)) {
205                         rc = 1;
206                         break;
207                 }
208                 if (ok_array && !(ok_array[compat_type] & mask)) {
209                         rc = 1;
210                         break;
211                 }
212                 if (neg)
213                         compat_array[compat_type] &= ~mask;
214                 else
215                         compat_array[compat_type] |= mask;
216         }
217         free(buf);
218         return rc;
219 }