xref: /linux/fs/hfsplus/options.c (revision 7fc2cd2e4b398c57c9cf961cfea05eadbf34c05c)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *  linux/fs/hfsplus/options.c
4  *
5  * Copyright (C) 2001
6  * Brad Boyer (flar@allandria.com)
7  * (C) 2003 Ardis Technologies <roman@ardistech.com>
8  *
9  * Option parsing
10  */
11 
12 #include <linux/string.h>
13 #include <linux/kernel.h>
14 #include <linux/sched.h>
15 #include <linux/fs_struct.h>
16 #include <linux/fs_context.h>
17 #include <linux/fs_parser.h>
18 #include <linux/nls.h>
19 #include <linux/mount.h>
20 #include <linux/seq_file.h>
21 #include <linux/slab.h>
22 #include "hfsplus_fs.h"
23 
24 enum {
25 	opt_creator, opt_type,
26 	opt_umask, opt_uid, opt_gid,
27 	opt_part, opt_session, opt_nls,
28 	opt_decompose, opt_barrier,
29 	opt_force,
30 };
31 
32 static const struct fs_parameter_spec hfs_param_spec[] = {
33 	fsparam_string	("creator",	opt_creator),
34 	fsparam_string	("type",	opt_type),
35 	fsparam_u32oct	("umask",	opt_umask),
36 	fsparam_u32	("uid",		opt_uid),
37 	fsparam_u32	("gid",		opt_gid),
38 	fsparam_u32	("part",	opt_part),
39 	fsparam_u32	("session",	opt_session),
40 	fsparam_string	("nls",		opt_nls),
41 	fsparam_flag_no	("decompose",	opt_decompose),
42 	fsparam_flag_no	("barrier",	opt_barrier),
43 	fsparam_flag	("force",	opt_force),
44 	{}
45 };
46 
47 /* Initialize an options object to reasonable defaults */
48 void hfsplus_fill_defaults(struct hfsplus_sb_info *opts)
49 {
50 	if (!opts)
51 		return;
52 
53 	opts->creator = HFSPLUS_DEF_CR_TYPE;
54 	opts->type = HFSPLUS_DEF_CR_TYPE;
55 	opts->umask = current_umask();
56 	opts->uid = current_uid();
57 	opts->gid = current_gid();
58 	opts->part = -1;
59 	opts->session = -1;
60 }
61 
62 /* Parse options from mount. Returns nonzero errno on failure */
63 int hfsplus_parse_param(struct fs_context *fc, struct fs_parameter *param)
64 {
65 	struct hfsplus_sb_info *sbi = fc->s_fs_info;
66 	struct fs_parse_result result;
67 	int opt;
68 
69 	/*
70 	 * Only the force option is examined during remount, all others
71 	 * are ignored.
72 	 */
73 	if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE &&
74 	    strncmp(param->key, "force", 5))
75 		return 0;
76 
77 	opt = fs_parse(fc, hfs_param_spec, param, &result);
78 	if (opt < 0)
79 		return opt;
80 
81 	switch (opt) {
82 	case opt_creator:
83 		if (strlen(param->string) != 4) {
84 			pr_err("creator requires a 4 character value\n");
85 			return -EINVAL;
86 		}
87 		memcpy(&sbi->creator, param->string, 4);
88 		break;
89 	case opt_type:
90 		if (strlen(param->string) != 4) {
91 			pr_err("type requires a 4 character value\n");
92 			return -EINVAL;
93 		}
94 		memcpy(&sbi->type, param->string, 4);
95 		break;
96 	case opt_umask:
97 		sbi->umask = (umode_t)result.uint_32;
98 		break;
99 	case opt_uid:
100 		sbi->uid = result.uid;
101 		set_bit(HFSPLUS_SB_UID, &sbi->flags);
102 		break;
103 	case opt_gid:
104 		sbi->gid = result.gid;
105 		set_bit(HFSPLUS_SB_GID, &sbi->flags);
106 		break;
107 	case opt_part:
108 		sbi->part = result.uint_32;
109 		break;
110 	case opt_session:
111 		sbi->session = result.uint_32;
112 		break;
113 	case opt_nls:
114 		if (sbi->nls) {
115 			pr_err("unable to change nls mapping\n");
116 			return -EINVAL;
117 		}
118 		sbi->nls = load_nls(param->string);
119 		if (!sbi->nls) {
120 			pr_err("unable to load nls mapping \"%s\"\n",
121 			       param->string);
122 			return -EINVAL;
123 		}
124 		break;
125 	case opt_decompose:
126 		if (result.negated)
127 			set_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags);
128 		else
129 			clear_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags);
130 		break;
131 	case opt_barrier:
132 		if (result.negated)
133 			set_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags);
134 		else
135 			clear_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags);
136 		break;
137 	case opt_force:
138 		set_bit(HFSPLUS_SB_FORCE, &sbi->flags);
139 		break;
140 	default:
141 		return -EINVAL;
142 	}
143 
144 	return 0;
145 }
146 
147 int hfsplus_show_options(struct seq_file *seq, struct dentry *root)
148 {
149 	struct hfsplus_sb_info *sbi = HFSPLUS_SB(root->d_sb);
150 
151 	if (sbi->creator != HFSPLUS_DEF_CR_TYPE)
152 		seq_show_option_n(seq, "creator", (char *)&sbi->creator, 4);
153 	if (sbi->type != HFSPLUS_DEF_CR_TYPE)
154 		seq_show_option_n(seq, "type", (char *)&sbi->type, 4);
155 	seq_printf(seq, ",umask=%o,uid=%u,gid=%u", sbi->umask,
156 			from_kuid_munged(&init_user_ns, sbi->uid),
157 			from_kgid_munged(&init_user_ns, sbi->gid));
158 	if (sbi->part >= 0)
159 		seq_printf(seq, ",part=%u", sbi->part);
160 	if (sbi->session >= 0)
161 		seq_printf(seq, ",session=%u", sbi->session);
162 	if (sbi->nls)
163 		seq_printf(seq, ",nls=%s", sbi->nls->charset);
164 	if (test_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags))
165 		seq_puts(seq, ",nodecompose");
166 	if (test_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags))
167 		seq_puts(seq, ",nobarrier");
168 	return 0;
169 }
170