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