Print this page
5704 libzfs can only handle 255 filedescriptors
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libzfs/common/libzfs_util.c
+++ new/usr/src/lib/libzfs/common/libzfs_util.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
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 /*
23 23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
25 25 * Copyright (c) 2012 by Delphix. All rights reserved.
26 26 */
27 27
28 28 /*
29 29 * Internal utility routines for the ZFS library.
30 30 */
31 31
32 32 #include <errno.h>
33 33 #include <fcntl.h>
34 34 #include <libintl.h>
35 35 #include <stdarg.h>
36 36 #include <stdio.h>
37 37 #include <stdlib.h>
38 38 #include <strings.h>
39 39 #include <unistd.h>
40 40 #include <ctype.h>
41 41 #include <math.h>
42 42 #include <sys/mnttab.h>
43 43 #include <sys/mntent.h>
44 44 #include <sys/types.h>
45 45
46 46 #include <libzfs.h>
47 47 #include <libzfs_core.h>
48 48
49 49 #include "libzfs_impl.h"
50 50 #include "zfs_prop.h"
51 51 #include "zfeature_common.h"
52 52
53 53 int
54 54 libzfs_errno(libzfs_handle_t *hdl)
55 55 {
56 56 return (hdl->libzfs_error);
57 57 }
58 58
59 59 const char *
60 60 libzfs_error_action(libzfs_handle_t *hdl)
61 61 {
62 62 return (hdl->libzfs_action);
63 63 }
64 64
65 65 const char *
66 66 libzfs_error_description(libzfs_handle_t *hdl)
67 67 {
68 68 if (hdl->libzfs_desc[0] != '\0')
69 69 return (hdl->libzfs_desc);
70 70
71 71 switch (hdl->libzfs_error) {
72 72 case EZFS_NOMEM:
73 73 return (dgettext(TEXT_DOMAIN, "out of memory"));
74 74 case EZFS_BADPROP:
75 75 return (dgettext(TEXT_DOMAIN, "invalid property value"));
76 76 case EZFS_PROPREADONLY:
77 77 return (dgettext(TEXT_DOMAIN, "read-only property"));
78 78 case EZFS_PROPTYPE:
79 79 return (dgettext(TEXT_DOMAIN, "property doesn't apply to "
80 80 "datasets of this type"));
81 81 case EZFS_PROPNONINHERIT:
82 82 return (dgettext(TEXT_DOMAIN, "property cannot be inherited"));
83 83 case EZFS_PROPSPACE:
84 84 return (dgettext(TEXT_DOMAIN, "invalid quota or reservation"));
85 85 case EZFS_BADTYPE:
86 86 return (dgettext(TEXT_DOMAIN, "operation not applicable to "
87 87 "datasets of this type"));
88 88 case EZFS_BUSY:
89 89 return (dgettext(TEXT_DOMAIN, "pool or dataset is busy"));
90 90 case EZFS_EXISTS:
91 91 return (dgettext(TEXT_DOMAIN, "pool or dataset exists"));
92 92 case EZFS_NOENT:
93 93 return (dgettext(TEXT_DOMAIN, "no such pool or dataset"));
94 94 case EZFS_BADSTREAM:
95 95 return (dgettext(TEXT_DOMAIN, "invalid backup stream"));
96 96 case EZFS_DSREADONLY:
97 97 return (dgettext(TEXT_DOMAIN, "dataset is read-only"));
98 98 case EZFS_VOLTOOBIG:
99 99 return (dgettext(TEXT_DOMAIN, "volume size exceeds limit for "
100 100 "this system"));
101 101 case EZFS_INVALIDNAME:
102 102 return (dgettext(TEXT_DOMAIN, "invalid name"));
103 103 case EZFS_BADRESTORE:
104 104 return (dgettext(TEXT_DOMAIN, "unable to restore to "
105 105 "destination"));
106 106 case EZFS_BADBACKUP:
107 107 return (dgettext(TEXT_DOMAIN, "backup failed"));
108 108 case EZFS_BADTARGET:
109 109 return (dgettext(TEXT_DOMAIN, "invalid target vdev"));
110 110 case EZFS_NODEVICE:
111 111 return (dgettext(TEXT_DOMAIN, "no such device in pool"));
112 112 case EZFS_BADDEV:
113 113 return (dgettext(TEXT_DOMAIN, "invalid device"));
114 114 case EZFS_NOREPLICAS:
115 115 return (dgettext(TEXT_DOMAIN, "no valid replicas"));
116 116 case EZFS_RESILVERING:
117 117 return (dgettext(TEXT_DOMAIN, "currently resilvering"));
118 118 case EZFS_BADVERSION:
119 119 return (dgettext(TEXT_DOMAIN, "unsupported version or "
120 120 "feature"));
121 121 case EZFS_POOLUNAVAIL:
122 122 return (dgettext(TEXT_DOMAIN, "pool is unavailable"));
123 123 case EZFS_DEVOVERFLOW:
124 124 return (dgettext(TEXT_DOMAIN, "too many devices in one vdev"));
125 125 case EZFS_BADPATH:
126 126 return (dgettext(TEXT_DOMAIN, "must be an absolute path"));
127 127 case EZFS_CROSSTARGET:
128 128 return (dgettext(TEXT_DOMAIN, "operation crosses datasets or "
129 129 "pools"));
130 130 case EZFS_ZONED:
131 131 return (dgettext(TEXT_DOMAIN, "dataset in use by local zone"));
132 132 case EZFS_MOUNTFAILED:
133 133 return (dgettext(TEXT_DOMAIN, "mount failed"));
134 134 case EZFS_UMOUNTFAILED:
135 135 return (dgettext(TEXT_DOMAIN, "umount failed"));
136 136 case EZFS_UNSHARENFSFAILED:
137 137 return (dgettext(TEXT_DOMAIN, "unshare(1M) failed"));
138 138 case EZFS_SHARENFSFAILED:
139 139 return (dgettext(TEXT_DOMAIN, "share(1M) failed"));
140 140 case EZFS_UNSHARESMBFAILED:
141 141 return (dgettext(TEXT_DOMAIN, "smb remove share failed"));
142 142 case EZFS_SHARESMBFAILED:
143 143 return (dgettext(TEXT_DOMAIN, "smb add share failed"));
144 144 case EZFS_PERM:
145 145 return (dgettext(TEXT_DOMAIN, "permission denied"));
146 146 case EZFS_NOSPC:
147 147 return (dgettext(TEXT_DOMAIN, "out of space"));
148 148 case EZFS_FAULT:
149 149 return (dgettext(TEXT_DOMAIN, "bad address"));
150 150 case EZFS_IO:
151 151 return (dgettext(TEXT_DOMAIN, "I/O error"));
152 152 case EZFS_INTR:
153 153 return (dgettext(TEXT_DOMAIN, "signal received"));
154 154 case EZFS_ISSPARE:
155 155 return (dgettext(TEXT_DOMAIN, "device is reserved as a hot "
156 156 "spare"));
157 157 case EZFS_INVALCONFIG:
158 158 return (dgettext(TEXT_DOMAIN, "invalid vdev configuration"));
159 159 case EZFS_RECURSIVE:
160 160 return (dgettext(TEXT_DOMAIN, "recursive dataset dependency"));
161 161 case EZFS_NOHISTORY:
162 162 return (dgettext(TEXT_DOMAIN, "no history available"));
163 163 case EZFS_POOLPROPS:
164 164 return (dgettext(TEXT_DOMAIN, "failed to retrieve "
165 165 "pool properties"));
166 166 case EZFS_POOL_NOTSUP:
167 167 return (dgettext(TEXT_DOMAIN, "operation not supported "
168 168 "on this type of pool"));
169 169 case EZFS_POOL_INVALARG:
170 170 return (dgettext(TEXT_DOMAIN, "invalid argument for "
171 171 "this pool operation"));
172 172 case EZFS_NAMETOOLONG:
173 173 return (dgettext(TEXT_DOMAIN, "dataset name is too long"));
174 174 case EZFS_OPENFAILED:
175 175 return (dgettext(TEXT_DOMAIN, "open failed"));
176 176 case EZFS_NOCAP:
177 177 return (dgettext(TEXT_DOMAIN,
178 178 "disk capacity information could not be retrieved"));
179 179 case EZFS_LABELFAILED:
180 180 return (dgettext(TEXT_DOMAIN, "write of label failed"));
181 181 case EZFS_BADWHO:
182 182 return (dgettext(TEXT_DOMAIN, "invalid user/group"));
183 183 case EZFS_BADPERM:
184 184 return (dgettext(TEXT_DOMAIN, "invalid permission"));
185 185 case EZFS_BADPERMSET:
186 186 return (dgettext(TEXT_DOMAIN, "invalid permission set name"));
187 187 case EZFS_NODELEGATION:
188 188 return (dgettext(TEXT_DOMAIN, "delegated administration is "
189 189 "disabled on pool"));
190 190 case EZFS_BADCACHE:
191 191 return (dgettext(TEXT_DOMAIN, "invalid or missing cache file"));
192 192 case EZFS_ISL2CACHE:
193 193 return (dgettext(TEXT_DOMAIN, "device is in use as a cache"));
194 194 case EZFS_VDEVNOTSUP:
195 195 return (dgettext(TEXT_DOMAIN, "vdev specification is not "
196 196 "supported"));
197 197 case EZFS_NOTSUP:
198 198 return (dgettext(TEXT_DOMAIN, "operation not supported "
199 199 "on this dataset"));
200 200 case EZFS_ACTIVE_SPARE:
201 201 return (dgettext(TEXT_DOMAIN, "pool has active shared spare "
202 202 "device"));
203 203 case EZFS_UNPLAYED_LOGS:
204 204 return (dgettext(TEXT_DOMAIN, "log device has unplayed intent "
205 205 "logs"));
206 206 case EZFS_REFTAG_RELE:
207 207 return (dgettext(TEXT_DOMAIN, "no such tag on this dataset"));
208 208 case EZFS_REFTAG_HOLD:
209 209 return (dgettext(TEXT_DOMAIN, "tag already exists on this "
210 210 "dataset"));
211 211 case EZFS_TAGTOOLONG:
212 212 return (dgettext(TEXT_DOMAIN, "tag too long"));
213 213 case EZFS_PIPEFAILED:
214 214 return (dgettext(TEXT_DOMAIN, "pipe create failed"));
215 215 case EZFS_THREADCREATEFAILED:
216 216 return (dgettext(TEXT_DOMAIN, "thread create failed"));
217 217 case EZFS_POSTSPLIT_ONLINE:
218 218 return (dgettext(TEXT_DOMAIN, "disk was split from this pool "
219 219 "into a new one"));
220 220 case EZFS_SCRUBBING:
221 221 return (dgettext(TEXT_DOMAIN, "currently scrubbing; "
222 222 "use 'zpool scrub -s' to cancel current scrub"));
223 223 case EZFS_NO_SCRUB:
224 224 return (dgettext(TEXT_DOMAIN, "there is no active scrub"));
225 225 case EZFS_DIFF:
226 226 return (dgettext(TEXT_DOMAIN, "unable to generate diffs"));
227 227 case EZFS_DIFFDATA:
228 228 return (dgettext(TEXT_DOMAIN, "invalid diff data"));
229 229 case EZFS_POOLREADONLY:
230 230 return (dgettext(TEXT_DOMAIN, "pool is read-only"));
231 231 case EZFS_UNKNOWN:
232 232 return (dgettext(TEXT_DOMAIN, "unknown error"));
233 233 default:
234 234 assert(hdl->libzfs_error == 0);
235 235 return (dgettext(TEXT_DOMAIN, "no error"));
236 236 }
237 237 }
238 238
239 239 /*PRINTFLIKE2*/
240 240 void
241 241 zfs_error_aux(libzfs_handle_t *hdl, const char *fmt, ...)
242 242 {
243 243 va_list ap;
244 244
245 245 va_start(ap, fmt);
246 246
247 247 (void) vsnprintf(hdl->libzfs_desc, sizeof (hdl->libzfs_desc),
248 248 fmt, ap);
249 249 hdl->libzfs_desc_active = 1;
250 250
251 251 va_end(ap);
252 252 }
253 253
254 254 static void
255 255 zfs_verror(libzfs_handle_t *hdl, int error, const char *fmt, va_list ap)
256 256 {
257 257 (void) vsnprintf(hdl->libzfs_action, sizeof (hdl->libzfs_action),
258 258 fmt, ap);
259 259 hdl->libzfs_error = error;
260 260
261 261 if (hdl->libzfs_desc_active)
262 262 hdl->libzfs_desc_active = 0;
263 263 else
264 264 hdl->libzfs_desc[0] = '\0';
265 265
266 266 if (hdl->libzfs_printerr) {
267 267 if (error == EZFS_UNKNOWN) {
268 268 (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "internal "
269 269 "error: %s\n"), libzfs_error_description(hdl));
270 270 abort();
271 271 }
272 272
273 273 (void) fprintf(stderr, "%s: %s\n", hdl->libzfs_action,
274 274 libzfs_error_description(hdl));
275 275 if (error == EZFS_NOMEM)
276 276 exit(1);
277 277 }
278 278 }
279 279
280 280 int
281 281 zfs_error(libzfs_handle_t *hdl, int error, const char *msg)
282 282 {
283 283 return (zfs_error_fmt(hdl, error, "%s", msg));
284 284 }
285 285
286 286 /*PRINTFLIKE3*/
287 287 int
288 288 zfs_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
289 289 {
290 290 va_list ap;
291 291
292 292 va_start(ap, fmt);
293 293
294 294 zfs_verror(hdl, error, fmt, ap);
295 295
296 296 va_end(ap);
297 297
298 298 return (-1);
299 299 }
300 300
301 301 static int
302 302 zfs_common_error(libzfs_handle_t *hdl, int error, const char *fmt,
303 303 va_list ap)
304 304 {
305 305 switch (error) {
306 306 case EPERM:
307 307 case EACCES:
308 308 zfs_verror(hdl, EZFS_PERM, fmt, ap);
309 309 return (-1);
310 310
311 311 case ECANCELED:
312 312 zfs_verror(hdl, EZFS_NODELEGATION, fmt, ap);
313 313 return (-1);
314 314
315 315 case EIO:
316 316 zfs_verror(hdl, EZFS_IO, fmt, ap);
317 317 return (-1);
318 318
319 319 case EFAULT:
320 320 zfs_verror(hdl, EZFS_FAULT, fmt, ap);
321 321 return (-1);
322 322
323 323 case EINTR:
324 324 zfs_verror(hdl, EZFS_INTR, fmt, ap);
325 325 return (-1);
326 326 }
327 327
328 328 return (0);
329 329 }
330 330
331 331 int
332 332 zfs_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
333 333 {
334 334 return (zfs_standard_error_fmt(hdl, error, "%s", msg));
335 335 }
336 336
337 337 /*PRINTFLIKE3*/
338 338 int
339 339 zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
340 340 {
341 341 va_list ap;
342 342
343 343 va_start(ap, fmt);
344 344
345 345 if (zfs_common_error(hdl, error, fmt, ap) != 0) {
346 346 va_end(ap);
347 347 return (-1);
348 348 }
349 349
350 350 switch (error) {
351 351 case ENXIO:
352 352 case ENODEV:
353 353 case EPIPE:
354 354 zfs_verror(hdl, EZFS_IO, fmt, ap);
355 355 break;
356 356
357 357 case ENOENT:
358 358 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
359 359 "dataset does not exist"));
360 360 zfs_verror(hdl, EZFS_NOENT, fmt, ap);
361 361 break;
362 362
363 363 case ENOSPC:
364 364 case EDQUOT:
365 365 zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
366 366 return (-1);
367 367
368 368 case EEXIST:
369 369 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
370 370 "dataset already exists"));
371 371 zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
372 372 break;
373 373
374 374 case EBUSY:
375 375 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
376 376 "dataset is busy"));
377 377 zfs_verror(hdl, EZFS_BUSY, fmt, ap);
378 378 break;
379 379 case EROFS:
380 380 zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap);
381 381 break;
382 382 case ENAMETOOLONG:
383 383 zfs_verror(hdl, EZFS_NAMETOOLONG, fmt, ap);
384 384 break;
385 385 case ENOTSUP:
386 386 zfs_verror(hdl, EZFS_BADVERSION, fmt, ap);
387 387 break;
388 388 case EAGAIN:
389 389 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
390 390 "pool I/O is currently suspended"));
391 391 zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap);
392 392 break;
393 393 default:
394 394 zfs_error_aux(hdl, strerror(error));
395 395 zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
396 396 break;
397 397 }
398 398
399 399 va_end(ap);
400 400 return (-1);
401 401 }
402 402
403 403 int
404 404 zpool_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
405 405 {
406 406 return (zpool_standard_error_fmt(hdl, error, "%s", msg));
407 407 }
408 408
409 409 /*PRINTFLIKE3*/
410 410 int
411 411 zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
412 412 {
413 413 va_list ap;
414 414
415 415 va_start(ap, fmt);
416 416
417 417 if (zfs_common_error(hdl, error, fmt, ap) != 0) {
418 418 va_end(ap);
419 419 return (-1);
420 420 }
421 421
422 422 switch (error) {
423 423 case ENODEV:
424 424 zfs_verror(hdl, EZFS_NODEVICE, fmt, ap);
425 425 break;
426 426
427 427 case ENOENT:
428 428 zfs_error_aux(hdl,
429 429 dgettext(TEXT_DOMAIN, "no such pool or dataset"));
430 430 zfs_verror(hdl, EZFS_NOENT, fmt, ap);
431 431 break;
432 432
433 433 case EEXIST:
434 434 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
435 435 "pool already exists"));
436 436 zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
437 437 break;
438 438
439 439 case EBUSY:
440 440 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool is busy"));
441 441 zfs_verror(hdl, EZFS_BUSY, fmt, ap);
442 442 break;
443 443
444 444 case ENXIO:
445 445 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
446 446 "one or more devices is currently unavailable"));
447 447 zfs_verror(hdl, EZFS_BADDEV, fmt, ap);
448 448 break;
449 449
450 450 case ENAMETOOLONG:
451 451 zfs_verror(hdl, EZFS_DEVOVERFLOW, fmt, ap);
452 452 break;
453 453
454 454 case ENOTSUP:
455 455 zfs_verror(hdl, EZFS_POOL_NOTSUP, fmt, ap);
456 456 break;
457 457
458 458 case EINVAL:
459 459 zfs_verror(hdl, EZFS_POOL_INVALARG, fmt, ap);
460 460 break;
461 461
462 462 case ENOSPC:
463 463 case EDQUOT:
464 464 zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
465 465 return (-1);
466 466
467 467 case EAGAIN:
468 468 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
469 469 "pool I/O is currently suspended"));
470 470 zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap);
471 471 break;
472 472
473 473 case EROFS:
474 474 zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap);
475 475 break;
476 476
477 477 default:
478 478 zfs_error_aux(hdl, strerror(error));
479 479 zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
480 480 }
481 481
482 482 va_end(ap);
483 483 return (-1);
484 484 }
485 485
486 486 /*
487 487 * Display an out of memory error message and abort the current program.
488 488 */
489 489 int
490 490 no_memory(libzfs_handle_t *hdl)
491 491 {
492 492 return (zfs_error(hdl, EZFS_NOMEM, "internal error"));
493 493 }
494 494
495 495 /*
496 496 * A safe form of malloc() which will die if the allocation fails.
497 497 */
498 498 void *
499 499 zfs_alloc(libzfs_handle_t *hdl, size_t size)
500 500 {
501 501 void *data;
502 502
503 503 if ((data = calloc(1, size)) == NULL)
504 504 (void) no_memory(hdl);
505 505
506 506 return (data);
507 507 }
508 508
509 509 /*
510 510 * A safe form of asprintf() which will die if the allocation fails.
511 511 */
512 512 /*PRINTFLIKE2*/
513 513 char *
514 514 zfs_asprintf(libzfs_handle_t *hdl, const char *fmt, ...)
515 515 {
516 516 va_list ap;
517 517 char *ret;
518 518 int err;
519 519
520 520 va_start(ap, fmt);
521 521
522 522 err = vasprintf(&ret, fmt, ap);
523 523
524 524 va_end(ap);
525 525
526 526 if (err < 0)
527 527 (void) no_memory(hdl);
528 528
529 529 return (ret);
530 530 }
531 531
532 532 /*
533 533 * A safe form of realloc(), which also zeroes newly allocated space.
534 534 */
535 535 void *
536 536 zfs_realloc(libzfs_handle_t *hdl, void *ptr, size_t oldsize, size_t newsize)
537 537 {
538 538 void *ret;
539 539
540 540 if ((ret = realloc(ptr, newsize)) == NULL) {
541 541 (void) no_memory(hdl);
542 542 return (NULL);
543 543 }
544 544
545 545 bzero((char *)ret + oldsize, (newsize - oldsize));
546 546 return (ret);
547 547 }
548 548
549 549 /*
550 550 * A safe form of strdup() which will die if the allocation fails.
551 551 */
552 552 char *
553 553 zfs_strdup(libzfs_handle_t *hdl, const char *str)
554 554 {
555 555 char *ret;
556 556
557 557 if ((ret = strdup(str)) == NULL)
558 558 (void) no_memory(hdl);
559 559
560 560 return (ret);
561 561 }
562 562
563 563 /*
564 564 * Convert a number to an appropriately human-readable output.
565 565 */
566 566 void
567 567 zfs_nicenum(uint64_t num, char *buf, size_t buflen)
568 568 {
569 569 uint64_t n = num;
570 570 int index = 0;
571 571 char u;
572 572
573 573 while (n >= 1024) {
574 574 n /= 1024;
575 575 index++;
576 576 }
577 577
578 578 u = " KMGTPE"[index];
579 579
580 580 if (index == 0) {
581 581 (void) snprintf(buf, buflen, "%llu", n);
582 582 } else if ((num & ((1ULL << 10 * index) - 1)) == 0) {
583 583 /*
584 584 * If this is an even multiple of the base, always display
585 585 * without any decimal precision.
586 586 */
587 587 (void) snprintf(buf, buflen, "%llu%c", n, u);
588 588 } else {
589 589 /*
590 590 * We want to choose a precision that reflects the best choice
591 591 * for fitting in 5 characters. This can get rather tricky when
592 592 * we have numbers that are very close to an order of magnitude.
593 593 * For example, when displaying 10239 (which is really 9.999K),
594 594 * we want only a single place of precision for 10.0K. We could
595 595 * develop some complex heuristics for this, but it's much
596 596 * easier just to try each combination in turn.
597 597 */
598 598 int i;
599 599 for (i = 2; i >= 0; i--) {
600 600 if (snprintf(buf, buflen, "%.*f%c", i,
601 601 (double)num / (1ULL << 10 * index), u) <= 5)
602 602 break;
603 603 }
604 604 }
605 605 }
606 606
607 607 void
608 608 libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr)
609 609 {
610 610 hdl->libzfs_printerr = printerr;
611 611 }
612 612
613 613 libzfs_handle_t *
614 614 libzfs_init(void)
615 615 {
616 616 libzfs_handle_t *hdl;
↓ open down ↓ |
616 lines elided |
↑ open up ↑ |
617 617
618 618 if ((hdl = calloc(1, sizeof (libzfs_handle_t))) == NULL) {
619 619 return (NULL);
620 620 }
621 621
622 622 if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR)) < 0) {
623 623 free(hdl);
624 624 return (NULL);
625 625 }
626 626
627 - if ((hdl->libzfs_mnttab = fopen(MNTTAB, "r")) == NULL) {
627 + if ((hdl->libzfs_mnttab = fopen(MNTTAB, "rF")) == NULL) {
628 628 (void) close(hdl->libzfs_fd);
629 629 free(hdl);
630 630 return (NULL);
631 631 }
632 632
633 - hdl->libzfs_sharetab = fopen("/etc/dfs/sharetab", "r");
633 + hdl->libzfs_sharetab = fopen("/etc/dfs/sharetab", "rF");
634 634
635 635 if (libzfs_core_init() != 0) {
636 636 (void) close(hdl->libzfs_fd);
637 637 (void) fclose(hdl->libzfs_mnttab);
638 638 (void) fclose(hdl->libzfs_sharetab);
639 639 free(hdl);
640 640 return (NULL);
641 641 }
642 642
643 643 zfs_prop_init();
644 644 zpool_prop_init();
645 645 zpool_feature_init();
646 646 libzfs_mnttab_init(hdl);
647 647
648 648 return (hdl);
649 649 }
650 650
651 651 void
652 652 libzfs_fini(libzfs_handle_t *hdl)
653 653 {
654 654 (void) close(hdl->libzfs_fd);
655 655 if (hdl->libzfs_mnttab)
656 656 (void) fclose(hdl->libzfs_mnttab);
657 657 if (hdl->libzfs_sharetab)
658 658 (void) fclose(hdl->libzfs_sharetab);
659 659 zfs_uninit_libshare(hdl);
660 660 zpool_free_handles(hdl);
661 661 libzfs_fru_clear(hdl, B_TRUE);
662 662 namespace_clear(hdl);
663 663 libzfs_mnttab_fini(hdl);
664 664 libzfs_core_fini();
665 665 free(hdl);
666 666 }
667 667
668 668 libzfs_handle_t *
669 669 zpool_get_handle(zpool_handle_t *zhp)
670 670 {
671 671 return (zhp->zpool_hdl);
672 672 }
673 673
674 674 libzfs_handle_t *
675 675 zfs_get_handle(zfs_handle_t *zhp)
676 676 {
677 677 return (zhp->zfs_hdl);
678 678 }
679 679
680 680 zpool_handle_t *
681 681 zfs_get_pool_handle(const zfs_handle_t *zhp)
682 682 {
683 683 return (zhp->zpool_hdl);
684 684 }
685 685
686 686 /*
687 687 * Given a name, determine whether or not it's a valid path
688 688 * (starts with '/' or "./"). If so, walk the mnttab trying
689 689 * to match the device number. If not, treat the path as an
690 690 * fs/vol/snap name.
691 691 */
692 692 zfs_handle_t *
693 693 zfs_path_to_zhandle(libzfs_handle_t *hdl, char *path, zfs_type_t argtype)
694 694 {
695 695 struct stat64 statbuf;
696 696 struct extmnttab entry;
697 697 int ret;
698 698
699 699 if (path[0] != '/' && strncmp(path, "./", strlen("./")) != 0) {
700 700 /*
701 701 * It's not a valid path, assume it's a name of type 'argtype'.
702 702 */
703 703 return (zfs_open(hdl, path, argtype));
704 704 }
705 705
706 706 if (stat64(path, &statbuf) != 0) {
707 707 (void) fprintf(stderr, "%s: %s\n", path, strerror(errno));
708 708 return (NULL);
709 709 }
710 710
711 711 rewind(hdl->libzfs_mnttab);
712 712 while ((ret = getextmntent(hdl->libzfs_mnttab, &entry, 0)) == 0) {
713 713 if (makedevice(entry.mnt_major, entry.mnt_minor) ==
714 714 statbuf.st_dev) {
715 715 break;
716 716 }
717 717 }
718 718 if (ret != 0) {
719 719 return (NULL);
720 720 }
721 721
722 722 if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) {
723 723 (void) fprintf(stderr, gettext("'%s': not a ZFS filesystem\n"),
724 724 path);
725 725 return (NULL);
726 726 }
727 727
728 728 return (zfs_open(hdl, entry.mnt_special, ZFS_TYPE_FILESYSTEM));
729 729 }
730 730
731 731 /*
732 732 * Initialize the zc_nvlist_dst member to prepare for receiving an nvlist from
733 733 * an ioctl().
734 734 */
735 735 int
736 736 zcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len)
737 737 {
738 738 if (len == 0)
739 739 len = 16 * 1024;
740 740 zc->zc_nvlist_dst_size = len;
741 741 if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
742 742 zfs_alloc(hdl, zc->zc_nvlist_dst_size)) == NULL)
743 743 return (-1);
744 744
745 745 return (0);
746 746 }
747 747
748 748 /*
749 749 * Called when an ioctl() which returns an nvlist fails with ENOMEM. This will
750 750 * expand the nvlist to the size specified in 'zc_nvlist_dst_size', which was
751 751 * filled in by the kernel to indicate the actual required size.
752 752 */
753 753 int
754 754 zcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc)
755 755 {
756 756 free((void *)(uintptr_t)zc->zc_nvlist_dst);
757 757 if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
758 758 zfs_alloc(hdl, zc->zc_nvlist_dst_size))
759 759 == NULL)
760 760 return (-1);
761 761
762 762 return (0);
763 763 }
764 764
765 765 /*
766 766 * Called to free the src and dst nvlists stored in the command structure.
767 767 */
768 768 void
769 769 zcmd_free_nvlists(zfs_cmd_t *zc)
770 770 {
771 771 free((void *)(uintptr_t)zc->zc_nvlist_conf);
772 772 free((void *)(uintptr_t)zc->zc_nvlist_src);
773 773 free((void *)(uintptr_t)zc->zc_nvlist_dst);
774 774 }
775 775
776 776 static int
777 777 zcmd_write_nvlist_com(libzfs_handle_t *hdl, uint64_t *outnv, uint64_t *outlen,
778 778 nvlist_t *nvl)
779 779 {
780 780 char *packed;
781 781 size_t len;
782 782
783 783 verify(nvlist_size(nvl, &len, NV_ENCODE_NATIVE) == 0);
784 784
785 785 if ((packed = zfs_alloc(hdl, len)) == NULL)
786 786 return (-1);
787 787
788 788 verify(nvlist_pack(nvl, &packed, &len, NV_ENCODE_NATIVE, 0) == 0);
789 789
790 790 *outnv = (uint64_t)(uintptr_t)packed;
791 791 *outlen = len;
792 792
793 793 return (0);
794 794 }
795 795
796 796 int
797 797 zcmd_write_conf_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl)
798 798 {
799 799 return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_conf,
800 800 &zc->zc_nvlist_conf_size, nvl));
801 801 }
802 802
803 803 int
804 804 zcmd_write_src_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl)
805 805 {
806 806 return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_src,
807 807 &zc->zc_nvlist_src_size, nvl));
808 808 }
809 809
810 810 /*
811 811 * Unpacks an nvlist from the ZFS ioctl command structure.
812 812 */
813 813 int
814 814 zcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp)
815 815 {
816 816 if (nvlist_unpack((void *)(uintptr_t)zc->zc_nvlist_dst,
817 817 zc->zc_nvlist_dst_size, nvlp, 0) != 0)
818 818 return (no_memory(hdl));
819 819
820 820 return (0);
821 821 }
822 822
823 823 int
824 824 zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc)
825 825 {
826 826 return (ioctl(hdl->libzfs_fd, request, zc));
827 827 }
828 828
829 829 /*
830 830 * ================================================================
831 831 * API shared by zfs and zpool property management
832 832 * ================================================================
833 833 */
834 834
835 835 static void
836 836 zprop_print_headers(zprop_get_cbdata_t *cbp, zfs_type_t type)
837 837 {
838 838 zprop_list_t *pl = cbp->cb_proplist;
839 839 int i;
840 840 char *title;
841 841 size_t len;
842 842
843 843 cbp->cb_first = B_FALSE;
844 844 if (cbp->cb_scripted)
845 845 return;
846 846
847 847 /*
848 848 * Start with the length of the column headers.
849 849 */
850 850 cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN, "NAME"));
851 851 cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN,
852 852 "PROPERTY"));
853 853 cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN,
854 854 "VALUE"));
855 855 cbp->cb_colwidths[GET_COL_RECVD] = strlen(dgettext(TEXT_DOMAIN,
856 856 "RECEIVED"));
857 857 cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN,
858 858 "SOURCE"));
859 859
860 860 /* first property is always NAME */
861 861 assert(cbp->cb_proplist->pl_prop ==
862 862 ((type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME : ZFS_PROP_NAME));
863 863
864 864 /*
865 865 * Go through and calculate the widths for each column. For the
866 866 * 'source' column, we kludge it up by taking the worst-case scenario of
867 867 * inheriting from the longest name. This is acceptable because in the
868 868 * majority of cases 'SOURCE' is the last column displayed, and we don't
869 869 * use the width anyway. Note that the 'VALUE' column can be oversized,
870 870 * if the name of the property is much longer than any values we find.
871 871 */
872 872 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
873 873 /*
874 874 * 'PROPERTY' column
875 875 */
876 876 if (pl->pl_prop != ZPROP_INVAL) {
877 877 const char *propname = (type == ZFS_TYPE_POOL) ?
878 878 zpool_prop_to_name(pl->pl_prop) :
879 879 zfs_prop_to_name(pl->pl_prop);
880 880
881 881 len = strlen(propname);
882 882 if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
883 883 cbp->cb_colwidths[GET_COL_PROPERTY] = len;
884 884 } else {
885 885 len = strlen(pl->pl_user_prop);
886 886 if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
887 887 cbp->cb_colwidths[GET_COL_PROPERTY] = len;
888 888 }
889 889
890 890 /*
891 891 * 'VALUE' column. The first property is always the 'name'
892 892 * property that was tacked on either by /sbin/zfs's
893 893 * zfs_do_get() or when calling zprop_expand_list(), so we
894 894 * ignore its width. If the user specified the name property
895 895 * to display, then it will be later in the list in any case.
896 896 */
897 897 if (pl != cbp->cb_proplist &&
898 898 pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE])
899 899 cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width;
900 900
901 901 /* 'RECEIVED' column. */
902 902 if (pl != cbp->cb_proplist &&
903 903 pl->pl_recvd_width > cbp->cb_colwidths[GET_COL_RECVD])
904 904 cbp->cb_colwidths[GET_COL_RECVD] = pl->pl_recvd_width;
905 905
906 906 /*
907 907 * 'NAME' and 'SOURCE' columns
908 908 */
909 909 if (pl->pl_prop == (type == ZFS_TYPE_POOL ? ZPOOL_PROP_NAME :
910 910 ZFS_PROP_NAME) &&
911 911 pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) {
912 912 cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width;
913 913 cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width +
914 914 strlen(dgettext(TEXT_DOMAIN, "inherited from"));
915 915 }
916 916 }
917 917
918 918 /*
919 919 * Now go through and print the headers.
920 920 */
921 921 for (i = 0; i < ZFS_GET_NCOLS; i++) {
922 922 switch (cbp->cb_columns[i]) {
923 923 case GET_COL_NAME:
924 924 title = dgettext(TEXT_DOMAIN, "NAME");
925 925 break;
926 926 case GET_COL_PROPERTY:
927 927 title = dgettext(TEXT_DOMAIN, "PROPERTY");
928 928 break;
929 929 case GET_COL_VALUE:
930 930 title = dgettext(TEXT_DOMAIN, "VALUE");
931 931 break;
932 932 case GET_COL_RECVD:
933 933 title = dgettext(TEXT_DOMAIN, "RECEIVED");
934 934 break;
935 935 case GET_COL_SOURCE:
936 936 title = dgettext(TEXT_DOMAIN, "SOURCE");
937 937 break;
938 938 default:
939 939 title = NULL;
940 940 }
941 941
942 942 if (title != NULL) {
943 943 if (i == (ZFS_GET_NCOLS - 1) ||
944 944 cbp->cb_columns[i + 1] == GET_COL_NONE)
945 945 (void) printf("%s", title);
946 946 else
947 947 (void) printf("%-*s ",
948 948 cbp->cb_colwidths[cbp->cb_columns[i]],
949 949 title);
950 950 }
951 951 }
952 952 (void) printf("\n");
953 953 }
954 954
955 955 /*
956 956 * Display a single line of output, according to the settings in the callback
957 957 * structure.
958 958 */
959 959 void
960 960 zprop_print_one_property(const char *name, zprop_get_cbdata_t *cbp,
961 961 const char *propname, const char *value, zprop_source_t sourcetype,
962 962 const char *source, const char *recvd_value)
963 963 {
964 964 int i;
965 965 const char *str;
966 966 char buf[128];
967 967
968 968 /*
969 969 * Ignore those source types that the user has chosen to ignore.
970 970 */
971 971 if ((sourcetype & cbp->cb_sources) == 0)
972 972 return;
973 973
974 974 if (cbp->cb_first)
975 975 zprop_print_headers(cbp, cbp->cb_type);
976 976
977 977 for (i = 0; i < ZFS_GET_NCOLS; i++) {
978 978 switch (cbp->cb_columns[i]) {
979 979 case GET_COL_NAME:
980 980 str = name;
981 981 break;
982 982
983 983 case GET_COL_PROPERTY:
984 984 str = propname;
985 985 break;
986 986
987 987 case GET_COL_VALUE:
988 988 str = value;
989 989 break;
990 990
991 991 case GET_COL_SOURCE:
992 992 switch (sourcetype) {
993 993 case ZPROP_SRC_NONE:
994 994 str = "-";
995 995 break;
996 996
997 997 case ZPROP_SRC_DEFAULT:
998 998 str = "default";
999 999 break;
1000 1000
1001 1001 case ZPROP_SRC_LOCAL:
1002 1002 str = "local";
1003 1003 break;
1004 1004
1005 1005 case ZPROP_SRC_TEMPORARY:
1006 1006 str = "temporary";
1007 1007 break;
1008 1008
1009 1009 case ZPROP_SRC_INHERITED:
1010 1010 (void) snprintf(buf, sizeof (buf),
1011 1011 "inherited from %s", source);
1012 1012 str = buf;
1013 1013 break;
1014 1014 case ZPROP_SRC_RECEIVED:
1015 1015 str = "received";
1016 1016 break;
1017 1017 }
1018 1018 break;
1019 1019
1020 1020 case GET_COL_RECVD:
1021 1021 str = (recvd_value == NULL ? "-" : recvd_value);
1022 1022 break;
1023 1023
1024 1024 default:
1025 1025 continue;
1026 1026 }
1027 1027
1028 1028 if (cbp->cb_columns[i + 1] == GET_COL_NONE)
1029 1029 (void) printf("%s", str);
1030 1030 else if (cbp->cb_scripted)
1031 1031 (void) printf("%s\t", str);
1032 1032 else
1033 1033 (void) printf("%-*s ",
1034 1034 cbp->cb_colwidths[cbp->cb_columns[i]],
1035 1035 str);
1036 1036 }
1037 1037
1038 1038 (void) printf("\n");
1039 1039 }
1040 1040
1041 1041 /*
1042 1042 * Given a numeric suffix, convert the value into a number of bits that the
1043 1043 * resulting value must be shifted.
1044 1044 */
1045 1045 static int
1046 1046 str2shift(libzfs_handle_t *hdl, const char *buf)
1047 1047 {
1048 1048 const char *ends = "BKMGTPEZ";
1049 1049 int i;
1050 1050
1051 1051 if (buf[0] == '\0')
1052 1052 return (0);
1053 1053 for (i = 0; i < strlen(ends); i++) {
1054 1054 if (toupper(buf[0]) == ends[i])
1055 1055 break;
1056 1056 }
1057 1057 if (i == strlen(ends)) {
1058 1058 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1059 1059 "invalid numeric suffix '%s'"), buf);
1060 1060 return (-1);
1061 1061 }
1062 1062
1063 1063 /*
1064 1064 * We want to allow trailing 'b' characters for 'GB' or 'Mb'. But don't
1065 1065 * allow 'BB' - that's just weird.
1066 1066 */
1067 1067 if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' &&
1068 1068 toupper(buf[0]) != 'B'))
1069 1069 return (10*i);
1070 1070
1071 1071 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1072 1072 "invalid numeric suffix '%s'"), buf);
1073 1073 return (-1);
1074 1074 }
1075 1075
1076 1076 /*
1077 1077 * Convert a string of the form '100G' into a real number. Used when setting
1078 1078 * properties or creating a volume. 'buf' is used to place an extended error
1079 1079 * message for the caller to use.
1080 1080 */
1081 1081 int
1082 1082 zfs_nicestrtonum(libzfs_handle_t *hdl, const char *value, uint64_t *num)
1083 1083 {
1084 1084 char *end;
1085 1085 int shift;
1086 1086
1087 1087 *num = 0;
1088 1088
1089 1089 /* Check to see if this looks like a number. */
1090 1090 if ((value[0] < '0' || value[0] > '9') && value[0] != '.') {
1091 1091 if (hdl)
1092 1092 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1093 1093 "bad numeric value '%s'"), value);
1094 1094 return (-1);
1095 1095 }
1096 1096
1097 1097 /* Rely on strtoull() to process the numeric portion. */
1098 1098 errno = 0;
1099 1099 *num = strtoull(value, &end, 10);
1100 1100
1101 1101 /*
1102 1102 * Check for ERANGE, which indicates that the value is too large to fit
1103 1103 * in a 64-bit value.
1104 1104 */
1105 1105 if (errno == ERANGE) {
1106 1106 if (hdl)
1107 1107 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1108 1108 "numeric value is too large"));
1109 1109 return (-1);
1110 1110 }
1111 1111
1112 1112 /*
1113 1113 * If we have a decimal value, then do the computation with floating
1114 1114 * point arithmetic. Otherwise, use standard arithmetic.
1115 1115 */
1116 1116 if (*end == '.') {
1117 1117 double fval = strtod(value, &end);
1118 1118
1119 1119 if ((shift = str2shift(hdl, end)) == -1)
1120 1120 return (-1);
1121 1121
1122 1122 fval *= pow(2, shift);
1123 1123
1124 1124 if (fval > UINT64_MAX) {
1125 1125 if (hdl)
1126 1126 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1127 1127 "numeric value is too large"));
1128 1128 return (-1);
1129 1129 }
1130 1130
1131 1131 *num = (uint64_t)fval;
1132 1132 } else {
1133 1133 if ((shift = str2shift(hdl, end)) == -1)
1134 1134 return (-1);
1135 1135
1136 1136 /* Check for overflow */
1137 1137 if (shift >= 64 || (*num << shift) >> shift != *num) {
1138 1138 if (hdl)
1139 1139 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1140 1140 "numeric value is too large"));
1141 1141 return (-1);
1142 1142 }
1143 1143
1144 1144 *num <<= shift;
1145 1145 }
1146 1146
1147 1147 return (0);
1148 1148 }
1149 1149
1150 1150 /*
1151 1151 * Given a propname=value nvpair to set, parse any numeric properties
1152 1152 * (index, boolean, etc) if they are specified as strings and add the
1153 1153 * resulting nvpair to the returned nvlist.
1154 1154 *
1155 1155 * At the DSL layer, all properties are either 64-bit numbers or strings.
1156 1156 * We want the user to be able to ignore this fact and specify properties
1157 1157 * as native values (numbers, for example) or as strings (to simplify
1158 1158 * command line utilities). This also handles converting index types
1159 1159 * (compression, checksum, etc) from strings to their on-disk index.
1160 1160 */
1161 1161 int
1162 1162 zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop,
1163 1163 zfs_type_t type, nvlist_t *ret, char **svalp, uint64_t *ivalp,
1164 1164 const char *errbuf)
1165 1165 {
1166 1166 data_type_t datatype = nvpair_type(elem);
1167 1167 zprop_type_t proptype;
1168 1168 const char *propname;
1169 1169 char *value;
1170 1170 boolean_t isnone = B_FALSE;
1171 1171
1172 1172 if (type == ZFS_TYPE_POOL) {
1173 1173 proptype = zpool_prop_get_type(prop);
1174 1174 propname = zpool_prop_to_name(prop);
1175 1175 } else {
1176 1176 proptype = zfs_prop_get_type(prop);
1177 1177 propname = zfs_prop_to_name(prop);
1178 1178 }
1179 1179
1180 1180 /*
1181 1181 * Convert any properties to the internal DSL value types.
1182 1182 */
1183 1183 *svalp = NULL;
1184 1184 *ivalp = 0;
1185 1185
1186 1186 switch (proptype) {
1187 1187 case PROP_TYPE_STRING:
1188 1188 if (datatype != DATA_TYPE_STRING) {
1189 1189 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1190 1190 "'%s' must be a string"), nvpair_name(elem));
1191 1191 goto error;
1192 1192 }
1193 1193 (void) nvpair_value_string(elem, svalp);
1194 1194 if (strlen(*svalp) >= ZFS_MAXPROPLEN) {
1195 1195 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1196 1196 "'%s' is too long"), nvpair_name(elem));
1197 1197 goto error;
1198 1198 }
1199 1199 break;
1200 1200
1201 1201 case PROP_TYPE_NUMBER:
1202 1202 if (datatype == DATA_TYPE_STRING) {
1203 1203 (void) nvpair_value_string(elem, &value);
1204 1204 if (strcmp(value, "none") == 0) {
1205 1205 isnone = B_TRUE;
1206 1206 } else if (zfs_nicestrtonum(hdl, value, ivalp)
1207 1207 != 0) {
1208 1208 goto error;
1209 1209 }
1210 1210 } else if (datatype == DATA_TYPE_UINT64) {
1211 1211 (void) nvpair_value_uint64(elem, ivalp);
1212 1212 } else {
1213 1213 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1214 1214 "'%s' must be a number"), nvpair_name(elem));
1215 1215 goto error;
1216 1216 }
1217 1217
1218 1218 /*
1219 1219 * Quota special: force 'none' and don't allow 0.
1220 1220 */
1221 1221 if ((type & ZFS_TYPE_DATASET) && *ivalp == 0 && !isnone &&
1222 1222 (prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_REFQUOTA)) {
1223 1223 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1224 1224 "use 'none' to disable quota/refquota"));
1225 1225 goto error;
1226 1226 }
1227 1227
1228 1228 /*
1229 1229 * Special handling for "*_limit=none". In this case it's not
1230 1230 * 0 but UINT64_MAX.
1231 1231 */
1232 1232 if ((type & ZFS_TYPE_DATASET) && isnone &&
1233 1233 (prop == ZFS_PROP_FILESYSTEM_LIMIT ||
1234 1234 prop == ZFS_PROP_SNAPSHOT_LIMIT)) {
1235 1235 *ivalp = UINT64_MAX;
1236 1236 }
1237 1237 break;
1238 1238
1239 1239 case PROP_TYPE_INDEX:
1240 1240 if (datatype != DATA_TYPE_STRING) {
1241 1241 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1242 1242 "'%s' must be a string"), nvpair_name(elem));
1243 1243 goto error;
1244 1244 }
1245 1245
1246 1246 (void) nvpair_value_string(elem, &value);
1247 1247
1248 1248 if (zprop_string_to_index(prop, value, ivalp, type) != 0) {
1249 1249 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1250 1250 "'%s' must be one of '%s'"), propname,
1251 1251 zprop_values(prop, type));
1252 1252 goto error;
1253 1253 }
1254 1254 break;
1255 1255
1256 1256 default:
1257 1257 abort();
1258 1258 }
1259 1259
1260 1260 /*
1261 1261 * Add the result to our return set of properties.
1262 1262 */
1263 1263 if (*svalp != NULL) {
1264 1264 if (nvlist_add_string(ret, propname, *svalp) != 0) {
1265 1265 (void) no_memory(hdl);
1266 1266 return (-1);
1267 1267 }
1268 1268 } else {
1269 1269 if (nvlist_add_uint64(ret, propname, *ivalp) != 0) {
1270 1270 (void) no_memory(hdl);
1271 1271 return (-1);
1272 1272 }
1273 1273 }
1274 1274
1275 1275 return (0);
1276 1276 error:
1277 1277 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1278 1278 return (-1);
1279 1279 }
1280 1280
1281 1281 static int
1282 1282 addlist(libzfs_handle_t *hdl, char *propname, zprop_list_t **listp,
1283 1283 zfs_type_t type)
1284 1284 {
1285 1285 int prop;
1286 1286 zprop_list_t *entry;
1287 1287
1288 1288 prop = zprop_name_to_prop(propname, type);
1289 1289
1290 1290 if (prop != ZPROP_INVAL && !zprop_valid_for_type(prop, type))
1291 1291 prop = ZPROP_INVAL;
1292 1292
1293 1293 /*
1294 1294 * When no property table entry can be found, return failure if
1295 1295 * this is a pool property or if this isn't a user-defined
1296 1296 * dataset property,
1297 1297 */
1298 1298 if (prop == ZPROP_INVAL && ((type == ZFS_TYPE_POOL &&
1299 1299 !zpool_prop_feature(propname) &&
1300 1300 !zpool_prop_unsupported(propname)) ||
1301 1301 (type == ZFS_TYPE_DATASET && !zfs_prop_user(propname) &&
1302 1302 !zfs_prop_userquota(propname) && !zfs_prop_written(propname)))) {
1303 1303 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1304 1304 "invalid property '%s'"), propname);
1305 1305 return (zfs_error(hdl, EZFS_BADPROP,
1306 1306 dgettext(TEXT_DOMAIN, "bad property list")));
1307 1307 }
1308 1308
1309 1309 if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL)
1310 1310 return (-1);
1311 1311
1312 1312 entry->pl_prop = prop;
1313 1313 if (prop == ZPROP_INVAL) {
1314 1314 if ((entry->pl_user_prop = zfs_strdup(hdl, propname)) ==
1315 1315 NULL) {
1316 1316 free(entry);
1317 1317 return (-1);
1318 1318 }
1319 1319 entry->pl_width = strlen(propname);
1320 1320 } else {
1321 1321 entry->pl_width = zprop_width(prop, &entry->pl_fixed,
1322 1322 type);
1323 1323 }
1324 1324
1325 1325 *listp = entry;
1326 1326
1327 1327 return (0);
1328 1328 }
1329 1329
1330 1330 /*
1331 1331 * Given a comma-separated list of properties, construct a property list
1332 1332 * containing both user-defined and native properties. This function will
1333 1333 * return a NULL list if 'all' is specified, which can later be expanded
1334 1334 * by zprop_expand_list().
1335 1335 */
1336 1336 int
1337 1337 zprop_get_list(libzfs_handle_t *hdl, char *props, zprop_list_t **listp,
1338 1338 zfs_type_t type)
1339 1339 {
1340 1340 *listp = NULL;
1341 1341
1342 1342 /*
1343 1343 * If 'all' is specified, return a NULL list.
1344 1344 */
1345 1345 if (strcmp(props, "all") == 0)
1346 1346 return (0);
1347 1347
1348 1348 /*
1349 1349 * If no props were specified, return an error.
1350 1350 */
1351 1351 if (props[0] == '\0') {
1352 1352 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1353 1353 "no properties specified"));
1354 1354 return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN,
1355 1355 "bad property list")));
1356 1356 }
1357 1357
1358 1358 /*
1359 1359 * It would be nice to use getsubopt() here, but the inclusion of column
1360 1360 * aliases makes this more effort than it's worth.
1361 1361 */
1362 1362 while (*props != '\0') {
1363 1363 size_t len;
1364 1364 char *p;
1365 1365 char c;
1366 1366
1367 1367 if ((p = strchr(props, ',')) == NULL) {
1368 1368 len = strlen(props);
1369 1369 p = props + len;
1370 1370 } else {
1371 1371 len = p - props;
1372 1372 }
1373 1373
1374 1374 /*
1375 1375 * Check for empty options.
1376 1376 */
1377 1377 if (len == 0) {
1378 1378 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1379 1379 "empty property name"));
1380 1380 return (zfs_error(hdl, EZFS_BADPROP,
1381 1381 dgettext(TEXT_DOMAIN, "bad property list")));
1382 1382 }
1383 1383
1384 1384 /*
1385 1385 * Check all regular property names.
1386 1386 */
1387 1387 c = props[len];
1388 1388 props[len] = '\0';
1389 1389
1390 1390 if (strcmp(props, "space") == 0) {
1391 1391 static char *spaceprops[] = {
1392 1392 "name", "avail", "used", "usedbysnapshots",
1393 1393 "usedbydataset", "usedbyrefreservation",
1394 1394 "usedbychildren", NULL
1395 1395 };
1396 1396 int i;
1397 1397
1398 1398 for (i = 0; spaceprops[i]; i++) {
1399 1399 if (addlist(hdl, spaceprops[i], listp, type))
1400 1400 return (-1);
1401 1401 listp = &(*listp)->pl_next;
1402 1402 }
1403 1403 } else {
1404 1404 if (addlist(hdl, props, listp, type))
1405 1405 return (-1);
1406 1406 listp = &(*listp)->pl_next;
1407 1407 }
1408 1408
1409 1409 props = p;
1410 1410 if (c == ',')
1411 1411 props++;
1412 1412 }
1413 1413
1414 1414 return (0);
1415 1415 }
1416 1416
1417 1417 void
1418 1418 zprop_free_list(zprop_list_t *pl)
1419 1419 {
1420 1420 zprop_list_t *next;
1421 1421
1422 1422 while (pl != NULL) {
1423 1423 next = pl->pl_next;
1424 1424 free(pl->pl_user_prop);
1425 1425 free(pl);
1426 1426 pl = next;
1427 1427 }
1428 1428 }
1429 1429
1430 1430 typedef struct expand_data {
1431 1431 zprop_list_t **last;
1432 1432 libzfs_handle_t *hdl;
1433 1433 zfs_type_t type;
1434 1434 } expand_data_t;
1435 1435
1436 1436 int
1437 1437 zprop_expand_list_cb(int prop, void *cb)
1438 1438 {
1439 1439 zprop_list_t *entry;
1440 1440 expand_data_t *edp = cb;
1441 1441
1442 1442 if ((entry = zfs_alloc(edp->hdl, sizeof (zprop_list_t))) == NULL)
1443 1443 return (ZPROP_INVAL);
1444 1444
1445 1445 entry->pl_prop = prop;
1446 1446 entry->pl_width = zprop_width(prop, &entry->pl_fixed, edp->type);
1447 1447 entry->pl_all = B_TRUE;
1448 1448
1449 1449 *(edp->last) = entry;
1450 1450 edp->last = &entry->pl_next;
1451 1451
1452 1452 return (ZPROP_CONT);
1453 1453 }
1454 1454
1455 1455 int
1456 1456 zprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp, zfs_type_t type)
1457 1457 {
1458 1458 zprop_list_t *entry;
1459 1459 zprop_list_t **last;
1460 1460 expand_data_t exp;
1461 1461
1462 1462 if (*plp == NULL) {
1463 1463 /*
1464 1464 * If this is the very first time we've been called for an 'all'
1465 1465 * specification, expand the list to include all native
1466 1466 * properties.
1467 1467 */
1468 1468 last = plp;
1469 1469
1470 1470 exp.last = last;
1471 1471 exp.hdl = hdl;
1472 1472 exp.type = type;
1473 1473
1474 1474 if (zprop_iter_common(zprop_expand_list_cb, &exp, B_FALSE,
1475 1475 B_FALSE, type) == ZPROP_INVAL)
1476 1476 return (-1);
1477 1477
1478 1478 /*
1479 1479 * Add 'name' to the beginning of the list, which is handled
1480 1480 * specially.
1481 1481 */
1482 1482 if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL)
1483 1483 return (-1);
1484 1484
1485 1485 entry->pl_prop = (type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME :
1486 1486 ZFS_PROP_NAME;
1487 1487 entry->pl_width = zprop_width(entry->pl_prop,
1488 1488 &entry->pl_fixed, type);
1489 1489 entry->pl_all = B_TRUE;
1490 1490 entry->pl_next = *plp;
1491 1491 *plp = entry;
1492 1492 }
1493 1493 return (0);
1494 1494 }
1495 1495
1496 1496 int
1497 1497 zprop_iter(zprop_func func, void *cb, boolean_t show_all, boolean_t ordered,
1498 1498 zfs_type_t type)
1499 1499 {
1500 1500 return (zprop_iter_common(func, cb, show_all, ordered, type));
1501 1501 }
↓ open down ↓ |
858 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX