reverted part of the file_storage API to match the previous one more closly

This commit is contained in:
Arvid Norberg 2010-11-29 05:44:29 +00:00
parent f82321c1dd
commit 2e69366b02
13 changed files with 232 additions and 195 deletions

View File

@ -48,11 +48,9 @@ namespace
ct.add_node(std::make_pair(addr, port)); ct.add_node(std::make_pair(addr, port));
} }
void add_file(file_storage& ct, file_entry const& fe void add_file(file_storage& ct, file_entry const& fe)
, std::string const& hash, std::string const& linkpath)
{ {
ct.add_file(fe, hash.empty() ? 0 : hash.c_str() ct.add_file(fe);
, linkpath.empty() ? 0 : &linkpath);
} }
} }
@ -73,21 +71,23 @@ void bind_create_torrent()
#endif #endif
void (*add_files0)(file_storage&, std::string const&, boost::uint32_t) = add_files; void (*add_files0)(file_storage&, std::string const&, boost::uint32_t) = add_files;
file_entry (file_storage::*at)(int) const = &file_storage::at;
class_<file_storage>("file_storage") 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("entry"), arg("hash") = std::string(), arg("symlink") = std::string())) .def("add_file", add_file, arg("entry"))
.def("add_file", add_file0, (arg("path"), arg("size"), arg("flags") = 0, arg("mtime") = 0, arg("linkpath") = "")) .def("add_file", add_file0, (arg("path"), arg("size"), arg("flags") = 0, arg("mtime") = 0, arg("linkpath") = ""))
#if TORRENT_USE_WSTRING #if TORRENT_USE_WSTRING
.def("add_file", add_file1, (arg("path"), arg("size"), arg("flags") = 0, arg("mtime") = 0, arg("linkpath") = "")) .def("add_file", add_file1, (arg("path"), arg("size"), arg("flags") = 0, arg("mtime") = 0, arg("linkpath") = ""))
#endif #endif
.def("num_files", &file_storage::num_files) .def("num_files", &file_storage::num_files)
.def("at", &file_storage::at, return_internal_reference<>()) .def("at", at)
.def("hash", &file_storage::hash) // .def("hash", &file_storage::hash)
.def("symlink", &file_storage::symlink, return_internal_reference<>()) // .def("symlink", &file_storage::symlink, return_internal_reference<>())
.def("file_index", &file_storage::file_index) // .def("file_index", &file_storage::file_index)
.def("file_base", &file_storage::file_base) // .def("file_base", &file_storage::file_base)
.def("set_file_base", &file_storage::set_file_base) // .def("set_file_base", &file_storage::set_file_base)
.def("file_path", &file_storage::file_path) // .def("file_path", &file_storage::file_path)
.def("total_size", &file_storage::total_size) .def("total_size", &file_storage::total_size)
.def("set_num_pieces", &file_storage::set_num_pieces) .def("set_num_pieces", &file_storage::set_num_pieces)
.def("num_pieces", &file_storage::num_pieces) .def("num_pieces", &file_storage::num_pieces)

View File

@ -55,10 +55,10 @@ namespace
list files(torrent_info const& ti, bool storage) { list files(torrent_info const& ti, bool storage) {
list result; list result;
typedef std::vector<file_entry> list_type; typedef torrent_info::file_iterator iter;
for (list_type::const_iterator i = ti.begin_files(); i != ti.end_files(); ++i) for (iter i = ti.begin_files(); i != ti.end_files(); ++i)
result.append(*i); result.append(ti.files().at(i));
return result; return result;
} }
@ -160,7 +160,7 @@ void bind_torrent_info()
.def("piece_size", &torrent_info::piece_size) .def("piece_size", &torrent_info::piece_size)
.def("num_files", &torrent_info::num_files, (arg("storage")=false)) .def("num_files", &torrent_info::num_files, (arg("storage")=false))
.def("file_at", &torrent_info::file_at, return_internal_reference<>()) .def("file_at", &torrent_info::file_at)
.def("file_at_offset", &torrent_info::file_at_offset) .def("file_at_offset", &torrent_info::file_at_offset)
.def("files", &files, (arg("storage")=false)) .def("files", &files, (arg("storage")=false))
.def("rename_file", rename_file0) .def("rename_file", rename_file0)
@ -182,8 +182,10 @@ void bind_torrent_info()
; ;
class_<file_entry>("file_entry") class_<file_entry>("file_entry")
.def("filename", &file_entry::filename) .def_readwrite("path", &file_entry::path)
.def("set_name", &file_entry::set_name) .def_readwrite("symlink_path", &file_entry::symlink_path)
.def_readwrite("filehash", &file_entry::filehash)
.def_readwrite("mtime", &file_entry::mtime)
.add_property("pad_file", &get_pad_file) .add_property("pad_file", &get_pad_file)
.add_property("executable_attribute", &get_executable_attribute) .add_property("executable_attribute", &get_executable_attribute)
.add_property("hidden_attribute", &get_hidden_attribute) .add_property("hidden_attribute", &get_hidden_attribute)

View File

@ -173,12 +173,12 @@ file structure. Its synopsis::
int piece_length() const; int piece_length() const;
int piece_size(int index) const; int piece_size(int index) const;
sha1_hash const& hash(file_entry const& fe) const; sha1_hash const& hash(internal_file_entry const& fe) const;
std::string const& symlink(file_entry const& fe) const; std::string const& symlink(internal_file_entry const& fe) const;
time_t mtime(file_entry const& fe) const; time_t mtime(internal_file_entry const& fe) const;
int file_index(file_entry const& fe) const; int file_index(internal_file_entry const& fe) const;
size_type file_base(file_entry const& fe) const; size_type file_base(internal_file_entry const& fe) const;
void set_file_base(file_entry const& fe, size_type off); void set_file_base(internal_file_entry const& fe, size_type off);
void set_name(std::string const& n); void set_name(std::string const& n);
void set_name(std::wstring const& n); void set_name(std::wstring const& n);
@ -193,8 +193,8 @@ add_file()
:: ::
void add_file(file_entry const& e); void add_file(file_entry const& e);
void add_file(fs::path const& p, size_type size, int flags = 0); void add_file(std::string const& p, size_type size, int flags = 0);
void add_file(fs::wpath const& p, size_type size, int flags = 0); void add_file(std::wstring const& p, size_type size, int flags = 0);
Adds a file to the file storage. The ``flags`` argument sets attributes on the file. Adds a file to the file storage. The ``flags`` argument sets attributes on the file.
The file attributes is an extension and may not work in all bittorrent clients. The file attributes is an extension and may not work in all bittorrent clients.
@ -204,17 +204,8 @@ The possible arreibutes are::
attribute_hidden attribute_hidden
attribute_executable attribute_executable
add_file If more files than one are added, certain restrictions to their paths apply.
-------- In a multi-file file storage (torrent), all files must share the same root directory.
::
void add_file(file_entry const& e);
void add_file(fs::path const& p, size_type size);
Adds a file to the file storage. If more files than one are added,
certain restrictions to their paths apply. In a multi-file file
storage (torrent), all files must share the same root directory.
That is, the first path element of all files must be the same. That is, the first path element of all files must be the same.
This shared path element is also set to the name of the torrent. It This shared path element is also set to the name of the torrent. It
@ -228,13 +219,14 @@ hash() symlink() mtime() file_index()
:: ::
sha1_hash hash(file_entry const& fe) const; sha1_hash hash(internal_file_entry const& fe) const;
std::string const& symlink(file_entry const& fe) const; std::string const& symlink(internal_file_entry const& fe) const;
time_t mtime(file_entry const& fe) const; time_t mtime(internal_file_entry const& fe) const;
int file_index(file_entry const& fe) const; int file_index(internal_file_entry const& fe) const;
These functions are used to query the symlink, file hash, These functions are used to query the symlink, file hash,
modification time and the file-index from a ``file_entry``. modification time and the file-index from a ``internal_file_entry``,
which typically would be acquired from an iterator.
For these functions to function, the file entry must be an For these functions to function, the file entry must be an
actual object from this same ``file_storage`` object. It may actual object from this same ``file_storage`` object. It may
@ -255,8 +247,8 @@ file_base() set_file_base()
:: ::
size_type file_base(file_entry const& fe) const; size_type file_base(internal_file_entry const& fe) const;
void set_file_base(file_entry const& fe, size_type off); void set_file_base(internal_file_entry const& fe, size_type off);
The file base of a file is the offset within the file on the filsystem The file base of a file is the offset within the file on the filsystem
where it starts to write. For the most part, this is always 0. It's where it starts to write. For the most part, this is always 0. It's

View File

@ -1546,28 +1546,29 @@ begin_files() end_files() rbegin_files() rend_files()
This class will need some explanation. First of all, to get a list of all files This class will need some explanation. First of all, to get a list of all files
in the torrent, you can use ``begin_files()``, ``end_files()``, in the torrent, you can use ``begin_files()``, ``end_files()``,
``rbegin_files()`` and ``rend_files()``. These will give you standard vector ``rbegin_files()`` and ``rend_files()``. These will give you standard vector
iterators with the type ``file_entry``. iterators with the type ``internal_file_entry``, which is an internal type.
You can resolve it into the public representation of a file (``file_entry``)
using the ``file_storage::at`` function, which takes an index and an iterator;
:: ::
struct file_entry struct file_entry
{ {
std::string filename(); std::string path;
size_type offset; size_type offset;
size_type size; size_type size;
size_type file_base; size_type file_base;
time_t mtime; time_t mtime;
int symlink_index; sha1_hash filehash;
int filehash_index;
bool pad_file:1; bool pad_file:1;
bool hidden_attribute:1; bool hidden_attribute:1;
bool executable_attribute:1; bool executable_attribute:1;
bool symlink_attribute:1; bool symlink_attribute:1;
}; };
The ``filename`` function returns the filename of this file. It does not include the The ``path`` is the full path of this file. The paths are unicode strings
path, just the leaf name. To get the full path name, use ``file_storage::file_path()``. encoded in UTF-8.
The filenames are unicode strings encoded in UTF-8.
``size`` is the size of the file (in bytes) and ``offset`` is the byte offset ``size`` is the size of the file (in bytes) and ``offset`` is the byte offset
of the file within the torrent. i.e. the sum of all the sizes of the files of the file within the torrent. i.e. the sum of all the sizes of the files
@ -1582,14 +1583,12 @@ file.
``mtime`` is the modification time of this file specified in posix time. ``mtime`` is the modification time of this file specified in posix time.
``symlink_index`` is an index into an array of paths in ``file_storage``, or ``symlink_path`` is the path which this is a symlink to, or empty if this is
-1 if this file is not a symlink. This field is only used if the ``symlink_attribute`` not a symlink. This field is only used if the ``symlink_attribute`` is set.
is set. To resolve the symlink, call ``file_storage::symlink(e.symlink_index)``.
``filehash_index`` is an index into an array of sha-1 hashes in ``file_storage``, or ``filehash`` is a sha-1 hash of the content of the file, or zeroes, if no
-1 if this file doesn't have a hash specified. The hash is the hash of the actual file hash was present in the torrent file. It can be used to potentially
content of the file, and can be used to potentially find alternative sources for it. find alternative sources for the file.
To resolve the hash, use ``file_storage::hash(e)``.
``pad_file`` is set to true for files that are not part of the data of the torrent. ``pad_file`` is set to true for files that are not part of the data of the torrent.
They are just there to make sure the next file is aligned to a particular byte offset They are just there to make sure the next file is aligned to a particular byte offset

View File

@ -47,18 +47,16 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/file.hpp" #include "libtorrent/file.hpp"
#include "libtorrent/ptime.hpp" #include "libtorrent/ptime.hpp"
#include "libtorrent/thread.hpp" #include "libtorrent/thread.hpp"
#include "libtorrent/file_storage.hpp"
namespace libtorrent namespace libtorrent
{ {
struct file_entry;
struct file_storage;
struct TORRENT_EXPORT file_pool : boost::noncopyable struct TORRENT_EXPORT file_pool : boost::noncopyable
{ {
file_pool(int size = 40): m_size(size), m_low_prio_io(true) {} file_pool(int size = 40): m_size(size), m_low_prio_io(true) {}
boost::intrusive_ptr<file> open_file(void* st, std::string const& p boost::intrusive_ptr<file> open_file(void* st, std::string const& p
, file_entry const& fe, file_storage const& fs, int m, error_code& ec); , file_storage::iterator fe, file_storage const& fs, int m, error_code& ec);
void release(void* st); void release(void* st);
void release(void* st, int file_index); void release(void* st, int file_index);
void resize(int size); void resize(int size);

View File

@ -47,9 +47,37 @@ namespace libtorrent
struct file; struct file;
struct TORRENT_EXPORT file_entry struct TORRENT_EXPORT file_entry
{
file_entry(): offset(0), size(0), file_base(0)
, mtime(0), pad_file(false), hidden_attribute(false)
, executable_attribute(false)
, symlink_attribute(false)
{}
std::string path;
size_type offset; // the offset of this file inside the torrent
size_type size; // the size of this file
// the offset in the file where the storage starts.
// This is always 0 unless parts of the torrent is
// compressed into a single file, such as a so-called part file.
size_type file_base;
std::time_t mtime;
sha1_hash filehash;
bool pad_file:1;
bool hidden_attribute:1;
bool executable_attribute:1;
bool symlink_attribute:1;
std::string symlink_path;
};
// this is used internally to hold the file entry
// it's smaller and optimized for smaller memory
// footprint, as opposed to file_entry, which is
// optimized for convenience
struct internal_file_entry
{ {
friend class file_storage; friend class file_storage;
file_entry() internal_file_entry()
: name(0) : name(0)
, offset(0) , offset(0)
, symlink_index(-1) , symlink_index(-1)
@ -62,10 +90,25 @@ namespace libtorrent
, path_index(-1) , path_index(-1)
{} {}
file_entry(file_entry const& fe); internal_file_entry(file_entry const& e)
file_entry& operator=(file_entry const& fe); : name(0)
, offset(e.offset)
, symlink_index(-1)
, size(e.size)
, name_len(0)
, pad_file(e.pad_file)
, hidden_attribute(e.hidden_attribute)
, executable_attribute(e.executable_attribute)
, symlink_attribute(e.symlink_attribute)
, path_index(-1)
{
set_name(e.path.c_str());
}
~file_entry(); internal_file_entry(internal_file_entry const& fe);
internal_file_entry& operator=(internal_file_entry const& fe);
~internal_file_entry();
void set_name(char const* n, int borrow_chars = 0); void set_name(char const* n, int borrow_chars = 0);
std::string filename() const; std::string filename() const;
@ -129,8 +172,7 @@ namespace libtorrent
void reserve(int num_files); void reserve(int num_files);
void add_file(file_entry const& e, char const* filehash = 0 void add_file(file_entry const& e, char const* filehash = 0);
, std::string const* symlink = 0, time_t mtime = 0);
void add_file(std::string const& p, size_type size, int flags = 0 void add_file(std::string const& p, size_type size, int flags = 0
, std::time_t mtime = 0, std::string const& s_p = ""); , std::time_t mtime = 0, std::string const& s_p = "");
@ -148,8 +190,8 @@ namespace libtorrent
, int size) const; , int size) const;
peer_request map_file(int file, size_type offset, int size) const; peer_request map_file(int file, size_type offset, int size) const;
typedef std::vector<file_entry>::const_iterator iterator; typedef std::vector<internal_file_entry>::const_iterator iterator;
typedef std::vector<file_entry>::const_reverse_iterator reverse_iterator; typedef std::vector<internal_file_entry>::const_reverse_iterator reverse_iterator;
iterator file_at_offset(size_type offset) const; iterator file_at_offset(size_type offset) const;
iterator begin() const { return m_files.begin(); } iterator begin() const { return m_files.begin(); }
@ -159,20 +201,8 @@ namespace libtorrent
int num_files() const int num_files() const
{ return int(m_files.size()); } { return int(m_files.size()); }
file_entry const& at(int index) const file_entry at(int index) const;
{ file_entry at(iterator i) const;
TORRENT_ASSERT(index >= 0 && index < int(m_files.size()));
return m_files[index];
}
sha1_hash hash(file_entry const& fe) const;
std::string const& symlink(file_entry const& fe) const;
time_t mtime(file_entry const& fe) const;
int file_index(file_entry const& fe) const;
size_type file_base(file_entry const& fe) const;
void set_file_base(file_entry const& fe, size_type off);
std::string file_path(file_entry const& fe) const;
size_type total_size() const { return m_total_size; } size_type total_size() const { return m_total_size; }
void set_num_pieces(int n) { m_num_pieces = n; } void set_num_pieces(int n) { m_num_pieces = n; }
@ -199,13 +229,21 @@ namespace libtorrent
// not add any padding // not add any padding
void optimize(int pad_file_limit = -1); void optimize(int pad_file_limit = -1);
sha1_hash hash(internal_file_entry const& fe) const;
std::string const& symlink(internal_file_entry const& fe) const;
time_t mtime(internal_file_entry const& fe) const;
int file_index(internal_file_entry const& fe) const;
size_type file_base(internal_file_entry const& fe) const;
void set_file_base(internal_file_entry const& fe, size_type off);
std::string file_path(internal_file_entry const& fe) const;
private: private:
void update_path_index(file_entry& e); void update_path_index(internal_file_entry& e);
void reorder_file(int index, int dst); void reorder_file(int index, int dst);
// the list of files that this torrent consists of // the list of files that this torrent consists of
std::vector<file_entry> m_files; std::vector<internal_file_entry> m_files;
// if there are sha1 hashes for each individual file // if there are sha1 hashes for each individual file
// there are as many entries in this array as the // there are as many entries in this array as the
@ -216,7 +254,7 @@ namespace libtorrent
std::vector<char const*> m_file_hashes; std::vector<char const*> m_file_hashes;
// for files that are symlinks, the symlink // for files that are symlinks, the symlink
// path_index in the file_entry indexes // path_index in the internal_file_entry indexes
// this vector of strings // this vector of strings
std::vector<std::string> m_symlinks; std::vector<std::string> m_symlinks;
@ -231,7 +269,7 @@ namespace libtorrent
// offsets) // offsets)
std::vector<size_type> m_file_base; std::vector<size_type> m_file_base;
// all unique paths files have. The file_entry::path_index // all unique paths files have. The internal_file_entry::path_index
// points into this array // points into this array
std::vector<std::string> m_paths; std::vector<std::string> m_paths;

View File

@ -302,7 +302,7 @@ namespace libtorrent
reverse_file_iterator rbegin_files() const { return m_files.rbegin(); } reverse_file_iterator rbegin_files() const { return m_files.rbegin(); }
reverse_file_iterator rend_files() const { return m_files.rend(); } reverse_file_iterator rend_files() const { return m_files.rend(); }
int num_files() const { return m_files.num_files(); } int num_files() const { return m_files.num_files(); }
file_entry const& file_at(int index) const { return m_files.at(index); } file_entry file_at(int index) const { return m_files.at(index); }
file_iterator file_at_offset(size_type offset) const file_iterator file_at_offset(size_type offset) const
{ return m_files.file_at_offset(offset); } { return m_files.file_at_offset(offset); }

View File

@ -118,7 +118,7 @@ namespace libtorrent
// return instead of crash in release mode // return instead of crash in release mode
if (fs.num_files() == 0) return; if (fs.num_files() == 0) return;
if (!m_multifile && has_parent_path(m_files.file_path(m_files.at(0)))) m_multifile = true; if (!m_multifile && has_parent_path(m_files.file_path(*m_files.begin()))) m_multifile = true;
// a piece_size of 0 means automatic // a piece_size of 0 means automatic
if (piece_size == 0 && !m_merkle_torrent) if (piece_size == 0 && !m_merkle_torrent)
@ -301,26 +301,26 @@ namespace libtorrent
if (!m_multifile) if (!m_multifile)
{ {
if (m_include_mtime) info["mtime"] = m_files.mtime(m_files.at(0)); file_entry e = m_files.at(0);
info["length"] = m_files.at(0).size; if (m_include_mtime) info["mtime"] = e.mtime;
if (m_files.at(0).pad_file info["length"] = e.size;
|| m_files.at(0).hidden_attribute if (e.pad_file
|| m_files.at(0).executable_attribute || e.hidden_attribute
|| m_files.at(0).symlink_attribute) || e.executable_attribute
|| e.symlink_attribute)
{ {
std::string& attr = info["attr"].string(); std::string& attr = info["attr"].string();
if (m_files.at(0).pad_file) attr += 'p'; if (e.pad_file) attr += 'p';
if (m_files.at(0).hidden_attribute) attr += 'h'; if (e.hidden_attribute) attr += 'h';
if (m_files.at(0).executable_attribute) attr += 'x'; if (e.executable_attribute) attr += 'x';
if (m_include_symlinks && m_files.at(0).symlink_attribute) attr += 'l'; if (m_include_symlinks && e.symlink_attribute) attr += 'l';
} }
if (m_include_symlinks if (m_include_symlinks
&& m_files.at(0).symlink_attribute && e.symlink_attribute)
&& m_files.at(0).symlink_index != -1)
{ {
entry& sympath_e = info["symlink path"]; entry& sympath_e = info["symlink path"];
std::string split = split_path(m_files.symlink(m_files.at(0))); std::string split = split_path(e.symlink_path);
for (char const* e = split.c_str(); e != 0; e = next_path_element(e)) for (char const* e = split.c_str(); e != 0; e = next_path_element(e))
sympath_e.list().push_back(entry(e)); sympath_e.list().push_back(entry(e));
} }

View File

@ -41,14 +41,14 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent namespace libtorrent
{ {
boost::intrusive_ptr<file> file_pool::open_file(void* st, std::string const& p boost::intrusive_ptr<file> file_pool::open_file(void* st, std::string const& p
, file_entry const& fe, file_storage const& fs, int m, error_code& ec) , file_storage::iterator fe, file_storage const& fs, int m, error_code& ec)
{ {
TORRENT_ASSERT(st != 0); TORRENT_ASSERT(st != 0);
TORRENT_ASSERT(is_complete(p)); TORRENT_ASSERT(is_complete(p));
TORRENT_ASSERT((m & file::rw_mask) == file::read_only TORRENT_ASSERT((m & file::rw_mask) == file::read_only
|| (m & file::rw_mask) == file::read_write); || (m & file::rw_mask) == file::read_write);
mutex::scoped_lock l(m_mutex); mutex::scoped_lock l(m_mutex);
file_set::iterator i = m_files.find(std::make_pair(st, fs.file_index(fe))); file_set::iterator i = m_files.find(std::make_pair(st, fs.file_index(*fe)));
if (i != m_files.end()) if (i != m_files.end())
{ {
lru_file_entry& e = i->second; lru_file_entry& e = i->second;
@ -77,7 +77,7 @@ namespace libtorrent
// the new read/write privilages // the new read/write privilages
TORRENT_ASSERT(e.file_ptr->refcount() == 1); TORRENT_ASSERT(e.file_ptr->refcount() == 1);
e.file_ptr->close(); e.file_ptr->close();
std::string full_path = combine_path(p, fs.file_path(fe)); std::string full_path = combine_path(p, fs.file_path(*fe));
if (!e.file_ptr->open(full_path, m, ec)) if (!e.file_ptr->open(full_path, m, ec))
{ {
m_files.erase(i); m_files.erase(i);
@ -115,12 +115,12 @@ namespace libtorrent
ec = error_code(ENOMEM, get_posix_category()); ec = error_code(ENOMEM, get_posix_category());
return e.file_ptr; return e.file_ptr;
} }
std::string full_path = combine_path(p, fs.file_path(fe)); std::string full_path = combine_path(p, fs.file_path(*fe));
if (!e.file_ptr->open(full_path, m, ec)) if (!e.file_ptr->open(full_path, m, ec))
return boost::intrusive_ptr<file>(); return boost::intrusive_ptr<file>();
e.mode = m; e.mode = m;
e.key = st; e.key = st;
m_files.insert(std::make_pair(std::make_pair(st, fs.file_index(fe)), e)); m_files.insert(std::make_pair(std::make_pair(st, fs.file_index(*fe)), e));
TORRENT_ASSERT(e.file_ptr->is_open()); TORRENT_ASSERT(e.file_ptr->is_open());
return e.file_ptr; return e.file_ptr;
} }

View File

@ -67,7 +67,7 @@ namespace libtorrent
return piece_length(); return piece_length();
} }
void file_storage::update_path_index(file_entry& e) void file_storage::update_path_index(internal_file_entry& e)
{ {
std::string parent = parent_path(e.filename()); std::string parent = parent_path(e.filename());
if (parent.empty()) if (parent.empty())
@ -95,9 +95,9 @@ namespace libtorrent
} }
} }
file_entry::~file_entry() { if (name_len == 0) free((void*)name); } internal_file_entry::~internal_file_entry() { if (name_len == 0) free((void*)name); }
file_entry::file_entry(file_entry const& fe) internal_file_entry::internal_file_entry(internal_file_entry const& fe)
: name(0) : name(0)
, offset(fe.offset) , offset(fe.offset)
, symlink_index(fe.symlink_index) , symlink_index(fe.symlink_index)
@ -112,7 +112,7 @@ namespace libtorrent
set_name(fe.name, fe.name_len); set_name(fe.name, fe.name_len);
} }
file_entry& file_entry::operator=(file_entry const& fe) internal_file_entry& internal_file_entry::operator=(internal_file_entry const& fe)
{ {
offset = fe.offset; offset = fe.offset;
size = fe.size; size = fe.size;
@ -126,7 +126,7 @@ namespace libtorrent
return *this; return *this;
} }
void file_entry::set_name(char const* n, int borrow_chars) void internal_file_entry::set_name(char const* n, int borrow_chars)
{ {
TORRENT_ASSERT(borrow_chars >= 0); TORRENT_ASSERT(borrow_chars >= 0);
if (borrow_chars > 1023) borrow_chars = 1023; if (borrow_chars > 1023) borrow_chars = 1023;
@ -143,7 +143,7 @@ namespace libtorrent
name_len = borrow_chars; name_len = borrow_chars;
} }
std::string file_entry::filename() const std::string internal_file_entry::filename() const
{ {
if (name_len) return std::string(name, name_len); if (name_len) return std::string(name, name_len);
return name ? name : ""; return name ? name : "";
@ -184,7 +184,7 @@ namespace libtorrent
namespace namespace
{ {
bool compare_file_offset(file_entry const& lhs, file_entry const& rhs) bool compare_file_offset(internal_file_entry const& lhs, internal_file_entry const& rhs)
{ {
return lhs.offset < rhs.offset; return lhs.offset < rhs.offset;
} }
@ -193,11 +193,11 @@ namespace libtorrent
file_storage::iterator file_storage::file_at_offset(size_type offset) const file_storage::iterator file_storage::file_at_offset(size_type offset) const
{ {
// find the file iterator and file offset // find the file iterator and file offset
file_entry target; internal_file_entry target;
target.offset = offset; target.offset = offset;
TORRENT_ASSERT(!compare_file_offset(target, m_files.front())); TORRENT_ASSERT(!compare_file_offset(target, m_files.front()));
std::vector<file_entry>::const_iterator file_iter = std::upper_bound( std::vector<internal_file_entry>::const_iterator file_iter = std::upper_bound(
begin(), end(), target, compare_file_offset); begin(), end(), target, compare_file_offset);
TORRENT_ASSERT(file_iter != begin()); TORRENT_ASSERT(file_iter != begin());
@ -214,12 +214,12 @@ namespace libtorrent
if (m_files.empty()) return ret; if (m_files.empty()) return ret;
// find the file iterator and file offset // find the file iterator and file offset
file_entry target; internal_file_entry target;
target.offset = piece * (size_type)m_piece_length + offset; target.offset = piece * (size_type)m_piece_length + offset;
TORRENT_ASSERT(target.offset + size <= m_total_size); TORRENT_ASSERT(target.offset + size <= m_total_size);
TORRENT_ASSERT(!compare_file_offset(target, m_files.front())); TORRENT_ASSERT(!compare_file_offset(target, m_files.front()));
std::vector<file_entry>::const_iterator file_iter = std::upper_bound( std::vector<internal_file_entry>::const_iterator file_iter = std::upper_bound(
begin(), end(), target, compare_file_offset); begin(), end(), target, compare_file_offset);
TORRENT_ASSERT(file_iter != begin()); TORRENT_ASSERT(file_iter != begin());
@ -244,8 +244,30 @@ namespace libtorrent
} }
return ret; return ret;
} }
std::string file_storage::file_path(file_entry const& fe) const file_entry file_storage::at(file_storage::iterator i) const
{ return at(i - begin()); }
file_entry file_storage::at(int index) const
{
TORRENT_ASSERT(index >= 0 && index < int(m_files.size()));
file_entry ret;
internal_file_entry const& ife = m_files[index];
ret.path = file_path(ife);
ret.offset = ife.offset;
ret.size = ife.size;
ret.file_base = file_base(ife);
ret.mtime = mtime(ife);
ret.pad_file = ife.pad_file;
ret.hidden_attribute = ife.hidden_attribute;
ret.executable_attribute = ife.executable_attribute;
ret.symlink_attribute = ife.symlink_attribute;
if (ife.symlink_index >= 0) ret.symlink_path = symlink(ife);
ret.filehash = hash(ife);
return ret;
}
std::string file_storage::file_path(internal_file_entry const& fe) const
{ {
TORRENT_ASSERT(fe.path_index >= -1 && fe.path_index < int(m_paths.size())); TORRENT_ASSERT(fe.path_index >= -1 && fe.path_index < int(m_paths.size()));
if (fe.path_index == -1) return fe.filename(); if (fe.path_index == -1) return fe.filename();
@ -285,8 +307,8 @@ namespace libtorrent
m_name = split_path(file).c_str(); m_name = split_path(file).c_str();
} }
TORRENT_ASSERT(m_name == split_path(file).c_str()); TORRENT_ASSERT(m_name == split_path(file).c_str());
m_files.push_back(file_entry()); m_files.push_back(internal_file_entry());
file_entry& e = m_files.back(); internal_file_entry& e = m_files.back();
e.set_name(file.c_str()); e.set_name(file.c_str());
e.size = size; e.size = size;
e.offset = m_total_size; e.offset = m_total_size;
@ -309,25 +331,25 @@ namespace libtorrent
m_total_size += size; m_total_size += size;
} }
void file_storage::add_file(file_entry const& ent, char const* filehash void file_storage::add_file(file_entry const& ent, char const* filehash)
, std::string const* symlink, time_t mtime)
{ {
if (!has_parent_path(ent.filename())) if (!has_parent_path(ent.path))
{ {
// you have already added at least one file with a // you have already added at least one file with a
// path to the file (branch_path), which means that // path to the file (branch_path), which means that
// all the other files need to be in the same top // all the other files need to be in the same top
// directory as the first file. // directory as the first file.
TORRENT_ASSERT(m_files.empty()); TORRENT_ASSERT(m_files.empty());
m_name = ent.filename(); m_name = ent.path;
} }
else else
{ {
if (m_files.empty()) if (m_files.empty())
m_name = split_path(ent.filename()).c_str(); m_name = split_path(ent.path).c_str();
} }
m_files.push_back(ent); internal_file_entry ife(ent);
file_entry& e = m_files.back(); m_files.push_back(ife);
internal_file_entry& e = m_files.back();
e.offset = m_total_size; e.offset = m_total_size;
m_total_size += ent.size; m_total_size += ent.size;
if (filehash) if (filehash)
@ -335,47 +357,48 @@ namespace libtorrent
if (m_file_hashes.size() < m_files.size()) m_file_hashes.resize(m_files.size()); if (m_file_hashes.size() < m_files.size()) m_file_hashes.resize(m_files.size());
m_file_hashes[m_files.size() - 1] = filehash; m_file_hashes[m_files.size() - 1] = filehash;
} }
if (symlink) if (!ent.symlink_path.empty())
{ {
e.symlink_index = m_symlinks.size(); e.symlink_index = m_symlinks.size();
m_symlinks.push_back(*symlink); m_symlinks.push_back(ent.symlink_path);
} }
if (mtime) if (ent.mtime)
{ {
if (m_mtime.size() < m_files.size()) m_mtime.resize(m_files.size()); if (m_mtime.size() < m_files.size()) m_mtime.resize(m_files.size());
m_mtime[m_files.size() - 1] = mtime; m_mtime[m_files.size() - 1] = ent.mtime;
} }
if (ent.file_base) set_file_base(e, ent.file_base);
update_path_index(e); update_path_index(e);
} }
sha1_hash file_storage::hash(file_entry const& fe) const sha1_hash file_storage::hash(internal_file_entry const& fe) const
{ {
int index = &fe - &m_files[0]; int index = &fe - &m_files[0];
if (index >= m_file_hashes.size()) return sha1_hash(0); if (index >= m_file_hashes.size()) return sha1_hash(0);
return sha1_hash(m_file_hashes[index]); return sha1_hash(m_file_hashes[index]);
} }
std::string const& file_storage::symlink(file_entry const& fe) const std::string const& file_storage::symlink(internal_file_entry const& fe) const
{ {
TORRENT_ASSERT(fe.symlink_index < int(m_symlinks.size())); TORRENT_ASSERT(fe.symlink_index < int(m_symlinks.size()));
return m_symlinks[fe.symlink_index]; return m_symlinks[fe.symlink_index];
} }
time_t file_storage::mtime(file_entry const& fe) const time_t file_storage::mtime(internal_file_entry const& fe) const
{ {
int index = &fe - &m_files[0]; int index = &fe - &m_files[0];
if (index >= m_mtime.size()) return 0; if (index >= m_mtime.size()) return 0;
return m_mtime[index]; return m_mtime[index];
} }
int file_storage::file_index(file_entry const& fe) const int file_storage::file_index(internal_file_entry const& fe) const
{ {
int index = &fe - &m_files[0]; int index = &fe - &m_files[0];
TORRENT_ASSERT(index >= 0 && index < m_files.size()); TORRENT_ASSERT(index >= 0 && index < m_files.size());
return index; return index;
} }
void file_storage::set_file_base(file_entry const& fe, size_type off) void file_storage::set_file_base(internal_file_entry const& fe, size_type off)
{ {
int index = &fe - &m_files[0]; int index = &fe - &m_files[0];
TORRENT_ASSERT(index >= 0 && index < m_files.size()); TORRENT_ASSERT(index >= 0 && index < m_files.size());
@ -383,19 +406,19 @@ namespace libtorrent
m_file_base[index] = off; m_file_base[index] = off;
} }
size_type file_storage::file_base(file_entry const& fe) const size_type file_storage::file_base(internal_file_entry const& fe) const
{ {
int index = &fe - &m_files[0]; int index = &fe - &m_files[0];
if (index >= m_file_base.size()) return 0; if (index >= m_file_base.size()) return 0;
return m_file_base[index]; return m_file_base[index];
} }
bool compare_file_entry_size(file_entry const& fe1, file_entry const& fe2) bool compare_file_entry_size(internal_file_entry const& fe1, internal_file_entry const& fe2)
{ return fe1.size < fe2.size; } { return fe1.size < fe2.size; }
void file_storage::reorder_file(int index, int dst) void file_storage::reorder_file(int index, int dst)
{ {
file_entry e = m_files[index]; internal_file_entry e = m_files[index];
m_files.erase(m_files.begin() + index); m_files.erase(m_files.begin() + index);
m_files.insert(m_files.begin() + dst, e); m_files.insert(m_files.begin() + dst, e);
if (!m_mtime.empty()) if (!m_mtime.empty())
@ -443,7 +466,7 @@ namespace libtorrent
// put the largest file at the front, to make sure // put the largest file at the front, to make sure
// it's aligned // it's aligned
std::vector<file_entry>::iterator i = std::max_element(m_files.begin(), m_files.end() std::vector<internal_file_entry>::iterator i = std::max_element(m_files.begin(), m_files.end()
, &compare_file_entry_size); , &compare_file_entry_size);
int index = file_index(*i); int index = file_index(*i);
@ -451,7 +474,7 @@ namespace libtorrent
size_type off = 0; size_type off = 0;
int padding_file = 0; int padding_file = 0;
for (std::vector<file_entry>::iterator i = m_files.begin(); for (std::vector<internal_file_entry>::iterator i = m_files.begin();
i != m_files.end(); ++i) i != m_files.end(); ++i)
{ {
if (pad_file_limit >= 0 if (pad_file_limit >= 0
@ -466,8 +489,8 @@ namespace libtorrent
int pad_size = alignment - (off & (alignment-1)); int pad_size = alignment - (off & (alignment-1));
// find the largest file that fits in pad_size // find the largest file that fits in pad_size
std::vector<file_entry>::iterator best_match = m_files.end(); std::vector<internal_file_entry>::iterator best_match = m_files.end();
for (std::vector<file_entry>::iterator j = i+1; j < m_files.end(); ++j) for (std::vector<internal_file_entry>::iterator j = i+1; j < m_files.end(); ++j)
{ {
if (j->size > pad_size) continue; if (j->size > pad_size) continue;
if (best_match == m_files.end() || j->size > best_match->size) if (best_match == m_files.end() || j->size > best_match->size)
@ -488,7 +511,7 @@ namespace libtorrent
// we could not find a file that fits in pad_size // we could not find a file that fits in pad_size
// add a padding file // add a padding file
file_entry e; internal_file_entry e;
i = m_files.insert(i, e); i = m_files.insert(i, e);
i->size = pad_size; i->size = pad_size;
i->offset = off; i->offset = off;

View File

@ -409,7 +409,8 @@ namespace libtorrent
file_storage const& m_files; file_storage const& m_files;
// helper function to open a file in the file pool with the right mode // helper function to open a file in the file pool with the right mode
boost::intrusive_ptr<file> open_file(file_entry const& fe, int mode, error_code& ec) const; boost::intrusive_ptr<file> open_file(file_storage::iterator fe, int mode
, error_code& ec) const;
std::vector<boost::uint8_t> m_file_priority; std::vector<boost::uint8_t> m_file_priority;
std::string m_save_path; std::string m_save_path;
@ -553,7 +554,7 @@ namespace libtorrent
if (ec || s.file_size > file_iter->size || file_iter->size == 0) if (ec || s.file_size > file_iter->size || file_iter->size == 0)
{ {
ec.clear(); ec.clear();
boost::intrusive_ptr<file> f = open_file(*file_iter, file::read_write, ec); boost::intrusive_ptr<file> f = open_file(file_iter, file::read_write, ec);
if (ec) set_error(file_path, ec); if (ec) set_error(file_path, ec);
else if (f) else if (f)
{ {
@ -577,7 +578,7 @@ namespace libtorrent
if (index < 0 || index >= m_files.num_files()) return; if (index < 0 || index >= m_files.num_files()) return;
error_code ec; error_code ec;
boost::intrusive_ptr<file> f = open_file(files().at(index), file::read_write, ec); boost::intrusive_ptr<file> f = open_file(files().begin() + index, file::read_write, ec);
if (ec || !f) return; if (ec || !f) return;
f->finalize(); f->finalize();
@ -702,7 +703,7 @@ namespace libtorrent
TORRENT_ASSERT(slot < m_files.num_pieces()); TORRENT_ASSERT(slot < m_files.num_pieces());
size_type file_offset = (size_type)slot * m_files.piece_length(); size_type file_offset = (size_type)slot * m_files.piece_length();
std::vector<file_entry>::const_iterator file_iter; file_storage::iterator file_iter;
for (file_iter = files().begin();;) for (file_iter = files().begin();;)
{ {
@ -715,7 +716,7 @@ namespace libtorrent
} }
error_code ec; error_code ec;
boost::intrusive_ptr<file> file_handle = open_file(*file_iter, file::read_only, ec); boost::intrusive_ptr<file> file_handle = open_file(file_iter, file::read_only, ec);
if (!file_handle || ec) return slot; if (!file_handle || ec) return slot;
size_type data_start = file_handle->sparse_end(file_offset); size_type data_start = file_handle->sparse_end(file_offset);
@ -1057,7 +1058,7 @@ ret:
// open the file read only to avoid re-opening // open the file read only to avoid re-opening
// it in case it's already opened in read-only mode // it in case it's already opened in read-only mode
error_code ec; error_code ec;
boost::intrusive_ptr<file> f = open_file(*file_iter, file::read_only, ec); boost::intrusive_ptr<file> f = open_file(file_iter, file::read_only, ec);
size_type ret = 0; size_type ret = 0;
if (f && !ec) ret = f->phys_offset(file_offset); if (f && !ec) ret = f->phys_offset(file_offset);
@ -1130,7 +1131,7 @@ ret:
// find the file iterator and file offset // find the file iterator and file offset
size_type file_offset = start; size_type file_offset = start;
std::vector<file_entry>::const_iterator file_iter; file_storage::iterator file_iter;
for (file_iter = files().begin();;) for (file_iter = files().begin();;)
{ {
@ -1179,8 +1180,8 @@ ret:
TORRENT_ASSERT(int(slices.size()) > counter); TORRENT_ASSERT(int(slices.size()) > counter);
size_type slice_size = slices[counter].size; size_type slice_size = slices[counter].size;
TORRENT_ASSERT(slice_size == file_bytes_left); TORRENT_ASSERT(slice_size == file_bytes_left);
TORRENT_ASSERT(&files().at(slices[counter].file_index) TORRENT_ASSERT((files().begin() + slices[counter].file_index)
== &*file_iter); == file_iter);
++counter; ++counter;
#endif #endif
@ -1199,7 +1200,7 @@ ret:
} }
error_code ec; error_code ec;
file_handle = open_file(*file_iter, op.mode, ec); file_handle = open_file(file_iter, op.mode, ec);
if (!file_handle || ec) if (!file_handle || ec)
{ {
std::string path = combine_path(m_save_path, files().file_path(*file_iter)); std::string path = combine_path(m_save_path, files().file_path(*file_iter));
@ -1309,12 +1310,13 @@ ret:
return readv(&b, slot, offset, 1); return readv(&b, slot, offset, 1);
} }
boost::intrusive_ptr<file> storage::open_file(file_entry const& fe, int mode, error_code& ec) const boost::intrusive_ptr<file> storage::open_file(file_storage::iterator fe, int mode
, error_code& ec) const
{ {
int cache_setting = m_settings ? settings().disk_io_write_mode : 0; int cache_setting = m_settings ? settings().disk_io_write_mode : 0;
if (cache_setting == session_settings::disable_os_cache if (cache_setting == session_settings::disable_os_cache
|| (cache_setting == session_settings::disable_os_cache_for_aligned_files || (cache_setting == session_settings::disable_os_cache_for_aligned_files
&& ((fe.offset + files().file_base(fe)) & (m_page_size-1)) == 0)) && ((fe->offset + files().file_base(*fe)) & (m_page_size-1)) == 0))
mode |= file::no_buffer; mode |= file::no_buffer;
if (!m_allocate_files) mode |= file::sparse; if (!m_allocate_files) mode |= file::sparse;
if (m_settings && settings().no_atime_storage) mode |= file::no_atime; if (m_settings && settings().no_atime_storage) mode |= file::no_atime;

View File

@ -182,12 +182,6 @@ namespace libtorrent
return valid_encoding; return valid_encoding;
} }
void verify_encoding(file_entry& target)
{
std::string p = target.filename();
if (!verify_encoding(p, true)) target.set_name(p.c_str());
}
// TODO: should this take a char const*? // TODO: should this take a char const*?
bool valid_path_element(std::string const& element) bool valid_path_element(std::string const& element)
{ {
@ -233,7 +227,7 @@ namespace libtorrent
} }
bool extract_single_file(lazy_entry const& dict, file_entry& target bool extract_single_file(lazy_entry const& dict, file_entry& target
, std::string const& root_dir, lazy_entry const** filehash, std::string* symlink , std::string const& root_dir, lazy_entry const** filehash
, lazy_entry const** filename, time_t* mtime) , lazy_entry const** filename, time_t* mtime)
{ {
if (dict.type() != lazy_entry::dict_t) return false; if (dict.type() != lazy_entry::dict_t) return false;
@ -266,13 +260,13 @@ namespace libtorrent
path = combine_path(path, path_element); path = combine_path(path, path_element);
} }
path = sanitize_path(path); path = sanitize_path(path);
verify_encoding(target); verify_encoding(path, true);
// bitcomet pad file // bitcomet pad file
if (path.find("_____padding_file_") != std::string::npos) if (path.find("_____padding_file_") != std::string::npos)
target.pad_file = true; target.pad_file = true;
target.set_name(path.c_str()); target.path = path;
lazy_entry const* attr = dict.dict_find_string("attr"); lazy_entry const* attr = dict.dict_find_string("attr");
if (attr) if (attr)
@ -300,10 +294,8 @@ namespace libtorrent
{ {
std::string path_element = s_p->list_at(i)->string_value(); std::string path_element = s_p->list_at(i)->string_value();
trim_path_element(path_element); trim_path_element(path_element);
*symlink = combine_path(*symlink, path_element); target.symlink_path = combine_path(target.symlink_path, path_element);
} }
// indeicate that we have a symlink
target.symlink_index = 0;
} }
return true; return true;
@ -339,11 +331,10 @@ namespace libtorrent
{ {
lazy_entry const* file_hash = 0; lazy_entry const* file_hash = 0;
time_t mtime = 0; time_t mtime = 0;
std::string symlink;
file_entry e; file_entry e;
lazy_entry const* fee = 0; lazy_entry const* fee = 0;
if (!extract_single_file(*list.list_at(i), e, root_dir if (!extract_single_file(*list.list_at(i), e, root_dir
, &file_hash, &symlink, &fee, &mtime)) , &file_hash, &fee, &mtime))
return false; return false;
// TODO: this logic should be a separate step // TODO: this logic should be a separate step
@ -354,22 +345,19 @@ namespace libtorrent
// as long as this file already exists // as long as this file already exists
// increase the counter // increase the counter
std::string path = e.filename(); while (!files.insert(e.path).second)
while (!files.insert(path).second)
{ {
++cnt; ++cnt;
char suffix[50]; char suffix[50];
snprintf(suffix, sizeof(suffix), ".%d%s", cnt, extension(path).c_str()); snprintf(suffix, sizeof(suffix), ".%d%s", cnt, extension(e.path).c_str());
replace_extension(path, suffix); replace_extension(e.path, suffix);
} }
e.set_name(path.c_str()); target.add_file(e, file_hash ? file_hash->string_ptr() + info_ptr_diff : 0);
target.add_file(e, file_hash ? file_hash->string_ptr() + info_ptr_diff : 0
, e.symlink_index != -1 ? &symlink : 0, mtime);
// This is a memory optimization! Instead of having // This is a memory optimization! Instead of having
// each entry keep a string for its filename, make it // each entry keep a string for its filename, make it
// simply point into the info-section buffer // simply point into the info-section buffer
file_entry const& fe = target.at(target.num_files() - 1); internal_file_entry const& fe = *target.rbegin();
// TODO: once the filename renaming is removed from here // TODO: once the filename renaming is removed from here
// this check can be removed as well // this check can be removed as well
if (fee && fe.filename() == fee->string_value()) if (fee && fe.filename() == fee->string_value())
@ -377,7 +365,7 @@ namespace libtorrent
// this string pointer does not necessarily point into // this string pointer does not necessarily point into
// the m_info_section buffer. // the m_info_section buffer.
char const* str_ptr = fee->string_ptr() + info_ptr_diff; char const* str_ptr = fee->string_ptr() + info_ptr_diff;
const_cast<file_entry&>(fe).set_name(str_ptr, fee->string_length()); const_cast<internal_file_entry&>(fe).set_name(str_ptr, fee->string_length());
} }
} }
return true; return true;
@ -807,12 +795,10 @@ namespace libtorrent
// if there's no list of files, there has to be a length // if there's no list of files, there has to be a length
// field. // field.
file_entry e; file_entry e;
e.set_name(name.c_str()); e.path = name;
e.offset = 0; e.offset = 0;
e.size = info.dict_find_int_value("length", -1); e.size = info.dict_find_int_value("length", -1);
size_type ts = info.dict_find_int_value("mtime", -1); e.mtime = info.dict_find_int_value("mtime", 0);
time_t mtime = 0;
if (ts > 0) mtime = std::time_t(ts);
lazy_entry const* attr = info.dict_find_string("attr"); lazy_entry const* attr = info.dict_find_string("attr");
if (attr) if (attr)
{ {
@ -829,30 +815,27 @@ namespace libtorrent
} }
lazy_entry const* s_p = info.dict_find("symlink path"); lazy_entry const* s_p = info.dict_find("symlink path");
std::string symlink;
if (s_p != 0 && s_p->type() == lazy_entry::list_t) if (s_p != 0 && s_p->type() == lazy_entry::list_t)
{ {
for (int i = 0, end(s_p->list_size()); i < end; ++i) for (int i = 0, end(s_p->list_size()); i < end; ++i)
{ {
std::string path_element = s_p->list_at(i)->string_value(); std::string path_element = s_p->list_at(i)->string_value();
trim_path_element(path_element); trim_path_element(path_element);
symlink = combine_path(symlink, path_element); e.symlink_path = combine_path(e.symlink_path, path_element);
} }
e.symlink_index = 0;
} }
lazy_entry const* fh = info.dict_find_string("sha1"); lazy_entry const* fh = info.dict_find_string("sha1");
if (fh && fh->string_length() != 20) fh = 0; if (fh && fh->string_length() != 20) fh = 0;
// bitcomet pad file // bitcomet pad file
if (e.filename().find("_____padding_file_") != std::string::npos) if (e.path.find("_____padding_file_") != std::string::npos)
e.pad_file = true; e.pad_file = true;
if (e.size < 0) if (e.size < 0)
{ {
ec = errors::torrent_invalid_length; ec = errors::torrent_invalid_length;
return false; return false;
} }
m_files.add_file(e, fh ? fh->string_ptr() + info_ptr_diff : 0 m_files.add_file(e, fh ? fh->string_ptr() + info_ptr_diff : 0);
, e.symlink_index != -1 ? &symlink : 0, mtime);
m_multifile = false; m_multifile = false;
} }
else else

View File

@ -257,11 +257,11 @@ int run_suite(char const* protocol, bool test_url_seed, bool chunked_encoding)
// verify that the file hashes are correct // verify that the file hashes are correct
for (int i = 0; i < torrent_file->num_files(); ++i) for (int i = 0; i < torrent_file->num_files(); ++i)
{ {
sha1_hash h1 = torrent_file->files().hash(torrent_file->file_at(i)); sha1_hash h1 = torrent_file->file_at(i).filehash;
sha1_hash h2 = file_hash(combine_path("./tmp1_web_seed" sha1_hash h2 = file_hash(combine_path("./tmp1_web_seed"
, torrent_file->files().file_path(torrent_file->file_at(i)))); , torrent_file->file_at(i).path));
fprintf(stderr, "%s: %s == %s\n" fprintf(stderr, "%s: %s == %s\n"
, torrent_file->files().file_path(torrent_file->file_at(i)).c_str() , torrent_file->file_at(i).path.c_str()
, to_hex(h1.to_string()).c_str(), to_hex(h2.to_string()).c_str()); , to_hex(h1.to_string()).c_str(), to_hex(h2.to_string()).c_str());
TEST_EQUAL(h1, h2); TEST_EQUAL(h1, h2);
} }