Hi Chris, I updated my git repository. You can pull from git pull http://cassiopea.homelinux.net/git/btrfs-command.git mlc-subvol (branch mlc-subvol, commit e59135a27dc1fde6acc4fb198499be2b6cbd9f6f) $ git diff remotes/origin/subvol | diffstat btrfs-list.c | 15 +++-- btrfs.c | 56 +++++++++++++++++- btrfs_cmds.c | 84 +++++++++++++++++----------- btrfs_cmds.h | 1 man/btrfs.8.in | 150 +++++++++++++++++++++++++++++++++++++++++++++[...] 5 files changed, 283 insertions(+), 43 deletions(-) As you requested I update the parser in order set the argv[0] argument as the program name + the verb. For example if I do $ btrfs dev add the argv[0] will be equal to "btrfs device add". I hope that is what you requested. Due to this change I update all the commands in order to evaluate the arguments from argv[1] and not from argv[0] anymore. (I update also your do_defrag() function) Also because I implemented that already the week ago: - I made some small modification to btrfs-list.c in order to be more friendly in case of error (replace some "exit(2)" with "return -ERR") - I implemented the command "btrf subvolume set-default" Hoping that this can you help Regards G.Baroncelli diff --git a/btrfs-list.c b/btrfs-list.c index 6305d3c..f2f119b 100644 --- a/btrfs-list.c +++ b/btrfs-list.c @@ -66,7 +66,7 @@ struct root_info { char name[]; }; -void root_lookup_init(struct root_lookup *tree) +static void root_lookup_init(struct root_lookup *tree) { tree->root.rb_node = NULL; } @@ -275,9 +275,9 @@ static int lookup_ino_path(int fd, struct root_info *ri) ret = ioctl(fd, BTRFS_IOC_INO_LOOKUP, &args); if (ret) { - fprintf(stderr, "Failed to lookup path for root %llu\n", + fprintf(stderr, "ERROR: Failed to lookup path for root %llu\n", (unsigned long long)ri->ref_tree); - exit(1); + return ret; } if (args.name[0]) { @@ -346,8 +346,8 @@ int list_subvols(int fd) while(1) { ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args); if (ret < 0) { - perror("ioctl:"); - break; + fprintf(stderr, "ERROR: can't perform the search\n"); + return ret; } /* the ioctl returns the number of item it found in nr_items */ if (sk->nr_items == 0) @@ -398,8 +398,11 @@ int list_subvols(int fd) n = rb_first(&root_lookup.root); while (n) { struct root_info *entry; + int ret; entry = rb_entry(n, struct root_info, rb_node); - lookup_ino_path(fd, entry); + ret = lookup_ino_path(fd, entry); + if(ret < 0) + return ret; n = rb_next(n); } diff --git a/btrfs.c b/btrfs.c index 20f7413..58271f6 100644 --- a/btrfs.c +++ b/btrfs.c @@ -60,10 +60,15 @@ static struct Command commands[] = { { do_subvol_list, 1, "subvolume list", "<path>\n" "List the snapshot/subvolume of a filesystem." }, - { do_defrag, -1, "filesystem defragment", "[-vcf] [-s start] [-l len] [-t size] <file>|<dir> [<file>|<dir>...]\n" "Defragment a file or a directory." + + }, + { do_set_default_subvol, 2, + "subvolume set-default", "<id> <path>\n" + "Set the subvolume of the filesystem <path> which will be mounted\n" + "as default." }, { do_fssync, 1, "filesystem sync", "<path>\n" @@ -88,11 +93,12 @@ static struct Command commands[] = { "Scan all device for or the passed device for a btrfs\n" "filesystem." }, - { do_add_volume, -1, + + { do_add_volume, -2, "device add", "<dev> [<dev>..] <path>\n" "Add a device to a filesystem." }, - { do_remove_volume, -1, + { do_remove_volume, -2, "device delete", "<dev> [<dev>..] <path>\n" "Remove a device from a filesystem." }, @@ -208,6 +214,41 @@ static int check_ambiguity(struct Command *cmd, char **argv){ } /* + * This function, compacts the program name and the command in the first + * element of the '*av' array + */ +static int prepare_args(int *ac, char ***av, char *prgname, struct Command *cmd ){ + + char **ret; + int i; + char *newname; + + ret = (char **)malloc(sizeof(char*)*(*ac+1)); + newname = (char*)malloc(strlen(prgname)+strlen(cmd->verb)+2); + if( !ret || !newname ){ + free(ret); + free(newname); + return -1; + } + + ret[0] = newname; + for(i=0; i < *ac ; i++ ) + ret[i+1] = (*av)[i]; + + strcpy(newname, prgname); + strcat(newname, " "); + strcat(newname, cmd->verb); + + (*ac)++; + *av = ret; + + return 0; + +} + + + +/* This function perform the following jobs: - show the help if '--help' or 'help' or '-h' are passed @@ -307,11 +348,18 @@ static int parse_args(int argc, char **argv, matchcmd->verb, -matchcmd->nargs); return -2; } - if(matchcmd->nargs >= 0 && matchcmd->nargs != *nargs_ && matchcmd- >nargs != 999 ){ + + if(matchcmd->nargs >= 0 && matchcmd->nargs != *nargs_ && matchcmd- >nargs != 999){ fprintf(stderr, "ERROR: '%s' requires %d arg(s)\n", matchcmd->verb, matchcmd->nargs); return -2; } + + if (prepare_args( nargs_, args_, prgname, matchcmd )){ + fprintf(stderr, "ERROR: not enough memory\\n"); + return -20; + } + return 1; } diff --git a/btrfs_cmds.c b/btrfs_cmds.c index 3a21be3..89f47c2 100644 --- a/btrfs_cmds.c +++ b/btrfs_cmds.c @@ -59,7 +59,7 @@ static inline int ioctl(int fd, int define, void *arg) { return 0; } static int test_issubvolume(char *path) { - struct stat st; + struct stat st; int res; res = stat(path, &st); @@ -79,7 +79,7 @@ static int test_issubvolume(char *path) */ static int test_isdir(char *path) { - struct stat st; + struct stat st; int res; res = stat(path, &st); @@ -142,7 +142,7 @@ static u64 parse_size(char *s) return atoll(s) * mult; } -int do_defrag(int ac, char **avp) +int do_defrag(int ac, char **av) { int fd; int compress = 0; @@ -156,17 +156,6 @@ int do_defrag(int ac, char **avp) int verbose = 0; int fancy_ioctl = 0; struct btrfs_ioctl_defrag_range_args range; - char **av; - - /* - * getopt expects av[0] to be the program name and it seems - * to get confused when this isn't the case - */ - av = malloc((ac + 2) * sizeof(char *)); - av[0] = "defrag"; - av[ac + 1] = NULL; - memcpy(av + 1, avp, ac * sizeof(char *)); - ac += 1; optind = 1; while(1) { @@ -264,7 +253,7 @@ int do_subvol_list(int argc, char **argv) int ret; char *subvol; - subvol = argv[0]; + subvol = argv[1]; ret = test_issubvolume(subvol); if (ret < 0) { @@ -289,13 +278,13 @@ int do_subvol_list(int argc, char **argv) int do_clone(int argc, char **argv) { - char *subvol, *dst; + char *subvol, *dst; int res, fd, fddst, len; char *newname; char *dstdir; - subvol = argv[0]; - dst = argv[1]; + subvol = argv[1]; + dst = argv[2]; struct btrfs_ioctl_vol_args args; res = test_issubvolume(subvol); @@ -375,7 +364,7 @@ int do_delete_subvolume(int argc, char **argv) int res, fd, len; struct btrfs_ioctl_vol_args args; char *dname, *vname, *cpath; - char *path = argv[0]; + char *path = argv[1]; res = test_issubvolume(path); if(res<0){ @@ -436,7 +425,7 @@ int do_create_subvol(int argc, char **argv) char *newname; char *dstdir; struct btrfs_ioctl_vol_args args; - char *dst = argv[0]; + char *dst = argv[1]; res = test_isdir(dst); if(res >= 0 ){ @@ -487,7 +476,7 @@ int do_create_subvol(int argc, char **argv) int do_fssync(int argc, char **argv) { int fd, res; - char *path = argv[0]; + char *path = argv[1]; fd = open_file_or_dir(path); if (fd < 0) { @@ -506,10 +495,10 @@ int do_fssync(int argc, char **argv) return 0; } -int do_scan(int nargs, char **argv) +int do_scan(int argc, char **argv) { int i, fd; - if(!nargs){ + if(argc<=1){ int ret; printf("Scanning for Btrfs filesystems\n"); @@ -527,8 +516,8 @@ int do_scan(int nargs, char **argv) return 10; } - for( i = 0 ; i < nargs ; i++ ){ - struct btrfs_ioctl_vol_args args; + for( i = 1 ; i < argc ; i++ ){ + struct btrfs_ioctl_vol_args args; int ret; printf("Scanning for Btrfs filesystems in '%s'\n", argv[i]); @@ -558,8 +547,8 @@ int do_resize(int argc, char **argv) struct btrfs_ioctl_vol_args args; int fd, res, len; - char *amount=argv[0], *path=argv[1]; - + char *amount=argv[1], *path=argv[2]; + fd = open_file_or_dir(path); if (fd < 0) { fprintf(stderr, "ERROR: can't access to '%s'\n", path); @@ -646,7 +635,7 @@ int do_show_filesystem(int argc, char **argv) struct list_head *all_uuids; struct btrfs_fs_devices *fs_devices; struct list_head *cur_uuid; - char *search = argv[0]; + char *search = argv[1]; int ret; ret = btrfs_scan_one_dir("/dev", 0); @@ -680,8 +669,8 @@ int do_add_volume(int nargs, char **args) return 12; } - for(i=0 ; i < (nargs-1) ; i++ ){ - struct btrfs_ioctl_vol_args ioctl_args; + for(i=1 ; i < (nargs-1) ; i++ ){ + struct btrfs_ioctl_vol_args ioctl_args; int devfd, res; u64 dev_block_count = 0; struct stat st; @@ -737,8 +726,8 @@ int do_balance(int argc, char **argv) { int fdmnt, ret=0; - char *path = argv[0]; struct btrfs_ioctl_vol_args args; + char *path = argv[1]; fdmnt = open_file_or_dir(path); if (fdmnt < 0) { @@ -768,8 +757,8 @@ int do_remove_volume(int nargs, char **args) return 12; } - for(i=0 ; i < (nargs-1) ; i++ ){ - struct btrfs_ioctl_vol_args arg; + for(i=1 ; i < (nargs-1) ; i++ ){ + struct btrfs_ioctl_vol_args arg; int res; strcpy(arg.name, args[i]); @@ -786,3 +775,32 @@ int do_remove_volume(int nargs, char **args) else return 0; } + +int do_set_default_subvol(int nargs, char **argv) +{ + int ret=0, fd; + u64 objectid; + char *path = argv[2]; + char *subvolid = argv[1]; + + fd = open_file_or_dir(path); + if (fd < 0) { + fprintf(stderr, "ERROR: can't access to '%s'\n", path); + return 12; + } + + objectid = (unsigned long long)strtoll(subvolid, NULL, 0); + if (errno == ERANGE) { + fprintf(stderr, "ERROR: invalid tree id (%s)\n",subvolid); + return 30; + } + ret = ioctl(fd, BTRFS_IOC_DEFAULT_SUBVOL, &objectid); + close(fd); + if( ret < 0 ){ + fprintf(stderr, "ERROR: unable to set a new default subvolume\n"); + return 30; + } + return 0; + +} + diff --git a/btrfs_cmds.h b/btrfs_cmds.h index cfdbde2..c63baa9 100644 --- a/btrfs_cmds.h +++ b/btrfs_cmds.h @@ -27,4 +27,5 @@ int do_remove_volume(int nargs, char **args); int do_scan(int nargs, char **argv); int do_resize(int nargs, char **argv); int do_subvol_list(int nargs, char **argv); +int do_set_default_subvol(int nargs, char **argv); int list_subvols(int fd); ---- On Thursday 11 March 2010, you (Chris Mason) wrote: > Thanks for all your work on btrfs! > > -chris > > On Thu, Mar 11, 2010 at 08:03:17PM +0100, Goffredo Baroncelli wrote: > > On Thursday 11 March 2010, Chris Mason wrote: > > > Hi everyone, > > > > > > I've pushed Goffredo's new btrfs utility into the subvol branch of the > > > btrfs-progs repo. I'm using it as my starting point for the subvol > > > listing utility as well as my fancy new defrag range ioctl. > > > > > > Goffredo, the new defrag ioctl takes a bunch of arguments, and I used > > > getopt inside the command to do it. The tricky part is that getopt > > > expects argv[0] to be the command name, so I had to hack things a bit. > > > > > > Could you please send a patch that changes the commands to include the > > > command name in argv[0]? That'll make it easier to be flexible. > > > > > > > I will start to work > > > > > -chris > > > > > > > > > -- > > gpg key@ keyserver.linux.it: Goffredo Baroncelli (ghigo) <kreijack@xxxxxxxxx> > > Key fingerprint = 4769 7E51 5293 D36C 814E C054 BF04 F161 3DC5 0512 > > -- > > To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in > > the body of a message to majordomo@xxxxxxxxxxxxxxx > > More majordomo info at http://vger.kernel.org/majordomo-info.html > -- gpg key@ keyserver.linux.it: Goffredo Baroncelli (ghigo) <kreijackATinwind.it> Key fingerprint = 4769 7E51 5293 D36C 814E C054 BF04 F161 3DC5 0512
Attachment:
signature.asc
Description: This is a digitally signed message part.
