Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit af66706

Browse files
committedMay 28, 2015
Merge pull request #3414 from rubinius/file-birthtime
Implemented File birthtime
2 parents 6304e7d + 7843e68 commit af66706

File tree

7 files changed

+119
-66
lines changed

7 files changed

+119
-66
lines changed
 

Diff for: ‎configure

+4
Original file line numberDiff line numberDiff line change
@@ -1230,6 +1230,10 @@ int main() { return tgetnum(""); }
12301230
@defines << "HAVE_GETTID"
12311231
end
12321232

1233+
if has_struct_member("stat", "st_birthtimespec", ["sys/stat.h"])
1234+
@defines << "HAVE_ST_BIRTHTIME"
1235+
end
1236+
12331237
# glibc has useless lchmod() so we don't try to use lchmod() on linux
12341238
if !@linux and has_function("lchmod", ["sys/stat.h", "unistd.h"])
12351239
@have_lchmod = true

Diff for: ‎kernel/bootstrap/stat.rb

+5
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ def ctime
8787
raise PrimitiveFailure, "Rubinius::Stat#ctime primitive failed"
8888
end
8989

90+
def birthtime
91+
Rubinius.primitive :stat_birthtime
92+
raise NotImplementedError, "birthtime() function is unimplemented on this machine"
93+
end
94+
9095
def inspect
9196
"#<#{self.class.name} dev=0x#{self.dev.to_s(16)}, ino=#{self.ino}, " \
9297
"mode=#{sprintf("%07d", self.mode.to_s(8).to_i)}, nlink=#{self.nlink}, " \

Diff for: ‎kernel/common/file.rb

+72-51
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,58 @@ def self.atime(path)
103103
Stat.new(path).atime
104104
end
105105

106+
##
107+
# Returns the change time for the named file (the
108+
# time at which directory information about the
109+
# file was changed, not the file itself).
110+
#
111+
# File.ctime("testfile") #=> Wed Apr 09 08:53:13 CDT 2003
112+
def self.ctime(path)
113+
Stat.new(path).ctime
114+
end
115+
116+
##
117+
# Returns the birthtime for the named file
118+
#
119+
# Note this is not supported on all platforms.
120+
# See stat(2) for more information.
121+
def self.birthtime(path)
122+
Stat.new(path).birthtime
123+
end
124+
125+
##
126+
# Returns the modification time for the named file as a Time object.
127+
#
128+
# File.mtime("testfile") #=> Tue Apr 08 12:58:04 CDT 2003
129+
def self.mtime(path)
130+
Stat.new(path).mtime
131+
end
132+
133+
##
134+
# Sets the access and modification times of each named
135+
# file to the first two arguments. Returns the number
136+
# of file names in the argument list.
137+
# #=> Integer
138+
def self.utime(a_in, m_in, *paths)
139+
a_in ||= Time.now
140+
m_in ||= Time.now
141+
FFI::MemoryPointer.new(POSIX::TimeVal, 2) do |ptr|
142+
atime = POSIX::TimeVal.new ptr
143+
mtime = POSIX::TimeVal.new ptr[1]
144+
atime[:tv_sec] = a_in.to_i
145+
atime[:tv_usec] = 0
146+
147+
mtime[:tv_sec] = m_in.to_i
148+
mtime[:tv_usec] = 0
149+
150+
paths.each do |path|
151+
152+
n = POSIX.utimes(Rubinius::Type.coerce_to_path(path), ptr)
153+
Errno.handle unless n == 0
154+
end
155+
end
156+
end
157+
106158
##
107159
# Returns the last component of the filename given
108160
# in file_name, which must be formed using forward
@@ -304,16 +356,6 @@ def self.lchown(owner, group, *paths)
304356
paths.size
305357
end
306358

307-
##
308-
# Returns the change time for the named file (the
309-
# time at which directory information about the
310-
# file was changed, not the file itself).
311-
#
312-
# File.ctime("testfile") #=> Wed Apr 09 08:53:13 CDT 2003
313-
def self.ctime(path)
314-
Stat.new(path).ctime
315-
end
316-
317359
##
318360
# Returns true if the named file is a directory, false otherwise.
319361
#
@@ -816,14 +858,6 @@ def self.lstat(path)
816858
Stat.lstat path
817859
end
818860

819-
##
820-
# Returns the modification time for the named file as a Time object.
821-
#
822-
# File.mtime("testfile") #=> Tue Apr 08 12:58:04 CDT 2003
823-
def self.mtime(path)
824-
Stat.new(path).mtime
825-
end
826-
827861
def self.path(obj)
828862
return obj.to_path if obj.respond_to? :to_path
829863

@@ -1072,31 +1106,6 @@ def self.unlink(*paths)
10721106
paths.size
10731107
end
10741108

1075-
##
1076-
# Sets the access and modification times of each named
1077-
# file to the first two arguments. Returns the number
1078-
# of file names in the argument list.
1079-
# #=> Integer
1080-
def self.utime(a_in, m_in, *paths)
1081-
a_in ||= Time.now
1082-
m_in ||= Time.now
1083-
FFI::MemoryPointer.new(POSIX::TimeVal, 2) do |ptr|
1084-
atime = POSIX::TimeVal.new ptr
1085-
mtime = POSIX::TimeVal.new ptr[1]
1086-
atime[:tv_sec] = a_in.to_i
1087-
atime[:tv_usec] = 0
1088-
1089-
mtime[:tv_sec] = m_in.to_i
1090-
mtime[:tv_usec] = 0
1091-
1092-
paths.each do |path|
1093-
1094-
n = POSIX.utimes(Rubinius::Type.coerce_to_path(path), ptr)
1095-
Errno.handle unless n == 0
1096-
end
1097-
end
1098-
end
1099-
11001109
def self.world_readable?(path)
11011110
path = Rubinius::Type.coerce_to_path path
11021111
return nil unless exist? path
@@ -1222,10 +1231,30 @@ def initialize(path_or_fd, mode=undefined, perm=undefined, options=undefined)
12221231

12231232
private :initialize
12241233

1234+
##
1235+
# see File.atime
12251236
def atime
12261237
Stat.new(@path).atime
12271238
end
12281239

1240+
##
1241+
# see File.ctime
1242+
def ctime
1243+
Stat.new(@path).ctime
1244+
end
1245+
1246+
##
1247+
# see File.birthtime
1248+
def birthtime
1249+
Stat.new(@path).birthtime
1250+
end
1251+
1252+
##
1253+
# see File.mtime
1254+
def mtime
1255+
Stat.new(@path).mtime
1256+
end
1257+
12291258
def reopen(other, mode = 'r+')
12301259
rewind unless closed?
12311260
unless other.kind_of? IO
@@ -1234,10 +1263,6 @@ def reopen(other, mode = 'r+')
12341263
super(other, mode)
12351264
end
12361265

1237-
def ctime
1238-
Stat.new(@path).ctime
1239-
end
1240-
12411266
def flock(const)
12421267
const = Rubinius::Type.coerce_to const, Integer, :to_int
12431268

@@ -1251,10 +1276,6 @@ def lstat
12511276
Stat.lstat @path
12521277
end
12531278

1254-
def mtime
1255-
Stat.new(@path).mtime
1256-
end
1257-
12581279
def stat
12591280
Stat.fstat @descriptor
12601281
end

Diff for: ‎spec/ruby/core/file/birthtime_spec.rb

+27-11
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,25 @@
99
@file = nil
1010
end
1111

12-
it "returns the birth time for the named file as a Time object" do
13-
File.birthtime(@file)
14-
File.birthtime(@file).should be_kind_of(Time)
15-
end
12+
platform_is :darwin do
13+
it "returns the birth time for the named file as a Time object" do
14+
File.birthtime(@file)
15+
File.birthtime(@file).should be_kind_of(Time)
16+
end
17+
18+
it "accepts an object that has a #to_path method" do
19+
File.birthtime(mock_to_path(@file))
20+
end
1621

17-
it "accepts an object that has a #to_path method" do
18-
File.birthtime(mock_to_path(@file))
22+
it "raises an Errno::ENOENT exception if the file is not found" do
23+
lambda { File.birthtime('bogus') }.should raise_error(Errno::ENOENT)
24+
end
1925
end
2026

21-
it "raises an Errno::ENOENT exception if the file is not found" do
22-
lambda { File.birthtime('bogus') }.should raise_error(Errno::ENOENT)
27+
platform_is :windows, :linux, :openbsd, :freebsd, :netbsd do
28+
it "raises an NotImplementedError" do
29+
lambda { File.birthtime(@file) }.should raise_error(NotImplementedError)
30+
end
2331
end
2432
end
2533

@@ -33,8 +41,16 @@
3341
@file = nil
3442
end
3543

36-
it "returns the birth time for self" do
37-
@file.birthtime
38-
@file.birthtime.should be_kind_of(Time)
44+
platform_is :darwin do
45+
it "returns the birth time for self" do
46+
@file.birthtime
47+
@file.birthtime.should be_kind_of(Time)
48+
end
49+
end
50+
51+
platform_is :windows, :linux, :openbsd, :freebsd, :netbsd do
52+
it "raises an NotImplementedError" do
53+
lambda { @file.birthtime }.should raise_error(NotImplementedError)
54+
end
3955
end
4056
end

Diff for: ‎spec/tags/ruby/core/file/birthtime_tags.txt

-4
This file was deleted.

Diff for: ‎vm/builtin/stat.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -77,5 +77,13 @@ namespace rubinius {
7777
return Time::at(state, st_.st_ctime);
7878
}
7979

80+
Object* Stat::stat_birthtime(STATE) {
81+
#ifdef HAVE_ST_BIRTHTIME
82+
return Time::at(state, st_.st_birthtimespec);
83+
#else
84+
return Primitives::failure();
85+
#endif
86+
}
87+
8088
}
8189

Diff for: ‎vm/builtin/stat.hpp

+3
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ namespace rubinius {
7373
// Rubinius.primitive+ :stat_ctime
7474
Time* stat_ctime(STATE);
7575

76+
// Rubinius.primitive+ :stat_birthtime
77+
Object* stat_birthtime(STATE);
78+
7679
class Info : public TypeInfo {
7780
public:
7881
BASIC_TYPEINFO(TypeInfo)

0 commit comments

Comments
 (0)
Please sign in to comment.