refactor: make parts of tr file private (#2241)
* refactor: make parts of tr_file private
This commit is contained in:
parent
f6f0db75e1
commit
34881f6295
|
@ -151,12 +151,12 @@ bool refreshFilesForeach(
|
|||
if (is_file)
|
||||
{
|
||||
auto const* tor = refresh_data.tor;
|
||||
auto const* inf = tr_torrentInfo(tor);
|
||||
int const enabled = inf->files[index].dnd ? 0 : 1;
|
||||
int const priority = inf->files[index].priority;
|
||||
auto const progress = tr_torrentFileProgress(tor, index);
|
||||
uint64_t const have = progress.bytes_completed;
|
||||
int const prog = std::clamp(int(100 * progress.progress), 0, 100);
|
||||
auto const file = tr_torrentFile(tor, index);
|
||||
int const enabled = file.wanted;
|
||||
int const priority = file.priority;
|
||||
auto const progress = file.progress;
|
||||
uint64_t const have = file.have;
|
||||
int const prog = std::clamp(int(100 * progress), 0, 100);
|
||||
|
||||
if (priority != old_priority || enabled != old_enabled || have != old_have || prog != old_prog)
|
||||
{
|
||||
|
@ -425,9 +425,9 @@ void buildTree(FileRowNode& node, build_data& build)
|
|||
|
||||
auto const mime_type = isLeaf ? gtr_get_mime_type_from_filename(child_data.name) : DIRECTORY_MIME_TYPE;
|
||||
auto const icon = gtr_get_mime_type_icon(mime_type, Gtk::ICON_SIZE_MENU, *build.w);
|
||||
auto const* inf = tr_torrentInfo(build.tor);
|
||||
int const priority = isLeaf ? inf->files[child_data.index].priority : 0;
|
||||
bool const enabled = isLeaf ? !inf->files[child_data.index].dnd : true;
|
||||
auto const file = tr_torrentFile(build.tor, child_data.index);
|
||||
int const priority = isLeaf ? file.priority : 0;
|
||||
bool const enabled = isLeaf ? file.wanted : true;
|
||||
auto name_esc = Glib::Markup::escape_text(child_data.name);
|
||||
|
||||
auto const child_iter = build.store->append(build.iter->children());
|
||||
|
@ -490,13 +490,12 @@ void FileList::Impl::set_torrent(int torrentId)
|
|||
root_data.index = -1;
|
||||
root_data.length = 0;
|
||||
|
||||
auto const* inf = tr_torrentInfo(tor);
|
||||
for (tr_file_index_t i = 0; i < inf->fileCount; ++i)
|
||||
for (tr_file_index_t i = 0, n_files = tr_torrentFileCount(tor); i < n_files; ++i)
|
||||
{
|
||||
auto* parent = &root;
|
||||
auto const* const file = &inf->files[i];
|
||||
auto const file = tr_torrentFile(tor, i);
|
||||
|
||||
for (char const *last = file->name, *next = strchr(last, '/'); last != nullptr;
|
||||
for (char const *last = file.name, *next = strchr(last, '/'); last != nullptr;
|
||||
last = next != nullptr ? next + 1 : nullptr, next = last != nullptr ? strchr(last, '/') : nullptr)
|
||||
{
|
||||
bool const isLeaf = next == nullptr;
|
||||
|
@ -509,7 +508,7 @@ void FileList::Impl::set_torrent(int torrentId)
|
|||
auto& row = node->data();
|
||||
row.name = std::move(name);
|
||||
row.index = isLeaf ? (int)i : -1;
|
||||
row.length = isLeaf ? file->length : 0;
|
||||
row.length = isLeaf ? file.length : 0;
|
||||
parent->append(*node);
|
||||
}
|
||||
|
||||
|
|
|
@ -623,15 +623,13 @@ bool testText(tr_torrent const* tor, Glib::ustring const* key)
|
|||
}
|
||||
else
|
||||
{
|
||||
tr_info const* inf = tr_torrentInfo(tor);
|
||||
|
||||
/* test the torrent name... */
|
||||
ret = Glib::ustring(tr_torrentName(tor)).casefold().find(*key) != Glib::ustring::npos;
|
||||
|
||||
/* test the files... */
|
||||
for (tr_file_index_t i = 0; i < inf->fileCount && !ret; ++i)
|
||||
for (tr_file_index_t i = 0, n = tr_torrentFileCount(tor); i < n && !ret; ++i)
|
||||
{
|
||||
ret = Glib::ustring(inf->files[i].name).casefold().find(*key) != Glib::ustring::npos;
|
||||
ret = Glib::ustring(tr_torrentFile(tor, i).name).casefold().find(*key) != Glib::ustring::npos;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -105,9 +105,8 @@ void g_signal_callback(
|
|||
}
|
||||
else if (action == "file")
|
||||
{
|
||||
auto const* inf = tr_torrentInfo(tor);
|
||||
char const* dir = tr_torrentGetDownloadDir(tor);
|
||||
auto const path = Glib::build_filename(dir, inf->files[0].name);
|
||||
auto const path = Glib::build_filename(dir, tr_torrentFile(tor, 0).name);
|
||||
gtr_open_file(path);
|
||||
}
|
||||
else if (action == "start-now")
|
||||
|
@ -193,9 +192,7 @@ void gtr_notify_torrent_completed(Glib::RefPtr<Session> const& core, int torrent
|
|||
std::vector<Glib::ustring> actions;
|
||||
if (server_supports_actions)
|
||||
{
|
||||
auto const* inf = tr_torrentInfo(tor);
|
||||
|
||||
if (inf->fileCount == 1)
|
||||
if (tr_torrentFileCount(tor) == 1)
|
||||
{
|
||||
actions.push_back("file");
|
||||
actions.push_back(_("Open File"));
|
||||
|
|
|
@ -1827,7 +1827,7 @@ void Session::open_folder(int torrent_id)
|
|||
|
||||
if (tor != nullptr)
|
||||
{
|
||||
bool const single = tr_torrentInfo(tor)->fileCount == 1;
|
||||
bool const single = tr_torrentFileCount(tor) == 1;
|
||||
char const* currentDir = tr_torrentGetCurrentDir(tor);
|
||||
|
||||
if (single)
|
||||
|
|
|
@ -383,23 +383,21 @@ namespace
|
|||
Glib::RefPtr<Gdk::Pixbuf> get_icon(tr_torrent const* tor, Gtk::IconSize icon_size, Gtk::Widget& for_widget)
|
||||
{
|
||||
Glib::ustring mime_type;
|
||||
auto const* const info = tr_torrentInfo(tor);
|
||||
auto const n_files = tr_torrentFileCount(tor);
|
||||
|
||||
if (info->fileCount == 0)
|
||||
if (n_files == 0)
|
||||
{
|
||||
mime_type = UNKNOWN_MIME_TYPE;
|
||||
}
|
||||
else if (info->fileCount > 1)
|
||||
{
|
||||
mime_type = DIRECTORY_MIME_TYPE;
|
||||
}
|
||||
else if (strchr(info->files[0].name, '/') != nullptr)
|
||||
else if (n_files > 1)
|
||||
{
|
||||
mime_type = DIRECTORY_MIME_TYPE;
|
||||
}
|
||||
else
|
||||
{
|
||||
mime_type = gtr_get_mime_type_from_filename(info->files[0].name);
|
||||
auto const* const name = tr_torrentFile(tor, 0).name;
|
||||
|
||||
mime_type = strchr(name, '/') != nullptr ? DIRECTORY_MIME_TYPE : gtr_get_mime_type_from_filename(name);
|
||||
}
|
||||
|
||||
return gtr_get_mime_type_icon(mime_type, icon_size, for_widget);
|
||||
|
|
|
@ -51,14 +51,13 @@ static int readOrWriteBytes(
|
|||
{
|
||||
int err = 0;
|
||||
bool const doWrite = ioMode >= TR_IO_WRITE;
|
||||
tr_info const* const info = &tor->info;
|
||||
tr_file const* const file = &info->files[fileIndex];
|
||||
|
||||
TR_ASSERT(fileIndex < info->fileCount);
|
||||
TR_ASSERT(file->length == 0 || fileOffset < file->length);
|
||||
TR_ASSERT(fileOffset + buflen <= file->length);
|
||||
TR_ASSERT(fileIndex < tr_torrentFileCount(tor));
|
||||
auto const file = tr_torrentFile(tor, fileIndex);
|
||||
TR_ASSERT(file.length == 0 || fileOffset < file.length);
|
||||
TR_ASSERT(fileOffset + buflen <= file.length);
|
||||
|
||||
if (file->length == 0)
|
||||
if (file.length == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -85,17 +84,17 @@ static int readOrWriteBytes(
|
|||
/* figure out where the file should go, so we can create it */
|
||||
base = tr_torrentGetCurrentDir(tor);
|
||||
subpath = tr_sessionIsIncompleteFileNamingEnabled(tor->session) ? tr_torrentBuildPartial(tor, fileIndex) :
|
||||
tr_strdup(file->name);
|
||||
tr_strdup(file.name);
|
||||
}
|
||||
|
||||
if (err == 0)
|
||||
{
|
||||
/* open (and maybe create) the file */
|
||||
auto const filename = tr_strvPath(base, subpath);
|
||||
tr_preallocation_mode const prealloc = (file->dnd || !doWrite) ? TR_PREALLOCATE_NONE :
|
||||
tor->session->preallocationMode;
|
||||
tr_preallocation_mode const prealloc = (!file.wanted || !doWrite) ? TR_PREALLOCATE_NONE :
|
||||
tor->session->preallocationMode;
|
||||
|
||||
fd = tr_fdFileCheckout(session, tor->uniqueId, fileIndex, filename.c_str(), doWrite, prealloc, file->length);
|
||||
fd = tr_fdFileCheckout(session, tor->uniqueId, fileIndex, filename.c_str(), doWrite, prealloc, file.length);
|
||||
if (fd == TR_BAD_SYS_FILE)
|
||||
{
|
||||
err = errno;
|
||||
|
@ -124,7 +123,7 @@ static int readOrWriteBytes(
|
|||
if (!tr_sys_file_read_at(fd, buf, buflen, fileOffset, nullptr, &error))
|
||||
{
|
||||
err = error->code;
|
||||
tr_logAddTorErr(tor, "read failed for \"%s\": %s", file->name, error->message);
|
||||
tr_logAddTorErr(tor, "read failed for \"%s\": %s", file.name, error->message);
|
||||
tr_error_free(error);
|
||||
}
|
||||
}
|
||||
|
@ -133,7 +132,7 @@ static int readOrWriteBytes(
|
|||
if (!tr_sys_file_write_at(fd, buf, buflen, fileOffset, nullptr, &error))
|
||||
{
|
||||
err = error->code;
|
||||
tr_logAddTorErr(tor, "write failed for \"%s\": %s", file->name, error->message);
|
||||
tr_logAddTorErr(tor, "write failed for \"%s\": %s", file.name, error->message);
|
||||
tr_error_free(error);
|
||||
}
|
||||
}
|
||||
|
@ -155,12 +154,12 @@ static int compareOffsetToFile(void const* a, void const* b)
|
|||
auto const offset = *static_cast<uint64_t const*>(a);
|
||||
auto const* file = static_cast<tr_file const*>(b);
|
||||
|
||||
if (offset < file->offset)
|
||||
if (offset < file->priv.offset)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (offset >= file->offset + file->length)
|
||||
if (offset >= file->priv.offset + file->length)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
@ -187,10 +186,10 @@ void tr_ioFindFileLocation(
|
|||
if (file != nullptr)
|
||||
{
|
||||
*fileIndex = file - tor->info.files;
|
||||
*fileOffset = offset - file->offset;
|
||||
*fileOffset = offset - file->priv.offset;
|
||||
TR_ASSERT(*fileIndex < tor->info.fileCount);
|
||||
TR_ASSERT(*fileOffset < file->length);
|
||||
TR_ASSERT(tor->info.files[*fileIndex].offset + *fileOffset == offset);
|
||||
TR_ASSERT(tor->info.files[*fileIndex].priv.offset + *fileOffset == offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "metainfo.h"
|
||||
#include "platform.h" /* tr_getTorrentDir() */
|
||||
#include "session.h"
|
||||
#include "torrent.h"
|
||||
#include "tr-assert.h"
|
||||
#include "utils.h"
|
||||
#include "variant.h"
|
||||
|
@ -213,7 +214,7 @@ static char const* parseFiles(tr_info* inf, tr_variant* files, tr_variant const*
|
|||
}
|
||||
|
||||
inf->files[i].length = len;
|
||||
inf->files[i].is_renamed = is_root_adjusted || is_file_adjusted;
|
||||
inf->files[i].priv.is_renamed = is_root_adjusted || is_file_adjusted;
|
||||
inf->totalSize += len;
|
||||
}
|
||||
}
|
||||
|
@ -224,7 +225,7 @@ static char const* parseFiles(tr_info* inf, tr_variant* files, tr_variant const*
|
|||
inf->files = tr_new0(tr_file, 1);
|
||||
inf->files[0].name = tr_strndup(root_name.c_str(), std::size(root_name));
|
||||
inf->files[0].length = len;
|
||||
inf->files[0].is_renamed = is_root_adjusted;
|
||||
inf->files[0].priv.is_renamed = is_root_adjusted;
|
||||
inf->totalSize += len;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -139,14 +139,12 @@ static uint64_t loadLabels(tr_variant* dict, tr_torrent* tor)
|
|||
|
||||
static void saveDND(tr_variant* dict, tr_torrent const* tor)
|
||||
{
|
||||
tr_info const* const inf = tr_torrentInfo(tor);
|
||||
tr_file_index_t const n = inf->fileCount;
|
||||
|
||||
auto const n = tr_torrentFileCount(tor);
|
||||
tr_variant* const list = tr_variantDictAddList(dict, TR_KEY_dnd, n);
|
||||
|
||||
for (tr_file_index_t i = 0; i < n; ++i)
|
||||
{
|
||||
tr_variantListAddBool(list, inf->files[i].dnd);
|
||||
tr_variantListAddBool(list, !tr_torrentFile(tor, i).wanted);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,13 +210,12 @@ static uint64_t loadDND(tr_variant* dict, tr_torrent* tor)
|
|||
|
||||
static void saveFilePriorities(tr_variant* dict, tr_torrent const* tor)
|
||||
{
|
||||
tr_info const* const inf = tr_torrentInfo(tor);
|
||||
tr_file_index_t const n = inf->fileCount;
|
||||
auto const n = tr_torrentFileCount(tor);
|
||||
|
||||
tr_variant* const list = tr_variantDictAddList(dict, TR_KEY_priority, n);
|
||||
for (tr_file_index_t i = 0; i < n; ++i)
|
||||
{
|
||||
tr_variantListAddInt(list, inf->files[i].priority);
|
||||
tr_variantListAddInt(list, tr_torrentFile(tor, i).priority);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -411,7 +408,7 @@ static void saveFilenames(tr_variant* dict, tr_torrent const* tor)
|
|||
|
||||
for (tr_file_index_t i = 0; !any_renamed && i < n; ++i)
|
||||
{
|
||||
any_renamed = files[i].is_renamed;
|
||||
any_renamed = files[i].priv.is_renamed;
|
||||
}
|
||||
|
||||
if (any_renamed)
|
||||
|
@ -420,7 +417,7 @@ static void saveFilenames(tr_variant* dict, tr_torrent const* tor)
|
|||
|
||||
for (tr_file_index_t i = 0; i < n; ++i)
|
||||
{
|
||||
tr_variantListAddStrView(list, files[i].is_renamed ? files[i].name : "");
|
||||
tr_variantListAddStrView(list, files[i].priv.is_renamed ? files[i].name : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -442,7 +439,7 @@ static uint64_t loadFilenames(tr_variant* dict, tr_torrent* tor)
|
|||
{
|
||||
tr_free(files[i].name);
|
||||
files[i].name = tr_strvDup(sv);
|
||||
files[i].is_renamed = true;
|
||||
files[i].priv.is_renamed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -493,11 +490,11 @@ static void saveProgress(tr_variant* dict, tr_torrent* tor)
|
|||
tr_variant* const prog = tr_variantDictAddDict(dict, TR_KEY_progress, 4);
|
||||
|
||||
// add the mtimes
|
||||
size_t const n = inf->fileCount;
|
||||
size_t const n = tr_torrentFileCount(tor);
|
||||
tr_variant* const l = tr_variantDictAddList(prog, TR_KEY_mtimes, n);
|
||||
for (auto const *file = inf->files, *end = file + inf->fileCount; file != end; ++file)
|
||||
for (auto const *file = inf->files, *end = file + n; file != end; ++file)
|
||||
{
|
||||
tr_variantListAddInt(l, file->mtime);
|
||||
tr_variantListAddInt(l, file->priv.mtime);
|
||||
}
|
||||
|
||||
// add the 'checked pieces' bitfield
|
||||
|
@ -538,14 +535,14 @@ static uint64_t loadProgress(tr_variant* dict, tr_torrent* tor)
|
|||
auto ret = uint64_t{};
|
||||
tr_info const* inf = tr_torrentInfo(tor);
|
||||
|
||||
tr_variant* prog = nullptr;
|
||||
if (tr_variantDictFindDict(dict, TR_KEY_progress, &prog))
|
||||
if (tr_variant* prog = nullptr; tr_variantDictFindDict(dict, TR_KEY_progress, &prog))
|
||||
{
|
||||
/// CHECKED PIECES
|
||||
|
||||
auto checked = tr_bitfield(inf->pieceCount);
|
||||
auto mtimes = std::vector<time_t>{};
|
||||
mtimes.reserve(inf->fileCount);
|
||||
auto const n_files = tr_torrentFileCount(tor);
|
||||
mtimes.reserve(n_files);
|
||||
|
||||
// try to load mtimes
|
||||
tr_variant* l = nullptr;
|
||||
|
@ -570,7 +567,7 @@ static uint64_t loadProgress(tr_variant* dict, tr_torrent* tor)
|
|||
// maybe it's a .resume file from [2.20 - 3.00] with the per-piece mtimes
|
||||
if (tr_variantDictFindList(prog, TR_KEY_time_checked, &l))
|
||||
{
|
||||
for (tr_file_index_t fi = 0; fi < inf->fileCount; ++fi)
|
||||
for (tr_file_index_t fi = 0; fi < n_files; ++fi)
|
||||
{
|
||||
tr_variant* const b = tr_variantListChild(l, fi);
|
||||
tr_file* const f = &inf->files[fi];
|
||||
|
@ -588,7 +585,7 @@ static uint64_t loadProgress(tr_variant* dict, tr_torrent* tor)
|
|||
tr_variantGetInt(tr_variantListChild(b, 0), &offset);
|
||||
|
||||
time_checked = tr_time();
|
||||
size_t const pieces = f->lastPiece + 1 - f->firstPiece;
|
||||
size_t const pieces = f->priv.lastPiece + 1 - f->priv.firstPiece;
|
||||
for (size_t i = 0; i < pieces; ++i)
|
||||
{
|
||||
int64_t piece_time = 0;
|
||||
|
|
|
@ -382,27 +382,25 @@ static void addLabels(tr_torrent const* tor, tr_variant* list)
|
|||
|
||||
static void addFileStats(tr_torrent const* tor, tr_variant* list)
|
||||
{
|
||||
auto const* const info = tr_torrentInfo(tor);
|
||||
for (tr_file_index_t i = 0; i < info->fileCount; ++i)
|
||||
for (tr_file_index_t i = 0, n = tr_torrentFileCount(tor); i < n; ++i)
|
||||
{
|
||||
auto const* const file = &info->files[i];
|
||||
tr_variant* const d = tr_variantListAddDict(list, 3);
|
||||
tr_variantDictAddInt(d, TR_KEY_bytesCompleted, tr_torrentFileProgress(tor, i).bytes_completed);
|
||||
tr_variantDictAddInt(d, TR_KEY_priority, file->priority);
|
||||
tr_variantDictAddBool(d, TR_KEY_wanted, !file->dnd);
|
||||
auto const file = tr_torrentFile(tor, i);
|
||||
tr_variant* d = tr_variantListAddDict(list, 3);
|
||||
tr_variantDictAddInt(d, TR_KEY_bytesCompleted, file.length);
|
||||
tr_variantDictAddInt(d, TR_KEY_priority, file.priority);
|
||||
tr_variantDictAddBool(d, TR_KEY_wanted, file.wanted);
|
||||
}
|
||||
}
|
||||
|
||||
static void addFiles(tr_torrent const* tor, tr_variant* list)
|
||||
{
|
||||
auto const* const info = tr_torrentInfo(tor);
|
||||
for (tr_file_index_t i = 0; i < info->fileCount; ++i)
|
||||
for (tr_file_index_t i = 0, n = tr_torrentFileCount(tor); i < n; ++i)
|
||||
{
|
||||
tr_file const* file = &info->files[i];
|
||||
auto const file = tr_torrentFile(tor, i);
|
||||
tr_variant* d = tr_variantListAddDict(list, 3);
|
||||
tr_variantDictAddInt(d, TR_KEY_bytesCompleted, tr_torrentFileProgress(tor, i).bytes_completed);
|
||||
tr_variantDictAddInt(d, TR_KEY_length, file->length);
|
||||
tr_variantDictAddStr(d, TR_KEY_name, file->name);
|
||||
tr_variantDictAddInt(d, TR_KEY_bytesCompleted, file.have);
|
||||
tr_variantDictAddInt(d, TR_KEY_length, file.length);
|
||||
tr_variantDictAddStr(d, TR_KEY_name, file.name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -570,16 +568,16 @@ static void initField(
|
|||
break;
|
||||
|
||||
case TR_KEY_file_count:
|
||||
tr_variantInitInt(initme, inf->fileCount);
|
||||
tr_variantInitInt(initme, tr_torrentFileCount(tor));
|
||||
break;
|
||||
|
||||
case TR_KEY_files:
|
||||
tr_variantInitList(initme, inf->fileCount);
|
||||
tr_variantInitList(initme, tr_torrentFileCount(tor));
|
||||
addFiles(tor, initme);
|
||||
break;
|
||||
|
||||
case TR_KEY_fileStats:
|
||||
tr_variantInitList(initme, inf->fileCount);
|
||||
tr_variantInitList(initme, tr_torrentFileCount(tor));
|
||||
addFileStats(tor, initme);
|
||||
break;
|
||||
|
||||
|
@ -715,12 +713,14 @@ static void initField(
|
|||
break;
|
||||
|
||||
case TR_KEY_priorities:
|
||||
tr_variantInitList(initme, inf->fileCount);
|
||||
for (tr_file_index_t i = 0; i < inf->fileCount; ++i)
|
||||
{
|
||||
tr_variantListAddInt(initme, inf->files[i].priority);
|
||||
auto const n = tr_torrentFileCount(tor);
|
||||
tr_variantInitList(initme, n);
|
||||
for (tr_file_index_t i = 0; i < n; ++i)
|
||||
{
|
||||
tr_variantListAddInt(initme, tr_torrentFile(tor, i).priority);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TR_KEY_queuePosition:
|
||||
|
@ -823,13 +823,14 @@ static void initField(
|
|||
break;
|
||||
|
||||
case TR_KEY_wanted:
|
||||
tr_variantInitList(initme, inf->fileCount);
|
||||
|
||||
for (tr_file_index_t i = 0; i < inf->fileCount; ++i)
|
||||
{
|
||||
tr_variantListAddInt(initme, inf->files[i].dnd ? 0 : 1);
|
||||
auto const n = tr_torrentFileCount(tor);
|
||||
tr_variantInitList(initme, n);
|
||||
for (tr_file_index_t i = 0; i < n; ++i)
|
||||
{
|
||||
tr_variantListAddInt(initme, tr_torrentFile(tor, i).wanted);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TR_KEY_webseeds:
|
||||
|
|
|
@ -584,17 +584,17 @@ static constexpr void initFilePieces(tr_torrent* tor, tr_file_index_t fileIndex)
|
|||
TR_ASSERT(tor != nullptr);
|
||||
TR_ASSERT(fileIndex < tor->info.fileCount);
|
||||
|
||||
tr_file* file = &tor->info.files[fileIndex];
|
||||
uint64_t first_byte = file->offset;
|
||||
uint64_t last_byte = first_byte + (file->length != 0 ? file->length - 1 : 0);
|
||||
tr_file& file = tor->info.files[fileIndex];
|
||||
uint64_t first_byte = file.priv.offset;
|
||||
uint64_t last_byte = first_byte + (file.length != 0 ? file.length - 1 : 0);
|
||||
|
||||
file->firstPiece = tor->pieceOf(first_byte);
|
||||
file->lastPiece = tor->pieceOf(last_byte);
|
||||
file.priv.firstPiece = tor->pieceOf(first_byte);
|
||||
file.priv.lastPiece = tor->pieceOf(last_byte);
|
||||
}
|
||||
|
||||
static constexpr bool pieceHasFile(tr_piece_index_t piece, tr_file const* file)
|
||||
{
|
||||
return file->firstPiece <= piece && piece <= file->lastPiece;
|
||||
return file->priv.firstPiece <= piece && piece <= file->priv.lastPiece;
|
||||
}
|
||||
|
||||
static tr_priority_t calculatePiecePriority(tr_info const& info, tr_piece_index_t piece, tr_file_index_t file_hint)
|
||||
|
@ -620,12 +620,12 @@ static tr_priority_t calculatePiecePriority(tr_info const& info, tr_piece_index_
|
|||
break;
|
||||
}
|
||||
|
||||
priority = std::max(priority, file->priority);
|
||||
priority = std::max(priority, file->priv.priority);
|
||||
|
||||
/* When dealing with multimedia files, getting the first and
|
||||
last pieces can sometimes allow you to preview it a bit
|
||||
before it's fully downloaded... */
|
||||
if ((file->priority >= TR_PRI_NORMAL) && (file->firstPiece == piece || file->lastPiece == piece))
|
||||
if ((file->priv.priority >= TR_PRI_NORMAL) && (file->priv.firstPiece == piece || file->priv.lastPiece == piece))
|
||||
{
|
||||
priority = TR_PRI_HIGH;
|
||||
}
|
||||
|
@ -642,7 +642,7 @@ static void tr_torrentInitFilePieces(tr_torrent* tor)
|
|||
/* assign the file offsets */
|
||||
for (tr_file_index_t f = 0; f < inf->fileCount; ++f)
|
||||
{
|
||||
inf->files[f].offset = offset;
|
||||
inf->files[f].priv.offset = offset;
|
||||
offset += inf->files[f].length;
|
||||
initFilePieces(tor, f);
|
||||
}
|
||||
|
@ -666,7 +666,7 @@ static void tr_torrentInitPiecePriorities(tr_torrent* tor)
|
|||
|
||||
for (tr_piece_index_t p = 0; p < inf->pieceCount; ++p)
|
||||
{
|
||||
while (inf->files[f].lastPiece < p)
|
||||
while (inf->files[f].priv.lastPiece < p)
|
||||
{
|
||||
++f;
|
||||
}
|
||||
|
@ -1288,7 +1288,7 @@ static uint64_t countFileBytesCompleted(tr_torrent const* tor, tr_file_index_t i
|
|||
// the first block
|
||||
if (tor->hasBlock(begin))
|
||||
{
|
||||
total += tor->block_size - f.offset % tor->block_size;
|
||||
total += tor->block_size - f.priv.offset % tor->block_size;
|
||||
}
|
||||
|
||||
// the middle blocks
|
||||
|
@ -1302,26 +1302,37 @@ static uint64_t countFileBytesCompleted(tr_torrent const* tor, tr_file_index_t i
|
|||
// the last block
|
||||
if (tor->hasBlock(end - 1))
|
||||
{
|
||||
total += f.offset + f.length - (uint64_t)tor->block_size * (end - 1);
|
||||
total += f.priv.offset + f.length - (uint64_t)tor->block_size * (end - 1);
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
tr_file_progress tr_torrentFileProgress(tr_torrent const* torrent, tr_file_index_t file)
|
||||
tr_file_view tr_torrentFile(tr_torrent const* torrent, tr_file_index_t i)
|
||||
{
|
||||
TR_ASSERT(tr_isTorrent(torrent));
|
||||
TR_ASSERT(file < torrent->info.fileCount);
|
||||
TR_ASSERT(i < torrent->info.fileCount);
|
||||
|
||||
tr_file_index_t const total = torrent->info.files[file].length;
|
||||
auto const& file = torrent->info.files[i];
|
||||
auto const* const name = file.name;
|
||||
auto const priority = file.priv.priority;
|
||||
auto const wanted = !file.priv.dnd;
|
||||
auto const length = file.length;
|
||||
|
||||
if (torrent->completeness == TR_SEED || total == 0)
|
||||
if (torrent->completeness == TR_SEED || length == 0)
|
||||
{
|
||||
return { total, total, 1.0 };
|
||||
return { name, length, length, 1.0, priority, wanted };
|
||||
}
|
||||
|
||||
auto const have = countFileBytesCompleted(torrent, file);
|
||||
return { have, total, have >= total ? 1.0 : have / double(total) };
|
||||
auto const have = countFileBytesCompleted(torrent, i);
|
||||
return { name, have, length, have >= length ? 1.0 : have / double(length), priority, wanted };
|
||||
}
|
||||
|
||||
size_t tr_torrentFileCount(tr_torrent const* torrent)
|
||||
{
|
||||
TR_ASSERT(tr_isTorrent(torrent));
|
||||
|
||||
return torrent->info.fileCount;
|
||||
}
|
||||
|
||||
/***
|
||||
|
@ -2060,9 +2071,9 @@ void tr_torrentInitFilePriority(tr_torrent* tor, tr_file_index_t fileIndex, tr_p
|
|||
auto& info = tor->info;
|
||||
tr_file* file = &info.files[fileIndex];
|
||||
|
||||
file->priority = priority;
|
||||
file->priv.priority = priority;
|
||||
|
||||
for (tr_piece_index_t i = file->firstPiece; i <= file->lastPiece; ++i)
|
||||
for (tr_piece_index_t i = file->priv.firstPiece; i <= file->priv.lastPiece; ++i)
|
||||
{
|
||||
tor->setPiecePriority(i, calculatePiecePriority(info, i, fileIndex));
|
||||
}
|
||||
|
@ -2096,7 +2107,7 @@ tr_priority_t* tr_torrentGetFilePriorities(tr_torrent const* tor)
|
|||
|
||||
for (tr_file_index_t i = 0; i < tor->info.fileCount; ++i)
|
||||
{
|
||||
p[i] = tor->info.files[i].priority;
|
||||
p[i] = tor->info.files[i].priv.priority;
|
||||
}
|
||||
|
||||
return p;
|
||||
|
@ -2111,9 +2122,9 @@ static void setFileDND(tr_torrent* tor, tr_file_index_t fileIndex, bool doDownlo
|
|||
bool const dnd = !doDownload;
|
||||
tr_file* file = &tor->info.files[fileIndex];
|
||||
|
||||
file->dnd = dnd;
|
||||
auto const firstPiece = file->firstPiece;
|
||||
auto const lastPiece = file->lastPiece;
|
||||
file->priv.dnd = dnd;
|
||||
auto const firstPiece = file->priv.firstPiece;
|
||||
auto const lastPiece = file->priv.lastPiece;
|
||||
|
||||
/* can't set the first piece to DND unless
|
||||
every file using that piece is DND */
|
||||
|
@ -2123,12 +2134,12 @@ static void setFileDND(tr_torrent* tor, tr_file_index_t fileIndex, bool doDownlo
|
|||
{
|
||||
for (tr_file_index_t i = fileIndex - 1; firstPieceDND; --i)
|
||||
{
|
||||
if (tor->info.files[i].lastPiece != firstPiece)
|
||||
if (tor->info.files[i].priv.lastPiece != firstPiece)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
firstPieceDND = tor->info.files[i].dnd;
|
||||
firstPieceDND = tor->info.files[i].priv.dnd;
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
|
@ -2143,12 +2154,12 @@ static void setFileDND(tr_torrent* tor, tr_file_index_t fileIndex, bool doDownlo
|
|||
|
||||
for (tr_file_index_t i = fileIndex + 1; lastPieceDND && i < tor->info.fileCount; ++i)
|
||||
{
|
||||
if (tor->info.files[i].firstPiece != lastPiece)
|
||||
if (tor->info.files[i].priv.firstPiece != lastPiece)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
lastPieceDND = tor->info.files[i].dnd;
|
||||
lastPieceDND = tor->info.files[i].priv.dnd;
|
||||
}
|
||||
|
||||
// update dnd_pieces_
|
||||
|
@ -2331,7 +2342,7 @@ tr_block_span_t tr_torGetFileBlockSpan(tr_torrent const* tor, tr_file_index_t co
|
|||
{
|
||||
tr_file const* f = &tor->info.files[file];
|
||||
|
||||
uint64_t offset = f->offset;
|
||||
uint64_t offset = f->priv.offset;
|
||||
tr_block_index_t const begin = offset / tor->block_size;
|
||||
if (f->length == 0)
|
||||
{
|
||||
|
@ -2519,7 +2530,7 @@ uint64_t tr_torrentGetBytesLeftToAllocate(tr_torrent const* tor)
|
|||
|
||||
for (tr_file_index_t i = 0; i < tor->info.fileCount; ++i)
|
||||
{
|
||||
if (!tor->info.files[i].dnd)
|
||||
if (!tor->info.files[i].priv.dnd)
|
||||
{
|
||||
tr_sys_path_info info;
|
||||
uint64_t const length = tor->info.files[i].length;
|
||||
|
@ -2967,7 +2978,7 @@ static void tr_torrentFileCompleted(tr_torrent* tor, tr_file_index_t fileIndex)
|
|||
|
||||
/* now that the file is complete and closed, we can start watching its
|
||||
* mtime timestamp for changes to know if we need to reverify pieces */
|
||||
f->mtime = now;
|
||||
f->priv.mtime = now;
|
||||
|
||||
/* if the torrent's current filename isn't the same as the one in the
|
||||
* metadata -- for example, if it had the ".part" suffix appended to
|
||||
|
@ -3002,7 +3013,7 @@ static void tr_torrentPieceCompleted(tr_torrent* tor, tr_piece_index_t pieceInde
|
|||
{
|
||||
tr_file const* file = &tor->info.files[i];
|
||||
|
||||
if ((file->firstPiece <= pieceIndex) && (pieceIndex <= file->lastPiece) &&
|
||||
if ((file->priv.firstPiece <= pieceIndex) && (pieceIndex <= file->priv.lastPiece) &&
|
||||
tor->completion.hasBlocks(tr_torGetFileBlockSpan(tor, i)))
|
||||
{
|
||||
tr_torrentFileCompleted(tor, i);
|
||||
|
@ -3435,7 +3446,7 @@ static void renameTorrentFileString(tr_torrent* tor, char const* oldpath, char c
|
|||
{
|
||||
tr_free(file->name);
|
||||
file->name = name;
|
||||
file->is_renamed = true;
|
||||
file->priv.is_renamed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -305,13 +305,13 @@ public:
|
|||
auto const found = this->findFile(filename, i);
|
||||
auto const mtime = found ? found->last_modified_at : 0;
|
||||
|
||||
info.files[i].mtime = mtime;
|
||||
info.files[i].priv.mtime = mtime;
|
||||
|
||||
// if a file has changed, mark its pieces as unchecked
|
||||
if (mtime == 0 || mtime != mtimes[i])
|
||||
{
|
||||
auto const begin = info.files[i].firstPiece;
|
||||
auto const end = info.files[i].lastPiece + 1;
|
||||
auto const begin = info.files[i].priv.firstPiece;
|
||||
auto const end = info.files[i].priv.lastPiece + 1;
|
||||
checked_pieces_.unsetSpan(begin, end);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ struct tr_block_span_t
|
|||
};
|
||||
|
||||
struct tr_ctor;
|
||||
struct tr_file;
|
||||
struct tr_error;
|
||||
struct tr_info;
|
||||
struct tr_session;
|
||||
|
@ -1530,14 +1531,37 @@ void tr_torrentTrackersFree(tr_tracker_stat* trackerStats, int trackerCount);
|
|||
*/
|
||||
double* tr_torrentWebSpeeds_KBps(tr_torrent const* torrent);
|
||||
|
||||
struct tr_file_progress
|
||||
struct tr_file_view
|
||||
{
|
||||
uint64_t bytes_completed;
|
||||
uint64_t bytes_total;
|
||||
// This file's name. Includes the full subpath in the torrent.
|
||||
char const* name;
|
||||
|
||||
// the current size of the file, i.e. how much we've downloaded
|
||||
uint64_t have;
|
||||
|
||||
// the total size of the file
|
||||
uint64_t length;
|
||||
|
||||
// have / length
|
||||
double progress;
|
||||
|
||||
// the file's priority
|
||||
tr_priority_t priority;
|
||||
|
||||
// do we want to download this file?
|
||||
bool wanted;
|
||||
};
|
||||
|
||||
tr_file_progress tr_torrentFileProgress(tr_torrent const* torrent, tr_file_index_t file);
|
||||
/**
|
||||
* Returns a tr_file_view containing information about a file.
|
||||
*
|
||||
* This view structure is intended for short-term use. Pointers in it are
|
||||
* owned and managed by the torrent. Callers who want to keep this info
|
||||
* must make their own copy.
|
||||
*/
|
||||
tr_file_view tr_torrentFile(tr_torrent const* torrent, tr_file_index_t file);
|
||||
|
||||
size_t tr_torrentFileCount(tr_torrent const* torrent);
|
||||
|
||||
/***********************************************************************
|
||||
* tr_torrentAvailability
|
||||
|
@ -1575,18 +1599,25 @@ void tr_torrentVerify(tr_torrent* torrent, tr_verify_done_func callback_func_or_
|
|||
* tr_info
|
||||
**********************************************************************/
|
||||
|
||||
struct tr_file_priv
|
||||
{
|
||||
uint64_t offset; // file begins at the torrent's nth byte
|
||||
time_t mtime;
|
||||
tr_piece_index_t firstPiece; // We need pieces [firstPiece...
|
||||
tr_piece_index_t lastPiece; // ...lastPiece] to dl this file
|
||||
int8_t priority; // TR_PRI_HIGH, _NORMAL, or _LOW
|
||||
bool dnd; // "do not download" flag
|
||||
bool is_renamed; // true if we're using a different path from the one in the metainfo; ie, if the user has renamed it */
|
||||
};
|
||||
/** @brief a part of tr_info that represents a single file of the torrent's content */
|
||||
struct tr_file
|
||||
{
|
||||
time_t mtime;
|
||||
uint64_t length; /* Length of the file, in bytes */
|
||||
uint64_t offset; /* file begins at the torrent's nth byte */
|
||||
// public
|
||||
char* name; /* Path to the file */
|
||||
tr_piece_index_t firstPiece; /* We need pieces [firstPiece... */
|
||||
tr_piece_index_t lastPiece; /* ...lastPiece] to dl this file */
|
||||
int8_t priority; /* TR_PRI_HIGH, _NORMAL, or _LOW */
|
||||
bool dnd; /* "do not download" flag */
|
||||
bool is_renamed; /* true if we're using a different path from the one in the metainfo; ie, if the user has renamed it */
|
||||
uint64_t length; /* Length of the file, in bytes */
|
||||
|
||||
// libtransmission implementation; do not use
|
||||
tr_file_priv priv;
|
||||
};
|
||||
|
||||
/** @brief information about a torrent that comes from its metainfo file */
|
||||
|
@ -1613,6 +1644,8 @@ struct tr_info
|
|||
/* torrent's source. empty if not set. */
|
||||
char* source;
|
||||
|
||||
// Private.
|
||||
// Use tr_torrentFile() and tr_torrentFileCount() instead.
|
||||
tr_file* files;
|
||||
|
||||
/* these trackers are sorted by tier */
|
||||
|
|
|
@ -51,7 +51,7 @@ static bool verifyTorrent(tr_torrent* tor, bool* stopFlag)
|
|||
|
||||
while (!*stopFlag && piece < tor->info.pieceCount)
|
||||
{
|
||||
tr_file const* file = &tor->info.files[fileIndex];
|
||||
auto const file_length = tor->info.files[fileIndex].length;
|
||||
|
||||
/* if we're starting a new piece... */
|
||||
if (piecePos == 0)
|
||||
|
@ -71,7 +71,7 @@ static bool verifyTorrent(tr_torrent* tor, bool* stopFlag)
|
|||
|
||||
/* figure out how much we can read this pass */
|
||||
uint64_t leftInPiece = tor->pieceSize(piece) - piecePos;
|
||||
uint64_t leftInFile = file->length - filePos;
|
||||
uint64_t leftInFile = file_length - filePos;
|
||||
uint64_t bytesThisPass = std::min(leftInFile, leftInPiece);
|
||||
bytesThisPass = std::min(bytesThisPass, uint64_t{ buflen });
|
||||
|
||||
|
|
|
@ -481,16 +481,16 @@ static void web_response_func(
|
|||
}
|
||||
}
|
||||
|
||||
static std::string make_url(tr_webseed* w, tr_file const* file)
|
||||
static std::string make_url(tr_webseed* w, char const* name)
|
||||
{
|
||||
struct evbuffer* buf = evbuffer_new();
|
||||
|
||||
evbuffer_add(buf, std::data(w->base_url), std::size(w->base_url));
|
||||
|
||||
/* if url ends with a '/', add the torrent name */
|
||||
if (*std::rbegin(w->base_url) == '/' && file->name != nullptr)
|
||||
if (*std::rbegin(w->base_url) == '/' && name != nullptr)
|
||||
{
|
||||
tr_http_escape(buf, file->name, false);
|
||||
tr_http_escape(buf, name, false);
|
||||
}
|
||||
|
||||
auto url = std::string{ (char const*)evbuffer_pullup(buf, -1), evbuffer_get_length(buf) };
|
||||
|
@ -518,12 +518,12 @@ static void task_request_next_chunk(struct tr_webseed_task* t)
|
|||
auto file_offset = uint64_t{};
|
||||
tr_ioFindFileLocation(tor, step_piece, step_piece_offset, &file_index, &file_offset);
|
||||
|
||||
tr_file const* const file = &inf->files[file_index];
|
||||
uint64_t this_pass = std::min(remain, file->length - file_offset);
|
||||
auto const& file = inf->files[file_index];
|
||||
uint64_t this_pass = std::min(remain, file.length - file_offset);
|
||||
|
||||
if (std::empty(urls[file_index]))
|
||||
{
|
||||
urls[file_index] = make_url(t->webseed, file);
|
||||
urls[file_index] = make_url(t->webseed, file.name);
|
||||
}
|
||||
|
||||
char range[64];
|
||||
|
|
|
@ -1570,7 +1570,7 @@ bool trashDataFile(char const* filename, tr_error** error)
|
|||
NSIndexSet* indexSet = node.indexes;
|
||||
for (NSInteger index = indexSet.firstIndex; index != NSNotFound; index = [indexSet indexGreaterThanIndex:index])
|
||||
{
|
||||
have += tr_torrentFileProgress(fHandle, index).bytes_completed;
|
||||
have += tr_torrentFile(fHandle, index).have;
|
||||
}
|
||||
|
||||
return (CGFloat)have / node.size;
|
||||
|
@ -1592,8 +1592,8 @@ bool trashDataFile(char const* filename, tr_error** error)
|
|||
|
||||
__block BOOL canChange = NO;
|
||||
[indexSet enumerateIndexesWithOptions:NSEnumerationConcurrent usingBlock:^(NSUInteger index, BOOL* stop) {
|
||||
auto const progress = tr_torrentFileProgress(fHandle, index);
|
||||
if (progress.bytes_completed < progress.bytes_total)
|
||||
auto const file = tr_torrentFile(fHandle, index);
|
||||
if (file.have < file.length)
|
||||
{
|
||||
canChange = YES;
|
||||
*stop = YES;
|
||||
|
@ -1607,7 +1607,8 @@ bool trashDataFile(char const* filename, tr_error** error)
|
|||
BOOL onState = NO, offState = NO;
|
||||
for (NSUInteger index = indexSet.firstIndex; index != NSNotFound; index = [indexSet indexGreaterThanIndex:index])
|
||||
{
|
||||
if (!fInfo->files[index].dnd || ![self canChangeDownloadCheckForFile:index])
|
||||
auto const file = tr_torrentFile(fHandle, index);
|
||||
if (file.wanted || ![self canChangeDownloadCheckForFile:index])
|
||||
{
|
||||
onState = YES;
|
||||
}
|
||||
|
@ -1657,7 +1658,7 @@ bool trashDataFile(char const* filename, tr_error** error)
|
|||
{
|
||||
for (NSUInteger index = indexSet.firstIndex; index != NSNotFound; index = [indexSet indexGreaterThanIndex:index])
|
||||
{
|
||||
if (priority == fInfo->files[index].priority && [self canChangeDownloadCheckForFile:index])
|
||||
if (priority == tr_torrentFile(fHandle, index).priority && [self canChangeDownloadCheckForFile:index])
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
@ -1677,7 +1678,7 @@ bool trashDataFile(char const* filename, tr_error** error)
|
|||
continue;
|
||||
}
|
||||
|
||||
tr_priority_t const priority = fInfo->files[index].priority;
|
||||
auto const priority = tr_torrentFile(fHandle, index).priority;
|
||||
switch (priority)
|
||||
{
|
||||
case TR_PRI_LOW:
|
||||
|
@ -1943,9 +1944,9 @@ bool trashDataFile(char const* filename, tr_error** error)
|
|||
|
||||
for (NSInteger i = 0; i < count; i++)
|
||||
{
|
||||
tr_file* file = &fInfo->files[i];
|
||||
auto const file = tr_torrentFile(fHandle, i);
|
||||
|
||||
NSString* fullPath = @(file->name);
|
||||
NSString* fullPath = @(file.name);
|
||||
NSArray* pathComponents = fullPath.pathComponents;
|
||||
|
||||
if (!tempNode)
|
||||
|
@ -1956,7 +1957,7 @@ bool trashDataFile(char const* filename, tr_error** error)
|
|||
[self insertPathForComponents:pathComponents
|
||||
withComponentIndex:1
|
||||
forParent:tempNode
|
||||
fileSize:file->length
|
||||
fileSize:file.length
|
||||
index:i
|
||||
flatList:flatFileList];
|
||||
}
|
||||
|
|
|
@ -51,9 +51,9 @@ TEST_P(IncompleteDirTest, incompleteDir)
|
|||
auto* tor = zeroTorrentInit();
|
||||
zeroTorrentPopulate(tor, false);
|
||||
EXPECT_EQ(
|
||||
makeString(tr_strdup_printf("%s/%s.part", incomplete_dir, tor->info.files[0].name)),
|
||||
makeString(tr_strdup_printf("%s/%s.part", incomplete_dir, tr_torrentFile(tor, 0).name)),
|
||||
makeString(tr_torrentFindFile(tor, 0)));
|
||||
EXPECT_EQ(tr_strvPath(incomplete_dir, tor->info.files[1].name), makeString(tr_torrentFindFile(tor, 1)));
|
||||
EXPECT_EQ(tr_strvPath(incomplete_dir, tr_torrentFile(tor, 1).name), makeString(tr_torrentFindFile(tor, 1)));
|
||||
EXPECT_EQ(tor->info.pieceSize, tr_torrentStat(tor)->leftUntilDone);
|
||||
|
||||
// auto constexpr completeness_unset = tr_completeness { -1 };
|
||||
|
@ -125,9 +125,10 @@ TEST_P(IncompleteDirTest, incompleteDir)
|
|||
EXPECT_TRUE(waitFor(test, 300));
|
||||
EXPECT_EQ(TR_SEED, completeness);
|
||||
|
||||
for (tr_file_index_t file_index = 0; file_index < tor->info.fileCount; ++file_index)
|
||||
auto const n = tr_torrentFileCount(tor);
|
||||
for (tr_file_index_t i = 0; i < n; ++i)
|
||||
{
|
||||
EXPECT_EQ(tr_strvPath(download_dir, tor->info.files[file_index].name), makeString(tr_torrentFindFile(tor, file_index)));
|
||||
EXPECT_EQ(tr_strvPath(download_dir, tr_torrentFile(tor, i).name), makeString(tr_torrentFindFile(tor, i)));
|
||||
}
|
||||
|
||||
// cleanup
|
||||
|
@ -178,11 +179,10 @@ TEST_F(MoveTest, setLocation)
|
|||
|
||||
// confirm the files really got moved
|
||||
sync();
|
||||
for (tr_file_index_t file_index = 0; file_index < tor->info.fileCount; ++file_index)
|
||||
auto const n = tr_torrentFileCount(tor);
|
||||
for (tr_file_index_t i = 0; i < n; ++i)
|
||||
{
|
||||
EXPECT_EQ(
|
||||
tr_strvPath(target_dir.data(), tor->info.files[file_index].name),
|
||||
makeString(tr_torrentFindFile(tor, file_index)));
|
||||
EXPECT_EQ(tr_strvPath(target_dir.data(), tr_torrentFile(tor, i).name), makeString(tr_torrentFindFile(tor, i)));
|
||||
}
|
||||
|
||||
// cleanup
|
||||
|
|
|
@ -152,11 +152,12 @@ TEST_F(RenameTest, singleFilenameTorrent)
|
|||
"OmhlbGxvLXdvcmxkLnR4dDEyOnBpZWNlIGxlbmd0aGkzMjc2OGU2OnBpZWNlczIwOukboJcrkFUY"
|
||||
"f6LvqLXBVvSHqCk6Nzpwcml2YXRlaTBlZWU=");
|
||||
EXPECT_TRUE(tr_isTorrent(tor));
|
||||
auto const& files = tor->info.files;
|
||||
|
||||
// sanity check the info
|
||||
EXPECT_EQ(tr_file_index_t{ 1 }, tor->info.fileCount);
|
||||
EXPECT_STREQ("hello-world.txt", tor->info.files[0].name);
|
||||
EXPECT_FALSE(tor->info.files[0].is_renamed);
|
||||
EXPECT_STREQ("hello-world.txt", files[0].name);
|
||||
EXPECT_FALSE(files[0].priv.is_renamed);
|
||||
|
||||
// sanity check the (empty) stats
|
||||
blockingTorrentVerify(tor);
|
||||
|
@ -189,8 +190,8 @@ TEST_F(RenameTest, singleFilenameTorrent)
|
|||
EXPECT_EQ(0, torrentRenameAndWait(tor, "hello-world.txt", "hello-world.txt"));
|
||||
EXPECT_EQ(EINVAL, torrentRenameAndWait(tor, "hello-world.txt", "hello/world.txt"));
|
||||
|
||||
EXPECT_FALSE(tor->info.files[0].is_renamed);
|
||||
EXPECT_STREQ("hello-world.txt", tor->info.files[0].name);
|
||||
EXPECT_FALSE(files[0].priv.is_renamed);
|
||||
EXPECT_STREQ("hello-world.txt", files[0].name);
|
||||
|
||||
/***
|
||||
**** Now try a rename that should succeed
|
||||
|
@ -201,9 +202,9 @@ TEST_F(RenameTest, singleFilenameTorrent)
|
|||
EXPECT_STREQ("hello-world.txt", tr_torrentName(tor));
|
||||
EXPECT_EQ(0, torrentRenameAndWait(tor, tor->info.name, "foobar"));
|
||||
EXPECT_FALSE(tr_sys_path_exists(tmpstr.c_str(), nullptr)); // confirm the old filename can't be found
|
||||
EXPECT_TRUE(tor->info.files[0].is_renamed); // confirm the file's 'renamed' flag is set
|
||||
EXPECT_TRUE(files[0].priv.is_renamed); // confirm the file's 'renamed' flag is set
|
||||
EXPECT_STREQ("foobar", tr_torrentName(tor)); // confirm the torrent's name is now 'foobar'
|
||||
EXPECT_STREQ("foobar", tor->info.files[0].name); // confirm the file's name is now 'foobar' in our struct
|
||||
EXPECT_STREQ("foobar", files[0].name); // confirm the file's name is now 'foobar' in our struct
|
||||
EXPECT_STREQ(nullptr, strstr(tor->info.torrent, "foobar")); // confirm the name in the .torrent file hasn't changed
|
||||
tmpstr = tr_strvPath(tor->currentDir, "foobar");
|
||||
EXPECT_TRUE(tr_sys_path_exists(tmpstr.c_str(), nullptr)); // confirm the file's name is now 'foobar' on the disk
|
||||
|
@ -224,8 +225,8 @@ TEST_F(RenameTest, singleFilenameTorrent)
|
|||
EXPECT_TRUE(tr_sys_path_exists(tmpstr.c_str(), nullptr));
|
||||
EXPECT_EQ(0, torrentRenameAndWait(tor, "foobar", "hello-world.txt"));
|
||||
EXPECT_FALSE(tr_sys_path_exists(tmpstr.c_str(), nullptr));
|
||||
EXPECT_TRUE(tor->info.files[0].is_renamed);
|
||||
EXPECT_STREQ("hello-world.txt", tor->info.files[0].name);
|
||||
EXPECT_TRUE(files[0].priv.is_renamed);
|
||||
EXPECT_STREQ("hello-world.txt", files[0].name);
|
||||
EXPECT_STREQ("hello-world.txt", tr_torrentName(tor));
|
||||
EXPECT_TRUE(testFileExistsAndConsistsOfThisString(tor, 0, "hello, world!\n"));
|
||||
|
||||
|
@ -269,7 +270,7 @@ TEST_F(RenameTest, multifileTorrent)
|
|||
"MjpwaWVjZSBsZW5ndGhpMzI3NjhlNjpwaWVjZXMyMDp27buFkmy8ICfNX4nsJmt0Ckm2Ljc6cHJp"
|
||||
"dmF0ZWkwZWVl");
|
||||
EXPECT_TRUE(tr_isTorrent(tor));
|
||||
auto const* files = tor->info.files;
|
||||
auto* files = tor->info.files;
|
||||
|
||||
// sanity check the info
|
||||
EXPECT_STREQ("Felidae", tor->info.name);
|
||||
|
@ -321,16 +322,16 @@ TEST_F(RenameTest, multifileTorrent)
|
|||
EXPECT_EQ(expected_files[3], files[3].name);
|
||||
EXPECT_TRUE(testFileExistsAndConsistsOfThisString(tor, 1, expected_contents[1]));
|
||||
EXPECT_TRUE(testFileExistsAndConsistsOfThisString(tor, 2, expected_contents[2]));
|
||||
EXPECT_FALSE(files[0].is_renamed);
|
||||
EXPECT_TRUE(files[1].is_renamed);
|
||||
EXPECT_TRUE(files[2].is_renamed);
|
||||
EXPECT_FALSE(files[3].is_renamed);
|
||||
EXPECT_FALSE(files[0].priv.is_renamed);
|
||||
EXPECT_TRUE(files[1].priv.is_renamed);
|
||||
EXPECT_TRUE(files[2].priv.is_renamed);
|
||||
EXPECT_FALSE(files[3].priv.is_renamed);
|
||||
|
||||
// (while the branch is renamed: confirm that the .resume file remembers the changes)
|
||||
tr_torrentSaveResume(tor);
|
||||
// this is a bit dodgy code-wise, but let's make sure the .resume file got the name
|
||||
tr_free(files[1].name);
|
||||
tor->info.files[1].name = tr_strdup("gabba gabba hey");
|
||||
files[1].name = tr_strdup("gabba gabba hey");
|
||||
auto const loaded = tr_torrentLoadResume(tor, ~0ULL, ctor, nullptr);
|
||||
EXPECT_NE(decltype(loaded){ 0 }, (loaded & TR_FR_FILENAMES));
|
||||
EXPECT_EQ(expected_files[0], files[0].name);
|
||||
|
@ -347,10 +348,10 @@ TEST_F(RenameTest, multifileTorrent)
|
|||
EXPECT_TRUE(testFileExistsAndConsistsOfThisString(tor, i, expected_contents[i]));
|
||||
}
|
||||
|
||||
EXPECT_FALSE(files[0].is_renamed);
|
||||
EXPECT_TRUE(files[1].is_renamed);
|
||||
EXPECT_TRUE(files[2].is_renamed);
|
||||
EXPECT_FALSE(files[3].is_renamed);
|
||||
EXPECT_FALSE(files[0].priv.is_renamed);
|
||||
EXPECT_TRUE(files[1].priv.is_renamed);
|
||||
EXPECT_TRUE(files[2].priv.is_renamed);
|
||||
EXPECT_FALSE(files[3].priv.is_renamed);
|
||||
|
||||
/***
|
||||
**** Test it an incomplete torrent...
|
||||
|
@ -448,18 +449,18 @@ TEST_F(RenameTest, multifileTorrent)
|
|||
// rename prefix of top
|
||||
EXPECT_EQ(EINVAL, torrentRenameAndWait(tor, "Feli", "FelidaeX"));
|
||||
EXPECT_STREQ("Felidae", tor->info.name);
|
||||
EXPECT_FALSE(files[0].is_renamed);
|
||||
EXPECT_FALSE(files[1].is_renamed);
|
||||
EXPECT_FALSE(files[2].is_renamed);
|
||||
EXPECT_FALSE(files[3].is_renamed);
|
||||
EXPECT_FALSE(files[0].priv.is_renamed);
|
||||
EXPECT_FALSE(files[1].priv.is_renamed);
|
||||
EXPECT_FALSE(files[2].priv.is_renamed);
|
||||
EXPECT_FALSE(files[3].priv.is_renamed);
|
||||
|
||||
// rename false path
|
||||
EXPECT_EQ(EINVAL, torrentRenameAndWait(tor, "Felidae/FelinaeX", "Genus Felinae"));
|
||||
EXPECT_STREQ("Felidae", tor->info.name);
|
||||
EXPECT_FALSE(files[0].is_renamed);
|
||||
EXPECT_FALSE(files[1].is_renamed);
|
||||
EXPECT_FALSE(files[2].is_renamed);
|
||||
EXPECT_FALSE(files[3].is_renamed);
|
||||
EXPECT_FALSE(files[0].priv.is_renamed);
|
||||
EXPECT_FALSE(files[1].priv.is_renamed);
|
||||
EXPECT_FALSE(files[2].priv.is_renamed);
|
||||
EXPECT_FALSE(files[3].priv.is_renamed);
|
||||
|
||||
/***
|
||||
****
|
||||
|
@ -486,17 +487,18 @@ TEST_F(RenameTest, partialFile)
|
|||
***/
|
||||
|
||||
auto* tor = zeroTorrentInit();
|
||||
auto const& files = tor->info.files;
|
||||
EXPECT_EQ(TotalSize, tor->info.totalSize);
|
||||
EXPECT_EQ(PieceSize, tor->info.pieceSize);
|
||||
EXPECT_EQ(PieceCount, tor->info.pieceCount);
|
||||
EXPECT_STREQ("files-filled-with-zeroes/1048576", tor->info.files[0].name);
|
||||
EXPECT_STREQ("files-filled-with-zeroes/4096", tor->info.files[1].name);
|
||||
EXPECT_STREQ("files-filled-with-zeroes/512", tor->info.files[2].name);
|
||||
EXPECT_STREQ("files-filled-with-zeroes/1048576", files[0].name);
|
||||
EXPECT_STREQ("files-filled-with-zeroes/4096", files[1].name);
|
||||
EXPECT_STREQ("files-filled-with-zeroes/512", files[2].name);
|
||||
|
||||
zeroTorrentPopulate(tor, false);
|
||||
EXPECT_EQ(Length[0], tr_torrentFileProgress(tor, 0).bytes_completed + PieceSize);
|
||||
EXPECT_EQ(Length[1], tr_torrentFileProgress(tor, 1).bytes_completed);
|
||||
EXPECT_EQ(Length[2], tr_torrentFileProgress(tor, 2).bytes_completed);
|
||||
EXPECT_EQ(Length[0], tr_torrentFile(tor, 0).have + PieceSize);
|
||||
EXPECT_EQ(Length[1], tr_torrentFile(tor, 1).have);
|
||||
EXPECT_EQ(Length[2], tr_torrentFile(tor, 2).have);
|
||||
auto const* st = tr_torrentStat(tor);
|
||||
EXPECT_EQ(TotalSize, st->sizeWhenDone);
|
||||
EXPECT_EQ(PieceSize, st->leftUntilDone);
|
||||
|
@ -514,7 +516,7 @@ TEST_F(RenameTest, partialFile)
|
|||
|
||||
for (tr_file_index_t i = 0; i < 3; ++i)
|
||||
{
|
||||
EXPECT_STREQ(strings[i], tor->info.files[i].name);
|
||||
EXPECT_STREQ(strings[i], files[i].name);
|
||||
}
|
||||
|
||||
strings[0] = "foo/bar.part";
|
||||
|
|
Loading…
Reference in New Issue