diff --git a/src/partition/repart.c b/src/partition/repart.c index 46b68c730c..a627d84305 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -158,9 +158,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep); STATIC_DESTRUCTOR_REGISTER(arg_tpm2_public_key, freep); STATIC_DESTRUCTOR_REGISTER(arg_filter_partitions, freep); -typedef struct Partition Partition; typedef struct FreeArea FreeArea; -typedef struct Context Context; typedef enum EncryptMode { ENCRYPT_OFF, @@ -180,7 +178,7 @@ typedef enum VerityMode { _VERITY_MODE_INVALID = -EINVAL, } VerityMode; -struct Partition { +typedef struct Partition { char *definition_path; char **drop_in_files; @@ -211,6 +209,7 @@ struct Partition { FreeArea *allocated_to_area; char *copy_blocks_path; + bool copy_blocks_path_is_our_file; bool copy_blocks_auto; const char *copy_blocks_root; int copy_blocks_fd; @@ -233,12 +232,12 @@ struct Partition { size_t roothash_size; char *split_name_format; - char *split_name_resolved; + char *split_path; - Partition *siblings[_VERITY_MODE_MAX]; + struct Partition *siblings[_VERITY_MODE_MAX]; - LIST_FIELDS(Partition, partitions); -}; + LIST_FIELDS(struct Partition, partitions); +} Partition; #define PARTITION_IS_FOREIGN(p) (!(p)->definition_path) #define PARTITION_EXISTS(p) (!!(p)->current_partition) @@ -249,7 +248,7 @@ struct FreeArea { uint64_t allocated; }; -struct Context { +typedef struct Context { LIST_HEAD(Partition, partitions); size_t n_partitions; @@ -263,7 +262,13 @@ struct Context { uint64_t grain_size; sd_id128_t seed; -}; + + char *node; + bool node_is_our_file; + int backing_fd; + + bool from_scratch; +} Context; static const char *encrypt_mode_table[_ENCRYPT_MODE_MAX] = { [ENCRYPT_OFF] = "off", @@ -340,7 +345,10 @@ static Partition* partition_free(Partition *p) { if (p->new_partition) fdisk_unref_partition(p->new_partition); - free(p->copy_blocks_path); + if (p->copy_blocks_path_is_our_file) + unlink_and_free(p->copy_blocks_path); + else + free(p->copy_blocks_path); safe_close(p->copy_blocks_fd); free(p->format); @@ -351,7 +359,7 @@ static Partition* partition_free(Partition *p) { free(p->roothash); free(p->split_name_format); - free(p->split_name_resolved); + unlink_and_free(p->split_path); return mfree(p); } @@ -464,6 +472,12 @@ static Context *context_free(Context *context) { if (context->fdisk_context) fdisk_unref_context(context->fdisk_context); + safe_close(context->backing_fd); + if (context->node_is_our_file) + unlink_and_free(context->node); + else + free(context->node); + return mfree(context); } @@ -1920,11 +1934,7 @@ static int derive_uuid(sd_id128_t base, const char *token, sd_id128_t *ret) { return 0; } -static int context_load_partition_table( - Context *context, - const char *node, - int *backing_fd) { - +static int context_load_partition_table(Context *context) { _cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL; _cleanup_(fdisk_unref_tablep) struct fdisk_table *t = NULL; uint64_t left_boundary = UINT64_MAX, first_lba, last_lba, nsectors; @@ -1937,8 +1947,6 @@ static int context_load_partition_table( int r; assert(context); - assert(node); - assert(backing_fd); assert(!context->fdisk_context); assert(!context->free_areas); assert(context->start == UINT64_MAX); @@ -1947,14 +1955,14 @@ static int context_load_partition_table( /* libfdisk doesn't have an API to operate on arbitrary fds, hence reopen the fd going via the * /proc/self/fd/ magic path if we have an existing fd. Open the original file otherwise. */ - if (*backing_fd < 0) { + if (context->backing_fd < 0) { c = fdisk_new_context(); if (!c) return log_oom(); - r = fdisk_assign_device(c, node, arg_dry_run); + r = fdisk_assign_device(c, context->node, arg_dry_run); } else - r = fdisk_new_context_fd(*backing_fd, arg_dry_run, &c); + r = fdisk_new_context_fd(context->backing_fd, arg_dry_run, &c); if (r == -EINVAL && arg_size_auto) { struct stat st; @@ -1962,12 +1970,12 @@ static int context_load_partition_table( /* libfdisk returns EINVAL if opening a file of size zero. Let's check for that, and accept * it if automatic sizing is requested. */ - if (*backing_fd < 0) - r = stat(node, &st); + if (context->backing_fd < 0) + r = stat(context->node, &st); else - r = fstat(*backing_fd, &st); + r = fstat(context->backing_fd, &st); if (r < 0) - return log_error_errno(errno, "Failed to stat block device '%s': %m", node); + return log_error_errno(errno, "Failed to stat block device '%s': %m", context->node); if (S_ISREG(st.st_mode) && st.st_size == 0) { /* User the fallback values if we have no better idea */ @@ -1979,16 +1987,16 @@ static int context_load_partition_table( r = -EINVAL; } if (r < 0) - return log_error_errno(r, "Failed to open device '%s': %m", node); + return log_error_errno(r, "Failed to open device '%s': %m", context->node); - if (*backing_fd < 0) { + if (context->backing_fd < 0) { /* If we have no fd referencing the device yet, make a copy of the fd now, so that we have one */ - *backing_fd = fd_reopen(fdisk_get_devfd(c), O_RDONLY|O_CLOEXEC); - if (*backing_fd < 0) - return log_error_errno(*backing_fd, "Failed to duplicate fdisk fd: %m"); + context->backing_fd = fd_reopen(fdisk_get_devfd(c), O_RDONLY|O_CLOEXEC); + if (context->backing_fd < 0) + return log_error_errno(context->backing_fd, "Failed to duplicate fdisk fd: %m"); /* Tell udev not to interfere while we are processing the device */ - if (flock(*backing_fd, arg_dry_run ? LOCK_SH : LOCK_EX) < 0) + if (flock(context->backing_fd, arg_dry_run ? LOCK_SH : LOCK_EX) < 0) return log_error_errno(errno, "Failed to lock block device: %m"); } @@ -2014,7 +2022,7 @@ static int context_load_partition_table( case EMPTY_REFUSE: /* Refuse empty disks, insist on an existing GPT partition table */ if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT)) - return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s has no GPT disk label, not repartitioning.", node); + return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s has no GPT disk label, not repartitioning.", context->node); break; @@ -2022,9 +2030,9 @@ static int context_load_partition_table( /* Require an empty disk, refuse any existing partition table */ r = fdisk_has_label(c); if (r < 0) - return log_error_errno(r, "Failed to determine whether disk %s has a disk label: %m", node); + return log_error_errno(r, "Failed to determine whether disk %s has a disk label: %m", context->node); if (r > 0) - return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s already has a disk label, refusing.", node); + return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s already has a disk label, refusing.", context->node); from_scratch = true; break; @@ -2033,10 +2041,10 @@ static int context_load_partition_table( /* Allow both an empty disk and an existing partition table, but only GPT */ r = fdisk_has_label(c); if (r < 0) - return log_error_errno(r, "Failed to determine whether disk %s has a disk label: %m", node); + return log_error_errno(r, "Failed to determine whether disk %s has a disk label: %m", context->node); if (r > 0) { if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT)) - return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s has non-GPT disk label, not repartitioning.", node); + return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s has non-GPT disk label, not repartitioning.", context->node); } else from_scratch = true; @@ -2342,30 +2350,47 @@ static const char *partition_label(const Partition *p) { return gpt_partition_type_uuid_to_string(p->type.uuid); } -static int context_dump_partitions(Context *context, const char *node) { +static int context_dump_partitions(Context *context) { _cleanup_(table_unrefp) Table *t = NULL; uint64_t sum_padding = 0, sum_size = 0; int r; - const size_t roothash_col = 13, dropin_files_col = 14; - bool has_roothash = false, has_dropin_files = false; + const size_t roothash_col = 13, dropin_files_col = 14, split_path_col = 15; + bool has_roothash = false, has_dropin_files = false, has_split_path = false; if ((arg_json_format_flags & JSON_FORMAT_OFF) && context->n_partitions == 0) { log_info("Empty partition table."); return 0; } - t = table_new("type", "label", "uuid", "file", "node", "offset", "old size", "raw size", "size", "old padding", "raw padding", "padding", "activity", "roothash", "drop-in files"); + t = table_new("type", + "label", + "uuid", + "file", + "node", + "offset", + "old size", + "raw size", + "size", + "old padding", + "raw padding", + "padding", + "activity", + "roothash", + "drop-in files", + "split path"); if (!t) return log_oom(); if (!DEBUG_LOGGING) { if (arg_json_format_flags & JSON_FORMAT_OFF) (void) table_set_display(t, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) 3, (size_t) 4, - (size_t) 8, (size_t) 11, roothash_col, dropin_files_col); + (size_t) 8, (size_t) 11, roothash_col, dropin_files_col, + split_path_col); else (void) table_set_display(t, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) 3, (size_t) 4, (size_t) 5, (size_t) 6, (size_t) 7, (size_t) 9, (size_t) 10, - (size_t) 12, roothash_col, dropin_files_col); + (size_t) 12, roothash_col, dropin_files_col, + split_path_col); } (void) table_set_align_percent(t, table_get_cell(t, 0, 5), 100); @@ -2390,7 +2415,7 @@ static int context_dump_partitions(Context *context, const char *node) { activity = "resize"; label = partition_label(p); - partname = p->partno != UINT64_MAX ? fdisk_partname(node, p->partno+1) : NULL; + partname = p->partno != UINT64_MAX ? fdisk_partname(context->node, p->partno+1) : NULL; r = format_size_change(p->current_size, p->new_size, &size_change); if (r < 0) @@ -2427,12 +2452,14 @@ static int context_dump_partitions(Context *context, const char *node) { TABLE_STRING, padding_change, TABLE_SET_COLOR, !p->partitions_next && sum_padding > 0 ? ansi_underline() : NULL, TABLE_STRING, activity ?: "unchanged", TABLE_STRING, rh, - TABLE_STRV, p->drop_in_files); + TABLE_STRV, p->drop_in_files, + TABLE_STRING, empty_to_null(p->split_path) ?: "-"); if (r < 0) return table_log_add_error(r); has_roothash = has_roothash || !isempty(rh); has_dropin_files = has_dropin_files || !strv_isempty(p->drop_in_files); + has_split_path = has_split_path || !isempty(p->split_path); } if ((arg_json_format_flags & JSON_FORMAT_OFF) && (sum_padding > 0 || sum_size > 0)) { @@ -2457,6 +2484,7 @@ static int context_dump_partitions(Context *context, const char *node) { TABLE_STRING, b, TABLE_EMPTY, TABLE_EMPTY, + TABLE_EMPTY, TABLE_EMPTY); if (r < 0) return table_log_add_error(r); @@ -2474,6 +2502,12 @@ static int context_dump_partitions(Context *context, const char *node) { return log_error_errno(r, "Failed to set columns to display: %m"); } + if (!has_split_path) { + r = table_hide_column_from_display(t, split_path_col); + if (r < 0) + return log_error_errno(r, "Failed to set columns to display: %m"); + } + return table_print_with_pager(t, arg_json_format_flags, arg_pager_flags, arg_legend); } @@ -2559,7 +2593,7 @@ done: return 0; } -static int context_dump_partition_bar(Context *context, const char *node) { +static int context_dump_partition_bar(Context *context) { _cleanup_free_ Partition **bar = NULL; _cleanup_free_ size_t *start_array = NULL; Partition *last = NULL; @@ -2635,7 +2669,7 @@ static int context_dump_partition_bar(Context *context, const char *node) { } else if (i == context->n_partitions - j) { _cleanup_free_ char *hint = NULL; - (void) partition_hint(p, node, &hint); + (void) partition_hint(p, context->node, &hint); if (streq_ptr(line[start_array[j-1]], special_glyph(SPECIAL_GLYPH_TREE_VERTICAL))) d = strjoin(special_glyph(SPECIAL_GLYPH_TREE_BRANCH), " ", strna(hint)); @@ -2680,11 +2714,10 @@ static bool context_has_roothash(Context *context) { return false; } -static int context_dump(Context *context, const char *node, bool late) { +static int context_dump(Context *context, bool late) { int r; assert(context); - assert(node); if (arg_pretty == 0 && FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF)) return 0; @@ -2699,7 +2732,7 @@ static int context_dump(Context *context, const char *node, bool late) { if (late && FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF) && !context_has_roothash(context)) return 0; - r = context_dump_partitions(context, node); + r = context_dump_partitions(context); if (r < 0) return r; @@ -2708,7 +2741,7 @@ static int context_dump(Context *context, const char *node, bool late) { if (FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF) && !late) { putc('\n', stdout); - r = context_dump_partition_bar(context, node); + r = context_dump_partition_bar(context); if (r < 0) return r; @@ -2951,7 +2984,7 @@ static int context_discard_gap_after(Context *context, Partition *p) { return 0; } -static int context_wipe_and_discard(Context *context, bool from_scratch) { +static int context_wipe_and_discard(Context *context) { int r; assert(context); @@ -2972,7 +3005,7 @@ static int context_wipe_and_discard(Context *context, bool from_scratch) { if (r < 0) return r; - if (!from_scratch) { + if (!context->from_scratch) { r = context_discard_partition(context, p); if (r < 0) return r; @@ -2983,7 +3016,7 @@ static int context_wipe_and_discard(Context *context, bool from_scratch) { } } - if (!from_scratch) { + if (!context->from_scratch) { r = context_discard_gap_after(context, NULL); if (r < 0) return r; @@ -4456,7 +4489,7 @@ static int context_mangle_partitions(Context *context) { return 0; } -static int split_name_printf(Partition *p) { +static int split_name_printf(Partition *p, char **ret) { assert(p); const Specifier table[] = { @@ -4469,45 +4502,7 @@ static int split_name_printf(Partition *p) { {} }; - return specifier_printf(p->split_name_format, NAME_MAX, table, arg_root, p, &p->split_name_resolved); -} - -static int split_name_resolve(Context *context) { - int r; - - LIST_FOREACH(partitions, p, context->partitions) { - if (p->dropped) - continue; - - if (!p->split_name_format) - continue; - - r = split_name_printf(p); - if (r < 0) - return log_error_errno(r, "Failed to resolve specifiers in %s: %m", p->split_name_format); - } - - LIST_FOREACH(partitions, p, context->partitions) { - if (!p->split_name_resolved) - continue; - - LIST_FOREACH(partitions, q, context->partitions) { - if (p == q) - continue; - - if (!q->split_name_resolved) - continue; - - if (!streq(p->split_name_resolved, q->split_name_resolved)) - continue; - - return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ), - "%s and %s have the same resolved split name \"%s\", refusing", - p->definition_path, q->definition_path, p->split_name_resolved); - } - } - - return 0; + return specifier_printf(p->split_name_format, NAME_MAX, table, arg_root, p, ret); } static int split_node(const char *node, char **ret_base, char **ret_ext) { @@ -4521,9 +4516,9 @@ static int split_node(const char *node, char **ret_base, char **ret_ext) { r = path_extract_filename(node, &base); if (r == O_DIRECTORY || r == -EADDRNOTAVAIL) - return log_error_errno(r, "Device node %s cannot be a directory", arg_node); + return log_error_errno(r, "Device node %s cannot be a directory", node); if (r < 0) - return log_error_errno(r, "Failed to extract filename from %s: %m", arg_node); + return log_error_errno(r, "Failed to extract filename from %s: %m", node); e = endswith(base, ".raw"); if (e) { @@ -4540,16 +4535,71 @@ static int split_node(const char *node, char **ret_base, char **ret_ext) { return 0; } +static int split_name_resolve(Context *context) { + _cleanup_free_ char *parent = NULL, *base = NULL, *ext = NULL; + int r; + + assert(context); + + r = path_extract_directory(context->node, &parent); + if (r < 0 && r != -EDESTADDRREQ) + return log_error_errno(r, "Failed to extract directory from %s: %m", context->node); + + r = split_node(context->node, &base, &ext); + if (r < 0) + return r; + + LIST_FOREACH(partitions, p, context->partitions) { + _cleanup_free_ char *resolved = NULL; + + if (p->dropped) + continue; + + if (!p->split_name_format) + continue; + + r = split_name_printf(p, &resolved); + if (r < 0) + return log_error_errno(r, "Failed to resolve specifiers in %s: %m", p->split_name_format); + + if (parent) + p->split_path = strjoin(parent, "/", base, ".", resolved, ext); + else + p->split_path = strjoin(base, ".", resolved, ext); + if (!p->split_path) + return log_oom(); + } + + LIST_FOREACH(partitions, p, context->partitions) { + if (!p->split_path) + continue; + + LIST_FOREACH(partitions, q, context->partitions) { + if (p == q) + continue; + + if (!q->split_path) + continue; + + if (!streq(p->split_path, q->split_path)) + continue; + + return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ), + "%s and %s have the same resolved split name \"%s\", refusing", + p->definition_path, q->definition_path, p->split_path); + } + } + + return 0; +} + static int context_split(Context *context) { - _cleanup_free_ char *base = NULL, *ext = NULL; - _cleanup_close_ int dir_fd = -1; int fd = -1, r; if (!arg_split) return 0; assert(context); - assert(arg_node); /* We can't do resolution earlier because the partition UUIDs for verity partitions are only filled * in after they've been generated. */ @@ -4558,36 +4608,21 @@ static int context_split(Context *context) { if (r < 0) return r; - r = split_node(arg_node, &base, &ext); - if (r < 0) - return r; - - dir_fd = r = open_parent(arg_node, O_PATH|O_CLOEXEC, 0); - if (r == -EDESTADDRREQ) - dir_fd = AT_FDCWD; - else if (r < 0) - return log_error_errno(r, "Failed to open parent directory of %s: %m", arg_node); - LIST_FOREACH(partitions, p, context->partitions) { - _cleanup_free_ char *fname = NULL; _cleanup_close_ int fdt = -1; if (p->dropped) continue; - if (!p->split_name_resolved) + if (!p->split_path) continue; if (partition_skip(p)) continue; - fname = strjoin(base, ".", p->split_name_resolved, ext); - if (!fname) - return log_oom(); - - fdt = openat(dir_fd, fname, O_WRONLY|O_NOCTTY|O_CLOEXEC|O_NOFOLLOW|O_CREAT|O_EXCL, 0666); + fdt = open(p->split_path, O_WRONLY|O_NOCTTY|O_CLOEXEC|O_NOFOLLOW|O_CREAT|O_EXCL, 0666); if (fdt < 0) - return log_error_errno(errno, "Failed to open %s: %m", fname); + return log_error_errno(fdt, "Failed to open split partition file %s: %m", p->split_path); if (fd < 0) assert_se((fd = fdisk_get_devfd(context->fdisk_context)) >= 0); @@ -4597,23 +4632,19 @@ static int context_split(Context *context) { r = copy_bytes(fd, fdt, p->new_size, COPY_REFLINK|COPY_HOLES); if (r < 0) - return log_error_errno(r, "Failed to copy to split partition %s: %m", fname); + return log_error_errno(r, "Failed to copy to split partition %s: %m", p->split_path); } return 0; } -static int context_write_partition_table( - Context *context, - const char *node, - bool from_scratch) { - +static int context_write_partition_table(Context *context) { _cleanup_(fdisk_unref_tablep) struct fdisk_table *original_table = NULL; int capable, r; assert(context); - if (!from_scratch && !context_changed(context)) { + if (!context->from_scratch && !context_changed(context)) { log_info("No changes."); return 0; } @@ -4625,7 +4656,7 @@ static int context_write_partition_table( log_info("Applying changes."); - if (from_scratch) { + if (context->from_scratch) { r = context_wipe_range(context, 0, context->total); if (r < 0) return r; @@ -4649,7 +4680,7 @@ static int context_write_partition_table( /* Wipe fs signatures and discard sectors where the new partitions are going to be placed and in the * gaps between partitions, just to be sure. */ - r = context_wipe_and_discard(context, from_scratch); + r = context_wipe_and_discard(context); if (r < 0) return r; @@ -4679,7 +4710,7 @@ static int context_write_partition_table( else if (capable > 0) { log_info("Telling kernel to reread partition table."); - if (from_scratch) + if (context->from_scratch) r = fdisk_reread_partition_table(context->fdisk_context); else r = fdisk_reread_changes(context->fdisk_context, original_table); @@ -4727,7 +4758,7 @@ static int context_read_seed(Context *context, const char *root) { return 0; } -static int context_factory_reset(Context *context, bool from_scratch) { +static int context_factory_reset(Context *context) { size_t n = 0; int r; @@ -4736,7 +4767,7 @@ static int context_factory_reset(Context *context, bool from_scratch) { if (arg_factory_reset <= 0) return 0; - if (from_scratch) /* Nothing to reset if we start from scratch */ + if (context->from_scratch) /* Nothing to reset if we start from scratch */ return 0; if (arg_dry_run) { @@ -5306,6 +5337,7 @@ static int context_minimize(Context *context) { * loopback file for us. */ if (fstype_is_ro(p->format)) { p->copy_blocks_path = TAKE_PTR(temp); + p->copy_blocks_path_is_our_file = true; continue; } @@ -5363,6 +5395,7 @@ static int context_minimize(Context *context) { } p->copy_blocks_path = TAKE_PTR(temp); + p->copy_blocks_path_is_our_file = true; } return 0; @@ -6002,12 +6035,11 @@ static int acquire_root_devno( return 0; } -static int find_root(char **ret, int *ret_fd) { +static int find_root(Context *context) { _cleanup_free_ char *device = NULL; int r; - assert(ret); - assert(ret_fd); + assert(context); if (arg_node) { if (arg_empty == EMPTY_CREATE) { @@ -6022,14 +6054,15 @@ static int find_root(char **ret, int *ret_fd) { if (fd < 0) return log_error_errno(errno, "Failed to create '%s': %m", arg_node); - *ret = TAKE_PTR(s); - *ret_fd = TAKE_FD(fd); + context->node = TAKE_PTR(s); + context->node_is_our_file = true; + context->backing_fd = TAKE_FD(fd); return 0; } /* Note that we don't specify a root argument here: if the user explicitly configured a node * we'll take it relative to the host, not the image */ - r = acquire_root_devno(arg_node, NULL, O_RDONLY|O_CLOEXEC, ret, ret_fd); + r = acquire_root_devno(arg_node, NULL, O_RDONLY|O_CLOEXEC, &context->node, &context->backing_fd); if (r == -EUCLEAN) return btrfs_log_dev_root(LOG_ERR, r, arg_node); if (r < 0) @@ -6051,7 +6084,8 @@ static int find_root(char **ret, int *ret_fd) { FOREACH_STRING(p, "/", "/usr") { - r = acquire_root_devno(p, arg_root, O_RDONLY|O_DIRECTORY|O_CLOEXEC, ret, ret_fd); + r = acquire_root_devno(p, arg_root, O_RDONLY|O_DIRECTORY|O_CLOEXEC, &context->node, + &context->backing_fd); if (r < 0) { if (r == -EUCLEAN) return btrfs_log_dev_root(LOG_ERR, r, p); @@ -6063,7 +6097,7 @@ static int find_root(char **ret, int *ret_fd) { } else if (r < 0) return log_error_errno(r, "Failed to read symlink /run/systemd/volatile-root: %m"); else { - r = acquire_root_devno(device, NULL, O_RDONLY|O_CLOEXEC, ret, ret_fd); + r = acquire_root_devno(device, NULL, O_RDONLY|O_CLOEXEC, &context->node, &context->backing_fd); if (r == -EUCLEAN) return btrfs_log_dev_root(LOG_ERR, r, device); if (r < 0) @@ -6269,9 +6303,7 @@ static int run(int argc, char *argv[]) { _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL; _cleanup_(umount_and_rmdir_and_freep) char *mounted_dir = NULL; _cleanup_(context_freep) Context* context = NULL; - _cleanup_free_ char *node = NULL; - _cleanup_close_ int backing_fd = -1; - bool from_scratch, node_is_our_loop = false; + bool node_is_our_loop = false; int r; log_show_color(true); @@ -6337,27 +6369,27 @@ static int run(int argc, char *argv[]) { if (r < 0) return r; - r = find_root(&node, &backing_fd); + r = find_root(context); if (r < 0) return r; if (arg_size != UINT64_MAX) { r = resize_backing_fd( - node, - &backing_fd, + context->node, + &context->backing_fd, node_is_our_loop ? arg_image : NULL, node_is_our_loop ? loop_device : NULL); if (r < 0) return r; } - r = context_load_partition_table(context, node, &backing_fd); + r = context_load_partition_table(context); if (r == -EHWPOISON) return 77; /* Special return value which means "Not GPT, so not doing anything". This isn't * really an error when called at boot. */ if (r < 0) return r; - from_scratch = r > 0; /* Starting from scratch */ + context->from_scratch = r > 0; /* Starting from scratch */ if (arg_can_factory_reset) { r = context_can_factory_reset(context); @@ -6369,7 +6401,7 @@ static int run(int argc, char *argv[]) { return 0; } - r = context_factory_reset(context, from_scratch); + r = context_factory_reset(context); if (r < 0) return r; if (r > 0) { @@ -6380,16 +6412,11 @@ static int run(int argc, char *argv[]) { /* Reload the reduced partition table */ context_unload_partition_table(context); - r = context_load_partition_table(context, node, &backing_fd); + r = context_load_partition_table(context); if (r < 0) return r; } -#if 0 - (void) context_dump_partitions(context, node); - putchar('\n'); -#endif - r = context_read_seed(context, arg_root); if (r < 0) return r; @@ -6422,14 +6449,14 @@ static int run(int argc, char *argv[]) { assert(arg_size != UINT64_MAX); r = resize_backing_fd( - node, - &backing_fd, + context->node, + &context->backing_fd, node_is_our_loop ? arg_image : NULL, node_is_our_loop ? loop_device : NULL); if (r < 0) return r; - r = context_load_partition_table(context, node, &backing_fd); + r = context_load_partition_table(context); if (r < 0) return r; } @@ -6458,9 +6485,9 @@ static int run(int argc, char *argv[]) { /* Now calculate where each new partition gets placed */ context_place_partitions(context); - (void) context_dump(context, node, /*late=*/ false); + (void) context_dump(context, /*late=*/ false); - r = context_write_partition_table(context, node, from_scratch); + r = context_write_partition_table(context); if (r < 0) return r; @@ -6468,7 +6495,12 @@ static int run(int argc, char *argv[]) { if (r < 0) return r; - (void) context_dump(context, node, /*late=*/ true); + (void) context_dump(context, /*late=*/ true); + + context->node = mfree(context->node); + + LIST_FOREACH(partitions, p, context->partitions) + p->split_path = mfree(p->split_path); return 0; }