1
- # code downloaded from Ruby on Rails 4.2.1
2
- # https://raw.githubusercontent.com/rails/rails/v4.2.1 /activesupport/lib/active_support/core_ext/file/atomic.rb
1
+ # code downloaded from Ruby on Rails 4.2.4
2
+ # https://raw.githubusercontent.com/rails/rails/v4.2.4 /activesupport/lib/active_support/core_ext/file/atomic.rb
3
3
require 'fileutils'
4
4
5
5
class File
@@ -16,7 +16,14 @@ class File
16
16
# File.atomic_write('/data/something.important', '/data/tmp') do |file|
17
17
# file.write('hello')
18
18
# end
19
- def self . atomic_write ( file_name )
19
+ def self . atomic_write ( file_name , temp_dir = Dir . tmpdir )
20
+ require 'tempfile' unless defined? ( Tempfile )
21
+ require 'fileutils' unless defined? ( FileUtils )
22
+
23
+ temp_file = Tempfile . new ( basename ( file_name ) , temp_dir )
24
+ temp_file . binmode
25
+ yield temp_file
26
+ temp_file . close
20
27
21
28
if File . exist? ( file_name )
22
29
# Get original file permissions
@@ -27,42 +34,35 @@ def self.atomic_write(file_name)
27
34
old_stat = probe_stat_in ( dirname ( file_name ) )
28
35
end
29
36
30
- mode = old_stat ? old_stat . mode : nil
31
-
32
- # Create temporary file with identical permissions
33
- temp_file = File . new ( rand_filename ( file_name ) , "w" , mode )
34
- temp_file . binmode
35
- return_val = yield temp_file
36
- temp_file . close
37
-
38
37
# Overwrite original file with temp file
39
- File . rename ( temp_file . path , file_name )
38
+ FileUtils . mv ( temp_file . path , file_name )
40
39
41
- # Unable to get permissions of the original file => return
42
- return return_val if old_stat . nil?
43
-
44
- # Set correct uid/gid on new file
45
- chown ( old_stat . uid , old_stat . gid , file_name ) if old_stat
46
-
47
- return_val
40
+ # Set correct permissions on new file
41
+ begin
42
+ chown ( old_stat . uid , old_stat . gid , file_name )
43
+ # This operation will affect filesystem ACL's
44
+ chmod ( old_stat . mode , file_name )
45
+ rescue Errno ::EPERM , Errno ::EACCES
46
+ # Changing file ownership failed, moving on.
47
+ end
48
48
end
49
49
50
50
# Private utility method.
51
51
def self . probe_stat_in ( dir ) #:nodoc:
52
- basename = rand_filename ( ".permissions_check" )
52
+ basename = [
53
+ '.permissions_check' ,
54
+ Thread . current . object_id ,
55
+ Process . pid ,
56
+ rand ( 1000000 )
57
+ ] . join ( '.' )
58
+
53
59
file_name = join ( dir , basename )
54
60
FileUtils . touch ( file_name )
55
61
stat ( file_name )
56
- rescue
57
- # ...
58
62
ensure
59
- FileUtils . rm_f ( file_name ) if File . exist? ( file_name )
63
+ FileUtils . rm_f ( file_name ) if file_name
60
64
end
61
-
62
- def self . rand_filename ( prefix )
63
- [ prefix , Thread . current . object_id , Process . pid , rand ( 1000000 ) ] . join ( '.' )
64
- end
65
-
65
+
66
66
def self . device? ( file_name )
67
67
chardev? ( file_name ) || blockdev? ( file_name )
68
68
end
0 commit comments