From 2649e7acddfb6f2e83e9a8f87e9c2f8afc3aff61 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 1 Feb 2026 15:37:37 -0600 Subject: [PATCH] refactor: use `std::filesystem` for more file utils (#8296) * fix: warning: declaration shadows a variable in the global namespace [clang-diagnostic-shadow] * fix: warning: use 'contains' to check for membership [readability-container-contains] * fix: warning: variable gl_confdir can be made static or moved into an anonymous namespace to enforce internal linkage [misc-use-internal-linkage] * warning: function 'TorrentFilter::match_mode' has a definition with different parameter names [readability-inconsistent-declaration-parameter-name] * refactor: use std::filesystem for tr_sys_path_is_same() * refactor: use std::filesystem for tr_sys_path_exists() * refactor: use std::filesystem for tr_sys_path_is_relative() * refactor: use std::filesystem for tr_sys_path_get_info() * refactor: use std::filesystem for tr_sys_dir_create() * refactor: add `maybe_set_error()` helper * refactor: change behavior to match previous impl * fix: tr_sys_path_is_same() checks refactor: address code review feedback * refactor: address code review feedback * chore: fix readability-else-after-return clang-tidy warning * fix: warning: Value stored to 'created' during its initialization is never read [clang-analyzer-deadcode.DeadStores] fix: warning: parameter 'permissions' is unused [misc-unused-parameters] * ci: work around a MSVC STL 14.44.35207 clang-tidy false warning * refactor: simplify return logic of tr_sys_path_is_same() --- gtk/DetailsDialog.cc | 6 +- gtk/Prefs.cc | 14 +- gtk/TorrentFilter.cc | 4 +- libtransmission/.clang-tidy | 5 + libtransmission/file-posix.cc | 186 --------------------------- libtransmission/file-win32.cc | 201 ----------------------------- libtransmission/file.cc | 233 ++++++++++++++++++++++++++++++++-- qt/main.cc | 20 +-- 8 files changed, 251 insertions(+), 418 deletions(-) diff --git a/gtk/DetailsDialog.cc b/gtk/DetailsDialog.cc index 7029202b3..323202300 100644 --- a/gtk/DetailsDialog.cc +++ b/gtk/DetailsDialog.cc @@ -1246,7 +1246,7 @@ void DetailsDialog::Impl::refreshPeerList(std::vector const& torren { auto const key = make_key(tor, peer); - if (hash.find(key) == hash.end()) + if (!hash.contains(key)) { auto const iter = store->append(); initPeerRow(iter, key, tr_torrentName(tor), peer); @@ -1314,7 +1314,7 @@ void DetailsDialog::Impl::refreshWebseedList(std::vector const& tor auto const* const url = tr_torrentWebseed(tor, j).url; auto const key = make_key(tor, url); - if (hash.find(key) == hash.end()) + if (!hash.contains(key)) { auto const iter = store->append(); (*iter)[webseed_cols.url] = url; @@ -1986,7 +1986,7 @@ void DetailsDialog::Impl::refreshTracker(std::vector const& torrent // build the key to find the row gstr.str({}); gstr << torrent_id << '\t' << tracker.tier << '\t' << tracker.announce; - if (hash.find(gstr.str()) == hash.end()) + if (!hash.contains(gstr.str())) { // if we didn't have that row, add it auto const iter = store->append(); diff --git a/gtk/Prefs.cc b/gtk/Prefs.cc index 82b2b86d7..5a81e336d 100644 --- a/gtk/Prefs.cc +++ b/gtk/Prefs.cc @@ -23,15 +23,10 @@ using namespace std::literals; using namespace tr::app; using tr::serializer::to_variant; -std::string gl_confdir; - -void gtr_pref_init(std::string_view config_dir) -{ - gl_confdir = config_dir; -} - namespace { +std::string gl_confdir; + [[nodiscard]] std::string get_default_download_dir() { if (auto dir = Glib::get_user_special_dir(TR_GLIB_USER_DIRECTORY(DOWNLOAD)); !std::empty(dir)) @@ -121,6 +116,11 @@ tr_variant& getPrefs() } } // namespace +void gtr_pref_init(std::string_view config_dir) +{ + gl_confdir = config_dir; +} + tr_variant& gtr_pref_get_all() { return getPrefs(); diff --git a/gtk/TorrentFilter.cc b/gtk/TorrentFilter.cc index 99db24039..86621515a 100644 --- a/gtk/TorrentFilter.cc +++ b/gtk/TorrentFilter.cc @@ -170,11 +170,11 @@ Glib::RefPtr TorrentFilter::create() return Glib::make_refptr_for_instance(new TorrentFilter()); } -bool TorrentFilter::match_mode(Torrent const& torrent, ShowMode const type) +bool TorrentFilter::match_mode(Torrent const& torrent, ShowMode const mode) { auto activity = tr_torrent_activity(); - switch (type) + switch (mode) { case ShowMode::ShowAll: return true; diff --git a/libtransmission/.clang-tidy b/libtransmission/.clang-tidy index 4cd544d27..a930da995 100644 --- a/libtransmission/.clang-tidy +++ b/libtransmission/.clang-tidy @@ -4,6 +4,10 @@ HeaderFilterRegex: .*/libtransmission/.* # TODO: Enable `portability-template-virtual-member-function` after https://github.com/llvm/llvm-project/issues/139031 is fixed # TODO: Enable `cppcoreguidelines-pro-bounds-pointer-arithmetic` after converting all pointers to std::span # TODO: Enable `modernize-use-integer-sign-comparison` (P0586R2) after GCC >= 10.1, clang >= 13 +# -clang-analyzer-optin.core.EnumCastOutOfRange: disabled due false warning in file.cc calling +# std::filesystem::last_write_time() on windows ci builds with MSVC STL 14.44.35207. +# Try re-enabling when the CI runner upgrades to a newer version. +# # PRs welcome to fix & re-enable any of these explicitly-disabled checks # # -modernize-use-ranges: GCC 10.1, clang 15 @@ -20,6 +24,7 @@ Checks: > -cert-err58-cpp, -cert-int09-c, clang-analyzer-*, + -clang-analyzer-optin.core.EnumCastOutOfRange, cppcoreguidelines-*, -cppcoreguidelines-avoid-c-arrays, -cppcoreguidelines-avoid-const-or-ref-data-members, diff --git a/libtransmission/file-posix.cc b/libtransmission/file-posix.cc index 661554f04..eeb07d02e 100644 --- a/libtransmission/file-posix.cc +++ b/libtransmission/file-posix.cc @@ -125,103 +125,6 @@ void set_file_for_single_pass(tr_sys_file_t handle) } } // namespace -bool tr_sys_path_exists(std::string_view const path, tr_error* error) -{ - auto const sz_path = tr_pathbuf{ path }; - bool const ret = access(sz_path.c_str(), F_OK) != -1; - - if (error != nullptr && !ret && errno != ENOENT) - { - error->set_from_errno(errno); - } - - return ret; -} - -namespace -{ -[[nodiscard]] auto stat_sv(std::string_view const path, struct stat* sb) -{ - auto const sz_path = tr_pathbuf{ path }; - return stat(sz_path.c_str(), sb); -} - -[[nodiscard]] auto lstat_sv(std::string_view const path, struct stat* sb) -{ - auto const sz_path = tr_pathbuf{ path }; - return lstat(sz_path.c_str(), sb); -} -} // namespace - -std::optional tr_sys_path_get_info(std::string_view const path, int const flags, tr_error* error) -{ - struct stat sb = {}; - - bool ok = false; - - if ((flags & TR_SYS_PATH_NO_FOLLOW) == 0) - { - ok = stat_sv(path, &sb) != -1; - } - else - { - ok = lstat_sv(path, &sb) != -1; - } - - if (!ok) - { - if (error != nullptr) - { - error->set_from_errno(errno); - } - - return {}; - } - - auto info = tr_sys_path_info{}; - - if (S_ISREG(sb.st_mode)) - { - info.type = TR_SYS_PATH_IS_FILE; - } - else if (S_ISDIR(sb.st_mode)) - { - info.type = TR_SYS_PATH_IS_DIRECTORY; - } - else - { - info.type = TR_SYS_PATH_IS_OTHER; - } - - info.size = static_cast(sb.st_size); - info.last_modified_at = sb.st_mtime; - - return info; -} - -bool tr_sys_path_is_relative(std::string_view path) -{ - return std::empty(path) || path.front() != '/'; -} - -bool tr_sys_path_is_same(std::string_view const path1, std::string_view const path2, tr_error* error) -{ - bool ret = false; - struct stat sb1 = {}; - struct stat sb2 = {}; - - if (stat_sv(path1, &sb1) != -1 && stat_sv(path2, &sb2) != -1) - { - ret = sb1.st_dev == sb2.st_dev && sb1.st_ino == sb2.st_ino; - } - else if (error != nullptr && errno != ENOENT) - { - error->set_from_errno(errno); - } - - return ret; -} - std::string_view tr_sys_path_basename(std::string_view path, tr_error* /*error*/) { // As per the basename() manpage: @@ -1002,95 +905,6 @@ std::string tr_sys_dir_get_current(tr_error* error) } } -namespace -{ -#ifndef HAVE_MKDIRP -[[nodiscard]] bool tr_mkdirp_(std::string_view path, int permissions, tr_error* error) -{ - auto walk = path.find_first_not_of('/'); // walk past the root - auto subpath = tr_pathbuf{}; - - while (walk < std::size(path)) - { - auto const end = path.find('/', walk); - subpath.assign(path.substr(0, end)); - auto const info = tr_sys_path_get_info(subpath, 0); - if (info && !info->isFolder()) - { - if (error != nullptr) - { - error->set(ENOTDIR, fmt::format("File is in the way: {:s}", path)); - } - - return false; - } - if (!info && mkdir(subpath, permissions) == -1) - { - if (error != nullptr) - { - error->set_from_errno(errno); - } - - return false; - } - if (end == std::string_view::npos) - { - break; - } - walk = end + 1; - } - - return true; -} -#endif -} // namespace - -bool tr_sys_dir_create(std::string_view const path, int const flags, int const permissions, tr_error* error) -{ - auto ret = false; - auto local_error = tr_error{}; - - auto const sz_path = tr_pathbuf{ path }; - - if ((flags & TR_SYS_DIR_CREATE_PARENTS) != 0) - { -#ifdef HAVE_MKDIRP - ret = mkdirp(sz_path.c_str(), permissions) != -1; -#else - ret = tr_mkdirp_(path, permissions, &local_error); -#endif - } - else - { - ret = mkdir(sz_path.c_str(), permissions) != -1; - } - - if (!ret && errno == EEXIST) - { - if (auto const info = tr_sys_path_get_info(path); info && info->type == TR_SYS_PATH_IS_DIRECTORY) - { - local_error = {}; - ret = true; - } - else - { - errno = EEXIST; - } - } - - if (error != nullptr && !ret) - { - if (!local_error) - { - local_error.set_from_errno(errno); - } - - *error = std::move(local_error); - } - - return ret; -} - bool tr_sys_dir_create_temp(char* path_template, tr_error* error) { TR_ASSERT(path_template != nullptr); diff --git a/libtransmission/file-win32.cc b/libtransmission/file-win32.cc index 76857e8ef..ed69b2f66 100644 --- a/libtransmission/file-win32.cc +++ b/libtransmission/file-win32.cc @@ -37,8 +37,6 @@ struct tr_sys_dir_win32 namespace { -auto constexpr DeltaEpochInMicrosecs = UINT64_C(11644473600000000); - auto constexpr NativeLocalPathPrefix = L"\\\\?\\"sv; auto constexpr NativeUncPathPrefix = L"\\\\?\\UNC\\"sv; @@ -59,49 +57,11 @@ void set_system_error_if_file_found(tr_error* error, DWORD code) } } -constexpr time_t filetime_to_unix_time(FILETIME const& t) -{ - uint64_t tmp = 0; - tmp |= t.dwHighDateTime; - tmp <<= 32; - tmp |= t.dwLowDateTime; - tmp /= 10; /* to microseconds */ - tmp -= DeltaEpochInMicrosecs; - - return tmp / 1000000UL; -} - constexpr bool to_bool(BOOL value) noexcept { return value != FALSE; } -constexpr auto stat_to_sys_path_info(DWORD attributes, DWORD size_low, DWORD size_high, FILETIME const& mtime) -{ - auto info = tr_sys_path_info{}; - - if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) - { - info.type = TR_SYS_PATH_IS_DIRECTORY; - } - else if ((attributes & (FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_VIRTUAL)) == 0) - { - info.type = TR_SYS_PATH_IS_FILE; - } - else - { - info.type = TR_SYS_PATH_IS_OTHER; - } - - info.size = size_high; - info.size <<= 32; - info.size |= size_low; - - info.last_modified_at = filetime_to_unix_time(mtime); - - return info; -} - auto constexpr Slashes = R"(\/)"sv; constexpr bool is_slash(char c) @@ -331,163 +291,7 @@ void create_temp_path(char* path_template, CallbackT const& callback, tr_error* } } -std::optional tr_sys_file_get_info_(tr_sys_file_t handle, tr_error* error) -{ - TR_ASSERT(handle != TR_BAD_SYS_FILE); - - auto attributes = BY_HANDLE_FILE_INFORMATION{}; - if (to_bool(GetFileInformationByHandle(handle, &attributes))) - { - return stat_to_sys_path_info( - attributes.dwFileAttributes, - attributes.nFileSizeLow, - attributes.nFileSizeHigh, - attributes.ftLastWriteTime); - } - - set_system_error(error, GetLastError()); - return {}; -} - -[[nodiscard]] std::optional get_file_info(std::string_view const path, tr_error* error) -{ - auto const wpath = path_to_native_path(path); - if (std::empty(wpath)) - { - set_system_error_if_file_found(error, GetLastError()); - return {}; - } - - auto const handle = CreateFileW(wpath.c_str(), 0, 0, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); - if (handle == INVALID_HANDLE_VALUE) - { - set_system_error_if_file_found(error, GetLastError()); - return {}; - } - - // TODO: Use GetFileInformationByHandleEx on >= Server 2012 - auto info = BY_HANDLE_FILE_INFORMATION{}; - if (!to_bool(GetFileInformationByHandle(handle, &info))) - { - set_system_error_if_file_found(error, GetLastError()); - CloseHandle(handle); - return {}; - } - - CloseHandle(handle); - return info; -} - } // namespace - -bool tr_sys_path_exists(std::string_view const path, tr_error* error) -{ - bool ret = false; - HANDLE handle = INVALID_HANDLE_VALUE; - - if (auto const wide_path = path_to_native_path(path); !std::empty(wide_path)) - { - DWORD const attributes = GetFileAttributesW(wide_path.c_str()); - - if (attributes != INVALID_FILE_ATTRIBUTES) - { - if ((attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) - { - handle = CreateFileW(wide_path.c_str(), 0, 0, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); - ret = handle != INVALID_HANDLE_VALUE; - } - else - { - ret = true; - } - } - } - - if (!ret) - { - set_system_error_if_file_found(error, GetLastError()); - } - - if (handle != INVALID_HANDLE_VALUE) - { - CloseHandle(handle); - } - - return ret; -} - -std::optional tr_sys_path_get_info(std::string_view path, int flags, tr_error* error) -{ - if (auto const wide_path = path_to_native_path(path); std::empty(wide_path)) - { - // do nothing - } - else if ((flags & TR_SYS_PATH_NO_FOLLOW) != 0) - { - auto attributes = WIN32_FILE_ATTRIBUTE_DATA{}; - if (to_bool(GetFileAttributesExW(wide_path.c_str(), GetFileExInfoStandard, &attributes))) - { - return stat_to_sys_path_info( - attributes.dwFileAttributes, - attributes.nFileSizeLow, - attributes.nFileSizeHigh, - attributes.ftLastWriteTime); - } - } - else if (auto const - handle = CreateFileW(wide_path.c_str(), 0, 0, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); - handle != INVALID_HANDLE_VALUE) - { - auto ret = tr_sys_file_get_info_(handle, error); - CloseHandle(handle); - return ret; - } - - set_system_error(error, GetLastError()); - return {}; -} - -bool tr_sys_path_is_relative(std::string_view path) -{ - /* UNC path: `\\...`. */ - if (is_unc_path(path)) - { - return false; - } - - /* Local path: `X:` */ - if (std::size(path) == 2 && isalpha(path[0]) != 0 && path[1] == ':') - { - return false; - } - - /* Local path: `X:\...`. */ - if (std::size(path) > 2 && isalpha(path[0]) != 0 && path[1] == ':' && is_slash(path[2])) - { - return false; - } - - return true; -} - -bool tr_sys_path_is_same(std::string_view const path1, std::string_view const path2, tr_error* error) -{ - auto const fi1 = get_file_info(path1, error); - if (!fi1) - { - return false; - } - - auto const fi2 = get_file_info(path2, error); - if (!fi2) - { - return false; - } - - return fi1->dwVolumeSerialNumber == fi2->dwVolumeSerialNumber && fi1->nFileIndexHigh == fi2->nFileIndexHigh && - fi1->nFileIndexLow == fi2->nFileIndexLow; -} - std::string_view tr_sys_path_basename(std::string_view path, tr_error* error) { if (std::empty(path)) @@ -1048,11 +852,6 @@ std::string tr_sys_dir_get_current(tr_error* error) return {}; } -bool tr_sys_dir_create(std::string_view const path, int const flags, int const permissions, tr_error* error) -{ - return create_dir(path, flags, permissions, true, error); -} - bool tr_sys_dir_create_temp(char* path_template, tr_error* error) { TR_ASSERT(path_template != nullptr); diff --git a/libtransmission/file.cc b/libtransmission/file.cc index aac39efaf..a32215bfe 100644 --- a/libtransmission/file.cc +++ b/libtransmission/file.cc @@ -3,6 +3,7 @@ // or any future license endorsed by Mnemosyne LLC. // License text can be found in the licenses/ folder. +#include #include #include #include @@ -12,6 +13,19 @@ #include "libtransmission/error.h" #include "libtransmission/file.h" +namespace +{ + +void maybe_set_error(tr_error* error, std::error_code const& ec) +{ + if (error != nullptr && ec) + { + error->set(ec.value(), ec.message()); + } +} + +} // namespace + std::string tr_sys_path_resolve(std::string_view path, tr_error* error) { auto ec = std::error_code{}; @@ -19,11 +33,7 @@ std::string tr_sys_path_resolve(std::string_view path, tr_error* error) if (ec) { - if (error != nullptr) - { - error->set(ec.value(), ec.message()); - } - + maybe_set_error(error, ec); return {}; } @@ -31,6 +41,214 @@ std::string tr_sys_path_resolve(std::string_view path, tr_error* error) return { std::begin(u8_path), std::end(u8_path) }; } +bool tr_sys_path_is_relative(std::string_view path) +{ +#ifdef _WIN32 + auto const is_slash = [](char ch) + { + return ch == '/' || ch == '\\'; + }; + + if (std::size(path) >= 2 && is_slash(path[0]) && path[1] == path[0]) + { + return false; + } + + if (std::size(path) == 2 && std::isalpha(static_cast(path[0])) != 0 && path[1] == ':') + { + return false; + } + + if (std::size(path) > 2 && std::isalpha(static_cast(path[0])) != 0 && path[1] == ':' && is_slash(path[2])) + { + return false; + } + + return true; +#else + return std::empty(path) || path.front() != '/'; +#endif +} + +bool tr_sys_path_exists(std::string_view path, tr_error* error) +{ + auto ec = std::error_code{}; + auto const exists = std::filesystem::exists(tr_u8path(path), ec); + maybe_set_error(error, ec); + return exists; +} + +std::optional tr_sys_path_get_info(std::string_view path, int flags, tr_error* error) +{ + auto const filesystem_path = tr_u8path(path); + + auto ec = std::error_code{}; + auto const status = (flags & TR_SYS_PATH_NO_FOLLOW) != 0 ? std::filesystem::symlink_status(filesystem_path, ec) : + std::filesystem::status(filesystem_path, ec); + + if (ec || status.type() == std::filesystem::file_type::not_found) + { + maybe_set_error(error, ec ? ec : std::make_error_code(std::errc::no_such_file_or_directory)); + return {}; + } + + auto info = tr_sys_path_info{}; + + if (std::filesystem::is_regular_file(status)) + { + info.type = TR_SYS_PATH_IS_FILE; + info.size = std::filesystem::file_size(filesystem_path, ec); + if (ec) + { + maybe_set_error(error, ec); + return {}; + } + } + else if (std::filesystem::is_directory(status)) + { + info.type = TR_SYS_PATH_IS_DIRECTORY; + info.size = 0; + } + else + { + info.type = TR_SYS_PATH_IS_OTHER; + info.size = 0; + } + + auto const ftime = std::filesystem::last_write_time(filesystem_path, ec); + if (ec) + { + maybe_set_error(error, ec); + return {}; + } + + // TODO: use std::chrono::clock_cast when available. + // https://github.com/llvm/llvm-project/issues/166050 + auto const sctp = std::chrono::time_point_cast( + ftime - std::filesystem::file_time_type::clock::now() + std::chrono::system_clock::now()); + info.last_modified_at = std::chrono::system_clock::to_time_t(sctp); + + return info; +} + +bool tr_sys_path_is_same(std::string_view path1, std::string_view path2, tr_error* error) +{ + auto const u8path1 = tr_u8path(path1); + auto const u8path2 = tr_u8path(path2); + + // std::filesystem::equivalent() returns an unspecified error + // when either path doesn't exist. libstdc++ and libc++ chose + // different errors. So let's check `exists` here for consistency. + auto ec = std::error_code{}; + if (!std::filesystem::exists(u8path1, ec) || !std::filesystem::exists(u8path2, ec)) + { + maybe_set_error(error, ec); + return false; + } + + auto const same = std::filesystem::equivalent(u8path1, u8path2, ec); + maybe_set_error(error, ec); + return same; +} + +bool tr_sys_dir_create(std::string_view path, int flags, [[maybe_unused]] int permissions, tr_error* error) +{ + auto const filesystem_path = tr_u8path(path); + auto const parents = (flags & TR_SYS_DIR_CREATE_PARENTS) != 0; + +#ifndef _WIN32 + auto missing = std::vector{}; + if (parents && permissions != 0) + { + auto current = std::filesystem::path{}; + for (auto const& part : filesystem_path) + { + current /= part; + auto check_ec = std::error_code{}; + if (std::filesystem::is_directory(current, check_ec)) + { + continue; + } + + if (check_ec && check_ec != std::errc::no_such_file_or_directory) + { + maybe_set_error(error, check_ec); + return false; + } + + missing.emplace_back(current); + } + } +#endif + + auto ec = std::error_code{}; + if (std::filesystem::is_directory(filesystem_path, ec)) + { + return true; + } + + if (ec && ec != std::errc::no_such_file_or_directory) + { + maybe_set_error(error, ec); + return false; + } + + ec = {}; + if (parents) + { + std::filesystem::create_directories(filesystem_path, ec); + } + else + { + std::filesystem::create_directory(filesystem_path, ec); + } + + if (ec) + { + maybe_set_error(error, ec); + return false; + } + +#ifndef _WIN32 + if (permissions != 0) + { + auto const apply_permissions = [&](std::filesystem::path const& target) + { + auto perm_ec = std::error_code{}; + std::filesystem::permissions( + target, + static_cast(permissions), + std::filesystem::perm_options::replace, + perm_ec); + if (perm_ec) + { + maybe_set_error(error, perm_ec); + return false; + } + + return true; + }; + + if (parents) + { + for (auto const& created_path : missing) + { + if (!apply_permissions(created_path)) + { + return false; + } + } + } + else if (!apply_permissions(filesystem_path)) + { + return false; + } + } +#endif + + return true; +} + std::vector tr_sys_dir_get_files( std::string_view folder, std::function const& test, @@ -74,9 +292,6 @@ std::optional tr_sys_path_get_capacity(std::filesys return space; } - if (error != nullptr) - { - error->set(ec.value(), ec.message()); - } + maybe_set_error(error, ec); return {}; } diff --git a/qt/main.cc b/qt/main.cc index 8b0829575..00233951b 100644 --- a/qt/main.cc +++ b/qt/main.cc @@ -118,32 +118,32 @@ int tr_main(int argc, char** argv) QStringList filenames; int opt = 0; - char const* optarg = nullptr; + char const* arg = nullptr; int file_args_start_idx = -1; int qt_args_start_idx = -1; while (file_args_start_idx < 0 && qt_args_start_idx < 0 && - (opt = tr_getopt(getUsage(), argc, static_cast(argv), std::data(Opts), &optarg)) != TR_OPT_DONE) + (opt = tr_getopt(getUsage(), argc, static_cast(argv), std::data(Opts), &arg)) != TR_OPT_DONE) { switch (opt) { case 'g': - config_dir = QString::fromUtf8(optarg); + config_dir = QString::fromUtf8(arg); break; case 'p': - port = QString::fromUtf8(optarg); + port = QString::fromUtf8(arg); break; case 'r': - host = QString::fromUtf8(optarg); + host = QString::fromUtf8(arg); break; case 'u': - username = QString::fromUtf8(optarg); + username = QString::fromUtf8(arg); break; case 'w': - password = QString::fromUtf8(optarg); + password = QString::fromUtf8(arg); break; case 'm': @@ -160,17 +160,17 @@ int tr_main(int argc, char** argv) return 1; default: - if (optarg == FileArgsSeparator) + if (arg == FileArgsSeparator) { file_args_start_idx = tr_optind; } - else if (optarg == QtArgsSeparator) + else if (arg == QtArgsSeparator) { qt_args_start_idx = tr_optind; } else { - filenames.append(QString::fromUtf8(optarg)); + filenames.append(QString::fromUtf8(arg)); } break;