1/* vi: set sw=4 ts=4: */
2/*
3 * mountopts.c --- convert between default mount options and strings
4 *
5 * Copyright (C) 2002  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 mntopt {
21	unsigned int	mask;
22	const char	*string;
23};
24
25static const struct mntopt mntopt_list[] = {
26	{ EXT2_DEFM_DEBUG,	"debug" },
27	{ EXT2_DEFM_BSDGROUPS,	"bsdgroups" },
28	{ EXT2_DEFM_XATTR_USER,	"user_xattr" },
29	{ EXT2_DEFM_ACL,	"acl" },
30	{ EXT2_DEFM_UID16,	"uid16" },
31	{ EXT3_DEFM_JMODE_DATA, "journal_data" },
32	{ EXT3_DEFM_JMODE_ORDERED, "journal_data_ordered" },
33	{ EXT3_DEFM_JMODE_WBACK, "journal_data_writeback" },
34	{ 0, 0 },
35};
36
37const char *e2p_mntopt2string(unsigned int mask)
38{
39	const struct mntopt  *f;
40	static char buf[20];
41	int	fnum;
42
43	for (f = mntopt_list; f->string; f++) {
44		if (mask == f->mask)
45			return f->string;
46	}
47	for (fnum = 0; mask >>= 1; fnum++);
48	sprintf(buf, "MNTOPT_%d", fnum);
49	return buf;
50}
51
52int e2p_string2mntopt(char *string, unsigned int *mask)
53{
54	const struct mntopt  *f;
55	char		*eptr;
56	int		num;
57
58	for (f = mntopt_list; f->string; f++) {
59		if (!strcasecmp(string, f->string)) {
60			*mask = f->mask;
61			return 0;
62		}
63	}
64	if (strncasecmp(string, "MNTOPT_", 8))
65		return 1;
66
67	if (string[8] == 0)
68		return 1;
69	num = strtol(string+8, &eptr, 10);
70	if (num > 32 || num < 0)
71		return 1;
72	if (*eptr)
73		return 1;
74	*mask = 1 << num;
75	return 0;
76}
77
78static char *skip_over_blanks(char *cp)
79{
80	while (*cp && isspace(*cp))
81		cp++;
82	return cp;
83}
84
85static char *skip_over_word(char *cp)
86{
87	while (*cp && !isspace(*cp) && *cp != ',')
88		cp++;
89	return cp;
90}
91
92/*
93 * Edit a mntopt set array as requested by the user.  The ok
94 * parameter, if non-zero, allows the application to limit what
95 * mntopts the user is allowed to set or clear using this function.
96 */
97int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok)
98{
99	char	*cp, *buf, *next;
100	int	neg;
101	unsigned int	mask;
102
103	buf = xstrdup(str);
104	cp = buf;
105	while (cp && *cp) {
106		neg = 0;
107		cp = skip_over_blanks(cp);
108		next = skip_over_word(cp);
109		if (*next == 0)
110			next = 0;
111		else
112			*next = 0;
113		switch (*cp) {
114		case '-':
115		case '^':
116			neg++;
117		case '+':
118			cp++;
119			break;
120		}
121		if (e2p_string2mntopt(cp, &mask))
122			return 1;
123		if (ok && !(ok & mask))
124			return 1;
125		if (mask & EXT3_DEFM_JMODE)
126			*mntopts &= ~EXT3_DEFM_JMODE;
127		if (neg)
128			*mntopts &= ~mask;
129		else
130			*mntopts |= mask;
131		cp = next ? next+1 : 0;
132	}
133	return 0;
134}
135