lib/ffi/libfuse/fuse_operations.rb in ffi-libfuse-0.0.1.rctest12 vs lib/ffi/libfuse/fuse_operations.rb in ffi-libfuse-0.1.0.rc20220550

- old
+ new

@@ -10,32 +10,37 @@ require_relative '../stat_vfs' require_relative '../flock' require_relative 'thread_pool' require_relative '../stat' require_relative '../struct_array' +require_relative '../encoding' require_relative 'fuse_callbacks' module FFI # Ruby FFI Binding for [libfuse](https://github.com/libfuse/libfuse) module Libfuse + # All paths are encoded in ruby's view of the filesystem encoding + typedef Encoding.for('filesystem'), :fs_string + # typedef int (*fuse_fill_dir_t) (void *buf, const char *name, const struct stat *stbuf, off_t off); - fill_dir_t_args = [:pointer, :string, Stat.by_ref, :off_t] + fill_dir_t_args = [:pointer, :fs_string, Stat.by_ref, :off_t] if FUSE_MAJOR_VERSION > 2 enum :fuse_readdir_flags, [:fuse_readdir_plus, (1 << 0)] enum :fuse_fill_dir_flags, [:fuse_fill_dir_plus, (1 << 1)] fill_dir_t_args << :fuse_fill_dir_flags end + bitmask :fuse_ioctl_flags, %i[compat unrestricted retry dir] bitmask :lock_op, [:lock_sh, 0, :lock_ex, 2, :lock_nb, 4, :lock_un, 8] bitmask :falloc_mode, %i[keep_size punch_hole no_hide_stale collapse_range zero_range insert_range unshare_range] bitmask :flags_mask, %i[nullpath_ok nopath utime_omit_ok] if FUSE_MAJOR_VERSION < 3 enum :xattr, [:xattr_create, 1, :xattr_replace] callback :fill_dir_t, fill_dir_t_args, :int # The file system operations as specified in libfuse. # - # All Callback and Configuration methods are optional, but some are essential for a useful filesystem + # All Callback methods are optional, but some are essential for a useful filesystem # e.g. {getattr},{readdir} # # Almost all callback operations take a path which can be of any length and will return 0 for success, or raise a # {::SystemCallError} on failure # @@ -142,33 +147,33 @@ # @param [String] target the link target # # @return [Integer] 0 for success or -ve errno # int (*symlink) (const char *, const char *); - op[:symlink] = [:string] + op[:symlink] = [:fs_string] # @!method rename(from_path,to_path) # @abstract # Rename a file # @param [String] from_path # @param [String] to_path # # @return [Integer] 0 for success or -ve errno # int (*rename) (const char *, const char *); - op[:rename] = [:string] + op[:rename] = [:fs_string] # @!method link(path,target) # @abstract # Create a hard link to a file # @param [String] path # @param [String] target # # @return [Integer] 0 for success or -ve errno # int (*link) (const char *, const char *); - op[:link] = [:string] + op[:link] = [:fs_string] # @!method chmod(path,mode,fuse_file_info=nil) # @abstract # Change the permission bits of a file # @param [String] path @@ -658,22 +663,25 @@ # Ioctl # @param [String] path # @param [Integer] cmd # @param [FFI::Pointer] arg # @param [FuseFileInfo] fuse_file_info - # @param [Integer] flags - # @param [FFI::Pointer] data + # @param [Array<Symbol>] flags # - # flags will have FUSE_IOCTL_COMPAT set for 32bit ioctls in 64bit environment. The size and direction of data - # is determined by _IOC_*() decoding of cmd. For _IOC_NONE, data will be NULL, for _IOC_WRITE data is out - # area, for _IOC_READ in area and if both are set in/out area. In all non-NULL cases, the area is of - # _IOC_SIZE(cmd) bytes. + # - :compat 32bit compat ioctl on 64bit machine + # - :unrestricted not restricted to well-formed ioctls, retry allowed (lowlevel fuse) + # - :retry retry with new iovecs (lowlevel fuse) + # - :dir is a directory file handle # - # If flags has FUSE_IOCTL_DIR then the fuse_file_info refers to a directory file handle. + # @param [FFI::Pointer] data + # + # The size and direction of data is determined by _IOC_*() decoding of cmd. For _IOC_NONE, data will be NULL, + # for _IOC_WRITE data is out area, for _IOC_READ in area and if both are set in/out area. In all non-NULL + # cases, the area is of _IOC_SIZE(cmd) bytes. # int (*ioctl) (const char *, int cmd, void *arg, struct fuse_file_info *, unsigned int flags, void *data); - op[:ioctl] = [:int, :pointer, FuseFileInfo.by_ref, :uint, :pointer] + op[:ioctl] = [:int, :pointer, FuseFileInfo.by_ref, :fuse_ioctl_flags, :pointer] # @!method poll(path,fuse_file_info,ph,reventsp) # @abstract # Poll for IO readiness events # @@ -695,12 +703,13 @@ # @!method write_buf(path,buf,offset,fuse_file_info) # @abstract # Write contents of buffer to an open file # - # Similar to the write() method, but data is supplied in a generic buffer. Use fuse_buf_copy() to transfer - # data to the destination. + # Similar to the write() method, but data is supplied in a generic buffer. + # Use {FuseBufVec#copy_to_fd} to copy data to an open file descriptor, or {FuseBufVec#copy_to_str} to extract + # string data from the buffer # # @param [String] path # @param [FuseBufVec] buf # @param [Integer] offset # @param [FuseFileInfo] fuse_file_info @@ -802,12 +811,12 @@ # const char *path_in, struct fuse_file_info *fi_in, off_t offset_in, const char *path_out, # struct fuse_file_info *fi_out, off_t offset_out, size_t size, int flags # ); op[:copy_file_range] = callback [ - :string, FuseFileInfo.by_ref, :off_t, - :string, FuseFileInfo.by_ref, :off_t, + :fs_string, FuseFileInfo.by_ref, :off_t, + :fs_string, FuseFileInfo.by_ref, :off_t, :size_t, :int ], :ssize_t # @!method lseek(path,offset,whence,fuse_file_info) # @abstract @@ -818,20 +827,20 @@ # either :seek_set ,:seek_cur, :seek_end, :seek_data, :seek_hole # @return [Integer] the found offset in bytes from the beginning of the file or -ve errno # @see lseek(2) # off_t (*lseek) (const char *, off_t off, int whence, struct fuse_file_info *); - op[:lseek] = callback [:string, :off_t, Flock::Enums::SeekWhence, FuseFileInfo.by_ref], :off_t + op[:lseek] = callback [:fs_string, :off_t, Flock::Enums::SeekWhence, FuseFileInfo.by_ref], :off_t end end # @!endgroup layout_data = op.transform_values do |v| if v.is_a?(Array) && !v.last.is_a?(Integer) # A typical fuse callback - callback([:string] + v, :int) + callback([:fs_string] + v, :int) else v end end @@ -862,9 +871,24 @@ return unless FUSE_MAJOR_VERSION < 3 fuse_flags.concat(delegate.fuse_flags) if delegate.respond_to?(:fuse_flags) send(:[]=, :flags, fuse_flags.uniq) + end + + # @!visibility private + def fuse_callbacks + self.class.fuse_callbacks + end + + # @return [Set<Symbol>] list of callback methods + def self.fuse_callbacks + @fuse_callbacks ||= Set.new(members - [:flags]) + end + + # @return [Set<Symbol>] list of path callback methods + def self.path_callbacks + @path_callbacks ||= fuse_callbacks - %i[init destroy] end end end end