From 6b4f9210b0a105c68d98ebf2b80eea160c3af6a5 Mon Sep 17 00:00:00 2001 From: naruse Date: Thu, 22 May 2014 11:49:22 +0000 Subject: * file.c (stat_birthtime): add birthtime support [Feature #9647] * file.c (rb_stat_birthtime): add File::Stat.birthtime * file.c (rb_file_s_birthtime): add File.birthtime * file.c (rb_file_birthtime): add File#birthtime * configure.in: check struct stat.st_birthtimespec. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46047 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- file.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 111 insertions(+), 1 deletion(-) (limited to 'file.c') diff --git a/file.c b/file.c index af42d98dfb..2305066970 100644 --- a/file.c +++ b/file.c @@ -782,6 +782,19 @@ stat_ctime(struct stat *st) return rb_time_nano_new(ts.tv_sec, ts.tv_nsec); } +#define HAVE_STAT_BIRTHTIME +#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC) +static VALUE +stat_birthtime(struct stat *st) +{ + struct timespec *ts = &st->st_birthtimespec; + return rb_time_nano_new(ts->tv_sec, ts->tv_nsec); +} +#elif defined(_WIN32) +#else +# undef HAVE_STAT_BIRTHTIME +#endif + /* * call-seq: * stat.atime -> time @@ -835,6 +848,37 @@ rb_stat_ctime(VALUE self) return stat_ctime(get_stat(self)); } +/* + * call-seq: + * stat.birthtime -> aTime + * + * Returns the birth time for stat. + * If the platform doesn't have birthtime, returns ctime. + * + * File.write("testfile", "foo") + * sleep 10 + * File.write("testfile", "bar") + * sleep 10 + * File.chmod(0644, "testfile") + * sleep 10 + * File.read("testfile") + * File.stat("testfile").birthtime #=> 2014-02-24 11:19:17 +0900 + * File.stat("testfile").mtime #=> 2014-02-24 11:19:27 +0900 + * File.stat("testfile").ctime #=> 2014-02-24 11:19:37 +0900 + * File.stat("testfile").atime #=> 2014-02-24 11:19:47 +0900 + * + */ + +#if defined(HAVE_STAT_BIRTHTIME) +static VALUE +rb_stat_birthtime(VALUE self) +{ + return stat_birthtime(get_stat(self)); +} +#else +# define rb_stat_birthtime rb_f_notimplement +#endif + /* * call-seq: * stat.inspect -> string @@ -846,7 +890,8 @@ rb_stat_ctime(VALUE self) * # nlink=1, uid=0, gid=0, rdev=0x0, size=1374, blksize=4096, * # blocks=8, atime=Wed Dec 10 10:16:12 CST 2003, * # mtime=Fri Sep 12 15:41:41 CDT 2003, - * # ctime=Mon Oct 27 11:20:27 CST 2003>" + * # ctime=Mon Oct 27 11:20:27 CST 2003, + * # birthtime=Mon Aug 04 08:13:49 CDT 2003>" */ static VALUE @@ -871,6 +916,9 @@ rb_stat_inspect(VALUE self) {"atime", rb_stat_atime}, {"mtime", rb_stat_mtime}, {"ctime", rb_stat_ctime}, +#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC) + {"birthtime", rb_stat_birthtime}, +#endif }; struct stat* st; @@ -2082,6 +2130,65 @@ rb_file_ctime(VALUE obj) return stat_ctime(&st); } +/* + * call-seq: + * File.birthtime(file_name) -> time + * + * Returns the birth time for the named file. + * + * _file_name_ can be an IO object. + * + * Note that on Windows (NTFS), returns creation time (birth time). + * + * File.birthtime("testfile") #=> Wed Apr 09 08:53:13 CDT 2003 + * + */ + +#if defined(HAVE_STAT_BIRTHTIME) +static VALUE +rb_file_s_birthtime(VALUE klass, VALUE fname) +{ + struct stat st; + + if (rb_stat(fname, &st) < 0) { + FilePathValue(fname); + rb_sys_fail_path(fname); + } + return stat_birthtime(&st); +} +#else +# define rb_file_s_birthtime rb_f_notimplement +#endif + +/* + * call-seq: + * file.birthtime -> time + * + * Returns the birth time for file. + * + * Note that on Windows (NTFS), returns creation time (birth time). + * + * File.new("testfile").birthtime #=> Wed Apr 09 08:53:14 CDT 2003 + * + */ + +#if defined(HAVE_STAT_BIRTHTIME) +static VALUE +rb_file_birthtime(VALUE obj) +{ + rb_io_t *fptr; + struct stat st; + + GetOpenFile(obj, fptr); + if (fstat(fptr->fd, &st) == -1) { + rb_sys_fail_path(fptr->pathv); + } + return stat_birthtime(&st); +} +#else +# define rb_file_birthtime rb_f_notimplement +#endif + /* * call-seq: * file.size -> integer @@ -5646,6 +5753,7 @@ Init_File(void) rb_define_singleton_method(rb_cFile, "atime", rb_file_s_atime, 1); rb_define_singleton_method(rb_cFile, "mtime", rb_file_s_mtime, 1); rb_define_singleton_method(rb_cFile, "ctime", rb_file_s_ctime, 1); + rb_define_singleton_method(rb_cFile, "birthtime", rb_file_s_birthtime, 1); rb_define_singleton_method(rb_cFile, "utime", rb_file_s_utime, -1); rb_define_singleton_method(rb_cFile, "chmod", rb_file_s_chmod, -1); @@ -5693,6 +5801,7 @@ Init_File(void) rb_define_method(rb_cFile, "atime", rb_file_atime, 0); rb_define_method(rb_cFile, "mtime", rb_file_mtime, 0); rb_define_method(rb_cFile, "ctime", rb_file_ctime, 0); + rb_define_method(rb_cFile, "birthtime", rb_file_birthtime, 0); rb_define_method(rb_cFile, "size", rb_file_size, 0); rb_define_method(rb_cFile, "chmod", rb_file_chmod, 1); @@ -5814,6 +5923,7 @@ Init_File(void) rb_define_method(rb_cStat, "atime", rb_stat_atime, 0); rb_define_method(rb_cStat, "mtime", rb_stat_mtime, 0); rb_define_method(rb_cStat, "ctime", rb_stat_ctime, 0); + rb_define_method(rb_cStat, "birthtime", rb_stat_birthtime, 0); rb_define_method(rb_cStat, "inspect", rb_stat_inspect, 0); -- cgit v1.2.3