Add total disk space to free-space RPC request (#1682)

* Add total space to free-space endpoint

* Update docs
This commit is contained in:
Johan 2021-10-14 20:07:16 +03:00 committed by GitHub
parent ab82e155be
commit 04f8b82308
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 89 additions and 62 deletions

View File

@ -679,10 +679,11 @@
Response arguments:
string | value type & description
------------+----------------------------------------------------------
"path" | string same as the Request argument
"size-bytes"| number the size, in bytes, of the free space in that directory
string | value type & description
-------------+----------------------------------------------------------
"path" | string same as the Request argument
"size-bytes" | number the size, in bytes, of the free space in that directory
"total_size" | number the total capacity, in bytes, of that directory
5.0. Protocol Versions
@ -854,6 +855,7 @@
| | | session-get | new arg "script-torrent-added-filename"
| | | torrent-get | new arg "file-count"
| | | torrent-get | new arg "primary-mime-type"
| | | free-space | new return arg "total-capacity"
5.1. Upcoming Breakage

View File

@ -268,11 +268,12 @@ extern "C"
#include <quota.h>
}
static int64_t getquota(char const* device)
struct tr_disk_space getquota(char const* device)
{
struct quotahandle* qh;
struct quotakey qk;
struct quotaval qv;
struct tr_disk_space disk_space = { -1, -1 };
int64_t limit;
int64_t freespace;
int64_t spaceused;
@ -281,7 +282,7 @@ static int64_t getquota(char const* device)
if (qh == nullptr)
{
return -1;
return disk_space;
}
qk.qk_idtype = QUOTA_IDTYPE_USER;
@ -291,7 +292,7 @@ static int64_t getquota(char const* device)
if (quota_get(qh, &qk, &qv) == -1)
{
quota_close(qh);
return -1;
return disk_space;
}
if (qv.qv_softlimit > 0)
@ -305,19 +306,21 @@ static int64_t getquota(char const* device)
else
{
quota_close(qh);
return -1;
return disk_space;
}
spaceused = qv.qv_usage;
quota_close(qh);
freespace = limit - spaceused;
return freespace < 0 ? 0 : freespace;
disk_space.free = freespace < 0 ? 0 : freespace;
disk_space.total = limit;
return disk_space;
}
#else
static int64_t getquota(char const* device)
static struct tr_disk_space getquota(char const* device)
{
#if defined(__DragonFly__)
struct ufs_dqblk dq;
@ -326,12 +329,13 @@ static int64_t getquota(char const* device)
#endif
int64_t limit;
int64_t freespace;
struct tr_disk_space disk_space = { -1, -1 };
int64_t spaceused;
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__)
if (quotactl(device, QCMD(Q_GETQUOTA, USRQUOTA), getuid(), (caddr_t)&dq) != 0)
{
return -1;
return disk_space;
}
#elif defined(__sun)
struct quotctl op;
@ -339,7 +343,7 @@ static int64_t getquota(char const* device)
if (fd < 0)
{
return -1;
return disk_space;
}
op.op = Q_GETQUOTA;
@ -349,14 +353,14 @@ static int64_t getquota(char const* device)
if (ioctl(fd, Q_QUOTACTL, &op) != 0)
{
close(fd);
return -1;
return disk_space;
}
close(fd);
#else
if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device, getuid(), (caddr_t)&dq) != 0)
{
return -1;
return disk_space;
}
#endif
@ -372,7 +376,7 @@ static int64_t getquota(char const* device)
else
{
/* No quota enabled for this user */
return -1;
return disk_space;
}
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
@ -390,9 +394,13 @@ static int64_t getquota(char const* device)
freespace = limit - spaceused;
#ifdef __APPLE__
return freespace < 0 ? 0 : freespace;
disk_space.free = freespace < 0 ? 0 : freespace;
disk_space.total = limit < 0 ? 0 : limit;
return disk_space;
#else
return freespace < 0 ? 0 : (freespace * 1024);
disk_space.free = freespace < 0 ? 0 : (freespace * 1024);
disk_space.total = limit < 0 ? 0 : (limit * 1024);
return disk_space;
#endif
}
@ -400,10 +408,11 @@ static int64_t getquota(char const* device)
#ifdef HAVE_XQM
static int64_t getxfsquota(char* device)
static struct tr_disk_space getxfsquota(char* device)
{
int64_t limit;
int64_t freespace;
struct tr_disk_space disk_space = { -1, -1 };
struct fs_disk_quota dq;
if (quotactl(QCMD(Q_XGETQUOTA, USRQUOTA), device, getuid(), (caddr_t)&dq) == 0)
@ -420,24 +429,28 @@ static int64_t getxfsquota(char* device)
else
{
/* No quota enabled for this user */
return -1;
return disk_space;
}
freespace = limit - (dq.d_bcount >> 1);
return freespace < 0 ? 0 : (freespace * 1024);
freespace = freespace < 0 ? 0 : (freespace * 1024);
limit = limit * 1024;
disk_space.free = freespace;
disk_space.total = limit;
return disk_space;
}
/* something went wrong */
return -1;
return disk_space;
}
#endif /* HAVE_XQM */
#endif /* _WIN32 */
static int64_t tr_getQuotaFreeSpace([[maybe_unused]] struct tr_device_info const* info)
static struct tr_disk_space tr_getQuotaSpace([[maybe_unused]] struct tr_device_info const* info)
{
int64_t ret = -1;
struct tr_disk_space ret = { -1, -1 };
#ifndef _WIN32
@ -457,11 +470,11 @@ static int64_t tr_getQuotaFreeSpace([[maybe_unused]] struct tr_device_info const
return ret;
}
static int64_t tr_getDiskFreeSpace(char const* path)
static struct tr_disk_space tr_getDiskSpace(char const* path)
{
#ifdef _WIN32
int64_t ret = -1;
struct tr_disk_space ret = { -1, -1 };
wchar_t* wide_path;
wide_path = tr_win32_utf8_to_native(path, -1);
@ -469,10 +482,12 @@ static int64_t tr_getDiskFreeSpace(char const* path)
if (wide_path != nullptr)
{
ULARGE_INTEGER freeBytesAvailable;
ULARGE_INTEGER totalBytesAvailable;
if (GetDiskFreeSpaceExW(wide_path, &freeBytesAvailable, nullptr, nullptr))
if (GetDiskFreeSpaceExW(wide_path, &freeBytesAvailable, &totalBytesAvailable, nullptr))
{
ret = freeBytesAvailable.QuadPart;
ret.free = freeBytesAvailable.QuadPart;
ret.total = totalBytesAvailable.QuadPart;
}
tr_free(wide_path);
@ -483,13 +498,15 @@ static int64_t tr_getDiskFreeSpace(char const* path)
#elif defined(HAVE_STATVFS)
struct statvfs buf;
return statvfs(path, &buf) ? -1 : (int64_t)buf.f_bavail * (int64_t)buf.f_frsize;
return statvfs(path, &buf) ?
(struct tr_disk_space){ -1, -1 } :
(struct tr_disk_space){ (int64_t)buf.f_bavail * (int64_t)buf.f_frsize, (int64_t)buf.f_blocks * (int64_t)buf.f_frsize };
#else
#warning FIXME: not implemented
return -1;
return { -1, -1 };
#endif
}
@ -520,26 +537,27 @@ void tr_device_info_free(struct tr_device_info* info)
}
}
int64_t tr_device_info_get_free_space(struct tr_device_info const* info)
struct tr_disk_space tr_device_info_get_disk_space(struct tr_device_info const* info)
{
int64_t free_space;
struct tr_disk_space space;
if (info == nullptr || info->path == nullptr)
{
errno = EINVAL;
free_space = -1;
space.free = -1;
space.total = -1;
}
else
{
free_space = tr_getQuotaFreeSpace(info);
space = tr_getQuotaSpace(info);
if (free_space < 0)
if (space.free < 0 || space.total < 0)
{
free_space = tr_getDiskFreeSpace(info->path);
space = tr_getDiskSpace(info->path);
}
}
return free_space;
return space;
}
/***

View File

@ -24,11 +24,18 @@ struct tr_device_info
char* fstype;
};
struct tr_disk_space
{
int64_t free;
int64_t total;
};
struct tr_device_info* tr_device_info_create(char const* path);
/** If the disk quota is enabled and readable, this returns how much is available in the quota.
Otherwise, it returns how much is available on the disk, or -1 on error. */
int64_t tr_device_info_get_free_space(struct tr_device_info const* info);
/** Values represents the total space on disk.
If the disk quota (free space) is enabled and readable, this returns how much is available in the quota.
Otherwise, it returns how much is available on the disk, or { -1, -1 } on error. */
struct tr_disk_space tr_device_info_get_disk_space(struct tr_device_info const* info);
void tr_device_info_free(struct tr_device_info* info);

View File

@ -26,7 +26,7 @@
#include "fdlimit.h"
#include "file.h"
#include "log.h"
#include "platform-quota.h" /* tr_device_info_get_free_space() */
#include "platform-quota.h" /* tr_device_info_get_disk_space() */
#include "rpcimpl.h"
#include "session.h"
#include "session-id.h"
@ -2388,7 +2388,7 @@ static void addSessionField(tr_session* s, tr_variant* d, tr_quark key)
break;
case TR_KEY_download_dir_free_space:
tr_variantDictAddInt(d, key, tr_device_info_get_free_space(s->downloadDir));
tr_variantDictAddInt(d, key, tr_device_info_get_disk_space(s->downloadDir).free);
break;
case TR_KEY_download_queue_enabled:
@ -2627,7 +2627,7 @@ static char const* freeSpace(
int tmperr;
char const* path = nullptr;
char const* err = nullptr;
int64_t free_space = -1;
struct tr_disk_space dir_space = { -1, -1 };
if (!tr_variantDictFindStr(args_in, TR_KEY_path, &path, nullptr))
{
@ -2642,9 +2642,9 @@ static char const* freeSpace(
/* get the free space */
tmperr = errno;
errno = 0;
free_space = tr_sessionGetDirFreeSpace(session, path);
dir_space = tr_getDirSpace(path);
if (free_space < 0)
if (dir_space.free < 0 || dir_space.total < 0)
{
err = tr_strerror(errno);
}
@ -2657,7 +2657,8 @@ static char const* freeSpace(
tr_variantDictAddStr(args_out, TR_KEY_path, path);
}
tr_variantDictAddInt(args_out, TR_KEY_size_bytes, free_space);
tr_variantDictAddInt(args_out, TR_KEY_size_bytes, dir_space.free);
tr_variantDictAddInt(args_out, TR_KEY_total_size, dir_space.total);
return err;
}

View File

@ -1232,11 +1232,11 @@ int64_t tr_sessionGetDirFreeSpace(tr_session* session, char const* dir)
if (tr_strcmp0(dir, tr_sessionGetDownloadDir(session)) == 0)
{
free_space = tr_device_info_get_free_space(session->downloadDir);
free_space = tr_device_info_get_disk_space(session->downloadDir).free;
}
else
{
free_space = tr_getDirFreeSpace(dir);
free_space = tr_getDirSpace(dir).free;
}
return free_space;

View File

@ -63,7 +63,7 @@
#include "mime-types.h"
#include "net.h"
#include "platform.h" /* tr_lockLock() */
#include "platform-quota.h" /* tr_device_info_create(), tr_device_info_get_free_space(), tr_device_info_free() */
#include "platform-quota.h" /* tr_device_info_create(), tr_device_info_get_disk_space(), tr_device_info_free() */
#include "tr-assert.h"
#include "utils.h"
#include "variant.h"
@ -390,24 +390,21 @@ char* tr_buildPath(char const* first_element, ...)
return buf;
}
int64_t tr_getDirFreeSpace(char const* dir)
struct tr_disk_space tr_getDirSpace(char const* dir)
{
int64_t free_space;
struct tr_disk_space disk_space = { -1, -1 };
if (tr_str_is_empty(dir))
{
errno = EINVAL;
free_space = -1;
}
else
{
struct tr_device_info* info;
info = tr_device_info_create(dir);
free_space = tr_device_info_get_free_space(info);
tr_device_info_free(info);
return disk_space;
}
return free_space;
struct tr_device_info* info;
info = tr_device_info_create(dir);
disk_space = tr_device_info_get_disk_space(info);
tr_device_info_free(info);
return disk_space;
}
/****

View File

@ -27,6 +27,8 @@ struct timeval;
struct tr_error;
struct tr_disk_space;
/**
* @addtogroup utils Utilities
* @{
@ -79,10 +81,10 @@ uint8_t* tr_loadFile(char const* filename, size_t* size, struct tr_error** error
char* tr_buildPath(char const* first_element, ...) TR_GNUC_NULL_TERMINATED TR_GNUC_MALLOC;
/**
* @brief Get available disk space (in bytes) for the specified folder.
* @return zero or positive integer on success, -1 in case of error.
* @brief Get disk capacity and free disk space (in bytes) for the specified folder.
* @return struct with free and total as zero or positive integer on success, -1 in case of error.
*/
int64_t tr_getDirFreeSpace(char const* path);
struct tr_disk_space tr_getDirSpace(char const* path);
/**
* @brief Convenience wrapper around timer_add() to have a timer wake up in a number of seconds and microseconds