ctor = tr_ctorNew (h);
- fileContents = tr_loadFile (torrentPath, &fileLength);
+ fileContents = tr_loadFile (torrentPath, &fileLength, NULL);
tr_ctorSetPaused (ctor, TR_FORCE, false);
if (fileContents != NULL)
{
{
size_t len = 0;
char * b64 = NULL;
- uint8_t * buf = tr_loadFile (filename, &len);
+ uint8_t * buf = tr_loadFile (filename, &len, NULL);
if (buf)
{
#include <windows.h>
+#define TR_ERROR_IS_ENOENT(code) ((code) == ERROR_FILE_NOT_FOUND || \
+ (code) == ERROR_PATH_NOT_FOUND)
#define TR_ERROR_IS_ENOSPC(code) ((code) == ERROR_DISK_FULL)
#define TR_ERROR_EINVAL ERROR_INVALID_PARAMETER
+#define TR_ERROR_EISDIR ERROR_DIRECTORY_NOT_SUPPORTED
#else /* _WIN32 */
#include <errno.h>
+#define TR_ERROR_IS_ENOENT(code) ((code) == ENOENT)
#define TR_ERROR_IS_ENOSPC(code) ((code) == ENOSPC)
#define TR_ERROR_EINVAL EINVAL
+#define TR_ERROR_EISDIR EISDIR
#endif /* _WIN32 */
tr_free (config_home);
/* read in user-dirs.dirs and look for the download dir entry */
- content = (char *) tr_loadFile (config_file, &content_len);
+ content = (char *) tr_loadFile (config_file, &content_len, NULL);
if (content && content_len>0)
{
const char * key = "XDG_DOWNLOAD_DIR=\"";
assert (tr_sys_path_exists (path, NULL));
- contents = tr_loadFile (path, &contents_len);
+ contents = tr_loadFile (path, &contents_len, NULL);
- success = (str_len == contents_len)
+ success = contents != NULL
+ && (str_len == contents_len)
&& (!memcmp (contents, str, contents_len));
tr_free (contents);
#include "transmission.h"
#include "completion.h"
+#include "error.h"
#include "file.h"
#include "log.h"
#include "metainfo.h" /* tr_metainfoGetBasename () */
bool boolVal;
uint64_t fieldsLoaded = 0;
const bool wasDirty = tor->isDirty;
+ tr_error * error = NULL;
assert (tr_isTorrent (tor));
filename = getResumeFilename (tor);
- if (tr_variantFromFile (&top, TR_VARIANT_FMT_BENC, filename))
+ if (!tr_variantFromFile (&top, TR_VARIANT_FMT_BENC, filename, &error))
{
- tr_logAddTorDbg (tor, "Couldn't read \"%s\"", filename);
+ tr_logAddTorDbg (tor, "Couldn't read \"%s\": %s", filename, error->message);
+ tr_error_free (error);
tr_free (filename);
return fieldsLoaded;
{
void * file;
size_t file_len;
- struct evbuffer * content;
- const int error = errno;
+ tr_error * error = NULL;
- errno = 0;
file_len = 0;
- file = tr_loadFile (filename, &file_len);
- content = evbuffer_new ();
- evbuffer_add_reference (content, file, file_len, evbuffer_ref_cleanup_tr_free, file);
+ file = tr_loadFile (filename, &file_len, &error);
- if (errno)
+ if (file == NULL)
{
- char * tmp = tr_strdup_printf ("%s (%s)", filename, tr_strerror (errno));
+ char * tmp = tr_strdup_printf ("%s (%s)", filename, error->message);
send_simple_response (req, HTTP_NOTFOUND, tmp);
tr_free (tmp);
+ tr_error_free (error);
}
else
{
+ struct evbuffer * content;
struct evbuffer * out;
const time_t now = tr_time ();
- errno = error;
+ content = evbuffer_new ();
+ evbuffer_add_reference (content, file, file_len, evbuffer_ref_cleanup_tr_free, file);
+
out = evbuffer_new ();
evhttp_add_header (req->output_headers, "Content-Type", mimetype_guess (filename));
add_time_header (req->output_headers, "Date", now);
evhttp_send_reply (req, HTTP_OK, "OK", out);
evbuffer_free (out);
+ evbuffer_free (content);
}
-
- evbuffer_free (content);
}
}
#include "blocklist.h"
#include "cache.h"
#include "crypto-utils.h"
+#include "error.h"
+#include "error-types.h"
#include "fdlimit.h"
#include "file.h"
#include "list.h"
bool
tr_sessionLoadSettings (tr_variant * dict, const char * configDir, const char * appName)
{
- int err = 0;
char * filename;
tr_variant fileSettings;
tr_variant sessionDefaults;
tr_variant tmp;
- bool success = false;
+ bool success;
+ tr_error * error = NULL;
assert (tr_variantIsDict (dict));
/* file settings override the defaults */
filename = tr_buildPath (configDir, "settings.json", NULL);
- err = tr_variantFromFile (&fileSettings, TR_VARIANT_FMT_JSON, filename);
- if (!err)
+ if (tr_variantFromFile (&fileSettings, TR_VARIANT_FMT_JSON, filename, &error))
{
tr_variantMergeDicts (dict, &fileSettings);
tr_variantFree (&fileSettings);
+ success = true;
+ }
+ else
+ {
+ success = TR_ERROR_IS_ENOENT (error->code);
+ tr_error_free (error);
}
/* cleanup */
tr_variantFree (&sessionDefaults);
tr_free (filename);
- success = (err==0) || (err==ENOENT);
return success;
}
/* the existing file settings are the fallback values */
{
tr_variant fileSettings;
- const int err = tr_variantFromFile (&fileSettings, TR_VARIANT_FMT_JSON, filename);
- if (!err)
+ if (tr_variantFromFile (&fileSettings, TR_VARIANT_FMT_JSON, filename, NULL))
{
tr_variantMergeDicts (&settings, &fileSettings);
tr_variantFree (&fileSettings);
bool loaded = false;
filename = getFilename (session);
- loaded = !tr_variantFromFile (&top, TR_VARIANT_FMT_JSON, filename);
+ loaded = tr_variantFromFile (&top, TR_VARIANT_FMT_JSON, filename, NULL);
tr_free (filename);
if (!loaded)
{
filename = getOldFilename (session);
- loaded = !tr_variantFromFile (&top, TR_VARIANT_FMT_BENC, filename);
+ loaded = tr_variantFromFile (&top, TR_VARIANT_FMT_BENC, filename, NULL);
tr_free (filename);
}
size_t len;
int err;
- metainfo = tr_loadFile (filename, &len);
+ metainfo = tr_loadFile (filename, &len, NULL);
if (metainfo && len)
err = tr_ctorSetMetainfo (ctor, metainfo, len);
else
int offset = 0;
/* load the file, and find the info dict's offset inside the file */
- if ((fileContents = tr_loadFile (tor->info.torrent, &fileLen)))
+ if ((fileContents = tr_loadFile (tor->info.torrent, &fileLen, NULL)))
{
tr_variant top;
tr_variant newMetainfo;
char * path = tr_strdup (tor->info.torrent);
- if (!tr_variantFromFile (&newMetainfo, TR_VARIANT_FMT_BENC, path))
+ if (tr_variantFromFile (&newMetainfo, TR_VARIANT_FMT_BENC, path, NULL))
{
bool hasInfo;
tr_info info;
ok = false;
/* save to the .torrent file */
- if (ok && !tr_variantFromFile (&metainfo, TR_VARIANT_FMT_BENC, tor->info.torrent))
+ if (ok && tr_variantFromFile (&metainfo, TR_VARIANT_FMT_BENC, tor->info.torrent, NULL))
{
bool hasInfo;
tr_info tmpInfo;
dht_debug = stderr;
dat_file = tr_buildPath (ss->configDir, "dht.dat", NULL);
- rc = tr_variantFromFile (&benc, TR_VARIANT_FMT_BENC, dat_file);
+ rc = tr_variantFromFile (&benc, TR_VARIANT_FMT_BENC, dat_file, NULL) ? 0 : -1;
tr_free (dat_file);
if (rc == 0) {
have_id = tr_variantDictFindRaw (&benc, TR_KEY_id, &raw, &len);
**/
uint8_t *
-tr_loadFile (const char * path,
- size_t * size)
+tr_loadFile (const char * path,
+ size_t * size,
+ tr_error ** error)
{
uint8_t * buf;
tr_sys_path_info info;
tr_sys_file_t fd;
- tr_error * error = NULL;
+ tr_error * my_error = NULL;
const char * const err_fmt = _("Couldn't read \"%1$s\": %2$s");
/* try to stat the file */
- if (!tr_sys_path_get_info (path, 0, &info, &error))
+ if (!tr_sys_path_get_info (path, 0, &info, &my_error))
{
- const int err = error->code;
- tr_logAddDebug (err_fmt, path, error->message);
- tr_error_free (error);
- errno = err;
+ tr_logAddDebug (err_fmt, path, my_error->message);
+ tr_error_propagate (error, &my_error);
return NULL;
}
if (info.type != TR_SYS_PATH_IS_FILE)
{
tr_logAddError (err_fmt, path, _("Not a regular file"));
- errno = EISDIR;
+ tr_error_set_literal (error, TR_ERROR_EISDIR, _("Not a regular file"));
return NULL;
}
assert (info.size <= SIZE_MAX);
/* Load the torrent file into our buffer */
- fd = tr_sys_file_open (path, TR_SYS_FILE_READ | TR_SYS_FILE_SEQUENTIAL, 0, &error);
+ fd = tr_sys_file_open (path, TR_SYS_FILE_READ | TR_SYS_FILE_SEQUENTIAL, 0, &my_error);
if (fd == TR_BAD_SYS_FILE)
{
- const int err = error->code;
- tr_logAddError (err_fmt, path, error->message);
- tr_error_free (error);
- errno = err;
+ tr_logAddError (err_fmt, path, my_error->message);
+ tr_error_propagate (error, &my_error);
return NULL;
}
+
buf = tr_malloc (info.size + 1);
- if (!buf)
- {
- const int err = errno;
- tr_logAddError (err_fmt, path, _("Memory allocation failed"));
- tr_sys_file_close (fd, NULL);
- errno = err;
- return NULL;
- }
- if (!tr_sys_file_read (fd, buf, info.size, NULL, &error))
+
+ if (!tr_sys_file_read (fd, buf, info.size, NULL, &my_error))
{
- const int err = error->code;
- tr_logAddError (err_fmt, path, error->message);
+ tr_logAddError (err_fmt, path, my_error->message);
tr_sys_file_close (fd, NULL);
free (buf);
- tr_error_free (error);
- errno = err;
+ tr_error_propagate (error, &my_error);
return NULL;
}
* @brief Loads a file and returns its contents.
* On failure, NULL is returned and errno is set.
*/
-uint8_t* tr_loadFile (const char * filename, size_t * size) TR_GNUC_MALLOC
- TR_GNUC_NONNULL (1);
+uint8_t * tr_loadFile (const char * filename,
+ size_t * size,
+ tr_error ** error) TR_GNUC_MALLOC TR_GNUC_NONNULL (1);
/** @brief build a filename from a series of elements using the
****
***/
-int
+bool
tr_variantFromFile (tr_variant * setme,
tr_variant_fmt fmt,
- const char * filename)
+ const char * filename,
+ tr_error ** error)
{
- int err;
- size_t buflen;
+ bool ret = false;
uint8_t * buf;
- const int old_errno = errno;
+ size_t buflen;
- errno = 0;
- buf = tr_loadFile (filename, &buflen);
+ buf = tr_loadFile (filename, &buflen, error);
+ if (buf != NULL)
+ {
+ if (tr_variantFromBuf (setme, fmt, buf, buflen, filename, NULL) == 0)
+ ret = true;
+ else
+ tr_error_set_literal (error, 0, _("Unable to parse file content"));
- if (errno)
- err = errno;
- else
- err = tr_variantFromBuf (setme, fmt, buf, buflen, filename, NULL);
+ tr_free (buf);
+ }
- tr_free (buf);
- errno = old_errno;
- return err;
+ return ret;
}
int
struct evbuffer;
+struct tr_error;
+
/**
* @addtogroup tr_variant Variant
*
tr_variant_fmt fmt);
/* TR_VARIANT_FMT_JSON_LEAN and TR_VARIANT_FMT_JSON are equivalent here. */
-int tr_variantFromFile (tr_variant * setme,
- tr_variant_fmt fmt,
- const char * filename);
+bool tr_variantFromFile (tr_variant * setme,
+ tr_variant_fmt fmt,
+ const char * filename,
+ struct tr_error ** error);
/* TR_VARIANT_FMT_JSON_LEAN and TR_VARIANT_FMT_JSON are equivalent here. */
int tr_variantFromBuf (tr_variant * setme,
// update settings.json with our settings
tr_variant file_settings;
const QFile file (QDir(myConfigDir).absoluteFilePath(QLatin1String ("settings.json")));
- if (tr_variantFromFile (&file_settings, TR_VARIANT_FMT_JSON, file.fileName().toUtf8().constData()))
+ if (!tr_variantFromFile (&file_settings, TR_VARIANT_FMT_JSON, file.fileName().toUtf8().constData(), NULL))
tr_variantInitDict (&file_settings, PREFS_COUNT);
tr_variantMergeDicts (&file_settings, ¤t_settings);
tr_variantToFile (&file_settings, TR_VARIANT_FMT_JSON, file.fileName().toUtf8().constData());
#include <event2/buffer.h>
#include <libtransmission/transmission.h>
+#include <libtransmission/error.h>
#include <libtransmission/tr-getopt.h>
#include <libtransmission/utils.h>
#include <libtransmission/variant.h>
tr_variant top;
bool changed = false;
const char * filename = files[i];
+ tr_error * error = NULL;
printf ("%s\n", filename);
- if (tr_variantFromFile (&top, TR_VARIANT_FMT_BENC, filename))
+ if (!tr_variantFromFile (&top, TR_VARIANT_FMT_BENC, filename, &error))
{
- printf ("\tError reading file\n");
+ printf ("\tError reading file: %s\n", error->message);
+ tr_error_free (error);
continue;
}