Bug 72892 - nsLocalFile::GetDiskSpaceAvaialble ignores quotas for unix, r=bsmedberg

--HG--
extra : rebase_source : 3bd5a75f7548a1ca45ff96676a752f23a2e9a13d
This commit is contained in:
Martin Stránský 2009-09-30 14:26:10 -04:00
parent 3d03f60b04
commit 485d0bfba9
2 changed files with 80 additions and 0 deletions

View File

@ -3047,6 +3047,9 @@ AC_CHECK_HEADERS(io.h)
dnl These are all the places some variant of statfs can be hiding.
AC_CHECK_HEADERS(sys/statvfs.h sys/statfs.h sys/vfs.h sys/mount.h)
dnl Quota support
AC_CHECK_HEADERS(sys/quota.h)
dnl Try for MMX support
dnl NB - later gcc versions require -mmmx for this header to be successfully
dnl included (or another option which implies it, such as -march=pentium-mmx)

View File

@ -67,6 +67,11 @@
#include <fabdef.h>
#endif
#if defined(HAVE_SYS_QUOTA_H)
#include <sys/sysmacros.h>
#include <sys/quota.h>
#endif
#include "nsDirectoryServiceDefs.h"
#include "nsCRT.h"
#include "nsCOMPtr.h"
@ -1125,6 +1130,56 @@ nsLocalFile::GetFileSizeOfLink(PRInt64 *aFileSize)
return NS_OK;
}
/*
* Searches /proc/self/mountinfo for given device (Major:Minor),
* returns exported name from /dev
*
* Fails when /proc/self/mountinfo or diven device don't exist.
*/
static PRBool
GetDeviceName(int deviceMajor, int deviceMinor, nsACString &deviceName)
{
PRBool ret = false;
const int kMountInfoLineLength = 200;
const int kMountInfoDevPosition = 6;
char mountinfo_line[kMountInfoLineLength];
char device_num[kMountInfoLineLength];
snprintf(device_num,kMountInfoLineLength,"%d:%d", deviceMajor, deviceMinor);
FILE *f = fopen("/proc/self/mountinfo","rt");
if(!f)
return ret;
// Expects /proc/self/mountinfo in format:
// 'ID ID major:minor root mountpoint flags - type devicename flags'
while(fgets(mountinfo_line,kMountInfoLineLength,f)) {
char *p_dev = strstr(mountinfo_line,device_num);
int i;
for(i = 0; i < kMountInfoDevPosition && p_dev != NULL; i++) {
p_dev = strchr(p_dev,' ');
if(p_dev)
p_dev++;
}
if(p_dev) {
char *p_dev_end = strchr(p_dev,' ');
if(p_dev_end) {
*p_dev_end = '\0';
deviceName.Assign(p_dev);
ret = true;
break;
}
}
}
fclose(f);
return ret;
}
NS_IMETHODIMP
nsLocalFile::GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable)
{
@ -1165,6 +1220,28 @@ nsLocalFile::GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable)
*/
*aDiskSpaceAvailable = (PRInt64)fs_buf.f_bsize * (fs_buf.f_bavail - 1);
#if defined(HAVE_SYS_STAT_H) || defined(HAVE_SYS_QUOTA_H)
if(!FillStatCache()) {
// Return available size from statfs
return NS_OK;
}
nsCString deviceName;
if(!GetDeviceName(major(mCachedStat.st_dev), minor(mCachedStat.st_dev), deviceName)) {
return NS_OK;
}
struct dqblk dq;
if(!quotactl(QCMD(Q_GETQUOTA, USRQUOTA), deviceName.get(), getuid(), (caddr_t)&dq)) {
PRInt64 QuotaSpaceAvailable = PRInt64(fs_buf.f_bsize * dq.dqb_bhardlimit);
if(QuotaSpaceAvailable < *aDiskSpaceAvailable) {
*aDiskSpaceAvailable = QuotaSpaceAvailable;
}
}
#endif
return NS_OK;
#else