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 ();
}
class Drive
{
public:
- Drive (std::string internal_name, uint64_t size, bool mounted, boost::optional<std::string> vendor, boost::optional<std::string> model)
- : _internal_name(internal_name)
+ Drive (std::string device, std::vector<boost::filesystem::path> mount_points, uint64_t size, boost::optional<std::string> vendor, boost::optional<std::string> 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<Drive> get ();
+
private:
- std::string _internal_name;
+ std::string _device;
+ std::vector<boost::filesystem::path> _mount_points;
/** size in bytes */
uint64_t _size;
- bool _mounted;
boost::optional<std::string> _vendor;
boost::optional<std::string> _model;
};
-std::vector<Drive> get_drives ();
-/** Unmount any mounted partitions on a drive.
- * @return true on success, false on failure.
- */
-bool unmount_drive (std::string drive);
-
#endif
#include "cross.h"
#include "compose.hpp"
+#include "dcpomatic_log.h"
+#include <dcp/raw_convert.h>
+#include <boost/foreach.hpp>
+#include <libxml++/libxml++.h>
+#include <iostream>
#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<uint64_t>("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<string>(_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
{
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]")
+ );
+}
return false;
}
+
+static
vector<pair<string, string> >
get_mounts (string prefix)
{
return mounts;
}
+
vector<Drive>
-get_drives ()
+Drive::get ()
{
vector<Drive> drives;
if (size == 0) {
continue;
}
- bool mounted = false;
optional<string> vendor;
try {
vendor = dcp::file_to_string("/sys/block/" + name + "/device/vendor");
model = dcp::file_to_string("/sys/block/" + name + "/device/model");
boost::trim(*model);
} catch (...) {}
+ vector<boost::filesystem::path> mount_points;
for (vector<pair<string, string> >::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 ()
{
return p;
}
-bool
-unmount_drive (string drive)
-{
- vector<pair<string, string> > mounts = get_mounts (drive);
- for (vector<pair<string, string> >::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;
-}
-
// 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
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<string> reply = _nanomsg.receive (2000);
_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) {
exit (EXIT_SUCCESS);
} else if (*s == DISK_WRITER_UNMOUNT) {
/* XXX: should do Linux polkit stuff here */
- optional<string> device = nanomsg->receive (LONG_TIMEOUT);
- if (!device) {
+ optional<string> xml_head = nanomsg->receive (LONG_TIMEOUT);
+ optional<string> 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();
}
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();
}