forked from premiere/premiere-libtorrent
make pad-file and symlink support conform to BEP47 (#992)
make pad-file and symlink support conform to BEP47
This commit is contained in:
parent
bc369683df
commit
8007b947fd
|
@ -1,5 +1,6 @@
|
||||||
1.1.1 release
|
1.1.1 release
|
||||||
|
|
||||||
|
* make pad-file and symlink support conform to BEP47
|
||||||
* fix piece picker bug that could result in division by zero
|
* fix piece picker bug that could result in division by zero
|
||||||
* fix value of current_tracker when all tracker failed
|
* fix value of current_tracker when all tracker failed
|
||||||
* deprecate lt_trackers extension
|
* deprecate lt_trackers extension
|
||||||
|
|
|
@ -109,7 +109,7 @@ namespace bdecode_errors
|
||||||
{
|
{
|
||||||
// Not an error
|
// Not an error
|
||||||
no_error = 0,
|
no_error = 0,
|
||||||
// expected string in bencoded string
|
// expected digit in bencoded string
|
||||||
expected_digit,
|
expected_digit,
|
||||||
// expected colon in bencoded string
|
// expected colon in bencoded string
|
||||||
expected_colon,
|
expected_colon,
|
||||||
|
|
|
@ -548,7 +548,7 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
if (m_include_mtime) info["mtime"] = m_files.mtime(0);
|
if (m_include_mtime) info["mtime"] = m_files.mtime(0);
|
||||||
info["length"] = m_files.file_size(0);
|
info["length"] = m_files.file_size(0);
|
||||||
int flags = m_files.file_flags(0);
|
int const flags = m_files.file_flags(0);
|
||||||
if (flags & (file_storage::flag_pad_file
|
if (flags & (file_storage::flag_pad_file
|
||||||
| file_storage::flag_hidden
|
| file_storage::flag_hidden
|
||||||
| file_storage::flag_executable
|
| file_storage::flag_executable
|
||||||
|
|
|
@ -47,8 +47,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#if defined(TORRENT_WINDOWS) || defined(TORRENT_OS2)
|
#if defined(TORRENT_WINDOWS) || defined(TORRENT_OS2)
|
||||||
#define TORRENT_SEPARATOR '\\'
|
#define TORRENT_SEPARATOR '\\'
|
||||||
|
#define TORRENT_SEPARATOR_STR "\\"
|
||||||
#else
|
#else
|
||||||
#define TORRENT_SEPARATOR '/'
|
#define TORRENT_SEPARATOR '/'
|
||||||
|
#define TORRENT_SEPARATOR_STR "/"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
|
@ -538,10 +540,10 @@ namespace libtorrent
|
||||||
, symlink_path);
|
, symlink_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void file_storage::add_file_borrow(char const* filename, int filename_len
|
void file_storage::add_file_borrow(char const* filename, int const filename_len
|
||||||
, std::string const& path, boost::int64_t file_size
|
, std::string const& path, boost::int64_t const file_size
|
||||||
, boost::uint32_t file_flags, char const* filehash
|
, boost::uint32_t const file_flags, char const* filehash
|
||||||
, boost::int64_t mtime, std::string const& symlink_path)
|
, boost::int64_t const mtime, std::string const& symlink_path)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT_PRECOND(file_size >= 0);
|
TORRENT_ASSERT_PRECOND(file_size >= 0);
|
||||||
if (!has_parent_path(path))
|
if (!has_parent_path(path))
|
||||||
|
@ -576,10 +578,10 @@ namespace libtorrent
|
||||||
|
|
||||||
e.size = file_size;
|
e.size = file_size;
|
||||||
e.offset = m_total_size;
|
e.offset = m_total_size;
|
||||||
e.pad_file = file_flags & file_storage::flag_pad_file;
|
e.pad_file = (file_flags & file_storage::flag_pad_file) != 0;
|
||||||
e.hidden_attribute = file_flags & file_storage::flag_hidden;
|
e.hidden_attribute = (file_flags & file_storage::flag_hidden) != 0;
|
||||||
e.executable_attribute = file_flags & file_storage::flag_executable;
|
e.executable_attribute = (file_flags & file_storage::flag_executable) != 0;
|
||||||
e.symlink_attribute = file_flags & file_storage::flag_symlink;
|
e.symlink_attribute = (file_flags & file_storage::flag_symlink) != 0;
|
||||||
|
|
||||||
if (filehash)
|
if (filehash)
|
||||||
{
|
{
|
||||||
|
@ -965,8 +967,8 @@ namespace libtorrent
|
||||||
|
|
||||||
if (best_match != i)
|
if (best_match != i)
|
||||||
{
|
{
|
||||||
int index = best_match - m_files.begin();
|
int const index = best_match - m_files.begin();
|
||||||
int cur_index = i - m_files.begin();
|
int const cur_index = i - m_files.begin();
|
||||||
reorder_file(index, cur_index);
|
reorder_file(index, cur_index);
|
||||||
i = m_files.begin() + cur_index;
|
i = m_files.begin() + cur_index;
|
||||||
}
|
}
|
||||||
|
@ -979,7 +981,7 @@ namespace libtorrent
|
||||||
// not piece-aligned and the file size exceeds the
|
// not piece-aligned and the file size exceeds the
|
||||||
// limit, and it's not a padding file itself.
|
// limit, and it's not a padding file itself.
|
||||||
// so add a padding file in front of it
|
// so add a padding file in front of it
|
||||||
int pad_size = alignment - (off % alignment);
|
int const pad_size = alignment - (off % alignment);
|
||||||
|
|
||||||
// find the largest file that fits in pad_size
|
// find the largest file that fits in pad_size
|
||||||
std::vector<internal_file_entry>::iterator best_match = m_files.end();
|
std::vector<internal_file_entry>::iterator best_match = m_files.end();
|
||||||
|
@ -1064,7 +1066,8 @@ namespace libtorrent
|
||||||
e.size = size;
|
e.size = size;
|
||||||
e.offset = offset;
|
e.offset = offset;
|
||||||
char name[30];
|
char name[30];
|
||||||
snprintf(name, sizeof(name), ".____padding_file/%d", pad_file_counter);
|
snprintf(name, sizeof(name), ".pad" TORRENT_SEPARATOR_STR "%d"
|
||||||
|
, pad_file_counter);
|
||||||
std::string path = combine_path(m_name, name);
|
std::string path = combine_path(m_name, name);
|
||||||
e.set_name(path.c_str());
|
e.set_name(path.c_str());
|
||||||
e.pad_file = true;
|
e.pad_file = true;
|
||||||
|
|
|
@ -161,7 +161,8 @@ namespace libtorrent
|
||||||
return valid_encoding;
|
return valid_encoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sanitize_append_path_element(std::string& path, char const* element, int element_len)
|
void sanitize_append_path_element(std::string& path
|
||||||
|
, char const* element, int element_len)
|
||||||
{
|
{
|
||||||
if (element_len == 1 && element[0] == '.') return;
|
if (element_len == 1 && element[0] == '.') return;
|
||||||
|
|
||||||
|
@ -390,6 +391,46 @@ namespace libtorrent
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
boost::uint32_t get_file_attributes(bdecode_node const& dict)
|
||||||
|
{
|
||||||
|
boost::uint32_t file_flags = 0;
|
||||||
|
bdecode_node attr = dict.dict_find_string("attr");
|
||||||
|
if (attr)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < attr.string_length(); ++i)
|
||||||
|
{
|
||||||
|
switch (attr.string_ptr()[i])
|
||||||
|
{
|
||||||
|
case 'l': file_flags |= file_storage::flag_symlink; break;
|
||||||
|
case 'x': file_flags |= file_storage::flag_executable; break;
|
||||||
|
case 'h': file_flags |= file_storage::flag_hidden; break;
|
||||||
|
case 'p': file_flags |= file_storage::flag_pad_file; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return file_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterates an array of strings and returns the sum of the lengths of all
|
||||||
|
// strings + one additional character per entry (to account for the presumed
|
||||||
|
// forward- or backslash to seaprate directory entries)
|
||||||
|
int path_length(bdecode_node const& p, error_code& ec)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
int const len = p.list_size();
|
||||||
|
for (int i = 0; i < len; ++i)
|
||||||
|
{
|
||||||
|
bdecode_node e = p.list_at(i);
|
||||||
|
if (e.type() != bdecode_node::string_t)
|
||||||
|
{
|
||||||
|
ec = errors::torrent_invalid_name;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ret += e.string_length();
|
||||||
|
}
|
||||||
|
return ret + len;
|
||||||
|
}
|
||||||
|
|
||||||
// 'top_level' is extracting the file for a single-file torrent. The
|
// 'top_level' is extracting the file for a single-file torrent. The
|
||||||
// distinction is that the filename is found in "name" rather than
|
// distinction is that the filename is found in "name" rather than
|
||||||
// "path"
|
// "path"
|
||||||
|
@ -397,17 +438,24 @@ namespace libtorrent
|
||||||
// torrent, in which case it's empty.
|
// torrent, in which case it's empty.
|
||||||
bool extract_single_file(bdecode_node const& dict, file_storage& files
|
bool extract_single_file(bdecode_node const& dict, file_storage& files
|
||||||
, std::string const& root_dir, ptrdiff_t info_ptr_diff, bool top_level
|
, std::string const& root_dir, ptrdiff_t info_ptr_diff, bool top_level
|
||||||
, error_code& ec)
|
, int& pad_file_cnt, error_code& ec)
|
||||||
{
|
{
|
||||||
if (dict.type() != bdecode_node::dict_t) return false;
|
if (dict.type() != bdecode_node::dict_t) return false;
|
||||||
boost::int64_t file_size = dict.dict_find_int_value("length", -1);
|
|
||||||
if (file_size < 0)
|
boost::uint32_t file_flags = get_file_attributes(dict);
|
||||||
|
|
||||||
|
// symlinks have an implied "size" of zero. i.e. they use up 0 bytes of
|
||||||
|
// the torrent payload space
|
||||||
|
boost::int64_t const file_size = (file_flags & file_storage::flag_symlink)
|
||||||
|
? 0
|
||||||
|
: dict.dict_find_int_value("length", -1);
|
||||||
|
if (file_size < 0 )
|
||||||
{
|
{
|
||||||
ec = errors::torrent_invalid_length;
|
ec = errors::torrent_invalid_length;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::int64_t mtime = dict.dict_find_int_value("mtime", 0);
|
boost::int64_t const mtime = dict.dict_find_int_value("mtime", 0);
|
||||||
|
|
||||||
std::string path = root_dir;
|
std::string path = root_dir;
|
||||||
std::string path_element;
|
std::string path_element;
|
||||||
|
@ -434,23 +482,11 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
bdecode_node p = dict.dict_find_list("path.utf-8");
|
bdecode_node p = dict.dict_find_list("path.utf-8");
|
||||||
if (!p) p = dict.dict_find_list("path");
|
if (!p) p = dict.dict_find_list("path");
|
||||||
if (!p || p.list_size() == 0)
|
|
||||||
{
|
|
||||||
ec = errors::torrent_missing_name;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int preallocate = path.size();
|
if (p && p.list_size() > 0)
|
||||||
for (int i = 0, end(p.list_size()); i < end; ++i)
|
|
||||||
{
|
{
|
||||||
bdecode_node e = p.list_at(i);
|
int const preallocate = path.size() + path_length(p, ec);
|
||||||
if (e.type() != bdecode_node::string_t)
|
if (ec) return false;
|
||||||
{
|
|
||||||
ec = errors::torrent_missing_name;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
preallocate += e.string_length() + 1;
|
|
||||||
}
|
|
||||||
path.reserve(preallocate);
|
path.reserve(preallocate);
|
||||||
|
|
||||||
for (int i = 0, end(p.list_size()); i < end; ++i)
|
for (int i = 0, end(p.list_size()); i < end; ++i)
|
||||||
|
@ -464,41 +500,45 @@ namespace libtorrent
|
||||||
sanitize_append_path_element(path, e.string_ptr(), e.string_length());
|
sanitize_append_path_element(path, e.string_ptr(), e.string_length());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (file_flags & file_storage::flag_pad_file)
|
||||||
|
{
|
||||||
|
// pad files don't need a path element, we'll just store them
|
||||||
|
// under the .pad directory
|
||||||
|
char cnt[10];
|
||||||
|
snprintf(cnt, sizeof(cnt), "%d", pad_file_cnt);
|
||||||
|
path = combine_path(".pad", cnt);
|
||||||
|
++pad_file_cnt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ec = errors::torrent_missing_name;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// bitcomet pad file
|
// bitcomet pad file
|
||||||
boost::uint32_t file_flags = 0;
|
|
||||||
if (path.find("_____padding_file_") != std::string::npos)
|
if (path.find("_____padding_file_") != std::string::npos)
|
||||||
file_flags = file_storage::flag_pad_file;
|
file_flags = file_storage::flag_pad_file;
|
||||||
|
|
||||||
bdecode_node attr = dict.dict_find_string("attr");
|
|
||||||
if (attr)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < attr.string_length(); ++i)
|
|
||||||
{
|
|
||||||
switch (attr.string_ptr()[i])
|
|
||||||
{
|
|
||||||
case 'l': file_flags |= file_storage::flag_symlink; file_size = 0; break;
|
|
||||||
case 'x': file_flags |= file_storage::flag_executable; break;
|
|
||||||
case 'h': file_flags |= file_storage::flag_hidden; break;
|
|
||||||
case 'p': file_flags |= file_storage::flag_pad_file; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bdecode_node fh = dict.dict_find_string("sha1");
|
bdecode_node fh = dict.dict_find_string("sha1");
|
||||||
char const* filehash = NULL;
|
char const* filehash = NULL;
|
||||||
if (fh && fh.string_length() == 20)
|
if (fh && fh.string_length() == 20)
|
||||||
filehash = fh.string_ptr() + info_ptr_diff;
|
filehash = fh.string_ptr() + info_ptr_diff;
|
||||||
|
|
||||||
std::string symlink_path;
|
std::string symlink_path;
|
||||||
bdecode_node s_p = dict.dict_find("symlink path");
|
if (file_flags & file_storage::flag_symlink)
|
||||||
if (s_p && s_p.type() == bdecode_node::list_t
|
|
||||||
&& (file_flags & file_storage::flag_symlink))
|
|
||||||
{
|
{
|
||||||
|
if (bdecode_node s_p = dict.dict_find_list("symlink path"))
|
||||||
|
{
|
||||||
|
int const preallocate = path_length(s_p, ec);
|
||||||
|
if (ec) return false;
|
||||||
|
symlink_path.reserve(preallocate);
|
||||||
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 pe = s_p.list_at(i).string_value();
|
bdecode_node const& n = s_p.list_at(i);
|
||||||
symlink_path = combine_path(symlink_path, pe);
|
sanitize_append_path_element(symlink_path, n.string_ptr()
|
||||||
|
, n.string_length());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -591,10 +631,12 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
target.reserve(list.list_size());
|
target.reserve(list.list_size());
|
||||||
|
|
||||||
|
// this is the counter used to name pad files
|
||||||
|
int pad_file_cnt = 0;
|
||||||
for (int i = 0, end(list.list_size()); i < end; ++i)
|
for (int i = 0, end(list.list_size()); i < end; ++i)
|
||||||
{
|
{
|
||||||
if (!extract_single_file(list.list_at(i), target, root_dir
|
if (!extract_single_file(list.list_at(i), target, root_dir
|
||||||
, info_ptr_diff, false, ec))
|
, info_ptr_diff, false, pad_file_cnt, ec))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -1226,7 +1268,9 @@ 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.
|
||||||
if (!extract_single_file(info, files, "", info_ptr_diff, true, ec))
|
// this is the counter used to name pad files
|
||||||
|
int pad_file_cnt = 0;
|
||||||
|
if (!extract_single_file(info, files, "", info_ptr_diff, true, pad_file_cnt, ec))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_multifile = false;
|
m_multifile = false;
|
||||||
|
@ -1287,7 +1331,7 @@ namespace libtorrent
|
||||||
m_merkle_tree[0].assign(root_hash.string_ptr());
|
m_merkle_tree[0].assign(root_hash.string_ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_private = info.dict_find_int_value("private", 0);
|
m_private = info.dict_find_int_value("private", 0) != 0;
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_MUTABLE_TORRENTS
|
#ifndef TORRENT_DISABLE_MUTABLE_TORRENTS
|
||||||
bdecode_node similar = info.dict_find_list("similar");
|
bdecode_node similar = info.dict_find_list("similar");
|
||||||
|
|
|
@ -75,6 +75,7 @@ EXTRA_DIST = Jamfile \
|
||||||
test_torrents/invalid_pieces.torrent \
|
test_torrents/invalid_pieces.torrent \
|
||||||
test_torrents/invalid_root_hash.torrent \
|
test_torrents/invalid_root_hash.torrent \
|
||||||
test_torrents/invalid_root_hash2.torrent \
|
test_torrents/invalid_root_hash2.torrent \
|
||||||
|
test_torrents/invalid_symlink.torrent \
|
||||||
test_torrents/long_name.torrent \
|
test_torrents/long_name.torrent \
|
||||||
test_torrents/missing_path_list.torrent \
|
test_torrents/missing_path_list.torrent \
|
||||||
test_torrents/missing_piece_len.torrent \
|
test_torrents/missing_piece_len.torrent \
|
||||||
|
@ -84,6 +85,7 @@ EXTRA_DIST = Jamfile \
|
||||||
test_torrents/no_creation_date.torrent \
|
test_torrents/no_creation_date.torrent \
|
||||||
test_torrents/no_name.torrent \
|
test_torrents/no_name.torrent \
|
||||||
test_torrents/pad_file.torrent \
|
test_torrents/pad_file.torrent \
|
||||||
|
test_torrents/pad_file_no_path.torrent \
|
||||||
test_torrents/parent_path.torrent \
|
test_torrents/parent_path.torrent \
|
||||||
test_torrents/root_hash.torrent \
|
test_torrents/root_hash.torrent \
|
||||||
test_torrents/sample.torrent \
|
test_torrents/sample.torrent \
|
||||||
|
@ -93,6 +95,7 @@ EXTRA_DIST = Jamfile \
|
||||||
test_torrents/slash_path3.torrent \
|
test_torrents/slash_path3.torrent \
|
||||||
test_torrents/string.torrent \
|
test_torrents/string.torrent \
|
||||||
test_torrents/symlink1.torrent \
|
test_torrents/symlink1.torrent \
|
||||||
|
test_torrents/symlink_zero_size.torrent \
|
||||||
test_torrents/unaligned_pieces.torrent \
|
test_torrents/unaligned_pieces.torrent \
|
||||||
test_torrents/unordered.torrent \
|
test_torrents/unordered.torrent \
|
||||||
test_torrents/url_list.torrent \
|
test_torrents/url_list.torrent \
|
||||||
|
|
|
@ -132,6 +132,8 @@ static test_torrent_t test_torrents[] =
|
||||||
{ "invalid_name3.torrent" },
|
{ "invalid_name3.torrent" },
|
||||||
{ "symlink1.torrent" },
|
{ "symlink1.torrent" },
|
||||||
{ "unordered.torrent" },
|
{ "unordered.torrent" },
|
||||||
|
{ "symlink_zero_size.torrent" },
|
||||||
|
{ "pad_file_no_path.torrent" },
|
||||||
};
|
};
|
||||||
|
|
||||||
struct test_failing_torrent_t
|
struct test_failing_torrent_t
|
||||||
|
@ -151,13 +153,14 @@ test_failing_torrent_t test_error_torrents[] =
|
||||||
{ "string.torrent", errors::torrent_is_no_dict },
|
{ "string.torrent", errors::torrent_is_no_dict },
|
||||||
{ "negative_size.torrent", errors::torrent_invalid_length },
|
{ "negative_size.torrent", errors::torrent_invalid_length },
|
||||||
{ "negative_file_size.torrent", errors::torrent_invalid_length },
|
{ "negative_file_size.torrent", errors::torrent_invalid_length },
|
||||||
{ "invalid_path_list.torrent", errors::torrent_missing_name},
|
{ "invalid_path_list.torrent", errors::torrent_invalid_name},
|
||||||
{ "missing_path_list.torrent", errors::torrent_missing_name },
|
{ "missing_path_list.torrent", errors::torrent_missing_name },
|
||||||
{ "invalid_pieces.torrent", errors::torrent_missing_pieces },
|
{ "invalid_pieces.torrent", errors::torrent_missing_pieces },
|
||||||
{ "unaligned_pieces.torrent", errors::torrent_invalid_hashes },
|
{ "unaligned_pieces.torrent", errors::torrent_invalid_hashes },
|
||||||
{ "invalid_root_hash.torrent", errors::torrent_invalid_hashes },
|
{ "invalid_root_hash.torrent", errors::torrent_invalid_hashes },
|
||||||
{ "invalid_root_hash2.torrent", errors::torrent_missing_pieces },
|
{ "invalid_root_hash2.torrent", errors::torrent_missing_pieces },
|
||||||
{ "invalid_file_size.torrent", errors::torrent_invalid_length },
|
{ "invalid_file_size.torrent", errors::torrent_invalid_length },
|
||||||
|
{ "invalid_symlink.torrent", errors::torrent_invalid_name },
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: test remap_files
|
// TODO: test remap_files
|
||||||
|
@ -168,7 +171,6 @@ test_failing_torrent_t test_error_torrents[] =
|
||||||
// TODO: torrent with 'l' (symlink) attribute
|
// TODO: torrent with 'l' (symlink) attribute
|
||||||
// TODO: creating a merkle torrent (torrent_info::build_merkle_list)
|
// TODO: creating a merkle torrent (torrent_info::build_merkle_list)
|
||||||
// TODO: torrent with multiple trackers in multiple tiers, making sure we shuffle them (how do you test shuffling?, load it multiple times and make sure it's in different order at least once)
|
// TODO: torrent with multiple trackers in multiple tiers, making sure we shuffle them (how do you test shuffling?, load it multiple times and make sure it's in different order at least once)
|
||||||
// TODO: torrents with a missing name
|
|
||||||
// TODO: torrents with a zero-length name
|
// TODO: torrents with a zero-length name
|
||||||
// TODO: torrents with a merkle tree and add_merkle_nodes
|
// TODO: torrents with a merkle tree and add_merkle_nodes
|
||||||
// TODO: torrent with a non-dictionary info-section
|
// TODO: torrent with a non-dictionary info-section
|
||||||
|
@ -718,6 +720,16 @@ TORRENT_TEST(parse_torrents)
|
||||||
TEST_EQUAL(ti->num_files(), 1);
|
TEST_EQUAL(ti->num_files(), 1);
|
||||||
TEST_EQUAL(ti->files().file_path(0), "temp....abc");
|
TEST_EQUAL(ti->files().file_path(0), "temp....abc");
|
||||||
}
|
}
|
||||||
|
else if (std::string(test_torrents[i].file) == "symlink_zero_size.torrent")
|
||||||
|
{
|
||||||
|
TEST_EQUAL(ti->num_files(), 2);
|
||||||
|
TEST_EQUAL(ti->files().symlink(1), combine_path("foo", "bar"));
|
||||||
|
}
|
||||||
|
else if (std::string(test_torrents[i].file) == "pad_file_no_path.torrent")
|
||||||
|
{
|
||||||
|
TEST_EQUAL(ti->num_files(), 2);
|
||||||
|
TEST_EQUAL(ti->files().file_path(1), combine_path(".pad", "0"));
|
||||||
|
}
|
||||||
|
|
||||||
file_storage const& fs = ti->files();
|
file_storage const& fs = ti->files();
|
||||||
for (int i = 0; i < fs.num_files(); ++i)
|
for (int i = 0; i < fs.num_files(); ++i)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
d10:created by10:libtorrent13:creation datei1359599503e4:infod5:filesld6:lengthi0e4:pathl1:a1:b3:bareed4:attr1:l6:lengthi425e4:pathl1:a1:b3:foo12:symlink pathl3:foo3:bari4eeeee4:name4:temp12:piece lengthi16384e6:pieces20:‚ž¼Œ&¾ÇJW›}ÜA4u,·¼‘‡ee
|
|
@ -0,0 +1 @@
|
||||||
|
d10:created by10:libtorrent13:creation datei1359599503e4:infod5:filesld4:pathl3:foo7:bar.txte6:lengthi45eed4:attr1:p6:lengthi2124eee4:name4:temp12:piece lengthi16384e6:pieces20:‚ž¼Œ&¾ÇJW›}ÜA4u,·¼‘‡ee
|
|
@ -1 +1 @@
|
||||||
d10:created by10:libtorrent13:creation datei1359599503e4:infod5:filesld6:lengthi425e4:pathl1:a1:b3:bareed4:attr1:l6:lengthi425e4:pathl1:a1:b3:fooeee4:name4:temp12:piece lengthi16384e6:pieces20:‚ž¼Œ&¾ÇJW›}ÜA4u,·¼‘‡ee
|
d10:created by10:libtorrent13:creation datei1359599503e4:infod5:filesld6:lengthi425e4:pathl1:a1:b3:bareed4:attr1:l6:lengthi425e4:pathl1:a1:b3:fooe12:symlink pathl3:foo3:bareee4:name4:temp12:piece lengthi16384e6:pieces20:‚ž¼Œ&¾ÇJW›}ÜA4u,·¼‘‡ee
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
d10:created by10:libtorrent13:creation datei1359599503e4:infod5:filesld6:lengthi425e4:pathl1:a1:b3:bareed4:attr1:l4:pathl1:a1:b3:fooe12:symlink pathl3:foo3:bareee4:name4:temp12:piece lengthi16384e6:pieces20:aaaaaaaaaaaaaaaaaaaaee
|
Loading…
Reference in New Issue