Tizen 2.0 Release
[platform/kernel/u-boot.git] / fs / ext4 / feature.c
1 /*
2  * feature.c --- convert between features and strings
3  *
4  * Copyright (C) 1999  Theodore Ts'o <tytso@mit.edu>
5  *
6  * %Begin-Header%
7  * This file may be redistributed under the terms of the GNU Library
8  * General Public License, version 2.
9  * %End-Header%
10  */
11
12 #include "e2p.h"
13 #include "ext2fs.h"
14
15 #include "util.h"
16 #include <common.h>
17 #include <linux/stat.h>
18 #include <linux/ctype.h>
19
20 struct feature {
21         int             compat;
22         unsigned int    mask;
23         const char      *string;
24 };
25
26 #define E2P_FEATURE_COMPAT 0
27 #define E2P_FEATURE_INCOMPAT    1
28 #define E2P_FEATURE_RO_INCOMPAT 2
29 #define E2P_FEATURE_TYPE_MASK 0x03
30
31 #define E2P_FEATURE_NEGATE_FLAG 0x80
32
33 #define E2P_FS_FEATURE          0
34 #define E2P_JOURNAL_FEATURE     1
35
36 #define JFS_FEATURE_COMPAT_CHECKSUM 0x00000001
37
38 #define JFS_FEATURE_INCOMPAT_REVOKE 0x00000001
39
40 #define JFS_FEATURE_INCOMPAT_REVOKE     0x00000001
41 #define JFS_FEATURE_INCOMPAT_64BIT              0x00000002
42 #define JFS_FEATURE_INCOMPAT_ASYNC_COMMIT 0x00000004
43
44 /* Features known to this kernel version: */
45 #define JFS_KNOWN_COMPAT_FEATURES       0
46 #define JFS_KNOWN_ROCOMPAT_FEATURES 0
47 #define JFS_KNOWN_INCOMPAT_FEATURES (JFS_FEATURE_INCOMPAT_REVOKE|\
48                                          JFS_FEATURE_INCOMPAT_ASYNC_COMMIT)
49
50 static struct feature feature_list[] = {
51         {       E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_PREALLOC,
52                         "dir_prealloc" },
53         {       E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL,
54                         "has_journal" },
55         {       E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_IMAGIC_INODES,
56                         "imagic_inodes" },
57         {       E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_EXT_ATTR,
58                         "ext_attr" },
59         {       E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_INDEX,
60                         "dir_index" },
61         {       E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_RESIZE_INODE,
62                         "resize_inode" },
63         {       E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_LAZY_BG,
64                         "lazy_bg" },
65
66         {       E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER,
67                         "sparse_super" },
68         {       E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_LARGE_FILE,
69                         "large_file" },
70         {       E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_HUGE_FILE,
71                         "huge_file" },
72         {       E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_GDT_CSUM,
73                         "uninit_bg" },
74         {       E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_GDT_CSUM,
75                         "uninit_groups" },
76         {       E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_DIR_NLINK,
77                         "dir_nlink" },
78         {       E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE,
79                         "extra_isize" },
80
81         {       E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_COMPRESSION,
82                         "compression" },
83         {       E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_FILETYPE,
84                         "filetype" },
85         {       E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_RECOVER,
86                         "needs_recovery" },
87         {       E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV,
88                         "journal_dev" },
89         {       E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS,
90                         "extent" },
91         {       E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS,
92                         "extents" },
93         {       E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_META_BG,
94                         "meta_bg" },
95         {       E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_64BIT,
96                         "64bit" },
97         {       E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_FLEX_BG,
98                         "flex_bg"},
99         {       0, 0, 0 },
100 };
101
102 static struct feature jrnl_feature_list[] = {
103        {       E2P_FEATURE_COMPAT, JFS_FEATURE_COMPAT_CHECKSUM,
104                        "journal_checksum" },
105
106        {       E2P_FEATURE_INCOMPAT, JFS_FEATURE_INCOMPAT_REVOKE,
107                        "journal_incompat_revoke" },
108        {       E2P_FEATURE_INCOMPAT, JFS_FEATURE_INCOMPAT_ASYNC_COMMIT,
109                        "journal_async_commit" },
110        {       0, 0, 0 },
111 };
112
113 const char *e2p_feature2string(int compat, unsigned int mask)
114 {
115         struct feature  *f;
116         static char buf[20];
117         char    fchar;
118         int     fnum;
119
120         for (f = feature_list; f->string; f++) {
121                 if ((compat == f->compat) &&
122                     (mask == f->mask))
123                         return f->string;
124         }
125         switch (compat) {
126         case  E2P_FEATURE_COMPAT:
127                 fchar = 'C';
128                 break;
129         case E2P_FEATURE_INCOMPAT:
130                 fchar = 'I';
131                 break;
132         case E2P_FEATURE_RO_INCOMPAT:
133                 fchar = 'R';
134                 break;
135         default:
136                 fchar = '?';
137                 break;
138         }
139         for (fnum = 0; mask >>= 1; fnum++);
140         sprintf(buf, "FEATURE_%c%d", fchar, fnum);
141         return buf;
142 }
143
144 /* strtoul API */
145 long ConvertString(char* buffer)
146 {
147                   char *ptr;
148                   long result=0;
149                   int i=0;
150                   ptr = buffer;
151                   while(*ptr!='\0')
152                   {
153                                          result = (result * 10) + (*ptr - '0');
154                                          ptr++;i++;
155                   }
156                   return result;
157 }
158
159
160 int e2p_string2feature(char *string, int *compat_type, unsigned int *mask)
161 {
162         struct feature  *f;
163         char            *eptr=NULL;
164         int             num;
165         char *temp=NULL; 
166         char buff[50]; 
167         int i=0; 
168
169         for (f = feature_list; f->string; f++) {
170                         if (!strcmp(string, f->string)) {
171                         *compat_type = f->compat;
172                         *mask = f->mask;
173                         return 0;
174                 }
175         }
176                 if (strncmp(string, "FEATURE_", 8))
177                 return 1;
178
179         switch (string[8]) {
180         case 'c':
181         case 'C':
182                 *compat_type = E2P_FEATURE_COMPAT;
183                 break;
184         case 'i':
185         case 'I':
186                 *compat_type = E2P_FEATURE_INCOMPAT;
187                 break;
188         case 'r':
189         case 'R':
190                 *compat_type = E2P_FEATURE_RO_INCOMPAT;
191                 break;
192         default:
193                 return 1;
194         }
195         if (string[9] == 0)
196                 return 1;
197         
198         /*uma added 
199          * Implemented strtoul API 
200         */
201         temp= string +9;
202         while(*temp !='\0')
203                 {
204                         buff[i]= *temp;
205                         i++;
206                 }
207         buff[i]='\0';
208
209         
210         for(i=0;i<strlen(buff);i++)
211                   {
212                           if(buff[i]>=48 && buff[i]<=57)
213                           {
214                           }
215                           else
216                           {
217                                         buff[i]='\0';
218                           }
219                   }
220          num=ConvertString(buff);
221
222         
223         if (num > 32 || num < 0)
224                 return 1;
225         if (*eptr)
226                 return 1;
227         *mask = 1 << num;
228         return 0;
229 }
230
231 const char *e2p_jrnl_feature2string(int compat, unsigned int mask)
232 {
233         struct feature  *f;
234         static char buf[20];
235         char    fchar;
236         int     fnum;
237
238         for (f = jrnl_feature_list; f->string; f++) {
239                 if ((compat == f->compat) &&
240                     (mask == f->mask))
241                         return f->string;
242         }
243         switch (compat) {
244         case  E2P_FEATURE_COMPAT:
245                 fchar = 'C';
246                 break;
247         case E2P_FEATURE_INCOMPAT:
248                 fchar = 'I';
249                 break;
250         case E2P_FEATURE_RO_INCOMPAT:
251                 fchar = 'R';
252                 break;
253         default:
254                 fchar = '?';
255                 break;
256         }
257         for (fnum = 0; mask >>= 1; fnum++);
258         sprintf(buf, "FEATURE_%c%d", fchar, fnum);
259         return buf;
260 }
261
262
263 #if 0
264 //uma 
265 int e2p_jrnl_string2feature(char *string, int *compat_type, unsigned int *mask)
266 {
267         struct feature  *f;
268         char            *eptr;
269         int             num;
270
271         for (f = jrnl_feature_list; f->string; f++) {
272                 if (!strcasecmp(string, f->string)) {
273                         *compat_type = f->compat;
274                         *mask = f->mask;
275                         return 0;
276                 }
277         }
278
279         //umacif (strncasecmp(string, "FEATURE_", 8))
280                 //return 1;
281
282         switch (string[8]) {
283         case 'c':
284         case 'C':
285                 *compat_type = E2P_FEATURE_COMPAT;
286                 break;
287         case 'i':
288         case 'I':
289                 *compat_type = E2P_FEATURE_INCOMPAT;
290                 break;
291         case 'r':
292         case 'R':
293                 *compat_type = E2P_FEATURE_RO_INCOMPAT;
294                 break;
295         default:
296                 return 1;
297         }
298         if (string[9] == 0)
299                 return 1;
300         num = strtol(string+9, &eptr, 10);
301         if (num > 32 || num < 0)
302                 return 1;
303         if (*eptr)
304                 return 1;
305         *mask = 1 << num;
306         return 0;
307 }
308
309 #endif
310 static char *skip_over_blanks(char *cp)
311 {
312         while (*cp && isspace(*cp))
313                 cp++;
314         return cp;
315 }
316
317 static char *skip_over_word(char *cp)
318 {
319         while (*cp && !isspace(*cp) && *cp != ',')
320                 cp++;
321         return cp;
322 }
323
324 /*
325  * Edit a feature set array as requested by the user.  The ok_array,
326  * if set, allows the application to limit what features the user is
327  * allowed to set or clear using this function.  If clear_ok_array is set,
328  * then use it tell whether or not it is OK to clear a filesystem feature.
329  */
330 int e2p_edit_feature2(const char *str, __u32 *compat_array, __u32 *ok_array,
331                       __u32 *clear_ok_array, int *type_err,
332                       unsigned int *mask_err)
333 {
334         char            *cp, *buf, *next;
335         int             neg;
336         unsigned int    mask;
337         int             compat_type;
338         int             rc = 0;
339
340         if (!clear_ok_array)
341                 clear_ok_array = ok_array;
342
343         if (type_err)
344                 *type_err = 0;
345         if (mask_err)
346                 *mask_err = 0;
347
348         buf = malloc(strlen(str)+1);
349         if (!buf)
350                 return 1;
351         strcpy(buf, str);
352         for (cp = buf; cp && *cp; cp = next ? next+1 : 0) {
353                 neg = 0;
354                 cp = skip_over_blanks(cp);
355                 next = skip_over_word(cp);
356
357                 if (*next == 0)
358                         next = 0;
359                 else
360                         *next = 0;
361
362                 //uma if ((strcasecmp(cp, "none") == 0) ||
363                    //uma  (strcasecmp(cp, "clear") == 0)) {
364
365                                         if ((strcmp(cp, "none") == 0) ||
366                     (strcmp(cp, "clear") == 0)) {
367                         compat_array[0] = 0;
368                         compat_array[1] = 0;
369                         compat_array[2] = 0;
370                         continue;
371                 }
372
373                 switch (*cp) {
374                 case '-':
375                 case '^':
376                         neg++;
377                 case '+':
378                         cp++;
379                         break;
380                 }
381                 if (e2p_string2feature(cp, &compat_type, &mask)) {
382                         rc = 1;
383                         break;
384                 }
385                 if (neg) {
386                         if (clear_ok_array &&
387                             !(clear_ok_array[compat_type] & mask)) {
388                                 rc = 1;
389                                 if (type_err)
390                                         *type_err = (compat_type |
391                                                      E2P_FEATURE_NEGATE_FLAG);
392                                 if (mask_err)
393                                         *mask_err = mask;
394                                 break;
395                         }
396                         compat_array[compat_type] &= ~mask;
397                 } else {
398                         if (ok_array && !(ok_array[compat_type] & mask)) {
399                                 rc = 1;
400                                 if (type_err)
401                                         *type_err = compat_type;
402                                 if (mask_err)
403                                         *mask_err = mask;
404                                 break;
405                         }
406                         compat_array[compat_type] |= mask;
407                 }
408         }
409         free(buf);
410         return rc;
411 }
412
413 int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array)
414 {
415         return e2p_edit_feature2(str, compat_array, ok_array, 0, 0, 0);
416 }
417 #if 0
418 //uma
419 #ifdef TEST_PROGRAM
420 int main(int argc, char **argv)
421 {
422         int compat, compat2, i;
423         unsigned int mask, mask2;
424         const char *str;
425         struct feature *f;
426
427         for (i = 0; i < 2; i++) {
428                 if (i == 0) {
429                         f = feature_list;
430                         printf("Feature list:\n");
431                 } else {
432                         printf("\nJournal feature list:\n");
433                         f = jrnl_feature_list;
434                 }
435                 for (; f->string; f++) {
436                         if (i == 0) {
437                                 e2p_string2feature((char *)f->string, &compat,
438                                                    &mask);
439                                 str = e2p_feature2string(compat, mask);
440                         } else {
441                                 e2p_jrnl_string2feature((char *)f->string,
442                                                         &compat, &mask);
443                                 str = e2p_jrnl_feature2string(compat, mask);
444                         }
445
446                         printf("\tCompat = %d, Mask = %u, %s\n",
447                                compat, mask, f->string);
448                         if (strcmp(f->string, str)) {
449                                 if (e2p_string2feature((char *) str, &compat2,
450                                                        &mask2) ||
451                                     (compat2 != compat) ||
452                                     (mask2 != mask)) {
453                                         fprintf(stderr, "Failure!\n");
454                                         exit(1);
455                                 }
456                         }
457                 }
458         }
459         exit(0);
460 }
461 #endif
462 #endif