159 { |
160 { |
160 switch (idx) { |
161 switch (idx) { |
161 case HELP_CLONE: |
162 case HELP_CLONE: |
162 return (gettext("\tclone <snapshot> <filesystem|volume>\n")); |
163 return (gettext("\tclone <snapshot> <filesystem|volume>\n")); |
163 case HELP_CREATE: |
164 case HELP_CREATE: |
164 return (gettext("\tcreate <filesystem>\n" |
165 return (gettext("\tcreate [[-o property=value] ... ] " |
165 "\tcreate [-s] [-b blocksize] -V <size> <volume>\n")); |
166 "<filesystem>\n" |
|
167 "\tcreate [-s] [-b blocksize] [[-o property=value] ...]\n" |
|
168 "\t -V <size> <volume>\n")); |
166 case HELP_DESTROY: |
169 case HELP_DESTROY: |
167 return (gettext("\tdestroy [-rRf] " |
170 return (gettext("\tdestroy [-rRf] " |
168 "<filesystem|volume|snapshot>\n")); |
171 "<filesystem|volume|snapshot>\n")); |
169 case HELP_GET: |
172 case HELP_GET: |
170 return (gettext("\tget [-rHp] [-o field[,field]...] " |
173 return (gettext("\tget [-rHp] [-o field[,field]...] " |
171 "[-s source[,source]...]\n" |
174 "[-s source[,source]...]\n" |
172 "\t <all | property[,property]...> " |
175 "\t <all | property[,property]...> " |
173 "<filesystem|volume|snapshot> ...\n")); |
176 "[filesystem|volume|snapshot] ...\n")); |
174 case HELP_INHERIT: |
177 case HELP_INHERIT: |
175 return (gettext("\tinherit [-r] <property> " |
178 return (gettext("\tinherit [-r] <property> " |
176 "<filesystem|volume> ...\n")); |
179 "<filesystem|volume> ...\n")); |
177 case HELP_LIST: |
180 case HELP_LIST: |
178 return (gettext("\tlist [-rH] [-o property[,property]...] " |
181 return (gettext("\tlist [-rH] [-o property[,property]...] " |
300 else |
303 else |
301 (void) fprintf(fp, "%s\n", zfs_prop_values(i)); |
304 (void) fprintf(fp, "%s\n", zfs_prop_values(i)); |
302 } |
305 } |
303 (void) fprintf(fp, gettext("\nSizes are specified in bytes " |
306 (void) fprintf(fp, gettext("\nSizes are specified in bytes " |
304 "with standard units such as K, M, G, etc.\n")); |
307 "with standard units such as K, M, G, etc.\n")); |
|
308 (void) fprintf(fp, gettext("\n\nUser-defined properties can " |
|
309 "be specified by using a name containing a colon (:).\n")); |
305 } else { |
310 } else { |
306 /* |
311 /* |
307 * TRANSLATION NOTE: |
312 * TRANSLATION NOTE: |
308 * "zfs set|get" must not be localised this is the |
313 * "zfs set|get" must not be localised this is the |
309 * command name and arguments. |
314 * command name and arguments. |
310 */ |
315 */ |
311 (void) fprintf(fp, |
316 (void) fprintf(fp, |
312 gettext("\nFor the property list, run: zfs set|get\n")); |
317 gettext("\nFor the property list, run: zfs set|get\n")); |
313 } |
318 } |
314 |
319 |
|
320 /* |
|
321 * See comments at end of main(). |
|
322 */ |
|
323 if (getenv("ZFS_ABORT") != NULL) { |
|
324 (void) printf("dumping core by request\n"); |
|
325 abort(); |
|
326 } |
|
327 |
315 exit(requested ? 0 : 2); |
328 exit(requested ? 0 : 2); |
316 } |
329 } |
317 |
330 |
318 /* |
331 /* |
319 * zfs clone <fs, snap, vol> fs |
332 * zfs clone <fs, snap, vol> fs |
388 */ |
401 */ |
389 static int |
402 static int |
390 zfs_do_create(int argc, char **argv) |
403 zfs_do_create(int argc, char **argv) |
391 { |
404 { |
392 zfs_type_t type = ZFS_TYPE_FILESYSTEM; |
405 zfs_type_t type = ZFS_TYPE_FILESYSTEM; |
393 zfs_handle_t *zhp; |
406 zfs_handle_t *zhp = NULL; |
394 char *size = NULL; |
407 uint64_t volsize; |
395 char *blocksize = NULL; |
|
396 int c; |
408 int c; |
397 boolean_t noreserve = B_FALSE; |
409 boolean_t noreserve = B_FALSE; |
398 int ret; |
410 int ret = 1; |
|
411 nvlist_t *props = NULL; |
|
412 uint64_t intval; |
|
413 char *propname; |
|
414 char *propval, *strval; |
|
415 |
|
416 if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) { |
|
417 (void) fprintf(stderr, gettext("internal error: " |
|
418 "out of memory\n")); |
|
419 return (1); |
|
420 } |
399 |
421 |
400 /* check options */ |
422 /* check options */ |
401 while ((c = getopt(argc, argv, ":V:b:s")) != -1) { |
423 while ((c = getopt(argc, argv, ":V:b:so:")) != -1) { |
402 switch (c) { |
424 switch (c) { |
403 case 'V': |
425 case 'V': |
404 type = ZFS_TYPE_VOLUME; |
426 type = ZFS_TYPE_VOLUME; |
405 size = optarg; |
427 if (zfs_nicestrtonum(g_zfs, optarg, &intval) != 0) { |
|
428 (void) fprintf(stderr, gettext("bad volume " |
|
429 "size '%s': %s\n"), optarg, |
|
430 libzfs_error_description(g_zfs)); |
|
431 goto error; |
|
432 } |
|
433 |
|
434 if (nvlist_add_uint64(props, |
|
435 zfs_prop_to_name(ZFS_PROP_VOLSIZE), |
|
436 intval) != 0) { |
|
437 (void) fprintf(stderr, gettext("internal " |
|
438 "error: out of memory\n")); |
|
439 goto error; |
|
440 } |
|
441 volsize = intval; |
406 break; |
442 break; |
407 case 'b': |
443 case 'b': |
408 blocksize = optarg; |
444 if (zfs_nicestrtonum(g_zfs, optarg, &intval) != 0) { |
|
445 (void) fprintf(stderr, gettext("bad volume " |
|
446 "block size '%s': %s\n"), optarg, |
|
447 libzfs_error_description(g_zfs)); |
|
448 goto error; |
|
449 } |
|
450 |
|
451 if (nvlist_add_uint64(props, |
|
452 zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), |
|
453 intval) != 0) { |
|
454 (void) fprintf(stderr, gettext("internal " |
|
455 "error: out of memory\n")); |
|
456 goto error; |
|
457 } |
|
458 break; |
|
459 case 'o': |
|
460 propname = optarg; |
|
461 if ((propval = strchr(propname, '=')) == NULL) { |
|
462 (void) fprintf(stderr, gettext("missing " |
|
463 "'=' for -o option\n")); |
|
464 goto error; |
|
465 } |
|
466 *propval = '\0'; |
|
467 propval++; |
|
468 if (nvlist_lookup_string(props, propname, |
|
469 &strval) == 0) { |
|
470 (void) fprintf(stderr, gettext("property '%s' " |
|
471 "specified multiple times\n"), propname); |
|
472 goto error; |
|
473 } |
|
474 if (nvlist_add_string(props, propname, propval) != 0) { |
|
475 (void) fprintf(stderr, gettext("internal " |
|
476 "error: out of memory\n")); |
|
477 goto error; |
|
478 } |
409 break; |
479 break; |
410 case 's': |
480 case 's': |
411 noreserve = B_TRUE; |
481 noreserve = B_TRUE; |
412 break; |
482 break; |
413 case ':': |
483 case ':': |
414 (void) fprintf(stderr, gettext("missing size " |
484 (void) fprintf(stderr, gettext("missing size " |
415 "argument\n")); |
485 "argument\n")); |
416 usage(B_FALSE); |
486 goto badusage; |
417 break; |
487 break; |
418 case '?': |
488 case '?': |
419 (void) fprintf(stderr, gettext("invalid option '%c'\n"), |
489 (void) fprintf(stderr, gettext("invalid option '%c'\n"), |
420 optopt); |
490 optopt); |
421 usage(B_FALSE); |
491 goto badusage; |
422 } |
492 } |
423 } |
493 } |
424 |
494 |
425 if (noreserve && type != ZFS_TYPE_VOLUME) { |
495 if (noreserve && type != ZFS_TYPE_VOLUME) { |
426 (void) fprintf(stderr, gettext("'-s' can only be used when " |
496 (void) fprintf(stderr, gettext("'-s' can only be used when " |
427 "creating a volume\n")); |
497 "creating a volume\n")); |
428 usage(B_FALSE); |
498 goto badusage; |
429 } |
499 } |
430 |
500 |
431 argc -= optind; |
501 argc -= optind; |
432 argv += optind; |
502 argv += optind; |
433 |
503 |
434 /* check number of arguments */ |
504 /* check number of arguments */ |
435 if (argc == 0) { |
505 if (argc == 0) { |
436 (void) fprintf(stderr, gettext("missing %s argument\n"), |
506 (void) fprintf(stderr, gettext("missing %s argument\n"), |
437 zfs_type_to_name(type)); |
507 zfs_type_to_name(type)); |
438 usage(B_FALSE); |
508 goto badusage; |
439 } |
509 } |
440 if (argc > 1) { |
510 if (argc > 1) { |
441 (void) fprintf(stderr, gettext("too many arguments\n")); |
511 (void) fprintf(stderr, gettext("too many arguments\n")); |
442 usage(B_FALSE); |
512 goto badusage; |
|
513 } |
|
514 |
|
515 if (type == ZFS_TYPE_VOLUME && !noreserve && |
|
516 nvlist_lookup_string(props, zfs_prop_to_name(ZFS_PROP_RESERVATION), |
|
517 &strval) != 0) { |
|
518 if (nvlist_add_uint64(props, |
|
519 zfs_prop_to_name(ZFS_PROP_RESERVATION), |
|
520 volsize) != 0) { |
|
521 (void) fprintf(stderr, gettext("internal " |
|
522 "error: out of memory\n")); |
|
523 nvlist_free(props); |
|
524 return (1); |
|
525 } |
443 } |
526 } |
444 |
527 |
445 /* pass to libzfs */ |
528 /* pass to libzfs */ |
446 if (zfs_create(g_zfs, argv[0], type, size, blocksize) != 0) |
529 if (zfs_create(g_zfs, argv[0], type, props) != 0) |
447 return (1); |
530 goto error; |
448 |
531 |
449 if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_ANY)) == NULL) |
532 if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_ANY)) == NULL) |
450 return (1); |
533 goto error; |
451 |
|
452 /* |
|
453 * Volume handling. By default, we try to create a reservation of equal |
|
454 * size for the volume. If we can't do this, then destroy the dataset |
|
455 * and report an error. |
|
456 */ |
|
457 if (type == ZFS_TYPE_VOLUME && !noreserve) { |
|
458 if (zfs_prop_set(zhp, ZFS_PROP_RESERVATION, size) != 0) { |
|
459 (void) fprintf(stderr, gettext("use '-s' to create a " |
|
460 "volume without a matching reservation\n")); |
|
461 (void) zfs_destroy(zhp); |
|
462 return (1); |
|
463 } |
|
464 } |
|
465 |
534 |
466 /* |
535 /* |
467 * Mount and/or share the new filesystem as appropriate. We provide a |
536 * Mount and/or share the new filesystem as appropriate. We provide a |
468 * verbose error message to let the user know that their filesystem was |
537 * verbose error message to let the user know that their filesystem was |
469 * in fact created, even if we failed to mount or share it. |
538 * in fact created, even if we failed to mount or share it. |
763 * columns to display as well as which property types to allow. |
839 * columns to display as well as which property types to allow. |
764 */ |
840 */ |
765 typedef struct get_cbdata { |
841 typedef struct get_cbdata { |
766 int cb_sources; |
842 int cb_sources; |
767 int cb_columns[4]; |
843 int cb_columns[4]; |
768 int cb_nprop; |
844 int cb_colwidths[5]; |
769 boolean_t cb_scripted; |
845 boolean_t cb_scripted; |
770 boolean_t cb_literal; |
846 boolean_t cb_literal; |
771 boolean_t cb_isall; |
847 boolean_t cb_first; |
772 zfs_prop_t cb_prop[ZFS_NPROP_ALL]; |
848 zfs_proplist_t *cb_proplist; |
773 } get_cbdata_t; |
849 } get_cbdata_t; |
774 |
850 |
775 #define GET_COL_NAME 1 |
851 #define GET_COL_NAME 1 |
776 #define GET_COL_PROPERTY 2 |
852 #define GET_COL_PROPERTY 2 |
777 #define GET_COL_VALUE 3 |
853 #define GET_COL_VALUE 3 |
778 #define GET_COL_SOURCE 4 |
854 #define GET_COL_SOURCE 4 |
779 |
855 |
780 /* |
856 /* |
|
857 * Print the column headers for 'zfs get'. |
|
858 */ |
|
859 static void |
|
860 print_get_headers(get_cbdata_t *cbp) |
|
861 { |
|
862 zfs_proplist_t *pl = cbp->cb_proplist; |
|
863 int i; |
|
864 char *title; |
|
865 size_t len; |
|
866 |
|
867 cbp->cb_first = B_FALSE; |
|
868 if (cbp->cb_scripted) |
|
869 return; |
|
870 |
|
871 /* |
|
872 * Start with the length of the column headers. |
|
873 */ |
|
874 cbp->cb_colwidths[GET_COL_NAME] = strlen(gettext("NAME")); |
|
875 cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(gettext("PROPERTY")); |
|
876 cbp->cb_colwidths[GET_COL_VALUE] = strlen(gettext("VALUE")); |
|
877 cbp->cb_colwidths[GET_COL_SOURCE] = strlen(gettext("SOURCE")); |
|
878 |
|
879 /* |
|
880 * Go through and calculate the widths for each column. For the |
|
881 * 'source' column, we kludge it up by taking the worst-case scenario of |
|
882 * inheriting from the longest name. This is acceptable because in the |
|
883 * majority of cases 'SOURCE' is the last column displayed, and we don't |
|
884 * use the width anyway. Note that the 'VALUE' column can be oversized, |
|
885 * if the name of the property is much longer the any values we find. |
|
886 */ |
|
887 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) { |
|
888 /* |
|
889 * 'PROPERTY' column |
|
890 */ |
|
891 if (pl->pl_prop != ZFS_PROP_INVAL) { |
|
892 len = strlen(zfs_prop_to_name(pl->pl_prop)); |
|
893 if (len > cbp->cb_colwidths[GET_COL_PROPERTY]) |
|
894 cbp->cb_colwidths[GET_COL_PROPERTY] = len; |
|
895 } else { |
|
896 len = strlen(pl->pl_user_prop); |
|
897 if (len > cbp->cb_colwidths[GET_COL_PROPERTY]) |
|
898 cbp->cb_colwidths[GET_COL_PROPERTY] = len; |
|
899 } |
|
900 |
|
901 /* |
|
902 * 'VALUE' column |
|
903 */ |
|
904 if ((pl->pl_prop != ZFS_PROP_NAME || !pl->pl_all) && |
|
905 pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE]) |
|
906 cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width; |
|
907 |
|
908 /* |
|
909 * 'NAME' and 'SOURCE' columns |
|
910 */ |
|
911 if (pl->pl_prop == ZFS_PROP_NAME && |
|
912 pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) { |
|
913 cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width; |
|
914 cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width + |
|
915 strlen(gettext("inherited from")); |
|
916 } |
|
917 } |
|
918 |
|
919 /* |
|
920 * Now go through and print the headers. |
|
921 */ |
|
922 for (i = 0; i < 4; i++) { |
|
923 switch (cbp->cb_columns[i]) { |
|
924 case GET_COL_NAME: |
|
925 title = gettext("NAME"); |
|
926 break; |
|
927 case GET_COL_PROPERTY: |
|
928 title = gettext("PROPERTY"); |
|
929 break; |
|
930 case GET_COL_VALUE: |
|
931 title = gettext("VALUE"); |
|
932 break; |
|
933 case GET_COL_SOURCE: |
|
934 title = gettext("SOURCE"); |
|
935 break; |
|
936 default: |
|
937 title = NULL; |
|
938 } |
|
939 |
|
940 if (title != NULL) { |
|
941 if (i == 3 || cbp->cb_columns[i + 1] == 0) |
|
942 (void) printf("%s", title); |
|
943 else |
|
944 (void) printf("%-*s ", |
|
945 cbp->cb_colwidths[cbp->cb_columns[i]], |
|
946 title); |
|
947 } |
|
948 } |
|
949 (void) printf("\n"); |
|
950 } |
|
951 |
|
952 /* |
781 * Display a single line of output, according to the settings in the callback |
953 * Display a single line of output, according to the settings in the callback |
782 * structure. |
954 * structure. |
783 */ |
955 */ |
784 static void |
956 static void |
785 print_one_property(zfs_handle_t *zhp, get_cbdata_t *cbp, zfs_prop_t prop, |
957 print_one_property(zfs_handle_t *zhp, get_cbdata_t *cbp, const char *propname, |
786 const char *value, zfs_source_t sourcetype, const char *source) |
958 const char *value, zfs_source_t sourcetype, const char *source) |
787 { |
959 { |
788 int i; |
960 int i; |
789 int width; |
|
790 const char *str; |
961 const char *str; |
791 char buf[128]; |
962 char buf[128]; |
792 |
963 |
793 /* |
964 /* |
794 * Ignore those source types that the user has chosen to ignore. |
965 * Ignore those source types that the user has chosen to ignore. |
795 */ |
966 */ |
796 if ((sourcetype & cbp->cb_sources) == 0) |
967 if ((sourcetype & cbp->cb_sources) == 0) |
797 return; |
968 return; |
798 |
969 |
|
970 if (cbp->cb_first) |
|
971 print_get_headers(cbp); |
|
972 |
799 for (i = 0; i < 4; i++) { |
973 for (i = 0; i < 4; i++) { |
800 switch (cbp->cb_columns[i]) { |
974 switch (cbp->cb_columns[i]) { |
801 case GET_COL_NAME: |
975 case GET_COL_NAME: |
802 width = 15; |
|
803 str = zfs_get_name(zhp); |
976 str = zfs_get_name(zhp); |
804 break; |
977 break; |
805 |
978 |
806 case GET_COL_PROPERTY: |
979 case GET_COL_PROPERTY: |
807 width = 13; |
980 str = propname; |
808 str = zfs_prop_to_name(prop); |
|
809 break; |
981 break; |
810 |
982 |
811 case GET_COL_VALUE: |
983 case GET_COL_VALUE: |
812 width = 25; |
|
813 str = value; |
984 str = value; |
814 break; |
985 break; |
815 |
986 |
816 case GET_COL_SOURCE: |
987 case GET_COL_SOURCE: |
817 width = 15; |
|
818 switch (sourcetype) { |
988 switch (sourcetype) { |
819 case ZFS_SRC_NONE: |
989 case ZFS_SRC_NONE: |
820 str = "-"; |
990 str = "-"; |
821 break; |
991 break; |
822 |
992 |
864 { |
1036 { |
865 char buf[ZFS_MAXPROPLEN]; |
1037 char buf[ZFS_MAXPROPLEN]; |
866 zfs_source_t sourcetype; |
1038 zfs_source_t sourcetype; |
867 char source[ZFS_MAXNAMELEN]; |
1039 char source[ZFS_MAXNAMELEN]; |
868 get_cbdata_t *cbp = data; |
1040 get_cbdata_t *cbp = data; |
869 int i; |
1041 nvlist_t *userprop = zfs_get_user_props(zhp); |
870 |
1042 zfs_proplist_t *pl = cbp->cb_proplist; |
871 for (i = 0; i < cbp->cb_nprop; i++) { |
1043 nvlist_t *propval; |
872 if (zfs_prop_get(zhp, cbp->cb_prop[i], buf, |
1044 char *strval; |
873 sizeof (buf), &sourcetype, source, sizeof (source), |
1045 char *sourceval; |
874 cbp->cb_literal) != 0) { |
1046 |
875 if (cbp->cb_isall) |
1047 for (; pl != NULL; pl = pl->pl_next) { |
876 continue; |
1048 /* |
877 (void) strlcpy(buf, "-", sizeof (buf)); |
1049 * Skip the special fake placeholder. This will also skip over |
878 sourcetype = ZFS_SRC_NONE; |
1050 * the name property when 'all' is specified. |
879 } |
1051 */ |
880 |
1052 if (pl->pl_prop == ZFS_PROP_NAME && |
881 print_one_property(zhp, cbp, cbp->cb_prop[i], |
1053 pl == cbp->cb_proplist) |
882 buf, sourcetype, source); |
1054 continue; |
|
1055 |
|
1056 if (pl->pl_prop != ZFS_PROP_INVAL) { |
|
1057 if (zfs_prop_get(zhp, pl->pl_prop, buf, |
|
1058 sizeof (buf), &sourcetype, source, |
|
1059 sizeof (source), |
|
1060 cbp->cb_literal) != 0) { |
|
1061 if (pl->pl_all) |
|
1062 continue; |
|
1063 sourcetype = ZFS_SRC_NONE; |
|
1064 (void) strlcpy(buf, "-", sizeof (buf)); |
|
1065 } |
|
1066 |
|
1067 print_one_property(zhp, cbp, |
|
1068 zfs_prop_to_name(pl->pl_prop), |
|
1069 buf, sourcetype, source); |
|
1070 } else { |
|
1071 if (nvlist_lookup_nvlist(userprop, |
|
1072 pl->pl_user_prop, &propval) != 0) { |
|
1073 if (pl->pl_all) |
|
1074 continue; |
|
1075 sourcetype = ZFS_SRC_NONE; |
|
1076 strval = "-"; |
|
1077 } else { |
|
1078 verify(nvlist_lookup_string(propval, |
|
1079 ZFS_PROP_VALUE, &strval) == 0); |
|
1080 verify(nvlist_lookup_string(propval, |
|
1081 ZFS_PROP_SOURCE, &sourceval) == 0); |
|
1082 |
|
1083 if (strcmp(sourceval, |
|
1084 zfs_get_name(zhp)) == 0) { |
|
1085 sourcetype = ZFS_SRC_LOCAL; |
|
1086 } else { |
|
1087 sourcetype = ZFS_SRC_INHERITED; |
|
1088 (void) strlcpy(source, |
|
1089 sourceval, sizeof (source)); |
|
1090 } |
|
1091 } |
|
1092 |
|
1093 print_one_property(zhp, cbp, |
|
1094 pl->pl_user_prop, strval, sourcetype, |
|
1095 source); |
|
1096 } |
883 } |
1097 } |
884 |
1098 |
885 return (0); |
1099 return (0); |
886 } |
1100 } |
887 |
1101 |
888 static int |
1102 static int |
889 zfs_do_get(int argc, char **argv) |
1103 zfs_do_get(int argc, char **argv) |
890 { |
1104 { |
891 get_cbdata_t cb = { 0 }; |
1105 get_cbdata_t cb = { 0 }; |
892 boolean_t recurse = B_FALSE; |
1106 boolean_t recurse = B_FALSE; |
893 int c; |
1107 int i, c; |
894 char *value, *fields, *badopt; |
1108 char *value, *fields; |
895 int i; |
|
896 int ret; |
1109 int ret; |
|
1110 zfs_proplist_t fake_name = { 0 }; |
897 |
1111 |
898 /* |
1112 /* |
899 * Set up default columns and sources. |
1113 * Set up default columns and sources. |
900 */ |
1114 */ |
901 cb.cb_sources = ZFS_SRC_ALL; |
1115 cb.cb_sources = ZFS_SRC_ALL; |
1012 usage(B_FALSE); |
1226 usage(B_FALSE); |
1013 } |
1227 } |
1014 |
1228 |
1015 fields = argv[0]; |
1229 fields = argv[0]; |
1016 |
1230 |
1017 /* |
1231 if (zfs_get_proplist(g_zfs, fields, &cb.cb_proplist) != 0) |
1018 * If the user specifies 'all', the behavior of 'zfs get' is slightly |
1232 usage(B_FALSE); |
1019 * different, because we don't show properties which don't apply to the |
|
1020 * given dataset. |
|
1021 */ |
|
1022 if (strcmp(fields, "all") == 0) |
|
1023 cb.cb_isall = B_TRUE; |
|
1024 |
|
1025 if ((ret = zfs_get_proplist(fields, cb.cb_prop, ZFS_NPROP_ALL, |
|
1026 &cb.cb_nprop, &badopt)) != 0) { |
|
1027 if (ret == EINVAL) |
|
1028 (void) fprintf(stderr, gettext("invalid property " |
|
1029 "'%s'\n"), badopt); |
|
1030 else |
|
1031 (void) fprintf(stderr, gettext("too many properties " |
|
1032 "specified\n")); |
|
1033 usage(B_FALSE); |
|
1034 } |
|
1035 |
1233 |
1036 argc--; |
1234 argc--; |
1037 argv++; |
1235 argv++; |
1038 |
1236 |
1039 /* check for at least one dataset name */ |
|
1040 if (argc < 1) { |
|
1041 (void) fprintf(stderr, gettext("missing dataset argument\n")); |
|
1042 usage(B_FALSE); |
|
1043 } |
|
1044 |
|
1045 /* |
1237 /* |
1046 * Print out any headers |
1238 * As part of zfs_expand_proplist(), we keep track of the maximum column |
|
1239 * width for each property. For the 'NAME' (and 'SOURCE') columns, we |
|
1240 * need to know the maximum name length. However, the user likely did |
|
1241 * not specify 'name' as one of the properties to fetch, so we need to |
|
1242 * make sure we always include at least this property for |
|
1243 * print_get_headers() to work properly. |
1047 */ |
1244 */ |
1048 if (!cb.cb_scripted) { |
1245 if (cb.cb_proplist != NULL) { |
1049 int i; |
1246 fake_name.pl_prop = ZFS_PROP_NAME; |
1050 for (i = 0; i < 4; i++) { |
1247 fake_name.pl_width = strlen(gettext("NAME")); |
1051 switch (cb.cb_columns[i]) { |
1248 fake_name.pl_next = cb.cb_proplist; |
1052 case GET_COL_NAME: |
1249 cb.cb_proplist = &fake_name; |
1053 (void) printf("%-15s ", "NAME"); |
1250 } |
1054 break; |
1251 |
1055 case GET_COL_PROPERTY: |
1252 cb.cb_first = B_TRUE; |
1056 (void) printf("%-13s ", "PROPERTY"); |
|
1057 break; |
|
1058 case GET_COL_VALUE: |
|
1059 (void) printf("%-25s ", "VALUE"); |
|
1060 break; |
|
1061 case GET_COL_SOURCE: |
|
1062 (void) printf("%s", "SOURCE"); |
|
1063 break; |
|
1064 } |
|
1065 } |
|
1066 (void) printf("\n"); |
|
1067 } |
|
1068 |
1253 |
1069 /* run for each object */ |
1254 /* run for each object */ |
1070 return (zfs_for_each(argc, argv, recurse, ZFS_TYPE_ANY, NULL, |
1255 ret = zfs_for_each(argc, argv, recurse, ZFS_TYPE_ANY, NULL, |
1071 get_callback, &cb)); |
1256 &cb.cb_proplist, get_callback, &cb); |
1072 |
1257 |
|
1258 if (cb.cb_proplist == &fake_name) |
|
1259 zfs_free_proplist(fake_name.pl_next); |
|
1260 else |
|
1261 zfs_free_proplist(cb.cb_proplist); |
|
1262 |
|
1263 return (ret); |
1073 } |
1264 } |
1074 |
1265 |
1075 /* |
1266 /* |
1076 * inherit [-r] <property> <fs|vol> ... |
1267 * inherit [-r] <property> <fs|vol> ... |
1077 * |
1268 * |
1125 (void) fprintf(stderr, gettext("missing dataset argument\n")); |
1314 (void) fprintf(stderr, gettext("missing dataset argument\n")); |
1126 usage(B_FALSE); |
1315 usage(B_FALSE); |
1127 } |
1316 } |
1128 |
1317 |
1129 propname = argv[0]; |
1318 propname = argv[0]; |
1130 |
1319 argc--; |
1131 /* |
1320 argv++; |
1132 * Get and validate the property before iterating over the datasets. We |
1321 |
1133 * do this now so as to avoid printing out an error message for each and |
1322 if ((prop = zfs_name_to_prop(propname)) != ZFS_PROP_INVAL) { |
1134 * every dataset. |
1323 if (zfs_prop_readonly(prop)) { |
1135 */ |
1324 (void) fprintf(stderr, gettext( |
1136 if ((prop = zfs_name_to_prop(propname)) == ZFS_PROP_INVAL) { |
1325 "%s property is read-only\n"), |
1137 (void) fprintf(stderr, gettext("invalid property '%s'\n"), |
1326 propname); |
|
1327 return (1); |
|
1328 } |
|
1329 if (!zfs_prop_inheritable(prop)) { |
|
1330 (void) fprintf(stderr, gettext("'%s' property cannot " |
|
1331 "be inherited\n"), propname); |
|
1332 if (prop == ZFS_PROP_QUOTA || |
|
1333 prop == ZFS_PROP_RESERVATION) |
|
1334 (void) fprintf(stderr, gettext("use 'zfs set " |
|
1335 "%s=none' to clear\n"), propname); |
|
1336 return (1); |
|
1337 } |
|
1338 } else if (!zfs_prop_user(propname)) { |
|
1339 (void) fprintf(stderr, gettext( |
|
1340 "invalid property '%s'\n"), |
1138 propname); |
1341 propname); |
1139 usage(B_FALSE); |
1342 usage(B_FALSE); |
1140 } |
1343 } |
1141 if (zfs_prop_readonly(prop)) { |
1344 |
1142 (void) fprintf(stderr, gettext("%s property is read-only\n"), |
1345 return (zfs_for_each(argc, argv, recurse, |
1143 propname); |
1346 ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, NULL, NULL, |
1144 return (1); |
1347 inherit_callback, propname)); |
1145 } |
|
1146 if (!zfs_prop_inheritable(prop)) { |
|
1147 (void) fprintf(stderr, gettext("%s property cannot be " |
|
1148 "inherited\n"), propname); |
|
1149 (void) fprintf(stderr, gettext("use 'zfs set %s=none' to " |
|
1150 "clear\n"), propname); |
|
1151 return (1); |
|
1152 } |
|
1153 |
|
1154 return (zfs_for_each(argc - 1, argv + 1, recurse, |
|
1155 ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, NULL, |
|
1156 inherit_callback, (void *)prop)); |
|
1157 } |
1348 } |
1158 |
1349 |
1159 /* |
1350 /* |
1160 * list [-rH] [-o property[,property]...] [-t type[,type]...] |
1351 * list [-rH] [-o property[,property]...] [-t type[,type]...] |
1161 * [-s property [-s property]...] [-S property [-S property]...] |
1352 * [-s property [-s property]...] [-S property [-S property]...] |
1173 * '-r' is specified. |
1364 * '-r' is specified. |
1174 */ |
1365 */ |
1175 typedef struct list_cbdata { |
1366 typedef struct list_cbdata { |
1176 boolean_t cb_first; |
1367 boolean_t cb_first; |
1177 boolean_t cb_scripted; |
1368 boolean_t cb_scripted; |
1178 zfs_prop_t cb_fields[ZFS_NPROP_ALL]; |
1369 zfs_proplist_t *cb_proplist; |
1179 int cb_fieldcount; |
|
1180 } list_cbdata_t; |
1370 } list_cbdata_t; |
1181 |
1371 |
1182 /* |
1372 /* |
1183 * Given a list of columns to display, output appropriate headers for each one. |
1373 * Given a list of columns to display, output appropriate headers for each one. |
1184 */ |
1374 */ |
1185 static void |
1375 static void |
1186 print_header(zfs_prop_t *fields, size_t count) |
1376 print_header(zfs_proplist_t *pl) |
1187 { |
1377 { |
|
1378 char headerbuf[ZFS_MAXPROPLEN]; |
|
1379 const char *header; |
1188 int i; |
1380 int i; |
1189 |
1381 boolean_t first = B_TRUE; |
1190 for (i = 0; i < count; i++) { |
1382 boolean_t right_justify; |
1191 if (i != 0) |
1383 |
|
1384 for (; pl != NULL; pl = pl->pl_next) { |
|
1385 if (!first) { |
1192 (void) printf(" "); |
1386 (void) printf(" "); |
1193 if (i == count - 1) |
1387 } else { |
1194 (void) printf("%s", zfs_prop_column_name(fields[i])); |
1388 first = B_FALSE; |
1195 else /* LINTED - format specifier */ |
1389 } |
1196 (void) printf(zfs_prop_column_format(fields[i]), |
1390 |
1197 zfs_prop_column_name(fields[i])); |
1391 right_justify = B_FALSE; |
|
1392 if (pl->pl_prop != ZFS_PROP_INVAL) { |
|
1393 header = zfs_prop_column_name(pl->pl_prop); |
|
1394 right_justify = zfs_prop_align_right(pl->pl_prop); |
|
1395 } else { |
|
1396 for (i = 0; pl->pl_user_prop[i] != '\0'; i++) |
|
1397 headerbuf[i] = toupper(pl->pl_user_prop[i]); |
|
1398 headerbuf[i] = '\0'; |
|
1399 header = headerbuf; |
|
1400 } |
|
1401 |
|
1402 if (pl->pl_next == NULL && !right_justify) |
|
1403 (void) printf("%s", header); |
|
1404 else if (right_justify) |
|
1405 (void) printf("%*s", pl->pl_width, header); |
|
1406 else |
|
1407 (void) printf("%-*s", pl->pl_width, header); |
1198 } |
1408 } |
1199 |
1409 |
1200 (void) printf("\n"); |
1410 (void) printf("\n"); |
1201 } |
1411 } |
1202 |
1412 |
1203 /* |
1413 /* |
1204 * Given a dataset and a list of fields, print out all the properties according |
1414 * Given a dataset and a list of fields, print out all the properties according |
1205 * to the described layout. |
1415 * to the described layout. |
1206 */ |
1416 */ |
1207 static void |
1417 static void |
1208 print_dataset(zfs_handle_t *zhp, zfs_prop_t *fields, size_t count, int scripted) |
1418 print_dataset(zfs_handle_t *zhp, zfs_proplist_t *pl, int scripted) |
1209 { |
1419 { |
1210 int i; |
1420 boolean_t first = B_TRUE; |
1211 char property[ZFS_MAXPROPLEN]; |
1421 char property[ZFS_MAXPROPLEN]; |
1212 |
1422 nvlist_t *userprops = zfs_get_user_props(zhp); |
1213 for (i = 0; i < count; i++) { |
1423 nvlist_t *propval; |
1214 if (i != 0) { |
1424 char *propstr; |
|
1425 boolean_t right_justify; |
|
1426 int width; |
|
1427 |
|
1428 for (; pl != NULL; pl = pl->pl_next) { |
|
1429 if (!first) { |
1215 if (scripted) |
1430 if (scripted) |
1216 (void) printf("\t"); |
1431 (void) printf("\t"); |
1217 else |
1432 else |
1218 (void) printf(" "); |
1433 (void) printf(" "); |
1219 } |
1434 } else { |
1220 |
1435 first = B_FALSE; |
1221 if (zfs_prop_get(zhp, fields[i], property, |
1436 } |
1222 sizeof (property), NULL, NULL, 0, B_FALSE) != 0) |
1437 |
1223 (void) strlcpy(property, "-", sizeof (property)); |
1438 right_justify = B_FALSE; |
|
1439 if (pl->pl_prop != ZFS_PROP_INVAL) { |
|
1440 if (zfs_prop_get(zhp, pl->pl_prop, property, |
|
1441 sizeof (property), NULL, NULL, 0, B_FALSE) != 0) |
|
1442 propstr = "-"; |
|
1443 else |
|
1444 propstr = property; |
|
1445 |
|
1446 right_justify = zfs_prop_align_right(pl->pl_prop); |
|
1447 } else { |
|
1448 if (nvlist_lookup_nvlist(userprops, |
|
1449 pl->pl_user_prop, &propval) != 0) |
|
1450 propstr = "-"; |
|
1451 else |
|
1452 verify(nvlist_lookup_string(propval, |
|
1453 ZFS_PROP_VALUE, &propstr) == 0); |
|
1454 } |
|
1455 |
|
1456 width = pl->pl_width; |
1224 |
1457 |
1225 /* |
1458 /* |
1226 * If this is being called in scripted mode, or if this is the |
1459 * If this is being called in scripted mode, or if this is the |
1227 * last column and it is left-justified, don't include a width |
1460 * last column and it is left-justified, don't include a width |
1228 * format specifier. |
1461 * format specifier. |
1229 */ |
1462 */ |
1230 if (scripted || (i == count - 1 && |
1463 if (scripted || (pl->pl_next == NULL && !right_justify)) |
1231 strchr(zfs_prop_column_format(fields[i]), '-') != NULL)) |
1464 (void) printf("%s", propstr); |
1232 (void) printf("%s", property); |
1465 else if (right_justify) |
1233 else /* LINTED - format specifier */ |
1466 (void) printf("%*s", width, propstr); |
1234 (void) printf(zfs_prop_column_format(fields[i]), |
1467 else |
1235 property); |
1468 (void) printf("%-*s", width, propstr); |
1236 } |
1469 } |
1237 |
1470 |
1238 (void) printf("\n"); |
1471 (void) printf("\n"); |
1239 } |
1472 } |
1240 |
1473 |
1290 break; |
1518 break; |
1291 case 'H': |
1519 case 'H': |
1292 scripted = B_TRUE; |
1520 scripted = B_TRUE; |
1293 break; |
1521 break; |
1294 case 's': |
1522 case 's': |
1295 if ((prop = zfs_name_to_prop(optarg)) == |
1523 if (zfs_add_sort_column(&sortcol, optarg, |
1296 ZFS_PROP_INVAL) { |
1524 B_FALSE) != 0) { |
1297 (void) fprintf(stderr, |
1525 (void) fprintf(stderr, |
1298 gettext("invalid property '%s'\n"), optarg); |
1526 gettext("invalid property '%s'\n"), optarg); |
1299 usage(B_FALSE); |
1527 usage(B_FALSE); |
1300 } |
1528 } |
1301 zfs_add_sort_column(&sortcol, prop, B_FALSE); |
|
1302 break; |
1529 break; |
1303 case 'S': |
1530 case 'S': |
1304 if ((prop = zfs_name_to_prop(optarg)) == |
1531 if (zfs_add_sort_column(&sortcol, optarg, |
1305 ZFS_PROP_INVAL) { |
1532 B_TRUE) != 0) { |
1306 (void) fprintf(stderr, |
1533 (void) fprintf(stderr, |
1307 gettext("invalid property '%s'\n"), optarg); |
1534 gettext("invalid property '%s'\n"), optarg); |
1308 usage(B_FALSE); |
1535 usage(B_FALSE); |
1309 } |
1536 } |
1310 zfs_add_sort_column(&sortcol, prop, B_TRUE); |
|
1311 break; |
1537 break; |
1312 case 't': |
1538 case 't': |
1313 types = 0; |
1539 types = 0; |
1314 while (*optarg != '\0') { |
1540 while (*optarg != '\0') { |
1315 switch (getsubopt(&optarg, type_subopts, |
1541 switch (getsubopt(&optarg, type_subopts, |
1352 /* |
1578 /* |
1353 * If the user specifies '-o all', the zfs_get_proplist() doesn't |
1579 * If the user specifies '-o all', the zfs_get_proplist() doesn't |
1354 * normally include the name of the dataset. For 'zfs list', we always |
1580 * normally include the name of the dataset. For 'zfs list', we always |
1355 * want this property to be first. |
1581 * want this property to be first. |
1356 */ |
1582 */ |
1357 if (strcmp(fields, "all") == 0) { |
1583 if (zfs_get_proplist(g_zfs, fields, &cb.cb_proplist) != 0) |
1358 cb.cb_fields[0] = ZFS_PROP_NAME; |
1584 usage(B_FALSE); |
1359 alloffset = 1; |
1585 |
1360 } else { |
|
1361 alloffset = 0; |
|
1362 } |
|
1363 |
|
1364 if ((ret = zfs_get_proplist(fields, cb.cb_fields + alloffset, |
|
1365 ZFS_NPROP_ALL - alloffset, &cb.cb_fieldcount, &badopt)) != 0) { |
|
1366 if (ret == EINVAL) |
|
1367 (void) fprintf(stderr, gettext("invalid property " |
|
1368 "'%s'\n"), badopt); |
|
1369 else |
|
1370 (void) fprintf(stderr, gettext("too many properties " |
|
1371 "specified\n")); |
|
1372 usage(B_FALSE); |
|
1373 } |
|
1374 |
|
1375 cb.cb_fieldcount += alloffset; |
|
1376 cb.cb_scripted = scripted; |
1586 cb.cb_scripted = scripted; |
1377 cb.cb_first = B_TRUE; |
1587 cb.cb_first = B_TRUE; |
1378 |
1588 |
1379 ret = zfs_for_each(argc, argv, recurse, types, sortcol, |
1589 ret = zfs_for_each(argc, argv, recurse, types, sortcol, &cb.cb_proplist, |
1380 list_callback, &cb); |
1590 list_callback, &cb); |
1381 |
1591 |
|
1592 zfs_free_proplist(cb.cb_proplist); |
1382 zfs_free_sort_columns(sortcol); |
1593 zfs_free_sort_columns(sortcol); |
1383 |
1594 |
1384 if (ret == 0 && cb.cb_first) |
1595 if (ret == 0 && cb.cb_first) |
1385 (void) printf(gettext("no datasets available\n")); |
1596 (void) printf(gettext("no datasets available\n")); |
1386 |
1597 |
1650 * Sets the given property for all datasets specified on the command line. |
1861 * Sets the given property for all datasets specified on the command line. |
1651 */ |
1862 */ |
1652 typedef struct set_cbdata { |
1863 typedef struct set_cbdata { |
1653 char *cb_propname; |
1864 char *cb_propname; |
1654 char *cb_value; |
1865 char *cb_value; |
1655 zfs_prop_t cb_prop; |
|
1656 } set_cbdata_t; |
1866 } set_cbdata_t; |
1657 |
1867 |
1658 static int |
1868 static int |
1659 set_callback(zfs_handle_t *zhp, void *data) |
1869 set_callback(zfs_handle_t *zhp, void *data) |
1660 { |
1870 { |
1661 set_cbdata_t *cbp = data; |
1871 set_cbdata_t *cbp = data; |
1662 int ret = 1; |
1872 int ret = 1; |
1663 |
1873 |
1664 /* don't allow setting of properties for snapshots */ |
1874 if (zfs_prop_set(zhp, cbp->cb_propname, cbp->cb_value) != 0) { |
1665 if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT) { |
|
1666 (void) fprintf(stderr, gettext("cannot set %s property for " |
|
1667 "'%s': snapshot properties cannot be modified\n"), |
|
1668 cbp->cb_propname, zfs_get_name(zhp)); |
|
1669 return (1); |
|
1670 } |
|
1671 |
|
1672 /* |
|
1673 * If we're changing the volsize, make sure the value is appropriate, |
|
1674 * and set the reservation if this is a non-sparse volume. |
|
1675 */ |
|
1676 if (cbp->cb_prop == ZFS_PROP_VOLSIZE && |
|
1677 zfs_get_type(zhp) == ZFS_TYPE_VOLUME) { |
|
1678 uint64_t volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE); |
|
1679 uint64_t avail = zfs_prop_get_int(zhp, ZFS_PROP_AVAILABLE); |
|
1680 uint64_t reservation = zfs_prop_get_int(zhp, |
|
1681 ZFS_PROP_RESERVATION); |
|
1682 uint64_t blocksize = zfs_prop_get_int(zhp, |
|
1683 ZFS_PROP_VOLBLOCKSIZE); |
|
1684 uint64_t value; |
|
1685 |
|
1686 verify(zfs_nicestrtonum(cbp->cb_value, &value) == 0); |
|
1687 |
|
1688 if (value % blocksize != 0) { |
|
1689 char buf[64]; |
|
1690 |
|
1691 zfs_nicenum(blocksize, buf, sizeof (buf)); |
|
1692 (void) fprintf(stderr, gettext("cannot set %s for " |
|
1693 "'%s': must be a multiple of volume block size " |
|
1694 "(%s)\n"), cbp->cb_propname, zfs_get_name(zhp), |
|
1695 buf); |
|
1696 return (1); |
|
1697 } |
|
1698 |
|
1699 if (value == 0) { |
|
1700 (void) fprintf(stderr, gettext("cannot set %s for " |
|
1701 "'%s': cannot be zero\n"), cbp->cb_propname, |
|
1702 zfs_get_name(zhp)); |
|
1703 return (1); |
|
1704 } |
|
1705 |
|
1706 if (volsize == reservation) { |
|
1707 if (value > volsize && (value - volsize) > avail) { |
|
1708 (void) fprintf(stderr, gettext("cannot set " |
|
1709 "%s property for '%s': volume size exceeds " |
|
1710 "amount of available space\n"), |
|
1711 cbp->cb_propname, zfs_get_name(zhp)); |
|
1712 return (1); |
|
1713 } |
|
1714 |
|
1715 if (zfs_prop_set(zhp, ZFS_PROP_RESERVATION, |
|
1716 cbp->cb_value) != 0) { |
|
1717 (void) fprintf(stderr, gettext("volsize and " |
|
1718 "reservation must remain equal\n")); |
|
1719 return (1); |
|
1720 } |
|
1721 } |
|
1722 } |
|
1723 |
|
1724 /* |
|
1725 * Do not allow the reservation to be set above the volume size. We do |
|
1726 * this here instead of inside libzfs because libzfs violates this rule |
|
1727 * internally. |
|
1728 */ |
|
1729 if (cbp->cb_prop == ZFS_PROP_RESERVATION && |
|
1730 zfs_get_type(zhp) == ZFS_TYPE_VOLUME) { |
|
1731 uint64_t value; |
|
1732 uint64_t volsize; |
|
1733 |
|
1734 volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE); |
|
1735 if (strcmp(cbp->cb_value, "none") == 0) |
|
1736 value = 0; |
|
1737 else |
|
1738 verify(zfs_nicestrtonum(cbp->cb_value, &value) == 0); |
|
1739 |
|
1740 if (value > volsize) { |
|
1741 (void) fprintf(stderr, gettext("cannot set %s " |
|
1742 "for '%s': size is greater than current " |
|
1743 "volume size\n"), cbp->cb_propname, |
|
1744 zfs_get_name(zhp)); |
|
1745 return (-1); |
|
1746 } |
|
1747 } |
|
1748 |
|
1749 if (zfs_prop_set(zhp, cbp->cb_prop, cbp->cb_value) != 0) { |
|
1750 switch (libzfs_errno(g_zfs)) { |
1875 switch (libzfs_errno(g_zfs)) { |
1751 case EZFS_MOUNTFAILED: |
1876 case EZFS_MOUNTFAILED: |
1752 (void) fprintf(stderr, gettext("property may be set " |
1877 (void) fprintf(stderr, gettext("property may be set " |
1753 "but unable to remount filesystem\n")); |
1878 "but unable to remount filesystem\n")); |
1754 break; |
1879 break; |
1801 if (*cb.cb_propname == '\0') { |
1926 if (*cb.cb_propname == '\0') { |
1802 (void) fprintf(stderr, |
1927 (void) fprintf(stderr, |
1803 gettext("missing property in property=value argument\n")); |
1928 gettext("missing property in property=value argument\n")); |
1804 usage(B_FALSE); |
1929 usage(B_FALSE); |
1805 } |
1930 } |
1806 if (*cb.cb_value == '\0') { |
|
1807 (void) fprintf(stderr, |
|
1808 gettext("missing value in property=value argument\n")); |
|
1809 usage(B_FALSE); |
|
1810 } |
|
1811 |
|
1812 /* get the property type */ |
|
1813 if ((cb.cb_prop = zfs_name_to_prop(cb.cb_propname)) == |
|
1814 ZFS_PROP_INVAL) { |
|
1815 (void) fprintf(stderr, |
|
1816 gettext("invalid property '%s'\n"), cb.cb_propname); |
|
1817 usage(B_FALSE); |
|
1818 } |
|
1819 |
|
1820 /* |
|
1821 * Validate that the value is appropriate for this property. We do this |
|
1822 * once now so we don't generate multiple errors each time we try to |
|
1823 * apply it to a dataset. |
|
1824 */ |
|
1825 if (zfs_prop_validate(g_zfs, cb.cb_prop, cb.cb_value, NULL) != 0) |
|
1826 return (1); |
|
1827 |
1931 |
1828 return (zfs_for_each(argc - 2, argv + 2, B_FALSE, |
1932 return (zfs_for_each(argc - 2, argv + 2, B_FALSE, |
1829 ZFS_TYPE_ANY, NULL, set_callback, &cb)); |
1933 ZFS_TYPE_ANY, NULL, NULL, set_callback, &cb)); |
1830 } |
1934 } |
1831 |
1935 |
1832 /* |
1936 /* |
1833 * zfs snapshot [-r] <fs@snap> |
1937 * zfs snapshot [-r] <fs@snap> |
1834 * |
1938 * |
2163 */ |
2267 */ |
2164 verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint, |
2268 verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint, |
2165 sizeof (mountpoint), NULL, NULL, 0, B_FALSE) == 0); |
2269 sizeof (mountpoint), NULL, NULL, 0, B_FALSE) == 0); |
2166 verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS, shareopts, |
2270 verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS, shareopts, |
2167 sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0); |
2271 sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0); |
|
2272 canmount = zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT); |
2168 |
2273 |
2169 if (cbp->cb_type == OP_SHARE) { |
2274 if (cbp->cb_type == OP_SHARE) { |
2170 if (strcmp(shareopts, "off") == 0) { |
2275 if (strcmp(shareopts, "off") == 0) { |
2171 if (!cbp->cb_explicit) |
2276 if (!cbp->cb_explicit) |
2172 return (0); |
2277 return (0); |