make file attributes (in file_storage) type safe

This commit is contained in:
arvidn 2017-08-03 02:31:03 -07:00 committed by Arvid Norberg
parent 35232a5a5f
commit a8a5986046
8 changed files with 200 additions and 190 deletions

View File

@ -16,6 +16,7 @@
#include "libtorrent/peer_info.hpp" #include "libtorrent/peer_info.hpp"
#include "libtorrent/alert_types.hpp" // for picker_flags_t #include "libtorrent/alert_types.hpp" // for picker_flags_t
#include "libtorrent/session_types.hpp" // for save_state_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 "libtorrent/alert.hpp"
#include <vector> #include <vector>
@ -312,6 +313,7 @@ void bind_converters()
to_python_converter<lt::save_state_flags_t, from_bitfield_flag<lt::save_state_flags_t>>(); to_python_converter<lt::save_state_flags_t, from_bitfield_flag<lt::save_state_flags_t>>();
to_python_converter<lt::session_flags_t, from_bitfield_flag<lt::session_flags_t>>(); to_python_converter<lt::session_flags_t, from_bitfield_flag<lt::session_flags_t>>();
to_python_converter<lt::remove_flags_t, from_bitfield_flag<lt::remove_flags_t>>(); to_python_converter<lt::remove_flags_t, from_bitfield_flag<lt::remove_flags_t>>();
to_python_converter<lt::file_flags_t, from_bitfield_flag<lt::file_flags_t>>();
// work-around types // work-around types
to_python_converter<lt::aux::noexcept_movable<lt::address>, address_to_tuple< to_python_converter<lt::aux::noexcept_movable<lt::address>, address_to_tuple<
@ -369,4 +371,5 @@ void bind_converters()
to_bitfield_flag<lt::save_state_flags_t>(); to_bitfield_flag<lt::save_state_flags_t>();
to_bitfield_flag<lt::session_flags_t>(); to_bitfield_flag<lt::session_flags_t>();
to_bitfield_flag<lt::remove_flags_t>(); to_bitfield_flag<lt::remove_flags_t>();
to_bitfield_flag<lt::file_flags_t>();
} }

View File

@ -102,7 +102,7 @@ namespace
{ return FileIter(self, self.end_file()); } { return FileIter(self, self.end_file()); }
void add_file_wstring(file_storage& fs, std::wstring const& file, std::int64_t size 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); 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 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); fs.add_file(file, size, flags, md, link);
} }
@ -124,6 +124,8 @@ namespace
{ {
ct.add_tracker(url, tier); ct.add_tracker(url, tier);
} }
struct dummy13 {};
} }
void bind_create_torrent() 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::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_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::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 #ifndef TORRENT_NO_DEPRECATE
file_entry (file_storage::*at)(int) const = &file_storage::at; file_entry (file_storage::*at)(int) const = &file_storage::at;
#endif #endif
// TODO: 3 move this to its own file // TODO: 3 move this to its own file
class_<file_storage>("file_storage") {
scope s = class_<file_storage>("file_storage")
.def("is_valid", &file_storage::is_valid) .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("add_file", add_file, (arg("path"), arg("size"), arg("flags") = 0, arg("mtime") = 0, arg("linkpath") = ""))
.def("num_files", &file_storage::num_files) .def("num_files", &file_storage::num_files)
@ -185,12 +188,19 @@ void bind_create_torrent()
.def("name", &file_storage::name, return_value_policy<copy_const_reference>()) .def("name", &file_storage::name, return_value_policy<copy_const_reference>())
; ;
enum_<file_storage::file_flags_t>("file_flags_t") s.attr("flag_pad_file") = file_storage::flag_pad_file;
.value("flag_pad_file", file_storage::flag_pad_file) s.attr("flag_hidden") = file_storage::flag_hidden;
.value("flag_hidden", file_storage::flag_hidden) s.attr("flag_executable") = file_storage::flag_executable;
.value("flag_executable", file_storage::flag_executable) s.attr("flag_symlink") = file_storage::flag_symlink;
.value("flag_symlink", file_storage::flag_symlink) }
;
{
scope s = class_<dummy13>("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>("create_torrent", no_init) class_<create_torrent>("create_torrent", no_init)
.def(init<file_storage&>()) .def(init<file_storage&>())

View File

@ -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 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; 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; std::stringstream file_hash;
if (!st.hash(i).is_all_zeros()) if (!st.hash(i).is_all_zeros())
file_hash << st.hash(i); file_hash << st.hash(i);

View File

@ -46,6 +46,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/string_view.hpp" #include "libtorrent/string_view.hpp"
#include "libtorrent/aux_/vector.hpp" #include "libtorrent/aux_/vector.hpp"
#include "libtorrent/aux_/noexcept_movable.hpp" #include "libtorrent/aux_/noexcept_movable.hpp"
#include "libtorrent/flags.hpp"
namespace libtorrent { namespace libtorrent {
@ -192,6 +193,10 @@ namespace libtorrent {
std::int64_t size; std::int64_t size;
}; };
// hidden
struct file_flags_tag;
using file_flags_t = flags::bitfield_flag<std::uint8_t, file_flags_tag>;
// The ``file_storage`` class represents a file list and the piece // The ``file_storage`` class represents a file list and the piece
// size. Everything necessary to interpret a regular bittorrent storage // size. Everything necessary to interpret a regular bittorrent storage
// file structure. // file structure.
@ -214,25 +219,12 @@ namespace libtorrent {
// not. // not.
bool is_valid() const { return m_piece_length > 0; } bool is_valid() const { return m_piece_length > 0; }
// file attribute flags #ifndef TORRENT_NO_DEPRECATE
enum flags_t static constexpr file_flags_t TORRENT_DEPRECATED_MEMBER pad_file = 0_bit;
{ static constexpr file_flags_t TORRENT_DEPRECATED_MEMBER attribute_hidden = 1_bit;
// the file is a pad file. It's required to contain zeros static constexpr file_flags_t TORRENT_DEPRECATED_MEMBER attribute_executable = 2_bit;
// at it will not be saved to disk. Its purpose is to make static constexpr file_flags_t TORRENT_DEPRECATED_MEMBER attribute_symlink = 3_bit;
// the following file start on a piece boundary. #endif
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
};
// allocates space for ``num_files`` in the internal file list. This can // allocates space for ``num_files`` in the internal file list. This can
// be used to avoid reallocating the internal file list when the number // 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``. // can be changed by calling ``set_name``.
void add_file_borrow(char const* filename, int filename_len void add_file_borrow(char const* filename, int filename_len
, std::string const& path, std::int64_t file_size , 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()); , 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()); , std::time_t mtime = 0, string_view symlink_path = string_view());
// renames the file at ``index`` to ``new_filename``. Keep in mind // renames the file at ``index`` to ``new_filename``. Keep in mind
@ -295,7 +288,8 @@ namespace libtorrent {
// instead, use the wchar -> utf8 conversion functions // instead, use the wchar -> utf8 conversion functions
// and pass in utf8 strings // and pass in utf8 strings
TORRENT_DEPRECATED 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 = ""); , std::time_t mtime = 0, string_view s_p = "");
TORRENT_DEPRECATED TORRENT_DEPRECATED
void rename_file(file_index_t index, std::wstring const& new_filename); void rename_file(file_index_t index, std::wstring const& new_filename);
@ -477,35 +471,27 @@ namespace libtorrent {
// the set. // the set.
void all_path_hashes(std::unordered_set<std::uint32_t>& table) const; void all_path_hashes(std::unordered_set<std::uint32_t>& table) const;
// flags indicating various attributes for files in // the file is a pad file. It's required to contain zeros
// a file_storage. // at it will not be saved to disk. Its purpose is to make
enum file_flags_t : std::uint32_t // the following file start on a piece boundary.
{ static constexpr file_flags_t flag_pad_file = 0_bit;
// 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,
// this file is hidden (sets the hidden attribute // this file has the hidden attribute set. This is primarily
// on windows) // a windows attribute
flag_hidden = 2, static constexpr file_flags_t flag_hidden = 1_bit;
// this file is executable (sets the executable bit // this file has the executable attribute set.
// on posix like systems) static constexpr file_flags_t flag_executable = 2_bit;
flag_executable = 4,
// this file is a symlink. The symlink target is // this file is a symbolic link. It should have a link
// specified in a separate field // target string associated with it.
flag_symlink = 8 static constexpr file_flags_t flag_symlink = 3_bit;
};
std::vector<std::string> const& paths() const { return m_paths; } std::vector<std::string> const& paths() const { return m_paths; }
// returns a bitmask of flags from file_flags_t that apply // returns a bitmask of flags from file_flags_t that apply
// to file at ``index``. // 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 // 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 // have an absolute path, i.e. is not anchored in the save path of the

View File

@ -50,148 +50,147 @@ POSSIBILITY OF SUCH DAMAGE.
using namespace std::placeholders; using namespace std::placeholders;
namespace libtorrent { 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) file_flags_t get_file_attributes(std::string const& p)
{ return leaf == ".." || leaf == "."; } {
std::uint32_t get_file_attributes(std::string const& p)
{
#ifdef TORRENT_WINDOWS #ifdef TORRENT_WINDOWS
WIN32_FILE_ATTRIBUTE_DATA attr; WIN32_FILE_ATTRIBUTE_DATA attr;
std::wstring path = convert_to_wstring(p); std::wstring path = convert_to_wstring(p);
GetFileAttributesExW(path.c_str(), GetFileExInfoStandard, &attr); GetFileAttributesExW(path.c_str(), GetFileExInfoStandard, &attr);
if (attr.dwFileAttributes == INVALID_FILE_ATTRIBUTES) return 0; if (attr.dwFileAttributes == INVALID_FILE_ATTRIBUTES) return {};
if (attr.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) return file_storage::attribute_hidden; if (attr.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) return file_storage::flag_hidden;
return 0; return {};
#else #else
struct ::stat s; struct ::stat s;
if (::lstat(convert_to_native(p).c_str(), &s) < 0) return 0; if (::lstat(convert_to_native(p).c_str(), &s) < 0) return {};
std::uint32_t file_attr = 0; file_flags_t file_attr = {};
if (s.st_mode & S_IXUSR) if (s.st_mode & S_IXUSR)
file_attr += file_storage::attribute_executable; file_attr |= file_storage::flag_executable;
if (S_ISLNK(s.st_mode)) if (S_ISLNK(s.st_mode))
file_attr += file_storage::attribute_symlink; file_attr |= file_storage::flag_symlink;
return file_attr; return file_attr;
#endif #endif
} }
#ifndef TORRENT_WINDOWS #ifndef TORRENT_WINDOWS
std::string get_symlink_path_impl(char const* path) std::string get_symlink_path_impl(char const* path)
{ {
constexpr int MAX_SYMLINK_PATH = 200; constexpr int MAX_SYMLINK_PATH = 200;
char buf[MAX_SYMLINK_PATH]; char buf[MAX_SYMLINK_PATH];
std::string f = convert_to_native(path); std::string f = convert_to_native(path);
int char_read = int(readlink(f.c_str(), buf, MAX_SYMLINK_PATH)); int char_read = int(readlink(f.c_str(), buf, MAX_SYMLINK_PATH));
if (char_read < 0) return ""; if (char_read < 0) return "";
if (char_read < MAX_SYMLINK_PATH) buf[char_read] = 0; if (char_read < MAX_SYMLINK_PATH) buf[char_read] = 0;
else buf[0] = 0; else buf[0] = 0;
return convert_from_native(buf); return convert_from_native(buf);
} }
#endif #endif
std::string get_symlink_path(std::string const& p) std::string get_symlink_path(std::string const& p)
{ {
#if defined TORRENT_WINDOWS #if defined TORRENT_WINDOWS
TORRENT_UNUSED(p); TORRENT_UNUSED(p);
return ""; return "";
#else #else
return get_symlink_path_impl(p.c_str()); return get_symlink_path_impl(p.c_str());
#endif #endif
} }
void add_files_impl(file_storage& fs, std::string const& p void add_files_impl(file_storage& fs, std::string const& p
, std::string const& l, std::function<bool(std::string)> pred , std::string const& l, std::function<bool(std::string)> pred
, std::uint32_t const flags) , std::uint32_t const flags)
{ {
std::string f = combine_path(p, l); std::string f = combine_path(p, l);
if (!pred(f)) return; if (!pred(f)) return;
error_code ec; error_code ec;
file_status s; file_status s;
stat_file(f, &s, ec, (flags & create_torrent::symlinks) ? dont_follow_links : 0); stat_file(f, &s, ec, (flags & create_torrent::symlinks) ? dont_follow_links : 0);
if (ec) return; if (ec) return;
// recurse into directories // recurse into directories
bool recurse = (s.mode & file_status::directory) != 0; 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 // if the file is not a link or we're following links, and it's a directory
// only then should we recurse // only then should we recurse
#ifndef TORRENT_WINDOWS #ifndef TORRENT_WINDOWS
if ((s.mode & file_status::link) && (flags & create_torrent::symlinks)) if ((s.mode & file_status::link) && (flags & create_torrent::symlinks))
recurse = false; recurse = false;
#endif #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;
std::string leaf = i.file(); add_files_impl(fs, p, combine_path(l, leaf), pred, flags);
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 else
{ {
// #error use the fields from s fs.add_file(l, s.file_size, file_flags, std::time_t(s.mtime));
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));
}
} }
} }
}
struct hash_state struct hash_state
{ {
create_torrent& ct; create_torrent& ct;
storage_holder storage; storage_holder storage;
disk_io_thread& iothread; disk_io_thread& iothread;
piece_index_t piece_counter; piece_index_t piece_counter;
piece_index_t completed_piece; piece_index_t completed_piece;
std::function<void(piece_index_t)> const& f; std::function<void(piece_index_t)> const& f;
error_code& ec; error_code& ec;
}; };
void on_hash(piece_index_t const piece, sha1_hash const& piece_hash void on_hash(piece_index_t const piece, sha1_hash const& piece_hash
, storage_error const& error, hash_state* st) , storage_error const& error, hash_state* st)
{
if (error)
{ {
if (error) // on error
{ st->ec = error.ec;
// on error st->iothread.abort(true);
st->ec = error.ec; return;
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();
} }
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 #ifndef TORRENT_NO_DEPRECATE
@ -526,7 +525,7 @@ namespace libtorrent {
file_index_t const first(0); file_index_t const first(0);
if (m_include_mtime) info["mtime"] = m_files.mtime(first); if (m_include_mtime) info["mtime"] = m_files.mtime(first);
info["length"] = m_files.file_size(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 if (flags & (file_storage::flag_pad_file
| file_storage::flag_hidden | file_storage::flag_hidden
| file_storage::flag_executable | file_storage::flag_executable
@ -577,8 +576,8 @@ namespace libtorrent {
path_e.list().push_back(entry(e)); path_e.list().push_back(entry(e));
} }
std::uint32_t const flags = m_files.file_flags(i); file_flags_t const flags = m_files.file_flags(i);
if (flags != 0) if (flags)
{ {
std::string& attr = file_e["attr"].string(); std::string& attr = file_e["attr"].string();
if (flags & file_storage::flag_pad_file) attr += 'p'; if (flags & file_storage::flag_pad_file) attr += 'p';

View File

@ -56,6 +56,18 @@ using namespace std::placeholders;
namespace libtorrent { 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() file_storage::file_storage()
: m_piece_length(0) : m_piece_length(0)
, m_num_pieces(0) , m_num_pieces(0)
@ -337,7 +349,7 @@ namespace {
void file_storage::add_file(file_entry const& fe, char const* filehash) 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.pad_file) flags |= file_storage::flag_pad_file;
if (fe.hidden_attribute) flags |= file_storage::flag_hidden; if (fe.hidden_attribute) flags |= file_storage::flag_hidden;
if (fe.executable_attribute) flags |= file_storage::flag_executable; 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 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); 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 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 add_file_borrow(nullptr, 0, path, file_size, file_flags, nullptr, mtime
, symlink_path); , symlink_path);
@ -540,7 +552,7 @@ namespace {
void file_storage::add_file_borrow(char const* filename, int const filename_len void file_storage::add_file_borrow(char const* filename, int const filename_len
, std::string const& path, std::int64_t const file_size , 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) , std::int64_t const mtime, string_view symlink_path)
{ {
TORRENT_ASSERT_PRECOND(file_size >= 0); TORRENT_ASSERT_PRECOND(file_size >= 0);
@ -576,10 +588,10 @@ namespace {
e.size = aux::numeric_cast<std::uint64_t>(file_size); e.size = aux::numeric_cast<std::uint64_t>(file_size);
e.offset = aux::numeric_cast<std::uint64_t>(m_total_size); e.offset = aux::numeric_cast<std::uint64_t>(m_total_size);
e.pad_file = (file_flags & file_storage::flag_pad_file) != 0; e.pad_file = bool(file_flags & file_storage::flag_pad_file);
e.hidden_attribute = (file_flags & file_storage::flag_hidden) != 0; e.hidden_attribute = bool(file_flags & file_storage::flag_hidden);
e.executable_attribute = (file_flags & file_storage::flag_executable) != 0; e.executable_attribute = bool(file_flags & file_storage::flag_executable);
e.symlink_attribute = (file_flags & file_storage::flag_symlink) != 0; e.symlink_attribute = bool(file_flags & file_storage::flag_symlink);
if (filehash) if (filehash)
{ {
@ -805,14 +817,14 @@ namespace {
return m_files[index].offset; 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()); TORRENT_ASSERT_PRECOND(index >= file_index_t(0) && index < end_file());
internal_file_entry const& fe = m_files[index]; internal_file_entry const& fe = m_files[index];
return (fe.pad_file ? flag_pad_file : 0u) return (fe.pad_file ? file_storage::flag_pad_file : file_flags_t{})
| (fe.hidden_attribute ? flag_hidden : 0u) | (fe.hidden_attribute ? file_storage::flag_hidden : file_flags_t{})
| (fe.executable_attribute ? flag_executable : 0u) | (fe.executable_attribute ? file_storage::flag_executable : file_flags_t{})
| (fe.symlink_attribute ? flag_symlink : 0u); | (fe.symlink_attribute ? file_storage::flag_symlink : file_flags_t{});
} }
bool file_storage::file_absolute_path(file_index_t const index) const bool file_storage::file_absolute_path(file_index_t const index) const

View File

@ -317,11 +317,11 @@ namespace libtorrent {
if (path.empty()) path = "_"; 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"); bdecode_node const attr = dict.dict_find_string("attr");
if (attr) if (attr)
{ {
@ -370,7 +370,7 @@ namespace libtorrent {
{ {
if (dict.type() != bdecode_node::dict_t) return false; 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 // symlinks have an implied "size" of zero. i.e. they use up 0 bytes of
// the torrent payload space // the torrent payload space
@ -445,7 +445,7 @@ namespace libtorrent {
// bitcomet pad file // bitcomet pad file
if (path.find("_____padding_file_") != std::string::npos) 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"); bdecode_node const fh = dict.dict_find_string("sha1");
char const* filehash = nullptr; char const* filehash = nullptr;
@ -566,7 +566,7 @@ namespace libtorrent {
return 0; return 0;
} }
} // anonymous namespace } // anonymous namespace
web_seed_entry::web_seed_entry(std::string const& url_, type_t type_ web_seed_entry::web_seed_entry(std::string const& url_, type_t type_
, std::string const& auth_ , std::string const& auth_

View File

@ -683,8 +683,8 @@ TORRENT_TEST(parse_torrents)
else if (std::string(test_torrents[i].file) == "pad_file.torrent") else if (std::string(test_torrents[i].file) == "pad_file.torrent")
{ {
TEST_EQUAL(ti->num_files(), 2); TEST_EQUAL(ti->num_files(), 2);
TEST_EQUAL(ti->files().file_flags(file_index_t{0}) & file_storage::flag_pad_file, false); TEST_EQUAL(bool(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{1}) & file_storage::flag_pad_file), true);
} }
else if (std::string(test_torrents[i].file) == "creation_date.torrent") 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 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; 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); sha1_hash const ih = fs.hash(i);
std::printf(" %11" PRId64 " %c%c%c%c [ %4d, %4d ] %7u %s %s %s%s\n" std::printf(" %11" PRId64 " %c%c%c%c [ %4d, %4d ] %7u %s %s %s%s\n"
, fs.file_size(i) , fs.file_size(i)