win32_filetime 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ab93d67c72d9ee9297f1866a934ea1fcec7d8fa4
4
+ data.tar.gz: e1d6485a99cc66a773f86b593bd893926958451c
5
+ SHA512:
6
+ metadata.gz: 53ca7e9c87cf267e09bdb6d2034953e53a7c9f1b4f2a10f17facf55163d5afba101216886ab985a4f1cf1a2eb33ac02e3156dee0532c7d9434f9331c2a0786f2
7
+ data.tar.gz: 432a4a192d9cdd71db37f6bed7987f3cc67a3958bba618fe018202478f867c10043e140f4fbf658d177ceb509bfdf62ac0c52b385a81a3f043f871a9dd019174
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in win32_filetime.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 windwiny
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # Win32Filetime
2
+
3
+ using FFI export win32 filetime api
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'win32_filetime'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install win32_filetime
18
+
19
+ ## Usage
20
+
21
+ require 'win32ft'
22
+ create_time, access_time, modify_time = Win32ft.getfiletime(filename)
23
+
24
+ ## Contributing
25
+
26
+ 1. Fork it
27
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
28
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
29
+ 4. Push to the branch (`git push origin my-new-feature`)
30
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,3 @@
1
+ module Win32Filetime
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,5 @@
1
+ require "win32_filetime/version"
2
+
3
+ module Win32Filetime
4
+ # Your code goes here...
5
+ end
data/lib/win32ft.rb ADDED
@@ -0,0 +1,301 @@
1
+ #!/usr/bin/env ruby -w
2
+ # encoding: GBK
3
+
4
+ require "win32_filetime/version"
5
+ require "ffi"
6
+
7
+ class FileTime < FFI::Struct
8
+ layout :dwLowDateTime, :uint,
9
+ :dwHighDateTime, :uint
10
+
11
+ include Comparable
12
+ def <=>(other)
13
+ s1 = self[:dwHighDateTime] << 32 | self[:dwLowDateTime]
14
+ o1 = other[:dwHighDateTime] << 32 | other[:dwLowDateTime]
15
+ if s1 < o1
16
+ -1
17
+ elsif s1 == o1
18
+ 0
19
+ else
20
+ 1
21
+ end
22
+ end
23
+
24
+ def ==(other)
25
+ if other.is_a? self.class
26
+ self[:dwLowDateTime] == other[:dwLowDateTime] && self[:dwHighDateTime] == other[:dwHighDateTime]
27
+ elsif other.is_a? Numeric
28
+ self[:dwHighDateTime] << 32 | self[:dwLowDateTime] == other
29
+ else
30
+ false
31
+ end
32
+ end
33
+ def equal?(other)
34
+ self == other
35
+ end
36
+ def eql?(other)
37
+ self == other
38
+ end
39
+ def to_s
40
+ "0x%08X%08X" % [self[:dwHighDateTime], self[:dwLowDateTime]]
41
+ end
42
+ def inspect
43
+ to_s
44
+ end
45
+ def to_i
46
+ ((self[:dwHighDateTime] << 32 | self[:dwLowDateTime]) - 116444736000000000) / 10**7.0
47
+ end
48
+ end
49
+
50
+ class SystemTime < FFI::Struct
51
+ layout :wYear, :ushort,
52
+ :wMonth, :ushort,
53
+ :wDayOfWeek, :ushort,
54
+ :wDay, :ushort,
55
+ :wHour, :ushort,
56
+ :wMinute, :ushort,
57
+ :wSecond, :ushort,
58
+ :wMilliseconds, :ushort
59
+
60
+ def ==(other)
61
+ if other.is_a? self.class
62
+ self[:wYear] == other[:wYear] &&
63
+ self[:wMonth] == other[:wMonth] &&
64
+ self[:wDay] == other[:wDay] &&
65
+ self[:wHour] == other[:wHour] &&
66
+ self[:wMinute] == other[:wMinute] &&
67
+ self[:wSecond] == other[:wSecond] &&
68
+ self[:wMilliseconds] == other[:wMilliseconds]
69
+ elsif other.is_a? String
70
+ self.to_s == other
71
+ else
72
+ false
73
+ end
74
+ end
75
+ def equal?(other)
76
+ self == other
77
+ end
78
+ def eql?(other)
79
+ self == other
80
+ end
81
+ def to_s
82
+ "%04d-%02d-%02d %02d:%02d:%02d.%d" % [
83
+ self[:wYear],self[:wMonth],self[:wDay],self[:wHour],self[:wMinute],self[:wSecond],self[:wMilliseconds]
84
+ ]
85
+ end
86
+ def inspect
87
+ to_s
88
+ end
89
+ end
90
+
91
+ class Large_Integer < FFI::Struct
92
+ layout :LowPart, :uint,
93
+ :HighPart, :uint
94
+
95
+ def ==(other)
96
+ if other.is_a? self.class
97
+ self[:HighPart] == other[:HighPart] && self[:LowPart] == other[:LowPart]
98
+ elsif other.is_a? Numeric
99
+ self[:HighPart] << 32 | self[:LowPart] == other
100
+ else
101
+ false
102
+ end
103
+ end
104
+ def equal?(other)
105
+ self == other
106
+ end
107
+ def eql?(other)
108
+ self == other
109
+ end
110
+ def to_i
111
+ self[:HighPart] << 32 | self[:LowPart]
112
+ end
113
+ def to_s
114
+ to_i.to_s
115
+ end
116
+ def inspect
117
+ to_i.to_s
118
+ end
119
+ end
120
+
121
+ class HANDLE < FFI::Struct
122
+ layout :handle, :uint
123
+ end
124
+
125
+ class CFflag
126
+ GENERIC_READ = 0x80000000
127
+ GENERIC_WRITE = 0x40000000
128
+ GENERIC_EXECUTE = 0x20000000
129
+ GENERIC_ALL = 0x10000000
130
+
131
+ FILE_SHARE_READ = 0x00000001
132
+ FILE_SHARE_WRITE = 0x00000002
133
+ FILE_SHARE_DELETE = 0x00000004
134
+
135
+ CREATE_NEW = 1
136
+ CREATE_ALWAYS = 2
137
+ OPEN_EXISTING = 3
138
+ OPEN_ALWAYS = 4
139
+ TRUNCATE_EXISTING = 5
140
+
141
+ FILE_FLAG_WRITE_THROUGH =0x80000000
142
+ FILE_FLAG_OVERLAPPED =0x40000000
143
+ FILE_FLAG_NO_BUFFERING =0x20000000
144
+ FILE_FLAG_RANDOM_ACCESS =0x10000000
145
+ FILE_FLAG_SEQUENTIAL_SCAN =0x08000000
146
+ FILE_FLAG_DELETE_ON_CLOSE =0x04000000
147
+ FILE_FLAG_BACKUP_SEMANTICS =0x02000000
148
+ FILE_FLAG_POSIX_SEMANTICS =0x01000000
149
+ FILE_FLAG_OPEN_REPARSE_POINT =0x00200000
150
+ FILE_FLAG_OPEN_NO_RECALL =0x00100000
151
+ FILE_FLAG_FIRST_PIPE_INSTANCE =0x00080000
152
+ end
153
+
154
+ module Win32ft
155
+ extend FFI::Library
156
+ ffi_lib 'msvcrt', 'kernel32'
157
+ ffi_convention :stdcall
158
+
159
+ attach_function :GetFileType, [:int], :int
160
+ attach_function :GetLastError, [], :int
161
+ attach_function :FormatMessageA, [:int, :pointer, :int, :int, :string, :int, :pointer], :int
162
+
163
+ attach_function :FileTimeToLocalFileTime, [FileTime.by_ref, FileTime.by_ref], :bool
164
+ attach_function :LocalFileTimeToFileTime, [FileTime.by_ref, FileTime.by_ref], :bool
165
+ def self.ft2lft(ft)
166
+ lft = FileTime.new
167
+ FileTimeToLocalFileTime(ft, lft)
168
+ lft
169
+ end
170
+ def self.lft2ft(lft)
171
+ ft = FileTime.new
172
+ LocalFileTimeToFileTime(lft, ft)
173
+ ft
174
+ end
175
+
176
+ attach_function :FileTimeToSystemTime, [FileTime.by_ref, SystemTime.by_ref], :bool
177
+ attach_function :SystemTimeToFileTime, [SystemTime.by_ref, FileTime.by_ref], :bool
178
+ def self.ft2st(ft, convft2lft: false)
179
+ ft = ft2lft(ft) if convft2lft
180
+ st = SystemTime.new
181
+ FileTimeToSystemTime(ft, st)
182
+ st
183
+ end
184
+ def self.st2ft(st, convlft2ft: false)
185
+ ft = FileTime.new
186
+ SystemTimeToFileTime(st, ft)
187
+ ft = lft2ft(ft) if convlft2ft
188
+ ft
189
+ end
190
+
191
+ attach_function :GetSystemTime, [SystemTime.by_ref], :void
192
+ def self.getsystemtime
193
+ st = SystemTime.new
194
+ GetSystemTime(st)
195
+ st
196
+ end
197
+ attach_function :GetLocalTime, [SystemTime.by_ref], :void
198
+ def self.getlocaltime
199
+ lt = SystemTime.new
200
+ GetLocalTime(lt)
201
+ lt
202
+ end
203
+
204
+ =begin
205
+ CreateFileA("", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)
206
+ CreateFileA("", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)
207
+
208
+ LPCSTR lpFileName, # "filename"
209
+ DWORD dwDesiredAccess, # GENERIC_READ / GENERIC_WRITE / GENERIC_EXECUTE / GENERIC_ALL
210
+ DWORD dwShareMode, # FILE_SHARE_READ /| FILE_SHARE_WRITE / FILE_SHARE_DELETE
211
+ LPSECURITY_ATTRIBUTES lp, # 0
212
+ DWORD dwCreationDisposition, # CREATE_NEW / CREATE_ALWAYS / OPEN_EXISTING / OPEN_ALWAYS / TRUNCATE_EXISTING
213
+ DWORD dwFlagsAndAttributes, # 0 | FILE_FLAG_BACKUP_SEMANTICS if dir
214
+ HANDLE hTemplateFile # 0
215
+
216
+ ReadFile(
217
+ HANDLE,
218
+ buf, # FFI::MemoryPointer.new(:char, 100)
219
+ 100, # max read len
220
+ rded, # FFI::MemoryPointer.new(:uint,1). # [output] read bytes
221
+ 0)
222
+
223
+ WriteFile(
224
+ HANDLE,
225
+ buf, # FFI::MemoryPointer.new(:char, 100)
226
+ 5, # write string len
227
+ wded, # FFI::MemoryPointer.new(:uint,1). # [output] write bytes
228
+ 0)
229
+
230
+ DeleteFile(
231
+ LPCSTR lpFileName, # "filename"
232
+ )
233
+
234
+ FlushFileBuffers(HANDLE)
235
+
236
+ CloseHandle(HANDLE)
237
+ =end
238
+ attach_function :CreateFileA, [:string, :uint, :uint, :pointer, :uint, :uint, :int], :int
239
+ attach_function :ReadFile, [:int, :pointer, :uint, :pointer, :pointer], :bool
240
+ attach_function :WriteFile, [:int, :pointer, :uint, :pointer, :pointer], :bool
241
+ attach_function :DeleteFile, :DeleteFileA, [:string], :bool
242
+ attach_function :FlushFileBuffers, [:int], :bool
243
+ attach_function :CloseHandle, [:int], :bool
244
+
245
+ attach_function :GetFileTime, [:int, FileTime.by_ref, FileTime.by_ref, FileTime.by_ref], :bool
246
+ attach_function :SetFileTime, [:int, FileTime.by_ref, FileTime.by_ref, FileTime.by_ref], :bool
247
+ def self.getfiletime(fn, getsize: false)
248
+ size = Large_Integer.new if getsize
249
+ tc, ta, tm = FileTime.new, FileTime.new, FileTime.new
250
+ ttts = [tc, ta, tm]
251
+ hf = CreateFileA(fn, CFflag::GENERIC_READ, CFflag::FILE_SHARE_READ | CFflag::FILE_SHARE_WRITE,
252
+ nil, CFflag::OPEN_EXISTING, CFflag::FILE_FLAG_BACKUP_SEMANTICS, 0)
253
+ raise "getfiletime: Can not open file \"#{fn}\"" if hf == -1
254
+ res = GetFileTime(hf, tc, ta, tm)
255
+ raise "getfiletime: GetFileTime error." if !res
256
+ if getsize
257
+ res = GetFileSizeEx(hf, size)
258
+ raise "getfiletime: GetFileSizeEx error." if !res
259
+ ttts << size.to_i
260
+ end
261
+ CloseHandle(hf)
262
+ ttts
263
+ end
264
+ def self.setfiletime(fn, tc, ta, tm)
265
+ hf = CreateFileA(fn, CFflag::GENERIC_WRITE, CFflag::FILE_SHARE_READ | CFflag::FILE_SHARE_WRITE,
266
+ nil, CFflag::OPEN_EXISTING, CFflag::FILE_FLAG_BACKUP_SEMANTICS, 0)
267
+ raise "setfiletime: Can not open file \"#{fn}\"" if hf == -1
268
+ res = SetFileTime(hf, tc, ta, tm)
269
+ raise "setfiletime: SetFileTime error." if !res
270
+ CloseHandle(hf)
271
+ true
272
+ end
273
+ def self.copyfiletime(fn1, fn2)
274
+ tc1, ta1, tm1 = getfiletime(fn1)
275
+ setfiletime(fn2, tc1, ta1, tm1)
276
+ end
277
+ def self.double2ft(tt)
278
+ wintt = (tt * 10**7 + 116444736000000000).to_i
279
+ ft = FileTime.new
280
+ ft[:dwHighDateTime] = wintt >> 32 & 0xFFFFFFFF
281
+ ft[:dwLowDateTime] = wintt & 0xFFFFFFFF
282
+ ft
283
+ end
284
+ def self.ft2double(ft)
285
+ wintt = ft[:dwHighDateTime] << 32 | ft[:dwLowDateTime]
286
+ tt = (wintt - 116444736000000000) / 10**7.0
287
+ tt
288
+ end
289
+
290
+ attach_function :GetFileSizeEx, [:int, Large_Integer.by_ref], :bool
291
+ def self.getfilesize(fn)
292
+ hf = CreateFileA(fn, CFflag::GENERIC_READ, CFflag::FILE_SHARE_READ | CFflag::FILE_SHARE_WRITE,
293
+ nil, CFflag::OPEN_EXISTING, CFflag::FILE_FLAG_BACKUP_SEMANTICS, 0)
294
+ raise "getfilesize: Can not open file \"#{fn}\"" if hf == -1
295
+ size = Large_Integer.new
296
+ res = GetFileSizeEx(hf, size)
297
+ raise "getfilesize: GetFileSizeEx error." if !res
298
+ CloseHandle(hf)
299
+ size.to_i
300
+ end
301
+ end
@@ -0,0 +1,303 @@
1
+ # encoding: GBK
2
+
3
+ require"win32ft"
4
+
5
+ describe "FileTime" do
6
+ it "new FileTime instance should ==" do
7
+ FileTime.new.should == FileTime.new
8
+ end
9
+ it "new FileTime instance should equal" do
10
+ FileTime.new.should equal(FileTime.new)
11
+ end
12
+ it "new FileTime instance should eql" do
13
+ FileTime.new.should eql(FileTime.new)
14
+ end
15
+ it "new FileTime instance should eq" do
16
+ FileTime.new.should eq(FileTime.new)
17
+ end
18
+ end
19
+
20
+ describe "SystemTime" do
21
+ it "new SystemTime instance should ==" do
22
+ SystemTime.new.should == SystemTime.new
23
+ end
24
+ it "new SystemTime instance should equal" do
25
+ SystemTime.new.should equal(SystemTime.new)
26
+ end
27
+ it "new SystemTime instance should eql" do
28
+ SystemTime.new.should eql(SystemTime.new)
29
+ end
30
+ it "new SystemTime instance should eq" do
31
+ SystemTime.new.should eq(SystemTime.new)
32
+ end
33
+ end
34
+
35
+ describe "Large_Integer" do
36
+ it "new Large_Integer instance should ==" do
37
+ Large_Integer.new.should == Large_Integer.new
38
+ end
39
+ it "new Large_Integer instance should equal" do
40
+ Large_Integer.new.should equal(Large_Integer.new)
41
+ end
42
+ it "new SystemTime instance should eql" do
43
+ Large_Integer.new.should eql(Large_Integer.new)
44
+ end
45
+ it "new SystemTime instance should eq" do
46
+ Large_Integer.new.should eq(Large_Integer.new)
47
+ end
48
+ end
49
+
50
+ describe "GetLastError" do
51
+ it "get last erro " do
52
+ # FIXME
53
+ #Win32ft.GetFileType -100
54
+ #Win32ft.GetLastError.should == 6
55
+ end
56
+ end
57
+
58
+ describe "FileTime LocalFileTime" do
59
+ it "test swap filetime localfiletime" do
60
+ ft1 = FileTime.new
61
+ ft1[:dwHighDateTime], ft1[:dwLowDateTime] = 0x1CCF838, 0x1F2B7320
62
+ ft2 = Win32ft.ft2lft(ft1)
63
+ ft3 = Win32ft.lft2ft(ft2)
64
+
65
+ ft1[:dwHighDateTime].should == ft3[:dwHighDateTime]
66
+ ft1[:dwLowDateTime].should == ft3[:dwLowDateTime]
67
+ end
68
+ end
69
+
70
+ describe "FileTime SystemTime" do
71
+ it "test swap filetime systemtime" do
72
+ ft1 = FileTime.new
73
+ ft1[:dwHighDateTime], ft1[:dwLowDateTime] = 0x01CCF838, 0x1F2B7320
74
+ st1 = Win32ft.ft2st(ft1)
75
+ ft3 = Win32ft.st2ft(st1)
76
+ ft1[:dwHighDateTime].should == ft3[:dwHighDateTime]
77
+ ft1[:dwLowDateTime].should == ft3[:dwLowDateTime]
78
+ end
79
+ end
80
+
81
+ describe "GetSystemTime" do
82
+ it "getsystemtime is_a? SystemTime" do
83
+ t1 = Win32ft.getsystemtime
84
+ t1.should satisfy { |st| st.is_a? SystemTime}
85
+ end
86
+ it "getsystemtime [:wYear] == current year" do
87
+ t1 = Win32ft.getsystemtime
88
+ t1[:wYear].should == Time.now.year
89
+ end
90
+ end
91
+
92
+ describe "GetLocalTime" do
93
+ it "getlocaltime is_a? SystemTime" do
94
+ t1 = Win32ft.getlocaltime
95
+ t1.should satisfy { |st| st.is_a? SystemTime}
96
+ end
97
+ it "getlocaltime [:wYear] == current year" do
98
+ t1 = Win32ft.getlocaltime
99
+ t1[:wYear].should == Time.now.year
100
+ end
101
+ end
102
+
103
+ describe "GetLocalTime GetSystemTime" do
104
+ it "diff localtime systemtime" do
105
+ st1 = Win32ft.getsystemtime
106
+ lt1 = Win32ft.getlocaltime
107
+ t1 = Time.utc st1[:wYear], st1[:wMonth], st1[:wDay], st1[:wHour],
108
+ st1[:wMinute], st1[:wSecond]
109
+ t2 = Time.local lt1[:wYear], lt1[:wMonth], lt1[:wDay], lt1[:wHour],
110
+ lt1[:wMinute], lt1[:wSecond]
111
+ t1.should == t2
112
+ end
113
+ end
114
+
115
+
116
+ describe "File Create Read Write Flush Close GetFileSizeEx" do
117
+ before(:all) do
118
+ Dir.mkdir "c:\\tmp" rescue nil
119
+ Dir.chdir "c:\\tmp"
120
+ @fn1 = "c:\\tmp\\f1.txt"
121
+ @msg = Time.now.to_s + " asfas f;asjf;lasdfj;s af;alsj f"
122
+ end
123
+
124
+ it "CreateFileA WriteFile CloseHandle GetFileSizeEx" do
125
+ hf = Win32ft.CreateFileA(@fn1, CFflag::GENERIC_WRITE,
126
+ CFflag::FILE_SHARE_READ | CFflag::FILE_SHARE_WRITE,
127
+ nil, CFflag::OPEN_ALWAYS, 0, 0)
128
+ hf.should satisfy { |obj| obj.is_a? Fixnum }
129
+
130
+ wded = FFI::MemoryPointer.new(:uint32, 1)
131
+ buffer = FFI::MemoryPointer.new(:char, @msg.bytesize)
132
+ buffer.write_string @msg
133
+ wfres = Win32ft.WriteFile(hf, buffer, @msg.bytesize, wded, nil)
134
+ wfres.should be(true)
135
+ wded.read_uint32.should == @msg.bytesize
136
+
137
+ chres = Win32ft.CloseHandle(hf)
138
+ chres.should be(true)
139
+ end
140
+
141
+ it "ReadFile" do
142
+ buffer = FFI::MemoryPointer.new :char, @msg.bytesize*2
143
+ rded = FFI::MemoryPointer.new :uint32, 1
144
+ hf = Win32ft.CreateFileA(@fn1, CFflag::GENERIC_READ,
145
+ CFflag::FILE_SHARE_READ | CFflag::FILE_SHARE_WRITE,
146
+ nil, CFflag::OPEN_EXISTING, 0, 0)
147
+ hf.should satisfy { |obj| obj.is_a? Fixnum }
148
+ rfres = Win32ft.ReadFile(hf, buffer, @msg.bytesize*2, rded, nil)
149
+ rfres.should be(true)
150
+ rded.read_uint32.should == @msg.bytesize
151
+ buffer.read_string.should == @msg
152
+ Win32ft.CloseHandle(hf)
153
+ end
154
+
155
+ it "ReadFile no exist file" do
156
+ Dir.mkdir "c:\\tmp" rescue nil
157
+ fn = "c:\\tmp\\noexist.txt"
158
+ hf = Win32ft.CreateFileA(fn, CFflag::GENERIC_READ,
159
+ CFflag::FILE_SHARE_READ | CFflag::FILE_SHARE_WRITE,
160
+ nil, CFflag::OPEN_EXISTING, 0, 0)
161
+ hf.should == -1
162
+ end
163
+
164
+ it "getfilesize" do
165
+ size = Win32ft.getfilesize(@fn1)
166
+ size.should == @msg.bytesize
167
+ end
168
+ end
169
+
170
+ describe "GetFileTime SetFileTime" do
171
+ before(:all) do
172
+ Dir.mkdir "c:\\tmp" rescue nil
173
+ Dir.chdir "c:\\tmp"
174
+ @fn1 = "c:\\tmp\\f1.txt"
175
+ @msg = Time.now.to_s * 2
176
+ end
177
+
178
+ after(:all) do
179
+ Win32ft.DeleteFile(@fn1).should == true
180
+ Dir.chdir "c:\\"
181
+ Dir.rmdir "c:\\tmp"
182
+ end
183
+
184
+ it "getfiletime" do
185
+ tc1, ta1, tm1 = Win32ft.getfiletime(@fn1)
186
+ tc1.should_not == FileTime.new
187
+ ta1.should_not == FileTime.new
188
+ tm1.should_not == FileTime.new
189
+ end
190
+
191
+ it "setfiletime getfiletime getfilesize" do
192
+ require 'tempfile'
193
+ tc1, ta1, tm1 = Win32ft.getfiletime(@fn1)
194
+ fnt = Tempfile.new 'test'
195
+ fnt.print @msg
196
+ fnt.close
197
+
198
+ tc2, ta2, tm2 = Win32ft.getfiletime(fnt.path)
199
+ tc2.should_not == tc1
200
+ ta2.should_not == ta1
201
+ tm2.should_not == tm1
202
+
203
+ res = Win32ft.setfiletime(fnt.path, tc1, ta1, tm1)
204
+ res.should be(true)
205
+ tc3, ta3, tm3, sz = Win32ft.getfiletime(fnt.path, getsize: true)
206
+ tc3.should == tc1
207
+ ta3.should == ta1
208
+ tm3.should == tm1
209
+ sz.to_i.should == @msg.bytesize
210
+ end
211
+
212
+ it "ft2double double2ft" do
213
+ tc1, ta1, tm1 = Win32ft.getfiletime(@fn1)
214
+ ftc1 = Win32ft.ft2double(tc1)
215
+ fta1 = Win32ft.ft2double(ta1)
216
+ ftm1 = Win32ft.ft2double(tm1)
217
+ tc2 = Win32ft.double2ft(ftc1)
218
+ ta2 = Win32ft.double2ft(fta1)
219
+ tm2 = Win32ft.double2ft(ftm1)
220
+ (tc2[:dwLowDateTime] - tc1[:dwLowDateTime]).should <= 10
221
+ (ta2[:dwLowDateTime] - ta1[:dwLowDateTime]).should <= 10
222
+ (tm2[:dwLowDateTime] - tm1[:dwLowDateTime]).should <= 10
223
+ end
224
+
225
+ it "copy file time" do
226
+ f1 = Tempfile.new 't1'
227
+ f1.print '111'
228
+ f1.close
229
+ sleep 0.1
230
+ f2 = Tempfile.new 't2'
231
+ f2.print '222222'
232
+ f2.close
233
+ tc1, ta1, tm1, sz1 = Win32ft.getfiletime f1.path, getsize: true
234
+ tc2, ta2, tm2, sz2 = Win32ft.getfiletime f2.path, getsize: true
235
+ tc2.should_not == tc1
236
+ ta2.should_not == ta1
237
+ tm2.should_not == tm1
238
+ sz1.should_not == sz2
239
+
240
+ tc1, ta1, tm1, sz1 = Win32ft.getfiletime f1.path, getsize: true
241
+ Win32ft.copyfiletime(f1.path, f2.path)
242
+ tc2, ta2, tm2, sz2 = Win32ft.getfiletime f2.path, getsize: true
243
+ tc2.should == tc1
244
+ ta2.should == ta1
245
+ tm2.should == tm1
246
+ end
247
+ it "copy file time on some directory" do
248
+ Dir.mkdir 'a' rescue nil
249
+ t=Time.now.to_f.to_s
250
+ f1 = open("a/a1#{t}", 'wb')
251
+ f1.print '111'
252
+ f1.close
253
+ sleep 0.1
254
+ f2 = open("a/a2#{t}", 'wb')
255
+ f2.print '222222'
256
+ f2.close
257
+ tc1, ta1, tm1, sz1 = Win32ft.getfiletime f1.path, getsize: true
258
+ tc2, ta2, tm2, sz2 = Win32ft.getfiletime f2.path, getsize: true
259
+ tc2.should_not == tc1
260
+ ta2.should_not == ta1
261
+ tm2.should_not == tm1
262
+ sz1.should_not == sz2
263
+
264
+ tc1, ta1, tm1, sz1 = Win32ft.getfiletime f1.path, getsize: true
265
+ Win32ft.copyfiletime(f1.path, f2.path)
266
+ tc2, ta2, tm2, sz2 = Win32ft.getfiletime f2.path, getsize: true
267
+ tc2.should == tc1
268
+ ta2.should == ta1
269
+ tm2.should == tm1
270
+ Win32ft.DeleteFile(f1.path).should == true
271
+ Win32ft.DeleteFile(f2.path).should == true
272
+ Dir.rmdir 'a' rescue nil
273
+ end
274
+ it "copy file time on diff directory" do
275
+ Dir.mkdir 'a' rescue nil
276
+ Dir.mkdir 'b' rescue nil
277
+ t=Time.now.to_f.to_s
278
+ f1 = open("a/a#{t}", 'wb')
279
+ f1.print '111'
280
+ f1.close
281
+ sleep 0.1
282
+ f2 = open("b/a#{t}", 'wb')
283
+ f2.print '222222'
284
+ f2.close
285
+ tc1, ta1, tm1, sz1 = Win32ft.getfiletime f1.path, getsize: true
286
+ tc2, ta2, tm2, sz2 = Win32ft.getfiletime f2.path, getsize: true
287
+ tc2.should_not == tc1
288
+ ta2.should_not == ta1
289
+ tm2.should_not == tm1
290
+ sz1.should_not == sz2
291
+
292
+ tc1, ta1, tm1, sz1 = Win32ft.getfiletime f1.path, getsize: true
293
+ Win32ft.copyfiletime(f1.path, f2.path)
294
+ tc2, ta2, tm2, sz2 = Win32ft.getfiletime f2.path, getsize: true
295
+ tc2.should == tc1
296
+ ta2.should == ta1
297
+ tm2.should == tm1
298
+ Win32ft.DeleteFile(f1.path).should == true
299
+ Win32ft.DeleteFile(f2.path).should == true
300
+ Dir.rmdir 'a' rescue nil
301
+ Dir.rmdir 'b' rescue nil
302
+ end
303
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'win32_filetime/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "win32_filetime"
8
+ spec.version = Win32Filetime::VERSION
9
+ spec.authors = ["windwiny"]
10
+ spec.email = ["windwiny.ubt@gmail.com"]
11
+ spec.description = %q{win32 filetime api}
12
+ spec.summary = %q{win32 filetime api}
13
+ spec.homepage = "https://github.com/windwiny/win32_filetime.git"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_dependency "ffi"
24
+ end
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: win32_filetime
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - windwiny
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-12-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: ffi
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: win32 filetime api
56
+ email:
57
+ - windwiny.ubt@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - Gemfile
64
+ - LICENSE.txt
65
+ - README.md
66
+ - Rakefile
67
+ - lib/win32_filetime.rb
68
+ - lib/win32_filetime/version.rb
69
+ - lib/win32ft.rb
70
+ - specs/win32ft.spec.rb
71
+ - win32_filetime.gemspec
72
+ homepage: https://github.com/windwiny/win32_filetime.git
73
+ licenses:
74
+ - MIT
75
+ metadata: {}
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubyforge_project:
92
+ rubygems_version: 2.0.14
93
+ signing_key:
94
+ specification_version: 4
95
+ summary: win32 filetime api
96
+ test_files: []