mirror of
https://github.com/transmission/transmission
synced 2025-01-30 19:03:04 +00:00
move platform.c's quota code into its own file. Fixes FTBFS reported in bug #5389 and is also a nice piece of encapsulation. Patch by rb07
This commit is contained in:
parent
e0e4849abd
commit
74d0f305a6
8 changed files with 449 additions and 401 deletions
|
@ -43,6 +43,7 @@ libtransmission_a_SOURCES = \
|
|||
peer-mgr.c \
|
||||
peer-msgs.c \
|
||||
platform.c \
|
||||
platform-quota.c \
|
||||
port-forwarding.c \
|
||||
ptrarray.c \
|
||||
quark.c \
|
||||
|
@ -100,6 +101,7 @@ noinst_HEADERS = \
|
|||
peer-mgr.h \
|
||||
peer-msgs.h \
|
||||
platform.h \
|
||||
platform-quota.h \
|
||||
port-forwarding.h \
|
||||
ptrarray.h \
|
||||
quark.h \
|
||||
|
|
390
libtransmission/platform-quota.c
Normal file
390
libtransmission/platform-quota.c
Normal file
|
@ -0,0 +1,390 @@
|
|||
/*
|
||||
* This file Copyright (C) Mnemosyne LLC
|
||||
*
|
||||
* This file is licensed by the GPL version 2. Works owned by the
|
||||
* Transmission project are granted a special exemption to clause 2 (b)
|
||||
* so that the bulk of its code can remain under the MIT license.
|
||||
* This exemption does not extend to derived works not owned by
|
||||
* the Transmission project.
|
||||
*
|
||||
* $Id:$
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h> /* getuid() */
|
||||
#include <event2/util.h> /* evutil_ascii_strcasecmp () */
|
||||
|
||||
#ifndef WIN32
|
||||
#include <sys/types.h> /* types needed by quota.h */
|
||||
#ifdef __FreeBSD__
|
||||
#include <ufs/ufs/quota.h> /* quotactl() */
|
||||
#elif defined (__sun)
|
||||
#include <sys/fs/ufs_quota.h> /* quotactl */
|
||||
#else
|
||||
#include <sys/quota.h> /* quotactl() */
|
||||
#endif
|
||||
#ifdef HAVE_GETMNTENT
|
||||
#ifdef __sun
|
||||
#include <stdio.h>
|
||||
#include <sys/mntent.h>
|
||||
#include <sys/mnttab.h>
|
||||
#define _PATH_MOUNTED MNTTAB
|
||||
#else
|
||||
#include <mntent.h>
|
||||
#include <paths.h> /* _PATH_MOUNTED */
|
||||
#endif
|
||||
#else /* BSD derived systems */
|
||||
#include <sys/param.h>
|
||||
#include <sys/ucred.h>
|
||||
#include <sys/mount.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SYS_DARWIN
|
||||
#define HAVE_SYS_STATVFS_H
|
||||
#define HAVE_STATVFS
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_STATVFS_H
|
||||
#include <sys/statvfs.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XFS_XFS_H
|
||||
#define HAVE_XQM
|
||||
#include <xfs/xqm.h>
|
||||
#endif
|
||||
|
||||
#include "transmission.h"
|
||||
#include "utils.h"
|
||||
#include "platform-quota.h"
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
#ifndef WIN32
|
||||
static const char *
|
||||
getdev (const char * path)
|
||||
{
|
||||
#ifdef HAVE_GETMNTENT
|
||||
|
||||
FILE * fp;
|
||||
|
||||
#ifdef __sun
|
||||
struct mnttab * mnt;
|
||||
fp = fopen(_PATH_MOUNTED, "r");
|
||||
if (fp == NULL)
|
||||
return NULL;
|
||||
|
||||
while (getmntent(fp, mnt))
|
||||
if (!tr_strcmp0 (path, mnt->mnt_mountp))
|
||||
break;
|
||||
fclose(fp);
|
||||
return mnt ? mnt->mnt_fstype : NULL;
|
||||
#else
|
||||
struct mntent * mnt;
|
||||
|
||||
fp = setmntent(_PATH_MOUNTED, "r");
|
||||
if (fp == NULL)
|
||||
return NULL;
|
||||
|
||||
while ((mnt = getmntent(fp)) != NULL)
|
||||
if (!tr_strcmp0 (path, mnt->mnt_dir))
|
||||
break;
|
||||
|
||||
endmntent(fp);
|
||||
return mnt ? mnt->mnt_fsname : NULL;
|
||||
#endif
|
||||
#else /* BSD derived systems */
|
||||
|
||||
int i;
|
||||
int n;
|
||||
struct statfs * mnt;
|
||||
|
||||
n = getmntinfo(&mnt, MNT_WAIT);
|
||||
if (!n)
|
||||
return NULL;
|
||||
|
||||
for (i=0; i<n; i++)
|
||||
if (!tr_strcmp0 (path, mnt[i].f_mntonname))
|
||||
break;
|
||||
|
||||
return (i < n) ? mnt[i].f_mntfromname : NULL;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char *
|
||||
getfstype (const char * device)
|
||||
{
|
||||
|
||||
#ifdef HAVE_GETMNTENT
|
||||
|
||||
FILE * fp;
|
||||
#ifdef __sun
|
||||
struct mnttab *mnt;
|
||||
fp = fopen(_PATH_MOUNTED, "r");
|
||||
if (fp == NULL)
|
||||
return NULL;
|
||||
while (getmntent(fp, mnt))
|
||||
if (!tr_strcmp0 (device, mnt->mnt_mountp))
|
||||
break;
|
||||
fclose(fp);
|
||||
return mnt ? mnt->mnt_fstype : NULL;
|
||||
#else
|
||||
struct mntent *mnt;
|
||||
|
||||
fp = setmntent (_PATH_MOUNTED, "r");
|
||||
if (fp == NULL)
|
||||
return NULL;
|
||||
|
||||
while ((mnt = getmntent (fp)) != NULL)
|
||||
if (!tr_strcmp0 (device, mnt->mnt_fsname))
|
||||
break;
|
||||
|
||||
endmntent(fp);
|
||||
return mnt ? mnt->mnt_type : NULL;
|
||||
#endif
|
||||
#else /* BSD derived systems */
|
||||
|
||||
int i;
|
||||
int n;
|
||||
struct statfs *mnt;
|
||||
|
||||
n = getmntinfo(&mnt, MNT_WAIT);
|
||||
if (!n)
|
||||
return NULL;
|
||||
|
||||
for (i=0; i<n; i++)
|
||||
if (!tr_strcmp0 (device, mnt[i].f_mntfromname))
|
||||
break;
|
||||
|
||||
return (i < n) ? mnt[i].f_fstypename : NULL;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char *
|
||||
getblkdev (const char * path)
|
||||
{
|
||||
char * c;
|
||||
char * dir;
|
||||
const char * device;
|
||||
|
||||
dir = tr_strdup(path);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
device = getdev (dir);
|
||||
if (device != NULL)
|
||||
break;
|
||||
|
||||
c = strrchr (dir, '/');
|
||||
if (c != NULL)
|
||||
*c = '\0';
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
tr_free (dir);
|
||||
return device;
|
||||
}
|
||||
|
||||
static int64_t
|
||||
getquota (const char * device)
|
||||
{
|
||||
struct dqblk dq;
|
||||
int64_t limit;
|
||||
int64_t freespace;
|
||||
int64_t spaceused;
|
||||
|
||||
#if defined(__FreeBSD__) || defined(SYS_DARWIN)
|
||||
if (quotactl(device, QCMD(Q_GETQUOTA, USRQUOTA), getuid(), (caddr_t) &dq) == 0)
|
||||
{
|
||||
#elif defined(__sun)
|
||||
struct quotctl op;
|
||||
int fd = open(device, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
op.op = Q_GETQUOTA;
|
||||
op.uid = getuid();
|
||||
op.addr = (caddr_t) &dq;
|
||||
if (ioctl(fd, Q_QUOTACTL, &op) == 0)
|
||||
{
|
||||
close(fd);
|
||||
#else
|
||||
if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device, getuid(), (caddr_t) &dq) == 0)
|
||||
{
|
||||
#endif
|
||||
if (dq.dqb_bsoftlimit > 0)
|
||||
{
|
||||
/* Use soft limit first */
|
||||
limit = dq.dqb_bsoftlimit;
|
||||
}
|
||||
else if (dq.dqb_bhardlimit > 0)
|
||||
{
|
||||
limit = dq.dqb_bhardlimit;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No quota enabled for this user */
|
||||
return -1;
|
||||
}
|
||||
#if defined(__FreeBSD__)
|
||||
spaceused = (int64_t) dq.dqb_curblocks >> 1;
|
||||
#elif defined(SYS_DARWIN)
|
||||
spaceused = (int64_t) dq.dqb_curbytes;
|
||||
#elif defined(__UCLIBC__)
|
||||
spaceused = (int64_t) btodb(dq.dqb_curblocks);
|
||||
#elif defined(__sun)
|
||||
spaceused = (int64_t) dq.dqb_curblocks >> 1;
|
||||
#else
|
||||
spaceused = btodb(dq.dqb_curspace);
|
||||
#endif
|
||||
freespace = limit - spaceused;
|
||||
#ifdef SYS_DARWIN
|
||||
return (freespace < 0) ? 0 : freespace;
|
||||
#else
|
||||
return (freespace < 0) ? 0 : freespace * 1024;
|
||||
#endif
|
||||
}
|
||||
#if defined(__sun)
|
||||
close(fd);
|
||||
#endif
|
||||
/* something went wrong */
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_XQM
|
||||
static int64_t
|
||||
getxfsquota (char * device)
|
||||
{
|
||||
int64_t limit;
|
||||
int64_t freespace;
|
||||
struct fs_disk_quota dq;
|
||||
|
||||
if (quotactl(QCMD(Q_XGETQUOTA, USRQUOTA), device, getuid(), (caddr_t) &dq) == 0)
|
||||
{
|
||||
if (dq.d_blk_softlimit > 0)
|
||||
{
|
||||
/* Use soft limit first */
|
||||
limit = dq.d_blk_softlimit >> 1;
|
||||
}
|
||||
else if (dq.d_blk_hardlimit > 0)
|
||||
{
|
||||
limit = dq.d_blk_hardlimit >> 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No quota enabled for this user */
|
||||
return -1;
|
||||
}
|
||||
|
||||
freespace = limit - (dq.d_bcount >> 1);
|
||||
return (freespace < 0) ? 0 : freespace * 1024;
|
||||
}
|
||||
|
||||
/* something went wrong */
|
||||
return -1;
|
||||
}
|
||||
#endif /* HAVE_XQM */
|
||||
#endif /* WIN32 */
|
||||
|
||||
static int64_t
|
||||
tr_getQuotaFreeSpace (const struct tr_device_info * info)
|
||||
{
|
||||
int64_t ret = -1;
|
||||
|
||||
#ifndef WIN32
|
||||
|
||||
if (info->fstype && !evutil_ascii_strcasecmp(info->fstype, "xfs"))
|
||||
{
|
||||
#ifdef HAVE_XQM
|
||||
ret = getxfsquota (info->device);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = getquota (info->device);
|
||||
}
|
||||
#endif /* WIN32 */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int64_t
|
||||
tr_getDiskFreeSpace (const char * path)
|
||||
{
|
||||
#ifdef WIN32
|
||||
|
||||
uint64_t freeBytesAvailable = 0;
|
||||
return GetDiskFreeSpaceEx (path, &freeBytesAvailable, NULL, NULL)
|
||||
? (int64_t)freeBytesAvailable
|
||||
: -1;
|
||||
|
||||
#elif defined(HAVE_STATVFS)
|
||||
|
||||
struct statvfs buf;
|
||||
return statvfs(path, &buf) ? -1 : (int64_t)buf.f_bavail * (int64_t)buf.f_frsize;
|
||||
|
||||
#else
|
||||
|
||||
#warning FIXME: not implemented
|
||||
return -1;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
struct tr_device_info *
|
||||
tr_device_info_create (const char * path)
|
||||
{
|
||||
struct tr_device_info * info;
|
||||
|
||||
info = tr_new0 (struct tr_device_info, 1);
|
||||
info->path = tr_strdup (path);
|
||||
#ifndef WIN32
|
||||
info->device = tr_strdup (getblkdev (path));
|
||||
info->fstype = tr_strdup (getfstype (path));
|
||||
#endif
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
void
|
||||
tr_device_info_free (struct tr_device_info * info)
|
||||
{
|
||||
if (info != NULL)
|
||||
{
|
||||
tr_free (info->fstype);
|
||||
tr_free (info->device);
|
||||
tr_free (info->path);
|
||||
tr_free (info);
|
||||
}
|
||||
}
|
||||
|
||||
int64_t
|
||||
tr_device_info_get_free_space (const struct tr_device_info * info)
|
||||
{
|
||||
int64_t free_space;
|
||||
|
||||
if ((info == NULL) || (info->path == NULL))
|
||||
{
|
||||
errno = EINVAL;
|
||||
free_space = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
free_space = tr_getQuotaFreeSpace (info);
|
||||
|
||||
if (free_space < 0)
|
||||
free_space = tr_getDiskFreeSpace (info->path);
|
||||
}
|
||||
|
||||
return free_space;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
42
libtransmission/platform-quota.h
Normal file
42
libtransmission/platform-quota.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* This file Copyright (C) Mnemosyne LLC
|
||||
*
|
||||
* This file is licensed by the GPL version 2. Works owned by the
|
||||
* Transmission project are granted a special exemption to clause 2 (b)
|
||||
* so that the bulk of its code can remain under the MIT license.
|
||||
* This exemption does not extend to derived works not owned by
|
||||
* the Transmission project.
|
||||
*
|
||||
* $Id:$
|
||||
*/
|
||||
|
||||
#ifndef __TRANSMISSION__
|
||||
#error only libtransmission should #include this header.
|
||||
#endif
|
||||
|
||||
#ifndef TR_PLATFORM_QUOTA_H
|
||||
#define TR_PLATFORM_QUOTA_H
|
||||
|
||||
/**
|
||||
* @addtogroup tr_session Session
|
||||
* @{
|
||||
*/
|
||||
|
||||
struct tr_device_info
|
||||
{
|
||||
char * path;
|
||||
char * device;
|
||||
char * fstype;
|
||||
};
|
||||
|
||||
struct tr_device_info * tr_device_info_create (const char * 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 (const struct tr_device_info * info);
|
||||
|
||||
void tr_device_info_free (struct tr_device_info * info);
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif
|
|
@ -10,32 +10,18 @@
|
|||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef WIN32
|
||||
#include <sys/types.h> /* types needed by quota.h */
|
||||
#ifdef __FreeBSD__
|
||||
#include <ufs/ufs/quota.h> /* quotactl() */
|
||||
#elif defined (__sun)
|
||||
#include <sys/fs/ufs_quota.h> /* quotactl */
|
||||
#else
|
||||
#include <sys/quota.h> /* quotactl() */
|
||||
#endif
|
||||
#ifdef HAVE_GETMNTENT
|
||||
#ifdef __sun
|
||||
#include <stdio.h>
|
||||
#include <sys/mntent.h>
|
||||
#include <sys/mnttab.h>
|
||||
#define _PATH_MOUNTED MNTTAB
|
||||
#else
|
||||
#include <mntent.h>
|
||||
#include <paths.h> /* _PATH_MOUNTED */
|
||||
#endif
|
||||
#else /* BSD derived systems */
|
||||
#include <sys/param.h>
|
||||
#include <sys/ucred.h>
|
||||
#include <sys/mount.h>
|
||||
#endif
|
||||
#define _XOPEN_SOURCE 600 /* needed for recursive locks. */
|
||||
#ifndef __USE_UNIX98
|
||||
#define __USE_UNIX98 /* some older Linuxes need it spelt out for them */
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h> /* getuid(), close() */
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <w32api.h>
|
||||
#define WINVER WindowsXP
|
||||
|
@ -48,48 +34,18 @@
|
|||
#ifdef __HAIKU__
|
||||
#include <FindDirectory.h>
|
||||
#endif
|
||||
#define _XOPEN_SOURCE 600 /* needed for recursive locks. */
|
||||
#ifndef __USE_UNIX98
|
||||
#define __USE_UNIX98 /* some older Linuxes need it spelt out for them */
|
||||
#endif
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef SYS_DARWIN
|
||||
#define HAVE_SYS_STATVFS_H
|
||||
#define HAVE_STATVFS
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_SYS_STATVFS_H
|
||||
#include <sys/statvfs.h>
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
#include <libgen.h>
|
||||
#include <libgen.h> /* dirname() */
|
||||
#endif
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h> /* getuid getpid close */
|
||||
|
||||
#ifdef HAVE_XFS_XFS_H
|
||||
#define HAVE_XQM
|
||||
#include <xfs/xqm.h>
|
||||
#endif
|
||||
|
||||
#include <event2/util.h> /* evutil_ascii_strcasecmp () */
|
||||
|
||||
#include "transmission.h"
|
||||
#include "session.h"
|
||||
#include "list.h"
|
||||
#include "log.h"
|
||||
#include "platform.h"
|
||||
#include "utils.h"
|
||||
|
||||
/***
|
||||
**** THREADS
|
||||
|
@ -611,334 +567,6 @@ tr_getWebClientDir (const tr_session * session UNUSED)
|
|||
return s;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
#ifndef WIN32
|
||||
static const char *
|
||||
getdev (const char * path)
|
||||
{
|
||||
#ifdef HAVE_GETMNTENT
|
||||
|
||||
FILE * fp;
|
||||
|
||||
#ifdef __sun
|
||||
struct mnttab * mnt;
|
||||
fp = fopen(_PATH_MOUNTED, "r");
|
||||
if (fp == NULL)
|
||||
return NULL;
|
||||
|
||||
while (getmntent(fp, mnt))
|
||||
if (!tr_strcmp0 (path, mnt->mnt_mountp))
|
||||
break;
|
||||
fclose(fp);
|
||||
return mnt ? mnt->mnt_fstype : NULL;
|
||||
#else
|
||||
struct mntent * mnt;
|
||||
|
||||
fp = setmntent(_PATH_MOUNTED, "r");
|
||||
if (fp == NULL)
|
||||
return NULL;
|
||||
|
||||
while ((mnt = getmntent(fp)) != NULL)
|
||||
if (!tr_strcmp0 (path, mnt->mnt_dir))
|
||||
break;
|
||||
|
||||
endmntent(fp);
|
||||
return mnt ? mnt->mnt_fsname : NULL;
|
||||
#endif
|
||||
#else /* BSD derived systems */
|
||||
|
||||
int i;
|
||||
int n;
|
||||
struct statfs * mnt;
|
||||
|
||||
n = getmntinfo(&mnt, MNT_WAIT);
|
||||
if (!n)
|
||||
return NULL;
|
||||
|
||||
for (i=0; i<n; i++)
|
||||
if (!tr_strcmp0 (path, mnt[i].f_mntonname))
|
||||
break;
|
||||
|
||||
return (i < n) ? mnt[i].f_mntfromname : NULL;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char *
|
||||
getfstype (const char * device)
|
||||
{
|
||||
|
||||
#ifdef HAVE_GETMNTENT
|
||||
|
||||
FILE * fp;
|
||||
#ifdef __sun
|
||||
struct mnttab *mnt;
|
||||
fp = fopen(_PATH_MOUNTED, "r");
|
||||
if (fp == NULL)
|
||||
return NULL;
|
||||
while (getmntent(fp, mnt))
|
||||
if (!tr_strcmp0 (device, mnt->mnt_mountp))
|
||||
break;
|
||||
fclose(fp);
|
||||
return mnt ? mnt->mnt_fstype : NULL;
|
||||
#else
|
||||
struct mntent *mnt;
|
||||
|
||||
fp = setmntent (_PATH_MOUNTED, "r");
|
||||
if (fp == NULL)
|
||||
return NULL;
|
||||
|
||||
while ((mnt = getmntent (fp)) != NULL)
|
||||
if (!tr_strcmp0 (device, mnt->mnt_fsname))
|
||||
break;
|
||||
|
||||
endmntent(fp);
|
||||
return mnt ? mnt->mnt_type : NULL;
|
||||
#endif
|
||||
#else /* BSD derived systems */
|
||||
|
||||
int i;
|
||||
int n;
|
||||
struct statfs *mnt;
|
||||
|
||||
n = getmntinfo(&mnt, MNT_WAIT);
|
||||
if (!n)
|
||||
return NULL;
|
||||
|
||||
for (i=0; i<n; i++)
|
||||
if (!tr_strcmp0 (device, mnt[i].f_mntfromname))
|
||||
break;
|
||||
|
||||
return (i < n) ? mnt[i].f_fstypename : NULL;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char *
|
||||
getblkdev (const char * path)
|
||||
{
|
||||
char * c;
|
||||
char * dir;
|
||||
const char * device;
|
||||
|
||||
dir = tr_strdup(path);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
device = getdev (dir);
|
||||
if (device != NULL)
|
||||
break;
|
||||
|
||||
c = strrchr (dir, '/');
|
||||
if (c != NULL)
|
||||
*c = '\0';
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
tr_free (dir);
|
||||
return device;
|
||||
}
|
||||
|
||||
static int64_t
|
||||
getquota (const char * device)
|
||||
{
|
||||
struct dqblk dq;
|
||||
int64_t limit;
|
||||
int64_t freespace;
|
||||
int64_t spaceused;
|
||||
|
||||
#if defined(__FreeBSD__) || defined(SYS_DARWIN)
|
||||
if (quotactl(device, QCMD(Q_GETQUOTA, USRQUOTA), getuid(), (caddr_t) &dq) == 0)
|
||||
{
|
||||
#elif defined(__sun)
|
||||
struct quotctl op;
|
||||
int fd = open(device, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
op.op = Q_GETQUOTA;
|
||||
op.uid = getuid();
|
||||
op.addr = (caddr_t) &dq;
|
||||
if (ioctl(fd, Q_QUOTACTL, &op) == 0)
|
||||
{
|
||||
close(fd);
|
||||
#else
|
||||
if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device, getuid(), (caddr_t) &dq) == 0)
|
||||
{
|
||||
#endif
|
||||
if (dq.dqb_bsoftlimit > 0)
|
||||
{
|
||||
/* Use soft limit first */
|
||||
limit = dq.dqb_bsoftlimit;
|
||||
}
|
||||
else if (dq.dqb_bhardlimit > 0)
|
||||
{
|
||||
limit = dq.dqb_bhardlimit;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No quota enabled for this user */
|
||||
return -1;
|
||||
}
|
||||
#if defined(__FreeBSD__)
|
||||
spaceused = (int64_t) dq.dqb_curblocks >> 1;
|
||||
#elif defined(SYS_DARWIN)
|
||||
spaceused = (int64_t) dq.dqb_curbytes;
|
||||
#elif defined(__UCLIBC__)
|
||||
spaceused = (int64_t) btodb(dq.dqb_curblocks);
|
||||
#elif defined(__sun)
|
||||
spaceused = (int64_t) dq.dqb_curblocks >> 1;
|
||||
#else
|
||||
spaceused = btodb(dq.dqb_curspace);
|
||||
#endif
|
||||
freespace = limit - spaceused;
|
||||
#ifdef SYS_DARWIN
|
||||
return (freespace < 0) ? 0 : freespace;
|
||||
#else
|
||||
return (freespace < 0) ? 0 : freespace * 1024;
|
||||
#endif
|
||||
}
|
||||
#if defined(__sun)
|
||||
close(fd);
|
||||
#endif
|
||||
/* something went wrong */
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_XQM
|
||||
static int64_t
|
||||
getxfsquota (char * device)
|
||||
{
|
||||
int64_t limit;
|
||||
int64_t freespace;
|
||||
struct fs_disk_quota dq;
|
||||
|
||||
if (quotactl(QCMD(Q_XGETQUOTA, USRQUOTA), device, getuid(), (caddr_t) &dq) == 0)
|
||||
{
|
||||
if (dq.d_blk_softlimit > 0)
|
||||
{
|
||||
/* Use soft limit first */
|
||||
limit = dq.d_blk_softlimit >> 1;
|
||||
}
|
||||
else if (dq.d_blk_hardlimit > 0)
|
||||
{
|
||||
limit = dq.d_blk_hardlimit >> 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No quota enabled for this user */
|
||||
return -1;
|
||||
}
|
||||
|
||||
freespace = limit - (dq.d_bcount >> 1);
|
||||
return (freespace < 0) ? 0 : freespace * 1024;
|
||||
}
|
||||
|
||||
/* something went wrong */
|
||||
return -1;
|
||||
}
|
||||
#endif /* HAVE_XQM */
|
||||
#endif /* WIN32 */
|
||||
|
||||
static int64_t
|
||||
tr_getQuotaFreeSpace (const struct tr_device_info * info)
|
||||
{
|
||||
int64_t ret = -1;
|
||||
|
||||
#ifndef WIN32
|
||||
|
||||
if (info->fstype && !evutil_ascii_strcasecmp(info->fstype, "xfs"))
|
||||
{
|
||||
#ifdef HAVE_XQM
|
||||
ret = getxfsquota (info->device);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = getquota (info->device);
|
||||
}
|
||||
#endif /* WIN32 */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int64_t
|
||||
tr_getDiskFreeSpace (const char * path)
|
||||
{
|
||||
#ifdef WIN32
|
||||
|
||||
uint64_t freeBytesAvailable = 0;
|
||||
return GetDiskFreeSpaceEx (path, &freeBytesAvailable, NULL, NULL)
|
||||
? (int64_t)freeBytesAvailable
|
||||
: -1;
|
||||
|
||||
#elif defined(HAVE_STATVFS)
|
||||
|
||||
struct statvfs buf;
|
||||
return statvfs(path, &buf) ? -1 : (int64_t)buf.f_bavail * (int64_t)buf.f_frsize;
|
||||
|
||||
#else
|
||||
|
||||
#warning FIXME: not implemented
|
||||
return -1;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
struct tr_device_info *
|
||||
tr_device_info_create (const char * path)
|
||||
{
|
||||
struct tr_device_info * info;
|
||||
|
||||
info = tr_new0 (struct tr_device_info, 1);
|
||||
info->path = tr_strdup (path);
|
||||
#ifndef WIN32
|
||||
info->device = tr_strdup (getblkdev (path));
|
||||
info->fstype = tr_strdup (getfstype (path));
|
||||
#endif
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
void
|
||||
tr_device_info_free (struct tr_device_info * info)
|
||||
{
|
||||
if (info != NULL)
|
||||
{
|
||||
tr_free (info->fstype);
|
||||
tr_free (info->device);
|
||||
tr_free (info->path);
|
||||
tr_free (info);
|
||||
}
|
||||
}
|
||||
|
||||
int64_t
|
||||
tr_device_info_get_free_space (const struct tr_device_info * info)
|
||||
{
|
||||
int64_t free_space;
|
||||
|
||||
if ((info == NULL) || (info->path == NULL))
|
||||
{
|
||||
errno = EINVAL;
|
||||
free_space = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
free_space = tr_getQuotaFreeSpace (info);
|
||||
|
||||
if (free_space < 0)
|
||||
free_space = tr_getDiskFreeSpace (info->path);
|
||||
}
|
||||
|
||||
return free_space;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
|
|
|
@ -42,22 +42,6 @@ const char * tr_getTorrentDir (const tr_session *);
|
|||
/** @brief return the directory where the Web Client's web ui files are kept */
|
||||
const char * tr_getWebClientDir (const tr_session *);
|
||||
|
||||
struct tr_device_info
|
||||
{
|
||||
char * path;
|
||||
char * device;
|
||||
char * fstype;
|
||||
};
|
||||
|
||||
struct tr_device_info * tr_device_info_create (const char * 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 (const struct tr_device_info * info);
|
||||
|
||||
void tr_device_info_free (struct tr_device_info * info);
|
||||
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include "completion.h"
|
||||
#include "fdlimit.h"
|
||||
#include "log.h"
|
||||
#include "platform.h" /* tr_device_info_get_free_space() */
|
||||
#include "platform-quota.h" /* tr_device_info_get_free_space() */
|
||||
#include "rpcimpl.h"
|
||||
#include "session.h"
|
||||
#include "torrent.h"
|
||||
|
|
|
@ -39,7 +39,8 @@
|
|||
#include "net.h"
|
||||
#include "peer-io.h"
|
||||
#include "peer-mgr.h"
|
||||
#include "platform.h" /* tr_lock, tr_getTorrentDir (), tr_getFreeSpace () */
|
||||
#include "platform.h" /* tr_lock, tr_getTorrentDir () */
|
||||
#include "platform-quota.h" /* tr_device_info_free() */
|
||||
#include "port-forwarding.h"
|
||||
#include "rpc-server.h"
|
||||
#include "session.h"
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include "log.h"
|
||||
#include "utils.h"
|
||||
#include "platform.h" /* tr_lockLock (), TR_PATH_MAX */
|
||||
#include "platform-quota.h" /* tr_device_info_create(), tr_device_info_get_free_space(), tr_device_info_free() */
|
||||
#include "variant.h"
|
||||
#include "version.h"
|
||||
|
||||
|
|
Loading…
Reference in a new issue