aboutsummaryrefslogtreecommitdiffstats
path: root/file.c
diff options
context:
space:
mode:
authornaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-04-22 10:35:57 +0000
committernaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-04-22 10:35:57 +0000
commit035a4e7d724888373382948d246d9ce87da2b247 (patch)
tree235273291cae101492cddc390db45545a35be4cd /file.c
parente419c88b0febd37d60a186dc776debb01d5cf6b5 (diff)
downloadruby-035a4e7d724888373382948d246d9ce87da2b247.tar.gz
* 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
Diffstat (limited to 'file.c')
-rw-r--r--file.c300
1 files changed, 300 insertions, 0 deletions
diff --git a/file.c b/file.c
index 89e1694d56..6de2feaa64 100644
--- a/file.c
+++ b/file.c
@@ -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);
}