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