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



commit d7503fd5ed399d502fcd0bafb0840a4f2f51886e
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Sat Apr 3 09:16:48 2021 +0100

    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] 8dff80edc65b2923b400ddadebacf9bcf378d09f
        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"

 include/FileSystem.h | 11 +++++++----
 src/FileSystem.cc    | 48 ++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 47 insertions(+), 12 deletions(-)
---
diff --git a/include/FileSystem.h b/include/FileSystem.h
index 403d84cb..bbad470e 100644
--- a/include/FileSystem.h
+++ b/include/FileSystem.h
@@ -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;
diff --git a/src/FileSystem.cc b/src/FileSystem.cc
index b9f3331c..6dfeb070 100644
--- a/src/FileSystem.cc
+++ b/src/FileSystem.cc
@@ -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 )


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]