Module: EasyIO::Disk

Defined in:
lib/easy_io/disk.rb

Constant Summary collapse

GetDiskFreeSpaceEx =

TODO: make this cross platform. sys-filesystem gem maybe?

Win32API.new('kernel32', 'GetDiskFreeSpaceEx', 'PPPP', 'I')

Class Method Summary collapse

Class Method Details

.free_space(path) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/easy_io/disk.rb', line 9

def free_space(path)
  raise 'Cannot check free space for path provided. Path is empty or nil.' if path.nil? || path.empty? || path == 'null'
  root_folder = root_directory(path)

  raise "Cannot check free space for #{path} - The path was not found." if root_folder.nil? || root_folder.empty?
  root_folder = EasyFormat::Directory.ensure_trailing_slash(root_folder)

  free = [0].pack('Q')
  GetDiskFreeSpaceEx.call(root_folder, 0, 0, free)
  free = free.unpack1('Q')

  (free / 1024.0 / 1024.0).round(2)
end

.move_files(search_string, destination_folder) ⇒ Object



37
38
39
40
41
# File 'lib/easy_io/disk.rb', line 37

def move_files(search_string, destination_folder)
  files = Dir.glob(search_string.tr('\\', '/'))
  FileUtils.mkdir_p destination_folder unless ::File.directory? destination_folder
  FileUtils.move(files, destination_folder) { true }
end

.open_file_and_wait_for_exclusive_lock(path, timeout: 60, status_interval: 15, silent: false) ⇒ Object

Opens a file in the filesystem and locks it exclusively. If it fails, it will keep trying until the timeout. Pass a block to be executed while the file is locked. The ::File object is passed to the block.



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/easy_io/disk.rb', line 62

def open_file_and_wait_for_exclusive_lock(path, timeout: 60, status_interval: 15, silent: false)
  start_time = Time.now
  raise "Cannot create #{::File.basename(path)} - the parent directory does not exist (#{::File.dirname(path)})!" unless ::File.directory?(::File.dirname(path))
  ::File.open(path, ::File::RDWR | ::File::CREAT) do |file|
    loop do
      if Time.now >= start_time + timeout # locking timed out.
        file.close
        raise "Failed to gain exclusive lock on #{path}! Timed out after #{timeout} seconds."
      end
      lock_success = file.flock(File::LOCK_EX | File::LOCK_NB)
      if lock_success
        yield(file)
        file.close
        break
      end
      seconds_elapsed = Time.now - start_time
      EasyIO.logger.info "Waiting for another process to unlock #{path}... Time elapsed: #{seconds_elapsed}" if seconds_elapsed % status_interval == 0 && !silent # Output status every (status_interval) seconds
      sleep(1)
    end
  end
end

.read_files(search_string) ⇒ Object



43
44
45
46
# File 'lib/easy_io/disk.rb', line 43

def read_files(search_string)
  files = Dir.glob(search_string.tr('\\', '/'))
  files.map { |file| ::File.read(file) }
end

.root_directory(path) ⇒ Object

Gets the root directory of a path. Local and UNC paths accepted



49
50
51
52
53
# File 'lib/easy_io/disk.rb', line 49

def root_directory(path)
  computed_path = path
  computed_path = File.dirname(computed_path) while computed_path != File.dirname(computed_path)
  computed_path
end

.size(path) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/easy_io/disk.rb', line 23

def size(path)
  raise 'Cannot check free space for path provided. Path is empty or nil.' if path.nil? || path.empty? || path == 'null'
  root_folder = root_directory(path)

  raise "Cannot check free space for #{path} - The path was not found." if root_folder.nil? || root_folder.empty?
  root_folder = EasyFormat::Directory.ensure_trailing_slash(root_folder)

  total = [0].pack('Q')
  GetDiskFreeSpaceEx.call(root_folder, 0, total, 0)
  total = total.unpack1('Q')

  (total / 1024.0 / 1024.0).round(2)
end

.valid_checksum?(file, sha256_checksum) ⇒ Boolean

Returns:

  • (Boolean)


55
56
57
58
# File 'lib/easy_io/disk.rb', line 55

def valid_checksum?(file, sha256_checksum)
  return false if sha256_checksum.nil? || !::File.exist?(file)
  Digest::SHA256.file(file).hexdigest.downcase == sha256_checksum.downcase
end