diff --git a/configure.ac b/configure.ac index 6ccc65b1c..1c514f5c4 100644 --- a/configure.ac +++ b/configure.ac @@ -125,6 +125,7 @@ AC_PATH_ZLIB AC_SYS_LARGEFILE AC_CHECK_FUNCS([lseek64]) +AC_FUNC_GETMNTENT dnl ---------------------------------------------------------------------------- dnl diff --git a/libtransmission/platform.c b/libtransmission/platform.c index 00ad0d375..3548792c9 100644 --- a/libtransmission/platform.c +++ b/libtransmission/platform.c @@ -10,6 +10,18 @@ * $Id$ */ +#ifndef WIN32 + #include /* quotactl */ + #ifdef HAVE_GETMNTENT + #include + #include /* _PATH_MOUNTED */ + #else /* BSD derived systems */ + #include + #include + #include + #endif +#endif + #ifdef WIN32 #include #define WINVER WindowsXP @@ -700,23 +712,145 @@ tr_getWebClientDir (const tr_session * session UNUSED) **** ***/ -int64_t -tr_getFreeSpace (const char * path) +#ifndef WIN32 +static char * +getdev( const char * path ) +{ +#ifdef HAVE_GETMNTENT + FILE *fp; + struct mntent *mnt; + + if ((fp = setmntent(_PATH_MOUNTED, "r")) == NULL) + { + return NULL; + } + while ((mnt = getmntent(fp)) != NULL) + { + if (strcmp(path, mnt->mnt_dir) == 0) + { + break; + } + } + endmntent(fp); + return mnt ? mnt->mnt_fsname : NULL; +#else /* BSD derived systems */ + int n, i; + struct statfs *mnt; + + if ((n = getmntinfo(&mnt, MNT_WAIT)) == 0) + { + return NULL; + } + for (i=0; i 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; + } + freespace = limit - btodb(dq.dqb_curspace); + return (freespace < 0) ? 0 : freespace * 1024; + } + + /* Something went wrong */ + return -1; +} +#endif + +static int64_t +tr_getQuotaFreeSpace( const char * path ) +{ + int64_t ret=-1; +#ifndef WIN32 + char *device; + + if ((device = getblkdev(path)) != NULL) + { + ret = getquota(device); + } +#endif + 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; + 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; + #warning FIXME: not implemented + return -1; #endif } +int64_t +tr_getFreeSpace( const char * path ) +{ + int64_t i = tr_getQuotaFreeSpace( path ); + if( i < 0 ) + i = tr_getDiskFreeSpace( path ); + return i; +} + /*** **** ***/ diff --git a/libtransmission/platform.h b/libtransmission/platform.h index 9e0e26834..7a55dd23d 100644 --- a/libtransmission/platform.h +++ b/libtransmission/platform.h @@ -42,7 +42,8 @@ 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 *); -/** @brief return the number of bytes available for use in the specified path, or -1 on error */ +/** 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_getFreeSpace (const char * path);