win32_filetime 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []