Skip to content

Instantly share code, notes, and snippets.

@bkmeneguello
Created June 28, 2013 12:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save bkmeneguello/5884492 to your computer and use it in GitHub Desktop.
Save bkmeneguello/5884492 to your computer and use it in GitHub Desktop.
FUSE implementation skelekton
/*
FUSE: Filesystem in Userspace
Copyright (C) 2013 Bruno Meneguello
This program can be distributed under the terms of the GNU GPL.
gcc -Wall skelfs.c `pkg-config fuse --cflags --libs` -o skelfs
*/
#define FUSE_USE_VERSION 26
#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
/** Get file attributes.
*
* 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.
*/
static int fs_getattr(const char *path, struct stat *buf) {
return 0;
}
/** Read the target of a symbolic link
*
* 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.
*/
static int fs_readlink(const char *path, char *buf, size_t len) {
return 0;
}
/* Deprecated, use readdir() instead */
//static int fs_getdir(const char *, fuse_dirh_t, fuse_dirfil_t) {
// return 0;
//}
/** Create a file node
*
* 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.
*/
static int fs_mknod(const char *path, mode_t mode, dev_t rdev) {
return 0;
}
/** Create a directory
*
* 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
* */
static int fs_mkdir(const char *path, mode_t mode) {
return 0;
}
/** Remove a file */
static int fs_unlink(const char *path) {
return 0;
}
/** Remove a directory */
static int fs_rmdir(const char *path) {
return 0;
}
/** Create a symbolic link */
static int fs_symlink(const char *linkname, const char *path) {
return 0;
}
/** Rename a file */
static int fs_rename(const char *oldpath, const char *newpath) {
return 0;
}
/** Create a hard link to a file */
static int fs_link(const char *oldpath, const char *newpath) {
return 0;
}
/** Change the permission bits of a file */
static int fs_chmod(const char *path, mode_t mode) {
return 0;
}
/** Change the owner and group of a file */
static int fs_chown(const char *path, uid_t uid, gid_t gid) {
return 0;
}
/** Change the size of a file */
static int fs_truncate(const char *path, off_t size) {
return 0;
}
/** Change the access and/or modification times of a file
*
* Deprecated, use utimens() instead.
*/
//static int fs_utime(const char *, struct utimbuf *) {
// return 0;
//}
/** File open operation
*
* 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.
*
* 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.
*
* Changed in version 2.2
*/
static int fs_open(const char *path, struct fuse_file_info *fi) {
return 0;
}
/** Read data from an open file
*
* 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.
*
* Changed in version 2.2
*/
static int fs_read(const char *path, char *buf, size_t size, off_t off, struct fuse_file_info *fi) {
return 0;
}
/** Write data to an open file
*
* 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).
*
* Changed in version 2.2
*/
static int fs_write(const char *path, const char *buf, size_t size, off_t off, struct fuse_file_info *fi) {
return 0;
}
/** Get file system statistics
*
* The 'f_frsize', 'f_favail', 'f_fsid' and 'f_flag' fields are ignored
*
* Replaced 'struct statfs' parameter with 'struct statvfs' in
* version 2.5
*/
static int fs_statfs(const char *path, struct statvfs *buf) {
return 0;
}
/** Possibly flush cached data
*
* BIG NOTE: This is not equivalent to fsync(). It's not a
* request to sync dirty data.
*
* 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.
*
* 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.
*
* Filesystems shouldn't assume that flush will always be called
* after some writes, or that if will be called at all.
*
* Changed in version 2.2
*/
static int fs_flush(const char *path, struct fuse_file_info *fi) {
return 0;
}
/** 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
* 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.
*
* Changed in version 2.2
*/
static int fs_release(const char *path, struct fuse_file_info *fi) {
return 0;
}
/** Synchronize file contents
*
* If the datasync parameter is non-zero, then only the user data
* should be flushed, not the meta data.
*
* Changed in version 2.2
*/
static int fs_fsync(const char *path, int datasync, struct fuse_file_info *fi) {
return 0;
}
/** Set extended attributes */
static int fs_setxattr(const char *path, const char *name, const char *value, size_t size, int flags) {
return 0;
}
/** Get extended attributes */
static int fs_getxattr(const char *path, const char *name, char *value, size_t size) {
return 0;
}
/** List extended attributes */
static int fs_listxattr(const char *path, char *list, size_t size) {
return 0;
}
/** Remove extended attributes */
static int fs_removexattr(const char *path, const char *name) {
return 0;
}
/** Open directory
*
* 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.
*
* Introduced in version 2.3
*/
static int fs_opendir(const char *path, struct fuse_file_info *fi) {
return 0;
}
/** Read directory
*
* This supersedes the old getdir() interface. New applications
* should use this.
*
* The filesystem may choose between two modes of operation:
*
* 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.
*
* 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'.
*
* Introduced in version 2.3
*/
static int fs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t off, struct fuse_file_info *fi) {
return 0;
}
/** Release directory
*
* Introduced in version 2.3
*/
static int fs_releasedir(const char *path, struct fuse_file_info *fi) {
return 0;
}
/** Synchronize directory contents
*
* If the datasync parameter is non-zero, then only the user data
* should be flushed, not the meta data
*
* Introduced in version 2.3
*/
static int fs_fsyncdir(const char *path, int datasync, struct fuse_file_info *fi) {
return 0;
}
/**
* Initialize filesystem
*
* 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.
*
* Introduced in version 2.3
* Changed in version 2.6
*/
static void *fs_init(struct fuse_conn_info *conn) {
return 0;
}
/**
* Clean up filesystem
*
* Called on filesystem exit.
*
* Introduced in version 2.3
*/
static void fs_destroy(void *data) {
}
/**
* Check file access permissions
*
* This will be called for the access() system call. If the
* 'default_permissions' mount option is given, this method is not
* called.
*
* This method is not called under Linux kernel versions 2.4.x
*
* Introduced in version 2.5
*/
static int fs_access(const char *path, int mask) {
return 0;
}
/**
* Create and open a file
*
* If the file does not exist, first create it with the specified
* mode, and then open it.
*
* 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.
*
* Introduced in version 2.5
*/
static int fs_create(const char *path, mode_t mode, struct fuse_file_info *fi) {
return 0;
}
/**
* Change the size of an open file
*
* This method is called instead of the truncate() method if the
* truncation was invoked from an ftruncate() system call.
*
* If this method is not implemented or under Linux kernel
* versions earlier than 2.6.15, the truncate() method will be
* called instead.
*
* Introduced in version 2.5
*/
static int fs_ftruncate(const char *path, off_t size, struct fuse_file_info *fi) {
return 0;
}
/**
* Get attributes from an open file
*
* This method is called instead of the getattr() method if the
* file information is available.
*
* 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.
*
* Introduced in version 2.5
*/
static int fs_fgetattr(const char *path, struct stat *buf, struct fuse_file_info *fi) {
return 0;
}
/**
* Perform POSIX file locking operation
*
* The cmd argument will be either F_GETLK, F_SETLK or F_SETLKW.
*
* 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.
*
* For checking lock ownership, the 'fuse_file_info->owner'
* argument must be used.
*
* 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 unlikly 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.
*
* For F_SETLK and F_SETLKW the l_pid field will be set to the pid
* of the process performing the locking operation.
*
* 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.
*
* Introduced in version 2.6
*/
static int fs_lock(const char *path, struct fuse_file_info *fi, int cmd, struct flock *lock) {
return 0;
}
/**
* Change the access and modification times of a file with
* nanosecond resolution
*
* Introduced in version 2.6
*/
static int fs_utimens(const char *path, const struct timespec tv[2]) {
return 0;
}
/**
* Map block index within file to block index within device
*
* Note: This makes sense only for block device backed filesystems
* mounted with the 'blkdev' option
*
* Introduced in version 2.6
*/
static int fs_bmap(const char *path, size_t blocksize, uint64_t *idx) {
return 0;
}
/**
* Ioctl
*
* 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.
*
* Introduced in version 2.8
*/
static int fs_ioctl(const char *path, int cmd, void *arg, struct fuse_file_info *fi, unsigned int flags, void *data) {
return 0;
}
/**
* Poll for IO readiness events
*
* Note: If ph is non-NULL, the client should notify
* when IO readiness events occur by calling
* fuse_notify_poll() with the specified ph.
*
* 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.
*
* The callee is responsible for destroying ph with
* fuse_pollhandle_destroy() when no longer in use.
*
* Introduced in version 2.8
*/
static int fs_poll(const char *path, struct fuse_file_info *fi, struct fuse_pollhandle *ph, unsigned *reventsp) {
return 0;
}
static struct fuse_operations fs_oper = {
.getattr = fs_getattr,
.readlink = fs_readlink,
.mknod = fs_mknod,
.mkdir = fs_mkdir,
.unlink = fs_unlink,
.rmdir = fs_rmdir,
.symlink = fs_symlink,
.rename = fs_rename,
.link = fs_link,
.chmod = fs_chmod,
.chown = fs_chown,
.truncate = fs_truncate,
.open = fs_open,
.read = fs_read,
.write = fs_write,
.statfs = fs_statfs,
.flush = fs_flush,
.release = fs_release,
.fsync = fs_fsync,
.setxattr = fs_setxattr,
.getxattr = fs_getxattr,
.listxattr = fs_listxattr,
.removexattr = fs_removexattr,
.opendir = fs_opendir,
.readdir = fs_readdir,
.releasedir = fs_releasedir,
.fsyncdir = fs_fsyncdir,
.init = fs_init,
.destroy = fs_destroy,
.access = fs_access,
.create = fs_create,
.ftruncate = fs_ftruncate,
.fgetattr = fs_fgetattr,
.lock = fs_lock,
.utimens = fs_utimens,
.bmap = fs_bmap,
.ioctl = fs_ioctl,
.poll = fs_poll,
};
int main(int argc, char *argv[]) {
return fuse_main(argc, argv, &fs_oper, NULL);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment