Bug 924874 - Add OS.File.getAvailableFreeSpace for Windows and Linux. r=Yoric

This commit is contained in:
Alessio Placitelli 2014-01-15 02:04:00 -05:00
parent 71772e679e
commit 800569a380
9 changed files with 147 additions and 2 deletions

View File

@ -13,9 +13,13 @@
#include "unistd.h"
#include "dirent.h"
#include "sys/stat.h"
#if !defined(ANDROID)
#if defined(ANDROID)
#include <sys/vfs.h>
#define statvfs statfs
#else
#include "sys/statvfs.h"
#include <spawn.h>
#endif // !defined(ANDROID)
#endif // defined(ANDROID)
#endif // defined(XP_UNIX)
#if defined(XP_LINUX)
@ -526,6 +530,9 @@ static const dom::ConstantSpec gLibcProperties[] =
// The size of |time_t|.
{ "OSFILE_SIZEOF_TIME_T", INT_TO_JSVAL(sizeof (time_t)) },
// The size of |fsblkcnt_t|.
{ "OSFILE_SIZEOF_FSBLKCNT_T", INT_TO_JSVAL(sizeof (fsblkcnt_t)) },
#if !defined(ANDROID)
// The size of |posix_spawn_file_actions_t|.
{ "OSFILE_SIZEOF_POSIX_SPAWN_FILE_ACTIONS_T", INT_TO_JSVAL(sizeof (posix_spawn_file_actions_t)) },
@ -585,6 +592,13 @@ static const dom::ConstantSpec gLibcProperties[] =
{ "OSFILE_OFFSETOF_STAT_ST_BIRTHTIME", INT_TO_JSVAL(offsetof (struct stat, st_birthtime)) },
#endif // defined(_DARWIN_FEATURE_64_BIT_INODE)
// Defining |statvfs|
{ "OSFILE_SIZEOF_STATVFS", INT_TO_JSVAL(sizeof (struct statvfs)) },
{ "OSFILE_OFFSETOF_STATVFS_F_BSIZE", INT_TO_JSVAL(offsetof (struct statvfs, f_bsize)) },
{ "OSFILE_OFFSETOF_STATVFS_F_BAVAIL", INT_TO_JSVAL(offsetof (struct statvfs, f_bavail)) },
#endif // defined(XP_UNIX)

View File

@ -784,6 +784,21 @@ File.move = function move(sourcePath, destPath, options) {
Type.path.toMsg(destPath), options], [sourcePath, destPath]);
};
/**
* Gets the number of bytes available on disk to the current user.
*
* @param {string} Platform-specific path to a directory on the disk to
* query for free available bytes.
*
* @return {number} The number of bytes available for the current user.
* @throws {OS.File.Error} In case of any error.
*/
File.getAvailableFreeSpace = function getAvailableFreeSpace(sourcePath) {
return Scheduler.post("getAvailableFreeSpace",
[Type.path.toMsg(sourcePath)], sourcePath
).then(Type.uint64_t.fromMsg);
};
/**
* Remove an empty directory.
*

View File

@ -324,6 +324,10 @@ const EXCEPTION_NAMES = {
return File.move(Type.path.fromMsg(sourcePath),
Type.path.fromMsg(destPath), options);
},
getAvailableFreeSpace: function getAvailableFreeSpace(sourcePath) {
return Type.uint64_t.toMsg(
File.getAvailableFreeSpace(Type.path.fromMsg(sourcePath)));
},
makeDir: function makeDir(path, options) {
return File.makeDir(Type.path.fromMsg(path), options);
},

View File

@ -218,6 +218,24 @@
ctypes.ArrayType(Type.timeval.implementation, 2));
}
// Types fsblkcnt_t and fsfilcnt_t, used by structure |statvfs|
Type.fsblkcnt_t =
Type.uintn_t(Const.OSFILE_SIZEOF_FSBLKCNT_T).withName("fsblkcnt_t");
// Structure |statvfs|
// Use an hollow structure
{
let statvfs = new SharedAll.HollowStructure("statvfs",
Const.OSFILE_SIZEOF_STATVFS);
statvfs.add_field_at(Const.OSFILE_OFFSETOF_STATVFS_F_BSIZE,
"f_bsize", Type.unsigned_long.implementation);
statvfs.add_field_at(Const.OSFILE_OFFSETOF_STATVFS_F_BAVAIL,
"f_bavail", Type.fsblkcnt_t.implementation);
Type.statvfs = statvfs.getType();
}
// Declare libc functions as functions of |OS.Unix.File|
// Finalizer-related functions
@ -506,6 +524,12 @@
/*len*/ Type.size_t,
/*flags*/ Type.unsigned_int); // Linux/Android-specific
libc.declareLazyFFI(SysFile, "statvfs",
"statvfs", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,
/*path*/ Type.path,
/*buf*/ Type.statvfs.out_ptr);
libc.declareLazyFFI(SysFile, "symlink",
"symlink", ctypes.default_abi,
/*return*/ Type.negativeone_or_nothing,

View File

@ -351,6 +351,27 @@
}
};
/**
* Gets the number of bytes available on disk to the current user.
*
* @param {string} sourcePath Platform-specific path to a directory on
* the disk to query for free available bytes.
*
* @return {number} The number of bytes available for the current user.
* @throws {OS.File.Error} In case of any error.
*/
File.getAvailableFreeSpace = function Unix_getAvailableFreeSpace(sourcePath) {
let fileSystemInfo = new Type.statvfs.implementation();
let fileSystemInfoPtr = fileSystemInfo.address();
throw_on_negative("statvfs", UnixFile.statvfs(sourcePath, fileSystemInfoPtr));
let bytes = new Type.uint64_t.implementation(
fileSystemInfo.f_bsize * fileSystemInfo.f_bavail);
return bytes.value;
};
/**
* Default mode for opening directories.
*/

View File

@ -296,6 +296,14 @@
/*buf*/ Type.out_path
);
libc.declareLazyFFI(SysFile, "GetDiskFreeSpaceEx",
"GetDiskFreeSpaceExW", ctypes.winapi_abi,
/*return*/ Type.zero_or_nothing,
/*directoryName*/ Type.path,
/*freeBytesForUser*/ Type.uint64_t.out_ptr,
/*totalBytesForUser*/ Type.uint64_t.out_ptr,
/*freeTotalBytesOnDrive*/ Type.uint64_t.out_ptr);
libc.declareLazyFFI(SysFile, "GetFileInformationByHandle",
"GetFileInformationByHandle", ctypes.winapi_abi,
/*return*/ Type.zero_or_nothing,

View File

@ -571,6 +571,26 @@
}
};
/**
* Gets the number of bytes available on disk to the current user.
*
* @param {string} sourcePath Platform-specific path to a directory on
* the disk to query for free available bytes.
*
* @return {number} The number of bytes available for the current user.
* @throws {OS.File.Error} In case of any error.
*/
File.getAvailableFreeSpace = function Win_getAvailableFreeSpace(sourcePath) {
let freeBytesAvailableToUser = new Type.uint64_t.implementation(0);
let freeBytesAvailableToUserPtr = freeBytesAvailableToUser.address();
throw_on_zero("getAvailableFreeSpace",
WinFile.GetDiskFreeSpaceEx(sourcePath, freeBytesAvailableToUserPtr, null, null)
);
return freeBytesAvailableToUser.value;
};
/**
* A global value used to receive data during time conversions.
*/

View File

@ -0,0 +1,38 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
Components.utils.import("resource://gre/modules/osfile.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
do_register_cleanup(function() {
Services.prefs.setBoolPref("toolkit.osfile.log", false);
});
function run_test() {
Services.prefs.setBoolPref("toolkit.osfile.log", true);
run_next_test();
}
/**
* Test OS.File.getAvailableFreeSpace
*/
add_task(function() {
// Set up profile. We will use profile path to query for available free
// space.
do_get_profile();
let dir = OS.Constants.Path.profileDir;
// Sanity checking for the test
do_check_true((yield OS.File.exists(dir)));
// Query for available bytes for user
let availableBytes = yield OS.File.getAvailableFreeSpace(dir);
do_check_true(!!availableBytes);
do_check_true(availableBytes > 0);
});

View File

@ -2,6 +2,7 @@
head =
tail =
[test_available_free_space.js]
[test_osfile_closed.js]
[test_path.js]
[test_osfile_async.js]