* 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
This commit is contained in:
parent
a999657e7e
commit
6b4f9210b0
12
ChangeLog
12
ChangeLog
@ -1,3 +1,15 @@
|
|||||||
|
Thu May 22 20:38:10 2014 NARUSE, Yui <naruse@ruby-lang.org>
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
|
||||||
Thu May 22 19:38:14 2014 NARUSE, Yui <naruse@ruby-lang.org>
|
Thu May 22 19:38:14 2014 NARUSE, Yui <naruse@ruby-lang.org>
|
||||||
|
|
||||||
* file.c: remove IO::Statfs because of reject. [Feature #9772]
|
* file.c: remove IO::Statfs because of reject. [Feature #9772]
|
||||||
|
9
NEWS
9
NEWS
@ -27,6 +27,15 @@ with all sufficient information, see the ChangeLog file.
|
|||||||
* Float#next_float
|
* Float#next_float
|
||||||
* Float#prev_float
|
* Float#prev_float
|
||||||
|
|
||||||
|
* File
|
||||||
|
* New methods:
|
||||||
|
* File.birthtime
|
||||||
|
* File#birthtime
|
||||||
|
|
||||||
|
* File::Stat
|
||||||
|
* New methods:
|
||||||
|
* File::Stat#birthtime
|
||||||
|
|
||||||
* Process
|
* Process
|
||||||
* Extended method:
|
* Extended method:
|
||||||
* Process execution methods such as Process.spawn opens the file in write
|
* Process execution methods such as Process.spawn opens the file in write
|
||||||
|
@ -1696,6 +1696,7 @@ AC_CHECK_MEMBERS([struct stat.st_mtimensec])
|
|||||||
AC_CHECK_MEMBERS([struct stat.st_ctim])
|
AC_CHECK_MEMBERS([struct stat.st_ctim])
|
||||||
AC_CHECK_MEMBERS([struct stat.st_ctimespec])
|
AC_CHECK_MEMBERS([struct stat.st_ctimespec])
|
||||||
AC_CHECK_MEMBERS([struct stat.st_ctimensec])
|
AC_CHECK_MEMBERS([struct stat.st_ctimensec])
|
||||||
|
AC_CHECK_MEMBERS([struct stat.st_birthtimespec])
|
||||||
|
|
||||||
AC_CHECK_TYPES([struct timeval], [], [], [@%:@ifdef HAVE_TIME_H
|
AC_CHECK_TYPES([struct timeval], [], [], [@%:@ifdef HAVE_TIME_H
|
||||||
@%:@include <time.h>
|
@%:@include <time.h>
|
||||||
|
112
file.c
112
file.c
@ -782,6 +782,19 @@ stat_ctime(struct stat *st)
|
|||||||
return rb_time_nano_new(ts.tv_sec, ts.tv_nsec);
|
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:
|
* call-seq:
|
||||||
* stat.atime -> time
|
* stat.atime -> time
|
||||||
@ -835,6 +848,37 @@ rb_stat_ctime(VALUE self)
|
|||||||
return stat_ctime(get_stat(self));
|
return stat_ctime(get_stat(self));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq:
|
||||||
|
* stat.birthtime -> aTime
|
||||||
|
*
|
||||||
|
* Returns the birth time for <i>stat</i>.
|
||||||
|
* If the platform doesn't have birthtime, returns <i>ctime</i>.
|
||||||
|
*
|
||||||
|
* 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:
|
* call-seq:
|
||||||
* stat.inspect -> string
|
* stat.inspect -> string
|
||||||
@ -846,7 +890,8 @@ rb_stat_ctime(VALUE self)
|
|||||||
* # nlink=1, uid=0, gid=0, rdev=0x0, size=1374, blksize=4096,
|
* # nlink=1, uid=0, gid=0, rdev=0x0, size=1374, blksize=4096,
|
||||||
* # blocks=8, atime=Wed Dec 10 10:16:12 CST 2003,
|
* # blocks=8, atime=Wed Dec 10 10:16:12 CST 2003,
|
||||||
* # mtime=Fri Sep 12 15:41:41 CDT 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
|
static VALUE
|
||||||
@ -871,6 +916,9 @@ rb_stat_inspect(VALUE self)
|
|||||||
{"atime", rb_stat_atime},
|
{"atime", rb_stat_atime},
|
||||||
{"mtime", rb_stat_mtime},
|
{"mtime", rb_stat_mtime},
|
||||||
{"ctime", rb_stat_ctime},
|
{"ctime", rb_stat_ctime},
|
||||||
|
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC)
|
||||||
|
{"birthtime", rb_stat_birthtime},
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stat* st;
|
struct stat* st;
|
||||||
@ -2082,6 +2130,65 @@ rb_file_ctime(VALUE obj)
|
|||||||
return stat_ctime(&st);
|
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 <i>file</i>.
|
||||||
|
*
|
||||||
|
* 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:
|
* call-seq:
|
||||||
* file.size -> integer
|
* 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, "atime", rb_file_s_atime, 1);
|
||||||
rb_define_singleton_method(rb_cFile, "mtime", rb_file_s_mtime, 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, "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, "utime", rb_file_s_utime, -1);
|
||||||
rb_define_singleton_method(rb_cFile, "chmod", rb_file_s_chmod, -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, "atime", rb_file_atime, 0);
|
||||||
rb_define_method(rb_cFile, "mtime", rb_file_mtime, 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, "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, "size", rb_file_size, 0);
|
||||||
|
|
||||||
rb_define_method(rb_cFile, "chmod", rb_file_chmod, 1);
|
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, "atime", rb_stat_atime, 0);
|
||||||
rb_define_method(rb_cStat, "mtime", rb_stat_mtime, 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, "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);
|
rb_define_method(rb_cStat, "inspect", rb_stat_inspect, 0);
|
||||||
|
|
||||||
|
@ -311,6 +311,31 @@ class TestFile < Test::Unit::TestCase
|
|||||||
assert_equal(mod_time_contents, stats.mtime, bug6385)
|
assert_equal(mod_time_contents, stats.mtime, bug6385)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_stat
|
||||||
|
file = Tempfile.new("stat")
|
||||||
|
file.close
|
||||||
|
path = file.path
|
||||||
|
|
||||||
|
t0 = Process.clock_gettime(Process::CLOCK_REALTIME)
|
||||||
|
File.write(path, "foo")
|
||||||
|
sleep 2
|
||||||
|
File.write(path, "bar")
|
||||||
|
sleep 2
|
||||||
|
File.chmod(0644, path)
|
||||||
|
sleep 2
|
||||||
|
File.read(path)
|
||||||
|
|
||||||
|
delta = 1
|
||||||
|
stat = File.stat(path)
|
||||||
|
if stat.birthtime != stat.ctime
|
||||||
|
assert_in_delta t0, stat.birthtime.to_f, delta
|
||||||
|
end
|
||||||
|
assert_in_delta t0+2, stat.mtime.to_f, delta
|
||||||
|
assert_in_delta t0+4, stat.ctime.to_f, delta
|
||||||
|
assert_in_delta t0+6, stat.atime.to_f, delta
|
||||||
|
rescue NotImplementedError
|
||||||
|
end
|
||||||
|
|
||||||
def test_chmod_m17n
|
def test_chmod_m17n
|
||||||
bug5671 = '[ruby-dev:44898]'
|
bug5671 = '[ruby-dev:44898]'
|
||||||
Dir.mktmpdir('test-file-chmod-m17n-') do |tmpdir|
|
Dir.mktmpdir('test-file-chmod-m17n-') do |tmpdir|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user