2 Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
4 This file is part of DCP-o-matic.
6 DCP-o-matic is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 DCP-o-matic is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
23 #include "compose.hpp"
24 #include "dcpomatic_log.h"
26 #include <dcp/raw_convert.h>
27 DCPOMATIC_DISABLE_WARNINGS
28 #include <libxml++/libxml++.h>
29 DCPOMATIC_ENABLE_WARNINGS
30 #include <boost/algorithm/string.hpp>
39 using boost::optional;
42 Drive::Drive (string xml)
45 doc.read_string (xml);
46 _device = doc.string_child("Device");
47 for (auto i: doc.node_children("MountPoint")) {
48 _mount_points.push_back (i->content());
50 _size = doc.number_child<uint64_t>("Size");
51 _vendor = doc.optional_string_child("Vendor");
52 _model = doc.optional_string_child("Model");
57 Drive::as_xml () const
60 auto root = doc.create_root_node ("Drive");
61 root->add_child("Device")->add_child_text(_device);
62 for (auto i: _mount_points) {
63 root->add_child("MountPoint")->add_child_text(i.string());
65 root->add_child("Size")->add_child_text(dcp::raw_convert<string>(_size));
67 root->add_child("Vendor")->add_child_text(*_vendor);
70 root->add_child("Model")->add_child_text(*_model);
73 return doc.write_to_string("UTF-8");
78 Drive::description () const
81 snprintf(gb, 64, "%.1f", _size / 1000000000.0);
88 if (name.size() > 0) {
89 name += " " + *_model;
94 if (name.size() == 0) {
98 return String::compose(_("%1 (%2 GB) [%3]"), name, gb, _device);
103 Drive::log_summary () const
106 for (auto i: _mount_points) {
107 mp += i.string() + ",";
112 mp = mp.substr (0, mp.length() - 1);
115 return String::compose(
116 "Device %1 mounted on %2 size %3 vendor %4 model %5",
117 _device, mp, _size, _vendor.get_value_or("[none]"), _model.get_value_or("[none]")
123 /* This is in _common so we can use it in unit tests */
124 optional<OSXMediaPath>
125 analyse_osx_media_path (string path)
127 using namespace boost::algorithm;
129 if (path.find("/IOHDIXController") != string::npos) {
130 /* This is a disk image, so we completely ignore it */
131 LOG_DISK_NC("Ignoring this as it seems to be a disk image");
136 if (starts_with(path, "IODeviceTree:")) {
138 } else if (starts_with(path, "IOService:")) {
145 split(bits, path, boost::is_any_of("/"));
147 if (starts_with(i, "PRT")) {
156 /* This is in _common so we can use it in unit tests */
158 osx_disks_to_drives (vector<OSXDisk> disks)
160 using namespace boost::algorithm;
162 /* Mark disks containing mounted partitions as themselves mounted */
163 for (auto& i: disks) {
167 for (auto& j: disks) {
168 if (!j.mount_points.empty() && starts_with(j.mount_point, i.mount_point)) {
169 LOG_DISK("Marking %1 as mounted because %2 is", i.mount_point, j.mount_point);
170 std::copy(j.mount_points.begin(), j.mount_points.end(), back_inserter(i.mount_points));
175 /* Make a map of the PRT codes and mount points of mounted, synthesized disks */
176 map<string, vector<boost::filesystem::path>> mounted_synths;
177 for (auto const& i: disks) {
178 if (!i.real && !i.mount_points.empty()) {
179 LOG_DISK("Found a mounted synth %1 with %2", i.mount_point, i.prt);
180 mounted_synths[i.prt] = i.mount_points;
184 /* Mark containers of those mounted synths as themselves mounted */
185 for (auto& i: disks) {
187 auto j = mounted_synths.find(i.prt);
188 if (j != mounted_synths.end()) {
189 LOG_DISK("Marking %1 (%2) as mounted because it contains a mounted synth", i.mount_point, i.prt);
190 std::copy(j->second.begin(), j->second.end(), back_inserter(i.mount_points));
195 vector<Drive> drives;
196 for (auto const& i: disks) {
198 /* A whole disk that is not a container for a mounted synth */
199 drives.push_back(Drive(i.mount_point, i.mount_points, i.size, i.vendor, i.model));
200 LOG_DISK_NC(drives.back().log_summary());