forked from premiere/premiere-libtorrent
added support for bitcomet padding files. simplified storage read/write code.
This commit is contained in:
parent
ff41246c42
commit
d4c206841b
|
@ -56,7 +56,7 @@ namespace libtorrent
|
|||
|
||||
struct TORRENT_EXPORT file_entry
|
||||
{
|
||||
file_entry(): offset(0), size(0), file_base(0) {}
|
||||
file_entry(): offset(0), size(0), file_base(0), pad_file(false) {}
|
||||
|
||||
fs::path path;
|
||||
size_type offset; // the offset of this file inside the torrent
|
||||
|
@ -65,6 +65,7 @@ namespace libtorrent
|
|||
// This is always 0 unless parts of the torrent is
|
||||
// compressed into a single file, such as a so-called part file.
|
||||
size_type file_base;
|
||||
bool pad_file:1;
|
||||
};
|
||||
|
||||
struct TORRENT_EXPORT file_slice
|
||||
|
@ -84,7 +85,7 @@ namespace libtorrent
|
|||
bool is_valid() const { return m_piece_length > 0; }
|
||||
|
||||
void add_file(file_entry const& e);
|
||||
void add_file(fs::path const& p, size_type size);
|
||||
void add_file(fs::path const& p, size_type size, bool pad_file = false);
|
||||
void rename_file(int index, std::string const& new_filename);
|
||||
|
||||
std::vector<file_slice> map_block(int piece, size_type offset
|
||||
|
|
|
@ -128,7 +128,7 @@ namespace libtorrent
|
|||
return ret;
|
||||
}
|
||||
|
||||
void file_storage::add_file(fs::path const& file, size_type size)
|
||||
void file_storage::add_file(fs::path const& file, size_type size, bool pad_file)
|
||||
{
|
||||
TORRENT_ASSERT(size >= 0);
|
||||
#if BOOST_VERSION < 103600
|
||||
|
@ -151,6 +151,7 @@ namespace libtorrent
|
|||
}
|
||||
TORRENT_ASSERT(m_name == *file.begin());
|
||||
file_entry e;
|
||||
e.pad_file = pad_file;
|
||||
m_files.push_back(e);
|
||||
m_files.back().size = size;
|
||||
m_files.back().path = file;
|
||||
|
@ -160,7 +161,7 @@ namespace libtorrent
|
|||
|
||||
void file_storage::add_file(file_entry const& e)
|
||||
{
|
||||
add_file(e.path, e.size);
|
||||
add_file(e.path, e.size, e.pad_file);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
227
src/storage.cpp
227
src/storage.cpp
|
@ -519,9 +519,12 @@ namespace libtorrent
|
|||
#endif
|
||||
}
|
||||
|
||||
int file_index = file_iter - files().begin();
|
||||
|
||||
// if the file is empty, just create it. But also make sure
|
||||
// the directory exists.
|
||||
if (file_iter->size == 0)
|
||||
if (file_iter->size == 0 && (int(m_file_priority.size()) <= file_index
|
||||
|| m_file_priority[file_index] > 0))
|
||||
{
|
||||
file(m_save_path / file_iter->path, file::out, ec);
|
||||
if (ec)
|
||||
|
@ -535,9 +538,10 @@ namespace libtorrent
|
|||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try {
|
||||
#endif
|
||||
// don't allocate files with priority 0
|
||||
int file_index = file_iter - files().begin();
|
||||
if (allocate_files && (int(m_file_priority.size()) <= file_index
|
||||
// don't allocate files with priority 0 or files
|
||||
// that are pad files
|
||||
if (allocate_files && !file_iter->pad_file
|
||||
&& (int(m_file_priority.size()) <= file_index
|
||||
|| m_file_priority[file_index] > 0))
|
||||
{
|
||||
error_code ec;
|
||||
|
@ -1023,38 +1027,13 @@ namespace libtorrent
|
|||
|
||||
file_offset -= file_iter->size;
|
||||
++file_iter;
|
||||
TORRENT_ASSERT(file_iter != files().end());
|
||||
}
|
||||
|
||||
int buf_pos = 0;
|
||||
error_code ec;
|
||||
boost::shared_ptr<file> in(m_pool.open_file(
|
||||
this, m_save_path / file_iter->path, file::in, ec));
|
||||
if (!in || ec)
|
||||
{
|
||||
set_error(m_save_path / file_iter->path, ec);
|
||||
return -1;
|
||||
}
|
||||
TORRENT_ASSERT(file_offset < file_iter->size);
|
||||
TORRENT_ASSERT(slices[0].offset == file_offset + file_iter->file_base);
|
||||
|
||||
size_type new_pos = in->seek(file_offset + file_iter->file_base, file::begin, ec);
|
||||
if (new_pos != file_offset + file_iter->file_base || ec)
|
||||
{
|
||||
// the file was not big enough
|
||||
if (!fill_zero)
|
||||
{
|
||||
set_error(m_save_path / file_iter->path, ec);
|
||||
return -1;
|
||||
}
|
||||
std::memset(buf + buf_pos, 0, size - buf_pos);
|
||||
return size;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
size_type in_tell = in->tell(ec);
|
||||
TORRENT_ASSERT(in_tell == file_offset + file_iter->file_base && !ec);
|
||||
#endif
|
||||
|
||||
boost::shared_ptr<file> in;
|
||||
int left_to_read = size;
|
||||
int slot_size = static_cast<int>(m_files.piece_size(slot));
|
||||
|
||||
|
@ -1069,22 +1048,56 @@ namespace libtorrent
|
|||
int counter = 0;
|
||||
#endif
|
||||
|
||||
while (left_to_read > 0)
|
||||
int read_bytes;
|
||||
for (;left_to_read > 0; ++file_iter, left_to_read -= read_bytes
|
||||
, buf_pos += read_bytes)
|
||||
{
|
||||
int read_bytes = left_to_read;
|
||||
if (file_offset + read_bytes > file_iter->size)
|
||||
read_bytes = static_cast<int>(file_iter->size - file_offset);
|
||||
TORRENT_ASSERT(file_iter != files().end());
|
||||
TORRENT_ASSERT(buf_pos >= 0);
|
||||
|
||||
read_bytes = left_to_read;
|
||||
if (file_offset + read_bytes > file_iter->size)
|
||||
read_bytes = std::max(static_cast<int>(file_iter->size - file_offset), 0);
|
||||
|
||||
if (read_bytes == 0) continue;
|
||||
|
||||
if (read_bytes > 0)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
TORRENT_ASSERT(int(slices.size()) > counter);
|
||||
size_type slice_size = slices[counter].size;
|
||||
TORRENT_ASSERT(slice_size == read_bytes);
|
||||
TORRENT_ASSERT(files().at(slices[counter].file_index).path
|
||||
== file_iter->path);
|
||||
++counter;
|
||||
#endif
|
||||
|
||||
if (file_iter->pad_file)
|
||||
{
|
||||
std::memset(buf + buf_pos, 0, read_bytes);
|
||||
continue;
|
||||
}
|
||||
|
||||
fs::path path = m_save_path / file_iter->path;
|
||||
|
||||
error_code ec;
|
||||
in = m_pool.open_file(this, path, file::in, ec);
|
||||
if (!in || ec)
|
||||
{
|
||||
set_error(path, ec);
|
||||
return -1;
|
||||
}
|
||||
size_type pos = in->seek(file_iter->file_base + file_offset, file::begin, ec);
|
||||
if (pos != file_iter->file_base + file_offset || ec)
|
||||
{
|
||||
if (!fill_zero)
|
||||
{
|
||||
set_error(m_save_path / file_iter->path, ec);
|
||||
return -1;
|
||||
}
|
||||
std::memset(buf + buf_pos, 0, size - buf_pos);
|
||||
return size;
|
||||
}
|
||||
file_offset = 0;
|
||||
|
||||
int actual_read = int(in->read(buf + buf_pos, read_bytes, ec));
|
||||
|
||||
if (read_bytes != actual_read || ec)
|
||||
|
@ -1100,42 +1113,6 @@ namespace libtorrent
|
|||
return size;
|
||||
}
|
||||
|
||||
left_to_read -= read_bytes;
|
||||
buf_pos += read_bytes;
|
||||
TORRENT_ASSERT(buf_pos >= 0);
|
||||
file_offset += read_bytes;
|
||||
}
|
||||
|
||||
if (left_to_read > 0)
|
||||
{
|
||||
++file_iter;
|
||||
#ifndef NDEBUG
|
||||
// empty files are not returned by map_block, so if
|
||||
// this file was empty, don't increment the slice counter
|
||||
if (read_bytes > 0) ++counter;
|
||||
#endif
|
||||
fs::path path = m_save_path / file_iter->path;
|
||||
|
||||
file_offset = 0;
|
||||
error_code ec;
|
||||
in = m_pool.open_file( this, path, file::in, ec);
|
||||
if (!in || ec)
|
||||
{
|
||||
set_error(path, ec);
|
||||
return -1;
|
||||
}
|
||||
size_type pos = in->seek(file_iter->file_base, file::begin, ec);
|
||||
if (pos != file_iter->file_base || ec)
|
||||
{
|
||||
if (!fill_zero)
|
||||
{
|
||||
set_error(m_save_path / file_iter->path, ec);
|
||||
return -1;
|
||||
}
|
||||
std::memset(buf + buf_pos, 0, size - buf_pos);
|
||||
return size;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -1159,6 +1136,7 @@ namespace libtorrent
|
|||
#endif
|
||||
|
||||
size_type start = slot * (size_type)m_files.piece_length() + offset;
|
||||
TORRENT_ASSERT(start + size <= m_files.total_size());
|
||||
|
||||
// find the file iterator and file offset
|
||||
size_type file_offset = start;
|
||||
|
@ -1174,27 +1152,10 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(file_iter != files().end());
|
||||
}
|
||||
|
||||
fs::path p(m_save_path / file_iter->path);
|
||||
int buf_pos = 0;
|
||||
error_code ec;
|
||||
boost::shared_ptr<file> out = m_pool.open_file(
|
||||
this, p, file::out | file::in, ec);
|
||||
|
||||
if (!out || ec)
|
||||
{
|
||||
set_error(p, ec);
|
||||
return -1;
|
||||
}
|
||||
TORRENT_ASSERT(file_offset < file_iter->size);
|
||||
TORRENT_ASSERT(slices[0].offset == file_offset + file_iter->file_base);
|
||||
|
||||
size_type pos = out->seek(file_offset + file_iter->file_base, file::begin, ec);
|
||||
|
||||
if (pos != file_offset + file_iter->file_base || ec)
|
||||
{
|
||||
set_error(p, ec);
|
||||
return -1;
|
||||
}
|
||||
|
||||
boost::shared_ptr<file> out;
|
||||
int left_to_write = size;
|
||||
int slot_size = static_cast<int>(m_files.piece_size(slot));
|
||||
|
||||
|
@ -1203,72 +1164,62 @@ namespace libtorrent
|
|||
|
||||
TORRENT_ASSERT(left_to_write >= 0);
|
||||
|
||||
int buf_pos = 0;
|
||||
#ifndef NDEBUG
|
||||
int counter = 0;
|
||||
#endif
|
||||
while (left_to_write > 0)
|
||||
{
|
||||
int write_bytes = left_to_write;
|
||||
if (file_offset + write_bytes > file_iter->size)
|
||||
{
|
||||
TORRENT_ASSERT(file_iter->size >= file_offset);
|
||||
write_bytes = static_cast<int>(file_iter->size - file_offset);
|
||||
}
|
||||
|
||||
if (write_bytes > 0)
|
||||
int write_bytes;
|
||||
for (;left_to_write > 0; ++file_iter, left_to_write -= write_bytes
|
||||
, buf_pos += write_bytes)
|
||||
{
|
||||
TORRENT_ASSERT(file_iter != files().end());
|
||||
TORRENT_ASSERT(buf_pos >= 0);
|
||||
|
||||
write_bytes = left_to_write;
|
||||
if (file_offset + write_bytes > file_iter->size)
|
||||
write_bytes = std::max(static_cast<int>(file_iter->size - file_offset), 0);
|
||||
|
||||
if (write_bytes == 0) continue;
|
||||
|
||||
#ifndef NDEBUG
|
||||
TORRENT_ASSERT(int(slices.size()) > counter);
|
||||
TORRENT_ASSERT(slices[counter].size == write_bytes);
|
||||
size_type slice_size = slices[counter].size;
|
||||
TORRENT_ASSERT(slice_size == write_bytes);
|
||||
TORRENT_ASSERT(files().at(slices[counter].file_index).path
|
||||
== file_iter->path);
|
||||
++counter;
|
||||
#endif
|
||||
|
||||
if (file_iter->pad_file)
|
||||
continue;
|
||||
|
||||
fs::path path = m_save_path / file_iter->path;
|
||||
|
||||
TORRENT_ASSERT(buf_pos >= 0);
|
||||
TORRENT_ASSERT(write_bytes >= 0);
|
||||
error_code ec;
|
||||
size_type written = out->write(buf + buf_pos, write_bytes, ec);
|
||||
|
||||
if (written != write_bytes || ec)
|
||||
out = m_pool.open_file(this, path, file::in | file::out, ec);
|
||||
if (!out || ec)
|
||||
{
|
||||
set_error(path, ec);
|
||||
return -1;
|
||||
}
|
||||
size_type pos = out->seek(file_iter->file_base + file_offset, file::begin, ec);
|
||||
if (pos != file_iter->file_base + file_offset || ec)
|
||||
{
|
||||
set_error(m_save_path / file_iter->path, ec);
|
||||
return -1;
|
||||
}
|
||||
|
||||
left_to_write -= write_bytes;
|
||||
buf_pos += write_bytes;
|
||||
TORRENT_ASSERT(buf_pos >= 0);
|
||||
file_offset += write_bytes;
|
||||
TORRENT_ASSERT(file_offset <= file_iter->size);
|
||||
}
|
||||
|
||||
if (left_to_write > 0)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (write_bytes > 0) ++counter;
|
||||
#endif
|
||||
++file_iter;
|
||||
|
||||
TORRENT_ASSERT(file_iter != files().end());
|
||||
fs::path p = m_save_path / file_iter->path;
|
||||
file_offset = 0;
|
||||
error_code ec;
|
||||
out = m_pool.open_file(
|
||||
this, p, file::out | file::in, ec);
|
||||
|
||||
if (!out || ec)
|
||||
int actual_written = int(out->write(buf + buf_pos, write_bytes, ec));
|
||||
|
||||
if (write_bytes != actual_written || ec)
|
||||
{
|
||||
set_error(p, ec);
|
||||
// the file was not big enough
|
||||
if (actual_written > 0) buf_pos += actual_written;
|
||||
set_error(m_save_path / file_iter->path, ec);
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_type pos = out->seek(file_iter->file_base, file::begin, ec);
|
||||
|
||||
if (pos != file_iter->file_base || ec)
|
||||
{
|
||||
set_error(p, ec);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
|
|
@ -506,6 +506,27 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
TORRENT_ASSERT(m_block_size > 0);
|
||||
int file = 0;
|
||||
for (file_storage::iterator i = m_torrent_file->files().begin()
|
||||
, end(m_torrent_file->files().end()); i != end; ++i, ++file)
|
||||
{
|
||||
if (!i->pad_file) continue;
|
||||
|
||||
peer_request pr = m_torrent_file->map_file(file, 0, m_torrent_file->file_at(file).size);
|
||||
int off = pr.start % m_block_size;
|
||||
if (off != 0) { pr.length -= m_block_size - off; pr.start += m_block_size - off; }
|
||||
TORRENT_ASSERT((pr.start % m_block_size) == 0);
|
||||
|
||||
int blocks_per_piece = m_torrent_file->piece_length() / m_block_size;
|
||||
piece_block pb(pr.piece, pr.start / m_block_size);
|
||||
for (; pr.length >= m_block_size; pr.length -= m_block_size, ++pb.block_index)
|
||||
{
|
||||
if (pb.block_index == blocks_per_piece) { pb.block_index = 0; ++pb.piece_index; }
|
||||
m_picker->mark_as_finished(pb, 0);
|
||||
}
|
||||
}
|
||||
|
||||
m_storage->async_check_fastresume(&m_resume_entry
|
||||
, bind(&torrent::on_resume_data_checked
|
||||
, shared_from_this(), _1, _2));
|
||||
|
|
|
@ -187,6 +187,11 @@ namespace
|
|||
verify_encoding(target);
|
||||
if (target.path.is_complete())
|
||||
return false;
|
||||
|
||||
// bitcomet pad file
|
||||
if (target.path.filename().substr(0, 18) == "_____padding_file_")
|
||||
target.pad_file = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -416,6 +421,9 @@ namespace libtorrent
|
|||
e.path = name;
|
||||
e.offset = 0;
|
||||
e.size = info.dict_find_int_value("length", -1);
|
||||
// bitcomet pad file
|
||||
if (e.path.filename().substr(0, 18) == "_____padding_file_")
|
||||
e.pad_file = true;
|
||||
if (e.size < 0)
|
||||
{
|
||||
error = "invalid length of torrent";
|
||||
|
|
Loading…
Reference in New Issue