Use dcp::File in DCP-o-matic (#2231).
authorCarl Hetherington <cth@carlh.net>
Sat, 16 Apr 2022 20:20:54 +0000 (22:20 +0200)
committerCarl Hetherington <cth@carlh.net>
Thu, 5 May 2022 21:38:41 +0000 (23:38 +0200)
34 files changed:
cscript
src/lib/config.cc
src/lib/cross.h
src/lib/cross_linux.cc
src/lib/cross_osx.cc
src/lib/cross_windows.cc
src/lib/curl_uploader.cc
src/lib/curl_uploader.h
src/lib/ext.cc
src/lib/file_group.cc
src/lib/file_group.h
src/lib/file_log.cc
src/lib/film.cc
src/lib/film.h
src/lib/image_examiner.cc
src/lib/internet.cc
src/lib/kdm_with_metadata.cc
src/lib/reel_writer.cc
src/lib/reel_writer.h
src/lib/scoped_temporary.cc
src/lib/scoped_temporary.h
src/lib/scp_uploader.cc
src/lib/string_text_file.cc
src/lib/util.cc
src/lib/util.h
src/lib/writer.cc
src/tools/dcpomatic_cli.cc
src/wx/config_dialog.cc
test/audio_merger_test.cc
test/cpl_hash_test.cc
test/hints_test.cc
test/test.cc
test/windows_test.cc [deleted file]
test/wscript

diff --git a/cscript b/cscript
index b65a430e5394ad4a9d849cbd513085ce1b755ec2..66e77e7db307b4bdc91e9bdd5ea7edab46601664 100644 (file)
--- a/cscript
+++ b/cscript
@@ -427,8 +427,8 @@ def dependencies(target, options):
         # Use distro-provided FFmpeg on Arch
         deps = []
 
-    deps.append(('libdcp', 'd0d456fcae355a07ac27102ae9da2680bece6454'))
-    deps.append(('libsub', 'a23d106d15259440ba66c15f1dca4b6ba30c075e'))
+    deps.append(('libdcp', 'f031667bd2769d3daf9c49115f21a099fafcee46'))
+    deps.append(('libsub', '210ac21fdb9d8eb37f5ecde70cd1d0e6c8719390'))
     deps.append(('leqm-nrt', '93ae9e6'))
     deps.append(('rtaudio', 'f619b76'))
     # We get our OpenSSL libraries from the environment, but we
index b46093726bed345c25b649209b2af8f580796e47..3661d8ba58268b85d0d606ea6e1b8123b19e449b 100644 (file)
@@ -1031,12 +1031,12 @@ Config::write_config () const
        try {
                auto const s = doc.write_to_string_formatted ();
                boost::filesystem::path tmp (string(target.string()).append(".tmp"));
-               auto f = fopen_boost (tmp, "w");
+               dcp::File f(tmp, "w");
                if (!f) {
                        throw FileError (_("Could not open file for writing"), tmp);
                }
-               checked_fwrite (s.c_str(), s.bytes(), f, tmp);
-               fclose (f);
+               f.checked_write(s.c_str(), s.bytes());
+               f.close();
                boost::filesystem::remove (target);
                boost::filesystem::rename (tmp, target);
        } catch (xmlpp::exception& e) {
@@ -1416,13 +1416,8 @@ Config::copy_and_link (boost::filesystem::path new_file) const
 bool
 Config::have_write_permission () const
 {
-       auto f = fopen_boost (config_write_file(), "r+");
-       if (!f) {
-               return false;
-       }
-
-       fclose (f);
-       return true;
+       dcp::File f(config_write_file(), "r+");
+       return static_cast<bool>(f);
 }
 
 /** @param  output_channels Number of output channels in use.
index 83cda4a04b41d723572ea43b890558d5dba048ca..b79f7ebdf6953071bef4df028470a4010e047d8a 100644 (file)
@@ -54,8 +54,6 @@ extern void maybe_open_console ();
 #endif
 extern boost::filesystem::path resources_path ();
 extern boost::filesystem::path libdcp_resources_path ();
-extern FILE * fopen_boost (boost::filesystem::path, std::string);
-extern int dcpomatic_fseek (FILE *, int64_t, int);
 extern void start_batch_converter ();
 extern void start_player ();
 extern uint64_t thread_id ();
@@ -65,7 +63,6 @@ extern bool running_32_on_64 ();
 extern void unprivileged ();
 extern boost::filesystem::path config_path (boost::optional<std::string> version);
 extern boost::filesystem::path directory_containing_executable ();
-extern boost::filesystem::path fix_long_path (boost::filesystem::path path);
 extern bool show_in_file_manager (boost::filesystem::path dir, boost::filesystem::path select);
 namespace dcpomatic {
        std::string get_process_id ();
index d7d1089fc8c90f2484436e30587d80eb8af00f40..89a9c5bb66df62ccf2eec05867d054c5fc843b30 100644 (file)
@@ -189,24 +189,6 @@ disk_writer_path ()
 #endif
 
 
-/* Apparently there is no way to create an ofstream using a UTF-8
-   filename under Windows.  We are hence reduced to using fopen
-   with this wrapper.
-*/
-FILE *
-fopen_boost (boost::filesystem::path p, string t)
-{
-        return fopen(p.c_str(), t.c_str());
-}
-
-
-int
-dcpomatic_fseek (FILE* stream, int64_t offset, int whence)
-{
-       return fseek (stream, offset, whence);
-}
-
-
 void
 Waker::nudge ()
 {
@@ -394,13 +376,6 @@ dcpomatic::get_process_id ()
 }
 
 
-boost::filesystem::path
-fix_long_path (boost::filesystem::path path)
-{
-       return path;
-}
-
-
 bool
 show_in_file_manager (boost::filesystem::path dir, boost::filesystem::path)
 {
index 02f720fee421835f511924874036304b6767bba9..b214b6359767b21749095b5f83a06b3466fe6ff8 100644 (file)
@@ -156,24 +156,6 @@ disk_writer_path ()
 #endif
 
 
-/* Apparently there is no way to create an ofstream using a UTF-8
-   filename under Windows.  We are hence reduced to using fopen
-   with this wrapper.
-*/
-FILE *
-fopen_boost (boost::filesystem::path p, string t)
-{
-        return fopen (p.c_str(), t.c_str());
-}
-
-
-int
-dcpomatic_fseek (FILE* stream, int64_t offset, int whence)
-{
-       return fseek (stream, offset, whence);
-}
-
-
 void
 Waker::nudge ()
 {
@@ -540,13 +522,6 @@ dcpomatic::get_process_id ()
 }
 
 
-boost::filesystem::path
-fix_long_path (boost::filesystem::path path)
-{
-       return path;
-}
-
-
 bool
 show_in_file_manager (boost::filesystem::path, boost::filesystem::path select)
 {
index f7638083656c2731411075144fbd10f8b72f9a2b..12fb5efa03659108b0a190a0afb0976fe7332ecc 100644 (file)
@@ -162,7 +162,7 @@ run_ffprobe (boost::filesystem::path content, boost::filesystem::path out)
                return;
        }
 
-       auto o = fopen_boost (out, "w");
+       dcp::File o(out, "w");
        if (!o) {
                LOG_ERROR_NC (N_("ffprobe call failed (could not create output file)"));
                return;
@@ -176,10 +176,10 @@ run_ffprobe (boost::filesystem::path content, boost::filesystem::path out)
                if (!ReadFile(child_stderr_read, buffer, sizeof(buffer), &read, 0) || read == 0) {
                        break;
                }
-               fwrite (buffer, read, 1, o);
+               o.write(buffer, read, 1);
        }
 
-       fclose (o);
+       o.close();
 
        WaitForSingleObject (process_info.hProcess, INFINITE);
        CloseHandle (process_info.hProcess);
@@ -232,64 +232,6 @@ disk_writer_path ()
 #endif
 
 
-/** 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
-fix_long_path (boost::filesystem::path long_path)
-{
-       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;
-}
-
-
-/* Apparently there is no way to create an ofstream using a UTF-8
-   filename under Windows.  We are hence reduced to using fopen
-   with this wrapper.
-*/
-FILE *
-fopen_boost (boost::filesystem::path p, string t)
-{
-        wstring w (t.begin(), t.end());
-       /* c_str() on fixed here should give a UTF-16 string */
-       return _wfopen (fix_long_path(p).c_str(), w.c_str());
-}
-
-
-int
-dcpomatic_fseek (FILE* stream, int64_t offset, int whence)
-{
-       return _fseeki64 (stream, offset, whence);
-}
-
-
 void
 Waker::nudge ()
 {
index 60835bea716cc6eab0e696f738dc95550ad06863..6fe7aba145c40ecfa2fd91f2ae035dee0d6f0a5b 100644 (file)
@@ -24,6 +24,7 @@
 #include "config.h"
 #include "cross.h"
 #include "compose.hpp"
+#include "dcpomatic_assert.h"
 #include <iostream>
 
 #include "i18n.h"
@@ -62,9 +63,6 @@ CurlUploader::CurlUploader (function<void (string)> set_status, function<void (f
 
 CurlUploader::~CurlUploader ()
 {
-       if (_file) {
-               fclose (_file);
-       }
        curl_easy_cleanup (_curl);
 }
 
@@ -85,10 +83,11 @@ CurlUploader::upload_file (boost::filesystem::path from, boost::filesystem::path
                String::compose ("ftp://%1/%2/%3", Config::instance()->tms_ip(), Config::instance()->tms_path(), to.generic_string ()).c_str ()
                );
 
-       _file = fopen_boost (from, "rb");
-       if (!_file) {
+       dcp::File file(from, "rb");
+       if (!file) {
                throw NetworkError (String::compose (_("Could not open %1 to send"), from));
        }
+       _file = file.get();
        _transferred = &transferred;
        _total_size = total_size;
 
@@ -97,15 +96,15 @@ CurlUploader::upload_file (boost::filesystem::path from, boost::filesystem::path
                throw NetworkError (String::compose (_("Could not write to remote file (%1)"), curl_easy_strerror (r)));
        }
 
-       fclose (_file);
-       _file = 0;
+       _file = nullptr;
 }
 
 
 size_t
 CurlUploader::read_callback (void* ptr, size_t size, size_t nmemb)
 {
-       size_t const r = fread (ptr, size, nmemb, _file);
+       DCPOMATIC_ASSERT (_file);
+       size_t const r = fread(ptr, size, nmemb, _file);
        *_transferred += size * nmemb;
 
        if (_total_size > 0) {
index 564e774934c1f16afb555886d9926e5e15b1661a..ea017eb8349f302b2d2c3b6fe8871a5242cc443b 100644 (file)
@@ -20,6 +20,7 @@
 
 
 #include "uploader.h"
+#include <dcp/file.h>
 #include <curl/curl.h>
 
 
index 1af6c137bf3f2945d22a0655579dec340a564eaa..7853984cf28e2b4ff123078fe02dccae39c03eaf 100644 (file)
@@ -79,7 +79,7 @@ static
 void
 count (boost::filesystem::path dir, uint64_t& total_bytes)
 {
-       dir = fix_long_path (dir);
+       dir = dcp::fix_long_path (dir);
 
        using namespace boost::filesystem;
        for (auto i: directory_iterator(dir)) {
@@ -113,7 +113,7 @@ write (boost::filesystem::path from, boost::filesystem::path to, uint64_t& total
                throw CopyError (String::compose("Failed to open file %1", to.generic_string()), r);
        }
 
-       FILE* in = fopen_boost (from, "rb");
+       dcp::File in(from, "rb");
        if (!in) {
                ext4_fclose (&out);
                throw CopyError (String::compose("Failed to open file %1", from.string()), 0);
@@ -127,9 +127,8 @@ write (boost::filesystem::path from, boost::filesystem::path to, uint64_t& total
        uint64_t remaining = file_size (from);
        while (remaining > 0) {
                uint64_t const this_time = min(remaining, block_size);
-               size_t read = fread (buffer.data(), 1, this_time, in);
+               size_t read = in.read(buffer.data(), 1, this_time);
                if (read != this_time) {
-                       fclose (in);
                        ext4_fclose (&out);
                        throw CopyError (String::compose("Short read; expected %1 but read %2", this_time, read), 0);
                }
@@ -139,12 +138,10 @@ write (boost::filesystem::path from, boost::filesystem::path to, uint64_t& total
                size_t written;
                r = ext4_fwrite (&out, buffer.data(), this_time, &written);
                if (r != EOK) {
-                       fclose (in);
                        ext4_fclose (&out);
                        throw CopyError ("Write failed", r);
                }
                if (written != this_time) {
-                       fclose (in);
                        ext4_fclose (&out);
                        throw CopyError (String::compose("Short write; expected %1 but wrote %2", this_time, written), 0);
                }
@@ -157,7 +154,6 @@ write (boost::filesystem::path from, boost::filesystem::path to, uint64_t& total
                }
        }
 
-       fclose (in);
        ext4_fclose (&out);
 
        set_timestamps_to_now (to);
@@ -229,7 +225,7 @@ void
 copy (boost::filesystem::path from, boost::filesystem::path to, uint64_t& total_remaining, uint64_t total, vector<CopiedFile>& copied_files, Nanomsg* nanomsg)
 {
        LOG_DISK ("Copy %1 -> %2", from.string(), to.generic_string());
-       from = fix_long_path (from);
+       from = dcp::fix_long_path (from);
 
        using namespace boost::filesystem;
 
index 7dae1da92c26690f40ccdff9c4dd7d026d3d24d1..71faacc4c0fa6bd27667c761c873ddce42d4ec88 100644 (file)
@@ -61,15 +61,6 @@ FileGroup::FileGroup (vector<boost::filesystem::path> const & p)
 }
 
 
-/** Destroy a FileGroup, closing any open file */
-FileGroup::~FileGroup ()
-{
-       if (_current_file) {
-               fclose (_current_file);
-       }
-}
-
-
 void
 FileGroup::set_paths (vector<boost::filesystem::path> const & p)
 {
@@ -89,11 +80,11 @@ FileGroup::ensure_open_path (size_t p) const
        }
 
        if (_current_file) {
-               fclose (_current_file);
+               _current_file->close();
        }
 
        _current_path = p;
-       _current_file = fopen_boost (_paths[_current_path], "rb");
+       _current_file = dcp::File(_paths[_current_path], "rb");
        if (!_current_file) {
                throw OpenFileError (_paths[_current_path], errno, OpenFileError::READ);
        }
@@ -130,10 +121,10 @@ FileGroup::seek (int64_t pos, int whence) const
 
        if (i < _paths.size()) {
                ensure_open_path (i);
-               dcpomatic_fseek (_current_file, sub_pos, SEEK_SET);
+               _current_file->seek(sub_pos, SEEK_SET);
        } else {
                ensure_open_path (_paths.size() - 1);
-               dcpomatic_fseek (_current_file, _current_size, SEEK_SET);
+               _current_file->seek(_current_size, SEEK_SET);
        }
 
        return _position;
@@ -148,6 +139,8 @@ FileGroup::seek (int64_t pos, int whence) const
 int
 FileGroup::read (uint8_t* buffer, int amount) const
 {
+       DCPOMATIC_ASSERT (_current_file);
+
        int read = 0;
        while (true) {
 
@@ -156,8 +149,7 @@ FileGroup::read (uint8_t* buffer, int amount) const
 
                DCPOMATIC_ASSERT (_current_file);
 
-#ifdef DCPOMATIC_WINDOWS
-               int64_t const current_position = _ftelli64 (_current_file);
+               auto const current_position = _current_file->tell();
                if (current_position == -1) {
                        to_read = 0;
                        eof = true;
@@ -165,15 +157,8 @@ FileGroup::read (uint8_t* buffer, int amount) const
                        to_read = _current_size - current_position;
                        eof = true;
                }
-#else
-               long const current_position = ftell(_current_file);
-               if ((current_position + to_read) > _current_size) {
-                       to_read = _current_size - current_position;
-                       eof = true;
-               }
-#endif
 
-               int const this_time = fread (buffer + read, 1, to_read, _current_file);
+               int const this_time = _current_file->read(buffer + read, 1, to_read);
                read += this_time;
                _position += this_time;
                if (read == amount) {
@@ -181,7 +166,7 @@ FileGroup::read (uint8_t* buffer, int amount) const
                        break;
                }
 
-               if (ferror(_current_file)) {
+               if (_current_file->error()) {
                        throw FileError (String::compose("fread error %1", errno), _paths[_current_path]);
                }
 
index 9521da7ec88c85b016dc2ef6889030d7c048a97a..693bf89baeb800757fa61acfdeccb243eeb02ae5 100644 (file)
@@ -28,7 +28,9 @@
 #define DCPOMATIC_FILE_GROUP_H
 
 
+#include <dcp/file.h>
 #include <boost/filesystem.hpp>
+#include <boost/optional.hpp>
 #include <vector>
 
 
@@ -41,7 +43,6 @@ public:
        FileGroup ();
        explicit FileGroup (boost::filesystem::path);
        explicit FileGroup (std::vector<boost::filesystem::path> const &);
-       ~FileGroup ();
 
        FileGroup (FileGroup const&) = delete;
        FileGroup& operator= (FileGroup const&) = delete;
@@ -58,7 +59,7 @@ private:
        std::vector<boost::filesystem::path> _paths;
        /** Index of path that we are currently reading from */
        mutable size_t _current_path = 0;
-       mutable FILE* _current_file = nullptr;
+       mutable boost::optional<dcp::File> _current_file;
        mutable size_t _current_size = 0;
        mutable int64_t _position = 0;
 };
index a9522bad507dc722033074c9a5abd45c7770dcf5..adb06b7f04fb71f4f6e986cdd930ffdc1ba3b602 100644 (file)
@@ -22,6 +22,7 @@
 #include "file_log.h"
 #include "cross.h"
 #include "config.h"
+#include <dcp/file.h>
 #include <cstdio>
 #include <iostream>
 #include <cerrno>
@@ -51,14 +52,13 @@ FileLog::FileLog (boost::filesystem::path file, int types)
 void
 FileLog::do_log (shared_ptr<const LogEntry> entry)
 {
-       auto f = fopen_boost (_file, "a");
+       dcp::File f(_file, "a");
        if (!f) {
                cout << "(could not log to " << _file.string() << " error " << errno << "): " << entry->get() << "\n";
                return;
        }
 
-       fprintf (f, "%s\n", entry->get().c_str());
-       fclose (f);
+       fprintf(f.get(), "%s\n", entry->get().c_str());
 }
 
 
@@ -80,7 +80,7 @@ FileLog::head_and_tail (int amount) const
                tail_amount = 0;
        }
 
-       auto f = fopen_boost (_file, "r");
+       dcp::File f(_file, "r");
        if (!f) {
                return "";
        }
@@ -89,21 +89,19 @@ FileLog::head_and_tail (int amount) const
 
        std::vector<char> buffer(max(head_amount, tail_amount) + 1);
 
-       int N = fread (buffer.data(), 1, head_amount, f);
+       int N = f.read(buffer.data(), 1, head_amount);
        buffer[N] = '\0';
        out += string (buffer.data());
 
        if (tail_amount > 0) {
                out +=  "\n .\n .\n .\n";
 
-               fseek (f, - tail_amount - 1, SEEK_END);
+               f.seek(- tail_amount - 1, SEEK_END);
 
-               N = fread (buffer.data(), 1, tail_amount, f);
+               N = f.read(buffer.data(), 1, tail_amount);
                buffer[N] = '\0';
-               out += string (buffer.data()) + "\n";
+               out += string(buffer.data()) + "\n";
        }
 
-       fclose (f);
-
        return out;
 }
index e49b7f78e7ed026cf14beb3bd8d96b0f311cb121..54267bc5686038d1006fd1c75ba62de41e641e3f 100644 (file)
@@ -1718,9 +1718,9 @@ Film::should_be_enough_disk_space (double& required, double& available, bool& ca
        boost::filesystem::path test = internal_video_asset_dir() / "test";
        boost::filesystem::path test2 = internal_video_asset_dir() / "test2";
        can_hard_link = true;
-       auto f = fopen_boost (test, "w");
+       dcp::File f(test, "w");
        if (f) {
-               fclose (f);
+               f.close();
                boost::system::error_code ec;
                boost::filesystem::create_hard_link (test, test2, ec);
                if (ec) {
@@ -2071,34 +2071,15 @@ Film::info_file_handle (DCPTimePeriod period, bool read) const
        return std::make_shared<InfoFileHandle>(_info_file_mutex, info_file(period), read);
 }
 
-InfoFileHandle::InfoFileHandle (boost::mutex& mutex, boost::filesystem::path file, bool read)
+InfoFileHandle::InfoFileHandle (boost::mutex& mutex, boost::filesystem::path path, bool read)
        : _lock (mutex)
-       , _file (file)
+       , _file (path, read ? "rb" : (boost::filesystem::exists(path) ? "r+b" : "wb"))
 {
-       if (read) {
-               _handle = fopen_boost (file, "rb");
-               if (!_handle) {
-                       throw OpenFileError (file, errno, OpenFileError::READ);
-               }
-       } else {
-               auto const exists = boost::filesystem::exists (file);
-               if (exists) {
-                       _handle = fopen_boost (file, "r+b");
-               } else {
-                       _handle = fopen_boost (file, "wb");
-               }
-
-               if (!_handle) {
-                       throw OpenFileError (file, errno, exists ? OpenFileError::READ_WRITE : OpenFileError::WRITE);
-               }
+       if (!_file) {
+               throw OpenFileError (path, errno, read ? OpenFileError::READ : (boost::filesystem::exists(path) ? OpenFileError::READ_WRITE : OpenFileError::WRITE));
        }
 }
 
-InfoFileHandle::~InfoFileHandle ()
-{
-       fclose (_handle);
-}
-
 
 /** Add FFOC and LFOC markers to a list if they are not already there */
 void
index d42eb5626b71dad5050e3fa5335002611f59edf1..5318d6a12aa837229d4e4ea6ff94ffe1a958fdb8 100644 (file)
@@ -37,6 +37,7 @@
 #include "types.h"
 #include "util.h"
 #include <dcp/encrypted_kdm.h>
+#include <dcp/file.h>
 #include <dcp/key.h>
 #include <dcp/language_tag.h>
 #include <dcp/rating.h>
@@ -75,13 +76,8 @@ class InfoFileHandle
 {
 public:
        InfoFileHandle (boost::mutex& mutex, boost::filesystem::path file, bool read);
-       ~InfoFileHandle ();
 
-       FILE* get () const {
-               return _handle;
-       }
-
-       boost::filesystem::path file () const {
+       dcp::File& get () {
                return _file;
        }
 
@@ -89,10 +85,10 @@ private:
        friend class Film;
 
        boost::mutex::scoped_lock _lock;
-       FILE* _handle;
-       boost::filesystem::path _file;
+       dcp::File _file;
 };
 
+
 /** @class Film
  *
  *  @brief A representation of some audio, video, subtitle and closed-caption content,
index 5a1672204d4f67d6adfa2162707df456bc3595bc..6e4dea7b7da6f1ddc104341f5a8c5bf415475578 100644 (file)
@@ -51,13 +51,13 @@ ImageExaminer::ImageExaminer (shared_ptr<const Film> film, shared_ptr<const Imag
        auto path = content->path(0);
        if (valid_j2k_file (path)) {
                auto size = boost::filesystem::file_size (path);
-               auto f = fopen_boost (path, "rb");
+               dcp::File f(path, "rb");
                if (!f) {
                        throw FileError ("Could not open file for reading", path);
                }
                std::vector<uint8_t> buffer(size);
-               checked_fread (buffer.data(), size, f, path);
-               fclose (f);
+               f.checked_read(buffer.data(), size);
+               f.close();
                try {
                        _video_size = dcp::decompress_j2k(buffer.data(), size, 0)->size();
                } catch (dcp::ReadError& e) {
index c0c8232eef6b13e3c3f843f0c28e451dcf6ff1cf..a9c30611df49d89f065cd04ee525f1b2bdf3ab72 100644 (file)
@@ -24,6 +24,7 @@
 #include "exceptions.h"
 #include "scoped_temporary.h"
 #include "util.h"
+#include <dcp/file.h>
 #include <curl/curl.h>
 #include <zip.h>
 #include <boost/optional.hpp>
@@ -98,9 +99,9 @@ get_from_url (string url, bool pasv, bool skip_pasv_ip, ScopedTemporary& temp)
        auto curl = curl_easy_init ();
        curl_easy_setopt (curl, CURLOPT_URL, url.c_str());
 
-       auto f = temp.open ("wb");
+       auto& f = temp.open ("wb");
        curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, get_from_url_data);
-       curl_easy_setopt (curl, CURLOPT_WRITEDATA, f);
+       curl_easy_setopt (curl, CURLOPT_WRITEDATA, f.get());
        curl_easy_setopt (curl, CURLOPT_FTP_USE_EPSV, 0);
        curl_easy_setopt (curl, CURLOPT_FTP_USE_EPRT, 0);
        if (skip_pasv_ip) {
@@ -115,7 +116,7 @@ get_from_url (string url, bool pasv, bool skip_pasv_ip, ScopedTemporary& temp)
 
        auto const cr = curl_easy_perform (curl);
 
-       temp.close ();
+       f.close();
        curl_easy_cleanup (curl);
        if (cr != CURLE_OK) {
                return String::compose (_("Download failed (%1 error %2)"), url, (int) cr);
@@ -133,7 +134,7 @@ get_from_url (string url, bool pasv, bool skip_pasv_ip, function<optional<string
        if (e) {
                return e;
        }
-       return load (temp.file(), url);
+       return load (temp.path(), url);
 }
 
 
@@ -159,14 +160,14 @@ get_from_zip_url (string url, string file, bool pasv, bool skip_pasv_ip, functio
           Centos 6, Centos 7, Debian 7 and Debian 8.
        */
 
-       auto zip_file = fopen_boost (temp_zip.file (), "rb");
+       auto& zip_file = temp_zip.open("rb");
        if (!zip_file) {
-               return optional<string> (_("Could not open downloaded ZIP file"));
+               return string(_("Could not open downloaded ZIP file"));
        }
 
-       auto zip_source = zip_source_filep_create (zip_file, 0, -1, 0);
+       auto zip_source = zip_source_filep_create (zip_file.take(), 0, -1, 0);
        if (!zip_source) {
-               return optional<string> (_("Could not open downloaded ZIP file"));
+               return string(_("Could not open downloaded ZIP file"));
        }
 
        zip_error_t error;
@@ -182,22 +183,22 @@ get_from_zip_url (string url, string file, bool pasv, bool skip_pasv_ip, functio
 
        struct zip_file* file_in_zip = zip_fopen (zip, file.c_str(), 0);
        if (!file_in_zip) {
-               return optional<string> (_("Unexpected ZIP file contents"));
+               return string(_("Unexpected ZIP file contents"));
        }
 
        ScopedTemporary temp_cert;
-       auto f = temp_cert.open ("wb");
+       auto& f = temp_cert.open ("wb");
        char buffer[4096];
        while (true) {
                int const N = zip_fread (file_in_zip, buffer, sizeof (buffer));
-               checked_fwrite (buffer, N, f, temp_cert.file());
+               f.checked_write(buffer, N);
                if (N < int (sizeof (buffer))) {
                        break;
                }
        }
        zip_fclose (file_in_zip);
        zip_close (zip);
-       temp_cert.close ();
+       f.close ();
 
-       return load (temp_cert.file(), url);
+       return load (temp_cert.path(), url);
 }
index 857fdca2c01c9590373c4fa286fd641cb0bf3562..123649d127c0a00fbf468d765505a17b89794046 100644 (file)
@@ -28,6 +28,7 @@
 #include "screen.h"
 #include "util.h"
 #include "zipper.h"
+#include <dcp/file.h>
 
 #include "i18n.h"
 
@@ -66,7 +67,7 @@ write_files (
 
        /* Write KDMs to the specified directory */
        for (auto i: kdms) {
-               auto out = fix_long_path(directory / careful_string_filter(name_format.get(i->name_values(), ".xml")));
+               auto out = dcp::fix_long_path(directory / careful_string_filter(name_format.get(i->name_values(), ".xml")));
                if (!boost::filesystem::exists (out) || confirm_overwrite (out)) {
                        i->kdm_as_xml (out);
                        ++written;
index 7a2c9c67087b68d3b500817de039303042ca293b..94920b95bce0cd82232e94c9aca0e9275ccf70c1 100644 (file)
@@ -208,10 +208,10 @@ void
 ReelWriter::write_frame_info (Frame frame, Eyes eyes, dcp::FrameInfo info) const
 {
        auto handle = film()->info_file_handle(_period, false);
-       dcpomatic_fseek (handle->get(), frame_info_position(frame, eyes), SEEK_SET);
-       checked_fwrite (&info.offset, sizeof(info.offset), handle->get(), handle->file());
-       checked_fwrite (&info.size, sizeof (info.size), handle->get(), handle->file());
-       checked_fwrite (info.hash.c_str(), info.hash.size(), handle->get(), handle->file());
+       handle->get().seek(frame_info_position(frame, eyes), SEEK_SET);
+       handle->get().checked_write(&info.offset, sizeof(info.offset));
+       handle->get().checked_write(&info.size, sizeof(info.size));
+       handle->get().checked_write(info.hash.c_str(), info.hash.size());
 }
 
 
@@ -219,12 +219,12 @@ dcp::FrameInfo
 ReelWriter::read_frame_info (shared_ptr<InfoFileHandle> info, Frame frame, Eyes eyes) const
 {
        dcp::FrameInfo frame_info;
-       dcpomatic_fseek (info->get(), frame_info_position(frame, eyes), SEEK_SET);
-       checked_fread (&frame_info.offset, sizeof(frame_info.offset), info->get(), info->file());
-       checked_fread (&frame_info.size, sizeof(frame_info.size), info->get(), info->file());
+       info->get().seek(frame_info_position(frame, eyes), SEEK_SET);
+       info->get().checked_read(&frame_info.offset, sizeof(frame_info.offset));
+       info->get().checked_read(&frame_info.size, sizeof(frame_info.size));
 
        char hash_buffer[33];
-       checked_fread (hash_buffer, 32, info->get(), info->file());
+       info->get().checked_read(hash_buffer, 32);
        hash_buffer[32] = '\0';
        frame_info.hash = hash_buffer;
 
@@ -260,7 +260,7 @@ ReelWriter::check_existing_picture_asset (boost::filesystem::path asset)
        }
 
        /* Try to open the existing asset */
-       auto asset_file = fopen_boost (asset, "rb");
+       dcp::File asset_file(asset, "rb");
        if (!asset_file) {
                LOG_GENERAL ("Could not open existing asset at %1 (errno=%2)", asset.string(), errno);
                return 0;
@@ -274,13 +274,12 @@ ReelWriter::check_existing_picture_asset (boost::filesystem::path asset)
                info_file = film()->info_file_handle (_period, true);
        } catch (OpenFileError &) {
                LOG_GENERAL_NC ("Could not open film info file");
-               fclose (asset_file);
                return 0;
        }
 
        /* Offset of the last dcp::FrameInfo in the info file */
-       int const n = (boost::filesystem::file_size(info_file->file()) / _info_size) - 1;
-       LOG_GENERAL ("The last FI is %1; info file is %2, info size %3", n, boost::filesystem::file_size(info_file->file()), _info_size);
+       int const n = (boost::filesystem::file_size(info_file->get().path()) / _info_size) - 1;
+       LOG_GENERAL ("The last FI is %1; info file is %2, info size %3", n, boost::filesystem::file_size(info_file->get().path()), _info_size);
 
        Frame first_nonexistant_frame;
        if (film()->three_d()) {
@@ -303,8 +302,6 @@ ReelWriter::check_existing_picture_asset (boost::filesystem::path asset)
 
        LOG_GENERAL ("Proceeding with first nonexistant frame %1", first_nonexistant_frame);
 
-       fclose (asset_file);
-
        return first_nonexistant_frame;
 }
 
@@ -921,7 +918,7 @@ ReelWriter::write (PlayerText subs, TextType type, optional<DCPTextTrack> track,
 
 
 bool
-ReelWriter::existing_picture_frame_ok (FILE* asset_file, shared_ptr<InfoFileHandle> info_file, Frame frame) const
+ReelWriter::existing_picture_frame_ok (dcp::File& asset_file, shared_ptr<InfoFileHandle> info_file, Frame frame) const
 {
        LOG_GENERAL ("Checking existing picture frame %1", frame);
 
@@ -933,9 +930,9 @@ ReelWriter::existing_picture_frame_ok (FILE* asset_file, shared_ptr<InfoFileHand
        bool ok = true;
 
        /* Read the data from the asset and hash it */
-       dcpomatic_fseek (asset_file, info.offset, SEEK_SET);
+       asset_file.seek(info.offset, SEEK_SET);
        ArrayData data (info.size);
-       size_t const read = fread (data.data(), 1, data.size(), asset_file);
+       size_t const read = asset_file.read(data.data(), 1, data.size());
        LOG_GENERAL ("Read %1 bytes of asset data; wanted %2", read, info.size);
        if (read != static_cast<size_t> (data.size ())) {
                LOG_GENERAL ("Existing frame %1 is incomplete", frame);
index 0308c64ecd1b753a4ca484768e73d3e7f5ea63d2..bee76ded3fd65b5fb6cbe7272d98c8ad2a3a7cd4 100644 (file)
@@ -25,8 +25,9 @@
 #include "player_text.h"
 #include "dcp_text_track.h"
 #include "weak_film.h"
-#include <dcp/picture_asset_writer.h>
 #include <dcp/atmos_asset_writer.h>
+#include <dcp/file.h>
+#include <dcp/picture_asset_writer.h>
 
 namespace dcpomatic {
        class FontData;
@@ -102,7 +103,7 @@ private:
        void write_frame_info (Frame frame, Eyes eyes, dcp::FrameInfo info) const;
        long frame_info_position (Frame frame, Eyes eyes) const;
        Frame check_existing_picture_asset (boost::filesystem::path asset);
-       bool existing_picture_frame_ok (FILE* asset_file, std::shared_ptr<InfoFileHandle> info_file, Frame frame) const;
+       bool existing_picture_frame_ok (dcp::File& asset_file, std::shared_ptr<InfoFileHandle> info_file, Frame frame) const;
        std::shared_ptr<dcp::SubtitleAsset> empty_text_asset (TextType type, boost::optional<DCPTextTrack> track, bool with_dummy) const;
 
        std::shared_ptr<dcp::ReelPictureAsset> create_reel_picture (std::shared_ptr<dcp::Reel> reel, std::list<ReferencedReelAsset> const & refs) const;
index 223100ba5f727df6180eab3b1ba191a38f1ff18b..0ead7b1655d5445244aa103f67dcc597f160e035 100644 (file)
  */
 ScopedTemporary::ScopedTemporary ()
 {
-       _file = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path ();
+       _path = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
 }
 
 
 /** Close and delete the temporary file */
 ScopedTemporary::~ScopedTemporary ()
 {
-       close ();
+       if (_file) {
+               _file->close();
+       }
        boost::system::error_code ec;
-       boost::filesystem::remove (_file, ec);
+       boost::filesystem::remove (_path, ec);
 }
 
 
@@ -46,31 +48,23 @@ ScopedTemporary::~ScopedTemporary ()
 char const *
 ScopedTemporary::c_str () const
 {
-       return _file.string().c_str();
+       return _path.string().c_str();
 }
 
 
 /** Open the temporary file.
  *  @return File's FILE pointer.
  */
-FILE*
+dcp::File&
 ScopedTemporary::open (char const * params)
 {
-       close ();
-       _open = fopen_boost (_file, params);
-       if (!_open) {
-               throw FileError ("Could not open scoped temporary", _file);
+       if (_file) {
+               _file->close();
        }
-       return _open;
-}
-
-
-/** Close the file */
-void
-ScopedTemporary::close ()
-{
-       if (_open) {
-               fclose (_open);
-               _open = nullptr;
+       _file = dcp::File(_path, params);
+       if (!*_file) {
+               throw FileError ("Could not open scoped temporary", _path);
        }
+       return *_file;
 }
+
index 75d9a272f74dab5341e2e3173bce935a90f501b9..b78f60541089fc6ed7833e69b8c05e965f0b4720 100644 (file)
@@ -19,7 +19,9 @@
 */
 
 
+#include <dcp/file.h>
 #include <boost/filesystem.hpp>
+#include <boost/optional.hpp>
 #include <cstdio>
 
 
@@ -35,16 +37,15 @@ public:
        ScopedTemporary (ScopedTemporary const&) = delete;
        ScopedTemporary& operator= (ScopedTemporary const&) = delete;
 
-       /** @return temporary filename */
-       boost::filesystem::path file () const {
-               return _file;
+       /** @return temporary pathname */
+       boost::filesystem::path path () const {
+               return _path;
        }
 
        char const * c_str () const;
-       FILE* open (char const *);
-       void close ();
+       dcp::File& open (char const *);
 
 private:
-       boost::filesystem::path _file;
-       FILE* _open = nullptr;
+       boost::filesystem::path _path;
+       boost::optional<dcp::File> _file;
 };
index 8bb41e3b1d3118aa43f453865ccc09901b1c6d93..c14c02215fd399eee8ac5d7b379d9a3b52eec82f 100644 (file)
@@ -25,6 +25,8 @@
 #include "config.h"
 #include "cross.h"
 #include "compose.hpp"
+#include <dcp/file.h>
+#include <dcp/warnings.h>
 #include <sys/stat.h>
 
 #include "i18n.h"
@@ -104,8 +106,8 @@ SCPUploader::upload_file (boost::filesystem::path from, boost::filesystem::path
        /* Use generic_string so that we get forward-slashes in the path, even on Windows */
        ssh_scp_push_file (_scp, to.generic_string().c_str(), to_do, S_IRUSR | S_IWUSR);
 
-       auto f = fopen_boost (from, "rb");
-       if (f == nullptr) {
+       dcp::File f(from, "rb");
+       if (!f) {
                throw NetworkError (String::compose(_("Could not open %1 to send"), from));
        }
 
@@ -114,15 +116,13 @@ SCPUploader::upload_file (boost::filesystem::path from, boost::filesystem::path
 
        while (to_do > 0) {
                int const t = min (to_do, buffer_size);
-               size_t const read = fread (buffer, 1, t, f);
+               size_t const read = f.read(buffer, 1, t);
                if (read != size_t (t)) {
-                       fclose (f);
                        throw ReadFileError (from);
                }
 
                int const r = ssh_scp_write (_scp, buffer, t);
                if (r != SSH_OK) {
-                       fclose (f);
                        throw NetworkError (String::compose(_("Could not write to remote file (%1)"), ssh_get_error(_session)));
                }
                to_do -= t;
@@ -132,6 +132,4 @@ SCPUploader::upload_file (boost::filesystem::path from, boost::filesystem::path
                        _set_progress ((double) transferred / total_size);
                }
        }
-
-       fclose (f);
 }
index 8c2c5651854e08a625f2d9602bfc9aaede91cf43..b8ca27e160ca989ad283768f963a1bdf974546db 100644 (file)
 
 */
 
-#include "string_text_file.h"
+
 #include "cross.h"
 #include "exceptions.h"
+#include "string_text_file.h"
 #include "string_text_file_content.h"
-#include <sub/subrip_reader.h>
+#include <dcp/file.h>
+#include <sub/collect.h>
 #include <sub/ssa_reader.h>
 #include <sub/stl_binary_reader.h>
-#include <sub/collect.h>
+#include <sub/subrip_reader.h>
 #include <unicode/ucsdet.h>
 #include <unicode/ucnv.h>
 #include <iostream>
 
 #include "i18n.h"
 
-using std::vector;
+
 using std::cout;
-using std::string;
 using std::shared_ptr;
+using std::string;
+using std::vector;
 using boost::scoped_array;
 using boost::optional;
 using dcp::ArrayData;
 using namespace dcpomatic;
 
+
 StringTextFile::StringTextFile (shared_ptr<const StringTextFileContent> content)
 {
        string ext = content->path(0).extension().string();
@@ -49,17 +53,15 @@ StringTextFile::StringTextFile (shared_ptr<const StringTextFileContent> content)
        std::unique_ptr<sub::Reader> reader;
 
        if (ext == ".stl") {
-               auto f = fopen_boost (content->path(0), "rb");
+               dcp::File f(content->path(0), "rb");
                if (!f) {
-                       throw OpenFileError (content->path(0), errno, OpenFileError::READ);
+                       throw OpenFileError (f.path(), errno, OpenFileError::READ);
                }
                try {
-                       reader.reset(new sub::STLBinaryReader(f));
+                       reader.reset(new sub::STLBinaryReader(f.get()));
                } catch (...) {
-                       fclose (f);
                        throw;
                }
-               fclose (f);
 
        } else {
                /* Text-based file; sort out its character encoding before we try to parse it */
index 6e2a1ad642c9d2b7a945abf32314879438b233c2..d020ba13d45250c00b009c251aaa95144a6cb607 100644 (file)
@@ -250,9 +250,11 @@ LIBDCP_DISABLE_WARNINGS
 LONG WINAPI
 exception_handler(struct _EXCEPTION_POINTERS * info)
 {
-       auto f = fopen_boost (backtrace_file, "w");
-       fprintf (f, "C-style exception %d\n", info->ExceptionRecord->ExceptionCode);
-       fclose(f);
+       dcp::File f(backtrace_file, "w");
+       if (f) {
+               fprintf(f.get(), "C-style exception %d\n", info->ExceptionRecord->ExceptionCode);
+               f.close();
+       }
 
        if (info->ExceptionRecord->ExceptionCode != EXCEPTION_STACK_OVERFLOW) {
                CONTEXT* context = info->ContextRecord;
@@ -490,16 +492,15 @@ digest_head_tail (vector<boost::filesystem::path> files, boost::uintmax_t size)
        char* p = buffer.get ();
        int i = 0;
        while (i < int64_t (files.size()) && to_do > 0) {
-               auto f = fopen_boost (files[i], "rb");
+               dcp::File f(files[i], "rb");
                if (!f) {
                        throw OpenFileError (files[i].string(), errno, OpenFileError::READ);
                }
 
                boost::uintmax_t this_time = min (to_do, boost::filesystem::file_size (files[i]));
-               checked_fread (p, this_time, f, files[i]);
+               f.checked_read(p, this_time);
                p += this_time;
                to_do -= this_time;
-               fclose (f);
 
                ++i;
        }
@@ -510,17 +511,16 @@ digest_head_tail (vector<boost::filesystem::path> files, boost::uintmax_t size)
        p = buffer.get ();
        i = files.size() - 1;
        while (i >= 0 && to_do > 0) {
-               auto f = fopen_boost (files[i], "rb");
+               dcp::File f(files[i], "rb");
                if (!f) {
                        throw OpenFileError (files[i].string(), errno, OpenFileError::READ);
                }
 
                boost::uintmax_t this_time = min (to_do, boost::filesystem::file_size (files[i]));
-               dcpomatic_fseek (f, -this_time, SEEK_END);
-               checked_fread (p, this_time, f, files[i]);
+               f.seek(-this_time, SEEK_END);
+               f.checked_read(p, this_time);
                p += this_time;
                to_do -= this_time;
-               fclose (f);
 
                --i;
        }
@@ -864,35 +864,6 @@ increment_eyes (Eyes e)
        return Eyes::LEFT;
 }
 
-void
-checked_fwrite (void const * ptr, size_t size, FILE* stream, boost::filesystem::path path)
-{
-       size_t N = fwrite (ptr, 1, size, stream);
-       if (N != size) {
-               if (ferror(stream)) {
-                       fclose (stream);
-                       throw FileError (String::compose("fwrite error %1", errno), path);
-               } else {
-                       fclose (stream);
-                       throw FileError ("Unexpected short write", path);
-               }
-       }
-}
-
-void
-checked_fread (void* ptr, size_t size, FILE* stream, boost::filesystem::path path)
-{
-       size_t N = fread (ptr, 1, size, stream);
-       if (N != size) {
-               if (ferror(stream)) {
-                       fclose (stream);
-                       throw FileError (String::compose("fread error %1", errno), path);
-               } else {
-                       fclose (stream);
-                       throw FileError ("Unexpected short read", path);
-               }
-       }
-}
 
 size_t
 utf8_strlen (string s)
@@ -1034,52 +1005,38 @@ show_jobs_on_console (bool progress)
 void
 copy_in_bits (boost::filesystem::path from, boost::filesystem::path to, std::function<void (float)> progress)
 {
-       auto f = fopen_boost (from, "rb");
+       dcp::File f(from, "rb");
        if (!f) {
                throw OpenFileError (from, errno, OpenFileError::READ);
        }
-       auto t = fopen_boost (to, "wb");
+       dcp::File t(to, "wb");
        if (!t) {
-               fclose (f);
                throw OpenFileError (to, errno, OpenFileError::WRITE);
        }
 
        /* on the order of a second's worth of copying */
        boost::uintmax_t const chunk = 20 * 1024 * 1024;
 
-       auto buffer = static_cast<uint8_t*> (malloc(chunk));
-       if (!buffer) {
-               throw std::bad_alloc ();
-       }
+       std::vector<uint8_t> buffer(chunk);
 
        boost::uintmax_t const total = boost::filesystem::file_size (from);
        boost::uintmax_t remaining = total;
 
        while (remaining) {
                boost::uintmax_t this_time = min (chunk, remaining);
-               size_t N = fread (buffer, 1, chunk, f);
+               size_t N = f.read(buffer.data(), 1, chunk);
                if (N < this_time) {
-                       fclose (f);
-                       fclose (t);
-                       free (buffer);
                        throw ReadFileError (from, errno);
                }
 
-               N = fwrite (buffer, 1, this_time, t);
+               N = t.write(buffer.data(), 1, this_time);
                if (N < this_time) {
-                       fclose (f);
-                       fclose (t);
-                       free (buffer);
                        throw WriteFileError (to, errno);
                }
 
                progress (1 - float(remaining) / total);
                remaining -= this_time;
        }
-
-       fclose (f);
-       fclose (t);
-       free (buffer);
 }
 
 
index 706056cdab962b3d7585453297b50551f09b9a66..233b3cb2a9bc7c698685ad83744ff634782c0968 100644 (file)
@@ -113,8 +113,6 @@ extern std::string careful_string_filter (std::string);
 extern std::pair<int, int> audio_channel_types (std::list<int> mapped, int channels);
 extern std::shared_ptr<AudioBuffers> remap (std::shared_ptr<const AudioBuffers> input, int output_channels, AudioMapping map);
 extern Eyes increment_eyes (Eyes e);
-extern void checked_fread (void* ptr, size_t size, FILE* stream, boost::filesystem::path path);
-extern void checked_fwrite (void const * ptr, size_t size, FILE* stream, boost::filesystem::path path);
 extern size_t utf8_strlen (std::string s);
 extern std::string day_of_week_to_string (boost::gregorian::greg_weekday d);
 extern void emit_subtitle_image (dcpomatic::ContentTimePeriod period, dcp::SubtitleImage sub, dcp::Size size, std::shared_ptr<TextDecoder> decoder);
index 309cfb78c8355211c16abfb617418fc9629edc24..3aca2ab89c96328445907dbbd88ae64156b722ac 100644 (file)
@@ -710,7 +710,7 @@ void
 Writer::write_cover_sheet (boost::filesystem::path output_dcp)
 {
        auto const cover = film()->file("COVER_SHEET.txt");
-       auto f = fopen_boost (cover, "w");
+       dcp::File f(cover, "w");
        if (!f) {
                throw OpenFileError (cover, errno, OpenFileError::WRITE);
        }
@@ -778,8 +778,7 @@ Writer::write_cover_sheet (boost::filesystem::path output_dcp)
 
        boost::algorithm::replace_all (text, "$LENGTH", length);
 
-       checked_fwrite (text.c_str(), text.length(), f, cover);
-       fclose (f);
+       f.checked_write(text.c_str(), text.length());
 }
 
 
index 71353d463858e9ee5da47cd01e5d39aa8445fd0c..dae904eb44335199a54fdcfb081a46c9bbd445ee 100644 (file)
@@ -301,19 +301,18 @@ main (int argc, char* argv[])
        }
 
        if (servers) {
-               auto f = fopen_boost (*servers, "r");
+               dcp::File f(*servers, "r");
                if (!f) {
                        cerr << "Could not open servers list file " << *servers << "\n";
                        exit (EXIT_FAILURE);
                }
                vector<string> servers;
-               while (!feof (f)) {
+               while (!f.eof()) {
                        char buffer[128];
-                       if (fscanf (f, "%s.127", buffer) == 1) {
+                       if (fscanf(f.get(), "%s.127", buffer) == 1) {
                                servers.push_back (buffer);
                        }
                }
-               fclose (f);
                Config::instance()->set_servers (servers);
        }
 
index 08e2721da35e49f448b3d2ccabd9de93dbea9f22..ae045d6365291c5ad52407f8bd0d842097fb5138 100644 (file)
 
 */
 
-#include "config_dialog.h"
-#include "static_text.h"
+
+#include "audio_mapping_view.h"
 #include "check_box.h"
-#include "nag_dialog.h"
+#include "config_dialog.h"
 #include "dcpomatic_button.h"
-#include "audio_mapping_view.h"
+#include "nag_dialog.h"
+#include "static_text.h"
+#include <dcp/file.h>
 #include <dcp/raw_convert.h>
 
 
@@ -462,14 +464,13 @@ CertificateChainEditor::export_certificate ()
                if (path.extension() != ".pem") {
                        path += ".pem";
                }
-               auto f = fopen_boost (path, "w");
+               dcp::File f(path, "w");
                if (!f) {
                        throw OpenFileError (path, errno, OpenFileError::WRITE);
                }
 
                string const s = j->certificate (true);
-               checked_fwrite (s.c_str(), s.length(), f, path);
-               fclose (f);
+               f.checked_write(s.c_str(), s.length());
        }
        d->Destroy ();
 }
@@ -487,14 +488,13 @@ CertificateChainEditor::export_chain ()
                if (path.extension() != ".pem") {
                        path += ".pem";
                }
-               auto f = fopen_boost (path, "w");
+               dcp::File f(path, "w");
                if (!f) {
                        throw OpenFileError (path, errno, OpenFileError::WRITE);
                }
 
                auto const s = _get()->chain();
-               checked_fwrite (s.c_str(), s.length(), f, path);
-               fclose (f);
+               f.checked_write (s.c_str(), s.length());
        }
 
        d->Destroy ();
@@ -616,14 +616,13 @@ CertificateChainEditor::export_private_key ()
                if (path.extension() != ".pem") {
                        path += ".pem";
                }
-               auto f = fopen_boost (path, "w");
+               dcp::File f(path, "w");
                if (!f) {
                        throw OpenFileError (path, errno, OpenFileError::WRITE);
                }
 
                auto const s = _get()->key().get ();
-               checked_fwrite (s.c_str(), s.length(), f, path);
-               fclose (f);
+               f.checked_write(s.c_str(), s.length());
        }
        d->Destroy ();
 }
@@ -733,17 +732,16 @@ KeysPage::export_decryption_chain_and_key ()
 
        if (d->ShowModal () == wxID_OK) {
                boost::filesystem::path path (wx_to_std(d->GetPath()));
-               auto f = fopen_boost (path, "w");
+               dcp::File f(path, "w");
                if (!f) {
                        throw OpenFileError (path, errno, OpenFileError::WRITE);
                }
 
                auto const chain = Config::instance()->decryption_chain()->chain();
-               checked_fwrite (chain.c_str(), chain.length(), f, path);
-               optional<string> const key = Config::instance()->decryption_chain()->key();
+               f.checked_write (chain.c_str(), chain.length());
+               auto const key = Config::instance()->decryption_chain()->key();
                DCPOMATIC_ASSERT (key);
-               checked_fwrite (key->c_str(), key->length(), f, path);
-               fclose (f);
+               f.checked_write(key->c_str(), key->length());
        }
        d->Destroy ();
 
@@ -768,15 +766,15 @@ KeysPage::import_decryption_chain_and_key ()
        if (d->ShowModal () == wxID_OK) {
                auto new_chain = make_shared<dcp::CertificateChain>();
 
-               FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "r");
+               dcp::File f(wx_to_std(d->GetPath()), "r");
                if (!f) {
-                       throw OpenFileError (wx_to_std (d->GetPath ()), errno, OpenFileError::WRITE);
+                       throw OpenFileError (f.path(), errno, OpenFileError::WRITE);
                }
 
                string current;
-               while (!feof (f)) {
+               while (!f.eof()) {
                        char buffer[128];
-                       if (fgets (buffer, 128, f) == 0) {
+                       if (f.gets(buffer, 128) == 0) {
                                break;
                        }
                        current += buffer;
@@ -788,7 +786,6 @@ KeysPage::import_decryption_chain_and_key ()
                                current = "";
                        }
                }
-               fclose (f);
 
                if (new_chain->chain_valid() && new_chain->private_key_valid()) {
                        Config::instance()->set_decryption_chain (new_chain);
@@ -833,14 +830,13 @@ KeysPage::export_decryption_certificate ()
                if (path.extension() != ".pem") {
                        path += ".pem";
                }
-               auto f = fopen_boost (path, "w");
+               dcp::File f(path, "w");
                if (!f) {
                        throw OpenFileError (path, errno, OpenFileError::WRITE);
                }
 
                auto const s = Config::instance()->decryption_chain()->leaf().certificate (true);
-               checked_fwrite (s.c_str(), s.length(), f, path);
-               fclose (f);
+               f.checked_write(s.c_str(), s.length());
        }
 
        d->Destroy ();
index 3a677bf820d034323761e322dc6e741481bbe5b2..336dfcdf38e5d58a87d47e1252154065f284ace1 100644 (file)
@@ -30,6 +30,7 @@
 #include "lib/audio_buffers.h"
 #include "lib/dcpomatic_time.h"
 #include "test.h"
+#include <dcp/file.h>
 #include <dcp/raw_convert.h>
 #include <boost/test/unit_test.hpp>
 #include <boost/bind/bind.hpp>
@@ -154,11 +155,11 @@ BOOST_AUTO_TEST_CASE (audio_merger_test3)
 /* Reply a sequence of calls to AudioMerger that resulted in a crash */
 BOOST_AUTO_TEST_CASE (audio_merger_test4)
 {
-       auto f = fopen_boost("test/data/audio_merger_bug1.log", "r");
+       dcp::File f("test/data/audio_merger_bug1.log", "r");
        BOOST_REQUIRE (f);
        list<string> tokens;
        char buf[64];
-       while (fscanf(f, "%63s", buf) == 1) {
+       while (fscanf(f.get(), "%63s", buf) == 1) {
                tokens.push_back (buf);
        }
 
index f34c295831db4dc8ee0b676770ccea7ba1ec6c18..56dc1974c5ba2f3f24f0e805119337118e0dcff3 100644 (file)
@@ -53,18 +53,18 @@ BOOST_AUTO_TEST_CASE (hash_added_to_imported_dcp_test)
        /* Remove <Hash> tags from the CPL */
        for (auto i: directory_iterator(String::compose("build/test/%1/%2", ov_name, ov->dcp_name()))) {
                if (boost::algorithm::starts_with(i.path().filename().string(), "cpl_")) {
-                       auto in = fopen_boost(i.path(), "r");
+                       dcp::File in(i.path(), "r");
                        BOOST_REQUIRE (in);
-                       auto out = fopen_boost(i.path().string() + ".tmp", "w");
+                       dcp::File out(i.path().string() + ".tmp", "w");
                        BOOST_REQUIRE (out);
                        char buffer[256];
-                       while (fgets(buffer, sizeof(buffer), in)) {
+                       while (in.gets(buffer, sizeof(buffer))) {
                                if (string(buffer).find("Hash") == string::npos) {
-                                       fputs (buffer, out);
+                                       out.puts(buffer);
                                }
                        }
-                       fclose (in);
-                       fclose (out);
+                       in.close();
+                       out.close();
                        rename (i.path().string() + ".tmp", i.path());
                }
        }
@@ -82,15 +82,14 @@ BOOST_AUTO_TEST_CASE (hash_added_to_imported_dcp_test)
        int hashes = 0;
        for (auto i: directory_iterator(String::compose("build/test/%1/%2", vf_name, vf->dcp_name()))) {
                if (boost::algorithm::starts_with(i.path().filename().string(), "cpl_")) {
-                       auto in = fopen_boost(i.path(), "r");
+                       dcp::File in(i.path(), "r");
                        BOOST_REQUIRE (in);
                        char buffer[256];
-                       while (fgets (buffer, sizeof(buffer), in)) {
+                       while (in.gets(buffer, sizeof(buffer))) {
                                if (string(buffer).find("Hash") != string::npos) {
                                        ++hashes;
                                }
                        }
-                       fclose (in);
                }
        }
        BOOST_CHECK_EQUAL (hashes, 2);
index 51374b274d74546faa5dc18e7f39f8ebda510c53..bc858192dc6f33876a82adc61603d81677727c5c 100644 (file)
@@ -200,16 +200,16 @@ BOOST_AUTO_TEST_CASE (hint_closed_caption_xml_too_big)
 
        auto film = new_test_film2 (name);
 
-       auto ccap = fopen_boost (String::compose("build/test/%1.srt", name), "w");
+       dcp::File ccap(String::compose("build/test/%1.srt", name), "w");
        BOOST_REQUIRE (ccap);
        for (int i = 0; i < 2048; ++i) {
-               fprintf(ccap, "%d\n", i + 1);
+               fprintf(ccap.get(), "%d\n", i + 1);
                int second = i * 2;
                int minute = second % 60;
-               fprintf(ccap, "00:%02d:%02d,000 --> 00:%02d:%02d,000\n", minute, second, minute, second + 1);
-               fprintf(ccap, "Here are some closed captions.\n\n");
+               fprintf(ccap.get(), "00:%02d:%02d,000 --> 00:%02d:%02d,000\n", minute, second, minute, second + 1);
+               fprintf(ccap.get(), "Here are some closed captions.\n\n");
        }
-       fclose (ccap);
+       ccap.close();
 
        auto content = content_factory("build/test/" + name + ".srt").front();
        content->text.front()->set_type (TextType::CLOSED_CAPTION);
index 21f27c36c31fbc28596a060d4f661c5aa8eab218..9260d568facce6a738b78f22bb182e18f4c5cd11 100644 (file)
@@ -462,9 +462,9 @@ check_file (boost::filesystem::path ref, boost::filesystem::path check)
 {
        auto N = boost::filesystem::file_size (ref);
        BOOST_CHECK_EQUAL (N, boost::filesystem::file_size (check));
-       auto ref_file = fopen_boost (ref, "rb");
+       dcp::File ref_file(ref, "rb");
        BOOST_CHECK (ref_file);
-       auto check_file = fopen_boost (check, "rb");
+       dcp::File check_file(check, "rb");
        BOOST_CHECK (check_file);
 
        int const buffer_size = 65536;
@@ -475,30 +475,27 @@ check_file (boost::filesystem::path ref, boost::filesystem::path check)
 
        while (N) {
                uintmax_t this_time = min (uintmax_t (buffer_size), N);
-               size_t r = fread (ref_buffer.data(), 1, this_time, ref_file);
+               size_t r = ref_file.read (ref_buffer.data(), 1, this_time);
                BOOST_CHECK_EQUAL (r, this_time);
-               r = fread (check_buffer.data(), 1, this_time, check_file);
+               r = check_file.read(check_buffer.data(), 1, this_time);
                BOOST_CHECK_EQUAL (r, this_time);
 
-               BOOST_CHECK_MESSAGE (memcmp(ref_buffer.data(), check_buffer.data(), this_time) == 0, error);
-               if (memcmp(ref_buffer.data(), check_buffer.data(), this_time)) {
+               BOOST_CHECK_MESSAGE (memcmp (ref_buffer.data(), check_buffer.data(), this_time) == 0, error);
+               if (memcmp (ref_buffer.data(), check_buffer.data(), this_time)) {
                        break;
                }
 
                N -= this_time;
        }
-
-       fclose (ref_file);
-       fclose (check_file);
 }
 
 
 void
 check_text_file (boost::filesystem::path ref, boost::filesystem::path check)
 {
-       auto ref_file = fopen_boost (ref, "r");
+       dcp::File ref_file(ref, "r");
        BOOST_CHECK (ref_file);
-       auto check_file = fopen_boost (check, "r");
+       dcp::File check_file(check, "r");
        BOOST_CHECK (check_file);
 
        int const buffer_size = std::max(
@@ -509,16 +506,13 @@ check_text_file (boost::filesystem::path ref, boost::filesystem::path check)
        DCPOMATIC_ASSERT (buffer_size < 1024 * 1024);
 
        std::vector<uint8_t> ref_buffer(buffer_size);
-       auto ref_read = fread(ref_buffer.data(), 1, buffer_size, ref_file);
+       auto ref_read = ref_file.read(ref_buffer.data(), 1, buffer_size);
        std::vector<uint8_t> check_buffer(buffer_size);
-       auto check_read = fread(check_buffer.data(), 1, buffer_size, check_file);
+       auto check_read = check_file.read(check_buffer.data(), 1, buffer_size);
        BOOST_CHECK_EQUAL (ref_read, check_read);
 
        string const error = "File " + check.string() + " differs from reference " + ref.string();
        BOOST_CHECK_MESSAGE(memcmp(ref_buffer.data(), check_buffer.data(), ref_read) == 0, error);
-
-       fclose (ref_file);
-       fclose (check_file);
 }
 
 
@@ -827,13 +821,12 @@ subtitle_file (shared_ptr<Film> film)
 void
 make_random_file (boost::filesystem::path path, size_t size)
 {
-       auto t = fopen_boost(path, "wb");
+       dcp::File t(path, "wb");
        BOOST_REQUIRE (t);
        for (size_t i = 0; i < size; ++i) {
                uint8_t r = rand() & 0xff;
-               fwrite (&r, 1, 1, t);
+               t.write(&r, 1, 1);
        }
-       fclose (t);
 }
 
 
diff --git a/test/windows_test.cc b/test/windows_test.cc
deleted file mode 100644 (file)
index bc9520b..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
-    Copyright (C) 2021 Carl Hetherington <cth@carlh.net>
-
-    This file is part of DCP-o-matic.
-
-    DCP-o-matic 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.
-
-    DCP-o-matic 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 DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-
-#include "lib/cross.h"
-#include "lib/util.h"
-#include <boost/filesystem.hpp>
-#include <boost/test/unit_test.hpp>
-#include <iostream>
-
-
-BOOST_AUTO_TEST_CASE (fix_long_path_test)
-{
-#ifdef DCPOMATIC_WINDOWS
-       BOOST_CHECK_EQUAL (fix_long_path("c:\\foo"), "\\\\?\\c:\\foo");
-       BOOST_CHECK_EQUAL (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 (fix_long_path("bar"), fixed_bar);
-
-       BOOST_CHECK_EQUAL (fix_long_path("\\\\?\\c:\\foo"), "\\\\?\\c:\\foo");
-#else
-       BOOST_CHECK_EQUAL (fix_long_path("foo/bar/baz"), "foo/bar/baz");
-#endif
-}
-
-
-#ifdef DCPOMATIC_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 = fix_long_path(too_long);
-       create_directories (fixed_path, ec);
-       BOOST_CHECK (!ec);
-
-       auto file = fopen_boost(too_long / "hello", "w");
-       BOOST_REQUIRE (file);
-       fprintf (file, "Hello_world");
-       fclose (file);
-
-       file = fopen_boost(too_long / "hello", "r");
-       BOOST_REQUIRE (file);
-       char buffer[64];
-       fscanf (file, "%63s", buffer);
-       BOOST_CHECK_EQUAL (strcmp(buffer, "Hello_world"), 0);
-}
-#endif
-
index 1555f2f59cd019dc3140a388a0ba2256a3cf5965..3aa803a0c396d5f6e3365d1e945b05d84c8a5a24 100644 (file)
@@ -151,7 +151,6 @@ def build(bld):
                  video_level_test.cc
                  video_mxf_content_test.cc
                  vf_kdm_test.cc
-                 windows_test.cc
                  writer_test.cc
                  zipper_test.cc
                  """