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.
#include "array_data.h"
#include "file.h"
+#include "filesystem.h"
#include "exceptions.h"
#include "util.h"
#include <cerrno>
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");
#include "dcp_assert.h"
#include "equality_options.h"
#include "exceptions.h"
+#include "filesystem.h"
#include "pkl.h"
#include "raw_convert.h"
#include "util.h"
using boost::function;
using std::shared_ptr;
using boost::optional;
-using namespace boost::filesystem;
using namespace dcp;
}
-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)
{
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) {
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);
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) {
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);
}
*/
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());
}
#include "asset_map.h"
#include "dcp_assert.h"
#include "exceptions.h"
+#include "filesystem.h"
#include "raw_convert.h"
#include "warnings.h"
LIBDCP_DISABLE_WARNINGS
{
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) {
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;
}
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)));
}
#include "asset.h"
#include "crypto_context.h"
#include "dcp_assert.h"
+#include "filesystem.h"
#include <asdcp/AS_DCP.h>
#include <memory>
{
_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));
, 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));
}
#include "crypto_context.h"
#include "dcp_assert.h"
#include "exceptions.h"
+#include "filesystem.h"
#include <asdcp/AS_DCP.h>
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));
}
#include "compose.hpp"
#include "dcp_assert.h"
#include "exceptions.h"
+#include "filesystem.h"
#include "util.h"
#include "warnings.h"
#include <asdcp/KM_util.h>
#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>
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()));
}
}
)
{
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() + "\"";
)
);
- 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")));
_key = dcp::file_to_string (directory / "leaf.key");
- boost::filesystem::remove_all (directory);
+ filesystem::remove_all(directory);
}
#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"
#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;
}
}
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;
}
shared_ptr<const CertificateChain> signer
)
{
- using namespace boost::filesystem;
-
DCP_ASSERT (!inputs.empty());
DCP output_dcp (output);
}
}
- vector<path> paths;
+ vector<boost::filesystem::path> paths;
vector<shared_ptr<dcp::Asset>> assets;
for (auto i: inputs) {
}
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());
}
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);
}
#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"
, _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;
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);
}
#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"
#include <libxml++/libxml++.h>
LIBDCP_ENABLE_WARNINGS
#include <boost/algorithm/string.hpp>
-#include <boost/filesystem.hpp>
#include <numeric>
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);
}
/* 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));
continue;
}
- if (!boost::filesystem::exists(path)) {
+ if (!filesystem::exists(path)) {
if (notes) {
notes->push_back ({VerificationNote::Type::ERROR, VerificationNote::Code::MISSING_ASSET, path});
}
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());
}
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");
}
#include "dcp_assert.h"
#include "file.h"
-#include <boost/algorithm/string.hpp>
+#include "filesystem.h"
#ifdef LIBDCP_WINDOWS
#include <errhandlingapi.h>
#endif
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();
}
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
-}
};
-boost::filesystem::path fix_long_path(boost::filesystem::path long_path);
-
-
}
--- /dev/null
+/*
+ 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;
+}
--- /dev/null
+/*
+ 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
#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"
_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");
#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"
: 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));
}
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));
}
#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"
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) {
*/
+#include "filesystem.h"
+
+
using std::shared_ptr;
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,
#include "dcp_assert.h"
#include "exceptions.h"
+#include "filesystem.h"
#include "pkl.h"
#include "raw_convert.h"
#include "util.h"
: _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;
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;
}
#include "dcp.h"
#include "decrypted_kdm.h"
#include "exceptions.h"
+#include "filesystem.h"
#include "search.h"
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).
*/
#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"
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 */
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 (
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);
}
}
/* 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 (
{
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);
}
/* 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));
}
#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"
: 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));
}
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));
}
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);
}
#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"
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));
}
#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"
: 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));
}
{
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));
}
#include "equality_options.h"
+#include "filesystem.h"
#include "subtitle_image.h"
#include "util.h"
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");
#include "dcp_assert.h"
#include "exceptions.h"
#include "file.h"
+#include "filesystem.h"
#include "language_tag.h"
#include "openjpeg_image.h"
#include "rating.h"
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));
}
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()));
}
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);
#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"
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) {
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) {
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() }
{
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;
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()});
}
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()});
}
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{};
encrypted_kdm.cc
exceptions.cc
file.cc
+ filesystem.cc
font_asset.cc
fsk.cc
gamma_transfer_function.cc
equality_options.h
exceptions.h
file.h
+ filesystem.h
font_asset.h
frame.h
fsk.h
#include "dcp.h"
#include "certificate_chain.h"
#include "cpl.h"
+#include "filesystem.h"
#include "mono_picture_asset.h"
#include "picture_asset_writer.h"
#include "sound_asset_writer.h"
kdm.encrypt (signer, signer->leaf(), vector<string>(), dcp::Formulation::MODIFIED_TRANSITIONAL_1, true, 0).as_xml("build/test/encryption_test.kdm.xml");
+ /* Make sure we aren't in a UNC current working directory otherwise the use of cmd.exe
+ * in system() below will fail.
+ */
+ boost::filesystem::current_path(dcp::filesystem::unfix_long_path(boost::filesystem::current_path()));
+
int r = system (
"xmllint --path schema --nonet --noout --schema schema/SMPTE-430-1-2006-Amd-1-2009-KDM.xsd build/test/encryption_test.kdm.xml "
#ifndef LIBDCP_WINDOWS
+++ /dev/null
-/*
- Copyright (C) 2022 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 "file.h"
-#include <boost/filesystem.hpp>
-#include <boost/test/unit_test.hpp>
-
-
-BOOST_AUTO_TEST_CASE (fix_long_path_test)
-{
-#ifdef LIBDCP_WINDOWS
- BOOST_CHECK_EQUAL (dcp::fix_long_path("c:\\foo"), "\\\\?\\c:\\foo");
- BOOST_CHECK_EQUAL (dcp::fix_long_path("c:\\foo\\bar"), "\\\\?\\c:\\foo\\bar");
- boost::filesystem::path fixed_bar = "\\\\?\\";
- fixed_bar += boost::filesystem::current_path();
- fixed_bar /= "bar";
- BOOST_CHECK_EQUAL (dcp::fix_long_path("bar"), fixed_bar);
-
- BOOST_CHECK_EQUAL (dcp::fix_long_path("\\\\?\\c:\\foo"), "\\\\?\\c:\\foo");
-#else
- BOOST_CHECK_EQUAL (dcp::fix_long_path("foo/bar/baz"), "foo/bar/baz");
-#endif
-}
-
-
-#ifdef LIBDCP_WINDOWS
-BOOST_AUTO_TEST_CASE (windows_long_filename_test)
-{
- using namespace boost::filesystem;
-
- path too_long = current_path() / "build\\test\\a\\really\\very\\long\\filesystem\\path\\indeed\\that\\will\\be\\so\\long\\that\\windows\\cannot\\normally\\cope\\with\\it\\unless\\we\\add\\this\\crazy\\prefix\\and\\then\\magically\\it\\can\\do\\it\\fine\\I\\dont\\really\\know\\why\\its\\like\\that\\but\\hey\\it\\is\\so\\here\\we\\are\\what\\can\\we\\do\\other\\than\\bodge\\it";
-
- BOOST_CHECK (too_long.string().length() > 260);
- boost::system::error_code ec;
- create_directories (too_long, ec);
- BOOST_CHECK (ec);
-
- path fixed_path = dcp::fix_long_path(too_long);
- create_directories (fixed_path, ec);
- BOOST_CHECK (!ec);
-
- {
- dcp::File file(too_long / "hello", "w");
- BOOST_REQUIRE (file);
- fprintf (file.get(), "Hello_world");
- }
-
- {
- dcp::File file(too_long / "hello", "r");
- BOOST_REQUIRE (file);
- char buffer[64];
- fscanf (file.get(), "%63s", buffer);
- BOOST_CHECK_EQUAL (strcmp(buffer, "Hello_world"), 0);
- }
-}
-#endif
-
--- /dev/null
+/*
+ Copyright (C) 2022 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 "file.h"
+#include "filesystem.h"
+#include <boost/filesystem.hpp>
+#include <boost/test/unit_test.hpp>
+
+
+BOOST_AUTO_TEST_CASE (fix_long_path_test)
+{
+#ifdef LIBDCP_WINDOWS
+ BOOST_CHECK_EQUAL(dcp::filesystem::fix_long_path("c:\\foo"), "\\\\?\\c:\\foo");
+ BOOST_CHECK_EQUAL(dcp::filesystem::fix_long_path("c:\\foo\\bar"), "\\\\?\\c:\\foo\\bar");
+ BOOST_CHECK_EQUAL(dcp::filesystem::fix_long_path("\\\\?\\c:\\foo"), "\\\\?\\c:\\foo");
+#else
+ BOOST_CHECK_EQUAL(dcp::filesystem::fix_long_path("foo/bar/baz"), "foo/bar/baz");
+#endif
+}
+
+
+BOOST_AUTO_TEST_CASE(unfix_long_path_test)
+{
+#ifdef LIBDCP_WINDOWS
+ BOOST_CHECK_EQUAL(dcp::filesystem::unfix_long_path("c:\\foo"), "c:\\foo");
+ BOOST_CHECK_EQUAL(dcp::filesystem::unfix_long_path("\\\\?\\c:\\foo"), "c:\\foo");
+#else
+ BOOST_CHECK_EQUAL(dcp::filesystem::unfix_long_path("c:\\foo"), "c:\\foo");
+ BOOST_CHECK_EQUAL(dcp::filesystem::unfix_long_path("\\\\?\\c:\\foo"), "\\\\?\\c:\\foo");
+#endif
+}
+
+
+#ifdef LIBDCP_WINDOWS
+BOOST_AUTO_TEST_CASE (windows_long_filename_test)
+{
+ using namespace boost::filesystem;
+
+ /* Make sure current_path() is not already fixed by using our dcp::filesystem version */
+ path too_long = dcp::filesystem::current_path() / "build\\test\\a\\really\\very\\long\\filesystem\\path\\indeed\\that\\will\\be\\so\\long\\that\\windows\\cannot\\normally\\cope\\with\\it\\unless\\we\\add\\this\\crazy\\prefix\\and\\then\\magically\\it\\can\\do\\it\\fine\\I\\dont\\really\\know\\why\\its\\like\\that\\but\\hey\\it\\is\\so\\here\\we\\are\\what\\can\\we\\do\\other\\than\\bodge\\it";
+
+ BOOST_CHECK (too_long.string().length() > 260);
+ boost::system::error_code ec;
+ create_directories (too_long, ec);
+ BOOST_CHECK (ec);
+
+ path fixed_path = dcp::filesystem::fix_long_path(too_long);
+ create_directories (fixed_path, ec);
+ BOOST_CHECK (!ec);
+
+ {
+ dcp::File file(too_long / "hello", "w");
+ BOOST_REQUIRE (file);
+ fprintf (file.get(), "Hello_world");
+ }
+
+ {
+ dcp::File file(too_long / "hello", "r");
+ BOOST_REQUIRE (file);
+ char buffer[64];
+ fscanf (file.get(), "%63s", buffer);
+ BOOST_CHECK_EQUAL (strcmp(buffer, "Hello_world"), 0);
+ }
+}
+#endif
+
--- /dev/null
+/*
+ Copyright (C) 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.
+*/
+
+
+#include "dcp.h"
+#include "filesystem.h"
+#include <boost/filesystem.hpp>
+#include <boost/test/unit_test.hpp>
+
+
+BOOST_AUTO_TEST_CASE(load_dcp_with_long_filename)
+{
+ boost::filesystem::path long_name = "build/test";
+ for (int i = 0; i < 27; ++i) {
+ long_name /= "letsmakeitlong";
+ }
+
+ dcp::filesystem::remove_all(long_name);
+ dcp::filesystem::create_directories(long_name);
+ for (auto file: dcp::filesystem::directory_iterator("test/ref/DCP/dcp_test1")) {
+ dcp::filesystem::copy(file.path(), long_name / file.path().filename());
+ }
+
+ dcp::DCP dcp(long_name);
+ BOOST_CHECK_NO_THROW(dcp.read());
+}
+
+
+
effect_test.cc
encryption_test.cc
exception_test.cc
- file_test.cc
+ filesystem_test.cc
fraction_test.cc
frame_info_hash_test.cc
gamma_transfer_function_test.cc
interop_load_font_test.cc
interop_subtitle_test.cc
local_time_test.cc
+ long_filenames_test.cc
make_digest_test.cc
markers_test.cc
mca_test.cc
*/
+#include "common.h"
#include "dcp.h"
#include "equality_options.h"
#include "exceptions.h"
-#include "common.h"
+#include "filesystem.h"
#include "mxf.h"
#include <getopt.h>
#include <boost/optional.hpp>
exit (EXIT_FAILURE);
}
- if (!boost::filesystem::exists (argv[optind])) {
+ if (!filesystem::exists(argv[optind])) {
cerr << argv[0] << ": DCP " << argv[optind] << " not found.\n";
exit (EXIT_FAILURE);
}
- if (!boost::filesystem::exists (argv[optind + 1])) {
+ if (!filesystem::exists(argv[optind + 1])) {
cerr << argv[0] << ": DCP " << argv[optind + 1] << " not found.\n";
exit (EXIT_FAILURE);
}
#include "decrypted_kdm.h"
#include "encrypted_kdm.h"
#include "exceptions.h"
+#include "filesystem.h"
#include "interop_subtitle_asset.h"
#include "mono_picture_asset.h"
#include "picture_asset.h"
exit (EXIT_FAILURE);
}
- if (!boost::filesystem::exists (argv[optind])) {
+ if (!filesystem::exists(argv[optind])) {
cerr << argv[0] << ": DCP or CPL " << argv[optind] << " not found.\n";
exit (EXIT_FAILURE);
}
#include "cpl.h"
#include "dcp.h"
#include "exceptions.h"
+#include "filesystem.h"
#include "reel_asset.h"
#include "warnings.h"
#include <getopt.h>
/* Look for a CPL */
shared_ptr<dcp::CPL> cpl;
- for (auto i: boost::filesystem::directory_iterator(dcp_dir)) {
+ for (auto i: dcp::filesystem::directory_iterator(dcp_dir)) {
if (i.path().extension() == ".xml") {
try {
cpl = make_shared<dcp::CPL>(i.path());
/* Read all MXF assets */
vector<shared_ptr<dcp::Asset>> assets;
- for (auto i: boost::filesystem::directory_iterator(dcp_dir)) {
+ for (auto i: dcp::filesystem::directory_iterator(dcp_dir)) {
if (i.path().extension() == ".mxf") {
try {
auto asset = dcp::asset_factory(i.path(), true);
#include "common.h"
#include "compose.hpp"
+#include "filesystem.h"
#include "raw_convert.h"
#include "verify.h"
#include "version.h"
exit (EXIT_FAILURE);
}
- if (!boost::filesystem::exists (argv[optind])) {
+ if (!dcp::filesystem::exists(argv[optind])) {
cerr << argv[0] << ": DCP " << argv[optind] << " not found.\n";
exit (EXIT_FAILURE);
}