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