summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2023-10-06 02:04:49 +0200
committerCarl Hetherington <cth@carlh.net>2023-10-09 01:20:01 +0200
commite4b2ebd80779a44d24fe87af26ef278c1e2d97d2 (patch)
tree3bc940c5eb49c96c3c18a896c8ccd8039e6db839 /src
parent3be26a66645de04c7b220abeebfd2f024990a696 (diff)
Add wrappers around boost::filesystem methods that handle the
required mangling of long filenames on Windows. Also wrap lots of missing places (e.g. calls to asdcplib, libxml++, libcxml etc.) in dcp::filesystem::fix_long_path(). The idea is to keep paths un-mangled until they we call some filesystem-related API and mangle them at that point. Otherwise we end up serialising mangled names, which seems like it will not end well. Should fix DoM #2623.
Diffstat (limited to 'src')
-rw-r--r--src/array_data.cc3
-rw-r--r--src/asset.cc32
-rw-r--r--src/asset_factory.cc2
-rw-r--r--src/asset_map.cc9
-rw-r--r--src/asset_reader.h3
-rw-r--r--src/atmos_asset.cc2
-rw-r--r--src/atmos_asset_writer.cc3
-rw-r--r--src/certificate_chain.cc21
-rw-r--r--src/combine.cc21
-rw-r--r--src/cpl.cc5
-rw-r--r--src/dcp.cc18
-rw-r--r--src/file.cc46
-rw-r--r--src/file.h3
-rw-r--r--src/filesystem.cc329
-rw-r--r--src/filesystem.h124
-rw-r--r--src/interop_subtitle_asset.cc3
-rw-r--r--src/mono_picture_asset.cc7
-rw-r--r--src/mono_picture_frame.cc3
-rw-r--r--src/picture_asset_writer_common.cc7
-rw-r--r--src/pkl.cc5
-rw-r--r--src/search.cc3
-rw-r--r--src/smpte_subtitle_asset.cc15
-rw-r--r--src/sound_asset.cc9
-rw-r--r--src/sound_asset_writer.cc3
-rw-r--r--src/stereo_picture_asset.cc7
-rw-r--r--src/subtitle_image.cc5
-rw-r--r--src/util.cc7
-rw-r--r--src/verify.cc15
-rw-r--r--src/wscript2
29 files changed, 574 insertions, 138 deletions
diff --git a/src/array_data.cc b/src/array_data.cc
index 52a22cf6..e388454a 100644
--- a/src/array_data.cc
+++ b/src/array_data.cc
@@ -39,6 +39,7 @@
#include "array_data.h"
#include "file.h"
+#include "filesystem.h"
#include "exceptions.h"
#include "util.h"
#include <cerrno>
@@ -71,7 +72,7 @@ ArrayData::ArrayData (uint8_t const * data, int size)
ArrayData::ArrayData (boost::filesystem::path file)
{
- auto const size = boost::filesystem::file_size (file);
+ auto const size = filesystem::file_size(file);
_data = std::make_shared<std::vector<uint8_t>>(size);
File f(file, "rb");
diff --git a/src/asset.cc b/src/asset.cc
index 213d4878..15f81015 100644
--- a/src/asset.cc
+++ b/src/asset.cc
@@ -43,6 +43,7 @@
#include "dcp_assert.h"
#include "equality_options.h"
#include "exceptions.h"
+#include "filesystem.h"
#include "pkl.h"
#include "raw_convert.h"
#include "util.h"
@@ -57,7 +58,6 @@ using std::string;
using boost::function;
using std::shared_ptr;
using boost::optional;
-using namespace boost::filesystem;
using namespace dcp;
@@ -67,14 +67,14 @@ Asset::Asset ()
}
-Asset::Asset (path file)
+Asset::Asset(boost::filesystem::path file)
: _file (file)
{
}
-Asset::Asset (string id, path file)
+Asset::Asset(string id, boost::filesystem::path file)
: Object (id)
, _file (file)
{
@@ -83,13 +83,13 @@ Asset::Asset (string id, path file)
void
-Asset::add_to_pkl (shared_ptr<PKL> pkl, path root) const
+Asset::add_to_pkl(shared_ptr<PKL> pkl, boost::filesystem::path root) const
{
DCP_ASSERT (_file);
auto path = relative_to_root (
- canonical(root),
- canonical(_file.get())
+ filesystem::canonical(root),
+ filesystem::canonical(_file.get())
);
if (!path) {
@@ -104,7 +104,7 @@ Asset::add_to_pkl (shared_ptr<PKL> pkl, path root) const
void
-Asset::add_to_assetmap (AssetMap& asset_map, path root) const
+Asset::add_to_assetmap(AssetMap& asset_map, boost::filesystem::path root) const
{
DCP_ASSERT (_file);
add_file_to_assetmap (asset_map, root, _file.get(), _id);
@@ -112,11 +112,11 @@ Asset::add_to_assetmap (AssetMap& asset_map, path root) const
void
-Asset::add_file_to_assetmap (AssetMap& asset_map, path root, path file, string id)
+Asset::add_file_to_assetmap(AssetMap& asset_map, boost::filesystem::path root, boost::filesystem::path file, string id)
{
auto path = relative_to_root (
- canonical(root),
- canonical(file)
+ filesystem::canonical(root),
+ filesystem::canonical(file)
);
if (!path) {
@@ -160,24 +160,24 @@ Asset::equals(std::shared_ptr<const Asset> other, EqualityOptions const& opt, No
void
-Asset::set_file (path file) const
+Asset::set_file(boost::filesystem::path file) const
{
- _file = absolute (file);
+ _file = filesystem::absolute(file);
_hash = optional<string>();
}
void
-Asset::set_file_preserving_hash(path file) const
+Asset::set_file_preserving_hash(boost::filesystem::path file) const
{
- _file = absolute(file);
+ _file = filesystem::absolute(file);
}
void
-Asset::rename_file(path file)
+Asset::rename_file(boost::filesystem::path file)
{
- _file = absolute(file);
+ _file = filesystem::absolute(file);
}
diff --git a/src/asset_factory.cc b/src/asset_factory.cc
index 2ab79899..1f830cce 100644
--- a/src/asset_factory.cc
+++ b/src/asset_factory.cc
@@ -61,7 +61,7 @@ dcp::asset_factory (boost::filesystem::path path, bool ignore_incorrect_picture_
*/
ASDCP::EssenceType_t type;
- auto const result = ASDCP::EssenceType(path.string().c_str(), type);
+ auto const result = ASDCP::EssenceType(dcp::filesystem::fix_long_path(path).string().c_str(), type);
if (result != ASDCP::RESULT_OK) {
throw ReadError(String::compose("Could not find essence type (%1)", result.Message()), path.string());
}
diff --git a/src/asset_map.cc b/src/asset_map.cc
index c1bafd92..281f27c3 100644
--- a/src/asset_map.cc
+++ b/src/asset_map.cc
@@ -35,6 +35,7 @@
#include "asset_map.h"
#include "dcp_assert.h"
#include "exceptions.h"
+#include "filesystem.h"
#include "raw_convert.h"
#include "warnings.h"
LIBDCP_DISABLE_WARNINGS
@@ -60,7 +61,7 @@ AssetMap::AssetMap(boost::filesystem::path file)
{
cxml::Document doc("AssetMap");
- doc.read_file(file);
+ doc.read_file(dcp::filesystem::fix_long_path(file));
if (doc.namespace_uri() == assetmap_interop_ns) {
_standard = Standard::INTEROP;
} else if (doc.namespace_uri() == assetmap_smpte_ns) {
@@ -191,7 +192,7 @@ AssetMap::write_xml(boost::filesystem::path file) const
asset.write_xml(asset_list, file.parent_path());
}
- doc.write_to_file_formatted(file.string(), "UTF-8");
+ doc.write_to_file_formatted(dcp::filesystem::fix_long_path(file).string(), "UTF-8");
_file = file;
}
@@ -207,12 +208,12 @@ AssetMap::Asset::write_xml(xmlpp::Element* asset_list, boost::filesystem::path d
auto chunk_list = node->add_child("ChunkList");
auto chunk = chunk_list->add_child("Chunk");
- auto relative_path = relative_to_root(boost::filesystem::canonical(dcp_root_directory), boost::filesystem::canonical(_path));
+ auto relative_path = relative_to_root(filesystem::canonical(dcp_root_directory), filesystem::canonical(_path));
DCP_ASSERT(relative_path);
chunk->add_child("Path")->add_child_text(relative_path->generic_string());
chunk->add_child("VolumeIndex")->add_child_text("1");
chunk->add_child("Offset")->add_child_text("0");
- chunk->add_child("Length")->add_child_text(raw_convert<string>(boost::filesystem::file_size(_path)));
+ chunk->add_child("Length")->add_child_text(raw_convert<string>(filesystem::file_size(_path)));
}
diff --git a/src/asset_reader.h b/src/asset_reader.h
index 8478b51f..c8953e09 100644
--- a/src/asset_reader.h
+++ b/src/asset_reader.h
@@ -44,6 +44,7 @@
#include "asset.h"
#include "crypto_context.h"
#include "dcp_assert.h"
+#include "filesystem.h"
#include <asdcp/AS_DCP.h>
#include <memory>
@@ -98,7 +99,7 @@ private:
{
_reader = new R ();
DCP_ASSERT (asset->file());
- auto const r = _reader->OpenRead (asset->file()->string().c_str());
+ auto const r = _reader->OpenRead(dcp::filesystem::fix_long_path(*asset->file()).string().c_str());
if (ASDCP_FAILURE(r)) {
delete _reader;
boost::throw_exception (FileError("could not open MXF file for reading", asset->file().get(), r));
diff --git a/src/atmos_asset.cc b/src/atmos_asset.cc
index ae381737..42a0774e 100644
--- a/src/atmos_asset.cc
+++ b/src/atmos_asset.cc
@@ -68,7 +68,7 @@ AtmosAsset::AtmosAsset (boost::filesystem::path file)
, MXF (Standard::SMPTE)
{
ASDCP::ATMOS::MXFReader reader;
- auto r = reader.OpenRead (file.string().c_str());
+ auto r = reader.OpenRead(dcp::filesystem::fix_long_path(file).string().c_str());
if (ASDCP_FAILURE (r)) {
boost::throw_exception (MXFFileError("could not open MXF file for reading", file.string(), r));
}
diff --git a/src/atmos_asset_writer.cc b/src/atmos_asset_writer.cc
index 9d7363d0..0c895b5b 100644
--- a/src/atmos_asset_writer.cc
+++ b/src/atmos_asset_writer.cc
@@ -43,6 +43,7 @@
#include "crypto_context.h"
#include "dcp_assert.h"
#include "exceptions.h"
+#include "filesystem.h"
#include <asdcp/AS_DCP.h>
@@ -94,7 +95,7 @@ AtmosAssetWriter::write (uint8_t const * data, int size)
DCP_ASSERT (!_finalized);
if (!_started) {
- auto r = _state->mxf_writer.OpenWrite (_file.string().c_str(), _state->writer_info, _state->desc);
+ auto r = _state->mxf_writer.OpenWrite(dcp::filesystem::fix_long_path(_file).string().c_str(), _state->writer_info, _state->desc);
if (ASDCP_FAILURE(r)) {
boost::throw_exception (FileError ("could not open atmos MXF for writing", _file.string(), r));
}
diff --git a/src/certificate_chain.cc b/src/certificate_chain.cc
index 449dba89..6748d73c 100644
--- a/src/certificate_chain.cc
+++ b/src/certificate_chain.cc
@@ -41,6 +41,7 @@
#include "compose.hpp"
#include "dcp_assert.h"
#include "exceptions.h"
+#include "filesystem.h"
#include "util.h"
#include "warnings.h"
#include <asdcp/KM_util.h>
@@ -57,7 +58,6 @@ LIBDCP_ENABLE_WARNINGS
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
-#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
#include <fstream>
#include <iostream>
@@ -114,7 +114,7 @@ command (string cmd)
int const code = WEXITSTATUS (r);
#endif
if (code) {
- throw dcp::MiscError (String::compose ("error %1 in %2 within %3", code, cmd, boost::filesystem::current_path().string()));
+ throw dcp::MiscError(String::compose("error %1 in %2 within %3", code, cmd, filesystem::current_path().string()));
}
}
@@ -196,10 +196,14 @@ CertificateChain::CertificateChain (
)
{
auto directory = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path ();
- boost::filesystem::create_directories (directory);
+ filesystem::create_directories(directory);
- auto const cwd = boost::filesystem::current_path ();
- boost::filesystem::current_path (directory);
+ auto const cwd = boost::filesystem::current_path();
+ /* On Windows we will use cmd.exe here, and that doesn't work with UNC paths, so make sure
+ * we don't use our own filesystem::current_path() as it will make the current working
+ * directory a UNC path.
+ */
+ boost::filesystem::current_path(directory);
string quoted_openssl = "\"" + openssl.string() + "\"";
@@ -319,7 +323,10 @@ CertificateChain::CertificateChain (
)
);
- boost::filesystem::current_path (cwd);
+ /* Use boost:: rather than dcp:: here so we don't force UNC into the current path if it
+ * wasn't there before.
+ */
+ boost::filesystem::current_path(cwd);
_certificates.push_back (dcp::Certificate(dcp::file_to_string(directory / "ca.self-signed.pem")));
_certificates.push_back (dcp::Certificate(dcp::file_to_string(directory / "intermediate.signed.pem")));
@@ -327,7 +334,7 @@ CertificateChain::CertificateChain (
_key = dcp::file_to_string (directory / "leaf.key");
- boost::filesystem::remove_all (directory);
+ filesystem::remove_all(directory);
}
diff --git a/src/combine.cc b/src/combine.cc
index b728298a..b7a625f0 100644
--- a/src/combine.cc
+++ b/src/combine.cc
@@ -43,6 +43,7 @@
#include "dcp.h"
#include "dcp_assert.h"
#include "exceptions.h"
+#include "filesystem.h"
#include "font_asset.h"
#include "interop_subtitle_asset.h"
#include "raw_convert.h"
@@ -52,25 +53,25 @@
#include <vector>
+using std::dynamic_pointer_cast;
using std::map;
using std::set;
+using std::shared_ptr;
using std::string;
using std::vector;
-using std::dynamic_pointer_cast;
using boost::optional;
-using std::shared_ptr;
boost::filesystem::path
make_unique (boost::filesystem::path path)
{
- if (!boost::filesystem::exists(path)) {
+ if (!dcp::filesystem::exists(path)) {
return path;
}
for (int i = 0; i < 10000; ++i) {
boost::filesystem::path p = path.parent_path() / (path.stem().string() + dcp::raw_convert<string>(i) + path.extension().string());
- if (!boost::filesystem::exists(p)) {
+ if (!dcp::filesystem::exists(p)) {
return p;
}
}
@@ -85,10 +86,10 @@ void
create_hard_link_or_copy (boost::filesystem::path from, boost::filesystem::path to)
{
try {
- create_hard_link (from, to);
+ dcp::filesystem::create_hard_link(from, to);
} catch (boost::filesystem::filesystem_error& e) {
if (e.code() == boost::system::errc::cross_device_link) {
- copy_file (from, to);
+ dcp::filesystem::copy_file(from, to);
} else {
throw;
}
@@ -107,8 +108,6 @@ dcp::combine (
shared_ptr<const CertificateChain> signer
)
{
- using namespace boost::filesystem;
-
DCP_ASSERT (!inputs.empty());
DCP output_dcp (output);
@@ -124,7 +123,7 @@ dcp::combine (
}
}
- vector<path> paths;
+ vector<boost::filesystem::path> paths;
vector<shared_ptr<dcp::Asset>> assets;
for (auto i: inputs) {
@@ -153,7 +152,7 @@ dcp::combine (
}
auto file = sub->file();
DCP_ASSERT (file);
- path new_path = make_unique(output / file->filename());
+ auto new_path = make_unique(output / file->filename());
sub->write (new_path);
add_to_container(assets, sub->font_assets());
}
@@ -168,7 +167,7 @@ dcp::combine (
if (!dynamic_pointer_cast<dcp::FontAsset>(i) && !dynamic_pointer_cast<dcp::CPL>(i)) {
auto file = i->file();
DCP_ASSERT (file);
- path new_path = make_unique(output / file->filename());
+ auto new_path = make_unique(output / file->filename());
create_hard_link_or_copy (*file, new_path);
i->set_file (new_path);
}
diff --git a/src/cpl.cc b/src/cpl.cc
index bbdaee18..5467fef3 100644
--- a/src/cpl.cc
+++ b/src/cpl.cc
@@ -42,6 +42,7 @@
#include "cpl.h"
#include "dcp_assert.h"
#include "equality_options.h"
+#include "filesystem.h"
#include "local_time.h"
#include "metadata.h"
#include "raw_convert.h"
@@ -108,7 +109,7 @@ CPL::CPL (boost::filesystem::path file)
, _content_kind (ContentKind::FEATURE)
{
cxml::Document f ("CompositionPlaylist");
- f.read_file (file);
+ f.read_file(dcp::filesystem::fix_long_path(file));
if (f.namespace_uri() == cpl_interop_ns) {
_standard = Standard::INTEROP;
@@ -239,7 +240,7 @@ CPL::write_xml(boost::filesystem::path file, shared_ptr<const CertificateChain>
signer->sign (root, _standard);
}
- doc.write_to_file_formatted (file.string(), "UTF-8");
+ doc.write_to_file_formatted(dcp::filesystem::fix_long_path(file).string(), "UTF-8");
set_file (file);
}
diff --git a/src/dcp.cc b/src/dcp.cc
index 7c253a17..d603cfae 100644
--- a/src/dcp.cc
+++ b/src/dcp.cc
@@ -47,6 +47,7 @@
#include "decrypted_kdm.h"
#include "decrypted_kdm_key.h"
#include "exceptions.h"
+#include "filesystem.h"
#include "font_asset.h"
#include "interop_subtitle_asset.h"
#include "metadata.h"
@@ -71,7 +72,6 @@ LIBDCP_DISABLE_WARNINGS
#include <libxml++/libxml++.h>
LIBDCP_ENABLE_WARNINGS
#include <boost/algorithm/string.hpp>
-#include <boost/filesystem.hpp>
#include <numeric>
@@ -98,11 +98,11 @@ static string const volindex_smpte_ns = "http://www.smpte-ra.org/schemas/429-9
DCP::DCP (boost::filesystem::path directory)
: _directory (directory)
{
- if (!boost::filesystem::exists (directory)) {
- boost::filesystem::create_directories (directory);
+ if (!filesystem::exists(directory)) {
+ filesystem::create_directories(directory);
}
- _directory = boost::filesystem::canonical (_directory);
+ _directory = filesystem::canonical(_directory);
}
@@ -141,9 +141,9 @@ DCP::read (vector<dcp::VerificationNote>* notes, bool ignore_incorrect_picture_m
/* Read the ASSETMAP and PKL */
boost::filesystem::path asset_map_path;
- if (boost::filesystem::exists(_directory / "ASSETMAP")) {
+ if (filesystem::exists(_directory / "ASSETMAP")) {
asset_map_path = _directory / "ASSETMAP";
- } else if (boost::filesystem::exists(_directory / "ASSETMAP.xml")) {
+ } else if (filesystem::exists(_directory / "ASSETMAP.xml")) {
asset_map_path = _directory / "ASSETMAP.xml";
} else {
boost::throw_exception(MissingAssetmapError(_directory));
@@ -189,7 +189,7 @@ DCP::read (vector<dcp::VerificationNote>* notes, bool ignore_incorrect_picture_m
continue;
}
- if (!boost::filesystem::exists(path)) {
+ if (!filesystem::exists(path)) {
if (notes) {
notes->push_back ({VerificationNote::Type::ERROR, VerificationNote::Code::MISSING_ASSET, path});
}
@@ -224,7 +224,7 @@ DCP::read (vector<dcp::VerificationNote>* notes, bool ignore_incorrect_picture_m
pkl_type == remove_parameters(InteropSubtitleAsset::static_pkl_type(standard))) {
auto p = new xmlpp::DomParser;
try {
- p->parse_file (path.string());
+ p->parse_file(dcp::filesystem::fix_long_path(path).string());
} catch (std::exception& e) {
delete p;
throw ReadError(String::compose("XML error in %1", path.string()), e.what());
@@ -442,7 +442,7 @@ DCP::write_volindex (Standard standard) const
}
root->add_child("Index")->add_child_text ("1");
- doc.write_to_file_formatted (p.string (), "UTF-8");
+ doc.write_to_file_formatted(dcp::filesystem::fix_long_path(p).string(), "UTF-8");
}
diff --git a/src/file.cc b/src/file.cc
index b5d2eed4..36102f72 100644
--- a/src/file.cc
+++ b/src/file.cc
@@ -34,7 +34,7 @@
#include "dcp_assert.h"
#include "file.h"
-#include <boost/algorithm/string.hpp>
+#include "filesystem.h"
#ifdef LIBDCP_WINDOWS
#include <errhandlingapi.h>
#endif
@@ -57,7 +57,7 @@ File::File(boost::filesystem::path path, std::string mode)
SetLastError(0);
std::wstring mode_wide(mode.begin(), mode.end());
/* c_str() here should give a UTF-16 string */
- _file = _wfopen(fix_long_path(path).c_str(), mode_wide.c_str());
+ _file = _wfopen(dcp::filesystem::fix_long_path(path).c_str(), mode_wide.c_str());
if (!_file) {
_open_error = GetLastError();
}
@@ -216,45 +216,3 @@ File::error ()
DCP_ASSERT(_file);
return ferror(_file);
}
-
-
-/** Windows can't "by default" cope with paths longer than 260 characters, so if you pass such a path to
- * any boost::filesystem method it will fail. There is a "fix" for this, which is to prepend
- * the string \\?\ to the path. This will make it work, so long as:
- * - the path is absolute.
- * - the path only uses backslashes.
- * - individual path components are "short enough" (probably less than 255 characters)
- *
- * See https://www.boost.org/doc/libs/1_57_0/libs/filesystem/doc/reference.html under
- * "Warning: Long paths on Windows" for some details.
- *
- * Our fopen_boost uses this method to get this fix, but any other calls to boost::filesystem
- * will not unless this method is explicitly called to pre-process the pathname.
- */
-boost::filesystem::path
-dcp::fix_long_path (boost::filesystem::path long_path)
-{
-#ifdef LIBDCP_WINDOWS
- using namespace boost::filesystem;
-
- if (boost::algorithm::starts_with(long_path.string(), "\\\\")) {
- /* This could mean it starts with \\ (i.e. a SMB path) or \\?\ (a long path)
- * or a variety of other things... anyway, we'll leave it alone.
- */
- return long_path;
- }
-
- /* We have to make the path canonical but we can't call canonical() on the long path
- * as it will fail. So we'll sort of do it ourselves (possibly badly).
- */
- path fixed = "\\\\?\\";
- if (long_path.is_absolute()) {
- fixed += long_path.make_preferred();
- } else {
- fixed += boost::filesystem::current_path() / long_path.make_preferred();
- }
- return fixed;
-#else
- return long_path;
-#endif
-}
diff --git a/src/file.h b/src/file.h
index 22083a9e..c530c26c 100644
--- a/src/file.h
+++ b/src/file.h
@@ -115,9 +115,6 @@ private:
};
-boost::filesystem::path fix_long_path(boost::filesystem::path long_path);
-
-
}
diff --git a/src/filesystem.cc b/src/filesystem.cc
new file mode 100644
index 00000000..0dd89228
--- /dev/null
+++ b/src/filesystem.cc
@@ -0,0 +1,329 @@
+/*
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ libdcp is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#include "filesystem.h"
+#include <boost/algorithm/string.hpp>
+
+
+bool
+dcp::filesystem::exists(boost::filesystem::path const& path)
+{
+ return boost::filesystem::exists(dcp::filesystem::fix_long_path(path));
+}
+
+
+bool
+dcp::filesystem::is_regular_file(boost::filesystem::path const& path)
+{
+ return boost::filesystem::is_regular_file(dcp::filesystem::fix_long_path(path));
+}
+
+
+bool
+dcp::filesystem::create_directory(boost::filesystem::path const& path)
+{
+ return boost::filesystem::create_directory(dcp::filesystem::fix_long_path(path));
+}
+
+
+void
+dcp::filesystem::copy(boost::filesystem::path const& from, boost::filesystem::path const& to)
+{
+ boost::filesystem::copy(dcp::filesystem::fix_long_path(from), dcp::filesystem::fix_long_path(to));
+}
+
+
+void
+dcp::filesystem::copy_file(boost::filesystem::path const& from, boost::filesystem::path const& to)
+{
+ boost::filesystem::copy_file(dcp::filesystem::fix_long_path(from), dcp::filesystem::fix_long_path(to));
+}
+
+
+bool
+dcp::filesystem::create_directories(boost::filesystem::path const& path)
+{
+ return boost::filesystem::create_directories(dcp::filesystem::fix_long_path(path));
+}
+
+
+boost::filesystem::path
+dcp::filesystem::absolute(boost::filesystem::path const& path)
+{
+ return dcp::filesystem::unfix_long_path(boost::filesystem::absolute(dcp::filesystem::fix_long_path(path)));
+}
+
+
+boost::filesystem::path
+dcp::filesystem::canonical(boost::filesystem::path const& path)
+{
+ return dcp::filesystem::unfix_long_path(boost::filesystem::canonical(dcp::filesystem::fix_long_path(path)));
+}
+
+
+uintmax_t
+dcp::filesystem::remove_all(boost::filesystem::path const& path)
+{
+ return boost::filesystem::remove_all(dcp::filesystem::fix_long_path(path));
+}
+
+
+uintmax_t
+dcp::filesystem::file_size(boost::filesystem::path const& path)
+{
+ return boost::filesystem::file_size(dcp::filesystem::fix_long_path(path));
+}
+
+
+boost::filesystem::path
+dcp::filesystem::current_path()
+{
+ return dcp::filesystem::unfix_long_path(boost::filesystem::current_path());
+}
+
+
+void
+dcp::filesystem::current_path(boost::filesystem::path const& path)
+{
+ boost::filesystem::current_path(dcp::filesystem::fix_long_path(path));
+}
+
+
+void
+dcp::filesystem::create_hard_link(boost::filesystem::path const& from, boost::filesystem::path const& to)
+{
+ boost::filesystem::create_hard_link(dcp::filesystem::fix_long_path(from), dcp::filesystem::fix_long_path(to));
+}
+
+
+#ifdef DCPOMATIC_WINDOWS
+
+dcp::filesystem::directory_iterator::directory_iterator(boost::filesystem::path const& path)
+ : _wrapped(dcp::filesystem::fix_long_path(path))
+{
+
+}
+
+
+boost::filesystem::path
+dcp::filesystem::directory_entry::path() const
+{
+ return dcp::filesystem::unfix_long_path(_path);
+}
+
+
+dcp::filesystem::directory_entry::operator boost::filesystem::path const &() const
+{
+ return dcp::filesystem::unfix_long_path(_path);
+}
+
+
+dcp::filesystem::recursive_directory_iterator::recursive_directory_iterator(boost::filesystem::path const& path)
+ : _wrapped(dcp::filesystem::fix_long_path(path))
+{
+
+}
+
+#else
+
+dcp::filesystem::directory_iterator::directory_iterator(boost::filesystem::path const& path)
+ : _wrapped(path)
+{
+
+}
+
+
+boost::filesystem::path
+dcp::filesystem::directory_entry::path() const
+{
+ return _path;
+}
+
+
+dcp::filesystem::directory_entry::operator boost::filesystem::path const &() const
+{
+ return _path;
+}
+
+
+dcp::filesystem::recursive_directory_iterator::recursive_directory_iterator(boost::filesystem::path const& path)
+ : _wrapped(path)
+{
+
+}
+
+#endif
+
+
+dcp::filesystem::directory_entry::directory_entry(boost::filesystem::path const& path)
+ : _path(path)
+{
+
+}
+
+
+dcp::filesystem::directory_iterator&
+dcp::filesystem::directory_iterator::operator++()
+{
+ ++_wrapped;
+ return *this;
+}
+
+
+dcp::filesystem::directory_entry
+dcp::filesystem::directory_iterator::operator*() const
+{
+ return dcp::filesystem::directory_entry(*_wrapped);
+}
+
+
+bool
+dcp::filesystem::directory_iterator::operator!=(dcp::filesystem::directory_iterator const& other) const
+{
+ return _wrapped != other._wrapped;
+}
+
+
+dcp::filesystem::directory_iterator const&
+dcp::filesystem::begin(dcp::filesystem::directory_iterator const& iter)
+{
+ return iter;
+}
+
+
+dcp::filesystem::directory_iterator
+dcp::filesystem::end(dcp::filesystem::directory_iterator const&)
+{
+ return dcp::filesystem::directory_iterator();
+}
+
+
+dcp::filesystem::recursive_directory_iterator&
+dcp::filesystem::recursive_directory_iterator::operator++()
+{
+ ++_wrapped;
+ return *this;
+}
+
+
+bool
+dcp::filesystem::recursive_directory_iterator::operator!=(dcp::filesystem::recursive_directory_iterator const& other) const
+{
+ return _wrapped != other._wrapped;
+}
+
+
+dcp::filesystem::directory_entry
+dcp::filesystem::recursive_directory_iterator::operator*() const
+{
+ _entry = dcp::filesystem::directory_entry(_wrapped->path());
+ return _entry;
+}
+
+
+dcp::filesystem::directory_entry*
+dcp::filesystem::recursive_directory_iterator::operator->() const
+{
+ _entry = dcp::filesystem::directory_entry(_wrapped->path());
+ return &_entry;
+}
+
+
+dcp::filesystem::recursive_directory_iterator const&
+dcp::filesystem::begin(dcp::filesystem::recursive_directory_iterator const& iter)
+{
+ return iter;
+}
+
+
+dcp::filesystem::recursive_directory_iterator
+dcp::filesystem::end(dcp::filesystem::recursive_directory_iterator const&)
+{
+ return dcp::filesystem::recursive_directory_iterator();
+}
+
+
+/** Windows can't "by default" cope with paths longer than 260 characters, so if you pass such a path to
+ * any boost::filesystem method it will fail. There is a "fix" for this, which is to prepend
+ * the string \\?\ to the path. This will make it work, so long as:
+ * - the path is absolute.
+ * - the path contains no .. parts.
+ * - the path only uses backslashes.
+ * - individual path components are "short enough" (probably less than 255 characters)
+ *
+ * See https://www.boost.org/doc/libs/1_57_0/libs/filesystem/doc/reference.html under
+ * "Warning: Long paths on Windows" for some details.
+ *
+ * Our fopen_boost uses this method to get this fix, but any other calls to boost::filesystem
+ * will not unless this method is explicitly called to pre-process the pathname.
+ */
+boost::filesystem::path
+dcp::filesystem::fix_long_path(boost::filesystem::path long_path)
+{
+#ifdef LIBDCP_WINDOWS
+ using namespace boost::filesystem;
+
+ if (boost::algorithm::starts_with(long_path.string(), "\\\\")) {
+ /* This could mean it starts with \\ (i.e. a SMB path) or \\?\ (a long path)
+ * or a variety of other things... anyway, we'll leave it alone.
+ */
+ return long_path;
+ }
+
+ /* We have to make the path canonical but we can't call canonical() on the long path
+ * as it will fail. So we'll sort of do it ourselves (possibly badly).
+ */
+ path fixed = "\\\\?\\";
+ if (long_path.is_absolute()) {
+ fixed += long_path.make_preferred();
+ } else {
+ fixed += filesystem::current_path() / long_path.make_preferred();
+ }
+ return fixed;
+#else
+ return long_path;
+#endif
+}
+
+
+boost::filesystem::path
+dcp::filesystem::unfix_long_path(boost::filesystem::path long_path)
+{
+#ifdef LIBDCP_WINDOWS
+ if (boost::algorithm::starts_with(long_path.string(), "\\\\?\\")) {
+ return long_path.string().substr(4);
+ }
+#endif
+ return long_path;
+}
diff --git a/src/filesystem.h b/src/filesystem.h
new file mode 100644
index 00000000..d9fb2791
--- /dev/null
+++ b/src/filesystem.h
@@ -0,0 +1,124 @@
+/*
+ Copyright (C) 2012-2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ libdcp is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#ifndef LIBDCP_FILESYSTEM_H
+#define LIBDCP_FILESYSTEM_H
+
+
+#include <boost/filesystem.hpp>
+
+
+namespace dcp
+{
+namespace filesystem
+{
+
+boost::filesystem::path absolute(boost::filesystem::path const& path);
+boost::filesystem::path canonical(boost::filesystem::path const& path);
+void copy(boost::filesystem::path const& from, boost::filesystem::path const& to);
+void copy_file(boost::filesystem::path const& from, boost::filesystem::path const& to);
+bool create_directory(boost::filesystem::path const& path);
+bool create_directories(boost::filesystem::path const& path);
+void create_hard_link(boost::filesystem::path const& from, boost::filesystem::path const& to);
+void current_path(boost::filesystem::path const& path);
+boost::filesystem::path current_path();
+bool exists(boost::filesystem::path const& path);
+bool is_regular_file(boost::filesystem::path const& path);
+uintmax_t file_size(boost::filesystem::path const& path);
+uintmax_t remove_all(boost::filesystem::path const& path);
+
+
+class directory_entry
+{
+public:
+ directory_entry() {}
+ directory_entry(boost::filesystem::path const& path);
+
+ boost::filesystem::path path() const;
+ operator boost::filesystem::path const&() const;
+
+private:
+ boost::filesystem::path _path;
+};
+
+
+class directory_iterator
+{
+public:
+ directory_iterator() = default;
+ directory_iterator(boost::filesystem::path const& path);
+
+ directory_iterator& operator++();
+ directory_entry operator*() const;
+ bool operator!=(directory_iterator const& other) const;
+
+private:
+ boost::filesystem::directory_iterator _wrapped;
+};
+
+
+directory_iterator const& begin(directory_iterator const& iter);
+directory_iterator end(directory_iterator const&);
+
+
+
+class recursive_directory_iterator
+{
+public:
+ recursive_directory_iterator() = default;
+ recursive_directory_iterator(boost::filesystem::path const& path);
+
+ recursive_directory_iterator& operator++();
+ directory_entry operator*() const;
+ directory_entry* operator->() const;
+ bool operator!=(recursive_directory_iterator const& other) const;
+
+private:
+ boost::filesystem::recursive_directory_iterator _wrapped;
+ mutable directory_entry _entry;
+};
+
+
+recursive_directory_iterator const& begin(recursive_directory_iterator const& iter);
+recursive_directory_iterator end(recursive_directory_iterator const&);
+
+
+boost::filesystem::path fix_long_path(boost::filesystem::path long_path);
+boost::filesystem::path unfix_long_path(boost::filesystem::path long_path);
+
+}
+}
+
+
+#endif
diff --git a/src/interop_subtitle_asset.cc b/src/interop_subtitle_asset.cc
index d26143a4..32c3f66a 100644
--- a/src/interop_subtitle_asset.cc
+++ b/src/interop_subtitle_asset.cc
@@ -40,6 +40,7 @@
#include "compose.hpp"
#include "dcp_assert.h"
#include "equality_options.h"
+#include "filesystem.h"
#include "font_asset.h"
#include "file.h"
#include "interop_load_font_node.h"
@@ -75,7 +76,7 @@ InteropSubtitleAsset::InteropSubtitleAsset (boost::filesystem::path file)
_raw_xml = dcp::file_to_string (file);
auto xml = make_shared<cxml::Document>("DCSubtitle");
- xml->read_file (file);
+ xml->read_file(dcp::filesystem::fix_long_path(file));
_id = xml->string_child ("SubtitleID");
_reel_number = xml->string_child ("ReelNumber");
_language = xml->string_child ("Language");
diff --git a/src/mono_picture_asset.cc b/src/mono_picture_asset.cc
index 55d3f6ba..cc24e198 100644
--- a/src/mono_picture_asset.cc
+++ b/src/mono_picture_asset.cc
@@ -41,6 +41,7 @@
#include "dcp_assert.h"
#include "equality_options.h"
#include "exceptions.h"
+#include "filesystem.h"
#include "mono_picture_asset.h"
#include "mono_picture_asset_reader.h"
#include "mono_picture_asset_writer.h"
@@ -66,7 +67,7 @@ MonoPictureAsset::MonoPictureAsset (boost::filesystem::path file)
: PictureAsset (file)
{
ASDCP::JP2K::MXFReader reader;
- auto r = reader.OpenRead (file.string().c_str());
+ auto r = reader.OpenRead(dcp::filesystem::fix_long_path(file).string().c_str());
if (ASDCP_FAILURE(r)) {
boost::throw_exception (MXFFileError("could not open MXF file for reading", file.string(), r));
}
@@ -110,14 +111,14 @@ MonoPictureAsset::equals(shared_ptr<const Asset> other, EqualityOptions const& o
ASDCP::JP2K::MXFReader reader_A;
DCP_ASSERT (_file);
- auto r = reader_A.OpenRead (_file->string().c_str());
+ auto r = reader_A.OpenRead(dcp::filesystem::fix_long_path(*_file).string().c_str());
if (ASDCP_FAILURE(r)) {
boost::throw_exception (MXFFileError("could not open MXF file for reading", _file->string(), r));
}
ASDCP::JP2K::MXFReader reader_B;
DCP_ASSERT (other->file ());
- r = reader_B.OpenRead (other->file()->string().c_str());
+ r = reader_B.OpenRead(dcp::filesystem::fix_long_path(*other->file()).string().c_str());
if (ASDCP_FAILURE (r)) {
boost::throw_exception (MXFFileError ("could not open MXF file for reading", other->file()->string(), r));
}
diff --git a/src/mono_picture_frame.cc b/src/mono_picture_frame.cc
index ddaed983..2abd57e4 100644
--- a/src/mono_picture_frame.cc
+++ b/src/mono_picture_frame.cc
@@ -42,6 +42,7 @@
#include "crypto_context.h"
#include "exceptions.h"
#include "file.h"
+#include "filesystem.h"
#include "j2k_transcode.h"
#include "mono_picture_frame.h"
#include "rgb_xyz.h"
@@ -59,7 +60,7 @@ using namespace dcp;
MonoPictureFrame::MonoPictureFrame (boost::filesystem::path path)
{
- auto const size = boost::filesystem::file_size (path);
+ auto const size = filesystem::file_size(path);
_buffer.reset(new ASDCP::JP2K::FrameBuffer(size));
File f(path, "rb");
if (!f) {
diff --git a/src/picture_asset_writer_common.cc b/src/picture_asset_writer_common.cc
index e719be72..82866aac 100644
--- a/src/picture_asset_writer_common.cc
+++ b/src/picture_asset_writer_common.cc
@@ -37,6 +37,9 @@
*/
+#include "filesystem.h"
+
+
using std::shared_ptr;
@@ -76,8 +79,8 @@ void dcp::start (PictureAssetWriter* writer, shared_ptr<P> state, Q* asset, uint
asset->fill_writer_info (&state->writer_info, asset->id());
- auto r = state->mxf_writer.OpenWrite (
- asset->file()->string().c_str(),
+ auto r = state->mxf_writer.OpenWrite(
+ dcp::filesystem::fix_long_path(*asset->file()).string().c_str(),
state->writer_info,
state->picture_descriptor,
16384,
diff --git a/src/pkl.cc b/src/pkl.cc
index 390d5df2..57eda9da 100644
--- a/src/pkl.cc
+++ b/src/pkl.cc
@@ -39,6 +39,7 @@
#include "dcp_assert.h"
#include "exceptions.h"
+#include "filesystem.h"
#include "pkl.h"
#include "raw_convert.h"
#include "util.h"
@@ -64,7 +65,7 @@ PKL::PKL (boost::filesystem::path file)
: _file (file)
{
cxml::Document pkl ("PackingList");
- pkl.read_file (file);
+ pkl.read_file(dcp::filesystem::fix_long_path(file));
if (pkl.namespace_uri() == pkl_interop_ns) {
_standard = Standard::INTEROP;
@@ -133,7 +134,7 @@ PKL::write_xml (boost::filesystem::path file, shared_ptr<const CertificateChain>
signer->sign (pkl, _standard);
}
- doc.write_to_file_formatted (file.string(), "UTF-8");
+ doc.write_to_file_formatted(dcp::filesystem::fix_long_path(file).string(), "UTF-8");
_file = file;
}
diff --git a/src/search.cc b/src/search.cc
index f45a2fb9..e7871dc6 100644
--- a/src/search.cc
+++ b/src/search.cc
@@ -35,6 +35,7 @@
#include "dcp.h"
#include "decrypted_kdm.h"
#include "exceptions.h"
+#include "filesystem.h"
#include "search.h"
@@ -59,7 +60,7 @@ dcp::find_and_resolve_cpls (vector<boost::filesystem::path> const& directories,
vector<shared_ptr<dcp::DCP>> dcps;
for (auto i: directories) {
- if (!boost::filesystem::exists(i)) {
+ if (!filesystem::exists(i)) {
/* Don't make a DCP object or it will try to create the parent directories
* of i if they do not exist (#2344).
*/
diff --git a/src/smpte_subtitle_asset.cc b/src/smpte_subtitle_asset.cc
index b9d7e9a3..ea1d7426 100644
--- a/src/smpte_subtitle_asset.cc
+++ b/src/smpte_subtitle_asset.cc
@@ -42,6 +42,7 @@
#include "dcp_assert.h"
#include "equality_options.h"
#include "exceptions.h"
+#include "filesystem.h"
#include "raw_convert.h"
#include "smpte_load_font_node.h"
#include "smpte_subtitle_asset.h"
@@ -98,7 +99,7 @@ SMPTESubtitleAsset::SMPTESubtitleAsset (boost::filesystem::path file)
auto r = Kumu::RESULT_OK;
{
ASDCPErrorSuspender sus;
- r = reader->OpenRead (_file->string().c_str ());
+ r = reader->OpenRead(dcp::filesystem::fix_long_path(*_file).string().c_str());
}
if (!ASDCP_FAILURE(r)) {
/* MXF-wrapped */
@@ -122,7 +123,7 @@ SMPTESubtitleAsset::SMPTESubtitleAsset (boost::filesystem::path file)
try {
_raw_xml = dcp::file_to_string (file);
xml = make_shared<cxml::Document>("SubtitleReel");
- xml->read_file (file);
+ xml->read_file(dcp::filesystem::fix_long_path(file));
parse_xml (xml);
} catch (cxml::Error& e) {
boost::throw_exception (
@@ -143,11 +144,11 @@ SMPTESubtitleAsset::SMPTESubtitleAsset (boost::filesystem::path file)
if (im && im->png_image().size() == 0) {
/* Even more dubious; allow <id>.png or urn:uuid:<id>.png */
auto p = file.parent_path() / String::compose("%1.png", im->id());
- if (boost::filesystem::is_regular_file(p)) {
+ if (filesystem::is_regular_file(p)) {
im->read_png_file (p);
} else if (starts_with (im->id(), "urn:uuid:")) {
p = file.parent_path() / String::compose("%1.png", remove_urn_uuid(im->id()));
- if (boost::filesystem::is_regular_file(p)) {
+ if (filesystem::is_regular_file(p)) {
im->read_png_file (p);
}
}
@@ -319,7 +320,7 @@ SMPTESubtitleAsset::set_key (Key key)
/* Our data was encrypted; now we can decrypt it */
auto reader = make_shared<ASDCP::TimedText::MXFReader>();
- auto r = reader->OpenRead (_file->string().c_str ());
+ auto r = reader->OpenRead(dcp::filesystem::fix_long_path(*_file).string().c_str());
if (ASDCP_FAILURE (r)) {
boost::throw_exception (
ReadError (
@@ -353,7 +354,7 @@ SMPTESubtitleAsset::valid_mxf (boost::filesystem::path file)
{
ASDCP::TimedText::MXFReader reader;
Kumu::DefaultLogSink().UnsetFilterFlag(Kumu::LOG_ALLOW_ALL);
- auto r = reader.OpenRead (file.string().c_str ());
+ auto r = reader.OpenRead(dcp::filesystem::fix_long_path(file).string().c_str());
Kumu::DefaultLogSink().SetFilterFlag(Kumu::LOG_ALLOW_ALL);
return !ASDCP_FAILURE (r);
}
@@ -450,7 +451,7 @@ SMPTESubtitleAsset::write (boost::filesystem::path p) const
/* This header size is a guess. Empirically it seems that each subtitle reference is 90 bytes, and we need some extra.
The default size is not enough for some feature-length PNG sub projects (see DCP-o-matic #1561).
*/
- ASDCP::Result_t r = writer.OpenWrite (p.string().c_str(), writer_info, descriptor, _subtitles.size() * 90 + 16384);
+ ASDCP::Result_t r = writer.OpenWrite(dcp::filesystem::fix_long_path(p).string().c_str(), writer_info, descriptor, _subtitles.size() * 90 + 16384);
if (ASDCP_FAILURE (r)) {
boost::throw_exception (FileError ("could not open subtitle MXF for writing", p.string(), r));
}
diff --git a/src/sound_asset.cc b/src/sound_asset.cc
index c31f8bf4..0ceba53d 100644
--- a/src/sound_asset.cc
+++ b/src/sound_asset.cc
@@ -41,6 +41,7 @@
#include "dcp_assert.h"
#include "equality_options.h"
#include "exceptions.h"
+#include "filesystem.h"
#include "sound_asset.h"
#include "sound_asset_reader.h"
#include "sound_asset_writer.h"
@@ -70,7 +71,7 @@ SoundAsset::SoundAsset (boost::filesystem::path file)
: Asset (file)
{
ASDCP::PCM::MXFReader reader;
- auto r = reader.OpenRead (file.string().c_str());
+ auto r = reader.OpenRead(dcp::filesystem::fix_long_path(file).string().c_str());
if (ASDCP_FAILURE(r)) {
boost::throw_exception (MXFFileError("could not open MXF file for reading", file.string(), r));
}
@@ -139,13 +140,13 @@ SoundAsset::equals(shared_ptr<const Asset> other, EqualityOptions const& opt, No
ASDCP::PCM::MXFReader reader_A;
DCP_ASSERT (file());
- auto r = reader_A.OpenRead (file()->string().c_str());
+ auto r = reader_A.OpenRead(dcp::filesystem::fix_long_path(*file()).string().c_str());
if (ASDCP_FAILURE(r)) {
boost::throw_exception (MXFFileError("could not open MXF file for reading", file()->string(), r));
}
ASDCP::PCM::MXFReader reader_B;
- r = reader_B.OpenRead (other->file()->string().c_str());
+ r = reader_B.OpenRead(dcp::filesystem::fix_long_path(*other->file()).string().c_str());
if (ASDCP_FAILURE (r)) {
boost::throw_exception (MXFFileError("could not open MXF file for reading", other->file()->string(), r));
}
@@ -278,7 +279,7 @@ bool
SoundAsset::valid_mxf (boost::filesystem::path file)
{
ASDCP::PCM::MXFReader reader;
- Kumu::Result_t r = reader.OpenRead (file.string().c_str());
+ Kumu::Result_t r = reader.OpenRead(dcp::filesystem::fix_long_path(file).string().c_str());
return !ASDCP_FAILURE (r);
}
diff --git a/src/sound_asset_writer.cc b/src/sound_asset_writer.cc
index 1185616a..a7be0859 100644
--- a/src/sound_asset_writer.cc
+++ b/src/sound_asset_writer.cc
@@ -42,6 +42,7 @@
#include "crypto_context.h"
#include "dcp_assert.h"
#include "exceptions.h"
+#include "filesystem.h"
#include "sound_asset.h"
#include "sound_asset_writer.h"
#include "warnings.h"
@@ -146,7 +147,7 @@ SoundAssetWriter::~SoundAssetWriter()
void
SoundAssetWriter::start ()
{
- auto r = _state->mxf_writer.OpenWrite (_file.string().c_str(), _state->writer_info, _state->desc);
+ auto r = _state->mxf_writer.OpenWrite(dcp::filesystem::fix_long_path(_file).string().c_str(), _state->writer_info, _state->desc);
if (ASDCP_FAILURE(r)) {
boost::throw_exception (FileError("could not open audio MXF for writing", _file.string(), r));
}
diff --git a/src/stereo_picture_asset.cc b/src/stereo_picture_asset.cc
index 3fec58ff..2ce3cdc9 100644
--- a/src/stereo_picture_asset.cc
+++ b/src/stereo_picture_asset.cc
@@ -40,6 +40,7 @@
#include "dcp_assert.h"
#include "equality_options.h"
#include "exceptions.h"
+#include "filesystem.h"
#include "stereo_picture_asset.h"
#include "stereo_picture_asset_reader.h"
#include "stereo_picture_asset_writer.h"
@@ -59,7 +60,7 @@ StereoPictureAsset::StereoPictureAsset (boost::filesystem::path file)
: PictureAsset (file)
{
ASDCP::JP2K::MXFSReader reader;
- auto r = reader.OpenRead (file.string().c_str());
+ auto r = reader.OpenRead(dcp::filesystem::fix_long_path(file).string().c_str());
if (ASDCP_FAILURE(r)) {
boost::throw_exception (MXFFileError("could not open MXF file for reading", file.string(), r));
}
@@ -106,14 +107,14 @@ StereoPictureAsset::equals(shared_ptr<const Asset> other, EqualityOptions const&
{
ASDCP::JP2K::MXFSReader reader_A;
DCP_ASSERT (file());
- auto r = reader_A.OpenRead (file()->string().c_str());
+ auto r = reader_A.OpenRead(dcp::filesystem::fix_long_path(*file()).string().c_str());
if (ASDCP_FAILURE (r)) {
boost::throw_exception (MXFFileError ("could not open MXF file for reading", file()->string(), r));
}
ASDCP::JP2K::MXFSReader reader_B;
DCP_ASSERT (other->file());
- r = reader_B.OpenRead (other->file()->string().c_str());
+ r = reader_B.OpenRead(dcp::filesystem::fix_long_path(*other->file()).string().c_str());
if (ASDCP_FAILURE (r)) {
boost::throw_exception (MXFFileError ("could not open MXF file for reading", other->file()->string(), r));
}
diff --git a/src/subtitle_image.cc b/src/subtitle_image.cc
index 1ef2e697..9340bc54 100644
--- a/src/subtitle_image.cc
+++ b/src/subtitle_image.cc
@@ -38,6 +38,7 @@
#include "equality_options.h"
+#include "filesystem.h"
#include "subtitle_image.h"
#include "util.h"
@@ -149,12 +150,12 @@ SubtitleImage::equals(shared_ptr<const Subtitle> other_sub, EqualityOptions cons
note (NoteType::ERROR, "subtitle image PNG data differs");
if (options.export_differing_subtitles) {
string const base = "dcpdiff_subtitle_";
- if (boost::filesystem::exists(base + "A.png")) {
+ if (filesystem::exists(base + "A.png")) {
note (NoteType::ERROR, "could not export subtitle as " + base + "A.png already exists");
} else {
png_image().write(base + "A.png");
}
- if (boost::filesystem::exists(base + "B.png")) {
+ if (filesystem::exists(base + "B.png")) {
note (NoteType::ERROR, "could not export subtitle as " + base + "B.png already exists");
} else {
other->png_image().write(base + "B.png");
diff --git a/src/util.cc b/src/util.cc
index bbfcd30e..1ff36f59 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -42,6 +42,7 @@
#include "dcp_assert.h"
#include "exceptions.h"
#include "file.h"
+#include "filesystem.h"
#include "language_tag.h"
#include "openjpeg_image.h"
#include "rating.h"
@@ -119,7 +120,7 @@ string
dcp::make_digest (boost::filesystem::path filename, function<void (float)> progress)
{
Kumu::FileReader reader;
- auto r = reader.OpenRead (filename.string().c_str ());
+ auto r = reader.OpenRead(dcp::filesystem::fix_long_path(filename).string().c_str());
if (ASDCP_FAILURE(r)) {
boost::throw_exception (FileError("could not open file to compute digest", filename, r));
}
@@ -254,7 +255,7 @@ dcp::ids_equal (string a, string b)
string
dcp::file_to_string (boost::filesystem::path p, uintmax_t max_length)
{
- auto len = boost::filesystem::file_size (p);
+ auto len = filesystem::file_size(p);
if (len > max_length) {
throw MiscError (String::compose("Unexpectedly long file (%1)", p.string()));
}
@@ -421,7 +422,7 @@ ASDCPErrorSuspender::~ASDCPErrorSuspender ()
boost::filesystem::path dcp::directory_containing_executable ()
{
#if BOOST_VERSION >= 106100
- return boost::filesystem::canonical(boost::dll::program_location().parent_path());
+ return filesystem::canonical(boost::dll::program_location().parent_path());
#else
char buffer[PATH_MAX];
ssize_t N = readlink ("/proc/self/exe", buffer, PATH_MAX);
diff --git a/src/verify.cc b/src/verify.cc
index 620ee31d..dba5dfb1 100644
--- a/src/verify.cc
+++ b/src/verify.cc
@@ -41,6 +41,7 @@
#include "cpl.h"
#include "dcp.h"
#include "exceptions.h"
+#include "filesystem.h"
#include "interop_subtitle_asset.h"
#include "mono_picture_asset.h"
#include "mono_picture_frame.h"
@@ -504,7 +505,7 @@ verify_main_picture_asset (
auto asset = reel_asset->asset();
auto const file = *asset->file();
- if (options.check_asset_hashes && (!options.maximum_asset_size_for_hash_check || boost::filesystem::file_size(file) < *options.maximum_asset_size_for_hash_check)) {
+ if (options.check_asset_hashes && (!options.maximum_asset_size_for_hash_check || filesystem::file_size(file) < *options.maximum_asset_size_for_hash_check)) {
stage ("Checking picture asset hash", file);
auto const r = verify_asset (dcp, reel_asset, progress);
switch (r) {
@@ -600,7 +601,7 @@ verify_main_sound_asset (
auto asset = reel_asset->asset();
auto const file = *asset->file();
- if (options.check_asset_hashes && (!options.maximum_asset_size_for_hash_check || boost::filesystem::file_size(file) < *options.maximum_asset_size_for_hash_check)) {
+ if (options.check_asset_hashes && (!options.maximum_asset_size_for_hash_check || filesystem::file_size(file) < *options.maximum_asset_size_for_hash_check)) {
stage("Checking sound asset hash", file);
auto const r = verify_asset (dcp, reel_asset, progress);
switch (r) {
@@ -678,7 +679,7 @@ verify_smpte_timed_text_asset (
notes.push_back ({ VerificationNote::Type::BV21_ERROR, VerificationNote::Code::MISSING_SUBTITLE_LANGUAGE, *asset->file() });
}
- auto const size = boost::filesystem::file_size(asset->file().get());
+ auto const size = filesystem::file_size(asset->file().get());
if (size > 115 * 1024 * 1024) {
notes.push_back (
{ VerificationNote::Type::BV21_ERROR, VerificationNote::Code::INVALID_TIMED_TEXT_SIZE_IN_BYTES, raw_convert<string>(size), *asset->file() }
@@ -1297,7 +1298,7 @@ verify_extension_metadata(shared_ptr<const CPL> cpl, vector<VerificationNote>& n
{
DCP_ASSERT (cpl->file());
cxml::Document doc ("CompositionPlaylist");
- doc.read_file (cpl->file().get());
+ doc.read_file(dcp::filesystem::fix_long_path(cpl->file().get()));
auto missing = false;
string malformed;
@@ -1739,7 +1740,7 @@ verify_cpl(
if (cpl->any_encrypted()) {
cxml::Document doc("CompositionPlaylist");
DCP_ASSERT(cpl->file());
- doc.read_file(cpl->file().get());
+ doc.read_file(dcp::filesystem::fix_long_path(cpl->file().get()));
if (!doc.optional_node_child("Signature")) {
notes.push_back({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::UNSIGNED_CPL_WITH_ENCRYPTED_CONTENT, cpl->id(), cpl->file().get()});
}
@@ -1761,7 +1762,7 @@ verify_pkl(
if (pkl_has_encrypted_assets(dcp, pkl)) {
cxml::Document doc("PackingList");
- doc.read_file(pkl->file().get());
+ doc.read_file(dcp::filesystem::fix_long_path(pkl->file().get()));
if (!doc.optional_node_child("Signature")) {
notes.push_back({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::UNSIGNED_PKL_WITH_ENCRYPTED_CONTENT, pkl->id(), pkl->file().get()});
}
@@ -1813,7 +1814,7 @@ dcp::verify (
if (!xsd_dtd_directory) {
xsd_dtd_directory = resources_directory() / "xsd";
}
- *xsd_dtd_directory = boost::filesystem::canonical (*xsd_dtd_directory);
+ *xsd_dtd_directory = filesystem::canonical(*xsd_dtd_directory);
vector<VerificationNote> notes;
State state{};
diff --git a/src/wscript b/src/wscript
index a408d7cd..e6bee6f2 100644
--- a/src/wscript
+++ b/src/wscript
@@ -57,6 +57,7 @@ def build(bld):
encrypted_kdm.cc
exceptions.cc
file.cc
+ filesystem.cc
font_asset.cc
fsk.cc
gamma_transfer_function.cc
@@ -156,6 +157,7 @@ def build(bld):
equality_options.h
exceptions.h
file.h
+ filesystem.h
font_asset.h
frame.h
fsk.h