fix: resolve some lgtm warnings (#1444)

* fix: warnings found by LGTM static analyzer
This commit is contained in:
Charles Kerr 2020-09-11 16:07:45 -05:00 committed by GitHub
parent d3323ddee0
commit efaa66a920
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 213 additions and 222 deletions

View File

@ -533,8 +533,11 @@ set(NEEDED_FUNCTIONS
flock flock
getmntent getmntent
getpagesize getpagesize
gmtime_r
gmtime_s
htonll htonll
localtime_r localtime_r
localtime_s
memmem memmem
mkdtemp mkdtemp
ntohll ntohll

View File

@ -261,20 +261,20 @@ static tr_watchdir_status onFileAdded(tr_watchdir_t dir, char const* name, void*
return err == TR_PARSE_ERR ? TR_WATCHDIR_RETRY : TR_WATCHDIR_ACCEPT; return err == TR_PARSE_ERR ? TR_WATCHDIR_RETRY : TR_WATCHDIR_ACCEPT;
} }
static void printMessage(tr_sys_file_t logfile, int level, char const* name, char const* message, char const* file, int line) static void printMessage(tr_sys_file_t file, int level, char const* name, char const* message, char const* filename, int line)
{ {
if (logfile != TR_BAD_SYS_FILE) if (file != TR_BAD_SYS_FILE)
{ {
char timestr[64]; char timestr[64];
tr_logGetTimeStr(timestr, sizeof(timestr)); tr_logGetTimeStr(timestr, sizeof(timestr));
if (name != NULL) if (name != NULL)
{ {
tr_sys_file_write_fmt(logfile, "[%s] %s %s (%s:%d)" TR_NATIVE_EOL_STR, NULL, timestr, name, message, file, line); tr_sys_file_write_fmt(file, "[%s] %s %s (%s:%d)" TR_NATIVE_EOL_STR, NULL, timestr, name, message, filename, line);
} }
else else
{ {
tr_sys_file_write_fmt(logfile, "[%s] %s (%s:%d)" TR_NATIVE_EOL_STR, NULL, timestr, message, file, line); tr_sys_file_write_fmt(file, "[%s] %s (%s:%d)" TR_NATIVE_EOL_STR, NULL, timestr, message, filename, line);
} }
} }
@ -302,11 +302,11 @@ static void printMessage(tr_sys_file_t logfile, int level, char const* name, cha
if (name != NULL) if (name != NULL)
{ {
syslog(priority, "%s %s (%s:%d)", name, message, file, line); syslog(priority, "%s %s (%s:%d)", name, message, filename, line);
} }
else else
{ {
syslog(priority, "%s (%s:%d)", message, file, line); syslog(priority, "%s (%s:%d)", message, filename, line);
} }
} }
@ -317,18 +317,18 @@ static void printMessage(tr_sys_file_t logfile, int level, char const* name, cha
#endif #endif
} }
static void pumpLogMessages(tr_sys_file_t logfile) static void pumpLogMessages(tr_sys_file_t file)
{ {
tr_log_message* list = tr_logGetQueue(); tr_log_message* list = tr_logGetQueue();
for (tr_log_message const* l = list; l != NULL; l = l->next) for (tr_log_message const* l = list; l != NULL; l = l->next)
{ {
printMessage(logfile, l->level, l->name, l->message, l->file, l->line); printMessage(file, l->level, l->name, l->message, l->file, l->line);
} }
if (logfile != TR_BAD_SYS_FILE) if (file != TR_BAD_SYS_FILE)
{ {
tr_sys_file_flush(logfile, NULL); tr_sys_file_flush(file, NULL);
} }
tr_logFreeQueue(list); tr_logFreeQueue(list);

View File

@ -2271,12 +2271,9 @@ static int tracker_list_get_current_torrent_id(struct DetailsImpl* di)
int torrent_id = -1; int torrent_id = -1;
/* if there's only one torrent in the dialog, always use it */ /* if there's only one torrent in the dialog, always use it */
if (torrent_id < 0) if (g_slist_length(di->ids) == 1)
{ {
if (g_slist_length(di->ids) == 1) torrent_id = GPOINTER_TO_INT(di->ids->data);
{
torrent_id = GPOINTER_TO_INT(di->ids->data);
}
} }
/* otherwise, use the selected tracker's torrent */ /* otherwise, use the selected tracker's torrent */

View File

@ -121,20 +121,12 @@ static void level_combo_changed_cb(GtkComboBox* combo_box, gpointer gdata)
} }
/* similar to asctime, but is utf8-clean */ /* similar to asctime, but is utf8-clean */
static char* gtr_localtime(time_t time) static char* gtr_asctime(time_t t)
{ {
char buf[256]; GDateTime* date_time = g_date_time_new_from_unix_local(t);
char* eoln; gchar* ret = g_date_time_format(date_time, "%a %b %2e %T %Y%n"); /* ctime equiv */
struct tm const tm = *localtime(&time); g_date_time_unref(date_time);
return ret;
g_strlcpy(buf, asctime(&tm), sizeof(buf));
if ((eoln = strchr(buf, '\n')) != NULL)
{
*eoln = '\0';
}
return g_locale_to_utf8(buf, -1, NULL, NULL, NULL);
} }
static void doSave(GtkWindow* parent, struct MsgData* data, char const* filename) static void doSave(GtkWindow* parent, struct MsgData* data, char const* filename)
@ -158,12 +150,11 @@ static void doSave(GtkWindow* parent, struct MsgData* data, char const* filename
{ {
do do
{ {
char* date;
char const* levelStr; char const* levelStr;
struct tr_log_message const* node; struct tr_log_message const* node;
gtk_tree_model_get(model, &iter, COL_TR_MSG, &node, -1); gtk_tree_model_get(model, &iter, COL_TR_MSG, &node, -1);
date = gtr_localtime(node->when); gchar* date = gtr_asctime(node->when);
switch (node->level) switch (node->level)
{ {
@ -271,14 +262,13 @@ static void renderTime(GtkTreeViewColumn* column, GtkCellRenderer* renderer, Gtk
TR_UNUSED(column); TR_UNUSED(column);
TR_UNUSED(data); TR_UNUSED(data);
struct tm tm;
char buf[16];
struct tr_log_message const* node; struct tr_log_message const* node;
gtk_tree_model_get(tree_model, iter, COL_TR_MSG, &node, -1); gtk_tree_model_get(tree_model, iter, COL_TR_MSG, &node, -1);
tm = *localtime(&node->when); GDateTime* date_time = g_date_time_new_from_unix_local(node->when);
g_snprintf(buf, sizeof(buf), "%02d:%02d:%02d", tm.tm_hour, tm.tm_min, tm.tm_sec); gchar* buf = g_date_time_format(date_time, "%T");
g_object_set(renderer, "text", buf, "foreground", getForegroundColor(node->level), NULL); g_object_set(renderer, "text", buf, "foreground", getForegroundColor(node->level), NULL);
g_free(buf);
g_date_time_unref(date_time);
} }
static void appendColumn(GtkTreeView* view, int col) static void appendColumn(GtkTreeView* view, int col)

View File

@ -1514,30 +1514,34 @@ static void on_scrape_done(tr_scrape_response const* response, void* vsession)
if (multiscrape_too_big(response->errmsg)) if (multiscrape_too_big(response->errmsg))
{ {
char const* url = response->url; char const* url = response->url;
int* multiscrape_max = &tr_announcerGetScrapeInfo(announcer, url)->multiscrape_max; struct tr_scrape_info* const scrape_info = tr_announcerGetScrapeInfo(announcer, url);
if (scrape_info != NULL)
/* Lower the max only if it hasn't already lowered for a similar error.
For example if N parallel multiscrapes all have the same `max` and
error out, lower the value once for that batch, not N times. */
if (*multiscrape_max >= response->row_count)
{ {
int const n = MAX(1, *multiscrape_max - TR_MULTISCRAPE_STEP); int* multiscrape_max = &scrape_info->multiscrape_max;
if (*multiscrape_max != n)
{
char* scheme = NULL;
char* host = NULL;
int port;
if (tr_urlParse(url, strlen(url), &scheme, &host, &port, NULL))
{
/* don't log the full URL, since that might have a personal announce id */
char* sanitized_url = tr_strdup_printf("%s://%s:%d", scheme, host, port);
tr_logAddNamedInfo(sanitized_url, "Reducing multiscrape max to %d", n);
tr_free(sanitized_url);
tr_free(host);
tr_free(scheme);
}
*multiscrape_max = n; /* Lower the max only if it hasn't already lowered for a similar error.
For example if N parallel multiscrapes all have the same `max` and
error out, lower the value once for that batch, not N times. */
if (*multiscrape_max >= response->row_count)
{
int const n = MAX(1, *multiscrape_max - TR_MULTISCRAPE_STEP);
if (*multiscrape_max != n)
{
char* scheme = NULL;
char* host = NULL;
int port;
if (tr_urlParse(url, strlen(url), &scheme, &host, &port, NULL))
{
/* don't log the full URL, since that might have a personal announce id */
char* sanitized_url = tr_strdup_printf("%s://%s:%d", scheme, host, port);
tr_logAddNamedInfo(sanitized_url, "Reducing multiscrape max to %d", n);
tr_free(sanitized_url);
tr_free(host);
tr_free(scheme);
}
*multiscrape_max = n;
}
} }
} }
} }

View File

@ -127,15 +127,18 @@ static inline bool cached_file_is_open(struct tr_cached_file const* o)
{ {
TR_ASSERT(o != NULL); TR_ASSERT(o != NULL);
return o->fd != TR_BAD_SYS_FILE; return (o != NULL) && (o->fd != TR_BAD_SYS_FILE);
} }
static void cached_file_close(struct tr_cached_file* o) static void cached_file_close(struct tr_cached_file* o)
{ {
TR_ASSERT(cached_file_is_open(o)); TR_ASSERT(cached_file_is_open(o));
tr_sys_file_close(o->fd, NULL); if (o != NULL)
o->fd = TR_BAD_SYS_FILE; {
tr_sys_file_close(o->fd, NULL);
o->fd = TR_BAD_SYS_FILE;
}
} }
/** /**
@ -333,7 +336,7 @@ static struct tr_cached_file* fileset_get_empty_slot(struct tr_fileset* set)
{ {
struct tr_cached_file* cull = NULL; struct tr_cached_file* cull = NULL;
if (set->begin != NULL) if (set != NULL && set->begin != NULL)
{ {
/* try to find an unused slot */ /* try to find an unused slot */
for (struct tr_cached_file* o = set->begin; o != set->end; ++o) for (struct tr_cached_file* o = set->begin; o != set->end; ++o)

View File

@ -38,8 +38,6 @@ static int const base32Lookup[] =
0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF /* 'x', 'y', 'z', '{', '|', '}', '~', 'DEL' */ 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF /* 'x', 'y', 'z', '{', '|', '}', '~', 'DEL' */
}; };
static int const base32LookupLen = TR_N_ELEMENTS(base32Lookup);
static void base32_to_sha1(uint8_t* out, char const* in, size_t const inlen) static void base32_to_sha1(uint8_t* out, char const* in, size_t const inlen)
{ {
TR_ASSERT(inlen == 32); TR_ASSERT(inlen == 32);
@ -54,7 +52,7 @@ static void base32_to_sha1(uint8_t* out, char const* in, size_t const inlen)
int lookup = in[i] - '0'; int lookup = in[i] - '0';
/* Skip chars outside the lookup table */ /* Skip chars outside the lookup table */
if (lookup < 0 || lookup >= base32LookupLen) if (lookup < 0)
{ {
continue; continue;
} }

View File

@ -44,7 +44,7 @@ static struct FileList* getFiles(char const* dir, char const* base, struct FileL
} }
char* buf = tr_buildPath(dir, base, NULL); char* buf = tr_buildPath(dir, base, NULL);
tr_sys_path_native_separators(buf); (void)tr_sys_path_native_separators(buf);
tr_sys_path_info info; tr_sys_path_info info;
tr_error* error = NULL; tr_error* error = NULL;

View File

@ -2098,6 +2098,7 @@ static bool myHandshakeDoneCB(tr_handshake* handshake, tr_peerIo* io, bool readA
} }
else if (tr_peerIoIsIncoming(io) && getPeerCount(s) >= getMaxPeerCount(s->tor)) else if (tr_peerIoIsIncoming(io) && getPeerCount(s) >= getMaxPeerCount(s->tor))
{ {
/* too many peers already */
} }
else else
{ {

View File

@ -2601,36 +2601,37 @@ static bool peermsgs_is_transferring_pieces(struct tr_peer const* peer, uint64_t
static void peermsgs_destruct(tr_peer* peer) static void peermsgs_destruct(tr_peer* peer)
{ {
tr_peerMsgs* msgs = PEER_MSGS(peer); tr_peerMsgs* const msgs = PEER_MSGS(peer);
TR_ASSERT(msgs != NULL); TR_ASSERT(msgs != NULL);
if (msgs != NULL)
tr_peerMsgsSetActive(msgs, TR_UP, false);
tr_peerMsgsSetActive(msgs, TR_DOWN, false);
if (msgs->pexTimer != NULL)
{ {
event_free(msgs->pexTimer); tr_peerMsgsSetActive(msgs, TR_UP, false);
tr_peerMsgsSetActive(msgs, TR_DOWN, false);
if (msgs->pexTimer != NULL)
{
event_free(msgs->pexTimer);
}
if (msgs->incoming.block != NULL)
{
evbuffer_free(msgs->incoming.block);
}
if (msgs->io != NULL)
{
tr_peerIoClear(msgs->io);
tr_peerIoUnref(msgs->io); /* balanced by the ref in handshakeDoneCB() */
}
evbuffer_free(msgs->outMessages);
tr_free(msgs->pex6);
tr_free(msgs->pex);
tr_peerDestruct(&msgs->peer);
memset(msgs, ~0, sizeof(tr_peerMsgs));
} }
if (msgs->incoming.block != NULL)
{
evbuffer_free(msgs->incoming.block);
}
if (msgs->io != NULL)
{
tr_peerIoClear(msgs->io);
tr_peerIoUnref(msgs->io); /* balanced by the ref in handshakeDoneCB() */
}
evbuffer_free(msgs->outMessages);
tr_free(msgs->pex6);
tr_free(msgs->pex);
tr_peerDestruct(&msgs->peer);
memset(msgs, ~0, sizeof(tr_peerMsgs));
} }
static struct tr_peer_virtual_funcs const my_funcs = static struct tr_peer_virtual_funcs const my_funcs =

View File

@ -368,10 +368,11 @@ static void add_response(struct evhttp_request* req, struct tr_rpc_server* serve
static void add_time_header(struct evkeyvalq* headers, char const* key, time_t value) static void add_time_header(struct evkeyvalq* headers, char const* key, time_t value)
{ {
char buf[128];
struct tm tm;
/* According to RFC 2616 this must follow RFC 1123's date format, /* According to RFC 2616 this must follow RFC 1123's date format,
so use gmtime instead of localtime... */ so use gmtime instead of localtime... */
char buf[128]; tr_gmtime_r(&value, &tm);
struct tm tm = *gmtime(&value);
strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S GMT", &tm); strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S GMT", &tm);
evhttp_add_header(headers, key, buf); evhttp_add_header(headers, key, buf);
} }

View File

@ -81,7 +81,7 @@ static bool tr_spawn_async_in_child(char* const* cmd, char* const* env, char con
return true; return true;
fail: fail:
write(pipe_fd, &errno, sizeof(errno)); (void)write(pipe_fd, &errno, sizeof(errno));
return false; return false;
} }

View File

@ -411,7 +411,7 @@ double tr_torrentGetMetadataPercent(tr_torrent const* tor)
return ret; return ret;
} }
/* FIXME: this should be renamed tr_metainfoGetMagnetLink() and moved to metainfo.c for consistency */ /* TODO: this should be renamed tr_metainfoGetMagnetLink() and moved to metainfo.c for consistency */
char* tr_torrentInfoGetMagnetLink(tr_info const* inf) char* tr_torrentInfoGetMagnetLink(tr_info const* inf)
{ {
char const* name; char const* name;

View File

@ -975,7 +975,7 @@ static void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
torrentInitFromInfo(tor); torrentInitFromInfo(tor);
bool didRenameResumeFileToHashOnlyName = false; bool didRenameResumeFileToHashOnlyName = false;
loaded = tr_torrentLoadResume(tor, ~0, ctor, &didRenameResumeFileToHashOnlyName); loaded = tr_torrentLoadResume(tor, ~(uint64_t)0, ctor, &didRenameResumeFileToHashOnlyName);
if (didRenameResumeFileToHashOnlyName) if (didRenameResumeFileToHashOnlyName)
{ {
@ -2226,21 +2226,6 @@ void tr_torrentClearIdleLimitHitCallback(tr_torrent* torrent)
tr_torrentSetIdleLimitHitCallback(torrent, NULL, NULL); tr_torrentSetIdleLimitHitCallback(torrent, NULL, NULL);
} }
static void get_local_time_str(char* const buffer, size_t const buffer_len)
{
time_t const now = tr_time();
tr_strlcpy(buffer, ctime(&now), buffer_len);
char* newline_pos = strchr(buffer, '\n');
/* ctime() includes '\n', but it's better to be safe */
if (newline_pos != NULL)
{
*newline_pos = '\0';
}
}
static void torrentCallScript(tr_torrent const* tor, char const* script) static void torrentCallScript(tr_torrent const* tor, char const* script)
{ {
if (tr_str_is_empty(script)) if (tr_str_is_empty(script))
@ -2248,8 +2233,11 @@ static void torrentCallScript(tr_torrent const* tor, char const* script)
return; return;
} }
char time_str[32]; time_t const now = tr_time();
get_local_time_str(time_str, TR_N_ELEMENTS(time_str)); struct tm tm;
char ctime_str[32];
tr_localtime_r(&now, &tm);
strftime(ctime_str, sizeof(ctime_str), "%a %b %2e %T %Y%n", &tm); /* ctime equiv */
char* const torrent_dir = tr_sys_path_native_separators(tr_strdup(tor->currentDir)); char* const torrent_dir = tr_sys_path_native_separators(tr_strdup(tor->currentDir));
@ -2264,7 +2252,7 @@ static void torrentCallScript(tr_torrent const* tor, char const* script)
char* const env[] = char* const env[] =
{ {
tr_strdup_printf("TR_APP_VERSION=%s", SHORT_VERSION_STRING), tr_strdup_printf("TR_APP_VERSION=%s", SHORT_VERSION_STRING),
tr_strdup_printf("TR_TIME_LOCALTIME=%s", time_str), tr_strdup_printf("TR_TIME_LOCALTIME=%s", ctime_str),
tr_strdup_printf("TR_TORRENT_DIR=%s", torrent_dir), tr_strdup_printf("TR_TORRENT_DIR=%s", torrent_dir),
tr_strdup_printf("TR_TORRENT_HASH=%s", tor->info.hashString), tr_strdup_printf("TR_TORRENT_HASH=%s", tor->info.hashString),
tr_strdup_printf("TR_TORRENT_ID=%d", tr_torrentId(tor)), tr_strdup_printf("TR_TORRENT_ID=%d", tr_torrentId(tor)),
@ -2614,7 +2602,9 @@ void tr_torrentGetBlockLocation(tr_torrent const* tor, tr_block_index_t block, t
uint64_t pos = block; uint64_t pos = block;
pos *= tor->blockSize; pos *= tor->blockSize;
*piece = pos / tor->info.pieceSize; *piece = pos / tor->info.pieceSize;
*offset = pos - *piece * tor->info.pieceSize; uint64_t piece_begin = tor->info.pieceSize;
piece_begin *= *piece;
*offset = pos - piece_begin;
*length = tr_torBlockCountBytes(tor, block); *length = tr_torBlockCountBytes(tor, block);
} }
@ -2756,9 +2746,11 @@ time_t tr_torrentGetFileMTime(tr_torrent const* tor, tr_file_index_t i)
bool tr_torrentPieceNeedsCheck(tr_torrent const* tor, tr_piece_index_t p) bool tr_torrentPieceNeedsCheck(tr_torrent const* tor, tr_piece_index_t p)
{ {
uint64_t unused; tr_info const* const inf = tr_torrentInfo(tor);
tr_file_index_t f; if (inf == NULL)
tr_info const* inf = tr_torrentInfo(tor); {
return false;
}
/* if we've never checked this piece, then it needs to be checked */ /* if we've never checked this piece, then it needs to be checked */
if (inf->pieces[p].timeChecked == 0) if (inf->pieces[p].timeChecked == 0)
@ -2769,6 +2761,8 @@ bool tr_torrentPieceNeedsCheck(tr_torrent const* tor, tr_piece_index_t p)
/* If we think we've completed one of the files in this piece, /* If we think we've completed one of the files in this piece,
* but it's been modified since we last checked it, * but it's been modified since we last checked it,
* then it needs to be rechecked */ * then it needs to be rechecked */
tr_file_index_t f;
uint64_t unused;
tr_ioFindFileLocation(tor, p, 0, &f, &unused); tr_ioFindFileLocation(tor, p, 0, &f, &unused);
for (tr_file_index_t i = f; i < inf->fileCount && pieceHasFile(p, &inf->files[i]); ++i) for (tr_file_index_t i = f; i < inf->fileCount && pieceHasFile(p, &inf->files[i]); ++i)

View File

@ -616,7 +616,7 @@ static int tr_lpdConsiderAnnounce(tr_pex* peer, char const* const msg)
* Further, by setting interval to zero (or negative) the caller may actually disable LPD * Further, by setting interval to zero (or negative) the caller may actually disable LPD
* announces on a per-interval basis. * announces on a per-interval basis.
* *
* FIXME: since this function's been made private and is called by a periodic timer, * TODO: since this function's been made private and is called by a periodic timer,
* most of the previous paragraph isn't true anymore... we weren't using that functionality * most of the previous paragraph isn't true anymore... we weren't using that functionality
* before. are there cases where we should? if not, should we remove the bells & whistles? * before. are there cases where we should? if not, should we remove the bells & whistles?
*/ */

View File

@ -142,7 +142,7 @@ void tr_sessionGetDefaultSettings(struct tr_variant* setme_dictionary);
/** /**
* Add the session's current configuration settings to the benc dictionary. * Add the session's current configuration settings to the benc dictionary.
* *
* FIXME: this probably belongs in libtransmissionapp * TODO: if we ever make libtransmissionapp, this would go there.
* *
* @param session the session to query * @param session the session to query
* @param setme_dictionary the dictionary to populate * @param setme_dictionary the dictionary to populate
@ -154,7 +154,7 @@ void tr_sessionGetSettings(tr_session* session, struct tr_variant* setme_diction
* Load settings from the configuration directory's settings.json file, * Load settings from the configuration directory's settings.json file,
* using libtransmission's default settings as fallbacks for missing keys. * using libtransmission's default settings as fallbacks for missing keys.
* *
* FIXME: this belongs in libtransmissionapp * TODO: if we ever make libtransmissionapp, this would go there.
* *
* @param dictionary pointer to an uninitialized tr_variant * @param dictionary pointer to an uninitialized tr_variant
* @param configDir the configuration directory to find settings.json * @param configDir the configuration directory to find settings.json
@ -170,7 +170,7 @@ bool tr_sessionLoadSettings(struct tr_variant* dictionary, char const* configDir
* Add the session's configuration settings to the benc dictionary * Add the session's configuration settings to the benc dictionary
* and save it to the configuration directory's settings.json file. * and save it to the configuration directory's settings.json file.
* *
* FIXME: this belongs in libtransmissionapp * TODO: if we ever make libtransmissionapp, this would go there.
* *
* @param session the session to save * @param session the session to save
* @param configDir the directory to write to * @param configDir the directory to write to
@ -1636,7 +1636,8 @@ struct tr_info
static inline bool tr_torrentHasMetadata(tr_torrent const* tor) static inline bool tr_torrentHasMetadata(tr_torrent const* tor)
{ {
return tr_torrentInfo(tor)->fileCount > 0; tr_info const* const inf = tr_torrentInfo(tor);
return (inf != NULL) && (inf->fileCount > 0);
} }
/** /**

View File

@ -63,22 +63,50 @@ time_t __tr_current_time = 0;
**** ****
***/ ***/
struct tm* tr_localtime_r(time_t const* _clock, struct tm* _result) struct tm* tr_gmtime_r(time_t const* timep, struct tm* result)
{ {
#ifdef HAVE_LOCALTIME_R #if defined(HAVE_GMTIME_R)
return localtime_r(_clock, _result); return gmtime_r(timep, result);
#elif defined(HAVE_GMTIME_S)
return gmtime_s(result, timep) == 0 ? result : NULL;
#else #else
struct tm* p = localtime(_clock); struct tm* p = gmtime(timep);
if (p != NULL) if (p != NULL)
{ {
*(_result) = *p; *result = *p;
return result;
} }
return p; return NULL;
#endif
}
struct tm* tr_localtime_r(time_t const* timep, struct tm* result)
{
#if defined(HAVE_LOCALTIME_R)
return localtime_r(timep, result);
#elif defined(HAVE_LOCALTIME_S)
return localtime_s(result, timep) == 0 ? result : NULL;
#else
struct tm* p = localtime(timep);
if (p != NULL)
{
*result = *p;
return result;
}
return NULL;
#endif #endif
} }

View File

@ -323,6 +323,9 @@ char* tr_strratio(char* buf, size_t buflen, double ratio, char const* infinity)
/** @brief Portability wrapper for localtime_r() that uses the system implementation if available */ /** @brief Portability wrapper for localtime_r() that uses the system implementation if available */
struct tm* tr_localtime_r(time_t const* _clock, struct tm* _result); struct tm* tr_localtime_r(time_t const* _clock, struct tm* _result);
/** @brief Portability wrapper for gmtime_r() that uses the system implementation if available */
struct tm* tr_gmtime_r(time_t const* _clock, struct tm* _result);
/** @brief Portability wrapper for gettimeofday(), with tz argument dropped */ /** @brief Portability wrapper for gettimeofday(), with tz argument dropped */
int tr_gettimeofday(struct timeval* tv); int tr_gettimeofday(struct timeval* tv);

View File

@ -279,7 +279,7 @@ static void on_content_changed(struct evbuffer* buf, struct evbuffer_cb_info con
/* we don't use locking on this evbuffer so we must copy out the data /* we don't use locking on this evbuffer so we must copy out the data
that will be needed when writing the block in a different thread */ that will be needed when writing the block in a different thread */
evbuffer_remove_buffer(task->content, data->content, block_size * completed); evbuffer_remove_buffer(task->content, data->content, (size_t)block_size * (size_t)completed);
tr_runInEventThread(w->session, write_block_func, data); tr_runInEventThread(w->session, write_block_func, data);
task->blocks_done += completed; task->blocks_done += completed;
@ -475,7 +475,7 @@ static void task_request_next_chunk(struct tr_webseed_task* t)
uint64_t const total_offset = tr_pieceOffset(tor, t->piece_index, t->piece_offset, t->length - remain); uint64_t const total_offset = tr_pieceOffset(tor, t->piece_index, t->piece_offset, t->length - remain);
tr_piece_index_t const step_piece = total_offset / inf->pieceSize; tr_piece_index_t const step_piece = total_offset / inf->pieceSize;
uint64_t const step_piece_offset = total_offset - inf->pieceSize * step_piece; uint64_t const step_piece_offset = total_offset - (uint64_t)inf->pieceSize * step_piece;
tr_file_index_t file_index; tr_file_index_t file_index;
tr_file const* file; tr_file const* file;

View File

@ -543,47 +543,47 @@ static char* getEncodedMetainfo(char const* filename)
return b64; return b64;
} }
static void addIdArg(tr_variant* args, char const* id, char const* fallback) static void addIdArg(tr_variant* args, char const* id_str, char const* fallback)
{ {
if (tr_str_is_empty(id)) if (tr_str_is_empty(id_str))
{ {
id = fallback; id_str = fallback;
if (tr_str_is_empty(id)) if (tr_str_is_empty(id_str))
{ {
fprintf(stderr, "No torrent specified! Please use the -t option first.\n"); fprintf(stderr, "No torrent specified! Please use the -t option first.\n");
id = "-1"; /* no torrent will have this ID, so will act as a no-op */ id_str = "-1"; /* no torrent will have this ID, so will act as a no-op */
} }
} }
if (tr_strcmp0(id, "active") == 0) if (tr_strcmp0(id_str, "active") == 0)
{ {
tr_variantDictAddStr(args, TR_KEY_ids, "recently-active"); tr_variantDictAddStr(args, TR_KEY_ids, "recently-active");
} }
else if (strcmp(id, "all") != 0) else if (strcmp(id_str, "all") != 0)
{ {
bool isList = strchr(id, ',') != NULL || strchr(id, '-') != NULL; bool isList = strchr(id_str, ',') != NULL || strchr(id_str, '-') != NULL;
bool isNum = true; bool isNum = true;
for (char const* pch = id; isNum && *pch != '\0'; ++pch) for (char const* pch = id_str; isNum && *pch != '\0'; ++pch)
{ {
isNum = isdigit(*pch); isNum = isdigit(*pch);
} }
if (isNum || isList) if (isNum || isList)
{ {
tr_rpc_parse_list_str(tr_variantDictAdd(args, TR_KEY_ids), id, strlen(id)); tr_rpc_parse_list_str(tr_variantDictAdd(args, TR_KEY_ids), id_str, strlen(id_str));
} }
else else
{ {
tr_variantDictAddStr(args, TR_KEY_ids, id); /* it's a torrent sha hash */ tr_variantDictAddStr(args, TR_KEY_ids, id_str); /* it's a torrent sha hash */
} }
} }
} }
static void addTime(tr_variant* args, tr_quark const key, char const* arg) static void addTime(tr_variant* args, tr_quark const key, char const* arg)
{ {
int time; int time = 0;
bool success = false; bool success = false;
if (arg != NULL && strlen(arg) == 4) if (arg != NULL && strlen(arg) == 4)
@ -857,7 +857,7 @@ static char* getStatusString(tr_variant* t, char* buf, size_t buflen)
if (tr_variantDictFindReal(t, TR_KEY_recheckProgress, &percent)) if (tr_variantDictFindReal(t, TR_KEY_recheckProgress, &percent))
{ {
tr_snprintf(buf, buflen, "%s (%.0f%%)", str, (floor)(percent * 100.0)); tr_snprintf(buf, buflen, "%s (%.0f%%)", str, floor(percent * 100.0));
} }
else else
{ {
@ -922,6 +922,14 @@ static char const* bandwidthPriorityNames[] =
"Invalid" "Invalid"
}; };
static char* format_date(char* buf, size_t buflen, time_t now)
{
struct tm tm;
tr_localtime_r(&now, &tm);
strftime(buf, buflen, "%a %b %2e %T %Y%n", &tm); /* ctime equiv */
return buf;
}
static void printDetails(tr_variant* top) static void printDetails(tr_variant* top)
{ {
tr_variant* args; tr_variant* args;
@ -1101,26 +1109,22 @@ static void printDetails(tr_variant* top)
if (tr_variantDictFindInt(t, TR_KEY_addedDate, &i) && i != 0) if (tr_variantDictFindInt(t, TR_KEY_addedDate, &i) && i != 0)
{ {
time_t const tt = i; printf(" Date added: %s", format_date(buf, sizeof(buf), i));
printf(" Date added: %s", ctime(&tt));
} }
if (tr_variantDictFindInt(t, TR_KEY_doneDate, &i) && i != 0) if (tr_variantDictFindInt(t, TR_KEY_doneDate, &i) && i != 0)
{ {
time_t const tt = i; printf(" Date finished: %s", format_date(buf, sizeof(buf), i));
printf(" Date finished: %s", ctime(&tt));
} }
if (tr_variantDictFindInt(t, TR_KEY_startDate, &i) && i != 0) if (tr_variantDictFindInt(t, TR_KEY_startDate, &i) && i != 0)
{ {
time_t const tt = i; printf(" Date started: %s", format_date(buf, sizeof(buf), i));
printf(" Date started: %s", ctime(&tt));
} }
if (tr_variantDictFindInt(t, TR_KEY_activityDate, &i) && i != 0) if (tr_variantDictFindInt(t, TR_KEY_activityDate, &i) && i != 0)
{ {
time_t const tt = i; printf(" Latest activity: %s", format_date(buf, sizeof(buf), i));
printf(" Latest activity: %s", ctime(&tt));
} }
if (tr_variantDictFindInt(t, TR_KEY_secondsDownloading, &i) && i > 0) if (tr_variantDictFindInt(t, TR_KEY_secondsDownloading, &i) && i > 0)
@ -1139,8 +1143,7 @@ static void printDetails(tr_variant* top)
if (tr_variantDictFindInt(t, TR_KEY_dateCreated, &i) && i != 0) if (tr_variantDictFindInt(t, TR_KEY_dateCreated, &i) && i != 0)
{ {
time_t const tt = i; printf(" Date created: %s", format_date(buf, sizeof(buf), i));
printf(" Date created: %s", ctime(&tt));
} }
if (tr_variantDictFindBool(t, TR_KEY_isPrivate, &boolVal)) if (tr_variantDictFindBool(t, TR_KEY_isPrivate, &boolVal))
@ -1303,7 +1306,7 @@ static void printFileList(tr_variant* top)
break; break;
} }
printf("%3d: %3.0f%% %-8s %-3s %9s %s\n", j, (floor)(100.0 * percent), pristr, wanted ? "Yes" : "No", printf("%3d: %3.0f%% %-8s %-3s %9s %s\n", j, floor(100.0 * percent), pristr, wanted ? "Yes" : "No",
sizestr, filename); sizestr, filename);
} }
} }
@ -1450,7 +1453,7 @@ static void printTorrentList(tr_variant* top)
for (int i = 0, n = tr_variantListSize(list); i < n; ++i) for (int i = 0, n = tr_variantListSize(list); i < n; ++i)
{ {
int64_t id; int64_t torId;
int64_t eta; int64_t eta;
int64_t status; int64_t status;
int64_t up; int64_t up;
@ -1462,7 +1465,7 @@ static void printTorrentList(tr_variant* top)
tr_variant* d = tr_variantListChild(list, i); tr_variant* d = tr_variantListChild(list, i);
if (tr_variantDictFindInt(d, TR_KEY_eta, &eta) && if (tr_variantDictFindInt(d, TR_KEY_eta, &eta) &&
tr_variantDictFindInt(d, TR_KEY_id, &id) && tr_variantDictFindInt(d, TR_KEY_id, &torId) &&
tr_variantDictFindInt(d, TR_KEY_leftUntilDone, &leftUntilDone) && tr_variantDictFindInt(d, TR_KEY_leftUntilDone, &leftUntilDone) &&
tr_variantDictFindStr(d, TR_KEY_name, &name, NULL) && tr_variantDictFindStr(d, TR_KEY_name, &name, NULL) &&
tr_variantDictFindInt(d, TR_KEY_rateDownload, &down) && tr_variantDictFindInt(d, TR_KEY_rateDownload, &down) &&
@ -1507,7 +1510,7 @@ static void printTorrentList(tr_variant* top)
errorMark = ' '; errorMark = ' ';
} }
printf("%6d%c %4s %9s %-8s %6.1f %6.1f %5s %-11s %s\n", (int)id, errorMark, doneStr, haveStr, etaStr, printf("%6d%c %4s %9s %-8s %6.1f %6.1f %5s %-11s %s\n", (int)torId, errorMark, doneStr, haveStr, etaStr,
up / (double)tr_speed_K, down / (double)tr_speed_K, strlratio2(ratioStr, ratio, sizeof(ratioStr)), up / (double)tr_speed_K, down / (double)tr_speed_K, strlratio2(ratioStr, ratio, sizeof(ratioStr)),
getStatusString(d, statusStr, sizeof(statusStr)), name); getStatusString(d, statusStr, sizeof(statusStr)), name);
@ -1533,7 +1536,7 @@ static void printTrackersImpl(tr_variant* trackerStats)
bool hasAnnounced; bool hasAnnounced;
bool hasScraped; bool hasScraped;
char const* host; char const* host;
int64_t id; int64_t trackerId;
bool isBackup; bool isBackup;
int64_t lastAnnouncePeerCount; int64_t lastAnnouncePeerCount;
char const* lastAnnounceResult; char const* lastAnnounceResult;
@ -1558,7 +1561,7 @@ static void printTrackersImpl(tr_variant* trackerStats)
tr_variantDictFindBool(t, TR_KEY_hasAnnounced, &hasAnnounced) && tr_variantDictFindBool(t, TR_KEY_hasAnnounced, &hasAnnounced) &&
tr_variantDictFindBool(t, TR_KEY_hasScraped, &hasScraped) && tr_variantDictFindBool(t, TR_KEY_hasScraped, &hasScraped) &&
tr_variantDictFindStr(t, TR_KEY_host, &host, NULL) && tr_variantDictFindStr(t, TR_KEY_host, &host, NULL) &&
tr_variantDictFindInt(t, TR_KEY_id, &id) && tr_variantDictFindInt(t, TR_KEY_id, &trackerId) &&
tr_variantDictFindBool(t, TR_KEY_isBackup, &isBackup) && tr_variantDictFindBool(t, TR_KEY_isBackup, &isBackup) &&
tr_variantDictFindInt(t, TR_KEY_announceState, &announceState) && tr_variantDictFindInt(t, TR_KEY_announceState, &announceState) &&
tr_variantDictFindInt(t, TR_KEY_scrapeState, &scrapeState) && tr_variantDictFindInt(t, TR_KEY_scrapeState, &scrapeState) &&
@ -1582,7 +1585,7 @@ static void printTrackersImpl(tr_variant* trackerStats)
time_t const now = time(NULL); time_t const now = time(NULL);
printf("\n"); printf("\n");
printf(" Tracker %d: %s\n", (int)(id), host); printf(" Tracker %d: %s\n", (int)trackerId, host);
if (isBackup) if (isBackup)
{ {

View File

@ -99,31 +99,18 @@ static int compare_files_by_name(void const* va, void const* vb)
return strcmp(a->name, b->name); return strcmp(a->name, b->name);
} }
static char const* unix_timestamp_to_str(time_t timestamp) static char const* time_t_to_str(time_t timestamp)
{ {
if (timestamp == 0) if (timestamp == 0)
{ {
return "Unknown"; return "Unknown";
} }
struct tm const* const local_time = localtime(&timestamp); struct tm tm;
tr_localtime_r(&timestamp, &tm);
if (local_time == NULL) static char buf[32];
{ strftime(buf, sizeof(buf), "%a %b %2e %T %Y%n", &tm); /* ctime equiv */
return "Invalid"; return buf;
}
static char buffer[32];
tr_strlcpy(buffer, asctime(local_time), TR_N_ELEMENTS(buffer));
char* const newline_pos = strchr(buffer, '\n');
if (newline_pos != NULL)
{
*newline_pos = '\0';
}
return buffer;
} }
static void showInfo(tr_info const* inf) static void showInfo(tr_info const* inf)
@ -140,7 +127,7 @@ static void showInfo(tr_info const* inf)
printf(" Name: %s\n", inf->name); printf(" Name: %s\n", inf->name);
printf(" Hash: %s\n", inf->hashString); printf(" Hash: %s\n", inf->hashString);
printf(" Created by: %s\n", inf->creator ? inf->creator : "Unknown"); printf(" Created by: %s\n", inf->creator ? inf->creator : "Unknown");
printf(" Created on: %s\n", unix_timestamp_to_str(inf->dateCreated)); printf(" Created on: %s\n", time_t_to_str(inf->dateCreated));
if (!tr_str_is_empty(inf->comment)) if (!tr_str_is_empty(inf->comment))
{ {

View File

@ -30,7 +30,7 @@ $.fn.tabbedDialog = function (dialog_opts) {
this.parent().addClass('ui-tabs').prepend(tabul).draggable('option', 'handle', tabul); this.parent().addClass('ui-tabs').prepend(tabul).draggable('option', 'handle', tabul);
this.siblings('.ui-dialog-titlebar').remove(); this.siblings('.ui-dialog-titlebar').remove();
tabul.addClass('ui-dialog-titlebar'); tabul.addClass('ui-dialog-titlebar');
} };
/** /**
* Checks to see if the content actually changed before poking the DOM. * Checks to see if the content actually changed before poking the DOM.
@ -224,7 +224,7 @@ jQuery.fn.forceNumeric = function () {
key === 46 || key === 45; key === 46 || key === 45;
}); });
}); });
} };
/** /**
* http://blog.stevenlevithan.com/archives/parseuri * http://blog.stevenlevithan.com/archives/parseuri

View File

@ -163,17 +163,13 @@ function FileRow(torrent, depth, name, indices, even) {
e = document.createElement('div'); e = document.createElement('div');
e.className = "inspector_torrent_file_list_entry_name"; e.className = "inspector_torrent_file_list_entry_name";
setTextContent(e, name); setTextContent(e, name);
$(e).click(function () { $(e).click(fireNameClicked);
fireNameClicked(-1);
});
root.appendChild(e); root.appendChild(e);
e = document.createElement('div'); e = document.createElement('div');
e.className = "inspector_torrent_file_list_entry_progress"; e.className = "inspector_torrent_file_list_entry_progress";
root.appendChild(e); root.appendChild(e);
$(e).click(function () { $(e).click(fireNameClicked);
fireNameClicked(-1);
});
elements.progress = e; elements.progress = e;
$(root).css('margin-left', '' + (depth * 16) + 'px'); $(root).css('margin-left', '' + (depth * 16) + 'px');

View File

@ -7,11 +7,9 @@
Transmission.fmt = (function () { Transmission.fmt = (function () {
var speed_K = 1000; var speed_K = 1000;
var speed_B_str = 'B/s';
var speed_K_str = 'kB/s'; var speed_K_str = 'kB/s';
var speed_M_str = 'MB/s'; var speed_M_str = 'MB/s';
var speed_G_str = 'GB/s'; var speed_G_str = 'GB/s';
var speed_T_str = 'TB/s';
var size_K = 1000; var size_K = 1000;
var size_B_str = 'B'; var size_B_str = 'B';
@ -290,5 +288,5 @@ Transmission.fmt = (function () {
return formattedFlags.join(''); return formattedFlags.join('');
} }
} };
})(); })();

View File

@ -14,13 +14,7 @@ function Inspector(controller) {
}, },
needsExtraInfo = function (torrents) { needsExtraInfo = function (torrents) {
var i, id, tor; return torrents.some(tor => !tor.hasExtraInfo());
for (i = 0; tor = torrents[i]; i++)
if (!tor.hasExtraInfo())
return true;
return false;
}, },
refreshTorrents = function (callback) { refreshTorrents = function (callback) {
@ -96,7 +90,7 @@ function Inspector(controller) {
unknown = 'Unknown', unknown = 'Unknown',
isMixed, allPaused, allFinished, isMixed, allPaused, allFinished,
str, str,
baseline, it, s, i, t, baseline, it, i, t,
sizeWhenDone = 0, sizeWhenDone = 0,
leftUntilDone = 0, leftUntilDone = 0,
available = 0, available = 0,
@ -110,7 +104,7 @@ function Inspector(controller) {
pieceSize, pieceSize,
creator, mixed_creator, creator, mixed_creator,
date, mixed_date, date, mixed_date,
v, u, f, d, pct, v, u, f, d,
uri, uri,
now = Date.now(); now = Date.now();
@ -305,7 +299,6 @@ function Inspector(controller) {
if (torrents.length < 1) { if (torrents.length < 1) {
str = none; str = none;
} else { } else {
baseline = torrents[0].getLastActivity();
for (i = 0; t = torrents[i]; ++i) { for (i = 0; t = torrents[i]; ++i) {
d = t.getLastActivity(); d = t.getLastActivity();
if (latest < d) { if (latest < d) {
@ -524,7 +517,7 @@ function Inspector(controller) {
}, },
createFileTreeModel = function (tor) { createFileTreeModel = function (tor) {
var i, j, n, name, tokens, walk, tree, token, sub, var i, j, n, name, tokens, walk, token, sub,
leaves = [], leaves = [],
tree = { tree = {
children: {}, children: {},
@ -806,8 +799,6 @@ function Inspector(controller) {
initialize = function (controller) { initialize = function (controller) {
var ti = '#torrent_inspector_';
data.controller = controller; data.controller = controller;
$('.inspector-tab').click(onTabClicked); $('.inspector-tab').click(onTabClicked);
@ -851,8 +842,7 @@ function Inspector(controller) {
****/ ****/
this.setTorrents = function (torrents) { this.setTorrents = function (torrents) {
var d = data, var d = data;
that = this;
// update the inspector when a selected torrent's data changes. // update the inspector when a selected torrent's data changes.
$(d.torrents).unbind('dataChanged.inspector'); $(d.torrents).unbind('dataChanged.inspector');

View File

@ -241,7 +241,7 @@ function PrefsDialog(remote) {
// update the dialog's controls // update the dialog's controls
this.set = function (o) { this.set = function (o) {
var e, i, key, val, option; var e, i, key, val;
var keys = data.keys; var keys = data.keys;
var root = data.elements.root; var root = data.elements.root;

View File

@ -149,7 +149,6 @@ TransmissionRemote.prototype = {
}, },
getFreeSpace: function (dir, callback, context) { getFreeSpace: function (dir, callback, context) {
var remote = this;
var o = { var o = {
method: 'free-space', method: 'free-space',
arguments: { arguments: {
@ -201,7 +200,6 @@ TransmissionRemote.prototype = {
}, },
moveTorrents: function (torrent_ids, new_location, callback, context) { moveTorrents: function (torrent_ids, new_location, callback, context) {
var remote = this;
this.sendTorrentSetRequests('torrent-set-location', torrent_ids, { this.sendTorrentSetRequests('torrent-set-location', torrent_ids, {
"move": true, "move": true,
"location": new_location "location": new_location

View File

@ -67,7 +67,7 @@ TorrentRendererHelper.createProgressbar = function (classes) {
}; };
TorrentRendererHelper.renderProgressbar = function (controller, t, progressbar) { TorrentRendererHelper.renderProgressbar = function (controller, t, progressbar) {
var e, style, width, display var e, style, width, display;
var info = TorrentRendererHelper.getProgressInfo(controller, t); var info = TorrentRendererHelper.getProgressInfo(controller, t);
// update the complete progressbar // update the complete progressbar

View File

@ -21,7 +21,7 @@ Transmission.prototype = {
// Initialize the helper classes // Initialize the helper classes
this.remote = new TransmissionRemote(this); this.remote = new TransmissionRemote(this);
this.inspector = new Inspector(this, this.remote); this.inspector = new Inspector(this);
this.prefsDialog = new PrefsDialog(this.remote); this.prefsDialog = new PrefsDialog(this.remote);
$(this.prefsDialog).bind('closed', $.proxy(this.onPrefsDialogClosed, this)); $(this.prefsDialog).bind('closed', $.proxy(this.onPrefsDialogClosed, this));
@ -572,7 +572,7 @@ Transmission.prototype = {
} }
if (m_key || l_key) { if (m_key || l_key) {
this.moveSelectedTorrents() this.moveSelectedTorrents();
handled = true; handled = true;
} }
@ -1086,7 +1086,6 @@ Transmission.prototype = {
* Select a torrent file to upload * Select a torrent file to upload
*/ */
uploadTorrentFile: function (confirmed) { uploadTorrentFile: function (confirmed) {
var i, file, reader;
var fileInput = $('input#torrent_upload_file'); var fileInput = $('input#torrent_upload_file');
var folderInput = $('input#add-dialog-folder-input'); var folderInput = $('input#add-dialog-folder-input');
var startInput = $('input#torrent_auto_start'); var startInput = $('input#torrent_auto_start');
@ -1424,7 +1423,6 @@ Transmission.prototype = {
updateFilterSelect: function () { updateFilterSelect: function () {
var i, names, name, str, o; var i, names, name, str, o;
var e = $('#filter-tracker');
var trackers = this.getTrackers(); var trackers = this.getTrackers();
// build a sorted list of names // build a sorted list of names
@ -1592,7 +1590,7 @@ Transmission.prototype = {
var renderer = this.torrentRenderer; var renderer = this.torrentRenderer;
var list = this.elements.torrent_list; var list = this.elements.torrent_list;
old_sel_count = $(list).children('.selected').length; const old_sel_count = $(list).children('.selected').length;
this.updateFilterSelect(); this.updateFilterSelect();
@ -1697,10 +1695,7 @@ Transmission.prototype = {
this.dirtyTorrents = {}; this.dirtyTorrents = {};
// jquery's even/odd starts with 1 not 0, so invert its logic // jquery's even/odd starts with 1 not 0, so invert its logic
e = [] e = rows.map(row => row.getElement());
for (i = 0; row = rows[i]; ++i) {
e.push(row.getElement());
};
$(e).filter(":odd").addClass('even'); $(e).filter(":odd").addClass('even');
$(e).filter(":even").removeClass('even'); $(e).filter(":even").removeClass('even');