more NFS quota support from <bouyer@ensta.fr> and myself.

This commit is contained in:
deraadt 1994-06-28 07:47:23 +00:00
parent e11807daea
commit c119261953
3 changed files with 247 additions and 59 deletions

View File

@ -1,8 +1,11 @@
# from: @(#)Makefile 8.1 (Berkeley) 6/6/93
# $Id: Makefile,v 1.3 1994/06/13 21:33:03 mycroft Exp $
# $Id: Makefile,v 1.4 1994/06/28 07:47:23 deraadt Exp $
PROG= quota
BINOWN= root
BINMODE=4555
DPADD= ${LIBRPCSVC}
LDADD= -lrpcsvc
.include <bsd.prog.mk>

View File

@ -33,7 +33,7 @@
.\" SUCH DAMAGE.
.\"
.\" from: @(#)quota.1 8.1 (Berkeley) 6/6/93
.\" $Id: quota.1,v 1.3 1994/06/13 21:33:11 mycroft Exp $
.\" $Id: quota.1,v 1.4 1994/06/28 07:47:24 deraadt Exp $
.\"
.Dd June 6, 1993
.Dt QUOTA 1
@ -103,7 +103,17 @@ flag takes precedence over the
flag.
.Pp
.Nm Quota
reports the quotas of all the filesystems listed in
tries to report the quotas of all mounted filesystems.
If the filesystem is mounted via
.Nm NFS ,
it will attempt to contact the
.Xr rpc.rquotad 8
daemon on the
.Nm NFS
server.
For
.Nm UFS
filesystems, quotas must be turned on in
.Pa /etc/fstab .
If
.Nm quota
@ -129,4 +139,5 @@ command appeared in
.Xr edquota 8 ,
.Xr quotacheck 8 ,
.Xr quotaon 8 ,
.Xr repquota 8
.Xr repquota 8 ,
.Xr rpc.rquotad 8

View File

@ -42,23 +42,32 @@ static char copyright[] =
#ifndef lint
/*static char sccsid[] = "from: @(#)quota.c 8.1 (Berkeley) 6/6/93";*/
static char rcsid[] = "$Id: quota.c,v 1.5 1994/06/13 21:33:18 mycroft Exp $";
static char rcsid[] = "$Id: quota.c,v 1.6 1994/06/28 07:47:25 deraadt Exp $";
#endif /* not lint */
/*
* Disk quota reporting program.
*/
#include <sys/param.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <sys/socket.h>
#include <ufs/ufs/quota.h>
#include <stdio.h>
#include <fstab.h>
#include <ctype.h>
#include <string.h>
#include <pwd.h>
#include <grp.h>
#include <errno.h>
#include <netdb.h>
#include <rpc/rpc.h>
#include <rpc/pmap_prot.h>
#include <rpcsvc/rquota.h>
char *qfname = QUOTAFILENAME;
char *qfextension[] = INITQFNAMES;
@ -67,9 +76,12 @@ struct quotause {
long flags;
struct dqblk dqblk;
char fsname[MAXPATHLEN + 1];
} *getprivs();
};
#define FOUND 0x01
char *timeprt __P((time_t seconds));
struct quotause *getprivs __P((long id, int quotatype));
int qflag;
int vflag;
@ -83,10 +95,6 @@ main(argc, argv)
extern char *optarg;
extern int optind, errno;
if (quotactl("/", 0, 0, (caddr_t)0) < 0 && errno == EOPNOTSUPP) {
fprintf(stderr, "There are no quotas on this system\n");
exit(0);
}
while ((ch = getopt(argc, argv, "ugvq")) != EOF) {
switch(ch) {
case 'g':
@ -268,8 +276,8 @@ showquotas(type, id, name)
char *name;
{
register struct quotause *qup;
struct quotause *quplist, *getprivs();
char *msgi, *msgb, *timeprt();
struct quotause *quplist;
char *msgi, *msgb, *nam;
int myuid, fd, lines = 0;
static int first;
static time_t now;
@ -319,8 +327,13 @@ showquotas(type, id, name)
qup->dqblk.dqb_curinodes) {
if (lines++ == 0)
heading(type, id, name, "");
nam = qup->fsname;
if (strlen(qup->fsname) > 15) {
printf("%s\n", qup->fsname);
nam = "";
}
printf("%15s%8d%c%7d%8d%8s"
, qup->fsname
, nam
, dbtob(qup->dqblk.dqb_curblocks) / 1024
, (msgb == (char *)0) ? ' ' : '*'
, dbtob(qup->dqblk.dqb_bsoftlimit) / 1024
@ -403,61 +416,56 @@ getprivs(id, quotatype)
register long id;
int quotatype;
{
register struct fstab *fs;
register struct quotause *qup, *quptail;
register struct fstab *fs;
struct quotause *quphead;
char *qfpathname;
int qcmd, fd;
struct statfs *fst;
int nfst, i;
qup = quphead = (struct quotause *)0;
nfst = getmntinfo(&fst, MNT_WAIT);
if (nfst == 0) {
fprintf(stderr, "quota: no filesystems mounted!\n");
exit(2);
}
setfsent();
quphead = (struct quotause *)0;
qcmd = QCMD(Q_GETQUOTA, quotatype);
while (fs = getfsent()) {
if (strcmp(fs->fs_vfstype, "ufs"))
continue;
if (!hasquota(fs, quotatype, &qfpathname))
continue;
if ((qup = (struct quotause *)malloc(sizeof *qup)) == NULL) {
fprintf(stderr, "quota: out of memory\n");
exit(2);
}
if (quotactl(fs->fs_file, qcmd, id, &qup->dqblk) != 0) {
if ((fd = open(qfpathname, O_RDONLY)) < 0) {
perror(qfpathname);
free(qup);
continue;
for (i=0; i<nfst; i++) {
if (qup == NULL) {
if ((qup = (struct quotause *)malloc(sizeof *qup)) == NULL) {
fprintf(stderr, "quota: out of memory\n");
exit(2);
}
lseek(fd, (off_t)(id * sizeof(struct dqblk)), L_SET);
switch (read(fd, &qup->dqblk, sizeof(struct dqblk))) {
case 0: /* EOF */
/*
* Convert implicit 0 quota (EOF)
* into an explicit one (zero'ed dqblk)
*/
bzero((caddr_t)&qup->dqblk,
sizeof(struct dqblk));
break;
case sizeof(struct dqblk): /* OK */
break;
default: /* ERROR */
fprintf(stderr, "quota: read error");
perror(qfpathname);
close(fd);
free(qup);
continue;
}
close(fd);
}
strcpy(qup->fsname, fs->fs_file);
if (strcmp(fst[i].f_fstypename, "nfs") == 0) {
if (getnfsquota(&fst[i], NULL, qup, id, quotatype) == 0)
continue;
} else if (strcmp(fst[i].f_fstypename, "ufs") == 0) {
/*
* XXX
* UFS filesystems must be in /etc/fstab, and must
* indicate that they have quotas on (?!) This is quite
* unlike SunOS where quotas can be enabled/disabled
* on a filesystem independent of /etc/fstab, and it
* will still print quotas for them.
*/
if ((fs = getfsspec(fst[i].f_mntfromname)) == NULL)
continue;
if (getufsquota(&fst[i], fs, qup, id, quotatype) == 0)
continue;
} else
continue;
strcpy(qup->fsname, fst[i].f_mntonname);
if (quphead == NULL)
quphead = qup;
else
quptail->next = qup;
quptail = qup;
qup->next = 0;
quptail->next = 0;
qup = NULL;
}
if (qup)
free(qup);
endfsent();
return (quphead);
}
@ -465,15 +473,14 @@ getprivs(id, quotatype)
/*
* Check to see if a particular quota is to be enabled.
*/
hasquota(fs, type, qfnamep)
ufshasquota(fs, type, qfnamep)
register struct fstab *fs;
int type;
char **qfnamep;
{
register char *opt;
char *cp, *index(), *strtok();
static char initname, usrname[100], grpname[100];
static char buf[BUFSIZ];
char *opt, *cp;
if (!initname) {
sprintf(usrname, "%s%s", qfextension[USRQUOTA], qfname);
@ -500,6 +507,173 @@ hasquota(fs, type, qfnamep)
return (1);
}
int
getufsquota(fst, fs, qup, id, quotatype)
struct statfs *fst;
struct fstab *fs;
struct quotause *qup;
long id;
int quotatype;
{
char *qfpathname;
int fd, qcmd;
qcmd = QCMD(Q_GETQUOTA, quotatype);
if (!ufshasquota(fs, quotatype, &qfpathname))
return (0);
if (quotactl(fs->fs_file, qcmd, id, &qup->dqblk) != 0) {
if ((fd = open(qfpathname, O_RDONLY)) < 0) {
perror(qfpathname);
return (0);
}
(void) lseek(fd, (off_t)(id * sizeof(struct dqblk)), L_SET);
switch (read(fd, &qup->dqblk, sizeof(struct dqblk))) {
case 0: /* EOF */
/*
* Convert implicit 0 quota (EOF)
* into an explicit one (zero'ed dqblk)
*/
bzero((caddr_t)&qup->dqblk, sizeof(struct dqblk));
break;
case sizeof(struct dqblk): /* OK */
break;
default: /* ERROR */
fprintf(stderr, "quota: read error");
perror(qfpathname);
close(fd);
return (0);
}
close(fd);
}
return (1);
}
int
getnfsquota(fst, fs, qup, id, quotatype)
struct statfs *fst;
struct fstab *fs;
struct quotause *qup;
long id;
int quotatype;
{
struct getquota_args gq_args;
struct getquota_rslt gq_rslt;
struct dqblk *dqp = &qup->dqblk;
struct timeval tv;
char *cp;
if (fst->f_flags & MNT_LOCAL)
return (0);
/*
* rpc.rquotad does not support group quotas
*/
if (quotatype != USRQUOTA)
return (0);
/*
* must be some form of "hostname:/path"
*/
cp = strchr(fst->f_mntfromname, ':');
if (cp == NULL) {
fprintf(stderr, "cannot find hostname for %s\n",
fst->f_mntfromname);
return (0);
}
*cp = '\0';
if (*(cp+1) != '/') {
*cp = ':';
return (0);
}
gq_args.gqa_pathp = cp + 1;
gq_args.gqa_uid = id;
if (callaurpc(fst->f_mntfromname, RQUOTAPROG, RQUOTAVERS,
RQUOTAPROC_GETQUOTA, xdr_getquota_args, &gq_args,
xdr_getquota_rslt, &gq_rslt) != 0) {
*cp = ':';
return (0);
}
switch (gq_rslt.status) {
case Q_NOQUOTA:
break;
case Q_EPERM:
fprintf(stderr, "quota permission error, host: %s\n",
fst->f_mntfromname);
break;
case Q_OK:
gettimeofday(&tv, NULL);
/* blocks*/
dqp->dqb_bhardlimit =
gq_rslt.getquota_rslt_u.gqr_rquota.rq_bhardlimit *
gq_rslt.getquota_rslt_u.gqr_rquota.rq_bsize / DEV_BSIZE;
dqp->dqb_bsoftlimit =
gq_rslt.getquota_rslt_u.gqr_rquota.rq_bsoftlimit *
gq_rslt.getquota_rslt_u.gqr_rquota.rq_bsize / DEV_BSIZE;
dqp->dqb_curblocks =
gq_rslt.getquota_rslt_u.gqr_rquota.rq_curblocks *
gq_rslt.getquota_rslt_u.gqr_rquota.rq_bsize / DEV_BSIZE;
/* inodes */
dqp->dqb_ihardlimit =
gq_rslt.getquota_rslt_u.gqr_rquota.rq_fhardlimit;
dqp->dqb_isoftlimit =
gq_rslt.getquota_rslt_u.gqr_rquota.rq_fsoftlimit;
dqp->dqb_curinodes =
gq_rslt.getquota_rslt_u.gqr_rquota.rq_curfiles;
/* grace times */
dqp->dqb_btime =
tv.tv_sec + gq_rslt.getquota_rslt_u.gqr_rquota.rq_btimeleft;
dqp->dqb_itime =
tv.tv_sec + gq_rslt.getquota_rslt_u.gqr_rquota.rq_ftimeleft;
*cp = ':';
return (1);
default:
fprintf(stderr, "bad rpc result, host: %s\n",
fst->f_mntfromname);
break;
}
*cp = ':';
return (0);
}
int
callaurpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
char *host;
xdrproc_t inproc, outproc;
char *in, *out;
{
struct sockaddr_in server_addr;
enum clnt_stat clnt_stat;
struct hostent *hp;
struct timeval timeout, tottimeout;
CLIENT *client = NULL;
int socket = RPC_ANYSOCK;
if ((hp = gethostbyname(host)) == NULL)
return ((int) RPC_UNKNOWNHOST);
timeout.tv_usec = 0;
timeout.tv_sec = 6;
bcopy(hp->h_addr, &server_addr.sin_addr, hp->h_length);
server_addr.sin_family = AF_INET;
server_addr.sin_port = 0;
if ((client = clntudp_create(&server_addr, prognum,
versnum, timeout, &socket)) == NULL)
return ((int) rpc_createerr.cf_stat);
client->cl_auth = authunix_create_default();
tottimeout.tv_sec = 25;
tottimeout.tv_usec = 0;
clnt_stat = clnt_call(client, procnum, inproc, in,
outproc, out, tottimeout);
return ((int) clnt_stat);
}
alldigits(s)
register char *s;
{