Home | History | Annotate | Line # | Download | only in libquota
      1 /*	$NetBSD: quota_kernel.c,v 1.6 2014/06/28 22:27:50 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.6 2014/06/28 22:27:50 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 int
     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 int
    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_DEL;
    224 	args.u.del.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 				 int 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 	if (maxnum > INT_MAX) {
    303 		/* joker, eh? */
    304 		errno = EINVAL;
    305 		return -1;
    306 	}
    307 
    308 	args.qc_op = QUOTACTL_CURSORGET;
    309 	args.u.cursorget.qc_cursor = &cursor->kcursor;
    310 	args.u.cursorget.qc_keys = keys;
    311 	args.u.cursorget.qc_vals = vals;
    312 	args.u.cursorget.qc_maxnum = maxnum;
    313 	args.u.cursorget.qc_ret = &ret;
    314 	if (__quotactl(qh->qh_mountpoint, &args) < 0) {
    315 		return -1;
    316 	}
    317 	return ret;
    318 }
    319 
    320 int
    321 __quota_kernel_cursor_atend(struct quotahandle *qh,
    322 			    struct kernel_quotacursor *cursor)
    323 {
    324 	struct quotactl_args args;
    325 	int ret;
    326 
    327 	args.qc_op = QUOTACTL_CURSORATEND;
    328 	args.u.cursoratend.qc_cursor = &cursor->kcursor;
    329 	args.u.cursoratend.qc_ret = &ret;
    330 	if (__quotactl(qh->qh_mountpoint, &args)) {
    331 		/*
    332 		 * Return -1 so naive callers, who test for the return
    333 		 * value being nonzero, stop iterating, and
    334 		 * sophisticated callers can tell an error from
    335 		 * end-of-data.
    336 		 */
    337 		return -1;
    338 	}
    339 	return ret;
    340 }
    341 
    342 int
    343 __quota_kernel_cursor_rewind(struct quotahandle *qh,
    344 			     struct kernel_quotacursor *cursor)
    345 {
    346 	struct quotactl_args args;
    347 
    348 	args.qc_op = QUOTACTL_CURSORREWIND;
    349 	args.u.cursorrewind.qc_cursor = &cursor->kcursor;
    350 	return __quotactl(qh->qh_mountpoint, &args);
    351 }
    352