From 6a1d4adad13246f2a4a262bfee2cb6fdd731eade Mon Sep 17 00:00:00 2001 From: Mark Harmstone Date: Mon, 30 Sep 2024 15:56:07 +0100 Subject: [PATCH] btrfs-progs: mkfs: avoid dynamic allocation when doing --subvol Reworks mkfs.btrfs --subvol so that dir and full_path in struct rootdir_subvol are stored as arrays rather than pointers. Signed-off-by: Mark Harmstone --- mkfs/main.c | 49 ++++++++++++++----------------------------------- mkfs/rootdir.c | 3 --- mkfs/rootdir.h | 4 ++-- 3 files changed, 16 insertions(+), 40 deletions(-) diff --git a/mkfs/main.c b/mkfs/main.c index c6ef4fc2..c9dbd234 100644 --- a/mkfs/main.c +++ b/mkfs/main.c @@ -1056,7 +1056,6 @@ int BOX_MAIN(mkfs)(int argc, char **argv) char *label = NULL; int nr_global_roots = sysconf(_SC_NPROCESSORS_ONLN); char *source_dir = NULL; - size_t source_dir_len = 0; struct rootdir_subvol *rds; bool has_default_subvol = false; LIST_HEAD(subvols); @@ -1245,10 +1244,12 @@ int BOX_MAIN(mkfs)(int argc, char **argv) } } - if (valid_prefix) - subvol->dir = strndup(colon + 1, strlen(colon + 1)); - else - subvol->dir = strdup(optarg); + if (arg_copy_path(subvol->dir, valid_prefix ? colon + 1 : optarg, + sizeof(subvol->dir))) { + error("--subvol path too long"); + ret = 1; + goto error; + } if (subvol->is_default) { if (has_default_subvol) { @@ -1343,57 +1344,37 @@ int BOX_MAIN(mkfs)(int argc, char **argv) free(source_dir); source_dir = canonical; - source_dir_len = strlen(source_dir); } list_for_each_entry(rds, &subvols, list) { - char *path, *canonical; + char path[PATH_MAX]; struct rootdir_subvol *rds2; - size_t dir_len; - dir_len = strlen(rds->dir); - - path = malloc(source_dir_len + 1 + dir_len + 1); - if (!path) { - error_msg(ERROR_MSG_MEMORY, NULL); + if (path_cat_out(path, source_dir, rds->dir)) { + error("path invalid"); ret = 1; goto error; } - memcpy(path, source_dir, source_dir_len); - path[source_dir_len] = '/'; - memcpy(path + source_dir_len + 1, rds->dir, dir_len + 1); - - canonical = realpath(path, NULL); - if (!canonical) { + if (!realpath(path, rds->full_path)) { error("could not get canonical path to %s", rds->dir); - free(path); ret = 1; goto error; } - free(path); - path = canonical; - - if (!path_exists(path)) { + if (!path_exists(rds->full_path)) { error("subvolume %s does not exist", rds->dir); - free(path); ret = 1; goto error; } - if (!path_is_dir(path)) { + if (!path_is_dir(rds->full_path)) { error("subvolume %s is not a directory", rds->dir); - free(path); ret = 1; goto error; } - rds->full_path = path; - - if (strlen(path) < source_dir_len + 1 || - memcmp(path, source_dir, source_dir_len) != 0 || - path[source_dir_len] != '/') { + if (!path_is_in_dir(source_dir, rds->full_path)) { error("subvolume %s is not a child of %s", rds->dir, source_dir); ret = 1; goto error; @@ -1402,7 +1383,7 @@ int BOX_MAIN(mkfs)(int argc, char **argv) for (rds2 = list_first_entry(&subvols, struct rootdir_subvol, list); rds2 != rds; rds2 = list_next_entry(rds2, list)) { - if (strcmp(rds2->full_path, path) == 0) { + if (strcmp(rds2->full_path, rds->full_path) == 0) { error("subvolume %s specified more than once", rds->dir); ret = 1; goto error; @@ -2113,8 +2094,6 @@ error: struct rootdir_subvol *head; head = list_entry(subvols.next, struct rootdir_subvol, list); - free(head->dir); - free(head->full_path); list_del(&head->list); free(head); } diff --git a/mkfs/rootdir.c b/mkfs/rootdir.c index 70cf0f84..ffe9aa1f 100644 --- a/mkfs/rootdir.c +++ b/mkfs/rootdir.c @@ -711,9 +711,6 @@ static int ftw_add_inode(const char *full_path, const struct stat *st, ret = ftw_add_subvol(full_path, st, typeflag, ftwbuf, rds); - free(rds->dir); - free(rds->full_path); - list_del(&rds->list); free(rds); diff --git a/mkfs/rootdir.h b/mkfs/rootdir.h index 44817374..9db6ff4d 100644 --- a/mkfs/rootdir.h +++ b/mkfs/rootdir.h @@ -30,8 +30,8 @@ struct btrfs_root; struct rootdir_subvol { struct list_head list; - char *dir; - char *full_path; + char dir[PATH_MAX]; + char full_path[PATH_MAX]; bool is_default; bool readonly; };