From 6d27b49a7a767a9c8b31dc0f799da940ddb7232f Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 9 Apr 2020 20:52:20 +0200 Subject: [PATCH] Tidy up Drive and unmounting a little. --- src/lib/copy_to_drive_job.cc | 2 +- src/lib/cross.h | 37 +++++++++++------- src/lib/cross_common.cc | 61 +++++++++++++++++++++++++++++- src/lib/cross_linux.cc | 42 ++++++++++---------- src/lib/disk_writer_messages.h | 2 +- src/tools/dcpomatic_disk.cc | 4 +- src/tools/dcpomatic_disk_writer.cc | 11 +++--- 7 files changed, 116 insertions(+), 43 deletions(-) diff --git a/src/lib/copy_to_drive_job.cc b/src/lib/copy_to_drive_job.cc index fcac7e41b..8a8073ec2 100644 --- a/src/lib/copy_to_drive_job.cc +++ b/src/lib/copy_to_drive_job.cc @@ -64,7 +64,7 @@ CopyToDriveJob::json_name () const void CopyToDriveJob::run () { - if (!_nanomsg.send(String::compose(DISK_WRITER_WRITE "\n%1\n%2\n", _dcp.string(), _drive.internal_name()), 2000)) { + if (!_nanomsg.send(String::compose(DISK_WRITER_WRITE "\n%1\n%2\n", _dcp.string(), _drive.device()), 2000)) { throw CommunicationFailedError (); } diff --git a/src/lib/cross.h b/src/lib/cross.h index 7bbb394a1..ece36fe25 100644 --- a/src/lib/cross.h +++ b/src/lib/cross.h @@ -98,35 +98,44 @@ private: class Drive { public: - Drive (std::string internal_name, uint64_t size, bool mounted, boost::optional vendor, boost::optional model) - : _internal_name(internal_name) + Drive (std::string device, std::vector mount_points, uint64_t size, boost::optional vendor, boost::optional model) + : _device(device) + , _mount_points(mount_points) , _size(size) - , _mounted(mounted) , _vendor(vendor) , _model(model) {} + explicit Drive (std::string); + + std::string as_xml () const; + std::string description () const; - std::string internal_name () const { - return _internal_name; + + std::string device () const { + return _device; } + bool mounted () const { - return _mounted; + return !_mount_points.empty(); } + std::string log_summary () const; + + /** Unmount any mounted partitions on a drive. + * @return true on success, false on failure. + */ + bool unmount (); + + static std::vector get (); + private: - std::string _internal_name; + std::string _device; + std::vector _mount_points; /** size in bytes */ uint64_t _size; - bool _mounted; boost::optional _vendor; boost::optional _model; }; -std::vector get_drives (); -/** Unmount any mounted partitions on a drive. - * @return true on success, false on failure. - */ -bool unmount_drive (std::string drive); - #endif diff --git a/src/lib/cross_common.cc b/src/lib/cross_common.cc index 10ffb0677..07e373436 100644 --- a/src/lib/cross_common.cc +++ b/src/lib/cross_common.cc @@ -20,11 +20,52 @@ #include "cross.h" #include "compose.hpp" +#include "dcpomatic_log.h" +#include +#include +#include +#include #include "i18n.h" using std::string; +Drive::Drive (string xml) +{ + cxml::Document doc; + doc.read_string (xml); + _device = doc.string_child("Device"); + BOOST_FOREACH (cxml::ConstNodePtr i, doc.node_children("MountPoint")) { + _mount_points.push_back (i->content()); + } + _size = doc.number_child("Size"); + _vendor = doc.optional_string_child("Vendor"); + _model = doc.optional_string_child("Model"); +} + + +string +Drive::as_xml () const +{ + xmlpp::Document doc; + xmlpp::Element* root = doc.create_root_node ("Drive"); + root->add_child("Device")->add_child_text(_device); + BOOST_FOREACH (boost::filesystem::path i, _mount_points) { + root->add_child("MountPoint")->add_child_text(i.string()); + } + root->add_child("Size")->add_child_text(dcp::raw_convert(_size)); + if (_vendor) { + root->add_child("Vendor")->add_child_text(*_vendor); + } + if (_model) { + root->add_child("Model")->add_child_text(*_model); + } + + std::cout << "xml is " << doc.write_to_string("UTF-8") << "\n"; + return doc.write_to_string("UTF-8"); +} + + string Drive::description () const { @@ -46,6 +87,24 @@ Drive::description () const name = _("Unknown"); } - return String::compose(_("%1 (%2 GB) [%3]"), name, gb, _internal_name); + return String::compose(_("%1 (%2 GB) [%3]"), name, gb, _device); } +string +Drive::log_summary () const +{ + string mp; + BOOST_FOREACH (boost::filesystem::path i, _mount_points) { + mp += i.string() + ","; + } + if (mp.empty()) { + mp = "[none]"; + } else { + mp = mp.substr (0, mp.length() - 1); + } + + return String::compose( + "Device %1 mounted on %2 size %3 vendor %4 model %5", + _device, mp, _size, _vendor.get_value_or("[none]"), _model.get_value_or("[none]") + ); +} diff --git a/src/lib/cross_linux.cc b/src/lib/cross_linux.cc index 14a7e5b47..d8a33482f 100644 --- a/src/lib/cross_linux.cc +++ b/src/lib/cross_linux.cc @@ -258,6 +258,8 @@ running_32_on_64 () return false; } + +static vector > get_mounts (string prefix) { @@ -278,8 +280,9 @@ get_mounts (string prefix) return mounts; } + vector -get_drives () +Drive::get () { vector drives; @@ -300,7 +303,6 @@ get_drives () if (size == 0) { continue; } - bool mounted = false; optional vendor; try { vendor = dcp::file_to_string("/sys/block/" + name + "/device/vendor"); @@ -311,19 +313,35 @@ get_drives () model = dcp::file_to_string("/sys/block/" + name + "/device/model"); boost::trim(*model); } catch (...) {} + vector mount_points; for (vector >::const_iterator j = mounted_devices.begin(); j != mounted_devices.end(); ++j) { if (boost::algorithm::starts_with(j->first, "/dev/" + name)) { - mounted = true; + mount_points.push_back (j->second); } } - drives.push_back(Drive("/dev/" + i->path().filename().string(), size, mounted, vendor, model)); - LOG_DISK("Block device %1 size %2 %3 vendor %4 model %5", name, size, mounted ? "mounted" : "not mounted", vendor.get_value_or("[none]"), model.get_value_or("[none]")); + drives.push_back(Drive("/dev/" + name, mount_points, size, vendor, model)); + LOG_DISK_NC(drives.back().log_summary()); } } return drives; } + +bool +Drive::unmount () +{ + BOOST_FOREACH (boost::filesystem::path i, _mount_points) { + int const r = umount(i.string().c_str()); + LOG_DISK("Tried to unmount %1 and got %2 and %3", i.string(), r, errno); + if (r == -1) { + return false; + } + } + return true; +} + + void unprivileged () { @@ -354,17 +372,3 @@ config_path () return p; } -bool -unmount_drive (string drive) -{ - vector > mounts = get_mounts (drive); - for (vector >::const_iterator i = mounts.begin(); i != mounts.end(); ++i) { - int const r = umount(i->second.c_str()); - LOG_DISK("Tried to unmount %1 and got %2 and %3", i->second, r, errno); - if (r == -1) { - return false; - } - } - return true; -} - diff --git a/src/lib/disk_writer_messages.h b/src/lib/disk_writer_messages.h index 39253a76e..9d8196374 100644 --- a/src/lib/disk_writer_messages.h +++ b/src/lib/disk_writer_messages.h @@ -59,7 +59,7 @@ // Front-end sends: #define DISK_WRITER_UNMOUNT "U" -// Internal name of the drive to write to +// XML representation of Drive object to unmount // Back-end responds: // DISK_WRITER_OK diff --git a/src/tools/dcpomatic_disk.cc b/src/tools/dcpomatic_disk.cc index ba92cf94e..3ceead860 100644 --- a/src/tools/dcpomatic_disk.cc +++ b/src/tools/dcpomatic_disk.cc @@ -178,7 +178,7 @@ private: if (!_nanomsg.send(DISK_WRITER_UNMOUNT "\n", 2000)) { throw CommunicationFailedError (); } - if (!_nanomsg.send(drive.internal_name() + "\n", 2000)) { + if (!_nanomsg.send(drive.as_xml() + "\n", 2000)) { throw CommunicationFailedError (); } optional reply = _nanomsg.receive (2000); @@ -218,7 +218,7 @@ private: _drive->Clear (); int re_select = wxNOT_FOUND; int j = 0; - _drives = get_drives (); + _drives = Drive::get (); 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 5e76341eb..4a93cba98 100644 --- a/src/tools/dcpomatic_disk_writer.cc +++ b/src/tools/dcpomatic_disk_writer.cc @@ -403,11 +403,12 @@ try exit (EXIT_SUCCESS); } else if (*s == DISK_WRITER_UNMOUNT) { /* XXX: should do Linux polkit stuff here */ - optional device = nanomsg->receive (LONG_TIMEOUT); - if (!device) { + optional xml_head = nanomsg->receive (LONG_TIMEOUT); + optional xml_body = nanomsg->receive (LONG_TIMEOUT); + if (!xml_head || !xml_body) { throw CommunicationFailedError (); } - if (unmount_drive(*device)) { + if (Drive(*xml_head + *xml_body).unmount()) { if (!nanomsg->send (DISK_WRITER_OK "\n", LONG_TIMEOUT)) { throw CommunicationFailedError(); } @@ -449,8 +450,8 @@ try bool on_drive_list = false; bool mounted = false; - for (auto const& i: get_drives()) { - if (i.internal_name() == *device) { + for (auto const& i: Drive::get()) { + if (i.device() == *device) { on_drive_list = true; mounted = i.mounted(); } -- 2.30.2