static int cmd_subvol_get_default(int argc, char **argv) { int fd = -1; int ret; char *subvol; struct btrfs_list_filter_set *filter_set; u64 default_id; DIR *dirstream = NULL; if (check_argc_exact(argc, 2)) usage(cmd_subvol_get_default_usage); subvol = argv[1]; fd = open_file_or_dir(subvol, &dirstream); if (fd < 0) { fprintf(stderr, "ERROR: can't access '%s'\n", subvol); return 1; } ret = btrfs_list_get_default_subvolume(fd, &default_id); if (ret) { fprintf(stderr, "ERROR: can't perform the search - %s\n", strerror(errno)); goto out; } ret = 1; if (default_id == 0) { fprintf(stderr, "ERROR: 'default' dir item not found\n"); goto out; } /* no need to resolve roots if FS_TREE is default */ if (default_id == BTRFS_FS_TREE_OBJECTID) { printf("ID 5 (FS_TREE)\n"); ret = 0; goto out; } filter_set = btrfs_list_alloc_filter_set(); btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_ROOTID, default_id); /* by default we shall print the following columns*/ btrfs_list_setup_print_column(BTRFS_LIST_OBJECTID); btrfs_list_setup_print_column(BTRFS_LIST_GENERATION); btrfs_list_setup_print_column(BTRFS_LIST_TOP_LEVEL); btrfs_list_setup_print_column(BTRFS_LIST_PATH); ret = btrfs_list_subvols_print(fd, filter_set, NULL, BTRFS_LIST_LAYOUT_DEFAULT, 1, NULL); if (filter_set) btrfs_list_free_filter_set(filter_set); out: close_file_or_dir(fd, dirstream); return !!ret; }
static int cmd_subvol_get_default(int argc, char **argv) { int fd = -1; int ret; char *subvol; struct btrfs_list_filter_set *filter_set; u64 default_id; DIR *dirstream = NULL; clean_args_no_options(argc, argv, cmd_subvol_get_default_usage); if (check_argc_exact(argc - optind, 1)) usage(cmd_subvol_get_default_usage); subvol = argv[1]; fd = btrfs_open_dir(subvol, &dirstream, 1); if (fd < 0) return 1; ret = btrfs_list_get_default_subvolume(fd, &default_id); if (ret) { error("failed to look up default subvolume: %s", strerror(errno)); goto out; } ret = 1; if (default_id == 0) { error("'default' dir item not found"); goto out; } /* no need to resolve roots if FS_TREE is default */ if (default_id == BTRFS_FS_TREE_OBJECTID) { printf("ID 5 (FS_TREE)\n"); ret = 0; goto out; } filter_set = btrfs_list_alloc_filter_set(); btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_ROOTID, default_id); /* by default we shall print the following columns*/ btrfs_list_setup_print_column(BTRFS_LIST_OBJECTID); btrfs_list_setup_print_column(BTRFS_LIST_GENERATION); btrfs_list_setup_print_column(BTRFS_LIST_TOP_LEVEL); btrfs_list_setup_print_column(BTRFS_LIST_PATH); ret = btrfs_list_subvols_print(fd, filter_set, NULL, BTRFS_LIST_LAYOUT_DEFAULT, 1, NULL); if (filter_set) free(filter_set); out: close_file_or_dir(fd, dirstream); return !!ret; }
static int cmd_subvol_show(int argc, char **argv) { struct root_info get_ri; struct btrfs_list_filter_set *filter_set; char tstr[256]; char uuidparse[BTRFS_UUID_UNPARSED_SIZE]; char *fullpath = NULL, *svpath = NULL, *mnt = NULL; char raw_prefix[] = "\t\t\t\t"; u64 sv_id, mntid; int fd = -1, mntfd = -1; int ret = 1; DIR *dirstream1 = NULL, *dirstream2 = NULL; if (check_argc_exact(argc, 2)) usage(cmd_subvol_show_usage); fullpath = realpath(argv[1], NULL); if (!fullpath) { fprintf(stderr, "ERROR: finding real path for '%s', %s\n", argv[1], strerror(errno)); goto out; } ret = test_issubvolume(fullpath); if (ret < 0) { fprintf(stderr, "ERROR: error accessing '%s'\n", fullpath); goto out; } if (!ret) { fprintf(stderr, "ERROR: '%s' is not a subvolume\n", fullpath); ret = 1; goto out; } ret = find_mount_root(fullpath, &mnt); if (ret < 0) { fprintf(stderr, "ERROR: find_mount_root failed on '%s': " "%s\n", fullpath, strerror(-ret)); goto out; } if (ret > 0) { fprintf(stderr, "ERROR: %s doesn't belong to btrfs mount point\n", fullpath); goto out; } ret = 1; svpath = get_subvol_name(mnt, fullpath); fd = open_file_or_dir(fullpath, &dirstream1); if (fd < 0) { fprintf(stderr, "ERROR: can't access '%s'\n", fullpath); goto out; } ret = btrfs_list_get_path_rootid(fd, &sv_id); if (ret) { fprintf(stderr, "ERROR: can't get rootid for '%s'\n", fullpath); goto out; } mntfd = open_file_or_dir(mnt, &dirstream2); if (mntfd < 0) { fprintf(stderr, "ERROR: can't access '%s'\n", mnt); goto out; } ret = btrfs_list_get_path_rootid(mntfd, &mntid); if (ret) { fprintf(stderr, "ERROR: can't get rootid for '%s'\n", mnt); goto out; } if (sv_id == BTRFS_FS_TREE_OBJECTID) { printf("%s is btrfs root\n", fullpath); goto out; } memset(&get_ri, 0, sizeof(get_ri)); get_ri.root_id = sv_id; ret = btrfs_get_subvol(mntfd, &get_ri); if (ret) { fprintf(stderr, "ERROR: can't find '%s'\n", svpath); goto out; } /* print the info */ printf("%s\n", fullpath); printf("\tName: \t\t\t%s\n", get_ri.name); if (uuid_is_null(get_ri.uuid)) strcpy(uuidparse, "-"); else uuid_unparse(get_ri.uuid, uuidparse); printf("\tUUID: \t\t\t%s\n", uuidparse); if (uuid_is_null(get_ri.puuid)) strcpy(uuidparse, "-"); else uuid_unparse(get_ri.puuid, uuidparse); printf("\tParent UUID: \t\t%s\n", uuidparse); if (uuid_is_null(get_ri.ruuid)) strcpy(uuidparse, "-"); else uuid_unparse(get_ri.ruuid, uuidparse); printf("\tReceived UUID: \t\t%s\n", uuidparse); if (get_ri.otime) { struct tm tm; localtime_r(&get_ri.otime, &tm); strftime(tstr, 256, "%Y-%m-%d %X %z", &tm); } else strcpy(tstr, "-"); printf("\tCreation time: \t\t%s\n", tstr); printf("\tSubvolume ID: \t\t%llu\n", get_ri.root_id); printf("\tGeneration: \t\t%llu\n", get_ri.gen); printf("\tGen at creation: \t%llu\n", get_ri.ogen); printf("\tParent ID: \t\t%llu\n", get_ri.ref_tree); printf("\tTop level ID: \t\t%llu\n", get_ri.top_id); if (get_ri.flags & BTRFS_ROOT_SUBVOL_RDONLY) printf("\tFlags: \t\t\treadonly\n"); else printf("\tFlags: \t\t\t-\n"); /* print the snapshots of the given subvol if any*/ printf("\tSnapshot(s):\n"); filter_set = btrfs_list_alloc_filter_set(); btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_BY_PARENT, (u64)(unsigned long)get_ri.uuid); btrfs_list_setup_print_column(BTRFS_LIST_PATH); btrfs_list_subvols_print(fd, filter_set, NULL, BTRFS_LIST_LAYOUT_RAW, 1, raw_prefix); /* clean up */ free(get_ri.path); free(get_ri.name); free(get_ri.full_path); btrfs_list_free_filter_set(filter_set); out: close_file_or_dir(fd, dirstream1); close_file_or_dir(mntfd, dirstream2); free(mnt); free(fullpath); return !!ret; }
static int cmd_subvol_list(int argc, char **argv) { struct btrfs_list_filter_set *filter_set; struct btrfs_list_comparer_set *comparer_set; u64 flags = 0; int fd = -1; u64 top_id; int ret = -1, uerr = 0; char *subvol; int is_tab_result = 0; int is_list_all = 0; int is_only_in_path = 0; DIR *dirstream = NULL; filter_set = btrfs_list_alloc_filter_set(); comparer_set = btrfs_list_alloc_comparer_set(); optind = 1; while(1) { int c; static const struct option long_options[] = { {"sort", required_argument, NULL, 'S'}, {NULL, 0, NULL, 0} }; c = getopt_long(argc, argv, "acdgopqsurRG:C:t", long_options, NULL); if (c < 0) break; switch(c) { case 'p': btrfs_list_setup_print_column(BTRFS_LIST_PARENT); break; case 'a': is_list_all = 1; break; case 'c': btrfs_list_setup_print_column(BTRFS_LIST_OGENERATION); break; case 'd': btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_DELETED, 0); break; case 'g': btrfs_list_setup_print_column(BTRFS_LIST_GENERATION); break; case 'o': is_only_in_path = 1; break; case 't': is_tab_result = 1; break; case 's': btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_SNAPSHOT_ONLY, 0); btrfs_list_setup_print_column(BTRFS_LIST_OGENERATION); btrfs_list_setup_print_column(BTRFS_LIST_OTIME); break; case 'u': btrfs_list_setup_print_column(BTRFS_LIST_UUID); break; case 'q': btrfs_list_setup_print_column(BTRFS_LIST_PUUID); break; case 'R': btrfs_list_setup_print_column(BTRFS_LIST_RUUID); break; case 'r': flags |= BTRFS_ROOT_SUBVOL_RDONLY; break; case 'G': btrfs_list_setup_print_column(BTRFS_LIST_GENERATION); ret = btrfs_list_parse_filter_string(optarg, &filter_set, BTRFS_LIST_FILTER_GEN); if (ret) { uerr = 1; goto out; } break; case 'C': btrfs_list_setup_print_column(BTRFS_LIST_OGENERATION); ret = btrfs_list_parse_filter_string(optarg, &filter_set, BTRFS_LIST_FILTER_CGEN); if (ret) { uerr = 1; goto out; } break; case 'S': ret = btrfs_list_parse_sort_string(optarg, &comparer_set); if (ret) { uerr = 1; goto out; } break; default: uerr = 1; goto out; } } if (flags) btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_FLAGS, flags); if (check_argc_exact(argc - optind, 1)) { uerr = 1; goto out; } subvol = argv[optind]; fd = open_file_or_dir(subvol, &dirstream); if (fd < 0) { ret = -1; fprintf(stderr, "ERROR: can't access '%s'\n", subvol); goto out; } ret = btrfs_list_get_path_rootid(fd, &top_id); if (ret) { fprintf(stderr, "ERROR: can't get rootid for '%s'\n", subvol); goto out; } if (is_list_all) btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_FULL_PATH, top_id); else if (is_only_in_path) btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_TOPID_EQUAL, top_id); /* by default we shall print the following columns*/ btrfs_list_setup_print_column(BTRFS_LIST_OBJECTID); btrfs_list_setup_print_column(BTRFS_LIST_GENERATION); btrfs_list_setup_print_column(BTRFS_LIST_TOP_LEVEL); btrfs_list_setup_print_column(BTRFS_LIST_PATH); if (is_tab_result) ret = btrfs_list_subvols_print(fd, filter_set, comparer_set, BTRFS_LIST_LAYOUT_TABLE, !is_list_all && !is_only_in_path, NULL); else ret = btrfs_list_subvols_print(fd, filter_set, comparer_set, BTRFS_LIST_LAYOUT_DEFAULT, !is_list_all && !is_only_in_path, NULL); out: close_file_or_dir(fd, dirstream); if (filter_set) btrfs_list_free_filter_set(filter_set); if (comparer_set) btrfs_list_free_comparer_set(comparer_set); if (uerr) usage(cmd_subvol_list_usage); return !!ret; }
static int cmd_subvol_show(int argc, char **argv) { struct root_info get_ri; struct btrfs_list_filter_set *filter_set = NULL; char tstr[256]; char uuidparse[BTRFS_UUID_UNPARSED_SIZE]; char *fullpath = NULL; char raw_prefix[] = "\t\t\t\t"; int fd = -1; int ret = 1; DIR *dirstream1 = NULL; clean_args_no_options(argc, argv, cmd_subvol_show_usage); if (check_argc_exact(argc - optind, 1)) usage(cmd_subvol_show_usage); memset(&get_ri, 0, sizeof(get_ri)); fullpath = realpath(argv[optind], NULL); if (!fullpath) { error("cannot find real path for '%s': %s", argv[optind], strerror(errno)); goto out; } ret = get_subvol_info(fullpath, &get_ri); if (ret == 2) { /* * Since the top level btrfs was given don't * take that as error */ printf("%s is toplevel subvolume\n", fullpath); ret = 0; goto out; } if (ret) { if (ret < 0) { error("Failed to get subvol info %s: %s\n", fullpath, strerror(-ret)); } else { error("Failed to get subvol info %s: %d\n", fullpath, ret); } return ret; } /* print the info */ printf("%s\n", fullpath); printf("\tName: \t\t\t%s\n", get_ri.name); if (uuid_is_null(get_ri.uuid)) strcpy(uuidparse, "-"); else uuid_unparse(get_ri.uuid, uuidparse); printf("\tUUID: \t\t\t%s\n", uuidparse); if (uuid_is_null(get_ri.puuid)) strcpy(uuidparse, "-"); else uuid_unparse(get_ri.puuid, uuidparse); printf("\tParent UUID: \t\t%s\n", uuidparse); if (uuid_is_null(get_ri.ruuid)) strcpy(uuidparse, "-"); else uuid_unparse(get_ri.ruuid, uuidparse); printf("\tReceived UUID: \t\t%s\n", uuidparse); if (get_ri.otime) { struct tm tm; localtime_r(&get_ri.otime, &tm); strftime(tstr, 256, "%Y-%m-%d %X %z", &tm); } else strcpy(tstr, "-"); printf("\tCreation time: \t\t%s\n", tstr); printf("\tSubvolume ID: \t\t%llu\n", get_ri.root_id); printf("\tGeneration: \t\t%llu\n", get_ri.gen); printf("\tGen at creation: \t%llu\n", get_ri.ogen); printf("\tParent ID: \t\t%llu\n", get_ri.ref_tree); printf("\tTop level ID: \t\t%llu\n", get_ri.top_id); if (get_ri.flags & BTRFS_ROOT_SUBVOL_RDONLY) printf("\tFlags: \t\t\treadonly\n"); else printf("\tFlags: \t\t\t-\n"); /* print the snapshots of the given subvol if any*/ printf("\tSnapshot(s):\n"); filter_set = btrfs_list_alloc_filter_set(); btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_BY_PARENT, (u64)(unsigned long)get_ri.uuid); btrfs_list_setup_print_column(BTRFS_LIST_PATH); fd = open_file_or_dir(fullpath, &dirstream1); if (fd < 0) { fprintf(stderr, "ERROR: can't access '%s'\n", fullpath); goto out; } btrfs_list_subvols_print(fd, filter_set, NULL, BTRFS_LIST_LAYOUT_RAW, 1, raw_prefix); out: /* clean up */ free(get_ri.path); free(get_ri.name); free(get_ri.full_path); free(filter_set); close_file_or_dir(fd, dirstream1); free(fullpath); return !!ret; }