Print this page
NEX-7498 Cannot display userquota of 2TB or larger using quota
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/fs.d/ufs/quota/quota.c
+++ new/usr/src/cmd/fs.d/ufs/quota/quota.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
|
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 +/* Copyright 2016 Nexenta Systems, Inc. All rights reserved. */
27 +
26 28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 29 /* All Rights Reserved */
28 30
29 31 /*
30 32 * University Copyright- Copyright (c) 1982, 1986, 1988
31 33 * The Regents of the University of California
32 34 * All Rights Reserved
33 35 *
34 36 * University Acknowledgment- Portions of this document are derived from
35 37 * software developed by the University of California, Berkeley, and its
36 38 * contributors.
37 39 */
38 40
39 41 /*
40 42 * Disk quota reporting program.
41 43 */
42 44 #include <stdio.h>
43 45 #include <sys/mnttab.h>
44 46 #include <ctype.h>
45 47 #include <pwd.h>
46 48 #include <errno.h>
47 49 #include <fcntl.h>
48 50 #include <memory.h>
49 51 #include <sys/time.h>
50 52 #include <sys/param.h>
51 53 #include <sys/types.h>
52 54 #include <sys/sysmacros.h>
53 55 #include <sys/mntent.h>
54 56 #include <sys/file.h>
55 57 #include <sys/stat.h>
56 58 #include <sys/fs/ufs_quota.h>
57 59 #include <priv_utils.h>
58 60 #include <locale.h>
59 61 #include <rpc/rpc.h>
|
↓ open down ↓ |
24 lines elided |
↑ open up ↑ |
60 62 #include <netdb.h>
61 63 #include <rpcsvc/rquota.h>
62 64 #include <zone.h>
63 65 #include "../../nfs/lib/replica.h"
64 66 #include <dlfcn.h>
65 67 #include <libzfs.h>
66 68
67 69 int vflag;
68 70 int nolocalquota;
69 71
72 +/*
73 + * struct dqblk is a 32 bit quantity and is common across NFS and UFS.
74 + * UFS has a 2TB limit and an uint32_t can hold this value.
75 + * NFS translates this to rquota where all members are unit32_t in size.
76 + * A private dqblk, dqblk_zfs is defined here.
77 + */
78 +struct dqblk_zfs {
79 + uint64_t dqbz_bhardlimit; /* absolute limit on disk blks alloc */
80 + uint64_t dqbz_bsoftlimit; /* preferred limit on disk blks */
81 + uint64_t dqbz_curblocks; /* current block count */
82 + uint64_t dqbz_fhardlimit; /* maximum # allocated files + 1 */
83 + uint64_t dqbz_fsoftlimit; /* preferred file limit */
84 + uint64_t dqbz_curfiles; /* current # allocated files */
85 + uint64_t dqbz_btimelimit; /* time limit for excessive disk use */
86 + uint64_t dqbz_ftimelimit; /* time limit for excessive files */
87 +};
70 88 extern int optind;
71 89 extern char *optarg;
72 90
73 91 #define QFNAME "quotas"
74 92
75 93 #if DEV_BSIZE < 1024
76 94 #define kb(x) ((x) / (1024 / DEV_BSIZE))
77 95 #else
78 96 #define kb(x) ((x) * (DEV_BSIZE / 1024))
79 97 #endif
80 98
81 99 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
82 100 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
83 101 #endif
84 102
85 103 static void zexit(int);
86 -static int getzfsquota(char *, char *, struct dqblk *);
104 +static boolean_t blklimits_is_zero(struct dqblk *, struct dqblk_zfs *);
105 +static int getzfsquota(char *, char *, struct dqblk_zfs *);
87 106 static int getnfsquota(char *, char *, uid_t, struct dqblk *);
88 107 static void showuid(uid_t);
89 108 static void showquotas(uid_t, char *);
90 -static void warn(struct mnttab *, struct dqblk *);
109 +static void warn(struct mnttab *, struct dqblk *, struct dqblk_zfs *);
110 +static void warn_dqblk_impl(struct mnttab *, struct dqblk *);
111 +static void warn_dqblk_zfs_impl(struct mnttab *, struct dqblk_zfs *);
91 112 static void heading(uid_t, char *);
92 -static void prquota(struct mnttab *, struct dqblk *);
113 +static void prquota(struct mnttab *, struct dqblk *, struct dqblk_zfs *);
114 +static void prquota_dqblk_impl(struct mnttab *, struct dqblk *);
115 +static void prquota_dqblk_zfs_impl(struct mnttab *, struct dqblk_zfs *);
93 116 static void fmttime(char *, long);
94 117
95 -static libzfs_handle_t *(*_libzfs_init)(void);
96 -static void (*_libzfs_fini)(libzfs_handle_t *);
97 -static zfs_handle_t *(*_zfs_open)(libzfs_handle_t *, const char *, int);
98 -static void (*_zfs_close)(zfs_handle_t *);
99 -static int (*_zfs_prop_get_userquota_int)(zfs_handle_t *, const char *,
100 - uint64_t *);
101 118 static libzfs_handle_t *g_zfs = NULL;
102 119
103 -/*
104 - * Dynamically check for libzfs, in case the user hasn't installed the SUNWzfs
105 - * packages. 'quota' utility supports zfs as an option.
106 - */
107 -static void
108 -load_libzfs(void)
109 -{
110 - void *hdl;
111 -
112 - if (g_zfs != NULL)
113 - return;
114 -
115 - if ((hdl = dlopen("libzfs.so", RTLD_LAZY)) != NULL) {
116 - _libzfs_init = (libzfs_handle_t *(*)(void))dlsym(hdl,
117 - "libzfs_init");
118 - _libzfs_fini = (void (*)())dlsym(hdl, "libzfs_fini");
119 - _zfs_open = (zfs_handle_t *(*)())dlsym(hdl, "zfs_open");
120 - _zfs_close = (void (*)())dlsym(hdl, "zfs_close");
121 - _zfs_prop_get_userquota_int = (int (*)())
122 - dlsym(hdl, "zfs_prop_get_userquota_int");
123 -
124 - if (_libzfs_init && _libzfs_fini && _zfs_open &&
125 - _zfs_close && _zfs_prop_get_userquota_int)
126 - g_zfs = _libzfs_init();
127 - }
128 -}
129 -
130 120 int
131 121 main(int argc, char *argv[])
132 122 {
133 123 int opt;
134 124 int i;
135 125 int status = 0;
136 126
137 127 (void) setlocale(LC_ALL, "");
138 128 (void) textdomain(TEXT_DOMAIN);
139 129
140 130 /*
141 131 * PRIV_FILE_DAC_READ is needed to read the QFNAME file
142 132 * Clear all other privleges from the limit set, and add
143 133 * the required privilege to the bracketed set.
144 134 */
145 135
|
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
146 136 if (__init_suid_priv(PU_CLEARLIMITSET, PRIV_FILE_DAC_READ,
147 137 NULL) == -1) {
148 138 (void) fprintf(stderr,
149 139 gettext("Insufficient privileges, "
150 140 "quota must be set-uid root or have "
151 141 "file_dac_read privileges\n"));
152 142
153 143 exit(1);
154 144 }
155 145
156 - load_libzfs();
157 146
158 147 while ((opt = getopt(argc, argv, "vV")) != EOF) {
159 148 switch (opt) {
160 149
161 150 case 'v':
162 151 vflag++;
163 152 break;
164 153
165 154 case 'V': /* Print command line */
166 155 {
167 156 char *opt_text;
168 157 int opt_count;
169 158
170 159 (void) fprintf(stdout, "quota -F UFS ");
171 160 for (opt_count = 1; opt_count < argc; opt_count++) {
172 161 opt_text = argv[opt_count];
173 162 if (opt_text)
174 163 (void) fprintf(stdout, " %s ",
175 164 opt_text);
176 165 }
177 166 (void) fprintf(stdout, "\n");
178 167 }
179 168 break;
180 169
181 170 case '?':
182 171 fprintf(stderr, "usage: quota [-v] [username]\n");
183 172 zexit(32);
184 173 }
185 174 }
186 175 if (quotactl(Q_ALLSYNC, NULL, (uid_t)0, NULL) < 0 && errno == EINVAL) {
187 176 if (vflag)
188 177 fprintf(stderr, "There are no quotas on this system\n");
189 178 nolocalquota++;
190 179 }
191 180 if (argc == optind) {
192 181 showuid(getuid());
193 182 zexit(0);
194 183 }
195 184 for (i = optind; i < argc; i++) {
196 185 if (alldigits(argv[i])) {
197 186 showuid((uid_t)atoi(argv[i]));
198 187 } else
199 188 status |= showname(argv[i]);
200 189 }
201 190 __priv_relinquish();
202 191 return (status);
203 192 }
204 193
205 194 static void
206 195 showuid(uid_t uid)
207 196 {
208 197 struct passwd *pwd = getpwuid(uid);
209 198
210 199 if (uid == 0) {
211 200 if (vflag)
212 201 printf("no disk quota for uid 0\n");
213 202 return;
214 203 }
215 204 if (pwd == NULL)
216 205 showquotas(uid, "(no account)");
217 206 else
218 207 showquotas(uid, pwd->pw_name);
219 208 }
220 209
221 210 int
222 211 showname(char *name)
223 212 {
224 213 struct passwd *pwd = getpwnam(name);
225 214
226 215 if (pwd == NULL) {
227 216 fprintf(stderr, "quota: %s: unknown user\n", name);
228 217 return (32);
229 218 }
230 219 if (pwd->pw_uid == 0) {
231 220 if (vflag)
232 221 printf("no disk quota for %s (uid 0)\n", name);
233 222 return (0);
234 223 }
|
↓ open down ↓ |
68 lines elided |
↑ open up ↑ |
235 224 showquotas(pwd->pw_uid, name);
236 225 return (0);
237 226 }
238 227
239 228 static void
240 229 showquotas(uid_t uid, char *name)
241 230 {
242 231 struct mnttab mnt;
243 232 FILE *mtab;
244 233 struct dqblk dqblk;
234 + struct dqblk_zfs dqblkz;
245 235 uid_t myuid;
246 236 struct failed_srv {
247 237 char *serv_name;
248 238 struct failed_srv *next;
249 239 };
250 240 struct failed_srv *failed_srv_list = NULL;
251 241 int rc;
252 242 char my_zonename[ZONENAME_MAX];
253 243 zoneid_t my_zoneid = getzoneid();
254 244
255 245 myuid = getuid();
256 246 if (uid != myuid && myuid != 0) {
257 247 printf("quota: %s (uid %d): permission denied\n", name, uid);
|
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
258 248 zexit(32);
259 249 }
260 250
261 251 memset(my_zonename, '\0', ZONENAME_MAX);
262 252 getzonenamebyid(my_zoneid, my_zonename, ZONENAME_MAX);
263 253
264 254 if (vflag)
265 255 heading(uid, name);
266 256 mtab = fopen(MNTTAB, "r");
267 257 while (getmntent(mtab, &mnt) == NULL) {
258 + boolean_t is_zfs = B_FALSE;
259 +
268 260 if (strcmp(mnt.mnt_fstype, MNTTYPE_ZFS) == 0) {
269 - bzero(&dqblk, sizeof (dqblk));
270 - if (getzfsquota(name, mnt.mnt_special, &dqblk))
261 + is_zfs = B_TRUE;
262 + bzero(&dqblkz, sizeof (dqblkz));
263 + if (getzfsquota(name, mnt.mnt_special, &dqblkz))
271 264 continue;
272 265 } else if (strcmp(mnt.mnt_fstype, MNTTYPE_UFS) == 0) {
273 266 if (nolocalquota ||
274 267 (quotactl(Q_GETQUOTA,
275 268 mnt.mnt_mountp, uid, &dqblk) != 0 &&
276 269 !(vflag && getdiskquota(&mnt, uid, &dqblk))))
277 270 continue;
278 271 } else if (strcmp(mnt.mnt_fstype, MNTTYPE_NFS) == 0) {
279 272
280 273 struct replica *rl;
281 274 int count;
282 275 char *mntopt = NULL;
283 276
284 277 /*
285 278 * Skip checking quotas for file systems mounted
286 279 * in other zones. Zone names will be passed in
287 280 * following format from hasmntopt():
288 281 * "zone=<zone-name>,<mnt options...>"
289 282 */
290 283 if ((mntopt = hasmntopt(&mnt, MNTOPT_ZONE)) &&
291 284 (my_zonename[0] != '\0')) {
292 285 mntopt += strcspn(mntopt, "=") + 1;
293 286 if (strncmp(mntopt, my_zonename,
294 287 strcspn(mntopt, ",")) != 0)
295 288 continue;
296 289 }
297 290
298 291 if (hasopt(MNTOPT_NOQUOTA, mnt.mnt_mntopts))
299 292 continue;
300 293
301 294 /*
302 295 * Skip quota processing if mounted with public
303 296 * option. We are not likely to be able to pierce
304 297 * a fire wall to contact the quota server.
305 298 */
306 299 if (hasopt(MNTOPT_PUBLIC, mnt.mnt_mntopts))
307 300 continue;
308 301
309 302 rl = parse_replica(mnt.mnt_special, &count);
310 303
311 304 if (rl == NULL) {
312 305
313 306 if (count < 0)
314 307 fprintf(stderr, "cannot find hostname "
315 308 "and/or pathname for %s\n",
316 309 mnt.mnt_mountp);
317 310 else
318 311 fprintf(stderr, "no memory to parse "
319 312 "mnttab entry for %s\n",
320 313 mnt.mnt_mountp);
321 314 continue;
322 315 }
323 316
324 317 /*
325 318 * We skip quota reporting on mounts with replicas
326 319 * for the following reasons:
327 320 *
328 321 * (1) Very little point in reporting quotas on
329 322 * a set of read-only replicas ... how will the
330 323 * user correct the problem?
331 324 *
332 325 * (2) Which replica would we report the quota
333 326 * for? If we pick the current replica, what
334 327 * happens when a fail over event occurs? The
335 328 * next time quota is run, the quota will look
336 329 * all different, or there won't even be one.
337 330 * This has the potential to break scripts.
338 331 *
339 332 * If we prnt quouta for all replicas, how do
340 333 * we present the output without breaking scripts?
341 334 */
342 335
343 336 if (count > 1) {
344 337 free_replica(rl, count);
345 338 continue;
346 339 }
347 340
348 341 /*
349 342 * Skip file systems mounted using public fh.
350 343 * We are not likely to be able to pierce
351 344 * a fire wall to contact the quota server.
352 345 */
353 346 if (strcmp(rl[0].host, "nfs") == 0 &&
354 347 strncmp(rl[0].path, "//", 2) == 0) {
355 348 free_replica(rl, count);
356 349 continue;
357 350 }
358 351
359 352 /*
360 353 * Skip getting quotas from failing servers
361 354 */
362 355 if (failed_srv_list != NULL) {
363 356 struct failed_srv *tmp_list;
364 357 int found_failed = 0;
365 358 size_t len = strlen(rl[0].host);
366 359
367 360 tmp_list = failed_srv_list;
368 361 do {
369 362 if (strncasecmp(rl[0].host,
370 363 tmp_list->serv_name, len) == 0) {
371 364 found_failed = 1;
372 365 break;
373 366 }
374 367 } while ((tmp_list = tmp_list->next) != NULL);
375 368 if (found_failed) {
376 369 free_replica(rl, count);
377 370 continue;
378 371 }
379 372 }
380 373
381 374 rc = getnfsquota(rl[0].host, rl[0].path, uid, &dqblk);
382 375 if (rc != RPC_SUCCESS) {
383 376 size_t len;
384 377 struct failed_srv *tmp_srv;
385 378
386 379 /*
387 380 * Failed to get quota from this server. Add
388 381 * this server to failed_srv_list and skip
389 382 * getting quotas for other mounted filesystems
390 383 * from this server.
391 384 */
392 385 if (rc == RPC_TIMEDOUT || rc == RPC_CANTSEND) {
393 386 len = strlen(rl[0].host);
394 387 tmp_srv = (struct failed_srv *)malloc(
395 388 sizeof (struct failed_srv));
396 389 tmp_srv->serv_name = (char *)malloc(
397 390 len * sizeof (char) + 1);
398 391 strncpy(tmp_srv->serv_name, rl[0].host,
399 392 len);
400 393 tmp_srv->serv_name[len] = '\0';
401 394
402 395 tmp_srv->next = failed_srv_list;
403 396 failed_srv_list = tmp_srv;
|
↓ open down ↓ |
123 lines elided |
↑ open up ↑ |
404 397 }
405 398
406 399 free_replica(rl, count);
407 400 continue;
408 401 }
409 402
410 403 free_replica(rl, count);
411 404 } else {
412 405 continue;
413 406 }
414 - if (dqblk.dqb_bsoftlimit == 0 && dqblk.dqb_bhardlimit == 0 &&
415 - dqblk.dqb_fsoftlimit == 0 && dqblk.dqb_fhardlimit == 0)
407 +
408 + if (blklimits_is_zero(&dqblk, is_zfs ? &dqblkz : NULL))
416 409 continue;
410 +
417 411 if (vflag)
418 - prquota(&mnt, &dqblk);
412 + prquota(&mnt, &dqblk, is_zfs ? &dqblkz : NULL);
419 413 else
420 - warn(&mnt, &dqblk);
414 + warn(&mnt, &dqblk, is_zfs ? &dqblkz : NULL);
415 +
421 416 }
422 417
423 418 /*
424 419 * Free list of failed servers
425 420 */
426 421 while (failed_srv_list != NULL) {
427 422 struct failed_srv *tmp_srv = failed_srv_list;
428 423
429 424 failed_srv_list = failed_srv_list->next;
430 425 free(tmp_srv->serv_name);
431 426 free(tmp_srv);
432 427 }
433 428
434 429 fclose(mtab);
435 430 }
436 431
437 432 static void
438 -warn(struct mnttab *mntp, struct dqblk *dqp)
433 +warn(struct mnttab *mntp, struct dqblk *dqp, struct dqblk_zfs *dqzp)
439 434 {
440 - struct timeval tv;
441 -
442 - time(&(tv.tv_sec));
443 - tv.tv_usec = 0;
444 - if (dqp->dqb_bhardlimit &&
445 - dqp->dqb_curblocks >= dqp->dqb_bhardlimit) {
446 - printf("Block limit reached on %s\n", mntp->mnt_mountp);
447 - } else if (dqp->dqb_bsoftlimit &&
448 - dqp->dqb_curblocks >= dqp->dqb_bsoftlimit) {
449 - if (dqp->dqb_btimelimit == 0) {
450 - printf("Over disk quota on %s, remove %luK\n",
451 - mntp->mnt_mountp,
452 - kb(dqp->dqb_curblocks - dqp->dqb_bsoftlimit + 1));
453 - } else if (dqp->dqb_btimelimit > tv.tv_sec) {
454 - char btimeleft[80];
455 -
456 - fmttime(btimeleft, dqp->dqb_btimelimit - tv.tv_sec);
457 - printf("Over disk quota on %s, remove %luK within %s\n",
458 - mntp->mnt_mountp,
459 - kb(dqp->dqb_curblocks - dqp->dqb_bsoftlimit + 1),
460 - btimeleft);
461 - } else {
462 - printf(
463 - "Over disk quota on %s, time limit has expired, remove %luK\n",
464 - mntp->mnt_mountp,
465 - kb(dqp->dqb_curblocks - dqp->dqb_bsoftlimit + 1));
466 - }
467 - }
468 - if (dqp->dqb_fhardlimit &&
469 - dqp->dqb_curfiles >= dqp->dqb_fhardlimit) {
470 - printf("File count limit reached on %s\n", mntp->mnt_mountp);
471 - } else if (dqp->dqb_fsoftlimit &&
472 - dqp->dqb_curfiles >= dqp->dqb_fsoftlimit) {
473 - if (dqp->dqb_ftimelimit == 0) {
474 - printf("Over file quota on %s, remove %lu file%s\n",
475 - mntp->mnt_mountp,
476 - dqp->dqb_curfiles - dqp->dqb_fsoftlimit + 1,
477 - ((dqp->dqb_curfiles - dqp->dqb_fsoftlimit + 1) > 1 ?
478 - "s" : ""));
479 - } else if (dqp->dqb_ftimelimit > tv.tv_sec) {
480 - char ftimeleft[80];
481 -
482 - fmttime(ftimeleft, dqp->dqb_ftimelimit - tv.tv_sec);
483 - printf(
484 -"Over file quota on %s, remove %lu file%s within %s\n",
485 - mntp->mnt_mountp,
486 - dqp->dqb_curfiles - dqp->dqb_fsoftlimit + 1,
487 - ((dqp->dqb_curfiles - dqp->dqb_fsoftlimit + 1) > 1 ?
488 - "s" : ""), ftimeleft);
489 - } else {
490 - printf(
491 -"Over file quota on %s, time limit has expired, remove %lu file%s\n",
492 - mntp->mnt_mountp,
493 - dqp->dqb_curfiles - dqp->dqb_fsoftlimit + 1,
494 - ((dqp->dqb_curfiles - dqp->dqb_fsoftlimit + 1) > 1 ?
495 - "s" : ""));
496 - }
497 - }
435 + if (dqzp != NULL)
436 + warn_dqblk_zfs_impl(mntp, dqzp);
437 + else
438 + warn_dqblk_impl(mntp, dqp);
498 439 }
499 440
500 441 static void
501 442 heading(uid_t uid, char *name)
502 443 {
503 444 printf("Disk quotas for %s (uid %ld):\n", name, (long)uid);
504 445 printf("%-12s %7s%7s%7s%12s%7s%7s%7s%12s\n",
505 446 "Filesystem",
506 447 "usage",
507 448 "quota",
508 449 "limit",
509 450 "timeleft",
510 451 "files",
511 452 "quota",
512 453 "limit",
513 454 "timeleft");
514 455 }
515 456
516 457 static void
517 -prquota(struct mnttab *mntp, struct dqblk *dqp)
458 +prquota(struct mnttab *mntp, struct dqblk *dqp, struct dqblk_zfs *dqzp)
518 459 {
519 - struct timeval tv;
520 - char ftimeleft[80], btimeleft[80];
521 - char *cp;
522 -
523 - time(&(tv.tv_sec));
524 - tv.tv_usec = 0;
525 - if (dqp->dqb_bsoftlimit && dqp->dqb_curblocks >= dqp->dqb_bsoftlimit) {
526 - if (dqp->dqb_btimelimit == 0) {
527 - strlcpy(btimeleft, "NOT STARTED", sizeof (btimeleft));
528 - } else if (dqp->dqb_btimelimit > tv.tv_sec) {
529 - fmttime(btimeleft, dqp->dqb_btimelimit - tv.tv_sec);
530 - } else {
531 - strlcpy(btimeleft, "EXPIRED", sizeof (btimeleft));
532 - }
533 - } else {
534 - btimeleft[0] = '\0';
535 - }
536 - if (dqp->dqb_fsoftlimit && dqp->dqb_curfiles >= dqp->dqb_fsoftlimit) {
537 - if (dqp->dqb_ftimelimit == 0) {
538 - strlcpy(ftimeleft, "NOT STARTED", sizeof (ftimeleft));
539 - } else if (dqp->dqb_ftimelimit > tv.tv_sec) {
540 - fmttime(ftimeleft, dqp->dqb_ftimelimit - tv.tv_sec);
541 - } else {
542 - strlcpy(ftimeleft, "EXPIRED", sizeof (ftimeleft));
543 - }
544 - } else {
545 - ftimeleft[0] = '\0';
546 - }
547 - if (strlen(mntp->mnt_mountp) > 12) {
548 - printf("%s\n", mntp->mnt_mountp);
549 - cp = "";
550 - } else {
551 - cp = mntp->mnt_mountp;
552 - }
553 -
554 - if (dqp->dqb_curfiles == 0 &&
555 - dqp->dqb_fsoftlimit == 0 && dqp->dqb_fhardlimit == 0) {
556 - printf("%-12.12s %7d %6d %6d %11s %6s %6s %6s %11s\n",
557 - cp,
558 - kb(dqp->dqb_curblocks),
559 - kb(dqp->dqb_bsoftlimit),
560 - kb(dqp->dqb_bhardlimit),
561 - "-",
562 - "-",
563 - "-",
564 - "-",
565 - "-");
566 - } else {
567 - printf("%-12.12s %7d %6d %6d %11s %6d %6d %6d %11s\n",
568 - cp,
569 - kb(dqp->dqb_curblocks),
570 - kb(dqp->dqb_bsoftlimit),
571 - kb(dqp->dqb_bhardlimit),
572 - btimeleft,
573 - dqp->dqb_curfiles,
574 - dqp->dqb_fsoftlimit,
575 - dqp->dqb_fhardlimit,
576 - ftimeleft);
577 - }
460 + if (dqzp != NULL)
461 + prquota_dqblk_zfs_impl(mntp, dqzp);
462 + else
463 + prquota_dqblk_impl(mntp, dqp);
578 464 }
579 465
580 466 static void
581 467 fmttime(char *buf, long time)
582 468 {
583 469 int i;
584 470 static struct {
585 471 int c_secs; /* conversion units in secs */
586 472 char *c_str; /* unit string */
587 473 } cunits [] = {
588 474 {60*60*24*28, "months"},
589 475 {60*60*24*7, "weeks"},
590 476 {60*60*24, "days"},
591 477 {60*60, "hours"},
592 478 {60, "mins"},
593 479 {1, "secs"}
594 480 };
595 481
596 482 if (time <= 0) {
597 483 strlcpy(buf, "EXPIRED", sizeof (*buf));
598 484 return;
599 485 }
600 486 for (i = 0; i < sizeof (cunits)/sizeof (cunits[0]); i++) {
601 487 if (time >= cunits[i].c_secs)
602 488 break;
603 489 }
604 490 snprintf(buf, sizeof (*buf), "%.1f %s",
605 491 (double)time/cunits[i].c_secs, cunits[i].c_str);
606 492 }
607 493
608 494 int
609 495 alldigits(char *s)
610 496 {
611 497 int c;
612 498
613 499 c = *s++;
614 500 do {
615 501 if (!isdigit(c))
616 502 return (0);
617 503 } while (c = *s++);
618 504 return (1);
619 505 }
620 506
621 507 int
622 508 getdiskquota(struct mnttab *mntp, uid_t uid, struct dqblk *dqp)
623 509 {
624 510 int fd;
625 511 dev_t fsdev;
626 512 struct stat64 statb;
627 513 char qfilename[MAXPATHLEN];
628 514
629 515 if (stat64(mntp->mnt_special, &statb) < 0 ||
630 516 (statb.st_mode & S_IFMT) != S_IFBLK)
631 517 return (0);
632 518 fsdev = statb.st_rdev;
633 519 (void) snprintf(qfilename, sizeof (qfilename), "%s/%s",
634 520 mntp->mnt_mountp, QFNAME);
635 521 if (stat64(qfilename, &statb) < 0 || statb.st_dev != fsdev)
636 522 return (0);
637 523 (void) __priv_bracket(PRIV_ON);
638 524 fd = open64(qfilename, O_RDONLY);
639 525 (void) __priv_bracket(PRIV_OFF);
640 526 if (fd < 0)
641 527 return (0);
642 528 (void) llseek(fd, (offset_t)dqoff(uid), L_SET);
643 529 switch (read(fd, dqp, sizeof (struct dqblk))) {
644 530 case 0: /* EOF */
645 531 /*
646 532 * Convert implicit 0 quota (EOF)
647 533 * into an explicit one (zero'ed dqblk).
648 534 */
649 535 memset((caddr_t)dqp, 0, sizeof (struct dqblk));
650 536 break;
651 537
652 538 case sizeof (struct dqblk): /* OK */
653 539 break;
654 540
655 541 default: /* ERROR */
656 542 close(fd);
657 543 return (0);
658 544 }
659 545 close(fd);
660 546 return (1);
661 547 }
662 548
663 549 int
664 550 quotactl(int cmd, char *mountp, uid_t uid, caddr_t addr)
665 551 {
666 552 int fd;
667 553 int status;
668 554 struct quotctl quota;
669 555 char qfile[MAXPATHLEN];
670 556
671 557 FILE *fstab;
672 558 struct mnttab mnt;
673 559
674 560
675 561 if ((mountp == NULL) && (cmd == Q_ALLSYNC)) {
676 562 /*
677 563 * Find the mount point of any mounted file system. This is
678 564 * because the ioctl that implements the quotactl call has
679 565 * to go to a real file, and not to the block device.
680 566 */
681 567 if ((fstab = fopen(MNTTAB, "r")) == NULL) {
682 568 fprintf(stderr, "%s: ", MNTTAB);
683 569 perror("open");
684 570 zexit(32);
685 571 }
686 572 fd = -1;
687 573 while ((status = getmntent(fstab, &mnt)) == NULL) {
688 574 if (strcmp(mnt.mnt_fstype, MNTTYPE_UFS) != 0 ||
689 575 hasopt(MNTOPT_RO, mnt.mnt_mntopts))
690 576 continue;
691 577 if ((strlcpy(qfile, mnt.mnt_mountp,
692 578 sizeof (qfile)) >= sizeof (qfile)) ||
693 579 (strlcat(qfile, "/" QFNAME, sizeof (qfile)) >=
694 580 sizeof (qfile))) {
695 581 continue;
696 582 }
697 583 (void) __priv_bracket(PRIV_ON);
698 584 fd = open64(qfile, O_RDONLY);
699 585 (void) __priv_bracket(PRIV_OFF);
700 586 if (fd != -1)
701 587 break;
702 588 }
703 589 fclose(fstab);
704 590 if (fd == -1) {
705 591 errno = ENOENT;
706 592 return (-1);
707 593 }
708 594 } else {
709 595 if (mountp == NULL || mountp[0] == '\0') {
710 596 errno = ENOENT;
711 597 return (-1);
712 598 }
713 599 if ((strlcpy(qfile, mountp, sizeof (qfile)) >= sizeof
714 600 (qfile)) ||
715 601 (strlcat(qfile, "/" QFNAME, sizeof (qfile)) >= sizeof
716 602 (qfile))) {
717 603 errno = ENOENT;
718 604 return (-1);
719 605 }
720 606 (void) __priv_bracket(PRIV_ON);
721 607 fd = open64(qfile, O_RDONLY);
722 608 (void) __priv_bracket(PRIV_OFF);
723 609 if (fd < 0)
724 610 return (-1);
725 611 } /* else */
726 612 quota.op = cmd;
727 613 quota.uid = uid;
728 614 quota.addr = addr;
729 615 status = ioctl(fd, Q_QUOTACTL, "a);
730 616 if (fd != 0)
731 617 close(fd);
732 618 return (status);
733 619 }
734 620
735 621
736 622 /*
737 623 * Return 1 if opt appears in optlist
738 624 */
739 625 int
740 626 hasopt(char *opt, char *optlist)
741 627 {
742 628 char *value;
743 629 char *opts[2];
744 630
745 631 opts[0] = opt;
746 632 opts[1] = NULL;
747 633
748 634 if (optlist == NULL)
749 635 return (0);
750 636 while (*optlist != '\0') {
751 637 if (getsubopt(&optlist, opts, &value) == 0)
752 638 return (1);
753 639 }
754 640 return (0);
755 641 }
756 642
757 643 /*
758 644 * If there are no quotas available, then getnfsquota() returns
759 645 * RPC_SYSTEMERROR to caller.
760 646 */
761 647 static int
762 648 getnfsquota(char *hostp, char *path, uid_t uid, struct dqblk *dqp)
763 649 {
764 650 struct getquota_args gq_args;
765 651 struct getquota_rslt gq_rslt;
766 652 struct rquota *rquota;
767 653 extern char *strchr();
768 654 int rpc_err;
769 655
770 656 gq_args.gqa_pathp = path;
771 657 gq_args.gqa_uid = uid;
772 658 rpc_err = callaurpc(hostp, RQUOTAPROG, RQUOTAVERS,
773 659 (vflag? RQUOTAPROC_GETQUOTA: RQUOTAPROC_GETACTIVEQUOTA),
774 660 xdr_getquota_args, &gq_args, xdr_getquota_rslt, &gq_rslt);
775 661 if (rpc_err != RPC_SUCCESS) {
776 662 return (rpc_err);
777 663 }
778 664 switch (gq_rslt.status) {
779 665 case Q_OK:
780 666 {
781 667 struct timeval tv;
782 668 u_longlong_t limit;
783 669
784 670 rquota = &gq_rslt.getquota_rslt_u.gqr_rquota;
785 671
786 672 if (!vflag && rquota->rq_active == FALSE) {
787 673 return (RPC_SYSTEMERROR);
788 674 }
789 675 gettimeofday(&tv, NULL);
790 676 limit = (u_longlong_t)(rquota->rq_bhardlimit) *
791 677 rquota->rq_bsize / DEV_BSIZE;
792 678 dqp->dqb_bhardlimit = limit;
793 679 limit = (u_longlong_t)(rquota->rq_bsoftlimit) *
794 680 rquota->rq_bsize / DEV_BSIZE;
795 681 dqp->dqb_bsoftlimit = limit;
796 682 limit = (u_longlong_t)(rquota->rq_curblocks) *
797 683 rquota->rq_bsize / DEV_BSIZE;
798 684 dqp->dqb_curblocks = limit;
799 685 dqp->dqb_fhardlimit = rquota->rq_fhardlimit;
800 686 dqp->dqb_fsoftlimit = rquota->rq_fsoftlimit;
801 687 dqp->dqb_curfiles = rquota->rq_curfiles;
802 688 dqp->dqb_btimelimit =
803 689 tv.tv_sec + rquota->rq_btimeleft;
804 690 dqp->dqb_ftimelimit =
805 691 tv.tv_sec + rquota->rq_ftimeleft;
806 692 return (RPC_SUCCESS);
807 693 }
808 694
809 695 case Q_NOQUOTA:
810 696 return (RPC_SYSTEMERROR);
811 697
812 698 case Q_EPERM:
813 699 fprintf(stderr, "quota permission error, host: %s\n", hostp);
814 700 return (RPC_AUTHERROR);
815 701
|
↓ open down ↓ |
228 lines elided |
↑ open up ↑ |
816 702 default:
817 703 fprintf(stderr, "bad rpc result, host: %s\n", hostp);
818 704 return (RPC_CANTDECODEARGS);
819 705 }
820 706
821 707 /* NOTREACHED */
822 708 }
823 709
824 710 int
825 711 callaurpc(char *host, int prognum, int versnum, int procnum,
826 - xdrproc_t inproc, char *in, xdrproc_t outproc, char *out)
712 + xdrproc_t inproc, char *in, xdrproc_t outproc, char *out)
827 713 {
828 714 static enum clnt_stat clnt_stat;
829 715 struct timeval tottimeout = {20, 0};
830 716
831 717 static CLIENT *cl = NULL;
832 718 static int oldprognum, oldversnum;
833 719 static char oldhost[MAXHOSTNAMELEN+1];
834 720
835 721 /*
836 722 * Cache the client handle in case there are lots
837 723 * of entries in the /etc/mnttab for the same
838 724 * server. If the server returns an error, don't
839 725 * make further calls.
840 726 */
841 727 if (cl == NULL || oldprognum != prognum || oldversnum != versnum ||
842 728 strcmp(oldhost, host) != 0) {
843 729 if (cl) {
844 730 clnt_destroy(cl);
845 731 cl = NULL;
846 732 }
847 733 cl = clnt_create_timed(host, prognum, versnum, "udp",
848 734 &tottimeout);
849 735 if (cl == NULL)
850 736 return ((int)RPC_TIMEDOUT);
851 737 if ((cl->cl_auth = authunix_create_default()) == NULL) {
852 738 clnt_destroy(cl);
853 739 return (RPC_CANTSEND);
854 740 }
855 741 oldprognum = prognum;
856 742 oldversnum = versnum;
857 743 (void) strlcpy(oldhost, host, sizeof (oldhost));
858 744 clnt_stat = RPC_SUCCESS;
859 745 }
860 746
|
↓ open down ↓ |
24 lines elided |
↑ open up ↑ |
861 747 if (clnt_stat != RPC_SUCCESS)
862 748 return ((int)clnt_stat); /* don't bother retrying */
863 749
864 750 clnt_stat = clnt_call(cl, procnum, inproc, in,
865 751 outproc, out, tottimeout);
866 752
867 753 return ((int)clnt_stat);
868 754 }
869 755
870 756 static int
871 -getzfsquota(char *user, char *dataset, struct dqblk *zq)
757 +getzfsquota(char *user, char *dataset, struct dqblk_zfs *zq)
872 758 {
873 759 zfs_handle_t *zhp = NULL;
874 760 char propname[ZFS_MAXPROPLEN];
875 761 uint64_t userquota, userused;
876 762
877 - if (g_zfs == NULL)
878 - return (1);
763 + if (g_zfs == NULL) {
764 + g_zfs = libzfs_init();
765 + }
879 766
880 - if ((zhp = _zfs_open(g_zfs, dataset, ZFS_TYPE_DATASET)) == NULL)
767 + if ((zhp = zfs_open(g_zfs, dataset, ZFS_TYPE_DATASET)) == NULL)
881 768 return (1);
882 769
883 770 (void) snprintf(propname, sizeof (propname), "userquota@%s", user);
884 - if (_zfs_prop_get_userquota_int(zhp, propname, &userquota) != 0) {
885 - _zfs_close(zhp);
771 + if (zfs_prop_get_userquota_int(zhp, propname, &userquota) != 0) {
772 + zfs_close(zhp);
886 773 return (1);
887 774 }
888 775
889 776 (void) snprintf(propname, sizeof (propname), "userused@%s", user);
890 - if (_zfs_prop_get_userquota_int(zhp, propname, &userused) != 0) {
891 - _zfs_close(zhp);
777 + if (zfs_prop_get_userquota_int(zhp, propname, &userused) != 0) {
778 + zfs_close(zhp);
892 779 return (1);
893 780 }
894 781
895 - zq->dqb_bhardlimit = userquota / DEV_BSIZE;
896 - zq->dqb_bsoftlimit = userquota / DEV_BSIZE;
897 - zq->dqb_curblocks = userused / DEV_BSIZE;
898 - _zfs_close(zhp);
782 + zq->dqbz_bhardlimit = userquota / DEV_BSIZE;
783 + zq->dqbz_bsoftlimit = userquota / DEV_BSIZE;
784 + zq->dqbz_curblocks = userused / DEV_BSIZE;
785 + zfs_close(zhp);
899 786 return (0);
900 787 }
901 788
789 +static boolean_t
790 +blklimits_is_zero(struct dqblk *dqp, struct dqblk_zfs *dqzp)
791 +{
792 + if (dqzp == NULL) {
793 + if (dqp->dqb_bsoftlimit == 0 && dqp->dqb_bhardlimit == 0 &&
794 + dqp->dqb_fsoftlimit == 0 && dqp->dqb_fhardlimit == 0) {
795 + return (B_TRUE);
796 + } else {
797 + return (B_FALSE);
798 + }
799 + } else {
800 + if (dqzp->dqbz_bsoftlimit == 0 && dqzp->dqbz_bhardlimit == 0 &&
801 + dqzp->dqbz_fsoftlimit == 0 && dqzp->dqbz_fhardlimit == 0) {
802 + return (B_TRUE);
803 + } else {
804 + return (B_FALSE);
805 + }
806 + }
807 +}
808 +
902 809 static void
810 +warn_dqblk_impl(struct mnttab *mntp, struct dqblk *dqp)
811 +{
812 + struct timeval tv;
813 +
814 + time(&(tv.tv_sec));
815 + tv.tv_usec = 0;
816 + if (dqp->dqb_bhardlimit &&
817 + dqp->dqb_curblocks >= dqp->dqb_bhardlimit) {
818 + printf("Block limit reached on %s\n", mntp->mnt_mountp);
819 + } else if (dqp->dqb_bsoftlimit &&
820 + dqp->dqb_curblocks >= dqp->dqb_bsoftlimit) {
821 + if (dqp->dqb_btimelimit == 0) {
822 + printf("Over disk quota on %s, remove %luK\n",
823 + mntp->mnt_mountp,
824 + kb(dqp->dqb_curblocks - dqp->dqb_bsoftlimit + 1));
825 + } else if (dqp->dqb_btimelimit > tv.tv_sec) {
826 + char btimeleft[80];
827 +
828 + fmttime(btimeleft, dqp->dqb_btimelimit - tv.tv_sec);
829 + printf("Over disk quota on %s, remove %luK within %s\n",
830 + mntp->mnt_mountp,
831 + kb(dqp->dqb_curblocks - dqp->dqb_bsoftlimit + 1),
832 + btimeleft);
833 + } else {
834 + printf("Over disk quota on %s, time limit has expired,"
835 + " remove %luK\n", mntp->mnt_mountp,
836 + kb(dqp->dqb_curblocks - dqp->dqb_bsoftlimit + 1));
837 + }
838 + }
839 + if (dqp->dqb_fhardlimit &&
840 + dqp->dqb_curfiles >= dqp->dqb_fhardlimit) {
841 + printf("File count limit reached on %s\n", mntp->mnt_mountp);
842 + } else if (dqp->dqb_fsoftlimit &&
843 + dqp->dqb_curfiles >= dqp->dqb_fsoftlimit) {
844 + if (dqp->dqb_ftimelimit == 0) {
845 + printf("Over file quota on %s, remove %lu file%s\n",
846 + mntp->mnt_mountp,
847 + dqp->dqb_curfiles - dqp->dqb_fsoftlimit + 1,
848 + ((dqp->dqb_curfiles - dqp->dqb_fsoftlimit + 1) > 1 ?
849 + "s" : ""));
850 + } else if (dqp->dqb_ftimelimit > tv.tv_sec) {
851 + char ftimeleft[80];
852 +
853 + fmttime(ftimeleft, dqp->dqb_ftimelimit - tv.tv_sec);
854 + printf("Over file quota on %s, remove %lu file%s"
855 + " within %s\n", mntp->mnt_mountp,
856 + dqp->dqb_curfiles - dqp->dqb_fsoftlimit + 1,
857 + ((dqp->dqb_curfiles - dqp->dqb_fsoftlimit + 1) > 1 ?
858 + "s" : ""), ftimeleft);
859 + } else {
860 + printf("Over file quota on %s, time limit has expired,"
861 + " remove %lu file%s\n", mntp->mnt_mountp,
862 + dqp->dqb_curfiles - dqp->dqb_fsoftlimit + 1,
863 + ((dqp->dqb_curfiles - dqp->dqb_fsoftlimit + 1) > 1 ?
864 + "s" : ""));
865 + }
866 + }
867 +}
868 +
869 +static void
870 +warn_dqblk_zfs_impl(struct mnttab *mntp, struct dqblk_zfs *dqzp)
871 +{
872 + struct timeval tv;
873 +
874 + time(&(tv.tv_sec));
875 + tv.tv_usec = 0;
876 + if (dqzp->dqbz_bhardlimit &&
877 + dqzp->dqbz_curblocks >= dqzp->dqbz_bhardlimit) {
878 + printf("Block limit reached on %s\n", mntp->mnt_mountp);
879 + } else if (dqzp->dqbz_bsoftlimit &&
880 + dqzp->dqbz_curblocks >= dqzp->dqbz_bsoftlimit) {
881 + if (dqzp->dqbz_btimelimit == 0) {
882 + printf("Over disk quota on %s, remove %luK\n",
883 + mntp->mnt_mountp,
884 + kb(dqzp->dqbz_curblocks -
885 + dqzp->dqbz_bsoftlimit + 1));
886 + } else if (dqzp->dqbz_btimelimit > tv.tv_sec) {
887 + char btimeleft[80];
888 +
889 + fmttime(btimeleft, dqzp->dqbz_btimelimit - tv.tv_sec);
890 + printf("Over disk quota on %s, remove %luK within %s\n",
891 + mntp->mnt_mountp,
892 + kb(dqzp->dqbz_curblocks -
893 + dqzp->dqbz_bsoftlimit + 1),
894 + btimeleft);
895 + } else {
896 + printf("Over disk quota on %s, time limit has expired,"
897 + " remove %luK\n", mntp->mnt_mountp,
898 + kb(dqzp->dqbz_curblocks -
899 + dqzp->dqbz_bsoftlimit + 1));
900 + }
901 + }
902 + if (dqzp->dqbz_fhardlimit &&
903 + dqzp->dqbz_curfiles >= dqzp->dqbz_fhardlimit) {
904 + printf("File count limit reached on %s\n", mntp->mnt_mountp);
905 + } else if (dqzp->dqbz_fsoftlimit &&
906 + dqzp->dqbz_curfiles >= dqzp->dqbz_fsoftlimit) {
907 + if (dqzp->dqbz_ftimelimit == 0) {
908 + printf("Over file quota on %s, remove %lu file%s\n",
909 + mntp->mnt_mountp,
910 + dqzp->dqbz_curfiles - dqzp->dqbz_fsoftlimit + 1,
911 + ((dqzp->dqbz_curfiles -
912 + dqzp->dqbz_fsoftlimit + 1) > 1 ?
913 + "s" : ""));
914 + } else if (dqzp->dqbz_ftimelimit > tv.tv_sec) {
915 + char ftimeleft[80];
916 +
917 + fmttime(ftimeleft, dqzp->dqbz_ftimelimit - tv.tv_sec);
918 + printf("Over file quota on %s, remove %lu file%s "
919 + " within %s\n", mntp->mnt_mountp,
920 + dqzp->dqbz_curfiles - dqzp->dqbz_fsoftlimit + 1,
921 + ((dqzp->dqbz_curfiles -
922 + dqzp->dqbz_fsoftlimit + 1) > 1 ?
923 + "s" : ""), ftimeleft);
924 + } else {
925 + printf("Over file quota on %s, time limit has expired,"
926 + " remove %lu file%s\n", mntp->mnt_mountp,
927 + dqzp->dqbz_curfiles - dqzp->dqbz_fsoftlimit + 1,
928 + ((dqzp->dqbz_curfiles -
929 + dqzp->dqbz_fsoftlimit + 1) > 1 ?
930 + "s" : ""));
931 + }
932 + }
933 +}
934 +
935 +static void
936 +prquota_dqblk_impl(struct mnttab *mntp, struct dqblk *dqp)
937 +{
938 + struct timeval tv;
939 + char ftimeleft[80], btimeleft[80];
940 + char *cp;
941 +
942 + time(&(tv.tv_sec));
943 + tv.tv_usec = 0;
944 + if (dqp->dqb_bsoftlimit && dqp->dqb_curblocks >= dqp->dqb_bsoftlimit) {
945 + if (dqp->dqb_btimelimit == 0) {
946 + strlcpy(btimeleft, "NOT STARTED", sizeof (btimeleft));
947 + } else if (dqp->dqb_btimelimit > tv.tv_sec) {
948 + fmttime(btimeleft, dqp->dqb_btimelimit - tv.tv_sec);
949 + } else {
950 + strlcpy(btimeleft, "EXPIRED", sizeof (btimeleft));
951 + }
952 + } else {
953 + btimeleft[0] = '\0';
954 + }
955 + if (dqp->dqb_fsoftlimit && dqp->dqb_curfiles >= dqp->dqb_fsoftlimit) {
956 + if (dqp->dqb_ftimelimit == 0) {
957 + strlcpy(ftimeleft, "NOT STARTED", sizeof (ftimeleft));
958 + } else if (dqp->dqb_ftimelimit > tv.tv_sec) {
959 + fmttime(ftimeleft, dqp->dqb_ftimelimit - tv.tv_sec);
960 + } else {
961 + strlcpy(ftimeleft, "EXPIRED", sizeof (ftimeleft));
962 + }
963 + } else {
964 + ftimeleft[0] = '\0';
965 + }
966 + if (strlen(mntp->mnt_mountp) > 12) {
967 + printf("%s\n", mntp->mnt_mountp);
968 + cp = "";
969 + } else {
970 + cp = mntp->mnt_mountp;
971 + }
972 +
973 + if (dqp->dqb_curfiles == 0 &&
974 + dqp->dqb_fsoftlimit == 0 && dqp->dqb_fhardlimit == 0) {
975 + printf("%-12.12s %7d %6d %6d %11s %6s %6s %6s %11s\n",
976 + cp,
977 + kb(dqp->dqb_curblocks),
978 + kb(dqp->dqb_bsoftlimit),
979 + kb(dqp->dqb_bhardlimit),
980 + "-",
981 + "-",
982 + "-",
983 + "-",
984 + "-");
985 + } else {
986 + printf("%-12.12s %7d %6d %6d %11s %6d %6d %6d %11s\n",
987 + cp,
988 + kb(dqp->dqb_curblocks),
989 + kb(dqp->dqb_bsoftlimit),
990 + kb(dqp->dqb_bhardlimit),
991 + btimeleft,
992 + dqp->dqb_curfiles,
993 + dqp->dqb_fsoftlimit,
994 + dqp->dqb_fhardlimit,
995 + ftimeleft);
996 + }
997 +}
998 +
999 +static void
1000 +prquota_dqblk_zfs_impl(struct mnttab *mntp, struct dqblk_zfs *dqzp)
1001 +{
1002 + struct timeval tv;
1003 + char ftimeleft[80], btimeleft[80];
1004 + char *cp;
1005 +
1006 + time(&(tv.tv_sec));
1007 + tv.tv_usec = 0;
1008 + if (dqzp->dqbz_bsoftlimit &&
1009 + dqzp->dqbz_curblocks >= dqzp->dqbz_bsoftlimit) {
1010 + if (dqzp->dqbz_btimelimit == 0) {
1011 + strlcpy(btimeleft, "NOT STARTED", sizeof (btimeleft));
1012 + } else if (dqzp->dqbz_btimelimit > tv.tv_sec) {
1013 + fmttime(btimeleft, dqzp->dqbz_btimelimit - tv.tv_sec);
1014 + } else {
1015 + strlcpy(btimeleft, "EXPIRED", sizeof (btimeleft));
1016 + }
1017 + } else {
1018 + btimeleft[0] = '\0';
1019 + }
1020 + if (dqzp->dqbz_fsoftlimit &&
1021 + dqzp->dqbz_curfiles >= dqzp->dqbz_fsoftlimit) {
1022 + if (dqzp->dqbz_ftimelimit == 0) {
1023 + strlcpy(ftimeleft, "NOT STARTED", sizeof (ftimeleft));
1024 + } else if (dqzp->dqbz_ftimelimit > tv.tv_sec) {
1025 + fmttime(ftimeleft, dqzp->dqbz_ftimelimit - tv.tv_sec);
1026 + } else {
1027 + strlcpy(ftimeleft, "EXPIRED", sizeof (ftimeleft));
1028 + }
1029 + } else {
1030 + ftimeleft[0] = '\0';
1031 + }
1032 + if (strlen(mntp->mnt_mountp) > 12) {
1033 + printf("%s\n", mntp->mnt_mountp);
1034 + cp = "";
1035 + } else {
1036 + cp = mntp->mnt_mountp;
1037 + }
1038 +
1039 + if (dqzp->dqbz_curfiles == 0 &&
1040 + dqzp->dqbz_fsoftlimit == 0 && dqzp->dqbz_fhardlimit == 0) {
1041 + printf("%-12.12s %7llu %6llu %6llu %11s %6s %6s %6s %11s\n",
1042 + cp,
1043 + kb(dqzp->dqbz_curblocks),
1044 + kb(dqzp->dqbz_bsoftlimit),
1045 + kb(dqzp->dqbz_bhardlimit),
1046 + "-",
1047 + "-",
1048 + "-",
1049 + "-",
1050 + "-");
1051 + } else {
1052 + printf("%-12.12s %7llu %6llu %6llu %11s %6d %6d %6d %11s\n",
1053 + cp,
1054 + kb(dqzp->dqbz_curblocks),
1055 + kb(dqzp->dqbz_bsoftlimit),
1056 + kb(dqzp->dqbz_bhardlimit),
1057 + btimeleft,
1058 + dqzp->dqbz_curfiles,
1059 + dqzp->dqbz_fsoftlimit,
1060 + dqzp->dqbz_fhardlimit,
1061 + ftimeleft);
1062 + }
1063 +}
1064 +
1065 +static void
903 1066 zexit(int n)
904 1067 {
905 1068 if (g_zfs != NULL)
906 - _libzfs_fini(g_zfs);
1069 + libzfs_fini(g_zfs);
907 1070 exit(n);
908 1071 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX