mirror of
https://github.com/transmission/transmission.git
synced 2025-12-25 04:45:56 +00:00
refactor: avoid referencing tr_file struct directly (#2373)
This commit is contained in:
@@ -45,19 +45,19 @@ static int readOrWriteBytes(
|
||||
tr_session* session,
|
||||
tr_torrent* tor,
|
||||
int ioMode,
|
||||
tr_file_index_t fileIndex,
|
||||
uint64_t fileOffset,
|
||||
tr_file_index_t file_index,
|
||||
uint64_t file_offset,
|
||||
void* buf,
|
||||
size_t buflen)
|
||||
{
|
||||
int err = 0;
|
||||
bool const doWrite = ioMode >= TR_IO_WRITE;
|
||||
|
||||
auto const& file = tor->file(fileIndex);
|
||||
TR_ASSERT(file.length == 0 || fileOffset < file.length);
|
||||
TR_ASSERT(fileOffset + buflen <= file.length);
|
||||
auto const file_size = tor->fileSize(file_index);
|
||||
TR_ASSERT(file_size == 0 || file_offset < file_size);
|
||||
TR_ASSERT(file_offset + buflen <= file_size);
|
||||
|
||||
if (file.length == 0)
|
||||
if (file_size == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -66,14 +66,14 @@ static int readOrWriteBytes(
|
||||
**** Find the fd
|
||||
***/
|
||||
|
||||
tr_sys_file_t fd = tr_fdFileGetCached(session, tr_torrentId(tor), fileIndex, doWrite);
|
||||
auto fd = tr_fdFileGetCached(session, tr_torrentId(tor), file_index, doWrite);
|
||||
|
||||
if (fd == TR_BAD_SYS_FILE) /* it's not cached, so open/create it now */
|
||||
{
|
||||
/* see if the file exists... */
|
||||
char const* base = nullptr;
|
||||
char* subpath = nullptr;
|
||||
if (!tr_torrentFindFile2(tor, fileIndex, &base, &subpath, nullptr))
|
||||
if (!tr_torrentFindFile2(tor, file_index, &base, &subpath, nullptr))
|
||||
{
|
||||
/* we can't read a file that doesn't exist... */
|
||||
if (!doWrite)
|
||||
@@ -83,19 +83,18 @@ 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);
|
||||
subpath = tr_sessionIsIncompleteFileNamingEnabled(tor->session) ? tr_torrentBuildPartial(tor, file_index) :
|
||||
tr_strvDup(tor->fileSubpath(file_index));
|
||||
}
|
||||
|
||||
if (err == 0)
|
||||
{
|
||||
/* open (and maybe create) the file */
|
||||
auto const filename = tr_strvPath(base, subpath);
|
||||
tr_preallocation_mode const prealloc = (!doWrite || !tor->fileIsWanted(fileIndex)) ?
|
||||
TR_PREALLOCATE_NONE :
|
||||
tor->session->preallocationMode;
|
||||
auto const prealloc = (!doWrite || !tor->fileIsWanted(file_index)) ? 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, file_index, filename.c_str(), doWrite, prealloc, file_size);
|
||||
if (fd == TR_BAD_SYS_FILE)
|
||||
{
|
||||
err = errno;
|
||||
@@ -121,25 +120,25 @@ static int readOrWriteBytes(
|
||||
|
||||
if (ioMode == TR_IO_READ)
|
||||
{
|
||||
if (!tr_sys_file_read_at(fd, buf, buflen, fileOffset, nullptr, &error))
|
||||
if (!tr_sys_file_read_at(fd, buf, buflen, file_offset, 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", tor->fileSubpath(file_index), error->message);
|
||||
tr_error_free(error);
|
||||
}
|
||||
}
|
||||
else if (ioMode == TR_IO_WRITE)
|
||||
{
|
||||
if (!tr_sys_file_write_at(fd, buf, buflen, fileOffset, nullptr, &error))
|
||||
if (!tr_sys_file_write_at(fd, buf, buflen, file_offset, 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", tor->fileSubpath(file_index), error->message);
|
||||
tr_error_free(error);
|
||||
}
|
||||
}
|
||||
else if (ioMode == TR_IO_PREFETCH)
|
||||
{
|
||||
tr_sys_file_advise(fd, fileOffset, buflen, TR_SYS_FILE_ADVICE_WILL_NEED, nullptr);
|
||||
tr_sys_file_advise(fd, file_offset, buflen, TR_SYS_FILE_ADVICE_WILL_NEED, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -166,22 +165,21 @@ static int readOrWritePiece(
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
auto [fileIndex, fileOffset] = tor->fileOffset(pieceIndex, pieceOffset);
|
||||
auto [file_index, file_offset] = tor->fileOffset(pieceIndex, pieceOffset);
|
||||
|
||||
while (buflen != 0 && err == 0)
|
||||
{
|
||||
auto const& file = tor->file(fileIndex);
|
||||
uint64_t const bytesThisPass = std::min(uint64_t{ buflen }, uint64_t{ file.length - fileOffset });
|
||||
uint64_t const bytes_this_pass = std::min(uint64_t{ buflen }, uint64_t{ tor->fileSize(file_index) - file_offset });
|
||||
|
||||
err = readOrWriteBytes(tor->session, tor, ioMode, fileIndex, fileOffset, buf, bytesThisPass);
|
||||
buf += bytesThisPass;
|
||||
buflen -= bytesThisPass;
|
||||
fileIndex++;
|
||||
fileOffset = 0;
|
||||
err = readOrWriteBytes(tor->session, tor, ioMode, file_index, file_offset, buf, bytes_this_pass);
|
||||
buf += bytes_this_pass;
|
||||
buflen -= bytes_this_pass;
|
||||
++file_index;
|
||||
file_offset = 0;
|
||||
|
||||
if (err != 0 && ioMode == TR_IO_WRITE && tor->error != TR_STAT_LOCAL_ERROR)
|
||||
{
|
||||
auto const path = tr_strvPath(tor->downloadDir().sv(), file.name);
|
||||
auto const path = tr_strvPath(tor->downloadDir().sv(), tor->fileSubpath(file_index));
|
||||
tor->setLocalError(tr_strvJoin(tr_strerror(err), " ("sv, path, ")"sv));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -403,7 +403,7 @@ static void saveFilenames(tr_variant* dict, tr_torrent const* tor)
|
||||
tr_variant* const list = tr_variantDictAddList(dict, TR_KEY_files, n);
|
||||
for (tr_file_index_t i = 0; i < n; ++i)
|
||||
{
|
||||
tr_variantListAddStrView(list, tor->file(i).name);
|
||||
tr_variantListAddStrView(list, tor->fileSubpath(i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,11 +420,9 @@ static uint64_t loadFilenames(tr_variant* dict, tr_torrent* tor)
|
||||
for (size_t i = 0; i < n_files && i < n_list; ++i)
|
||||
{
|
||||
auto sv = std::string_view{};
|
||||
auto& file = tor->file(i);
|
||||
if (tr_variantGetStrView(tr_variantListChild(list, i), &sv) && !std::empty(sv) && sv != file.name)
|
||||
if (tr_variantGetStrView(tr_variantListChild(list, i), &sv) && !std::empty(sv))
|
||||
{
|
||||
tr_free(file.name);
|
||||
file.name = tr_strvDup(sv);
|
||||
tor->setFileSubpath(i, sv);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1109,19 +1109,18 @@ tr_file_view tr_torrentFile(tr_torrent const* tor, tr_file_index_t i)
|
||||
{
|
||||
TR_ASSERT(tr_isTorrent(tor));
|
||||
|
||||
auto const& file = tor->file(i);
|
||||
auto const* const name = file.name;
|
||||
auto const* subpath = tor->fileSubpath(i);
|
||||
auto const priority = tor->file_priorities_.filePriority(i);
|
||||
auto const wanted = tor->files_wanted_.fileWanted(i);
|
||||
auto const length = file.length;
|
||||
auto const length = tor->fileSize(i);
|
||||
|
||||
if (tor->completeness == TR_SEED || length == 0)
|
||||
{
|
||||
return { name, length, length, 1.0, priority, wanted };
|
||||
return { subpath, length, length, 1.0, priority, wanted };
|
||||
}
|
||||
|
||||
auto const have = tor->completion.countHasBytesInSpan(tor->fpm_.byteSpan(i));
|
||||
return { name, have, length, have >= length ? 1.0 : have / double(length), priority, wanted };
|
||||
return { subpath, have, length, have >= length ? 1.0 : have / double(length), priority, wanted };
|
||||
}
|
||||
|
||||
size_t tr_torrentFileCount(tr_torrent const* torrent)
|
||||
@@ -2186,7 +2185,7 @@ static void deleteLocalData(tr_torrent* tor, tr_fileFunc func)
|
||||
for (tr_file_index_t f = 0, n = tor->fileCount(); f < n; ++f)
|
||||
{
|
||||
/* try to find the file, looking in the partial and download dirs */
|
||||
auto filename = tr_strvPath(top, tor->file(f).name);
|
||||
auto filename = tr_strvPath(top, tor->fileSubpath(f));
|
||||
|
||||
if (!tr_sys_path_exists(filename.c_str(), nullptr))
|
||||
{
|
||||
@@ -2201,7 +2200,7 @@ static void deleteLocalData(tr_torrent* tor, tr_fileFunc func)
|
||||
/* if we found the file, move it */
|
||||
if (!std::empty(filename))
|
||||
{
|
||||
auto target = tr_strvPath(tmpdir, tor->file(f).name);
|
||||
auto target = tr_strvPath(tmpdir, tor->fileSubpath(f));
|
||||
tr_moveFile(filename.c_str(), target.c_str(), nullptr);
|
||||
files.emplace_back(target);
|
||||
}
|
||||
@@ -2258,7 +2257,7 @@ static void deleteLocalData(tr_torrent* tor, tr_fileFunc func)
|
||||
for (tr_file_index_t f = 0, n = tor->fileCount(); f < n; ++f)
|
||||
{
|
||||
/* get the directory that this file goes in... */
|
||||
auto const filename = tr_strvPath(top, tor->file(f).name);
|
||||
auto const filename = tr_strvPath(top, tor->fileSubpath(f));
|
||||
char* dir = tr_sys_path_dirname(filename.c_str(), nullptr);
|
||||
if (dir == nullptr)
|
||||
{
|
||||
@@ -2358,7 +2357,7 @@ static void setLocationImpl(void* vdata)
|
||||
* if the target directory runs out of space halfway through... */
|
||||
for (tr_file_index_t i = 0, n = tor->fileCount(); !err && i < n; ++i)
|
||||
{
|
||||
auto const file_length = tor->file(i).length;
|
||||
auto const file_size = tor->fileSize(i);
|
||||
|
||||
char const* oldbase = nullptr;
|
||||
char* sub = nullptr;
|
||||
@@ -2393,7 +2392,7 @@ static void setLocationImpl(void* vdata)
|
||||
|
||||
if (data->setme_progress != nullptr)
|
||||
{
|
||||
bytesHandled += file_length;
|
||||
bytesHandled += file_size;
|
||||
*data->setme_progress = bytesHandled / tor->totalSize();
|
||||
}
|
||||
}
|
||||
@@ -2473,9 +2472,8 @@ std::string_view tr_torrent::primaryMimeType() const
|
||||
auto size_per_mime_type = std::unordered_map<std::string_view, size_t>{};
|
||||
for (tr_file_index_t i = 0, n = this->fileCount(); i < n; ++i)
|
||||
{
|
||||
auto const& file = this->file(i);
|
||||
auto const mime_type = tr_get_mime_type_for_filename(file.name);
|
||||
size_per_mime_type[mime_type] += file.length;
|
||||
auto const mime_type = tr_get_mime_type_for_filename(this->fileSubpath(i));
|
||||
size_per_mime_type[mime_type] += this->fileSize(i);
|
||||
}
|
||||
|
||||
if (std::empty(size_per_mime_type))
|
||||
@@ -2515,10 +2513,10 @@ static void tr_torrentFileCompleted(tr_torrent* tor, tr_file_index_t i)
|
||||
char* sub = nullptr;
|
||||
if (tr_torrentFindFile2(tor, i, &base, &sub, nullptr))
|
||||
{
|
||||
if (tr_file& file = tor->file(i); strcmp(sub, file.name) != 0)
|
||||
if (char const* file_subpath = tor->fileSubpath(i); strcmp(sub, file_subpath) != 0)
|
||||
{
|
||||
auto const oldpath = tr_strvPath(base, sub);
|
||||
auto const newpath = tr_strvPath(base, file.name);
|
||||
auto const newpath = tr_strvPath(base, file_subpath);
|
||||
tr_error* error = nullptr;
|
||||
|
||||
if (!tr_sys_path_rename(oldpath.c_str(), newpath.c_str(), &error))
|
||||
@@ -2591,20 +2589,20 @@ void tr_torrentGotBlock(tr_torrent* tor, tr_block_index_t block)
|
||||
|
||||
std::optional<tr_torrent::tr_found_file_t> tr_torrent::findFile(std::string& filename, tr_file_index_t i) const
|
||||
{
|
||||
tr_file const& file = this->file(i);
|
||||
auto const subpath = std::string_view{ this->fileSubpath(i) };
|
||||
auto file_info = tr_sys_path_info{};
|
||||
|
||||
if (!std::empty(this->downloadDir()))
|
||||
{
|
||||
auto const base = this->downloadDir().sv();
|
||||
|
||||
tr_buildBuf(filename, base, "/"sv, file.name);
|
||||
tr_buildBuf(filename, base, "/"sv, subpath);
|
||||
if (tr_sys_path_get_info(filename.c_str(), 0, &file_info, nullptr))
|
||||
{
|
||||
return tr_found_file_t{ file_info, filename, base };
|
||||
}
|
||||
|
||||
tr_buildBuf(filename, base, "/"sv, file.name, ".part"sv);
|
||||
tr_buildBuf(filename, base, "/"sv, subpath, ".part"sv);
|
||||
if (tr_sys_path_get_info(filename.c_str(), 0, &file_info, nullptr))
|
||||
{
|
||||
return tr_found_file_t{ file_info, filename, base };
|
||||
@@ -2615,13 +2613,13 @@ std::optional<tr_torrent::tr_found_file_t> tr_torrent::findFile(std::string& fil
|
||||
{
|
||||
auto const base = this->incompleteDir().sv();
|
||||
|
||||
tr_buildBuf(filename, base, "/"sv, file.name);
|
||||
tr_buildBuf(filename, base, "/"sv, subpath);
|
||||
if (tr_sys_path_get_info(filename.c_str(), 0, &file_info, nullptr))
|
||||
{
|
||||
return tr_found_file_t{ file_info, filename, base };
|
||||
}
|
||||
|
||||
tr_buildBuf(filename, base, "/"sv, file.name, ".part"sv);
|
||||
tr_buildBuf(filename, base, "/"sv, subpath, ".part"sv);
|
||||
if (tr_sys_path_get_info(filename.c_str(), 0, &file_info, nullptr))
|
||||
{
|
||||
return tr_found_file_t{ file_info, filename, base };
|
||||
@@ -2696,7 +2694,7 @@ static void refreshCurrentDir(tr_torrent* tor)
|
||||
|
||||
char* tr_torrentBuildPartial(tr_torrent const* tor, tr_file_index_t i)
|
||||
{
|
||||
return tr_strvDup(tr_strvJoin(tor->file(i).name, ".part"sv));
|
||||
return tr_strvDup(tr_strvJoin(tor->fileSubpath(i), ".part"sv));
|
||||
}
|
||||
|
||||
/***
|
||||
@@ -2870,7 +2868,7 @@ static tr_file_index_t* renameFindAffectedFiles(tr_torrent* tor, char const* old
|
||||
|
||||
for (tr_file_index_t i = 0; i < n_files; ++i)
|
||||
{
|
||||
char const* name = tor->file(i).name;
|
||||
char const* name = tor->fileSubpath(i);
|
||||
size_t const len = strlen(name);
|
||||
|
||||
if ((len == oldpath_len || (len > oldpath_len && name[oldpath_len] == '/')) && memcmp(oldpath, name, oldpath_len) == 0)
|
||||
@@ -2927,21 +2925,21 @@ static int renamePath(tr_torrent* tor, char const* oldpath, char const* newname)
|
||||
return err;
|
||||
}
|
||||
|
||||
static void renameTorrentFileString(tr_torrent* tor, char const* oldpath, char const* newname, tr_file_index_t fileIndex)
|
||||
static void renameTorrentFileString(tr_torrent* tor, char const* oldpath, char const* newname, tr_file_index_t file_index)
|
||||
{
|
||||
char* name = nullptr;
|
||||
tr_file& file = tor->file(fileIndex);
|
||||
size_t const oldpath_len = strlen(oldpath);
|
||||
auto name = std::string{};
|
||||
auto const subpath = std::string_view{ tor->fileSubpath(file_index) };
|
||||
auto const oldpath_len = strlen(oldpath);
|
||||
|
||||
if (strchr(oldpath, TR_PATH_DELIMITER) == nullptr)
|
||||
{
|
||||
if (oldpath_len >= strlen(file.name))
|
||||
if (oldpath_len >= std::size(subpath))
|
||||
{
|
||||
name = tr_buildPath(newname, nullptr);
|
||||
name = tr_strvPath(newname);
|
||||
}
|
||||
else
|
||||
{
|
||||
name = tr_buildPath(newname, file.name + oldpath_len + 1, nullptr);
|
||||
name = tr_strvPath(newname, subpath.substr(oldpath_len + 1));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -2953,26 +2951,21 @@ static void renameTorrentFileString(tr_torrent* tor, char const* oldpath, char c
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldpath_len >= strlen(file.name))
|
||||
if (oldpath_len >= std::size(subpath))
|
||||
{
|
||||
name = tr_buildPath(tmp, newname, nullptr);
|
||||
name = tr_strvPath(tmp, newname);
|
||||
}
|
||||
else
|
||||
{
|
||||
name = tr_buildPath(tmp, newname, file.name + oldpath_len + 1, nullptr);
|
||||
name = tr_strvPath(tmp, newname, subpath.substr(oldpath_len + 1));
|
||||
}
|
||||
|
||||
tr_free(tmp);
|
||||
}
|
||||
|
||||
if (strcmp(file.name, name) == 0)
|
||||
if (subpath != name)
|
||||
{
|
||||
tr_free(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_free(file.name);
|
||||
file.name = name;
|
||||
tor->setFileSubpath(file_index, name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3138,3 +3131,13 @@ void tr_torrent::setName(std::string_view name)
|
||||
tr_free(this->info.name);
|
||||
this->info.name = tr_strvDup(name);
|
||||
}
|
||||
|
||||
void tr_torrent::setFileSubpath(tr_file_index_t i, std::string_view subpath)
|
||||
{
|
||||
if (fileSubpath(i) != subpath)
|
||||
{
|
||||
auto* old = this->info.files[i].name;
|
||||
this->info.files[i].name = tr_strvDup(subpath);
|
||||
tr_free(old);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,20 +317,22 @@ public:
|
||||
return info.fileCount;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto& file(tr_file_index_t i)
|
||||
[[nodiscard]] char const* fileSubpath(tr_file_index_t i) const
|
||||
{
|
||||
TR_ASSERT(i < this->fileCount());
|
||||
|
||||
return info.files[i];
|
||||
return info.files[i].name ? info.files[i].name : "";
|
||||
}
|
||||
|
||||
[[nodiscard]] auto const& file(tr_file_index_t i) const
|
||||
[[nodiscard]] auto fileSize(tr_file_index_t i) const
|
||||
{
|
||||
TR_ASSERT(i < this->fileCount());
|
||||
|
||||
return info.files[i];
|
||||
return info.files[i].length;
|
||||
}
|
||||
|
||||
void setFileSubpath(tr_file_index_t i, std::string_view subpath);
|
||||
|
||||
struct tr_found_file_t : public tr_sys_path_info
|
||||
{
|
||||
std::string& filename; // /home/foo/Downloads/torrent/01-file-one.txt
|
||||
|
||||
@@ -54,7 +54,6 @@ struct tr_byte_span_t
|
||||
|
||||
struct tr_ctor;
|
||||
struct tr_error;
|
||||
struct tr_file;
|
||||
struct tr_info;
|
||||
struct tr_session;
|
||||
struct tr_torrent;
|
||||
|
||||
@@ -50,7 +50,7 @@ static bool verifyTorrent(tr_torrent* tor, bool* stopFlag)
|
||||
|
||||
while (!*stopFlag && piece < tor->pieceCount())
|
||||
{
|
||||
auto const file_length = tor->file(fileIndex).length;
|
||||
auto const file_length = tor->fileSize(fileIndex);
|
||||
|
||||
/* if we're starting a new piece... */
|
||||
if (piecePos == 0)
|
||||
|
||||
@@ -491,14 +491,14 @@ static void web_response_func(
|
||||
}
|
||||
}
|
||||
|
||||
static std::string make_url(tr_webseed* w, char const* name)
|
||||
static std::string make_url(tr_webseed* w, std::string_view 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) == '/' && name != nullptr)
|
||||
if (*std::rbegin(w->base_url) == '/' && !std::empty(name))
|
||||
{
|
||||
tr_http_escape(buf, name, false);
|
||||
}
|
||||
@@ -525,12 +525,11 @@ static void task_request_next_chunk(struct tr_webseed_task* t)
|
||||
uint64_t const step_piece_offset = total_offset - uint64_t(piece_size) * step_piece;
|
||||
|
||||
auto const [file_index, file_offset] = tor->fileOffset(step_piece, step_piece_offset);
|
||||
auto const& file = tor->file(file_index);
|
||||
uint64_t this_pass = std::min(remain, file.length - file_offset);
|
||||
uint64_t this_pass = std::min(remain, tor->fileSize(file_index) - file_offset);
|
||||
|
||||
if (std::empty(urls[file_index]))
|
||||
{
|
||||
urls[file_index] = make_url(t->webseed, file.name);
|
||||
urls[file_index] = make_url(t->webseed, tor->fileSubpath(file_index));
|
||||
}
|
||||
|
||||
char range[64];
|
||||
|
||||
Reference in New Issue
Block a user