From 6571be2b953b1c793b97ae5b9c78cbf7f7f5399e Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 12 Nov 2021 18:10:04 -0600 Subject: [PATCH] feat: add tr_strvPath() (#2134) * feat: add tr_strvJoin * feat: add tr_strvPath --- daemon/daemon.cc | 12 +- libtransmission/inout.cc | 13 +- libtransmission/makemeta.cc | 16 +- libtransmission/platform.cc | 29 +- libtransmission/platform.h | 5 +- libtransmission/resume.cc | 2 +- libtransmission/rpcimpl.cc | 15 +- libtransmission/session-id.cc | 29 +- libtransmission/session.cc | 74 ++-- libtransmission/stats.cc | 25 +- libtransmission/torrent.cc | 112 ++--- libtransmission/tr-dht.cc | 23 +- libtransmission/tr-macros.h | 3 + libtransmission/utils.h | 34 ++ libtransmission/variant.cc | 2 +- libtransmission/watchdir.cc | 7 +- libtransmission/web.cc | 7 +- tests/libtransmission/blocklist-test.cc | 5 +- tests/libtransmission/copy-test.cc | 15 +- tests/libtransmission/file-test.cc | 557 +++++++++++------------- tests/libtransmission/makemeta-test.cc | 46 +- tests/libtransmission/move-test.cc | 12 +- tests/libtransmission/rename-test.cc | 21 +- tests/libtransmission/test-fixtures.h | 20 +- tests/libtransmission/utils-test.cc | 20 + 25 files changed, 527 insertions(+), 577 deletions(-) diff --git a/daemon/daemon.cc b/daemon/daemon.cc index 00f886d2e..0c7a12cb4 100644 --- a/daemon/daemon.cc +++ b/daemon/daemon.cc @@ -231,9 +231,9 @@ static tr_watchdir_status onFileAdded(tr_watchdir_t dir, char const* name, void* return TR_WATCHDIR_IGNORE; } - char* filename = tr_buildPath(tr_watchdir_get_path(dir), name, nullptr); + auto filename = tr_strvPath(tr_watchdir_get_path(dir), name); tr_ctor* ctor = tr_ctorNew(session); - int err = tr_ctorSetMetainfoFromFile(ctor, filename); + int err = tr_ctorSetMetainfoFromFile(ctor, filename.c_str()); if (err == 0) { @@ -256,7 +256,7 @@ static tr_watchdir_status onFileAdded(tr_watchdir_t dir, char const* name, void* tr_logAddInfo("Deleting input .torrent file \"%s\"", name); - if (!tr_sys_path_remove(filename, &error)) + if (!tr_sys_path_remove(filename.c_str(), &error)) { tr_logAddError("Error deleting .torrent file: %s", error->message); tr_error_free(error); @@ -264,9 +264,8 @@ static tr_watchdir_status onFileAdded(tr_watchdir_t dir, char const* name, void* } else { - char* new_filename = tr_strdup_printf("%s.added", filename); - tr_sys_path_rename(filename, new_filename, nullptr); - tr_free(new_filename); + auto const new_filename = filename + ".added"; + tr_sys_path_rename(filename.c_str(), new_filename.c_str(), nullptr); } } } @@ -276,7 +275,6 @@ static tr_watchdir_status onFileAdded(tr_watchdir_t dir, char const* name, void* } tr_ctorFree(ctor); - tr_free(filename); return err == TR_PARSE_ERR ? TR_WATCHDIR_RETRY : TR_WATCHDIR_ACCEPT; } diff --git a/libtransmission/inout.cc b/libtransmission/inout.cc index dbff7a081..1957210a4 100644 --- a/libtransmission/inout.cc +++ b/libtransmission/inout.cc @@ -91,23 +91,21 @@ static int readOrWriteBytes( if (err == 0) { /* open (and maybe create) the file */ - char* filename = tr_buildPath(base, subpath, nullptr); + auto const filename = tr_strvPath(base, subpath); tr_preallocation_mode const prealloc = (file->dnd || !doWrite) ? TR_PREALLOCATE_NONE : tor->session->preallocationMode; - fd = tr_fdFileCheckout(session, tor->uniqueId, fileIndex, filename, 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; - tr_logAddTorErr(tor, "tr_fdFileCheckout failed for \"%s\": %s", filename, tr_strerror(err)); + tr_logAddTorErr(tor, "tr_fdFileCheckout failed for \"%s\": %s", filename.c_str(), tr_strerror(err)); } else if (doWrite) { /* make a note that we just created a file */ tr_statsFileCreated(tor->session); } - - tr_free(filename); } tr_free(subpath); @@ -230,9 +228,8 @@ static int readOrWritePiece( if (err != 0 && ioMode == TR_IO_WRITE && tor->error != TR_STAT_LOCAL_ERROR) { - char* path = tr_buildPath(tor->downloadDir, file->name, nullptr); - tr_torrentSetLocalError(tor, "%s (%s)", tr_strerror(err), path); - tr_free(path); + auto const path = tr_strvPath(tor->downloadDir, file->name); + tr_torrentSetLocalError(tor, "%s (%s)", tr_strerror(err), path.c_str()); } } diff --git a/libtransmission/makemeta.cc b/libtransmission/makemeta.cc index c37439883..0c182b5c0 100644 --- a/libtransmission/makemeta.cc +++ b/libtransmission/makemeta.cc @@ -46,20 +46,19 @@ static struct FileList* getFiles(char const* dir, char const* base, struct FileL return nullptr; } - char* buf = tr_buildPath(dir, base, nullptr); - (void)tr_sys_path_native_separators(buf); + auto buf = tr_strvPath(dir, base); + tr_sys_path_native_separators(std::data(buf)); tr_sys_path_info info; tr_error* error = nullptr; - if (!tr_sys_path_get_info(buf, 0, &info, &error)) + if (!tr_sys_path_get_info(buf.c_str(), 0, &info, &error)) { - tr_logAddError(_("Torrent Creator is skipping file \"%s\": %s"), buf, error->message); - tr_free(buf); + tr_logAddError(_("Torrent Creator is skipping file \"%s\": %s"), buf.c_str(), error->message); tr_error_free(error); return list; } - tr_sys_dir_t odir = info.type == TR_SYS_PATH_IS_DIRECTORY ? tr_sys_dir_open(buf, nullptr) : TR_BAD_SYS_DIR; + tr_sys_dir_t odir = info.type == TR_SYS_PATH_IS_DIRECTORY ? tr_sys_dir_open(buf.c_str(), nullptr) : TR_BAD_SYS_DIR; if (odir != TR_BAD_SYS_DIR) { @@ -68,7 +67,7 @@ static struct FileList* getFiles(char const* dir, char const* base, struct FileL { if (name[0] != '.') /* skip dotfiles */ { - list = getFiles(buf, name, list); + list = getFiles(buf.c_str(), name, list); } } @@ -78,12 +77,11 @@ static struct FileList* getFiles(char const* dir, char const* base, struct FileL { struct FileList* node = tr_new(struct FileList, 1); node->size = info.size; - node->filename = tr_strdup(buf); + node->filename = tr_strvDup(buf); node->next = list; list = node; } - tr_free(buf); return list; } diff --git a/libtransmission/platform.cc b/libtransmission/platform.cc index 8175a0020..efba13b76 100644 --- a/libtransmission/platform.cc +++ b/libtransmission/platform.cc @@ -45,6 +45,8 @@ #include "tr-assert.h" #include "utils.h" +using namespace std::literals; + /*** **** THREADS ***/ @@ -388,15 +390,14 @@ char const* tr_getDefaultDownloadDir(void) /* figure out where to look for user-dirs.dirs */ char* const config_home = tr_env_get_string("XDG_CONFIG_HOME", nullptr); - char* const config_file = !tr_str_is_empty(config_home) ? - tr_buildPath(config_home, "user-dirs.dirs", nullptr) : - tr_buildPath(getHomeDir(), ".config", "user-dirs.dirs", nullptr); + auto const config_file = !tr_str_is_empty(config_home) ? tr_strvPath(config_home, "user-dirs.dirs") : + tr_strvPath(getHomeDir(), ".config", "user-dirs.dirs"); tr_free(config_home); /* read in user-dirs.dirs and look for the download dir entry */ size_t content_len = 0; - char* const content = (char*)tr_loadFile(config_file, &content_len, nullptr); + char* const content = (char*)tr_loadFile(config_file.c_str(), &content_len, nullptr); if (content != nullptr && content_len > 0) { @@ -447,7 +448,6 @@ char const* tr_getDefaultDownloadDir(void) } tr_free(content); - tr_free(config_file); } return user_dir; @@ -459,10 +459,9 @@ char const* tr_getDefaultDownloadDir(void) static bool isWebClientDir(char const* path) { - char* tmp = tr_buildPath(path, "index.html", nullptr); - bool const ret = tr_sys_path_exists(tmp, nullptr); - tr_logAddInfo(_("Searching for web interface file \"%s\""), tmp); - tr_free(tmp); + auto tmp = tr_strvPath(path, "index.html"); + bool const ret = tr_sys_path_exists(tmp.c_str(), nullptr); + tr_logAddInfo(_("Searching for web interface file \"%s\""), tmp.c_str()); return ret; } @@ -579,9 +578,7 @@ char const* tr_getWebClientDir([[maybe_unused]] tr_session const* session) } else { - char* dhome = tr_buildPath(getHomeDir(), ".local", "share", nullptr); - candidates.emplace_back(dhome); - tr_free(dhome); + candidates.emplace_back(tr_strvPath(getHomeDir(), ".local"sv, "share"sv)); } tr_free(tmp); @@ -639,18 +636,18 @@ char const* tr_getWebClientDir([[maybe_unused]] tr_session const* session) return s; } -char* tr_getSessionIdDir(void) +std::string tr_getSessionIdDir() { #ifndef _WIN32 - return tr_strdup("/tmp"); + return std::string{ "/tmp"sv }; #else char* program_data_dir = win32_get_known_folder_ex(FOLDERID_ProgramData, KF_FLAG_CREATE); - char* result = tr_buildPath(program_data_dir, "Transmission", nullptr); + auto const result = tr_strvPath(program_data_dir, "Transmission"); tr_free(program_data_dir); - tr_sys_dir_create(result, 0, 0, nullptr); + tr_sys_dir_create(result.c_str(), 0, 0, nullptr); return result; #endif diff --git a/libtransmission/platform.h b/libtransmission/platform.h index 3012bbd7c..01234fbc2 100644 --- a/libtransmission/platform.h +++ b/libtransmission/platform.h @@ -12,8 +12,7 @@ #error only libtransmission should #include this header. #endif -#define TR_PATH_DELIMITER '/' -#define TR_PATH_DELIMITER_STR "/" +#include /** * @addtogroup tr_session Session @@ -38,7 +37,7 @@ char const* tr_getTorrentDir(tr_session const*); char const* tr_getWebClientDir(tr_session const*); /** @brief return the directory where session id lock files are stored */ -char* tr_getSessionIdDir(void); +std::string tr_getSessionIdDir(); /** @} */ diff --git a/libtransmission/resume.cc b/libtransmission/resume.cc index 606ec45b5..18c828666 100644 --- a/libtransmission/resume.cc +++ b/libtransmission/resume.cc @@ -23,7 +23,7 @@ #include "session.h" #include "torrent.h" #include "tr-assert.h" -#include "utils.h" /* tr_buildPath */ +#include "utils.h" #include "variant.h" using namespace std::literals; diff --git a/libtransmission/rpcimpl.cc b/libtransmission/rpcimpl.cc index b13ee562c..4438b4f90 100644 --- a/libtransmission/rpcimpl.cc +++ b/libtransmission/rpcimpl.cc @@ -1534,12 +1534,12 @@ static void gotNewBlocklist( stream.avail_in = response_byte_count; inflateInit2(&stream, windowBits); - char* const filename = tr_buildPath(configDir, "blocklist.tmp.XXXXXX", nullptr); - tr_sys_file_t const fd = tr_sys_file_open_temp(filename, &error); + auto filename = tr_strvPath(configDir, "blocklist.tmp.XXXXXX"); + tr_sys_file_t const fd = tr_sys_file_open_temp(std::data(filename), &error); if (fd == TR_BAD_SYS_FILE) { - tr_snprintf(result, sizeof(result), _("Couldn't save file \"%1$s\": %2$s"), filename, error->message); + tr_snprintf(result, sizeof(result), _("Couldn't save file \"%1$s\": %2$s"), filename.c_str(), error->message); tr_error_clear(&error); } @@ -1552,7 +1552,7 @@ static void gotNewBlocklist( if ((stream.avail_out < buflen) && (!tr_sys_file_write(fd, buf, buflen - stream.avail_out, nullptr, &error))) { - tr_snprintf(result, sizeof(result), _("Couldn't save file \"%1$s\": %2$s"), filename, error->message); + tr_snprintf(result, sizeof(result), _("Couldn't save file \"%1$s\": %2$s"), filename.c_str(), error->message); tr_error_clear(&error); break; } @@ -1573,7 +1573,7 @@ static void gotNewBlocklist( if ((err == Z_DATA_ERROR) && // couldn't inflate it... it's probably already uncompressed !tr_sys_file_write(fd, response, response_byte_count, nullptr, &error)) { - tr_snprintf(result, sizeof(result), _("Couldn't save file \"%1$s\": %2$s"), filename, error->message); + tr_snprintf(result, sizeof(result), _("Couldn't save file \"%1$s\": %2$s"), filename.c_str(), error->message); tr_error_clear(&error); } @@ -1586,13 +1586,12 @@ static void gotNewBlocklist( else { /* feed it to the session and give the client a response */ - int const rule_count = tr_blocklistSetContent(session, filename); + int const rule_count = tr_blocklistSetContent(session, filename.c_str()); tr_variantDictAddInt(data->args_out, TR_KEY_blocklist_size, rule_count); tr_snprintf(result, sizeof(result), "success"); } - tr_sys_path_remove(filename, nullptr); - tr_free(filename); + tr_sys_path_remove(filename.c_str(), nullptr); tr_free(buf); } diff --git a/libtransmission/session-id.cc b/libtransmission/session-id.cc index 0b8a58c3a..4ec777670 100644 --- a/libtransmission/session-id.cc +++ b/libtransmission/session-id.cc @@ -23,6 +23,8 @@ #include "session-id.h" #include "utils.h" +using namespace std::literals; + #define SESSION_ID_SIZE 48 #define SESSION_ID_DURATION_SEC (60 * 60) /* expire in an hour */ @@ -54,12 +56,9 @@ static char* generate_new_session_id_value(void) return buf; } -static char* get_session_id_lock_file_path(char const* session_id) +static std::string get_session_id_lock_file_path(std::string_view session_id) { - char* lock_file_dir = tr_getSessionIdDir(); - char* lock_file_path = tr_strdup_printf("%s/tr_session_id_%s", lock_file_dir, session_id); - tr_free(lock_file_dir); - return lock_file_path; + return tr_strvJoin(tr_getSessionIdDir(), TR_PATH_DELIMITER_STR, "tr_session_id_"sv, session_id); } static tr_sys_file_t create_session_id_lock_file(char const* session_id) @@ -69,9 +68,13 @@ static tr_sys_file_t create_session_id_lock_file(char const* session_id) return TR_BAD_SYS_FILE; } - char* lock_file_path = get_session_id_lock_file_path(session_id); + auto const lock_file_path = get_session_id_lock_file_path(session_id); tr_error* error = nullptr; - auto lock_file = tr_sys_file_open(lock_file_path, TR_SYS_FILE_READ | TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0600, &error); + auto lock_file = tr_sys_file_open( + lock_file_path.c_str(), + TR_SYS_FILE_READ | TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, + 0600, + &error); if (lock_file != TR_BAD_SYS_FILE) { @@ -95,7 +98,6 @@ static tr_sys_file_t create_session_id_lock_file(char const* session_id) tr_error_free(error); } - tr_free(lock_file_path); return lock_file; } @@ -108,9 +110,8 @@ static void destroy_session_id_lock_file(tr_sys_file_t lock_file, char const* se if (session_id != nullptr) { - char* lock_file_path = get_session_id_lock_file_path(session_id); - tr_sys_path_remove(lock_file_path, nullptr); - tr_free(lock_file_path); + auto const lock_file_path = get_session_id_lock_file_path(session_id); + tr_sys_path_remove(lock_file_path.c_str(), nullptr); } } @@ -167,9 +168,9 @@ bool tr_session_id_is_local(char const* session_id) if (session_id != nullptr) { - char* lock_file_path = get_session_id_lock_file_path(session_id); + auto const lock_file_path = get_session_id_lock_file_path(session_id); tr_error* error = nullptr; - auto lock_file = tr_sys_file_open(lock_file_path, TR_SYS_FILE_READ, 0, &error); + auto lock_file = tr_sys_file_open(lock_file_path.c_str(), TR_SYS_FILE_READ, 0, &error); if (lock_file == TR_BAD_SYS_FILE) { @@ -199,8 +200,6 @@ bool tr_session_id_is_local(char const* session_id) tr_logAddError("Unable to open session lock file (%d): %s", error->code, error->message); tr_error_free(error); } - - tr_free(lock_file_path); } return ret; diff --git a/libtransmission/session.cc b/libtransmission/session.cc index 6e5844df8..15cc6f398 100644 --- a/libtransmission/session.cc +++ b/libtransmission/session.cc @@ -65,6 +65,8 @@ #include "version.h" #include "web.h" +using namespace std::literals; + #ifdef TR_LIGHTWEIGHT static auto constexpr DefaultCacheSizeMB = int{ 2 }; static auto constexpr DefaultPrefetchEnabled = bool{ false }; @@ -500,10 +502,10 @@ bool tr_sessionLoadSettings(tr_variant* dict, char const* configDir, char const* /* file settings override the defaults */ auto fileSettings = tr_variant{}; - char* const filename = tr_buildPath(configDir, "settings.json", nullptr); + auto const filename = tr_strvPath(configDir, "settings.json"sv); auto success = bool{}; tr_error* error = nullptr; - if (tr_variantFromFile(&fileSettings, TR_VARIANT_FMT_JSON, filename, &error)) + if (tr_variantFromFile(&fileSettings, TR_VARIANT_FMT_JSON, filename.c_str(), &error)) { tr_variantMergeDicts(dict, &fileSettings); tr_variantFree(&fileSettings); @@ -516,7 +518,6 @@ bool tr_sessionLoadSettings(tr_variant* dict, char const* configDir, char const* } /* cleanup */ - tr_free(filename); return success; } @@ -525,7 +526,7 @@ void tr_sessionSaveSettings(tr_session* session, char const* configDir, tr_varia TR_ASSERT(tr_variantIsDict(clientSettings)); tr_variant settings; - char* filename = tr_buildPath(configDir, "settings.json", nullptr); + auto const filename = tr_strvPath(configDir, "settings.json"sv); tr_variantInitDict(&settings, 0); @@ -533,7 +534,7 @@ void tr_sessionSaveSettings(tr_session* session, char const* configDir, tr_varia { tr_variant fileSettings; - if (tr_variantFromFile(&fileSettings, TR_VARIANT_FMT_JSON, filename, nullptr)) + if (tr_variantFromFile(&fileSettings, TR_VARIANT_FMT_JSON, filename.c_str(), nullptr)) { tr_variantMergeDicts(&settings, &fileSettings); tr_variantFree(&fileSettings); @@ -553,10 +554,9 @@ void tr_sessionSaveSettings(tr_session* session, char const* configDir, tr_varia } /* save the result */ - tr_variantToFile(&settings, TR_VARIANT_FMT_JSON, filename); + tr_variantToFile(&settings, TR_VARIANT_FMT_JSON, filename.c_str()); /* cleanup */ - tr_free(filename); tr_variantFree(&settings); } @@ -747,9 +747,8 @@ static void tr_sessionInitImpl(void* vdata) **/ { - char* filename = tr_buildPath(session->configDir, "blocklists", nullptr); - tr_sys_dir_create(filename, TR_SYS_DIR_CREATE_PARENTS, 0777, nullptr); - tr_free(filename); + auto const filename = tr_strvPath(session->configDir, "blocklists"sv); + tr_sys_dir_create(filename.c_str(), TR_SYS_DIR_CREATE_PARENTS, 0777, nullptr); loadBlocklists(session); } @@ -2374,83 +2373,76 @@ static void loadBlocklists(tr_session* session) auto const isEnabled = session->isBlocklistEnabled; /* walk the blocklist directory... */ - char* const dirname = tr_buildPath(session->configDir, "blocklists", nullptr); - auto const odir = tr_sys_dir_open(dirname, nullptr); + auto const dirname = tr_strvPath(session->configDir, "blocklists"sv); + auto const odir = tr_sys_dir_open(dirname.c_str(), nullptr); if (odir == TR_BAD_SYS_DIR) { - tr_free(dirname); return; } char const* name = nullptr; while ((name = tr_sys_dir_read_name(odir, nullptr)) != nullptr) { - char* load = nullptr; + auto load = std::string{}; if (name[0] == '.') /* ignore dotfiles */ { continue; } - char* const path = tr_buildPath(dirname, name, nullptr); + auto const path = tr_strvPath(dirname, name); - if (tr_stringEndsWith(path, ".bin")) + if (tr_strvEndsWith(path, ".bin"sv)) { - load = tr_strdup(path); + load = path; } else { tr_sys_path_info path_info; tr_sys_path_info binname_info; - char* const binname = tr_strdup_printf("%s" TR_PATH_DELIMITER_STR "%s.bin", dirname, name); + auto const binname = tr_strvJoin(dirname, TR_PATH_DELIMITER_STR, name, ".bin"sv); - if (!tr_sys_path_get_info(binname, 0, &binname_info, nullptr)) /* create it */ + if (!tr_sys_path_get_info(binname.c_str(), 0, &binname_info, nullptr)) /* create it */ { - tr_blocklistFile* b = tr_blocklistFileNew(binname, isEnabled); - int const n = tr_blocklistFileSetContent(b, path); + tr_blocklistFile* b = tr_blocklistFileNew(binname.c_str(), isEnabled); + int const n = tr_blocklistFileSetContent(b, path.c_str()); if (n > 0) { - load = tr_strdup(binname); + load = binname; } tr_blocklistFileFree(b); } else if ( - tr_sys_path_get_info(path, 0, &path_info, nullptr) && + tr_sys_path_get_info(path.c_str(), 0, &path_info, nullptr) && path_info.last_modified_at >= binname_info.last_modified_at) /* update it */ { - char* const old = tr_strdup_printf("%s.old", binname); - tr_sys_path_remove(old, nullptr); - tr_sys_path_rename(binname, old, nullptr); - auto* const b = tr_blocklistFileNew(binname, isEnabled); + auto const old = binname + ".old"; + tr_sys_path_remove(old.c_str(), nullptr); + tr_sys_path_rename(binname.c_str(), old.c_str(), nullptr); + auto* const b = tr_blocklistFileNew(binname.c_str(), isEnabled); - if (tr_blocklistFileSetContent(b, path) > 0) + if (tr_blocklistFileSetContent(b, path.c_str()) > 0) { - tr_sys_path_remove(old, nullptr); + tr_sys_path_remove(old.c_str(), nullptr); } else { - tr_sys_path_remove(binname, nullptr); - tr_sys_path_rename(old, binname, nullptr); + tr_sys_path_remove(binname.c_str(), nullptr); + tr_sys_path_rename(old.c_str(), binname.c_str(), nullptr); } tr_blocklistFileFree(b); - tr_free(old); } - - tr_free(binname); } - if (load != nullptr) + if (!std::empty(load)) { loadme.emplace(load); - tr_free(load); } - - tr_free(path); } session->blocklists.clear(); @@ -2462,7 +2454,6 @@ static void loadBlocklists(tr_session* session) /* cleanup */ tr_sys_dir_close(odir, nullptr); - tr_free(dirname); } static void closeBlocklists(tr_session* session) @@ -2533,10 +2524,9 @@ int tr_blocklistSetContent(tr_session* session, char const* contentFilename) [&name](auto const* blocklist) { return tr_stringEndsWith(tr_blocklistFileGetFilename(blocklist), name); }); if (it == std::end(src)) { - char* path = tr_buildPath(session->configDir, "blocklists", name, nullptr); - b = tr_blocklistFileNew(path, session->isBlocklistEnabled); + auto path = tr_strvJoin(session->configDir, "blocklists"sv, name); + b = tr_blocklistFileNew(path.c_str(), session->isBlocklistEnabled); src.push_back(b); - tr_free(path); } else { diff --git a/libtransmission/stats.cc b/libtransmission/stats.cc index db867750a..9ffa16d0a 100644 --- a/libtransmission/stats.cc +++ b/libtransmission/stats.cc @@ -11,7 +11,7 @@ #include "log.h" #include "platform.h" /* tr_sessionGetConfigDir() */ #include "stats.h" -#include "utils.h" /* tr_buildPath */ +#include "utils.h" #include "variant.h" /*** @@ -27,29 +27,27 @@ struct tr_stats_handle bool isDirty; }; -static char* getOldFilename(tr_session const* session) +static std::string getOldFilename(tr_session const* session) { - return tr_buildPath(tr_sessionGetConfigDir(session), "stats.benc", nullptr); + return tr_strvPath(tr_sessionGetConfigDir(session), "stats.benc"); } -static char* getFilename(tr_session const* session) +static std::string getFilename(tr_session const* session) { - return tr_buildPath(tr_sessionGetConfigDir(session), "stats.json", nullptr); + return tr_strvPath(tr_sessionGetConfigDir(session), "stats.json"); } static void loadCumulativeStats(tr_session const* session, tr_session_stats* setme) { auto top = tr_variant{}; - char* filename = getFilename(session); - bool loaded = tr_variantFromFile(&top, TR_VARIANT_FMT_JSON, filename, nullptr); - tr_free(filename); + auto filename = getFilename(session); + bool loaded = tr_variantFromFile(&top, TR_VARIANT_FMT_JSON, filename.c_str(), nullptr); if (!loaded) { filename = getOldFilename(session); - loaded = tr_variantFromFile(&top, TR_VARIANT_FMT_BENC, filename, nullptr); - tr_free(filename); + loaded = tr_variantFromFile(&top, TR_VARIANT_FMT_BENC, filename.c_str(), nullptr); } if (loaded) @@ -95,15 +93,14 @@ static void saveCumulativeStats(tr_session const* session, tr_session_stats cons tr_variantDictAddInt(&top, TR_KEY_session_count, s->sessionCount); tr_variantDictAddInt(&top, TR_KEY_uploaded_bytes, s->uploadedBytes); - char* const filename = getFilename(session); + auto const filename = getFilename(session); if (tr_logGetDeepEnabled()) { - tr_logAddDeep(__FILE__, __LINE__, nullptr, "Saving stats to \"%s\"", filename); + tr_logAddDeep(__FILE__, __LINE__, nullptr, "Saving stats to \"%s\"", filename.c_str()); } - tr_variantToFile(&top, TR_VARIANT_FMT_JSON, filename); + tr_variantToFile(&top, TR_VARIANT_FMT_JSON, filename.c_str()); - tr_free(filename); tr_variantFree(&top); } diff --git a/libtransmission/torrent.cc b/libtransmission/torrent.cc index 3a28f8ad0..cddfb6c23 100644 --- a/libtransmission/torrent.cc +++ b/libtransmission/torrent.cc @@ -2756,19 +2756,17 @@ static void removeEmptyFoldersAndJunkFiles(char const* folder) { if (strcmp(name, ".") != 0 && strcmp(name, "..") != 0) { - char* const filename = tr_buildPath(folder, name, nullptr); + auto const filename = tr_strvPath(folder, name); auto info = tr_sys_path_info{}; - if (tr_sys_path_get_info(filename, 0, &info, nullptr) && info.type == TR_SYS_PATH_IS_DIRECTORY) + if (tr_sys_path_get_info(filename.c_str(), 0, &info, nullptr) && info.type == TR_SYS_PATH_IS_DIRECTORY) { - removeEmptyFoldersAndJunkFiles(filename); + removeEmptyFoldersAndJunkFiles(filename.c_str()); } else if (isJunkFile(name)) { - tr_sys_path_remove(filename, nullptr); + tr_sys_path_remove(filename.c_str(), nullptr); } - - tr_free(filename); } } @@ -2807,38 +2805,30 @@ static void deleteLocalData(tr_torrent* tor, tr_fileFunc func) **** Move the local data to a new tmpdir ***/ - char* base = tr_strdup_printf("%s__XXXXXX", tr_torrentName(tor)); - char* tmpdir = tr_buildPath(top, base, nullptr); - tr_sys_dir_create_temp(tmpdir, nullptr); - tr_free(base); + auto tmpdir = tr_strvPath(top, TR_PATH_DELIMITER_STR, tr_torrentName(tor), "__XXXXXX"); + tr_sys_dir_create_temp(std::data(tmpdir), nullptr); for (tr_file_index_t f = 0; f < tor->info.fileCount; ++f) { /* try to find the file, looking in the partial and download dirs */ - char* filename = tr_buildPath(top, tor->info.files[f].name, nullptr); + auto filename = tr_strvPath(top, tor->info.files[f].name); - if (!tr_sys_path_exists(filename, nullptr)) + if (!tr_sys_path_exists(filename.c_str(), nullptr)) { - char* partial = tr_torrentBuildPartial(tor, f); - tr_free(filename); - filename = tr_buildPath(top, partial, nullptr); - tr_free(partial); + filename += ".part"sv; - if (!tr_sys_path_exists(filename, nullptr)) + if (!tr_sys_path_exists(filename.c_str(), nullptr)) { - tr_free(filename); - filename = nullptr; + filename.clear(); } } /* if we found the file, move it */ - if (filename != nullptr) + if (!std::empty(filename)) { - char* target = tr_buildPath(tmpdir, tor->info.files[f].name, nullptr); - tr_moveFile(filename, target, nullptr); + auto target = tr_strvPath(tmpdir, tor->info.files[f].name); + tr_moveFile(filename.c_str(), target.c_str(), nullptr); files.emplace_back(target); - tr_free(filename); - tr_free(target); } } @@ -2852,7 +2842,7 @@ static void deleteLocalData(tr_torrent* tor, tr_fileFunc func) ***/ /* try deleting the local data's top-level files & folders */ - tr_sys_dir_t const odir = tr_sys_dir_open(tmpdir, nullptr); + tr_sys_dir_t const odir = tr_sys_dir_open(tmpdir.c_str(), nullptr); if (odir != TR_BAD_SYS_DIR) { char const* name = nullptr; @@ -2860,9 +2850,8 @@ static void deleteLocalData(tr_torrent* tor, tr_fileFunc func) { if (strcmp(name, ".") != 0 && strcmp(name, "..") != 0) { - char* file = tr_buildPath(tmpdir, name, nullptr); - (*func)(file, nullptr); - tr_free(file); + auto const file = tr_strvPath(tmpdir, name); + (*func)(file.c_str(), nullptr); } } @@ -2874,7 +2863,7 @@ static void deleteLocalData(tr_torrent* tor, tr_fileFunc func) { char* walk = tr_strvDup(file); - while (tr_sys_path_exists(walk, nullptr) && !tr_sys_path_is_same(tmpdir, walk, nullptr)) + while (tr_sys_path_exists(walk, nullptr) && !tr_sys_path_is_same(tmpdir.c_str(), walk, nullptr)) { char* tmp = tr_sys_path_dirname(walk, nullptr); (*func)(walk, nullptr); @@ -2895,10 +2884,8 @@ static void deleteLocalData(tr_torrent* tor, tr_fileFunc func) for (tr_file_index_t f = 0; f < tor->info.fileCount; ++f) { /* get the directory that this file goes in... */ - char* const filename = tr_buildPath(top, tor->info.files[f].name, nullptr); - char* dir = tr_sys_path_dirname(filename, nullptr); - tr_free(filename); - + auto const filename = tr_strvPath(top, tor->info.files[f].name); + char* dir = tr_sys_path_dirname(filename.c_str(), nullptr); if (dir == nullptr) { continue; @@ -2933,8 +2920,7 @@ static void deleteLocalData(tr_torrent* tor, tr_fileFunc func) } /* cleanup */ - tr_sys_path_remove(tmpdir, nullptr); - tr_free(tmpdir); + tr_sys_path_remove(tmpdir.c_str(), nullptr); } static void tr_torrentDeleteLocalData(tr_torrent* tor, tr_fileFunc func) @@ -3000,27 +2986,30 @@ static void setLocation(void* vdata) char* sub = nullptr; if (tr_torrentFindFile2(tor, i, &oldbase, &sub, nullptr)) { - char* oldpath = tr_buildPath(oldbase, sub, nullptr); - char* newpath = tr_buildPath(location, sub, nullptr); + auto const oldpath = tr_strvPath(oldbase, sub); + auto const newpath = tr_strvPath(location, sub); - tr_logAddDebug("Found file #%d: %s", (int)i, oldpath); + tr_logAddDebug("Found file #%d: %s", (int)i, oldpath.c_str()); - if (do_move && !tr_sys_path_is_same(oldpath, newpath, nullptr)) + if (do_move && !tr_sys_path_is_same(oldpath.c_str(), newpath.c_str(), nullptr)) { tr_error* error = nullptr; - tr_logAddTorInfo(tor, "moving \"%s\" to \"%s\"", oldpath, newpath); + tr_logAddTorInfo(tor, "moving \"%s\" to \"%s\"", oldpath.c_str(), newpath.c_str()); - if (!tr_moveFile(oldpath, newpath, &error)) + if (!tr_moveFile(oldpath.c_str(), newpath.c_str(), &error)) { err = true; - tr_logAddTorErr(tor, "error moving \"%s\" to \"%s\": %s", oldpath, newpath, error->message); + tr_logAddTorErr( + tor, + "error moving \"%s\" to \"%s\": %s", + oldpath.c_str(), + newpath.c_str(), + error->message); tr_error_free(error); } } - tr_free(newpath); - tr_free(oldpath); tr_free(sub); } @@ -3148,18 +3137,15 @@ static void tr_torrentFileCompleted(tr_torrent* tor, tr_file_index_t fileIndex) { if (strcmp(sub, f->name) != 0) { - char* oldpath = tr_buildPath(base, sub, nullptr); - char* newpath = tr_buildPath(base, f->name, nullptr); + auto const oldpath = tr_strvPath(base, sub); + auto const newpath = tr_strvPath(base, f->name); tr_error* error = nullptr; - if (!tr_sys_path_rename(oldpath, newpath, &error)) + if (!tr_sys_path_rename(oldpath.c_str(), newpath.c_str(), &error)) { - tr_logAddTorErr(tor, "Error moving \"%s\" to \"%s\": %s", oldpath, newpath, error->message); + tr_logAddTorErr(tor, "Error moving \"%s\" to \"%s\": %s", oldpath.c_str(), newpath.c_str(), error->message); tr_error_free(error); } - - tr_free(newpath); - tr_free(oldpath); } tr_free(sub); @@ -3523,24 +3509,21 @@ static int renamePath(tr_torrent* tor, char const* oldpath, char const* newname) char const* const base = !tr_torrentIsSeed(tor) && tor->incompleteDir != nullptr ? tor->incompleteDir : tor->downloadDir; - char* src = tr_buildPath(base, oldpath, nullptr); + auto src = tr_strvPath(base, oldpath); - if (!tr_sys_path_exists(src, nullptr)) /* check for it as a partial */ + if (!tr_sys_path_exists(src.c_str(), nullptr)) /* check for it as a partial */ { - char* tmp = tr_strdup_printf("%s.part", src); - tr_free(src); - src = tmp; + src += ".part"sv; } - if (tr_sys_path_exists(src, nullptr)) + if (tr_sys_path_exists(src.c_str(), nullptr)) { - char* parent = tr_sys_path_dirname(src, nullptr); - char* const tgt = tr_str_has_suffix(src, ".part") ? - tr_strdup_printf("%s" TR_PATH_DELIMITER_STR "%s.part", parent, newname) : - tr_buildPath(parent, newname, nullptr); + char* const parent = tr_sys_path_dirname(src.c_str(), nullptr); + auto const tgt = tr_strvEndsWith(src, ".part"sv) ? tr_strvJoin(parent, TR_PATH_DELIMITER_STR, newname, ".part"sv) : + tr_strvPath(parent, newname); auto tmp = errno; - bool const tgt_exists = tr_sys_path_exists(tgt, nullptr); + bool const tgt_exists = tr_sys_path_exists(tgt.c_str(), nullptr); errno = tmp; if (!tgt_exists) @@ -3549,7 +3532,7 @@ static int renamePath(tr_torrent* tor, char const* oldpath, char const* newname) tmp = errno; - if (!tr_sys_path_rename(src, tgt, &error)) + if (!tr_sys_path_rename(src.c_str(), tgt.c_str(), &error)) { err = error->code; tr_error_free(error); @@ -3558,12 +3541,9 @@ static int renamePath(tr_torrent* tor, char const* oldpath, char const* newname) errno = tmp; } - tr_free(tgt); tr_free(parent); } - tr_free(src); - return err; } diff --git a/libtransmission/tr-dht.cc b/libtransmission/tr-dht.cc index 01d3f8ba2..1ce9ebe80 100644 --- a/libtransmission/tr-dht.cc +++ b/libtransmission/tr-dht.cc @@ -62,6 +62,8 @@ #include "utils.h" #include "variant.h" +using namespace std::literals; + static struct event* dht_timer = nullptr; static unsigned char myid[20]; static tr_session* session_ = nullptr; @@ -215,14 +217,9 @@ static void dht_bootstrap(void* closure) if (!bootstrap_done(cl->session, 0)) { - tr_sys_file_t f = TR_BAD_SYS_FILE; + auto const bootstrap_file = tr_strvPath(cl->session->configDir, "dht.bootstrap"); - char* const bootstrap_file = tr_buildPath(cl->session->configDir, "dht.bootstrap", nullptr); - - if (bootstrap_file != nullptr) - { - f = tr_sys_file_open(bootstrap_file, TR_SYS_FILE_READ, 0, nullptr); - } + tr_sys_file_t const f = tr_sys_file_open(bootstrap_file.c_str(), TR_SYS_FILE_READ, 0, nullptr); if (f != TR_BAD_SYS_FILE) { @@ -262,8 +259,6 @@ static void dht_bootstrap(void* closure) tr_sys_file_close(f, nullptr); } - - tr_free(bootstrap_file); } if (!bootstrap_done(cl->session, 0)) @@ -318,10 +313,9 @@ int tr_dhtInit(tr_session* ss) dht_debug = stderr; } - char* const dat_file = tr_buildPath(ss->configDir, "dht.dat", nullptr); + auto const dat_file = tr_strvPath(ss->configDir, "dht.dat"sv); auto benc = tr_variant{}; - int rc = tr_variantFromFile(&benc, TR_VARIANT_FMT_BENC, dat_file, nullptr) ? 0 : -1; - tr_free(dat_file); + int rc = tr_variantFromFile(&benc, TR_VARIANT_FMT_BENC, dat_file.c_str(), nullptr) ? 0 : -1; bool have_id = false; uint8_t* nodes = nullptr; @@ -472,10 +466,9 @@ void tr_dhtUninit(tr_session* ss) tr_variantDictAddRaw(&benc, TR_KEY_nodes6, compact6, out6 - compact6); } - char* const dat_file = tr_buildPath(ss->configDir, "dht.dat", nullptr); - tr_variantToFile(&benc, TR_VARIANT_FMT_BENC, dat_file); + auto const dat_file = tr_strvPath(ss->configDir, "dht.dat"); + tr_variantToFile(&benc, TR_VARIANT_FMT_BENC, dat_file.c_str()); tr_variantFree(&benc); - tr_free(dat_file); } dht_uninit(); diff --git a/libtransmission/tr-macros.h b/libtransmission/tr-macros.h index 6fa8ab51d..796fc8728 100644 --- a/libtransmission/tr-macros.h +++ b/libtransmission/tr-macros.h @@ -110,6 +110,9 @@ **** ***/ +#define TR_PATH_DELIMITER '/' +#define TR_PATH_DELIMITER_STR "/" + /* Only use this macro to suppress false-positive alignment warnings */ #define TR_DISCARD_ALIGN(ptr, type) ((type)(void*)(ptr)) diff --git a/libtransmission/utils.h b/libtransmission/utils.h index 8f9636bf4..5b4d56ffa 100644 --- a/libtransmission/utils.h +++ b/libtransmission/utils.h @@ -257,6 +257,40 @@ char const* tr_strcasestr(char const* haystack, char const* needle); **** std::string_view utils ***/ +template && ...), bool> = true> +std::string tr_strvPath(T... args) +{ + auto setme = std::string{}; + auto const n_args = sizeof...(args); + auto const n = n_args + (std::size(std::string_view{ args }) + ...); + + if (setme.capacity() < n) + { + setme.reserve(n); + } + auto const foo = [](std::string& setme, std::string_view a) + { + setme += a; + setme += TR_PATH_DELIMITER; + }; + (foo(setme, args), ...); + setme.resize(setme.size() - 1); + return setme; +} + +template && ...), bool> = true> +std::string tr_strvJoin(T... args) +{ + auto setme = std::string{}; + auto const n = (std::size(std::string_view{ args }) + ...); + if (setme.capacity() < n) + { + setme.reserve(n); + } + ((setme += args), ...); + return setme; +} + template constexpr bool tr_strvContains(std::string_view sv, T key) // c++23 { diff --git a/libtransmission/variant.cc b/libtransmission/variant.cc index 331dff082..7f79f915c 100644 --- a/libtransmission/variant.cc +++ b/libtransmission/variant.cc @@ -41,7 +41,7 @@ #include "file.h" #include "log.h" #include "tr-assert.h" -#include "utils.h" /* tr_new(), tr_free() */ +#include "utils.h" #include "variant.h" #include "variant-common.h" diff --git a/libtransmission/watchdir.cc b/libtransmission/watchdir.cc index 9fefb1cca..5a2bacebc 100644 --- a/libtransmission/watchdir.cc +++ b/libtransmission/watchdir.cc @@ -54,23 +54,22 @@ struct tr_watchdir static bool is_regular_file(char const* dir, char const* name) { - char* const path = tr_buildPath(dir, name, nullptr); + auto const path = tr_strvPath(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); + bool const ret = tr_sys_path_get_info(path.c_str(), 0, &path_info, &error) && (path_info.type == TR_SYS_PATH_IS_FILE); if (error != nullptr) { if (!TR_ERROR_IS_ENOENT(error->code)) { - log_error("Failed to get type of \"%s\" (%d): %s", path, error->code, error->message); + log_error("Failed to get type of \"%s\" (%d): %s", path.c_str(), error->code, error->message); } tr_error_free(error); } - tr_free(path); return ret; } diff --git a/libtransmission/web.cc b/libtransmission/web.cc index 0f26c1ac3..0ff418d57 100644 --- a/libtransmission/web.cc +++ b/libtransmission/web.cc @@ -433,12 +433,11 @@ static void tr_webThreadFunc(void* vsession) tr_logAddNamedInfo("web", "NB: invalid certs will show up as 'Could not connect to tracker' like many other errors"); } - char* const str = tr_buildPath(session->configDir, "cookies.txt", nullptr); - if (tr_sys_path_exists(str, nullptr)) + auto const str = tr_strvPath(session->configDir, "cookies.txt"); + if (tr_sys_path_exists(str.c_str(), nullptr)) { - web->cookie_filename = tr_strdup(str); + web->cookie_filename = tr_strvDup(str); } - tr_free(str); auto* const multi = curl_multi_init(); session->web = web; diff --git a/tests/libtransmission/blocklist-test.cc b/tests/libtransmission/blocklist-test.cc index 7b2c2707d..09dcc1852 100644 --- a/tests/libtransmission/blocklist-test.cc +++ b/tests/libtransmission/blocklist-test.cc @@ -75,7 +75,7 @@ TEST_F(BlocklistTest, parsing) EXPECT_EQ(0, tr_blocklistGetRuleCount(session_)); // init the blocklist - auto const path = makeString(tr_buildPath(tr_sessionGetConfigDir(session_), "blocklists", "level1", nullptr)); + auto const path = tr_strvPath(tr_sessionGetConfigDir(session_), "blocklists", "level1"); createFileWithContents(path, Contents1); tr_sessionReloadBlocklists(session_); EXPECT_TRUE(tr_blocklistExists(session_)); @@ -111,7 +111,7 @@ TEST_F(BlocklistTest, parsing) TEST_F(BlocklistTest, updating) { // init the session - char* path = tr_buildPath(tr_sessionGetConfigDir(session_), "blocklists", "level1", nullptr); + auto const path = tr_strvPath(tr_sessionGetConfigDir(session_), "blocklists", "level1"); // no blocklist to start with... EXPECT_EQ(0, tr_blocklistGetRuleCount(session_)); @@ -137,7 +137,6 @@ TEST_F(BlocklistTest, updating) EXPECT_EQ(5, tr_blocklistGetRuleCount(session_)); // cleanup - tr_free(path); } } // namespace test diff --git a/tests/libtransmission/copy-test.cc b/tests/libtransmission/copy-test.cc index 4cafb5158..51121fa93 100644 --- a/tests/libtransmission/copy-test.cc +++ b/tests/libtransmission/copy-test.cc @@ -25,7 +25,7 @@ class CopyTest : public SandboxedTest protected: void testImpl(char const* filename1, char const* filename2, size_t const file_length) { - auto const path1 = tr_buildPath(sandboxDir().data(), filename1, nullptr); + auto const path1 = tr_strvPath(sandboxDir(), filename1); /* Create a file. */ char* file_content = static_cast(tr_malloc(file_length)); @@ -33,22 +33,19 @@ protected: createFileWithContents(path1, file_content, file_length); tr_free(file_content); - auto const path2 = tr_buildPath(sandboxDir().data(), filename2, nullptr); + auto const path2 = tr_strvPath(sandboxDir(), filename2); tr_error* err = nullptr; /* Copy it. */ - EXPECT_TRUE(tr_sys_path_copy(path1, path2, &err)); + EXPECT_TRUE(tr_sys_path_copy(path1.c_str(), path2.c_str(), &err)); EXPECT_EQ(nullptr, err); tr_error_clear(&err); - EXPECT_TRUE(filesAreIdentical(path1, path2)); + EXPECT_TRUE(filesAreIdentical(path1.c_str(), path2.c_str())); /* Dispose of those files that we created. */ - tr_sys_path_remove(path1, nullptr); - tr_free(path1); - - tr_sys_path_remove(path2, nullptr); - tr_free(path2); + tr_sys_path_remove(path1.c_str(), nullptr); + tr_sys_path_remove(path2.c_str(), nullptr); } private: diff --git a/tests/libtransmission/file-test.cc b/tests/libtransmission/file-test.cc index 9fdc0245c..73ab44299 100644 --- a/tests/libtransmission/file-test.cc +++ b/tests/libtransmission/file-test.cc @@ -35,6 +35,8 @@ #define NATIVE_PATH_SEP "\\" #endif +using namespace std::literals; + namespace libtransmission { @@ -46,8 +48,8 @@ class FileTest : public SessionTest protected: auto createTestDir(std::string const& child_name) { - auto test_dir = makeString(tr_buildPath(tr_sessionGetConfigDir(session_), child_name.c_str(), nullptr)); - tr_sys_dir_create(test_dir.data(), 0, 0777, nullptr); + auto test_dir = tr_strvPath(tr_sessionGetConfigDir(session_), child_name); + tr_sys_dir_create(std::data(test_dir), 0, 0777, nullptr); return test_dir; } @@ -225,12 +227,12 @@ TEST_F(FileTest, getInfo) auto const test_dir = createTestDir(currentTestName()); tr_sys_path_info info; - char* path1 = tr_buildPath(test_dir.data(), "a", nullptr); - char* path2 = tr_buildPath(test_dir.data(), "b", nullptr); + auto const path1 = tr_strvPath(test_dir, "a"sv); + auto const path2 = tr_strvPath(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)); + EXPECT_FALSE(tr_sys_path_get_info(path1.c_str(), 0, &info, &err)); EXPECT_NE(nullptr, err); tr_error_clear(&err); @@ -239,7 +241,7 @@ TEST_F(FileTest, getInfo) // Good file info clearPathInfo(&info); - EXPECT_TRUE(tr_sys_path_get_info(path1, 0, &info, &err)); + EXPECT_TRUE(tr_sys_path_get_info(path1.c_str(), 0, &info, &err)); EXPECT_EQ(nullptr, err); EXPECT_EQ(TR_SYS_PATH_IS_FILE, info.type); EXPECT_EQ(4, info.size); @@ -247,7 +249,7 @@ TEST_F(FileTest, getInfo) 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, nullptr); + auto fd = tr_sys_file_open(path1.c_str(), TR_SYS_FILE_READ, 0, nullptr); clearPathInfo(&info); EXPECT_TRUE(tr_sys_file_get_info(fd, &info, &err)); EXPECT_EQ(nullptr, err); @@ -257,24 +259,24 @@ TEST_F(FileTest, getInfo) EXPECT_LE(info.last_modified_at, time(nullptr) + 1); tr_sys_file_close(fd, nullptr); - tr_sys_path_remove(path1, nullptr); + tr_sys_path_remove(path1.c_str(), nullptr); // Good directory info t = time(nullptr); - tr_sys_dir_create(path1, 0, 0777, nullptr); + tr_sys_dir_create(path1.c_str(), 0, 0777, nullptr); clearPathInfo(&info); - EXPECT_TRUE(tr_sys_path_get_info(path1, 0, &info, &err)); + EXPECT_TRUE(tr_sys_path_get_info(path1.c_str(), 0, &info, &err)); EXPECT_EQ(nullptr, 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); - tr_sys_path_remove(path1, nullptr); + tr_sys_path_remove(path1.c_str(), nullptr); - if (createSymlink(path1, path2, false)) + if (createSymlink(path1.c_str(), path2.c_str(), false)) { // Can't get info of non-existent file/directory - EXPECT_FALSE(tr_sys_path_get_info(path1, 0, &info, &err)); + EXPECT_FALSE(tr_sys_path_get_info(path1.c_str(), 0, &info, &err)); EXPECT_NE(nullptr, err); tr_error_clear(&err); @@ -283,7 +285,7 @@ TEST_F(FileTest, getInfo) // Good file info clearPathInfo(&info); - EXPECT_TRUE(tr_sys_path_get_info(path1, 0, &info, &err)); + EXPECT_TRUE(tr_sys_path_get_info(path1.c_str(), 0, &info, &err)); EXPECT_EQ(nullptr, err); EXPECT_EQ(TR_SYS_PATH_IS_FILE, info.type); EXPECT_EQ(4, info.size); @@ -291,7 +293,7 @@ TEST_F(FileTest, getInfo) 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, nullptr); + fd = tr_sys_file_open(path1.c_str(), TR_SYS_FILE_READ, 0, nullptr); clearPathInfo(&info); EXPECT_TRUE(tr_sys_file_get_info(fd, &info, &err)); EXPECT_EQ(nullptr, err); @@ -301,89 +303,83 @@ TEST_F(FileTest, getInfo) EXPECT_LE(info.last_modified_at, time(nullptr) + 1); tr_sys_file_close(fd, nullptr); - tr_sys_path_remove(path2, nullptr); - tr_sys_path_remove(path1, nullptr); + tr_sys_path_remove(path2.c_str(), nullptr); + tr_sys_path_remove(path1.c_str(), nullptr); // Good directory info t = time(nullptr); - tr_sys_dir_create(path2, 0, 0777, nullptr); - EXPECT_TRUE(createSymlink(path1, path2, true)); /* Win32: directory and file symlinks differ :( */ + tr_sys_dir_create(path2.c_str(), 0, 0777, nullptr); + EXPECT_TRUE(createSymlink(path1.c_str(), path2.c_str(), true)); /* Win32: directory and file symlinks differ :( */ clearPathInfo(&info); - EXPECT_TRUE(tr_sys_path_get_info(path1, 0, &info, &err)); + EXPECT_TRUE(tr_sys_path_get_info(path1.c_str(), 0, &info, &err)); EXPECT_EQ(nullptr, 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); - tr_sys_path_remove(path2, nullptr); - tr_sys_path_remove(path1, nullptr); + tr_sys_path_remove(path2.c_str(), nullptr); + tr_sys_path_remove(path1.c_str(), nullptr); } else { fprintf(stderr, "WARNING: [%s] unable to run symlink tests\n", __FUNCTION__); } - - tr_free(path2); - tr_free(path1); } TEST_F(FileTest, pathExists) { auto const test_dir = createTestDir(currentTestName()); - auto* path1 = tr_buildPath(test_dir.data(), "a", nullptr); - auto* path2 = tr_buildPath(test_dir.data(), "b", nullptr); + auto const path1 = tr_strvPath(test_dir.data(), "a"sv); + auto const path2 = tr_strvPath(test_dir.data(), "b"sv); // Non-existent file does not exist tr_error* err = nullptr; - EXPECT_FALSE(tr_sys_path_exists(path1, &err)); + EXPECT_FALSE(tr_sys_path_exists(path1.c_str(), &err)); EXPECT_EQ(nullptr, err); // Create file and see that it exists createFileWithContents(path1, "test"); - EXPECT_TRUE(tr_sys_path_exists(path1, &err)); + EXPECT_TRUE(tr_sys_path_exists(path1.c_str(), &err)); EXPECT_EQ(nullptr, err); - tr_sys_path_remove(path1, nullptr); + tr_sys_path_remove(path1.c_str(), nullptr); // Create directory and see that it exists - tr_sys_dir_create(path1, 0, 0777, nullptr); - EXPECT_TRUE(tr_sys_path_exists(path1, &err)); + tr_sys_dir_create(path1.c_str(), 0, 0777, nullptr); + EXPECT_TRUE(tr_sys_path_exists(path1.c_str(), &err)); EXPECT_EQ(nullptr, err); - tr_sys_path_remove(path1, nullptr); + tr_sys_path_remove(path1.c_str(), nullptr); - if (createSymlink(path1, path2, false)) + if (createSymlink(path1.c_str(), path2.c_str(), false)) { // Non-existent file does not exist (via symlink) - EXPECT_FALSE(tr_sys_path_exists(path1, &err)); + EXPECT_FALSE(tr_sys_path_exists(path1.c_str(), &err)); EXPECT_EQ(nullptr, err); // Create file and see that it exists (via symlink) createFileWithContents(path2, "test"); - EXPECT_TRUE(tr_sys_path_exists(path1, &err)); + EXPECT_TRUE(tr_sys_path_exists(path1.c_str(), &err)); EXPECT_EQ(nullptr, err); - tr_sys_path_remove(path2, nullptr); - tr_sys_path_remove(path1, nullptr); + tr_sys_path_remove(path2.c_str(), nullptr); + tr_sys_path_remove(path1.c_str(), nullptr); /* Create directory and see that it exists (via symlink) */ - tr_sys_dir_create(path2, 0, 0777, nullptr); - EXPECT_TRUE(createSymlink(path1, path2, true)); /* Win32: directory and file symlinks differ :( */ - EXPECT_TRUE(tr_sys_path_exists(path1, &err)); + tr_sys_dir_create(path2.c_str(), 0, 0777, nullptr); + EXPECT_TRUE(createSymlink(path1.c_str(), path2.c_str(), true)); /* Win32: directory and file symlinks differ :( */ + EXPECT_TRUE(tr_sys_path_exists(path1.c_str(), &err)); EXPECT_EQ(nullptr, err); - tr_sys_path_remove(path2, nullptr); - tr_sys_path_remove(path1, nullptr); + tr_sys_path_remove(path2.c_str(), nullptr); + tr_sys_path_remove(path1.c_str(), nullptr); } else { fprintf(stderr, "WARNING: [%s] unable to run symlink tests\n", __FUNCTION__); } - - tr_free(path2); - tr_free(path1); } TEST_F(FileTest, pathIsRelative) @@ -436,194 +432,193 @@ TEST_F(FileTest, pathIsSame) { auto const test_dir = createTestDir(currentTestName()); - auto* path1 = tr_buildPath(test_dir.data(), "a", nullptr); - auto* path2 = tr_buildPath(test_dir.data(), "b", nullptr); - auto* path3 = tr_buildPath(path2, "c", nullptr); + auto const path1 = tr_strvPath(test_dir, "a"sv); + auto const path2 = tr_strvPath(test_dir, "b"sv); + auto path3 = tr_strvPath(path2, "c"sv); /* Two non-existent files are not the same */ tr_error* err = nullptr; - EXPECT_FALSE(tr_sys_path_is_same(path1, path1, &err)); + EXPECT_FALSE(tr_sys_path_is_same(path1.c_str(), path1.c_str(), &err)); EXPECT_EQ(nullptr, err); - EXPECT_FALSE(tr_sys_path_is_same(path1, path2, &err)); + EXPECT_FALSE(tr_sys_path_is_same(path1.c_str(), path2.c_str(), &err)); EXPECT_EQ(nullptr, err); /* Two same files are the same */ createFileWithContents(path1, "test"); - EXPECT_TRUE(tr_sys_path_is_same(path1, path1, &err)); + EXPECT_TRUE(tr_sys_path_is_same(path1.c_str(), path1.c_str(), &err)); EXPECT_EQ(nullptr, err); /* Existent and non-existent files are not the same */ - EXPECT_FALSE(tr_sys_path_is_same(path1, path2, &err)); + EXPECT_FALSE(tr_sys_path_is_same(path1.c_str(), path2.c_str(), &err)); EXPECT_EQ(nullptr, err); - EXPECT_FALSE(tr_sys_path_is_same(path2, path1, &err)); + EXPECT_FALSE(tr_sys_path_is_same(path2.c_str(), path1.c_str(), &err)); EXPECT_EQ(nullptr, err); /* Two separate files (even with same content) are not the same */ createFileWithContents(path2, "test"); - EXPECT_FALSE(tr_sys_path_is_same(path1, path2, &err)); + EXPECT_FALSE(tr_sys_path_is_same(path1.c_str(), path2.c_str(), &err)); EXPECT_EQ(nullptr, err); - tr_sys_path_remove(path1, nullptr); + tr_sys_path_remove(path1.c_str(), nullptr); /* Two same directories are the same */ - tr_sys_dir_create(path1, 0, 0777, nullptr); - EXPECT_TRUE(tr_sys_path_is_same(path1, path1, &err)); + tr_sys_dir_create(path1.c_str(), 0, 0777, nullptr); + EXPECT_TRUE(tr_sys_path_is_same(path1.c_str(), path1.c_str(), &err)); EXPECT_EQ(nullptr, err); /* File and directory are not the same */ - EXPECT_FALSE(tr_sys_path_is_same(path1, path2, &err)); + EXPECT_FALSE(tr_sys_path_is_same(path1.c_str(), path2.c_str(), &err)); EXPECT_EQ(nullptr, err); - EXPECT_FALSE(tr_sys_path_is_same(path2, path1, &err)); + EXPECT_FALSE(tr_sys_path_is_same(path2.c_str(), path1.c_str(), &err)); EXPECT_EQ(nullptr, err); - tr_sys_path_remove(path2, nullptr); + tr_sys_path_remove(path2.c_str(), nullptr); /* Two separate directories are not the same */ - tr_sys_dir_create(path2, 0, 0777, nullptr); - EXPECT_FALSE(tr_sys_path_is_same(path1, path2, &err)); + tr_sys_dir_create(path2.c_str(), 0, 0777, nullptr); + EXPECT_FALSE(tr_sys_path_is_same(path1.c_str(), path2.c_str(), &err)); EXPECT_EQ(nullptr, err); - tr_sys_path_remove(path1, nullptr); - tr_sys_path_remove(path2, nullptr); + tr_sys_path_remove(path1.c_str(), nullptr); + tr_sys_path_remove(path2.c_str(), nullptr); - if (createSymlink(path1, ".", true)) + if (createSymlink(path1.c_str(), ".", true)) { /* Directory and symlink pointing to it are the same */ - EXPECT_TRUE(tr_sys_path_is_same(path1, test_dir.data(), &err)); + EXPECT_TRUE(tr_sys_path_is_same(path1.c_str(), test_dir.data(), &err)); EXPECT_EQ(nullptr, err); - EXPECT_TRUE(tr_sys_path_is_same(test_dir.data(), path1, &err)); + EXPECT_TRUE(tr_sys_path_is_same(test_dir.data(), path1.c_str(), &err)); EXPECT_EQ(nullptr, err); /* Non-existent file and symlink are not the same */ - EXPECT_FALSE(tr_sys_path_is_same(path1, path2, &err)); + EXPECT_FALSE(tr_sys_path_is_same(path1.c_str(), path2.c_str(), &err)); EXPECT_EQ(nullptr, err); - EXPECT_FALSE(tr_sys_path_is_same(path2, path1, &err)); + EXPECT_FALSE(tr_sys_path_is_same(path2.c_str(), path1.c_str(), &err)); EXPECT_EQ(nullptr, err); /* Symlinks pointing to different directories are not the same */ - createSymlink(path2, "..", true); - EXPECT_FALSE(tr_sys_path_is_same(path1, path2, &err)); + createSymlink(path2.c_str(), "..", true); + EXPECT_FALSE(tr_sys_path_is_same(path1.c_str(), path2.c_str(), &err)); EXPECT_EQ(nullptr, err); - EXPECT_FALSE(tr_sys_path_is_same(path2, path1, &err)); + EXPECT_FALSE(tr_sys_path_is_same(path2.c_str(), path1.c_str(), &err)); EXPECT_EQ(nullptr, err); - tr_sys_path_remove(path2, nullptr); + tr_sys_path_remove(path2.c_str(), nullptr); /* Symlinks pointing to same directory are the same */ - createSymlink(path2, ".", true); - EXPECT_TRUE(tr_sys_path_is_same(path1, path2, &err)); + createSymlink(path2.c_str(), ".", true); + EXPECT_TRUE(tr_sys_path_is_same(path1.c_str(), path2.c_str(), &err)); EXPECT_EQ(nullptr, err); - tr_sys_path_remove(path2, nullptr); + tr_sys_path_remove(path2.c_str(), nullptr); /* Directory and symlink pointing to another directory are not the same */ - tr_sys_dir_create(path2, 0, 0777, nullptr); - EXPECT_FALSE(tr_sys_path_is_same(path1, path2, &err)); + tr_sys_dir_create(path2.c_str(), 0, 0777, nullptr); + EXPECT_FALSE(tr_sys_path_is_same(path1.c_str(), path2.c_str(), &err)); EXPECT_EQ(nullptr, err); - EXPECT_FALSE(tr_sys_path_is_same(path2, path1, &err)); + EXPECT_FALSE(tr_sys_path_is_same(path2.c_str(), path1.c_str(), &err)); EXPECT_EQ(nullptr, err); /* Symlinks pointing to same directory are the same */ - createSymlink(path3, "..", true); - EXPECT_TRUE(tr_sys_path_is_same(path1, path3, &err)); + createSymlink(path3.c_str(), "..", true); + EXPECT_TRUE(tr_sys_path_is_same(path1.c_str(), path3.c_str(), &err)); EXPECT_EQ(nullptr, err); - tr_sys_path_remove(path1, nullptr); + tr_sys_path_remove(path1.c_str(), nullptr); /* File and symlink pointing to directory are not the same */ createFileWithContents(path1, "test"); - EXPECT_FALSE(tr_sys_path_is_same(path1, path3, &err)); + EXPECT_FALSE(tr_sys_path_is_same(path1.c_str(), path3.c_str(), &err)); EXPECT_EQ(nullptr, err); - EXPECT_FALSE(tr_sys_path_is_same(path3, path1, &err)); + EXPECT_FALSE(tr_sys_path_is_same(path3.c_str(), path1.c_str(), &err)); EXPECT_EQ(nullptr, err); - tr_sys_path_remove(path3, nullptr); + tr_sys_path_remove(path3.c_str(), nullptr); /* File and symlink pointing to same file are the same */ - createSymlink(path3, path1, false); - EXPECT_TRUE(tr_sys_path_is_same(path1, path3, &err)); + createSymlink(path3.c_str(), path1.c_str(), false); + EXPECT_TRUE(tr_sys_path_is_same(path1.c_str(), path3.c_str(), &err)); EXPECT_EQ(nullptr, err); - EXPECT_TRUE(tr_sys_path_is_same(path3, path1, &err)); + EXPECT_TRUE(tr_sys_path_is_same(path3.c_str(), path1.c_str(), &err)); EXPECT_EQ(nullptr, err); /* Symlinks pointing to non-existent files are not the same */ - tr_sys_path_remove(path1, nullptr); - createSymlink(path1, "missing", false); - tr_sys_path_remove(path3, nullptr); - createSymlink(path3, "missing", false); - EXPECT_FALSE(tr_sys_path_is_same(path1, path3, &err)); + tr_sys_path_remove(path1.c_str(), nullptr); + createSymlink(path1.c_str(), "missing", false); + tr_sys_path_remove(path3.c_str(), nullptr); + createSymlink(path3.c_str(), "missing", false); + EXPECT_FALSE(tr_sys_path_is_same(path1.c_str(), path3.c_str(), &err)); EXPECT_EQ(nullptr, err); - EXPECT_FALSE(tr_sys_path_is_same(path3, path1, &err)); + EXPECT_FALSE(tr_sys_path_is_same(path3.c_str(), path1.c_str(), &err)); EXPECT_EQ(nullptr, err); - tr_sys_path_remove(path3, nullptr); + tr_sys_path_remove(path3.c_str(), nullptr); /* Symlinks pointing to same non-existent file are not the same */ - createSymlink(path3, ".." NATIVE_PATH_SEP "missing", false); - EXPECT_FALSE(tr_sys_path_is_same(path1, path3, &err)); + createSymlink(path3.c_str(), ".." NATIVE_PATH_SEP "missing", false); + EXPECT_FALSE(tr_sys_path_is_same(path1.c_str(), path3.c_str(), &err)); EXPECT_EQ(nullptr, err); - EXPECT_FALSE(tr_sys_path_is_same(path3, path1, &err)); + EXPECT_FALSE(tr_sys_path_is_same(path3.c_str(), path1.c_str(), &err)); EXPECT_EQ(nullptr, err); /* Non-existent file and symlink pointing to non-existent file are not the same */ - tr_sys_path_remove(path3, nullptr); - EXPECT_FALSE(tr_sys_path_is_same(path1, path3, &err)); + tr_sys_path_remove(path3.c_str(), nullptr); + EXPECT_FALSE(tr_sys_path_is_same(path1.c_str(), path3.c_str(), &err)); EXPECT_EQ(nullptr, err); - EXPECT_FALSE(tr_sys_path_is_same(path3, path1, &err)); + EXPECT_FALSE(tr_sys_path_is_same(path3.c_str(), path1.c_str(), &err)); EXPECT_EQ(nullptr, err); - tr_sys_path_remove(path2, nullptr); - tr_sys_path_remove(path1, nullptr); + tr_sys_path_remove(path2.c_str(), nullptr); + tr_sys_path_remove(path1.c_str(), nullptr); } else { fprintf(stderr, "WARNING: [%s] unable to run symlink tests\n", __FUNCTION__); } - tr_free(path3); - path3 = tr_buildPath(test_dir.data(), "c", nullptr); + path3 = tr_strvPath(test_dir, "c"sv); createFileWithContents(path1, "test"); - if (createHardlink(path2, path1)) + if (createHardlink(path2.c_str(), path1.c_str())) { /* File and hardlink to it are the same */ - EXPECT_TRUE(tr_sys_path_is_same(path1, path2, &err)); + EXPECT_TRUE(tr_sys_path_is_same(path1.c_str(), path2.c_str(), &err)); EXPECT_EQ(nullptr, err); /* Two hardlinks to the same file are the same */ - createHardlink(path3, path2); - EXPECT_TRUE(tr_sys_path_is_same(path2, path3, &err)); + createHardlink(path3.c_str(), path2.c_str()); + EXPECT_TRUE(tr_sys_path_is_same(path2.c_str(), path3.c_str(), &err)); EXPECT_EQ(nullptr, err); - EXPECT_TRUE(tr_sys_path_is_same(path1, path3, &err)); + EXPECT_TRUE(tr_sys_path_is_same(path1.c_str(), path3.c_str(), &err)); EXPECT_EQ(nullptr, err); - tr_sys_path_remove(path2, nullptr); + tr_sys_path_remove(path2.c_str(), nullptr); - EXPECT_TRUE(tr_sys_path_is_same(path1, path3, &err)); + EXPECT_TRUE(tr_sys_path_is_same(path1.c_str(), path3.c_str(), &err)); EXPECT_EQ(nullptr, err); - tr_sys_path_remove(path3, nullptr); + tr_sys_path_remove(path3.c_str(), nullptr); /* File and hardlink to another file are not the same */ createFileWithContents(path3, "test"); - createHardlink(path2, path3); - EXPECT_FALSE(tr_sys_path_is_same(path1, path2, &err)); + createHardlink(path2.c_str(), path3.c_str()); + EXPECT_FALSE(tr_sys_path_is_same(path1.c_str(), path2.c_str(), &err)); EXPECT_EQ(nullptr, err); - EXPECT_FALSE(tr_sys_path_is_same(path2, path1, &err)); + EXPECT_FALSE(tr_sys_path_is_same(path2.c_str(), path1.c_str(), &err)); EXPECT_EQ(nullptr, err); - tr_sys_path_remove(path3, nullptr); - tr_sys_path_remove(path2, nullptr); + tr_sys_path_remove(path3.c_str(), nullptr); + tr_sys_path_remove(path2.c_str(), nullptr); } else { fprintf(stderr, "WARNING: [%s] unable to run hardlink tests\n", __FUNCTION__); } - if (createSymlink(path2, path1, false) && createHardlink(path3, path1)) + if (createSymlink(path2.c_str(), path1.c_str(), false) && createHardlink(path3.c_str(), path1.c_str())) { - EXPECT_TRUE(tr_sys_path_is_same(path2, path3, &err)); + EXPECT_TRUE(tr_sys_path_is_same(path2.c_str(), path3.c_str(), &err)); EXPECT_EQ(nullptr, err); } else @@ -631,13 +626,9 @@ TEST_F(FileTest, pathIsSame) fprintf(stderr, "WARNING: [%s] unable to run combined symlink and hardlink tests\n", __FUNCTION__); } - tr_sys_path_remove(path3, nullptr); - tr_sys_path_remove(path2, nullptr); - tr_sys_path_remove(path1, nullptr); - - tr_free(path3); - tr_free(path2); - tr_free(path1); + tr_sys_path_remove(path3.c_str(), nullptr); + tr_sys_path_remove(path2.c_str(), nullptr); + tr_sys_path_remove(path1.c_str(), nullptr); } TEST_F(FileTest, pathResolve) @@ -645,23 +636,23 @@ TEST_F(FileTest, pathResolve) auto const test_dir = createTestDir(currentTestName()); tr_error* err = nullptr; - auto* path1 = tr_buildPath(test_dir.data(), "a", nullptr); - auto* path2 = tr_buildPath(test_dir.data(), "b", nullptr); + auto const path1 = tr_strvPath(test_dir, "a"sv); + auto const path2 = tr_strvPath(test_dir, "b"sv); createFileWithContents(path1, "test"); - if (createSymlink(path2, path1, false)) + if (createSymlink(path2.c_str(), path1.c_str(), false)) { - auto tmp = makeString(tr_sys_path_resolve(path2, &err)); + auto tmp = makeString(tr_sys_path_resolve(path2.c_str(), &err)); EXPECT_EQ(nullptr, err); EXPECT_TRUE(pathContainsNoSymlinks(tmp.c_str())); - tr_sys_path_remove(path2, nullptr); - tr_sys_path_remove(path1, nullptr); + tr_sys_path_remove(path2.c_str(), nullptr); + tr_sys_path_remove(path1.c_str(), nullptr); - tr_sys_dir_create(path1, 0, 0755, nullptr); - EXPECT_TRUE(createSymlink(path2, path1, true)); /* Win32: directory and file symlinks differ :( */ - tmp = makeString(tr_sys_path_resolve(path2, &err)); + tr_sys_dir_create(path1.c_str(), 0, 0755, nullptr); + EXPECT_TRUE(createSymlink(path2.c_str(), path1.c_str(), true)); /* Win32: directory and file symlinks differ :( */ + tmp = makeString(tr_sys_path_resolve(path2.c_str(), &err)); EXPECT_EQ(nullptr, err); EXPECT_TRUE(pathContainsNoSymlinks(tmp.c_str())); } @@ -670,11 +661,8 @@ TEST_F(FileTest, pathResolve) fprintf(stderr, "WARNING: [%s] unable to run symlink tests\n", __FUNCTION__); } - tr_sys_path_remove(path2, nullptr); - tr_sys_path_remove(path1, nullptr); - - tr_free(path2); - tr_free(path1); + tr_sys_path_remove(path2.c_str(), nullptr); + tr_sys_path_remove(path1.c_str(), nullptr); #ifdef _WIN32 @@ -802,161 +790,152 @@ TEST_F(FileTest, pathRename) { auto const test_dir = createTestDir(currentTestName()); - auto* path1 = tr_buildPath(test_dir.data(), "a", nullptr); - auto* path2 = tr_buildPath(test_dir.data(), "b", nullptr); - auto* path3 = tr_buildPath(path2, "c", nullptr); + auto const path1 = tr_strvPath(test_dir, "a"sv); + auto const path2 = tr_strvPath(test_dir, "b"sv); + auto path3 = tr_strvPath(path2, "c"sv); createFileWithContents(path1, "test"); /* Preconditions */ - EXPECT_TRUE(tr_sys_path_exists(path1, nullptr)); - EXPECT_FALSE(tr_sys_path_exists(path2, nullptr)); + EXPECT_TRUE(tr_sys_path_exists(path1.c_str(), nullptr)); + EXPECT_FALSE(tr_sys_path_exists(path2.c_str(), nullptr)); /* Forward rename works */ tr_error* err = nullptr; - EXPECT_TRUE(tr_sys_path_rename(path1, path2, &err)); - EXPECT_FALSE(tr_sys_path_exists(path1, nullptr)); - EXPECT_TRUE(tr_sys_path_exists(path2, nullptr)); + EXPECT_TRUE(tr_sys_path_rename(path1.c_str(), path2.c_str(), &err)); + EXPECT_FALSE(tr_sys_path_exists(path1.c_str(), nullptr)); + EXPECT_TRUE(tr_sys_path_exists(path2.c_str(), nullptr)); EXPECT_EQ(nullptr, err); /* Backward rename works */ - EXPECT_TRUE(tr_sys_path_rename(path2, path1, &err)); - EXPECT_TRUE(tr_sys_path_exists(path1, nullptr)); - EXPECT_FALSE(tr_sys_path_exists(path2, nullptr)); + EXPECT_TRUE(tr_sys_path_rename(path2.c_str(), path1.c_str(), &err)); + EXPECT_TRUE(tr_sys_path_exists(path1.c_str(), nullptr)); + EXPECT_FALSE(tr_sys_path_exists(path2.c_str(), nullptr)); EXPECT_EQ(nullptr, err); /* Another backward rename [of non-existent file] does not work */ - EXPECT_FALSE(tr_sys_path_rename(path2, path1, &err)); + EXPECT_FALSE(tr_sys_path_rename(path2.c_str(), path1.c_str(), &err)); EXPECT_NE(nullptr, err); tr_error_clear(&err); /* Rename to file which couldn't be created does not work */ - EXPECT_FALSE(tr_sys_path_rename(path1, path3, &err)); + EXPECT_FALSE(tr_sys_path_rename(path1.c_str(), path3.c_str(), &err)); EXPECT_NE(nullptr, err); tr_error_clear(&err); /* Rename of non-existent file does not work */ - EXPECT_FALSE(tr_sys_path_rename(path3, path2, &err)); + EXPECT_FALSE(tr_sys_path_rename(path3.c_str(), path2.c_str(), &err)); EXPECT_NE(nullptr, err); tr_error_clear(&err); createFileWithContents(path2, "test"); /* Renaming file does overwrite existing file */ - EXPECT_TRUE(tr_sys_path_rename(path2, path1, &err)); + EXPECT_TRUE(tr_sys_path_rename(path2.c_str(), path1.c_str(), &err)); EXPECT_EQ(nullptr, err); - tr_sys_dir_create(path2, 0, 0777, nullptr); + tr_sys_dir_create(path2.c_str(), 0, 0777, nullptr); /* Renaming file does not overwrite existing directory, and vice versa */ - EXPECT_FALSE(tr_sys_path_rename(path1, path2, &err)); + EXPECT_FALSE(tr_sys_path_rename(path1.c_str(), path2.c_str(), &err)); EXPECT_NE(nullptr, err); tr_error_clear(&err); - EXPECT_FALSE(tr_sys_path_rename(path2, path1, &err)); + EXPECT_FALSE(tr_sys_path_rename(path2.c_str(), path1.c_str(), &err)); EXPECT_NE(nullptr, err); tr_error_clear(&err); - tr_sys_path_remove(path2, nullptr); + tr_sys_path_remove(path2.c_str(), nullptr); - tr_free(path3); - path3 = tr_buildPath(test_dir.data(), "c", nullptr); + path3 = tr_strvPath(test_dir, "c"sv); - if (createSymlink(path2, path1, false)) + if (createSymlink(path2.c_str(), path1.c_str(), false)) { /* Preconditions */ - EXPECT_TRUE(tr_sys_path_exists(path2, nullptr)); - EXPECT_FALSE(tr_sys_path_exists(path3, nullptr)); - EXPECT_TRUE(tr_sys_path_is_same(path1, path2, nullptr)); + EXPECT_TRUE(tr_sys_path_exists(path2.c_str(), nullptr)); + EXPECT_FALSE(tr_sys_path_exists(path3.c_str(), nullptr)); + EXPECT_TRUE(tr_sys_path_is_same(path1.c_str(), path2.c_str(), nullptr)); /* Rename of symlink works, files stay the same */ - EXPECT_TRUE(tr_sys_path_rename(path2, path3, &err)); + EXPECT_TRUE(tr_sys_path_rename(path2.c_str(), path3.c_str(), &err)); EXPECT_EQ(nullptr, err); - EXPECT_FALSE(tr_sys_path_exists(path2, nullptr)); - EXPECT_TRUE(tr_sys_path_exists(path3, nullptr)); - EXPECT_TRUE(tr_sys_path_is_same(path1, path3, nullptr)); + EXPECT_FALSE(tr_sys_path_exists(path2.c_str(), nullptr)); + EXPECT_TRUE(tr_sys_path_exists(path3.c_str(), nullptr)); + EXPECT_TRUE(tr_sys_path_is_same(path1.c_str(), path3.c_str(), nullptr)); - tr_sys_path_remove(path3, nullptr); + tr_sys_path_remove(path3.c_str(), nullptr); } else { fprintf(stderr, "WARNING: [%s] unable to run symlink tests\n", __FUNCTION__); } - if (createHardlink(path2, path1)) + if (createHardlink(path2.c_str(), path1.c_str())) { /* Preconditions */ - EXPECT_TRUE(tr_sys_path_exists(path2, nullptr)); - EXPECT_FALSE(tr_sys_path_exists(path3, nullptr)); - EXPECT_TRUE(tr_sys_path_is_same(path1, path2, nullptr)); + EXPECT_TRUE(tr_sys_path_exists(path2.c_str(), nullptr)); + EXPECT_FALSE(tr_sys_path_exists(path3.c_str(), nullptr)); + EXPECT_TRUE(tr_sys_path_is_same(path1.c_str(), path2.c_str(), nullptr)); /* Rename of hardlink works, files stay the same */ - EXPECT_TRUE(tr_sys_path_rename(path2, path3, &err)); + EXPECT_TRUE(tr_sys_path_rename(path2.c_str(), path3.c_str(), &err)); EXPECT_EQ(nullptr, err); - EXPECT_FALSE(tr_sys_path_exists(path2, nullptr)); - EXPECT_TRUE(tr_sys_path_exists(path3, nullptr)); - EXPECT_TRUE(tr_sys_path_is_same(path1, path3, nullptr)); + EXPECT_FALSE(tr_sys_path_exists(path2.c_str(), nullptr)); + EXPECT_TRUE(tr_sys_path_exists(path3.c_str(), nullptr)); + EXPECT_TRUE(tr_sys_path_is_same(path1.c_str(), path3.c_str(), nullptr)); - tr_sys_path_remove(path3, nullptr); + tr_sys_path_remove(path3.c_str(), nullptr); } else { fprintf(stderr, "WARNING: [%s] unable to run hardlink tests\n", __FUNCTION__); } - tr_sys_path_remove(path1, nullptr); - - tr_free(path3); - tr_free(path2); - tr_free(path1); + tr_sys_path_remove(path1.c_str(), nullptr); } TEST_F(FileTest, pathRemove) { auto const test_dir = createTestDir(currentTestName()); - auto* path1 = tr_buildPath(test_dir.data(), "a", nullptr); - auto* path2 = tr_buildPath(test_dir.data(), "b", nullptr); - auto* path3 = tr_buildPath(path2, "c", nullptr); + auto const path1 = tr_strvPath(test_dir.data(), "a"sv); + auto const path2 = tr_strvPath(test_dir.data(), "b"sv); + auto const path3 = tr_strvPath(path2.c_str(), "c"sv); /* Can't remove non-existent file/directory */ - EXPECT_FALSE(tr_sys_path_exists(path1, nullptr)); + EXPECT_FALSE(tr_sys_path_exists(path1.c_str(), nullptr)); tr_error* err = nullptr; - EXPECT_FALSE(tr_sys_path_remove(path1, &err)); + EXPECT_FALSE(tr_sys_path_remove(path1.c_str(), &err)); EXPECT_NE(nullptr, err); - EXPECT_FALSE(tr_sys_path_exists(path1, nullptr)); + EXPECT_FALSE(tr_sys_path_exists(path1.c_str(), nullptr)); tr_error_clear(&err); /* Removing file works */ createFileWithContents(path1, "test"); - EXPECT_TRUE(tr_sys_path_exists(path1, nullptr)); - EXPECT_TRUE(tr_sys_path_remove(path1, &err)); + EXPECT_TRUE(tr_sys_path_exists(path1.c_str(), nullptr)); + EXPECT_TRUE(tr_sys_path_remove(path1.c_str(), &err)); EXPECT_EQ(nullptr, err); - EXPECT_FALSE(tr_sys_path_exists(path1, nullptr)); + EXPECT_FALSE(tr_sys_path_exists(path1.c_str(), nullptr)); /* Removing empty directory works */ - tr_sys_dir_create(path1, 0, 0777, nullptr); - EXPECT_TRUE(tr_sys_path_exists(path1, nullptr)); - EXPECT_TRUE(tr_sys_path_remove(path1, &err)); + tr_sys_dir_create(path1.c_str(), 0, 0777, nullptr); + EXPECT_TRUE(tr_sys_path_exists(path1.c_str(), nullptr)); + EXPECT_TRUE(tr_sys_path_remove(path1.c_str(), &err)); EXPECT_EQ(nullptr, err); - EXPECT_FALSE(tr_sys_path_exists(path1, nullptr)); + EXPECT_FALSE(tr_sys_path_exists(path1.c_str(), nullptr)); /* Removing non-empty directory fails */ - tr_sys_dir_create(path2, 0, 0777, nullptr); + tr_sys_dir_create(path2.c_str(), 0, 0777, nullptr); createFileWithContents(path3, "test"); - EXPECT_TRUE(tr_sys_path_exists(path2, nullptr)); - EXPECT_TRUE(tr_sys_path_exists(path3, nullptr)); - EXPECT_FALSE(tr_sys_path_remove(path2, &err)); + EXPECT_TRUE(tr_sys_path_exists(path2.c_str(), nullptr)); + EXPECT_TRUE(tr_sys_path_exists(path3.c_str(), nullptr)); + EXPECT_FALSE(tr_sys_path_remove(path2.c_str(), &err)); EXPECT_NE(nullptr, err); - EXPECT_TRUE(tr_sys_path_exists(path2, nullptr)); - EXPECT_TRUE(tr_sys_path_exists(path3, nullptr)); + EXPECT_TRUE(tr_sys_path_exists(path2.c_str(), nullptr)); + EXPECT_TRUE(tr_sys_path_exists(path3.c_str(), nullptr)); tr_error_clear(&err); - tr_sys_path_remove(path3, nullptr); - tr_sys_path_remove(path2, nullptr); - - tr_free(path3); - tr_free(path2); - tr_free(path1); + tr_sys_path_remove(path3.c_str(), nullptr); + tr_sys_path_remove(path2.c_str(), nullptr); } TEST_F(FileTest, pathNativeSeparators) @@ -991,67 +970,67 @@ TEST_F(FileTest, fileOpen) auto const test_dir = createTestDir(currentTestName()); // can't open non-existent file - auto* path1 = tr_buildPath(test_dir.data(), "a", nullptr); - EXPECT_FALSE(tr_sys_path_exists(path1, nullptr)); + auto const path1 = tr_strvPath(test_dir, "a"sv); + EXPECT_FALSE(tr_sys_path_exists(path1.c_str(), nullptr)); tr_error* err = nullptr; - EXPECT_EQ(TR_BAD_SYS_FILE, tr_sys_file_open(path1, TR_SYS_FILE_READ, 0600, &err)); + EXPECT_EQ(TR_BAD_SYS_FILE, tr_sys_file_open(path1.c_str(), TR_SYS_FILE_READ, 0600, &err)); EXPECT_NE(nullptr, err); - EXPECT_FALSE(tr_sys_path_exists(path1, nullptr)); + EXPECT_FALSE(tr_sys_path_exists(path1.c_str(), nullptr)); tr_error_clear(&err); - EXPECT_EQ(TR_BAD_SYS_FILE, tr_sys_file_open(path1, TR_SYS_FILE_WRITE, 0600, &err)); + EXPECT_EQ(TR_BAD_SYS_FILE, tr_sys_file_open(path1.c_str(), TR_SYS_FILE_WRITE, 0600, &err)); EXPECT_NE(nullptr, err); - EXPECT_FALSE(tr_sys_path_exists(path1, nullptr)); + EXPECT_FALSE(tr_sys_path_exists(path1.c_str(), nullptr)); tr_error_clear(&err); // can't open directory - tr_sys_dir_create(path1, 0, 0777, nullptr); + tr_sys_dir_create(path1.c_str(), 0, 0777, nullptr); #ifdef _WIN32 // this works on *NIX - EXPECT_EQ(TR_BAD_SYS_FILE, tr_sys_file_open(path1, TR_SYS_FILE_READ, 0600, &err)); + EXPECT_EQ(TR_BAD_SYS_FILE, tr_sys_file_open(path1.c_str(), TR_SYS_FILE_READ, 0600, &err)); EXPECT_NE(nullptr, err); tr_error_clear(&err); #endif - EXPECT_EQ(TR_BAD_SYS_FILE, tr_sys_file_open(path1, TR_SYS_FILE_WRITE, 0600, &err)); + EXPECT_EQ(TR_BAD_SYS_FILE, tr_sys_file_open(path1.c_str(), TR_SYS_FILE_WRITE, 0600, &err)); EXPECT_NE(nullptr, err); tr_error_clear(&err); - tr_sys_path_remove(path1, nullptr); + tr_sys_path_remove(path1.c_str(), nullptr); // can create non-existent file - auto fd = tr_sys_file_open(path1, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0640, &err); + auto fd = tr_sys_file_open(path1.c_str(), TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0640, &err); EXPECT_NE(TR_BAD_SYS_FILE, fd); EXPECT_EQ(nullptr, err); tr_sys_file_close(fd, nullptr); - EXPECT_TRUE(tr_sys_path_exists(path1, nullptr)); - EXPECT_TRUE(validatePermissions(path1, 0640)); + EXPECT_TRUE(tr_sys_path_exists(path1.c_str(), nullptr)); + EXPECT_TRUE(validatePermissions(path1.c_str(), 0640)); // can open existing file - EXPECT_TRUE(tr_sys_path_exists(path1, nullptr)); - fd = tr_sys_file_open(path1, TR_SYS_FILE_READ, 0600, &err); + EXPECT_TRUE(tr_sys_path_exists(path1.c_str(), nullptr)); + fd = tr_sys_file_open(path1.c_str(), TR_SYS_FILE_READ, 0600, &err); EXPECT_NE(TR_BAD_SYS_FILE, fd); EXPECT_EQ(nullptr, err); tr_sys_file_close(fd, nullptr); - fd = tr_sys_file_open(path1, TR_SYS_FILE_WRITE, 0600, &err); + fd = tr_sys_file_open(path1.c_str(), TR_SYS_FILE_WRITE, 0600, &err); EXPECT_NE(TR_BAD_SYS_FILE, fd); EXPECT_EQ(nullptr, err); tr_sys_file_close(fd, nullptr); - tr_sys_path_remove(path1, nullptr); + tr_sys_path_remove(path1.c_str(), nullptr); createFileWithContents(path1, "test"); /* Can't create new file if it already exists */ - fd = tr_sys_file_open(path1, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE_NEW, 0640, &err); + fd = tr_sys_file_open(path1.c_str(), TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE_NEW, 0640, &err); 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, nullptr); + tr_sys_path_get_info(path1.c_str(), TR_SYS_PATH_NO_FOLLOW, &info, nullptr); EXPECT_EQ(4, info.size); /* Pointer is at the end of file */ - tr_sys_path_get_info(path1, TR_SYS_PATH_NO_FOLLOW, &info, nullptr); + tr_sys_path_get_info(path1.c_str(), TR_SYS_PATH_NO_FOLLOW, &info, nullptr); EXPECT_EQ(4, info.size); - fd = tr_sys_file_open(path1, TR_SYS_FILE_WRITE | TR_SYS_FILE_APPEND, 0600, &err); + fd = tr_sys_file_open(path1.c_str(), TR_SYS_FILE_WRITE | TR_SYS_FILE_APPEND, 0600, &err); EXPECT_NE(TR_BAD_SYS_FILE, fd); EXPECT_EQ(nullptr, err); tr_sys_file_write(fd, "s", 1, nullptr, nullptr); /* On *NIX, pointer is positioned on each write but not initially */ @@ -1061,30 +1040,28 @@ TEST_F(FileTest, fileOpen) tr_sys_file_close(fd, nullptr); /* File gets truncated */ - tr_sys_path_get_info(path1, TR_SYS_PATH_NO_FOLLOW, &info, nullptr); + tr_sys_path_get_info(path1.c_str(), TR_SYS_PATH_NO_FOLLOW, &info, nullptr); EXPECT_EQ(5, info.size); - fd = tr_sys_file_open(path1, TR_SYS_FILE_WRITE | TR_SYS_FILE_TRUNCATE, 0600, &err); + fd = tr_sys_file_open(path1.c_str(), TR_SYS_FILE_WRITE | TR_SYS_FILE_TRUNCATE, 0600, &err); EXPECT_NE(TR_BAD_SYS_FILE, fd); EXPECT_EQ(nullptr, err); tr_sys_file_get_info(fd, &info, nullptr); EXPECT_EQ(0, info.size); tr_sys_file_close(fd, nullptr); - tr_sys_path_get_info(path1, TR_SYS_PATH_NO_FOLLOW, &info, nullptr); + tr_sys_path_get_info(path1.c_str(), TR_SYS_PATH_NO_FOLLOW, &info, nullptr); EXPECT_EQ(0, info.size); /* TODO: symlink and hardlink tests */ - tr_sys_path_remove(path1, nullptr); - - tr_free(path1); + tr_sys_path_remove(path1.c_str(), nullptr); } TEST_F(FileTest, fileReadWriteSeek) { auto const test_dir = createTestDir(currentTestName()); - auto* path1 = tr_buildPath(test_dir.data(), "a", nullptr); - auto const fd = tr_sys_file_open(path1, TR_SYS_FILE_READ | TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0600, nullptr); + auto const path1 = tr_strvPath(test_dir, "a"sv); + auto const fd = tr_sys_file_open(path1.c_str(), TR_SYS_FILE_READ | TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0600, nullptr); uint64_t n; tr_error* err = nullptr; @@ -1159,17 +1136,15 @@ TEST_F(FileTest, fileReadWriteSeek) tr_sys_file_close(fd, nullptr); - tr_sys_path_remove(path1, nullptr); - - tr_free(path1); + tr_sys_path_remove(path1.c_str(), nullptr); } TEST_F(FileTest, fileTruncate) { auto const test_dir = createTestDir(currentTestName()); - auto* path1 = tr_buildPath(test_dir.c_str(), "a", nullptr); - auto fd = tr_sys_file_open(path1, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0600, nullptr); + auto const path1 = tr_strvPath(test_dir, "a"sv); + auto fd = tr_sys_file_open(path1.c_str(), TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0600, nullptr); tr_error* err = nullptr; EXPECT_TRUE(tr_sys_file_truncate(fd, 10, &err)); @@ -1193,30 +1168,28 @@ TEST_F(FileTest, fileTruncate) tr_sys_file_close(fd, nullptr); - tr_sys_path_get_info(path1, 0, &info, nullptr); + tr_sys_path_get_info(path1.c_str(), 0, &info, nullptr); EXPECT_EQ(50, info.size); - fd = tr_sys_file_open(path1, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0600, nullptr); + fd = tr_sys_file_open(path1.c_str(), TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0600, nullptr); EXPECT_TRUE(tr_sys_file_truncate(fd, 25, &err)); EXPECT_EQ(nullptr, err); tr_sys_file_close(fd, nullptr); - tr_sys_path_get_info(path1, 0, &info, nullptr); + tr_sys_path_get_info(path1.c_str(), 0, &info, nullptr); EXPECT_EQ(25, info.size); - tr_sys_path_remove(path1, nullptr); - - tr_free(path1); + tr_sys_path_remove(path1.c_str(), nullptr); } TEST_F(FileTest, filePreallocate) { auto const test_dir = createTestDir(currentTestName()); - auto* path1 = tr_buildPath(test_dir.data(), "a", nullptr); - auto fd = tr_sys_file_open(path1, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0600, nullptr); + auto const path1 = tr_strvPath(test_dir, "a"sv); + auto fd = tr_sys_file_open(path1.c_str(), TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0600, nullptr); tr_error* err = nullptr; auto prealloc_size = size_t{ 50 }; @@ -1236,9 +1209,9 @@ TEST_F(FileTest, filePreallocate) tr_sys_file_close(fd, nullptr); - tr_sys_path_remove(path1, nullptr); + tr_sys_path_remove(path1.c_str(), nullptr); - fd = tr_sys_file_open(path1, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0600, nullptr); + fd = tr_sys_file_open(path1.c_str(), TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0600, nullptr); prealloc_size = 500 * 1024 * 1024; if (tr_sys_file_preallocate(fd, prealloc_size, TR_SYS_FILE_PREALLOC_SPARSE, &err)) @@ -1257,20 +1230,18 @@ TEST_F(FileTest, filePreallocate) tr_sys_file_close(fd, nullptr); - tr_sys_path_remove(path1, nullptr); - - tr_free(path1); + tr_sys_path_remove(path1.c_str(), nullptr); } TEST_F(FileTest, map) { auto const test_dir = createTestDir(currentTestName()); - auto* path1 = tr_buildPath(test_dir.data(), "a", nullptr); + auto const path1 = tr_strvPath(test_dir, "a"sv); auto const contents = std::string{ "test" }; createFileWithContents(path1, contents.data()); - auto fd = tr_sys_file_open(path1, TR_SYS_FILE_READ | TR_SYS_FILE_WRITE, 0600, nullptr); + auto fd = tr_sys_file_open(path1.c_str(), TR_SYS_FILE_READ | TR_SYS_FILE_WRITE, 0600, nullptr); tr_error* err = nullptr; auto map_len = contents.size(); @@ -1296,20 +1267,18 @@ TEST_F(FileTest, map) tr_sys_file_close(fd, nullptr); - tr_sys_path_remove(path1, nullptr); - - tr_free(path1); + tr_sys_path_remove(path1.c_str(), nullptr); } TEST_F(FileTest, fileUtilities) { auto const test_dir = createTestDir(currentTestName()); - auto* path1 = tr_buildPath(test_dir.data(), "a", nullptr); + auto const path1 = tr_strvPath(test_dir, "a"sv); auto const contents = std::string{ "a\nbc\r\ndef\nghij\r\n\n\nklmno\r" }; createFileWithContents(path1, contents.data()); - auto fd = tr_sys_file_open(path1, TR_SYS_FILE_READ, 0, nullptr); + auto fd = tr_sys_file_open(path1.c_str(), TR_SYS_FILE_READ, 0, nullptr); tr_error* err = nullptr; auto buffer = std::array{}; @@ -1343,7 +1312,7 @@ TEST_F(FileTest, fileUtilities) tr_sys_file_close(fd, nullptr); - fd = tr_sys_file_open(path1, TR_SYS_FILE_READ | TR_SYS_FILE_WRITE | TR_SYS_FILE_TRUNCATE, 0, nullptr); + fd = tr_sys_file_open(path1.c_str(), TR_SYS_FILE_READ | TR_SYS_FILE_WRITE | TR_SYS_FILE_TRUNCATE, 0, nullptr); EXPECT_TRUE(tr_sys_file_write_line(fd, "p", &err)); EXPECT_EQ(nullptr, err); @@ -1389,71 +1358,66 @@ TEST_F(FileTest, fileUtilities) tr_sys_file_close(fd, nullptr); - tr_sys_path_remove(path1, nullptr); - - tr_free(path1); + tr_sys_path_remove(path1.c_str(), nullptr); } TEST_F(FileTest, dirCreate) { auto const test_dir = createTestDir(currentTestName()); - auto* path1 = tr_buildPath(test_dir.data(), "a", nullptr); - auto* path2 = tr_buildPath(path1, "b", nullptr); + auto const path1 = tr_strvPath(test_dir.data(), "a"sv); + auto const path2 = tr_strvPath(path1, "b"sv); // Can create directory which has parent tr_error* err = nullptr; - EXPECT_TRUE(tr_sys_dir_create(path1, 0, 0700, &err)); + EXPECT_TRUE(tr_sys_dir_create(path1.c_str(), 0, 0700, &err)); EXPECT_EQ(nullptr, err); - EXPECT_TRUE(tr_sys_path_exists(path1, nullptr)); - EXPECT_TRUE(validatePermissions(path1, 0700)); + EXPECT_TRUE(tr_sys_path_exists(path1.c_str(), nullptr)); + EXPECT_TRUE(validatePermissions(path1.c_str(), 0700)); - tr_sys_path_remove(path1, nullptr); + tr_sys_path_remove(path1.c_str(), nullptr); createFileWithContents(path1, "test"); // Can't create directory where file already exists - EXPECT_FALSE(tr_sys_dir_create(path1, 0, 0700, &err)); + EXPECT_FALSE(tr_sys_dir_create(path1.c_str(), 0, 0700, &err)); EXPECT_NE(nullptr, err); tr_error_clear(&err); - EXPECT_FALSE(tr_sys_dir_create(path1, TR_SYS_DIR_CREATE_PARENTS, 0700, &err)); + EXPECT_FALSE(tr_sys_dir_create(path1.c_str(), TR_SYS_DIR_CREATE_PARENTS, 0700, &err)); EXPECT_NE(nullptr, err); tr_error_clear(&err); - tr_sys_path_remove(path1, nullptr); + tr_sys_path_remove(path1.c_str(), nullptr); // Can't create directory which has no parent - EXPECT_FALSE(tr_sys_dir_create(path2, 0, 0700, &err)); + EXPECT_FALSE(tr_sys_dir_create(path2.c_str(), 0, 0700, &err)); EXPECT_NE(nullptr, err); - EXPECT_FALSE(tr_sys_path_exists(path2, nullptr)); + EXPECT_FALSE(tr_sys_path_exists(path2.c_str(), nullptr)); tr_error_clear(&err); // Can create directory with parent directories - EXPECT_TRUE(tr_sys_dir_create(path2, TR_SYS_DIR_CREATE_PARENTS, 0751, &err)); + EXPECT_TRUE(tr_sys_dir_create(path2.c_str(), TR_SYS_DIR_CREATE_PARENTS, 0751, &err)); EXPECT_EQ(nullptr, err); - EXPECT_TRUE(tr_sys_path_exists(path1, nullptr)); - EXPECT_TRUE(tr_sys_path_exists(path2, nullptr)); - EXPECT_TRUE(validatePermissions(path1, 0751)); - EXPECT_TRUE(validatePermissions(path2, 0751)); + EXPECT_TRUE(tr_sys_path_exists(path1.c_str(), nullptr)); + EXPECT_TRUE(tr_sys_path_exists(path2.c_str(), nullptr)); + EXPECT_TRUE(validatePermissions(path1.c_str(), 0751)); + EXPECT_TRUE(validatePermissions(path2.c_str(), 0751)); // Can create existing directory (no-op) - EXPECT_TRUE(tr_sys_dir_create(path1, 0, 0700, &err)); + EXPECT_TRUE(tr_sys_dir_create(path1.c_str(), 0, 0700, &err)); EXPECT_EQ(nullptr, err); - EXPECT_TRUE(tr_sys_dir_create(path1, TR_SYS_DIR_CREATE_PARENTS, 0700, &err)); + EXPECT_TRUE(tr_sys_dir_create(path1.c_str(), TR_SYS_DIR_CREATE_PARENTS, 0700, &err)); EXPECT_EQ(nullptr, err); - tr_sys_path_remove(path2, nullptr); - tr_sys_path_remove(path1, nullptr); - - tr_free(path2); - tr_free(path1); + tr_sys_path_remove(path2.c_str(), nullptr); + tr_sys_path_remove(path1.c_str(), nullptr); } TEST_F(FileTest, dirRead) { auto const test_dir = createTestDir(currentTestName()); - auto* path1 = tr_buildPath(test_dir.data(), "a", nullptr); - auto* path2 = tr_buildPath(test_dir.data(), "b", nullptr); + auto const path1 = tr_strvPath(test_dir, "a"sv); + auto const path2 = tr_strvPath(test_dir, "b"sv); bool have1; bool have2; @@ -1471,13 +1435,10 @@ TEST_F(FileTest, dirRead) EXPECT_TRUE(have1); EXPECT_TRUE(have2); - tr_sys_path_remove(path1, nullptr); + tr_sys_path_remove(path1.c_str(), nullptr); testDirReadImpl(test_dir, &have1, &have2); EXPECT_FALSE(have1); EXPECT_TRUE(have2); - - tr_free(path2); - tr_free(path1); } } // namespace test diff --git a/tests/libtransmission/makemeta-test.cc b/tests/libtransmission/makemeta-test.cc index f8d79ad1b..ebb0b5ff3 100644 --- a/tests/libtransmission/makemeta-test.cc +++ b/tests/libtransmission/makemeta-test.cc @@ -19,6 +19,8 @@ #include // strlen() #include +using namespace std::literals; + namespace libtransmission { @@ -40,23 +42,23 @@ protected: { // create a single input file - auto input_file = makeString(tr_buildPath(sandboxDir().data(), "test.XXXXXX", nullptr)); + auto input_file = tr_strvPath(sandboxDir().data(), "test.XXXXXX"); createTmpfileWithContents(input_file, payload, payloadSize); - tr_sys_path_native_separators(&input_file.front()); + tr_sys_path_native_separators(std::data(input_file)); auto* builder = tr_metaInfoBuilderCreate(input_file.c_str()); EXPECT_EQ(tr_file_index_t{ 1 }, builder->fileCount); - EXPECT_STREQ(input_file.c_str(), builder->top); - EXPECT_STREQ(input_file.c_str(), builder->files[0].filename); + EXPECT_EQ(input_file, builder->top); + EXPECT_EQ(input_file, builder->files[0].filename); EXPECT_EQ(payloadSize, builder->files[0].size); EXPECT_EQ(payloadSize, builder->totalSize); EXPECT_FALSE(builder->isFolder); EXPECT_FALSE(builder->abortFlag); // have tr_makeMetaInfo() build the .torrent file - auto* torrent_file = tr_strdup_printf("%s.torrent", input_file.data()); - tr_makeMetaInfo(builder, torrent_file, trackers, trackerCount, comment, isPrivate, source); + auto const torrent_file = tr_strvJoin(input_file, ".torrent"); + tr_makeMetaInfo(builder, torrent_file.c_str(), trackers, trackerCount, comment, isPrivate, source); EXPECT_EQ(isPrivate, builder->isPrivate); - EXPECT_STREQ(torrent_file, builder->outputFile); + EXPECT_EQ(torrent_file, builder->outputFile); EXPECT_STREQ(comment, builder->comment); EXPECT_STREQ(source, builder->source); EXPECT_EQ(trackerCount, builder->trackerCount); @@ -69,7 +71,7 @@ protected: // now let's check our work: parse the .torrent file auto* ctor = tr_ctorNew(nullptr); sync(); - tr_ctorSetMetainfoFromFile(ctor, torrent_file); + tr_ctorSetMetainfoFromFile(ctor, torrent_file.c_str()); auto const parse_result = tr_torrentParse(ctor, &inf); EXPECT_EQ(TR_PARSE_OK, parse_result); @@ -83,7 +85,6 @@ protected: EXPECT_EQ(trackerCount, inf.trackerCount); // cleanup - tr_free(torrent_file); tr_ctorFree(ctor); tr_metaInfoBuilderFree(builder); } @@ -99,9 +100,9 @@ protected: char const* source) { // create the top temp directory - auto* top = tr_buildPath(sandboxDir().data(), "folder.XXXXXX", nullptr); - tr_sys_path_native_separators(top); - tr_sys_dir_create_temp(top, nullptr); + auto top = tr_strvPath(sandboxDir(), "folder.XXXXXX"); + tr_sys_path_native_separators(std::data(top)); + tr_sys_dir_create_temp(std::data(top), nullptr); // build the payload files that go into the top temp directory auto files = std::vector{}; @@ -112,9 +113,9 @@ protected: { auto tmpl = std::array{}; tr_snprintf(tmpl.data(), tmpl.size(), "file.%04zu%s", i, "XXXXXX"); - auto path = makeString(tr_buildPath(top, tmpl.data(), nullptr)); + auto path = tr_strvPath(top, std::data(tmpl)); createTmpfileWithContents(path, payloads[i], payload_sizes[i]); - tr_sys_path_native_separators(&path.front()); + tr_sys_path_native_separators(std::data(path)); files.push_back(path); total_size += payload_sizes[i]; } @@ -122,9 +123,9 @@ protected: sync(); // init the builder - auto* builder = tr_metaInfoBuilderCreate(top); + auto* builder = tr_metaInfoBuilderCreate(top.c_str()); EXPECT_FALSE(builder->abortFlag); - EXPECT_STREQ(top, builder->top); + EXPECT_EQ(top, builder->top); EXPECT_EQ(payload_count, builder->fileCount); EXPECT_EQ(total_size, builder->totalSize); EXPECT_TRUE(builder->isFolder); @@ -136,10 +137,10 @@ protected: } // build the .torrent file - auto* torrent_file = tr_strdup_printf("%s.torrent", top); - tr_makeMetaInfo(builder, torrent_file, trackers, tracker_count, comment, is_private, source); + auto torrent_file = tr_strvJoin(top, ".torrent"sv); + tr_makeMetaInfo(builder, torrent_file.c_str(), trackers, tracker_count, comment, is_private, source); EXPECT_EQ(is_private, builder->isPrivate); - EXPECT_STREQ(torrent_file, builder->outputFile); + EXPECT_EQ(torrent_file, builder->outputFile); EXPECT_STREQ(comment, builder->comment); EXPECT_STREQ(source, builder->source); EXPECT_EQ(tracker_count, builder->trackerCount); @@ -152,14 +153,14 @@ protected: // now let's check our work: parse the .torrent file auto* ctor = tr_ctorNew(nullptr); - tr_ctorSetMetainfoFromFile(ctor, torrent_file); + tr_ctorSetMetainfoFromFile(ctor, torrent_file.c_str()); auto inf = tr_info{}; auto parse_result = tr_torrentParse(ctor, &inf); EXPECT_EQ(TR_PARSE_OK, parse_result); // quick check of some of the parsed metainfo EXPECT_EQ(total_size, inf.totalSize); - auto* tmpstr = tr_sys_path_basename(top, nullptr); + auto* tmpstr = tr_sys_path_basename(top.c_str(), nullptr); EXPECT_STREQ(tmpstr, inf.name); tr_free(tmpstr); EXPECT_STREQ(comment, inf.comment); @@ -170,12 +171,9 @@ protected: EXPECT_EQ(tracker_count, inf.trackerCount); // cleanup - tr_free(torrent_file); tr_ctorFree(ctor); tr_metainfoFree(&inf); tr_metaInfoBuilderFree(builder); - - tr_free(top); } void testSingleDirectoryRandomPayloadImpl( diff --git a/tests/libtransmission/move-test.cc b/tests/libtransmission/move-test.cc index a0d1e3dd4..265a78abf 100644 --- a/tests/libtransmission/move-test.cc +++ b/tests/libtransmission/move-test.cc @@ -53,9 +53,7 @@ TEST_P(IncompleteDirTest, incompleteDir) EXPECT_EQ( makeString(tr_strdup_printf("%s/%s.part", incomplete_dir, tor->info.files[0].name)), makeString(tr_torrentFindFile(tor, 0))); - EXPECT_EQ( - makeString(tr_buildPath(incomplete_dir, tor->info.files[1].name, nullptr)), - makeString(tr_torrentFindFile(tor, 1))); + EXPECT_EQ(tr_strvPath(incomplete_dir, tor->info.files[1].name), makeString(tr_torrentFindFile(tor, 1))); EXPECT_EQ(tor->info.pieceSize, tr_torrentStat(tor)->leftUntilDone); // auto constexpr completeness_unset = tr_completeness { -1 }; @@ -129,9 +127,7 @@ TEST_P(IncompleteDirTest, incompleteDir) for (tr_file_index_t file_index = 0; file_index < tor->info.fileCount; ++file_index) { - EXPECT_EQ( - makeString(tr_buildPath(download_dir, tor->info.files[file_index].name, nullptr)), - makeString(tr_torrentFindFile(tor, file_index))); + EXPECT_EQ(tr_strvPath(download_dir, tor->info.files[file_index].name), makeString(tr_torrentFindFile(tor, file_index))); } // cleanup @@ -157,7 +153,7 @@ using MoveTest = SessionTest; TEST_F(MoveTest, setLocation) { - auto const target_dir = makeString(tr_buildPath(tr_sessionGetConfigDir(session_), "target", nullptr)); + auto const target_dir = tr_strvPath(tr_sessionGetConfigDir(session_), "target"); tr_sys_dir_create(target_dir.data(), TR_SYS_DIR_CREATE_PARENTS, 0777, nullptr); // init a torrent. @@ -185,7 +181,7 @@ TEST_F(MoveTest, setLocation) for (tr_file_index_t file_index = 0; file_index < tor->info.fileCount; ++file_index) { EXPECT_EQ( - makeString(tr_buildPath(target_dir.data(), tor->info.files[file_index].name, nullptr)), + tr_strvPath(target_dir.data(), tor->info.files[file_index].name), makeString(tr_torrentFindFile(tor, file_index))); } diff --git a/tests/libtransmission/rename-test.cc b/tests/libtransmission/rename-test.cc index 13d4ff85e..a5871a715 100644 --- a/tests/libtransmission/rename-test.cc +++ b/tests/libtransmission/rename-test.cc @@ -45,22 +45,22 @@ protected: void createSingleFileTorrentContents(char const* top) { - auto const path = makeString(tr_buildPath(top, "hello-world.txt", nullptr)); + auto const path = tr_strvPath(top, "hello-world.txt"); createFileWithContents(path, "hello, world!\n"); } void createMultifileTorrentContents(char const* top) { - auto path = makeString(tr_buildPath(top, "Felidae", "Felinae", "Acinonyx", "Cheetah", "Chester", nullptr)); + auto path = tr_strvPath(top, "Felidae", "Felinae", "Acinonyx", "Cheetah", "Chester"); createFileWithContents(path, "It ain't easy bein' cheesy.\n"); - path = makeString(tr_buildPath(top, "Felidae", "Pantherinae", "Panthera", "Tiger", "Tony", nullptr)); + path = tr_strvPath(top, "Felidae", "Pantherinae", "Panthera", "Tiger", "Tony"); createFileWithContents(path, "They’re Grrrrreat!\n"); - path = makeString(tr_buildPath(top, "Felidae", "Felinae", "Felis", "catus", "Kyphi", nullptr)); + path = tr_strvPath(top, "Felidae", "Felinae", "Felis", "catus", "Kyphi"); createFileWithContents(path, "Inquisitive\n"); - path = makeString(tr_buildPath(top, "Felidae", "Felinae", "Felis", "catus", "Saffron", nullptr)); + path = tr_strvPath(top, "Felidae", "Felinae", "Felis", "catus", "Saffron"); createFileWithContents(path, "Tough\n"); sync(); @@ -196,7 +196,7 @@ TEST_F(RenameTest, singleFilenameTorrent) **** Now try a rename that should succeed ***/ - auto tmpstr = makeString(tr_buildPath(tor->currentDir, "hello-world.txt", nullptr)); + auto tmpstr = tr_strvPath(tor->currentDir, "hello-world.txt"); EXPECT_TRUE(tr_sys_path_exists(tmpstr.c_str(), nullptr)); EXPECT_STREQ("hello-world.txt", tr_torrentName(tor)); EXPECT_EQ(0, torrentRenameAndWait(tor, tor->info.name, "foobar")); @@ -205,7 +205,7 @@ TEST_F(RenameTest, singleFilenameTorrent) 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(nullptr, strstr(tor->info.torrent, "foobar")); // confirm the name in the .torrent file hasn't changed - tmpstr = makeString(tr_buildPath(tor->currentDir, "foobar", nullptr)); + 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 EXPECT_TRUE(testFileExistsAndConsistsOfThisString(tor, 0, "hello, world!\n")); // confirm the contents are right @@ -220,7 +220,7 @@ TEST_F(RenameTest, singleFilenameTorrent) **** ...and rename it back again ***/ - tmpstr = makeString(tr_buildPath(tor->currentDir, "foobar", nullptr)); + tmpstr = tr_strvPath(tor->currentDir, "foobar"); 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)); @@ -521,11 +521,10 @@ TEST_F(RenameTest, partialFile) for (tr_file_index_t i = 0; i < 3; ++i) { - char* expected = tr_buildPath(tor->currentDir, strings[i], nullptr); + auto const expected = tr_strvPath(tor->currentDir, strings[i]); char* path = tr_torrentFindFile(tor, i); - EXPECT_STREQ(expected, path); + EXPECT_EQ(expected, path); tr_free(path); - tr_free(expected); } torrentRemoveAndWait(tor, 0); diff --git a/tests/libtransmission/test-fixtures.h b/tests/libtransmission/test-fixtures.h index 94c2e3672..de1d58601 100644 --- a/tests/libtransmission/test-fixtures.h +++ b/tests/libtransmission/test-fixtures.h @@ -105,9 +105,9 @@ protected: static std::string create_sandbox(std::string const& parent_dir, std::string const& tmpl) { - std::string path = makeString(tr_buildPath(parent_dir.data(), tmpl.data(), nullptr)); - tr_sys_dir_create_temp(&path.front(), nullptr); - tr_sys_path_native_separators(&path.front()); + auto path = tr_strvPath(parent_dir, tmpl); + tr_sys_dir_create_temp(std::data(path), nullptr); + tr_sys_path_native_separators(std::data(path)); return path; } @@ -126,7 +126,7 @@ protected: { if (strcmp(name, ".") != 0 && strcmp(name, "..") != 0) { - ret.push_back(makeString(tr_buildPath(path.data(), name, nullptr))); + ret.push_back(tr_strvPath(path, name)); } } @@ -302,21 +302,19 @@ private: // download dir auto sv = std::string_view{}; auto q = TR_KEY_download_dir; - auto const download_dir = tr_variantDictFindStrView(settings, q, &sv) ? - makeString(tr_strdup_printf("%s/%" TR_PRIsv, sandboxDir().data(), TR_PRIsv_ARG(sv))) : - makeString(tr_buildPath(sandboxDir().data(), "Downloads", nullptr)); + auto const download_dir = tr_variantDictFindStrView(settings, q, &sv) ? tr_strvPath(sandboxDir(), sv) : + tr_strvPath(sandboxDir(), "Downloads"); tr_sys_dir_create(download_dir.data(), TR_SYS_DIR_CREATE_PARENTS, 0700, nullptr); tr_variantDictAddStr(settings, q, download_dir.data()); // incomplete dir q = TR_KEY_incomplete_dir; - auto const incomplete_dir = tr_variantDictFindStrView(settings, q, &sv) ? - makeString(tr_strdup_printf("%s/%" TR_PRIsv, sandboxDir().data(), TR_PRIsv_ARG(sv))) : - makeString(tr_buildPath(sandboxDir().data(), "Incomplete", nullptr)); + auto const incomplete_dir = tr_variantDictFindStrView(settings, q, &sv) ? tr_strvPath(sandboxDir(), sv) : + tr_strvPath(sandboxDir(), "Incomplete"); tr_variantDictAddStr(settings, q, incomplete_dir.data()); // blocklists - auto const blocklist_dir = makeString(tr_buildPath(sandboxDir().data(), "blocklists", nullptr)); + auto const blocklist_dir = tr_strvPath(sandboxDir(), "blocklists"); tr_sys_dir_create(blocklist_dir.data(), TR_SYS_DIR_CREATE_PARENTS, 0700, nullptr); // fill in any missing settings diff --git a/tests/libtransmission/utils-test.cc b/tests/libtransmission/utils-test.cc index e8e81f51e..7b09d8849 100644 --- a/tests/libtransmission/utils-test.cc +++ b/tests/libtransmission/utils-test.cc @@ -49,6 +49,14 @@ TEST_F(UtilsTest, trStripPositionalArgs) EXPECT_STREQ(expected, out); } +TEST_F(UtilsTest, trStrvJoin) +{ + EXPECT_EQ(""sv, tr_strvJoin(""sv)); + EXPECT_EQ("test"sv, tr_strvJoin("test"sv)); + EXPECT_EQ("foo/bar"sv, tr_strvJoin("foo"sv, "/", std::string{ "bar" })); + EXPECT_EQ("abcde"sv, tr_strvJoin("a", "b", "c", "d", "e")); +} + TEST_F(UtilsTest, trStrvContains) { EXPECT_FALSE(tr_strvContains("a test is this"sv, "TEST"sv)); @@ -148,6 +156,18 @@ TEST_F(UtilsTest, trBuildpath) EXPECT_EQ(TR_PATH_DELIMITER_STR "foo" TR_PATH_DELIMITER_STR "bar", out); } +TEST_F(UtilsTest, trStrvPath) +{ + EXPECT_EQ("foo" TR_PATH_DELIMITER_STR "bar", tr_strvPath("foo", "bar")); + EXPECT_EQ(TR_PATH_DELIMITER_STR "foo" TR_PATH_DELIMITER_STR "bar", tr_strvPath("", "foo", "bar")); + + EXPECT_EQ("", tr_strvPath(""sv)); + EXPECT_EQ("foo"sv, tr_strvPath("foo"sv)); + EXPECT_EQ( + "foo" TR_PATH_DELIMITER_STR "bar" TR_PATH_DELIMITER_STR "baz" TR_PATH_DELIMITER_STR "mum"sv, + tr_strvPath("foo"sv, "bar", std::string{ "baz" }, "mum"sv)); +} + TEST_F(UtilsTest, trUtf8clean) { auto in = "hello world"sv;