diff --git a/docs/manual.rst b/docs/manual.rst index 73e4574e1..03a28de53 100755 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -2243,6 +2243,15 @@ The file format is a bencoded dictionary containing the following fields: | | +-------------+--------------------------------------------+ | | | | +----------------------+--------------------------------------------------------------+ +| ``file sizes`` | list where each entry corresponds to a file in the file list | +| | in the metadata. Each entry has a list of two values, the | +| | first value is the size of the file in bytes, the second | +| | is the timestamp when the last time someone wrote to it. | +| | This information is used to compare with the files on disk. | +| | All the files must match exactly this information in order | +| | to consider the resume data as current. Otherwise a full | +| | re-check is issued. | ++----------------------+--------------------------------------------------------------+ extensions diff --git a/include/libtorrent/storage.hpp b/include/libtorrent/storage.hpp index 50d859c24..f15bafffe 100755 --- a/include/libtorrent/storage.hpp +++ b/include/libtorrent/storage.hpp @@ -61,14 +61,14 @@ namespace libtorrent class session; - std::vector get_filesizes( + std::vector > get_filesizes( torrent_info const& t , boost::filesystem::path p); bool match_filesizes( torrent_info const& t , boost::filesystem::path p - , std::vector const& sizes); + , std::vector > const& sizes); struct file_allocation_failed: std::exception { diff --git a/src/session.cpp b/src/session.cpp index a735441a4..f5dc5d6d4 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -1311,25 +1311,16 @@ namespace libtorrent // verify file sizes - std::vector file_sizes; + std::vector > file_sizes; entry::list_type& l = rd["file sizes"].list(); -#if defined(_MSC_VER) && _MSC_VER < 1300 for (entry::list_type::iterator i = l.begin(); - i != l.end(); - ++i) + i != l.end(); ++i) { - file_sizes.push_back(i->integer()); + file_sizes.push_back(std::pair( + i->list().front().integer() + , i->list().back().integer())); } -#else - typedef entry::integer_type const& (entry::*mem_fun_type)() const; - - std::transform( - l.begin() - , l.end() - , std::back_inserter(file_sizes) - , boost::bind((mem_fun_type)&entry::integer, _1)); -#endif if ((int)tmp_pieces.size() == info.num_pieces() && std::find_if(tmp_pieces.begin(), tmp_pieces.end() @@ -1338,13 +1329,14 @@ namespace libtorrent if (info.num_files() != (int)file_sizes.size()) return; - std::vector::iterator fs = file_sizes.begin(); + std::vector >::iterator + fs = file_sizes.begin(); // the resume data says we have the entire torrent // make sure the file sizes are the right ones for (torrent_info::file_iterator i = info.begin_files() , end(info.end_files()); i != end; ++i, ++fs) { - if (i->size != *fs) return; + if (i->size != fs->first) return; } } diff --git a/src/storage.cpp b/src/storage.cpp index ac1a08b5e..d8d1ce504 100755 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -52,6 +52,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #ifdef _MSC_VER #pragma warning(pop) @@ -74,6 +75,14 @@ namespace std } #endif +#if BOOST_VERSION < 103200 +bool operator<(boost::filesystem::path const& lhs + , boost::filesystem::path const& rhs) +{ + return lhs.string() < rhs.string(); +} +#endif + using namespace boost::filesystem; namespace pt = boost::posix_time; using boost::bind; @@ -160,28 +169,26 @@ namespace namespace libtorrent { - std::vector get_filesizes( + std::vector > get_filesizes( const torrent_info& t , path p) { p = complete(p); - std::vector sizes; + std::vector > sizes; for (torrent_info::file_iterator i = t.begin_files(); i != t.end_files(); ++i) { - size_type file_size; + size_type size = 0; + std::time_t time = 0; try { - file f(p / get_filename(t, i->path), file::in); - f.seek(0, file::end); - file_size = f.tell(); + path f = p / get_filename(t, i->path); + size = file_size(f); + time = last_write_time(f); } - catch (file_error&) - { - file_size = 0; - } - sizes.push_back(file_size); + catch (file_error&) {} + sizes.push_back(std::make_pair(size, time)); } return sizes; } @@ -189,28 +196,28 @@ namespace libtorrent bool match_filesizes( torrent_info const& t , path p - , std::vector const& sizes) + , std::vector > const& sizes) { if ((int)sizes.size() != t.num_files()) return false; p = complete(p); - std::vector::const_iterator s = sizes.begin(); + std::vector >::const_iterator s + = sizes.begin(); for (torrent_info::file_iterator i = t.begin_files(); i != t.end_files(); ++i, ++s) { - size_type file_size; + size_type size = 0; + std::time_t time = 0; try { - file f(p / get_filename(t, i->path), file::in); - f.seek(0, file::end); - file_size = f.tell(); + path f = p / get_filename(t, i->path); + size = file_size(f); + time = last_write_time(f); } - catch (file_error&) - { - file_size = 0; - } - if (file_size != *s) return false; + catch (file_error&) {} + if (size != s->first || time != s->second) + return false; } return true; } diff --git a/src/torrent_handle.cpp b/src/torrent_handle.cpp index 6c90efe61..47685159f 100755 --- a/src/torrent_handle.cpp +++ b/src/torrent_handle.cpp @@ -464,14 +464,19 @@ namespace libtorrent peer_list.push_back(peer); } - std::vector file_sizes + std::vector > file_sizes = get_filesizes(t->torrent_file(), t->save_path()); ret["file sizes"] = entry::list_type(); - std::copy( - file_sizes.begin() - , file_sizes.end() - , std::back_inserter(ret["file sizes"].list())); + entry::list_type& fl = ret["file sizes"].list(); + for (std::vector >::iterator i + = file_sizes.begin(), end(file_sizes.end()); i != end; ++i) + { + entry::list_type p; + p.push_back(entry(i->first)); + p.push_back(entry(i->second)); + fl.push_back(entry(p)); + } return ret; }