refactor: replace tr_sys_file_write_line() with fmt::print("...\n") (#6619)

* refactor: use fmt::print in log.cc

https://github.com/fmtlib/fmt/issues/428#issuecomment-395442159
> You can use fmt::print("...\n") on Windows as well.

Use this mechanism instead of tr_sys_file_write_line()

* refactor: use FILE* in daemon

* refactor: remove unused tr_sys_file_flush_possible()

* refactor: remove unused tr_sys_file_write_line()

* refactor: remove unused tr_sys_file_get_std()

* refactor: remove unused tr_std_sys_file_t
This commit is contained in:
Charles Kerr 2024-02-25 16:12:08 -06:00 committed by GitHub
parent 7f029acf6e
commit 1855cdb731
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 49 additions and 217 deletions

View File

@ -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<char, 64>{};
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[])

View File

@ -5,6 +5,7 @@
#pragma once
#include <cstdio>
#include <string>
#ifdef HAVE_SYS_SIGNALFD_H
@ -13,7 +14,6 @@
#include <libtransmission/variant.h>
#include <libtransmission/quark.h>
#include <libtransmission/file.h>
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);

View File

@ -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<int>(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);

View File

@ -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);

View File

@ -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<std::string> tr_sys_dir_get_files(
std::string_view folder,
std::function<bool(std::string_view)> const& test,

View File

@ -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 */
/**

View File

@ -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<char, 64U>{};
tr_logGetTimeStr(std::data(timestr), std::size(timestr));
auto buf = tr_strbuf<char, 2048U>{};
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
}

View File

@ -3,9 +3,12 @@
// or any future license endorsed by Mnemosyne LLC.
// License text can be found in the licenses/ folder.
#include <libtransmission/file.h> // tr_sys_file_write_line(), tr_sys_file_close(), tr_sy...
#include <libtransmission/file.h> // tr_sys_dir_get_current()
#include <libtransmission/utils.h> // tr_env_get_string()
#include <fmt/core.h>
#include <cstdio>
#include <string>
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], "<null>");
tr_sys_file_write_line(fd, value);
fmt::print(out, "{:s}\n", tr_env_get_string(argv[i], "<null>"));
}
}
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 : "<null>");
auto cwd = tr_sys_dir_get_current(nullptr);
if (std::empty(cwd))
{
cwd = "<null>";
}
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;
}