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.
25 #define _LINUX_QUOTA_VERSION 1
31 #include <sys/param.h>
32 #include <sys/quota.h>
33 #include <sys/mount.h>
42 #define TYPE_EXTENDED 0x01
45 #ifndef MNTTYPE_AUTOFS
46 #define MNTTYPE_AUTOFS "autofs"
50 #define BLOCK_SIZE 1024
54 * Global unix authentication credentials.
56 extern struct authunix_parms *unix_cred;
58 int in_group (gid_t *gids, u_int len, gid_t gid)
70 getquota_rslt *getquotainfo(int flags, caddr_t *argp, struct svc_req *rqstp)
72 static getquota_rslt result;
75 ext_getquota_args *ext_args;
80 char *pathname, *qfpathname;
81 int fd, err, id, type;
83 struct rquota *rquota;
86 * First check authentication.
88 if (flags & TYPE_EXTENDED) {
89 arguments.ext_args = (ext_getquota_args *)argp;
90 id = arguments.ext_args->gqa_id;
91 type = arguments.ext_args->gqa_type;
92 pathname = arguments.ext_args->gqa_pathp;
94 if (type == USRQUOTA && unix_cred->aup_uid && unix_cred->aup_uid != id) {
95 result.status = Q_EPERM;
99 if (type == GRPQUOTA && unix_cred->aup_uid && unix_cred->aup_gid != id &&
100 !in_group((gid_t *)unix_cred->aup_gids, unix_cred->aup_len, id)) {
101 result.status = Q_EPERM;
105 arguments.args = (getquota_args *)argp;
106 id = arguments.args->gqa_uid;
108 pathname = arguments.args->gqa_pathp;
110 if (unix_cred->aup_uid && unix_cred->aup_uid != id) {
111 result.status = Q_EPERM;
116 fp = setmntent(MNTTAB, "r");
117 while ((mnt = getmntent(fp)) != (struct mntent *)0) {
118 if (stat(mnt->mnt_dir, &stm) == -1)
121 if (stat(pathname, &stn) == -1)
123 else if (stm.st_dev != stn.st_dev)
126 if (mnt->mnt_fsname [0] != '/'
127 || strcasecmp (mnt->mnt_type, MNTTYPE_NFS) == 0
128 || strcasecmp (mnt->mnt_type, MNTTYPE_AUTOFS) == 0
129 || strcasecmp (mnt->mnt_type, MNTTYPE_SWAP) == 0
130 || strcasecmp (mnt->mnt_type, MNTTYPE_IGNORE) == 0)
133 /* All blocks reported are in BLOCK_SIZE. */
134 result.getquota_rslt_u.gqr_rquota.rq_bsize = BLOCK_SIZE;
136 if (hasquota(mnt, type, &qfpathname)) {
137 if ((err = quotactl(QCMD(Q_GETQUOTA, type), mnt->mnt_fsname,
138 id, (caddr_t)&dq_dqb)) == -1
139 && !(flags & ACTIVE)) {
140 if ((fd = open(qfpathname, O_RDONLY)) < 0)
146 lseek(fd, (long) dqoff(id), L_SET);
147 switch (read(fd, &dq_dqb, sizeof(struct dqblk))) {
150 * Convert implicit 0 quota (EOF) into an
151 * explicit one (zero'ed dqblk)
153 memset((caddr_t)&dq_dqb, 0, sizeof(struct dqblk));
155 case sizeof(struct dqblk): /* OK */
165 if (err && (flags & ACTIVE)) {
166 result.status = Q_NOQUOTA;
170 result.status = Q_OK;
171 result.getquota_rslt_u.gqr_rquota.rq_active = (err == 0) ? TRUE : FALSE;
173 * Make a copy of the info into the last part of the remote quota
174 * struct might not be exactly the same on all architectures...
177 rquota = &result.getquota_rslt_u.gqr_rquota;
178 rquota->rq_bhardlimit = dq_dqb.dqb_bhardlimit;
179 rquota->rq_bsoftlimit = dq_dqb.dqb_bsoftlimit;;
180 rquota->rq_curblocks = dq_dqb.dqb_curblocks;
181 rquota->rq_fhardlimit = dq_dqb.dqb_ihardlimit;
182 rquota->rq_fsoftlimit = dq_dqb.dqb_isoftlimit;
183 rquota->rq_curfiles = dq_dqb.dqb_curinodes;
184 rquota->rq_btimeleft = dq_dqb.dqb_btime;
185 rquota->rq_ftimeleft = dq_dqb.dqb_itime;
192 result.status = Q_NOQUOTA;
196 getquota_rslt *rquotaproc_getquota_1(getquota_args *argp, struct svc_req *rqstp)
198 return(getquotainfo(0, (caddr_t *)argp, rqstp));
201 getquota_rslt *rquotaproc_getactivequota_1(getquota_args *argp, struct svc_req *rqstp)
203 return(getquotainfo(ACTIVE, (caddr_t *)argp, rqstp));
206 getquota_rslt *rquotaproc_getquota_2(ext_getquota_args *argp, struct svc_req *rqstp)
208 return(getquotainfo(TYPE_EXTENDED, (caddr_t *)argp, rqstp));
211 getquota_rslt *rquotaproc_getactivequota_2(ext_getquota_args *argp, struct svc_req *rqstp)
213 return(getquotainfo(TYPE_EXTENDED | ACTIVE, (caddr_t *)argp, rqstp));