Module: FFI::Libfuse::Filesystem::Utils

Included in:
MappedDir, PassThroughDir, VirtualDir, VirtualFS
Defined in:
lib/ffi/libfuse/filesystem/utils.rb

Overview

RubySpace File Utilities

This module provides utility methods for file operations in RubySpace which are useful for creating custom entries prior to mounting, or otherwise manipulating the filesystem from within the Ruby process that is running FUSE.

Note You cannot generally call Ruby's File and Dir operations from within the same Ruby process as the mounted filesystem because MRI will not release the GVL to allow the Fuse callbacks to run.

Instance Method Summary collapse

Instance Method Details

#directory?(path) ⇒ Boolean

Returns true if directory exists at path.

Parameters:

  • path (:to_s)

Returns:

  • (Boolean)

    true if directory exists at path



66
67
68
# File 'lib/ffi/libfuse/filesystem/utils.rb', line 66

def directory?(path)
  stat(path)&.directory? || false
end

#empty_dir?(path) ⇒ Boolean

Check if a directory is empty

Parameters:

  • path (String)

Returns:

  • (Boolean)

    true if an empty directory exists at path

Raises:

  • (Errno::ENOTDIR)

    if path does not point to a directory



81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/ffi/libfuse/filesystem/utils.rb', line 81

def empty_dir?(path)
  return false unless directory?(path)

  empty = true
  fake_filler = proc do |_buf, name, _stat = nil, _offset = 0, _fuse_flag = 0|
    next 0 if %w[. ..].include?(name)

    empty = false
    -1 # buf full don't send more entries!
  end
  readdir(path.to_s, nil, fake_filler, 0, nil, *(fuse3_compat? ? [] : [0]))
  empty
end

#empty_file?(path) ⇒ Boolean

Returns File exists at path and has zero size.

Parameters:

  • path (:to_s)

Returns:

  • (Boolean)

    File exists at path and has zero size



72
73
74
75
# File 'lib/ffi/libfuse/filesystem/utils.rb', line 72

def empty_file?(path)
  s = stat(path)
  (s&.file? && s.size.zero?) || false # rubocop:disable Style/ZeroLengthPredicate
end

#exists?(path) ⇒ Boolean

Returns true if file or directory exists at path.

Parameters:

  • path (:to_s)

Returns:

  • (Boolean)

    true if file or directory exists at path



54
55
56
# File 'lib/ffi/libfuse/filesystem/utils.rb', line 54

def exists?(path)
  stat(path) && true
end

#file?(path) ⇒ Boolean

Returns true if regular file exists at path.

Parameters:

  • path (:to_s)

Returns:

  • (Boolean)

    true if regular file exists at path



60
61
62
# File 'lib/ffi/libfuse/filesystem/utils.rb', line 60

def file?(path)
  stat(path)&.file? || false
end

#mkdir_p(path, mode = (~FuseContext.get.umask & 0o0777)) {|the| ... } ⇒ Object Also known as: mkpath

Recursive mkdir

Parameters:

  • path (:to_s)
  • mode (Integer) (defaults to: (~FuseContext.get.umask & 0o0777))

    permissions for any dirs that need to be created

Yield Parameters:

  • the (String)

    path component being created

Yield Returns:

  • (FuseOperations)

    optionally a filesystem to mount at path, if the path did not previously exist



22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/ffi/libfuse/filesystem/utils.rb', line 22

def mkdir_p(path, mode = (~FuseContext.get.umask & 0o0777), &mount_fs)
  return if root?(path) # nothing to make

  path.to_s.split('/')[1..].inject('') do |base_path, sub_dir|
    full_path = "#{base_path}/#{sub_dir}"
    err = Adapter::Safe.safe_callback(:mkdir) { mkdir(full_path, mode, &mount_fs) }
    unless [0, -Errno::EEXIST::Errno].include?(err)
      raise SystemCallError.new("Unexpected err #{err.abs} from mkdir #{full_path}", err.abs)
    end

    full_path
  end
  0
end

#stat(path) ⇒ FFI::Stat

Parameters:

  • path (:to_s)

Returns:

Raises:

  • (SystemCallError)


40
41
42
43
44
45
46
47
48
49
50
# File 'lib/ffi/libfuse/filesystem/utils.rb', line 40

def stat(path)
  path = path.to_s
  stat_buf = FFI::Stat.new

  err = Adapter::Safe.safe_callback(:getattr) { getattr(path, stat_buf) }

  return nil if err == -Errno::ENOENT::Errno
  raise SystemCallError, "Unexpected error from #{fs}.getattr #{path}", err unless err.zero?

  stat_buf
end