Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add statvfs functions to the `fs` module

  • Loading branch information...
commit 501df0a5000f2a86acf7a03f5fb6edaa9fa3d319 1 parent c11c19b
Sambasiva Rao Suda authored
View
3  deps/uv/include/uv-private/uv-unix.h
@@ -28,6 +28,7 @@
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/statvfs.h>
#include <fcntl.h>
#include <sys/socket.h>
@@ -98,6 +99,7 @@ typedef struct {
typedef int uv_file;
typedef int uv_os_sock_t;
typedef struct stat uv_statbuf_t;
+typedef struct statvfs uv_statvfsbuf_t;
#define UV_ONCE_INIT PTHREAD_ONCE_INIT
@@ -281,6 +283,7 @@ typedef struct {
double mtime; \
struct uv__work work_req; \
struct stat statbuf; \
+ struct statvfs statvfsbuf; \
#define UV_WORK_PRIVATE_FIELDS \
struct uv__work work_req;
View
8 deps/uv/include/uv.h
@@ -1421,9 +1421,11 @@ typedef enum {
UV_FS_READ,
UV_FS_WRITE,
UV_FS_SENDFILE,
+ UV_FS_STATVFS,
UV_FS_STAT,
UV_FS_LSTAT,
UV_FS_FSTAT,
+ UV_FS_FSTATVFS,
UV_FS_FTRUNCATE,
UV_FS_UTIME,
UV_FS_FUTIME,
@@ -1485,9 +1487,15 @@ UV_EXTERN int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req,
UV_EXTERN int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path,
uv_fs_cb cb);
+UV_EXTERN int uv_fs_statvfs(uv_loop_t* loop, uv_fs_t* req, const char* path,
+ uv_fs_cb cb);
+
UV_EXTERN int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file,
uv_fs_cb cb);
+UV_EXTERN int uv_fs_fstatvfs(uv_loop_t* loop, uv_fs_t* req, uv_file file,
+ uv_fs_cb cb);
+
UV_EXTERN int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path,
const char* new_path, uv_fs_cb cb);
View
20 deps/uv/src/unix/fs.c
@@ -477,6 +477,7 @@ static void uv__fs_work(struct uv__work* w) {
X(FCHOWN, fchown(req->file, req->uid, req->gid));
X(FDATASYNC, uv__fs_fdatasync(req));
X(FSTAT, fstat(req->file, &req->statbuf));
+ X(FSTATVFS, fstatvfs(req->file, &req->statvfsbuf));
X(FSYNC, fsync(req->file));
X(FTRUNCATE, ftruncate(req->file, req->off));
X(FUTIME, uv__fs_futime(req));
@@ -491,6 +492,7 @@ static void uv__fs_work(struct uv__work* w) {
X(RMDIR, rmdir(req->path));
X(SENDFILE, uv__fs_sendfile(req));
X(STAT, stat(req->path, &req->statbuf));
+ X(STATVFS, statvfs(req->path, &req->statvfsbuf));
X(SYMLINK, symlink(req->path, req->new_path));
X(UNLINK, unlink(req->path));
X(UTIME, uv__fs_utime(req));
@@ -510,6 +512,11 @@ static void uv__fs_work(struct uv__work* w) {
req->fs_type == UV_FS_LSTAT)) {
req->ptr = &req->statbuf;
}
+
+ if (r == 0 && (req->fs_type == UV_FS_STATVFS ||
+ req->fs_type == UV_FS_FSTATVFS)) {
+ req->ptr = &req->statvfsbuf;
+ }
}
@@ -601,6 +608,12 @@ int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
POST;
}
+int uv_fs_fstatvfs(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
+ INIT(FSTATVFS);
+ req->file = file;
+ POST;
+}
+
int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
INIT(FSYNC);
@@ -756,6 +769,11 @@ int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
POST;
}
+int uv_fs_statvfs(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
+ INIT(STATVFS);
+ PATH;
+ POST;
+}
int uv_fs_symlink(uv_loop_t* loop,
uv_fs_t* req,
@@ -812,7 +830,7 @@ void uv_fs_req_cleanup(uv_fs_t* req) {
req->path = NULL;
req->new_path = NULL;
- if (req->ptr != &req->statbuf)
+ if (req->ptr != &req->statbuf && req->ptr != &req->statvfsbuf)
free(req->ptr);
req->ptr = NULL;
}
View
21 lib/fs.js
@@ -579,6 +579,27 @@ fs.stat = function(path, callback) {
binding.stat(pathModule._makeLong(path), makeCallback(callback));
};
+if ('statvfs' in binding) {
+ fs.statvfs = function(path, callback) {
+ binding.statvfs(pathModule._makeLong(path), makeCallback(callback));
+ };
+
+ fs.statvfsSync = function(path) {
+ return binding.statvfs(pathModule._makeLong(path));
+ };
+}
+
+if ('fstatvfs' in binding ) {
+ fs.fstatvfs = function(fd, callback) {
+ binding.fstatvfs(fd, makeCallback(callback));
+ };
+
+ fs.fstatvfsSync = function(fd) {
+ return binding.fstatvfs(fd);
+ };
+}
+
+
fs.fstatSync = function(fd) {
return binding.fstat(fd);
};
View
111 src/node_file.cc
@@ -66,6 +66,7 @@ static Persistent<String> errno_symbol;
static Persistent<String> buf_symbol;
static Persistent<String> oncomplete_sym;
+static Local<Object> BuildStatVfsObject(const uv_statvfsbuf_t* s);
#define ASSERT_OFFSET(a) \
if (!(a)->IsUndefined() && !(a)->IsNull() && !IsInt64((a)->NumberValue())) { \
@@ -159,6 +160,13 @@ static void After(uv_fs_t *req) {
argv[1] = BuildStatsObject(static_cast<const uv_statbuf_t*>(req->ptr));
break;
+#ifdef __POSIX__
+ case UV_FS_FSTATVFS:
+ case UV_FS_STATVFS:
+ argv[1] = BuildStatVfsObject(static_cast<const uv_statvfsbuf_t*>(req->ptr));
+ break;
+#endif
+
case UV_FS_READLINK:
argv[1] = String::New(static_cast<char*>(req->ptr));
break;
@@ -375,6 +383,100 @@ static Handle<Value> Stat(const Arguments& args) {
}
}
+#ifdef __POSIX__
+static Persistent<FunctionTemplate> statvfs_constructor_template;
+
+static Persistent<String> bsize_symbol;
+static Persistent<String> frsize_symbol;
+static Persistent<String> bfree_symbol;
+static Persistent<String> bavail_symbol;
+static Persistent<String> files_symbol;
+static Persistent<String> ffree_symbol;
+static Persistent<String> favail_symbol;
+static Persistent<String> fsid_symbol;
+static Persistent<String> flag_symbol;
+static Persistent<String> namemax_symbol;
+
+Local<Object> BuildStatVfsObject(const uv_statvfsbuf_t* s) {
+ HandleScope scope;
+
+ if (bsize_symbol.IsEmpty()) {
+ bsize_symbol = NODE_PSYMBOL("bsize");
+ frsize_symbol = NODE_PSYMBOL("frsize");
+ bfree_symbol = NODE_PSYMBOL("bfree");
+ bavail_symbol = NODE_PSYMBOL("bavail");
+ files_symbol = NODE_PSYMBOL("files");
+ ffree_symbol = NODE_PSYMBOL("ffree");
+ favail_symbol = NODE_PSYMBOL("favail");
+ fsid_symbol = NODE_PSYMBOL("fsid");
+ flag_symbol = NODE_PSYMBOL("flag");
+ namemax_symbol = NODE_PSYMBOL("namemax");
+ }
+
+ if (blocks_symbol.IsEmpty()) {
+ blocks_symbol = NODE_PSYMBOL("blocks");
+ }
+ Local<Object> statvfs =
+ statvfs_constructor_template->GetFunction()->NewInstance();
+
+ if (statvfs.IsEmpty()) return Local<Object>();
+
+#define X(name) \
+ { \
+ Local<Value> val = Integer::New(s->f_##name); \
+ if (val.IsEmpty()) return Local<Object>(); \
+ statvfs->Set(name##_symbol, val); \
+ }
+ X(bsize)
+ X(frsize)
+ X(blocks)
+ X(bfree)
+ X(bavail)
+ X(files)
+ X(ffree)
+ X(favail)
+ X(fsid)
+ X(flag)
+ X(namemax)
+#undef X
+ return scope.Close(statvfs);
+}
+
+static Handle<Value> StatVfs(const Arguments& args) {
+ HandleScope scope;
+
+ if (args.Length() < 1) return TYPE_ERROR("path required");
+ if (!args[0]->IsString()) return TYPE_ERROR("path must be a string");
+
+ String::Utf8Value path(args[0]);
+
+ if (args[1]->IsFunction()) {
+ ASYNC_CALL(statvfs, args[1], *path)
+ } else {
+ SYNC_CALL(statvfs, *path, *path)
+ return scope.Close(
+ BuildStatVfsObject(static_cast<const uv_statvfsbuf_t*>(SYNC_REQ.ptr)));
+ }
+}
+
+static Handle<Value> FStatVfs(const Arguments& args) {
+ HandleScope scope;
+
+ if (args.Length() < 1 || !args[0]->IsInt32()) {
+ return THROW_BAD_ARGS;
+ }
+
+ int fd = args[0]->Int32Value();
+
+ if (args[1]->IsFunction()) {
+ ASYNC_CALL(fstatvfs, args[1], fd)
+ } else {
+ SYNC_CALL(fstatvfs, 0, fd)
+ return scope.Close(
+ BuildStatVfsObject(static_cast<const uv_statvfsbuf_t*>(SYNC_REQ.ptr)));
+ }
+}
+#endif
static Handle<Value> LStat(const Arguments& args) {
HandleScope scope;
@@ -487,7 +589,7 @@ static Handle<Value> Rename(const Arguments& args) {
if (len < 2) return TYPE_ERROR("new path required");
if (!args[0]->IsString()) return TYPE_ERROR("old path must be a string");
if (!args[1]->IsString()) return TYPE_ERROR("new path must be a string");
-
+
String::Utf8Value old_path(args[0]);
String::Utf8Value new_path(args[1]);
@@ -979,6 +1081,11 @@ void File::Initialize(Handle<Object> target) {
NODE_SET_METHOD(target, "utimes", UTimes);
NODE_SET_METHOD(target, "futimes", FUTimes);
+#ifdef __POSIX__
+ NODE_SET_METHOD(target, "statvfs", StatVfs);
+ NODE_SET_METHOD(target, "fstatvfs", FStatVfs);
+#endif
+
errno_symbol = NODE_PSYMBOL("errno");
encoding_symbol = NODE_PSYMBOL("node:encoding");
buf_symbol = NODE_PSYMBOL("__buf");
@@ -991,6 +1098,8 @@ void InitFs(Handle<Object> target) {
stats_constructor_template = Persistent<FunctionTemplate>::New(stat_templ);
target->Set(String::NewSymbol("Stats"),
stats_constructor_template->GetFunction());
+ Local<FunctionTemplate> statvfs_templ = FunctionTemplate::New();
+ statvfs_constructor_template = Persistent<FunctionTemplate>::New(statvfs_templ);
File::Initialize(target);
oncomplete_sym = NODE_PSYMBOL("oncomplete");
View
85 test/simple/test-fs-statvfs.js
@@ -0,0 +1,85 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var common = require('../common');
+var assert = require('assert');
+var fs = require('fs');
+var got_error = false;
+var success_count = 0;
+
+if (!'statvfs' in fs) {
+ process.exit(0);
+}
+
+// statvfs
+fs.statvfs('.', function(err, stats) {
+ if (err) {
+ got_error = true;
+ } else {
+ console.dir(stats);
+ success_count++;
+ }
+ assert(this === global);
+});
+
+// statvfsSync
+var stats = fs.statvfsSync('.');
+assert.ok('bfree' in stats);
+
+// fstatvfs
+fs.open('.', 'r', undefined, function(err, fd) {
+ assert.ok(!err);
+ assert.ok(fd);
+
+ fs.fstatvfs(fd, function(err, stats) {
+ if (err) {
+ got_error = true;
+ } else {
+ console.dir(stats);
+ success_count++;
+ fs.close(fd);
+ }
+ assert(this === global);
+ });
+
+ assert(this === global);
+});
+
+// fstatvfsSync
+fs.open('.', 'r', undefined, function(err, fd) {
+ var stats;
+ try {
+ stats = fs.fstatvfsSync(fd);
+ } catch (err) {
+ got_error = true;
+ }
+ if (stats) {
+ console.dir(stats);
+ success_count++;
+ }
+ fs.close(fd);
+});
+
+process.on('exit', function() {
+ assert.equal(3, success_count);
+ assert.equal(false, got_error);
+});
+
Please sign in to comment.
Something went wrong with that request. Please try again.