1 /* $NetBSD: quota_open.c,v 1.4 2012/01/09 15:41:58 dholland Exp $ */ 2 /*- 3 * Copyright (c) 2011 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_open.c,v 1.4 2012/01/09 15:41:58 dholland Exp $"); 33 34 #include <sys/types.h> 35 #include <sys/statvfs.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <unistd.h> 39 #include <errno.h> 40 41 #include <quota.h> 42 #include "quotapvt.h" 43 44 struct quotahandle * 45 quota_open(const char *path) 46 { 47 48 struct statvfs stv; 49 struct quotahandle *qh; 50 int isnfs; 51 int serrno; 52 53 if (statvfs(path, &stv) < 0) { 54 return NULL; 55 } 56 57 /* 58 * We need to know up front if the volume is NFS. If so, we 59 * don't go to the kernel at all but instead do RPCs to the 60 * NFS server's rpc.rquotad. Therefore, don't check the 61 * mount flags for quota support or do anything else that 62 * reaches the kernel. 63 */ 64 65 if (!strcmp(stv.f_fstypename, "nfs")) { 66 isnfs = 1; 67 } else { 68 isnfs = 0; 69 if ((stv.f_flag & ST_QUOTA) == 0) { 70 /* XXX: correct errno? */ 71 errno = EOPNOTSUPP; 72 return NULL; 73 } 74 } 75 76 qh = malloc(sizeof(*qh)); 77 if (qh == NULL) { 78 return NULL; 79 } 80 81 /* 82 * Get the mount point from statvfs; this way the passed-in 83 * path can be any path on the volume. 84 */ 85 86 qh->qh_mountpoint = strdup(stv.f_mntonname); 87 if (qh->qh_mountpoint == NULL) { 88 serrno = errno; 89 free(qh); 90 errno = serrno; 91 return NULL; 92 } 93 94 qh->qh_mountdevice = strdup(stv.f_mntfromname); 95 if (qh->qh_mountdevice == NULL) { 96 serrno = errno; 97 free(qh->qh_mountpoint); 98 free(qh); 99 errno = serrno; 100 return NULL; 101 } 102 103 qh->qh_isnfs = isnfs; 104 105 qh->qh_hasoldfiles = 0; 106 qh->qh_userfile = -1; 107 qh->qh_groupfile = -1; 108 109 return qh; 110 } 111 112 const char * 113 quota_getmountpoint(struct quotahandle *qh) 114 { 115 return qh->qh_mountpoint; 116 } 117 118 const char * 119 quota_getmountdevice(struct quotahandle *qh) 120 { 121 return qh->qh_mountdevice; 122 } 123 124 void 125 quota_close(struct quotahandle *qh) 126 { 127 if (qh->qh_userfile >= 0) { 128 close(qh->qh_userfile); 129 } 130 if (qh->qh_groupfile >= 0) { 131 close(qh->qh_groupfile); 132 } 133 free(qh->qh_mountdevice); 134 free(qh->qh_mountpoint); 135 free(qh); 136 } 137