* added support for storing symbolic links in .torrent files

This commit is contained in:
Arvid Norberg 2009-07-01 08:35:45 +00:00
parent 76db4627f6
commit ece98a8ef6
7 changed files with 136 additions and 18 deletions

View File

@ -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

View File

@ -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;

View File

@ -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);
}
}
}
}

View File

@ -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

View File

@ -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));
}
}
}
}

View File

@ -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;
}

View File

@ -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;