// Copyright (c) 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef LIBRARIES_NACL_IO_FUSE_H_ #define LIBRARIES_NACL_IO_FUSE_H_ #include "osinttypes.h" #include "ostypes.h" // These interfaces are copied from the FUSE library. // // FUSE has two interfaces that can be implemented: low-level and high-level. // In nacl_io, we only support the high-level interface. // // See http://fuse.sourceforge.net/ for more information. // This struct is typically passed to functions that would normally use return // or receive an fd; that is, operations to open/create a node, or operations // that act on an already opened node. struct fuse_file_info { // This is filled with the flags passed to open() int flags; // Deprecated in FUSE. Use fh instead. unsigned long fh_old; int writepage; // Currently unsupported unsigned int direct_io : 1; // Currently unsupported unsigned int keep_cache : 1; // Currently unsupported unsigned int flush : 1; // Currently unsupported unsigned int nonseekable : 1; // Currently unsupported unsigned int padding : 27; // This value is not used by nacl_io. It can be filled by the developer when // open() is called, and reused for subsequent calls on the same node. uint64_t fh; // Currently unsupported uint64_t lock_owner; // Currently unsupported uint32_t poll_events; }; // A dummy structure that currently exists only to match the FUSE interface. struct fuse_conn_info {}; // A function of this type will be passed to readdir (see below). The developer // should call this function once for each directory entry. // // See the documentation for readdir() below for more information on how to use // this function. typedef int (*fuse_fill_dir_t)(void* buf, const char* name, const struct stat* stbuf, off_t off); // This structure defines the interface to create a user filesystem. Pass this // to // nacl_io_register_fs_type(). (see nacl_io.h) // // Example: // // struct fuse_operations g_my_fuse_operations = { ... }; // ... // nacl_io_register_fs_type("myfusefs", &g_my_fuse_operations); // ... // mount("", "/fs/fuse", "myfusefs", 0, NULL); // // It is not necessary to implement every function -- nacl_io will first check // if the function pointer is NULL before calling it. If it is NULL and // required by the current operation, the call will fail and return ENOSYS in // errno. // // Except where specified below, each function should return one of the // following values: // == 0: operation completed successfully. // < 0: operation failed. The error is a negative errno. e.g. -EACCES, -EPERM, // etc. The sign will be flipped when the error is actually set. // // Some functions (e.g. read, write) also return a positive count, which is the // number of bytes read/written. // struct fuse_operations { // Currently unsupported unsigned int flag_nopath : 1; unsigned int flag_reserved : 31; // Called when a filesystem of this type is initialized. void* (*init)(struct fuse_conn_info* conn); // Called when a filesystem of this type is unmounted. void (*destroy)(void*); // Called by access() int (*access)(const char* path, int mode); // Called when O_CREAT is passed to open() int (*create)(const char* path, mode_t mode, struct fuse_file_info*); // Called by stat()/fstat(). If this function pointer is non-NULL, it is // called, otherwise fuse_operations.getattr will be called. int (*fgetattr)(const char* path, struct stat*, struct fuse_file_info*); // Called by fsync(). The datasync paramater is not currently supported. int (*fsync)(const char* path, int datasync, struct fuse_file_info*); // Called by ftruncate() int (*ftruncate)(const char* path, off_t, struct fuse_file_info*); // Called by stat()/fstat(), but only when fuse_operations.fgetattr is NULL. // Also called by open() to determine if the path is a directory or a regular // file. int (*getattr)(const char* path, struct stat*); // Called by mkdir() int (*mkdir)(const char* path, mode_t); // Called when O_CREAT is passed to open(), but only if fuse_operations.create // is non-NULL. int (*mknod)(const char* path, mode_t, dev_t); // Called by open() int (*open)(const char* path, struct fuse_file_info*); // Called by getdents(), which is called by the more standard functions // opendir()/readdir(). int (*opendir)(const char* path, struct fuse_file_info*); // Called by read(). Note that FUSE specifies that all reads will fill the // entire requested buffer. If this function returns less than that, the // remainder of the buffer is zeroed. int (*read)(const char* path, char* buf, size_t count, off_t, struct fuse_file_info*); // Called by getdents(), which is called by the more standard function // readdir(). // // NOTE: it is the responsibility of this function to add the "." and ".." // entries. // // This function can be implemented one of two ways: // 1) Ignore the offset, and always write every entry in a given directory. // In this case, you should always call filler() with an offset of 0. You // can ignore the return value of the filler. // // int my_readdir(const char* path, void* buf, fuse_fill_dir_t filler, // off_t offset, struct fuse_file_info*) { // ... // filler(buf, ".", NULL, 0); // filler(buf, "..", NULL, 0); // filler(buf, "file1", &file1stat, 0); // filler(buf, "file2", &file2stat, 0); // return 0; // } // // 2) Only write entries starting from offset. Always pass the correct offset // to the filler function. When the filler function returns 1, the buffer // is full so you can exit readdir. // // int my_readdir(const char* path, void* buf, fuse_fill_dir_t filler, // off_t offset, struct fuse_file_info*) { // ... // size_t kNumEntries = 4; // const char* my_entries[] = { ".", "..", "file1", "file2" }; // int entry_index = offset / sizeof(dirent); // offset = entry_index * sizeof(dirent); // while (entry_index < kNumEntries) { // int result = filler(buf, my_entries[entry_index], NULL, offset); // if (filler == 1) { // // buffer filled, we're done. // return 0; // } // offset += sizeof(dirent); // entry_index++; // } // // // No more entries, we're done. // return 0; // } // int (*readdir)(const char* path, void* buf, fuse_fill_dir_t filldir, off_t, struct fuse_file_info*); // Called when the last reference to this node is released. This is only // called for regular files. For directories, fuse_operations.releasedir is // called instead. int (*release)(const char* path, struct fuse_file_info*); // Called when the last reference to this node is released. This is only // called for directories. For regular files, fuse_operations.release is // called instead. int (*releasedir)(const char* path, struct fuse_file_info*); // Called by rename() int (*rename)(const char* path, const char* new_path); // Called by rmdir() int (*rmdir)(const char* path); // Called by truncate(), as well as open() when O_TRUNC is passed. int (*truncate)(const char* path, off_t); // Called by unlink() int (*unlink)(const char* path); // Called by write(). Note that FUSE specifies that a write should always // return the full count, unless an error occurs. int (*write)(const char* path, const char* buf, size_t count, off_t, struct fuse_file_info*); // The following functions are not currently called by the nacl_io // implementation of FUSE. int (*bmap)(const char*, size_t blocksize, uint64_t* idx); int (*chmod)(const char*, mode_t); int (*chown)(const char*, uid_t, gid_t); int (*fallocate)(const char*, int, off_t, off_t, struct fuse_file_info*); int (*flock)(const char*, struct fuse_file_info*, int op); int (*flush)(const char*, struct fuse_file_info*); int (*fsyncdir)(const char*, int, struct fuse_file_info*); int (*getxattr)(const char*, const char*, char*, size_t); int (*ioctl)(const char*, int cmd, void* arg, struct fuse_file_info*, unsigned int flags, void* data); int (*link)(const char*, const char*); int (*listxattr)(const char*, char*, size_t); int (*lock)(const char*, struct fuse_file_info*, int cmd, struct flock*); int (*poll)(const char*, struct fuse_file_info*, struct fuse_pollhandle* ph, unsigned* reventsp); int (*read_buf)(const char*, struct fuse_bufvec** bufp, size_t size, off_t off, struct fuse_file_info*); int (*readlink)(const char*, char*, size_t); int (*removexattr)(const char*, const char*); int (*setxattr)(const char*, const char*, const char*, size_t, int); int (*statfs)(const char*, struct statvfs*); int (*symlink)(const char*, const char*); int (*utimens)(const char*, const struct timespec tv[2]); int (*write_buf)(const char*, struct fuse_bufvec* buf, off_t off, struct fuse_file_info*); }; #endif // LIBRARIES_NACL_IO_FUSE_H_