From bb7ad3f6d9896e669f2fd790f32dc329dc9f2031 Mon Sep 17 00:00:00 2001 From: Antonio SJ Musumeci Date: Mon, 15 Apr 2024 19:12:08 -0500 Subject: [PATCH] fuse.cpp --- libfuse/include/fuse_lowlevel.h | 929 ++----------------------------- libfuse/lib/crc32b.h | 9 + libfuse/lib/fmp.h | 2 +- libfuse/lib/{fuse.c => fuse.cpp} | 185 +++--- libfuse/lib/node.h | 12 + 5 files changed, 157 insertions(+), 980 deletions(-) rename libfuse/lib/{fuse.c => fuse.cpp} (95%) diff --git a/libfuse/include/fuse_lowlevel.h b/libfuse/include/fuse_lowlevel.h index 3b9d8c14..f9e09122 100644 --- a/libfuse/include/fuse_lowlevel.h +++ b/libfuse/include/fuse_lowlevel.h @@ -131,891 +131,52 @@ struct fuse_ctx */ struct fuse_lowlevel_ops { - /** - * Initialize filesystem - * - * Called before any other filesystem method - * - * There's no reply to this function - * - * @param userdata the user data passed to fuse_lowlevel_new() - */ - void (*init)(void *userdata, struct fuse_conn_info *conn); - - /** - * Clean up filesystem - * - * Called on filesystem exit - * - * There's no reply to this function - * - * @param userdata the user data passed to fuse_lowlevel_new() - */ + void (*access)(fuse_req_t req, struct fuse_in_header *hdr); + void (*bmap)(fuse_req_t req, const struct fuse_in_header *hdr); + void (*copy_file_range)(fuse_req_t req, const struct fuse_in_header *hdr); + void (*create)(fuse_req_t req, struct fuse_in_header *hdr); void (*destroy)(void *userdata); - - /** - * Look up a directory entry by name and get its attributes. - * - * Valid replies: - * fuse_reply_entry - * fuse_reply_err - * - * @param req request handle - * @param parent inode number of the parent directory - * @param name the name to look up - */ - void (*lookup)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * Forget about an inode - * - * This function is called when the kernel removes an inode - * from its internal caches. - * - * The inode's lookup count increases by one for every call to - * fuse_reply_entry and fuse_reply_create. The nlookup parameter - * indicates by how much the lookup count should be decreased. - * - * Inodes with a non-zero lookup count may receive request from - * the kernel even after calls to unlink, rmdir or (when - * overwriting an existing file) rename. Filesystems must handle - * such requests properly and it is recommended to defer removal - * of the inode until the lookup count reaches zero. Calls to - * unlink, remdir or rename will be followed closely by forget - * unless the file or directory is open, in which case the - * kernel issues forget only after the release or releasedir - * calls. - * - * Note that if a file system will be exported over NFS the - * inodes lifetime must extend even beyond forget. See the - * generation field in struct fuse_entry_param above. - * - * On unmount the lookup count for all inodes implicitly drops - * to zero. It is not guaranteed that the file system will - * receive corresponding forget messages for the affected - * inodes. - * - * Valid replies: - * fuse_reply_none - * - * @param req request handle - * @param ino the inode number - * @param nlookup the number of lookups to forget - */ - void (*forget)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * Get file attributes - * - * Valid replies: - * fuse_reply_attr - * fuse_reply_err - */ - void (*getattr)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * Set file attributes - * - * In the 'attr' argument only members indicated by the 'to_set' - * bitmask contain valid values. Other members contain undefined - * values. - * - * If the setattr was invoked from the ftruncate() system call - * under Linux kernel versions 2.6.15 or later, the fi->fh will - * contain the value set by the open method or will be undefined - * if the open method didn't set any value. Otherwise (not - * ftruncate call, or kernel version earlier than 2.6.15) the fi - * parameter will be NULL. - * - * Valid replies: - * fuse_reply_attr - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param attr the attributes - * @param to_set bit mask of attributes which should be set - * @param fi file information, or NULL - * - * Changed in version 2.5: - * file information filled in for ftruncate - */ - void (*setattr)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * Read symbolic link - * - * Valid replies: - * fuse_reply_readlink - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - */ - void (*readlink)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * Create file node - * - * Create a regular file, character device, block device, fifo or - * socket node. - * - * Valid replies: - * fuse_reply_entry - * fuse_reply_err - * - * @param req request handle - * @param parent inode number of the parent directory - * @param name to create - * @param mode file type and mode with which to create the new file - * @param rdev the device number (only valid if created file is a device) - */ - void (*mknod)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * Create a directory - * - * Valid replies: - * fuse_reply_entry - * fuse_reply_err - * - * @param req request handle - * @param parent inode number of the parent directory - * @param name to create - * @param mode with which to create the new file - */ - void (*mkdir)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * Remove a file - * - * If the file's inode's lookup count is non-zero, the file - * system is expected to postpone any removal of the inode - * until the lookup count reaches zero (see description of the - * forget function). - * - * Valid replies: - * fuse_reply_err - * - * @param req request handle - * @param parent inode number of the parent directory - * @param name to remove - */ - void (*unlink)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * Remove a directory - * - * If the directory's inode's lookup count is non-zero, the - * file system is expected to postpone any removal of the - * inode until the lookup count reaches zero (see description - * of the forget function). - * - * Valid replies: - * fuse_reply_err - * - * @param req request handle - * @param parent inode number of the parent directory - * @param name to remove - */ - void (*rmdir)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * Create a symbolic link - * - * Valid replies: - * fuse_reply_entry - * fuse_reply_err - * - * @param req request handle - * @param link the contents of the symbolic link - * @param parent inode number of the parent directory - * @param name to create - */ - void (*symlink)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** Rename a file - * - * If the target exists it should be atomically replaced. If - * the target's inode's lookup count is non-zero, the file - * system is expected to postpone any removal of the inode - * until the lookup count reaches zero (see description of the - * forget function). - * - * Valid replies: - * fuse_reply_err - * - * @param req request handle - * @param parent inode number of the old parent directory - * @param name old name - * @param newparent inode number of the new parent directory - * @param newname new name - */ - void (*rename)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * Create a hard link - * - * Valid replies: - * fuse_reply_entry - * fuse_reply_err - * - * @param req request handle - * @param ino the old inode number - * @param newparent inode number of the new parent directory - * @param newname new name to create - */ - void (*link)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * 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 for more details. - * - * Valid replies: - * fuse_reply_open - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param fi file information - */ - void (*open)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * 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_iov - * fuse_reply_data - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param size number of bytes to read - * @param off offset to read from - * @param fi file information - */ - void (*read)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * 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 - * - * @param req request handle - * @param ino the inode number - * @param buf data to write - * @param size number of bytes to write - * @param off offset to write to - * @param fi file information - */ - void (*write)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * 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. - * - * Filesystems shouldn't assume that flush will always be called - * after some writes, or that if will be called at all. - * - * 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. - * - * If the filesystem supports file locking operations (setlk, - * getlk) it should remove all locks belonging to 'fi->owner'. - * - * Valid replies: - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param fi file information - */ - void (*flush)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * 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 - * - * @param req request handle - * @param ino the inode number - * @param fi file information - */ - void (*release)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * 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 - * - * @param req request handle - * @param ino the inode number - * @param datasync flag indicating if only data should be flushed - * @param fi file information - */ - void (*fsync)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * 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 - * - * @param req request handle - * @param ino the inode number - * @param fi file information - */ - void (*opendir)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * Read directory - * - * Send a buffer filled using fuse_add_direntry(), 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_data - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param size maximum number of bytes to send - * @param off offset to continue reading the directory stream - * @param fi file information - */ - void (*readdir)(fuse_req_t req, - struct fuse_in_header *hdr); - - void (*readdir_plus)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * Release an open directory - * - * For every opendir call there will be exactly one releasedir - * call. - * - * 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 - * - * @param req request handle - * @param ino the inode number - * @param fi file information - */ - void (*releasedir)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * 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 - * - * @param req request handle - * @param ino the inode number - * @param datasync flag indicating if only data should be flushed - * @param fi file information - */ - void (*fsyncdir)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * Get file system statistics - * - * Valid replies: - * fuse_reply_statfs - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number, zero means "undefined" - */ - void (*statfs)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * Set an extended attribute - * - * Valid replies: - * fuse_reply_err - */ - void (*setxattr)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * 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_data - * fuse_reply_xattr - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param name of the extended attribute - * @param size maximum size of the value to send - */ - void (*getxattr)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * 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 character 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_data - * fuse_reply_xattr - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param size maximum size of the list to send - */ - void (*listxattr)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * Remove an extended attribute - * - * Valid replies: - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param name of the extended attribute - */ - void (*removexattr)(fuse_req_t req, - const struct fuse_in_header *hdr); - - /** - * 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 - * - * Valid replies: - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param mask requested access mode - */ - void (*access)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * Create and open a file - * - * If the file does not exist, first create it with the specified - * mode, and then open it. - * - * Open flags (with the exception of O_NOCTTY) 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). - * - * 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 for more details. - * - * 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 - * - * Valid replies: - * fuse_reply_create - * fuse_reply_err - * - * @param req request handle - * @param parent inode number of the parent directory - * @param name to create - * @param mode file type and mode with which to create the new file - * @param fi file information - */ - void (*create)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * Test for a POSIX file lock - * - * Introduced in version 2.6 - * - * Valid replies: - * fuse_reply_lock - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param fi file information - * @param lock the region/type to test - */ - void (*getlk)(fuse_req_t req, - const struct fuse_in_header *hdr); - /** - * Acquire, modify or release a POSIX file lock - * - * For POSIX threads (NPTL) there's a 1-1 relation between pid and - * owner, but otherwise this is not always the case. For checking - * lock ownership, 'fi->owner' must be used. The l_pid field in - * 'struct flock' should only be used to fill in this field in - * getlk(). - * - * Note: if the locking methods are not implemented, the kernel - * will still allow file locking to work locally. Hence these are - * only interesting for network filesystems and similar. - * - * Introduced in version 2.6 - * - * Valid replies: - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param fi file information - * @param lock the region/type to set - * @param sleep locking operation may sleep - */ - void (*setlk)(fuse_req_t req, uint64_t ino, - fuse_file_info_t *fi, - struct flock *lock, int sleep); - - /** - * 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 - * - * Valid replies: - * fuse_reply_bmap - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param blocksize unit of block index - * @param idx block index within file - */ - void (*bmap)(fuse_req_t req, - const struct fuse_in_header *hdr); - - /** - * Ioctl - * - * Note: For unrestricted ioctls (not allowed for FUSE - * servers), data in and out areas can be discovered by giving - * iovs and setting FUSE_IOCTL_RETRY in @flags. For - * restricted ioctls, kernel prepares in/out data area - * according to the information encoded in cmd. - * - * Introduced in version 2.8 - * - * Valid replies: - * fuse_reply_ioctl_retry - * fuse_reply_ioctl - * fuse_reply_ioctl_iov - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param cmd ioctl command - * @param arg ioctl argument - * @param fi file information - * @param flags for FUSE_IOCTL_* flags - * @param in_buf data fetched from the caller - * @param in_bufsz number of fetched bytes - * @param out_bufsz maximum size of output data - */ - void (*ioctl)(fuse_req_t req, - const struct fuse_in_header *hdr); - - /** - * Poll for IO readiness - * - * Introduced in version 2.8 - * - * Note: If ph is non-NULL, the client should notify - * when IO readiness events occur by calling - * fuse_lowelevel_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. - * - * Valid replies: - * fuse_reply_poll - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param fi file information - * @param ph poll handle to be used for notification - */ - void (*poll)(fuse_req_t req, - const struct fuse_in_header *hdr); - - /** - * Callback function for the retrieve request - * - * Introduced in version 2.9 - * - * Valid replies: - * fuse_reply_none - * - * @param req request handle - * @param cookie user data supplied to fuse_lowlevel_notify_retrieve() - * @param ino the inode number supplied to fuse_lowlevel_notify_retrieve() - * @param offset the offset supplied to fuse_lowlevel_notify_retrieve() - * @param bufv the buffer containing the returned data - */ - void (*retrieve_reply)(fuse_req_t req, - void *cookie, - uint64_t ino, - off_t offset); - - /** - * Forget about multiple inodes - * - * See description of the forget function for more - * information. - * - * Introduced in version 2.9 - * - * Valid replies: - * fuse_reply_none - * - * @param req request handle - */ - void (*forget_multi)(fuse_req_t req, - struct fuse_in_header *hdr); - - /** - * Acquire, modify or release a BSD file lock - * - * Note: if the locking methods are not implemented, the kernel - * will still allow file locking to work locally. Hence these are - * only interesting for network filesystems and similar. - * - * Introduced in version 2.9 - * - * Valid replies: - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param fi file information - * @param op the locking operation, see flock(2) - */ - void (*flock)(fuse_req_t req, uint64_t ino, - fuse_file_info_t *fi, int op); - - /** - * Allocate requested space. If this function returns success then - * subsequent writes to the specified range shall not fail due to the lack - * of free space on the file system storage media. - * - * Introduced in version 2.9 - * - * Valid replies: - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param offset starting point for allocated region - * @param length size of allocated region - * @param mode determines the operation to be performed on the given range, - * see fallocate(2) - */ - void (*fallocate)(fuse_req_t req, - const struct fuse_in_header *hdr); - - /** - * Copy a range of data from one file to another - * - * Performs an optimized copy between two file descriptors without - * the - * additional cost of transferring data through the FUSE kernel - * module - * to user space (glibc) and then back into the FUSE filesystem - * again. - * - * In case this method is not implemented, glibc falls back to - * reading - * data from the source and writing to the destination. Effectively - * doing an inefficient copy of the data. - * - * If this request is answered with an error code of ENOSYS, this is - * treated as a permanent failure with error code EOPNOTSUPP, - * i.e. all - * future copy_file_range() requests will fail with EOPNOTSUPP - * without - * being send to the filesystem process. - * - * Valid replies: - * fuse_reply_write - * fuse_reply_err - * - * @param req request handle - * @param ino_in the inode number of the source file - * @param off_in starting point from were the data should be read - * @param fi_in file information of the source file - * @param ino_out the inode number of the destination file - * @param off_out starting point where the data should be written - * @param fi_out file information of the destination file - * @param len maximum size of the data to copy - * @param flags passed along with the copy_file_range() syscall - */ - void (*copy_file_range)(fuse_req_t req, - const struct fuse_in_header *hdr); - - void (*setupmapping)(fuse_req_t req, - const struct fuse_in_header *hdr); - void (*removemapping)(fuse_req_t req, - const struct fuse_in_header *hdr); - void (*syncfs)(fuse_req_t req, - const struct fuse_in_header *hdr); - void (*tmpfile)(fuse_req_t req, - const struct fuse_in_header *hdr); + void (*fallocate)(fuse_req_t req, const struct fuse_in_header *hdr); + void (*flock)(fuse_req_t req, uint64_t ino, fuse_file_info_t *fi, int op); + void (*flush)(fuse_req_t req, struct fuse_in_header *hdr); + void (*forget)(fuse_req_t req, struct fuse_in_header *hdr); + void (*forget_multi)(fuse_req_t req, struct fuse_in_header *hdr); + void (*fsync)(fuse_req_t req, struct fuse_in_header *hdr); + void (*fsyncdir)(fuse_req_t req, struct fuse_in_header *hdr); + void (*getattr)(fuse_req_t req, struct fuse_in_header *hdr); + void (*getlk)(fuse_req_t req, const struct fuse_in_header *hdr); + void (*getxattr)(fuse_req_t req, struct fuse_in_header *hdr); + void (*init)(void *userdata, struct fuse_conn_info *conn); + void (*ioctl)(fuse_req_t req, const struct fuse_in_header *hdr); + void (*link)(fuse_req_t req, struct fuse_in_header *hdr); + void (*listxattr)(fuse_req_t req, struct fuse_in_header *hdr); + void (*lookup)(fuse_req_t req, struct fuse_in_header *hdr); + void (*mkdir)(fuse_req_t req, struct fuse_in_header *hdr); + void (*mknod)(fuse_req_t req, struct fuse_in_header *hdr); + void (*open)(fuse_req_t req, struct fuse_in_header *hdr); + void (*opendir)(fuse_req_t req, struct fuse_in_header *hdr); + void (*poll)(fuse_req_t req, const struct fuse_in_header *hdr); + void (*read)(fuse_req_t req, struct fuse_in_header *hdr); + void (*readdir)(fuse_req_t req, struct fuse_in_header *hdr); + void (*readdir_plus)(fuse_req_t req, struct fuse_in_header *hdr); + void (*readlink)(fuse_req_t req, struct fuse_in_header *hdr); + void (*release)(fuse_req_t req, struct fuse_in_header *hdr); + void (*releasedir)(fuse_req_t req, struct fuse_in_header *hdr); + void (*removemapping)(fuse_req_t req, const struct fuse_in_header *hdr); + void (*removexattr)(fuse_req_t req, const struct fuse_in_header *hdr); + void (*rename)(fuse_req_t req, struct fuse_in_header *hdr); + void (*retrieve_reply)(fuse_req_t req, void *cookie, uint64_t ino, off_t offset); + void (*rmdir)(fuse_req_t req, struct fuse_in_header *hdr); + void (*setattr)(fuse_req_t req, struct fuse_in_header *hdr); + void (*setlk)(fuse_req_t req, uint64_t ino, fuse_file_info_t *fi, struct flock *lock, int sleep); + void (*setupmapping)(fuse_req_t req, const struct fuse_in_header *hdr); + void (*setxattr)(fuse_req_t req, struct fuse_in_header *hdr); + void (*statfs)(fuse_req_t req, struct fuse_in_header *hdr); + void (*symlink)(fuse_req_t req, struct fuse_in_header *hdr); + void (*syncfs)(fuse_req_t req, const struct fuse_in_header *hdr); + void (*tmpfile)(fuse_req_t req, const struct fuse_in_header *hdr); + void (*unlink)(fuse_req_t req, struct fuse_in_header *hdr); + void (*write)(fuse_req_t req, struct fuse_in_header *hdr); }; /** diff --git a/libfuse/lib/crc32b.h b/libfuse/lib/crc32b.h index bf3dbe89..6f9ef8eb 100644 --- a/libfuse/lib/crc32b.h +++ b/libfuse/lib/crc32b.h @@ -19,6 +19,11 @@ #ifndef CRC32B_H_INCLUDED #define CRC32B_H_INCLUDED +#ifdef __cplusplus +extern "C" +{ +#endif + typedef unsigned int crc32b_t; crc32b_t crc32b_start(void); @@ -29,4 +34,8 @@ crc32b_t crc32b_finish(const crc32b_t crc); crc32b_t crc32b(const void *buf, crc32b_t len); +#ifdef __cplusplus +} +#endif + #endif diff --git a/libfuse/lib/fmp.h b/libfuse/lib/fmp.h index ee07e30e..899db340 100644 --- a/libfuse/lib/fmp.h +++ b/libfuse/lib/fmp.h @@ -328,7 +328,7 @@ fmp_gc_slab(fmp_t *fmp_, slab_idx_ = (slab_idx_ % kv_size(fmp_->slabs)); - slab = kv_A(fmp_->slabs,slab_idx_); + slab = (char*)kv_A(fmp_->slabs,slab_idx_); objs_per_slab = fmp_objs_per_slab(fmp_); objs_in_slab = fmp_objs_in_slab(fmp_,slab); diff --git a/libfuse/lib/fuse.c b/libfuse/lib/fuse.cpp similarity index 95% rename from libfuse/lib/fuse.c rename to libfuse/lib/fuse.cpp index 3cb3b5ad..34e9eb23 100644 --- a/libfuse/lib/fuse.c +++ b/libfuse/lib/fuse.cpp @@ -7,7 +7,9 @@ */ /* For pthread_rwlock_t */ +#ifndef _GNU_SOURCE #define _GNU_SOURCE +#endif #include "crc32b.h" #include "fuse_node.h" @@ -104,13 +106,6 @@ struct node_table size_t split; }; -#define container_of(ptr,type,member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) - -#define list_entry(ptr,type,member) \ - container_of(ptr,type,member) - struct list_head { struct list_head *next; @@ -218,32 +213,32 @@ fuse_hdr_arg(const struct fuse_in_header *hdr_) static void -list_add(struct list_head *new, - struct list_head *prev, - struct list_head *next) +list_add(struct list_head *new_, + struct list_head *prev_, + struct list_head *next_) { - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; + next_->prev = new_; + new_->next = next_; + new_->prev = prev_; + prev_->next = new_; } static inline void -list_add_head(struct list_head *new, - struct list_head *head) +list_add_head(struct list_head *new_, + struct list_head *head_) { - list_add(new,head,head->next); + list_add(new_,head_,head_->next); } static inline void -list_add_tail(struct list_head *new, - struct list_head *head) +list_add_tail(struct list_head *new_, + struct list_head *head_) { - list_add(new,head->prev,head); + list_add(new_,head_->prev,head_); } static @@ -384,7 +379,7 @@ node_table_reduce(struct node_table *t) newarray = realloc(t->array,sizeof(node_t*) * newsize); if(newarray != NULL) - t->array = newarray; + t->array = (node_t**)newarray; t->size = newsize; t->split = t->size / 2; @@ -450,7 +445,7 @@ node_table_resize(struct node_table *t) if(newarray == NULL) return -1; - t->array = newarray; + t->array = (node_t**)newarray; memset(t->array + t->size,0,t->size * sizeof(node_t*)); t->size = newsize; t->split = 0; @@ -795,7 +790,7 @@ add_name(char **buf, newbufsize *= 2; } - newbuf = realloc(*buf,newbufsize); + newbuf = (char*)realloc(*buf,newbufsize); if(newbuf == NULL) return NULL; @@ -857,7 +852,7 @@ try_get_path(struct fuse *f, *path = NULL; err = -ENOMEM; - buf = malloc(bufsize); + buf = (char*)malloc(bufsize); if(buf == NULL) goto out_err; @@ -1562,7 +1557,7 @@ fuse_lib_lookup(fuse_req_t req, node_t *dot = NULL; struct fuse_entry_param e = {0}; - name = fuse_hdr_arg(hdr_); + name = (const char*)fuse_hdr_arg(hdr_); nodeid = hdr_->nodeid; f = req_fuse_prepare(req); @@ -1628,7 +1623,7 @@ fuse_lib_forget(fuse_req_t req, struct fuse_forget_in *arg; f = req_fuse(req); - arg = fuse_hdr_arg(hdr_); + arg = (fuse_forget_in*)fuse_hdr_arg(hdr_); forget_node(f,hdr_->nodeid,arg->nlookup); @@ -1645,8 +1640,8 @@ fuse_lib_forget_multi(fuse_req_t req, struct fuse_forget_one *entry; f = req_fuse(req); - arg = fuse_hdr_arg(hdr_); - entry = PARAM(arg); + arg = (fuse_batch_forget_in*)fuse_hdr_arg(hdr_); + entry = (fuse_forget_one*)PARAM(arg); for(uint32_t i = 0; i < arg->count; i++) { @@ -1673,7 +1668,7 @@ fuse_lib_getattr(fuse_req_t req, fuse_file_info_t ffi = {0}; const struct fuse_getattr_in *arg; - arg = fuse_hdr_arg(hdr_); + arg = (fuse_getattr_in*)fuse_hdr_arg(hdr_); f = req_fuse_prepare(req); if(arg->getattr_flags & FUSE_GETATTR_FH) @@ -1735,7 +1730,7 @@ fuse_lib_setattr(fuse_req_t req, fuse_file_info_t ffi = {0}; struct fuse_setattr_in *arg; - arg = fuse_hdr_arg(hdr_); + arg = (fuse_setattr_in*)fuse_hdr_arg(hdr_); fi = NULL; if(arg->valid & FATTR_FH) @@ -1796,12 +1791,12 @@ fuse_lib_setattr(fuse_req_t req, if(arg->valid & FATTR_ATIME_NOW) tv[0].tv_nsec = UTIME_NOW; else if(arg->valid & FATTR_ATIME) - tv[0] = (struct timespec){ arg->atime, arg->atimensec }; + tv[0] = (struct timespec){ static_cast(arg->atime), arg->atimensec }; if(arg->valid & FATTR_MTIME_NOW) tv[1].tv_nsec = UTIME_NOW; else if(arg->valid & FATTR_MTIME) - tv[1] = (struct timespec){ arg->mtime, arg->mtimensec }; + tv[1] = (struct timespec){ static_cast(arg->mtime), arg->mtimensec }; err = ((fi == NULL) ? f->fs->op.utimens(path,tv) : @@ -1853,7 +1848,7 @@ fuse_lib_access(fuse_req_t req, struct fuse *f; struct fuse_access_in *arg; - arg = fuse_hdr_arg(hdr_); + arg = (fuse_access_in*)fuse_hdr_arg(hdr_); f = req_fuse_prepare(req); @@ -1909,8 +1904,8 @@ fuse_lib_mknod(fuse_req_t req, struct fuse_entry_param e; struct fuse_mknod_in *arg; - arg = fuse_hdr_arg(hdr_); - name = PARAM(arg); + arg = (fuse_mknod_in*)fuse_hdr_arg(hdr_); + name = (const char*)PARAM(arg); if(req->f->conn.proto_minor >= 12) req->ctx.umask = arg->umask; else @@ -1961,8 +1956,8 @@ fuse_lib_mkdir(fuse_req_t req, struct fuse_entry_param e; struct fuse_mkdir_in *arg; - arg = fuse_hdr_arg(hdr_); - name = PARAM(arg); + arg = (fuse_mkdir_in*)fuse_hdr_arg(hdr_); + name = (const char*)PARAM(arg); if(req->f->conn.proto_minor >= 12) req->ctx.umask = arg->umask; @@ -1991,7 +1986,7 @@ fuse_lib_unlink(fuse_req_t req, const char *name; node_t *wnode; - name = PARAM(hdr_); + name = (const char*)PARAM(hdr_); f = req_fuse_prepare(req); err = get_path_wrlock(f,hdr_->nodeid,name,&path,&wnode); @@ -2024,7 +2019,7 @@ fuse_lib_rmdir(fuse_req_t req, const char *name; node_t *wnode; - name = PARAM(hdr_); + name = (const char*)PARAM(hdr_); f = req_fuse_prepare(req); @@ -2052,7 +2047,7 @@ fuse_lib_symlink(fuse_req_t req_, const char *linkname; struct fuse_entry_param e = {0}; - name = fuse_hdr_arg(hdr_); + name = (const char*)fuse_hdr_arg(hdr_); linkname = (name + strlen(name) + 1); f = req_fuse_prepare(req_); @@ -2084,8 +2079,8 @@ fuse_lib_rename(fuse_req_t req, node_t *wnode2; struct fuse_rename_in *arg; - arg = fuse_hdr_arg(hdr_); - oldname = PARAM(arg); + arg = (fuse_rename_in*)fuse_hdr_arg(hdr_); + oldname = (const char*)PARAM(arg); newname = (oldname + strlen(oldname) + 1); f = req_fuse_prepare(req); @@ -2122,8 +2117,8 @@ fuse_lib_link(fuse_req_t req, struct fuse_link_in *arg; struct fuse_entry_param e = {0}; - arg = fuse_hdr_arg(hdr_); - newname = PARAM(arg); + arg = (fuse_link_in*)fuse_hdr_arg(hdr_); + newname = (const char*)PARAM(arg); f = req_fuse_prepare(req); @@ -2186,8 +2181,8 @@ fuse_lib_create(fuse_req_t req, struct fuse_entry_param e; struct fuse_create_in *arg; - arg = fuse_hdr_arg(hdr_); - name = PARAM(arg); + arg = (fuse_create_in*)fuse_hdr_arg(hdr_); + name = (const char*)PARAM(arg); ffi.flags = arg->flags; @@ -2287,7 +2282,7 @@ fuse_lib_open(fuse_req_t req, fuse_file_info_t ffi = {0}; struct fuse_open_in *arg; - arg = fuse_hdr_arg(hdr_); + arg = (fuse_open_in*)fuse_hdr_arg(hdr_); ffi.flags = arg->flags; @@ -2332,7 +2327,7 @@ fuse_lib_read(fuse_req_t req, struct fuse_read_in *arg; fuse_msgbuf_t *msgbuf; - arg = fuse_hdr_arg(hdr_); + arg = (fuse_read_in*)fuse_hdr_arg(hdr_); ffi.fh = arg->fh; if(req->f->conn.proto_minor >= 9) { @@ -2365,7 +2360,7 @@ fuse_lib_write(fuse_req_t req, fuse_file_info_t ffi = {0}; struct fuse_write_in *arg; - arg = fuse_hdr_arg(hdr_); + arg = (fuse_write_in*)fuse_hdr_arg(hdr_); ffi.fh = arg->fh; ffi.writepage = !!(arg->write_flags & 1); if(req->f->conn.proto_minor < 9) @@ -2376,7 +2371,7 @@ fuse_lib_write(fuse_req_t req, { ffi.flags = arg->flags; ffi.lock_owner = arg->lock_owner; - data = PARAM(arg); + data = (char*)PARAM(arg); } f = req_fuse_prepare(req); @@ -2400,7 +2395,7 @@ fuse_lib_fsync(fuse_req_t req, struct fuse_fsync_in *arg; fuse_file_info_t ffi = {0}; - arg = fuse_hdr_arg(hdr_); + arg = (fuse_fsync_in*)fuse_hdr_arg(hdr_); ffi.fh = arg->fh; f = req_fuse_prepare(req); @@ -2435,7 +2430,7 @@ fuse_lib_opendir(fuse_req_t req, struct fuse *f; struct fuse_open_in *arg; - arg = fuse_hdr_arg(hdr_); + arg = (fuse_open_in*)fuse_hdr_arg(hdr_); llffi.flags = arg->flags; f = req_fuse_prepare(req); @@ -2522,7 +2517,7 @@ fuse_lib_readdir(fuse_req_t req_, fuse_file_info_t llffi = {0}; struct fuse_read_in *arg; - arg = fuse_hdr_arg(hdr_); + arg = (fuse_read_in*)fuse_hdr_arg(hdr_); size = arg->size; llffi.fh = arg->fh; @@ -2566,7 +2561,7 @@ fuse_lib_readdir_plus(fuse_req_t req_, fuse_file_info_t llffi = {0}; struct fuse_read_in *arg; - arg = fuse_hdr_arg(hdr_); + arg = (fuse_read_in*)fuse_hdr_arg(hdr_); size = arg->size; llffi.fh = arg->fh; @@ -2607,7 +2602,7 @@ fuse_lib_releasedir(fuse_req_t req_, fuse_file_info_t llffi = {0}; struct fuse_release_in *arg; - arg = fuse_hdr_arg(hdr_); + arg = (fuse_release_in*)fuse_hdr_arg(hdr_); llffi.fh = arg->fh; llffi.flags = arg->flags; @@ -2636,7 +2631,7 @@ fuse_lib_fsyncdir(fuse_req_t req, fuse_file_info_t llffi = {0}; struct fuse_fsync_in *arg; - arg = fuse_hdr_arg(hdr_); + arg = (fuse_fsync_in*)fuse_hdr_arg(hdr_); llffi.fh = arg->fh; f = req_fuse_prepare(req); @@ -2688,9 +2683,9 @@ fuse_lib_setxattr(fuse_req_t req, struct fuse *f; struct fuse_setxattr_in *arg; - arg = fuse_hdr_arg(hdr_); + arg = (fuse_setxattr_in*)fuse_hdr_arg(hdr_); if((req->f->conn.capable & FUSE_SETXATTR_EXT) && (req->f->conn.want & FUSE_SETXATTR_EXT)) - name = PARAM(arg); + name = (const char*)PARAM(arg); else name = (((char*)arg) + FUSE_COMPAT_SETXATTR_IN_SIZE); @@ -2741,8 +2736,8 @@ fuse_lib_getxattr(fuse_req_t req, const char* name; struct fuse_getxattr_in *arg; - arg = fuse_hdr_arg(hdr_); - name = PARAM(arg); + arg = (fuse_getxattr_in*)fuse_hdr_arg(hdr_); + name = (const char*)PARAM(arg); f = req_fuse_prepare(req); @@ -2802,7 +2797,7 @@ fuse_lib_listxattr(fuse_req_t req, struct fuse *f; struct fuse_getxattr_in *arg; - arg = fuse_hdr_arg(hdr_); + arg = (fuse_getxattr_in*)fuse_hdr_arg(hdr_); f = req_fuse_prepare(req); @@ -2842,7 +2837,7 @@ fuse_lib_removexattr(fuse_req_t req, const char *name; struct fuse *f; - name = fuse_hdr_arg(hdr_); + name = (const char*)fuse_hdr_arg(hdr_); f = req_fuse_prepare(req); @@ -2867,7 +2862,7 @@ fuse_lib_copy_file_range(fuse_req_t req_, fuse_file_info_t ffi_out = {0}; const struct fuse_copy_file_range_in *arg; - arg = fuse_hdr_arg(hdr_); + arg = (fuse_copy_file_range_in*)fuse_hdr_arg(hdr_); ffi_in.fh = arg->fh_in; ffi_out.fh = arg->fh_out; @@ -2927,8 +2922,8 @@ fuse_lib_tmpfile(fuse_req_t req_, struct fuse_entry_param e; struct fuse_create_in *arg; - arg = fuse_hdr_arg(hdr_); - name = PARAM(arg); + arg = (fuse_create_in*)fuse_hdr_arg(hdr_); + name = (const char*)PARAM(arg); ffi.flags = arg->flags; @@ -3026,8 +3021,8 @@ locks_insert(node_t *node, if(lock->type != F_UNLCK || lock->start != 0 || lock->end != OFFSET_MAX) { - newl1 = malloc(sizeof(lock_t)); - newl2 = malloc(sizeof(lock_t)); + newl1 = (lock_t*)malloc(sizeof(lock_t)); + newl2 = (lock_t*)malloc(sizeof(lock_t)); if(!newl1 || !newl2) { @@ -3055,7 +3050,7 @@ locks_insert(node_t *node, lock->start = l->start; if(lock->end < l->end) lock->end = l->end; - goto delete; + goto delete_lock; } else { @@ -3064,7 +3059,7 @@ locks_insert(node_t *node, if(lock->end < l->start) break; if(lock->start <= l->start && l->end <= lock->end) - goto delete; + goto delete_lock; if(l->end <= lock->end) { l->end = lock->start - 1; @@ -3085,7 +3080,7 @@ locks_insert(node_t *node, lp = &l->next; continue; - delete: + delete_lock: delete_lock(lp); } if(lock->type != F_UNLCK) @@ -3168,7 +3163,7 @@ fuse_lib_release(fuse_req_t req, fuse_file_info_t ffi = {0}; struct fuse_release_in *arg; - arg = fuse_hdr_arg(hdr_); + arg = (fuse_release_in*)fuse_hdr_arg(hdr_); ffi.fh = arg->fh; ffi.flags = arg->flags; if(req->f->conn.proto_minor >= 8) @@ -3206,7 +3201,7 @@ fuse_lib_flush(fuse_req_t req, fuse_file_info_t ffi = {0}; struct fuse_flush_in *arg; - arg = fuse_hdr_arg(hdr_); + arg = (fuse_flush_in*)fuse_hdr_arg(hdr_); ffi.fh = arg->fh; ffi.flush = 1; @@ -3265,7 +3260,7 @@ fuse_lib_getlk(fuse_req_t req, fuse_file_info_t ffi = {0}; const struct fuse_lk_in *arg; - arg = fuse_hdr_arg(hdr_); + arg = (fuse_lk_in*)fuse_hdr_arg(hdr_); ffi.fh = arg->fh; ffi.lock_owner = arg->owner; @@ -3341,7 +3336,7 @@ fuse_lib_bmap(fuse_req_t req, uint64_t block; const struct fuse_bmap_in *arg; - arg = fuse_hdr_arg(hdr_); + arg = (fuse_bmap_in*)fuse_hdr_arg(hdr_); block = arg->block; f = req_fuse_prepare(req); @@ -3373,7 +3368,7 @@ fuse_lib_ioctl(fuse_req_t req, uint32_t out_size; const struct fuse_ioctl_in *arg; - arg = fuse_hdr_arg(hdr_); + arg = (fuse_ioctl_in*)fuse_hdr_arg(hdr_); if((arg->flags & FUSE_IOCTL_DIR) && !(req->f->conn.want & FUSE_CAP_IOCTL_DIR)) { fuse_reply_err(req,ENOTTY); @@ -3403,7 +3398,7 @@ fuse_lib_ioctl(fuse_req_t req, if(out_size) { err = -ENOMEM; - out_buf = malloc(out_size); + out_buf = (char*)malloc(out_size); if(!out_buf) goto err; } @@ -3441,7 +3436,7 @@ fuse_lib_poll(fuse_req_t req, fuse_pollhandle_t *ph = NULL; const struct fuse_poll_in *arg; - arg = fuse_hdr_arg(hdr_); + arg = (fuse_poll_in*)fuse_hdr_arg(hdr_); ffi.fh = arg->fh; if(arg->flags & FUSE_POLL_SCHEDULE_NOTIFY) @@ -3476,7 +3471,7 @@ fuse_lib_fallocate(fuse_req_t req, fuse_file_info_t ffi = {0}; const struct fuse_fallocate_in *arg; - arg = fuse_hdr_arg(hdr_); + arg = (fuse_fallocate_in*)fuse_hdr_arg(hdr_); ffi.fh = arg->fh; f = req_fuse_prepare(req); @@ -3494,8 +3489,8 @@ int remembered_node_cmp(const void *a_, const void *b_) { - const remembered_node_t *a = a_; - const remembered_node_t *b = b_; + const remembered_node_t *a = (const remembered_node_t*)a_; + const remembered_node_t *b = (const remembered_node_t*)b_; return (a->time - b->time); } @@ -3830,21 +3825,21 @@ metrics_log_nodes_info(struct fuse *f_, snprintf(buf,sizeof(buf), "time: %s\n" - "sizeof(node): %"PRIu64"\n" - "node id_table size: %"PRIu64"\n" - "node id_table usage: %"PRIu64"\n" - "node id_table total allocated memory: %"PRIu64"\n" - "node name_table size: %"PRIu64"\n" - "node name_table usage: %"PRIu64"\n" - "node name_table total allocated memory: %"PRIu64"\n" - "node memory pool slab count: %"PRIu64"\n" + "sizeof(node): %" PRIu64 "\n" + "node id_table size: %" PRIu64 "\n" + "node id_table usage: %" PRIu64 "\n" + "node id_table total allocated memory: %" PRIu64 "\n" + "node name_table size: %" PRIu64 "\n" + "node name_table usage: %" PRIu64 "\n" + "node name_table total allocated memory: %" PRIu64 "\n" + "node memory pool slab count: %" PRIu64 "\n" "node memory pool usage ratio: %f\n" - "node memory pool avail objs: %"PRIu64"\n" - "node memory pool total allocated memory: %"PRIu64"\n" - "msgbuf bufsize: %"PRIu64"\n" - "msgbuf allocation count: %"PRIu64"\n" - "msgbuf available count: %"PRIu64"\n" - "msgbuf total allocated memory: %"PRIu64"\n" + "node memory pool avail objs: %" PRIu64 "\n" + "node memory pool total allocated memory: %" PRIu64 "\n" + "msgbuf bufsize: %" PRIu64 "\n" + "msgbuf allocation count: %" PRIu64 "\n" + "msgbuf available count: %" PRIu64 "\n" + "msgbuf total allocated memory: %" PRIu64 "\n" "\n" , time_str, @@ -3911,7 +3906,7 @@ fuse_invalidate_all_nodes() syslog(LOG_INFO,"invalidating file entries"); pthread_mutex_lock(&f->lock); - for(int i = 0; i < f->id_table.size; i++) + for(size_t i = 0; i < f->id_table.size; i++) { node_t *node; diff --git a/libfuse/lib/node.h b/libfuse/lib/node.h index c5636de0..bf237070 100644 --- a/libfuse/lib/node.h +++ b/libfuse/lib/node.h @@ -1,3 +1,5 @@ +#pragma once + #include "lock.h" #include "lfmp.h" @@ -23,8 +25,18 @@ struct node_s uint8_t is_stat_cache_valid:1; }; +#ifdef __cplusplus +extern "C" +{ +#endif + node_t *node_alloc(); void node_free(node_t*); int node_gc1(); void node_gc(); lfmp_t *node_lfmp(); + + +#ifdef __cplusplus +} +#endif