1 789 ahrens /* 2 789 ahrens * CDDL HEADER START 3 789 ahrens * 4 789 ahrens * The contents of this file are subject to the terms of the 5 1544 eschrock * Common Development and Distribution License (the "License"). 6 1544 eschrock * You may not use this file except in compliance with the License. 7 789 ahrens * 8 789 ahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 789 ahrens * or http://www.opensolaris.org/os/licensing. 10 789 ahrens * See the License for the specific language governing permissions 11 789 ahrens * and limitations under the License. 12 789 ahrens * 13 789 ahrens * When distributing Covered Code, include this CDDL HEADER in each 14 789 ahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 789 ahrens * If applicable, add the following below this CDDL HEADER, with the 16 789 ahrens * fields enclosed by brackets "[]" replaced with your own identifying 17 789 ahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18 789 ahrens * 19 789 ahrens * CDDL HEADER END 20 789 ahrens */ 21 3126 ahl 22 789 ahrens /* 23 8584 Lori * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 789 ahrens * Use is subject to license terms. 25 789 ahrens */ 26 789 ahrens 27 789 ahrens #include <assert.h> 28 2676 eschrock #include <ctype.h> 29 789 ahrens #include <errno.h> 30 789 ahrens #include <libgen.h> 31 789 ahrens #include <libintl.h> 32 789 ahrens #include <libuutil.h> 33 4543 marks #include <libnvpair.h> 34 789 ahrens #include <locale.h> 35 789 ahrens #include <stddef.h> 36 789 ahrens #include <stdio.h> 37 789 ahrens #include <stdlib.h> 38 789 ahrens #include <strings.h> 39 789 ahrens #include <unistd.h> 40 789 ahrens #include <fcntl.h> 41 789 ahrens #include <zone.h> 42 9396 Matthew #include <grp.h> 43 9396 Matthew #include <pwd.h> 44 789 ahrens #include <sys/mkdev.h> 45 789 ahrens #include <sys/mntent.h> 46 789 ahrens #include <sys/mnttab.h> 47 789 ahrens #include <sys/mount.h> 48 789 ahrens #include <sys/stat.h> 49 9396 Matthew #include <sys/fs/zfs.h> 50 789 ahrens 51 789 ahrens #include <libzfs.h> 52 4543 marks #include <libuutil.h> 53 789 ahrens 54 789 ahrens #include "zfs_iter.h" 55 2082 eschrock #include "zfs_util.h" 56 2082 eschrock 57 2082 eschrock libzfs_handle_t *g_zfs; 58 789 ahrens 59 789 ahrens static FILE *mnttab_file; 60 4988 ek110237 static char history_str[HIS_MAX_RECORD_LEN]; 61 9396 Matthew const char *pypath = "/usr/lib/zfs/pyzfs.py"; 62 789 ahrens 63 789 ahrens static int zfs_do_clone(int argc, char **argv); 64 789 ahrens static int zfs_do_create(int argc, char **argv); 65 789 ahrens static int zfs_do_destroy(int argc, char **argv); 66 789 ahrens static int zfs_do_get(int argc, char **argv); 67 789 ahrens static int zfs_do_inherit(int argc, char **argv); 68 789 ahrens static int zfs_do_list(int argc, char **argv); 69 789 ahrens static int zfs_do_mount(int argc, char **argv); 70 789 ahrens static int zfs_do_rename(int argc, char **argv); 71 789 ahrens static int zfs_do_rollback(int argc, char **argv); 72 789 ahrens static int zfs_do_set(int argc, char **argv); 73 4577 ahrens static int zfs_do_upgrade(int argc, char **argv); 74 789 ahrens static int zfs_do_snapshot(int argc, char **argv); 75 789 ahrens static int zfs_do_unmount(int argc, char **argv); 76 789 ahrens static int zfs_do_share(int argc, char **argv); 77 789 ahrens static int zfs_do_unshare(int argc, char **argv); 78 1749 ahrens static int zfs_do_send(int argc, char **argv); 79 1749 ahrens static int zfs_do_receive(int argc, char **argv); 80 2082 eschrock static int zfs_do_promote(int argc, char **argv); 81 9396 Matthew static int zfs_do_userspace(int argc, char **argv); 82 9396 Matthew static int zfs_do_python(int argc, char **argv); 83 10242 chris static int zfs_do_hold(int argc, char **argv); 84 10242 chris static int zfs_do_release(int argc, char **argv); 85 789 ahrens 86 789 ahrens /* 87 6865 rm160521 * Enable a reasonable set of defaults for libumem debugging on DEBUG builds. 88 6865 rm160521 */ 89 6865 rm160521 90 6865 rm160521 #ifdef DEBUG 91 789 ahrens const char * 92 3126 ahl _umem_debug_init(void) 93 789 ahrens { 94 789 ahrens return ("default,verbose"); /* $UMEM_DEBUG setting */ 95 789 ahrens } 96 789 ahrens 97 789 ahrens const char * 98 789 ahrens _umem_logging_init(void) 99 789 ahrens { 100 789 ahrens return ("fail,contents"); /* $UMEM_LOGGING setting */ 101 789 ahrens } 102 6865 rm160521 #endif 103 789 ahrens 104 1387 eschrock typedef enum { 105 1387 eschrock HELP_CLONE, 106 1387 eschrock HELP_CREATE, 107 1387 eschrock HELP_DESTROY, 108 1387 eschrock HELP_GET, 109 1387 eschrock HELP_INHERIT, 110 4577 ahrens HELP_UPGRADE, 111 1387 eschrock HELP_LIST, 112 1387 eschrock HELP_MOUNT, 113 2082 eschrock HELP_PROMOTE, 114 1749 ahrens HELP_RECEIVE, 115 1387 eschrock HELP_RENAME, 116 1387 eschrock HELP_ROLLBACK, 117 1749 ahrens HELP_SEND, 118 1387 eschrock HELP_SET, 119 1387 eschrock HELP_SHARE, 120 1387 eschrock HELP_SNAPSHOT, 121 1387 eschrock HELP_UNMOUNT, 122 4543 marks HELP_UNSHARE, 123 4543 marks HELP_ALLOW, 124 9396 Matthew HELP_UNALLOW, 125 9396 Matthew HELP_USERSPACE, 126 10242 chris HELP_GROUPSPACE, 127 10242 chris HELP_HOLD, 128 10242 chris HELP_HOLDS, 129 10242 chris HELP_RELEASE 130 1387 eschrock } zfs_help_t; 131 1387 eschrock 132 789 ahrens typedef struct zfs_command { 133 789 ahrens const char *name; 134 789 ahrens int (*func)(int argc, char **argv); 135 1387 eschrock zfs_help_t usage; 136 789 ahrens } zfs_command_t; 137 789 ahrens 138 789 ahrens /* 139 789 ahrens * Master command table. Each ZFS command has a name, associated function, and 140 1544 eschrock * usage message. The usage messages need to be internationalized, so we have 141 1544 eschrock * to have a function to return the usage message based on a command index. 142 1387 eschrock * 143 1387 eschrock * These commands are organized according to how they are displayed in the usage 144 1387 eschrock * message. An empty command (one with a NULL name) indicates an empty line in 145 1387 eschrock * the generic usage message. 146 789 ahrens */ 147 789 ahrens static zfs_command_t command_table[] = { 148 1387 eschrock { "create", zfs_do_create, HELP_CREATE }, 149 1387 eschrock { "destroy", zfs_do_destroy, HELP_DESTROY }, 150 789 ahrens { NULL }, 151 1387 eschrock { "snapshot", zfs_do_snapshot, HELP_SNAPSHOT }, 152 1387 eschrock { "rollback", zfs_do_rollback, HELP_ROLLBACK }, 153 1387 eschrock { "clone", zfs_do_clone, HELP_CLONE }, 154 2082 eschrock { "promote", zfs_do_promote, HELP_PROMOTE }, 155 1387 eschrock { "rename", zfs_do_rename, HELP_RENAME }, 156 789 ahrens { NULL }, 157 1387 eschrock { "list", zfs_do_list, HELP_LIST }, 158 789 ahrens { NULL }, 159 1387 eschrock { "set", zfs_do_set, HELP_SET }, 160 11022 Tom { "get", zfs_do_get, HELP_GET }, 161 1387 eschrock { "inherit", zfs_do_inherit, HELP_INHERIT }, 162 4577 ahrens { "upgrade", zfs_do_upgrade, HELP_UPGRADE }, 163 9396 Matthew { "userspace", zfs_do_userspace, HELP_USERSPACE }, 164 9396 Matthew { "groupspace", zfs_do_userspace, HELP_GROUPSPACE }, 165 789 ahrens { NULL }, 166 1387 eschrock { "mount", zfs_do_mount, HELP_MOUNT }, 167 1387 eschrock { "unmount", zfs_do_unmount, HELP_UNMOUNT }, 168 1387 eschrock { "share", zfs_do_share, HELP_SHARE }, 169 1387 eschrock { "unshare", zfs_do_unshare, HELP_UNSHARE }, 170 789 ahrens { NULL }, 171 1749 ahrens { "send", zfs_do_send, HELP_SEND }, 172 1749 ahrens { "receive", zfs_do_receive, HELP_RECEIVE }, 173 4543 marks { NULL }, 174 9396 Matthew { "allow", zfs_do_python, HELP_ALLOW }, 175 9396 Matthew { NULL }, 176 9396 Matthew { "unallow", zfs_do_python, HELP_UNALLOW }, 177 10242 chris { NULL }, 178 10242 chris { "hold", zfs_do_hold, HELP_HOLD }, 179 10242 chris { "holds", zfs_do_python, HELP_HOLDS }, 180 10242 chris { "release", zfs_do_release, HELP_RELEASE }, 181 789 ahrens }; 182 789 ahrens 183 789 ahrens #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0])) 184 789 ahrens 185 789 ahrens zfs_command_t *current_command; 186 1387 eschrock 187 1387 eschrock static const char * 188 1387 eschrock get_usage(zfs_help_t idx) 189 1387 eschrock { 190 1387 eschrock switch (idx) { 191 1387 eschrock case HELP_CLONE: 192 7265 ahrens return (gettext("\tclone [-p] [-o property=value] ... " 193 7265 ahrens "<snapshot> <filesystem|volume>\n")); 194 1387 eschrock case HELP_CREATE: 195 4849 ahrens return (gettext("\tcreate [-p] [-o property=value] ... " 196 2676 eschrock "<filesystem>\n" 197 4849 ahrens "\tcreate [-ps] [-b blocksize] [-o property=value] ... " 198 4849 ahrens "-V <size> <volume>\n")); 199 1387 eschrock case HELP_DESTROY: 200 10385 chris return (gettext("\tdestroy [-rRf] <filesystem|volume>\n" 201 10385 chris "\tdestroy [-rRd] <snapshot>\n")); 202 1387 eschrock case HELP_GET: 203 9365 Chris return (gettext("\tget [-rHp] [-d max] " 204 11022 Tom "[-o \"all\" | field[,...]] [-s source[,...]]\n" 205 4849 ahrens "\t <\"all\" | property[,...]> " 206 2676 eschrock "[filesystem|volume|snapshot] ...\n")); 207 1387 eschrock case HELP_INHERIT: 208 11022 Tom return (gettext("\tinherit [-rS] <property> " 209 7265 ahrens "<filesystem|volume|snapshot> ...\n")); 210 4577 ahrens case HELP_UPGRADE: 211 4577 ahrens return (gettext("\tupgrade [-v]\n" 212 4577 ahrens "\tupgrade [-r] [-V version] <-a | filesystem ...>\n")); 213 1387 eschrock case HELP_LIST: 214 9365 Chris return (gettext("\tlist [-rH][-d max] " 215 9365 Chris "[-o property[,...]] [-t type[,...]] [-s property] ...\n" 216 4849 ahrens "\t [-S property] ... " 217 4849 ahrens "[filesystem|volume|snapshot] ...\n")); 218 1387 eschrock case HELP_MOUNT: 219 1387 eschrock return (gettext("\tmount\n" 220 4849 ahrens "\tmount [-vO] [-o opts] <-a | filesystem>\n")); 221 2082 eschrock case HELP_PROMOTE: 222 4849 ahrens return (gettext("\tpromote <clone-filesystem>\n")); 223 1749 ahrens case HELP_RECEIVE: 224 2665 nd150628 return (gettext("\treceive [-vnF] <filesystem|volume|" 225 2665 nd150628 "snapshot>\n" 226 2665 nd150628 "\treceive [-vnF] -d <filesystem>\n")); 227 1387 eschrock case HELP_RENAME: 228 1387 eschrock return (gettext("\trename <filesystem|volume|snapshot> " 229 4007 mmusante "<filesystem|volume|snapshot>\n" 230 4490 vb160487 "\trename -p <filesystem|volume> <filesystem|volume>\n" 231 4007 mmusante "\trename -r <snapshot> <snapshot>")); 232 1387 eschrock case HELP_ROLLBACK: 233 5568 ahrens return (gettext("\trollback [-rRf] <snapshot>\n")); 234 1749 ahrens case HELP_SEND: 235 11022 Tom return (gettext("\tsend [-RDp] [-[iI] snapshot] <snapshot>\n")); 236 1387 eschrock case HELP_SET: 237 1387 eschrock return (gettext("\tset <property=value> " 238 7265 ahrens "<filesystem|volume|snapshot> ...\n")); 239 1387 eschrock case HELP_SHARE: 240 4849 ahrens return (gettext("\tshare <-a | filesystem>\n")); 241 1387 eschrock case HELP_SNAPSHOT: 242 7265 ahrens return (gettext("\tsnapshot [-r] [-o property=value] ... " 243 4849 ahrens "<filesystem@snapname|volume@snapname>\n")); 244 1387 eschrock case HELP_UNMOUNT: 245 4849 ahrens return (gettext("\tunmount [-f] " 246 4849 ahrens "<-a | filesystem|mountpoint>\n")); 247 1387 eschrock case HELP_UNSHARE: 248 10228 Stephanie return (gettext("\tunshare " 249 4849 ahrens "<-a | filesystem|mountpoint>\n")); 250 4543 marks case HELP_ALLOW: 251 9564 Stephanie return (gettext("\tallow <filesystem|volume>\n" 252 9564 Stephanie "\tallow [-ldug] " 253 4849 ahrens "<\"everyone\"|user|group>[,...] <perm|@setname>[,...]\n" 254 4849 ahrens "\t <filesystem|volume>\n" 255 4849 ahrens "\tallow [-ld] -e <perm|@setname>[,...] " 256 4849 ahrens "<filesystem|volume>\n" 257 4849 ahrens "\tallow -c <perm|@setname>[,...] <filesystem|volume>\n" 258 4849 ahrens "\tallow -s @setname <perm|@setname>[,...] " 259 4849 ahrens "<filesystem|volume>\n")); 260 4543 marks case HELP_UNALLOW: 261 4849 ahrens return (gettext("\tunallow [-rldug] " 262 4849 ahrens "<\"everyone\"|user|group>[,...]\n" 263 4849 ahrens "\t [<perm|@setname>[,...]] <filesystem|volume>\n" 264 4849 ahrens "\tunallow [-rld] -e [<perm|@setname>[,...]] " 265 4849 ahrens "<filesystem|volume>\n" 266 4849 ahrens "\tunallow [-r] -c [<perm|@setname>[,...]] " 267 4849 ahrens "<filesystem|volume>\n" 268 4849 ahrens "\tunallow [-r] -s @setname [<perm|@setname>[,...]] " 269 4849 ahrens "<filesystem|volume>\n")); 270 9396 Matthew case HELP_USERSPACE: 271 9396 Matthew return (gettext("\tuserspace [-hniHp] [-o field[,...]] " 272 9396 Matthew "[-sS field] ... [-t type[,...]]\n" 273 9396 Matthew "\t <filesystem|snapshot>\n")); 274 9396 Matthew case HELP_GROUPSPACE: 275 9396 Matthew return (gettext("\tgroupspace [-hniHpU] [-o field[,...]] " 276 9396 Matthew "[-sS field] ... [-t type[,...]]\n" 277 9396 Matthew "\t <filesystem|snapshot>\n")); 278 10242 chris case HELP_HOLD: 279 10242 chris return (gettext("\thold [-r] <tag> <snapshot> ...\n")); 280 10242 chris case HELP_HOLDS: 281 10242 chris return (gettext("\tholds [-r] <snapshot> ...\n")); 282 10242 chris case HELP_RELEASE: 283 10242 chris return (gettext("\trelease [-r] <tag> <snapshot> ...\n")); 284 1387 eschrock } 285 1387 eschrock 286 1387 eschrock abort(); 287 1387 eschrock /* NOTREACHED */ 288 1387 eschrock } 289 789 ahrens 290 789 ahrens /* 291 789 ahrens * Utility function to guarantee malloc() success. 292 789 ahrens */ 293 789 ahrens void * 294 789 ahrens safe_malloc(size_t size) 295 789 ahrens { 296 789 ahrens void *data; 297 789 ahrens 298 789 ahrens if ((data = calloc(1, size)) == NULL) { 299 789 ahrens (void) fprintf(stderr, "internal error: out of memory\n"); 300 789 ahrens exit(1); 301 789 ahrens } 302 789 ahrens 303 789 ahrens return (data); 304 789 ahrens } 305 789 ahrens 306 789 ahrens /* 307 5094 lling * Callback routine that will print out information for each of 308 3654 gw25295 * the properties. 309 3654 gw25295 */ 310 5094 lling static int 311 5094 lling usage_prop_cb(int prop, void *cb) 312 3654 gw25295 { 313 3654 gw25295 FILE *fp = cb; 314 3654 gw25295 315 6643 eschrock (void) fprintf(fp, "\t%-15s ", zfs_prop_to_name(prop)); 316 6643 eschrock 317 6643 eschrock if (zfs_prop_readonly(prop)) 318 6643 eschrock (void) fprintf(fp, " NO "); 319 6643 eschrock else 320 6643 eschrock (void) fprintf(fp, "YES "); 321 3654 gw25295 322 3654 gw25295 if (zfs_prop_inheritable(prop)) 323 3654 gw25295 (void) fprintf(fp, " YES "); 324 3654 gw25295 else 325 3654 gw25295 (void) fprintf(fp, " NO "); 326 3654 gw25295 327 3654 gw25295 if (zfs_prop_values(prop) == NULL) 328 3654 gw25295 (void) fprintf(fp, "-\n"); 329 3654 gw25295 else 330 3654 gw25295 (void) fprintf(fp, "%s\n", zfs_prop_values(prop)); 331 3654 gw25295 332 5094 lling return (ZPROP_CONT); 333 3654 gw25295 } 334 3654 gw25295 335 3654 gw25295 /* 336 789 ahrens * Display usage message. If we're inside a command, display only the usage for 337 789 ahrens * that command. Otherwise, iterate over the entire command table and display 338 789 ahrens * a complete usage message. 339 789 ahrens */ 340 789 ahrens static void 341 2082 eschrock usage(boolean_t requested) 342 789 ahrens { 343 789 ahrens int i; 344 2082 eschrock boolean_t show_properties = B_FALSE; 345 789 ahrens FILE *fp = requested ? stdout : stderr; 346 789 ahrens 347 789 ahrens if (current_command == NULL) { 348 789 ahrens 349 789 ahrens (void) fprintf(fp, gettext("usage: zfs command args ...\n")); 350 789 ahrens (void) fprintf(fp, 351 789 ahrens gettext("where 'command' is one of the following:\n\n")); 352 789 ahrens 353 789 ahrens for (i = 0; i < NCOMMAND; i++) { 354 789 ahrens if (command_table[i].name == NULL) 355 789 ahrens (void) fprintf(fp, "\n"); 356 789 ahrens else 357 789 ahrens (void) fprintf(fp, "%s", 358 1387 eschrock get_usage(command_table[i].usage)); 359 789 ahrens } 360 789 ahrens 361 789 ahrens (void) fprintf(fp, gettext("\nEach dataset is of the form: " 362 789 ahrens "pool/[dataset/]*dataset[@name]\n")); 363 789 ahrens } else { 364 789 ahrens (void) fprintf(fp, gettext("usage:\n")); 365 1387 eschrock (void) fprintf(fp, "%s", get_usage(current_command->usage)); 366 789 ahrens } 367 789 ahrens 368 2190 darrenm if (current_command != NULL && 369 2190 darrenm (strcmp(current_command->name, "set") == 0 || 370 789 ahrens strcmp(current_command->name, "get") == 0 || 371 789 ahrens strcmp(current_command->name, "inherit") == 0 || 372 2190 darrenm strcmp(current_command->name, "list") == 0)) 373 2082 eschrock show_properties = B_TRUE; 374 789 ahrens 375 789 ahrens if (show_properties) { 376 789 ahrens (void) fprintf(fp, 377 789 ahrens gettext("\nThe following properties are supported:\n")); 378 789 ahrens 379 5378 ck153898 (void) fprintf(fp, "\n\t%-14s %s %s %s\n\n", 380 789 ahrens "PROPERTY", "EDIT", "INHERIT", "VALUES"); 381 789 ahrens 382 3654 gw25295 /* Iterate over all properties */ 383 5094 lling (void) zprop_iter(usage_prop_cb, fp, B_FALSE, B_TRUE, 384 5094 lling ZFS_TYPE_DATASET); 385 9396 Matthew 386 9396 Matthew (void) fprintf(fp, "\t%-15s ", "userused (at) ..."); 387 9396 Matthew (void) fprintf(fp, " NO NO <size>\n"); 388 9396 Matthew (void) fprintf(fp, "\t%-15s ", "groupused (at) ..."); 389 9396 Matthew (void) fprintf(fp, " NO NO <size>\n"); 390 9396 Matthew (void) fprintf(fp, "\t%-15s ", "userquota (at) ..."); 391 9396 Matthew (void) fprintf(fp, "YES NO <size> | none\n"); 392 9396 Matthew (void) fprintf(fp, "\t%-15s ", "groupquota (at) ..."); 393 9396 Matthew (void) fprintf(fp, "YES NO <size> | none\n"); 394 789 ahrens 395 789 ahrens (void) fprintf(fp, gettext("\nSizes are specified in bytes " 396 789 ahrens "with standard units such as K, M, G, etc.\n")); 397 7390 Matthew (void) fprintf(fp, gettext("\nUser-defined properties can " 398 2676 eschrock "be specified by using a name containing a colon (:).\n")); 399 9396 Matthew (void) fprintf(fp, gettext("\nThe {user|group}{used|quota}@ " 400 9396 Matthew "properties must be appended with\n" 401 9396 Matthew "a user or group specifier of one of these forms:\n" 402 9396 Matthew " POSIX name (eg: \"matt\")\n" 403 9396 Matthew " POSIX id (eg: \"126829\")\n" 404 9396 Matthew " SMB name@domain (eg: \"matt@sun\")\n" 405 9396 Matthew " SMB SID (eg: \"S-1-234-567-89\")\n")); 406 2190 darrenm } else { 407 8269 Mark (void) fprintf(fp, 408 8269 Mark gettext("\nFor the property list, run: %s\n"), 409 8269 Mark "zfs set|get"); 410 8269 Mark (void) fprintf(fp, 411 8269 Mark gettext("\nFor the delegated permission list, run: %s\n"), 412 8269 Mark "zfs allow|unallow"); 413 2676 eschrock } 414 2676 eschrock 415 2676 eschrock /* 416 2676 eschrock * See comments at end of main(). 417 2676 eschrock */ 418 2676 eschrock if (getenv("ZFS_ABORT") != NULL) { 419 2676 eschrock (void) printf("dumping core by request\n"); 420 2676 eschrock abort(); 421 789 ahrens } 422 789 ahrens 423 789 ahrens exit(requested ? 0 : 2); 424 789 ahrens } 425 789 ahrens 426 7265 ahrens static int 427 7265 ahrens parseprop(nvlist_t *props) 428 7265 ahrens { 429 7265 ahrens char *propname = optarg; 430 7265 ahrens char *propval, *strval; 431 7265 ahrens 432 7265 ahrens if ((propval = strchr(propname, '=')) == NULL) { 433 7265 ahrens (void) fprintf(stderr, gettext("missing " 434 7265 ahrens "'=' for -o option\n")); 435 7265 ahrens return (-1); 436 7265 ahrens } 437 7265 ahrens *propval = '\0'; 438 7265 ahrens propval++; 439 7265 ahrens if (nvlist_lookup_string(props, propname, &strval) == 0) { 440 7265 ahrens (void) fprintf(stderr, gettext("property '%s' " 441 7265 ahrens "specified multiple times\n"), propname); 442 7265 ahrens return (-1); 443 7265 ahrens } 444 7265 ahrens if (nvlist_add_string(props, propname, propval) != 0) { 445 7265 ahrens (void) fprintf(stderr, gettext("internal " 446 7265 ahrens "error: out of memory\n")); 447 7265 ahrens return (-1); 448 7265 ahrens } 449 7265 ahrens return (0); 450 7265 ahrens } 451 7265 ahrens 452 9365 Chris static int 453 9365 Chris parse_depth(char *opt, int *flags) 454 9365 Chris { 455 9365 Chris char *tmp; 456 9365 Chris int depth; 457 9365 Chris 458 9365 Chris depth = (int)strtol(opt, &tmp, 0); 459 9365 Chris if (*tmp) { 460 9365 Chris (void) fprintf(stderr, 461 9365 Chris gettext("%s is not an integer\n"), optarg); 462 9365 Chris usage(B_FALSE); 463 9365 Chris } 464 9365 Chris if (depth < 0) { 465 9365 Chris (void) fprintf(stderr, 466 9365 Chris gettext("Depth can not be negative.\n")); 467 9365 Chris usage(B_FALSE); 468 9365 Chris } 469 9365 Chris *flags |= (ZFS_ITER_DEPTH_LIMIT|ZFS_ITER_RECURSE); 470 9365 Chris return (depth); 471 9365 Chris } 472 9365 Chris 473 7265 ahrens /* 474 7265 ahrens * zfs clone [-p] [-o prop=value] ... <snap> <fs | vol> 475 789 ahrens * 476 789 ahrens * Given an existing dataset, create a writable copy whose initial contents 477 789 ahrens * are the same as the source. The newly created dataset maintains a 478 789 ahrens * dependency on the original; the original cannot be destroyed so long as 479 789 ahrens * the clone exists. 480 4490 vb160487 * 481 4490 vb160487 * The '-p' flag creates all the non-existing ancestors of the target first. 482 789 ahrens */ 483 789 ahrens static int 484 789 ahrens zfs_do_clone(int argc, char **argv) 485 789 ahrens { 486 7265 ahrens zfs_handle_t *zhp = NULL; 487 4490 vb160487 boolean_t parents = B_FALSE; 488 7265 ahrens nvlist_t *props; 489 7265 ahrens int ret; 490 7265 ahrens int c; 491 7265 ahrens 492 7265 ahrens if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) { 493 7265 ahrens (void) fprintf(stderr, gettext("internal error: " 494 7265 ahrens "out of memory\n")); 495 7265 ahrens return (1); 496 7265 ahrens } 497 7265 ahrens 498 7265 ahrens /* check options */ 499 7265 ahrens while ((c = getopt(argc, argv, "o:p")) != -1) { 500 7265 ahrens switch (c) { 501 7265 ahrens case 'o': 502 7265 ahrens if (parseprop(props)) 503 7265 ahrens return (1); 504 7265 ahrens break; 505 4490 vb160487 case 'p': 506 4490 vb160487 parents = B_TRUE; 507 4490 vb160487 break; 508 4490 vb160487 case '?': 509 4490 vb160487 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 510 4490 vb160487 optopt); 511 7265 ahrens goto usage; 512 4490 vb160487 } 513 789 ahrens } 514 789 ahrens 515 4490 vb160487 argc -= optind; 516 4490 vb160487 argv += optind; 517 4490 vb160487 518 789 ahrens /* check number of arguments */ 519 4490 vb160487 if (argc < 1) { 520 789 ahrens (void) fprintf(stderr, gettext("missing source dataset " 521 789 ahrens "argument\n")); 522 7265 ahrens goto usage; 523 789 ahrens } 524 4490 vb160487 if (argc < 2) { 525 789 ahrens (void) fprintf(stderr, gettext("missing target dataset " 526 789 ahrens "argument\n")); 527 7265 ahrens goto usage; 528 789 ahrens } 529 4490 vb160487 if (argc > 2) { 530 789 ahrens (void) fprintf(stderr, gettext("too many arguments\n")); 531 7265 ahrens goto usage; 532 789 ahrens } 533 789 ahrens 534 789 ahrens /* open the source dataset */ 535 4490 vb160487 if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_SNAPSHOT)) == NULL) 536 789 ahrens return (1); 537 789 ahrens 538 4490 vb160487 if (parents && zfs_name_valid(argv[1], ZFS_TYPE_FILESYSTEM | 539 4490 vb160487 ZFS_TYPE_VOLUME)) { 540 4490 vb160487 /* 541 4490 vb160487 * Now create the ancestors of the target dataset. If the 542 4490 vb160487 * target already exists and '-p' option was used we should not 543 4490 vb160487 * complain. 544 4490 vb160487 */ 545 4490 vb160487 if (zfs_dataset_exists(g_zfs, argv[1], ZFS_TYPE_FILESYSTEM | 546 4490 vb160487 ZFS_TYPE_VOLUME)) 547 4490 vb160487 return (0); 548 4490 vb160487 if (zfs_create_ancestors(g_zfs, argv[1]) != 0) 549 4490 vb160487 return (1); 550 4490 vb160487 } 551 4490 vb160487 552 789 ahrens /* pass to libzfs */ 553 7265 ahrens ret = zfs_clone(zhp, argv[1], props); 554 789 ahrens 555 789 ahrens /* create the mountpoint if necessary */ 556 789 ahrens if (ret == 0) { 557 5094 lling zfs_handle_t *clone; 558 5094 lling 559 5094 lling clone = zfs_open(g_zfs, argv[1], ZFS_TYPE_DATASET); 560 789 ahrens if (clone != NULL) { 561 789 ahrens if ((ret = zfs_mount(clone, NULL, 0)) == 0) 562 789 ahrens ret = zfs_share(clone); 563 789 ahrens zfs_close(clone); 564 789 ahrens } 565 789 ahrens } 566 789 ahrens 567 789 ahrens zfs_close(zhp); 568 7265 ahrens nvlist_free(props); 569 7265 ahrens 570 7265 ahrens return (!!ret); 571 7265 ahrens 572 7265 ahrens usage: 573 7265 ahrens if (zhp) 574 7265 ahrens zfs_close(zhp); 575 7265 ahrens nvlist_free(props); 576 7265 ahrens usage(B_FALSE); 577 7265 ahrens return (-1); 578 789 ahrens } 579 789 ahrens 580 789 ahrens /* 581 4490 vb160487 * zfs create [-p] [-o prop=value] ... fs 582 4490 vb160487 * zfs create [-ps] [-b blocksize] [-o prop=value] ... -V vol size 583 789 ahrens * 584 789 ahrens * Create a new dataset. This command can be used to create filesystems 585 789 ahrens * and volumes. Snapshot creation is handled by 'zfs snapshot'. 586 789 ahrens * For volumes, the user must specify a size to be used. 587 789 ahrens * 588 789 ahrens * The '-s' flag applies only to volumes, and indicates that we should not try 589 789 ahrens * to set the reservation for this volume. By default we set a reservation 590 5481 ck153898 * equal to the size for any volume. For pools with SPA_VERSION >= 591 5481 ck153898 * SPA_VERSION_REFRESERVATION, we set a refreservation instead. 592 4490 vb160487 * 593 4490 vb160487 * The '-p' flag creates all the non-existing ancestors of the target first. 594 789 ahrens */ 595 789 ahrens static int 596 789 ahrens zfs_do_create(int argc, char **argv) 597 789 ahrens { 598 789 ahrens zfs_type_t type = ZFS_TYPE_FILESYSTEM; 599 2676 eschrock zfs_handle_t *zhp = NULL; 600 2676 eschrock uint64_t volsize; 601 789 ahrens int c; 602 2082 eschrock boolean_t noreserve = B_FALSE; 603 5367 ahrens boolean_t bflag = B_FALSE; 604 4490 vb160487 boolean_t parents = B_FALSE; 605 2676 eschrock int ret = 1; 606 7265 ahrens nvlist_t *props; 607 2676 eschrock uint64_t intval; 608 6168 hs24103 int canmount; 609 2676 eschrock 610 2676 eschrock if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) { 611 2676 eschrock (void) fprintf(stderr, gettext("internal error: " 612 2676 eschrock "out of memory\n")); 613 2676 eschrock return (1); 614 2676 eschrock } 615 789 ahrens 616 789 ahrens /* check options */ 617 4490 vb160487 while ((c = getopt(argc, argv, ":V:b:so:p")) != -1) { 618 789 ahrens switch (c) { 619 789 ahrens case 'V': 620 789 ahrens type = ZFS_TYPE_VOLUME; 621 2676 eschrock if (zfs_nicestrtonum(g_zfs, optarg, &intval) != 0) { 622 2676 eschrock (void) fprintf(stderr, gettext("bad volume " 623 2676 eschrock "size '%s': %s\n"), optarg, 624 2676 eschrock libzfs_error_description(g_zfs)); 625 2676 eschrock goto error; 626 2676 eschrock } 627 2676 eschrock 628 2676 eschrock if (nvlist_add_uint64(props, 629 2676 eschrock zfs_prop_to_name(ZFS_PROP_VOLSIZE), 630 2676 eschrock intval) != 0) { 631 2676 eschrock (void) fprintf(stderr, gettext("internal " 632 2676 eschrock "error: out of memory\n")); 633 2676 eschrock goto error; 634 2676 eschrock } 635 2676 eschrock volsize = intval; 636 4490 vb160487 break; 637 4490 vb160487 case 'p': 638 4490 vb160487 parents = B_TRUE; 639 789 ahrens break; 640 789 ahrens case 'b': 641 5367 ahrens bflag = B_TRUE; 642 2676 eschrock if (zfs_nicestrtonum(g_zfs, optarg, &intval) != 0) { 643 2676 eschrock (void) fprintf(stderr, gettext("bad volume " 644 2676 eschrock "block size '%s': %s\n"), optarg, 645 2676 eschrock libzfs_error_description(g_zfs)); 646 2676 eschrock goto error; 647 2676 eschrock } 648 2676 eschrock 649 2676 eschrock if (nvlist_add_uint64(props, 650 2676 eschrock zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 651 2676 eschrock intval) != 0) { 652 2676 eschrock (void) fprintf(stderr, gettext("internal " 653 2676 eschrock "error: out of memory\n")); 654 2676 eschrock goto error; 655 2676 eschrock } 656 2676 eschrock break; 657 2676 eschrock case 'o': 658 7265 ahrens if (parseprop(props)) 659 7265 ahrens goto error; 660 789 ahrens break; 661 789 ahrens case 's': 662 2082 eschrock noreserve = B_TRUE; 663 789 ahrens break; 664 789 ahrens case ':': 665 789 ahrens (void) fprintf(stderr, gettext("missing size " 666 789 ahrens "argument\n")); 667 2676 eschrock goto badusage; 668 789 ahrens break; 669 789 ahrens case '?': 670 789 ahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 671 789 ahrens optopt); 672 2676 eschrock goto badusage; 673 789 ahrens } 674 789 ahrens } 675 789 ahrens 676 5367 ahrens if ((bflag || noreserve) && type != ZFS_TYPE_VOLUME) { 677 5367 ahrens (void) fprintf(stderr, gettext("'-s' and '-b' can only be " 678 5367 ahrens "used when creating a volume\n")); 679 2676 eschrock goto badusage; 680 789 ahrens } 681 789 ahrens 682 789 ahrens argc -= optind; 683 789 ahrens argv += optind; 684 789 ahrens 685 789 ahrens /* check number of arguments */ 686 789 ahrens if (argc == 0) { 687 789 ahrens (void) fprintf(stderr, gettext("missing %s argument\n"), 688 789 ahrens zfs_type_to_name(type)); 689 2676 eschrock goto badusage; 690 789 ahrens } 691 789 ahrens if (argc > 1) { 692 789 ahrens (void) fprintf(stderr, gettext("too many arguments\n")); 693 2676 eschrock goto badusage; 694 2676 eschrock } 695 2676 eschrock 696 5481 ck153898 if (type == ZFS_TYPE_VOLUME && !noreserve) { 697 5481 ck153898 zpool_handle_t *zpool_handle; 698 5481 ck153898 uint64_t spa_version; 699 5481 ck153898 char *p; 700 5481 ck153898 zfs_prop_t resv_prop; 701 7265 ahrens char *strval; 702 5481 ck153898 703 5481 ck153898 if (p = strchr(argv[0], '/')) 704 5481 ck153898 *p = '\0'; 705 5481 ck153898 zpool_handle = zpool_open(g_zfs, argv[0]); 706 5481 ck153898 if (p != NULL) 707 5481 ck153898 *p = '/'; 708 5481 ck153898 if (zpool_handle == NULL) 709 5481 ck153898 goto error; 710 5481 ck153898 spa_version = zpool_get_prop_int(zpool_handle, 711 5481 ck153898 ZPOOL_PROP_VERSION, NULL); 712 5481 ck153898 zpool_close(zpool_handle); 713 5481 ck153898 if (spa_version >= SPA_VERSION_REFRESERVATION) 714 5481 ck153898 resv_prop = ZFS_PROP_REFRESERVATION; 715 5481 ck153898 else 716 5481 ck153898 resv_prop = ZFS_PROP_RESERVATION; 717 5481 ck153898 718 5481 ck153898 if (nvlist_lookup_string(props, zfs_prop_to_name(resv_prop), 719 5481 ck153898 &strval) != 0) { 720 5481 ck153898 if (nvlist_add_uint64(props, 721 5481 ck153898 zfs_prop_to_name(resv_prop), volsize) != 0) { 722 5481 ck153898 (void) fprintf(stderr, gettext("internal " 723 5481 ck153898 "error: out of memory\n")); 724 5481 ck153898 nvlist_free(props); 725 5481 ck153898 return (1); 726 5481 ck153898 } 727 2676 eschrock } 728 4490 vb160487 } 729 4490 vb160487 730 4490 vb160487 if (parents && zfs_name_valid(argv[0], type)) { 731 4490 vb160487 /* 732 4490 vb160487 * Now create the ancestors of target dataset. If the target 733 4490 vb160487 * already exists and '-p' option was used we should not 734 4490 vb160487 * complain. 735 4490 vb160487 */ 736 4490 vb160487 if (zfs_dataset_exists(g_zfs, argv[0], type)) { 737 4490 vb160487 ret = 0; 738 4490 vb160487 goto error; 739 4490 vb160487 } 740 4490 vb160487 if (zfs_create_ancestors(g_zfs, argv[0]) != 0) 741 4490 vb160487 goto error; 742 789 ahrens } 743 789 ahrens 744 789 ahrens /* pass to libzfs */ 745 2676 eschrock if (zfs_create(g_zfs, argv[0], type, props) != 0) 746 2676 eschrock goto error; 747 789 ahrens 748 5094 lling if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_DATASET)) == NULL) 749 2676 eschrock goto error; 750 6168 hs24103 /* 751 6168 hs24103 * if the user doesn't want the dataset automatically mounted, 752 6168 hs24103 * then skip the mount/share step 753 6168 hs24103 */ 754 6168 hs24103 755 6168 hs24103 canmount = zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT); 756 789 ahrens 757 789 ahrens /* 758 789 ahrens * Mount and/or share the new filesystem as appropriate. We provide a 759 789 ahrens * verbose error message to let the user know that their filesystem was 760 789 ahrens * in fact created, even if we failed to mount or share it. 761 789 ahrens */ 762 6168 hs24103 ret = 0; 763 6168 hs24103 if (canmount == ZFS_CANMOUNT_ON) { 764 6168 hs24103 if (zfs_mount(zhp, NULL, 0) != 0) { 765 6168 hs24103 (void) fprintf(stderr, gettext("filesystem " 766 6168 hs24103 "successfully created, but not mounted\n")); 767 6168 hs24103 ret = 1; 768 6168 hs24103 } else if (zfs_share(zhp) != 0) { 769 6168 hs24103 (void) fprintf(stderr, gettext("filesystem " 770 6168 hs24103 "successfully created, but not shared\n")); 771 6168 hs24103 ret = 1; 772 6168 hs24103 } 773 789 ahrens } 774 789 ahrens 775 2676 eschrock error: 776 2676 eschrock if (zhp) 777 2676 eschrock zfs_close(zhp); 778 2676 eschrock nvlist_free(props); 779 789 ahrens return (ret); 780 2676 eschrock badusage: 781 2676 eschrock nvlist_free(props); 782 2676 eschrock usage(B_FALSE); 783 2676 eschrock return (2); 784 789 ahrens } 785 789 ahrens 786 789 ahrens /* 787 10385 chris * zfs destroy [-rRf] <fs, vol> 788 10385 chris * zfs destroy [-rRd] <snap> 789 789 ahrens * 790 11022 Tom * -r Recursively destroy all children 791 11022 Tom * -R Recursively destroy all dependents, including clones 792 11022 Tom * -f Force unmounting of any dependents 793 10242 chris * -d If we can't destroy now, mark for deferred destruction 794 789 ahrens * 795 789 ahrens * Destroys the given dataset. By default, it will unmount any filesystems, 796 789 ahrens * and refuse to destroy a dataset that has any dependents. A dependent can 797 789 ahrens * either be a child, or a clone of a child. 798 789 ahrens */ 799 789 ahrens typedef struct destroy_cbdata { 800 2082 eschrock boolean_t cb_first; 801 789 ahrens int cb_force; 802 789 ahrens int cb_recurse; 803 789 ahrens int cb_error; 804 789 ahrens int cb_needforce; 805 789 ahrens int cb_doclones; 806 3265 ahrens boolean_t cb_closezhp; 807 789 ahrens zfs_handle_t *cb_target; 808 2199 ahrens char *cb_snapname; 809 10242 chris boolean_t cb_defer_destroy; 810 789 ahrens } destroy_cbdata_t; 811 789 ahrens 812 789 ahrens /* 813 789 ahrens * Check for any dependents based on the '-r' or '-R' flags. 814 789 ahrens */ 815 789 ahrens static int 816 789 ahrens destroy_check_dependent(zfs_handle_t *zhp, void *data) 817 789 ahrens { 818 789 ahrens destroy_cbdata_t *cbp = data; 819 789 ahrens const char *tname = zfs_get_name(cbp->cb_target); 820 789 ahrens const char *name = zfs_get_name(zhp); 821 789 ahrens 822 789 ahrens if (strncmp(tname, name, strlen(tname)) == 0 && 823 789 ahrens (name[strlen(tname)] == '/' || name[strlen(tname)] == '@')) { 824 789 ahrens /* 825 789 ahrens * This is a direct descendant, not a clone somewhere else in 826 789 ahrens * the hierarchy. 827 789 ahrens */ 828 789 ahrens if (cbp->cb_recurse) 829 789 ahrens goto out; 830 789 ahrens 831 789 ahrens if (cbp->cb_first) { 832 789 ahrens (void) fprintf(stderr, gettext("cannot destroy '%s': " 833 789 ahrens "%s has children\n"), 834 789 ahrens zfs_get_name(cbp->cb_target), 835 789 ahrens zfs_type_to_name(zfs_get_type(cbp->cb_target))); 836 789 ahrens (void) fprintf(stderr, gettext("use '-r' to destroy " 837 789 ahrens "the following datasets:\n")); 838 2082 eschrock cbp->cb_first = B_FALSE; 839 789 ahrens cbp->cb_error = 1; 840 789 ahrens } 841 789 ahrens 842 789 ahrens (void) fprintf(stderr, "%s\n", zfs_get_name(zhp)); 843 789 ahrens } else { 844 789 ahrens /* 845 789 ahrens * This is a clone. We only want to report this if the '-r' 846 789 ahrens * wasn't specified, or the target is a snapshot. 847 789 ahrens */ 848 789 ahrens if (!cbp->cb_recurse && 849 789 ahrens zfs_get_type(cbp->cb_target) != ZFS_TYPE_SNAPSHOT) 850 789 ahrens goto out; 851 789 ahrens 852 789 ahrens if (cbp->cb_first) { 853 789 ahrens (void) fprintf(stderr, gettext("cannot destroy '%s': " 854 789 ahrens "%s has dependent clones\n"), 855 789 ahrens zfs_get_name(cbp->cb_target), 856 789 ahrens zfs_type_to_name(zfs_get_type(cbp->cb_target))); 857 789 ahrens (void) fprintf(stderr, gettext("use '-R' to destroy " 858 789 ahrens "the following datasets:\n")); 859 2082 eschrock cbp->cb_first = B_FALSE; 860 789 ahrens cbp->cb_error = 1; 861 789 ahrens } 862 789 ahrens 863 789 ahrens (void) fprintf(stderr, "%s\n", zfs_get_name(zhp)); 864 789 ahrens } 865 789 ahrens 866 789 ahrens out: 867 789 ahrens zfs_close(zhp); 868 789 ahrens return (0); 869 789 ahrens } 870 789 ahrens 871 789 ahrens static int 872 789 ahrens destroy_callback(zfs_handle_t *zhp, void *data) 873 789 ahrens { 874 789 ahrens destroy_cbdata_t *cbp = data; 875 789 ahrens 876 789 ahrens /* 877 789 ahrens * Ignore pools (which we've already flagged as an error before getting 878 10588 Eric * here). 879 789 ahrens */ 880 789 ahrens if (strchr(zfs_get_name(zhp), '/') == NULL && 881 789 ahrens zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) { 882 789 ahrens zfs_close(zhp); 883 789 ahrens return (0); 884 789 ahrens } 885 789 ahrens 886 789 ahrens /* 887 789 ahrens * Bail out on the first error. 888 789 ahrens */ 889 789 ahrens if (zfs_unmount(zhp, NULL, cbp->cb_force ? MS_FORCE : 0) != 0 || 890 10242 chris zfs_destroy(zhp, cbp->cb_defer_destroy) != 0) { 891 789 ahrens zfs_close(zhp); 892 789 ahrens return (-1); 893 789 ahrens } 894 789 ahrens 895 789 ahrens zfs_close(zhp); 896 789 ahrens return (0); 897 789 ahrens } 898 789 ahrens 899 2199 ahrens static int 900 2199 ahrens destroy_snap_clones(zfs_handle_t *zhp, void *arg) 901 2199 ahrens { 902 2199 ahrens destroy_cbdata_t *cbp = arg; 903 2199 ahrens char thissnap[MAXPATHLEN]; 904 2199 ahrens zfs_handle_t *szhp; 905 3265 ahrens boolean_t closezhp = cbp->cb_closezhp; 906 3265 ahrens int rv; 907 2199 ahrens 908 2199 ahrens (void) snprintf(thissnap, sizeof (thissnap), 909 2199 ahrens "%s@%s", zfs_get_name(zhp), cbp->cb_snapname); 910 2199 ahrens 911 2199 ahrens libzfs_print_on_error(g_zfs, B_FALSE); 912 2199 ahrens szhp = zfs_open(g_zfs, thissnap, ZFS_TYPE_SNAPSHOT); 913 2199 ahrens libzfs_print_on_error(g_zfs, B_TRUE); 914 2199 ahrens if (szhp) { 915 2199 ahrens /* 916 2199 ahrens * Destroy any clones of this snapshot 917 2199 ahrens */ 918 2474 eschrock if (zfs_iter_dependents(szhp, B_FALSE, destroy_callback, 919 2474 eschrock cbp) != 0) { 920 2474 eschrock zfs_close(szhp); 921 3265 ahrens if (closezhp) 922 3265 ahrens zfs_close(zhp); 923 2474 eschrock return (-1); 924 2474 eschrock } 925 2199 ahrens zfs_close(szhp); 926 2199 ahrens } 927 2199 ahrens 928 3265 ahrens cbp->cb_closezhp = B_TRUE; 929 3265 ahrens rv = zfs_iter_filesystems(zhp, destroy_snap_clones, arg); 930 3265 ahrens if (closezhp) 931 3265 ahrens zfs_close(zhp); 932 3265 ahrens return (rv); 933 2199 ahrens } 934 789 ahrens 935 789 ahrens static int 936 789 ahrens zfs_do_destroy(int argc, char **argv) 937 789 ahrens { 938 789 ahrens destroy_cbdata_t cb = { 0 }; 939 789 ahrens int c; 940 789 ahrens zfs_handle_t *zhp; 941 2199 ahrens char *cp; 942 10385 chris zfs_type_t type = ZFS_TYPE_DATASET; 943 789 ahrens 944 789 ahrens /* check options */ 945 10242 chris while ((c = getopt(argc, argv, "dfrR")) != -1) { 946 10242 chris switch (c) { 947 10242 chris case 'd': 948 10242 chris cb.cb_defer_destroy = B_TRUE; 949 10385 chris type = ZFS_TYPE_SNAPSHOT; 950 10242 chris break; 951 789 ahrens case 'f': 952 789 ahrens cb.cb_force = 1; 953 789 ahrens break; 954 789 ahrens case 'r': 955 789 ahrens cb.cb_recurse = 1; 956 789 ahrens break; 957 789 ahrens case 'R': 958 789 ahrens cb.cb_recurse = 1; 959 789 ahrens cb.cb_doclones = 1; 960 789 ahrens break; 961 789 ahrens case '?': 962 789 ahrens default: 963 789 ahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 964 789 ahrens optopt); 965 2082 eschrock usage(B_FALSE); 966 789 ahrens } 967 789 ahrens } 968 789 ahrens 969 789 ahrens argc -= optind; 970 789 ahrens argv += optind; 971 789 ahrens 972 789 ahrens /* check number of arguments */ 973 789 ahrens if (argc == 0) { 974 789 ahrens (void) fprintf(stderr, gettext("missing path argument\n")); 975 2082 eschrock usage(B_FALSE); 976 789 ahrens } 977 789 ahrens if (argc > 1) { 978 789 ahrens (void) fprintf(stderr, gettext("too many arguments\n")); 979 2082 eschrock usage(B_FALSE); 980 789 ahrens } 981 10242 chris 982 2199 ahrens /* 983 2199 ahrens * If we are doing recursive destroy of a snapshot, then the 984 2199 ahrens * named snapshot may not exist. Go straight to libzfs. 985 2199 ahrens */ 986 2199 ahrens if (cb.cb_recurse && (cp = strchr(argv[0], '@'))) { 987 2199 ahrens int ret; 988 2199 ahrens 989 2199 ahrens *cp = '\0'; 990 5094 lling if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_DATASET)) == NULL) 991 2199 ahrens return (1); 992 2199 ahrens *cp = '@'; 993 2199 ahrens cp++; 994 2199 ahrens 995 2199 ahrens if (cb.cb_doclones) { 996 10385 chris boolean_t defer = cb.cb_defer_destroy; 997 10385 chris 998 10385 chris /* 999 10385 chris * Temporarily ignore the defer_destroy setting since 1000 10385 chris * it's not supported for clones. 1001 10385 chris */ 1002 10385 chris cb.cb_defer_destroy = B_FALSE; 1003 2199 ahrens cb.cb_snapname = cp; 1004 2474 eschrock if (destroy_snap_clones(zhp, &cb) != 0) { 1005 2474 eschrock zfs_close(zhp); 1006 2474 eschrock return (1); 1007 2474 eschrock } 1008 10385 chris cb.cb_defer_destroy = defer; 1009 2199 ahrens } 1010 2199 ahrens 1011 10242 chris ret = zfs_destroy_snaps(zhp, cp, cb.cb_defer_destroy); 1012 2199 ahrens zfs_close(zhp); 1013 2199 ahrens if (ret) { 1014 2199 ahrens (void) fprintf(stderr, 1015 2199 ahrens gettext("no snapshots destroyed\n")); 1016 2199 ahrens } 1017 2199 ahrens return (ret != 0); 1018 2199 ahrens } 1019 2199 ahrens 1020 789 ahrens /* Open the given dataset */ 1021 10385 chris if ((zhp = zfs_open(g_zfs, argv[0], type)) == NULL) 1022 789 ahrens return (1); 1023 789 ahrens 1024 789 ahrens cb.cb_target = zhp; 1025 789 ahrens 1026 789 ahrens /* 1027 789 ahrens * Perform an explicit check for pools before going any further. 1028 789 ahrens */ 1029 789 ahrens if (!cb.cb_recurse && strchr(zfs_get_name(zhp), '/') == NULL && 1030 789 ahrens zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) { 1031 789 ahrens (void) fprintf(stderr, gettext("cannot destroy '%s': " 1032 789 ahrens "operation does not apply to pools\n"), 1033 789 ahrens zfs_get_name(zhp)); 1034 789 ahrens (void) fprintf(stderr, gettext("use 'zfs destroy -r " 1035 789 ahrens "%s' to destroy all datasets in the pool\n"), 1036 789 ahrens zfs_get_name(zhp)); 1037 789 ahrens (void) fprintf(stderr, gettext("use 'zpool destroy %s' " 1038 789 ahrens "to destroy the pool itself\n"), zfs_get_name(zhp)); 1039 789 ahrens zfs_close(zhp); 1040 789 ahrens return (1); 1041 789 ahrens } 1042 789 ahrens 1043 789 ahrens /* 1044 789 ahrens * Check for any dependents and/or clones. 1045 789 ahrens */ 1046 2082 eschrock cb.cb_first = B_TRUE; 1047 10242 chris if (!cb.cb_doclones && !cb.cb_defer_destroy && 1048 2474 eschrock zfs_iter_dependents(zhp, B_TRUE, destroy_check_dependent, 1049 2474 eschrock &cb) != 0) { 1050 2474 eschrock zfs_close(zhp); 1051 2474 eschrock return (1); 1052 2474 eschrock } 1053 789 ahrens 1054 10242 chris if (cb.cb_error || (!cb.cb_defer_destroy && 1055 10242 chris (zfs_iter_dependents(zhp, B_FALSE, destroy_callback, &cb) != 0))) { 1056 789 ahrens zfs_close(zhp); 1057 789 ahrens return (1); 1058 789 ahrens } 1059 789 ahrens 1060 789 ahrens /* 1061 2474 eschrock * Do the real thing. The callback will close the handle regardless of 1062 2474 eschrock * whether it succeeds or not. 1063 789 ahrens */ 1064 4543 marks 1065 2474 eschrock if (destroy_callback(zhp, &cb) != 0) 1066 2474 eschrock return (1); 1067 789 ahrens 1068 2474 eschrock return (0); 1069 789 ahrens } 1070 789 ahrens 1071 11022 Tom static boolean_t 1072 11022 Tom is_recvd_column(zprop_get_cbdata_t *cbp) 1073 11022 Tom { 1074 11022 Tom int i; 1075 11022 Tom zfs_get_column_t col; 1076 11022 Tom 1077 11022 Tom for (i = 0; i < ZFS_GET_NCOLS && 1078 11022 Tom (col = cbp->cb_columns[i]) != GET_COL_NONE; i++) 1079 11022 Tom if (col == GET_COL_RECVD) 1080 11022 Tom return (B_TRUE); 1081 11022 Tom return (B_FALSE); 1082 11022 Tom } 1083 11022 Tom 1084 11022 Tom /* 1085 11022 Tom * zfs get [-rHp] [-o all | field[,field]...] [-s source[,source]...] 1086 11022 Tom * < all | property[,property]... > < fs | snap | vol > ... 1087 789 ahrens * 1088 789 ahrens * -r recurse over any child datasets 1089 789 ahrens * -H scripted mode. Headers are stripped, and fields are separated 1090 789 ahrens * by tabs instead of spaces. 1091 11022 Tom * -o Set of fields to display. One of "name,property,value, 1092 11022 Tom * received,source". Default is "name,property,value,source". 1093 11022 Tom * "all" is an alias for all five. 1094 789 ahrens * -s Set of sources to allow. One of 1095 11022 Tom * "local,default,inherited,received,temporary,none". Default is 1096 11022 Tom * all six. 1097 789 ahrens * -p Display values in parsable (literal) format. 1098 789 ahrens * 1099 789 ahrens * Prints properties for the given datasets. The user can control which 1100 789 ahrens * columns to display as well as which property types to allow. 1101 789 ahrens */ 1102 789 ahrens 1103 789 ahrens /* 1104 789 ahrens * Invoked to display the properties for a single dataset. 1105 789 ahrens */ 1106 789 ahrens static int 1107 789 ahrens get_callback(zfs_handle_t *zhp, void *data) 1108 789 ahrens { 1109 789 ahrens char buf[ZFS_MAXPROPLEN]; 1110 11022 Tom char rbuf[ZFS_MAXPROPLEN]; 1111 5094 lling zprop_source_t sourcetype; 1112 789 ahrens char source[ZFS_MAXNAMELEN]; 1113 5094 lling zprop_get_cbdata_t *cbp = data; 1114 11022 Tom nvlist_t *user_props = zfs_get_user_props(zhp); 1115 5094 lling zprop_list_t *pl = cbp->cb_proplist; 1116 2676 eschrock nvlist_t *propval; 1117 2676 eschrock char *strval; 1118 2676 eschrock char *sourceval; 1119 11022 Tom boolean_t received = is_recvd_column(cbp); 1120 789 ahrens 1121 2676 eschrock for (; pl != NULL; pl = pl->pl_next) { 1122 11022 Tom char *recvdval = NULL; 1123 2676 eschrock /* 1124 2676 eschrock * Skip the special fake placeholder. This will also skip over 1125 2676 eschrock * the name property when 'all' is specified. 1126 2676 eschrock */ 1127 2676 eschrock if (pl->pl_prop == ZFS_PROP_NAME && 1128 2676 eschrock pl == cbp->cb_proplist) 1129 2676 eschrock continue; 1130 2676 eschrock 1131 5094 lling if (pl->pl_prop != ZPROP_INVAL) { 1132 2676 eschrock if (zfs_prop_get(zhp, pl->pl_prop, buf, 1133 2676 eschrock sizeof (buf), &sourcetype, source, 1134 2676 eschrock sizeof (source), 1135 2676 eschrock cbp->cb_literal) != 0) { 1136 2676 eschrock if (pl->pl_all) 1137 2676 eschrock continue; 1138 3912 lling if (!zfs_prop_valid_for_type(pl->pl_prop, 1139 5094 lling ZFS_TYPE_DATASET)) { 1140 3912 lling (void) fprintf(stderr, 1141 3912 lling gettext("No such property '%s'\n"), 1142 3912 lling zfs_prop_to_name(pl->pl_prop)); 1143 3912 lling continue; 1144 3912 lling } 1145 5094 lling sourcetype = ZPROP_SRC_NONE; 1146 2676 eschrock (void) strlcpy(buf, "-", sizeof (buf)); 1147 2676 eschrock } 1148 2676 eschrock 1149 11022 Tom if (received && (zfs_prop_get_recvd(zhp, 1150 11022 Tom zfs_prop_to_name(pl->pl_prop), rbuf, sizeof (rbuf), 1151 11022 Tom cbp->cb_literal) == 0)) 1152 11022 Tom recvdval = rbuf; 1153 11022 Tom 1154 5094 lling zprop_print_one_property(zfs_get_name(zhp), cbp, 1155 2676 eschrock zfs_prop_to_name(pl->pl_prop), 1156 11022 Tom buf, sourcetype, source, recvdval); 1157 9396 Matthew } else if (zfs_prop_userquota(pl->pl_user_prop)) { 1158 9396 Matthew sourcetype = ZPROP_SRC_LOCAL; 1159 9396 Matthew 1160 9396 Matthew if (zfs_prop_get_userquota(zhp, pl->pl_user_prop, 1161 9396 Matthew buf, sizeof (buf), cbp->cb_literal) != 0) { 1162 9396 Matthew sourcetype = ZPROP_SRC_NONE; 1163 9396 Matthew (void) strlcpy(buf, "-", sizeof (buf)); 1164 9396 Matthew } 1165 9396 Matthew 1166 9396 Matthew zprop_print_one_property(zfs_get_name(zhp), cbp, 1167 11022 Tom pl->pl_user_prop, buf, sourcetype, source, NULL); 1168 11022 Tom } else { 1169 11022 Tom if (nvlist_lookup_nvlist(user_props, 1170 2676 eschrock pl->pl_user_prop, &propval) != 0) { 1171 2676 eschrock if (pl->pl_all) 1172 2676 eschrock continue; 1173 5094 lling sourcetype = ZPROP_SRC_NONE; 1174 2676 eschrock strval = "-"; 1175 2676 eschrock } else { 1176 2676 eschrock verify(nvlist_lookup_string(propval, 1177 5094 lling ZPROP_VALUE, &strval) == 0); 1178 2676 eschrock verify(nvlist_lookup_string(propval, 1179 5094 lling ZPROP_SOURCE, &sourceval) == 0); 1180 2676 eschrock 1181 2676 eschrock if (strcmp(sourceval, 1182 2676 eschrock zfs_get_name(zhp)) == 0) { 1183 5094 lling sourcetype = ZPROP_SRC_LOCAL; 1184 11022 Tom } else if (strcmp(sourceval, 1185 11022 Tom ZPROP_SOURCE_VAL_RECVD) == 0) { 1186 11022 Tom sourcetype = ZPROP_SRC_RECEIVED; 1187 2676 eschrock } else { 1188 5094 lling sourcetype = ZPROP_SRC_INHERITED; 1189 2676 eschrock (void) strlcpy(source, 1190 2676 eschrock sourceval, sizeof (source)); 1191 2676 eschrock } 1192 2676 eschrock } 1193 2676 eschrock 1194 11022 Tom if (received && (zfs_prop_get_recvd(zhp, 1195 11022 Tom pl->pl_user_prop, rbuf, sizeof (rbuf), 1196 11022 Tom cbp->cb_literal) == 0)) 1197 11022 Tom recvdval = rbuf; 1198 11022 Tom 1199 5094 lling zprop_print_one_property(zfs_get_name(zhp), cbp, 1200 2676 eschrock pl->pl_user_prop, strval, sourcetype, 1201 11022 Tom source, recvdval); 1202 866 eschrock } 1203 789 ahrens } 1204 789 ahrens 1205 789 ahrens return (0); 1206 789 ahrens } 1207 789 ahrens 1208 789 ahrens static int 1209 789 ahrens zfs_do_get(int argc, char **argv) 1210 789 ahrens { 1211 5094 lling zprop_get_cbdata_t cb = { 0 }; 1212 7538 Richard int i, c, flags = 0; 1213 2676 eschrock char *value, *fields; 1214 866 eschrock int ret; 1215 9365 Chris int limit = 0; 1216 5094 lling zprop_list_t fake_name = { 0 }; 1217 789 ahrens 1218 789 ahrens /* 1219 789 ahrens * Set up default columns and sources. 1220 789 ahrens */ 1221 5094 lling cb.cb_sources = ZPROP_SRC_ALL; 1222 789 ahrens cb.cb_columns[0] = GET_COL_NAME; 1223 789 ahrens cb.cb_columns[1] = GET_COL_PROPERTY; 1224 789 ahrens cb.cb_columns[2] = GET_COL_VALUE; 1225 789 ahrens cb.cb_columns[3] = GET_COL_SOURCE; 1226 5094 lling cb.cb_type = ZFS_TYPE_DATASET; 1227 789 ahrens 1228 789 ahrens /* check options */ 1229 9365 Chris while ((c = getopt(argc, argv, ":d:o:s:rHp")) != -1) { 1230 789 ahrens switch (c) { 1231 789 ahrens case 'p': 1232 2082 eschrock cb.cb_literal = B_TRUE; 1233 9365 Chris break; 1234 9365 Chris case 'd': 1235 9365 Chris limit = parse_depth(optarg, &flags); 1236 789 ahrens break; 1237 789 ahrens case 'r': 1238 7538 Richard flags |= ZFS_ITER_RECURSE; 1239 789 ahrens break; 1240 789 ahrens case 'H': 1241 2082 eschrock cb.cb_scripted = B_TRUE; 1242 789 ahrens break; 1243 789 ahrens case ':': 1244 789 ahrens (void) fprintf(stderr, gettext("missing argument for " 1245 789 ahrens "'%c' option\n"), optopt); 1246 2082 eschrock usage(B_FALSE); 1247 789 ahrens break; 1248 789 ahrens case 'o': 1249 789 ahrens /* 1250 789 ahrens * Process the set of columns to display. We zero out 1251 789 ahrens * the structure to give us a blank slate. 1252 789 ahrens */ 1253 789 ahrens bzero(&cb.cb_columns, sizeof (cb.cb_columns)); 1254 789 ahrens i = 0; 1255 789 ahrens while (*optarg != '\0') { 1256 789 ahrens static char *col_subopts[] = 1257 11022 Tom { "name", "property", "value", "received", 1258 11022 Tom "source", "all", NULL }; 1259 11022 Tom 1260 11022 Tom if (i == ZFS_GET_NCOLS) { 1261 789 ahrens (void) fprintf(stderr, gettext("too " 1262 789 ahrens "many fields given to -o " 1263 789 ahrens "option\n")); 1264 2082 eschrock usage(B_FALSE); 1265 789 ahrens } 1266 789 ahrens 1267 789 ahrens switch (getsubopt(&optarg, col_subopts, 1268 789 ahrens &value)) { 1269 789 ahrens case 0: 1270 789 ahrens cb.cb_columns[i++] = GET_COL_NAME; 1271 789 ahrens break; 1272 789 ahrens case 1: 1273 789 ahrens cb.cb_columns[i++] = GET_COL_PROPERTY; 1274 789 ahrens break; 1275 789 ahrens case 2: 1276 789 ahrens cb.cb_columns[i++] = GET_COL_VALUE; 1277 789 ahrens break; 1278 789 ahrens case 3: 1279 11022 Tom cb.cb_columns[i++] = GET_COL_RECVD; 1280 11022 Tom flags |= ZFS_ITER_RECVD_PROPS; 1281 11022 Tom break; 1282 11022 Tom case 4: 1283 789 ahrens cb.cb_columns[i++] = GET_COL_SOURCE; 1284 11022 Tom break; 1285 11022 Tom case 5: 1286 11022 Tom if (i > 0) { 1287 11022 Tom (void) fprintf(stderr, 1288 11022 Tom gettext("\"all\" conflicts " 1289 11022 Tom "with specific fields " 1290 11022 Tom "given to -o option\n")); 1291 11022 Tom usage(B_FALSE); 1292 11022 Tom } 1293 11022 Tom cb.cb_columns[0] = GET_COL_NAME; 1294 11022 Tom cb.cb_columns[1] = GET_COL_PROPERTY; 1295 11022 Tom cb.cb_columns[2] = GET_COL_VALUE; 1296 11022 Tom cb.cb_columns[3] = GET_COL_RECVD; 1297 11022 Tom cb.cb_columns[4] = GET_COL_SOURCE; 1298 11022 Tom flags |= ZFS_ITER_RECVD_PROPS; 1299 11022 Tom i = ZFS_GET_NCOLS; 1300 789 ahrens break; 1301 789 ahrens default: 1302 789 ahrens (void) fprintf(stderr, 1303 789 ahrens gettext("invalid column name " 1304 789 ahrens "'%s'\n"), value); 1305 3912 lling usage(B_FALSE); 1306 789 ahrens } 1307 789 ahrens } 1308 789 ahrens break; 1309 789 ahrens 1310 789 ahrens case 's': 1311 789 ahrens cb.cb_sources = 0; 1312 789 ahrens while (*optarg != '\0') { 1313 789 ahrens static char *source_subopts[] = { 1314 789 ahrens "local", "default", "inherited", 1315 11022 Tom "received", "temporary", "none", 1316 11022 Tom NULL }; 1317 789 ahrens 1318 789 ahrens switch (getsubopt(&optarg, source_subopts, 1319 789 ahrens &value)) { 1320 789 ahrens case 0: 1321 5094 lling cb.cb_sources |= ZPROP_SRC_LOCAL; 1322 789 ahrens break; 1323 789 ahrens case 1: 1324 5094 lling cb.cb_sources |= ZPROP_SRC_DEFAULT; 1325 789 ahrens break; 1326 789 ahrens case 2: 1327 5094 lling cb.cb_sources |= ZPROP_SRC_INHERITED; 1328 789 ahrens break; 1329 789 ahrens case 3: 1330 11022 Tom cb.cb_sources |= ZPROP_SRC_RECEIVED; 1331 11022 Tom break; 1332 11022 Tom case 4: 1333 5094 lling cb.cb_sources |= ZPROP_SRC_TEMPORARY; 1334 789 ahrens break; 1335 11022 Tom case 5: 1336 5094 lling cb.cb_sources |= ZPROP_SRC_NONE; 1337 789 ahrens break; 1338 789 ahrens default: 1339 789 ahrens (void) fprintf(stderr, 1340 789 ahrens gettext("invalid source " 1341 789 ahrens "'%s'\n"), value); 1342 3912 lling usage(B_FALSE); 1343 789 ahrens } 1344 789 ahrens } 1345 789 ahrens break; 1346 789 ahrens 1347 789 ahrens case '?': 1348 789 ahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1349 789 ahrens optopt); 1350 2082 eschrock usage(B_FALSE); 1351 789 ahrens } 1352 789 ahrens } 1353 789 ahrens 1354 789 ahrens argc -= optind; 1355 789 ahrens argv += optind; 1356 789 ahrens 1357 789 ahrens if (argc < 1) { 1358 789 ahrens (void) fprintf(stderr, gettext("missing property " 1359 789 ahrens "argument\n")); 1360 2082 eschrock usage(B_FALSE); 1361 789 ahrens } 1362 789 ahrens 1363 789 ahrens fields = argv[0]; 1364 789 ahrens 1365 5094 lling if (zprop_get_list(g_zfs, fields, &cb.cb_proplist, ZFS_TYPE_DATASET) 1366 5094 lling != 0) 1367 2082 eschrock usage(B_FALSE); 1368 789 ahrens 1369 789 ahrens argc--; 1370 789 ahrens argv++; 1371 789 ahrens 1372 2676 eschrock /* 1373 2676 eschrock * As part of zfs_expand_proplist(), we keep track of the maximum column 1374 2676 eschrock * width for each property. For the 'NAME' (and 'SOURCE') columns, we 1375 2676 eschrock * need to know the maximum name length. However, the user likely did 1376 2676 eschrock * not specify 'name' as one of the properties to fetch, so we need to 1377 2676 eschrock * make sure we always include at least this property for 1378 2676 eschrock * print_get_headers() to work properly. 1379 2676 eschrock */ 1380 2676 eschrock if (cb.cb_proplist != NULL) { 1381 2676 eschrock fake_name.pl_prop = ZFS_PROP_NAME; 1382 2676 eschrock fake_name.pl_width = strlen(gettext("NAME")); 1383 2676 eschrock fake_name.pl_next = cb.cb_proplist; 1384 2676 eschrock cb.cb_proplist = &fake_name; 1385 789 ahrens } 1386 789 ahrens 1387 2676 eschrock cb.cb_first = B_TRUE; 1388 789 ahrens 1389 789 ahrens /* run for each object */ 1390 7538 Richard ret = zfs_for_each(argc, argv, flags, ZFS_TYPE_DATASET, NULL, 1391 9365 Chris &cb.cb_proplist, limit, get_callback, &cb); 1392 2379 sjelinek 1393 2676 eschrock if (cb.cb_proplist == &fake_name) 1394 5094 lling zprop_free_list(fake_name.pl_next); 1395 2676 eschrock else 1396 5094 lling zprop_free_list(cb.cb_proplist); 1397 2676 eschrock 1398 2676 eschrock return (ret); 1399 789 ahrens } 1400 789 ahrens 1401 789 ahrens /* 1402 11022 Tom * inherit [-rS] <property> <fs|vol> ... 1403 11022 Tom * 1404 11022 Tom * -r Recurse over all children 1405 11022 Tom * -S Revert to received value, if any 1406 789 ahrens * 1407 789 ahrens * For each dataset specified on the command line, inherit the given property 1408 789 ahrens * from its parent. Inheriting a property at the pool level will cause it to 1409 789 ahrens * use the default value. The '-r' flag will recurse over all children, and is 1410 789 ahrens * useful for setting a property on a hierarchy-wide basis, regardless of any 1411 789 ahrens * local modifications for each dataset. 1412 789 ahrens */ 1413 2926 ek110237 1414 11022 Tom typedef struct inherit_cbdata { 1415 11022 Tom const char *cb_propname; 1416 11022 Tom boolean_t cb_received; 1417 11022 Tom } inherit_cbdata_t; 1418 11022 Tom 1419 789 ahrens static int 1420 7265 ahrens inherit_recurse_cb(zfs_handle_t *zhp, void *data) 1421 789 ahrens { 1422 11022 Tom inherit_cbdata_t *cb = data; 1423 11022 Tom zfs_prop_t prop = zfs_name_to_prop(cb->cb_propname); 1424 7265 ahrens 1425 7265 ahrens /* 1426 7265 ahrens * If we're doing it recursively, then ignore properties that 1427 7265 ahrens * are not valid for this type of dataset. 1428 7265 ahrens */ 1429 7265 ahrens if (prop != ZPROP_INVAL && 1430 7265 ahrens !zfs_prop_valid_for_type(prop, zfs_get_type(zhp))) 1431 7265 ahrens return (0); 1432 7265 ahrens 1433 11022 Tom return (zfs_prop_inherit(zhp, cb->cb_propname, cb->cb_received) != 0); 1434 7265 ahrens } 1435 7265 ahrens 1436 7265 ahrens static int 1437 7265 ahrens inherit_cb(zfs_handle_t *zhp, void *data) 1438 7265 ahrens { 1439 11022 Tom inherit_cbdata_t *cb = data; 1440 11022 Tom 1441 11022 Tom return (zfs_prop_inherit(zhp, cb->cb_propname, cb->cb_received) != 0); 1442 789 ahrens } 1443 789 ahrens 1444 789 ahrens static int 1445 789 ahrens zfs_do_inherit(int argc, char **argv) 1446 789 ahrens { 1447 789 ahrens int c; 1448 789 ahrens zfs_prop_t prop; 1449 11022 Tom inherit_cbdata_t cb = { 0 }; 1450 4543 marks char *propname; 1451 2926 ek110237 int ret; 1452 7538 Richard int flags = 0; 1453 11022 Tom boolean_t received = B_FALSE; 1454 11022 Tom 1455 11022 Tom /* check options */ 1456 11022 Tom while ((c = getopt(argc, argv, "rS")) != -1) { 1457 789 ahrens switch (c) { 1458 789 ahrens case 'r': 1459 7538 Richard flags |= ZFS_ITER_RECURSE; 1460 11022 Tom break; 1461 11022 Tom case 'S': 1462 11022 Tom received = B_TRUE; 1463 789 ahrens break; 1464 789 ahrens case '?': 1465 789 ahrens default: 1466 789 ahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1467 789 ahrens optopt); 1468 2082 eschrock usage(B_FALSE); 1469 789 ahrens } 1470 789 ahrens } 1471 789 ahrens 1472 789 ahrens argc -= optind; 1473 789 ahrens argv += optind; 1474 789 ahrens 1475 789 ahrens /* check number of arguments */ 1476 789 ahrens if (argc < 1) { 1477 789 ahrens (void) fprintf(stderr, gettext("missing property argument\n")); 1478 2082 eschrock usage(B_FALSE); 1479 789 ahrens } 1480 789 ahrens if (argc < 2) { 1481 789 ahrens (void) fprintf(stderr, gettext("missing dataset argument\n")); 1482 2082 eschrock usage(B_FALSE); 1483 789 ahrens } 1484 789 ahrens 1485 4543 marks propname = argv[0]; 1486 2676 eschrock argc--; 1487 2676 eschrock argv++; 1488 789 ahrens 1489 5094 lling if ((prop = zfs_name_to_prop(propname)) != ZPROP_INVAL) { 1490 2676 eschrock if (zfs_prop_readonly(prop)) { 1491 2676 eschrock (void) fprintf(stderr, gettext( 1492 2676 eschrock "%s property is read-only\n"), 1493 4543 marks propname); 1494 2676 eschrock return (1); 1495 2676 eschrock } 1496 11022 Tom if (!zfs_prop_inheritable(prop) && !received) { 1497 2676 eschrock (void) fprintf(stderr, gettext("'%s' property cannot " 1498 4543 marks "be inherited\n"), propname); 1499 2676 eschrock if (prop == ZFS_PROP_QUOTA || 1500 5378 ck153898 prop == ZFS_PROP_RESERVATION || 1501 5378 ck153898 prop == ZFS_PROP_REFQUOTA || 1502 5378 ck153898 prop == ZFS_PROP_REFRESERVATION) 1503 2676 eschrock (void) fprintf(stderr, gettext("use 'zfs set " 1504 4543 marks "%s=none' to clear\n"), propname); 1505 2676 eschrock return (1); 1506 2676 eschrock } 1507 4543 marks } else if (!zfs_prop_user(propname)) { 1508 4543 marks (void) fprintf(stderr, gettext("invalid property '%s'\n"), 1509 4543 marks propname); 1510 2082 eschrock usage(B_FALSE); 1511 789 ahrens } 1512 789 ahrens 1513 11022 Tom cb.cb_propname = propname; 1514 11022 Tom cb.cb_received = received; 1515 11022 Tom 1516 7538 Richard if (flags & ZFS_ITER_RECURSE) { 1517 7538 Richard ret = zfs_for_each(argc, argv, flags, ZFS_TYPE_DATASET, 1518 11022 Tom NULL, NULL, 0, inherit_recurse_cb, &cb); 1519 7538 Richard } else { 1520 7538 Richard ret = zfs_for_each(argc, argv, flags, ZFS_TYPE_DATASET, 1521 11022 Tom NULL, NULL, 0, inherit_cb, &cb); 1522 7265 ahrens } 1523 4577 ahrens 1524 4577 ahrens return (ret); 1525 4577 ahrens } 1526 4577 ahrens 1527 4577 ahrens typedef struct upgrade_cbdata { 1528 4577 ahrens uint64_t cb_numupgraded; 1529 4577 ahrens uint64_t cb_numsamegraded; 1530 4849 ahrens uint64_t cb_numfailed; 1531 4577 ahrens uint64_t cb_version; 1532 4577 ahrens boolean_t cb_newer; 1533 4577 ahrens boolean_t cb_foundone; 1534 4577 ahrens char cb_lastfs[ZFS_MAXNAMELEN]; 1535 4577 ahrens } upgrade_cbdata_t; 1536 4577 ahrens 1537 4577 ahrens static int 1538 4577 ahrens same_pool(zfs_handle_t *zhp, const char *name) 1539 4577 ahrens { 1540 4577 ahrens int len1 = strcspn(name, "/@"); 1541 4577 ahrens const char *zhname = zfs_get_name(zhp); 1542 4577 ahrens int len2 = strcspn(zhname, "/@"); 1543 4577 ahrens 1544 4577 ahrens if (len1 != len2) 1545 4577 ahrens return (B_FALSE); 1546 4988 ek110237 return (strncmp(name, zhname, len1) == 0); 1547 4577 ahrens } 1548 4577 ahrens 1549 4577 ahrens static int 1550 4577 ahrens upgrade_list_callback(zfs_handle_t *zhp, void *data) 1551 4577 ahrens { 1552 4577 ahrens upgrade_cbdata_t *cb = data; 1553 4577 ahrens int version = zfs_prop_get_int(zhp, ZFS_PROP_VERSION); 1554 4577 ahrens 1555 4577 ahrens /* list if it's old/new */ 1556 4577 ahrens if ((!cb->cb_newer && version < ZPL_VERSION) || 1557 5367 ahrens (cb->cb_newer && version > ZPL_VERSION)) { 1558 4577 ahrens char *str; 1559 4577 ahrens if (cb->cb_newer) { 1560 4577 ahrens str = gettext("The following filesystems are " 1561 4577 ahrens "formatted using a newer software version and\n" 1562 4577 ahrens "cannot be accessed on the current system.\n\n"); 1563 4577 ahrens } else { 1564 4577 ahrens str = gettext("The following filesystems are " 1565 4577 ahrens "out of date, and can be upgraded. After being\n" 1566 4577 ahrens "upgraded, these filesystems (and any 'zfs send' " 1567 4577 ahrens "streams generated from\n" 1568 4577 ahrens "subsequent snapshots) will no longer be " 1569 4577 ahrens "accessible by older software versions.\n\n"); 1570 4577 ahrens } 1571 4577 ahrens 1572 4577 ahrens if (!cb->cb_foundone) { 1573 4577 ahrens (void) puts(str); 1574 4577 ahrens (void) printf(gettext("VER FILESYSTEM\n")); 1575 4577 ahrens (void) printf(gettext("--- ------------\n")); 1576 4577 ahrens cb->cb_foundone = B_TRUE; 1577 4577 ahrens } 1578 4577 ahrens 1579 4577 ahrens (void) printf("%2u %s\n", version, zfs_get_name(zhp)); 1580 4577 ahrens } 1581 4577 ahrens 1582 4577 ahrens return (0); 1583 4577 ahrens } 1584 4577 ahrens 1585 4577 ahrens static int 1586 4577 ahrens upgrade_set_callback(zfs_handle_t *zhp, void *data) 1587 4577 ahrens { 1588 4577 ahrens upgrade_cbdata_t *cb = data; 1589 4577 ahrens int version = zfs_prop_get_int(zhp, ZFS_PROP_VERSION); 1590 9396 Matthew int i; 1591 9396 Matthew static struct { int zplver; int spaver; } table[] = { 1592 9396 Matthew {ZPL_VERSION_FUID, SPA_VERSION_FUID}, 1593 9396 Matthew {ZPL_VERSION_USERSPACE, SPA_VERSION_USERSPACE}, 1594 9396 Matthew {0, 0} 1595 9396 Matthew }; 1596 9396 Matthew 1597 9396 Matthew 1598 9396 Matthew for (i = 0; table[i].zplver; i++) { 1599 9396 Matthew if (cb->cb_version >= table[i].zplver) { 1600 9396 Matthew int spa_version; 1601 9396 Matthew 1602 9396 Matthew if (zfs_spa_version(zhp, &spa_version) < 0) 1603 9396 Matthew return (-1); 1604 9396 Matthew 1605 9396 Matthew if (spa_version < table[i].spaver) { 1606 9396 Matthew /* can't upgrade */ 1607 9396 Matthew (void) printf(gettext("%s: can not be " 1608 9396 Matthew "upgraded; the pool version needs to first " 1609 9396 Matthew "be upgraded\nto version %d\n\n"), 1610 9396 Matthew zfs_get_name(zhp), table[i].spaver); 1611 9396 Matthew cb->cb_numfailed++; 1612 9396 Matthew return (0); 1613 9396 Matthew } 1614 5331 amw } 1615 5331 amw } 1616 4577 ahrens 1617 4577 ahrens /* upgrade */ 1618 4577 ahrens if (version < cb->cb_version) { 1619 4577 ahrens char verstr[16]; 1620 4849 ahrens (void) snprintf(verstr, sizeof (verstr), 1621 4849 ahrens "%llu", cb->cb_version); 1622 4577 ahrens if (cb->cb_lastfs[0] && !same_pool(zhp, cb->cb_lastfs)) { 1623 4577 ahrens /* 1624 4577 ahrens * If they did "zfs upgrade -a", then we could 1625 4577 ahrens * be doing ioctls to different pools. We need 1626 4577 ahrens * to log this history once to each pool. 1627 4577 ahrens */ 1628 4988 ek110237 verify(zpool_stage_history(g_zfs, history_str) == 0); 1629 4577 ahrens } 1630 4577 ahrens if (zfs_prop_set(zhp, "version", verstr) == 0) 1631 4577 ahrens cb->cb_numupgraded++; 1632 4849 ahrens else 1633 4849 ahrens cb->cb_numfailed++; 1634 4577 ahrens (void) strcpy(cb->cb_lastfs, zfs_get_name(zhp)); 1635 4577 ahrens } else if (version > cb->cb_version) { 1636 4577 ahrens /* can't downgrade */ 1637 4577 ahrens (void) printf(gettext("%s: can not be downgraded; " 1638 4577 ahrens "it is already at version %u\n"), 1639 4577 ahrens zfs_get_name(zhp), version); 1640 4849 ahrens cb->cb_numfailed++; 1641 4577 ahrens } else { 1642 4577 ahrens cb->cb_numsamegraded++; 1643 4577 ahrens } 1644 4577 ahrens return (0); 1645 4577 ahrens } 1646 4577 ahrens 1647 4577 ahrens /* 1648 4577 ahrens * zfs upgrade 1649 4577 ahrens * zfs upgrade -v 1650 4577 ahrens * zfs upgrade [-r] [-V <version>] <-a | filesystem> 1651 4577 ahrens */ 1652 4577 ahrens static int 1653 4577 ahrens zfs_do_upgrade(int argc, char **argv) 1654 4577 ahrens { 1655 4577 ahrens boolean_t all = B_FALSE; 1656 4577 ahrens boolean_t showversions = B_FALSE; 1657 4577 ahrens int ret; 1658 4577 ahrens upgrade_cbdata_t cb = { 0 }; 1659 4577 ahrens char c; 1660 7538 Richard int flags = ZFS_ITER_ARGS_CAN_BE_PATHS; 1661 4577 ahrens 1662 4577 ahrens /* check options */ 1663 4577 ahrens while ((c = getopt(argc, argv, "rvV:a")) != -1) { 1664 4577 ahrens switch (c) { 1665 4577 ahrens case 'r': 1666 7538 Richard flags |= ZFS_ITER_RECURSE; 1667 4577 ahrens break; 1668 4577 ahrens case 'v': 1669 4577 ahrens showversions = B_TRUE; 1670 4577 ahrens break; 1671 4577 ahrens case 'V': 1672 4577 ahrens if (zfs_prop_string_to_index(ZFS_PROP_VERSION, 1673 4577 ahrens optarg, &cb.cb_version) != 0) { 1674 4577 ahrens (void) fprintf(stderr, 1675 4577 ahrens gettext("invalid version %s\n"), optarg); 1676 4577 ahrens usage(B_FALSE); 1677 4577 ahrens } 1678 4577 ahrens break; 1679 4577 ahrens case 'a': 1680 4577 ahrens all = B_TRUE; 1681 4577 ahrens break; 1682 4577 ahrens case '?': 1683 4577 ahrens default: 1684 4577 ahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1685 4577 ahrens optopt); 1686 4577 ahrens usage(B_FALSE); 1687 4577 ahrens } 1688 4577 ahrens } 1689 4577 ahrens 1690 4577 ahrens argc -= optind; 1691 4577 ahrens argv += optind; 1692 4577 ahrens 1693 7538 Richard if ((!all && !argc) && ((flags & ZFS_ITER_RECURSE) | cb.cb_version)) 1694 7538 Richard usage(B_FALSE); 1695 7538 Richard if (showversions && (flags & ZFS_ITER_RECURSE || all || 1696 7538 Richard cb.cb_version || argc)) 1697 4577 ahrens usage(B_FALSE); 1698 4577 ahrens if ((all || argc) && (showversions)) 1699 4577 ahrens usage(B_FALSE); 1700 4577 ahrens if (all && argc) 1701 4577 ahrens usage(B_FALSE); 1702 4577 ahrens 1703 4577 ahrens if (showversions) { 1704 4577 ahrens /* Show info on available versions. */ 1705 4577 ahrens (void) printf(gettext("The following filesystem versions are " 1706 4577 ahrens "supported:\n\n")); 1707 4577 ahrens (void) printf(gettext("VER DESCRIPTION\n")); 1708 4577 ahrens (void) printf("--- -----------------------------------------" 1709 4577 ahrens "---------------\n"); 1710 4577 ahrens (void) printf(gettext(" 1 Initial ZFS filesystem version\n")); 1711 4577 ahrens (void) printf(gettext(" 2 Enhanced directory entries\n")); 1712 5331 amw (void) printf(gettext(" 3 Case insensitive and File system " 1713 10228 Stephanie "unique identifier (FUID)\n")); 1714 9396 Matthew (void) printf(gettext(" 4 userquota, groupquota " 1715 9396 Matthew "properties\n")); 1716 4577 ahrens (void) printf(gettext("\nFor more information on a particular " 1717 4577 ahrens "version, including supported releases, see:\n\n")); 1718 4577 ahrens (void) printf("http://www.opensolaris.org/os/community/zfs/" 1719 4577 ahrens "version/zpl/N\n\n"); 1720 4577 ahrens (void) printf(gettext("Where 'N' is the version number.\n")); 1721 4577 ahrens ret = 0; 1722 4577 ahrens } else if (argc || all) { 1723 4577 ahrens /* Upgrade filesystems */ 1724 4577 ahrens if (cb.cb_version == 0) 1725 4577 ahrens cb.cb_version = ZPL_VERSION; 1726 7538 Richard ret = zfs_for_each(argc, argv, flags, ZFS_TYPE_FILESYSTEM, 1727 9365 Chris NULL, NULL, 0, upgrade_set_callback, &cb); 1728 4577 ahrens (void) printf(gettext("%llu filesystems upgraded\n"), 1729 4577 ahrens cb.cb_numupgraded); 1730 4577 ahrens if (cb.cb_numsamegraded) { 1731 4577 ahrens (void) printf(gettext("%llu filesystems already at " 1732 4577 ahrens "this version\n"), 1733 4577 ahrens cb.cb_numsamegraded); 1734 4577 ahrens } 1735 4849 ahrens if (cb.cb_numfailed != 0) 1736 4577 ahrens ret = 1; 1737 4577 ahrens } else { 1738 4577 ahrens /* List old-version filesytems */ 1739 4577 ahrens boolean_t found; 1740 4577 ahrens (void) printf(gettext("This system is currently running " 1741 4577 ahrens "ZFS filesystem version %llu.\n\n"), ZPL_VERSION); 1742 4577 ahrens 1743 7538 Richard flags |= ZFS_ITER_RECURSE; 1744 7538 Richard ret = zfs_for_each(0, NULL, flags, ZFS_TYPE_FILESYSTEM, 1745 9365 Chris NULL, NULL, 0, upgrade_list_callback, &cb); 1746 4577 ahrens 1747 4577 ahrens found = cb.cb_foundone; 1748 4577 ahrens cb.cb_foundone = B_FALSE; 1749 4577 ahrens cb.cb_newer = B_TRUE; 1750 4577 ahrens 1751 7538 Richard ret = zfs_for_each(0, NULL, flags, ZFS_TYPE_FILESYSTEM, 1752 9365 Chris NULL, NULL, 0, upgrade_list_callback, &cb); 1753 4577 ahrens 1754 4577 ahrens if (!cb.cb_foundone && !found) { 1755 4577 ahrens (void) printf(gettext("All filesystems are " 1756 4577 ahrens "formatted with the current version.\n")); 1757 4577 ahrens } 1758 4577 ahrens } 1759 2926 ek110237 1760 2926 ek110237 return (ret); 1761 789 ahrens } 1762 789 ahrens 1763 789 ahrens /* 1764 9396 Matthew * zfs userspace 1765 9396 Matthew */ 1766 9554 Matthew static int 1767 9396 Matthew userspace_cb(void *arg, const char *domain, uid_t rid, uint64_t space) 1768 9396 Matthew { 1769 9396 Matthew zfs_userquota_prop_t *typep = arg; 1770 9396 Matthew zfs_userquota_prop_t p = *typep; 1771 9554 Matthew char *name = NULL; 1772 9554 Matthew char *ug, *propname; 1773 9396 Matthew char namebuf[32]; 1774 9396 Matthew char sizebuf[32]; 1775 9396 Matthew 1776 9396 Matthew if (domain == NULL || domain[0] == '\0') { 1777 9396 Matthew if (p == ZFS_PROP_GROUPUSED || p == ZFS_PROP_GROUPQUOTA) { 1778 9396 Matthew struct group *g = getgrgid(rid); 1779 9396 Matthew if (g) 1780 9396 Matthew name = g->gr_name; 1781 9396 Matthew } else { 1782 9396 Matthew struct passwd *p = getpwuid(rid); 1783 9396 Matthew if (p) 1784 9396 Matthew name = p->pw_name; 1785 9396 Matthew } 1786 9396 Matthew } 1787 9396 Matthew 1788 9396 Matthew if (p == ZFS_PROP_GROUPUSED || p == ZFS_PROP_GROUPQUOTA) 1789 9396 Matthew ug = "group"; 1790 9396 Matthew else 1791 9396 Matthew ug = "user"; 1792 9396 Matthew 1793 9396 Matthew if (p == ZFS_PROP_USERUSED || p == ZFS_PROP_GROUPUSED) 1794 9396 Matthew propname = "used"; 1795 9396 Matthew else 1796 9396 Matthew propname = "quota"; 1797 9396 Matthew 1798 9554 Matthew if (name == NULL) { 1799 9396 Matthew (void) snprintf(namebuf, sizeof (namebuf), 1800 9396 Matthew "%llu", (longlong_t)rid); 1801 9396 Matthew name = namebuf; 1802 9396 Matthew } 1803 9396 Matthew zfs_nicenum(space, sizebuf, sizeof (sizebuf)); 1804 9396 Matthew 1805 9396 Matthew (void) printf("%s %s %s%c%s %s\n", propname, ug, domain, 1806 9396 Matthew domain[0] ? '-' : ' ', name, sizebuf); 1807 9554 Matthew 1808 9554 Matthew return (0); 1809 9396 Matthew } 1810 9396 Matthew 1811 9396 Matthew static int 1812 9396 Matthew zfs_do_userspace(int argc, char **argv) 1813 9396 Matthew { 1814 9396 Matthew zfs_handle_t *zhp; 1815 9396 Matthew zfs_userquota_prop_t p; 1816 9396 Matthew int error; 1817 9396 Matthew 1818 9396 Matthew /* 1819 9396 Matthew * Try the python version. If the execv fails, we'll continue 1820 9396 Matthew * and do a simplistic implementation. 1821 9396 Matthew */ 1822 9396 Matthew (void) execv(pypath, argv-1); 1823 9396 Matthew 1824 9396 Matthew (void) printf("internal error: %s not found\n" 1825 9396 Matthew "falling back on built-in implementation, " 1826 9396 Matthew "some features will not work\n", pypath); 1827 9396 Matthew 1828 9396 Matthew if ((zhp = zfs_open(g_zfs, argv[argc-1], ZFS_TYPE_DATASET)) == NULL) 1829 9396 Matthew return (1); 1830 9396 Matthew 1831 9396 Matthew (void) printf("PROP TYPE NAME VALUE\n"); 1832 9396 Matthew 1833 9396 Matthew for (p = 0; p < ZFS_NUM_USERQUOTA_PROPS; p++) { 1834 9396 Matthew error = zfs_userspace(zhp, p, userspace_cb, &p); 1835 9396 Matthew if (error) 1836 9396 Matthew break; 1837 9396 Matthew } 1838 9396 Matthew return (error); 1839 9396 Matthew } 1840 9396 Matthew 1841 9396 Matthew /* 1842 9365 Chris * list [-r][-d max] [-H] [-o property[,property]...] [-t type[,type]...] 1843 2379 sjelinek * [-s property [-s property]...] [-S property [-S property]...] 1844 2379 sjelinek * <dataset> ... 1845 789 ahrens * 1846 11022 Tom * -r Recurse over all children 1847 11022 Tom * -d Limit recursion by depth. 1848 11022 Tom * -H Scripted mode; elide headers and separate columns by tabs 1849 11022 Tom * -o Control which fields to display. 1850 11022 Tom * -t Control which object types to display. 1851 2379 sjelinek * -s Specify sort columns, descending order. 1852 2379 sjelinek * -S Specify sort columns, ascending order. 1853 789 ahrens * 1854 789 ahrens * When given no arguments, lists all filesystems in the system. 1855 789 ahrens * Otherwise, list the specified datasets, optionally recursing down them if 1856 789 ahrens * '-r' is specified. 1857 789 ahrens */ 1858 789 ahrens typedef struct list_cbdata { 1859 2082 eschrock boolean_t cb_first; 1860 2082 eschrock boolean_t cb_scripted; 1861 5094 lling zprop_list_t *cb_proplist; 1862 789 ahrens } list_cbdata_t; 1863 789 ahrens 1864 789 ahrens /* 1865 789 ahrens * Given a list of columns to display, output appropriate headers for each one. 1866 789 ahrens */ 1867 789 ahrens static void 1868 5094 lling print_header(zprop_list_t *pl) 1869 789 ahrens { 1870 2676 eschrock char headerbuf[ZFS_MAXPROPLEN]; 1871 2676 eschrock const char *header; 1872 789 ahrens int i; 1873 2676 eschrock boolean_t first = B_TRUE; 1874 2676 eschrock boolean_t right_justify; 1875 789 ahrens 1876 2676 eschrock for (; pl != NULL; pl = pl->pl_next) { 1877 2676 eschrock if (!first) { 1878 789 ahrens (void) printf(" "); 1879 2676 eschrock } else { 1880 2676 eschrock first = B_FALSE; 1881 2676 eschrock } 1882 2676 eschrock 1883 2676 eschrock right_justify = B_FALSE; 1884 5094 lling if (pl->pl_prop != ZPROP_INVAL) { 1885 2676 eschrock header = zfs_prop_column_name(pl->pl_prop); 1886 2676 eschrock right_justify = zfs_prop_align_right(pl->pl_prop); 1887 2676 eschrock } else { 1888 2676 eschrock for (i = 0; pl->pl_user_prop[i] != '\0'; i++) 1889 2676 eschrock headerbuf[i] = toupper(pl->pl_user_prop[i]); 1890 2676 eschrock headerbuf[i] = '\0'; 1891 2676 eschrock header = headerbuf; 1892 2676 eschrock } 1893 2676 eschrock 1894 2676 eschrock if (pl->pl_next == NULL && !right_justify) 1895 2676 eschrock (void) printf("%s", header); 1896 2676 eschrock else if (right_justify) 1897 2676 eschrock (void) printf("%*s", pl->pl_width, header); 1898 2676 eschrock else 1899 2676 eschrock (void) printf("%-*s", pl->pl_width, header); 1900 789 ahrens } 1901 789 ahrens 1902 789 ahrens (void) printf("\n"); 1903 789 ahrens } 1904 789 ahrens 1905 789 ahrens /* 1906 789 ahrens * Given a dataset and a list of fields, print out all the properties according 1907 789 ahrens * to the described layout. 1908 789 ahrens */ 1909 789 ahrens static void 1910 5094 lling print_dataset(zfs_handle_t *zhp, zprop_list_t *pl, boolean_t scripted) 1911 789 ahrens { 1912 2676 eschrock boolean_t first = B_TRUE; 1913 789 ahrens char property[ZFS_MAXPROPLEN]; 1914 2676 eschrock nvlist_t *userprops = zfs_get_user_props(zhp); 1915 2676 eschrock nvlist_t *propval; 1916 2676 eschrock char *propstr; 1917 2676 eschrock boolean_t right_justify; 1918 2676 eschrock int width; 1919 789 ahrens 1920 2676 eschrock for (; pl != NULL; pl = pl->pl_next) { 1921 2676 eschrock if (!first) { 1922 789 ahrens if (scripted) 1923 789 ahrens (void) printf("\t"); 1924 789 ahrens else 1925 789 ahrens (void) printf(" "); 1926 2676 eschrock } else { 1927 2676 eschrock first = B_FALSE; 1928 789 ahrens } 1929 789 ahrens 1930 5094 lling if (pl->pl_prop != ZPROP_INVAL) { 1931 2676 eschrock if (zfs_prop_get(zhp, pl->pl_prop, property, 1932 2676 eschrock sizeof (property), NULL, NULL, 0, B_FALSE) != 0) 1933 2676 eschrock propstr = "-"; 1934 2676 eschrock else 1935 2676 eschrock propstr = property; 1936 2676 eschrock 1937 2676 eschrock right_justify = zfs_prop_align_right(pl->pl_prop); 1938 9396 Matthew } else if (zfs_prop_userquota(pl->pl_user_prop)) { 1939 9396 Matthew if (zfs_prop_get_userquota(zhp, pl->pl_user_prop, 1940 9396 Matthew property, sizeof (property), B_FALSE) != 0) 1941 9396 Matthew propstr = "-"; 1942 9396 Matthew else 1943 9396 Matthew propstr = property; 1944 9396 Matthew right_justify = B_TRUE; 1945 2676 eschrock } else { 1946 2676 eschrock if (nvlist_lookup_nvlist(userprops, 1947 2676 eschrock pl->pl_user_prop, &propval) != 0) 1948 2676 eschrock propstr = "-"; 1949 2676 eschrock else 1950 2676 eschrock verify(nvlist_lookup_string(propval, 1951 5094 lling ZPROP_VALUE, &propstr) == 0); 1952 9396 Matthew right_justify = B_FALSE; 1953 2676 eschrock } 1954 2676 eschrock 1955 2676 eschrock width = pl->pl_width; 1956 789 ahrens 1957 866 eschrock /* 1958 866 eschrock * If this is being called in scripted mode, or if this is the 1959 866 eschrock * last column and it is left-justified, don't include a width 1960 866 eschrock * format specifier. 1961 866 eschrock */ 1962 2676 eschrock if (scripted || (pl->pl_next == NULL && !right_justify)) 1963 2676 eschrock (void) printf("%s", propstr); 1964 2676 eschrock else if (right_justify) 1965 2676 eschrock (void) printf("%*s", width, propstr); 1966 2676 eschrock else 1967 2676 eschrock (void) printf("%-*s", width, propstr); 1968 789 ahrens } 1969 789 ahrens 1970 789 ahrens (void) printf("\n"); 1971 789 ahrens } 1972 789 ahrens 1973 789 ahrens /* 1974 789 ahrens * Generic callback function to list a dataset or snapshot. 1975 789 ahrens */ 1976 789 ahrens static int 1977 789 ahrens list_callback(zfs_handle_t *zhp, void *data) 1978 789 ahrens { 1979 789 ahrens list_cbdata_t *cbp = data; 1980 789 ahrens 1981 789 ahrens if (cbp->cb_first) { 1982 789 ahrens if (!cbp->cb_scripted) 1983 2676 eschrock print_header(cbp->cb_proplist); 1984 2082 eschrock cbp->cb_first = B_FALSE; 1985 789 ahrens } 1986 789 ahrens 1987 2676 eschrock print_dataset(zhp, cbp->cb_proplist, cbp->cb_scripted); 1988 789 ahrens 1989 789 ahrens return (0); 1990 789 ahrens } 1991 789 ahrens 1992 789 ahrens static int 1993 789 ahrens zfs_do_list(int argc, char **argv) 1994 789 ahrens { 1995 789 ahrens int c; 1996 2082 eschrock boolean_t scripted = B_FALSE; 1997 789 ahrens static char default_fields[] = 1998 789 ahrens "name,used,available,referenced,mountpoint"; 1999 8415 Richard int types = ZFS_TYPE_DATASET; 2000 7538 Richard boolean_t types_specified = B_FALSE; 2001 789 ahrens char *fields = NULL; 2002 789 ahrens list_cbdata_t cb = { 0 }; 2003 789 ahrens char *value; 2004 9365 Chris int limit = 0; 2005 789 ahrens int ret; 2006 2379 sjelinek zfs_sort_column_t *sortcol = NULL; 2007 7538 Richard int flags = ZFS_ITER_PROP_LISTSNAPS | ZFS_ITER_ARGS_CAN_BE_PATHS; 2008 789 ahrens 2009 789 ahrens /* check options */ 2010 9365 Chris while ((c = getopt(argc, argv, ":d:o:rt:Hs:S:")) != -1) { 2011 789 ahrens switch (c) { 2012 789 ahrens case 'o': 2013 789 ahrens fields = optarg; 2014 9365 Chris break; 2015 9365 Chris case 'd': 2016 9365 Chris limit = parse_depth(optarg, &flags); 2017 789 ahrens break; 2018 789 ahrens case 'r': 2019 7538 Richard flags |= ZFS_ITER_RECURSE; 2020 789 ahrens break; 2021 789 ahrens case 'H': 2022 2082 eschrock scripted = B_TRUE; 2023 2379 sjelinek break; 2024 2379 sjelinek case 's': 2025 2676 eschrock if (zfs_add_sort_column(&sortcol, optarg, 2026 2676 eschrock B_FALSE) != 0) { 2027 2379 sjelinek (void) fprintf(stderr, 2028 2379 sjelinek gettext("invalid property '%s'\n"), optarg); 2029 2379 sjelinek usage(B_FALSE); 2030 2379 sjelinek } 2031 2379 sjelinek break; 2032 2379 sjelinek case 'S': 2033 2676 eschrock if (zfs_add_sort_column(&sortcol, optarg, 2034 2676 eschrock B_TRUE) != 0) { 2035 2379 sjelinek (void) fprintf(stderr, 2036 2379 sjelinek gettext("invalid property '%s'\n"), optarg); 2037 2379 sjelinek usage(B_FALSE); 2038 2379 sjelinek } 2039 789 ahrens break; 2040 789 ahrens case 't': 2041 789 ahrens types = 0; 2042 7538 Richard types_specified = B_TRUE; 2043 7538 Richard flags &= ~ZFS_ITER_PROP_LISTSNAPS; 2044 789 ahrens while (*optarg != '\0') { 2045 7538 Richard static char *type_subopts[] = { "filesystem", 2046 7538 Richard "volume", "snapshot", "all", NULL }; 2047 7538 Richard 2048 789 ahrens switch (getsubopt(&optarg, type_subopts, 2049 789 ahrens &value)) { 2050 789 ahrens case 0: 2051 789 ahrens types |= ZFS_TYPE_FILESYSTEM; 2052 789 ahrens break; 2053 789 ahrens case 1: 2054 789 ahrens types |= ZFS_TYPE_VOLUME; 2055 789 ahrens break; 2056 789 ahrens case 2: 2057 789 ahrens types |= ZFS_TYPE_SNAPSHOT; 2058 789 ahrens break; 2059 7538 Richard case 3: 2060 7538 Richard types = ZFS_TYPE_DATASET; 2061 7538 Richard break; 2062 7538 Richard 2063 789 ahrens default: 2064 789 ahrens (void) fprintf(stderr, 2065 789 ahrens gettext("invalid type '%s'\n"), 2066 789 ahrens value); 2067 2082 eschrock usage(B_FALSE); 2068 789 ahrens } 2069 789 ahrens } 2070 789 ahrens break; 2071 789 ahrens case ':': 2072 789 ahrens (void) fprintf(stderr, gettext("missing argument for " 2073 789 ahrens "'%c' option\n"), optopt); 2074 2082 eschrock usage(B_FALSE); 2075 789 ahrens break; 2076 789 ahrens case '?': 2077 789 ahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2078 789 ahrens optopt); 2079 2082 eschrock usage(B_FALSE); 2080 789 ahrens } 2081 789 ahrens } 2082 789 ahrens 2083 789 ahrens argc -= optind; 2084 789 ahrens argv += optind; 2085 789 ahrens 2086 789 ahrens if (fields == NULL) 2087 7390 Matthew fields = default_fields; 2088 7390 Matthew 2089 7390 Matthew /* 2090 7538 Richard * If "-o space" and no types were specified, don't display snapshots. 2091 7538 Richard */ 2092 7538 Richard if (strcmp(fields, "space") == 0 && types_specified == B_FALSE) 2093 7390 Matthew types &= ~ZFS_TYPE_SNAPSHOT; 2094 789 ahrens 2095 866 eschrock /* 2096 5094 lling * If the user specifies '-o all', the zprop_get_list() doesn't 2097 866 eschrock * normally include the name of the dataset. For 'zfs list', we always 2098 866 eschrock * want this property to be first. 2099 866 eschrock */ 2100 5094 lling if (zprop_get_list(g_zfs, fields, &cb.cb_proplist, ZFS_TYPE_DATASET) 2101 5094 lling != 0) 2102 2676 eschrock usage(B_FALSE); 2103 789 ahrens 2104 789 ahrens cb.cb_scripted = scripted; 2105 2082 eschrock cb.cb_first = B_TRUE; 2106 789 ahrens 2107 7538 Richard ret = zfs_for_each(argc, argv, flags, types, sortcol, &cb.cb_proplist, 2108 9365 Chris limit, list_callback, &cb); 2109 2379 sjelinek 2110 5094 lling zprop_free_list(cb.cb_proplist); 2111 2379 sjelinek zfs_free_sort_columns(sortcol); 2112 789 ahrens 2113 4221 mmusante if (ret == 0 && cb.cb_first && !cb.cb_scripted) 2114 789 ahrens (void) printf(gettext("no datasets available\n")); 2115 789 ahrens 2116 789 ahrens return (ret); 2117 789 ahrens } 2118 789 ahrens 2119 789 ahrens /* 2120 4490 vb160487 * zfs rename <fs | snap | vol> <fs | snap | vol> 2121 4490 vb160487 * zfs rename -p <fs | vol> <fs | vol> 2122 4490 vb160487 * zfs rename -r <snap> <snap> 2123 789 ahrens * 2124 789 ahrens * Renames the given dataset to another of the same type. 2125 4490 vb160487 * 2126 4490 vb160487 * The '-p' flag creates all the non-existing ancestors of the target first. 2127 789 ahrens */ 2128 789 ahrens /* ARGSUSED */ 2129 789 ahrens static int 2130 789 ahrens zfs_do_rename(int argc, char **argv) 2131 789 ahrens { 2132 789 ahrens zfs_handle_t *zhp; 2133 4007 mmusante int c; 2134 2082 eschrock int ret; 2135 4490 vb160487 boolean_t recurse = B_FALSE; 2136 4490 vb160487 boolean_t parents = B_FALSE; 2137 789 ahrens 2138 789 ahrens /* check options */ 2139 4490 vb160487 while ((c = getopt(argc, argv, "pr")) != -1) { 2140 4007 mmusante switch (c) { 2141 4490 vb160487 case 'p': 2142 4490 vb160487 parents = B_TRUE; 2143 4490 vb160487 break; 2144 4007 mmusante case 'r': 2145 4490 vb160487 recurse = B_TRUE; 2146 4007 mmusante break; 2147 4007 mmusante case '?': 2148 4007 mmusante default: 2149 4007 mmusante (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2150 4007 mmusante optopt); 2151 4007 mmusante usage(B_FALSE); 2152 4007 mmusante } 2153 789 ahrens } 2154 789 ahrens 2155 4007 mmusante argc -= optind; 2156 4007 mmusante argv += optind; 2157 4007 mmusante 2158 789 ahrens /* check number of arguments */ 2159 4007 mmusante if (argc < 1) { 2160 789 ahrens (void) fprintf(stderr, gettext("missing source dataset " 2161 789 ahrens "argument\n")); 2162 2082 eschrock usage(B_FALSE); 2163 789 ahrens } 2164 4007 mmusante if (argc < 2) { 2165 789 ahrens (void) fprintf(stderr, gettext("missing target dataset " 2166 789 ahrens "argument\n")); 2167 2082 eschrock usage(B_FALSE); 2168 789 ahrens } 2169 4007 mmusante if (argc > 2) { 2170 789 ahrens (void) fprintf(stderr, gettext("too many arguments\n")); 2171 2082 eschrock usage(B_FALSE); 2172 789 ahrens } 2173 789 ahrens 2174 4490 vb160487 if (recurse && parents) { 2175 4490 vb160487 (void) fprintf(stderr, gettext("-p and -r options are mutually " 2176 4490 vb160487 "exclusive\n")); 2177 4490 vb160487 usage(B_FALSE); 2178 4490 vb160487 } 2179 4490 vb160487 2180 4007 mmusante if (recurse && strchr(argv[0], '@') == 0) { 2181 4007 mmusante (void) fprintf(stderr, gettext("source dataset for recursive " 2182 4007 mmusante "rename must be a snapshot\n")); 2183 4007 mmusante usage(B_FALSE); 2184 4007 mmusante } 2185 4007 mmusante 2186 4490 vb160487 if ((zhp = zfs_open(g_zfs, argv[0], parents ? ZFS_TYPE_FILESYSTEM | 2187 5094 lling ZFS_TYPE_VOLUME : ZFS_TYPE_DATASET)) == NULL) 2188 789 ahrens return (1); 2189 4490 vb160487 2190 4490 vb160487 /* If we were asked and the name looks good, try to create ancestors. */ 2191 4490 vb160487 if (parents && zfs_name_valid(argv[1], zfs_get_type(zhp)) && 2192 4490 vb160487 zfs_create_ancestors(g_zfs, argv[1]) != 0) { 2193 4490 vb160487 zfs_close(zhp); 2194 4490 vb160487 return (1); 2195 4490 vb160487 } 2196 789 ahrens 2197 4007 mmusante ret = (zfs_rename(zhp, argv[1], recurse) != 0); 2198 789 ahrens 2199 2082 eschrock zfs_close(zhp); 2200 2082 eschrock return (ret); 2201 2082 eschrock } 2202 2082 eschrock 2203 2082 eschrock /* 2204 2082 eschrock * zfs promote <fs> 2205 2082 eschrock * 2206 2082 eschrock * Promotes the given clone fs to be the parent 2207 2082 eschrock */ 2208 2082 eschrock /* ARGSUSED */ 2209 2082 eschrock static int 2210 2082 eschrock zfs_do_promote(int argc, char **argv) 2211 2082 eschrock { 2212 2082 eschrock zfs_handle_t *zhp; 2213 2082 eschrock int ret; 2214 2082 eschrock 2215 2082 eschrock /* check options */ 2216 2082 eschrock if (argc > 1 && argv[1][0] == '-') { 2217 2082 eschrock (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2218 2082 eschrock argv[1][1]); 2219 2082 eschrock usage(B_FALSE); 2220 2082 eschrock } 2221 2082 eschrock 2222 2082 eschrock /* check number of arguments */ 2223 2082 eschrock if (argc < 2) { 2224 2082 eschrock (void) fprintf(stderr, gettext("missing clone filesystem" 2225 2597 nd150628 " argument\n")); 2226 2082 eschrock usage(B_FALSE); 2227 2082 eschrock } 2228 2082 eschrock if (argc > 2) { 2229 2082 eschrock (void) fprintf(stderr, gettext("too many arguments\n")); 2230 2082 eschrock usage(B_FALSE); 2231 2082 eschrock } 2232 2082 eschrock 2233 2082 eschrock zhp = zfs_open(g_zfs, argv[1], ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); 2234 2082 eschrock if (zhp == NULL) 2235 2082 eschrock return (1); 2236 2082 eschrock 2237 2082 eschrock ret = (zfs_promote(zhp) != 0); 2238 2926 ek110237 2239 2082 eschrock 2240 789 ahrens zfs_close(zhp); 2241 789 ahrens return (ret); 2242 789 ahrens } 2243 789 ahrens 2244 789 ahrens /* 2245 5568 ahrens * zfs rollback [-rRf] <snapshot> 2246 789 ahrens * 2247 11022 Tom * -r Delete any intervening snapshots before doing rollback 2248 11022 Tom * -R Delete any snapshots and their clones 2249 11022 Tom * -f ignored for backwards compatability 2250 789 ahrens * 2251 789 ahrens * Given a filesystem, rollback to a specific snapshot, discarding any changes 2252 789 ahrens * since then and making it the active dataset. If more recent snapshots exist, 2253 789 ahrens * the command will complain unless the '-r' flag is given. 2254 789 ahrens */ 2255 789 ahrens typedef struct rollback_cbdata { 2256 789 ahrens uint64_t cb_create; 2257 2082 eschrock boolean_t cb_first; 2258 789 ahrens int cb_doclones; 2259 789 ahrens char *cb_target; 2260 789 ahrens int cb_error; 2261 2082 eschrock boolean_t cb_recurse; 2262 2082 eschrock boolean_t cb_dependent; 2263 789 ahrens } rollback_cbdata_t; 2264 789 ahrens 2265 789 ahrens /* 2266 789 ahrens * Report any snapshots more recent than the one specified. Used when '-r' is 2267 789 ahrens * not specified. We reuse this same callback for the snapshot dependents - if 2268 789 ahrens * 'cb_dependent' is set, then this is a dependent and we should report it 2269 789 ahrens * without checking the transaction group. 2270 789 ahrens */ 2271 789 ahrens static int 2272 789 ahrens rollback_check(zfs_handle_t *zhp, void *data) 2273 789 ahrens { 2274 789 ahrens rollback_cbdata_t *cbp = data; 2275 789 ahrens 2276 2082 eschrock if (cbp->cb_doclones) { 2277 2082 eschrock zfs_close(zhp); 2278 789 ahrens return (0); 2279 2082 eschrock } 2280 789 ahrens 2281 789 ahrens if (!cbp->cb_dependent) { 2282 789 ahrens if (strcmp(zfs_get_name(zhp), cbp->cb_target) != 0 && 2283 1294 lling zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT && 2284 789 ahrens zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > 2285 789 ahrens cbp->cb_create) { 2286 789 ahrens 2287 789 ahrens if (cbp->cb_first && !cbp->cb_recurse) { 2288 789 ahrens (void) fprintf(stderr, gettext("cannot " 2289 789 ahrens "rollback to '%s': more recent snapshots " 2290 789 ahrens "exist\n"), 2291 789 ahrens cbp->cb_target); 2292 789 ahrens (void) fprintf(stderr, gettext("use '-r' to " 2293 789 ahrens "force deletion of the following " 2294 789 ahrens "snapshots:\n")); 2295 789 ahrens cbp->cb_first = 0; 2296 789 ahrens cbp->cb_error = 1; 2297 789 ahrens } 2298 789 ahrens 2299 789 ahrens if (cbp->cb_recurse) { 2300 2082 eschrock cbp->cb_dependent = B_TRUE; 2301 2474 eschrock if (zfs_iter_dependents(zhp, B_TRUE, 2302 2474 eschrock rollback_check, cbp) != 0) { 2303 2474 eschrock zfs_close(zhp); 2304 2474 eschrock return (-1); 2305 2474 eschrock } 2306 2082 eschrock cbp->cb_dependent = B_FALSE; 2307 789 ahrens } else { 2308 789 ahrens (void) fprintf(stderr, "%s\n", 2309 789 ahrens zfs_get_name(zhp)); 2310 789 ahrens } 2311 789 ahrens } 2312 789 ahrens } else { 2313 789 ahrens if (cbp->cb_first && cbp->cb_recurse) { 2314 789 ahrens (void) fprintf(stderr, gettext("cannot rollback to " 2315 789 ahrens "'%s': clones of previous snapshots exist\n"), 2316 789 ahrens cbp->cb_target); 2317 789 ahrens (void) fprintf(stderr, gettext("use '-R' to " 2318 789 ahrens "force deletion of the following clones and " 2319 789 ahrens "dependents:\n")); 2320 789 ahrens cbp->cb_first = 0; 2321 789 ahrens cbp->cb_error = 1; 2322 789 ahrens } 2323 789 ahrens 2324 789 ahrens (void) fprintf(stderr, "%s\n", zfs_get_name(zhp)); 2325 789 ahrens } 2326 789 ahrens 2327 789 ahrens zfs_close(zhp); 2328 789 ahrens return (0); 2329 789 ahrens } 2330 789 ahrens 2331 789 ahrens static int 2332 789 ahrens zfs_do_rollback(int argc, char **argv) 2333 789 ahrens { 2334 789 ahrens int ret; 2335 789 ahrens int c; 2336 5749 ahrens boolean_t force = B_FALSE; 2337 789 ahrens rollback_cbdata_t cb = { 0 }; 2338 789 ahrens zfs_handle_t *zhp, *snap; 2339 789 ahrens char parentname[ZFS_MAXNAMELEN]; 2340 789 ahrens char *delim; 2341 5446 ahrens 2342 5446 ahrens /* check options */ 2343 5568 ahrens while ((c = getopt(argc, argv, "rRf")) != -1) { 2344 5446 ahrens switch (c) { 2345 789 ahrens case 'r': 2346 789 ahrens cb.cb_recurse = 1; 2347 789 ahrens break; 2348 789 ahrens case 'R': 2349 789 ahrens cb.cb_recurse = 1; 2350 789 ahrens cb.cb_doclones = 1; 2351 5568 ahrens break; 2352 5568 ahrens case 'f': 2353 5749 ahrens force = B_TRUE; 2354 789 ahrens break; 2355 789 ahrens case '?': 2356 789 ahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2357 789 ahrens optopt); 2358 2082 eschrock usage(B_FALSE); 2359 789 ahrens } 2360 789 ahrens } 2361 789 ahrens 2362 789 ahrens argc -= optind; 2363 789 ahrens argv += optind; 2364 789 ahrens 2365 789 ahrens /* check number of arguments */ 2366 789 ahrens if (argc < 1) { 2367 789 ahrens (void) fprintf(stderr, gettext("missing dataset argument\n")); 2368 2082 eschrock usage(B_FALSE); 2369 789 ahrens } 2370 789 ahrens if (argc > 1) { 2371 789 ahrens (void) fprintf(stderr, gettext("too many arguments\n")); 2372 2082 eschrock usage(B_FALSE); 2373 789 ahrens } 2374 789 ahrens 2375 789 ahrens /* open the snapshot */ 2376 2082 eschrock if ((snap = zfs_open(g_zfs, argv[0], ZFS_TYPE_SNAPSHOT)) == NULL) 2377 789 ahrens return (1); 2378 789 ahrens 2379 1294 lling /* open the parent dataset */ 2380 1294 lling (void) strlcpy(parentname, argv[0], sizeof (parentname)); 2381 789 ahrens verify((delim = strrchr(parentname, '@')) != NULL); 2382 789 ahrens *delim = '\0'; 2383 5094 lling if ((zhp = zfs_open(g_zfs, parentname, ZFS_TYPE_DATASET)) == NULL) { 2384 789 ahrens zfs_close(snap); 2385 789 ahrens return (1); 2386 789 ahrens } 2387 789 ahrens 2388 789 ahrens /* 2389 789 ahrens * Check for more recent snapshots and/or clones based on the presence 2390 789 ahrens * of '-r' and '-R'. 2391 789 ahrens */ 2392 1294 lling cb.cb_target = argv[0]; 2393 1294 lling cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG); 2394 2082 eschrock cb.cb_first = B_TRUE; 2395 789 ahrens cb.cb_error = 0; 2396 2474 eschrock if ((ret = zfs_iter_children(zhp, rollback_check, &cb)) != 0) 2397 2474 eschrock goto out; 2398 789 ahrens 2399 789 ahrens if ((ret = cb.cb_error) != 0) 2400 789 ahrens goto out; 2401 789 ahrens 2402 789 ahrens /* 2403 1294 lling * Rollback parent to the given snapshot. 2404 789 ahrens */ 2405 5749 ahrens ret = zfs_rollback(zhp, snap, force); 2406 789 ahrens 2407 789 ahrens out: 2408 789 ahrens zfs_close(snap); 2409 789 ahrens zfs_close(zhp); 2410 789 ahrens 2411 789 ahrens if (ret == 0) 2412 789 ahrens return (0); 2413 789 ahrens else 2414 789 ahrens return (1); 2415 789 ahrens } 2416 789 ahrens 2417 789 ahrens /* 2418 789 ahrens * zfs set property=value { fs | snap | vol } ... 2419 789 ahrens * 2420 789 ahrens * Sets the given property for all datasets specified on the command line. 2421 789 ahrens */ 2422 789 ahrens typedef struct set_cbdata { 2423 789 ahrens char *cb_propname; 2424 789 ahrens char *cb_value; 2425 789 ahrens } set_cbdata_t; 2426 789 ahrens 2427 789 ahrens static int 2428 789 ahrens set_callback(zfs_handle_t *zhp, void *data) 2429 789 ahrens { 2430 789 ahrens set_cbdata_t *cbp = data; 2431 789 ahrens 2432 2676 eschrock if (zfs_prop_set(zhp, cbp->cb_propname, cbp->cb_value) != 0) { 2433 2169 nd150628 switch (libzfs_errno(g_zfs)) { 2434 2169 nd150628 case EZFS_MOUNTFAILED: 2435 2169 nd150628 (void) fprintf(stderr, gettext("property may be set " 2436 2169 nd150628 "but unable to remount filesystem\n")); 2437 2169 nd150628 break; 2438 3126 ahl case EZFS_SHARENFSFAILED: 2439 2169 nd150628 (void) fprintf(stderr, gettext("property may be set " 2440 2169 nd150628 "but unable to reshare filesystem\n")); 2441 2169 nd150628 break; 2442 2169 nd150628 } 2443 789 ahrens return (1); 2444 2169 nd150628 } 2445 2856 nd150628 return (0); 2446 789 ahrens } 2447 789 ahrens 2448 789 ahrens static int 2449 789 ahrens zfs_do_set(int argc, char **argv) 2450 789 ahrens { 2451 789 ahrens set_cbdata_t cb; 2452 2926 ek110237 int ret; 2453 789 ahrens 2454 789 ahrens /* check for options */ 2455 789 ahrens if (argc > 1 && argv[1][0] == '-') { 2456 789 ahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2457 789 ahrens argv[1][1]); 2458 2082 eschrock usage(B_FALSE); 2459 789 ahrens } 2460 789 ahrens 2461 789 ahrens /* check number of arguments */ 2462 789 ahrens if (argc < 2) { 2463 789 ahrens (void) fprintf(stderr, gettext("missing property=value " 2464 789 ahrens "argument\n")); 2465 2082 eschrock usage(B_FALSE); 2466 789 ahrens } 2467 789 ahrens if (argc < 3) { 2468 789 ahrens (void) fprintf(stderr, gettext("missing dataset name\n")); 2469 2082 eschrock usage(B_FALSE); 2470 789 ahrens } 2471 789 ahrens 2472 789 ahrens /* validate property=value argument */ 2473 789 ahrens cb.cb_propname = argv[1]; 2474 6993 sg201626 if (((cb.cb_value = strchr(cb.cb_propname, '=')) == NULL) || 2475 6993 sg201626 (cb.cb_value[1] == '\0')) { 2476 789 ahrens (void) fprintf(stderr, gettext("missing value in " 2477 789 ahrens "property=value argument\n")); 2478 2082 eschrock usage(B_FALSE); 2479 789 ahrens } 2480 789 ahrens 2481 789 ahrens *cb.cb_value = '\0'; 2482 789 ahrens cb.cb_value++; 2483 789 ahrens 2484 789 ahrens if (*cb.cb_propname == '\0') { 2485 789 ahrens (void) fprintf(stderr, 2486 789 ahrens gettext("missing property in property=value argument\n")); 2487 2082 eschrock usage(B_FALSE); 2488 789 ahrens } 2489 4543 marks 2490 7538 Richard ret = zfs_for_each(argc - 2, argv + 2, NULL, 2491 9365 Chris ZFS_TYPE_DATASET, NULL, NULL, 0, set_callback, &cb); 2492 2926 ek110237 2493 2926 ek110237 return (ret); 2494 789 ahrens } 2495 789 ahrens 2496 789 ahrens /* 2497 7265 ahrens * zfs snapshot [-r] [-o prop=value] ... <fs@snap> 2498 789 ahrens * 2499 789 ahrens * Creates a snapshot with the given name. While functionally equivalent to 2500 5331 amw * 'zfs create', it is a separate command to differentiate intent. 2501 789 ahrens */ 2502 789 ahrens static int 2503 789 ahrens zfs_do_snapshot(int argc, char **argv) 2504 789 ahrens { 2505 4490 vb160487 boolean_t recursive = B_FALSE; 2506 2199 ahrens int ret; 2507 2199 ahrens char c; 2508 7265 ahrens nvlist_t *props; 2509 7265 ahrens 2510 7265 ahrens if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) { 2511 7265 ahrens (void) fprintf(stderr, gettext("internal error: " 2512 7265 ahrens "out of memory\n")); 2513 7265 ahrens return (1); 2514 7265 ahrens } 2515 7265 ahrens 2516 7265 ahrens /* check options */ 2517 7265 ahrens while ((c = getopt(argc, argv, "ro:")) != -1) { 2518 7265 ahrens switch (c) { 2519 7265 ahrens case 'o': 2520 7265 ahrens if (parseprop(props)) 2521 7265 ahrens return (1); 2522 7265 ahrens break; 2523 2199 ahrens case 'r': 2524 2199 ahrens recursive = B_TRUE; 2525 2199 ahrens break; 2526 2199 ahrens case '?': 2527 2199 ahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2528 2199 ahrens optopt); 2529 7265 ahrens goto usage; 2530 2199 ahrens } 2531 789 ahrens } 2532 789 ahrens 2533 2199 ahrens argc -= optind; 2534 2199 ahrens argv += optind; 2535 2199 ahrens 2536 789 ahrens /* check number of arguments */ 2537 2199 ahrens if (argc < 1) { 2538 789 ahrens (void) fprintf(stderr, gettext("missing snapshot argument\n")); 2539 7265 ahrens goto usage; 2540 7265 ahrens } 2541 7265 ahrens if (argc > 1) { 2542 7265 ahrens (void) fprintf(stderr, gettext("too many arguments\n")); 2543 7265 ahrens goto usage; 2544 7265 ahrens } 2545 7265 ahrens 2546 7265 ahrens ret = zfs_snapshot(g_zfs, argv[0], recursive, props); 2547 7265 ahrens nvlist_free(props); 2548 2199 ahrens if (ret && recursive) 2549 2199 ahrens (void) fprintf(stderr, gettext("no snapshots were created\n")); 2550 2199 ahrens return (ret != 0); 2551 7265 ahrens 2552 7265 ahrens usage: 2553 7265 ahrens nvlist_free(props); 2554 7265 ahrens usage(B_FALSE); 2555 7265 ahrens return (-1); 2556 789 ahrens } 2557 789 ahrens 2558 789 ahrens /* 2559 11022 Tom * zfs send [-vDp] -R [-i|-I <@snap>] <fs@snap> 2560 11022 Tom * zfs send [-vDp] [-i|-I <@snap>] <fs@snap> 2561 789 ahrens * 2562 789 ahrens * Send a backup stream to stdout. 2563 789 ahrens */ 2564 789 ahrens static int 2565 1749 ahrens zfs_do_send(int argc, char **argv) 2566 789 ahrens { 2567 789 ahrens char *fromname = NULL; 2568 5367 ahrens char *toname = NULL; 2569 2885 ahrens char *cp; 2570 2885 ahrens zfs_handle_t *zhp; 2571 11007 Lori sendflags_t flags = { 0 }; 2572 789 ahrens int c, err; 2573 789 ahrens 2574 789 ahrens /* check options */ 2575 11022 Tom while ((c = getopt(argc, argv, ":i:I:RDpv")) != -1) { 2576 789 ahrens switch (c) { 2577 789 ahrens case 'i': 2578 2885 ahrens if (fromname) 2579 2885 ahrens usage(B_FALSE); 2580 789 ahrens fromname = optarg; 2581 789 ahrens break; 2582 5367 ahrens case 'I': 2583 5367 ahrens if (fromname) 2584 5367 ahrens usage(B_FALSE); 2585 5367 ahrens fromname = optarg; 2586 11007 Lori flags.doall = B_TRUE; 2587 5367 ahrens break; 2588 5367 ahrens case 'R': 2589 11007 Lori flags.replicate = B_TRUE; 2590 11022 Tom break; 2591 11022 Tom case 'p': 2592 11022 Tom flags.props = B_TRUE; 2593 5367 ahrens break; 2594 5367 ahrens case 'v': 2595 11007 Lori flags.verbose = B_TRUE; 2596 11007 Lori break; 2597 11007 Lori case 'D': 2598 11007 Lori flags.dedup = B_TRUE; 2599 5367 ahrens break; 2600 789 ahrens case ':': 2601 789 ahrens (void) fprintf(stderr, gettext("missing argument for " 2602 789 ahrens "'%c' option\n"), optopt); 2603 2082 eschrock usage(B_FALSE); 2604 789 ahrens break; 2605 789 ahrens case '?': 2606 789 ahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2607 789 ahrens optopt); 2608 2082 eschrock usage(B_FALSE); 2609 789 ahrens } 2610 789 ahrens } 2611 789 ahrens 2612 789 ahrens argc -= optind; 2613 789 ahrens argv += optind; 2614 789 ahrens 2615 789 ahrens /* check number of arguments */ 2616 789 ahrens if (argc < 1) { 2617 789 ahrens (void) fprintf(stderr, gettext("missing snapshot argument\n")); 2618 2082 eschrock usage(B_FALSE); 2619 789 ahrens } 2620 789 ahrens if (argc > 1) { 2621 789 ahrens (void) fprintf(stderr, gettext("too many arguments\n")); 2622 2082 eschrock usage(B_FALSE); 2623 789 ahrens } 2624 789 ahrens 2625 789 ahrens if (isatty(STDOUT_FILENO)) { 2626 789 ahrens (void) fprintf(stderr, 2627 2885 ahrens gettext("Error: Stream can not be written to a terminal.\n" 2628 3912 lling "You must redirect standard output.\n")); 2629 789 ahrens return (1); 2630 789 ahrens } 2631 789 ahrens 2632 5367 ahrens cp = strchr(argv[0], '@'); 2633 5367 ahrens if (cp == NULL) { 2634 5367 ahrens (void) fprintf(stderr, 2635 5367 ahrens gettext("argument must be a snapshot\n")); 2636 5367 ahrens usage(B_FALSE); 2637 5367 ahrens } 2638 5367 ahrens *cp = '\0'; 2639 5367 ahrens toname = cp + 1; 2640 5367 ahrens zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); 2641 5367 ahrens if (zhp == NULL) 2642 2665 nd150628 return (1); 2643 2665 nd150628 2644 2885 ahrens /* 2645 2885 ahrens * If they specified the full path to the snapshot, chop off 2646 5367 ahrens * everything except the short name of the snapshot, but special 2647 5367 ahrens * case if they specify the origin. 2648 2885 ahrens */ 2649 2885 ahrens if (fromname && (cp = strchr(fromname, '@')) != NULL) { 2650 5367 ahrens char origin[ZFS_MAXNAMELEN]; 2651 5367 ahrens zprop_source_t src; 2652 5367 ahrens 2653 5367 ahrens (void) zfs_prop_get(zhp, ZFS_PROP_ORIGIN, 2654 5367 ahrens origin, sizeof (origin), &src, NULL, 0, B_FALSE); 2655 5367 ahrens 2656 5367 ahrens if (strcmp(origin, fromname) == 0) { 2657 5367 ahrens fromname = NULL; 2658 11007 Lori flags.fromorigin = B_TRUE; 2659 5367 ahrens } else { 2660 5367 ahrens *cp = '\0'; 2661 5367 ahrens if (cp != fromname && strcmp(argv[0], fromname)) { 2662 5367 ahrens (void) fprintf(stderr, 2663 5367 ahrens gettext("incremental source must be " 2664 5367 ahrens "in same filesystem\n")); 2665 5367 ahrens usage(B_FALSE); 2666 5367 ahrens } 2667 5367 ahrens fromname = cp + 1; 2668 5367 ahrens if (strchr(fromname, '@') || strchr(fromname, '/')) { 2669 5367 ahrens (void) fprintf(stderr, 2670 5367 ahrens gettext("invalid incremental source\n")); 2671 5367 ahrens usage(B_FALSE); 2672 5367 ahrens } 2673 5367 ahrens } 2674 5367 ahrens } 2675 5367 ahrens 2676 11007 Lori if (flags.replicate && fromname == NULL) 2677 11007 Lori flags.doall = B_TRUE; 2678 11007 Lori 2679 11007 Lori err = zfs_send(zhp, fromname, toname, flags, STDOUT_FILENO, NULL, 0); 2680 2885 ahrens zfs_close(zhp); 2681 789 ahrens 2682 789 ahrens return (err != 0); 2683 789 ahrens } 2684 789 ahrens 2685 789 ahrens /* 2686 5367 ahrens * zfs receive [-dnvF] <fs@snap> 2687 789 ahrens * 2688 789 ahrens * Restore a backup stream from stdin. 2689 789 ahrens */ 2690 789 ahrens static int 2691 1749 ahrens zfs_do_receive(int argc, char **argv) 2692 789 ahrens { 2693 789 ahrens int c, err; 2694 11022 Tom recvflags_t flags = { 0 }; 2695 11022 Tom 2696 789 ahrens /* check options */ 2697 8584 Lori while ((c = getopt(argc, argv, ":dnuvF")) != -1) { 2698 789 ahrens switch (c) { 2699 789 ahrens case 'd': 2700 5367 ahrens flags.isprefix = B_TRUE; 2701 789 ahrens break; 2702 789 ahrens case 'n': 2703 5367 ahrens flags.dryrun = B_TRUE; 2704 8584 Lori break; 2705 8584 Lori case 'u': 2706 8584 Lori flags.nomount = B_TRUE; 2707 789 ahrens break; 2708 789 ahrens case 'v': 2709 5367 ahrens flags.verbose = B_TRUE; 2710 2665 nd150628 break; 2711 2665 nd150628 case 'F': 2712 5367 ahrens flags.force = B_TRUE; 2713 789 ahrens break; 2714 789 ahrens case ':': 2715 789 ahrens (void) fprintf(stderr, gettext("missing argument for " 2716 789 ahrens "'%c' option\n"), optopt); 2717 2082 eschrock usage(B_FALSE); 2718 789 ahrens break; 2719 789 ahrens case '?': 2720 789 ahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2721 789 ahrens optopt); 2722 2082 eschrock usage(B_FALSE); 2723 789 ahrens } 2724 789 ahrens } 2725 789 ahrens 2726 789 ahrens argc -= optind; 2727 789 ahrens argv += optind; 2728 789 ahrens 2729 789 ahrens /* check number of arguments */ 2730 789 ahrens if (argc < 1) { 2731 789 ahrens (void) fprintf(stderr, gettext("missing snapshot argument\n")); 2732 2082 eschrock usage(B_FALSE); 2733 789 ahrens } 2734 789 ahrens if (argc > 1) { 2735 789 ahrens (void) fprintf(stderr, gettext("too many arguments\n")); 2736 2082 eschrock usage(B_FALSE); 2737 789 ahrens } 2738 789 ahrens 2739 789 ahrens if (isatty(STDIN_FILENO)) { 2740 789 ahrens (void) fprintf(stderr, 2741 789 ahrens gettext("Error: Backup stream can not be read " 2742 3912 lling "from a terminal.\n" 2743 3912 lling "You must redirect standard input.\n")); 2744 789 ahrens return (1); 2745 789 ahrens } 2746 789 ahrens 2747 5367 ahrens err = zfs_receive(g_zfs, argv[0], flags, STDIN_FILENO, NULL); 2748 2926 ek110237 2749 4543 marks return (err != 0); 2750 789 ahrens } 2751 789 ahrens 2752 10242 chris static int 2753 10242 chris zfs_do_hold_rele_impl(int argc, char **argv, boolean_t holding) 2754 10242 chris { 2755 10242 chris int errors = 0; 2756 10242 chris int i; 2757 10242 chris const char *tag; 2758 10242 chris boolean_t recursive = B_FALSE; 2759 10342 chris boolean_t temphold = B_FALSE; 2760 10342 chris const char *opts = holding ? "rt" : "r"; 2761 10342 chris int c; 2762 10342 chris 2763 10342 chris /* check options */ 2764 10342 chris while ((c = getopt(argc, argv, opts)) != -1) { 2765 10242 chris switch (c) { 2766 10242 chris case 'r': 2767 10242 chris recursive = B_TRUE; 2768 10342 chris break; 2769 10342 chris case 't': 2770 10342 chris temphold = B_TRUE; 2771 10242 chris break; 2772 10242 chris case '?': 2773 10242 chris (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2774 10242 chris optopt); 2775 10242 chris usage(B_FALSE); 2776 10242 chris } 2777 10242 chris } 2778 10242 chris 2779 10242 chris argc -= optind; 2780 10242 chris argv += optind; 2781 10242 chris 2782 10242 chris /* check number of arguments */ 2783 10242 chris if (argc < 2) 2784 10242 chris usage(B_FALSE); 2785 10242 chris 2786 10242 chris tag = argv[0]; 2787 10242 chris --argc; 2788 10242 chris ++argv; 2789 10242 chris 2790 10342 chris if (holding && tag[0] == '.') { 2791 10342 chris /* tags starting with '.' are reserved for libzfs */ 2792 10342 chris (void) fprintf(stderr, gettext("tag may not start with '.'\n")); 2793 10342 chris usage(B_FALSE); 2794 10242 chris } 2795 10242 chris 2796 10242 chris for (i = 0; i < argc; ++i) { 2797 10242 chris zfs_handle_t *zhp; 2798 10242 chris char parent[ZFS_MAXNAMELEN]; 2799 10242 chris const char *delim; 2800 10242 chris char *path = argv[i]; 2801 10242 chris 2802 10242 chris delim = strchr(path, '@'); 2803 10242 chris if (delim == NULL) { 2804 10242 chris (void) fprintf(stderr, 2805 10242 chris gettext("'%s' is not a snapshot\n"), path); 2806 10242 chris ++errors; 2807 10242 chris continue; 2808 10242 chris } 2809 10242 chris (void) strncpy(parent, path, delim - path); 2810 10242 chris parent[delim - path] = '\0'; 2811 10242 chris 2812 10242 chris zhp = zfs_open(g_zfs, parent, 2813 10242 chris ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); 2814 10242 chris if (zhp == NULL) { 2815 10242 chris ++errors; 2816 10242 chris continue; 2817 10242 chris } 2818 10342 chris if (holding) { 2819 10342 chris if (zfs_hold(zhp, delim+1, tag, recursive, 2820 10342 chris temphold) != 0) 2821 10342 chris ++errors; 2822 10342 chris } else { 2823 10342 chris if (zfs_release(zhp, delim+1, tag, recursive) != 0) 2824 10342 chris ++errors; 2825 10342 chris } 2826 10242 chris zfs_close(zhp); 2827 10242 chris } 2828 10242 chris 2829 10242 chris return (errors != 0); 2830 10242 chris } 2831 10242 chris 2832 10242 chris /* 2833 10342 chris * zfs hold [-r] [-t] <tag> <snap> ... 2834 10242 chris * 2835 11022 Tom * -r Recursively hold 2836 10342 chris * -t Temporary hold (hidden option) 2837 10242 chris * 2838 10242 chris * Apply a user-hold with the given tag to the list of snapshots. 2839 10242 chris */ 2840 10242 chris static int 2841 10242 chris zfs_do_hold(int argc, char **argv) 2842 10242 chris { 2843 10242 chris return (zfs_do_hold_rele_impl(argc, argv, B_TRUE)); 2844 10242 chris } 2845 10242 chris 2846 10242 chris /* 2847 10242 chris * zfs release [-r] <tag> <snap> ... 2848 10242 chris * 2849 11022 Tom * -r Recursively release 2850 10242 chris * 2851 10242 chris * Release a user-hold with the given tag from the list of snapshots. 2852 10242 chris */ 2853 10242 chris static int 2854 10242 chris zfs_do_release(int argc, char **argv) 2855 10242 chris { 2856 10242 chris return (zfs_do_hold_rele_impl(argc, argv, B_FALSE)); 2857 10242 chris } 2858 10242 chris 2859 1356 eschrock typedef struct get_all_cbdata { 2860 1356 eschrock zfs_handle_t **cb_handles; 2861 1356 eschrock size_t cb_alloc; 2862 1356 eschrock size_t cb_used; 2863 3126 ahl uint_t cb_types; 2864 4737 mmusante boolean_t cb_verbose; 2865 1356 eschrock } get_all_cbdata_t; 2866 4737 mmusante 2867 4737 mmusante #define CHECK_SPINNER 30 2868 4737 mmusante #define SPINNER_TIME 3 /* seconds */ 2869 4737 mmusante #define MOUNT_TIME 5 /* seconds */ 2870 1356 eschrock 2871 1356 eschrock static int 2872 3126 ahl get_one_dataset(zfs_handle_t *zhp, void *data) 2873 1356 eschrock { 2874 4737 mmusante static char spin[] = { '-', '\\', '|', '/' }; 2875 4737 mmusante static int spinval = 0; 2876 4737 mmusante static int spincheck = 0; 2877 4737 mmusante static time_t last_spin_time = (time_t)0; 2878 1356 eschrock get_all_cbdata_t *cbp = data; 2879 3126 ahl zfs_type_t type = zfs_get_type(zhp); 2880 4737 mmusante 2881 4737 mmusante if (cbp->cb_verbose) { 2882 4737 mmusante if (--spincheck < 0) { 2883 4737 mmusante time_t now = time(NULL); 2884 4737 mmusante if (last_spin_time + SPINNER_TIME < now) { 2885 4737 mmusante (void) printf("\b%c", spin[spinval++ % 4]); 2886 4737 mmusante (void) fflush(stdout); 2887 4737 mmusante last_spin_time = now; 2888 4737 mmusante } 2889 4737 mmusante spincheck = CHECK_SPINNER; 2890 4737 mmusante } 2891 4737 mmusante } 2892 1356 eschrock 2893 1356 eschrock /* 2894 3126 ahl * Interate over any nested datasets. 2895 1356 eschrock */ 2896 3126 ahl if (type == ZFS_TYPE_FILESYSTEM && 2897 3126 ahl zfs_iter_filesystems(zhp, get_one_dataset, data) != 0) { 2898 3265 ahrens zfs_close(zhp); 2899 3126 ahl return (1); 2900 3126 ahl } 2901 3126 ahl 2902 3126 ahl /* 2903 3126 ahl * Skip any datasets whose type does not match. 2904 3126 ahl */ 2905 3126 ahl if ((type & cbp->cb_types) == 0) { 2906 1356 eschrock zfs_close(zhp); 2907 1356 eschrock return (0); 2908 1356 eschrock } 2909 1356 eschrock 2910 1356 eschrock if (cbp->cb_alloc == cbp->cb_used) { 2911 1356 eschrock zfs_handle_t **handles; 2912 1356 eschrock 2913 1356 eschrock if (cbp->cb_alloc == 0) 2914 1356 eschrock cbp->cb_alloc = 64; 2915 1356 eschrock else 2916 1356 eschrock cbp->cb_alloc *= 2; 2917 1356 eschrock 2918 1356 eschrock handles = safe_malloc(cbp->cb_alloc * sizeof (void *)); 2919 1356 eschrock 2920 1356 eschrock if (cbp->cb_handles) { 2921 1356 eschrock bcopy(cbp->cb_handles, handles, 2922 1356 eschrock cbp->cb_used * sizeof (void *)); 2923 1356 eschrock free(cbp->cb_handles); 2924 1356 eschrock } 2925 1356 eschrock 2926 1356 eschrock cbp->cb_handles = handles; 2927 1356 eschrock } 2928 1356 eschrock 2929 1356 eschrock cbp->cb_handles[cbp->cb_used++] = zhp; 2930 1356 eschrock 2931 3126 ahl return (0); 2932 1356 eschrock } 2933 1356 eschrock 2934 1356 eschrock static void 2935 4737 mmusante get_all_datasets(uint_t types, zfs_handle_t ***dslist, size_t *count, 2936 4737 mmusante boolean_t verbose) 2937 1356 eschrock { 2938 1356 eschrock get_all_cbdata_t cb = { 0 }; 2939 3126 ahl cb.cb_types = types; 2940 4737 mmusante cb.cb_verbose = verbose; 2941 4737 mmusante 2942 4737 mmusante if (verbose) { 2943 4737 mmusante (void) printf("%s: *", gettext("Reading ZFS config")); 2944 4737 mmusante (void) fflush(stdout); 2945 4737 mmusante } 2946 1356 eschrock 2947 3126 ahl (void) zfs_iter_root(g_zfs, get_one_dataset, &cb); 2948 1356 eschrock 2949 3126 ahl *dslist = cb.cb_handles; 2950 1356 eschrock *count = cb.cb_used; 2951 4737 mmusante 2952 4737 mmusante if (verbose) { 2953 4737 mmusante (void) printf("\b%s\n", gettext("done.")); 2954 4737 mmusante } 2955 1356 eschrock } 2956 1356 eschrock 2957 1356 eschrock static int 2958 3126 ahl dataset_cmp(const void *a, const void *b) 2959 1356 eschrock { 2960 1356 eschrock zfs_handle_t **za = (zfs_handle_t **)a; 2961 1356 eschrock zfs_handle_t **zb = (zfs_handle_t **)b; 2962 1356 eschrock char mounta[MAXPATHLEN]; 2963 1356 eschrock char mountb[MAXPATHLEN]; 2964 3126 ahl boolean_t gota, gotb; 2965 1356 eschrock 2966 3126 ahl if ((gota = (zfs_get_type(*za) == ZFS_TYPE_FILESYSTEM)) != 0) 2967 3126 ahl verify(zfs_prop_get(*za, ZFS_PROP_MOUNTPOINT, mounta, 2968 3126 ahl sizeof (mounta), NULL, NULL, 0, B_FALSE) == 0); 2969 3126 ahl if ((gotb = (zfs_get_type(*zb) == ZFS_TYPE_FILESYSTEM)) != 0) 2970 3126 ahl verify(zfs_prop_get(*zb, ZFS_PROP_MOUNTPOINT, mountb, 2971 3126 ahl sizeof (mountb), NULL, NULL, 0, B_FALSE) == 0); 2972 1356 eschrock 2973 3126 ahl if (gota && gotb) 2974 3126 ahl return (strcmp(mounta, mountb)); 2975 3126 ahl 2976 3126 ahl if (gota) 2977 3126 ahl return (-1); 2978 3126 ahl if (gotb) 2979 3126 ahl return (1); 2980 3126 ahl 2981 3126 ahl return (strcmp(zfs_get_name(a), zfs_get_name(b))); 2982 1356 eschrock } 2983 789 ahrens 2984 789 ahrens /* 2985 789 ahrens * Generic callback for sharing or mounting filesystems. Because the code is so 2986 789 ahrens * similar, we have a common function with an extra parameter to determine which 2987 789 ahrens * mode we are using. 2988 789 ahrens */ 2989 789 ahrens #define OP_SHARE 0x1 2990 789 ahrens #define OP_MOUNT 0x2 2991 789 ahrens 2992 789 ahrens /* 2993 3126 ahl * Share or mount a dataset. 2994 789 ahrens */ 2995 789 ahrens static int 2996 5331 amw share_mount_one(zfs_handle_t *zhp, int op, int flags, char *protocol, 2997 5331 amw boolean_t explicit, const char *options) 2998 789 ahrens { 2999 789 ahrens char mountpoint[ZFS_MAXPROPLEN]; 3000 789 ahrens char shareopts[ZFS_MAXPROPLEN]; 3001 5331 amw char smbshareopts[ZFS_MAXPROPLEN]; 3002 3126 ahl const char *cmdname = op == OP_SHARE ? "share" : "mount"; 3003 789 ahrens struct mnttab mnt; 3004 2676 eschrock uint64_t zoned, canmount; 3005 3126 ahl zfs_type_t type = zfs_get_type(zhp); 3006 5331 amw boolean_t shared_nfs, shared_smb; 3007 789 ahrens 3008 3126 ahl assert(type & (ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)); 3009 789 ahrens 3010 3126 ahl if (type == ZFS_TYPE_FILESYSTEM) { 3011 3126 ahl /* 3012 3126 ahl * Check to make sure we can mount/share this dataset. If we 3013 3126 ahl * are in the global zone and the filesystem is exported to a 3014 3126 ahl * local zone, or if we are in a local zone and the 3015 3126 ahl * filesystem is not exported, then it is an error. 3016 3126 ahl */ 3017 3126 ahl zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED); 3018 789 ahrens 3019 3126 ahl if (zoned && getzoneid() == GLOBAL_ZONEID) { 3020 3126 ahl if (!explicit) 3021 3126 ahl return (0); 3022 789 ahrens 3023 3126 ahl (void) fprintf(stderr, gettext("cannot %s '%s': " 3024 3126 ahl "dataset is exported to a local zone\n"), cmdname, 3025 3126 ahl zfs_get_name(zhp)); 3026 3126 ahl return (1); 3027 789 ahrens 3028 3126 ahl } else if (!zoned && getzoneid() != GLOBAL_ZONEID) { 3029 3126 ahl if (!explicit) 3030 3126 ahl return (0); 3031 789 ahrens 3032 3126 ahl (void) fprintf(stderr, gettext("cannot %s '%s': " 3033 3126 ahl "permission denied\n"), cmdname, 3034 3126 ahl zfs_get_name(zhp)); 3035 3126 ahl return (1); 3036 3126 ahl } 3037 789 ahrens 3038 3126 ahl /* 3039 3126 ahl * Ignore any filesystems which don't apply to us. This 3040 3126 ahl * includes those with a legacy mountpoint, or those with 3041 3126 ahl * legacy share options. 3042 3126 ahl */ 3043 3126 ahl verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint, 3044 3126 ahl sizeof (mountpoint), NULL, NULL, 0, B_FALSE) == 0); 3045 3126 ahl verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS, shareopts, 3046 3126 ahl sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0); 3047 5331 amw verify(zfs_prop_get(zhp, ZFS_PROP_SHARESMB, smbshareopts, 3048 5331 amw sizeof (smbshareopts), NULL, NULL, 0, B_FALSE) == 0); 3049 789 ahrens 3050 5331 amw if (op == OP_SHARE && strcmp(shareopts, "off") == 0 && 3051 5331 amw strcmp(smbshareopts, "off") == 0) { 3052 3126 ahl if (!explicit) 3053 789 ahrens return (0); 3054 789 ahrens 3055 789 ahrens (void) fprintf(stderr, gettext("cannot share '%s': " 3056 789 ahrens "legacy share\n"), zfs_get_name(zhp)); 3057 789 ahrens (void) fprintf(stderr, gettext("use share(1M) to " 3058 8269 Mark "share this filesystem, or set " 3059 8269 Mark "sharenfs property on\n")); 3060 789 ahrens return (1); 3061 789 ahrens } 3062 789 ahrens 3063 3126 ahl /* 3064 3126 ahl * We cannot share or mount legacy filesystems. If the 3065 3126 ahl * shareopts is non-legacy but the mountpoint is legacy, we 3066 3126 ahl * treat it as a legacy share. 3067 3126 ahl */ 3068 3126 ahl if (strcmp(mountpoint, "legacy") == 0) { 3069 3126 ahl if (!explicit) 3070 3126 ahl return (0); 3071 789 ahrens 3072 3126 ahl (void) fprintf(stderr, gettext("cannot %s '%s': " 3073 3126 ahl "legacy mountpoint\n"), cmdname, zfs_get_name(zhp)); 3074 5367 ahrens (void) fprintf(stderr, gettext("use %s(1M) to " 3075 5367 ahrens "%s this filesystem\n"), cmdname, cmdname); 3076 3126 ahl return (1); 3077 3126 ahl } 3078 789 ahrens 3079 3126 ahl if (strcmp(mountpoint, "none") == 0) { 3080 3126 ahl if (!explicit) 3081 3126 ahl return (0); 3082 789 ahrens 3083 3126 ahl (void) fprintf(stderr, gettext("cannot %s '%s': no " 3084 3126 ahl "mountpoint set\n"), cmdname, zfs_get_name(zhp)); 3085 3126 ahl return (1); 3086 3126 ahl } 3087 2676 eschrock 3088 6168 hs24103 /* 3089 6168 hs24103 * canmount explicit outcome 3090 6168 hs24103 * on no pass through 3091 6168 hs24103 * on yes pass through 3092 6168 hs24103 * off no return 0 3093 6168 hs24103 * off yes display error, return 1 3094 6168 hs24103 * noauto no return 0 3095 6168 hs24103 * noauto yes pass through 3096 6168 hs24103 */ 3097 8269 Mark canmount = zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT); 3098 6168 hs24103 if (canmount == ZFS_CANMOUNT_OFF) { 3099 3126 ahl if (!explicit) 3100 3126 ahl return (0); 3101 2676 eschrock