diff options
| author | Carl Hetherington <cth@carlh.net> | 2022-04-16 22:20:54 +0200 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2022-05-05 23:38:41 +0200 |
| commit | 8a8c977c12fc65f1f50ea05099387e0fc8840e7d (patch) | |
| tree | 2d2c8663652939d643779d1ab1c18a12813fcbd2 /src/lib | |
| parent | efe153ab23b54cdbf28c653f2ccb0f25ca6bd015 (diff) | |
Use dcp::File in DCP-o-matic (#2231).
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/config.cc | 15 | ||||
| -rw-r--r-- | src/lib/cross.h | 3 | ||||
| -rw-r--r-- | src/lib/cross_linux.cc | 25 | ||||
| -rw-r--r-- | src/lib/cross_osx.cc | 25 | ||||
| -rw-r--r-- | src/lib/cross_windows.cc | 64 | ||||
| -rw-r--r-- | src/lib/curl_uploader.cc | 15 | ||||
| -rw-r--r-- | src/lib/curl_uploader.h | 1 | ||||
| -rw-r--r-- | src/lib/ext.cc | 12 | ||||
| -rw-r--r-- | src/lib/file_group.cc | 33 | ||||
| -rw-r--r-- | src/lib/file_group.h | 5 | ||||
| -rw-r--r-- | src/lib/file_log.cc | 18 | ||||
| -rw-r--r-- | src/lib/film.cc | 31 | ||||
| -rw-r--r-- | src/lib/film.h | 12 | ||||
| -rw-r--r-- | src/lib/image_examiner.cc | 6 | ||||
| -rw-r--r-- | src/lib/internet.cc | 27 | ||||
| -rw-r--r-- | src/lib/kdm_with_metadata.cc | 3 | ||||
| -rw-r--r-- | src/lib/reel_writer.cc | 31 | ||||
| -rw-r--r-- | src/lib/reel_writer.h | 5 | ||||
| -rw-r--r-- | src/lib/scoped_temporary.cc | 34 | ||||
| -rw-r--r-- | src/lib/scoped_temporary.h | 15 | ||||
| -rw-r--r-- | src/lib/scp_uploader.cc | 12 | ||||
| -rw-r--r-- | src/lib/string_text_file.cc | 22 | ||||
| -rw-r--r-- | src/lib/util.cc | 73 | ||||
| -rw-r--r-- | src/lib/util.h | 2 | ||||
| -rw-r--r-- | src/lib/writer.cc | 5 |
25 files changed, 142 insertions, 352 deletions
diff --git a/src/lib/config.cc b/src/lib/config.cc index b46093726..3661d8ba5 100644 --- a/src/lib/config.cc +++ b/src/lib/config.cc @@ -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. diff --git a/src/lib/cross.h b/src/lib/cross.h index 83cda4a04..b79f7ebdf 100644 --- a/src/lib/cross.h +++ b/src/lib/cross.h @@ -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 (); diff --git a/src/lib/cross_linux.cc b/src/lib/cross_linux.cc index d7d1089fc..89a9c5bb6 100644 --- a/src/lib/cross_linux.cc +++ b/src/lib/cross_linux.cc @@ -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) { diff --git a/src/lib/cross_osx.cc b/src/lib/cross_osx.cc index 02f720fee..b214b6359 100644 --- a/src/lib/cross_osx.cc +++ b/src/lib/cross_osx.cc @@ -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) { diff --git a/src/lib/cross_windows.cc b/src/lib/cross_windows.cc index f76380836..12fb5efa0 100644 --- a/src/lib/cross_windows.cc +++ b/src/lib/cross_windows.cc @@ -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 () { diff --git a/src/lib/curl_uploader.cc b/src/lib/curl_uploader.cc index 60835bea7..6fe7aba14 100644 --- a/src/lib/curl_uploader.cc +++ b/src/lib/curl_uploader.cc @@ -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) { diff --git a/src/lib/curl_uploader.h b/src/lib/curl_uploader.h index 564e77493..ea017eb83 100644 --- a/src/lib/curl_uploader.h +++ b/src/lib/curl_uploader.h @@ -20,6 +20,7 @@ #include "uploader.h" +#include <dcp/file.h> #include <curl/curl.h> diff --git a/src/lib/ext.cc b/src/lib/ext.cc index 1af6c137b..7853984cf 100644 --- a/src/lib/ext.cc +++ b/src/lib/ext.cc @@ -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; diff --git a/src/lib/file_group.cc b/src/lib/file_group.cc index 7dae1da92..71faacc4c 100644 --- a/src/lib/file_group.cc +++ b/src/lib/file_group.cc @@ -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]); } diff --git a/src/lib/file_group.h b/src/lib/file_group.h index 9521da7ec..693bf89ba 100644 --- a/src/lib/file_group.h +++ b/src/lib/file_group.h @@ -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; }; diff --git a/src/lib/file_log.cc b/src/lib/file_log.cc index a9522bad5..adb06b7f0 100644 --- a/src/lib/file_log.cc +++ b/src/lib/file_log.cc @@ -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; } diff --git a/src/lib/film.cc b/src/lib/film.cc index e49b7f78e..54267bc56 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -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 diff --git a/src/lib/film.h b/src/lib/film.h index d42eb5626..5318d6a12 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -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, diff --git a/src/lib/image_examiner.cc b/src/lib/image_examiner.cc index 5a1672204..6e4dea7b7 100644 --- a/src/lib/image_examiner.cc +++ b/src/lib/image_examiner.cc @@ -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) { diff --git a/src/lib/internet.cc b/src/lib/internet.cc index c0c8232ee..a9c30611d 100644 --- a/src/lib/internet.cc +++ b/src/lib/internet.cc @@ -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); } diff --git a/src/lib/kdm_with_metadata.cc b/src/lib/kdm_with_metadata.cc index 857fdca2c..123649d12 100644 --- a/src/lib/kdm_with_metadata.cc +++ b/src/lib/kdm_with_metadata.cc @@ -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; diff --git a/src/lib/reel_writer.cc b/src/lib/reel_writer.cc index 7a2c9c670..94920b95b 100644 --- a/src/lib/reel_writer.cc +++ b/src/lib/reel_writer.cc @@ -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); diff --git a/src/lib/reel_writer.h b/src/lib/reel_writer.h index 0308c64ec..bee76ded3 100644 --- a/src/lib/reel_writer.h +++ b/src/lib/reel_writer.h @@ -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; diff --git a/src/lib/scoped_temporary.cc b/src/lib/scoped_temporary.cc index 223100ba5..0ead7b165 100644 --- a/src/lib/scoped_temporary.cc +++ b/src/lib/scoped_temporary.cc @@ -29,16 +29,18 @@ */ 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; } + diff --git a/src/lib/scoped_temporary.h b/src/lib/scoped_temporary.h index 75d9a272f..b78f60541 100644 --- a/src/lib/scoped_temporary.h +++ b/src/lib/scoped_temporary.h @@ -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; }; diff --git a/src/lib/scp_uploader.cc b/src/lib/scp_uploader.cc index 8bb41e3b1..c14c02215 100644 --- a/src/lib/scp_uploader.cc +++ b/src/lib/scp_uploader.cc @@ -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); } diff --git a/src/lib/string_text_file.cc b/src/lib/string_text_file.cc index 8c2c56518..b8ca27e16 100644 --- a/src/lib/string_text_file.cc +++ b/src/lib/string_text_file.cc @@ -18,29 +18,33 @@ */ -#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 */ diff --git a/src/lib/util.cc b/src/lib/util.cc index 6e2a1ad64..d020ba13d 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -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); } diff --git a/src/lib/util.h b/src/lib/util.h index 706056cda..233b3cb2a 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -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); diff --git a/src/lib/writer.cc b/src/lib/writer.cc index 309cfb78c..3aca2ab89 100644 --- a/src/lib/writer.cc +++ b/src/lib/writer.cc @@ -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()); } |
