* added support for storing symbolic links in .torrent files
This commit is contained in:
parent
76db4627f6
commit
ece98a8ef6
|
@ -1,3 +1,4 @@
|
|||
* added support for storing symbolic links in .torrent files
|
||||
* added support for uTorrent interpretation of multi-tracker torrents
|
||||
* handle torrents with duplicate filenames
|
||||
* piece timeouts are adjusted to download rate limits
|
||||
|
|
|
@ -123,9 +123,13 @@ int main(int argc, char* argv[])
|
|||
<< (i->pad_file?'p':'-')
|
||||
<< (i->executable_attribute?'x':'-')
|
||||
<< (i->hidden_attribute?'h':'-')
|
||||
<< (i->symlink_attribute?'l':'-')
|
||||
<< " "
|
||||
<< i->path.string() << "[ " << first << ", "
|
||||
<< last << " ]\n";
|
||||
<< "[ " << std::setw(3) << first << ", " << std::setw(3) << last << " ]\t"
|
||||
<< i->path.string() ;
|
||||
if (i->symlink_attribute)
|
||||
std::cout << " -> " << i->symlink_path.string();
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -164,6 +164,9 @@ namespace libtorrent
|
|||
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);
|
||||
|
||||
fs::path TORRENT_EXPORT get_symlink_path(boost::filesystem::path const& p);
|
||||
fs::path TORRENT_EXPORT get_symlink_path(boost::filesystem::wpath const& p);
|
||||
|
||||
template <class Pred, class Str, class PathTraits>
|
||||
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)
|
||||
|
@ -191,7 +194,16 @@ namespace libtorrent
|
|||
{
|
||||
int file_flags = get_file_attributes(f);
|
||||
std::time_t mtime = get_file_mtime(f);
|
||||
fs.add_file(l, file_size(f), file_flags, mtime);
|
||||
//Masking all bits to check if the file is a symlink
|
||||
if(file_flags & file_storage::attribute_symlink)
|
||||
{
|
||||
fs::path sym_path = get_symlink_path(f);
|
||||
fs.add_file(l, 0 ,file_flags, mtime, sym_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
fs.add_file(l, file_size(f), file_flags, mtime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,8 +57,10 @@ namespace libtorrent
|
|||
struct TORRENT_EXPORT file_entry
|
||||
{
|
||||
file_entry(): offset(0), size(0), file_base(0)
|
||||
, pad_file(false), hidden_attribute(false)
|
||||
, executable_attribute(false) {}
|
||||
, mtime(0), pad_file(false), hidden_attribute(false)
|
||||
, executable_attribute(false)
|
||||
, symlink_attribute(false)
|
||||
{}
|
||||
|
||||
fs::path path;
|
||||
size_type offset; // the offset of this file inside the torrent
|
||||
|
@ -71,6 +73,8 @@ namespace libtorrent
|
|||
bool pad_file:1;
|
||||
bool hidden_attribute:1;
|
||||
bool executable_attribute:1;
|
||||
bool symlink_attribute:1;
|
||||
fs::path symlink_path;
|
||||
};
|
||||
|
||||
struct TORRENT_EXPORT file_slice
|
||||
|
@ -93,15 +97,16 @@ namespace libtorrent
|
|||
{
|
||||
pad_file = 1,
|
||||
attribute_hidden = 2,
|
||||
attribute_executable = 4
|
||||
attribute_executable = 4,
|
||||
attribute_symlink = 8
|
||||
};
|
||||
|
||||
void add_file(file_entry const& e);
|
||||
void add_file(fs::path const& p, size_type size, int flags = 0, std::time_t mtime = 0);
|
||||
void add_file(fs::path const& p, size_type size, int flags = 0, std::time_t mtime = 0, fs::path const& s_p = "");
|
||||
void rename_file(int index, std::string const& new_filename);
|
||||
|
||||
#ifndef BOOST_FILESYSTEM_NARROW_ONLY
|
||||
void add_file(fs::wpath const& p, size_type size, int flags = 0, std::time_t mtime = 0);
|
||||
void add_file(fs::wpath const& p, size_type size, int flags = 0, std::time_t mtime = 0, fs::path const& s_p = "");
|
||||
void rename_file(int index, std::wstring const& new_filename);
|
||||
void set_name(std::wstring const& n);
|
||||
#endif
|
||||
|
|
|
@ -42,6 +42,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define MAX_SYMLINK_PATH 200
|
||||
|
||||
namespace gr = boost::gregorian;
|
||||
|
||||
namespace libtorrent
|
||||
|
@ -69,8 +71,13 @@ namespace libtorrent
|
|||
return 0;
|
||||
#else
|
||||
struct stat s;
|
||||
if (stat(convert_to_native(p.external_file_string()).c_str(), &s) < 0) return 0;
|
||||
return (s.st_mode & S_IXUSR) ? file_storage::attribute_executable : 0;
|
||||
if (lstat(convert_to_native(p.external_file_string()).c_str(), &s) < 0) return 0;
|
||||
int file_attr = 0;
|
||||
if (s.st_mode & S_IXUSR)
|
||||
file_attr += file_storage::attribute_executable;
|
||||
if(S_ISLNK(s.st_mode))
|
||||
file_attr += file_storage::attribute_symlink;
|
||||
return file_attr;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -87,8 +94,13 @@ namespace libtorrent
|
|||
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;
|
||||
if (lstat(native.c_str(), &s) < 0) return 0;
|
||||
int file_attr = 0;
|
||||
if (s.st_mode & S_IXUSR)
|
||||
file_attr += file_storage::attribute_executable;
|
||||
if (S_ISLNK(s.st_mode))
|
||||
file_attr += file_storage::attribute_symlink;
|
||||
return file_attr;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -130,6 +142,40 @@ namespace libtorrent
|
|||
return get_file_mtime(utf8.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
boost::filesystem::path get_symlink_path(char const* path)
|
||||
{
|
||||
char buf[MAX_SYMLINK_PATH];
|
||||
int char_read = readlink(path,buf,MAX_SYMLINK_PATH);
|
||||
if (char_read < 0) return "";
|
||||
if (char_read < MAX_SYMLINK_PATH) buf[char_read] = 0;
|
||||
else buf[0] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
boost::filesystem::path TORRENT_EXPORT get_symlink_path(boost::filesystem::path const& p)
|
||||
{
|
||||
#if defined TORRENT_WINDOWS && TORRENT_USE_WPATH
|
||||
std::wstring path = convert_to_wstring(p.external_file_string());
|
||||
return get_symlink_path(path.c_str());
|
||||
#else
|
||||
std::string path = convert_to_native(p.external_file_string());
|
||||
return get_symlink_path(p.string().c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
boost::filesystem::path TORRENT_EXPORT get_symlink_path(boost::filesystem::wpath const& p)
|
||||
{
|
||||
#ifdef TORRENT_WINDOWS
|
||||
return get_symlink_path(p.string().c_str());
|
||||
#else
|
||||
std::string utf8;
|
||||
wchar_utf8(p.string(), utf8);
|
||||
utf8 = convert_to_native(utf8);
|
||||
return get_symlink_path(utf8.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
create_torrent::create_torrent(file_storage& fs, int piece_size, int pad_file_limit, int flags)
|
||||
|
@ -305,12 +351,23 @@ namespace libtorrent
|
|||
{
|
||||
info["mtime"] = m_files.at(0).mtime;
|
||||
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)
|
||||
if (m_files.at(0).pad_file || m_files.at(0).hidden_attribute || m_files.at(0).executable_attribute || m_files.at(0).symlink_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';
|
||||
if (m_files.at(0).symlink_attribute) attr += 'l';
|
||||
}
|
||||
if (m_files.at(0).symlink_attribute)
|
||||
{
|
||||
entry& sympath_e = info["symlink path"];
|
||||
|
||||
for (fs::path::iterator j = (m_files.at(0).symlink_path.begin());
|
||||
j != m_files.at(0).symlink_path.end(); ++j)
|
||||
{
|
||||
sympath_e.list().push_back(entry(*j));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -340,12 +397,23 @@ namespace libtorrent
|
|||
{
|
||||
path_e.list().push_back(entry(*j));
|
||||
}
|
||||
if (i->pad_file || i->hidden_attribute || i->executable_attribute)
|
||||
if (i->pad_file || i->hidden_attribute || i->executable_attribute || i->symlink_attribute)
|
||||
{
|
||||
std::string& attr = file_e["attr"].string();
|
||||
if (i->pad_file) attr += 'p';
|
||||
if (i->hidden_attribute) attr += 'h';
|
||||
if (i->executable_attribute) attr += 'x';
|
||||
if (i->symlink_attribute) attr += 'l';
|
||||
}
|
||||
if (i->symlink_attribute)
|
||||
{
|
||||
entry& sympath_e = file_e["symlink path"];
|
||||
|
||||
for (fs::path::iterator j = (i->symlink_path.begin());
|
||||
j != i->symlink_path.end(); ++j)
|
||||
{
|
||||
sympath_e.list().push_back(entry(*j));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,11 +76,12 @@ namespace libtorrent
|
|||
m_files[index].path = utf8;
|
||||
}
|
||||
|
||||
void file_storage::add_file(fs::wpath const& file, size_type size, int flags, std::time_t mtime)
|
||||
void file_storage::add_file(fs::wpath const& file, size_type size, int flags
|
||||
, std::time_t mtime, fs::path const& symlink_path)
|
||||
{
|
||||
std::string utf8;
|
||||
wchar_utf8(file.string(), utf8);
|
||||
add_file(utf8, size, flags, mtime);
|
||||
add_file(utf8, size, flags, mtime, symlink_path);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -164,7 +165,8 @@ namespace libtorrent
|
|||
return ret;
|
||||
}
|
||||
|
||||
void file_storage::add_file(fs::path const& file, size_type size, int flags, std::time_t mtime)
|
||||
void file_storage::add_file(fs::path const& file, size_type size, int flags
|
||||
, std::time_t mtime, fs::path const& symlink_path)
|
||||
{
|
||||
TORRENT_ASSERT(size >= 0);
|
||||
#if BOOST_VERSION < 103600
|
||||
|
@ -194,6 +196,8 @@ namespace libtorrent
|
|||
e.pad_file = bool(flags & pad_file);
|
||||
e.hidden_attribute = bool(flags & attribute_hidden);
|
||||
e.executable_attribute = bool(flags & attribute_executable);
|
||||
e.symlink_attribute = bool(flags & attribute_symlink);
|
||||
if (e.symlink_attribute) e.symlink_path = symlink_path.string();
|
||||
e.mtime = mtime;
|
||||
m_total_size += size;
|
||||
}
|
||||
|
|
|
@ -259,6 +259,7 @@ namespace libtorrent
|
|||
{
|
||||
switch (attr->string_ptr()[i])
|
||||
{
|
||||
case 'l': target.symlink_attribute = true; target.size = 0; break;
|
||||
case 'x': target.executable_attribute = true; break;
|
||||
case 'h': target.hidden_attribute = true; break;
|
||||
case 'p': target.pad_file = true; break;
|
||||
|
@ -266,6 +267,17 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
lazy_entry const* s_p = dict.dict_find("symlink path");
|
||||
if (s_p != 0 && s_p->type() == lazy_entry::list_t)
|
||||
{
|
||||
for (int i = 0, end(s_p->list_size()); i < end; ++i)
|
||||
{
|
||||
std::string path_element = s_p->list_at(i)->string_value();
|
||||
trim_path_element(path_element);
|
||||
target.symlink_path /= path_element;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -641,12 +653,24 @@ namespace libtorrent
|
|||
{
|
||||
switch (attr->string_ptr()[i])
|
||||
{
|
||||
case 'l': e.symlink_attribute = true; e.size = 0; break;
|
||||
case 'x': e.executable_attribute = true; break;
|
||||
case 'h': e.hidden_attribute = true; break;
|
||||
case 'p': e.pad_file = true; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lazy_entry const* s_p = info.dict_find("symlink path");
|
||||
if (s_p != 0 && s_p->type() == lazy_entry::list_t)
|
||||
{
|
||||
for (int i = 0, end(s_p->list_size()); i < end; ++i)
|
||||
{
|
||||
std::string path_element = s_p->list_at(i)->string_value();
|
||||
trim_path_element(path_element);
|
||||
e.symlink_path /= path_element;
|
||||
}
|
||||
}
|
||||
// bitcomet pad file
|
||||
if (e.path.string().find("_____padding_file_") != std::string::npos)
|
||||
e.pad_file = true;
|
||||
|
|
Loading…
Reference in New Issue