mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-03 18:47:53 +00:00
Bug 1735717 - Add a way for getting information about total disk space (disk capacity); r=dom-storage-reviewers,jari,xpcom-reviewers,nika
Differential Revision: https://phabricator.services.mozilla.com/D130640
This commit is contained in:
parent
05f4d5a4aa
commit
1a3d2b084c
@ -401,6 +401,11 @@ FileDescriptorFile::GetDiskSpaceAvailable(int64_t* aDiskSpaceAvailable) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FileDescriptorFile::GetDiskCapacity(int64_t* aDiskCapacity) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FileDescriptorFile::Reveal() { return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
|
@ -453,6 +453,9 @@ interface nsIFile : nsISupports
|
||||
// number of bytes available on disk to non-superuser
|
||||
[must_use] readonly attribute int64_t diskSpaceAvailable;
|
||||
|
||||
// disk capacity in bytes
|
||||
[must_use] readonly attribute int64_t diskCapacity;
|
||||
|
||||
/**
|
||||
* appendRelative[Native]Path
|
||||
*
|
||||
|
@ -8,8 +8,11 @@
|
||||
* Implementation of nsIFile for "unixy" systems.
|
||||
*/
|
||||
|
||||
#include "nsLocalFile.h"
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
#include "mozilla/FilePreferences.h"
|
||||
@ -32,8 +35,7 @@
|
||||
# include <sys/xattr.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SYS_QUOTA_H) && defined(HAVE_LINUX_QUOTA_H)
|
||||
# define USE_LINUX_QUOTACTL
|
||||
#if defined(USE_LINUX_QUOTACTL)
|
||||
# include <sys/mount.h>
|
||||
# include <sys/quota.h>
|
||||
# include <sys/sysmacros.h>
|
||||
@ -49,7 +51,6 @@
|
||||
#include "nsIFile.h"
|
||||
#include "nsString.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsLocalFile.h"
|
||||
#include "prproces.h"
|
||||
#include "nsIDirectoryEnumerator.h"
|
||||
#include "nsSimpleEnumerator.h"
|
||||
@ -1439,9 +1440,18 @@ static bool GetDeviceName(unsigned int aDeviceMajor, unsigned int aDeviceMinor,
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetDiskSpaceAvailable(int64_t* aDiskSpaceAvailable) {
|
||||
if (NS_WARN_IF(!aDiskSpaceAvailable)) {
|
||||
#if defined(USE_LINUX_QUOTACTL)
|
||||
template <typename StatInfoFunc, typename QuotaInfoFunc>
|
||||
nsresult nsLocalFile::GetDiskInfo(StatInfoFunc&& aStatInfoFunc,
|
||||
QuotaInfoFunc&& aQuotaInfoFunc,
|
||||
int64_t* aResult)
|
||||
#else
|
||||
template <typename StatInfoFunc>
|
||||
nsresult nsLocalFile::GetDiskInfo(StatInfoFunc&& aStatInfoFunc,
|
||||
int64_t* aResult)
|
||||
#endif
|
||||
{
|
||||
if (NS_WARN_IF(!aResult)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
@ -1459,26 +1469,34 @@ nsLocalFile::GetDiskSpaceAvailable(int64_t* aDiskSpaceAvailable) {
|
||||
* F_BSIZE = block size on disk.
|
||||
* f_bavail = number of free blocks available to a non-superuser.
|
||||
* f_bfree = number of total free blocks in file system.
|
||||
* f_blocks = number of total used or free blocks in file system.
|
||||
*/
|
||||
|
||||
if (STATFS(mPath.get(), &fs_buf) < 0) {
|
||||
// The call to STATFS failed.
|
||||
# ifdef DEBUG
|
||||
printf("ERROR: GetDiskSpaceAvailable: STATFS call FAILED. \n");
|
||||
printf("ERROR: GetDiskInfo: STATFS call FAILED. \n");
|
||||
# endif
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aDiskSpaceAvailable = (int64_t)fs_buf.F_BSIZE * fs_buf.f_bavail;
|
||||
CheckedInt64 checkedResult;
|
||||
|
||||
checkedResult = std::forward<StatInfoFunc>(aStatInfoFunc)(fs_buf);
|
||||
if (!checkedResult.isValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aResult = checkedResult.value();
|
||||
|
||||
# ifdef DEBUG_DISK_SPACE
|
||||
printf("DiskSpaceAvailable: %lu bytes\n", *aDiskSpaceAvailable);
|
||||
printf("DiskInfo: %lu bytes\n", *aResult);
|
||||
# endif
|
||||
|
||||
# if defined(USE_LINUX_QUOTACTL)
|
||||
|
||||
if (!FillStatCache()) {
|
||||
// Return available size from statfs
|
||||
// Return info from statfs
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1495,13 +1513,13 @@ nsLocalFile::GetDiskSpaceAvailable(int64_t* aDiskSpaceAvailable) {
|
||||
&& dq.dqb_valid & QIF_BLIMITS
|
||||
# endif
|
||||
&& dq.dqb_bhardlimit) {
|
||||
int64_t QuotaSpaceAvailable = 0;
|
||||
// dqb_bhardlimit is count of BLOCK_SIZE blocks, dqb_curspace is bytes
|
||||
if ((BLOCK_SIZE * dq.dqb_bhardlimit) > dq.dqb_curspace)
|
||||
QuotaSpaceAvailable =
|
||||
int64_t(BLOCK_SIZE * dq.dqb_bhardlimit - dq.dqb_curspace);
|
||||
if (QuotaSpaceAvailable < *aDiskSpaceAvailable) {
|
||||
*aDiskSpaceAvailable = QuotaSpaceAvailable;
|
||||
checkedResult = std::forward<QuotaInfoFunc>(aQuotaInfoFunc)(dq);
|
||||
if (!checkedResult.isValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (checkedResult.value() < *aResult) {
|
||||
*aResult = checkedResult.value();
|
||||
}
|
||||
}
|
||||
# endif
|
||||
@ -1511,22 +1529,54 @@ nsLocalFile::GetDiskSpaceAvailable(int64_t* aDiskSpaceAvailable) {
|
||||
#else
|
||||
/*
|
||||
* This platform doesn't have statfs or statvfs. I'm sure that there's
|
||||
* a way to check for free disk space on platforms that don't have statfs
|
||||
* (I'm SURE they have df, for example).
|
||||
* a way to check for free disk space and disk capacity on platforms that
|
||||
* don't have statfs (I'm SURE they have df, for example).
|
||||
*
|
||||
* Until we figure out how to do that, lets be honest and say that this
|
||||
* command isn't implemented properly for these platforms yet.
|
||||
*/
|
||||
# ifdef DEBUG
|
||||
printf(
|
||||
"ERROR: GetDiskSpaceAvailable: Not implemented for plaforms without "
|
||||
"statfs.\n");
|
||||
printf("ERROR: GetDiskInfo: Not implemented for plaforms without statfs.\n");
|
||||
# endif
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
#endif /* STATFS */
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetDiskSpaceAvailable(int64_t* aDiskSpaceAvailable) {
|
||||
return GetDiskInfo(
|
||||
[](const struct STATFS& aStatInfo) {
|
||||
return aStatInfo.f_bavail * static_cast<uint64_t>(aStatInfo.F_BSIZE);
|
||||
},
|
||||
#if defined(USE_LINUX_QUOTACTL)
|
||||
[](const struct dqblk& aQuotaInfo) -> uint64_t {
|
||||
// dqb_bhardlimit is count of BLOCK_SIZE blocks, dqb_curspace is bytes
|
||||
const uint64_t hardlimit = aQuotaInfo.dqb_bhardlimit * BLOCK_SIZE;
|
||||
if (hardlimit > aQuotaInfo.dqb_curspace) {
|
||||
return hardlimit - aQuotaInfo.dqb_curspace;
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
#endif
|
||||
aDiskSpaceAvailable);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetDiskCapacity(int64_t* aDiskCapacity) {
|
||||
return GetDiskInfo(
|
||||
[](const struct STATFS& aStatInfo) {
|
||||
return aStatInfo.f_blocks * static_cast<uint64_t>(aStatInfo.F_BSIZE);
|
||||
},
|
||||
#if defined(USE_LINUX_QUOTACTL)
|
||||
[](const struct dqblk& aQuotaInfo) {
|
||||
// dqb_bhardlimit is count of BLOCK_SIZE blocks
|
||||
return aQuotaInfo.dqb_bhardlimit * BLOCK_SIZE;
|
||||
},
|
||||
#endif
|
||||
aDiskCapacity);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetParent(nsIFile** aParent) {
|
||||
CHECK_mPath();
|
||||
|
@ -40,6 +40,10 @@
|
||||
# define LSTAT lstat
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SYS_QUOTA_H) && defined(HAVE_LINUX_QUOTA_H)
|
||||
# define USE_LINUX_QUOTACTL
|
||||
#endif
|
||||
|
||||
class nsLocalFile final
|
||||
#ifdef MOZ_WIDGET_COCOA
|
||||
: public nsILocalFileMac
|
||||
@ -89,6 +93,15 @@ class nsLocalFile final
|
||||
nsresult SetLastModifiedTimeImpl(PRTime aLastModTime, bool aFollowLinks);
|
||||
nsresult GetLastModifiedTimeImpl(PRTime* aLastModTime, bool aFollowLinks);
|
||||
nsresult GetCreationTimeImpl(PRTime* aCreationTime, bool aFollowLinks);
|
||||
|
||||
#if defined(USE_LINUX_QUOTACTL)
|
||||
template <typename StatInfoFunc, typename QuotaInfoFunc>
|
||||
nsresult GetDiskInfo(StatInfoFunc&& aStatInfoFunc,
|
||||
QuotaInfoFunc&& aQuotaInfoFunc, int64_t* aResult);
|
||||
#else
|
||||
template <typename StatInfoFunc>
|
||||
nsresult GetDiskInfo(StatInfoFunc&& aStatInfoFunc, int64_t* aResult);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* _nsLocalFileUNIX_H_ */
|
||||
|
@ -2676,6 +2676,12 @@ nsLocalFile::GetDiskSpaceAvailable(int64_t* aDiskSpaceAvailable) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetDiskCapacity(int64_t* aDiskCapacity) {
|
||||
*aDiskCapacity = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocalFile::GetParent(nsIFile** aParent) {
|
||||
// Check we are correctly initialized.
|
||||
|
@ -392,6 +392,34 @@ static bool TestNormalizeNativePath(nsIFile* aBase, nsIFile* aStart) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test nsIFile::GetDiskSpaceAvailable
|
||||
static bool TestDiskSpaceAvailable(nsIFile* aBase) {
|
||||
nsCOMPtr<nsIFile> file = NewFile(aBase);
|
||||
if (!file) return false;
|
||||
|
||||
int64_t diskSpaceAvailable = 0;
|
||||
nsresult rv = file->GetDiskSpaceAvailable(&diskSpaceAvailable);
|
||||
VerifyResult(rv, "GetDiskSpaceAvailable");
|
||||
|
||||
EXPECT_GE(diskSpaceAvailable, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test nsIFile::GetDiskCapacity
|
||||
static bool TestDiskCapacity(nsIFile* aBase) {
|
||||
nsCOMPtr<nsIFile> file = NewFile(aBase);
|
||||
if (!file) return false;
|
||||
|
||||
int64_t diskCapacity = 0;
|
||||
nsresult rv = file->GetDiskCapacity(&diskCapacity);
|
||||
VerifyResult(rv, "GetDiskCapacity");
|
||||
|
||||
EXPECT_GE(diskCapacity, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void SetupAndTestFunctions(const nsAString& aDirName,
|
||||
bool aTestCreateUnique, bool aTestNormalize) {
|
||||
nsCOMPtr<nsIFile> base;
|
||||
@ -484,6 +512,9 @@ static void SetupAndTestFunctions(const nsAString& aDirName,
|
||||
ASSERT_TRUE(
|
||||
TestDeleteOnClose(base, "file7.txt", PR_RDWR | PR_CREATE_FILE, 0600));
|
||||
|
||||
ASSERT_TRUE(TestDiskSpaceAvailable(base));
|
||||
ASSERT_TRUE(TestDiskCapacity(base));
|
||||
|
||||
// Clean up temporary stuff
|
||||
rv = base->Remove(true);
|
||||
VerifyResult(rv, "Cleaning up temp directory");
|
||||
|
Loading…
Reference in New Issue
Block a user