2 * QUOTA An implementation of the diskquota system for the LINUX
3 * operating system. QUOTA is implemented using the BSD systemcall
4 * interface as the means of communication with the user level.
5 * Should work for all filesystems because of integration into the
6 * VFS layer of the operating system.
7 * This is based on the Melbourne quota system wich uses both user and
10 * This part does the lookup of the info.
12 * Version: $Id: rquota_server.c,v 2.9 1996/11/17 16:59:46 mvw Exp mvw $
14 * Author: Marco van Wieringen <mvw@planets.elm.net>
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version
19 * 2 of the License, or (at your option) any later version.
27 #include <sys/param.h>
28 #include <sys/quota.h>
37 #define TYPE_EXTENDED 0x01
41 #define _PATH_DEV_DSK "/dev/dsk/"
43 #define _PATH_DEV_DSK "/dev/"
47 * Global unix authentication credentials.
49 extern struct authunix_parms *unix_cred;
51 char *nfsmount_to_devname(char *pathname, int *blksize)
57 static char *devicename = NULL;
58 static int devicelen = 0;
60 if (stat(pathname, &st) == -1)
64 *blksize = st.st_blksize;
67 * search for devicename in _PATH_DEV_DSK dir.
69 if ((dp = opendir(_PATH_DEV_DSK)) == (DIR *)0)
72 while ((de = readdir(dp)) != (struct dirent *)0) {
73 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
77 devicelen = sizeof (_PATH_DEV_DSK) + strlen (de->d_name) + 1;
78 devicename = (char *) xmalloc (devicelen);
81 int newlen = sizeof (_PATH_DEV_DSK) + strlen (de->d_name) + 1;
82 if (newlen > devicelen) {
84 devicename = (char *) xrealloc (devicename, devicelen);
88 strcpy(devicename, _PATH_DEV_DSK);
89 strcat(devicename, de->d_name);
90 if (stat(devicename, &st) == -1)
93 if (!S_ISBLK(st.st_mode))
96 if ((device == st.st_rdev) && S_ISBLK(st.st_mode))
101 if (de != (struct dirent *)0) {
107 int in_group (gid_t *gids, u_int len, gid_t gid)
112 if (gids[cnt] == gid)
119 getquota_rslt *getquotainfo(int flags, caddr_t *argp, struct svc_req *rqstp)
121 static getquota_rslt result;
124 ext_getquota_args *ext_args;
129 char *pathname, *devicename, *qfpathname;
130 int fd, err, id, type;
133 * First check authentication.
135 if (flags & TYPE_EXTENDED) {
136 arguments.ext_args = (ext_getquota_args *)argp;
137 id = arguments.ext_args->gqa_id;
138 type = arguments.ext_args->gqa_type;
139 pathname = arguments.ext_args->gqa_pathp;
141 if (type == USRQUOTA && unix_cred->aup_uid && unix_cred->aup_uid != id) {
142 result.status = Q_EPERM;
146 if (type == GRPQUOTA && unix_cred->aup_uid && unix_cred->aup_gid != id &&
147 !in_group((gid_t *)unix_cred->aup_gids, unix_cred->aup_len, id)) {
148 result.status = Q_EPERM;
152 arguments.args = (getquota_args *)argp;
153 id = arguments.args->gqa_uid;
155 pathname = arguments.args->gqa_pathp;
157 if (unix_cred->aup_uid && unix_cred->aup_uid != id) {
158 result.status = Q_EPERM;
164 * Convert a nfs_mountpoint to a local devicename.
166 if ((devicename = nfsmount_to_devname(pathname,
167 &result.getquota_rslt_u.gqr_rquota.rq_bsize)) == (char *)0) {
168 result.status = Q_NOQUOTA;
172 fp = setmntent(MNTTAB, "r");
173 while ((mnt = getmntent(fp)) != (struct mntent *)0) {
174 if (strcmp(devicename, mnt->mnt_fsname))
177 if (hasquota(mnt, type, &qfpathname)) {
178 if ((err = quotactl(QCMD(Q_GETQUOTA, type), devicename, id,
179 (caddr_t)&dq_dqb)) == -1 && !(flags & ACTIVE)) {
180 if ((fd = open(qfpathname, O_RDONLY)) < 0)
186 lseek(fd, (long) dqoff(id), L_SET);
187 switch (read(fd, &dq_dqb, sizeof(struct dqblk))) {
190 * Convert implicit 0 quota (EOF) into an
191 * explicit one (zero'ed dqblk)
193 memset((caddr_t)&dq_dqb, 0, sizeof(struct dqblk));
195 case sizeof(struct dqblk): /* OK */
205 if (err && (flags & ACTIVE)) {
206 result.status = Q_NOQUOTA;
210 result.status = Q_OK;
211 result.getquota_rslt_u.gqr_rquota.rq_active = (err == 0) ? TRUE : FALSE;
213 * Make a copy of the info into the last part of the remote quota
214 * struct which is exactly the same.
216 memcpy((caddr_t *)&result.getquota_rslt_u.gqr_rquota.rq_bhardlimit,
217 (caddr_t *)&dq_dqb, sizeof(struct dqblk));
224 result.status = Q_NOQUOTA;
228 getquota_rslt *rquotaproc_getquota_1(getquota_args *argp, struct svc_req *rqstp)
230 return(getquotainfo(0, (caddr_t *)argp, rqstp));
233 getquota_rslt *rquotaproc_getactivequota_1(getquota_args *argp, struct svc_req *rqstp)
235 return(getquotainfo(ACTIVE, (caddr_t *)argp, rqstp));
238 getquota_rslt *rquotaproc_getquota_2(ext_getquota_args *argp, struct svc_req *rqstp)
240 return(getquotainfo(TYPE_EXTENDED, (caddr_t *)argp, rqstp));
243 getquota_rslt *rquotaproc_getactivequota_2(ext_getquota_args *argp, struct svc_req *rqstp)
245 return(getquotainfo(TYPE_EXTENDED | ACTIVE, (caddr_t *)argp, rqstp));