vfs_quotactl.c revision 1.7 1 /* $NetBSD: vfs_quotactl.c,v 1.7 2012/01/29 06:37:30 dholland Exp $ */
2
3 /*
4 * Copyright (c) 1991, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)ufs_vfsops.c 8.8 (Berkeley) 5/20/95
37 * From NetBSD: ufs_vfsops.c,v 1.42 2011/03/24 17:05:46 bouyer Exp
38 */
39
40 /*
41 * Copyright (c) 1982, 1986, 1990, 1993, 1995
42 * The Regents of the University of California. All rights reserved.
43 *
44 * This code is derived from software contributed to Berkeley by
45 * Robert Elz at The University of Melbourne.
46 *
47 * Redistribution and use in source and binary forms, with or without
48 * modification, are permitted provided that the following conditions
49 * are met:
50 * 1. Redistributions of source code must retain the above copyright
51 * notice, this list of conditions and the following disclaimer.
52 * 2. Redistributions in binary form must reproduce the above copyright
53 * notice, this list of conditions and the following disclaimer in the
54 * documentation and/or other materials provided with the distribution.
55 * 3. Neither the name of the University nor the names of its contributors
56 * may be used to endorse or promote products derived from this software
57 * without specific prior written permission.
58 *
59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * SUCH DAMAGE.
70 *
71 * @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95
72 * From NetBSD: ufs_quota.c,v 1.70 2011/03/24 17:05:46 bouyer Exp
73 */
74
75 /*
76 * Note that both of the copyrights above are moderately spurious;
77 * this code should almost certainly have the Copyright 2010 Manuel
78 * Bouyer notice and license found in e.g. sys/ufs/ufs/quota2_subr.c.
79 * However, they're what was on the files this code was sliced out of.
80 */
81
82 #include <sys/cdefs.h>
83 __KERNEL_RCSID(0, "$NetBSD: vfs_quotactl.c,v 1.7 2012/01/29 06:37:30 dholland Exp $");
84
85 #include <sys/mount.h>
86 #include <sys/quotactl.h>
87 #include <quota/quotaprop.h>
88
89 static int
90 vfs_quotactl_getversion(struct mount *mp,
91 prop_dictionary_t cmddict, int q2type,
92 prop_array_t datas)
93 {
94 prop_array_t replies;
95 prop_dictionary_t data;
96 int q2version;
97 struct vfs_quotactl_args args;
98 int error;
99
100 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY);
101 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY);
102
103 args.qc_type = QCT_GETVERSION;
104 args.u.getversion.qc_version_ret = &q2version;
105 error = VFS_QUOTACTL(mp, QUOTACTL_GETVERSION, &args);
106 if (error) {
107 return error;
108 }
109
110 data = prop_dictionary_create();
111 if (data == NULL) {
112 return ENOMEM;
113 }
114
115 if (!prop_dictionary_set_int8(data, "version", q2version)) {
116 prop_object_release(data);
117 return ENOMEM;
118 }
119
120 replies = prop_array_create();
121 if (replies == NULL) {
122 prop_object_release(data);
123 return ENOMEM;
124 }
125
126 if (!prop_array_add_and_rel(replies, data)) {
127 prop_object_release(data);
128 prop_object_release(replies);
129 return ENOMEM;
130 }
131
132 if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) {
133 prop_object_release(replies);
134 return ENOMEM;
135 }
136
137 return error;
138 }
139
140 static int
141 vfs_quotactl_quotaon(struct mount *mp,
142 prop_dictionary_t cmddict, int q2type,
143 prop_array_t datas)
144 {
145 struct vfs_quotactl_args args;
146
147 args.qc_type = QCT_PROPLIB;
148 args.u.proplib.qc_cmddict = cmddict;
149 args.u.proplib.qc_q2type = q2type;
150 args.u.proplib.qc_datas = datas;
151 return VFS_QUOTACTL(mp, QUOTACTL_QUOTAON, &args);
152 }
153
154 static int
155 vfs_quotactl_quotaoff(struct mount *mp,
156 prop_dictionary_t cmddict, int q2type,
157 prop_array_t datas)
158 {
159 struct vfs_quotactl_args args;
160
161 args.qc_type = QCT_PROPLIB;
162 args.u.proplib.qc_cmddict = cmddict;
163 args.u.proplib.qc_q2type = q2type;
164 args.u.proplib.qc_datas = datas;
165 return VFS_QUOTACTL(mp, QUOTACTL_QUOTAOFF, &args);
166 }
167
168 static int
169 vfs_quotactl_get(struct mount *mp,
170 prop_dictionary_t cmddict, int q2type,
171 prop_array_t datas)
172 {
173 prop_object_iterator_t iter;
174 prop_dictionary_t data;
175 uint32_t id;
176 int defaultq;
177 const char *idstr;
178 prop_array_t replies;
179 struct vfs_quotactl_args args;
180 int error;
181
182 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY);
183 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY);
184
185 replies = prop_array_create();
186 if (replies == NULL) {
187 return ENOMEM;
188 }
189
190 iter = prop_array_iterator(datas);
191 if (iter == NULL) {
192 prop_object_release(replies);
193 return ENOMEM;
194 }
195
196 while ((data = prop_object_iterator_next(iter)) != NULL) {
197 if (!prop_dictionary_get_uint32(data, "id", &id)) {
198 if (!prop_dictionary_get_cstring_nocopy(data, "id",
199 &idstr))
200 continue;
201 if (strcmp(idstr, "default")) {
202 error = EINVAL;
203 goto fail;
204 }
205 id = 0;
206 defaultq = 1;
207 } else {
208 defaultq = 0;
209 }
210
211 args.qc_type = QCT_GET;
212 args.u.get.qc_q2type = q2type;
213 args.u.get.qc_id = id;
214 args.u.get.qc_defaultq = defaultq;
215 args.u.get.qc_replies = replies;
216 error = VFS_QUOTACTL(mp, QUOTACTL_GET, &args);
217 if (error == EPERM) {
218 /* XXX does this make sense? */
219 continue;
220 } else if (error == ENOENT) {
221 /* XXX does *this* make sense? */
222 continue;
223 } else if (error) {
224 goto fail;
225 }
226 }
227
228 prop_object_iterator_release(iter);
229 if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) {
230 error = ENOMEM;
231 } else {
232 error = 0;
233 }
234
235 return error;
236
237 fail:
238 prop_object_iterator_release(iter);
239 prop_object_release(replies);
240 return error;
241 }
242
243 static int
244 vfs_quotactl_set(struct mount *mp,
245 prop_dictionary_t cmddict, int q2type,
246 prop_array_t datas)
247 {
248 struct vfs_quotactl_args args;
249
250 args.qc_type = QCT_PROPLIB;
251 args.u.proplib.qc_cmddict = cmddict;
252 args.u.proplib.qc_q2type = q2type;
253 args.u.proplib.qc_datas = datas;
254 return VFS_QUOTACTL(mp, QUOTACTL_SET, &args);
255 }
256
257 static int
258 vfs_quotactl_getall(struct mount *mp,
259 prop_dictionary_t cmddict, int q2type,
260 prop_array_t datas)
261 {
262 struct vfs_quotactl_args args;
263
264 args.qc_type = QCT_PROPLIB;
265 args.u.proplib.qc_cmddict = cmddict;
266 args.u.proplib.qc_q2type = q2type;
267 args.u.proplib.qc_datas = datas;
268 return VFS_QUOTACTL(mp, QUOTACTL_GETALL, &args);
269 }
270
271 static int
272 vfs_quotactl_clear(struct mount *mp,
273 prop_dictionary_t cmddict, int q2type,
274 prop_array_t datas)
275 {
276 struct vfs_quotactl_args args;
277
278 args.qc_type = QCT_PROPLIB;
279 args.u.proplib.qc_cmddict = cmddict;
280 args.u.proplib.qc_q2type = q2type;
281 args.u.proplib.qc_datas = datas;
282 return VFS_QUOTACTL(mp, QUOTACTL_CLEAR, &args);
283 }
284
285 static int
286 vfs_quotactl_cmd(struct mount *mp, prop_dictionary_t cmddict)
287 {
288 int error;
289 const char *cmd, *type;
290 prop_array_t datas;
291 int q2type;
292
293 if (!prop_dictionary_get_cstring_nocopy(cmddict, "command", &cmd))
294 return EINVAL;
295 if (!prop_dictionary_get_cstring_nocopy(cmddict, "type", &type))
296 return EINVAL;
297
298 if (!strcmp(type, QUOTADICT_CLASS_USER)) {
299 q2type = QUOTA_CLASS_USER;
300 } else if (!strcmp(type, QUOTADICT_CLASS_GROUP)) {
301 q2type = QUOTA_CLASS_GROUP;
302 } else {
303 /* XXX this is a bad errno for this case */
304 return EOPNOTSUPP;
305 }
306
307 datas = prop_dictionary_get(cmddict, "data");
308 if (datas == NULL || prop_object_type(datas) != PROP_TYPE_ARRAY)
309 return EINVAL;
310
311 prop_object_retain(datas);
312 prop_dictionary_remove(cmddict, "data"); /* prepare for return */
313
314 if (strcmp(cmd, "get version") == 0) {
315 error = vfs_quotactl_getversion(mp, cmddict, q2type, datas);
316 } else if (strcmp(cmd, "quotaon") == 0) {
317 error = vfs_quotactl_quotaon(mp, cmddict, q2type, datas);
318 } else if (strcmp(cmd, "quotaoff") == 0) {
319 error = vfs_quotactl_quotaoff(mp, cmddict, q2type, datas);
320 } else if (strcmp(cmd, "get") == 0) {
321 error = vfs_quotactl_get(mp, cmddict, q2type, datas);
322 } else if (strcmp(cmd, "set") == 0) {
323 error = vfs_quotactl_set(mp, cmddict, q2type, datas);
324 } else if (strcmp(cmd, "getall") == 0) {
325 error = vfs_quotactl_getall(mp, cmddict, q2type, datas);
326 } else if (strcmp(cmd, "clear") == 0) {
327 error = vfs_quotactl_clear(mp, cmddict, q2type, datas);
328 } else {
329 /* XXX this a bad errno for this case */
330 error = EOPNOTSUPP;
331 }
332
333 error = (prop_dictionary_set_int8(cmddict, "return",
334 error) ? 0 : ENOMEM);
335 prop_object_release(datas);
336
337 return error;
338 }
339
340 int
341 vfs_quotactl(struct mount *mp, prop_dictionary_t dict)
342 {
343 prop_dictionary_t cmddict;
344 prop_array_t commands;
345 prop_object_iterator_t iter;
346 int error;
347
348 error = quota_get_cmds(dict, &commands);
349 if (error) {
350 return error;
351 }
352
353 iter = prop_array_iterator(commands);
354 if (iter == NULL) {
355 return ENOMEM;
356 }
357
358 while ((cmddict = prop_object_iterator_next(iter)) != NULL) {
359 if (prop_object_type(cmddict) != PROP_TYPE_DICTIONARY) {
360 /* XXX shouldn't this be an error? */
361 continue;
362 }
363 error = vfs_quotactl_cmd(mp, cmddict);
364 if (error) {
365 break;
366 }
367 }
368 prop_object_iterator_release(iter);
369 return error;
370 }
371