Class: File

Inherits:
Object
  • Object
show all
Defined in:
lib/filewatch/helper.rb

Class Method Summary collapse

Class Method Details

.atomic_write(file_name) ⇒ Object

Write to a file atomically. Useful for situations where you don’t want other processes or threads to see half-written files.

File.atomic_write('important.file') do |file|
  file.write('hello')
end

If your temp directory is not on the same filesystem as the file you’re trying to write, you can provide a different temporary directory.

File.atomic_write('/data/something.important', '/data/tmp') do |file|
  file.write('hello')
end


19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/filewatch/helper.rb', line 19

def self.atomic_write(file_name)

  if File.exist?(file_name)
    # Get original file permissions
    old_stat = stat(file_name)
  else
    # If not possible, probe which are the default permissions in the
    # destination directory.
    old_stat = probe_stat_in(dirname(file_name))
  end

  mode = old_stat ? old_stat.mode : nil

  # Create temporary file with identical permissions
  temp_file = File.new(rand_filename(file_name), "w", mode)
  temp_file.binmode
  return_val = yield temp_file
  temp_file.close

  # Overwrite original file with temp file
  File.rename(temp_file.path, file_name)

  # Unable to get permissions of the original file => return
  return return_val if old_stat.nil?

  # Set correct uid/gid on new file
  chown(old_stat.uid, old_stat.gid, file_name) if old_stat

  return_val
end

.device?(file_name) ⇒ Boolean

Returns:

  • (Boolean)


66
67
68
# File 'lib/filewatch/helper.rb', line 66

def self.device?(file_name)
  chardev?(file_name) || blockdev?(file_name)
end

.probe_stat_in(dir) ⇒ Object

Private utility method.



51
52
53
54
55
56
57
58
59
60
# File 'lib/filewatch/helper.rb', line 51

def self.probe_stat_in(dir) #:nodoc:
  basename = rand_filename(".permissions_check")
  file_name = join(dir, basename)
  FileUtils.touch(file_name)
  stat(file_name)
rescue
  # ...
ensure
  FileUtils.rm_f(file_name) if File.exist?(file_name)
end

.rand_filename(prefix) ⇒ Object



62
63
64
# File 'lib/filewatch/helper.rb', line 62

def self.rand_filename(prefix)
  [ prefix, Thread.current.object_id, Process.pid, rand(1000000) ].join('.')
end