diff --git a/daemon/daemon.cc b/daemon/daemon.cc index 5c553ad77..8c82e09ff 100644 --- a/daemon/daemon.cc +++ b/daemon/daemon.cc @@ -268,7 +268,7 @@ auto onFileAdded(tr_session* session, std::string_view dirname, std::string_view } void printMessage( - tr_sys_file_t file, + FILE* ostream, tr_log_level level, std::string_view name, std::string_view message, @@ -286,11 +286,11 @@ void printMessage( fmt::format_to(std::back_inserter(out), "{:s} {:s} ({:s}:{:d})", name, message, filename, line); } - if (file != TR_BAD_SYS_FILE) + if (ostream != nullptr) { auto timestr = std::array{}; tr_logGetTimeStr(std::data(timestr), std::size(timestr)); - tr_sys_file_write_line(file, fmt::format("[{:s}] {:s} {:s}", std::data(timestr), levelName(level), std::data(out))); + fmt::print(ostream, "[{:s}] {:s} {:s}\n", std::data(timestr), levelName(level), out.c_str()); } #ifdef HAVE_SYSLOG @@ -329,18 +329,21 @@ void printMessage( #endif } -void pumpLogMessages(tr_sys_file_t file, bool flush) +void pumpLogMessages(FILE* log_stream) { tr_log_message* list = tr_logGetQueue(); for (tr_log_message const* l = list; l != nullptr; l = l->next) { - printMessage(file, l->level, l->name, l->message, l->file, l->line); + printMessage(log_stream, l->level, l->name, l->message, l->file, l->line); } - if (flush && file != TR_BAD_SYS_FILE) + // two reasons to not flush stderr: + // 1. it's usually redundant, since stderr flushes itself + // 2. when running as a systemd unit, it's redirected to a socket + if (log_stream != stderr) { - tr_sys_file_flush(file); + fflush(log_stream); } tr_logFreeQueue(list); @@ -374,31 +377,26 @@ tr_variant load_settings(char const* config_dir) bool tr_daemon::reopen_log_file(char const* filename) { - auto error = tr_error{}; - tr_sys_file_t const old_log_file = logfile_; - tr_sys_file_t const new_log_file = tr_sys_file_open( - filename, - TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE | TR_SYS_FILE_APPEND, - 0666, - &error); + auto* const old_stream = log_stream_; - if (new_log_file == TR_BAD_SYS_FILE) + auto* new_stream = std::fopen(filename, "a"); + if (new_stream == nullptr) { + auto const err = errno; auto const errmsg = fmt::format( "Couldn't open '{path}': {error} ({error_code})", fmt::arg("path", filename), - fmt::arg("error", error.message()), - fmt::arg("error_code", error.code())); + fmt::arg("error", tr_strerror(err)), + fmt::arg("error_code", err)); fmt::print(stderr, "{:s}\n", errmsg); return false; } - logfile_ = new_log_file; - logfile_flush_ = tr_sys_file_flush_possible(logfile_); + log_stream_ = new_stream; - if (old_log_file != TR_BAD_SYS_FILE) + if (old_stream != nullptr && old_stream != stderr) { - tr_sys_file_close(old_log_file); + fclose(old_stream); } return true; @@ -421,7 +419,7 @@ void tr_daemon::report_status() void tr_daemon::periodic_update() { - pumpLogMessages(logfile_, logfile_flush_); + pumpLogMessages(log_stream_); report_status(); } @@ -710,7 +708,7 @@ int tr_daemon::start([[maybe_unused]] bool foreground) _("Couldn't initialize daemon: {error} ({error_code})"), fmt::arg("error", tr_strerror(error_code)), fmt::arg("error_code", error_code)); - printMessage(logfile_, TR_LOG_ERROR, MyName, errmsg, __FILE__, __LINE__); + printMessage(log_stream_, TR_LOG_ERROR, MyName, errmsg, __FILE__, __LINE__); cleanup_signals(sig_ev); return 1; } @@ -870,7 +868,7 @@ CLEANUP: tr_sessionSaveSettings(my_session_, cdir, settings_); tr_sessionClose(my_session_); - pumpLogMessages(logfile_, logfile_flush_); + pumpLogMessages(log_stream_); printf(" done.\n"); /* shutdown */ @@ -912,10 +910,9 @@ bool tr_daemon::init(int argc, char const* const argv[], bool* foreground, int* return false; } - if (*foreground && logfile_ == TR_BAD_SYS_FILE) + if (*foreground && log_stream_ == nullptr) { - logfile_ = tr_sys_file_get_std(TR_STD_SYS_FILE_ERR); - logfile_flush_ = tr_sys_file_flush_possible(logfile_); + log_stream_ = stderr; } if (dumpSettings) @@ -930,7 +927,7 @@ bool tr_daemon::init(int argc, char const* const argv[], bool* foreground, int* void tr_daemon::handle_error(tr_error const& error) const { auto const errmsg = fmt::format("Couldn't daemonize: {:s} ({:d})", error.message(), error.code()); - printMessage(logfile_, TR_LOG_ERROR, MyName, errmsg, __FILE__, __LINE__); + printMessage(log_stream_, TR_LOG_ERROR, MyName, errmsg, __FILE__, __LINE__); } int tr_main(int argc, char* argv[]) diff --git a/daemon/daemon.h b/daemon/daemon.h index d22c5e26a..a25eea529 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -5,6 +5,7 @@ #pragma once +#include #include #ifdef HAVE_SYS_SIGNALFD_H @@ -13,7 +14,6 @@ #include #include -#include struct event_base; struct tr_error; @@ -50,11 +50,10 @@ private: bool seen_hup_ = false; std::string config_dir_; tr_variant settings_ = {}; - bool logfile_flush_ = false; tr_session* my_session_ = nullptr; char const* log_file_name_ = nullptr; struct event_base* ev_base_ = nullptr; - tr_sys_file_t logfile_ = TR_BAD_SYS_FILE; + FILE* log_stream_ = nullptr; bool parse_args(int argc, char const* const* argv, bool* dump_settings, bool* foreground, int* exit_code); bool reopen_log_file(char const* filename); diff --git a/libtransmission/file-posix.cc b/libtransmission/file-posix.cc index 2e261d00f..9644c2617 100644 --- a/libtransmission/file-posix.cc +++ b/libtransmission/file-posix.cc @@ -545,37 +545,6 @@ char* tr_sys_path_native_separators(char* path) return path; } -tr_sys_file_t tr_sys_file_get_std(tr_std_sys_file_t std_file, tr_error* error) -{ - tr_sys_file_t ret = TR_BAD_SYS_FILE; - - switch (std_file) - { - case TR_STD_SYS_FILE_IN: - ret = STDIN_FILENO; - break; - - case TR_STD_SYS_FILE_OUT: - ret = STDOUT_FILENO; - break; - - case TR_STD_SYS_FILE_ERR: - ret = STDERR_FILENO; - break; - - default: - TR_ASSERT_MSG(false, fmt::format("unknown standard file {:d}", static_cast(std_file))); - - if (error != nullptr) - { - error->set_from_errno(EINVAL); - } - break; - } - - return ret; -} - tr_sys_file_t tr_sys_file_open(char const* path, int flags, int permissions, tr_error* error) { TR_ASSERT(path != nullptr); @@ -811,23 +780,6 @@ bool tr_sys_file_flush(tr_sys_file_t handle, tr_error* error) return ret; } -bool tr_sys_file_flush_possible(tr_sys_file_t handle, tr_error* error) -{ - TR_ASSERT(handle != TR_BAD_SYS_FILE); - - if (struct stat statbuf = {}; fstat(handle, &statbuf) == 0) - { - return S_ISREG(statbuf.st_mode); - } - - if (error != nullptr) - { - error->set_from_errno(errno); - } - - return false; -} - bool tr_sys_file_truncate(tr_sys_file_t handle, uint64_t size, tr_error* error) { TR_ASSERT(handle != TR_BAD_SYS_FILE); diff --git a/libtransmission/file-win32.cc b/libtransmission/file-win32.cc index e3b2119bc..d04717106 100644 --- a/libtransmission/file-win32.cc +++ b/libtransmission/file-win32.cc @@ -819,42 +819,6 @@ char* tr_sys_path_native_separators(char* path) return path; } -tr_sys_file_t tr_sys_file_get_std(tr_std_sys_file_t std_file, tr_error* error) -{ - tr_sys_file_t ret = TR_BAD_SYS_FILE; - - switch (std_file) - { - case TR_STD_SYS_FILE_IN: - ret = GetStdHandle(STD_INPUT_HANDLE); - break; - - case TR_STD_SYS_FILE_OUT: - ret = GetStdHandle(STD_OUTPUT_HANDLE); - break; - - case TR_STD_SYS_FILE_ERR: - ret = GetStdHandle(STD_ERROR_HANDLE); - break; - - default: - TR_ASSERT_MSG(false, fmt::format("unknown standard file {:d}", std_file)); - set_system_error(error, ERROR_INVALID_PARAMETER); - return TR_BAD_SYS_FILE; - } - - if (ret == TR_BAD_SYS_FILE) - { - set_system_error(error, GetLastError()); - } - else if (ret == nullptr) - { - ret = TR_BAD_SYS_FILE; - } - - return ret; -} - tr_sys_file_t tr_sys_file_open(char const* path, int flags, int /*permissions*/, tr_error* error) { TR_ASSERT(path != nullptr); @@ -1097,21 +1061,6 @@ bool tr_sys_file_flush(tr_sys_file_t handle, tr_error* error) return ret; } -bool tr_sys_file_flush_possible(tr_sys_file_t handle, tr_error* error) -{ - TR_ASSERT(handle != TR_BAD_SYS_FILE); - - DWORD type = GetFileType(handle); - - if (type == FILE_TYPE_UNKNOWN) - { - set_system_error(error, GetLastError()); - return false; - } - - return type == FILE_TYPE_DISK; -} - bool tr_sys_file_truncate(tr_sys_file_t handle, uint64_t size, tr_error* error) { TR_ASSERT(handle != TR_BAD_SYS_FILE); diff --git a/libtransmission/file.cc b/libtransmission/file.cc index b87c22678..4f2d6a867 100644 --- a/libtransmission/file.cc +++ b/libtransmission/file.cc @@ -11,22 +11,6 @@ #include "libtransmission/file.h" #include "libtransmission/tr-assert.h" -using namespace std::literals; - -#ifdef _WIN32 -static auto constexpr NativeEol = "\r\n"sv; -#else -static auto constexpr NativeEol = "\n"sv; -#endif - -bool tr_sys_file_write_line(tr_sys_file_t handle, std::string_view buffer, tr_error* error) -{ - TR_ASSERT(handle != TR_BAD_SYS_FILE); - - return tr_sys_file_write(handle, std::data(buffer), std::size(buffer), nullptr, error) && - tr_sys_file_write(handle, std::data(NativeEol), std::size(NativeEol), nullptr, error); -} - std::vector tr_sys_dir_get_files( std::string_view folder, std::function const& test, diff --git a/libtransmission/file.h b/libtransmission/file.h index 3f6a00df6..e31dac876 100644 --- a/libtransmission/file.h +++ b/libtransmission/file.h @@ -45,13 +45,6 @@ using tr_sys_dir_t = tr_sys_dir_win32*; /** @brief Platform-specific invalid directory descriptor constant. */ #define TR_BAD_SYS_DIR ((tr_sys_dir_t) nullptr) -enum tr_std_sys_file_t -{ - TR_STD_SYS_FILE_IN, - TR_STD_SYS_FILE_OUT, - TR_STD_SYS_FILE_ERR -}; - enum tr_sys_file_open_flags_t { TR_SYS_FILE_READ = (1 << 0), @@ -301,19 +294,6 @@ char* tr_sys_path_native_separators(char* path); /* File-related wrappers */ -/** - * @brief Get handle to one of standard I/O files. - * - * @param[in] std_file Standard file identifier. - * @param[out] error Pointer to error object. Optional, pass `nullptr` if you - * are not interested in error details. - * - * @return Opened file descriptor on success, `TR_BAD_SYS_FILE` otherwise (with - * `error` set accordingly). DO NOT pass this descriptor to - * @ref tr_sys_file_close (unless you know what you are doing). - */ -tr_sys_file_t tr_sys_file_get_std(tr_std_sys_file_t std_file, tr_error* error = nullptr); - /** * @brief Portability wrapper for `open()`. * @@ -448,9 +428,6 @@ bool tr_sys_file_write_at( */ bool tr_sys_file_flush(tr_sys_file_t handle, tr_error* error = nullptr); -/* @brief Check whether `handle` may be flushed via `tr_sys_file_flush()`. */ -bool tr_sys_file_flush_possible(tr_sys_file_t handle, tr_error* error = nullptr); - /** * @brief Portability wrapper for `ftruncate()`. * @@ -491,26 +468,6 @@ bool tr_sys_file_preallocate(tr_sys_file_t handle, uint64_t size, int flags, tr_ */ bool tr_sys_file_lock(tr_sys_file_t handle, int operation, tr_error* error = nullptr); -/* File-related wrappers (utility) */ - -/** - * @brief Portability wrapper for `fputs()`, appending EOL internally. - * - * Special care should be taken when writing to one of standard output streams - * (@ref tr_std_sys_file_t) since no UTF-8 conversion is currently being made. - * - * Writing to other streams (files, pipes) also leaves data untouched, so it - * should already be in UTF-8 encoding, or whichever else you expect. - * - * @param[in] handle Valid file descriptor. - * @param[in] buffer String to write. - * @param[out] error Pointer to error object. Optional, pass `nullptr` if you - * are not interested in error details. - * - * @return `True` on success, `false` otherwise (with `error` set accordingly). - */ -bool tr_sys_file_write_line(tr_sys_file_t handle, std::string_view buffer, tr_error* error = nullptr); - /* Directory-related wrappers */ /** diff --git a/libtransmission/log.cc b/libtransmission/log.cc index 92115c928..47a52ca90 100644 --- a/libtransmission/log.cc +++ b/libtransmission/log.cc @@ -134,26 +134,17 @@ void logAddImpl( } else { - static auto const fp = tr_sys_file_get_std(TR_STD_SYS_FILE_ERR); - if (fp == TR_BAD_SYS_FILE) - { - return; - } - auto timestr = std::array{}; tr_logGetTimeStr(std::data(timestr), std::size(timestr)); - auto buf = tr_strbuf{}; if (std::empty(name)) { - fmt::format_to(std::back_inserter(buf), "[{:s}] {:s}", std::data(timestr), msg); + fmt::print(stderr, "[{:s}] {:s}\n", std::data(timestr), msg); } else { - fmt::format_to(std::back_inserter(buf), "[{:s}] {:s}: {:s}", std::data(timestr), name, msg); + fmt::print("[{:s}] {:s}: {:s}\n", std::data(timestr), name, msg); } - tr_sys_file_write_line(fp, buf); - tr_sys_file_flush(fp); } #endif } diff --git a/tests/libtransmission/subprocess-test-program.cc b/tests/libtransmission/subprocess-test-program.cc index 97eddd82a..82343afd8 100644 --- a/tests/libtransmission/subprocess-test-program.cc +++ b/tests/libtransmission/subprocess-test-program.cc @@ -3,9 +3,12 @@ // or any future license endorsed by Mnemosyne LLC. // License text can be found in the licenses/ folder. -#include // tr_sys_file_write_line(), tr_sys_file_close(), tr_sy... +#include // tr_sys_dir_get_current() #include // tr_env_get_string() +#include + +#include #include int main(int argc, char** argv) @@ -19,13 +22,8 @@ int main(int argc, char** argv) auto const test_action = std::string{ argv[2] }; auto const tmp_result_path = result_path + ".tmp"; - auto fd = tr_sys_file_open( - tmp_result_path.data(), // NOLINT - TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE | TR_SYS_FILE_TRUNCATE, - 0644, - nullptr); - - if (fd == TR_BAD_SYS_FILE) + FILE* out = std::fopen(tmp_result_path.c_str(), "w+"); + if (out == nullptr) { return 1; } @@ -34,30 +32,35 @@ int main(int argc, char** argv) { for (int i = 3; i < argc; ++i) { - tr_sys_file_write_line(fd, argv[i]); + fmt::print(out, "{:s}\n", argv[i]); } } else if (test_action == "--dump-env") { for (int i = 3; i < argc; ++i) { - auto const value = tr_env_get_string(argv[i], ""); - tr_sys_file_write_line(fd, value); + fmt::print(out, "{:s}\n", tr_env_get_string(argv[i], "")); } } else if (test_action == "--dump-cwd") { - auto const value = tr_sys_dir_get_current(nullptr); - tr_sys_file_write_line(fd, !std::empty(value) ? value : ""); + auto cwd = tr_sys_dir_get_current(nullptr); + + if (std::empty(cwd)) + { + cwd = ""; + } + + fmt::print(out, "{:s}\n", cwd); } else { - tr_sys_file_close(fd); - tr_sys_path_remove(tmp_result_path.data()); + std::fclose(out); + std::remove(tmp_result_path.c_str()); return 1; } - tr_sys_file_close(fd); - tr_sys_path_rename(tmp_result_path.data(), result_path.data()); + std::fclose(out); + tr_sys_path_rename(tmp_result_path.c_str(), result_path.c_str()); return 0; }