From a8a59860461c9e7661534c5643a1ce082f527219 Mon Sep 17 00:00:00 2001 From: arvidn Date: Thu, 3 Aug 2017 02:31:03 -0700 Subject: [PATCH] make file attributes (in file_storage) type safe --- bindings/python/src/converters.cpp | 3 + bindings/python/src/create_torrent.cpp | 30 ++-- examples/dump_torrent.cpp | 2 +- include/libtorrent/file_storage.hpp | 72 ++++---- src/create_torrent.cpp | 227 ++++++++++++------------- src/file_storage.cpp | 38 +++-- src/torrent_info.cpp | 12 +- test/test_torrent_info.cpp | 6 +- 8 files changed, 200 insertions(+), 190 deletions(-) diff --git a/bindings/python/src/converters.cpp b/bindings/python/src/converters.cpp index 72630a2dd..dac4ffdc5 100644 --- a/bindings/python/src/converters.cpp +++ b/bindings/python/src/converters.cpp @@ -16,6 +16,7 @@ #include "libtorrent/peer_info.hpp" #include "libtorrent/alert_types.hpp" // for picker_flags_t #include "libtorrent/session_types.hpp" // for save_state_flags_t +#include "libtorrent/file_storage.hpp" // for file_flags_t #include "libtorrent/alert.hpp" #include @@ -312,6 +313,7 @@ void bind_converters() to_python_converter>(); to_python_converter>(); to_python_converter>(); + to_python_converter>(); // work-around types to_python_converter, address_to_tuple< @@ -369,4 +371,5 @@ void bind_converters() to_bitfield_flag(); to_bitfield_flag(); to_bitfield_flag(); + to_bitfield_flag(); } diff --git a/bindings/python/src/create_torrent.cpp b/bindings/python/src/create_torrent.cpp index b35f67b2f..8ee0412a0 100644 --- a/bindings/python/src/create_torrent.cpp +++ b/bindings/python/src/create_torrent.cpp @@ -102,7 +102,7 @@ namespace { return FileIter(self, self.end_file()); } void add_file_wstring(file_storage& fs, std::wstring const& file, std::int64_t size - , int flags, std::time_t md, std::string link) + , file_flags_t const flags, std::time_t md, std::string link) { fs.add_file(file, size, flags, md, link); } @@ -115,7 +115,7 @@ namespace } void add_file(file_storage& fs, std::string const& file, std::int64_t size - , int flags, std::time_t md, std::string link) + , file_flags_t const flags, std::time_t md, std::string link) { fs.add_file(file, size, flags, md, link); } @@ -124,6 +124,8 @@ namespace { ct.add_tracker(url, tier); } + + struct dummy13 {}; } void bind_create_torrent() @@ -145,14 +147,15 @@ void bind_create_torrent() std::string (file_storage::*file_storage_file_path)(file_index_t, std::string const&) const = &file_storage::file_path; std::int64_t (file_storage::*file_storage_file_size)(file_index_t) const = &file_storage::file_size; std::int64_t (file_storage::*file_storage_file_offset)(file_index_t) const = &file_storage::file_offset; - std::uint32_t (file_storage::*file_storage_file_flags)(file_index_t) const = &file_storage::file_flags; + file_flags_t (file_storage::*file_storage_file_flags)(file_index_t) const = &file_storage::file_flags; #ifndef TORRENT_NO_DEPRECATE file_entry (file_storage::*at)(int) const = &file_storage::at; #endif // TODO: 3 move this to its own file - class_("file_storage") + { + scope s = class_("file_storage") .def("is_valid", &file_storage::is_valid) .def("add_file", add_file, (arg("path"), arg("size"), arg("flags") = 0, arg("mtime") = 0, arg("linkpath") = "")) .def("num_files", &file_storage::num_files) @@ -185,12 +188,19 @@ void bind_create_torrent() .def("name", &file_storage::name, return_value_policy()) ; - enum_("file_flags_t") - .value("flag_pad_file", file_storage::flag_pad_file) - .value("flag_hidden", file_storage::flag_hidden) - .value("flag_executable", file_storage::flag_executable) - .value("flag_symlink", file_storage::flag_symlink) - ; + s.attr("flag_pad_file") = file_storage::flag_pad_file; + s.attr("flag_hidden") = file_storage::flag_hidden; + s.attr("flag_executable") = file_storage::flag_executable; + s.attr("flag_symlink") = file_storage::flag_symlink; + } + + { + scope s = class_("file_flags_t"); + s.attr("flag_pad_file") = file_storage::flag_pad_file; + s.attr("flag_hidden") = file_storage::flag_hidden; + s.attr("flag_executable") = file_storage::flag_executable; + s.attr("flag_symlink") = file_storage::flag_symlink; + } class_("create_torrent", no_init) .def(init()) diff --git a/examples/dump_torrent.cpp b/examples/dump_torrent.cpp index d8a6fec84..37f6eb329 100644 --- a/examples/dump_torrent.cpp +++ b/examples/dump_torrent.cpp @@ -190,7 +190,7 @@ int main(int argc, char* argv[]) { piece_index_t const first = st.map_file(i, 0, 0).piece; piece_index_t const last = st.map_file(i, (std::max)(std::int64_t(st.file_size(i))-1, std::int64_t(0)), 0).piece; - int const flags = st.file_flags(i); + auto const flags = st.file_flags(i); std::stringstream file_hash; if (!st.hash(i).is_all_zeros()) file_hash << st.hash(i); diff --git a/include/libtorrent/file_storage.hpp b/include/libtorrent/file_storage.hpp index 1df95dfa5..47b68e47c 100644 --- a/include/libtorrent/file_storage.hpp +++ b/include/libtorrent/file_storage.hpp @@ -46,6 +46,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/string_view.hpp" #include "libtorrent/aux_/vector.hpp" #include "libtorrent/aux_/noexcept_movable.hpp" +#include "libtorrent/flags.hpp" namespace libtorrent { @@ -192,6 +193,10 @@ namespace libtorrent { std::int64_t size; }; + // hidden + struct file_flags_tag; + using file_flags_t = flags::bitfield_flag; + // The ``file_storage`` class represents a file list and the piece // size. Everything necessary to interpret a regular bittorrent storage // file structure. @@ -214,25 +219,12 @@ namespace libtorrent { // not. bool is_valid() const { return m_piece_length > 0; } - // file attribute flags - enum flags_t - { - // the file is a pad file. It's required to contain zeros - // at it will not be saved to disk. Its purpose is to make - // the following file start on a piece boundary. - pad_file = 1, - - // this file has the hidden attribute set. This is primarily - // a windows attribute - attribute_hidden = 2, - - // this file has the executable attribute set. - attribute_executable = 4, - - // this file is a symbolic link. It should have a link - // target string associated with it. - attribute_symlink = 8 - }; +#ifndef TORRENT_NO_DEPRECATE + static constexpr file_flags_t TORRENT_DEPRECATED_MEMBER pad_file = 0_bit; + static constexpr file_flags_t TORRENT_DEPRECATED_MEMBER attribute_hidden = 1_bit; + static constexpr file_flags_t TORRENT_DEPRECATED_MEMBER attribute_executable = 2_bit; + static constexpr file_flags_t TORRENT_DEPRECATED_MEMBER attribute_symlink = 3_bit; +#endif // allocates space for ``num_files`` in the internal file list. This can // be used to avoid reallocating the internal file list when the number @@ -278,9 +270,10 @@ namespace libtorrent { // can be changed by calling ``set_name``. void add_file_borrow(char const* filename, int filename_len , std::string const& path, std::int64_t file_size - , std::uint32_t file_flags = 0, char const* filehash = 0 + , file_flags_t file_flags = {}, char const* filehash = 0 , std::int64_t mtime = 0, string_view symlink_path = string_view()); - void add_file(std::string const& path, std::int64_t file_size, std::uint32_t file_flags = 0 + void add_file(std::string const& path, std::int64_t file_size + , file_flags_t file_flags = {} , std::time_t mtime = 0, string_view symlink_path = string_view()); // renames the file at ``index`` to ``new_filename``. Keep in mind @@ -295,7 +288,8 @@ namespace libtorrent { // instead, use the wchar -> utf8 conversion functions // and pass in utf8 strings TORRENT_DEPRECATED - void add_file(std::wstring const& p, std::int64_t size, std::uint32_t flags = 0 + void add_file(std::wstring const& p, std::int64_t size + , file_flags_t flags = {} , std::time_t mtime = 0, string_view s_p = ""); TORRENT_DEPRECATED void rename_file(file_index_t index, std::wstring const& new_filename); @@ -477,35 +471,27 @@ namespace libtorrent { // the set. void all_path_hashes(std::unordered_set& table) const; - // flags indicating various attributes for files in - // a file_storage. - enum file_flags_t : std::uint32_t - { - // this file is a pad file. The creator of the - // torrent promises the file is entirely filled with - // zeros and does not need to be downloaded. The - // purpose is just to align the next file to either - // a block or piece boundary. - flag_pad_file = 1, + // the file is a pad file. It's required to contain zeros + // at it will not be saved to disk. Its purpose is to make + // the following file start on a piece boundary. + static constexpr file_flags_t flag_pad_file = 0_bit; - // this file is hidden (sets the hidden attribute - // on windows) - flag_hidden = 2, + // this file has the hidden attribute set. This is primarily + // a windows attribute + static constexpr file_flags_t flag_hidden = 1_bit; - // this file is executable (sets the executable bit - // on posix like systems) - flag_executable = 4, + // this file has the executable attribute set. + static constexpr file_flags_t flag_executable = 2_bit; - // this file is a symlink. The symlink target is - // specified in a separate field - flag_symlink = 8 - }; + // this file is a symbolic link. It should have a link + // target string associated with it. + static constexpr file_flags_t flag_symlink = 3_bit; std::vector const& paths() const { return m_paths; } // returns a bitmask of flags from file_flags_t that apply // to file at ``index``. - std::uint32_t file_flags(file_index_t index) const; + file_flags_t file_flags(file_index_t index) const; // returns true if the file at the specified index has been renamed to // have an absolute path, i.e. is not anchored in the save path of the diff --git a/src/create_torrent.cpp b/src/create_torrent.cpp index 5f5eea226..c8c85c0ad 100644 --- a/src/create_torrent.cpp +++ b/src/create_torrent.cpp @@ -50,148 +50,147 @@ POSSIBILITY OF SUCH DAMAGE. using namespace std::placeholders; namespace libtorrent { +namespace { - namespace { + bool default_pred(std::string const&) { return true; } - inline bool default_pred(std::string const&) { return true; } + bool ignore_subdir(std::string const& leaf) + { return leaf == ".." || leaf == "."; } - inline bool ignore_subdir(std::string const& leaf) - { return leaf == ".." || leaf == "."; } - - std::uint32_t get_file_attributes(std::string const& p) - { + file_flags_t get_file_attributes(std::string const& p) + { #ifdef TORRENT_WINDOWS - WIN32_FILE_ATTRIBUTE_DATA attr; - std::wstring path = convert_to_wstring(p); - GetFileAttributesExW(path.c_str(), GetFileExInfoStandard, &attr); - if (attr.dwFileAttributes == INVALID_FILE_ATTRIBUTES) return 0; - if (attr.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) return file_storage::attribute_hidden; - return 0; + WIN32_FILE_ATTRIBUTE_DATA attr; + std::wstring path = convert_to_wstring(p); + GetFileAttributesExW(path.c_str(), GetFileExInfoStandard, &attr); + if (attr.dwFileAttributes == INVALID_FILE_ATTRIBUTES) return {}; + if (attr.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) return file_storage::flag_hidden; + return {}; #else - struct ::stat s; - if (::lstat(convert_to_native(p).c_str(), &s) < 0) return 0; - std::uint32_t file_attr = 0; - if (s.st_mode & S_IXUSR) - file_attr += file_storage::attribute_executable; - if (S_ISLNK(s.st_mode)) - file_attr += file_storage::attribute_symlink; - return file_attr; + struct ::stat s; + if (::lstat(convert_to_native(p).c_str(), &s) < 0) return {}; + file_flags_t file_attr = {}; + if (s.st_mode & S_IXUSR) + file_attr |= file_storage::flag_executable; + if (S_ISLNK(s.st_mode)) + file_attr |= file_storage::flag_symlink; + return file_attr; #endif - } + } #ifndef TORRENT_WINDOWS - std::string get_symlink_path_impl(char const* path) - { - constexpr int MAX_SYMLINK_PATH = 200; + std::string get_symlink_path_impl(char const* path) + { + constexpr int MAX_SYMLINK_PATH = 200; - char buf[MAX_SYMLINK_PATH]; - std::string f = convert_to_native(path); - int char_read = int(readlink(f.c_str(), buf, MAX_SYMLINK_PATH)); - if (char_read < 0) return ""; - if (char_read < MAX_SYMLINK_PATH) buf[char_read] = 0; - else buf[0] = 0; - return convert_from_native(buf); - } + char buf[MAX_SYMLINK_PATH]; + std::string f = convert_to_native(path); + int char_read = int(readlink(f.c_str(), buf, MAX_SYMLINK_PATH)); + if (char_read < 0) return ""; + if (char_read < MAX_SYMLINK_PATH) buf[char_read] = 0; + else buf[0] = 0; + return convert_from_native(buf); + } #endif - std::string get_symlink_path(std::string const& p) - { + std::string get_symlink_path(std::string const& p) + { #if defined TORRENT_WINDOWS - TORRENT_UNUSED(p); - return ""; + TORRENT_UNUSED(p); + return ""; #else - return get_symlink_path_impl(p.c_str()); + return get_symlink_path_impl(p.c_str()); #endif - } + } - void add_files_impl(file_storage& fs, std::string const& p - , std::string const& l, std::function pred - , std::uint32_t const flags) - { - std::string f = combine_path(p, l); - if (!pred(f)) return; - error_code ec; - file_status s; - stat_file(f, &s, ec, (flags & create_torrent::symlinks) ? dont_follow_links : 0); - if (ec) return; + void add_files_impl(file_storage& fs, std::string const& p + , std::string const& l, std::function pred + , std::uint32_t const flags) + { + std::string f = combine_path(p, l); + if (!pred(f)) return; + error_code ec; + file_status s; + stat_file(f, &s, ec, (flags & create_torrent::symlinks) ? dont_follow_links : 0); + if (ec) return; - // recurse into directories - bool recurse = (s.mode & file_status::directory) != 0; + // recurse into directories + bool recurse = (s.mode & file_status::directory) != 0; - // if the file is not a link or we're following links, and it's a directory - // only then should we recurse + // if the file is not a link or we're following links, and it's a directory + // only then should we recurse #ifndef TORRENT_WINDOWS - if ((s.mode & file_status::link) && (flags & create_torrent::symlinks)) - recurse = false; + if ((s.mode & file_status::link) && (flags & create_torrent::symlinks)) + recurse = false; #endif - if (recurse) + if (recurse) + { + for (directory i(f, ec); !i.done(); i.next(ec)) { - for (directory i(f, ec); !i.done(); i.next(ec)) - { - std::string leaf = i.file(); - if (ignore_subdir(leaf)) continue; - add_files_impl(fs, p, combine_path(l, leaf), pred, flags); - } + std::string leaf = i.file(); + if (ignore_subdir(leaf)) continue; + add_files_impl(fs, p, combine_path(l, leaf), pred, flags); + } + } + else + { + // #error use the fields from s + file_flags_t const file_flags = get_file_attributes(f); + + // mask all bits to check if the file is a symlink + if ((file_flags & file_storage::flag_symlink) + && (flags & create_torrent::symlinks)) + { + std::string sym_path = get_symlink_path(f); + fs.add_file(l, 0, file_flags, std::time_t(s.mtime), sym_path); } else { - // #error use the fields from s - std::uint32_t file_flags = get_file_attributes(f); - - // mask all bits to check if the file is a symlink - if ((file_flags & file_storage::attribute_symlink) - && (flags & create_torrent::symlinks)) - { - std::string sym_path = get_symlink_path(f); - fs.add_file(l, 0, file_flags, std::time_t(s.mtime), sym_path); - } - else - { - fs.add_file(l, s.file_size, file_flags, std::time_t(s.mtime)); - } + fs.add_file(l, s.file_size, file_flags, std::time_t(s.mtime)); } } + } - struct hash_state - { - create_torrent& ct; - storage_holder storage; - disk_io_thread& iothread; - piece_index_t piece_counter; - piece_index_t completed_piece; - std::function const& f; - error_code& ec; - }; + struct hash_state + { + create_torrent& ct; + storage_holder storage; + disk_io_thread& iothread; + piece_index_t piece_counter; + piece_index_t completed_piece; + std::function const& f; + error_code& ec; + }; - void on_hash(piece_index_t const piece, sha1_hash const& piece_hash - , storage_error const& error, hash_state* st) + void on_hash(piece_index_t const piece, sha1_hash const& piece_hash + , storage_error const& error, hash_state* st) + { + if (error) { - if (error) - { - // on error - st->ec = error.ec; - st->iothread.abort(true); - return; - } - st->ct.set_hash(piece, piece_hash); - st->f(st->completed_piece); - ++st->completed_piece; - if (st->piece_counter < st->ct.files().end_piece()) - { - st->iothread.async_hash(st->storage, st->piece_counter - , disk_interface::sequential_access - , std::bind(&on_hash, _1, _2, _3, st)); - ++st->piece_counter; - } - else - { - st->iothread.abort(true); - } - st->iothread.submit_jobs(); + // on error + st->ec = error.ec; + st->iothread.abort(true); + return; } + st->ct.set_hash(piece, piece_hash); + st->f(st->completed_piece); + ++st->completed_piece; + if (st->piece_counter < st->ct.files().end_piece()) + { + st->iothread.async_hash(st->storage, st->piece_counter + , disk_interface::sequential_access + , std::bind(&on_hash, _1, _2, _3, st)); + ++st->piece_counter; + } + else + { + st->iothread.abort(true); + } + st->iothread.submit_jobs(); + } - } // anonymous namespace +} // anonymous namespace #ifndef TORRENT_NO_DEPRECATE @@ -526,7 +525,7 @@ namespace libtorrent { file_index_t const first(0); if (m_include_mtime) info["mtime"] = m_files.mtime(first); info["length"] = m_files.file_size(first); - std::uint32_t const flags = m_files.file_flags(first); + file_flags_t const flags = m_files.file_flags(first); if (flags & (file_storage::flag_pad_file | file_storage::flag_hidden | file_storage::flag_executable @@ -577,8 +576,8 @@ namespace libtorrent { path_e.list().push_back(entry(e)); } - std::uint32_t const flags = m_files.file_flags(i); - if (flags != 0) + file_flags_t const flags = m_files.file_flags(i); + if (flags) { std::string& attr = file_e["attr"].string(); if (flags & file_storage::flag_pad_file) attr += 'p'; diff --git a/src/file_storage.cpp b/src/file_storage.cpp index f7804a192..69f654b1d 100644 --- a/src/file_storage.cpp +++ b/src/file_storage.cpp @@ -56,6 +56,18 @@ using namespace std::placeholders; namespace libtorrent { + constexpr file_flags_t file_storage::flag_pad_file; + constexpr file_flags_t file_storage::flag_hidden; + constexpr file_flags_t file_storage::flag_executable; + constexpr file_flags_t file_storage::flag_symlink; + +#ifndef TORRENT_NO_DEPRECATE + constexpr file_flags_t file_storage::pad_file; + constexpr file_flags_t file_storage::attribute_hidden; + constexpr file_flags_t file_storage::attribute_executable; + constexpr file_flags_t file_storage::attribute_symlink; +#endif + file_storage::file_storage() : m_piece_length(0) , m_num_pieces(0) @@ -337,7 +349,7 @@ namespace { void file_storage::add_file(file_entry const& fe, char const* filehash) { - std::uint32_t flags = 0; + file_flags_t flags = {}; if (fe.pad_file) flags |= file_storage::flag_pad_file; if (fe.hidden_attribute) flags |= file_storage::flag_hidden; if (fe.executable_attribute) flags |= file_storage::flag_executable; @@ -359,7 +371,7 @@ namespace { } void file_storage::add_file(std::wstring const& file, std::int64_t file_size - , std::uint32_t file_flags, std::time_t mtime, string_view symlink_path) + , file_flags_t const file_flags, std::time_t mtime, string_view symlink_path) { add_file(wchar_utf8(file), file_size, file_flags, mtime, symlink_path); } @@ -532,7 +544,7 @@ namespace { } void file_storage::add_file(std::string const& path, std::int64_t file_size - , std::uint32_t file_flags, std::time_t mtime, string_view symlink_path) + , file_flags_t const file_flags, std::time_t mtime, string_view symlink_path) { add_file_borrow(nullptr, 0, path, file_size, file_flags, nullptr, mtime , symlink_path); @@ -540,7 +552,7 @@ namespace { void file_storage::add_file_borrow(char const* filename, int const filename_len , std::string const& path, std::int64_t const file_size - , std::uint32_t const file_flags, char const* filehash + , file_flags_t const file_flags, char const* filehash , std::int64_t const mtime, string_view symlink_path) { TORRENT_ASSERT_PRECOND(file_size >= 0); @@ -576,10 +588,10 @@ namespace { e.size = aux::numeric_cast(file_size); e.offset = aux::numeric_cast(m_total_size); - e.pad_file = (file_flags & file_storage::flag_pad_file) != 0; - e.hidden_attribute = (file_flags & file_storage::flag_hidden) != 0; - e.executable_attribute = (file_flags & file_storage::flag_executable) != 0; - e.symlink_attribute = (file_flags & file_storage::flag_symlink) != 0; + e.pad_file = bool(file_flags & file_storage::flag_pad_file); + e.hidden_attribute = bool(file_flags & file_storage::flag_hidden); + e.executable_attribute = bool(file_flags & file_storage::flag_executable); + e.symlink_attribute = bool(file_flags & file_storage::flag_symlink); if (filehash) { @@ -805,14 +817,14 @@ namespace { return m_files[index].offset; } - std::uint32_t file_storage::file_flags(file_index_t const index) const + file_flags_t file_storage::file_flags(file_index_t const index) const { TORRENT_ASSERT_PRECOND(index >= file_index_t(0) && index < end_file()); internal_file_entry const& fe = m_files[index]; - return (fe.pad_file ? flag_pad_file : 0u) - | (fe.hidden_attribute ? flag_hidden : 0u) - | (fe.executable_attribute ? flag_executable : 0u) - | (fe.symlink_attribute ? flag_symlink : 0u); + return (fe.pad_file ? file_storage::flag_pad_file : file_flags_t{}) + | (fe.hidden_attribute ? file_storage::flag_hidden : file_flags_t{}) + | (fe.executable_attribute ? file_storage::flag_executable : file_flags_t{}) + | (fe.symlink_attribute ? file_storage::flag_symlink : file_flags_t{}); } bool file_storage::file_absolute_path(file_index_t const index) const diff --git a/src/torrent_info.cpp b/src/torrent_info.cpp index 91c5e1e83..2f7a72726 100644 --- a/src/torrent_info.cpp +++ b/src/torrent_info.cpp @@ -317,11 +317,11 @@ namespace libtorrent { if (path.empty()) path = "_"; } - namespace { +namespace { - std::uint32_t get_file_attributes(bdecode_node const& dict) + file_flags_t get_file_attributes(bdecode_node const& dict) { - std::uint32_t file_flags = 0; + file_flags_t file_flags = {}; bdecode_node const attr = dict.dict_find_string("attr"); if (attr) { @@ -370,7 +370,7 @@ namespace libtorrent { { if (dict.type() != bdecode_node::dict_t) return false; - std::uint32_t file_flags = get_file_attributes(dict); + file_flags_t file_flags = get_file_attributes(dict); // symlinks have an implied "size" of zero. i.e. they use up 0 bytes of // the torrent payload space @@ -445,7 +445,7 @@ namespace libtorrent { // bitcomet pad file if (path.find("_____padding_file_") != std::string::npos) - file_flags = file_storage::flag_pad_file; + file_flags |= file_storage::flag_pad_file; bdecode_node const fh = dict.dict_find_string("sha1"); char const* filehash = nullptr; @@ -566,7 +566,7 @@ namespace libtorrent { return 0; } - } // anonymous namespace +} // anonymous namespace web_seed_entry::web_seed_entry(std::string const& url_, type_t type_ , std::string const& auth_ diff --git a/test/test_torrent_info.cpp b/test/test_torrent_info.cpp index 2addb2a86..930b58258 100644 --- a/test/test_torrent_info.cpp +++ b/test/test_torrent_info.cpp @@ -683,8 +683,8 @@ TORRENT_TEST(parse_torrents) else if (std::string(test_torrents[i].file) == "pad_file.torrent") { TEST_EQUAL(ti->num_files(), 2); - TEST_EQUAL(ti->files().file_flags(file_index_t{0}) & file_storage::flag_pad_file, false); - TEST_EQUAL(ti->files().file_flags(file_index_t{1}) & file_storage::flag_pad_file, true); + TEST_EQUAL(bool(ti->files().file_flags(file_index_t{0}) & file_storage::flag_pad_file), false); + TEST_EQUAL(bool(ti->files().file_flags(file_index_t{1}) & file_storage::flag_pad_file), true); } else if (std::string(test_torrents[i].file) == "creation_date.torrent") { @@ -776,7 +776,7 @@ TORRENT_TEST(parse_torrents) { piece_index_t const first = ti->map_file(i, 0, 0).piece; piece_index_t const last = ti->map_file(i, std::max(fs.file_size(i)-1, std::int64_t(0)), 0).piece; - int const flags = fs.file_flags(i); + file_flags_t const flags = fs.file_flags(i); sha1_hash const ih = fs.hash(i); std::printf(" %11" PRId64 " %c%c%c%c [ %4d, %4d ] %7u %s %s %s%s\n" , fs.file_size(i)