Module: FileHelper

Extended by:
FileHelper
Included in:
FileHelper
Defined in:
lib/filewatch/helper.rb

Instance Method Summary collapse

Instance Method Details

#device?(file_name) ⇒ Boolean



49
50
51
# File 'lib/filewatch/helper.rb', line 49

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

#probe_stat_in(dir) ⇒ Object

Private utility method.



54
55
56
57
58
59
60
61
62
63
# File 'lib/filewatch/helper.rb', line 54

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

#rand_filename(prefix) ⇒ Object



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

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

#write_atomically(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.write_atomically('important.file') do |file|
  file.write('hello')
end


15
16
17
18
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
# File 'lib/filewatch/helper.rb', line 15

def write_atomically(file_name)

  if File.exist?(file_name)
    # Get original file permissions
    old_stat = File.stat(file_name)
  else
    # If not possible, probe which are the default permissions in the
    # destination directory.
    old_stat = probe_stat_in(File.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
  new_stat = File.stat(temp_file)

  # 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 if ownership is different.
  if old_stat && (old_stat.gid != new_stat.gid || old_stat.uid != new_stat.uid)
    File.chown(old_stat.uid, old_stat.gid, file_name) if old_stat
  end

  return_val
end