Add ability for small writes to stdin of operation tracked child processes (#59)

This is the equivalent to what was previously done when adding opening
of LUKS mappings.  Namely to add a way to pass the LUKS passphrase to
'cryptsetup luksOpen' via standard input.  Previously the functionality
was added to Utils::execute_command() [1].  Now it is also needed to
pass the LUKS passphrase to 'cryptsetup resize', which is executed as
part of applying resize and check operations to an encrypted file
system.  So add this functionality to FileSystem::execute_command().

For now writing to stdin is only needed for the one variant of
FileSystem::execute_command() which doesn't have progress tracking
callbacks.  Writing to stdin can easily be added to the other progress
tracking callback variants of execute_command() when needed.

[1] 8dff80edc6
    Add ability for small writes to stdin of child processes (#795617)

Closes #59 - Resize of LUKS2 encrypted file system fails with "Nothing
             to read on input"
This commit is contained in:
Mike Fleetwood 2021-04-03 09:16:48 +01:00 committed by Curtis Gedak
parent 2ccbc3ec92
commit d7503fd5ed
2 changed files with 47 additions and 12 deletions

View File

@ -146,6 +146,8 @@ protected:
int execute_command( const Glib::ustring & command, OperationDetail & operationdetail,
ExecFlags flags = EXEC_NONE );
int execute_command(const Glib::ustring& command, const char *input, OperationDetail& operationdetail,
ExecFlags flags = EXEC_NONE);
int execute_command( const Glib::ustring & command, OperationDetail & operationdetail,
ExecFlags flags,
StreamSlot stream_progress_slot );
@ -167,10 +169,11 @@ protected:
int exit_status ;
private:
int execute_command_internal( const Glib::ustring & command, OperationDetail & operationdetail,
ExecFlags flags,
StreamSlot stream_progress_slot,
TimedSlot timed_progress_slot );
int execute_command_internal(const Glib::ustring& command, const char *input,
OperationDetail& operationdetail,
ExecFlags flags,
StreamSlot stream_progress_slot,
TimedSlot timed_progress_slot);
void store_exit_status( GPid pid, int status );
bool running;
int pipecount;

View File

@ -84,38 +84,53 @@ static void setup_child()
setpgrp();
}
int FileSystem::execute_command( const Glib::ustring & command, OperationDetail & operationdetail,
ExecFlags flags )
{
StreamSlot empty_stream_slot;
TimedSlot empty_timed_slot;
return execute_command_internal( command, operationdetail, flags, empty_stream_slot, empty_timed_slot );
return execute_command_internal(command, NULL, operationdetail, flags, empty_stream_slot, empty_timed_slot);
}
int FileSystem::execute_command(const Glib::ustring& command, const char *input, OperationDetail& operationdetail,
ExecFlags flags)
{
StreamSlot empty_stream_slot;
TimedSlot empty_timed_slot;
return execute_command_internal(command, input, operationdetail, flags, empty_stream_slot, empty_timed_slot);
}
int FileSystem::execute_command( const Glib::ustring & command, OperationDetail & operationdetail,
ExecFlags flags,
StreamSlot stream_progress_slot )
{
TimedSlot empty_timed_slot;
return execute_command_internal( command, operationdetail, flags, stream_progress_slot, empty_timed_slot );
return execute_command_internal(command, NULL, operationdetail, flags, stream_progress_slot, empty_timed_slot);
}
int FileSystem::execute_command( const Glib::ustring & command, OperationDetail & operationdetail,
ExecFlags flags,
TimedSlot timed_progress_slot )
{
StreamSlot empty_stream_slot;
return execute_command_internal( command, operationdetail, flags, empty_stream_slot, timed_progress_slot );
return execute_command_internal(command, NULL, operationdetail, flags, empty_stream_slot, timed_progress_slot);
}
int FileSystem::execute_command_internal( const Glib::ustring & command, OperationDetail & operationdetail,
ExecFlags flags,
StreamSlot stream_progress_slot,
TimedSlot timed_progress_slot )
int FileSystem::execute_command_internal(const Glib::ustring& command, const char *input,
OperationDetail& operationdetail,
ExecFlags flags,
StreamSlot stream_progress_slot,
TimedSlot timed_progress_slot)
{
operationdetail.add_child( OperationDetail( command, STATUS_EXECUTE, FONT_BOLD_ITALIC ) );
OperationDetail & cmd_operationdetail = operationdetail.get_last_child();
Glib::Pid pid;
int in = -1;
// set up pipes for capture
int out, err;
// spawn external process
@ -127,7 +142,7 @@ int FileSystem::execute_command_internal( const Glib::ustring & command, Operati
Glib::SPAWN_DO_NOT_REAP_CHILD | Glib::SPAWN_SEARCH_PATH,
sigc::ptr_fun(setup_child),
&pid,
0,
(input != NULL) ? &in : 0,
&out,
&err );
} catch (Glib::SpawnError &e) {
@ -170,6 +185,23 @@ int FileSystem::execute_command_internal( const Glib::ustring & command, Operati
sigc::ptr_fun( cancel_command ),
pid,
flags & EXEC_CANCEL_SAFE ) );
if (input != NULL && in != -1)
{
// Write small amount of input to pipe to the child process. Linux will
// always accept up to 4096 bytes without blocking. See pipe(7).
size_t len = strlen(input);
ssize_t written = write(in, input, len);
if (written == -1 || (size_t)written < len)
{
int e = errno;
std::cerr << "Write to child failed: " << Glib::strerror(e) << std::endl;
cmd_operationdetail.add_child(OperationDetail("Write to child failed: " + Glib::strerror(e),
STATUS_NONE, FONT_ITALIC));
}
close(in);
}
Gtk::Main::run();
if ( flags & EXEC_CHECK_STATUS )