summaryrefslogtreecommitdiffstats
path: root/usr.bin/quota
diff options
context:
space:
mode:
authorgraichen <graichen@FreeBSD.org>1996-01-05 08:37:29 +0000
committergraichen <graichen@FreeBSD.org>1996-01-05 08:37:29 +0000
commitfa1beef3d1355720caf95045f9f1a27c3d48b7e5 (patch)
tree5a08503ad7cb9e38dea3986a3cd29d3ed526a937 /usr.bin/quota
parentd977de1bb8ed0b4f1f0fc23a85162f735b0ade09 (diff)
downloadFreeBSD-src-fa1beef3d1355720caf95045f9f1a27c3d48b7e5.zip
FreeBSD-src-fa1beef3d1355720caf95045f9f1a27c3d48b7e5.tar.gz
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
Diffstat (limited to 'usr.bin/quota')
-rw-r--r--usr.bin/quota/Makefile3
-rw-r--r--usr.bin/quota/quota.118
-rw-r--r--usr.bin/quota/quota.c359
3 files changed, 291 insertions, 89 deletions
diff --git a/usr.bin/quota/Makefile b/usr.bin/quota/Makefile
index 2ee365e..de2b4a8 100644
--- a/usr.bin/quota/Makefile
+++ b/usr.bin/quota/Makefile
@@ -4,4 +4,7 @@ PROG= quota
BINOWN= root
BINMODE=4555
+DPADD= ${LIBRPCSVC}
+LDADD= -lrpcsvc
+
.include <bsd.prog.mk>
diff --git a/usr.bin/quota/quota.1 b/usr.bin/quota/quota.1
index e87a3a4..43fb51f 100644
--- a/usr.bin/quota/quota.1
+++ b/usr.bin/quota/quota.1
@@ -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
diff --git a/usr.bin/quota/quota.c b/usr.bin/quota/quota.c
index 8140ebb..b26e144 100644
--- a/usr.bin/quota/quota.c
+++ b/usr.bin/quota/quota.c
@@ -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);
+ 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);
+ }
}
- if (quotactl(fs->fs_file, qcmd, id, &qup->dqblk) != 0) {
- if ((fd = open(qfpathname, O_RDONLY)) < 0) {
- perror(qfpathname);
- free(qup);
+ if (fst[i].f_type == MOUNT_NFS) {
+ if (getnfsquota(&fst[i], NULL, qup, id, quotatype) == 0)
continue;
- }
- 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);
+ } 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;
- }
- close(fd);
- }
- strcpy(qup->fsname, fs->fs_file);
+ 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;
{
OpenPOWER on IntegriCloud