package ru.serce.jnrfuse; import jnr.ffi.Pointer; import jnr.ffi.types.dev_t; import jnr.ffi.types.gid_t; import jnr.ffi.types.mode_t; import jnr.ffi.types.off_t; import jnr.ffi.types.size_t; import jnr.ffi.types.u_int32_t; import jnr.ffi.types.uid_t; import ru.serce.jnrfuse.struct.FileStat; import ru.serce.jnrfuse.struct.Flock; import ru.serce.jnrfuse.struct.FuseBufvec; import ru.serce.jnrfuse.struct.FuseFileInfo; import ru.serce.jnrfuse.struct.FusePollhandle; import ru.serce.jnrfuse.struct.Statvfs; import ru.serce.jnrfuse.struct.Timespec; /** * Fuse file system. * All documentation from "fuse.h" * * @author Sergey Tselovalnikov * @see <fuse.h> * <p> * Most of these should work very similarly to the well known UNIX * file system operations. A major exception is that instead of * returning an error in 'errno', the operation should return the * negated error value (-errno) directly. * <p> * All methods are optional, but some are essential for a useful * filesystem (e.g. getattr). Open, flush, release, fsync, opendir, * releasedir, fsyncdir, access, create, ftruncate, fgetattr, lock, * init and destroy are special purpose methods, without which a full * featured filesystem can still be implemented. * <p> * See http://fuse.sourceforge.net/wiki/ for more information. * @since 27.05.15 */ public interface FuseFS extends Mountable { /** * Get file attributes. * <p> * Similar to stat(). The 'st_dev' and 'st_blksize' fields are * ignored. The 'st_ino' field is ignored except if the 'use_ino' * mount option is given. */ int getattr(String path, FileStat stat); /** * Read the target of a symbolic link * <p> * The buffer should be filled with a null terminated string. The * buffer size argument includes the space for the terminating * null character. If the linkname is too long to fit in the * buffer, it should be truncated. The return value should be 0 * for success. */ int readlink(String path, Pointer buf, @size_t long size); /** * Create a file node * <p> * This is called for creation of all non-directory, non-symlink * nodes. If the filesystem defines a create() method, then for * regular files that will be called instead. * * @param mode The argument mode specifies the permissions to use in case a new file * is created. @see ru.serce.jnrfuse.struct.FileStat flags */ int mknod(String path, @mode_t long mode, @dev_t long rdev); /** * Create a directory * <p> * Note that the mode argument may not have the type specification * bits set, i.e. S_ISDIR(mode) can be false. To obtain the * correct directory type bits use mode|S_IFDIR * * @param mode The argument mode specifies the permissions to use in case a new file * is created. @see ru.serce.jnrfuse.struct.FileStat flags */ int mkdir(String path, @mode_t long mode); /** * Remove a file */ int unlink(String path); /** * Remove a directory */ int rmdir(String path); /** * Create a symbolic link */ int symlink(String oldpath, String newpath); /** * Rename a file */ int rename(String oldpath, String newpath); /** * Create a hard link to a file */ int link(String oldpath, String newpath); /** * Change the permission bits of a file * * @param mode The argument mode specifies the permissions to use in case a new file * is created. @see ru.serce.jnrfuse.struct.FileStat flags */ int chmod(String path, @mode_t long mode); /** * Change the owner and group of a file */ int chown(String path, @uid_t long uid, @gid_t long gid); /** * Change the size of a file */ int truncate(String path, @off_t long size); /** * File open operation * <p> * No creation (O_CREAT, O_EXCL) and by default also no * truncation (O_TRUNC) flags will be passed to open(). If an * application specifies O_TRUNC, fuse first calls truncate() * and then open(). Only if 'atomic_o_trunc' has been * specified and kernel version is 2.6.24 or later, O_TRUNC is * passed on to open. * <p> * Unless the 'default_permissions' mount option is given, * open should check if the operation is permitted for the * given flags. Optionally open may also return an arbitrary * filehandle in the fuse_file_info structure, which will be * passed to all file operations. * * @see jnr.constants.platform.OpenFlags */ int open(String path, FuseFileInfo fi); /** * Read data from an open file * <p> * Read should return exactly the number of bytes requested except * on EOF or error, otherwise the rest of the data will be * substituted with zeroes. An exception to this is when the * 'direct_io' mount option is specified, in which case the return * value of the read system call will reflect the return value of * this operation. */ int read(String path, Pointer buf, @size_t long size, @off_t long offset, FuseFileInfo fi); /** * Write data to an open file * <p> * Write should return exactly the number of bytes requested * except on error. An exception to this is when the 'direct_io' * mount option is specified (see read operation). */ int write(String path, Pointer buf, @size_t long size, @off_t long offset, FuseFileInfo fi); /** * Get file system statistics * <p> * The 'f_frsize', 'f_favail', 'f_fsid' and 'f_flag' fields are ignored */ int statfs(String path, Statvfs stbuf); /** * Possibly flush cached data * <p> * BIG NOTE: This is not equivalent to fsync(). It's not a * request to sync dirty data. * <p> * Flush is called on each close() of a file descriptor. So if a * filesystem wants to return write errors in close() and the file * has cached dirty data, this is a good place to write back data * and return any errors. Since many applications ignore close() * errors this is not always useful. * <p> * NOTE: The flush() method may be called more than once for each * open(). This happens if more than one file descriptor refers * to an opened file due to dup(), dup2() or fork() calls. It is * not possible to determine if a flush is final, so each flush * should be treated equally. Multiple write-flush sequences are * relatively rare, so this shouldn't be a problem. * <p> * Filesystems shouldn't assume that flush will always be called * after some writes, or that if will be called at all. */ int flush(String path, FuseFileInfo fi); /** * Release an open file * <p> * Release is called when there are no more references to an open * file: all file descriptors are closed and all memory mappings * are unmapped. * <p> * For every open() call there will be exactly one release() call * with the same flags and file descriptor. It is possible to * have a file opened more than once, in which case only the last * release will mean, that no more reads/writes will happen on the * file. The return value of release is ignored. */ int release(String path, FuseFileInfo fi); /** * Synchronize file contents * <p> * If the datasync parameter is non-zero, then only the user data * should be flushed, not the meta data. */ int fsync(String path, int isdatasync, FuseFileInfo fi); /** * Set the attribute NAME of the file pointed to by PATH to VALUE (which * is SIZE bytes long). * * @param flags @see {@link ru.serce.jnrfuse.flags.XAttrConstants} * @return Return 0 on success, -1 for errors. */ int setxattr(String path, String name, Pointer value, @size_t long size, int flags); /** * Get the attribute NAME of the file pointed to by PATH to VALUE (which is * SIZE bytes long). * * @return Return 0 on success, -1 for errors. */ int getxattr(String path, String name, Pointer value, @size_t long size); /** * List extended attributes * <p> * The retrieved list is placed * in list, a caller-allocated buffer whose size (in bytes) is specified * in the argument size. The list is the set of (null-terminated) * names, one after the other. Names of extended attributes to which * the calling process does not have access may be omitted from the * list. The length of the attribute name list is returned */ int listxattr(String path, Pointer list, @size_t long size); /** * Remove the attribute NAME from the file pointed to by PATH. * * @return Return 0 on success, -1 for errors. */ int removexattr(String path, String name); /** * Open directory * <p> * Unless the 'default_permissions' mount option is given, * this method should check if opendir is permitted for this * directory. Optionally opendir may also return an arbitrary * filehandle in the fuse_file_info structure, which will be * passed to readdir, closedir and fsyncdir. */ int opendir(String path, FuseFileInfo fi); /** * Read directory * <p> * This supersedes the old getdir() interface. New applications * should use this. * <p> * The filesystem may choose between two modes of operation: * <p> * 1) The readdir implementation ignores the offset parameter, and * passes zero to the filler function's offset. The filler * function will not return '1' (unless an error happens), so the * whole directory is read in a single readdir operation. This * works just like the old getdir() method. * <p> * 2) The readdir implementation keeps track of the offsets of the * directory entries. It uses the offset parameter and always * passes non-zero offset to the filler function. When the buffer * is full (or an error happens) the filler function will return * '1'. */ int readdir(String path, Pointer buf, FuseFillDir filter, @off_t long offset, FuseFileInfo fi); /** * Release directory */ int releasedir(String path, FuseFileInfo fi); /** * Synchronize directory contents * <p> * If the datasync parameter is non-zero, then only the user data * should be flushed, not the meta data */ int fsyncdir(String path, FuseFileInfo fi); /** * Initialize filesystem * <p> * The return value will passed in the private_data field of * fuse_context to all file operations and as a parameter to the * destroy() method. */ Pointer init(Pointer conn); /** * Clean up filesystem * <p> * Called on filesystem exit. */ void destroy(Pointer initResult); /** * Check file access permissions * <p> * This will be called for the access() system call. If the * 'default_permissions' mount option is given, this method is not * called. * <p> * This method is not called under Linux kernel versions 2.4.x * * @param mask see @{link ru.serce.jnrfuse.flags.AccessConstants} * @return -ENOENT if the path doesn't exist, -EACCESS if the requested permission isn't available, or 0 for success */ int access(String path, int mask); /** * Create and open a file * <p> * If the file does not exist, first create it with the specified * mode, and then open it. * <p> * If this method is not implemented or under Linux kernel * versions earlier than 2.6.15, the mknod() and open() methods * will be called instead. * * @param mode The argument mode specifies the permissions to use in case a new file * is created. See ru.serce.jnrfuse.struct.FileStat flags */ int create(String path, @mode_t long mode, FuseFileInfo fi); /** * Change the size of an open file * <p> * This method is called instead of the truncate() method if the * truncation was invoked from an ftruncate() system call. * <p> * If this method is not implemented or under Linux kernel * versions earlier than 2.6.15, the truncate() method will be * called instead. */ int ftruncate(String path, @off_t long size, FuseFileInfo fi); /** * Get attributes from an open file * <p> * This method is called instead of the getattr() method if the * file information is available. * <p> * Currently this is only called after the create() method if that * is implemented (see above). Later it may be called for * invocations of fstat() too. */ int fgetattr(String path, FileStat stbuf, FuseFileInfo fi); /** * Perform POSIX file locking operation * <p> * The cmd argument will be either F_GETLK, F_SETLK or F_SETLKW. * <p> * For the meaning of fields in 'struct flock' see the man page * for fcntl(2). The l_whence field will always be set to * SEEK_SET. * <p> * For checking lock ownership, the 'fuse_file_info->owner' * argument must be used. * <p> * For F_GETLK operation, the library will first check currently * held locks, and if a conflicting lock is found it will return * information without calling this method. This ensures, that * for local locks the l_pid field is correctly filled in. The * results may not be accurate in case of race conditions and in * the presence of hard links, but it's unlikely that an * application would rely on accurate GETLK results in these * cases. If a conflicting lock is not found, this method will be * called, and the filesystem may fill out l_pid by a meaningful * value, or it may leave this field zero. * <p> * For F_SETLK and F_SETLKW the l_pid field will be set to the pid * of the process performing the locking operation. * <p> * Note: if this method is not implemented, the kernel will still * allow file locking to work locally. Hence it is only * interesting for network filesystems and similar. * * @param cmd see {@link jnr.constants.platform.Fcntl} */ int lock(String path, FuseFileInfo fi, int cmd, Flock flock); /** * Change the access and modification times of a file with * nanosecond resolution * <p> * This supersedes the old utime() interface. New applications * should use this. * <p> * See the utimensat(2) man page for details. */ int utimens(String path, Timespec[] timespec); /** * Map block index within file to block index within device * <p> * Note: This makes sense only for block device backed filesystems * mounted with the 'blkdev' option * * @param idx block index within file * @param blocksize unit of block index */ int bmap(String path, @size_t long blocksize, long idx); /** * Ioctl * <p> * 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. * * @param flags See {@link ru.serce.jnrfuse.flags.IoctlFlags} */ int ioctl(String path, int cmd, Pointer arg, FuseFileInfo fi, @u_int32_t long flags, Pointer data); /** * Poll for IO readiness events * <p> * Note: If ph is non-NULL, the client should notify * when IO readiness events occur by calling * fuse_notify_poll() with the specified ph. * <p> * Regardless of the number of times poll with a non-NULL ph * is received, single notification is enough to clear all. * Notifying more times incurs overhead but doesn't harm * correctness. * <p> * The callee is responsible for destroying ph with * fuse_pollhandle_destroy() when no longer in use. * * @param reventsp A pointer to a bitmask of the returned events satisfied. */ int poll(String path, FuseFileInfo fi, FusePollhandle ph, Pointer reventsp); /** * Write contents of buffer to an open file * <p> * Similar to the write() method, but data is supplied in a * generic buffer. Use fuse_buf_copy() to transfer data to * the destination. * <p> * IMPORTANT: * Is not enabled by default, for enabling use * ru.serce.jnrfuse.AbstractFuseFS#isBufOperationsImplemented() */ int write_buf(String path, FuseBufvec buf, @off_t long off, FuseFileInfo fi); /** * Store data from an open file in a buffer * <p> * Similar to the read() method, but data is stored and * returned in a generic buffer. * <p> * No actual copying of data has to take place, the source * file descriptor may simply be stored in the buffer for * later data transfer. * <p> * The buffer must be allocated dynamically and stored at the * location pointed to by bufp. If the buffer contains memory * regions, they too must be allocated using malloc(). The * allocated memory will be freed by the caller. * <p> * IMPORTANT: * Is not enabled by default, for enabling use * ru.serce.jnrfuse.AbstractFuseFS#isBufOperationsImplemented() */ int read_buf(String path, Pointer bufp, @size_t long size, @off_t long off, FuseFileInfo fi); /** * Perform BSD file locking operation * <p> * The op argument will be either LOCK_SH, LOCK_EX or LOCK_UN * <p> * Nonblocking requests will be indicated by ORing LOCK_NB to * the above operations * <p> * For more information see the flock(2) manual page. * <p> * Additionally fi->owner will be set to a value unique to * this open file. This same value will be supplied to * ->release() when the file is released. * <p> * Note: if this method is not implemented, the kernel will still * allow file locking to work locally. Hence it is only * interesting for network filesystems and similar. * * @param op see {@link ru.serce.jnrfuse.struct.Flock} */ int flock(String path, FuseFileInfo fi, int op); /** * Allocates space for an open file * <p> * This function ensures that required space is allocated for specified * file. If this function returns success then any subsequent write * request to specified range is guaranteed not to fail because of lack * of space on the file system media. */ int fallocate(String path, int mode, @off_t long off, @off_t long length, FuseFileInfo fi); }