win32-file 0.7.3 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5f6a139f0549b0a2b960a270847d1a889fb9e74f
4
- data.tar.gz: 938ff2a79f3abb35d78e3d1d12d57daa3b054c13
3
+ metadata.gz: 4e7711498726b528b1298a6c03de0e4bb8b8b7f0
4
+ data.tar.gz: e2888cd5b82f1eb3300ab8f19accaa7d888a78e8
5
5
  SHA512:
6
- metadata.gz: 7deb66b6745f6c6399c3b083e0aa5af62eadf79b8fdf72a32c4de6a8e52b32ce629486df1269e9435ba133b9a0b93bb068af349f82b779b46fba86ad11ae0b4f
7
- data.tar.gz: bc907afe4b105e6eeac4555f7c3ee44ec9edf63447bdcf7465fd8019bdd4dd04172a8355dacf58ec690d970c61a2f6079f2fb620944a658bd7e95530c08971a5
6
+ metadata.gz: fc3da34d570cd22907250e285e56656f0d46102b8273b4be3c1334f1869f9420c4ab4a223fa94f63b3c312579cea7832771df55b35f21c4051dc72e23ce300ab
7
+ data.tar.gz: f9eb5764bd2eaba797d8c3e759c650f7955ed4178363687f305672c5546587ee8790abd938318ce48760c4805741f0a18306a3ae01802a698fb1ef550a12c832
Binary file
data.tar.gz.sig CHANGED
Binary file
data/CHANGES CHANGED
@@ -1,3 +1,8 @@
1
+ == 0.8.0 - 30-Oct-2015
2
+ * The File.atime, File.ctime and File.mtime methods now accept an optional
3
+ second argument. If present, those values are set to whatever value that
4
+ you provided.
5
+
1
6
  == 0.7.3 - 26-Oct-2015
2
7
  * This gem is now signed.
3
8
  * Fixed a test for File.file?
data/README CHANGED
@@ -21,10 +21,12 @@
21
21
  * File.short_path
22
22
 
23
23
  == Singleton Methods Redefined
24
+ * File.atime # Takes an optional 2nd argument to set the value.
24
25
  * File.basename # UNC path issues, root path differences.
25
26
  * File.blksize # Not implemented in MRI
26
27
  * File.blockdev? # Not implemented in MRI
27
28
  * File.chardev? # Not implemented in MRI
29
+ * File.ctime # Takes an optional 2nd argument to set the value.
28
30
  * File.directory? # Better wide character string handling than MRI
29
31
  * File.dirname # UNC path issues in MRI
30
32
  * File.executable? # Not implemented in MRI
@@ -33,6 +35,7 @@
33
35
  * File.join # For uniform handling of path separators.
34
36
  * File.grpowned? # Not implemented in MRI
35
37
  * File.lstat # Not implemented in MRI
38
+ * File.mtime # Takes an optional 2nd argument to set the value.
36
39
  * File.owned? # Not implemented in MRI
37
40
  * File.pipe? # Not implemented in MRI
38
41
  * File.readable? # Not implemented in MRI
@@ -9,16 +9,16 @@ class File
9
9
  extend Windows::File::Functions
10
10
 
11
11
  # The version of the win32-file library
12
- WIN32_FILE_VERSION = '0.7.3'
12
+ WIN32_FILE_VERSION = '0.8.0'
13
13
 
14
14
  class << self
15
15
  alias_method :join_orig, :join
16
16
  alias_method :realpath_orig, :realpath
17
17
  alias_method :realdirpath_orig, :realdirpath
18
18
 
19
- remove_method :basename, :blockdev?, :chardev?, :dirname, :directory?
20
- remove_method :executable?, :executable_real?, :file?, :ftype, :grpowned?
21
- remove_method :join, :lstat, :owned?, :pipe?, :socket?
19
+ remove_method :atime, :basename, :blockdev?, :chardev?, :ctime, :dirname
20
+ remove_method :directory?, :executable?, :executable_real?, :file?
21
+ remove_method :ftype, :grpowned?, :join, :lstat, :owned?, :pipe?, :socket?
22
22
  remove_method :readable?, :readable_real?, :readlink, :realpath
23
23
  remove_method :realdirpath
24
24
  remove_method :split, :stat
@@ -366,6 +366,15 @@ class File
366
366
 
367
367
  ## STAT METHODS
368
368
 
369
+ # Returns the file's last access time. If a +time+ argument is provided, it
370
+ # sets the file's access time. The +time+ argument may be a Time object or
371
+ # a numeric value.
372
+ #
373
+ def self.atime(file, time = nil)
374
+ set_filetime(file, nil, time) if time
375
+ File::Stat.new(file).atime
376
+ end
377
+
369
378
  # Returns the filesystem's block size.
370
379
  #
371
380
  def self.blksize(file)
@@ -387,6 +396,15 @@ class File
387
396
  File::Stat.new(file).chardev?
388
397
  end
389
398
 
399
+ # Returns the file's creation time. If a +time+ argument is provided, it
400
+ # sets the file's creation time. The +time+ argument may be a Time object or
401
+ # a numeric value.
402
+ #
403
+ def self.ctime(file, time = nil)
404
+ set_filetime(file, time) if time
405
+ File::Stat.new(file).ctime
406
+ end
407
+
390
408
  # Returns whether or not the file is a directory.
391
409
  #
392
410
  def self.directory?(file)
@@ -422,6 +440,15 @@ class File
422
440
  File::Stat.new(file).grpowned?
423
441
  end
424
442
 
443
+ # Returns the file's creation time. If a +time+ argument is provided, it
444
+ # sets the file's creation time. The +time+ argument may be a Time object or
445
+ # a numeric value.
446
+ #
447
+ def self.mtime(file, time = nil)
448
+ set_filetime(file, nil, nil, time) if time
449
+ File::Stat.new(file).mtime
450
+ end
451
+
425
452
  # Returns whether or not the current process owner is the owner of the file.
426
453
  #
427
454
  def self.owned?(file)
@@ -502,15 +529,56 @@ class File
502
529
  end
503
530
 
504
531
  # Private singleton methods
505
- class << self
506
- private
507
-
508
- # Simulate Ruby's string checking
509
- def string_check(arg)
510
- return arg if arg.is_a?(String)
511
- return arg.send(:to_str) if arg.respond_to?(:to_str, true) # MRI allows private to_str
512
- return arg.to_path if arg.respond_to?(:to_path)
513
- raise TypeError
532
+ private
533
+
534
+ # Simulate Ruby's string checking
535
+ def self.string_check(arg)
536
+ return arg if arg.is_a?(String)
537
+ return arg.send(:to_str) if arg.respond_to?(:to_str, true) # MRI allows private to_str
538
+ return arg.to_path if arg.respond_to?(:to_path)
539
+ raise TypeError
540
+ end
541
+
542
+ # Internal method for setting the file time.
543
+ def self.set_filetime(path, ctime = nil, atime = nil, mtime = nil)
544
+ begin
545
+ handle = CreateFileW(
546
+ path.wincode,
547
+ FILE_WRITE_ATTRIBUTES,
548
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
549
+ nil,
550
+ OPEN_EXISTING,
551
+ FILE_ATTRIBUTE_NORMAL,
552
+ 0
553
+ )
554
+
555
+ if handle == INVALID_HANDLE_VALUE
556
+ raise SystemCallError.new('CreateFile', FFI.errno)
557
+ end
558
+
559
+ ftimes = [] # 0 = ctime, 1 = atime, 2 = mtime
560
+
561
+ [ctime, atime, mtime].each{ |time|
562
+ if time.nil?
563
+ ftimes << nil
564
+ next
565
+ else
566
+ systime = SYSTEMTIME.new(time)
567
+ ftime = FILETIME.new
568
+
569
+ if SystemTimeToFileTime(systime, ftime)
570
+ ftimes << ftime
571
+ else
572
+ raise SystemCallError.new('SystemTimetoFileTime', FFI.errno)
573
+ end
574
+ end
575
+ }
576
+
577
+ unless SetFileTime(handle, ftimes[0], ftimes[1], ftimes[2])
578
+ raise SystemCallError.new('SetFileTime', FFI.errno)
579
+ end
580
+ ensure
581
+ CloseHandle(handle) if handle
514
582
  end
515
583
  end
516
584
  end
@@ -7,13 +7,19 @@ module Windows
7
7
  FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400
8
8
  FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
9
9
  FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000
10
- FILE_SHARE_READ = 1
10
+
11
+ FILE_SHARE_READ = 1
12
+ FILE_SHARE_WRITE = 2
13
+
14
+ FILE_WRITE_ATTRIBUTES = 256
11
15
 
12
16
  FILE_TYPE_UNKNOWN = 0x0000
13
17
  FILE_TYPE_CHAR = 0x0002
14
18
  NO_ERROR = 0
15
19
 
16
- GENERIC_READ = 0x80000000
20
+ GENERIC_READ = 0x80000000
21
+ GENERIC_WRITE = 0x40000000
22
+
17
23
  INVALID_HANDLE_VALUE = (1 << FFI::Platform::ADDRESS_SIZE) - 1
18
24
  INVALID_FILE_ATTRIBUTES = (1 << FFI::Platform::ADDRESS_SIZE) - 1
19
25
  IO_REPARSE_TAG_SYMLINK = 0xA000000C
@@ -25,6 +25,8 @@ module Windows
25
25
  attach_pfunc :GetShortPathNameW, [:buffer_in, :buffer_out, :dword], :dword
26
26
  attach_pfunc :GetLongPathNameW, [:buffer_in, :buffer_out, :dword], :dword
27
27
  attach_pfunc :QueryDosDeviceA, [:string, :buffer_out, :dword], :dword
28
+ attach_pfunc :SetFileTime, [:handle, :ptr, :ptr, :ptr], :bool
29
+ attach_pfunc :SystemTimeToFileTime, [:ptr, :ptr], :bool
28
30
 
29
31
  ffi_lib :shlwapi
30
32
 
@@ -5,6 +5,36 @@ module Windows
5
5
  layout(:dwLowDateTime, :ulong, :dwHighDateTime, :ulong)
6
6
  end
7
7
 
8
+ class SYSTEMTIME < FFI::Struct
9
+ layout(
10
+ :wYear, :ushort,
11
+ :wMonth, :ushort,
12
+ :wDayOfWeek, :ushort,
13
+ :wDay, :ushort,
14
+ :wHour, :ushort,
15
+ :wMinute, :ushort,
16
+ :wSecond, :ushort,
17
+ :wMilliseconds, :ushort
18
+ )
19
+
20
+ # Allow a time object or raw numeric in constructor
21
+ def initialize(time = nil)
22
+ super()
23
+
24
+ time = Time.at(time) if time.is_a?(Numeric)
25
+ time = time.utc unless time.utc?
26
+
27
+ self[:wYear] = time.year
28
+ self[:wMonth] = time.month
29
+ self[:wDayOfWeek] = time.wday
30
+ self[:wDay] = time.day
31
+ self[:wHour] = time.hour
32
+ self[:wMinute] = time.min
33
+ self[:wSecond] = time.sec
34
+ self[:wMilliseconds] = time.nsec / 1000000
35
+ end
36
+ end
37
+
8
38
  class WIN32_FIND_DATA < FFI::Struct
9
39
  layout(
10
40
  :dwFileAttributes, :ulong,
@@ -6,7 +6,7 @@ require 'test-unit'
6
6
 
7
7
  class TC_Win32_File_Misc < Test::Unit::TestCase
8
8
  test "version constant is set to expected value" do
9
- assert_equal('0.7.3', File::WIN32_FILE_VERSION)
9
+ assert_equal('0.8.0', File::WIN32_FILE_VERSION)
10
10
  end
11
11
 
12
12
  test "ffi functions are private" do
@@ -42,6 +42,7 @@ class TC_Win32_File_Stat < Test::Unit::TestCase
42
42
 
43
43
  def setup
44
44
  @blksize = 4096 # Most likely
45
+ @time_file = 'stat_time.txt'
45
46
  end
46
47
 
47
48
  test "File::Stat class returned is from win32-file-stat library" do
@@ -50,6 +51,20 @@ class TC_Win32_File_Stat < Test::Unit::TestCase
50
51
  assert_nothing_raised{ File.stat(@@txt_file).hidden? }
51
52
  end
52
53
 
54
+ test "atime method basic functionality" do
55
+ assert_nothing_raised{ File.atime(@@txt_file) }
56
+ assert_kind_of(Time, File.atime(@@txt_file))
57
+ end
58
+
59
+ test "atime with two arguments sets the creation time" do
60
+ FileUtils.touch(@time_file)
61
+ original_time = File.atime(@time_file)
62
+ updated_time = original_time - 100000
63
+
64
+ assert_equal(updated_time, File.atime(@time_file, updated_time))
65
+ assert_equal(updated_time, File.atime(@time_file))
66
+ end
67
+
53
68
  test "blksize basic functionality" do
54
69
  assert_respond_to(File, :blksize)
55
70
  assert_kind_of(Fixnum, File.blksize(@@txt_file))
@@ -109,6 +124,20 @@ class TC_Win32_File_Stat < Test::Unit::TestCase
109
124
  assert_raises(ArgumentError){ File.chardev?(@@txt_file, 'foo') }
110
125
  end
111
126
 
127
+ test "ctime method basic functionality" do
128
+ assert_nothing_raised{ File.ctime(@@txt_file) }
129
+ assert_kind_of(Time, File.ctime(@@txt_file))
130
+ end
131
+
132
+ test "ctime with two arguments sets the creation time" do
133
+ FileUtils.touch(@time_file)
134
+ original_time = File.ctime(@time_file)
135
+ updated_time = original_time - 100000
136
+
137
+ assert_equal(updated_time, File.ctime(@time_file, updated_time))
138
+ assert_equal(updated_time, File.ctime(@time_file))
139
+ end
140
+
112
141
  test "lstat is an alias for stat" do
113
142
  assert_respond_to(File, :lstat)
114
143
  assert_alias_method(File, :stat, :lstat)
@@ -177,6 +206,20 @@ class TC_Win32_File_Stat < Test::Unit::TestCase
177
206
  assert_false(File.grpowned?('bogus'))
178
207
  end
179
208
 
209
+ test "mtime method basic functionality" do
210
+ assert_nothing_raised{ File.mtime(@@txt_file) }
211
+ assert_kind_of(Time, File.mtime(@@txt_file))
212
+ end
213
+
214
+ test "mtime with two arguments sets the creation time" do
215
+ FileUtils.touch(@time_file)
216
+ original_time = File.mtime(@time_file)
217
+ updated_time = original_time - 100000
218
+
219
+ assert_equal(updated_time, File.mtime(@time_file, updated_time))
220
+ assert_equal(updated_time, File.mtime(@time_file))
221
+ end
222
+
180
223
  test "owned? method basic functionality" do
181
224
  assert_respond_to(File, :owned?)
182
225
  assert_nothing_raised{ File.owned?(Dir.pwd) }
@@ -269,7 +312,10 @@ class TC_Win32_File_Stat < Test::Unit::TestCase
269
312
  end
270
313
 
271
314
  def teardown
315
+ File.delete(@time_file) if File.exist?(@time_file)
316
+
272
317
  @blksize = nil
318
+ @time_file = nil
273
319
  end
274
320
 
275
321
  def self.shutdown
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = 'win32-file'
5
- spec.version = '0.7.3'
5
+ spec.version = '0.8.0'
6
6
  spec.authors = ['Daniel J. Berger', 'Park Heesob']
7
7
  spec.license = 'Artistic 2.0'
8
8
  spec.email = 'djberg96@gmail.com'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: win32-file
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.3
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel J. Berger
@@ -31,7 +31,7 @@ cert_chain:
31
31
  EJYzxdPOrx2n6NYR3Hk+vHP0U7UBSveI6+qx+ndQYaeyCn+GRX2PKS9h66YF/Q1V
32
32
  tGSHgAmcLlkdGgan182qsE/4kKM=
33
33
  -----END CERTIFICATE-----
34
- date: 2015-10-27 00:00:00.000000000 Z
34
+ date: 2015-10-30 00:00:00.000000000 Z
35
35
  dependencies:
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: ffi
metadata.gz.sig CHANGED
@@ -1 +1 @@
1
- 4C|J`�jh��� ��/�k�2Xj�Kc })N����u�ϫ@�Sh��"�����R<JX|a#��~O/��?��-A�E)\'v��dWtJ-ݗ^2l��nE�J����P"yF$�M~dH)&���,QHYU u�?汦�����}&����MXG����a���O%��޳�9�:�t�:0����@*�(o' ;/WeR��qF u[A`�<q>�Q�$�r<������++��}IZ�
1
+ q{`b'D��z�k�PO���]^$^A-�l�����H7D{gFwN�uwj b6�{m~X>}��w:9/q��).݂�Se29�����<9}E�O8�BG���#�D���J��%�a$Bç�;b*altۋ�!T&ms-��:�����&���d(s