libperfuse(3) is a PUFFS relay to FUSE. In order to use it,
FUSE filesystem must be patched to #include <perfuse.h> in the source files that open /dev/fuse and perform the mount(2) system call. The FUSE filesystem must be linked with -lperfuse. libperfuse(3) implements the FUSE kernel interface, on which libfuse or any FUSE filesystem that opens /dev/fuse directly can be used. For now, an external daemon called perfused(8) is used. This may change in the future.
This commit is contained in:
parent
3a12eae410
commit
7b1d1ee680
|
@ -0,0 +1,14 @@
|
|||
LIB= perfuse
|
||||
LIBDPLIBS+= puffs /usr/src/lib/libpuffs
|
||||
|
||||
|
||||
PERFUSE_OPT_DEBUG_FLAGS= -g -DPERFUSE_DEBUG
|
||||
|
||||
CFLAGS+= ${PERFUSE_OPT_DEBUG_FLAGS}
|
||||
SRCS= perfuse.c ops.c subr.c debug.c
|
||||
MAN= libperfuse.3
|
||||
WARNS= 4
|
||||
INCS= perfuse.h
|
||||
INCSDIR= /usr/include
|
||||
|
||||
.include <bsd.lib.mk>
|
|
@ -0,0 +1,94 @@
|
|||
/* $NetBSD: debug.c,v 1.1 2010/08/25 07:16:00 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <puffs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "perfuse_if.h"
|
||||
#include "fuse.h"
|
||||
|
||||
struct perfuse_opcode {
|
||||
int opcode;
|
||||
const char *opname;
|
||||
};
|
||||
|
||||
const struct perfuse_opcode perfuse_opcode[] = {
|
||||
{ FUSE_LOOKUP, "LOOKUP" },
|
||||
{ FUSE_FORGET, "FORGET" },
|
||||
{ FUSE_GETATTR, "GETATTR" },
|
||||
{ FUSE_SETATTR, "SETATTR" },
|
||||
{ FUSE_READLINK, "READLINK" },
|
||||
{ FUSE_SYMLINK, "SYMLINK" },
|
||||
{ FUSE_MKNOD, "MKNOD" },
|
||||
{ FUSE_MKDIR, "MKDIR" },
|
||||
{ FUSE_UNLINK, "UNLINK" },
|
||||
{ FUSE_RMDIR, "RMDIR" },
|
||||
{ FUSE_RENAME, "RENAME" },
|
||||
{ FUSE_LINK, "LINK" },
|
||||
{ FUSE_OPEN, "OPEN" },
|
||||
{ FUSE_READ, "READ" },
|
||||
{ FUSE_WRITE, "WRITE" },
|
||||
{ FUSE_STATFS, "STATFS" },
|
||||
{ FUSE_RELEASE, "RELEASE" },
|
||||
{ FUSE_FSYNC, "FSYNC" },
|
||||
{ FUSE_SETXATTR, "SETXATTR" },
|
||||
{ FUSE_GETXATTR, "GETXATTR" },
|
||||
{ FUSE_LISTXATTR, "LISTXATTR" },
|
||||
{ FUSE_REMOVEXATTR, "REMOVEXATTR" },
|
||||
{ FUSE_FLUSH, "FLUSH" },
|
||||
{ FUSE_INIT, "INIT" },
|
||||
{ FUSE_OPENDIR, "OPENDIR" },
|
||||
{ FUSE_READDIR, "READDIR" },
|
||||
{ FUSE_RELEASEDIR, "RELEASEDIR" },
|
||||
{ FUSE_FSYNCDIR, "FSYNCDIR" },
|
||||
{ FUSE_GETLK, "GETLK" },
|
||||
{ FUSE_SETLK, "SETLK" },
|
||||
{ FUSE_SETLKW, "SETLKW" },
|
||||
{ FUSE_ACCESS, "ACCESS" },
|
||||
{ FUSE_CREATE, "CREATE" },
|
||||
{ FUSE_INTERRUPT, "INTERRUPT" },
|
||||
{ FUSE_BMAP, "BMAP" },
|
||||
{ FUSE_DESTROY, "DESTROY" },
|
||||
{ FUSE_IOCTL, "IOCTL" },
|
||||
{ FUSE_POLL, "POLL" },
|
||||
{ FUSE_CUSE_INIT, "CUSE_INIT" },
|
||||
{ 0, "UNKNOWN" },
|
||||
};
|
||||
|
||||
const char *
|
||||
perfuse_opname(opcode)
|
||||
int opcode;
|
||||
{
|
||||
const struct perfuse_opcode *po;
|
||||
|
||||
for (po = perfuse_opcode; po->opcode; po++) {
|
||||
if (po->opcode == opcode)
|
||||
return po->opname;
|
||||
}
|
||||
|
||||
return po->opname; /* "UNKNOWN" */
|
||||
}
|
|
@ -0,0 +1,496 @@
|
|||
/* $NetBSD: fuse.h,v 1.1 2010/08/25 07:16:00 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _FUSE_H
|
||||
#define _FUSE_H
|
||||
|
||||
#define FUSE_KERNEL_VERSION 7
|
||||
#define FUSE_KERNEL_MINOR_VERSION 12
|
||||
#define FUSE_ROOT_ID 1
|
||||
#define FUSE_UNKNOWN_FH (uint64_t)0
|
||||
|
||||
#define FUSE_MIN_BUFSIZE 0x21000
|
||||
#define FUSE_PREF_BUFSIZE (PAGE_SIZE + 0x1000)
|
||||
#define FUSE_BUFSIZE MAX(FUSE_PREF_BUFSIZE, FUSE_MIN_BUFSIZE)
|
||||
|
||||
struct fuse_attr {
|
||||
uint64_t ino;
|
||||
uint64_t size;
|
||||
uint64_t blocks;
|
||||
uint64_t atime;
|
||||
uint64_t mtime;
|
||||
uint64_t ctime;
|
||||
uint32_t atimensec;
|
||||
uint32_t mtimensec;
|
||||
uint32_t ctimensec;
|
||||
uint32_t mode;
|
||||
uint32_t nlink;
|
||||
uint32_t uid;
|
||||
uint32_t gid;
|
||||
uint32_t rdev;
|
||||
uint32_t blksize;
|
||||
uint32_t padding;
|
||||
};
|
||||
|
||||
struct fuse_kstatfs {
|
||||
uint64_t blocks;
|
||||
uint64_t bfree;
|
||||
uint64_t bavail;
|
||||
uint64_t files;
|
||||
uint64_t ffree;
|
||||
uint32_t bsize;
|
||||
uint32_t namelen;
|
||||
uint32_t frsize;
|
||||
uint32_t padding;
|
||||
uint32_t spare[6];
|
||||
};
|
||||
|
||||
struct fuse_file_lock {
|
||||
uint64_t start;
|
||||
uint64_t end;
|
||||
uint32_t type;
|
||||
uint32_t pid;
|
||||
};
|
||||
|
||||
/*
|
||||
* Various flags
|
||||
*/
|
||||
#define FUSE_FATTR_MODE 0x0001
|
||||
#define FUSE_FATTR_UID 0x0002
|
||||
#define FUSE_FATTR_GID 0x0004
|
||||
#define FUSE_FATTR_SIZE 0x0008
|
||||
#define FUSE_FATTR_ATIME 0x0010
|
||||
#define FUSE_FATTR_MTIME 0x0020
|
||||
#define FUSE_FATTR_FH 0x0040
|
||||
#define FUSE_FATTR_ATIME_NOW 0x0080
|
||||
#define FUSE_FATTR_MTIME_NOW 0x0100
|
||||
#define FUSE_FATTR_LOCKOWNER 0x0200
|
||||
|
||||
#define FUSE_FOPEN_DIRECT_IO 0x0001
|
||||
#define FUSE_FOPEN_KEEP_CACHE 0x0002
|
||||
#define FUSE_FOPEN_NONSEEKABLE 0x0004
|
||||
|
||||
#define FUSE_ASYNC_READ 0x0001
|
||||
#define FUSE_POSIX_LOCKS 0x0002
|
||||
#define FUSE_FILE_OPS 0x0004
|
||||
#define FUSE_ATOMIC_O_TRUNC 0x0008
|
||||
#define FUSE_EXPORT_SUPPORT 0x0010
|
||||
#define FUSE_BIG_WRITES 0x0020
|
||||
#define FUSE_DONT_MASK 0x0040
|
||||
|
||||
#define FUSE_CUSE_UNRESTRICTED_IOCTL 0x0001
|
||||
|
||||
#define FUSE_RELEASE_FLUSH 0x0001
|
||||
|
||||
#define FUSE_GETATTR_FH 0x0001
|
||||
|
||||
#define FUSE_LK_FLOCK 0x0001
|
||||
|
||||
#define FUSE_WRITE_CACHE 0x0001
|
||||
#define FUSE_WRITE_LOCKOWNER 0x0002
|
||||
|
||||
#define FUSE_READ_LOCKOWNER 0x0002
|
||||
|
||||
#define FUSE_IOCTL_COMPAT 0x0001
|
||||
#define FUSE_IOCTL_UNRESTRICTED 0x0002
|
||||
#define FUSE_IOCTL_RETRY 0x0004
|
||||
|
||||
#define FUSE_IOCTL_MAX_IOV 256
|
||||
|
||||
#define FUSE_POLL_SCHEDULE_NOTIFY 0x0001
|
||||
|
||||
enum fuse_opcode {
|
||||
FUSE_LOOKUP = 1,
|
||||
FUSE_FORGET = 2,
|
||||
FUSE_GETATTR = 3,
|
||||
FUSE_SETATTR = 4,
|
||||
FUSE_READLINK = 5,
|
||||
FUSE_SYMLINK = 6,
|
||||
FUSE_MKNOD = 8,
|
||||
FUSE_MKDIR = 9,
|
||||
FUSE_UNLINK = 10,
|
||||
FUSE_RMDIR = 11,
|
||||
FUSE_RENAME = 12,
|
||||
FUSE_LINK = 13,
|
||||
FUSE_OPEN = 14,
|
||||
FUSE_READ = 15,
|
||||
FUSE_WRITE = 16,
|
||||
FUSE_STATFS = 17,
|
||||
FUSE_RELEASE = 18,
|
||||
FUSE_FSYNC = 20,
|
||||
FUSE_SETXATTR = 21,
|
||||
FUSE_GETXATTR = 22,
|
||||
FUSE_LISTXATTR = 23,
|
||||
FUSE_REMOVEXATTR = 24,
|
||||
FUSE_FLUSH = 25,
|
||||
FUSE_INIT = 26,
|
||||
FUSE_OPENDIR = 27,
|
||||
FUSE_READDIR = 28,
|
||||
FUSE_RELEASEDIR = 29,
|
||||
FUSE_FSYNCDIR = 30,
|
||||
FUSE_GETLK = 31,
|
||||
FUSE_SETLK = 32,
|
||||
FUSE_SETLKW = 33,
|
||||
FUSE_ACCESS = 34,
|
||||
FUSE_CREATE = 35,
|
||||
FUSE_INTERRUPT = 36,
|
||||
FUSE_BMAP = 37,
|
||||
FUSE_DESTROY = 38,
|
||||
FUSE_IOCTL = 39,
|
||||
FUSE_POLL = 40,
|
||||
|
||||
FUSE_CUSE_INIT = 4096
|
||||
};
|
||||
|
||||
enum fuse_notify_code {
|
||||
FUSE_NOTIFY_POLL = 1,
|
||||
FUSE_NOTIFY_INVAL_INODE = 2,
|
||||
FUSE_NOTIFY_INVAL_ENTRY = 3,
|
||||
FUSE_NOTIFY_CODE_MAX
|
||||
};
|
||||
|
||||
#define FUSE_MIN_READ_BUFFER 8192
|
||||
|
||||
#define FUSE_COMPAT_ENTRY_OUT_SIZE 120
|
||||
|
||||
struct fuse_entry_out {
|
||||
uint64_t nodeid;
|
||||
uint64_t generation;
|
||||
uint64_t entry_valid;
|
||||
uint64_t attr_valid;
|
||||
uint32_t entry_valid_nsec;
|
||||
uint32_t attr_valid_nsec;
|
||||
struct fuse_attr attr;
|
||||
};
|
||||
|
||||
struct fuse_forget_in {
|
||||
uint64_t nlookup;
|
||||
};
|
||||
|
||||
struct fuse_getattr_in {
|
||||
uint32_t getattr_flags;
|
||||
uint32_t dummy;
|
||||
uint64_t fh;
|
||||
};
|
||||
|
||||
#define FUSE_COMPAT_ATTR_OUT_SIZE 96
|
||||
|
||||
struct fuse_attr_out {
|
||||
uint64_t attr_valid;
|
||||
uint32_t attr_valid_nsec;
|
||||
uint32_t dummy;
|
||||
struct fuse_attr attr;
|
||||
};
|
||||
|
||||
#define FUSE_COMPAT_MKNOD_IN_SIZE 8
|
||||
|
||||
struct fuse_mknod_in {
|
||||
uint32_t mode;
|
||||
uint32_t rdev;
|
||||
uint32_t umask;
|
||||
uint32_t padding;
|
||||
};
|
||||
|
||||
struct fuse_mkdir_in {
|
||||
uint32_t mode;
|
||||
uint32_t umask;
|
||||
};
|
||||
|
||||
struct fuse_rename_in {
|
||||
uint64_t newdir;
|
||||
};
|
||||
|
||||
struct fuse_link_in {
|
||||
uint64_t oldnodeid;
|
||||
};
|
||||
|
||||
struct fuse_setattr_in {
|
||||
uint32_t valid;
|
||||
uint32_t padding;
|
||||
uint64_t fh;
|
||||
uint64_t size;
|
||||
uint64_t lock_owner;
|
||||
uint64_t atime;
|
||||
uint64_t mtime;
|
||||
uint64_t unused2;
|
||||
uint32_t atimensec;
|
||||
uint32_t mtimensec;
|
||||
uint32_t unused3;
|
||||
uint32_t mode;
|
||||
uint32_t unused4;
|
||||
uint32_t uid;
|
||||
uint32_t gid;
|
||||
uint32_t unused5;
|
||||
};
|
||||
|
||||
struct fuse_open_in {
|
||||
uint32_t flags;
|
||||
uint32_t unused;
|
||||
};
|
||||
|
||||
struct fuse_create_in {
|
||||
uint32_t flags;
|
||||
uint32_t mode;
|
||||
uint32_t umask;
|
||||
uint32_t padding;
|
||||
};
|
||||
|
||||
struct fuse_open_out {
|
||||
uint64_t fh;
|
||||
uint32_t open_flags; /* FUSE_FOPEN_ */
|
||||
uint32_t padding;
|
||||
};
|
||||
|
||||
struct fuse_release_in {
|
||||
uint64_t fh;
|
||||
uint32_t flags;
|
||||
uint32_t release_flags;
|
||||
uint64_t lock_owner;
|
||||
};
|
||||
|
||||
struct fuse_flush_in {
|
||||
uint64_t fh;
|
||||
uint32_t unused;
|
||||
uint32_t padding;
|
||||
uint64_t lock_owner;
|
||||
};
|
||||
|
||||
struct fuse_read_in {
|
||||
uint64_t fh;
|
||||
uint64_t offset;
|
||||
uint32_t size;
|
||||
uint32_t read_flags;
|
||||
uint64_t lock_owner;
|
||||
uint32_t flags;
|
||||
uint32_t padding;
|
||||
};
|
||||
|
||||
#define FUSE_COMPAT_WRITE_IN_SIZE 24
|
||||
|
||||
struct fuse_write_in {
|
||||
uint64_t fh;
|
||||
uint64_t offset;
|
||||
uint32_t size;
|
||||
uint32_t write_flags;
|
||||
uint64_t lock_owner;
|
||||
uint32_t flags;
|
||||
uint32_t padding;
|
||||
};
|
||||
|
||||
struct fuse_write_out {
|
||||
uint32_t size;
|
||||
uint32_t padding;
|
||||
};
|
||||
|
||||
#define FUSE_COMPAT_STATFS_SIZE 48
|
||||
|
||||
struct fuse_statfs_out {
|
||||
struct fuse_kstatfs st;
|
||||
};
|
||||
|
||||
struct fuse_fsync_in {
|
||||
uint64_t fh;
|
||||
uint32_t fsync_flags;
|
||||
uint32_t padding;
|
||||
};
|
||||
|
||||
struct fuse_setxattr_in {
|
||||
uint32_t size;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct fuse_getxattr_in {
|
||||
uint32_t size;
|
||||
uint32_t padding;
|
||||
};
|
||||
|
||||
struct fuse_getxattr_out {
|
||||
uint32_t size;
|
||||
uint32_t padding;
|
||||
};
|
||||
|
||||
struct fuse_lk_in {
|
||||
uint64_t fh;
|
||||
uint64_t owner;
|
||||
struct fuse_file_lock lk;
|
||||
uint32_t lk_flags;
|
||||
uint32_t padding;
|
||||
};
|
||||
|
||||
struct fuse_lk_out {
|
||||
struct fuse_file_lock lk;
|
||||
};
|
||||
|
||||
struct fuse_access_in {
|
||||
uint32_t mask;
|
||||
uint32_t padding;
|
||||
};
|
||||
|
||||
struct fuse_init_in {
|
||||
uint32_t major;
|
||||
uint32_t minor;
|
||||
uint32_t max_readahead;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct fuse_init_out {
|
||||
uint32_t major;
|
||||
uint32_t minor;
|
||||
uint32_t max_readahead;
|
||||
uint32_t flags;
|
||||
uint32_t unused;
|
||||
uint32_t max_write;
|
||||
};
|
||||
|
||||
#define FUSE_CUSE_INIT_INFO_MAX 4096
|
||||
|
||||
struct fuse_cuse_init_in {
|
||||
uint32_t major;
|
||||
uint32_t minor;
|
||||
uint32_t unused;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct fuse_cuse_init_out {
|
||||
uint32_t major;
|
||||
uint32_t minor;
|
||||
uint32_t unused;
|
||||
uint32_t flags;
|
||||
uint32_t max_read;
|
||||
uint32_t max_write;
|
||||
uint32_t dev_major; /* chardev major */
|
||||
uint32_t dev_minor; /* chardev minor */
|
||||
uint32_t spare[10];
|
||||
};
|
||||
|
||||
struct fuse_interrupt_in {
|
||||
uint64_t unique;
|
||||
};
|
||||
|
||||
struct fuse_bmap_in {
|
||||
uint64_t block;
|
||||
uint32_t blocksize;
|
||||
uint32_t padding;
|
||||
};
|
||||
|
||||
struct fuse_bmap_out {
|
||||
uint64_t block;
|
||||
};
|
||||
|
||||
struct fuse_ioctl_in {
|
||||
uint64_t fh;
|
||||
uint32_t flags;
|
||||
uint32_t cmd;
|
||||
uint64_t arg;
|
||||
uint32_t in_size;
|
||||
uint32_t out_size;
|
||||
};
|
||||
|
||||
struct fuse_ioctl_out {
|
||||
int32_t result;
|
||||
uint32_t flags;
|
||||
uint32_t in_iovs;
|
||||
uint32_t out_iovs;
|
||||
};
|
||||
|
||||
struct fuse_poll_in {
|
||||
uint64_t fh;
|
||||
uint64_t kh;
|
||||
uint32_t flags;
|
||||
uint32_t padding;
|
||||
};
|
||||
|
||||
struct fuse_poll_out {
|
||||
uint32_t revents;
|
||||
uint32_t padding;
|
||||
};
|
||||
|
||||
struct fuse_notify_poll_wakeup_out {
|
||||
uint64_t kh;
|
||||
};
|
||||
|
||||
#if 0 /* Duplicated in perfuse.h to avoid making fuse.h public */
|
||||
/* Send from kernel to proces */
|
||||
struct fuse_in_header {
|
||||
uint32_t len;
|
||||
uint32_t opcode;
|
||||
uint64_t unique;
|
||||
uint64_t nodeid;
|
||||
uint32_t uid;
|
||||
uint32_t gid;
|
||||
uint32_t pid;
|
||||
uint32_t padding;
|
||||
};
|
||||
|
||||
struct fuse_in_arg {
|
||||
uint32_t size;
|
||||
const void *value;
|
||||
};
|
||||
|
||||
struct fuse_in {
|
||||
struct fuse_in_header h;
|
||||
uint32_t argpages:1; /* Req fits in a page? Always 1 */
|
||||
uint32_t numargs;
|
||||
struct fuse_in_arg args[3]; /* args copied to userspace */
|
||||
};
|
||||
|
||||
|
||||
/* From process to kernel */
|
||||
struct fuse_out_header {
|
||||
uint32_t len;
|
||||
int32_t error;
|
||||
uint64_t unique;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct fuse_dirent {
|
||||
uint64_t ino;
|
||||
uint64_t off; /* offset of next field from after foh */
|
||||
uint32_t namelen;
|
||||
uint32_t type;
|
||||
char name[0];
|
||||
};
|
||||
|
||||
#define FUSE_NAME_OFFSET offsetof(struct fuse_dirent, name)
|
||||
#define FUSE_DIRENT_ALIGN(x) \
|
||||
(((x) + sizeof(uint64_t) - 1) & ~(sizeof(uint64_t) - 1))
|
||||
#define FUSE_DIRENT_SIZE(d) \
|
||||
FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen)
|
||||
|
||||
struct fuse_notify_inval_inode_out {
|
||||
uint64_t ino;
|
||||
int64_t off;
|
||||
int64_t len;
|
||||
};
|
||||
|
||||
struct fuse_notify_inval_entry_out {
|
||||
uint64_t parent;
|
||||
uint32_t namelen;
|
||||
uint32_t padding;
|
||||
};
|
||||
|
||||
#endif /* _FUSE_H */
|
|
@ -0,0 +1,117 @@
|
|||
.\" $NetBSD: libperfuse.3,v 1.1 2010/08/25 07:16:00 manu Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.ds str-Lb-libperfuse PUFFS enabled relay to FUSE Library (libperfuse, \-lperfuse)
|
||||
.Dd August 12, 2010
|
||||
.Dt LIBPERFUSE 2
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm perfuse_mount ,
|
||||
.Nm perfuse_open
|
||||
.Nd Request a
|
||||
.Xr puffs 3 mount from
|
||||
.Xr perfused 8 .
|
||||
.Sh LIBRARY
|
||||
.Lb libperfuse
|
||||
.Sh SYNOPSIS
|
||||
.In perfuse.h
|
||||
.Ft int
|
||||
.Fn perfuse_mount "const char *source" "const char *dir" "const char *filesystemtype" "long int mountflags" "void *data"
|
||||
.Ft int
|
||||
.Fn perfuse_open "const char *path" "int flags"
|
||||
.Sh DESCRIPTION
|
||||
.Fn perfuse_mount
|
||||
sends a mount request to
|
||||
.Xr perfused 8 .
|
||||
It is intended as a drop-in replacement for
|
||||
.Xr mount 2
|
||||
for FUSE filesystems daemons and libraries, so that they can work with
|
||||
.Xr perfused 8 .
|
||||
.Pp
|
||||
The function prototype mimics Linux's
|
||||
.Xr mount 2 ,
|
||||
with the following arguments:
|
||||
.Bl -tag -width indent
|
||||
.It Ar source
|
||||
The source fileystem that will appear in
|
||||
.Xr df 1 ,
|
||||
and
|
||||
.Xr mount 8
|
||||
listings. Defaults to
|
||||
.Pa /dev/fuse
|
||||
if NULL.
|
||||
.It Ar dir
|
||||
The filesystem mount point.
|
||||
.It Ar filesystemtype
|
||||
The gileystem type, as displayed by
|
||||
.Xr df 1 ,
|
||||
and
|
||||
.Xr mount 8 .
|
||||
Defaults to "fuse"
|
||||
if NULL.
|
||||
.It Ar mountflags
|
||||
This contains the same value as in
|
||||
.Xr mount 2
|
||||
.Ar flags
|
||||
argument.
|
||||
.It Ar data
|
||||
This contains the same value as in
|
||||
.Xr mount 2
|
||||
.Ar data
|
||||
argument.
|
||||
.El
|
||||
.Pp
|
||||
.Fn perfuse_open
|
||||
is a drop-in replacement for the
|
||||
.Xr open 2
|
||||
system call where
|
||||
.Pa /dev/fuse
|
||||
is used. If
|
||||
.Ar path
|
||||
is different than
|
||||
.Pa /dev/fuse ,
|
||||
.Fn perfuse_open
|
||||
handles control to the regular
|
||||
.Xr open 2 .
|
||||
.Sh RETURN VALUES
|
||||
.Fn perfuse_mount
|
||||
returns a file descriptor to the
|
||||
.Pa /dev/fuse
|
||||
socket on success, and cause exit on failure.
|
||||
.Sh ERRORS
|
||||
.Fn perfuse_mount
|
||||
will fail when one of the following occurs:
|
||||
.Bl -tag -width Er
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xd df 1 ,
|
||||
.Xr mount 2 ,
|
||||
.Xr open 2 ,
|
||||
.Xr mount 8 ,
|
||||
.Xr perfused 8
|
||||
.Sh AUTHORS
|
||||
The program was written by
|
||||
.An Emmanuel Dreyfus
|
||||
.Aq manu@NetBSD.org .
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,416 @@
|
|||
/* $NetBSD: perfuse.c,v 1.1 2010/08/25 07:16:00 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <puffs.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#define LIBPERFUSE
|
||||
#include "perfuse.h"
|
||||
#include "perfuse_if.h"
|
||||
#include "perfuse_priv.h"
|
||||
|
||||
int perfuse_diagflags = 0; /* global used only in DPRINTF/DERR/DWARN */
|
||||
|
||||
static struct perfuse_state *init_state(void);
|
||||
static int get_fd(const char *);
|
||||
|
||||
static struct perfuse_state *
|
||||
init_state(void)
|
||||
{
|
||||
struct perfuse_state *ps;
|
||||
|
||||
if ((ps = malloc(sizeof(*ps))) == NULL)
|
||||
DERR(EX_OSERR, "malloc failed");
|
||||
|
||||
(void)memset(ps, 0, sizeof(*ps));
|
||||
ps->ps_max_write = UINT_MAX;
|
||||
ps->ps_max_readahead = UINT_MAX;
|
||||
|
||||
return ps;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
get_fd(data)
|
||||
const char *data;
|
||||
{
|
||||
char *string;
|
||||
const char fdopt[] = "fd=";
|
||||
char *lastp;
|
||||
char *opt;
|
||||
int fd = -1;
|
||||
|
||||
if ((string = strdup(data)) == NULL)
|
||||
return -1;
|
||||
|
||||
for (opt = strtok_r(string, ",", &lastp);
|
||||
opt != NULL;
|
||||
opt = strtok_r(NULL, ",", &lastp)) {
|
||||
if (strncmp(opt, fdopt, strlen(fdopt)) == 0) {
|
||||
fd = atoi(opt + strlen(fdopt));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* No file descriptor found
|
||||
*/
|
||||
if (fd == -1)
|
||||
errno = EINVAL;
|
||||
|
||||
free(string);
|
||||
return fd;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
perfuse_open(path, flags, mode)
|
||||
const char *path;
|
||||
int flags;
|
||||
mode_t mode;
|
||||
{
|
||||
int s;
|
||||
struct sockaddr_un sun;
|
||||
struct sockaddr *sa;
|
||||
|
||||
if (strcmp(path, _PATH_FUSE) != 0)
|
||||
return open(path, flags, mode);
|
||||
|
||||
if ((s = socket(PF_LOCAL, SOCK_STREAM, 0)) == -1) {
|
||||
#ifdef PERFUSE_DEBUG
|
||||
printf("%s:%d socket failed: %s",
|
||||
__func__, __LINE__, strerror(errno));
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
sa = (struct sockaddr *)(void *)&sun;
|
||||
sun.sun_len = sizeof(sun);
|
||||
sun.sun_family = AF_LOCAL;
|
||||
(void)strcpy(sun.sun_path, path);
|
||||
|
||||
if (connect(s, sa, (socklen_t)sun.sun_len) == -1) {
|
||||
#ifdef PERFUSE_DEBUG
|
||||
printf("%s:%d connect failed: %s",
|
||||
__func__, __LINE__, strerror(errno));
|
||||
#endif
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
perfuse_mount(source, target, filesystemtype, mountflags, data)
|
||||
const char *source;
|
||||
const char *target;
|
||||
const char *filesystemtype;
|
||||
long mountflags;
|
||||
const void *data;
|
||||
{
|
||||
int s;
|
||||
#if 0
|
||||
struct sockaddr_un sun;
|
||||
#endif
|
||||
size_t len;
|
||||
struct perfuse_mount_out pmo;
|
||||
|
||||
#ifdef PERFUSE_DEBUG
|
||||
printf("%s(\"%s\", \"%s\", \"%s\", 0x%lx, \"%s\")\n", __func__,
|
||||
source, target, filesystemtype, mountflags, (const char *)data);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
if ((s = socket(PF_LOCAL, SOCK_STREAM, 0)) == -1)
|
||||
err(EX_OSERR, "socket failed");
|
||||
|
||||
sun.sun_len = sizeof(sun);
|
||||
sun.sun_family = AF_LOCAL;
|
||||
(void)strcpy(sun.sun_path, _PATH_FUSE);
|
||||
|
||||
if (connect(s, (struct sockaddr *)&sun, sun.sun_len) == -1)
|
||||
err(EX_UNAVAILABLE, "cannot connect to \"%s\"", _PATH_FUSE);
|
||||
#endif
|
||||
if ((s = get_fd(data)) == -1)
|
||||
return -1;
|
||||
|
||||
|
||||
pmo.pmo_len = sizeof(pmo);
|
||||
pmo.pmo_len += source ? strlen(source) : 0;
|
||||
pmo.pmo_len += target ? strlen(target) : 0;
|
||||
pmo.pmo_len += filesystemtype ? strlen(filesystemtype) : 0;
|
||||
pmo.pmo_len += data ? strlen(data) : 0;
|
||||
pmo.pmo_error = 0;
|
||||
pmo.pmo_unique = (uint64_t)-1;
|
||||
|
||||
(void)strcpy(pmo.pmo_magic, PERFUSE_MOUNT_MAGIC);
|
||||
pmo.pmo_source_len = source ? strlen(source) : 0;
|
||||
pmo.pmo_target_len = target ? strlen(target) : 0;
|
||||
pmo.pmo_filesystemtype_len =
|
||||
filesystemtype ? strlen(filesystemtype) : 0;
|
||||
pmo.pmo_mountflags = mountflags;
|
||||
pmo.pmo_data_len = data ? strlen(data) : 0;
|
||||
|
||||
|
||||
if (write(s, &pmo, sizeof(pmo)) != sizeof(pmo)) {
|
||||
#ifdef PERFUSE_DEBUG
|
||||
printf("%s:%d short write", __func__, __LINE__);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (source) {
|
||||
len = pmo.pmo_source_len;
|
||||
if (write(s, source, len) != (ssize_t)len) {
|
||||
#ifdef PERFUSE_DEBUG
|
||||
printf("%s:%d short write", __func__, __LINE__);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (target) {
|
||||
len = pmo.pmo_target_len;
|
||||
if (write(s, target, len) != (ssize_t)len) {
|
||||
#ifdef PERFUSE_DEBUG
|
||||
printf("%s:%d short write", __func__, __LINE__);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (filesystemtype) {
|
||||
len = pmo.pmo_filesystemtype_len;
|
||||
if (write(s, filesystemtype, len) != (ssize_t)len) {
|
||||
#ifdef PERFUSE_DEBUG
|
||||
printf("%s:%d short write", __func__, __LINE__);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (data) {
|
||||
len = pmo.pmo_data_len;
|
||||
if (write(s, data, len) != (ssize_t)len) {
|
||||
#ifdef PERFUSE_DEBUG
|
||||
printf("%s:%d short write", __func__, __LINE__);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint64_t
|
||||
perfuse_next_unique(pu)
|
||||
struct puffs_usermount *pu;
|
||||
{
|
||||
struct perfuse_state *ps;
|
||||
|
||||
ps = puffs_getspecific(pu);
|
||||
|
||||
return ps->ps_unique++;
|
||||
}
|
||||
|
||||
struct puffs_usermount *
|
||||
perfuse_init(pc, pmi)
|
||||
struct perfuse_callbacks *pc;
|
||||
struct perfuse_mount_info *pmi;
|
||||
{
|
||||
struct perfuse_state *ps;
|
||||
struct puffs_usermount *pu;
|
||||
struct puffs_ops *pops;
|
||||
char name[] = "perfuse";
|
||||
unsigned int puffs_flags;
|
||||
struct puffs_node *pn_root;
|
||||
struct puffs_pathobj *po_root;
|
||||
|
||||
ps = init_state();
|
||||
ps->ps_uid = pmi->pmi_uid;
|
||||
|
||||
if (pmi->pmi_source)
|
||||
ps->ps_source = strdup(pmi->pmi_source);
|
||||
if (pmi->pmi_filesystemtype)
|
||||
ps->ps_filesystemtype = strdup(pmi->pmi_filesystemtype);
|
||||
ps->ps_target = strdup(pmi->pmi_target);
|
||||
ps->ps_mountflags = pmi->pmi_mountflags;
|
||||
|
||||
/*
|
||||
* Some options are forbidden for non root users
|
||||
*/
|
||||
if (ps->ps_uid != 0)
|
||||
ps->ps_mountflags |= MNT_NOSUID|MNT_NODEV;
|
||||
|
||||
PUFFSOP_INIT(pops);
|
||||
PUFFSOP_SET(pops, perfuse, fs, unmount);
|
||||
PUFFSOP_SET(pops, perfuse, fs, statvfs);
|
||||
PUFFSOP_SET(pops, perfuse, fs, sync);
|
||||
PUFFSOP_SET(pops, perfuse, node, lookup);
|
||||
PUFFSOP_SET(pops, perfuse, node, create);
|
||||
PUFFSOP_SET(pops, perfuse, node, mknod);
|
||||
PUFFSOP_SET(pops, perfuse, node, open);
|
||||
PUFFSOP_SET(pops, perfuse, node, close);
|
||||
PUFFSOP_SET(pops, perfuse, node, access);
|
||||
PUFFSOP_SET(pops, perfuse, node, getattr);
|
||||
PUFFSOP_SET(pops, perfuse, node, setattr);
|
||||
PUFFSOP_SET(pops, perfuse, node, poll);
|
||||
#if 0
|
||||
PUFFSOP_SET(pops, perfuse, node, mmap);
|
||||
#endif
|
||||
PUFFSOP_SET(pops, perfuse, node, fsync);
|
||||
PUFFSOP_SET(pops, perfuse, node, seek);
|
||||
PUFFSOP_SET(pops, perfuse, node, remove);
|
||||
PUFFSOP_SET(pops, perfuse, node, link);
|
||||
PUFFSOP_SET(pops, perfuse, node, rename);
|
||||
PUFFSOP_SET(pops, perfuse, node, mkdir);
|
||||
PUFFSOP_SET(pops, perfuse, node, rmdir);
|
||||
PUFFSOP_SET(pops, perfuse, node, symlink);
|
||||
PUFFSOP_SET(pops, perfuse, node, readdir);
|
||||
PUFFSOP_SET(pops, perfuse, node, readlink);
|
||||
PUFFSOP_SET(pops, perfuse, node, reclaim);
|
||||
PUFFSOP_SET(pops, perfuse, node, inactive);
|
||||
PUFFSOP_SET(pops, perfuse, node, print);
|
||||
PUFFSOP_SET(pops, perfuse, node, advlock);
|
||||
PUFFSOP_SET(pops, perfuse, node, read);
|
||||
PUFFSOP_SET(pops, perfuse, node, write);
|
||||
|
||||
puffs_flags = PUFFS_FLAG_BUILDPATH | PUFFS_FLAG_HASHPATH;
|
||||
if (perfuse_diagflags & PDF_PUFFS)
|
||||
puffs_flags |= PUFFS_FLAG_OPDUMP;
|
||||
|
||||
if ((pu = puffs_init(pops, _PATH_PUFFS, name, ps, puffs_flags)) == NULL)
|
||||
DERR(EX_OSERR, "puffs_init failed");
|
||||
|
||||
ps->ps_pu = pu;
|
||||
|
||||
/*
|
||||
* Setup filesystem root
|
||||
*/
|
||||
pn_root = perfuse_new_pn(pu, NULL);
|
||||
PERFUSE_NODE_DATA(pn_root)->pnd_ino = FUSE_ROOT_ID;
|
||||
puffs_setroot(pu, pn_root);
|
||||
ps->ps_fsid = pn_root->pn_va.va_fsid;
|
||||
|
||||
po_root = puffs_getrootpathobj(pu);
|
||||
if ((po_root->po_path = strdup("/")) == NULL)
|
||||
DERRX(EX_OSERR, "perfuse_mount_start() failed");
|
||||
|
||||
po_root->po_len = 1;
|
||||
puffs_path_buildhash(pu, po_root);
|
||||
|
||||
puffs_vattr_null(&pn_root->pn_va);
|
||||
pn_root->pn_va.va_type = VDIR;
|
||||
pn_root->pn_va.va_mode = 0755;
|
||||
|
||||
ps->ps_root = pn_root;
|
||||
|
||||
/*
|
||||
* Callbacks
|
||||
*/
|
||||
ps->ps_new_msg = pc->pc_new_msg;
|
||||
ps->ps_xchg_msg = pc->pc_xchg_msg;
|
||||
ps->ps_destroy_msg = pc->pc_destroy_msg;
|
||||
ps->ps_get_inhdr = pc->pc_get_inhdr;
|
||||
ps->ps_get_inpayload = pc->pc_get_inpayload;
|
||||
ps->ps_get_outhdr = pc->pc_get_outhdr;
|
||||
ps->ps_get_outpayload = pc->pc_get_outpayload;
|
||||
|
||||
return pu;
|
||||
}
|
||||
|
||||
void
|
||||
perfuse_setspecific(pu, priv)
|
||||
struct puffs_usermount *pu;
|
||||
void *priv;
|
||||
{
|
||||
struct perfuse_state *ps;
|
||||
|
||||
ps = puffs_getspecific(pu);
|
||||
ps->ps_private = priv;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void *
|
||||
perfuse_getspecific(pu)
|
||||
struct puffs_usermount *pu;
|
||||
{
|
||||
struct perfuse_state *ps;
|
||||
|
||||
ps = puffs_getspecific(pu);
|
||||
|
||||
return ps->ps_private;
|
||||
}
|
||||
|
||||
int
|
||||
perfuse_inloop(pu)
|
||||
struct puffs_usermount *pu;
|
||||
{
|
||||
struct perfuse_state *ps;
|
||||
|
||||
ps = puffs_getspecific(pu);
|
||||
|
||||
return ps->ps_flags & PS_INLOOP;
|
||||
}
|
||||
|
||||
int
|
||||
perfuse_mainloop(pu)
|
||||
struct puffs_usermount *pu;
|
||||
{
|
||||
struct perfuse_state *ps;
|
||||
|
||||
ps = puffs_getspecific(pu);
|
||||
|
||||
ps->ps_flags |= PS_INLOOP;
|
||||
if (puffs_mainloop(ps->ps_pu) != 0)
|
||||
DERR(EX_OSERR, "puffs_mainloop failed");
|
||||
DERR(EX_OSERR, "puffs_mainloop exit");
|
||||
|
||||
/* NOTREACHED */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ARGSUSED0 */
|
||||
uint64_t
|
||||
perfuse_get_ino(pu, opc)
|
||||
struct puffs_usermount *pu;
|
||||
puffs_cookie_t opc;
|
||||
{
|
||||
return PERFUSE_NODE_DATA(opc)->pnd_ino;
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/* $NetBSD: perfuse.h,v 1.1 2010/08/25 07:16:00 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _REFUSE_PERFUSE_WRAPPER_H
|
||||
#define _REFUSE_PERFUSE_WRAPPER_H
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
int perfuse_open(const char *, int, mode_t);
|
||||
int perfuse_mount(const char *, const char *, const char *, long, const void *);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#ifndef LIBPERFUSE
|
||||
#define mount(source, mnt, type, flags, optbuf) \
|
||||
perfuse_mount(source, mnt, type, flags, optbuf)
|
||||
#define open(path, flags) \
|
||||
perfuse_open(path, flags, 0)
|
||||
#endif /* LIBPERFUSE */
|
||||
|
||||
#endif /* _REFUSE_PERFUSE_WRAPPER_H */
|
|
@ -0,0 +1,201 @@
|
|||
/* $NetBSD: perfuse_if.h,v 1.1 2010/08/25 07:16:00 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _REFUSE_PERFUSE_H
|
||||
#define _REFUSE_PERFUSE_H
|
||||
|
||||
#define _PATH_FUSE "/dev/fuse"
|
||||
#define FUSE_COMMFD_ENV "_FUSE_COMMFD"
|
||||
#define PERFUSE_MOUNT_MAGIC "noFuseRq"
|
||||
#define PERFUSE_UNKNOWN_INO 0xffffffff
|
||||
|
||||
/*
|
||||
* Diagnostic flags. This global is used only for DPRINTF/DERR/DWARN
|
||||
*/
|
||||
extern int perfuse_diagflags;
|
||||
#define PDF_FOREGROUND 0x001 /* we run in foreground */
|
||||
#define PDF_FUSE 0x002 /* Display FUSE reqeusts and reply */
|
||||
#define PDF_DUMP 0x004 /* Dump FUSE frames */
|
||||
#define PDF_PUFFS 0x008 /* Display PUFFS requets and reply */
|
||||
#define PDF_FH 0x010 /* File handles */
|
||||
#define PDF_RECLAIM 0x020 /* Reclaimed files */
|
||||
#define PDF_READDIR 0x040 /* readdir operations */
|
||||
#define PDF_REQUEUE 0x080 /* reueued messages */
|
||||
#define PDF_MISC 0x100 /* Miscelaneous messages */
|
||||
#define PDF_SYSLOG 0x200 /* use syslog */
|
||||
|
||||
/*
|
||||
* Diagnostic functions
|
||||
*/
|
||||
#define DPRINTF(fmt, ...) do { \
|
||||
if (perfuse_diagflags & PDF_FOREGROUND) \
|
||||
(void)printf(fmt, ## __VA_ARGS__); \
|
||||
} while (0 /* CONSTCOND */)
|
||||
|
||||
#define DERRX(status, fmt, ...) do { \
|
||||
if (perfuse_diagflags & PDF_SYSLOG) \
|
||||
syslog(LOG_ERR, fmt, ## __VA_ARGS__); \
|
||||
\
|
||||
if (perfuse_diagflags & PDF_FOREGROUND) { \
|
||||
(void)fprintf(stderr, fmt, ## __VA_ARGS__); \
|
||||
abort(); \
|
||||
} else { \
|
||||
errx(status, fmt, ## __VA_ARGS__); \
|
||||
} \
|
||||
} while (0 /* CONSTCOND */)
|
||||
|
||||
#define DERR(status, fmt, ...) do { \
|
||||
char fmterr[BUFSIZ]; \
|
||||
char strerrbuf[BUFSIZ]; \
|
||||
\
|
||||
(void)strerror_r(errno, strerrbuf, sizeof(strerrbuf)); \
|
||||
(void)sprintf(fmterr, "%s: %s\n", fmt, strerrbuf); \
|
||||
\
|
||||
if (perfuse_diagflags & PDF_SYSLOG) \
|
||||
syslog(LOG_ERR, fmterr, ## __VA_ARGS__); \
|
||||
\
|
||||
if (perfuse_diagflags & PDF_FOREGROUND) { \
|
||||
(void)fprintf(stderr, fmterr, ## __VA_ARGS__); \
|
||||
abort(); \
|
||||
} else { \
|
||||
errx(status, fmt, ## __VA_ARGS__); \
|
||||
} \
|
||||
} while (0 /* CONSTCOND */)
|
||||
|
||||
#define DWARNX(fmt, ...) do { \
|
||||
if (perfuse_diagflags & PDF_SYSLOG) \
|
||||
syslog(LOG_WARNING, fmt, ## __VA_ARGS__); \
|
||||
\
|
||||
warnx(fmt, ## __VA_ARGS__); \
|
||||
} while (0 /* CONSTCOND */)
|
||||
|
||||
#define DWARN(fmt, ...) do { \
|
||||
char fmterr[BUFSIZ]; \
|
||||
char strerrbuf[BUFSIZ]; \
|
||||
\
|
||||
(void)strerror_r(errno, strerrbuf, sizeof(strerrbuf)); \
|
||||
(void)sprintf(fmterr, "%s: %s\n", fmt, strerrbuf); \
|
||||
\
|
||||
if (perfuse_diagflags & PDF_SYSLOG) \
|
||||
syslog(LOG_WARNING, fmterr, ## __VA_ARGS__); \
|
||||
\
|
||||
warn(fmterr, ## __VA_ARGS__); \
|
||||
} while (0 /* CONSTCOND */)
|
||||
|
||||
/*
|
||||
* frame handling callbacks
|
||||
*/
|
||||
#ifndef PEFUSE_MSG_T
|
||||
#define PEFUSE_MSG_T struct perfuse_framebuf
|
||||
#endif
|
||||
typedef PEFUSE_MSG_T perfuse_msg_t;
|
||||
|
||||
#define PERFUSE_UNSPEC_REPLY_LEN (size_t)-1
|
||||
|
||||
enum perfuse_xchg_pb_reply { wait_reply, no_reply };
|
||||
typedef perfuse_msg_t *(*perfuse_new_msg_fn)(struct puffs_usermount *,
|
||||
puffs_cookie_t, int, size_t, const struct puffs_cred *);
|
||||
typedef int (*perfuse_xchg_msg_fn)(struct puffs_usermount *,
|
||||
perfuse_msg_t *, size_t, enum perfuse_xchg_pb_reply);
|
||||
typedef void (*perfuse_destroy_msg_fn)(perfuse_msg_t *);
|
||||
typedef struct fuse_out_header *(*perfuse_get_outhdr_fn)(perfuse_msg_t *);
|
||||
typedef struct fuse_in_header *(*perfuse_get_inhdr_fn)(perfuse_msg_t *);
|
||||
typedef char *(*perfuse_get_inpayload_fn)(perfuse_msg_t *);
|
||||
typedef char *(*perfuse_get_outpayload_fn)(perfuse_msg_t *);
|
||||
|
||||
struct perfuse_callbacks {
|
||||
perfuse_new_msg_fn pc_new_msg;
|
||||
perfuse_xchg_msg_fn pc_xchg_msg;
|
||||
perfuse_destroy_msg_fn pc_destroy_msg;
|
||||
perfuse_get_inhdr_fn pc_get_inhdr;
|
||||
perfuse_get_inpayload_fn pc_get_inpayload;
|
||||
perfuse_get_outhdr_fn pc_get_outhdr;
|
||||
perfuse_get_outpayload_fn pc_get_outpayload;
|
||||
};
|
||||
|
||||
/*
|
||||
* mount request
|
||||
*/
|
||||
struct perfuse_mount_out {
|
||||
uint32_t pmo_len;
|
||||
int32_t pmo_error;
|
||||
uint64_t pmo_unique;
|
||||
char pmo_magic[sizeof(PERFUSE_MOUNT_MAGIC)];
|
||||
size_t pmo_source_len;
|
||||
size_t pmo_target_len;
|
||||
size_t pmo_filesystemtype_len;
|
||||
int pmo_mountflags;
|
||||
size_t pmo_data_len;
|
||||
};
|
||||
|
||||
struct perfuse_mount_info {
|
||||
const char *pmi_source;
|
||||
const char *pmi_target;
|
||||
const char *pmi_filesystemtype;
|
||||
int pmi_mountflags;
|
||||
void *pmi_data;
|
||||
uid_t pmi_uid;
|
||||
};
|
||||
|
||||
/*
|
||||
* Duplicated fro fuse.h to avoid making it public
|
||||
*/
|
||||
#define FUSE_MIN_BUFSIZE 0x21000
|
||||
#define FUSE_PREF_BUFSIZE (PAGE_SIZE + 0x1000)
|
||||
#define FUSE_BUFSIZE MAX(FUSE_PREF_BUFSIZE, FUSE_MIN_BUFSIZE)
|
||||
|
||||
struct fuse_in_header {
|
||||
uint32_t len;
|
||||
uint32_t opcode;
|
||||
uint64_t unique;
|
||||
uint64_t nodeid;
|
||||
uint32_t uid;
|
||||
uint32_t gid;
|
||||
uint32_t pid;
|
||||
uint32_t padding;
|
||||
};
|
||||
|
||||
struct fuse_out_header {
|
||||
uint32_t len;
|
||||
int32_t error;
|
||||
uint64_t unique;
|
||||
};
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
struct puffs_usermount *perfuse_init(struct perfuse_callbacks *,
|
||||
struct perfuse_mount_info *);
|
||||
void perfuse_setspecific(struct puffs_usermount *, void *);
|
||||
void *perfuse_getspecific(struct puffs_usermount *);
|
||||
uint64_t perfuse_next_unique(struct puffs_usermount *);
|
||||
uint64_t perfuse_get_ino(struct puffs_usermount *, puffs_cookie_t);
|
||||
int perfuse_inloop(struct puffs_usermount *);
|
||||
const char *perfuse_opname(int);
|
||||
void perfuse_fs_init(struct puffs_usermount *);
|
||||
int perfuse_mainloop(struct puffs_usermount *);
|
||||
|
||||
#endif /* _REFUSE_PERFUSE_H */
|
|
@ -0,0 +1,215 @@
|
|||
/* $NetBSD: perfuse_priv.h,v 1.1 2010/08/25 07:16:00 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _PERFUSE_PRIV_H_
|
||||
#define _PERFUSE_PRIV_H_
|
||||
|
||||
#include <syslog.h>
|
||||
#include <paths.h>
|
||||
#include <err.h>
|
||||
#include <sysexits.h>
|
||||
#include <puffs.h>
|
||||
|
||||
#include "perfuse_if.h"
|
||||
#include "fuse.h"
|
||||
|
||||
struct perfuse_state {
|
||||
void *ps_private; /* Private field for libperfuse user */
|
||||
struct puffs_usermount *ps_pu;
|
||||
struct puffs_node *ps_root;
|
||||
uid_t ps_uid;
|
||||
gid_t ps_gid;
|
||||
pid_t ps_pid;
|
||||
int ps_flags;
|
||||
#define PS_NO_ACCESS 0x0001 /* access is unimplemented; */
|
||||
#define PS_NO_FSYNC 0x0002 /* fsync is unimplemented */
|
||||
#define PS_NO_CREAT 0x0004 /* create is unimplemented */
|
||||
#define PS_INLOOP 0x0008 /* puffs mainloop started */
|
||||
long ps_fsid;
|
||||
uint32_t ps_max_readahead;
|
||||
uint32_t ps_max_write;
|
||||
uint64_t ps_syncreads;
|
||||
uint64_t ps_syncwrites;
|
||||
uint64_t ps_asyncreads;
|
||||
uint64_t ps_asyncwrites;
|
||||
char *ps_source;
|
||||
char *ps_target;
|
||||
char *ps_filesystemtype;
|
||||
int ps_mountflags;
|
||||
uint64_t ps_unique;
|
||||
uint32_t ps_readahead;
|
||||
uint32_t ps_write;
|
||||
perfuse_new_msg_fn ps_new_msg;
|
||||
perfuse_xchg_msg_fn ps_xchg_msg;
|
||||
perfuse_destroy_msg_fn ps_destroy_msg;
|
||||
perfuse_get_inhdr_fn ps_get_inhdr;
|
||||
perfuse_get_inpayload_fn ps_get_inpayload;
|
||||
perfuse_get_outhdr_fn ps_get_outhdr;
|
||||
perfuse_get_outpayload_fn ps_get_outpayload;
|
||||
};
|
||||
|
||||
|
||||
struct perfuse_file_handle {
|
||||
uint64_t pfh_fh;
|
||||
TAILQ_ENTRY(perfuse_file_handle) pfh_entries;
|
||||
};
|
||||
|
||||
|
||||
enum perfuse_qtype { PCQ_READDIR, PCQ_READ, PCQ_WRITE };
|
||||
|
||||
struct perfuse_cc_queue {
|
||||
enum perfuse_qtype pcq_type;
|
||||
struct puffs_cc *pcq_cc;
|
||||
TAILQ_ENTRY(perfuse_cc_queue) pcq_next;
|
||||
};
|
||||
|
||||
|
||||
struct perfuse_node_data {
|
||||
TAILQ_HEAD(,perfuse_file_handle) pnd_fh;
|
||||
uint64_t pnd_ino; /* inode */
|
||||
uint64_t pnd_nlookup; /* vnode refcount */
|
||||
uint64_t pnd_offset; /* seek state */
|
||||
uint64_t pnd_lock_owner;
|
||||
struct dirent *pnd_dirent; /* native buffer for readdir */
|
||||
size_t pnd_dirent_len;
|
||||
struct fuse_dirent *pnd_all_fd; /* FUSE buffer for readdir */
|
||||
size_t pnd_all_fd_len;
|
||||
TAILQ_HEAD(,perfuse_cc_queue) pnd_pcq; /* queued requests */
|
||||
int pnd_flags;
|
||||
#define PND_RECLAIMED 0x1 /* reclaim pending */
|
||||
#define PND_INREADDIR 0x2 /* readdir in progress */
|
||||
puffs_cookie_t pnd_parent;
|
||||
int pnd_childcount;
|
||||
};
|
||||
|
||||
#define PERFUSE_NODE_DATA(opc) \
|
||||
((struct perfuse_node_data *)puffs_pn_getpriv((struct puffs_node *)opc))
|
||||
|
||||
|
||||
#define UNSPEC_REPLY_LEN PERFUSE_UNSPEC_REPLY_LEN /* shorter! */
|
||||
#define NO_PAYLOAD_REPLY_LEN 0
|
||||
|
||||
#define GET_INHDR(ps, pm) ps->ps_get_inhdr(pm)
|
||||
#define GET_INPAYLOAD(ps, pm, type) \
|
||||
(struct type *)(void *)ps->ps_get_inpayload(pm)
|
||||
#define _GET_INPAYLOAD(ps, pm, type) (type)ps->ps_get_inpayload(pm)
|
||||
#define GET_OUTHDR(ps, pm) ps->ps_get_outhdr(pm)
|
||||
#define GET_OUTPAYLOAD(ps, pm, type) \
|
||||
(struct type *)(void *)ps->ps_get_outpayload(pm)
|
||||
#define _GET_OUTPAYLOAD(ps, pm, type) (type)ps->ps_get_outpayload(pm)
|
||||
|
||||
#define XCHG_MSG(ps, pu, opc, len) ps->ps_xchg_msg(pu, opc, len, wait_reply)
|
||||
#define XCHG_MSG_NOREPLY(ps, pu, opc, len) \
|
||||
ps->ps_xchg_msg(pu, opc, len, no_reply)
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
struct puffs_node *perfuse_new_pn(struct puffs_usermount *,
|
||||
struct puffs_node *);
|
||||
void perfuse_destroy_pn(struct puffs_node *);
|
||||
void perfuse_new_fh(puffs_cookie_t, uint64_t);
|
||||
void perfuse_destroy_fh(puffs_cookie_t, uint64_t);
|
||||
uint64_t perfuse_get_fh(puffs_cookie_t);
|
||||
uint64_t perfuse_next_unique(struct puffs_usermount *);
|
||||
|
||||
char *perfuse_fs_mount(int, ssize_t);
|
||||
|
||||
|
||||
/*
|
||||
* opc.c - filesystem operations
|
||||
*/
|
||||
int perfuse_fs_unmount(struct puffs_usermount *, int);
|
||||
int perfuse_fs_statvfs(struct puffs_usermount *, struct statvfs *);
|
||||
int perfuse_fs_sync(struct puffs_usermount *, int,
|
||||
const struct puffs_cred *);
|
||||
int perfuse_fs_fhtonode(struct puffs_usermount *, void *, size_t,
|
||||
struct puffs_newinfo *);
|
||||
int perfuse_fs_nodetofh(struct puffs_usermount *, puffs_cookie_t,
|
||||
void *, size_t *);
|
||||
void perfuse_fs_suspend(struct puffs_usermount *, int);
|
||||
int perfuse_node_lookup(struct puffs_usermount *,
|
||||
puffs_cookie_t, struct puffs_newinfo *, const struct puffs_cn *);
|
||||
int perfuse_node_create(struct puffs_usermount *,
|
||||
puffs_cookie_t, struct puffs_newinfo *, const struct puffs_cn *,
|
||||
const struct vattr *);
|
||||
int perfuse_node_mknod(struct puffs_usermount *,
|
||||
puffs_cookie_t, struct puffs_newinfo *, const struct puffs_cn *,
|
||||
const struct vattr *);
|
||||
int perfuse_node_open(struct puffs_usermount *,
|
||||
puffs_cookie_t, int, const struct puffs_cred *);
|
||||
int perfuse_node_close(struct puffs_usermount *,
|
||||
puffs_cookie_t, int, const struct puffs_cred *);
|
||||
int perfuse_node_access(struct puffs_usermount *,
|
||||
puffs_cookie_t, int, const struct puffs_cred *);
|
||||
int perfuse_node_getattr(struct puffs_usermount *,
|
||||
puffs_cookie_t, struct vattr *, const struct puffs_cred *);
|
||||
int perfuse_node_setattr(struct puffs_usermount *,
|
||||
puffs_cookie_t, const struct vattr *, const struct puffs_cred *);
|
||||
int perfuse_node_poll(struct puffs_usermount *, puffs_cookie_t, int *);
|
||||
int perfuse_node_mmap(struct puffs_usermount *,
|
||||
puffs_cookie_t, vm_prot_t, const struct puffs_cred *);
|
||||
int perfuse_node_fsync(struct puffs_usermount *,
|
||||
puffs_cookie_t, const struct puffs_cred *, int, off_t, off_t);
|
||||
int perfuse_node_seek(struct puffs_usermount *,
|
||||
puffs_cookie_t, off_t, off_t, const struct puffs_cred *);
|
||||
int perfuse_node_remove(struct puffs_usermount *,
|
||||
puffs_cookie_t, puffs_cookie_t, const struct puffs_cn *);
|
||||
int perfuse_node_link(struct puffs_usermount *,
|
||||
puffs_cookie_t, puffs_cookie_t, const struct puffs_cn *);
|
||||
int perfuse_node_rename(struct puffs_usermount *,
|
||||
puffs_cookie_t, puffs_cookie_t, const struct puffs_cn *,
|
||||
puffs_cookie_t, puffs_cookie_t, const struct puffs_cn *);
|
||||
int perfuse_node_mkdir(struct puffs_usermount *,
|
||||
puffs_cookie_t, struct puffs_newinfo *, const struct puffs_cn *,
|
||||
const struct vattr *);
|
||||
int perfuse_node_rmdir(struct puffs_usermount *,
|
||||
puffs_cookie_t, puffs_cookie_t, const struct puffs_cn *);
|
||||
int perfuse_node_symlink(struct puffs_usermount *,
|
||||
puffs_cookie_t, struct puffs_newinfo *, const struct puffs_cn *,
|
||||
const struct vattr *, const char *);
|
||||
int perfuse_node_readdir(struct puffs_usermount *,
|
||||
puffs_cookie_t, struct dirent *, off_t *, size_t *,
|
||||
const struct puffs_cred *, int *, off_t *, size_t *);
|
||||
int perfuse_node_readlink(struct puffs_usermount *,
|
||||
puffs_cookie_t, const struct puffs_cred *, char *, size_t *);
|
||||
int perfuse_node_reclaim(struct puffs_usermount *, puffs_cookie_t);
|
||||
int perfuse_node_inactive(struct puffs_usermount *, puffs_cookie_t);
|
||||
int perfuse_node_print(struct puffs_usermount *, puffs_cookie_t);
|
||||
int perfuse_node_pathconf(struct puffs_usermount *,
|
||||
puffs_cookie_t, int, int *);
|
||||
int perfuse_node_advlock(struct puffs_usermount *,
|
||||
puffs_cookie_t, void *, int, struct flock *, int);
|
||||
int perfuse_node_read(struct puffs_usermount *, puffs_cookie_t,
|
||||
uint8_t *, off_t, size_t *, const struct puffs_cred *, int);
|
||||
int perfuse_node_write(struct puffs_usermount *, puffs_cookie_t,
|
||||
uint8_t *, off_t, size_t *, const struct puffs_cred *, int);
|
||||
void perfuse_cache_write(struct puffs_usermount *,
|
||||
puffs_cookie_t, size_t, struct puffs_cacherun *);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _PERFUSE_PRIV_H_ */
|
|
@ -0,0 +1,4 @@
|
|||
# $NetBSD: shlib_version,v 1.1 2010/08/25 07:16:00 manu Exp $
|
||||
#
|
||||
major=0
|
||||
minor=0
|
|
@ -0,0 +1,160 @@
|
|||
/* $NetBSD: subr.c,v 1.1 2010/08/25 07:16:00 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <sysexits.h>
|
||||
#include <syslog.h>
|
||||
#include <puffs.h>
|
||||
#include <paths.h>
|
||||
|
||||
#include "perfuse_priv.h"
|
||||
|
||||
struct puffs_node *
|
||||
perfuse_new_pn(pu, parent)
|
||||
struct puffs_usermount *pu;
|
||||
struct puffs_node *parent;
|
||||
{
|
||||
struct puffs_node *pn;
|
||||
struct perfuse_node_data *pnd;
|
||||
|
||||
if ((pnd = malloc(sizeof(*pnd))) == NULL)
|
||||
DERR(EX_OSERR, "malloc failed");
|
||||
|
||||
if ((pn = puffs_pn_new(pu, pnd)) == NULL)
|
||||
DERR(EX_SOFTWARE, "puffs_pn_new failed");
|
||||
|
||||
(void)memset(pnd, 0, sizeof(*pnd));
|
||||
TAILQ_INIT(&pnd->pnd_fh);
|
||||
pnd->pnd_ino = PERFUSE_UNKNOWN_INO;
|
||||
pnd->pnd_nlookup = 1;
|
||||
pnd->pnd_parent = parent;
|
||||
TAILQ_INIT(&pnd->pnd_pcq);
|
||||
|
||||
if (parent != NULL)
|
||||
PERFUSE_NODE_DATA(parent)->pnd_childcount++;
|
||||
|
||||
return pn;
|
||||
}
|
||||
|
||||
void
|
||||
perfuse_destroy_pn(pn)
|
||||
struct puffs_node *pn;
|
||||
{
|
||||
struct perfuse_node_data *pnd;
|
||||
|
||||
if ((pnd = puffs_pn_getpriv(pn)) != NULL) {
|
||||
if (pnd->pnd_parent != NULL)
|
||||
PERFUSE_NODE_DATA(pnd->pnd_parent)->pnd_childcount--;
|
||||
|
||||
if (pnd->pnd_dirent != NULL)
|
||||
free(pnd->pnd_dirent);
|
||||
|
||||
if (pnd->pnd_all_fd != NULL)
|
||||
free(pnd->pnd_all_fd);
|
||||
#ifdef PERFUSE_DEBUG
|
||||
if (!TAILQ_EMPTY(&pnd->pnd_fh))
|
||||
DERRX(EX_SOFTWARE, "%s: non empty pnd_fh", __func__);
|
||||
|
||||
if (!TAILQ_EMPTY(&pnd->pnd_pcq))
|
||||
DERRX(EX_SOFTWARE, "%s: non empty pnd_pcq", __func__);
|
||||
#endif /* PERFUSE_DEBUG */
|
||||
|
||||
free(pnd);
|
||||
}
|
||||
|
||||
puffs_pn_remove(pn);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
perfuse_new_fh(opc, fh)
|
||||
puffs_cookie_t opc;
|
||||
uint64_t fh;
|
||||
{
|
||||
struct perfuse_node_data *pnd;
|
||||
struct perfuse_file_handle *pfh;
|
||||
|
||||
if (fh == FUSE_UNKNOWN_FH)
|
||||
return;
|
||||
|
||||
pnd = PERFUSE_NODE_DATA(opc);
|
||||
|
||||
if ((pfh = malloc(sizeof(*pfh))) == NULL)
|
||||
DERR(EX_OSERR, "malloc failed");
|
||||
|
||||
pfh->pfh_fh = fh;
|
||||
|
||||
TAILQ_INSERT_TAIL(&pnd->pnd_fh, pfh, pfh_entries);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
perfuse_destroy_fh(opc, fh)
|
||||
puffs_cookie_t opc;
|
||||
uint64_t fh;
|
||||
{
|
||||
struct perfuse_node_data *pnd;
|
||||
struct perfuse_file_handle *pfh;
|
||||
|
||||
pnd = PERFUSE_NODE_DATA(opc);
|
||||
|
||||
TAILQ_FOREACH(pfh, &pnd->pnd_fh, pfh_entries) {
|
||||
if (pfh->pfh_fh == fh) {
|
||||
TAILQ_REMOVE(&pnd->pnd_fh, pfh, pfh_entries);
|
||||
free(pfh);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pfh == NULL)
|
||||
warnx("%s: unexistant fh = %lld (double close?)", __func__, fh);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
perfuse_get_fh(opc)
|
||||
puffs_cookie_t opc;
|
||||
{
|
||||
struct perfuse_node_data *pnd;
|
||||
struct perfuse_file_handle *pfh;
|
||||
uint64_t fh = FUSE_UNKNOWN_FH;
|
||||
|
||||
pnd = PERFUSE_NODE_DATA(opc);
|
||||
|
||||
if ((pfh = TAILQ_FIRST(&pnd->pnd_fh)) != NULL)
|
||||
fh = pfh->pfh_fh;;
|
||||
|
||||
return fh;
|
||||
}
|
||||
|
Loading…
Reference in New Issue