win32-file 0.7.3 → 0.8.0

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 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