diff options
author | Lin Ling <Lin.Ling@Sun.COM> | 2009-04-27 11:08:32 -0700 |
---|---|---|
committer | Lin Ling <Lin.Ling@Sun.COM> | 2009-04-27 11:08:32 -0700 |
commit | edea4b556f0b07459cdcc780ffcd28a40b374945 (patch) | |
tree | b4a3df57ae8f98c99122a68576f165c1a3c4582e /usr/src/cmd | |
parent | 4baa2c25868c5c0ae97aa381b8b1c571c85dc5ef (diff) | |
download | illumos-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.c | 243 | ||||
-rw-r--r-- | usr/src/cmd/fs.d/ufs/quota/quota.c | 149 |
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); +} |