quota_kernel.c revision 1.2 1 /* $NetBSD: quota_kernel.c,v 1.2 2012/02/01 05:43:53 dholland Exp $ */
2 /*-
3 * Copyright (c) 2012 The NetBSD Foundation, Inc.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to The NetBSD Foundation
7 * by David A. Holland.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: quota_kernel.c,v 1.2 2012/02/01 05:43:53 dholland Exp $");
33
34 #include <stdlib.h>
35 #include <err.h>
36 #include <errno.h>
37 #include <limits.h>
38
39 #include <quota.h>
40 #include <sys/quotactl.h>
41
42 #include "quotapvt.h"
43
44 struct kernel_quotacursor {
45 /* just wrap the kernel interface type */
46 struct quotakcursor kcursor;
47 };
48
49 static int
50 __quota_kernel_stat(struct quotahandle *qh, struct quotastat *stat)
51 {
52 struct quotactl_args args;
53
54 args.qc_op = QUOTACTL_STAT;
55 args.u.stat.qc_info = stat;
56 return __quotactl(qh->qh_mountpoint, &args);
57 }
58
59 const char *
60 __quota_kernel_getimplname(struct quotahandle *qh)
61 {
62 static struct quotastat stat;
63
64 if (__quota_kernel_stat(qh, &stat)) {
65 return NULL;
66 }
67 return stat.qs_implname;
68 }
69
70 unsigned
71 __quota_kernel_getrestrictions(struct quotahandle *qh)
72 {
73 struct quotastat stat;
74
75 if (__quota_kernel_stat(qh, &stat)) {
76 /* XXX no particularly satisfactory thing to do here */
77 return 0;
78 }
79 return stat.qs_restrictions;
80 }
81
82 unsigned
83 __quota_kernel_getnumidtypes(struct quotahandle *qh)
84 {
85 struct quotastat stat;
86
87 if (__quota_kernel_stat(qh, &stat)) {
88 return 0;
89 }
90 return stat.qs_numidtypes;
91 }
92
93 const char *
94 __quota_kernel_idtype_getname(struct quotahandle *qh, int idtype)
95 {
96 static struct quotaidtypestat stat;
97 struct quotactl_args args;
98
99 args.qc_op = QUOTACTL_IDTYPESTAT;
100 args.u.idtypestat.qc_idtype = idtype;
101 args.u.idtypestat.qc_info = &stat;
102 if (__quotactl(qh->qh_mountpoint, &args)) {
103 return NULL;
104 }
105 return stat.qis_name;
106 }
107
108 unsigned
109 __quota_kernel_getnumobjtypes(struct quotahandle *qh)
110 {
111 struct quotastat stat;
112
113 if (__quota_kernel_stat(qh, &stat)) {
114 return 0;
115 }
116 return stat.qs_numobjtypes;
117 }
118
119 const char *
120 __quota_kernel_objtype_getname(struct quotahandle *qh, int objtype)
121 {
122 static struct quotaobjtypestat stat;
123 struct quotactl_args args;
124
125 args.qc_op = QUOTACTL_OBJTYPESTAT;
126 args.u.objtypestat.qc_objtype = objtype;
127 args.u.objtypestat.qc_info = &stat;
128 if (__quotactl(qh->qh_mountpoint, &args)) {
129 return NULL;
130 }
131 return stat.qos_name;
132 }
133
134 int
135 __quota_kernel_objtype_isbytes(struct quotahandle *qh, int objtype)
136 {
137 struct quotaobjtypestat stat;
138 struct quotactl_args args;
139
140 args.qc_op = QUOTACTL_OBJTYPESTAT;
141 args.u.objtypestat.qc_objtype = objtype;
142 args.u.objtypestat.qc_info = &stat;
143 if (__quotactl(qh->qh_mountpoint, &args)) {
144 return 0;
145 }
146 return stat.qos_isbytes;
147 }
148
149 int
150 __quota_kernel_quotaon(struct quotahandle *qh, int idtype)
151 {
152 struct quotactl_args args;
153 const char *file;
154 char path[PATH_MAX];
155
156 /*
157 * Note that while it is an error to call quotaon on something
158 * that isn't a volume with old-style quotas that expects
159 * quotaon to be called, it's not our responsibility to check
160 * for that; the filesystem will. Also note that it is not an
161 * error to call quotaon repeatedly -- apparently this is to
162 * permit changing the quota file in use on the fly or
163 * something. So all we need to do here is ask the oldfiles
164 * code if the mount option was set in fstab and fetch back
165 * the filename.
166 */
167
168 file = __quota_oldfiles_getquotafile(qh, idtype, path, sizeof(path));
169 if (file == NULL) {
170 /*
171 * This idtype (or maybe any idtype) was not enabled
172 * in fstab.
173 */
174 errno = ENXIO;
175 return -1;
176 }
177
178 args.qc_op = QUOTACTL_QUOTAON;
179 args.u.quotaon.qc_idtype = idtype;
180 args.u.quotaon.qc_quotafile = file;
181 return __quotactl(qh->qh_mountpoint, &args);
182 }
183
184 int
185 __quota_kernel_quotaoff(struct quotahandle *qh, int idtype)
186 {
187 struct quotactl_args args;
188
189 args.qc_op = QUOTACTL_QUOTAOFF;
190 args.u.quotaoff.qc_idtype = idtype;
191 return __quotactl(qh->qh_mountpoint, &args);
192 }
193
194 int
195 __quota_kernel_get(struct quotahandle *qh, const struct quotakey *qk,
196 struct quotaval *qv)
197 {
198 struct quotactl_args args;
199
200 args.qc_op = QUOTACTL_GET;
201 args.u.get.qc_key = qk;
202 args.u.get.qc_val = qv;
203 return __quotactl(qh->qh_mountpoint, &args);
204 }
205
206 int
207 __quota_kernel_put(struct quotahandle *qh, const struct quotakey *qk,
208 const struct quotaval *qv)
209 {
210 struct quotactl_args args;
211
212 args.qc_op = QUOTACTL_PUT;
213 args.u.put.qc_key = qk;
214 args.u.put.qc_val = qv;
215 return __quotactl(qh->qh_mountpoint, &args);
216 }
217
218 int
219 __quota_kernel_delete(struct quotahandle *qh, const struct quotakey *qk)
220 {
221 struct quotactl_args args;
222
223 args.qc_op = QUOTACTL_DELETE;
224 args.u.delete.qc_key = qk;
225 return __quotactl(qh->qh_mountpoint, &args);
226 }
227
228 struct kernel_quotacursor *
229 __quota_kernel_cursor_create(struct quotahandle *qh)
230 {
231 struct quotactl_args args;
232 struct kernel_quotacursor *cursor;
233 int sverrno;
234
235 cursor = malloc(sizeof(*cursor));
236 if (cursor == NULL) {
237 return NULL;
238 }
239
240 args.qc_op = QUOTACTL_CURSOROPEN;
241 args.u.cursoropen.qc_cursor = &cursor->kcursor;
242 if (__quotactl(qh->qh_mountpoint, &args)) {
243 sverrno = errno;
244 free(cursor);
245 errno = sverrno;
246 return NULL;
247 }
248 return cursor;
249 }
250
251 void
252 __quota_kernel_cursor_destroy(struct quotahandle *qh,
253 struct kernel_quotacursor *cursor)
254 {
255 struct quotactl_args args;
256
257 args.qc_op = QUOTACTL_CURSORCLOSE;
258 args.u.cursorclose.qc_cursor = &cursor->kcursor;
259 if (__quotactl(qh->qh_mountpoint, &args)) {
260 /* XXX should we really print from inside the library? */
261 warn("__quotactl cursorclose");
262 }
263 free(cursor);
264 }
265
266 int
267 __quota_kernel_cursor_skipidtype(struct quotahandle *qh,
268 struct kernel_quotacursor *cursor,
269 unsigned idtype)
270 {
271 struct quotactl_args args;
272
273 args.qc_op = QUOTACTL_CURSORSKIPIDTYPE;
274 args.u.cursorskipidtype.qc_cursor = &cursor->kcursor;
275 args.u.cursorskipidtype.qc_idtype = idtype;
276 return __quotactl(qh->qh_mountpoint, &args);
277 }
278
279 int
280 __quota_kernel_cursor_get(struct quotahandle *qh,
281 struct kernel_quotacursor *cursor,
282 struct quotakey *key, struct quotaval *val)
283 {
284 int ret;
285
286 ret = __quota_kernel_cursor_getn(qh, cursor, key, val, 1);
287 if (ret < 0) {
288 return -1;
289 }
290 return 0;
291 }
292
293 int
294 __quota_kernel_cursor_getn(struct quotahandle *qh,
295 struct kernel_quotacursor *cursor,
296 struct quotakey *keys, struct quotaval *vals,
297 unsigned maxnum)
298 {
299 struct quotactl_args args;
300 unsigned ret;
301
302 args.qc_op = QUOTACTL_CURSORGET;
303 args.u.cursorget.qc_cursor = &cursor->kcursor;
304 args.u.cursorget.qc_keys = keys;
305 args.u.cursorget.qc_vals = vals;
306 args.u.cursorget.qc_maxnum = maxnum;
307 args.u.cursorget.qc_ret = &ret;
308 return __quotactl(qh->qh_mountpoint, &args);
309 }
310
311 int
312 __quota_kernel_cursor_atend(struct quotahandle *qh,
313 struct kernel_quotacursor *cursor)
314 {
315 struct quotactl_args args;
316 int ret;
317
318 args.qc_op = QUOTACTL_CURSORATEND;
319 args.u.cursoratend.qc_cursor = &cursor->kcursor;
320 args.u.cursoratend.qc_ret = &ret;
321 if (__quotactl(qh->qh_mountpoint, &args)) {
322 /*
323 * Return -1 so naive callers, who test for the return
324 * value being nonzero, stop iterating, and
325 * sophisticated callers can tell an error from
326 * end-of-data.
327 */
328 return -1;
329 }
330 return ret;
331 }
332
333 int
334 __quota_kernel_cursor_rewind(struct quotahandle *qh,
335 struct kernel_quotacursor *cursor)
336 {
337 struct quotactl_args args;
338
339 args.qc_op = QUOTACTL_CURSORREWIND;
340 args.u.cursorrewind.qc_cursor = &cursor->kcursor;
341 return __quotactl(qh->qh_mountpoint, &args);
342 }
343