mirror of
https://github.com/transmission/transmission.git
synced 2026-05-08 09:39:08 +01:00
refactor: tr_sys_path_get_info() now returns a tr_sys_path_info (#3566)
* refactor: tr_sys_path_get_info() now returns a tr_sys_path_info * refactor: tr_sys_file_get_info() now returns a tr_sys_path_info
This commit is contained in:
@@ -42,14 +42,14 @@ void BlocklistFile::load()
|
||||
{
|
||||
close();
|
||||
|
||||
auto info = tr_sys_path_info{};
|
||||
if (!tr_sys_path_get_info(getFilename(), 0, &info))
|
||||
auto const info = tr_sys_path_get_info(getFilename());
|
||||
if (!info)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto const byteCount = info.size;
|
||||
if (byteCount == 0)
|
||||
auto const byte_count = info->size;
|
||||
if (byte_count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -67,7 +67,7 @@ void BlocklistFile::load()
|
||||
return;
|
||||
}
|
||||
|
||||
rules_ = static_cast<struct IPv4Range*>(tr_sys_file_map_for_reading(fd, 0, byteCount, &error));
|
||||
rules_ = static_cast<struct IPv4Range*>(tr_sys_file_map_for_reading(fd, 0, byte_count, &error));
|
||||
if (rules_ == nullptr)
|
||||
{
|
||||
tr_logAddWarn(fmt::format(
|
||||
@@ -81,8 +81,8 @@ void BlocklistFile::load()
|
||||
}
|
||||
|
||||
fd_ = fd;
|
||||
byte_count_ = byteCount;
|
||||
rule_count_ = byteCount / sizeof(IPv4Range);
|
||||
byte_count_ = byte_count;
|
||||
rule_count_ = byte_count / sizeof(IPv4Range);
|
||||
|
||||
tr_logAddInfo(fmt::format(
|
||||
ngettext("Blocklist '{path}' has {count} entry", "Blocklist '{path}' has {count} entries", rule_count_),
|
||||
|
||||
@@ -123,7 +123,7 @@ public:
|
||||
unsigned int hash_length = 0;
|
||||
auto digest = DigestType{};
|
||||
auto* const digest_as_uchar = reinterpret_cast<unsigned char*>(std::data(digest));
|
||||
bool const ok = check_result(EVP_DigestFinal_ex(handle_.get(), digest_as_uchar, &hash_length));
|
||||
[[maybe_unused]] bool const ok = check_result(EVP_DigestFinal_ex(handle_.get(), digest_as_uchar, &hash_length));
|
||||
TR_ASSERT(!ok || hash_length == std::size(digest));
|
||||
|
||||
clear();
|
||||
|
||||
@@ -117,23 +117,27 @@ static void set_system_error_if_file_found(tr_error** error, int code)
|
||||
}
|
||||
}
|
||||
|
||||
static void stat_to_sys_path_info(struct stat const* sb, tr_sys_path_info* info)
|
||||
static constexpr auto stat_to_sys_path_info(struct stat const& sb)
|
||||
{
|
||||
if (S_ISREG(sb->st_mode))
|
||||
auto info = tr_sys_path_info{};
|
||||
|
||||
if (S_ISREG(sb.st_mode))
|
||||
{
|
||||
info->type = TR_SYS_PATH_IS_FILE;
|
||||
info.type = TR_SYS_PATH_IS_FILE;
|
||||
}
|
||||
else if (S_ISDIR(sb->st_mode))
|
||||
else if (S_ISDIR(sb.st_mode))
|
||||
{
|
||||
info->type = TR_SYS_PATH_IS_DIRECTORY;
|
||||
info.type = TR_SYS_PATH_IS_DIRECTORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
info->type = TR_SYS_PATH_IS_OTHER;
|
||||
info.type = TR_SYS_PATH_IS_OTHER;
|
||||
}
|
||||
|
||||
info->size = (uint64_t)sb->st_size;
|
||||
info->last_modified_at = sb->st_mtime;
|
||||
info.size = static_cast<uint64_t>(sb.st_size);
|
||||
info.last_modified_at = sb.st_mtime;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static void set_file_for_single_pass(tr_sys_file_t handle)
|
||||
@@ -299,33 +303,29 @@ bool tr_sys_path_exists(char const* path, tr_error** error)
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool tr_sys_path_get_info(char const* path, int flags, tr_sys_path_info* info, tr_error** error)
|
||||
std::optional<tr_sys_path_info> tr_sys_path_get_info(std::string_view path, int flags, tr_error** error)
|
||||
{
|
||||
TR_ASSERT(path != nullptr);
|
||||
TR_ASSERT(info != nullptr);
|
||||
struct stat sb = {};
|
||||
|
||||
bool ret = false;
|
||||
struct stat sb;
|
||||
bool ok = false;
|
||||
auto const szpath = tr_pathbuf{ path };
|
||||
|
||||
if ((flags & TR_SYS_PATH_NO_FOLLOW) == 0)
|
||||
{
|
||||
ret = stat(path, &sb) != -1;
|
||||
ok = stat(szpath, &sb) != -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = lstat(path, &sb) != -1;
|
||||
ok = lstat(szpath, &sb) != -1;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
if (ok)
|
||||
{
|
||||
stat_to_sys_path_info(&sb, info);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_system_error(error, errno);
|
||||
return stat_to_sys_path_info(sb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
set_system_error(error, errno);
|
||||
return {};
|
||||
}
|
||||
|
||||
bool tr_sys_path_is_relative(std::string_view path)
|
||||
@@ -486,8 +486,8 @@ bool tr_sys_path_copy(char const* src_path, char const* dst_path, tr_error** err
|
||||
return false;
|
||||
}
|
||||
|
||||
tr_sys_path_info info;
|
||||
if (!tr_sys_file_get_info(in, &info, error))
|
||||
auto const info = tr_sys_file_get_info(in, error);
|
||||
if (!info)
|
||||
{
|
||||
tr_error_prefix(error, "Unable to get information on source file: ");
|
||||
tr_sys_file_close(in);
|
||||
@@ -506,11 +506,11 @@ bool tr_sys_path_copy(char const* src_path, char const* dst_path, tr_error** err
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t file_size = info.size;
|
||||
uint64_t file_size = info->size;
|
||||
|
||||
#if defined(USE_COPY_FILE_RANGE) || defined(USE_SENDFILE64)
|
||||
|
||||
while (file_size > 0)
|
||||
while (file_size > 0U)
|
||||
{
|
||||
size_t const chunk_size = std::min(file_size, uint64_t{ SSIZE_MAX });
|
||||
ssize_t const copied =
|
||||
@@ -538,12 +538,12 @@ bool tr_sys_path_copy(char const* src_path, char const* dst_path, tr_error** err
|
||||
|
||||
/* Fallback to user-space copy. */
|
||||
|
||||
size_t const buflen = 1024 * 1024; /* 1024 KiB buffer */
|
||||
auto* buf = static_cast<char*>(tr_malloc(buflen));
|
||||
static auto constexpr Buflen = size_t{ 1024U * 1024U }; /* 1024 KiB buffer */
|
||||
auto* buf = static_cast<char*>(tr_malloc(Buflen));
|
||||
|
||||
while (file_size > 0)
|
||||
while (file_size > 0U)
|
||||
{
|
||||
uint64_t const chunk_size = std::min(file_size, uint64_t{ buflen });
|
||||
uint64_t const chunk_size = std::min(file_size, uint64_t{ Buflen });
|
||||
uint64_t bytes_read;
|
||||
uint64_t bytes_written;
|
||||
|
||||
@@ -707,24 +707,19 @@ bool tr_sys_file_close(tr_sys_file_t handle, tr_error** error)
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool tr_sys_file_get_info(tr_sys_file_t handle, tr_sys_path_info* info, tr_error** error)
|
||||
std::optional<tr_sys_path_info> tr_sys_file_get_info(tr_sys_file_t handle, tr_error** error)
|
||||
{
|
||||
TR_ASSERT(handle != TR_BAD_SYS_FILE);
|
||||
TR_ASSERT(info != nullptr);
|
||||
|
||||
struct stat sb;
|
||||
bool const ret = fstat(handle, &sb) != -1;
|
||||
|
||||
if (ret)
|
||||
if (fstat(handle, &sb) != -1)
|
||||
{
|
||||
stat_to_sys_path_info(&sb, info);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_system_error(error, errno);
|
||||
return stat_to_sys_path_info(sb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
set_system_error(error, errno);
|
||||
return {};
|
||||
}
|
||||
|
||||
bool tr_sys_file_seek(tr_sys_file_t handle, int64_t offset, tr_seek_origin_t origin, uint64_t* new_offset, tr_error** error)
|
||||
|
||||
@@ -72,48 +72,42 @@ static void set_system_error_if_file_found(tr_error** error, DWORD code)
|
||||
}
|
||||
}
|
||||
|
||||
static time_t filetime_to_unix_time(FILETIME const* t)
|
||||
static constexpr time_t filetime_to_unix_time(FILETIME const& t)
|
||||
{
|
||||
TR_ASSERT(t != nullptr);
|
||||
|
||||
uint64_t tmp = 0;
|
||||
tmp |= t->dwHighDateTime;
|
||||
tmp |= t.dwHighDateTime;
|
||||
tmp <<= 32;
|
||||
tmp |= t->dwLowDateTime;
|
||||
tmp |= t.dwLowDateTime;
|
||||
tmp /= 10; /* to microseconds */
|
||||
tmp -= DELTA_EPOCH_IN_MICROSECS;
|
||||
|
||||
return tmp / 1000000UL;
|
||||
}
|
||||
|
||||
static void stat_to_sys_path_info(
|
||||
DWORD attributes,
|
||||
DWORD size_low,
|
||||
DWORD size_high,
|
||||
FILETIME const* mtime,
|
||||
tr_sys_path_info* info)
|
||||
static constexpr auto stat_to_sys_path_info(DWORD attributes, DWORD size_low, DWORD size_high, FILETIME const& mtime)
|
||||
{
|
||||
TR_ASSERT(mtime != nullptr);
|
||||
TR_ASSERT(info != nullptr);
|
||||
auto info = tr_sys_path_info{};
|
||||
|
||||
if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
|
||||
{
|
||||
info->type = TR_SYS_PATH_IS_DIRECTORY;
|
||||
info.type = TR_SYS_PATH_IS_DIRECTORY;
|
||||
}
|
||||
else if ((attributes & (FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_VIRTUAL)) == 0)
|
||||
{
|
||||
info->type = TR_SYS_PATH_IS_FILE;
|
||||
info.type = TR_SYS_PATH_IS_FILE;
|
||||
}
|
||||
else
|
||||
{
|
||||
info->type = TR_SYS_PATH_IS_OTHER;
|
||||
info.type = TR_SYS_PATH_IS_OTHER;
|
||||
}
|
||||
|
||||
info->size = size_high;
|
||||
info->size <<= 32;
|
||||
info->size |= size_low;
|
||||
info.size = size_high;
|
||||
info.size <<= 32;
|
||||
info.size |= size_low;
|
||||
|
||||
info->last_modified_at = filetime_to_unix_time(mtime);
|
||||
info.last_modified_at = filetime_to_unix_time(mtime);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static constexpr bool is_slash(char c)
|
||||
@@ -235,6 +229,18 @@ static wchar_t* path_to_native_path(char const* path)
|
||||
return path_to_native_path_ex(path, 0, nullptr);
|
||||
}
|
||||
|
||||
static std::wstring path_to_native_path_wstr(std::string_view path)
|
||||
{
|
||||
if (auto* const rawptr = path_to_native_path(tr_pathbuf{ path }); rawptr != nullptr)
|
||||
{
|
||||
auto ret = std::wstring{ rawptr };
|
||||
tr_free(rawptr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
static char* native_path_to_path(wchar_t const* wide_path)
|
||||
{
|
||||
if (wide_path == nullptr)
|
||||
@@ -423,67 +429,35 @@ bool tr_sys_path_exists(char const* path, tr_error** error)
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool tr_sys_path_get_info(char const* path, int flags, tr_sys_path_info* info, tr_error** error)
|
||||
std::optional<tr_sys_path_info> tr_sys_path_get_info(std::string_view path, int flags, tr_error** error)
|
||||
{
|
||||
TR_ASSERT(path != nullptr);
|
||||
TR_ASSERT(info != nullptr);
|
||||
|
||||
bool ret = false;
|
||||
wchar_t* wide_path = path_to_native_path(path);
|
||||
|
||||
if ((flags & TR_SYS_PATH_NO_FOLLOW) == 0)
|
||||
if (auto const wide_path = path_to_native_path_wstr(path); std::empty(wide_path))
|
||||
{
|
||||
HANDLE handle = INVALID_HANDLE_VALUE;
|
||||
|
||||
if (wide_path != nullptr)
|
||||
{
|
||||
handle = CreateFileW(wide_path, 0, 0, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
||||
}
|
||||
|
||||
if (handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
tr_error* my_error = nullptr;
|
||||
ret = tr_sys_file_get_info(handle, info, &my_error);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
tr_error_propagate(error, &my_error);
|
||||
}
|
||||
|
||||
CloseHandle(handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_system_error(error, GetLastError());
|
||||
}
|
||||
// do nothing
|
||||
}
|
||||
else
|
||||
else if ((flags & TR_SYS_PATH_NO_FOLLOW) != 0)
|
||||
{
|
||||
WIN32_FILE_ATTRIBUTE_DATA attributes;
|
||||
|
||||
if (wide_path != nullptr)
|
||||
auto attributes = WIN32_FILE_ATTRIBUTE_DATA{};
|
||||
if (GetFileAttributesExW(wide_path.c_str(), GetFileExInfoStandard, &attributes))
|
||||
{
|
||||
ret = GetFileAttributesExW(wide_path, GetFileExInfoStandard, &attributes);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
{
|
||||
stat_to_sys_path_info(
|
||||
return stat_to_sys_path_info(
|
||||
attributes.dwFileAttributes,
|
||||
attributes.nFileSizeLow,
|
||||
attributes.nFileSizeHigh,
|
||||
&attributes.ftLastWriteTime,
|
||||
info);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_system_error(error, GetLastError());
|
||||
attributes.ftLastWriteTime);
|
||||
}
|
||||
}
|
||||
else if (auto const
|
||||
handle = CreateFileW(wide_path.c_str(), 0, 0, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
||||
handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
auto ret = tr_sys_file_get_info(handle, error);
|
||||
CloseHandle(handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
tr_free(wide_path);
|
||||
|
||||
return ret;
|
||||
set_system_error(error, GetLastError());
|
||||
return {};
|
||||
}
|
||||
|
||||
bool tr_sys_path_is_relative(std::string_view path)
|
||||
@@ -1071,29 +1045,22 @@ bool tr_sys_file_close(tr_sys_file_t handle, tr_error** error)
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool tr_sys_file_get_info(tr_sys_file_t handle, tr_sys_path_info* info, tr_error** error)
|
||||
std::optional<tr_sys_path_info> tr_sys_file_get_info(tr_sys_file_t handle, tr_error** error)
|
||||
{
|
||||
TR_ASSERT(handle != TR_BAD_SYS_FILE);
|
||||
TR_ASSERT(info != nullptr);
|
||||
|
||||
BY_HANDLE_FILE_INFORMATION attributes;
|
||||
bool ret = GetFileInformationByHandle(handle, &attributes);
|
||||
|
||||
if (ret)
|
||||
auto attributes = BY_HANDLE_FILE_INFORMATION{};
|
||||
if (GetFileInformationByHandle(handle, &attributes))
|
||||
{
|
||||
stat_to_sys_path_info(
|
||||
return stat_to_sys_path_info(
|
||||
attributes.dwFileAttributes,
|
||||
attributes.nFileSizeLow,
|
||||
attributes.nFileSizeHigh,
|
||||
&attributes.ftLastWriteTime,
|
||||
info);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_system_error(error, GetLastError());
|
||||
attributes.ftLastWriteTime);
|
||||
}
|
||||
|
||||
return ret;
|
||||
set_system_error(error, GetLastError());
|
||||
return {};
|
||||
}
|
||||
|
||||
bool tr_sys_file_seek(tr_sys_file_t handle, int64_t offset, tr_seek_origin_t origin, uint64_t* new_offset, tr_error** error)
|
||||
|
||||
+20
-9
@@ -8,9 +8,9 @@
|
||||
#include <cstddef> // size_t
|
||||
#include <cstdint> // uint64_t
|
||||
#include <ctime> // time_t
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
@@ -117,8 +117,18 @@ enum tr_sys_path_type_t
|
||||
struct tr_sys_path_info
|
||||
{
|
||||
tr_sys_path_type_t type = {};
|
||||
uint64_t size = 0;
|
||||
time_t last_modified_at = 0;
|
||||
uint64_t size = {};
|
||||
time_t last_modified_at = {};
|
||||
|
||||
[[nodiscard]] constexpr auto isFile() const noexcept
|
||||
{
|
||||
return type == TR_SYS_PATH_IS_FILE;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto isFolder() const noexcept
|
||||
{
|
||||
return type == TR_SYS_PATH_IS_DIRECTORY;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -153,13 +163,15 @@ bool tr_sys_path_copy(char const* src_path, char const* dst_path, struct tr_erro
|
||||
*
|
||||
* @param[in] path Path to file or directory.
|
||||
* @param[in] flags Combination of @ref tr_sys_path_get_info_flags_t values.
|
||||
* @param[out] info Result buffer.
|
||||
* @param[out] error Pointer to error object. Optional, pass `nullptr` if you
|
||||
* are not interested in error details.
|
||||
*
|
||||
* @return `True` on success, `false` otherwise (with `error` set accordingly).
|
||||
* @return info on success, or nullopt with `error` set accordingly.
|
||||
*/
|
||||
bool tr_sys_path_get_info(char const* path, int flags, tr_sys_path_info* info, struct tr_error** error = nullptr);
|
||||
[[nodiscard]] std::optional<tr_sys_path_info> tr_sys_path_get_info(
|
||||
std::string_view path,
|
||||
int flags = 0,
|
||||
tr_error** error = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Portability wrapper for `access()`.
|
||||
@@ -369,13 +381,12 @@ bool tr_sys_file_close(tr_sys_file_t handle, struct tr_error** error = nullptr);
|
||||
* @brief Portability wrapper for `fstat()`.
|
||||
*
|
||||
* @param[in] handle Valid file descriptor.
|
||||
* @param[out] info Result buffer.
|
||||
* @param[out] error Pointer to error object. Optional, pass `nullptr` if you
|
||||
* are not interested in error details.
|
||||
*
|
||||
* @return `True` on success, `false` otherwise (with `error` set accordingly).
|
||||
* @return info on success, or nullopt with `error` set accordingly.
|
||||
*/
|
||||
bool tr_sys_file_get_info(tr_sys_file_t handle, tr_sys_path_info* info, struct tr_error** error = nullptr);
|
||||
[[nodiscard]] std::optional<tr_sys_path_info> tr_sys_file_get_info(tr_sys_file_t handle, struct tr_error** error = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Portability wrapper for `lseek()`.
|
||||
|
||||
+30
-22
@@ -54,8 +54,9 @@ static struct FileList* getFiles(std::string_view dir, std::string_view base, st
|
||||
auto buf = tr_pathbuf{ dir, '/', base };
|
||||
tr_sys_path_native_separators(std::data(buf));
|
||||
|
||||
tr_sys_path_info info;
|
||||
if (tr_error* error = nullptr; !tr_sys_path_get_info(buf, 0, &info, &error))
|
||||
tr_error* error = nullptr;
|
||||
auto const info = tr_sys_path_get_info(buf, 0, &error);
|
||||
if (!info)
|
||||
{
|
||||
tr_logAddWarn(fmt::format(
|
||||
_("Skipping '{path}': {error} ({error_code})"),
|
||||
@@ -66,27 +67,36 @@ static struct FileList* getFiles(std::string_view dir, std::string_view base, st
|
||||
return list;
|
||||
}
|
||||
|
||||
if (tr_sys_dir_t odir = info.type == TR_SYS_PATH_IS_DIRECTORY ? tr_sys_dir_open(buf.c_str()) : TR_BAD_SYS_DIR;
|
||||
odir != TR_BAD_SYS_DIR)
|
||||
switch (info->type)
|
||||
{
|
||||
char const* name = nullptr;
|
||||
while ((name = tr_sys_dir_read_name(odir)) != nullptr)
|
||||
case TR_SYS_PATH_IS_DIRECTORY:
|
||||
if (auto const odir = tr_sys_dir_open(buf.c_str()); odir != TR_BAD_SYS_DIR)
|
||||
{
|
||||
if (name[0] != '.') /* skip dotfiles */
|
||||
char const* name = nullptr;
|
||||
while ((name = tr_sys_dir_read_name(odir)) != nullptr)
|
||||
{
|
||||
list = getFiles(buf.c_str(), name, list);
|
||||
if (name[0] != '.') /* skip dotfiles */
|
||||
{
|
||||
list = getFiles(buf.c_str(), name, list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tr_sys_dir_close(odir);
|
||||
}
|
||||
else if (info.type == TR_SYS_PATH_IS_FILE)
|
||||
{
|
||||
auto* const node = tr_new0(FileList, 1);
|
||||
node->size = info.size;
|
||||
node->filename = tr_strvDup(buf);
|
||||
node->next = list;
|
||||
list = node;
|
||||
tr_sys_dir_close(odir);
|
||||
}
|
||||
break;
|
||||
|
||||
case TR_SYS_PATH_IS_FILE:
|
||||
{
|
||||
auto* const node = tr_new0(FileList, 1);
|
||||
node->size = info->size;
|
||||
node->filename = tr_strvDup(buf);
|
||||
node->next = list;
|
||||
list = node;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return list;
|
||||
@@ -145,10 +155,8 @@ tr_metainfo_builder* tr_metaInfoBuilderCreate(char const* topFileArg)
|
||||
|
||||
ret->top = real_top;
|
||||
|
||||
{
|
||||
tr_sys_path_info info;
|
||||
ret->isFolder = tr_sys_path_get_info(ret->top, 0, &info) && info.type == TR_SYS_PATH_IS_DIRECTORY;
|
||||
}
|
||||
auto const info = tr_sys_path_get_info(ret->top);
|
||||
ret->isFolder = info && info->isFolder();
|
||||
|
||||
/* build a list of files containing top file and,
|
||||
if it's a directory, all of its children */
|
||||
|
||||
@@ -167,11 +167,11 @@ std::optional<tr_sys_file_t> tr_open_files::get(
|
||||
}
|
||||
}
|
||||
|
||||
auto info = tr_sys_path_info{};
|
||||
bool const already_existed = tr_sys_path_get_info(filename, 0, &info) && info.type == TR_SYS_PATH_IS_FILE;
|
||||
auto const info = tr_sys_path_get_info(filename);
|
||||
bool const already_existed = info && info->isFile();
|
||||
|
||||
// we need write permissions to resize the file
|
||||
bool const resize_needed = already_existed && (file_size < info.size);
|
||||
bool const resize_needed = already_existed && (file_size < info->size);
|
||||
writable |= resize_needed;
|
||||
|
||||
// open the file
|
||||
|
||||
+11
-15
@@ -2045,11 +2045,9 @@ static void sessionLoadTorrents(struct sessionLoadTorrentsData* const data)
|
||||
{
|
||||
TR_ASSERT(tr_isSession(data->session));
|
||||
|
||||
tr_sys_path_info info;
|
||||
auto const& dirname = data->session->torrentDir();
|
||||
tr_sys_dir_t odir = (tr_sys_path_get_info(dirname.c_str(), 0, &info) && info.type == TR_SYS_PATH_IS_DIRECTORY) ?
|
||||
tr_sys_dir_open(dirname.c_str()) :
|
||||
TR_BAD_SYS_DIR;
|
||||
auto const info = tr_sys_path_get_info(dirname);
|
||||
auto const odir = info && info->isFolder() ? tr_sys_dir_open(dirname.c_str()) : TR_BAD_SYS_DIR;
|
||||
|
||||
auto torrents = std::list<tr_torrent*>{};
|
||||
if (odir != TR_BAD_SYS_DIR)
|
||||
@@ -2342,7 +2340,7 @@ bool tr_sessionIsPortForwardingEnabled(tr_session const* session)
|
||||
static void loadBlocklists(tr_session* session)
|
||||
{
|
||||
auto loadme = std::unordered_set<std::string>{};
|
||||
auto const isEnabled = session->useBlocklist();
|
||||
auto const is_enabled = session->useBlocklist();
|
||||
|
||||
/* walk the blocklist directory... */
|
||||
auto const dirname = tr_pathbuf{ session->configDir(), "/blocklists"sv };
|
||||
@@ -2369,28 +2367,26 @@ static void loadBlocklists(tr_session* session)
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_sys_path_info path_info;
|
||||
tr_sys_path_info binname_info;
|
||||
|
||||
auto const binname = tr_pathbuf{ dirname, '/', name, ".bin"sv };
|
||||
|
||||
if (!tr_sys_path_get_info(binname, 0, &binname_info)) /* create it */
|
||||
if (auto const bininfo = tr_sys_path_get_info(binname); !bininfo)
|
||||
{
|
||||
BlocklistFile b(binname, isEnabled);
|
||||
// create it
|
||||
auto b = BlocklistFile{ binname, is_enabled };
|
||||
if (auto const n = b.setContent(path); n > 0)
|
||||
{
|
||||
load = binname;
|
||||
}
|
||||
}
|
||||
else if (
|
||||
tr_sys_path_get_info(path, 0, &path_info) &&
|
||||
path_info.last_modified_at >= binname_info.last_modified_at) /* update it */
|
||||
else if (auto const pathinfo = tr_sys_path_get_info(path);
|
||||
path && pathinfo->last_modified_at >= bininfo->last_modified_at)
|
||||
{
|
||||
// update it
|
||||
auto const old = tr_pathbuf{ binname, ".old"sv };
|
||||
tr_sys_path_remove(old);
|
||||
tr_sys_path_rename(binname, old);
|
||||
|
||||
BlocklistFile b(binname, isEnabled);
|
||||
BlocklistFile b(binname, is_enabled);
|
||||
|
||||
if (b.setContent(path) > 0)
|
||||
{
|
||||
@@ -2415,7 +2411,7 @@ static void loadBlocklists(tr_session* session)
|
||||
std::begin(loadme),
|
||||
std::end(loadme),
|
||||
std::back_inserter(session->blocklists),
|
||||
[&isEnabled](auto const& path) { return std::make_unique<BlocklistFile>(path.c_str(), isEnabled); });
|
||||
[&is_enabled](auto const& path) { return std::make_unique<BlocklistFile>(path.c_str(), is_enabled); });
|
||||
|
||||
/* cleanup */
|
||||
tr_sys_dir_close(odir);
|
||||
|
||||
@@ -27,15 +27,15 @@ namespace
|
||||
|
||||
using file_func_t = std::function<void(char const* filename)>;
|
||||
|
||||
bool isDirectory(char const* path)
|
||||
bool isFolder(std::string_view path)
|
||||
{
|
||||
auto info = tr_sys_path_info{};
|
||||
return tr_sys_path_get_info(path, 0, &info) && (info.type == TR_SYS_PATH_IS_DIRECTORY);
|
||||
auto const info = tr_sys_path_get_info(path);
|
||||
return info && info->isFolder();
|
||||
}
|
||||
|
||||
bool isEmptyDirectory(char const* path)
|
||||
bool isEmptyFolder(char const* path)
|
||||
{
|
||||
if (!isDirectory(path))
|
||||
if (!isFolder(path))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -60,7 +60,7 @@ bool isEmptyDirectory(char const* path)
|
||||
|
||||
void depthFirstWalk(char const* path, file_func_t const& func, std::optional<int> max_depth = {})
|
||||
{
|
||||
if (isDirectory(path) && (!max_depth || *max_depth > 0))
|
||||
if (isFolder(path) && (!max_depth || *max_depth > 0))
|
||||
{
|
||||
if (auto const odir = tr_sys_dir_open(path); odir != TR_BAD_SYS_DIR)
|
||||
{
|
||||
@@ -114,7 +114,6 @@ std::optional<tr_torrent_files::FoundFile> tr_torrent_files::find(
|
||||
size_t n_paths) const
|
||||
{
|
||||
auto filename = tr_pathbuf{};
|
||||
auto file_info = tr_sys_path_info{};
|
||||
auto const& subpath = path(file_index);
|
||||
|
||||
for (size_t path_idx = 0; path_idx < n_paths; ++path_idx)
|
||||
@@ -122,15 +121,15 @@ std::optional<tr_torrent_files::FoundFile> tr_torrent_files::find(
|
||||
auto const base = search_paths[path_idx];
|
||||
|
||||
filename.assign(base, '/', subpath);
|
||||
if (tr_sys_path_get_info(filename, 0, &file_info))
|
||||
if (auto const info = tr_sys_path_get_info(filename); info)
|
||||
{
|
||||
return FoundFile{ file_info, std::move(filename), std::size(base) };
|
||||
return FoundFile{ *info, std::move(filename), std::size(base) };
|
||||
}
|
||||
|
||||
filename.assign(filename, base, '/', subpath, PartialFileSuffix);
|
||||
if (tr_sys_path_get_info(filename, 0, &file_info))
|
||||
filename.assign(base, '/', subpath, PartialFileSuffix);
|
||||
if (auto const info = tr_sys_path_get_info(filename); info)
|
||||
{
|
||||
return FoundFile{ file_info, std::move(filename), std::size(base) };
|
||||
return FoundFile{ *info, std::move(filename), std::size(base) };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,7 +219,7 @@ bool tr_torrent_files::move(
|
||||
{
|
||||
auto const remove_empty_directories = [](char const* filename)
|
||||
{
|
||||
if (isEmptyDirectory(filename))
|
||||
if (isEmptyFolder(filename))
|
||||
{
|
||||
tr_sys_path_remove(filename, nullptr);
|
||||
}
|
||||
@@ -304,7 +303,7 @@ void tr_torrent_files::remove(std::string_view parent_in, std::string_view tmpdi
|
||||
// Remove the first two categories and leave the third alone.
|
||||
auto const remove_junk = [](char const* filename)
|
||||
{
|
||||
if (isEmptyDirectory(filename) || isJunkFile(filename))
|
||||
if (isEmptyFolder(filename) || isJunkFile(filename))
|
||||
{
|
||||
tr_sys_path_remove(filename);
|
||||
}
|
||||
|
||||
@@ -142,9 +142,9 @@ bool tr_loadFile(std::string_view path_in, std::vector<char>& setme, tr_error**
|
||||
auto const path = tr_pathbuf{ path_in };
|
||||
|
||||
/* try to stat the file */
|
||||
auto info = tr_sys_path_info{};
|
||||
tr_error* my_error = nullptr;
|
||||
if (!tr_sys_path_get_info(path, 0, &info, &my_error))
|
||||
auto const info = tr_sys_path_get_info(path, 0, &my_error);
|
||||
if (!info)
|
||||
{
|
||||
tr_logAddError(fmt::format(
|
||||
_("Couldn't read '{path}': {error} ({error_code})"),
|
||||
@@ -155,7 +155,7 @@ bool tr_loadFile(std::string_view path_in, std::vector<char>& setme, tr_error**
|
||||
return false;
|
||||
}
|
||||
|
||||
if (info.type != TR_SYS_PATH_IS_FILE)
|
||||
if (!info->isFile())
|
||||
{
|
||||
tr_logAddError(fmt::format(_("Couldn't read '{path}': Not a regular file"), fmt::arg("path", path)));
|
||||
tr_error_set(error, TR_ERROR_EISDIR, "Not a regular file"sv);
|
||||
@@ -175,8 +175,8 @@ bool tr_loadFile(std::string_view path_in, std::vector<char>& setme, tr_error**
|
||||
return false;
|
||||
}
|
||||
|
||||
setme.resize(info.size);
|
||||
if (!tr_sys_file_read(fd, std::data(setme), info.size, nullptr, &my_error))
|
||||
setme.resize(info->size);
|
||||
if (!tr_sys_file_read(fd, std::data(setme), info->size, nullptr, &my_error))
|
||||
{
|
||||
tr_logAddError(fmt::format(
|
||||
_("Couldn't read '{path}': {error} ({error_code})"),
|
||||
@@ -851,13 +851,13 @@ bool tr_moveFile(std::string_view oldpath_in, std::string_view newpath_in, tr_er
|
||||
auto const newpath = tr_pathbuf{ newpath_in };
|
||||
|
||||
// make sure the old file exists
|
||||
auto info = tr_sys_path_info{};
|
||||
if (!tr_sys_path_get_info(oldpath, 0, &info, error))
|
||||
auto const info = tr_sys_path_get_info(oldpath, 0, error);
|
||||
if (!info)
|
||||
{
|
||||
tr_error_prefix(error, "Unable to get information on old file: ");
|
||||
return false;
|
||||
}
|
||||
if (info.type != TR_SYS_PATH_IS_FILE)
|
||||
if (!info->isFile())
|
||||
{
|
||||
tr_error_set(error, TR_ERROR_EINVAL, "Old path does not point to a file."sv);
|
||||
return false;
|
||||
|
||||
@@ -265,10 +265,8 @@ private:
|
||||
{
|
||||
auto const path = tr_pathbuf{ dir, '/', name };
|
||||
|
||||
auto path_info = tr_sys_path_info{};
|
||||
tr_error* error = nullptr;
|
||||
bool const ret = tr_sys_path_get_info(path, 0, &path_info, &error) && (path_info.type == TR_SYS_PATH_IS_FILE);
|
||||
|
||||
auto const info = tr_sys_path_get_info(path, 0, &error);
|
||||
if (error != nullptr)
|
||||
{
|
||||
if (!TR_ERROR_IS_ENOENT(error->code))
|
||||
@@ -283,7 +281,7 @@ private:
|
||||
tr_error_free(error);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return info && info->isFile();
|
||||
}
|
||||
|
||||
static constexpr std::string_view statusToString(tr_watchdir_status status)
|
||||
|
||||
@@ -81,14 +81,14 @@ private:
|
||||
EXPECT_NE(fd1, TR_BAD_SYS_FILE);
|
||||
EXPECT_NE(fd2, TR_BAD_SYS_FILE);
|
||||
|
||||
tr_sys_path_info info1;
|
||||
tr_sys_path_info info2;
|
||||
tr_sys_file_get_info(fd1, &info1);
|
||||
tr_sys_file_get_info(fd2, &info2);
|
||||
EXPECT_EQ(info1.size, info2.size);
|
||||
auto const info1 = tr_sys_file_get_info(fd1);
|
||||
auto const info2 = tr_sys_file_get_info(fd2);
|
||||
EXPECT_TRUE(info1);
|
||||
EXPECT_TRUE(info2);
|
||||
EXPECT_EQ(info1->size, info2->size);
|
||||
|
||||
uint64_t bytes_left1 = info1.size;
|
||||
uint64_t bytes_left2 = info2.size;
|
||||
auto bytes_left1 = info1->size;
|
||||
auto bytes_left2 = info2->size;
|
||||
|
||||
size_t const buflen = 2 * 1024 * 1024; /* 2 MiB buffer */
|
||||
auto* readbuf1 = static_cast<char*>(tr_malloc(buflen));
|
||||
|
||||
@@ -107,7 +107,6 @@ protected:
|
||||
|
||||
while (*p != '\0')
|
||||
{
|
||||
tr_sys_path_info info;
|
||||
char const* slash_pos = strchr(p, '/');
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -127,9 +126,8 @@ protected:
|
||||
}
|
||||
|
||||
auto const path_part = std::string{ path, size_t(slash_pos - path + 1) };
|
||||
|
||||
if (!tr_sys_path_get_info(path_part.c_str(), TR_SYS_PATH_NO_FOLLOW, &info) ||
|
||||
(info.type != TR_SYS_PATH_IS_FILE && info.type != TR_SYS_PATH_IS_DIRECTORY))
|
||||
auto const info = tr_sys_path_get_info(path_part, TR_SYS_PATH_NO_FOLLOW);
|
||||
if (!info || (!info->isFile() && !info->isFolder()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -226,14 +224,14 @@ protected:
|
||||
TEST_F(FileTest, getInfo)
|
||||
{
|
||||
auto const test_dir = createTestDir(currentTestName());
|
||||
tr_sys_path_info info;
|
||||
|
||||
auto const path1 = tr_pathbuf{ test_dir, "/a"sv };
|
||||
auto const path2 = tr_pathbuf{ test_dir, "/b"sv };
|
||||
|
||||
// Can't get info of non-existent file/directory
|
||||
tr_error* err = nullptr;
|
||||
EXPECT_FALSE(tr_sys_path_get_info(path1, 0, &info, &err));
|
||||
auto info = tr_sys_path_get_info(path1, 0, &err);
|
||||
EXPECT_FALSE(info);
|
||||
EXPECT_NE(nullptr, err);
|
||||
tr_error_clear(&err);
|
||||
|
||||
@@ -241,23 +239,23 @@ TEST_F(FileTest, getInfo)
|
||||
createFileWithContents(path1, "test");
|
||||
|
||||
// Good file info
|
||||
clearPathInfo(&info);
|
||||
EXPECT_TRUE(tr_sys_path_get_info(path1, 0, &info, &err));
|
||||
info = tr_sys_path_get_info(path1, 0, &err);
|
||||
EXPECT_TRUE(info);
|
||||
EXPECT_EQ(nullptr, err) << *err;
|
||||
EXPECT_EQ(TR_SYS_PATH_IS_FILE, info.type);
|
||||
EXPECT_EQ(4, info.size);
|
||||
EXPECT_GE(info.last_modified_at, t - 1);
|
||||
EXPECT_LE(info.last_modified_at, time(nullptr) + 1);
|
||||
EXPECT_EQ(TR_SYS_PATH_IS_FILE, info->type);
|
||||
EXPECT_EQ(4U, info->size);
|
||||
EXPECT_GE(info->last_modified_at, t - 1);
|
||||
EXPECT_LE(info->last_modified_at, time(nullptr) + 1);
|
||||
|
||||
// Good file info (by handle)
|
||||
auto fd = tr_sys_file_open(path1, TR_SYS_FILE_READ, 0);
|
||||
clearPathInfo(&info);
|
||||
EXPECT_TRUE(tr_sys_file_get_info(fd, &info, &err));
|
||||
info = tr_sys_file_get_info(fd, &err);
|
||||
EXPECT_TRUE(info);
|
||||
EXPECT_EQ(nullptr, err) << *err;
|
||||
EXPECT_EQ(TR_SYS_PATH_IS_FILE, info.type);
|
||||
EXPECT_EQ(4, info.size);
|
||||
EXPECT_GE(info.last_modified_at, t - 1);
|
||||
EXPECT_LE(info.last_modified_at, time(nullptr) + 1);
|
||||
EXPECT_EQ(TR_SYS_PATH_IS_FILE, info->type);
|
||||
EXPECT_EQ(4, info->size);
|
||||
EXPECT_GE(info->last_modified_at, t - 1);
|
||||
EXPECT_LE(info->last_modified_at, time(nullptr) + 1);
|
||||
tr_sys_file_close(fd);
|
||||
|
||||
tr_sys_path_remove(path1);
|
||||
@@ -265,19 +263,20 @@ TEST_F(FileTest, getInfo)
|
||||
// Good directory info
|
||||
t = time(nullptr);
|
||||
tr_sys_dir_create(path1, 0, 0777);
|
||||
clearPathInfo(&info);
|
||||
EXPECT_TRUE(tr_sys_path_get_info(path1, 0, &info, &err));
|
||||
info = tr_sys_path_get_info(path1, 0, &err);
|
||||
EXPECT_TRUE(info);
|
||||
EXPECT_EQ(nullptr, err) << *err;
|
||||
EXPECT_EQ(TR_SYS_PATH_IS_DIRECTORY, info.type);
|
||||
EXPECT_NE(uint64_t(-1), info.size);
|
||||
EXPECT_GE(info.last_modified_at, t - 1);
|
||||
EXPECT_LE(info.last_modified_at, time(nullptr) + 1);
|
||||
EXPECT_EQ(TR_SYS_PATH_IS_DIRECTORY, info->type);
|
||||
EXPECT_NE(uint64_t(-1), info->size);
|
||||
EXPECT_GE(info->last_modified_at, t - 1);
|
||||
EXPECT_LE(info->last_modified_at, time(nullptr) + 1);
|
||||
tr_sys_path_remove(path1);
|
||||
|
||||
if (createSymlink(path1, path2, false))
|
||||
{
|
||||
// Can't get info of non-existent file/directory
|
||||
EXPECT_FALSE(tr_sys_path_get_info(path1, 0, &info, &err));
|
||||
info = tr_sys_path_get_info(path1, 0, &err);
|
||||
EXPECT_FALSE(info);
|
||||
EXPECT_NE(nullptr, err);
|
||||
tr_error_clear(&err);
|
||||
|
||||
@@ -285,23 +284,23 @@ TEST_F(FileTest, getInfo)
|
||||
createFileWithContents(path2, "test");
|
||||
|
||||
// Good file info
|
||||
clearPathInfo(&info);
|
||||
EXPECT_TRUE(tr_sys_path_get_info(path1, 0, &info, &err));
|
||||
info = tr_sys_path_get_info(path1, 0, &err);
|
||||
EXPECT_TRUE(info);
|
||||
EXPECT_EQ(nullptr, err) << *err;
|
||||
EXPECT_EQ(TR_SYS_PATH_IS_FILE, info.type);
|
||||
EXPECT_EQ(4, info.size);
|
||||
EXPECT_GE(info.last_modified_at, t - 1);
|
||||
EXPECT_LE(info.last_modified_at, time(nullptr) + 1);
|
||||
EXPECT_EQ(TR_SYS_PATH_IS_FILE, info->type);
|
||||
EXPECT_EQ(4, info->size);
|
||||
EXPECT_GE(info->last_modified_at, t - 1);
|
||||
EXPECT_LE(info->last_modified_at, time(nullptr) + 1);
|
||||
|
||||
// Good file info (by handle)
|
||||
fd = tr_sys_file_open(path1, TR_SYS_FILE_READ, 0);
|
||||
clearPathInfo(&info);
|
||||
EXPECT_TRUE(tr_sys_file_get_info(fd, &info, &err));
|
||||
info = tr_sys_file_get_info(fd, &err);
|
||||
EXPECT_TRUE(info);
|
||||
EXPECT_EQ(nullptr, err) << *err;
|
||||
EXPECT_EQ(TR_SYS_PATH_IS_FILE, info.type);
|
||||
EXPECT_EQ(4, info.size);
|
||||
EXPECT_GE(info.last_modified_at, t - 1);
|
||||
EXPECT_LE(info.last_modified_at, time(nullptr) + 1);
|
||||
EXPECT_EQ(TR_SYS_PATH_IS_FILE, info->type);
|
||||
EXPECT_EQ(4, info->size);
|
||||
EXPECT_GE(info->last_modified_at, t - 1);
|
||||
EXPECT_LE(info->last_modified_at, time(nullptr) + 1);
|
||||
tr_sys_file_close(fd);
|
||||
|
||||
tr_sys_path_remove(path2);
|
||||
@@ -311,13 +310,13 @@ TEST_F(FileTest, getInfo)
|
||||
t = time(nullptr);
|
||||
tr_sys_dir_create(path2, 0, 0777);
|
||||
EXPECT_TRUE(createSymlink(path1, path2, true)); /* Win32: directory and file symlinks differ :( */
|
||||
clearPathInfo(&info);
|
||||
EXPECT_TRUE(tr_sys_path_get_info(path1, 0, &info, &err));
|
||||
info = tr_sys_path_get_info(path1, 0, &err);
|
||||
EXPECT_TRUE(info);
|
||||
EXPECT_EQ(nullptr, err) << *err;
|
||||
EXPECT_EQ(TR_SYS_PATH_IS_DIRECTORY, info.type);
|
||||
EXPECT_NE(uint64_t(-1), info.size);
|
||||
EXPECT_GE(info.last_modified_at, t - 1);
|
||||
EXPECT_LE(info.last_modified_at, time(nullptr) + 1);
|
||||
EXPECT_EQ(TR_SYS_PATH_IS_DIRECTORY, info->type);
|
||||
EXPECT_NE(uint64_t(-1), info->size);
|
||||
EXPECT_GE(info->last_modified_at, t - 1);
|
||||
EXPECT_LE(info->last_modified_at, time(nullptr) + 1);
|
||||
|
||||
tr_sys_path_remove(path2);
|
||||
tr_sys_path_remove(path1);
|
||||
@@ -1088,13 +1087,14 @@ TEST_F(FileTest, fileOpen)
|
||||
EXPECT_EQ(TR_BAD_SYS_FILE, fd);
|
||||
EXPECT_NE(nullptr, err);
|
||||
tr_error_clear(&err);
|
||||
tr_sys_path_info info;
|
||||
tr_sys_path_get_info(path1, TR_SYS_PATH_NO_FOLLOW, &info);
|
||||
EXPECT_EQ(4, info.size);
|
||||
auto info = tr_sys_path_get_info(path1, TR_SYS_PATH_NO_FOLLOW);
|
||||
EXPECT_TRUE(info);
|
||||
EXPECT_EQ(4U, info->size);
|
||||
|
||||
/* Pointer is at the end of file */
|
||||
tr_sys_path_get_info(path1, TR_SYS_PATH_NO_FOLLOW, &info);
|
||||
EXPECT_EQ(4, info.size);
|
||||
info = tr_sys_path_get_info(path1, TR_SYS_PATH_NO_FOLLOW);
|
||||
EXPECT_TRUE(info);
|
||||
EXPECT_EQ(4U, info->size);
|
||||
fd = tr_sys_file_open(path1, TR_SYS_FILE_WRITE | TR_SYS_FILE_APPEND, 0600, &err);
|
||||
EXPECT_NE(TR_BAD_SYS_FILE, fd);
|
||||
EXPECT_EQ(nullptr, err) << *err;
|
||||
@@ -1105,16 +1105,19 @@ TEST_F(FileTest, fileOpen)
|
||||
tr_sys_file_close(fd);
|
||||
|
||||
/* File gets truncated */
|
||||
tr_sys_path_get_info(path1, TR_SYS_PATH_NO_FOLLOW, &info);
|
||||
EXPECT_EQ(5, info.size);
|
||||
info = tr_sys_path_get_info(path1, TR_SYS_PATH_NO_FOLLOW);
|
||||
EXPECT_TRUE(info);
|
||||
EXPECT_EQ(5U, info->size);
|
||||
fd = tr_sys_file_open(path1, TR_SYS_FILE_WRITE | TR_SYS_FILE_TRUNCATE, 0600, &err);
|
||||
EXPECT_NE(TR_BAD_SYS_FILE, fd);
|
||||
EXPECT_EQ(nullptr, err) << *err;
|
||||
tr_sys_file_get_info(fd, &info);
|
||||
EXPECT_EQ(0, info.size);
|
||||
info = tr_sys_file_get_info(fd);
|
||||
EXPECT_TRUE(info);
|
||||
EXPECT_EQ(0U, info->size);
|
||||
tr_sys_file_close(fd);
|
||||
tr_sys_path_get_info(path1, TR_SYS_PATH_NO_FOLLOW, &info);
|
||||
EXPECT_EQ(0, info.size);
|
||||
info = tr_sys_path_get_info(path1, TR_SYS_PATH_NO_FOLLOW);
|
||||
EXPECT_TRUE(info);
|
||||
EXPECT_EQ(0U, info->size);
|
||||
|
||||
/* TODO: symlink and hardlink tests */
|
||||
|
||||
@@ -1214,27 +1217,30 @@ TEST_F(FileTest, fileTruncate)
|
||||
tr_error* err = nullptr;
|
||||
EXPECT_TRUE(tr_sys_file_truncate(fd, 10, &err));
|
||||
EXPECT_EQ(nullptr, err) << *err;
|
||||
tr_sys_path_info info;
|
||||
tr_sys_file_get_info(fd, &info);
|
||||
EXPECT_EQ(10, info.size);
|
||||
auto info = tr_sys_file_get_info(fd);
|
||||
EXPECT_TRUE(info);
|
||||
EXPECT_EQ(10U, info->size);
|
||||
|
||||
EXPECT_TRUE(tr_sys_file_truncate(fd, 20, &err));
|
||||
EXPECT_EQ(nullptr, err) << *err;
|
||||
tr_sys_file_get_info(fd, &info);
|
||||
EXPECT_EQ(20, info.size);
|
||||
info = tr_sys_file_get_info(fd);
|
||||
EXPECT_TRUE(info);
|
||||
EXPECT_EQ(20U, info->size);
|
||||
|
||||
EXPECT_TRUE(tr_sys_file_truncate(fd, 0, &err));
|
||||
EXPECT_EQ(nullptr, err) << *err;
|
||||
tr_sys_file_get_info(fd, &info);
|
||||
EXPECT_EQ(0, info.size);
|
||||
info = tr_sys_file_get_info(fd);
|
||||
EXPECT_TRUE(info);
|
||||
EXPECT_EQ(0U, info->size);
|
||||
|
||||
EXPECT_TRUE(tr_sys_file_truncate(fd, 50, &err));
|
||||
EXPECT_EQ(nullptr, err) << *err;
|
||||
|
||||
tr_sys_file_close(fd);
|
||||
|
||||
tr_sys_path_get_info(path1, 0, &info);
|
||||
EXPECT_EQ(50, info.size);
|
||||
info = tr_sys_path_get_info(path1);
|
||||
EXPECT_TRUE(info);
|
||||
EXPECT_EQ(50U, info->size);
|
||||
|
||||
fd = tr_sys_file_open(path1, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0600);
|
||||
|
||||
@@ -1243,8 +1249,9 @@ TEST_F(FileTest, fileTruncate)
|
||||
|
||||
tr_sys_file_close(fd);
|
||||
|
||||
tr_sys_path_get_info(path1, 0, &info);
|
||||
EXPECT_EQ(25, info.size);
|
||||
info = tr_sys_path_get_info(path1);
|
||||
EXPECT_TRUE(info);
|
||||
EXPECT_EQ(25U, info->size);
|
||||
|
||||
tr_sys_path_remove(path1);
|
||||
}
|
||||
@@ -1261,9 +1268,9 @@ TEST_F(FileTest, filePreallocate)
|
||||
if (tr_sys_file_preallocate(fd, prealloc_size, 0, &err))
|
||||
{
|
||||
EXPECT_EQ(nullptr, err) << *err;
|
||||
tr_sys_path_info info;
|
||||
tr_sys_file_get_info(fd, &info);
|
||||
EXPECT_EQ(prealloc_size, info.size);
|
||||
auto info = tr_sys_file_get_info(fd);
|
||||
EXPECT_TRUE(info);
|
||||
EXPECT_EQ(prealloc_size, info->size);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1282,9 +1289,9 @@ TEST_F(FileTest, filePreallocate)
|
||||
if (tr_sys_file_preallocate(fd, prealloc_size, TR_SYS_FILE_PREALLOC_SPARSE, &err))
|
||||
{
|
||||
EXPECT_EQ(nullptr, err) << *err;
|
||||
tr_sys_path_info info;
|
||||
tr_sys_file_get_info(fd, &info);
|
||||
EXPECT_EQ(prealloc_size, info.size);
|
||||
auto info = tr_sys_file_get_info(fd);
|
||||
EXPECT_TRUE(info);
|
||||
EXPECT_EQ(prealloc_size, info->size);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -45,15 +45,19 @@ using file_func_t = std::function<void(char const* filename)>;
|
||||
|
||||
static void depthFirstWalk(char const* path, file_func_t func)
|
||||
{
|
||||
auto info = tr_sys_path_info{};
|
||||
if (tr_sys_path_get_info(path, 0, &info) && (info.type == TR_SYS_PATH_IS_DIRECTORY))
|
||||
if (auto const info = tr_sys_path_get_info(path); info && info->isFolder())
|
||||
{
|
||||
if (auto const odir = tr_sys_dir_open(path); odir != TR_BAD_SYS_DIR)
|
||||
{
|
||||
char const* name;
|
||||
while ((name = tr_sys_dir_read_name(odir)) != nullptr)
|
||||
for (;;)
|
||||
{
|
||||
if (strcmp(name, ".") != 0 && strcmp(name, "..") != 0)
|
||||
char const* const name = tr_sys_dir_read_name(odir);
|
||||
if (name == nullptr)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ("."sv != name && ".."sv != name)
|
||||
{
|
||||
auto const child = fmt::format("{:s}/{:s}"sv, path, name);
|
||||
depthFirstWalk(child.c_str(), func);
|
||||
|
||||
Reference in New Issue
Block a user