diff options
-rw-r--r-- | cmds-device.c | 60 | ||||
-rw-r--r-- | cmds-replace.c | 13 | ||||
-rw-r--r-- | utils.c | 58 | ||||
-rw-r--r-- | utils.h | 2 |
4 files changed, 118 insertions, 15 deletions
diff --git a/cmds-device.c b/cmds-device.c index 29da661e..d7af0901 100644 --- a/cmds-device.c +++ b/cmds-device.c @@ -94,6 +94,7 @@ static int cmd_add_dev(int argc, char **argv) int devfd, res; u64 dev_block_count = 0; int mixed = 0; + char *path; res = test_dev_for_mkfs(argv[i], force, estr); if (res) { @@ -117,15 +118,24 @@ static int cmd_add_dev(int argc, char **argv) goto error_out; } - strncpy_null(ioctl_args.name, argv[i]); + path = canonicalize_path(argv[i]); + if (!path) { + fprintf(stderr, + "ERROR: Could not canonicalize pathname '%s': %s\n", + argv[i], strerror(errno)); + ret++; + goto error_out; + } + + strncpy_null(ioctl_args.name, path); res = ioctl(fdmnt, BTRFS_IOC_ADD_DEV, &ioctl_args); e = errno; - if(res<0){ + if (res < 0) { fprintf(stderr, "ERROR: error adding the device '%s' - %s\n", - argv[i], strerror(e)); + path, strerror(e)); ret++; } - + free(path); } error_out: @@ -241,6 +251,7 @@ static int cmd_scan_dev(int argc, char **argv) for( i = devstart ; i < argc ; i++ ){ struct btrfs_ioctl_vol_args args; + char *path; if (!is_block_device(argv[i])) { fprintf(stderr, @@ -248,9 +259,17 @@ static int cmd_scan_dev(int argc, char **argv) ret = 1; goto close_out; } - printf("Scanning for Btrfs filesystems in '%s'\n", argv[i]); + path = canonicalize_path(argv[i]); + if (!path) { + fprintf(stderr, + "ERROR: Could not canonicalize path '%s': %s\n", + argv[i], strerror(errno)); + ret = 1; + goto close_out; + } + printf("Scanning for Btrfs filesystems in '%s'\n", path); - strncpy_null(args.name, argv[i]); + strncpy_null(args.name, path); /* * FIXME: which are the error code returned by this ioctl ? * it seems that is impossible to understand if there no is @@ -261,9 +280,11 @@ static int cmd_scan_dev(int argc, char **argv) if( ret < 0 ){ fprintf(stderr, "ERROR: unable to scan the device '%s' - %s\n", - argv[i], strerror(e)); + path, strerror(e)); + free(path); goto close_out; } + free(path); } close_out: @@ -283,6 +304,7 @@ static int cmd_ready_dev(int argc, char **argv) struct btrfs_ioctl_vol_args args; int fd; int ret; + char *path; if (check_argc_min(argc, 2)) usage(cmd_ready_dev_usage); @@ -292,22 +314,34 @@ static int cmd_ready_dev(int argc, char **argv) perror("failed to open /dev/btrfs-control"); return 1; } - if (!is_block_device(argv[1])) { + + path = canonicalize_path(argv[argc - 1]); + if (!path) { fprintf(stderr, - "ERROR: %s is not a block device\n", argv[1]); - close(fd); - return 1; + "ERROR: Could not canonicalize pathname '%s': %s\n", + argv[argc - 1], strerror(errno)); + ret = 1; + goto out; } - strncpy(args.name, argv[argc - 1], BTRFS_PATH_NAME_MAX); + if (!is_block_device(path)) { + fprintf(stderr, + "ERROR: %s is not a block device\n", path); + ret = 1; + goto out; + } + + strncpy(args.name, path, BTRFS_PATH_NAME_MAX); ret = ioctl(fd, BTRFS_IOC_DEVICES_READY, &args); if (ret < 0) { fprintf(stderr, "ERROR: unable to determine if the device '%s'" - " is ready for mounting - %s\n", argv[argc - 1], + " is ready for mounting - %s\n", path, strerror(errno)); ret = 1; } +out: + free(path); close(fd); return ret; } diff --git a/cmds-replace.c b/cmds-replace.c index 9eb981ba..186a127f 100644 --- a/cmds-replace.c +++ b/cmds-replace.c @@ -134,7 +134,7 @@ static int cmd_start_replace(int argc, char **argv) int fddstdev = -1; char *path; char *srcdev; - char *dstdev; + char *dstdev = NULL; int avoid_reading_from_srcdev = 0; int force_using_targetdev = 0; struct stat st; @@ -209,7 +209,12 @@ static int cmd_start_replace(int argc, char **argv) } srcdev = argv[optind]; - dstdev = argv[optind + 1]; + dstdev = canonicalize_path(argv[optind + 1]); + if (!dstdev) { + fprintf(stderr, + "ERROR: Could not canonicalize path '%s': %s\n", + argv[optind + 1], strerror(errno)); + } if (is_numerical(srcdev)) { struct btrfs_ioctl_fs_info_args fi_args; @@ -283,6 +288,8 @@ static int cmd_start_replace(int argc, char **argv) close(fddstdev); fddstdev = -1; + free(dstdev); + dstdev = NULL; dev_replace_handle_sigint(fdmnt); if (!do_not_background) { @@ -317,6 +324,8 @@ static int cmd_start_replace(int argc, char **argv) return 0; leave_with_error: + if (dstdev) + free(dstdev); if (fdmnt != -1) close(fdmnt); if (fdsrcdev != -1) @@ -1027,6 +1027,64 @@ static int blk_file_in_dev_list(struct btrfs_fs_devices* fs_devices, } /* + * Resolve a pathname to a device mapper node to /dev/mapper/<name> + * Returns NULL on invalid input or malloc failure; Other failures + * will be handled by the caller using the input pathame. + */ +char *canonicalize_dm_name(const char *ptname) +{ + FILE *f; + size_t sz; + char path[PATH_MAX], name[PATH_MAX], *res = NULL; + + if (!ptname || !*ptname) + return NULL; + + snprintf(path, sizeof(path), "/sys/block/%s/dm/name", ptname); + if (!(f = fopen(path, "r"))) + return NULL; + + /* read <name>\n from sysfs */ + if (fgets(name, sizeof(name), f) && (sz = strlen(name)) > 1) { + name[sz - 1] = '\0'; + snprintf(path, sizeof(path), "/dev/mapper/%s", name); + + if (access(path, F_OK) == 0) + res = strdup(path); + } + fclose(f); + return res; +} + +/* + * Resolve a pathname to a canonical device node, e.g. /dev/sda1 or + * to a device mapper pathname. + * Returns NULL on invalid input or malloc failure; Other failures + * will be handled by the caller using the input pathame. + */ +char *canonicalize_path(const char *path) +{ + char *canonical, *p; + + if (!path || !*path) + return NULL; + + canonical = realpath(path, NULL); + if (!canonical) + return strdup(path); + p = strrchr(canonical, '/'); + if (p && strncmp(p, "/dm-", 4) == 0 && isdigit(*(p + 4))) { + char *dm = canonicalize_dm_name(p + 1); + + if (dm) { + free(canonical); + return dm; + } + } + return canonical; +} + +/* * returns 1 if the device was mounted, < 0 on error or 0 if everything * is safe to continue. */ @@ -53,6 +53,8 @@ int btrfs_add_to_fsid(struct btrfs_trans_handle *trans, int btrfs_scan_for_fsid(int run_ioctls); void btrfs_register_one_device(char *fname); int btrfs_scan_one_dir(char *dirname, int run_ioctl); +char *canonicalize_dm_name(const char *ptname); +char *canonicalize_path(const char *path); int check_mounted(const char *devicename); int check_mounted_where(int fd, const char *file, char *where, int size, struct btrfs_fs_devices **fs_devices_mnt); |