Obtained from: NetBSD

replaced our quota with the NetBSD one, then added all changes we made
to our - this is done to support the displaying of quota's over nfs
using the rpc.rquotad
This commit is contained in:
Thomas Graichen 1996-01-05 08:37:29 +00:00
parent cf7e4ac2cf
commit 9288f2661b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=13236
3 changed files with 292 additions and 90 deletions

View File

@ -4,4 +4,7 @@ PROG= quota
BINOWN= root
BINMODE=4555
DPADD= ${LIBRPCSVC}
LDADD= -lrpcsvc
.include <bsd.prog.mk>

View File

@ -32,7 +32,8 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)quota.1 8.1 (Berkeley) 6/6/93
.\" from: @(#)quota.1 8.1 (Berkeley) 6/6/93
.\" $Id: quota.1,v 1.4 1994/06/28 07:47:24 deraadt Exp $
.\"
.Dd June 6, 1993
.Dt QUOTA 1
@ -102,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
@ -128,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

@ -41,23 +41,34 @@ static char copyright[] =
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)quota.c 8.1 (Berkeley) 6/6/93";
/*static char sccsid[] = "from: @(#)quota.c 8.1 (Berkeley) 6/6/93";*/
static char rcsid[] = "$Id: quota.c,v 1.9 1995/06/18 11:00:49 cgd 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 <stdlib.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;
@ -66,25 +77,25 @@ 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;
main(argc, argv)
char *argv[];
{
int ngroups, gidset[NGROUPS];
int ngroups;
gid_t mygid, gidset[NGROUPS];
int i, gflag = 0, uflag = 0;
char ch;
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':
@ -111,13 +122,16 @@ main(argc, argv)
if (uflag)
showuid(getuid());
if (gflag) {
mygid = getgid();
ngroups = getgroups(NGROUPS, gidset);
if (ngroups < 0) {
perror("quota: getgroups");
exit(1);
}
for (i = 1; i < ngroups; i++)
showgid(gidset[i]);
showgid(mygid);
for (i = 0; i < ngroups; i++)
if (gidset[i] != mygid)
showgid(gidset[i]);
}
exit(0);
}
@ -169,7 +183,7 @@ showuid(uid)
name = pwd->pw_name;
myuid = getuid();
if (uid != myuid && myuid != 0) {
printf("quota: %s (uid %lu): permission denied\n", name, uid);
printf("quota: %s (uid %d): permission denied\n", name, uid);
return;
}
showquotas(USRQUOTA, uid, name);
@ -204,7 +218,8 @@ showgid(gid)
u_long gid;
{
struct group *grp = getgrgid(gid);
int ngroups, gidset[NGROUPS];
int ngroups;
gid_t mygid, gidset[NGROUPS];
register int i;
char *name;
@ -212,18 +227,22 @@ showgid(gid)
name = "(no entry)";
else
name = grp->gr_name;
mygid = getgid();
ngroups = getgroups(NGROUPS, gidset);
if (ngroups < 0) {
perror("quota: getgroups");
return;
}
for (i = 1; i < ngroups; i++)
if (gid == gidset[i])
break;
if (i >= ngroups && getuid() != 0) {
fprintf(stderr, "quota: %s (gid %lu): permission denied\n",
name, gid);
return;
if (gid != mygid) {
for (i = 0; i < ngroups; i++)
if (gid == gidset[i])
break;
if (i >= ngroups && getuid() != 0) {
fprintf(stderr,
"quota: %s (gid %d): permission denied\n",
name, gid);
return;
}
}
showquotas(GRPQUOTA, gid, name);
}
@ -235,25 +254,30 @@ showgrpname(name)
char *name;
{
struct group *grp = getgrnam(name);
int ngroups, gidset[NGROUPS];
int ngroups;
gid_t mygid, gidset[NGROUPS];
register int i;
if (grp == NULL) {
fprintf(stderr, "quota: %s: unknown group\n", name);
return;
}
mygid = getgid();
ngroups = getgroups(NGROUPS, gidset);
if (ngroups < 0) {
perror("quota: getgroups");
return;
}
for (i = 1; i < ngroups; i++)
if (grp->gr_gid == gidset[i])
break;
if (i >= ngroups && getuid() != 0) {
fprintf(stderr, "quota: %s (gid %d): permission denied\n",
name, grp->gr_gid);
return;
if (grp->gr_gid != mygid) {
for (i = 0; i < ngroups; i++)
if (grp->gr_gid == gidset[i])
break;
if (i >= ngroups && getuid() != 0) {
fprintf(stderr,
"quota: %s (gid %d): permission denied\n",
name, grp->gr_gid);
return;
}
}
showquotas(GRPQUOTA, grp->gr_gid, name);
}
@ -264,8 +288,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;
@ -315,18 +339,20 @@ 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%8lu%c%7lu%8lu%8s"
, qup->fsname
, (u_long)
(dbtob(qup->dqblk.dqb_curblocks) / 1024)
, nam
, (u_long) (dbtob(qup->dqblk.dqb_curblocks) / 1024)
, (msgb == (char *)0) ? ' ' : '*'
, (u_long)
(dbtob(qup->dqblk.dqb_bsoftlimit) / 1024)
, (u_long)
(dbtob(qup->dqblk.dqb_bhardlimit) / 1024)
, (u_long) (dbtob(qup->dqblk.dqb_bsoftlimit) / 1024)
, (u_long) (dbtob(qup->dqblk.dqb_bhardlimit) / 1024)
, (msgb == (char *)0) ? ""
: timeprt(qup->dqblk.dqb_btime));
printf("%8lu%c%7lu%8lu%8s\n"
:timeprt(qup->dqblk.dqb_btime));
printf("%8d%c%7d%8d%8s\n"
, qup->dqblk.dqb_curinodes
, (msgi == (char *)0) ? ' ' : '*'
, qup->dqblk.dqb_isoftlimit
@ -347,7 +373,7 @@ heading(type, id, name, tag)
char *name, *tag;
{
printf("Disk quotas for %s %s (%cid %lu): %s\n", qfextension[type],
printf("Disk quotas for %s %s (%cid %d): %s\n", qfextension[type],
name, *qfextension[type], id, tag);
if (!qflag && tag[0] == '\0') {
printf("%15s%8s %7s%8s%8s%8s %7s%8s%8s\n"
@ -383,14 +409,14 @@ timeprt(seconds)
minutes = (seconds + 30) / 60;
hours = (minutes + 30) / 60;
if (hours >= 36) {
sprintf(buf, "%lddays", (hours + 12) / 24);
sprintf(buf, "%ddays", (hours + 12) / 24);
return (buf);
}
if (minutes >= 60) {
sprintf(buf, "%2ld:%ld", minutes / 60, minutes % 60);
sprintf(buf, "%2d:%d", minutes / 60, minutes % 60);
return (buf);
}
sprintf(buf, "%2ld", minutes);
sprintf(buf, "%2d", minutes);
return (buf);
}
@ -402,61 +428,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, (long)(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 (fst[i].f_type == MOUNT_NFS) {
if (getnfsquota(&fst[i], NULL, qup, id, quotatype) == 0)
continue;
} else if (fst[i].f_type == MOUNT_UFS) {
/*
* 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);
}
@ -464,15 +485,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);
@ -499,6 +519,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;
{