diff options
| author | Carl Hetherington <cth@carlh.net> | 2020-04-09 00:58:42 +0200 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2020-04-13 00:23:41 +0200 |
| commit | 350afcbc40fffd8c8780180e153a2ee91088f562 (patch) | |
| tree | ccbabb8b91239555ed01ca762d2f56b02858a8cf /src/tools | |
| parent | a16523af5f70b60f4890f198f6214177077a9c1d (diff) | |
Tidy up nanomsg class API; add unmounting for Linux.
Diffstat (limited to 'src/tools')
| -rw-r--r-- | src/tools/dcpomatic_disk.cc | 41 | ||||
| -rw-r--r-- | src/tools/dcpomatic_disk_writer.cc | 109 |
2 files changed, 106 insertions, 44 deletions
diff --git a/src/tools/dcpomatic_disk.cc b/src/tools/dcpomatic_disk.cc index baccdbce3..6dbfbe4b0 100644 --- a/src/tools/dcpomatic_disk.cc +++ b/src/tools/dcpomatic_disk.cc @@ -22,6 +22,8 @@ #include "wx/wx_util.h" #include "wx/job_manager_view.h" #include "wx/drive_wipe_warning_dialog.h" +#include "wx/try_unmount_dialog.h" +#include "wx/message_dialog.h" #include "lib/file_log.h" #include "lib/dcpomatic_log.h" #include "lib/util.h" @@ -44,8 +46,8 @@ using std::string; using std::exception; using std::cout; using std::cerr; -using std::runtime_error; using boost::shared_ptr; +using boost::optional; class DOMFrame : public wxFrame { @@ -133,7 +135,7 @@ public: ~DOMFrame () { - _nanomsg.blocking_send(DISK_WRITER_QUIT "\n"); + _nanomsg.send(DISK_WRITER_QUIT "\n", 2000); } private: @@ -163,6 +165,34 @@ private: { DCPOMATIC_ASSERT (_drive->GetSelection() != wxNOT_FOUND); DCPOMATIC_ASSERT (static_cast<bool>(_dcp_path)); + + Drive const& drive = _drives[_drive->GetSelection()]; + if (drive.mounted()) { + TryUnmountDialog* d = new TryUnmountDialog(this, drive.description()); + int const r = d->ShowModal (); + d->Destroy (); + if (r == wxID_OK) { + if (!_nanomsg.send(DISK_WRITER_UNMOUNT "\n", 2000)) { + throw CommunicationFailedError (); + } + if (!_nanomsg.send(drive.internal_name() + "\n", 2000)) { + throw CommunicationFailedError (); + } + optional<string> reply = _nanomsg.receive (2000); + if (!reply || *reply != DISK_WRITER_OK) { + MessageDialog* m = new MessageDialog ( + this, + _("DCP-o-matic Disk Writer"), + wxString::Format(_("The drive %s could not be unmounted.\nClose any application that is using it, then try again."), std_to_wx(drive.description())) + ); + m->ShowModal (); + m->Destroy (); + return; + } + } + } + + DriveWipeWarningDialog* d = new DriveWipeWarningDialog (this, _drive->GetString(_drive->GetSelection())); int const r = d->ShowModal (); bool ok = r == wxID_OK && d->confirmed(); @@ -186,12 +216,7 @@ private: _drive->Clear (); int re_select = wxNOT_FOUND; int j = 0; - _drives.clear (); - BOOST_FOREACH (Drive i, get_drives()) { - if (!i.mounted()) { - _drives.push_back (i); - } - } + _drives = get_drives (); BOOST_FOREACH (Drive i, _drives) { wxString const s = std_to_wx(i.description()); if (s == current) { diff --git a/src/tools/dcpomatic_disk_writer.cc b/src/tools/dcpomatic_disk_writer.cc index 9518ac555..5e76341eb 100644 --- a/src/tools/dcpomatic_disk_writer.cc +++ b/src/tools/dcpomatic_disk_writer.cc @@ -80,11 +80,12 @@ using boost::optional; #ifdef DCPOMATIC_LINUX static PolkitAuthority* polkit_authority = 0; #endif -static boost::filesystem::path dcp_path; -static std::string device; static uint64_t const block_size = 4096; static Nanomsg* nanomsg = 0; +#define SHORT_TIMEOUT 100 +#define LONG_TIMEOUT 2000 + static void count (boost::filesystem::path dir, uint64_t& total_bytes) @@ -147,7 +148,7 @@ write (boost::filesystem::path from, boost::filesystem::path to, uint64_t& total } remaining -= this_time; total_remaining -= this_time; - nanomsg->blocking_send(String::compose(DISK_WRITER_PROGRESS "\n%1\n", (1 - float(total_remaining) / total))); + nanomsg->send(String::compose(DISK_WRITER_PROGRESS "\n%1\n", (1 - float(total_remaining) / total)), SHORT_TIMEOUT); } fclose (in); @@ -186,7 +187,7 @@ read (boost::filesystem::path from, boost::filesystem::path to, uint64_t& total_ digester.add (buffer, this_time); remaining -= this_time; total_remaining -= this_time; - nanomsg->blocking_send(String::compose(DISK_WRITER_PROGRESS "\n%1\n", (1 - float(total_remaining) / total))); + nanomsg->send(String::compose(DISK_WRITER_PROGRESS "\n%1\n", (1 - float(total_remaining) / total)), SHORT_TIMEOUT); } ext4_fclose (&in); @@ -229,9 +230,10 @@ copy (boost::filesystem::path from, boost::filesystem::path to, uint64_t& total_ } } + static void -write () +write (boost::filesystem::path dcp_path, string device) try { // ext4_dmask_set (DEBUG_ALL); @@ -314,7 +316,7 @@ try } LOG_DISK_NC ("Opened partition"); - nanomsg->blocking_send(DISK_WRITER_FORMATTING "\n"); + nanomsg->send(DISK_WRITER_FORMATTING "\n", SHORT_TIMEOUT); r = ext4_mkfs(&fs, bd, &info, F_SET_EXT4); if (r != EOK) { @@ -349,27 +351,37 @@ try } ext4_device_unregister("ext4_fs"); - nanomsg->blocking_send(DISK_WRITER_OK "\n"); + if (!nanomsg->send(DISK_WRITER_OK "\n", LONG_TIMEOUT)) { + throw CommunicationFailedError (); + } } catch (CopyError& e) { - LOG_DISK("CopyError: %1 %2", e.message(), e.number()); - nanomsg->blocking_send(String::compose(DISK_WRITER_ERROR "\n%1\n%2\n", e.message(), e.number())); + LOG_DISK("CopyError (from write): %1 %2", e.message(), e.number().get_value_or(0)); + nanomsg->send(String::compose(DISK_WRITER_ERROR "\n%1\n%2\n", e.message(), e.number().get_value_or(0)), LONG_TIMEOUT); } catch (VerifyError& e) { - LOG_DISK("VerifyError: %1 %2", e.message(), e.number()); - nanomsg->blocking_send(String::compose(DISK_WRITER_ERROR "\n%1\n%2\n", e.message(), e.number())); + LOG_DISK("VerifyError (from write): %1 %2", e.message(), e.number()); + nanomsg->send(String::compose(DISK_WRITER_ERROR "\n%1\n%2\n", e.message(), e.number()), LONG_TIMEOUT); } catch (exception& e) { - LOG_DISK("Exception: %1", e.what()); - nanomsg->blocking_send(String::compose(DISK_WRITER_ERROR "\n%1\n0\n", e.what())); + LOG_DISK("Exception (from write): %1", e.what()); + nanomsg->send(String::compose(DISK_WRITER_ERROR "\n%1\n0\n", e.what()), LONG_TIMEOUT); } +struct Parameters +{ + boost::filesystem::path dcp_path; + std::string device; +}; + #ifdef DCPOMATIC_LINUX static void -polkit_callback (GObject *, GAsyncResult* res, gpointer) +polkit_callback (GObject *, GAsyncResult* res, gpointer data) { + Parameters* parameters = reinterpret_cast<Parameters*> (data); PolkitAuthorizationResult* result = polkit_authority_check_authorization_finish (polkit_authority, res, 0); if (result && polkit_authorization_result_get_is_authorized(result)) { - write (); + write (parameters->dcp_path, parameters->device); } + delete parameters; if (result) { g_object_unref (result); } @@ -378,40 +390,59 @@ polkit_callback (GObject *, GAsyncResult* res, gpointer) bool idle () +try { using namespace boost::algorithm; - optional<string> s = nanomsg->nonblocking_get (); + optional<string> s = nanomsg->receive (0); if (!s) { return true; } if (*s == DISK_WRITER_QUIT) { exit (EXIT_SUCCESS); - } else if (*s == DISK_WRITER_WRITE) { - dcp_path = nanomsg->blocking_get(); - device = nanomsg->blocking_get(); + } else if (*s == DISK_WRITER_UNMOUNT) { + /* XXX: should do Linux polkit stuff here */ + optional<string> device = nanomsg->receive (LONG_TIMEOUT); + if (!device) { + throw CommunicationFailedError (); + } + if (unmount_drive(*device)) { + if (!nanomsg->send (DISK_WRITER_OK "\n", LONG_TIMEOUT)) { + throw CommunicationFailedError(); + } + } else { + if (!nanomsg->send (DISK_WRITER_ERROR "\n", LONG_TIMEOUT)) { + throw CommunicationFailedError(); + } + } + } else { + optional<string> dcp_path = nanomsg->receive(LONG_TIMEOUT); + optional<string> device = nanomsg->receive(LONG_TIMEOUT); + if (!dcp_path || !device) { + throw CommunicationFailedError(); + } /* Do some basic sanity checks; this is a bit belt-and-braces but it can't hurt... */ #ifdef DCPOMATIC_OSX - if (!starts_with(device, "/dev/disk")) { - LOG_DISK ("Will not write to %1", device); - nanomsg->blocking_send(DISK_WRITER_ERROR "\nRefusing to write to this drive\n1\n"); + if (!starts_with(*device, "/dev/disk")) { + LOG_DISK ("Will not write to %1", *device); + nanomsg->try_send(DISK_WRITER_ERROR "\nRefusing to write to this drive\n1\n", LONG_TIMEOUT); return true; } #endif #ifdef DCPOMATIC_LINUX - if (!starts_with(device, "/dev/sd") && !starts_with(device, "/dev/hd")) { - LOG_DISK ("Will not write to %1", device); - nanomsg->blocking_send(DISK_WRITER_ERROR "\nRefusing to write to this drive\n1\n"); + if (!starts_with(*device, "/dev/sd") && !starts_with(*device, "/dev/hd")) { + LOG_DISK ("Will not write to %1", *device); + nanomsg->send(DISK_WRITER_ERROR "\nRefusing to write to this drive\n1\n", LONG_TIMEOUT); return true; } #endif #ifdef DCPOMATIC_WINDOWS - if (!starts_with(device, "\\\\.\\PHYSICALDRIVE")) { - LOG_DISK ("Will not write to %1", device); - nanomsg->blocking_send(DISK_WRITER_ERROR "\nRefusing to write to this drive\n1\n"); + if (!starts_with(*device, "\\\\.\\PHYSICALDRIVE")) { + LOG_DISK ("Will not write to %1", *device); + nanomsg->try_send(DISK_WRITER_ERROR "\nRefusing to write to this drive\n1\n", LONG_TIMEOUT); return true; } #endif @@ -419,37 +450,43 @@ idle () bool on_drive_list = false; bool mounted = false; for (auto const& i: get_drives()) { - if (i.internal_name() == device) { + if (i.internal_name() == *device) { on_drive_list = true; mounted = i.mounted(); } } if (!on_drive_list) { - LOG_DISK ("Will not write to %1 as it's not recognised as a drive", device); - nanomsg->blocking_send(DISK_WRITER_ERROR "\nRefusing to write to this drive\n1\n"); + LOG_DISK ("Will not write to %1 as it's not recognised as a drive", *device); + nanomsg->send(DISK_WRITER_ERROR "\nRefusing to write to this drive\n1\n", LONG_TIMEOUT); return true; } if (mounted) { - LOG_DISK ("Will not write to %1 as it's mounted", device); - nanomsg->blocking_send(DISK_WRITER_ERROR "\nRefusing to write to this drive\n1\n"); + LOG_DISK ("Will not write to %1 as it's mounted", *device); + nanomsg->send(DISK_WRITER_ERROR "\nRefusing to write to this drive\n1\n", LONG_TIMEOUT); return true; } - LOG_DISK ("Here we go writing %1 to %2", dcp_path, device); + LOG_DISK ("Here we go writing %1 to %2", *dcp_path, *device); #ifdef DCPOMATIC_LINUX polkit_authority = polkit_authority_get_sync (0, 0); PolkitSubject* subject = polkit_unix_process_new (getppid()); + Parameters* parameters = new Parameters; + parameters->dcp_path = *dcp_path; + parameters->device = *device; polkit_authority_check_authorization ( - polkit_authority, subject, "com.dcpomatic.write-drive", 0, POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, 0, polkit_callback, 0 + polkit_authority, subject, "com.dcpomatic.write-drive", 0, POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, 0, polkit_callback, parameters ); #else - write (); + write (*dcp_path, *device); #endif } return true; +} catch (exception& e) { + LOG_DISK("Exception (from idle): %1", e.what()); + return true; } int |
