dissect: immediately close pipes when we determined we have no data for them

This effectively makes little difference because we exit soon later
anyway, which will close the fds, too. However, it's still useful since
it means the parent will get EOF events on them in the order we process
things and isn't delayed to process the data from the pipes until the
child dies.
This commit is contained in:
Lennart Poettering 2020-07-29 15:17:22 +02:00
parent f5ea63a5e1
commit 37e44c3f95
2 changed files with 328 additions and 301 deletions

View file

@ -315,58 +315,13 @@ static int parse_argv(int argc, char *argv[]) {
return 1;
}
static int run(int argc, char *argv[]) {
_cleanup_(loop_device_unrefp) LoopDevice *d = NULL;
_cleanup_(decrypted_image_unrefp) DecryptedImage *di = NULL;
_cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
int r;
log_parse_environment();
log_open();
r = parse_argv(argc, argv);
if (r <= 0)
return r;
r = verity_metadata_load(
arg_image, NULL,
arg_root_hash ? NULL : &arg_root_hash,
&arg_root_hash_size,
arg_verity_data ? NULL : &arg_verity_data,
arg_root_hash_sig_path || arg_root_hash_sig ? NULL : &arg_root_hash_sig_path);
if (r < 0)
return log_error_errno(r, "Failed to read verity artifacts for %s: %m", arg_image);
r = loop_device_make_by_path(
arg_image,
(arg_flags & DISSECT_IMAGE_READ_ONLY) ? O_RDONLY : O_RDWR,
arg_verity_data ? 0 : LO_FLAGS_PARTSCAN,
&d);
if (r < 0)
return log_error_errno(r, "Failed to set up loopback device: %m");
if (arg_verity_data)
arg_flags |= DISSECT_IMAGE_NO_PARTITION_TABLE; /* We only support Verity per file system,
* hence if there's external Verity data
* available we turn off partition table
* support */
r = dissect_image_and_warn(
d->fd,
arg_image,
arg_root_hash,
arg_root_hash_size,
arg_verity_data,
NULL,
arg_flags,
&m);
if (r < 0)
return r;
switch (arg_action) {
case ACTION_DISSECT: {
static int action_dissect(DissectedImage *m, LoopDevice *d) {
_cleanup_(table_unrefp) Table *t = NULL;
uint64_t size;
int r;
assert(m);
assert(d);
r = dissected_image_acquire_metadata(m);
if (r == -EMEDIUMTYPE)
@ -454,7 +409,6 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return table_log_add_error(r);
if (p->partno < 0) /* no partition table, naked file system */ {
r = table_add_cell(t, NULL, TABLE_STRING, arg_image);
if (r < 0)
@ -476,10 +430,16 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to dump table: %m");
break;
return 0;
}
case ACTION_MOUNT:
static int action_mount(DissectedImage *m, LoopDevice *d) {
_cleanup_(decrypted_image_unrefp) DecryptedImage *di = NULL;
int r;
assert(m);
assert(d);
r = dissected_image_decrypt_interactively(
m, NULL,
arg_root_hash, arg_root_hash_size,
@ -503,13 +463,18 @@ static int run(int argc, char *argv[]) {
}
loop_device_relinquish(d);
break;
return 0;
}
case ACTION_COPY_FROM:
case ACTION_COPY_TO: {
static int action_copy(DissectedImage *m, LoopDevice *d) {
_cleanup_(umount_and_rmdir_and_freep) char *mounted_dir = NULL;
_cleanup_(decrypted_image_unrefp) DecryptedImage *di = NULL;
_cleanup_(rmdir_and_freep) char *created_dir = NULL;
_cleanup_free_ char *temp = NULL;
int r;
assert(m);
assert(d);
r = dissected_image_decrypt_interactively(
m, NULL,
@ -565,13 +530,13 @@ static int run(int argc, char *argv[]) {
return log_error_errno(r, "Failed to copy bytes from %s in mage '%s' to stdout: %m", arg_source, arg_image);
/* When we copy to stdou we don't copy any attributes (i.e. no access mode, no ownership, no xattr, no times) */
break;
return 0;
}
/* Try to copy as directory? */
r = copy_directory_fd(source_fd, arg_target, COPY_REFLINK|COPY_MERGE_EMPTY|COPY_SIGINT);
if (r >= 0)
break;
return 0;
if (r != -ENOTDIR)
return log_error_errno(r, "Failed to copy %s in image '%s' to '%s': %m", arg_source, arg_image, arg_target);
@ -622,7 +587,7 @@ static int run(int argc, char *argv[]) {
return log_error_errno(r, "Failed to copy bytes from stdin to '%s' in image '%s': %m", arg_target, arg_image);
/* When we copy from stdin we don't copy any attributes (i.e. no access mode, no ownership, no xattr, no times) */
break;
return 0;
}
source_fd = open(arg_source, O_RDONLY|O_CLOEXEC|O_NOCTTY);
@ -647,7 +612,7 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to copy '%s' to '%s' in image '%s': %m", arg_source, arg_target, arg_image);
break;
return 0;
}
/* We area looking at a regular file */
@ -666,14 +631,75 @@ static int run(int argc, char *argv[]) {
/* When this is a regular file we don't copy ownership! */
}
break;
return 0;
}
static int run(int argc, char *argv[]) {
_cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
_cleanup_(loop_device_unrefp) LoopDevice *d = NULL;
int r;
log_parse_environment();
log_open();
r = parse_argv(argc, argv);
if (r <= 0)
return r;
r = verity_metadata_load(
arg_image, NULL,
arg_root_hash ? NULL : &arg_root_hash,
&arg_root_hash_size,
arg_verity_data ? NULL : &arg_verity_data,
arg_root_hash_sig_path || arg_root_hash_sig ? NULL : &arg_root_hash_sig_path);
if (r < 0)
return log_error_errno(r, "Failed to read verity artifacts for %s: %m", arg_image);
r = loop_device_make_by_path(
arg_image,
(arg_flags & DISSECT_IMAGE_READ_ONLY) ? O_RDONLY : O_RDWR,
arg_verity_data ? 0 : LO_FLAGS_PARTSCAN,
&d);
if (r < 0)
return log_error_errno(r, "Failed to set up loopback device: %m");
if (arg_verity_data)
arg_flags |= DISSECT_IMAGE_NO_PARTITION_TABLE; /* We only support Verity per file system,
* hence if there's external Verity data
* available we turn off partition table
* support */
r = dissect_image_and_warn(
d->fd,
arg_image,
arg_root_hash,
arg_root_hash_size,
arg_verity_data,
NULL,
arg_flags,
&m);
if (r < 0)
return r;
switch (arg_action) {
case ACTION_DISSECT:
r = action_dissect(m, d);
break;
case ACTION_MOUNT:
r = action_mount(m, d);
break;
case ACTION_COPY_FROM:
case ACTION_COPY_TO:
r = action_copy(m, d);
break;
default:
assert_not_reached("Unknown action.");
}
return 0;
return r;
}
DEFINE_MAIN_FUNCTION(run);

View file

@ -1776,7 +1776,7 @@ int dissected_image_acquire_metadata(DissectedImage *m) {
}
for (k = 0; k < _META_MAX; k++) {
_cleanup_close_ int fd = -1;
_cleanup_close_ int fd = -ENOENT;
const char *p;
fds[2*k] = safe_close(fds[2*k]);
@ -1788,6 +1788,7 @@ int dissected_image_acquire_metadata(DissectedImage *m) {
}
if (fd < 0) {
log_debug_errno(fd, "Failed to read %s file of image, ignoring: %m", paths[k]);
fds[2*k+1] = safe_close(fds[2*k+1]);
continue;
}