summaryrefslogtreecommitdiff
path: root/usr/src/cmd
diff options
context:
space:
mode:
authorLin Ling <Lin.Ling@Sun.COM>2009-04-27 11:08:32 -0700
committerLin Ling <Lin.Ling@Sun.COM>2009-04-27 11:08:32 -0700
commitedea4b556f0b07459cdcc780ffcd28a40b374945 (patch)
treeb4a3df57ae8f98c99122a68576f165c1a3c4582e /usr/src/cmd
parent4baa2c25868c5c0ae97aa381b8b1c571c85dc5ef (diff)
downloadillumos-gate-edea4b556f0b07459cdcc780ffcd28a40b374945.tar.gz
6824968 add ZFS userquota support to rquotad
Diffstat (limited to 'usr/src/cmd')
-rw-r--r--usr/src/cmd/fs.d/nfs/rquotad/rpc.rquotad.c243
-rw-r--r--usr/src/cmd/fs.d/ufs/quota/quota.c149
2 files changed, 307 insertions, 85 deletions
diff --git a/usr/src/cmd/fs.d/nfs/rquotad/rpc.rquotad.c b/usr/src/cmd/fs.d/nfs/rquotad/rpc.rquotad.c
index b06a240969..04216a941e 100644
--- a/usr/src/cmd/fs.d/nfs/rquotad/rpc.rquotad.c
+++ b/usr/src/cmd/fs.d/nfs/rquotad/rpc.rquotad.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,15 +19,12 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
@@ -52,11 +48,14 @@
#include <rpcsvc/rquota.h>
#include <tiuser.h>
#include <unistd.h>
+#include <dlfcn.h>
+#include <libzfs.h>
#define QFNAME "quotas" /* name of quota file */
#define RPCSVC_CLOSEDOWN 120 /* 2 minutes */
struct fsquot {
+ char *fsq_fstype;
struct fsquot *fsq_next;
char *fsq_dir;
char *fsq_devname;
@@ -78,6 +77,42 @@ void getquota();
int hasquota();
void log_cant_reply();
void setupfs();
+static void zexit();
+
+static libzfs_handle_t *(*_libzfs_init)(void);
+static void (*_libzfs_fini)(libzfs_handle_t *);
+static zfs_handle_t *(*_zfs_open)(libzfs_handle_t *, const char *, int);
+static void (*_zfs_close)(zfs_handle_t *);
+static int (*_zfs_prop_get_userquota_int)(zfs_handle_t *, const char *,
+ uint64_t *);
+static libzfs_handle_t *g_zfs = NULL;
+
+/*
+ * Dynamically check for libzfs, in case the user hasn't installed the SUNWzfs
+ * packages. 'rquotad' supports zfs as an option.
+ */
+static void
+load_libzfs(void)
+{
+ void *hdl;
+
+ if (g_zfs != NULL)
+ return;
+
+ if ((hdl = dlopen("libzfs.so", RTLD_LAZY)) != NULL) {
+ _libzfs_init = (libzfs_handle_t *(*)(void))dlsym(hdl,
+ "libzfs_init");
+ _libzfs_fini = (void (*)())dlsym(hdl, "libzfs_fini");
+ _zfs_open = (zfs_handle_t *(*)())dlsym(hdl, "zfs_open");
+ _zfs_close = (void (*)())dlsym(hdl, "zfs_close");
+ _zfs_prop_get_userquota_int = (int (*)())
+ dlsym(hdl, "zfs_prop_get_userquota_int");
+
+ if (_libzfs_init && _libzfs_fini && _zfs_open &&
+ _zfs_close && _zfs_prop_get_userquota_int)
+ g_zfs = _libzfs_init();
+ }
+}
/*ARGSUSED*/
int
@@ -85,6 +120,8 @@ main(int argc, char *argv[])
{
register SVCXPRT *transp;
+ load_libzfs();
+
/*
* If stdin looks like a TLI endpoint, we assume
* that we were started by a port monitor. If
@@ -102,11 +139,11 @@ main(int argc, char *argv[])
if (t_sync(0) == -1) {
syslog(LOG_ERR, "could not do t_sync");
- exit(1);
+ zexit(1);
}
if (t_getinfo(0, &tinfo) == -1) {
syslog(LOG_ERR, "t_getinfo failed");
- exit(1);
+ zexit(1);
}
if (tinfo.servtype == T_CLTS) {
if (tinfo.addr == INET_ADDRSTRLEN)
@@ -115,7 +152,7 @@ main(int argc, char *argv[])
netid = "udp6";
} else {
syslog(LOG_ERR, "wrong transport");
- exit(1);
+ zexit(1);
}
}
if ((nconf = getnetconfigent(netid)) == NULL) {
@@ -124,22 +161,22 @@ main(int argc, char *argv[])
if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {
syslog(LOG_ERR, "cannot create server handle");
- exit(1);
+ zexit(1);
}
if (nconf)
freenetconfigent(nconf);
if (!svc_reg(transp, RQUOTAPROG, RQUOTAVERS, dispatch, 0)) {
syslog(LOG_ERR,
- "unable to register (RQUOTAPROG, RQUOTAVERS).");
- exit(1);
+ "unable to register (RQUOTAPROG, RQUOTAVERS).");
+ zexit(1);
}
(void) sigset(SIGALRM, (void(*)(int)) closedown);
(void) alarm(RPCSVC_CLOSEDOWN);
svc_run();
- exit(1);
+ zexit(1);
/* NOTREACHED */
}
@@ -152,9 +189,9 @@ main(int argc, char *argv[])
break;
case -1:
perror("rquotad: can't fork");
- exit(1);
+ zexit(1);
default: /* parent */
- exit(0);
+ zexit(0);
}
/*
@@ -175,7 +212,7 @@ main(int argc, char *argv[])
*/
if (svc_create(dispatch, RQUOTAPROG, RQUOTAVERS, "datagram_v") == 0) {
syslog(LOG_ERR, "couldn't register datagram_v service");
- exit(1);
+ zexit(1);
}
/*
@@ -222,7 +259,7 @@ closedown()
struct t_info tinfo;
if (!t_getinfo(0, &tinfo) && (tinfo.servtype == T_CLTS))
- exit(0);
+ zexit(0);
for (i = 0, openfd = 0; i < svc_max_pollfd && openfd < 2; i++) {
if (svc_pollfd[i].fd >= 0)
@@ -230,11 +267,45 @@ closedown()
}
if (openfd <= 1)
- exit(0);
+ zexit(0);
}
(void) alarm(RPCSVC_CLOSEDOWN);
}
+static int
+getzfsquota(uid_t user, char *dataset, struct dqblk *zq)
+{
+ zfs_handle_t *zhp = NULL;
+ char propname[ZFS_MAXPROPLEN];
+ uint64_t userquota, userused;
+
+ if (g_zfs == NULL)
+ return (1);
+
+ if ((zhp = _zfs_open(g_zfs, dataset, ZFS_TYPE_DATASET)) == NULL) {
+ syslog(LOG_ERR, "can not open zfs dataset %s", dataset);
+ return (1);
+ }
+
+ (void) snprintf(propname, sizeof (propname), "userquota@%u", user);
+ if (_zfs_prop_get_userquota_int(zhp, propname, &userquota) != 0) {
+ _zfs_close(zhp);
+ return (1);
+ }
+
+ (void) snprintf(propname, sizeof (propname), "userused@%u", user);
+ if (_zfs_prop_get_userquota_int(zhp, propname, &userused) != 0) {
+ _zfs_close(zhp);
+ return (1);
+ }
+
+ zq->dqb_bhardlimit = userquota / DEV_BSIZE;
+ zq->dqb_bsoftlimit = userquota / DEV_BSIZE;
+ zq->dqb_curblocks = userused / DEV_BSIZE;
+ _zfs_close(zhp);
+ return (0);
+}
+
void
getquota(rqstp, transp)
register struct svc_req *rqstp;
@@ -268,41 +339,54 @@ getquota(rqstp, transp)
goto sendreply;
}
- if (quotactl(Q_GETQUOTA, fsqp->fsq_dir, (uid_t)gqa.gqa_uid, &dqblk) !=
- 0) {
- qactive = FALSE;
- if ((errno == ENOENT) ||
- (rqstp->rq_proc != RQUOTAPROC_GETQUOTA)) {
+ bzero(&dqblk, sizeof (dqblk));
+ if (strcmp(fsqp->fsq_fstype, MNTTYPE_ZFS) == 0) {
+ if (getzfsquota(gqa.gqa_uid, fsqp->fsq_devname, &dqblk)) {
gqr.status = Q_NOQUOTA;
goto sendreply;
}
-
- /*
- * If there is no quotas file, don't bother to sync it.
- */
- if (errno != ENOENT) {
- if (quotactl(Q_ALLSYNC, fsqp->fsq_dir,
- (uid_t)gqa.gqa_uid, &dqblk) < 0 &&
- errno == EINVAL)
- syslog(LOG_WARNING,
- "Quotas are not compiled into this kernel");
- if (getdiskquota(fsqp, (uid_t)gqa.gqa_uid, &dqblk) ==
- 0) {
+ qactive = TRUE;
+ } else {
+ if (quotactl(Q_GETQUOTA, fsqp->fsq_dir,
+ (uid_t)gqa.gqa_uid, &dqblk) != 0) {
+ qactive = FALSE;
+ if ((errno == ENOENT) ||
+ (rqstp->rq_proc != RQUOTAPROC_GETQUOTA)) {
gqr.status = Q_NOQUOTA;
goto sendreply;
}
+
+ /*
+ * If there is no quotas file, don't bother to sync it.
+ */
+ if (errno != ENOENT) {
+ if (quotactl(Q_ALLSYNC, fsqp->fsq_dir,
+ (uid_t)gqa.gqa_uid, &dqblk) < 0 &&
+ errno == EINVAL)
+ syslog(LOG_WARNING,
+ "Quotas are not compiled "
+ "into this kernel");
+ if (getdiskquota(fsqp, (uid_t)gqa.gqa_uid,
+ &dqblk) == 0) {
+ gqr.status = Q_NOQUOTA;
+ goto sendreply;
+ }
+ }
+ } else {
+ qactive = TRUE;
}
- } else {
- qactive = TRUE;
- }
- /*
- * We send the remaining time instead of the absolute time
- * because clock skew between machines should be much greater
- * than rpc delay.
- */
+ /*
+ * We send the remaining time instead of the absolute time
+ * because clock skew between machines should be much greater
+ * than rpc delay.
+ */
#define gqrslt getquota_rslt_u.gqr_rquota
- gettimeofday(&tv, NULL);
+ gettimeofday(&tv, NULL);
+ gqr.gqrslt.rq_btimeleft = dqblk.dqb_btimelimit - tv.tv_sec;
+ gqr.gqrslt.rq_ftimeleft = dqblk.dqb_ftimelimit - tv.tv_sec;
+ }
+
gqr.status = Q_OK;
gqr.gqrslt.rq_active = qactive;
gqr.gqrslt.rq_bsize = DEV_BSIZE;
@@ -312,8 +396,6 @@ getquota(rqstp, transp)
gqr.gqrslt.rq_fhardlimit = dqblk.dqb_fhardlimit;
gqr.gqrslt.rq_fsoftlimit = dqblk.dqb_fsoftlimit;
gqr.gqrslt.rq_curfiles = dqblk.dqb_curfiles;
- gqr.gqrslt.rq_btimeleft = dqblk.dqb_btimelimit - tv.tv_sec;
- gqr.gqrslt.rq_ftimeleft = dqblk.dqb_ftimelimit - tv.tv_sec;
sendreply:
errno = 0;
if (!svc_sendreply(transp, xdr_getquota_rslt, (caddr_t)&gqr))
@@ -350,7 +432,8 @@ quotactl(cmd, mountp, uid, dqp)
!(hasmntopt(&mntp, MNTOPT_RQ) ||
hasmntopt(&mntp, MNTOPT_QUOTA)))
continue;
- (void) strcpy(mountpoint, mntp.mnt_mountp);
+ (void) strlcpy(mountpoint, mntp.mnt_mountp,
+ sizeof (mountpoint));
strcat(mountpoint, "/quotas");
if ((fd = open64(mountpoint, O_RDWR)) >= 0)
break;
@@ -365,7 +448,7 @@ quotactl(cmd, mountp, uid, dqp)
errno = ENOENT;
return (-1);
}
- (void) strcpy(mountpoint, mountp);
+ (void) strlcpy(mountpoint, mountp, sizeof (mountpoint));
strcat(mountpoint, "/quotas");
if ((fd = open64(mountpoint, O_RDONLY)) < 0) {
@@ -423,16 +506,41 @@ findfsq(dir)
if (stat(dir, &sb) < 0)
return (NULL);
for (fsqp = fsqlist; fsqp != NULL; fsqp = fsqp->fsq_next) {
- if (sb.st_dev == fsqp->fsq_dev)
+ if (strcmp(fsqp->fsq_fstype, MNTTYPE_ZFS) == 0) {
+ if (strcmp(fsqp->fsq_dir, dir) == 0)
+ return (fsqp);
+ } else if (sb.st_dev == fsqp->fsq_dev) {
return (fsqp);
+ }
}
return (NULL);
}
+static void
+setup_zfs(struct mnttab *mp)
+{
+ struct fsquot *fsqp;
+
+ fsqp = malloc(sizeof (struct fsquot));
+ if (fsqp == NULL) {
+ syslog(LOG_ERR, "out of memory");
+ zexit(1);
+ }
+ fsqp->fsq_dir = strdup(mp->mnt_mountp);
+ fsqp->fsq_devname = strdup(mp->mnt_special);
+ if (fsqp->fsq_dir == NULL || fsqp->fsq_devname == NULL) {
+ syslog(LOG_ERR, "out of memory");
+ zexit(1);
+ }
+ fsqp->fsq_fstype = MNTTYPE_ZFS;
+ fsqp->fsq_next = fsqlist;
+ fsqlist = fsqp;
+}
+
void
setupfs()
{
- register struct fsquot *fsqp;
+ struct fsquot *fsqp;
FILE *mt;
struct mnttab m;
struct stat sb;
@@ -445,31 +553,36 @@ setupfs()
}
while (getmntent(mt, &m) == 0) {
+ if (strcmp(m.mnt_fstype, MNTTYPE_ZFS) == 0) {
+ setup_zfs(&m);
+ continue;
+ }
+
if (strcmp(m.mnt_fstype, MNTTYPE_UFS) != 0)
continue;
if (!hasquota(m.mnt_mntopts)) {
- sprintf(qfilename, "%s/%s", m.mnt_mountp, QFNAME);
+ snprintf(qfilename, sizeof (qfilename), "%s/%s",
+ m.mnt_mountp, QFNAME);
if (access(qfilename, F_OK) < 0)
continue;
}
if (stat(m.mnt_special, &sb) < 0 ||
(sb.st_mode & S_IFMT) != S_IFBLK)
continue;
- fsqp = (struct fsquot *)malloc(sizeof (struct fsquot));
+ fsqp = malloc(sizeof (struct fsquot));
if (fsqp == NULL) {
syslog(LOG_ERR, "out of memory");
- exit(1);
+ zexit(1);
}
- fsqp->fsq_next = fsqlist;
- fsqp->fsq_dir = (char *)malloc(strlen(m.mnt_mountp) + 1);
- fsqp->fsq_devname = (char *)malloc(strlen(m.mnt_special) + 1);
+ fsqp->fsq_dir = strdup(m.mnt_mountp);
+ fsqp->fsq_devname = strdup(m.mnt_special);
if (fsqp->fsq_dir == NULL || fsqp->fsq_devname == NULL) {
syslog(LOG_ERR, "out of memory");
- exit(1);
+ zexit(1);
}
- strcpy(fsqp->fsq_dir, m.mnt_mountp);
- strcpy(fsqp->fsq_devname, m.mnt_special);
+ fsqp->fsq_fstype = MNTTYPE_UFS;
fsqp->fsq_dev = sb.st_rdev;
+ fsqp->fsq_next = fsqlist;
fsqlist = fsqp;
}
(void) fclose(mt);
@@ -502,7 +615,7 @@ getdiskquota(fsqp, uid, dqp)
int fd;
char qfilename[MAXPATHLEN];
- sprintf(qfilename, "%s/%s", fsqp->fsq_dir, QFNAME);
+ snprintf(qfilename, sizeof (qfilename), "%s/%s", fsqp->fsq_dir, QFNAME);
if ((fd = open64(qfilename, O_RDONLY)) < 0)
return (0);
(void) llseek(fd, (offset_t)dqoff(uid), L_SET);
@@ -606,3 +719,11 @@ hasquota(opts)
return (0);
}
+
+static void
+zexit(int n)
+{
+ if (g_zfs != NULL)
+ _libzfs_fini(g_zfs);
+ exit(n);
+}
diff --git a/usr/src/cmd/fs.d/ufs/quota/quota.c b/usr/src/cmd/fs.d/ufs/quota/quota.c
index 8595a15b78..615e3c8655 100644
--- a/usr/src/cmd/fs.d/ufs/quota/quota.c
+++ b/usr/src/cmd/fs.d/ufs/quota/quota.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -61,6 +61,8 @@
#include <rpcsvc/rquota.h>
#include <zone.h>
#include "../../nfs/lib/replica.h"
+#include <dlfcn.h>
+#include <libzfs.h>
int vflag;
int nolocalquota;
@@ -80,6 +82,8 @@ extern char *optarg;
#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
#endif
+static void zexit(int);
+static int getzfsquota(char *, char *, struct dqblk *);
static int getnfsquota(char *, char *, uid_t, struct dqblk *);
static void showuid(uid_t);
static void showquotas(uid_t, char *);
@@ -88,6 +92,41 @@ static void heading(uid_t, char *);
static void prquota(struct mnttab *, struct dqblk *);
static void fmttime(char *, long);
+static libzfs_handle_t *(*_libzfs_init)(void);
+static void (*_libzfs_fini)(libzfs_handle_t *);
+static zfs_handle_t *(*_zfs_open)(libzfs_handle_t *, const char *, int);
+static void (*_zfs_close)(zfs_handle_t *);
+static int (*_zfs_prop_get_userquota_int)(zfs_handle_t *, const char *,
+ uint64_t *);
+static libzfs_handle_t *g_zfs = NULL;
+
+/*
+ * Dynamically check for libzfs, in case the user hasn't installed the SUNWzfs
+ * packages. 'quota' utility supports zfs as an option.
+ */
+static void
+load_libzfs(void)
+{
+ void *hdl;
+
+ if (g_zfs != NULL)
+ return;
+
+ if ((hdl = dlopen("libzfs.so", RTLD_LAZY)) != NULL) {
+ _libzfs_init = (libzfs_handle_t *(*)(void))dlsym(hdl,
+ "libzfs_init");
+ _libzfs_fini = (void (*)())dlsym(hdl, "libzfs_fini");
+ _zfs_open = (zfs_handle_t *(*)())dlsym(hdl, "zfs_open");
+ _zfs_close = (void (*)())dlsym(hdl, "zfs_close");
+ _zfs_prop_get_userquota_int = (int (*)())
+ dlsym(hdl, "zfs_prop_get_userquota_int");
+
+ if (_libzfs_init && _libzfs_fini && _zfs_open &&
+ _zfs_close && _zfs_prop_get_userquota_int)
+ g_zfs = _libzfs_init();
+ }
+}
+
int
main(int argc, char *argv[])
{
@@ -114,6 +153,8 @@ main(int argc, char *argv[])
exit(1);
}
+ load_libzfs();
+
while ((opt = getopt(argc, argv, "vV")) != EOF) {
switch (opt) {
@@ -138,8 +179,8 @@ main(int argc, char *argv[])
break;
case '?':
- fprintf(stderr, "ufs usage: quota [-v] [username]\n");
- exit(32);
+ fprintf(stderr, "usage: quota [-v] [username]\n");
+ zexit(32);
}
}
if (quotactl(Q_ALLSYNC, NULL, (uid_t)0, NULL) < 0 && errno == EINVAL) {
@@ -149,7 +190,7 @@ main(int argc, char *argv[])
}
if (argc == optind) {
showuid(getuid());
- exit(0);
+ zexit(0);
}
for (i = optind; i < argc; i++) {
if (alldigits(argv[i])) {
@@ -214,7 +255,7 @@ showquotas(uid_t uid, char *name)
myuid = getuid();
if (uid != myuid && myuid != 0) {
printf("quota: %s (uid %d): permission denied\n", name, uid);
- exit(32);
+ zexit(32);
}
memset(my_zonename, '\0', ZONENAME_MAX);
@@ -224,7 +265,11 @@ showquotas(uid_t uid, char *name)
heading(uid, name);
mtab = fopen(MNTTAB, "r");
while (getmntent(mtab, &mnt) == NULL) {
- if (strcmp(mnt.mnt_fstype, MNTTYPE_UFS) == 0) {
+ if (strcmp(mnt.mnt_fstype, MNTTYPE_ZFS) == 0) {
+ bzero(&dqblk, sizeof (dqblk));
+ if (getzfsquota(name, mnt.mnt_special, &dqblk))
+ continue;
+ } else if (strcmp(mnt.mnt_fstype, MNTTYPE_UFS) == 0) {
if (nolocalquota ||
(quotactl(Q_GETQUOTA,
mnt.mnt_mountp, uid, &dqblk) != 0 &&
@@ -479,22 +524,22 @@ prquota(struct mnttab *mntp, struct dqblk *dqp)
tv.tv_usec = 0;
if (dqp->dqb_bsoftlimit && dqp->dqb_curblocks >= dqp->dqb_bsoftlimit) {
if (dqp->dqb_btimelimit == 0) {
- strcpy(btimeleft, "NOT STARTED");
+ strlcpy(btimeleft, "NOT STARTED", sizeof (btimeleft));
} else if (dqp->dqb_btimelimit > tv.tv_sec) {
fmttime(btimeleft, dqp->dqb_btimelimit - tv.tv_sec);
} else {
- strcpy(btimeleft, "EXPIRED");
+ strlcpy(btimeleft, "EXPIRED", sizeof (btimeleft));
}
} else {
btimeleft[0] = '\0';
}
if (dqp->dqb_fsoftlimit && dqp->dqb_curfiles >= dqp->dqb_fsoftlimit) {
if (dqp->dqb_ftimelimit == 0) {
- strcpy(ftimeleft, "NOT STARTED");
+ strlcpy(ftimeleft, "NOT STARTED", sizeof (ftimeleft));
} else if (dqp->dqb_ftimelimit > tv.tv_sec) {
fmttime(ftimeleft, dqp->dqb_ftimelimit - tv.tv_sec);
} else {
- strcpy(ftimeleft, "EXPIRED");
+ strlcpy(ftimeleft, "EXPIRED", sizeof (ftimeleft));
}
} else {
ftimeleft[0] = '\0';
@@ -505,16 +550,31 @@ prquota(struct mnttab *mntp, struct dqblk *dqp)
} else {
cp = mntp->mnt_mountp;
}
- printf("%-12.12s %7d %6d %6d %11s %6d %6d %6d %11s\n",
- cp,
- kb(dqp->dqb_curblocks),
- kb(dqp->dqb_bsoftlimit),
- kb(dqp->dqb_bhardlimit),
- btimeleft,
- dqp->dqb_curfiles,
- dqp->dqb_fsoftlimit,
- dqp->dqb_fhardlimit,
- ftimeleft);
+
+ if (dqp->dqb_curfiles == 0 &&
+ dqp->dqb_fsoftlimit == 0 && dqp->dqb_fhardlimit == 0) {
+ printf("%-12.12s %7d %6d %6d %11s %6s %6s %6s %11s\n",
+ cp,
+ kb(dqp->dqb_curblocks),
+ kb(dqp->dqb_bsoftlimit),
+ kb(dqp->dqb_bhardlimit),
+ "-",
+ "-",
+ "-",
+ "-",
+ "-");
+ } else {
+ printf("%-12.12s %7d %6d %6d %11s %6d %6d %6d %11s\n",
+ cp,
+ kb(dqp->dqb_curblocks),
+ kb(dqp->dqb_bsoftlimit),
+ kb(dqp->dqb_bhardlimit),
+ btimeleft,
+ dqp->dqb_curfiles,
+ dqp->dqb_fsoftlimit,
+ dqp->dqb_fhardlimit,
+ ftimeleft);
+ }
}
static void
@@ -534,14 +594,15 @@ fmttime(char *buf, long time)
};
if (time <= 0) {
- strcpy(buf, "EXPIRED");
+ strlcpy(buf, "EXPIRED", sizeof (*buf));
return;
}
for (i = 0; i < sizeof (cunits)/sizeof (cunits[0]); i++) {
if (time >= cunits[i].c_secs)
break;
}
- sprintf(buf, "%.1f %s", (double)time/cunits[i].c_secs, cunits[i].c_str);
+ snprintf(buf, sizeof (*buf), "%.1f %s",
+ (double)time/cunits[i].c_secs, cunits[i].c_str);
}
int
@@ -620,7 +681,7 @@ quotactl(int cmd, char *mountp, uid_t uid, caddr_t addr)
if ((fstab = fopen(MNTTAB, "r")) == NULL) {
fprintf(stderr, "%s: ", MNTTAB);
perror("open");
- exit(32);
+ zexit(32);
}
fd = -1;
while ((status = getmntent(fstab, &mnt)) == NULL) {
@@ -793,7 +854,7 @@ callaurpc(char *host, int prognum, int versnum, int procnum,
}
oldprognum = prognum;
oldversnum = versnum;
- (void) strcpy(oldhost, host);
+ (void) strlcpy(oldhost, host, sizeof (oldhost));
clnt_stat = RPC_SUCCESS;
}
@@ -805,3 +866,43 @@ callaurpc(char *host, int prognum, int versnum, int procnum,
return ((int)clnt_stat);
}
+
+static int
+getzfsquota(char *user, char *dataset, struct dqblk *zq)
+{
+ zfs_handle_t *zhp = NULL;
+ char propname[ZFS_MAXPROPLEN];
+ uint64_t userquota, userused;
+
+ if (g_zfs == NULL)
+ return (1);
+
+ if ((zhp = _zfs_open(g_zfs, dataset, ZFS_TYPE_DATASET)) == NULL)
+ return (1);
+
+ (void) snprintf(propname, sizeof (propname), "userquota@%s", user);
+ if (_zfs_prop_get_userquota_int(zhp, propname, &userquota) != 0) {
+ _zfs_close(zhp);
+ return (1);
+ }
+
+ (void) snprintf(propname, sizeof (propname), "userused@%s", user);
+ if (_zfs_prop_get_userquota_int(zhp, propname, &userused) != 0) {
+ _zfs_close(zhp);
+ return (1);
+ }
+
+ zq->dqb_bhardlimit = userquota / DEV_BSIZE;
+ zq->dqb_bsoftlimit = userquota / DEV_BSIZE;
+ zq->dqb_curblocks = userused / DEV_BSIZE;
+ _zfs_close(zhp);
+ return (0);
+}
+
+static void
+zexit(int n)
+{
+ if (g_zfs != NULL)
+ _libzfs_fini(g_zfs);
+ exit(n);
+}