refactor: make tr_buildPath() private (#2374)
This commit is contained in:
parent
eafbf59832
commit
a5c6168805
|
@ -7,7 +7,9 @@
|
|||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdarg>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
@ -48,6 +50,50 @@
|
|||
|
||||
using namespace std::literals;
|
||||
|
||||
static char* tr_buildPath(char const* first_element, ...)
|
||||
{
|
||||
// pass 1: allocate enough space for the string
|
||||
va_list vl;
|
||||
va_start(vl, first_element);
|
||||
auto bufLen = size_t{};
|
||||
for (char const* element = first_element; element != nullptr;)
|
||||
{
|
||||
bufLen += strlen(element) + 1;
|
||||
element = va_arg(vl, char const*);
|
||||
}
|
||||
va_end(vl);
|
||||
char* const buf = tr_new(char, bufLen);
|
||||
if (buf == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* pass 2: build the string piece by piece */
|
||||
char* pch = buf;
|
||||
va_start(vl, first_element);
|
||||
for (char const* element = first_element; element != nullptr;)
|
||||
{
|
||||
size_t const elementLen = strlen(element);
|
||||
pch = std::copy_n(element, elementLen, pch);
|
||||
*pch++ = TR_PATH_DELIMITER;
|
||||
element = va_arg(vl, char const*);
|
||||
}
|
||||
va_end(vl);
|
||||
|
||||
// if nonempty, eat the unwanted trailing slash
|
||||
if (pch != buf)
|
||||
{
|
||||
--pch;
|
||||
}
|
||||
|
||||
// zero-terminate the string
|
||||
*pch++ = '\0';
|
||||
|
||||
/* sanity checks & return */
|
||||
TR_ASSERT(pch - buf == (ptrdiff_t)bufLen);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/***
|
||||
**** THREADS
|
||||
***/
|
||||
|
@ -219,32 +265,28 @@ static char const* getHomeDir(void)
|
|||
#define TORRENT_SUBDIR "torrents"
|
||||
#endif
|
||||
|
||||
void tr_setConfigDir(tr_session* session, char const* configDir)
|
||||
void tr_setConfigDir(tr_session* session, std::string_view config_dir)
|
||||
{
|
||||
session->configDir = tr_strdup(configDir);
|
||||
|
||||
char* path = tr_buildPath(configDir, RESUME_SUBDIR, nullptr);
|
||||
tr_sys_dir_create(path, TR_SYS_DIR_CREATE_PARENTS, 0777, nullptr);
|
||||
session->resumeDir = path;
|
||||
|
||||
path = tr_buildPath(configDir, TORRENT_SUBDIR, nullptr);
|
||||
tr_sys_dir_create(path, TR_SYS_DIR_CREATE_PARENTS, 0777, nullptr);
|
||||
session->torrentDir = path;
|
||||
session->config_dir = config_dir;
|
||||
session->resume_dir = tr_strvPath(config_dir, RESUME_SUBDIR);
|
||||
session->torrent_dir = tr_strvPath(config_dir, TORRENT_SUBDIR);
|
||||
tr_sys_dir_create(session->resume_dir.c_str(), TR_SYS_DIR_CREATE_PARENTS, 0777, nullptr);
|
||||
tr_sys_dir_create(session->torrent_dir.c_str(), TR_SYS_DIR_CREATE_PARENTS, 0777, nullptr);
|
||||
}
|
||||
|
||||
char const* tr_sessionGetConfigDir(tr_session const* session)
|
||||
{
|
||||
return session->configDir;
|
||||
return session->config_dir.c_str();
|
||||
}
|
||||
|
||||
char const* tr_getTorrentDir(tr_session const* session)
|
||||
{
|
||||
return session->torrentDir;
|
||||
return session->torrent_dir.c_str();
|
||||
}
|
||||
|
||||
char const* tr_getResumeDir(tr_session const* session)
|
||||
{
|
||||
return session->resumeDir;
|
||||
return session->resume_dir.c_str();
|
||||
}
|
||||
|
||||
char const* tr_getDefaultConfigDir(char const* appname)
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
/**
|
||||
* @addtogroup tr_session Session
|
||||
|
@ -25,7 +26,7 @@
|
|||
* @see tr_getTorrentDir()
|
||||
* @see tr_getWebClientDir()
|
||||
*/
|
||||
void tr_setConfigDir(tr_session* session, char const* configDir);
|
||||
void tr_setConfigDir(tr_session* session, std::string_view config_dir);
|
||||
|
||||
/** @brief return the directory where .resume files are stored */
|
||||
char const* tr_getResumeDir(tr_session const*);
|
||||
|
|
|
@ -472,7 +472,7 @@ void tr_sessionGetSettings(tr_session const* s, tr_variant* d)
|
|||
tr_variantDictAddBool(d, TR_KEY_anti_brute_force_enabled, tr_sessionGetAntiBruteForceEnabled(s));
|
||||
}
|
||||
|
||||
bool tr_sessionLoadSettings(tr_variant* dict, char const* configDir, char const* appName)
|
||||
bool tr_sessionLoadSettings(tr_variant* dict, char const* config_dir, char const* appName)
|
||||
{
|
||||
TR_ASSERT(tr_variantIsDict(dict));
|
||||
|
||||
|
@ -485,14 +485,14 @@ bool tr_sessionLoadSettings(tr_variant* dict, char const* configDir, char const*
|
|||
tr_variantFree(&oldDict);
|
||||
|
||||
/* if caller didn't specify a config dir, use the default */
|
||||
if (tr_str_is_empty(configDir))
|
||||
if (tr_str_is_empty(config_dir))
|
||||
{
|
||||
configDir = tr_getDefaultConfigDir(appName);
|
||||
config_dir = tr_getDefaultConfigDir(appName);
|
||||
}
|
||||
|
||||
/* file settings override the defaults */
|
||||
auto fileSettings = tr_variant{};
|
||||
auto const filename = tr_strvPath(configDir, "settings.json"sv);
|
||||
auto const filename = tr_strvPath(config_dir, "settings.json"sv);
|
||||
auto success = bool{};
|
||||
if (tr_error* error = nullptr; tr_variantFromFile(&fileSettings, TR_VARIANT_PARSE_JSON, filename.c_str(), &error))
|
||||
{
|
||||
|
@ -510,12 +510,12 @@ bool tr_sessionLoadSettings(tr_variant* dict, char const* configDir, char const*
|
|||
return success;
|
||||
}
|
||||
|
||||
void tr_sessionSaveSettings(tr_session* session, char const* configDir, tr_variant const* clientSettings)
|
||||
void tr_sessionSaveSettings(tr_session* session, char const* config_dir, tr_variant const* clientSettings)
|
||||
{
|
||||
TR_ASSERT(tr_variantIsDict(clientSettings));
|
||||
|
||||
tr_variant settings;
|
||||
auto const filename = tr_strvPath(configDir, "settings.json"sv);
|
||||
auto const filename = tr_strvPath(config_dir, "settings.json"sv);
|
||||
|
||||
tr_variantInitDict(&settings, 0);
|
||||
|
||||
|
@ -588,11 +588,11 @@ struct init_data
|
|||
bool done;
|
||||
bool messageQueuingEnabled;
|
||||
tr_session* session;
|
||||
char const* configDir;
|
||||
char const* config_dir;
|
||||
tr_variant* clientSettings;
|
||||
};
|
||||
|
||||
tr_session* tr_sessionInit(char const* configDir, bool messageQueuingEnabled, tr_variant* clientSettings)
|
||||
tr_session* tr_sessionInit(char const* config_dir, bool messageQueuingEnabled, tr_variant* clientSettings)
|
||||
{
|
||||
TR_ASSERT(tr_variantIsDict(clientSettings));
|
||||
|
||||
|
@ -625,7 +625,7 @@ tr_session* tr_sessionInit(char const* configDir, bool messageQueuingEnabled, tr
|
|||
auto data = init_data{};
|
||||
data.done = false;
|
||||
data.session = session;
|
||||
data.configDir = configDir;
|
||||
data.config_dir = config_dir;
|
||||
data.messageQueuingEnabled = messageQueuingEnabled;
|
||||
data.clientSettings = clientSettings;
|
||||
tr_runInEventThread(session, tr_sessionInitImpl, &data);
|
||||
|
@ -724,7 +724,7 @@ static void tr_sessionInitImpl(void* vdata)
|
|||
|
||||
tr_logSetQueueEnabled(data->messageQueuingEnabled);
|
||||
|
||||
tr_setConfigDir(session, data->configDir);
|
||||
tr_setConfigDir(session, data->config_dir);
|
||||
|
||||
session->peerMgr = tr_peerMgrNew(session);
|
||||
|
||||
|
@ -735,7 +735,7 @@ static void tr_sessionInitImpl(void* vdata)
|
|||
**/
|
||||
|
||||
{
|
||||
auto const filename = tr_strvPath(session->configDir, "blocklists"sv);
|
||||
auto const filename = tr_strvPath(session->config_dir, "blocklists"sv);
|
||||
tr_sys_dir_create(filename.c_str(), TR_SYS_DIR_CREATE_PARENTS, 0777, nullptr);
|
||||
loadBlocklists(session);
|
||||
}
|
||||
|
@ -2003,9 +2003,6 @@ void tr_sessionClose(tr_session* session)
|
|||
delete session->turtle.minutes;
|
||||
tr_session_id_free(session->session_id);
|
||||
|
||||
tr_free(session->configDir);
|
||||
tr_free(session->resumeDir);
|
||||
tr_free(session->torrentDir);
|
||||
delete session;
|
||||
}
|
||||
|
||||
|
@ -2290,7 +2287,7 @@ static void loadBlocklists(tr_session* session)
|
|||
auto const isEnabled = session->useBlocklist();
|
||||
|
||||
/* walk the blocklist directory... */
|
||||
auto const dirname = tr_strvPath(session->configDir, "blocklists"sv);
|
||||
auto const dirname = tr_strvPath(session->config_dir, "blocklists"sv);
|
||||
auto const odir = tr_sys_dir_open(dirname.c_str(), nullptr);
|
||||
|
||||
if (odir == TR_BAD_SYS_DIR)
|
||||
|
@ -2444,7 +2441,7 @@ int tr_blocklistSetContent(tr_session* session, char const* contentFilename)
|
|||
|
||||
if (it == std::end(src))
|
||||
{
|
||||
auto path = tr_strvJoin(session->configDir, "blocklists"sv, name);
|
||||
auto path = tr_strvJoin(session->config_dir, "blocklists"sv, name);
|
||||
b = tr_blocklistFileNew(path.c_str(), session->useBlocklist());
|
||||
src.push_back(b);
|
||||
}
|
||||
|
|
|
@ -321,9 +321,9 @@ public:
|
|||
std::map<int, tr_torrent*> torrentsById;
|
||||
std::map<tr_sha1_digest_t, tr_torrent*> torrentsByHash;
|
||||
|
||||
char* configDir;
|
||||
char* resumeDir;
|
||||
char* torrentDir;
|
||||
std::string config_dir;
|
||||
std::string resume_dir;
|
||||
std::string torrent_dir;
|
||||
|
||||
std::list<tr_blocklistFile*> blocklists;
|
||||
struct tr_peerMgr* peerMgr;
|
||||
|
|
|
@ -751,7 +751,7 @@ void tr_torrentGotBlock(tr_torrent* tor, tr_block_index_t blockIndex);
|
|||
/**
|
||||
* @brief Like tr_torrentFindFile(), but splits the filename into base and subpath.
|
||||
*
|
||||
* If the file is found, "tr_buildPath(base, subpath, nullptr)"
|
||||
* If the file is found, "tr_strvPath(base, subpath, nullptr)"
|
||||
* will generate the complete filename.
|
||||
*
|
||||
* @return true if the file is found, false otherwise.
|
||||
|
|
|
@ -218,7 +218,7 @@ static void dht_bootstrap(void* closure)
|
|||
|
||||
if (!bootstrap_done(cl->session, 0))
|
||||
{
|
||||
auto const bootstrap_file = tr_strvPath(cl->session->configDir, "dht.bootstrap");
|
||||
auto const bootstrap_file = tr_strvPath(cl->session->config_dir, "dht.bootstrap");
|
||||
|
||||
tr_sys_file_t const f = tr_sys_file_open(bootstrap_file.c_str(), TR_SYS_FILE_READ, 0, nullptr);
|
||||
|
||||
|
@ -314,7 +314,7 @@ int tr_dhtInit(tr_session* ss)
|
|||
dht_debug = stderr;
|
||||
}
|
||||
|
||||
auto const dat_file = tr_strvPath(ss->configDir, "dht.dat"sv);
|
||||
auto const dat_file = tr_strvPath(ss->config_dir, "dht.dat"sv);
|
||||
auto benc = tr_variant{};
|
||||
auto const ok = tr_variantFromFile(&benc, TR_VARIANT_PARSE_BENC, dat_file);
|
||||
|
||||
|
@ -465,7 +465,7 @@ void tr_dhtUninit(tr_session* ss)
|
|||
tr_variantDictAddRaw(&benc, TR_KEY_nodes6, compact6, out6 - compact6);
|
||||
}
|
||||
|
||||
auto const dat_file = tr_strvPath(ss->configDir, "dht.dat");
|
||||
auto const dat_file = tr_strvPath(ss->config_dir, "dht.dat");
|
||||
tr_variantToFile(&benc, TR_VARIANT_FMT_BENC, dat_file);
|
||||
tr_variantFree(&benc);
|
||||
}
|
||||
|
|
|
@ -401,51 +401,6 @@ bool tr_saveFile(std::string_view filename_in, std::string_view contents, tr_err
|
|||
return true;
|
||||
}
|
||||
|
||||
char* tr_buildPath(char const* first_element, ...)
|
||||
{
|
||||
|
||||
/* pass 1: allocate enough space for the string */
|
||||
va_list vl;
|
||||
va_start(vl, first_element);
|
||||
auto bufLen = size_t{};
|
||||
for (char const* element = first_element; element != nullptr;)
|
||||
{
|
||||
bufLen += strlen(element) + 1;
|
||||
element = va_arg(vl, char const*);
|
||||
}
|
||||
va_end(vl);
|
||||
char* const buf = tr_new(char, bufLen);
|
||||
if (buf == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* pass 2: build the string piece by piece */
|
||||
char* pch = buf;
|
||||
va_start(vl, first_element);
|
||||
for (char const* element = first_element; element != nullptr;)
|
||||
{
|
||||
size_t const elementLen = strlen(element);
|
||||
pch = std::copy_n(element, elementLen, pch);
|
||||
*pch++ = TR_PATH_DELIMITER;
|
||||
element = va_arg(vl, char const*);
|
||||
}
|
||||
va_end(vl);
|
||||
|
||||
// if nonempty, eat the unwanted trailing slash
|
||||
if (pch != buf)
|
||||
{
|
||||
--pch;
|
||||
}
|
||||
|
||||
// zero-terminate the string
|
||||
*pch++ = '\0';
|
||||
|
||||
/* sanity checks & return */
|
||||
TR_ASSERT(pch - buf == (ptrdiff_t)bufLen);
|
||||
return buf;
|
||||
}
|
||||
|
||||
tr_disk_space tr_dirSpace(std::string_view dir)
|
||||
{
|
||||
if (std::empty(dir))
|
||||
|
|
|
@ -82,10 +82,6 @@ bool tr_loadFile(std::vector<char>& setme, std::string_view filename, tr_error**
|
|||
|
||||
bool tr_saveFile(std::string_view filename, std::string_view contents, tr_error** error = nullptr);
|
||||
|
||||
/** @brief build a filename from a series of elements using the
|
||||
platform's correct directory separator. */
|
||||
char* tr_buildPath(char const* first_element, ...) TR_GNUC_NULL_TERMINATED TR_GNUC_MALLOC;
|
||||
|
||||
template<typename... T, typename std::enable_if_t<(std::is_convertible_v<T, std::string_view> && ...), bool> = true>
|
||||
std::string& tr_buildBuf(std::string& setme, T... args)
|
||||
{
|
||||
|
|
|
@ -424,7 +424,7 @@ 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");
|
||||
}
|
||||
|
||||
auto const str = tr_strvPath(session->configDir, "cookies.txt");
|
||||
auto const str = tr_strvPath(session->config_dir, "cookies.txt");
|
||||
if (tr_sys_path_exists(str.c_str(), nullptr))
|
||||
{
|
||||
web->cookie_filename = tr_strvDup(str);
|
||||
|
|
|
@ -146,15 +146,6 @@ TEST_F(UtilsTest, trStrvDup)
|
|||
tr_free(str);
|
||||
}
|
||||
|
||||
TEST_F(UtilsTest, trBuildpath)
|
||||
{
|
||||
auto out = makeString(tr_buildPath("foo", "bar", nullptr));
|
||||
EXPECT_EQ("foo" TR_PATH_DELIMITER_STR "bar", out);
|
||||
|
||||
out = makeString(tr_buildPath("", "foo", "bar", nullptr));
|
||||
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"));
|
||||
|
|
|
@ -7,11 +7,13 @@
|
|||
*/
|
||||
|
||||
#include <array>
|
||||
#include <stdio.h> /* fprintf() */
|
||||
#include <stdlib.h> /* strtoul(), EXIT_FAILURE */
|
||||
#include <inttypes.h> /* PRIu32 */
|
||||
#include <cinttypes>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
|
||||
#include <libtransmission/transmission.h>
|
||||
|
||||
#include <libtransmission/error.h>
|
||||
#include <libtransmission/file.h>
|
||||
#include <libtransmission/makemeta.h>
|
||||
|
@ -23,12 +25,15 @@
|
|||
|
||||
using namespace std::literals;
|
||||
|
||||
static char constexpr MyName[] = "transmission-create";
|
||||
static char constexpr Usage[] = "Usage: transmission-create [options] <file|directory>";
|
||||
namespace
|
||||
{
|
||||
|
||||
static uint32_t constexpr KiB = 1024;
|
||||
char constexpr MyName[] = "transmission-create";
|
||||
char constexpr Usage[] = "Usage: transmission-create [options] <file|directory>";
|
||||
|
||||
static auto constexpr Options = std::array<tr_option, 8>{
|
||||
uint32_t constexpr KiB = 1024;
|
||||
|
||||
auto constexpr Options = std::array<tr_option, 8>{
|
||||
{ { 'p', "private", "Allow this torrent to only be used with the specified tracker(s)", "p", false, nullptr },
|
||||
{ 'r', "source", "Set the source for private trackers", "r", true, "<source>" },
|
||||
{ 'o', "outfile", "Save the generated .torrent to this filename", "o", true, "<file>" },
|
||||
|
@ -42,16 +47,16 @@ static auto constexpr Options = std::array<tr_option, 8>{
|
|||
struct app_options
|
||||
{
|
||||
std::vector<tr_tracker_info> trackers;
|
||||
std::string outfile;
|
||||
char const* comment = nullptr;
|
||||
char const* infile = nullptr;
|
||||
char const* source = nullptr;
|
||||
uint32_t piecesize_kib = 0;
|
||||
bool is_private = false;
|
||||
bool show_version = false;
|
||||
char const* comment = nullptr;
|
||||
char const* outfile = nullptr;
|
||||
char const* infile = nullptr;
|
||||
uint32_t piecesize_kib = 0;
|
||||
char const* source = nullptr;
|
||||
};
|
||||
|
||||
static int parseCommandLine(app_options& options, int argc, char const* const* argv)
|
||||
int parseCommandLine(app_options& options, int argc, char const* const* argv)
|
||||
{
|
||||
int c;
|
||||
char const* optarg;
|
||||
|
@ -110,7 +115,7 @@ static int parseCommandLine(app_options& options, int argc, char const* const* a
|
|||
return 0;
|
||||
}
|
||||
|
||||
static char* tr_getcwd(void)
|
||||
char* tr_getcwd(void)
|
||||
{
|
||||
char* result;
|
||||
tr_error* error = nullptr;
|
||||
|
@ -127,9 +132,10 @@ static char* tr_getcwd(void)
|
|||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int tr_main(int argc, char* argv[])
|
||||
{
|
||||
char* out2 = nullptr;
|
||||
tr_metainfo_builder* b = nullptr;
|
||||
|
||||
tr_logSetLevel(TR_LOG_ERROR);
|
||||
|
@ -157,7 +163,7 @@ int tr_main(int argc, char* argv[])
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (options.outfile == nullptr)
|
||||
if (std::empty(options.outfile))
|
||||
{
|
||||
tr_error* error = nullptr;
|
||||
char* base = tr_sys_path_basename(options.infile, &error);
|
||||
|
@ -170,7 +176,7 @@ int tr_main(int argc, char* argv[])
|
|||
|
||||
auto const end = tr_strvJoin(base, ".torrent"sv);
|
||||
char* cwd = tr_getcwd();
|
||||
options.outfile = out2 = tr_buildPath(cwd, end.c_str(), nullptr);
|
||||
options.outfile = tr_strvDup(tr_strvPath(cwd, end.c_str()));
|
||||
tr_free(cwd);
|
||||
tr_free(base);
|
||||
}
|
||||
|
@ -188,7 +194,7 @@ int tr_main(int argc, char* argv[])
|
|||
}
|
||||
}
|
||||
|
||||
printf("Creating torrent \"%s\"\n", options.outfile);
|
||||
printf("Creating torrent \"%s\"\n", options.outfile.c_str());
|
||||
|
||||
b = tr_metaInfoBuilderCreate(options.infile);
|
||||
|
||||
|
@ -214,7 +220,7 @@ int tr_main(int argc, char* argv[])
|
|||
|
||||
tr_makeMetaInfo(
|
||||
b,
|
||||
options.outfile,
|
||||
options.outfile.c_str(),
|
||||
std::data(options.trackers),
|
||||
std::size(options.trackers),
|
||||
options.comment,
|
||||
|
@ -264,6 +270,5 @@ int tr_main(int argc, char* argv[])
|
|||
putc('\n', stdout);
|
||||
|
||||
tr_metaInfoBuilderFree(b);
|
||||
tr_free(out2);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue