#define FUSE_SET_ATTR_MTIME (1 << 5)
#define FUSE_SET_ATTR_CTIME (1 << 6)
-/* ------------------------------------------ */
-
+/** Low level filesystem operations */
struct fuse_lowlevel_ops {
+ /** Initialize filesystem
+ *
+ * Called before any other filesystem method
+ *
+ * 'userdata' from fuse_lowlevel_new() is passed to this function
+ *
+ * There's no reply to this function
+ */
void (*init) (void *);
+
+ /** Clean up filesystem
+ *
+ * Called on filesystem exit
+ *
+ * 'userdata' from fuse_lowlevel_new() is passed to this function
+ *
+ * There's no reply to this function
+ */
void (*destroy)(void *);
+ /** Look up a directory entry by name
+ *
+ * Valid replies:
+ * fuse_reply_entry()
+ * fuse_reply_err()
+ */
void (*lookup) (fuse_req_t req, fuse_ino_t parent, const char *name);
+
+ /**
+ * Forget about an inode
+ *
+ * The nlookup parameter indicates the number of lookups
+ * previously performed on this inode.
+ *
+ * If the filesystem implements inode lifetimes, it is recommended
+ * that inodes acquire a single reference on each lookup, and lose
+ * nlookup references on each forget.
+ *
+ * The filesystem may ignore forget calls, if the inodes don't
+ * need to have a limited lifetime.
+ *
+ * On unmount it is not guaranteed, that all referenced inodes
+ * will receive a forget message.
+ *
+ * Valid replies:
+ * fuse_reply_none()
+ */
void (*forget) (fuse_req_t req, fuse_ino_t ino, unsigned long nlookup);
+
+ /** Get file attributes
+ *
+ * Valid replies:
+ * fuse_reply_attr()
+ * fuse_reply_err()
+ */
void (*getattr)(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi);
+
+ /** Set file attributes
+ *
+ * Valid replies:
+ * fuse_reply_attr()
+ * fuse_reply_err()
+ */
void (*setattr)(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
int to_set, struct fuse_file_info *fi);
+
+ /** Read symbolic link
+ *
+ * Valid replies:
+ * fuse_reply_readlink
+ * fuse_reply_err
+ */
void (*readlink)(fuse_req_t req, fuse_ino_t ino);
+
+ /** Create file node
+ *
+ * Create a regular file, character device, block device, fifo or
+ * socket node.
+ *
+ * Valid replies:
+ * fuse_reply_entry
+ * fuse_reply_err
+ */
void (*mknod) (fuse_req_t req, fuse_ino_t parent, const char *name,
mode_t mode, dev_t rdev);
+
+ /** Create a directory
+ *
+ * Valid replies:
+ * fuse_reply_entry
+ * fuse_reply_err
+ */
void (*mkdir) (fuse_req_t req, fuse_ino_t parent, const char *name,
mode_t mode);
+
+ /** Remove a file
+ *
+ * Valid replies:
+ * fuse_reply_err
+ */
void (*unlink) (fuse_req_t req, fuse_ino_t parent, const char *name);
+
+ /** Remove a directory
+ *
+ * Valid replies:
+ * fuse_reply_err
+ */
void (*rmdir) (fuse_req_t req, fuse_ino_t parent, const char *name);
+
+ /** Create a symbolic link
+ *
+ * Valid replies:
+ * fuse_reply_entry
+ * fuse_reply_err
+ */
void (*symlink)(fuse_req_t req, const char *link, fuse_ino_t parent,
const char *name);
+
+ /** Rename a file
+ *
+ * Valid replies:
+ * fuse_reply_err
+ */
void (*rename) (fuse_req_t req, fuse_ino_t parent, const char *name,
fuse_ino_t newparent, const char *newname);
+
+ /** Create a hard link
+ *
+ * Valid replies:
+ * fuse_reply_entry
+ * fuse_reply_err
+ */
void (*link) (fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,
const char *newname);
+
+ /** Open a file
+ *
+ * Open flags (with the exception of O_CREAT, O_EXCL, O_NOCTTY and
+ * O_TRUNC) are available in fi->flags.
+ *
+ * Filesystem may store an arbitrary file handle (pointer, index,
+ * etc) in fi->fh, and use this in other all other file operations
+ * (read, write, flush, release, fsync).
+ *
+ * Filesystem may also implement stateless file I/O and not store
+ * anything in fi->fh.
+ *
+ * There are also some flags (direct_io, keep_cache) which the
+ * filesystem may set in fi, to change the way the file is opened.
+ * See fuse_file_info structure in <fuse_common.h> for more details.
+ *
+ * Valid replies:
+ * fuse_reply_open
+ * fuse_reply_err
+ */
void (*open) (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi);
+
+ /** Read data
+ *
+ * Read should send 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 file
+ * has been opened in 'direct_io' mode, in which case the return
+ * value of the read system call will reflect the return value of
+ * this operation.
+ *
+ * fi->fh will contain the value set by the open method, or will
+ * be undefined if the open method didn't set any value.
+ *
+ * Valid replies:
+ * fuse_reply_buf
+ * fuse_reply_err
+ */
void (*read) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
struct fuse_file_info *fi);
+
+ /** Write data
+ *
+ * Write should return exactly the number of bytes requested
+ * except on error. An exception to this is when the file has
+ * been opened in 'direct_io' mode, in which case the return value
+ * of the write system call will reflect the return value of this
+ * operation.
+ *
+ * fi->fh will contain the value set by the open method, or will
+ * be undefined if the open method didn't set any value.
+ *
+ * Valid replies:
+ * fuse_reply_write
+ * fuse_reply_err
+ */
void (*write) (fuse_req_t req, fuse_ino_t ino, const char *buf,
size_t size, off_t off, struct fuse_file_info *fi);
+
+ /** Flush method
+ *
+ * This is called on each close() of the opened file.
+ *
+ * Since file descriptors can be duplicated (dup, dup2, fork), for
+ * one open call there may be many flush calls.
+ *
+ * fi->fh will contain the value set by the open method, or will
+ * be undefined if the open method didn't set any value.
+ *
+ * NOTE: the name of the method is misleading, since (unlike
+ * fsync) the filesystem is not forced to flush pending writes.
+ * One reason to flush data, is if the filesystem wants to return
+ * write errors.
+ *
+ * Valid replies:
+ * fuse_reply_err
+ */
void (*flush) (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi);
+
+ /** Release an open file
+ *
+ * Release is called when there are no more references to an open
+ * file: all file descriptors are closed and all memory mappings
+ * are unmapped.
+ *
+ * For every open call there will be exactly one release call.
+ *
+ * The filesystem may reply with an error, but error values are
+ * not returned to close() or munmap() which triggered the
+ * release.
+ *
+ * fi->fh will contain the value set by the open method, or will
+ * be undefined if the open method didn't set any value.
+ * fi->flags will contain the same flags as for open.
+ *
+ * Valid replies:
+ * fuse_reply_err
+ */
void (*release)(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi);
+
+ /** Synchronize file contents
+ *
+ * If the datasync parameter is non-zero, then only the user data
+ * should be flushed, not the meta data.
+ *
+ * Valid replies:
+ * fuse_reply_err
+ */
void (*fsync) (fuse_req_t req, fuse_ino_t ino, int datasync,
struct fuse_file_info *fi);
+
+ /** Open a directory
+ *
+ * Filesystem may store an arbitrary file handle (pointer, index,
+ * etc) in fi->fh, and use this in other all other directory
+ * stream operations (readdir, releasedir, fsyncdir).
+ *
+ * Filesystem may also implement stateless directory I/O and not
+ * store anything in fi->fh, though that makes it impossible to
+ * implement standard conforming directory stream operations in
+ * case the contents of the directory can change between opendir
+ * and releasedir.
+ *
+ * Valid replies:
+ * fuse_reply_open
+ * fuse_reply_err
+ */
void (*opendir)(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi);
+
+ /** Read directory
+ *
+ * Send a buffer filled using fuse_add_dirent(), with size not
+ * exceeding the requested size. Send an empty buffer on end of
+ * stream.
+ *
+ * fi->fh will contain the value set by the opendir method, or
+ * will be undefined if the opendir method didn't set any value.
+ *
+ * Valid replies:
+ * fuse_reply_buf
+ * fuse_reply_err
+ */
void (*readdir)(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
struct fuse_file_info *fi);
+
+ /** Release an open directory
+ *
+ * For every opendir call there will be exactly one releasedir
+ * call.
+ *
+ * Any errors sent by releasedir will be ignored.
+ *
+ * fi->fh will contain the value set by the opendir method, or
+ * will be undefined if the opendir method didn't set any value.
+ *
+ * Valid replies:
+ * fuse_reply_err
+ */
void (*releasedir)(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi);
+
+ /** Synchronize directory contents
+ *
+ * If the datasync parameter is non-zero, then only the directory
+ * contents should be flushed, not the meta data.
+ *
+ * fi->fh will contain the value set by the opendir method, or
+ * will be undefined if the opendir method didn't set any value.
+ *
+ * Valid replies:
+ * fuse_reply_err
+ */
void (*fsyncdir)(fuse_req_t req, fuse_ino_t ino, int datasync,
struct fuse_file_info *fi);
+
+ /** Get file system statistics
+ *
+ * Valid replies:
+ * fuse_reply_statfs
+ * fuse_reply_err
+ */
void (*statfs) (fuse_req_t req);
+
+ /** Set an extended attribute
+ *
+ * Valid replies:
+ * fuse_reply_err
+ */
void (*setxattr)(fuse_req_t req, fuse_ino_t ino, const char *name,
const char *value, size_t size, int flags);
+
+ /** Get an extended attribute
+ *
+ * If size is zero, the size of the value should be sent with
+ * fuse_reply_xattr.
+ *
+ * If the size is non-zero, and the value fits in the buffer, the
+ * value should be sent with fuse_reply_buf.
+ *
+ * If the size is too small for the value, the ERANGE error should
+ * be sent.
+ *
+ * Valid replies:
+ * fuse_reply_buf
+ * fuse_reply_xattr
+ * fuse_reply_err
+ */
void (*getxattr)(fuse_req_t req, fuse_ino_t ino, const char *name,
size_t size);
+
+ /** List extended attribute names
+ *
+ * If size is zero, the total size of the attribute list should be
+ * sent with fuse_reply_xattr.
+ *
+ * If the size is non-zero, and the null charater separated
+ * attribute list fits in the buffer, the list should be sent with
+ * fuse_reply_buf.
+ *
+ * If the size is too small for the list, the ERANGE error should
+ * be sent.
+ *
+ * Valid replies:
+ * fuse_reply_buf
+ * fuse_reply_xattr
+ * fuse_reply_err
+ */
void (*listxattr)(fuse_req_t req, fuse_ino_t ino, size_t size);
+
+ /** Remove an extended attribute
+ *
+ * Valid replies:
+ * fuse_reply_err
+ */
void (*removexattr)(fuse_req_t req, fuse_ino_t ino, const char *name);
};
-/* ------------------------------------------ */
-/* all except forget */
+/** Reply with an error code or success (zero)
+ *
+ * all except forget may send an error
+ *
+ * unlink, rmdir, rename, flush, release, fsync, fsyncdir, setxattr
+ * and removexattr may send a succes code
+*/
int fuse_reply_err(fuse_req_t req, int err);
/* forget */
void (*exit) (void *data, int val);
int (*exited) (void *data);
-
+
void (*destroy) (void *data);
};