1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* file.c: newly added a class File::Statfs. (experimental)

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@45661 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
naruse 2014-04-22 10:35:57 +00:00
parent e419c88b0f
commit 035a4e7d72
5 changed files with 351 additions and 0 deletions

View file

@ -1,3 +1,7 @@
Tue Apr 22 19:32:48 2014 NARUSE, Yui <naruse@ruby-lang.org>
* file.c: newly added a class File::Statfs. (experimental)
Tue Apr 22 08:22:33 2014 Koichi Sasada <ko1@atdot.net>
* gc.c (objspace_malloc_increase): don't cause GC by malloc_increase

7
NEWS
View file

@ -20,6 +20,13 @@ with all sufficient information, see the ChangeLog file.
* min, min_by, max and max_by supports optional argument to return
multiple elements.
* File
* new class File::Statfs to hold filesystem information. (experimental)
* IO
* New methods
* IO#statfs returns filesystem information as File::Statfs. (experimental)
* Symbol
* New methods
* Symbol.find(str) returns whether given string is defined as symbol or not.

View file

@ -1116,10 +1116,12 @@ AC_CHECK_HEADERS( \
sys/syscall.h \
fcntl.h \
sys/fcntl.h \
sys/mount.h \
sys/select.h \
sys/time.h \
sys/times.h \
sys/param.h \
sys/vfs.h \
syscall.h \
pwd.h \
grp.h \
@ -1719,6 +1721,25 @@ AC_CHECK_TYPES([struct timezone], [], [], [@%:@ifdef HAVE_TIME_H
@%:@ include <sys/time.h>
@%:@endif])
AC_CHECK_TYPES([struct statfs], [], [], [@%:@ifdef HAVE_SYS_PARAM_H
@%:@ include <sys/param.h>
@%:@endif
@%:@ifdef HAVE_SYS_MOUNT_H
@%:@ include <sys/mount.h>
@%:@endif
@%:@ifdef HAVE_SYS_VFS_H
@%:@ include <sys/vfs.h>
@%:@endif])
AC_CHECK_MEMBERS([struct statfs.f_fstypename], [], [], [@%:@ifdef HAVE_SYS_PARAM_H
@%:@ include <sys/param.h>
@%:@endif
@%:@ifdef HAVE_SYS_MOUNT_H
@%:@ include <sys/mount.h>
@%:@endif
@%:@ifdef HAVE_SYS_VFS_H
@%:@ include <sys/vfs.h>
@%:@endif])
AC_CHECK_TYPES([clockid_t], [], [], [@%:@ifdef HAVE_TIME_H
@%:@ include <time.h>
@%:@endif

300
file.c
View file

@ -63,6 +63,14 @@ int flock(int, int);
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_SYS_MOUNT_H
#include <sys/mount.h>
#endif
#ifdef HAVE_SYS_VFS_H
#include <sys/vfs.h>
#endif
VALUE rb_statfs_new(const struct statfs *st);
#if defined(__native_client__) && defined(NACL_NEWLIB)
# include "nacl/utime.h"
# include "nacl/stat.h"
@ -139,6 +147,7 @@ be_fchown(int fd, uid_t owner, gid_t group)
VALUE rb_cFile;
VALUE rb_mFileTest;
VALUE rb_cStat;
VALUE rb_cStatfs;
#define insecure_obj_p(obj, level) ((level) >= 4 || ((level) > 0 && OBJ_TAINTED(obj)))
@ -1086,6 +1095,34 @@ rb_file_lstat(VALUE obj)
#endif
}
/*
* call-seq:
* ios.statfs -> statfs
*
* Returns filesystem status information for <em>ios</em> as an object of type
* <code>File::Statfs</code>.
*
* f = File.new("testfile")
* s = f.statfs
* s.mode #=> "100644"
* s.bsize #=> 512
* s.fstypename #=> "zfs"
*
*/
static VALUE
rb_io_statfs(VALUE obj)
{
rb_io_t *fptr;
struct statfs st;
GetOpenFile(obj, fptr);
if (fstatfs(fptr->fd, &st) == -1) {
rb_sys_fail_path(fptr->pathv);
}
return rb_statfs_new(&st);
}
static int
rb_group_member(GETGROUPS_T gid)
{
@ -5263,6 +5300,254 @@ rb_stat_sticky(VALUE obj)
return Qfalse;
}
/* File::Statfs */
static size_t
statfs_memsize(const void *p)
{
return p ? sizeof(struct statfs) : 0;
}
static const rb_data_type_t statfs_data_type = {
"statfs",
{NULL, RUBY_TYPED_DEFAULT_FREE, statfs_memsize,},
NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
};
static VALUE
statfs_new_0(VALUE klass, const struct statfs *st)
{
struct statfs *nst = 0;
if (st) {
nst = ALLOC(struct statfs);
*nst = *st;
}
return TypedData_Wrap_Struct(klass, &statfs_data_type, nst);
}
VALUE
rb_statfs_new(const struct statfs *st)
{
return statfs_new_0(rb_cStatfs, st);
}
static struct statfs*
get_statfs(VALUE self)
{
struct statfs* st;
TypedData_Get_Struct(self, struct statfs, &statfs_data_type, st);
if (!st) rb_raise(rb_eTypeError, "uninitialized File::Statfs");
return st;
}
/*
* Document-class: File::Statfs
*
* Objects of class <code>File::Statfs</code> encapsulate common status
* information for filesystem. The information is
* recorded at the moment the <code>File::Statfs</code> object is
* created; changes made to the filesystem after that point will not be
* reflected. <code>File::Statfs</code> objects are returned by
* <code>IO#statfs</code>.
*/
static VALUE
rb_statfs_s_alloc(VALUE klass)
{
return statfs_new_0(klass, 0);
}
/*
* call-seq:
*
* File::Statfs.new(file_name) -> statfs
*
* Create a File::Statfs object for the given file name (raising an
* exception if the file doesn't exist).
*/
static VALUE
rb_statfs_init(VALUE obj, VALUE fname)
{
struct statfs st, *nst;
rb_secure(2);
FilePathValue(fname);
fname = rb_str_encode_ospath(fname);
if (statfs(StringValueCStr(fname), &st) == -1) {
rb_sys_fail_path(fname);
}
if (DATA_PTR(obj)) {
xfree(DATA_PTR(obj));
DATA_PTR(obj) = NULL;
}
nst = ALLOC(struct statfs);
*nst = st;
DATA_PTR(obj) = nst;
return Qnil;
}
/* :nodoc: */
static VALUE
rb_statfs_init_copy(VALUE copy, VALUE orig)
{
struct statfs *nst;
if (!OBJ_INIT_COPY(copy, orig)) return copy;
if (DATA_PTR(copy)) {
xfree(DATA_PTR(copy));
DATA_PTR(copy) = 0;
}
if (DATA_PTR(orig)) {
nst = ALLOC(struct statfs);
*nst = *(struct statfs*)DATA_PTR(orig);
DATA_PTR(copy) = nst;
}
return copy;
}
/*
* call-seq:
* st.type -> fixnum
*
* Returns type of filesystem.
*
* f = File.new("testfile")
* s = f.statfs
* "%d" % s.type #=> 17
*
*/
static VALUE
statfs_type(VALUE self)
{
return LL2NUM(get_statfs(self)->f_type);
}
/*
* call-seq:
* st.bsize -> integer
*
* Returns block size in filesystem.
*
*/
static VALUE
statfs_bsize(VALUE self)
{
return LL2NUM(get_statfs(self)->f_bsize);
}
/*
* call-seq:
* st.blocks -> integer
*
* Returns total data bocks of filesystem.
*
*/
static VALUE
statfs_blocks(VALUE self)
{
return LL2NUM(get_statfs(self)->f_blocks);
}
/*
* call-seq:
* st.bfree -> integer
*
* Returns free blocks in filesystem.
*
*/
static VALUE
statfs_bfree(VALUE self)
{
return LL2NUM(get_statfs(self)->f_bfree);
}
/*
* call-seq:
* st.bavail -> integer
*
* Returns available blocks to non-super user in filesystem.
*
*/
static VALUE
statfs_bavail(VALUE self)
{
return LL2NUM(get_statfs(self)->f_bavail);
}
/*
* call-seq:
* st.files -> integer
*
* Returns total file nodes in filesystem.
*
*/
static VALUE
statfs_files(VALUE self)
{
return LL2NUM(get_statfs(self)->f_files);
}
/*
* call-seq:
* st.ffree -> integer
*
* Returns free nodes in filesystem.
*
*/
static VALUE
statfs_ffree(VALUE self)
{
return LL2NUM(get_statfs(self)->f_ffree);
}
/*
* call-seq:
* st.fsid -> integer
*
* Returns filesystem id.
*
*/
static VALUE
statfs_fsid(VALUE self)
{
fsid_t n = get_statfs(self)->f_fsid;
return LL2NUM(*(LONG_LONG*)&n);
}
#ifdef HAVE_STRUCT_STATFS_F_FSTYPENAME
/*
* call-seq:
* st.fstypename -> string
*
* Returns name of filesystem.
*
* f = File.new("testfile")
* s = f.statfs
* s.fstypename #=> "zfs"
*
*/
static VALUE
statfs_fstypename(VALUE self)
{
return rb_str_new_cstr(get_statfs(self)->f_fstypename);
}
#else
#define statfs_fsname rb_f_notimplement
#endif
VALUE rb_mFConst;
void
@ -5689,6 +5974,7 @@ Init_File(void)
rb_define_const(rb_cFile, "PATH_SEPARATOR", rb_obj_freeze(rb_str_new2(PATH_SEP)));
rb_define_method(rb_cIO, "stat", rb_io_stat, 0); /* this is IO's method */
rb_define_method(rb_cIO, "statfs", rb_io_statfs, 0); /* this is IO's method */
rb_define_method(rb_cFile, "lstat", rb_file_lstat, 0);
rb_define_method(rb_cFile, "atime", rb_file_atime, 0);
@ -5845,4 +6131,18 @@ Init_File(void)
rb_define_method(rb_cStat, "setuid?", rb_stat_suid, 0);
rb_define_method(rb_cStat, "setgid?", rb_stat_sgid, 0);
rb_define_method(rb_cStat, "sticky?", rb_stat_sticky, 0);
rb_cStatfs = rb_define_class_under(rb_cFile, "Statfs", rb_cObject);
rb_define_alloc_func(rb_cStatfs, rb_statfs_s_alloc);
rb_define_method(rb_cStatfs, "initialize", rb_statfs_init, 1);
rb_define_method(rb_cStatfs, "initialize_copy", rb_statfs_init_copy, 1);
rb_define_method(rb_cStatfs, "type", statfs_type, 0);
rb_define_method(rb_cStatfs, "bsize", statfs_bsize, 0);
rb_define_method(rb_cStatfs, "blocks", statfs_blocks, 0);
rb_define_method(rb_cStatfs, "bfree", statfs_bfree, 0);
rb_define_method(rb_cStatfs, "bavail", statfs_bavail, 0);
rb_define_method(rb_cStatfs, "files", statfs_files, 0);
rb_define_method(rb_cStatfs, "ffree", statfs_ffree, 0);
rb_define_method(rb_cStatfs, "fsid", statfs_fsid, 0);
rb_define_method(rb_cStatfs, "fstypename", statfs_fstypename, 0);
}

View file

@ -383,4 +383,23 @@ class TestFile < Test::Unit::TestCase
assert_file.not_exist?(path)
end
end
def test_statfs
open(__FILE__) do |f|
st = f.statfs
assert_kind_of File::Statfs, st
assert_kind_of Integer, st.type
assert_kind_of Integer, st.bsize
assert_kind_of Integer, st.blocks
assert_kind_of Integer, st.bfree
assert_kind_of Integer, st.bavail
assert_kind_of Integer, st.files
assert_kind_of Integer, st.ffree
assert_kind_of Integer, st.fsid
begin
assert_kind_of String, st.fstypename
rescue NotImplementedError
end
end
end
end