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