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