added support for preserving modification time of files in torrents

This commit is contained in:
Arvid Norberg 2009-06-23 02:50:41 +00:00
parent 3e3c60b1ca
commit 5de60fad78
5 changed files with 86 additions and 12 deletions

View File

@ -161,6 +161,9 @@ namespace libtorrent
int TORRENT_EXPORT get_file_attributes(boost::filesystem::path const& p); int TORRENT_EXPORT get_file_attributes(boost::filesystem::path const& p);
int TORRENT_EXPORT get_file_attributes(boost::filesystem::wpath const& p); int TORRENT_EXPORT get_file_attributes(boost::filesystem::wpath const& p);
std::time_t TORRENT_EXPORT get_file_mtime(boost::filesystem::path const& p);
std::time_t TORRENT_EXPORT get_file_mtime(boost::filesystem::wpath const& p);
template <class Pred, class Str, class PathTraits> template <class Pred, class Str, class PathTraits>
void add_files_impl(file_storage& fs, boost::filesystem::basic_path<Str, PathTraits> const& p void add_files_impl(file_storage& fs, boost::filesystem::basic_path<Str, PathTraits> const& p
, boost::filesystem::basic_path<Str, PathTraits> const& l, Pred pred) , boost::filesystem::basic_path<Str, PathTraits> const& l, Pred pred)
@ -187,7 +190,8 @@ namespace libtorrent
else else
{ {
int file_flags = get_file_attributes(f); int file_flags = get_file_attributes(f);
fs.add_file(l, file_size(f), file_flags); std::time_t mtime = get_file_mtime(f);
fs.add_file(l, file_size(f), file_flags, mtime);
} }
} }
} }
@ -349,4 +353,3 @@ namespace libtorrent
} }
#endif #endif

View File

@ -67,6 +67,7 @@ namespace libtorrent
// This is always 0 unless parts of the torrent is // This is always 0 unless parts of the torrent is
// compressed into a single file, such as a so-called part file. // compressed into a single file, such as a so-called part file.
size_type file_base; size_type file_base;
std::time_t mtime;
bool pad_file:1; bool pad_file:1;
bool hidden_attribute:1; bool hidden_attribute:1;
bool executable_attribute:1; bool executable_attribute:1;
@ -96,11 +97,11 @@ namespace libtorrent
}; };
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(fs::path const& p, size_type size, int flags = 0, std::time_t mtime = 0);
void rename_file(int index, std::string const& new_filename); void rename_file(int index, std::string const& new_filename);
#ifndef BOOST_FILESYSTEM_NARROW_ONLY #ifndef BOOST_FILESYSTEM_NARROW_ONLY
void add_file(fs::wpath const& p, size_type size, int flags = 0); void add_file(fs::wpath const& p, size_type size, int flags = 0, std::time_t mtime = 0);
void rename_file(int index, std::wstring const& new_filename); void rename_file(int index, std::wstring const& new_filename);
void set_name(std::wstring const& n); void set_name(std::wstring const& n);
#endif #endif

View File

@ -33,6 +33,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/create_torrent.hpp" #include "libtorrent/create_torrent.hpp"
#include "libtorrent/file_pool.hpp" #include "libtorrent/file_pool.hpp"
#include "libtorrent/storage.hpp" #include "libtorrent/storage.hpp"
#include "libtorrent/escape_string.hpp"
#include <boost/date_time/posix_time/posix_time.hpp> #include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/gregorian/gregorian.hpp> #include <boost/date_time/gregorian/gregorian.hpp>
@ -59,7 +60,7 @@ namespace libtorrent
{ {
#ifdef TORRENT_WINDOWS #ifdef TORRENT_WINDOWS
#ifdef TORRENT_USE_WPATH #if TORRENT_USE_WPATH
std::wstring path = convert_to_wstring(p.external_file_string()); std::wstring path = convert_to_wstring(p.external_file_string());
DWORD attr = GetFileAttributesW(path.c_str()); DWORD attr = GetFileAttributesW(path.c_str());
#else #else
@ -82,12 +83,53 @@ namespace libtorrent
DWORD attr = GetFileAttributesW(path.c_str()); DWORD attr = GetFileAttributesW(path.c_str());
if (attr & FILE_ATTRIBUTE_HIDDEN) return file_storage::attribute_hidden; if (attr & FILE_ATTRIBUTE_HIDDEN) return file_storage::attribute_hidden;
return 0; return 0;
#else
std::string native;
wchar_utf8(p.string(), native);
native = convert_to_native(native);
struct stat s;
if (stat(native.c_str(), &s) < 0) return 0;
return (s.st_mode & S_IXUSR) ? file_storage::attribute_executable : 0;
#endif
}
std::time_t get_file_mtime(char const* path)
{
#ifdef TORRENT_WINDOWS
struct _stat s;
if (::_stat(path, &s) < 0) return 0;
#else
struct stat s;
if (lstat(path, &s) < 0) return 0;
#endif
return s.st_mtime;
}
std::time_t TORRENT_EXPORT get_file_mtime(boost::filesystem::path const& p)
{
#if defined TORRENT_WINDOWS && TORRENT_USE_WPATH
std::wstring path = convert_to_wstring(p.external_file_string());
struct _stat s;
if (::_wstat(path.c_str(), &s) < 0) return 0;
return s.st_mtime;
#else
std::string path = convert_to_native(p.external_file_string());
return get_file_mtime(p.string().c_str());
#endif
}
std::time_t TORRENT_EXPORT get_file_mtime(boost::filesystem::wpath const& p)
{
#ifdef TORRENT_WINDOWS
struct _stat s;
if (::_wstat(p.string().c_str(), &s) < 0) return 0;
return s.st_mtime;
#else #else
std::string utf8; std::string utf8;
wchar_utf8(p.string(), utf8); wchar_utf8(p.string(), utf8);
struct stat s; utf8 = convert_to_native(utf8);
if (stat(utf8.c_str(), &s) < 0) return 0; return get_file_mtime(utf8.c_str());
return (s.st_mode & S_IXUSR) ? file_storage::attribute_executable : 0;
#endif #endif
} }
} }
@ -263,7 +305,15 @@ namespace libtorrent
if (!m_multifile) if (!m_multifile)
{ {
info["mtime"] = m_files.at(0).mtime;
info["length"] = m_files.at(0).size; info["length"] = m_files.at(0).size;
if (m_files.at(0).pad_file || m_files.at(0).hidden_attribute || m_files.at(0).executable_attribute)
{
std::string& attr = info["attr"].string();
if (m_files.at(0).pad_file) attr += 'p';
if (m_files.at(0).hidden_attribute) attr += 'h';
if (m_files.at(0).executable_attribute) attr += 'x';
}
} }
else else
{ {
@ -276,6 +326,7 @@ namespace libtorrent
{ {
files.list().push_back(entry()); files.list().push_back(entry());
entry& file_e = files.list().back(); entry& file_e = files.list().back();
file_e["mtime"] = i->mtime;
file_e["length"] = i->size; file_e["length"] = i->size;
entry& path_e = file_e["path"]; entry& path_e = file_e["path"];

View File

@ -37,7 +37,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <cstdio> #include <cstdio>
namespace libtorrent namespace libtorrent
{ {
file_storage::file_storage() file_storage::file_storage()
@ -77,11 +76,11 @@ namespace libtorrent
m_files[index].path = utf8; m_files[index].path = utf8;
} }
void file_storage::add_file(fs::wpath const& file, size_type size, int flags) void file_storage::add_file(fs::wpath const& file, size_type size, int flags, std::time_t mtime)
{ {
std::string utf8; std::string utf8;
wchar_utf8(file.string(), utf8); wchar_utf8(file.string(), utf8);
add_file(utf8, size, flags); add_file(utf8, size, flags, mtime);
} }
#endif #endif
@ -165,7 +164,7 @@ namespace libtorrent
return ret; return ret;
} }
void file_storage::add_file(fs::path const& file, size_type size, int flags) void file_storage::add_file(fs::path const& file, size_type size, int flags, std::time_t mtime)
{ {
TORRENT_ASSERT(size >= 0); TORRENT_ASSERT(size >= 0);
#if BOOST_VERSION < 103600 #if BOOST_VERSION < 103600
@ -195,6 +194,7 @@ namespace libtorrent
e.pad_file = bool(flags & pad_file); e.pad_file = bool(flags & pad_file);
e.hidden_attribute = bool(flags & attribute_hidden); e.hidden_attribute = bool(flags & attribute_hidden);
e.executable_attribute = bool(flags & attribute_executable); e.executable_attribute = bool(flags & attribute_executable);
e.mtime = mtime;
m_total_size += size; m_total_size += size;
} }

View File

@ -223,6 +223,9 @@ namespace libtorrent
target.path = root_dir; target.path = root_dir;
target.file_base = 0; target.file_base = 0;
size_type ts = dict.dict_find_int_value("mtime", -1);
if (ts >= 0) target.mtime = std::time_t(ts);
// prefer the name.utf-8 // prefer the name.utf-8
// because if it exists, it is more // because if it exists, it is more
// likely to be correctly encoded // likely to be correctly encoded
@ -612,6 +615,22 @@ namespace libtorrent
e.path = name; 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);
if (ts >= 0)
e.mtime = std::time_t(ts);
lazy_entry const* attr = info.dict_find_string("attr");
if (attr)
{
for (int i = 0; i < attr->string_length(); ++i)
{
switch (attr->string_ptr()[i])
{
case 'x': e.executable_attribute = true; break;
case 'h': e.hidden_attribute = true; break;
case 'p': e.pad_file = true; break;
}
}
}
// bitcomet pad file // bitcomet pad file
if (e.path.string().find("_____padding_file_") != std::string::npos) if (e.path.string().find("_____padding_file_") != std::string::npos)
e.pad_file = true; e.pad_file = true;