Add wrappers around boost::filesystem methods that handle the
authorCarl Hetherington <cth@carlh.net>
Fri, 6 Oct 2023 00:04:49 +0000 (02:04 +0200)
committerCarl Hetherington <cth@carlh.net>
Sun, 8 Oct 2023 23:20:01 +0000 (01:20 +0200)
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.

38 files changed:
src/array_data.cc
src/asset.cc
src/asset_factory.cc
src/asset_map.cc
src/asset_reader.h
src/atmos_asset.cc
src/atmos_asset_writer.cc
src/certificate_chain.cc
src/combine.cc
src/cpl.cc
src/dcp.cc
src/file.cc
src/file.h
src/filesystem.cc [new file with mode: 0644]
src/filesystem.h [new file with mode: 0644]
src/interop_subtitle_asset.cc
src/mono_picture_asset.cc
src/mono_picture_frame.cc
src/picture_asset_writer_common.cc
src/pkl.cc
src/search.cc
src/smpte_subtitle_asset.cc
src/sound_asset.cc
src/sound_asset_writer.cc
src/stereo_picture_asset.cc
src/subtitle_image.cc
src/util.cc
src/verify.cc
src/wscript
test/encryption_test.cc
test/file_test.cc [deleted file]
test/filesystem_test.cc [new file with mode: 0644]
test/long_filenames_test.cc [new file with mode: 0644]
test/wscript
tools/dcpdiff.cc
tools/dcpinfo.cc
tools/dcprecover.cc
tools/dcpverify.cc

index 52a22cf67b706e04bbb5ffc3a11dd8df288e91f7..e388454af248d1d61b1811facee68484bf3f708b 100644 (file)
@@ -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");
index 213d4878410e2553f7b48963da1ea185432d9f06..15f810154c1c9939e6969c0e3c3d3e0c44356070 100644 (file)
@@ -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);
 }
 
 
index 2ab798997799eda72a5afc90c87ebab906e1f4a6..1f830cceecf4d3e248ba84c0a23895863f107620 100644 (file)
@@ -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());
        }
index c1bafd92788006fa8d321625eeef1d9dc1663559..281f27c3a520006040809837fa5dd238b6ea7143 100644 (file)
@@ -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)));
 }
 
index 8478b51fd94c4c45c531c36cca1e07f0f2c912fc..c8953e09281956020935a0751e7b266b643c7e74 100644 (file)
@@ -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));
index ae38173725331c63aeedd1a11607eaa0236dbacd..42a0774e2656d34adec8faedc17be3661d885b04 100644 (file)
@@ -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));
        }
index 9d7363d04eaaafafd2534e060e7de22730b391aa..0c895b5bbcb31bf651ffd5d61b0b1f680d0a4187 100644 (file)
@@ -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));
                }
index 449dba89e7a07a0bfda61c4db9a66e1952122f48..6748d73c7fe5d0173ee110aff9059ac75a28d2bf 100644 (file)
@@ -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);
 }
 
 
index b728298ad2f3ba2c9f45cb587a6b2fc8f84b83bc..b7a625f089df8e236722da76e7cad5f8f37d3a3d 100644 (file)
@@ -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"
 #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);
                }
index bbdaee18f77cd03aa443c35236b37c91d5863090..5467fef3b1db0b38ebf859e5d4adf623e7342dd7 100644 (file)
@@ -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);
 }
index 7c253a17c82c69567dd76b6627d3298f263b6bd5..d603cfae48694ae71d89ae9f0b57a673efd0381a 100644 (file)
@@ -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");
 }
 
 
index b5d2eed462b12794dd91dc5db59486007c99961d..36102f72081d979b7a61bac5ca4609805beb87d8 100644 (file)
@@ -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
-}
index 22083a9efded891e8de479ec8ee094c3adf8fb62..c530c26c64e9f4399c5fc2a0ad914044ec52c7d3 100644 (file)
@@ -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 (file)
index 0000000..0dd8922
--- /dev/null
@@ -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 (file)
index 0000000..d9fb279
--- /dev/null
@@ -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
index d26143a4435d658405591115a77739910f0346cf..32c3f66a4268649985fb0c031313b54c5b9123cc 100644 (file)
@@ -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");
index 55d3f6badbc811238680d9282cad6a456f5dcc77..cc24e198a860512aa9228ce4bcfe492416581c9f 100644 (file)
@@ -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));
        }
index ddaed9839cfb78c816ed7f4c3b8d92108528ca0c..2abd57e453248d68bb916ea513163fa3f559e85e 100644 (file)
@@ -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) {
index e719be72354d9b7c771d39352679896c40bed015..82866aac518207586c643fdee4492e0ce9e10f34 100644 (file)
@@ -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,
index 390d5df269ddf952f1f52a6d066bd6820fe82537..57eda9dad025dd285ed725f2b8614b570417845e 100644 (file)
@@ -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;
 }
 
index f45a2fb9c5020a2a923dfcb7c9aa53179505a216..e7871dc669e1754f849d1d3403dfeb5972598c28 100644 (file)
@@ -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).
                         */
index b9d7e9a341d25fbf8fe396edaeb2d391e8e4feeb..ea1d74269da2184c456d1c01f6b5b6c6423f6566 100644 (file)
@@ -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));
        }
index c31f8bf44cd173e7791bbbae676082cab8921e92..0ceba53dd091766ee85c3dec4ba281befa2e41a4 100644 (file)
@@ -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);
 }
 
index 1185616a30927be43af82d63e19dcaa108ef7ac2..a7be0859251c4fb74d7be4562cd985aad4a484a2 100644 (file)
@@ -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));
        }
index 3fec58ffaf8971e02ce5c7df5ce7bd0b5bd06acd..2ce3cdc90f386ed172e7bc23315c6a6ed8ed8910 100644 (file)
@@ -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));
        }
index 1ef2e6970e46fb4c7a9def254520933507e46d1f..9340bc54ad8075ef6b2efd3cf750bf0cd99b9d56 100644 (file)
@@ -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");
index bbfcd30ebbfb9606d8f238b3545dcf89bbddd7a7..1ff36f598f0f9afc44946b1d165cc65217b9c6f2 100644 (file)
@@ -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);
index 620ee31d872718be1be86295766a3045d70eb413..dba5dfb13b76cd35a0a3e35ea225067631fb17fb 100644 (file)
@@ -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{};
index a408d7cd683e969922d4de67b9f59425e5e7fc60..e6bee6f2d2a344869decb452efc91c9843e4275d 100644 (file)
@@ -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
index f2a4084322d64ba77f48e7c47dd19db3cc3b3817..358a3fd96fc7a67c855b5c49a8114de931b906f5 100644 (file)
@@ -36,6 +36,7 @@
 #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"
@@ -155,6 +156,11 @@ BOOST_AUTO_TEST_CASE (encryption_test)
 
        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
diff --git a/test/file_test.cc b/test/file_test.cc
deleted file mode 100644 (file)
index 8c6ded2..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
-    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
-
diff --git a/test/filesystem_test.cc b/test/filesystem_test.cc
new file mode 100644 (file)
index 0000000..fc13db9
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+    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
+
diff --git a/test/long_filenames_test.cc b/test/long_filenames_test.cc
new file mode 100644 (file)
index 0000000..f818988
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+    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());
+}
+
+
+
index bc78632242e0905178f21c4ad7210b2a6bca3e47..4d9278eb9e8cdfdd54a458ba9af69028fdda78fd 100644 (file)
@@ -82,7 +82,7 @@ def build(bld):
                  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
@@ -90,6 +90,7 @@ def build(bld):
                  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
index 3dace12adb1a00dcae366822ac6a1fdc30703fd5..7c7c4b71da2ef8d3c70e2c4bf3342cbd612234f1 100644 (file)
 */
 
 
+#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>
@@ -207,12 +208,12 @@ main (int argc, char* argv[])
                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);
        }
index 6a37be1c1f4941347e1d218a22f9774658e55007..e812afe40775161afc2c1370a951bb4b56ea2b92 100644 (file)
@@ -39,6 +39,7 @@
 #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"
@@ -352,7 +353,7 @@ main (int argc, char* argv[])
                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);
        }
index 840a671142caa58b5caed29ca3d345e8e4ca1782..b78846ff7712e18dd50e7bafd72722686dc082cc 100644 (file)
@@ -36,6 +36,7 @@
 #include "cpl.h"
 #include "dcp.h"
 #include "exceptions.h"
+#include "filesystem.h"
 #include "reel_asset.h"
 #include "warnings.h"
 #include <getopt.h>
@@ -124,7 +125,7 @@ main (int argc, char* argv[])
        /* 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());
@@ -146,7 +147,7 @@ main (int argc, char* argv[])
 
                /* 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);
index 770dd78fa75c93bf9f37df5e2329f15dbf17ca56..875a92b7321401b1cb79295af001da6ea8e6275c 100644 (file)
@@ -34,6 +34,7 @@
 
 #include "common.h"
 #include "compose.hpp"
+#include "filesystem.h"
 #include "raw_convert.h"
 #include "verify.h"
 #include "version.h"
@@ -133,7 +134,7 @@ main (int argc, char* argv[])
                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);
        }