9pfuse
This commit is contained in:
parent
30f8beab32
commit
5551e51d2b
7 changed files with 2395 additions and 0 deletions
62
man/man4/9pfuse.4
Normal file
62
man/man4/9pfuse.4
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
.TH 9PFUSE 4
|
||||||
|
.SH NAME
|
||||||
|
9pfuse \- mount 9P service via FUSE
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B 9pfuse
|
||||||
|
[
|
||||||
|
.B -D
|
||||||
|
]
|
||||||
|
[
|
||||||
|
.B -a
|
||||||
|
.I t
|
||||||
|
]
|
||||||
|
[
|
||||||
|
.B -e
|
||||||
|
.I t
|
||||||
|
]
|
||||||
|
.I addr
|
||||||
|
.I mtpt
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.I 9pfuse
|
||||||
|
mounts the 9P service running at
|
||||||
|
.I addr
|
||||||
|
onto
|
||||||
|
.I mtpt
|
||||||
|
using the FUSE user-level file system driver.
|
||||||
|
.PP
|
||||||
|
.I 9pfuse
|
||||||
|
sets up the initial mount and then forks itself
|
||||||
|
into the background, where it serves the FUSE
|
||||||
|
protocol, translating the requests into 9P.
|
||||||
|
.PP
|
||||||
|
The options are:
|
||||||
|
.TP
|
||||||
|
.B -D
|
||||||
|
Print each FUSE and 9P message to standard error.
|
||||||
|
.TP
|
||||||
|
.B -a\fI t
|
||||||
|
Set the kernel cache timeout for attribute information
|
||||||
|
to
|
||||||
|
.I t
|
||||||
|
(default 1.0) seconds.
|
||||||
|
.TP
|
||||||
|
.B -e\fI t
|
||||||
|
Set the kernel cache timeout for directory entries to
|
||||||
|
.I t
|
||||||
|
(default 1.0) seconds.
|
||||||
|
.PD
|
||||||
|
.PP
|
||||||
|
The
|
||||||
|
.I fusermount
|
||||||
|
binary must exist in the current search path.
|
||||||
|
.PP
|
||||||
|
FUSE is available for Linux 2.4.21 and later,
|
||||||
|
Linux 2.6, and FreeBSD 6.x and later.
|
||||||
|
.SH SEE ALSO
|
||||||
|
FUSE Homepage,
|
||||||
|
.HR http://fuse.sourceforge.net
|
||||||
|
.PP
|
||||||
|
FUSE for FreeBSD,
|
||||||
|
.HR http://fuse4bsd.creo.hu
|
||||||
|
.SH SOURCE
|
||||||
|
.B \*9/src/cmd/9pfuse
|
||||||
17
src/cmd/9pfuse/COPYRIGHT
Normal file
17
src/cmd/9pfuse/COPYRIGHT
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
The files in this directory are subject to the following license.
|
||||||
|
|
||||||
|
The author of this software is Russ Cox.
|
||||||
|
|
||||||
|
Copyright (c) 2006 Russ Cox
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
|
purpose without fee is hereby granted, provided that this entire notice
|
||||||
|
is included in all copies of any software which is or includes a copy
|
||||||
|
or modification of this software and in all copies of the supporting
|
||||||
|
documentation for such software.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
|
||||||
|
WARRANTY. IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION OR WARRANTY
|
||||||
|
OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS
|
||||||
|
FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||||
|
|
||||||
51
src/cmd/9pfuse/a.h
Normal file
51
src/cmd/9pfuse/a.h
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <fcall.h>
|
||||||
|
#include <thread.h>
|
||||||
|
#include <9pclient.h>
|
||||||
|
#include "fuse_kernel.h"
|
||||||
|
|
||||||
|
/* Somehow the FUSE guys forgot to define this one! */
|
||||||
|
struct fuse_create_out {
|
||||||
|
struct fuse_entry_out e;
|
||||||
|
struct fuse_open_out o;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct FuseMsg FuseMsg;
|
||||||
|
struct FuseMsg
|
||||||
|
{
|
||||||
|
FuseMsg *next;
|
||||||
|
uchar *buf;
|
||||||
|
int nbuf;
|
||||||
|
struct fuse_in_header *hdr; /* = buf */
|
||||||
|
void *tx; /* = hdr+1 */
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int debug;
|
||||||
|
|
||||||
|
extern int fusefd;
|
||||||
|
extern int fuseeof;
|
||||||
|
extern int fusebufsize;
|
||||||
|
extern int fusemaxwrite;
|
||||||
|
extern FuseMsg *fusemsglist;
|
||||||
|
extern char *fusemtpt;
|
||||||
|
|
||||||
|
void freefusemsg(FuseMsg *m);
|
||||||
|
int fusefmt(Fmt*);
|
||||||
|
void initfuse(char *mtpt);
|
||||||
|
FuseMsg* readfusemsg(void);
|
||||||
|
void replyfuse(FuseMsg *m, void *arg, int narg);
|
||||||
|
void replyfuseerrno(FuseMsg *m, int e);
|
||||||
|
void replyfuseerrstr(FuseMsg*);
|
||||||
|
void request9p(Fcall *tx);
|
||||||
|
|
||||||
|
void* emalloc(size_t n);
|
||||||
|
void* erealloc(void *p, size_t n);
|
||||||
|
char* estrdup(char *p);
|
||||||
|
|
||||||
|
int errstr2errno(void);
|
||||||
|
void unmountatexit(void);
|
||||||
|
|
||||||
772
src/cmd/9pfuse/fuse.c
Normal file
772
src/cmd/9pfuse/fuse.c
Normal file
|
|
@ -0,0 +1,772 @@
|
||||||
|
#include "a.h"
|
||||||
|
|
||||||
|
int fusefd;
|
||||||
|
int fuseeof;
|
||||||
|
int fusebufsize;
|
||||||
|
int fusemaxwrite;
|
||||||
|
FuseMsg *fusemsglist;
|
||||||
|
|
||||||
|
FuseMsg*
|
||||||
|
allocfusemsg(void)
|
||||||
|
{
|
||||||
|
FuseMsg *m;
|
||||||
|
void *vbuf;
|
||||||
|
|
||||||
|
if((m = fusemsglist) != nil){
|
||||||
|
fusemsglist = m->next;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
m = emalloc(sizeof(*m) + fusebufsize);
|
||||||
|
vbuf = m+1;
|
||||||
|
m->buf = vbuf;
|
||||||
|
m->nbuf = 0;
|
||||||
|
m->hdr = vbuf;
|
||||||
|
m->tx = m->hdr+1;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
freefusemsg(FuseMsg *m)
|
||||||
|
{
|
||||||
|
m->next = fusemsglist;
|
||||||
|
fusemsglist = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
FuseMsg*
|
||||||
|
readfusemsg(void)
|
||||||
|
{
|
||||||
|
FuseMsg *m;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
m = allocfusemsg();
|
||||||
|
errno = 0;
|
||||||
|
/*
|
||||||
|
* The FUSE kernel device apparently guarantees
|
||||||
|
* that this read will return exactly one message.
|
||||||
|
* You get an error return if you ask for just the
|
||||||
|
* length (first 4 bytes).
|
||||||
|
* FUSE returns an ENODEV error, not EOF,
|
||||||
|
* when the connection is unmounted.
|
||||||
|
*/
|
||||||
|
if((n = read(fusefd, m->buf, fusebufsize)) < 0){
|
||||||
|
if(errno != ENODEV)
|
||||||
|
sysfatal("readfusemsg: %r");
|
||||||
|
}
|
||||||
|
if(n <= 0){
|
||||||
|
fuseeof = 1;
|
||||||
|
freefusemsg(m);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
m->nbuf = n;
|
||||||
|
if(m->hdr->len != n)
|
||||||
|
sysfatal("readfusemsg: got %d wanted %d",
|
||||||
|
n, m->hdr->len);
|
||||||
|
m->hdr->len -= sizeof(m->hdr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Paranoia.
|
||||||
|
* Make sure lengths are long enough.
|
||||||
|
* Make sure string arguments are NUL terminated.
|
||||||
|
* (I don't trust the kernel module.)
|
||||||
|
*/
|
||||||
|
switch(m->hdr->opcode){
|
||||||
|
default:
|
||||||
|
/*
|
||||||
|
* Could sysfatal here, but can also let message go
|
||||||
|
* and assume higher-level code will return an
|
||||||
|
* "I don't know what you mean" error and recover.
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
case FUSE_LOOKUP:
|
||||||
|
case FUSE_UNLINK:
|
||||||
|
case FUSE_RMDIR:
|
||||||
|
case FUSE_REMOVEXATTR:
|
||||||
|
/* just a string */
|
||||||
|
if(((char*)m->tx)[m->hdr->len-1] != 0)
|
||||||
|
bad:
|
||||||
|
sysfatal("readfusemsg: bad message");
|
||||||
|
break;
|
||||||
|
case FUSE_FORGET:
|
||||||
|
if(m->hdr->len < sizeof(struct fuse_forget_in))
|
||||||
|
goto bad;
|
||||||
|
break;
|
||||||
|
case FUSE_GETATTR:
|
||||||
|
break;
|
||||||
|
case FUSE_SETATTR:
|
||||||
|
if(m->hdr->len < sizeof(struct fuse_setattr_in))
|
||||||
|
goto bad;
|
||||||
|
break;
|
||||||
|
case FUSE_READLINK:
|
||||||
|
break;
|
||||||
|
case FUSE_SYMLINK:
|
||||||
|
/* two strings */
|
||||||
|
if(((char*)m->tx)[m->hdr->len-1] != 0
|
||||||
|
|| memchr(m->tx, 0, m->hdr->len-1) == 0)
|
||||||
|
goto bad;
|
||||||
|
break;
|
||||||
|
case FUSE_MKNOD:
|
||||||
|
if(m->hdr->len <= sizeof(struct fuse_mknod_in)
|
||||||
|
|| ((char*)m->tx)[m->hdr->len-1] != 0)
|
||||||
|
goto bad;
|
||||||
|
break;
|
||||||
|
case FUSE_MKDIR:
|
||||||
|
if(m->hdr->len <= sizeof(struct fuse_mkdir_in)
|
||||||
|
|| ((char*)m->tx)[m->hdr->len-1] != 0)
|
||||||
|
goto bad;
|
||||||
|
break;
|
||||||
|
case FUSE_RENAME:
|
||||||
|
/* a struct and two strings */
|
||||||
|
if(m->hdr->len <= sizeof(struct fuse_rename_in)
|
||||||
|
|| ((char*)m->tx)[m->hdr->len-1] != 0
|
||||||
|
|| memchr((uchar*)m->tx+sizeof(struct fuse_rename_in), 0, m->hdr->len-sizeof(struct fuse_rename_in)-1) == 0)
|
||||||
|
goto bad;
|
||||||
|
break;
|
||||||
|
case FUSE_LINK:
|
||||||
|
if(m->hdr->len <= sizeof(struct fuse_link_in)
|
||||||
|
|| ((char*)m->tx)[m->hdr->len-1] != 0)
|
||||||
|
goto bad;
|
||||||
|
break;
|
||||||
|
case FUSE_OPEN:
|
||||||
|
case FUSE_OPENDIR:
|
||||||
|
if(m->hdr->len < sizeof(struct fuse_open_in))
|
||||||
|
goto bad;
|
||||||
|
break;
|
||||||
|
case FUSE_READ:
|
||||||
|
case FUSE_READDIR:
|
||||||
|
if(m->hdr->len < sizeof(struct fuse_read_in))
|
||||||
|
goto bad;
|
||||||
|
break;
|
||||||
|
case FUSE_WRITE:
|
||||||
|
/* no strings, but check that write length is sane */
|
||||||
|
if(m->hdr->len < sizeof(struct fuse_write_in)+((struct fuse_write_in*)m->tx)->size)
|
||||||
|
goto bad;
|
||||||
|
break;
|
||||||
|
case FUSE_STATFS:
|
||||||
|
break;
|
||||||
|
case FUSE_RELEASE:
|
||||||
|
case FUSE_RELEASEDIR:
|
||||||
|
if(m->hdr->len < sizeof(struct fuse_release_in))
|
||||||
|
goto bad;
|
||||||
|
break;
|
||||||
|
case FUSE_FSYNC:
|
||||||
|
case FUSE_FSYNCDIR:
|
||||||
|
if(m->hdr->len < sizeof(struct fuse_fsync_in))
|
||||||
|
goto bad;
|
||||||
|
break;
|
||||||
|
case FUSE_SETXATTR:
|
||||||
|
/* struct and two strings */
|
||||||
|
if(m->hdr->len <= sizeof(struct fuse_setxattr_in)
|
||||||
|
|| ((char*)m->tx)[m->hdr->len-1] != 0
|
||||||
|
|| memchr((uchar*)m->tx+sizeof(struct fuse_setxattr_in), 0, m->hdr->len-sizeof(struct fuse_setxattr_in)-1) == 0)
|
||||||
|
goto bad;
|
||||||
|
break;
|
||||||
|
case FUSE_GETXATTR:
|
||||||
|
/* struct and one string */
|
||||||
|
if(m->hdr->len <= sizeof(struct fuse_getxattr_in)
|
||||||
|
|| ((char*)m->tx)[m->hdr->len-1] != 0)
|
||||||
|
goto bad;
|
||||||
|
break;
|
||||||
|
case FUSE_LISTXATTR:
|
||||||
|
if(m->hdr->len < sizeof(struct fuse_getxattr_in))
|
||||||
|
goto bad;
|
||||||
|
break;
|
||||||
|
case FUSE_FLUSH:
|
||||||
|
if(m->hdr->len < sizeof(struct fuse_flush_in))
|
||||||
|
goto bad;
|
||||||
|
break;
|
||||||
|
case FUSE_INIT:
|
||||||
|
if(m->hdr->len < sizeof(struct fuse_init_in))
|
||||||
|
goto bad;
|
||||||
|
break;
|
||||||
|
case FUSE_ACCESS:
|
||||||
|
if(m->hdr->len < sizeof(struct fuse_access_in))
|
||||||
|
goto bad;
|
||||||
|
break;
|
||||||
|
case FUSE_CREATE:
|
||||||
|
if(m->hdr->len <= sizeof(struct fuse_open_in)
|
||||||
|
|| ((char*)m->tx)[m->hdr->len-1] != 0)
|
||||||
|
goto bad;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(debug)
|
||||||
|
fprint(2, "FUSE -> %G\n", m->hdr, m->tx);
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reply to FUSE request m using additonal
|
||||||
|
* argument buffer arg of size narg bytes.
|
||||||
|
* Perhaps should free the FuseMsg here?
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
replyfuse(FuseMsg *m, void *arg, int narg)
|
||||||
|
{
|
||||||
|
struct iovec vec[2];
|
||||||
|
struct fuse_out_header hdr;
|
||||||
|
int nvec;
|
||||||
|
|
||||||
|
hdr.len = sizeof hdr + narg;
|
||||||
|
hdr.error = 0;
|
||||||
|
hdr.unique = m->hdr->unique;
|
||||||
|
if(debug)
|
||||||
|
fprint(2, "FUSE <- %#G\n", m->hdr, &hdr, arg);
|
||||||
|
|
||||||
|
vec[0].iov_base = &hdr;
|
||||||
|
vec[0].iov_len = sizeof hdr;
|
||||||
|
nvec = 1;
|
||||||
|
if(arg && narg){
|
||||||
|
vec[1].iov_base = arg;
|
||||||
|
vec[1].iov_len = narg;
|
||||||
|
nvec++;
|
||||||
|
}
|
||||||
|
if(writev(fusefd, vec, nvec) < 0)
|
||||||
|
sysfatal("replyfuse: %r");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reply to FUSE request m with errno e.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
replyfuseerrno(FuseMsg *m, int e)
|
||||||
|
{
|
||||||
|
struct fuse_out_header hdr;
|
||||||
|
|
||||||
|
hdr.len = sizeof hdr;
|
||||||
|
hdr.error = -e; /* FUSE sends negative errnos. */
|
||||||
|
hdr.unique = m->hdr->unique;
|
||||||
|
if(debug)
|
||||||
|
fprint(2, "FUSE <- %#G\n", m->hdr, &hdr, 0);
|
||||||
|
if(write(fusefd, &hdr, sizeof hdr) < 0)
|
||||||
|
sysfatal("replyfuseerror: %r");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
replyfuseerrstr(FuseMsg *m)
|
||||||
|
{
|
||||||
|
replyfuseerrno(m, errstr2errno());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mounts a fuse file system on mtpt and returns
|
||||||
|
* a file descriptor for the corresponding fuse
|
||||||
|
* message conversation.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
mountfuse(char *mtpt)
|
||||||
|
{
|
||||||
|
int p[2], pid, fd;
|
||||||
|
char buf[20];
|
||||||
|
|
||||||
|
if(socketpair(AF_UNIX, SOCK_STREAM, 0, p) < 0)
|
||||||
|
return -1;
|
||||||
|
pid = fork();
|
||||||
|
if(pid < 0)
|
||||||
|
return -1;
|
||||||
|
if(pid == 0){
|
||||||
|
close(p[1]);
|
||||||
|
snprint(buf, sizeof buf, "%d", p[0]);
|
||||||
|
putenv("_FUSE_COMMFD", buf);
|
||||||
|
execlp("fusermount", "fusermount", "--", mtpt, nil);
|
||||||
|
fprint(2, "exec fusermount: %r\n");
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
close(p[0]);
|
||||||
|
fd = recvfd(p[1]);
|
||||||
|
close(p[1]);
|
||||||
|
waitpid();
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
unmountfuse(char *mtpt)
|
||||||
|
{
|
||||||
|
int pid;
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if(pid < 0)
|
||||||
|
return;
|
||||||
|
if(pid == 0){
|
||||||
|
atexitdont(unmountatexit);
|
||||||
|
execlp("fusermount", "fusermount", "-u", "-z", "--", mtpt, nil);
|
||||||
|
fprint(2, "exec fusermount -u: %r\n");
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
waitpid();
|
||||||
|
}
|
||||||
|
|
||||||
|
char *fusemtpt;
|
||||||
|
void
|
||||||
|
unmountatexit(void)
|
||||||
|
{
|
||||||
|
if(fusemtpt)
|
||||||
|
unmountfuse(fusemtpt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
initfuse(char *mtpt)
|
||||||
|
{
|
||||||
|
FuseMsg *m;
|
||||||
|
struct fuse_init_in *tx;
|
||||||
|
struct fuse_init_out rx;
|
||||||
|
|
||||||
|
fusemtpt = mtpt;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The 4096 is for the message headers.
|
||||||
|
* It's a lot, but it's what the FUSE libraries ask for.
|
||||||
|
*/
|
||||||
|
fusemaxwrite = getpagesize();
|
||||||
|
fusebufsize = 4096 + fusemaxwrite;
|
||||||
|
|
||||||
|
if((fusefd = mountfuse(mtpt)) < 0)
|
||||||
|
sysfatal("mountfuse: %r");
|
||||||
|
|
||||||
|
if((m = readfusemsg()) == nil)
|
||||||
|
sysfatal("readfusemsg: %r");
|
||||||
|
if(m->hdr->opcode != FUSE_INIT)
|
||||||
|
sysfatal("fuse: expected FUSE_INIT (26) got %d", m->hdr->opcode);
|
||||||
|
tx = m->tx;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Complain if the kernel is too new.
|
||||||
|
* We could forge ahead, but at least the one time I tried,
|
||||||
|
* the kernel rejected the newer version by making the
|
||||||
|
* writev fail in replyfuse, which is a much more confusing
|
||||||
|
* error message. In the future, might be nice to try to
|
||||||
|
* support older versions that differ only slightly.
|
||||||
|
*/
|
||||||
|
if(tx->major < FUSE_KERNEL_VERSION
|
||||||
|
|| (tx->major == FUSE_KERNEL_VERSION && tx->minor < FUSE_KERNEL_MINOR_VERSION))
|
||||||
|
sysfatal("fuse: too kernel version %d.%d older than program version %d.%d",
|
||||||
|
tx->major, tx->minor, FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
|
||||||
|
|
||||||
|
memset(&rx, 0, sizeof rx);
|
||||||
|
rx.major = FUSE_KERNEL_VERSION;
|
||||||
|
rx.minor = FUSE_KERNEL_MINOR_VERSION;
|
||||||
|
rx.max_write = fusemaxwrite;
|
||||||
|
replyfuse(m, &rx, sizeof rx);
|
||||||
|
freefusemsg(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print FUSE messages. Assuming it is installed as %G,
|
||||||
|
* use %G with hdr, arg arguments to format a request,
|
||||||
|
* and %#G with reqhdr, hdr, arg arguments to format a response.
|
||||||
|
* The reqhdr is necessary in the %#G form because the
|
||||||
|
* response does not contain an opcode tag.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fusefmt(Fmt *fmt)
|
||||||
|
{
|
||||||
|
struct fuse_in_header *hdr = va_arg(fmt->args, void*);
|
||||||
|
if((fmt->flags&FmtSharp) == 0){ /* "%G", hdr, arg */
|
||||||
|
void *a = va_arg(fmt->args, void*);
|
||||||
|
fmtprint(fmt, "len %d unique %#llux uid %d gid %d pid %d ",
|
||||||
|
hdr->len, hdr->unique, hdr->uid, hdr->gid, hdr->pid);
|
||||||
|
|
||||||
|
switch(hdr->opcode){
|
||||||
|
default: {
|
||||||
|
fmtprint(fmt, "??? opcode %d", hdr->opcode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_LOOKUP: {
|
||||||
|
fmtprint(fmt, "Lookup nodeid %#llux name %#q",
|
||||||
|
hdr->nodeid, a);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_FORGET: {
|
||||||
|
struct fuse_forget_in *tx = a;
|
||||||
|
/* nlookup (a ref count) is a vlong! */
|
||||||
|
fmtprint(fmt, "Forget nodeid %#llux nlookup %lld",
|
||||||
|
hdr->nodeid, tx->nlookup);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_GETATTR: {
|
||||||
|
fmtprint(fmt, "Getattr nodeid %#llux", hdr->nodeid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_SETATTR: {
|
||||||
|
struct fuse_setattr_in *tx = a;
|
||||||
|
fmtprint(fmt, "Setattr nodeid %#llux", hdr->nodeid);
|
||||||
|
if(tx->valid&FATTR_FH)
|
||||||
|
fmtprint(fmt, " fh %#llux", tx->fh);
|
||||||
|
if(tx->valid&FATTR_SIZE)
|
||||||
|
fmtprint(fmt, " size %lld", tx->size);
|
||||||
|
if(tx->valid&FATTR_ATIME)
|
||||||
|
fmtprint(fmt, " atime %.20g", tx->atime+tx->atimensec*1e-9);
|
||||||
|
if(tx->valid&FATTR_MTIME)
|
||||||
|
fmtprint(fmt, " mtime %.20g", tx->mtime+tx->mtimensec*1e-9);
|
||||||
|
if(tx->valid&FATTR_MODE)
|
||||||
|
fmtprint(fmt, " mode %#uo", tx->mode);
|
||||||
|
if(tx->valid&FATTR_UID)
|
||||||
|
fmtprint(fmt, " uid %d", tx->uid);
|
||||||
|
if(tx->valid&FATTR_GID)
|
||||||
|
fmtprint(fmt, " gid %d", tx->gid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_READLINK: {
|
||||||
|
fmtprint(fmt, "Readlink nodeid %#llux", hdr->nodeid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_SYMLINK: {
|
||||||
|
char *old, *new;
|
||||||
|
|
||||||
|
old = a;
|
||||||
|
new = a + strlen(a) + 1;
|
||||||
|
fmtprint(fmt, "Symlink nodeid %#llux old %#q new %#q",
|
||||||
|
hdr->nodeid, old, new);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_MKNOD: {
|
||||||
|
struct fuse_mknod_in *tx = a;
|
||||||
|
fmtprint(fmt, "Mknod nodeid %#llux mode %#uo rdev %#ux name %#q",
|
||||||
|
hdr->nodeid, tx->mode, tx->rdev, tx+1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_MKDIR: {
|
||||||
|
struct fuse_mkdir_in *tx = a;
|
||||||
|
fmtprint(fmt, "Mkdir nodeid %#llux mode %#uo name %#q",
|
||||||
|
hdr->nodeid, tx->mode, tx+1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_UNLINK: {
|
||||||
|
fmtprint(fmt, "Unlink nodeid %#llux name %#q",
|
||||||
|
hdr->nodeid, a);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_RMDIR: {
|
||||||
|
fmtprint(fmt, "Rmdir nodeid %#llux name %#q",
|
||||||
|
hdr->nodeid, a);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_RENAME: {
|
||||||
|
struct fuse_rename_in *tx = a;
|
||||||
|
char *old = (char*)(tx+1);
|
||||||
|
char *new = old + strlen(old) + 1;
|
||||||
|
fmtprint(fmt, "Rename nodeid %#llux old %#q newdir %#llux new %#q",
|
||||||
|
hdr->nodeid, old, tx->newdir, new);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_LINK: {
|
||||||
|
struct fuse_link_in *tx = a;
|
||||||
|
fmtprint(fmt, "Link oldnodeid %#llux nodeid %#llux name %#q",
|
||||||
|
tx->oldnodeid, hdr->nodeid, tx+1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_OPEN: {
|
||||||
|
struct fuse_open_in *tx = a;
|
||||||
|
/* Should one or both of flags and mode be octal? */
|
||||||
|
fmtprint(fmt, "Open nodeid %#llux flags %#ux mode %#ux",
|
||||||
|
hdr->nodeid, tx->flags, tx->mode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_READ: {
|
||||||
|
struct fuse_read_in *tx = a;
|
||||||
|
fmtprint(fmt, "Read nodeid %#llux fh %#llux offset %lld size %ud",
|
||||||
|
hdr->nodeid, tx->fh, tx->offset, tx->size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_WRITE: {
|
||||||
|
struct fuse_write_in *tx = a;
|
||||||
|
fmtprint(fmt, "Write nodeid %#llux fh %#llux offset %lld size %ud flags %#ux",
|
||||||
|
hdr->nodeid, tx->fh, tx->offset, tx->size, tx->write_flags);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_STATFS: {
|
||||||
|
fmtprint(fmt, "Statfs");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_RELEASE: {
|
||||||
|
struct fuse_release_in *tx = a;
|
||||||
|
fmtprint(fmt, "Release nodeid %#llux fh %#llux flags %#ux",
|
||||||
|
hdr->nodeid, tx->fh, tx->flags);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_FSYNC: {
|
||||||
|
struct fuse_fsync_in *tx = a;
|
||||||
|
fmtprint(fmt, "Fsync nodeid %#llux fh %#llux flags %#ux",
|
||||||
|
hdr->nodeid, tx->fh, tx->fsync_flags);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_SETXATTR: {
|
||||||
|
struct fuse_setxattr_in *tx = a;
|
||||||
|
char *name = (char*)(tx+1);
|
||||||
|
char *value = name + strlen(name) + 1;
|
||||||
|
fmtprint(fmt, "Setxattr nodeid %#llux size %d flags %#ux name %#q value %#q",
|
||||||
|
hdr->nodeid, tx->size, tx->flags, name, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_GETXATTR: {
|
||||||
|
struct fuse_getxattr_in *tx = a;
|
||||||
|
fmtprint(fmt, "Getxattr nodeid %#llux size %d name %#q",
|
||||||
|
hdr->nodeid, tx->size, tx+1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_LISTXATTR: {
|
||||||
|
struct fuse_getxattr_in *tx = a;
|
||||||
|
fmtprint(fmt, "Listxattr nodeid %#llux size %d",
|
||||||
|
hdr->nodeid, tx->size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_REMOVEXATTR: {
|
||||||
|
fmtprint(fmt, "Removexattr nodeid %#llux name %#q",
|
||||||
|
hdr->nodeid, a);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_FLUSH: {
|
||||||
|
struct fuse_flush_in *tx = a;
|
||||||
|
fmtprint(fmt, "Flush nodeid %#llux fh %#llux flags %#ux",
|
||||||
|
hdr->nodeid, tx->fh, tx->flush_flags);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_INIT: {
|
||||||
|
struct fuse_init_in *tx = a;
|
||||||
|
fmtprint(fmt, "Init major %d minor %d",
|
||||||
|
tx->major, tx->minor);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_OPENDIR: {
|
||||||
|
struct fuse_open_in *tx = a;
|
||||||
|
fmtprint(fmt, "Opendir nodeid %#llux flags %#ux mode %#ux",
|
||||||
|
hdr->nodeid, tx->flags, tx->mode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_READDIR: {
|
||||||
|
struct fuse_read_in *tx = a;
|
||||||
|
fmtprint(fmt, "Readdir nodeid %#llux fh %#llux offset %lld size %ud",
|
||||||
|
hdr->nodeid, tx->fh, tx->offset, tx->size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_RELEASEDIR: {
|
||||||
|
struct fuse_release_in *tx = a;
|
||||||
|
fmtprint(fmt, "Releasedir nodeid %#llux fh %#llux flags %#ux",
|
||||||
|
hdr->nodeid, tx->fh, tx->flags);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_FSYNCDIR: {
|
||||||
|
struct fuse_fsync_in *tx = a;
|
||||||
|
fmtprint(fmt, "Fsyncdir nodeid %#llux fh %#llux flags %#ux",
|
||||||
|
hdr->nodeid, tx->fh, tx->fsync_flags);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_ACCESS: {
|
||||||
|
struct fuse_access_in *tx = a;
|
||||||
|
fmtprint(fmt, "Access nodeid %#llux mask %#ux",
|
||||||
|
hdr->nodeid, tx->mask);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_CREATE: {
|
||||||
|
struct fuse_open_in *tx = a;
|
||||||
|
fmtprint(fmt, "Create nodeid %#llx flags %#ux mode %#ux name %#q",
|
||||||
|
hdr->nodeid, tx->flags, tx->mode, tx+1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{ /* "%#G", reqhdr, hdr, arg - use reqhdr only for type */
|
||||||
|
struct fuse_out_header *ohdr = va_arg(fmt->args, void*);
|
||||||
|
void *a = va_arg(fmt->args, void*);
|
||||||
|
int len = ohdr->len - sizeof *ohdr;
|
||||||
|
fmtprint(fmt, "unique %#llux ", ohdr->unique);
|
||||||
|
if(ohdr->error){
|
||||||
|
fmtprint(fmt, "error %d %s", ohdr->error, strerror(-ohdr->error));
|
||||||
|
}else
|
||||||
|
switch(hdr->opcode){
|
||||||
|
default: {
|
||||||
|
fmtprint(fmt, "??? opcode %d", hdr->opcode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_LOOKUP: {
|
||||||
|
/*
|
||||||
|
* For a negative entry, can send back ENOENT
|
||||||
|
* or rx->ino == 0.
|
||||||
|
* In protocol version 7.4 and before, can only use
|
||||||
|
* the ENOENT method.
|
||||||
|
* Presumably the benefit of sending rx->ino == 0
|
||||||
|
* is that you can specify the length of time to cache
|
||||||
|
* the negative result.
|
||||||
|
*/
|
||||||
|
struct fuse_entry_out *rx;
|
||||||
|
fmtprint(fmt, "(Lookup) ");
|
||||||
|
fmt_entry_out:
|
||||||
|
rx = a;
|
||||||
|
fmtprint(fmt, "nodeid %#llux gen %#llux entry_valid %.20g attr_valid %.20g ",
|
||||||
|
rx->nodeid, rx->generation,
|
||||||
|
rx->entry_valid+rx->entry_valid_nsec*1e-9,
|
||||||
|
rx->attr_valid+rx->attr_valid_nsec*1e-9);
|
||||||
|
fmtprint(fmt, " ino %#llux size %lld blocks %lld atime %.20g mtime %.20g ctime %.20g mode %#uo nlink %d uid %d gid %d rdev %#ux",
|
||||||
|
rx->attr.ino, rx->attr.size, rx->attr.blocks,
|
||||||
|
rx->attr.atime+rx->attr.atimensec*1e-9,
|
||||||
|
rx->attr.mtime+rx->attr.mtimensec*1e-9,
|
||||||
|
rx->attr.ctime+rx->attr.ctimensec*1e-9,
|
||||||
|
rx->attr.mode, rx->attr.nlink, rx->attr.uid,
|
||||||
|
rx->attr.gid, rx->attr.rdev);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_FORGET: {
|
||||||
|
/* Can't happen! No reply. */
|
||||||
|
fmtprint(fmt, "(Forget) can't happen");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_GETATTR: {
|
||||||
|
struct fuse_attr_out *rx;
|
||||||
|
fmtprint(fmt, "(Getattr) ");
|
||||||
|
fmt_attr_out:
|
||||||
|
rx = a;
|
||||||
|
fmtprint(fmt, "attr_valid %.20g",
|
||||||
|
rx->attr_valid+rx->attr_valid_nsec*1e-9);
|
||||||
|
fmtprint(fmt, " ino %#llux size %lld blocks %lld atime %.20g mtime %.20g ctime %.20g mode %#uo nlink %d uid %d gid %d rdev %#ux",
|
||||||
|
rx->attr.ino, rx->attr.size, rx->attr.blocks,
|
||||||
|
rx->attr.atime+rx->attr.atimensec*1e-9,
|
||||||
|
rx->attr.mtime+rx->attr.mtimensec*1e-9,
|
||||||
|
rx->attr.ctime+rx->attr.ctimensec*1e-9,
|
||||||
|
rx->attr.mode, rx->attr.nlink, rx->attr.uid,
|
||||||
|
rx->attr.gid, rx->attr.rdev);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_SETATTR: {
|
||||||
|
fmtprint(fmt, "(Setattr) ");
|
||||||
|
goto fmt_attr_out;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_READLINK: {
|
||||||
|
fmtprint(fmt, "(Readlink) %#.*q",
|
||||||
|
utfnlen(a, len), a);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_SYMLINK: {
|
||||||
|
fmtprint(fmt, "(Symlink) ");
|
||||||
|
goto fmt_entry_out;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_MKNOD: {
|
||||||
|
fmtprint(fmt, "(Mknod) ");
|
||||||
|
goto fmt_entry_out;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_MKDIR: {
|
||||||
|
fmtprint(fmt, "(Mkdir) ");
|
||||||
|
goto fmt_entry_out;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_UNLINK: {
|
||||||
|
fmtprint(fmt, "(Unlink)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_RMDIR: {
|
||||||
|
fmtprint(fmt, "(Rmdir)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_RENAME: {
|
||||||
|
fmtprint(fmt, "(Rename)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_LINK: {
|
||||||
|
fmtprint(fmt, "(Link) ");
|
||||||
|
goto fmt_entry_out;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_OPEN: {
|
||||||
|
struct fuse_open_out *rx;
|
||||||
|
fmtprint(fmt, "(Open) ");
|
||||||
|
fmt_open_out:
|
||||||
|
rx = a;
|
||||||
|
fmtprint(fmt, "fh %#llux flags %#ux", rx->fh, rx->open_flags);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_READ: {
|
||||||
|
fmtprint(fmt, "(Read) size %d", len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_WRITE: {
|
||||||
|
struct fuse_write_out *rx = a;
|
||||||
|
fmtprint(fmt, "(Write) size %d", rx->size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_STATFS: {
|
||||||
|
/*
|
||||||
|
* Before protocol version 7.4, only first 48 bytes are used.
|
||||||
|
*/
|
||||||
|
struct fuse_statfs_out *rx = a;
|
||||||
|
fmtprint(fmt, "(Statfs) blocks %lld bfree %lld bavail %lld files %lld ffree %lld bsize %ud namelen %ud frsize %ud",
|
||||||
|
rx->st.blocks, rx->st.bfree, rx->st.bavail,
|
||||||
|
rx->st.files, rx->st.ffree, rx->st.bsize,
|
||||||
|
rx->st.namelen, rx->st.frsize);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_RELEASE: {
|
||||||
|
fmtprint(fmt, "(Release)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_FSYNC: {
|
||||||
|
fmtprint(fmt, "(Fsync)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_SETXATTR: {
|
||||||
|
fmtprint(fmt, "(Serxattr)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_GETXATTR: {
|
||||||
|
fmtprint(fmt, "(Getxattr) size %d", len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_LISTXATTR: {
|
||||||
|
fmtprint(fmt, "(Lisrxattr) size %d", len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_REMOVEXATTR: {
|
||||||
|
fmtprint(fmt, "(Removexattr)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_FLUSH: {
|
||||||
|
fmtprint(fmt, "(Flush)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_INIT: {
|
||||||
|
struct fuse_init_out *rx = a;
|
||||||
|
fmtprint(fmt, "(Init) major %d minor %d max_write %d",
|
||||||
|
rx->major, rx->minor, rx->max_write);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_OPENDIR: {
|
||||||
|
fmtprint(fmt, "(Opendir) ");
|
||||||
|
goto fmt_open_out;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_READDIR: {
|
||||||
|
fmtprint(fmt, "(Readdir) size %d", len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_RELEASEDIR: {
|
||||||
|
fmtprint(fmt, "(Releasedir)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_FSYNCDIR: {
|
||||||
|
fmtprint(fmt, "(Fsyncdir)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_ACCESS: {
|
||||||
|
fmtprint(fmt, "(Access)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUSE_CREATE: {
|
||||||
|
struct fuse_create_out *rx = a;
|
||||||
|
fmtprint(fmt, "(Create) ");
|
||||||
|
fmtprint(fmt, "nodeid %#llux gen %#llux entry_valid %.20g attr_valid %.20g ",
|
||||||
|
rx->e.nodeid, rx->e.generation,
|
||||||
|
rx->e.entry_valid+rx->e.entry_valid_nsec*1e-9,
|
||||||
|
rx->e.attr_valid+rx->e.attr_valid_nsec*1e-9);
|
||||||
|
fmtprint(fmt, " ino %#llux size %lld blocks %lld atime %.20g mtime %.20g ctime %.20g mode %#uo nlink %d uid %d gid %d rdev %#ux",
|
||||||
|
rx->e.attr.ino, rx->e.attr.size, rx->e.attr.blocks,
|
||||||
|
rx->e.attr.atime+rx->e.attr.atimensec*1e-9,
|
||||||
|
rx->e.attr.mtime+rx->e.attr.mtimensec*1e-9,
|
||||||
|
rx->e.attr.ctime+rx->e.attr.ctimensec*1e-9,
|
||||||
|
rx->e.attr.mode, rx->e.attr.nlink, rx->e.attr.uid,
|
||||||
|
rx->e.attr.gid, rx->e.attr.rdev);
|
||||||
|
fmtprint(fmt, " fh %#llux flags %#ux", rx->o.fh, rx->o.open_flags);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
312
src/cmd/9pfuse/fuse_kernel.h
Normal file
312
src/cmd/9pfuse/fuse_kernel.h
Normal file
|
|
@ -0,0 +1,312 @@
|
||||||
|
/* This file defines the kernel interface of FUSE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
This -- and only this -- header file may also be distributed under
|
||||||
|
the terms of the BSD Licence as follows:
|
||||||
|
|
||||||
|
Copyright (C) 2001-2006 Miklos Szeredi. 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 AUTHOR 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 AUTHOR 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* RSC changed these lines */
|
||||||
|
#include <inttypes.h>
|
||||||
|
#define __u64 uint64_t
|
||||||
|
#define __u32 uint32_t
|
||||||
|
#define __s32 int32_t
|
||||||
|
|
||||||
|
/** Version number of this interface */
|
||||||
|
#define FUSE_KERNEL_VERSION 7
|
||||||
|
|
||||||
|
/** Minor version number of this interface */
|
||||||
|
#define FUSE_KERNEL_MINOR_VERSION 5
|
||||||
|
|
||||||
|
/** The node ID of the root inode */
|
||||||
|
#define FUSE_ROOT_ID 1
|
||||||
|
|
||||||
|
/** The major number of the fuse character device */
|
||||||
|
#define FUSE_MAJOR 10
|
||||||
|
|
||||||
|
/** The minor number of the fuse character device */
|
||||||
|
#define FUSE_MINOR 229
|
||||||
|
|
||||||
|
/* Make sure all structures are padded to 64bit boundary, so 32bit
|
||||||
|
userspace works under 64bit kernels */
|
||||||
|
|
||||||
|
struct fuse_attr {
|
||||||
|
__u64 ino;
|
||||||
|
__u64 size;
|
||||||
|
__u64 blocks;
|
||||||
|
__u64 atime;
|
||||||
|
__u64 mtime;
|
||||||
|
__u64 ctime;
|
||||||
|
__u32 atimensec;
|
||||||
|
__u32 mtimensec;
|
||||||
|
__u32 ctimensec;
|
||||||
|
__u32 mode;
|
||||||
|
__u32 nlink;
|
||||||
|
__u32 uid;
|
||||||
|
__u32 gid;
|
||||||
|
__u32 rdev;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_kstatfs {
|
||||||
|
__u64 blocks;
|
||||||
|
__u64 bfree;
|
||||||
|
__u64 bavail;
|
||||||
|
__u64 files;
|
||||||
|
__u64 ffree;
|
||||||
|
__u32 bsize;
|
||||||
|
__u32 namelen;
|
||||||
|
__u32 frsize;
|
||||||
|
__u32 padding;
|
||||||
|
__u32 spare[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FATTR_MODE (1 << 0)
|
||||||
|
#define FATTR_UID (1 << 1)
|
||||||
|
#define FATTR_GID (1 << 2)
|
||||||
|
#define FATTR_SIZE (1 << 3)
|
||||||
|
#define FATTR_ATIME (1 << 4)
|
||||||
|
#define FATTR_MTIME (1 << 5)
|
||||||
|
#define FATTR_FH (1 << 6)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flags returned by the OPEN request
|
||||||
|
*
|
||||||
|
* FOPEN_DIRECT_IO: bypass page cache for this open file
|
||||||
|
* FOPEN_KEEP_CACHE: don't invalidate the data cache on open
|
||||||
|
*/
|
||||||
|
#define FOPEN_DIRECT_IO (1 << 0)
|
||||||
|
#define FOPEN_KEEP_CACHE (1 << 1)
|
||||||
|
|
||||||
|
enum fuse_opcode {
|
||||||
|
FUSE_LOOKUP = 1,
|
||||||
|
FUSE_FORGET = 2, /* no reply */
|
||||||
|
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_ACCESS = 34,
|
||||||
|
FUSE_CREATE = 35
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The read buffer is required to be at least 8k, but may be much larger */
|
||||||
|
#define FUSE_MIN_READ_BUFFER 8192
|
||||||
|
|
||||||
|
struct fuse_entry_out {
|
||||||
|
__u64 nodeid; /* Inode ID */
|
||||||
|
__u64 generation; /* Inode generation: nodeid:gen must
|
||||||
|
be unique for the fs's lifetime */
|
||||||
|
__u64 entry_valid; /* Cache timeout for the name */
|
||||||
|
__u64 attr_valid; /* Cache timeout for the attributes */
|
||||||
|
__u32 entry_valid_nsec;
|
||||||
|
__u32 attr_valid_nsec;
|
||||||
|
struct fuse_attr attr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_forget_in {
|
||||||
|
__u64 nlookup;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_attr_out {
|
||||||
|
__u64 attr_valid; /* Cache timeout for the attributes */
|
||||||
|
__u32 attr_valid_nsec;
|
||||||
|
__u32 dummy;
|
||||||
|
struct fuse_attr attr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_mknod_in {
|
||||||
|
__u32 mode;
|
||||||
|
__u32 rdev;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_mkdir_in {
|
||||||
|
__u32 mode;
|
||||||
|
__u32 padding;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_rename_in {
|
||||||
|
__u64 newdir;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_link_in {
|
||||||
|
__u64 oldnodeid;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_setattr_in {
|
||||||
|
__u32 valid;
|
||||||
|
__u32 padding;
|
||||||
|
__u64 fh;
|
||||||
|
__u64 size;
|
||||||
|
__u64 unused1;
|
||||||
|
__u64 atime;
|
||||||
|
__u64 mtime;
|
||||||
|
__u64 unused2;
|
||||||
|
__u32 atimensec;
|
||||||
|
__u32 mtimensec;
|
||||||
|
__u32 unused3;
|
||||||
|
__u32 mode;
|
||||||
|
__u32 unused4;
|
||||||
|
__u32 uid;
|
||||||
|
__u32 gid;
|
||||||
|
__u32 unused5;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_open_in {
|
||||||
|
__u32 flags;
|
||||||
|
__u32 mode;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_open_out {
|
||||||
|
__u64 fh;
|
||||||
|
__u32 open_flags;
|
||||||
|
__u32 padding;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_release_in {
|
||||||
|
__u64 fh;
|
||||||
|
__u32 flags;
|
||||||
|
__u32 padding;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_flush_in {
|
||||||
|
__u64 fh;
|
||||||
|
__u32 flush_flags;
|
||||||
|
__u32 padding;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_read_in {
|
||||||
|
__u64 fh;
|
||||||
|
__u64 offset;
|
||||||
|
__u32 size;
|
||||||
|
__u32 padding;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_write_in {
|
||||||
|
__u64 fh;
|
||||||
|
__u64 offset;
|
||||||
|
__u32 size;
|
||||||
|
__u32 write_flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_write_out {
|
||||||
|
__u32 size;
|
||||||
|
__u32 padding;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FUSE_COMPAT_STATFS_SIZE 48
|
||||||
|
|
||||||
|
struct fuse_statfs_out {
|
||||||
|
struct fuse_kstatfs st;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_fsync_in {
|
||||||
|
__u64 fh;
|
||||||
|
__u32 fsync_flags;
|
||||||
|
__u32 padding;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_setxattr_in {
|
||||||
|
__u32 size;
|
||||||
|
__u32 flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_getxattr_in {
|
||||||
|
__u32 size;
|
||||||
|
__u32 padding;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_getxattr_out {
|
||||||
|
__u32 size;
|
||||||
|
__u32 padding;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_access_in {
|
||||||
|
__u32 mask;
|
||||||
|
__u32 padding;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_init_in {
|
||||||
|
__u32 major;
|
||||||
|
__u32 minor;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_init_out {
|
||||||
|
__u32 major;
|
||||||
|
__u32 minor;
|
||||||
|
__u32 unused[3];
|
||||||
|
__u32 max_write;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_in_header {
|
||||||
|
__u32 len;
|
||||||
|
__u32 opcode;
|
||||||
|
__u64 unique;
|
||||||
|
__u64 nodeid;
|
||||||
|
__u32 uid;
|
||||||
|
__u32 gid;
|
||||||
|
__u32 pid;
|
||||||
|
__u32 padding;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_out_header {
|
||||||
|
__u32 len;
|
||||||
|
__s32 error;
|
||||||
|
__u64 unique;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* RSC changed name[0] to name[1] for old C compilers */
|
||||||
|
struct fuse_dirent {
|
||||||
|
__u64 ino;
|
||||||
|
__u64 off;
|
||||||
|
__u32 namelen;
|
||||||
|
__u32 type;
|
||||||
|
char name[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FUSE_NAME_OFFSET ((unsigned) ((struct fuse_dirent *) 0)->name)
|
||||||
|
#define FUSE_DIRENT_ALIGN(x) (((x) + sizeof(__u64) - 1) & ~(sizeof(__u64) - 1))
|
||||||
|
#define FUSE_DIRENT_SIZE(d) \
|
||||||
|
FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen)
|
||||||
1169
src/cmd/9pfuse/main.c
Normal file
1169
src/cmd/9pfuse/main.c
Normal file
File diff suppressed because it is too large
Load diff
12
src/cmd/9pfuse/mkfile
Normal file
12
src/cmd/9pfuse/mkfile
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
<$PLAN9/src/mkhdr
|
||||||
|
|
||||||
|
TARG=9pfuse
|
||||||
|
|
||||||
|
OFILES=\
|
||||||
|
fuse.$O\
|
||||||
|
main.$O\
|
||||||
|
|
||||||
|
HFILES=a.h
|
||||||
|
|
||||||
|
<$PLAN9/src/mkone
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue