ruby-changes:33580
From: naruse <ko1@a...>
Date: Tue, 22 Apr 2014 19:36:04 +0900 (JST)
Subject: [ruby-changes:33580] naruse:r45661 (trunk): * file.c: newly added a class File::Statfs. (experimental)
naruse 2014-04-22 19:35:57 +0900 (Tue, 22 Apr 2014) New Revision: 45661 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=45661 Log: * file.c: newly added a class File::Statfs. (experimental) Modified files: trunk/ChangeLog trunk/NEWS trunk/configure.in trunk/file.c trunk/test/ruby/test_file.rb Index: configure.in =================================================================== --- configure.in (revision 45660) +++ configure.in (revision 45661) @@ -1116,10 +1116,12 @@ AC_CHECK_HEADERS( \ https://github.com/ruby/ruby/blob/trunk/configure.in#L1116 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], [], [] https://github.com/ruby/ruby/blob/trunk/configure.in#L1721 @%:@ 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 Index: ChangeLog =================================================================== --- ChangeLog (revision 45660) +++ ChangeLog (revision 45661) @@ -1,3 +1,7 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Tue Apr 22 19:32:48 2014 NARUSE, Yui <naruse@r...> + + * file.c: newly added a class File::Statfs. (experimental) + Tue Apr 22 08:22:33 2014 Koichi Sasada <ko1@a...> * gc.c (objspace_malloc_increase): don't cause GC by malloc_increase Index: NEWS =================================================================== --- NEWS (revision 45660) +++ NEWS (revision 45661) @@ -20,6 +20,13 @@ with all sufficient information, see the https://github.com/ruby/ruby/blob/trunk/NEWS#L20 * 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. Index: test/ruby/test_file.rb =================================================================== --- test/ruby/test_file.rb (revision 45660) +++ test/ruby/test_file.rb (revision 45661) @@ -383,4 +383,23 @@ class TestFile < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_file.rb#L383 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 Index: file.c =================================================================== --- file.c (revision 45660) +++ file.c (revision 45661) @@ -63,6 +63,14 @@ int flock(int, int); https://github.com/ruby/ruby/blob/trunk/file.c#L63 #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 gro https://github.com/ruby/ruby/blob/trunk/file.c#L147 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) https://github.com/ruby/ruby/blob/trunk/file.c#L1095 #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) https://github.com/ruby/ruby/blob/trunk/file.c#L5300 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) https://github.com/ruby/ruby/blob/trunk/file.c#L5974 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) https://github.com/ruby/ruby/blob/trunk/file.c#L6131 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); } -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/