# 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
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) {
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.
#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 ();
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 ();
#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 ()
{
}
-boost::filesystem::path
-fix_long_path (boost::filesystem::path path)
-{
- return path;
-}
-
-
bool
show_in_file_manager (boost::filesystem::path dir, boost::filesystem::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 ()
{
}
-boost::filesystem::path
-fix_long_path (boost::filesystem::path path)
-{
- return path;
-}
-
-
bool
show_in_file_manager (boost::filesystem::path, boost::filesystem::path select)
{
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;
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);
#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 ()
{
#include "config.h"
#include "cross.h"
#include "compose.hpp"
+#include "dcpomatic_assert.h"
#include <iostream>
#include "i18n.h"
CurlUploader::~CurlUploader ()
{
- if (_file) {
- fclose (_file);
- }
curl_easy_cleanup (_curl);
}
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;
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) {
#include "uploader.h"
+#include <dcp/file.h>
#include <curl/curl.h>
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)) {
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);
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);
}
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);
}
}
}
- fclose (in);
ext4_fclose (&out);
set_timestamps_to_now (to);
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;
}
-/** 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)
{
}
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);
}
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;
int
FileGroup::read (uint8_t* buffer, int amount) const
{
+ DCPOMATIC_ASSERT (_current_file);
+
int read = 0;
while (true) {
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;
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) {
break;
}
- if (ferror(_current_file)) {
+ if (_current_file->error()) {
throw FileError (String::compose("fread error %1", errno), _paths[_current_path]);
}
#define DCPOMATIC_FILE_GROUP_H
+#include <dcp/file.h>
#include <boost/filesystem.hpp>
+#include <boost/optional.hpp>
#include <vector>
FileGroup ();
explicit FileGroup (boost::filesystem::path);
explicit FileGroup (std::vector<boost::filesystem::path> const &);
- ~FileGroup ();
FileGroup (FileGroup const&) = delete;
FileGroup& operator= (FileGroup const&) = delete;
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;
};
#include "file_log.h"
#include "cross.h"
#include "config.h"
+#include <dcp/file.h>
#include <cstdio>
#include <iostream>
#include <cerrno>
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());
}
tail_amount = 0;
}
- auto f = fopen_boost (_file, "r");
+ dcp::File f(_file, "r");
if (!f) {
return "";
}
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;
}
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) {
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
#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>
{
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;
}
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,
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) {
#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>
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) {
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);
if (e) {
return e;
}
- return load (temp.file(), url);
+ return load (temp.path(), url);
}
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;
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);
}
#include "screen.h"
#include "util.h"
#include "zipper.h"
+#include <dcp/file.h>
#include "i18n.h"
/* 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;
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());
}
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;
}
/* 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;
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()) {
LOG_GENERAL ("Proceeding with first nonexistant frame %1", first_nonexistant_frame);
- fclose (asset_file);
-
return first_nonexistant_frame;
}
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);
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);
#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;
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;
*/
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);
}
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;
}
+
*/
+#include <dcp/file.h>
#include <boost/filesystem.hpp>
+#include <boost/optional.hpp>
#include <cstdio>
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;
};
#include "config.h"
#include "cross.h"
#include "compose.hpp"
+#include <dcp/file.h>
+#include <dcp/warnings.h>
#include <sys/stat.h>
#include "i18n.h"
/* 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));
}
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;
_set_progress ((double) transferred / total_size);
}
}
-
- fclose (f);
}
*/
-#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();
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 */
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;
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;
}
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;
}
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)
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);
}
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);
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);
}
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());
}
}
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);
}
*/
-#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>
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 ();
}
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 ();
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 ();
}
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 ();
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;
current = "";
}
}
- fclose (f);
if (new_chain->chain_valid() && new_chain->private_key_valid()) {
Config::instance()->set_decryption_chain (new_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 = 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 ();
#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>
/* 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);
}
/* 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());
}
}
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);
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);
{
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;
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(
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);
}
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);
}
+++ /dev/null
-/*
- 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
-
video_level_test.cc
video_mxf_content_test.cc
vf_kdm_test.cc
- windows_test.cc
writer_test.cc
zipper_test.cc
"""