wip import mount_sysvbfs

This commit is contained in:
Jean-Baptiste Boric 2016-12-27 23:36:19 +01:00
parent 5084102fbc
commit cfbb0c09fc
91 changed files with 11153 additions and 1 deletions

View File

@ -1222,6 +1222,7 @@
./usr/sbin/pwd_mkdb minix-base
./usr/sbin/rdate minix-base
./usr/sbin/rump.traceroute minix-base rump
./usr/sbin/rump_sysvbfs minix-base rump
./usr/sbin/syslogd minix-base
./usr/sbin/traceroute minix-base
./usr/sbin/unlink minix-base

View File

@ -2297,6 +2297,7 @@
./usr/lib/libobjc.a minix-comp gcc=45
./usr/lib/libobjc_pic.a minix-comp gcc=45
./usr/lib/libp2k.a minix-comp rump
./usr/lib/libp2k_pic.a minix-comp rump
./usr/lib/libpci.a minix-comp
./usr/lib/libpci_pic.a minix-comp
./usr/lib/libprop.a minix-comp
@ -2462,6 +2463,7 @@
./usr/lib/libtimers.a minix-comp
./usr/lib/libtimers_pic.a minix-comp
./usr/lib/libukfs.a minix-comp rump
./usr/lib/libukfs_pic.a minix-comp rump
./usr/lib/libusb.a minix-comp
./usr/lib/libusb_pic.a minix-comp
./usr/lib/libutil.a minix-comp

View File

@ -3444,6 +3444,7 @@
./usr/man/man8/repartition.8 minix-man
./usr/man/man8/rotate.8 minix-man
./usr/man/man8/rshd.8 minix-man
./usr/man/man8/rump_sysvbfs.8 minix-man rump
./usr/man/man8/screendump.8 minix-man
./usr/man/man8/serial-ip.8 minix-man obsolete
./usr/man/man8/service.8 minix-man

46
sbin/mount/pathadj.c Normal file
View File

@ -0,0 +1,46 @@
/* $NetBSD: pathadj.c,v 1.2 2011/02/17 16:57:46 pooka Exp $ */
/*
* Copyright (c) 2008 The NetBSD Foundation. 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 AUTHOR ``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 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.
*/
#include <sys/param.h>
#include <err.h>
#include <stdlib.h>
#include <string.h>
#include "mountprog.h"
void
pathadj(const char *input, char *adjusted)
{
if (realpath(input, adjusted) == NULL)
warn("Warning: realpath %s", input);
if (strncmp(input, adjusted, MAXPATHLEN)) {
warnx("\"%s\" is a non-resolved or relative path.", input);
warnx("using \"%s\" instead.", adjusted);
}
}

View File

@ -0,0 +1,16 @@
# $NetBSD: Makefile,v 1.2 2008/09/04 12:07:58 pooka Exp $
.include <bsd.own.mk>
PROG= mount_sysvbfs
SRCS= mount_sysvbfs.c fattr.c pathadj.c
MAN= mount_sysvbfs.8
MOUNT= ${NETBSDSRCDIR}/sbin/mount
CPPFLAGS+= -I${MOUNT}
.PATH: ${MOUNT}
DPADD+=${LIBUTIL}
LDADD+=-lutil
.include <bsd.prog.mk>

View File

@ -0,0 +1,80 @@
.\" $NetBSD: mount_sysvbfs.8,v 1.1 2005/12/29 14:53:45 tsutsui Exp $
.\"
.\" Copyright (c) 1980, 1989, 1991, 1993
.\" The Regents of the University of California. 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.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
.\"
.\" @(#)mount.8 8.7 (Berkeley) 3/27/94
.\"
.Dd September 21, 2005
.Dt MOUNT_SYSVBFS 8
.Os
.Sh NAME
.Nm mount_sysvbfs
.Nd mount a System V Boot File System
.Sh SYNOPSIS
.Nm
.Op Fl o Ar options
.Ar special node
.Sh DESCRIPTION
The
.Nm
command attaches the System V Boot File System on the
.Ar special
device on to the file system tree at point
.Ar node .
Both
.Ar special
and
.Ar node
are converted to absolute paths before use.
.Pp
This command is normally executed by
.Xr mount 8
at boot time.
The options are as follows:
.Bl -tag -width Ds
.It Fl o
Options are specified with a
.Fl o
flag followed by a comma separated string of options.
See the
.Xr mount 8
man page for possible options and their meanings.
.El
.Sh SEE ALSO
.Xr mount 2 ,
.Xr unmount 2 ,
.Xr fstab 5 ,
.Xr mount 8
.Sh HISTORY
A
.Nm
command first appeared in
.Nx 4.0 .
.Sh BUGS
The sysvbfs support is still experimental and there are few sanity checks,
so it is possible for a corrupted file system to cause a crash.

View File

@ -0,0 +1,157 @@
/* $NetBSD: mount_sysvbfs.c,v 1.8 2011/08/29 14:35:02 joerg Exp $ */
/*-
* Copyright (c) 1993, 1994
* The Regents of the University of California. 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1993, 1994\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
__RCSID("$NetBSD: mount_sysvbfs.c,v 1.8 2011/08/29 14:35:02 joerg Exp $");
#endif /* not lint */
#include <sys/param.h>
#include <sys/mount.h>
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <mntopts.h>
#include "mountprog.h"
#include "mount_sysvbfs.h"
static const struct mntopt mopts[] = {
MOPT_STDOPTS,
MOPT_UPDATE,
MOPT_GETARGS,
MOPT_NULL,
};
__dead static void
sysvbfs_usage(void)
{
(void)fprintf(stderr, "usage: %s [-o options] special node\n",
getprogname());
exit(EXIT_FAILURE);
}
#ifndef MOUNT_NOMAIN
int
main(int argc, char **argv)
{
return mount_sysvbfs(argc, argv);
}
#endif
void
mount_sysvbfs_parseargs(int argc, char **argv,
struct sysvbfs_args *args, int *mntflags,
char *canon_dev, char *canon_dir)
{
int ch;
mntoptparse_t mp;
*mntflags = 0;
optind = optreset = 1; /* Reset for parse of new argv. */
while ((ch = getopt(argc, argv, "o:")) != -1)
switch (ch) {
case 'o':
mp = getmntopts(optarg, mopts, mntflags, 0);
if (mp == NULL)
err(1, "getmntopts");
freemntopts(mp);
break;
case '?':
default:
sysvbfs_usage();
}
argc -= optind;
argv += optind;
if (argc != 2)
sysvbfs_usage();
pathadj(argv[0], canon_dev);
args->fspec = canon_dev;
pathadj(argv[1], canon_dir);
}
int
mount_sysvbfs(int argc, char *argv[])
{
struct sysvbfs_args args;
char canon_dev[MAXPATHLEN], canon_dir[MAXPATHLEN];
const char *errcause;
int mntflags;
mount_sysvbfs_parseargs(argc, argv, &args, &mntflags,
canon_dev, canon_dir);
if (mount(MOUNT_SYSVBFS, canon_dir, mntflags, &args, sizeof args)==-1) {
switch (errno) {
case EMFILE:
errcause = "mount table full";
break;
case EINVAL:
if (mntflags & MNT_UPDATE)
errcause =
"specified device does not match mounted device";
else
errcause = "incorrect super block";
break;
default:
errcause = strerror(errno);
break;
}
errx(EXIT_FAILURE, "%s on %s: %s",
canon_dev, canon_dir, errcause);
}
exit(EXIT_SUCCESS);
}
#if defined(__minix)
int __real_main(int argc, char *argv[]);
int
__real_main(int argc, char *argv[])
{
return mount_sysvbfs(argc, argv);
}
#endif

View File

@ -0,0 +1,37 @@
/* $NetBSD: mount_sysvbfs.h,v 1.1 2008/09/04 12:07:58 pooka Exp $ */
/*
* Copyright (c) 2008 The NetBSD Foundation. 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 AUTHOR ``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 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.
*/
#ifndef _SBIN_MOUNT_SYSVBFS_MOUNT_SYSVBFS_H_
#define _SBIN_MOUNT_SYSVBFS_MOUNT_SYSVBFS_H_
#include <fs/sysvbfs/sysvbfs_args.h>
int mount_sysvbfs(int, char **);
void mount_sysvbfs_parseargs(int, char **, struct sysvbfs_args *, int *,
char *, char *);
#endif /* _SBIN_MOUNT_SYSVBFS_MOUNT_SYSVBFS_H_ */

View File

@ -44,7 +44,7 @@ SUBDIR+= rpc.yppasswdd ypbind yppoll ypserv ypset
.endif
.if (${MKRUMP} != "no")
#SUBDIR+= puffs
SUBDIR+= puffs
.endif
.if ${TOOLCHAIN_MISSING} != "no"

37
usr.sbin/puffs/Makefile Normal file
View File

@ -0,0 +1,37 @@
# $NetBSD: Makefile,v 1.16 2011/07/24 08:55:30 uch Exp $
.include <bsd.own.mk>
.if !defined(__MINIX)
SUBDIR= mount_9p mount_psshfs mount_sysctlfs
SUBDIR+=rump_cd9660 rump_efs rump_ext2fs rump_ffs rump_hfs rump_lfs
SUBDIR+=rump_msdos rump_nfs rump_ntfs rump_syspuffs rump_sysvbfs
SUBDIR+=rump_tmpfs rump_udf rump_v7fs
.if ${MKCRYPTO} != "no"
SUBDIR+=rump_smbfs
.endif
.else
SUBDIR= rump_sysvbfs
.endif
#
# The following are not built by default
#
# userspace fdesc server cannot grope the fd info from the kernel,
# and is therefore not useful for the average user
#SUBDIR+=rump_fdesc
# ditto for kernfs
#SUBDIR+=rump_kernfs
# rump_mqmfs is just another ffs, useful mainly for debugging
#SUBDIR+=rump_nqmfs
# rump_au-naturel presents lets you access '/' for a rump kernel.
# mostly for debugging.
#SUBDIR+=rump_au-naturel
.include <bsd.subdir.mk>

View File

@ -0,0 +1,58 @@
# $NetBSD: Makefile.inc,v 1.14 2014/01/16 01:15:34 christos Exp $
WARNS?= 4
.include <bsd.own.mk>
USE_FORT?= yes # network client
.if exists(${.CURDIR}/../../Makefile.inc)
.include "${.CURDIR}/../../Makefile.inc"
.endif
.ifdef ISRUMP
.ifdef MOUNTNAME
PROG= rump_${MOUNTNAME}
MAN= rump_${MOUNTNAME}.8
MOUNTDIR= ${.CURDIR}/../../../sbin
MOUNT= ${MOUNTDIR}/mount
CPPFLAGS+= -I${MOUNTDIR}/mount_${MOUNTNAME} -I${MOUNT} -DMOUNT_NOMAIN
SRCS+= mount_${MOUNTNAME}.c rump_${MOUNTNAME}.c pathadj.c fattr.c
# on select archs use the kernel module directly, otherwise fallback
# to the rump library
.ifndef DONOTLINKLIBS
.undef RUMPKMOD
.ifdef RUMPKMOD
OSRELEASE!= ${HOST_SH} ${NETBSDSRCDIR}/sys/conf/osrelease.sh
KMODULEDIR= ${DESTDIR}/stand/${MACHINE}/${OSRELEASE}/modules/${MOUNTNAME}
LDADD+= ${KMODULEDIR}/${MOUNTNAME}.kmod
.else
LDADD+= -lrumpfs_${MOUNTNAME}
.endif
.endif
.PATH: ${MOUNT} ${MOUNTDIR}/mount_${MOUNTNAME}
.endif # MOUNTNAME
# disk components for disk-based file systems
.if RUMP_DISKFS
LDADD+= -lrumpdev_disk -lrumpdev
.endif
LDADD+= -lp2k -lukfs -lrumpvfs -lrump -lrumpuser -lpuffs -lutil
.if defined(__MINIX)
LDADD+= -lmthread -lfsdriver -lsys
.else
LDADD+= -lpthread
.endif # defined(__MINIX)
DPADD+= ${LIBP2K} ${LIBUKFS} ${LIBRUMPVFS} ${LIBRUMP} ${LIBRUMPUSER}
.if defined(__MINIX)
DPADD+= ${LIBPUFFS} ${LIBUTIL} ${LIBMTHREAD}
.else
DPADD+= ${LIBPUFFS} ${LIBUTIL} ${LIBPTHREAD}
.endif # defined(__MINIX)
.endif # ISRUMP

View File

@ -0,0 +1,232 @@
#!/bin/sh
#
# $NetBSD: makerumpmanpages.sh,v 1.13 2011/07/24 08:55:30 uch Exp $
#
IFS=' '
COPYRIGHT='.\" WARNING: GENERATED FILE, DO NOT EDIT
.\" INSTEAD, EDIT makerumpmanpages.sh AND REGEN
.\" from: $NetBSD: makerumpmanpages.sh,v 1.13 2011/07/24 08:55:30 uch Exp $
.\"
.\" Copyright (c) 2008-2010 Antti Kantee. 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 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 THE 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.
.\"'
MANTMPL1='.Dd November 21, 2010
.Dt RUMP_XXXFSXXX 8
.Os
.Sh NAME
.Nm rump_xxxfsxxx
.Nd mount a xxxfsxxx xxxfssrcxxx with a userspace server
.Sh SYNOPSIS
.Cd "file-system PUFFS"
.Cd "pseudo-device putter"
.Pp
.Nm
.Op options
.Ar xxximagexxx
.Ar mountpoint
.Sh DESCRIPTION
.Em NOTE!
This manual page describes features specific to the
.Xr rump 3
file server.
Please see
.Xr mount_xxxfsxxx 8
for a full description of the available command line options.
.Pp
The
.Nm
utility can be used to mount xxxfsxxx file systems.
It uses
.Xr rump 3
and
.Xr p2k 3
to facilitate running the file system as a server in userspace.
As opposed to
.Xr mount_xxxfsxxx 8 ,
.Nm
does not use file system code within the kernel and therefore does
not require kernel support except
.Xr puffs 4 .
Apart from a minor speed penalty there is no downside with respect to
in-kernel code.'
MANTMPL_BLK='.Pp
.Nm
does not require using
.Xr vnconfig 8
for mounts from regular files and the file path can be passed
directly as the
.Ar xxximagexxx
parameter.
In fact, the use of
.Xr vnconfig 8
is discouraged, since it is unable to properly deal with images on
sparse files.
.Pp
In case the image contains multiple partitions, the desired partition
must be indicated by appending the token
.Dq %DISKLABEL:p%
to the
.Ar xxximagexxx
path.
The letter
.Dq p
specifies the partition as obtained via
.Xr disklabel 8 .
For example, to mount partition
.Dq e
from image
.Pa /tmp/wd0.img ,
use
.Dq /tmp/wd0.img%DISKLABEL:e% .
.Pp
It is recommended that untrusted file system images be mounted with
.Nm
instead of
.Xr mount_xxxfsxxx 8 .
Corrupt file system images commonly cause the file system
to crash the entire kernel, but with
.Nm
only the userspace server process will dump core.'
MANTMPL_NET='.Pp
Even though the
.Nm
file system client runs within a virtual rump kernel in userspace,
it uses host network services
.Pq by means of Dq rump sockin .
This means that regardless of whether using
.Nm
or
.Xr mount_xxxfsxxx 8 ,
the same network configurations will be used.
Currently,
.Dq sockin
supports IPv4.'
MANTMPL2='.Pp
To use
.Nm
via
.Xr mount 8 ,
the flags
.Fl o Ar rump
and
.Fl t Ar xxxfsxxx
should be given.
Similarly,
.Nm
is used instead of
.Xr mount_xxxfsxxx 8
if
.Dq rump
is added to the options field of
.Xr fstab 5 .
.Sh SEE ALSO
.Xr p2k 3 ,
.Xr puffs 3 ,
.Xr rump 3 ,
.Xr mount_xxxfsxxx 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx xxxfirstxxx .'
# vary manpages slightly based on the type of server in question
disk="cd9660 efs ext2fs ffs hfs lfs msdos ntfs sysvbfs udf v7fs"
net="nfs smbfs"
fictional="fdesc kernfs tmpfs"
special="au-naturel nqmfs syspuffs"
first5="cd9660 efs ext2fs ffs hfs lfs msdos nfs ntfs syspuffs sysvbfs tmpfs udf"
member ()
{
what=$1
shift
while [ $# -gt 0 ] ; do
[ "$1" = "${what}" ] && return 0
shift
done
return 1
}
sedsub='s/xxxfsxxx/$fs/g\;s/XXXFSXXX/$fsc/g\;s/xxximagexxx/$image/g\;'\
's/xxxfirstxxx/$first/g\;s/xxxfssrcxxx/$fssrc/g\;'
# auto manual pages
for x in rump_*
do
fs=${x#rump_}
# see if we are dealing with a new server
if ! member $fs $disk $net $fictional $special ; then
echo ERROR: $fs not found in any class!
exit 1
fi
# special file systems have special manpages
member $fs $special && continue
# figure out our type
if member $fs $disk ; then
mytype=disk
image=image
fssrc=image
fi
if member $fs $net ; then
mytype=net
image=share
fssrc=share
fi
if member $fs $fictional ; then
mytype=special
image=$fs
fssrc='fictional fs'
fi
# which version did server first appear?
if member $fs $first5 ; then
first=5.0
else
first=6.0
fi
fsc=`echo $fs | tr '[:lower:]' '[:upper:]'`
eval sedstr="${sedsub}"
printf '.\\" $NetBSD: makerumpmanpages.sh,v 1.13 2011/07/24 08:55:30 uch Exp $\n.\\"\n' > rump_${fs}/rump_${fs}.8
echo ${COPYRIGHT} | sed -e 's/\$//g' >> rump_${fs}/rump_${fs}.8
echo ${MANTMPL1} | sed -e "$sedstr" >> rump_${fs}/rump_${fs}.8
[ ${mytype} = disk ] && \
echo ${MANTMPL_BLK} | sed -e "$sedstr" >> rump_${fs}/rump_${fs}.8
[ ${mytype} = net ] && \
echo ${MANTMPL_NET} | sed -e "$sedstr" >> rump_${fs}/rump_${fs}.8
echo ${MANTMPL2} | sed -e "$sedstr" >> rump_${fs}/rump_${fs}.8
done

View File

@ -0,0 +1,10 @@
# $NetBSD: Makefile,v 1.3 2009/04/22 15:23:06 lukem Exp $
#
PROG= mount_9p
SRCS= ninepuffs.c ninebuf.c nineproto.c fs.c node.c subr.c
LDADD+= -lpuffs -lutil
MAN= mount_9p.8
.include <bsd.prog.mk>

View File

@ -0,0 +1,236 @@
/* $NetBSD: fs.c,v 1.9 2011/06/22 04:03:23 mrg Exp $ */
/*
* Copyright (c) 2007 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: fs.c,v 1.9 2011/06/22 04:03:23 mrg Exp $");
#endif /* !lint */
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <puffs.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "ninepuffs.h"
#include "nineproto.h"
#define DO_IO(fname, a1, a2, a3, a4, rv) \
puffs_framebuf_seekset(a2, 0); \
*(a4) = 0; \
rv = fname(a1, a2, a3, a4); \
if (rv) errx(1, "p9p_handshake io failed %d, %d", rv, *a4)
struct puffs_node *
p9p_handshake(struct puffs_usermount *pu,
const char *username, const char *path)
{
struct puffs9p *p9p = puffs_getspecific(pu);
struct puffs_framebuf *pb;
struct puffs_node *pn;
struct vattr rootva;
uint32_t maxreq;
uint16_t dummy;
p9ptag_t tagid, rtagid;
p9pfid_t curfid;
const char *p;
uint8_t type;
int rv, done, x = 1, ncomp;
/* send initial handshake */
pb = p9pbuf_makeout();
p9pbuf_put_1(pb, P9PROTO_T_VERSION);
p9pbuf_put_2(pb, P9PROTO_NOTAG);
p9pbuf_put_4(pb, p9p->maxreq);
p9pbuf_put_str(pb, P9PROTO_VERSION);
DO_IO(p9pbuf_write, pu, pb, p9p->servsock, &done, rv);
puffs_framebuf_recycle(pb);
DO_IO(p9pbuf_read, pu, pb, p9p->servsock, &done, rv);
if ((type = p9pbuf_get_type(pb)) != P9PROTO_R_VERSION)
errx(1, "server invalid response to Tversion: %d", type);
if ((rtagid = p9pbuf_get_tag(pb)) != P9PROTO_NOTAG) {
errx(1, "server invalid tag: %d vs. %d",
P9PROTO_NOTAG, rtagid);
return NULL;
}
if (p9pbuf_get_4(pb, &maxreq))
errx(1, "server invalid response: no request length");
if (maxreq < P9P_MINREQLEN)
errx(1, "server request length below minimum accepted: "
"%d vs. %d", P9P_MINREQLEN, maxreq);
p9p->maxreq = maxreq;
/* tell the server we don't support authentication */
p9pbuf_recycleout(pb);
tagid = NEXTTAG(p9p);
p9pbuf_put_1(pb, P9PROTO_T_AUTH);
p9pbuf_put_2(pb, tagid);
p9pbuf_put_4(pb, P9PROTO_NOFID);
p9pbuf_put_str(pb, username);
p9pbuf_put_str(pb, "");
DO_IO(p9pbuf_write, pu, pb, p9p->servsock, &done, rv);
puffs_framebuf_recycle(pb);
DO_IO(p9pbuf_read, pu, pb, p9p->servsock, &done, rv);
/* assume all Rerror is "no auth" */
if (p9pbuf_get_type(pb) != P9PROTO_R_ERROR)
errx(1, "mount_9p supports only NO auth");
if ((rtagid = p9pbuf_get_tag(pb)) != tagid)
errx(1, "server invalid tag: %d vs. %d", tagid, rtagid);
/* build attach message */
p9pbuf_recycleout(pb);
tagid = NEXTTAG(p9p);
p9pbuf_put_1(pb, P9PROTO_T_ATTACH);
p9pbuf_put_2(pb, tagid);
p9pbuf_put_4(pb, P9P_ROOTFID);
p9pbuf_put_4(pb, P9PROTO_NOFID);
p9pbuf_put_str(pb, username);
p9pbuf_put_str(pb, "");
DO_IO(p9pbuf_write, pu, pb, p9p->servsock, &done, rv);
puffs_framebuf_recycle(pb);
DO_IO(p9pbuf_read, pu, pb, p9p->servsock, &done, rv);
if ((type = p9pbuf_get_type(pb)) != P9PROTO_R_ATTACH)
errx(1, "Rattach not received, got %d", type);
if ((rtagid = p9pbuf_get_tag(pb)) != tagid)
errx(1, "server invalid tag: %d vs. %d", tagid, rtagid);
/* just walk away rootfid, you won't see me follow you back home */
#define EATSLASH(p) while (*(p) == '/') p++
assert(*path == '/');
p = path;
EATSLASH(p);
for (ncomp = 0; p && *p; ncomp++) {
EATSLASH(p);
if (!*p)
break;
p = strchr(p, '/');
}
if (ncomp == 0) {
curfid = P9P_ROOTFID;
} else {
uint16_t walked;
p9pbuf_recycleout(pb);
tagid = NEXTTAG(p9p);
curfid = NEXTFID(p9p);
p9pbuf_put_1(pb, P9PROTO_T_WALK);
p9pbuf_put_2(pb, tagid);
p9pbuf_put_4(pb, P9P_ROOTFID);
p9pbuf_put_4(pb, curfid);
p9pbuf_put_2(pb, ncomp);
p = path;
while (p && *p) {
char *p2;
EATSLASH(p);
if (!*p)
break;
if ((p2 = strchr(p, '/')) == NULL)
p2 = strchr(p, '\0');
p9pbuf_put_data(pb, p, p2-p);
p = p2;
}
DO_IO(p9pbuf_write, pu, pb, p9p->servsock, &done, rv);
puffs_framebuf_recycle(pb);
DO_IO(p9pbuf_read, pu, pb, p9p->servsock, &done, rv);
if ((type = p9pbuf_get_type(pb)) != P9PROTO_R_WALK)
errx(1, "Rwalk not received for rnode, got %d", type);
if ((rtagid = p9pbuf_get_tag(pb)) != tagid)
errx(1, "server invalid tag: %d vs. %d",
tagid, rtagid);
if (p9pbuf_get_2(pb, &walked) == -1)
errx(1, "can't get number of walked qids");
if (walked != ncomp)
errx(1, "can't locate rootpath %s, only %d/%d "
"components found", path, walked, ncomp);
/* curfid is alive, clunk P9P_ROOTFID */
p9pbuf_recycleout(pb);
tagid = NEXTTAG(p9p);
p9pbuf_put_1(pb, P9PROTO_T_CLUNK);
p9pbuf_put_2(pb, tagid);
p9pbuf_put_4(pb, P9P_ROOTFID);
DO_IO(p9pbuf_write, pu, pb, p9p->servsock, &done, rv);
puffs_framebuf_recycle(pb);
DO_IO(p9pbuf_read, pu, pb, p9p->servsock, &done, rv);
/* wedontcare */
}
/* finally, stat the node */
p9pbuf_recycleout(pb);
tagid = NEXTTAG(p9p);
p9pbuf_put_1(pb, P9PROTO_T_STAT);
p9pbuf_put_2(pb, tagid);
p9pbuf_put_4(pb, curfid);
DO_IO(p9pbuf_write, pu, pb, p9p->servsock, &done, rv);
puffs_framebuf_recycle(pb);
DO_IO(p9pbuf_read, pu, pb, p9p->servsock, &done, rv);
if ((type = p9pbuf_get_type(pb)) != P9PROTO_R_STAT)
errx(1, "Rstat not received, got %d", type);
if ((rtagid = p9pbuf_get_tag(pb)) != tagid)
errx(1, "server invalid tag: %d vs. %d", tagid, rtagid);
if (p9pbuf_get_2(pb, &dummy))
errx(1, "couldn't get stat len parameter");
if (proto_getstat(pb, &rootva, NULL, NULL))
errx(1, "could not parse root attributes");
puffs_framebuf_destroy(pb);
rootva.va_nlink = 0156; /* guess, will be fixed with first readdir */
pn = newp9pnode_va(pu, &rootva, curfid);
if (ioctl(p9p->servsock, FIONBIO, &x) == -1)
err(1, "cannot set socket in nonblocking mode");
return pn;
}
int
puffs9p_fs_unmount(struct puffs_usermount *pu, int flags)
{
struct puffs9p *p9p = puffs_getspecific(pu);
close(p9p->servsock);
return 0;
}

View File

@ -0,0 +1,70 @@
.\" $NetBSD: mount_9p.8,v 1.4 2007/12/02 21:03:32 wiz Exp $
.\"
.\" Copyright (c) 2007 Antti Kantee. 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 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 THE 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.
.\"
.Dd July 8, 2007
.Dt MOUNT_9P 8
.Os
.Sh NAME
.Nm mount_9p
.Nd mount a file server using the 9P resource sharing protocol
.Sh SYNOPSIS
.Nm
.Op Fl s
.Op Fl o Ar mntopts
.Op Fl p Ar port
.Ar [user@]host[:path]
.Ar mount_point
.Sh DESCRIPTION
The
.Nm
program is used to mount a file hierarchy served with the Plan 9
file sharing protocol: 9P.
After the file system is mounted, the files on the remote
.Ar host
will be accessed using the credentials of the user named
.Ar user
and whatever UID the user happens to have on the remote server.
If
.Ar path
is supplied, it is used as the mount rootpath on the remote host.
.Ar path
must be an absolute path.
.Sh SEE ALSO
.Xr puffs 3 ,
.Xr puffs 4 ,
.Xr mount 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 5.0 .
.Sh CAVEATS
Permissions are not handled well.
.Pp
Authentication support is missing.
.Pp
Error code handling is missing.
.Pp
Under construction.

View File

@ -0,0 +1,338 @@
/* $NetBSD: ninebuf.c,v 1.8 2012/11/04 22:38:19 christos Exp $ */
/*
* Copyright (c) 2006, 2007 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: ninebuf.c,v 1.8 2012/11/04 22:38:19 christos Exp $");
#endif /* !lint */
#include <sys/types.h>
#include <sys/time.h>
#include <sys/vnode.h>
#include <sys/socket.h>
#include <err.h>
#include <errno.h>
#include <stdlib.h>
#include <util.h>
#include <unistd.h>
#include "ninepuffs.h"
#define CHECK(v) if (!(v)) abort()
uint8_t
p9pbuf_get_type(struct puffs_framebuf *pb)
{
uint8_t val;
puffs_framebuf_getdata_atoff(pb, 4, &val, 1);
return val;
}
uint16_t
p9pbuf_get_tag(struct puffs_framebuf *pb)
{
uint16_t val;
puffs_framebuf_getdata_atoff(pb, 5, &val, 2);
return le16toh(val);
}
static uint32_t
p9pbuf_get_len(struct puffs_framebuf *pb)
{
uint32_t val;
puffs_framebuf_getdata_atoff(pb, 0, &val, 4);
return le32toh(val);
}
#define CUROFF(pb) (puffs_framebuf_telloff(pb))
int
p9pbuf_read(struct puffs_usermount *pu, struct puffs_framebuf *pb,
int fd, int *done)
{
void *win;
ssize_t n;
size_t howmuch, winlen;
int lenstate;
the_next_level:
if ((lenstate = (CUROFF(pb) < 4)))
howmuch = 4 - CUROFF(pb);
else
howmuch = p9pbuf_get_len(pb) - CUROFF(pb);
if (puffs_framebuf_reserve_space(pb, howmuch) == -1)
return errno;
while (howmuch) {
winlen = howmuch;
if (puffs_framebuf_getwindow(pb, CUROFF(pb), &win, &winlen)==-1)
return errno;
n = read(fd, win, winlen);
switch (n) {
case 0:
return ECONNRESET;
case -1:
if (errno == EAGAIN)
return 0;
return errno;
default:
howmuch -= n;
puffs_framebuf_seekset(pb, CUROFF(pb) + n);
break;
}
}
if (!lenstate) {
puffs_framebuf_seekset(pb, 7);
*done = 1;
return 0;
} else
goto the_next_level;
}
int
p9pbuf_write(struct puffs_usermount *pu, struct puffs_framebuf *pb,
int fd, int *done)
{
void *win;
ssize_t n;
size_t winlen, howmuch;
if (CUROFF(pb) == 0) {
uint32_t len;
len = htole32(puffs_framebuf_tellsize(pb));
puffs_framebuf_putdata_atoff(pb, 0, &len, 4);
}
howmuch = puffs_framebuf_tellsize(pb) - CUROFF(pb);
while (howmuch) {
winlen = howmuch;
if (puffs_framebuf_getwindow(pb, CUROFF(pb), &win, &winlen)==-1)
return errno;
n = send(fd, win, winlen, MSG_NOSIGNAL);
switch (n) {
case 0:
return ECONNRESET;
case -1:
if (errno == EAGAIN)
return 0;
return errno;
default:
howmuch -= n;
puffs_framebuf_seekset(pb, CUROFF(pb) + n);
break;
}
}
*done = 1;
return 0;
}
#undef CUROFF
int
p9pbuf_cmp(struct puffs_usermount *pu,
struct puffs_framebuf *c1, struct puffs_framebuf *c2, int *notresp)
{
return p9pbuf_get_tag(c1) != p9pbuf_get_tag(c2);
}
struct puffs_framebuf *
p9pbuf_makeout()
{
struct puffs_framebuf *pb;
pb = puffs_framebuf_make();
puffs_framebuf_seekset(pb, 4);
return pb;
}
void
p9pbuf_recycleout(struct puffs_framebuf *pb)
{
puffs_framebuf_recycle(pb);
puffs_framebuf_seekset(pb, 4);
}
void
p9pbuf_put_1(struct puffs_framebuf *pb, uint8_t val)
{
int rv;
rv = puffs_framebuf_putdata(pb, &val, 1);
CHECK(rv == 0);
}
void
p9pbuf_put_2(struct puffs_framebuf *pb, uint16_t val)
{
int rv;
HTOLE16(val);
rv = puffs_framebuf_putdata(pb, &val, 2);
CHECK(rv == 0);
}
void
p9pbuf_put_4(struct puffs_framebuf *pb, uint32_t val)
{
int rv;
HTOLE32(val);
rv = puffs_framebuf_putdata(pb, &val, 4);
CHECK(rv == 0);
}
void
p9pbuf_put_8(struct puffs_framebuf *pb, uint64_t val)
{
int rv;
HTOLE64(val);
rv = puffs_framebuf_putdata(pb, &val, 8);
CHECK(rv == 0);
}
void
p9pbuf_put_data(struct puffs_framebuf *pb, const void *data, uint16_t dlen)
{
int rv;
p9pbuf_put_2(pb, dlen);
rv = puffs_framebuf_putdata(pb, data, dlen);
CHECK(rv == 0);
}
void
p9pbuf_put_str(struct puffs_framebuf *pb, const char *str)
{
p9pbuf_put_data(pb, str, strlen(str));
}
void
p9pbuf_write_data(struct puffs_framebuf *pb, uint8_t *data, uint32_t dlen)
{
int rv;
rv = puffs_framebuf_putdata(pb, data, dlen);
CHECK(rv == 0);
}
#define ERETURN(rv) return ((rv) == -1 ? errno : 0)
int
p9pbuf_get_1(struct puffs_framebuf *pb, uint8_t *val)
{
ERETURN(puffs_framebuf_getdata(pb, val, 1));
}
int
p9pbuf_get_2(struct puffs_framebuf *pb, uint16_t *val)
{
int rv;
rv = puffs_framebuf_getdata(pb, val, 2);
LE16TOH(*val);
ERETURN(rv);
}
int
p9pbuf_get_4(struct puffs_framebuf *pb, uint32_t *val)
{
int rv;
rv = puffs_framebuf_getdata(pb, val, 4);
LE32TOH(*val);
ERETURN(rv);
}
int
p9pbuf_get_8(struct puffs_framebuf *pb, uint64_t *val)
{
int rv;
rv = puffs_framebuf_getdata(pb, val, 8);
LE64TOH(*val);
ERETURN(rv);
}
int
p9pbuf_get_data(struct puffs_framebuf *pb, uint8_t **dp, uint16_t *dlenp)
{
uint8_t *data;
uint16_t len;
int rv;
rv = p9pbuf_get_2(pb, &len);
if (rv)
return errno;
if (puffs_framebuf_remaining(pb) < len)
return EPROTO;
if (dp) {
data = emalloc(len+1);
rv = puffs_framebuf_getdata(pb, data, len);
if (rv) {
free(data);
return errno;
}
data[len] = '\0';
*dp = data;
} else
puffs_framebuf_seekset(pb, puffs_framebuf_telloff(pb)+len);
if (dlenp)
*dlenp = len;
return 0;
}
int
p9pbuf_read_data(struct puffs_framebuf *pb, uint8_t *buf, uint32_t dlen)
{
ERETURN(puffs_framebuf_getdata(pb, buf, dlen));
}
int
p9pbuf_get_str(struct puffs_framebuf *pb, char **dp, uint16_t *dlenp)
{
return p9pbuf_get_data(pb, (uint8_t **)dp, dlenp);
}

View File

@ -0,0 +1,365 @@
/* $NetBSD: nineproto.c,v 1.9 2007/11/30 19:02:38 pooka Exp $ */
/*
* Copyright (c) 2007 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: nineproto.c,v 1.9 2007/11/30 19:02:38 pooka Exp $");
#endif /* !lint */
#include <sys/types.h>
#include <errno.h>
#include <grp.h>
#include <pwd.h>
#include <puffs.h>
#include <stdio.h>
#include <stdlib.h>
#include "ninepuffs.h"
#include "nineproto.h"
int
proto_getqid(struct puffs_framebuf *pb, struct qid9p *qid)
{
if (puffs_framebuf_remaining(pb) < 1+4+8)
return ENOBUFS;
p9pbuf_get_1(pb, &qid->qidtype);
p9pbuf_get_4(pb, &qid->qidvers);
p9pbuf_get_8(pb, &qid->qidpath);
return 0;
}
static uid_t
ustr2uid(char *uid)
{
struct passwd *pw;
pw = getpwnam(uid);
if (pw == NULL)
return 0; /* XXXXX */
return pw->pw_uid;
}
static gid_t
gstr2gid(char *gid)
{
struct group *grr;
grr = getgrnam(gid);
if (grr == NULL)
return 0; /* more XXXX */
return grr->gr_gid;
}
static const char *
uid2ustr(uid_t uid)
{
struct passwd *pw;
pw = getpwuid(uid);
if (pw == NULL)
return "root"; /* XXXXX */
return pw->pw_name;
}
static const char *
gid2gstr(gid_t gid)
{
struct group *grr;
grr = getgrgid(gid);
if (grr == NULL)
return "wheel"; /* XXXXXX */
return grr->gr_name;
}
#define GETFIELD(a,b,unitsize) \
do { \
if (size < unitsize) return EPROTO; \
if ((rv = (a(pb, b)))) return rv; \
size -= unitsize; \
} while (/*CONSTCOND*/0)
#define GETSTR(val,strsize) \
do { \
if ((rv = p9pbuf_get_str(pb, val, strsize))) return rv; \
if (*strsize > size) return EPROTO; \
size -= *strsize; \
} while (/*CONSTCOND*/0)
int
proto_getstat(struct puffs_framebuf *pb, struct vattr *vap,
char **name, uint16_t *rs)
{
char *uid, *gid;
struct qid9p qid;
uint64_t flen;
uint32_t rdev, mode, atime, mtime;
uint16_t size, v16;
int rv;
/* check size */
if ((rv = p9pbuf_get_2(pb, &size)))
return rv;
if (puffs_framebuf_remaining(pb) < size)
return ENOBUFS;
if (rs)
*rs = size+2; /* compensate for size field itself */
GETFIELD(p9pbuf_get_2, &v16, 2);
if (v16)
printf("%d\n", v16);
GETFIELD(p9pbuf_get_4, &rdev, 4);
GETFIELD(proto_getqid, &qid, 13);
GETFIELD(p9pbuf_get_4, &mode, 4);
GETFIELD(p9pbuf_get_4, &atime, 4);
GETFIELD(p9pbuf_get_4, &mtime, 4);
GETFIELD(p9pbuf_get_8, &flen, 8);
GETSTR(name, &v16);
GETSTR(&uid, &v16);
GETSTR(&gid, &v16);
if (rdev)
printf("%d\n", rdev);
vap->va_rdev = rdev;
vap->va_mode = mode & 0777; /* may contain other uninteresting bits */
vap->va_atime.tv_sec = atime;
vap->va_mtime.tv_sec = mtime;
vap->va_ctime.tv_sec = mtime;
vap->va_atime.tv_nsec=vap->va_mtime.tv_nsec=vap->va_ctime.tv_nsec = 0;
vap->va_birthtime.tv_sec = vap->va_birthtime.tv_nsec = 0;
vap->va_size = vap->va_bytes = flen;
vap->va_uid = ustr2uid(uid);
vap->va_gid = gstr2gid(gid);
free(uid);
free(gid);
qid2vattr(vap, &qid);
/* some defaults */
if (vap->va_type == VDIR)
vap->va_nlink = 1906;
else
vap->va_nlink = 1;
vap->va_blocksize = 512;
vap->va_flags = vap->va_vaflags = 0;
vap->va_filerev = PUFFS_VNOVAL;
/* muid, not used */
GETSTR(NULL, &v16);
return 0;
}
int
proto_cc_dupfid(struct puffs_usermount *pu, p9pfid_t oldfid, p9pfid_t newfid)
{
struct puffs_cc *pcc = puffs_cc_getcc(pu);
struct puffs9p *p9p = puffs_getspecific(pu);
struct puffs_framebuf *pb;
p9ptag_t tag = NEXTTAG(p9p);
uint16_t qids;
int rv = 0;
pb = p9pbuf_makeout();
p9pbuf_put_1(pb, P9PROTO_T_WALK);
p9pbuf_put_2(pb, tag);
p9pbuf_put_4(pb, oldfid);
p9pbuf_put_4(pb, newfid);
p9pbuf_put_2(pb, 0);
GETRESPONSE(pb);
rv = proto_expect_walk_nqids(pb, &qids);
if (rv == 0 && qids != 0)
rv = EPROTO;
out:
puffs_framebuf_destroy(pb);
return rv;
}
int
proto_cc_clunkfid(struct puffs_usermount *pu, p9pfid_t fid, int waitforit)
{
struct puffs_cc *pcc = puffs_cc_getcc(pu);
struct puffs9p *p9p = puffs_getspecific(pu);
struct puffs_framebuf *pb;
p9ptag_t tag = NEXTTAG(p9p);
int rv = 0;
pb = p9pbuf_makeout();
p9pbuf_put_1(pb, P9PROTO_T_CLUNK);
p9pbuf_put_2(pb, tag);
p9pbuf_put_4(pb, fid);
if (waitforit) {
if (puffs_framev_enqueue_cc(pcc, p9p->servsock, pb, 0) == 0) {
if (p9pbuf_get_type(pb) != P9PROTO_R_CLUNK)
rv = EPROTO;
} else {
rv = errno;
}
puffs_framebuf_destroy(pb);
} else {
JUSTSEND(pb);
}
out:
return rv;
}
/*
* walk a new fid, then open it
*/
int
proto_cc_open(struct puffs_usermount *pu, p9pfid_t fid,
p9pfid_t newfid, int mode)
{
struct puffs_cc *pcc = puffs_cc_getcc(pu);
struct puffs9p *p9p = puffs_getspecific(pu);
struct puffs_framebuf *pb;
p9ptag_t tag = NEXTTAG(p9p);
int rv;
rv = proto_cc_dupfid(pu, fid, newfid);
if (rv)
return rv;
pb = p9pbuf_makeout();
p9pbuf_put_1(pb, P9PROTO_T_OPEN);
p9pbuf_put_2(pb, tag);
p9pbuf_put_4(pb, newfid);
p9pbuf_put_1(pb, mode);
GETRESPONSE(pb);
if (p9pbuf_get_type(pb) != P9PROTO_R_OPEN)
rv = EPROTO;
out:
puffs_framebuf_destroy(pb);
return rv;
}
void
proto_make_stat(struct puffs_framebuf *pb, const struct vattr *vap,
const char *filename, enum vtype vt)
{
struct vattr fakeva;
uint32_t mode, atime, mtime;
uint64_t flen;
const char *owner, *group;
int startoff, curoff;
if (vap == NULL) {
puffs_vattr_null(&fakeva);
vap = &fakeva;
}
startoff = puffs_framebuf_telloff(pb);
puffs_framebuf_seekset(pb, startoff + 2+2); /* stat[n] incl. stat[2] */
if (vap->va_mode != (mode_t)PUFFS_VNOVAL)
mode = vap->va_mode | (vt == VDIR ? P9PROTO_CPERM_DIR : 0);
else
mode = P9PROTO_STAT_NOVAL4;
if (vap->va_atime.tv_sec != (time_t)PUFFS_VNOVAL)
atime = vap->va_atime.tv_sec;
else
atime = P9PROTO_STAT_NOVAL4;
if (vap->va_mtime.tv_sec != (time_t)PUFFS_VNOVAL)
mtime = vap->va_mtime.tv_sec;
else
mtime = P9PROTO_STAT_NOVAL4;
if (vap->va_size != (u_quad_t)PUFFS_VNOVAL)
flen = vap->va_size;
else
flen = P9PROTO_STAT_NOVAL8;
if (vap->va_uid != (uid_t)PUFFS_VNOVAL)
owner = uid2ustr(vap->va_uid);
else
owner = "";
if (vap->va_gid != (gid_t)PUFFS_VNOVAL)
group = gid2gstr(vap->va_gid);
else
group = "";
p9pbuf_put_2(pb, P9PROTO_STAT_NOVAL2); /* kernel type */
p9pbuf_put_4(pb, P9PROTO_STAT_NOVAL4); /* dev */
p9pbuf_put_1(pb, P9PROTO_STAT_NOVAL1); /* type */
p9pbuf_put_4(pb, P9PROTO_STAT_NOVAL4); /* version */
p9pbuf_put_8(pb, P9PROTO_STAT_NOVAL8); /* path */
p9pbuf_put_4(pb, mode);
p9pbuf_put_4(pb, atime);
p9pbuf_put_4(pb, mtime);
p9pbuf_put_8(pb, flen);
p9pbuf_put_str(pb, filename ? filename : "");
p9pbuf_put_str(pb, owner);
p9pbuf_put_str(pb, group);
p9pbuf_put_str(pb, ""); /* muid */
curoff = puffs_framebuf_telloff(pb);
puffs_framebuf_seekset(pb, startoff);
p9pbuf_put_2(pb, curoff-(startoff+2)); /* stat[n] size */
p9pbuf_put_2(pb, curoff-(startoff+4)); /* size[2] stat */
puffs_framebuf_seekset(pb, curoff);
}
int
proto_expect_walk_nqids(struct puffs_framebuf *pb, uint16_t *nqids)
{
if (p9pbuf_get_type(pb) != P9PROTO_R_WALK)
return EPROTO;
return p9pbuf_get_2(pb, nqids);
}
int
proto_expect_qid(struct puffs_framebuf *pb, uint8_t op, struct qid9p *qid)
{
if (p9pbuf_get_type(pb) != op)
return EPROTO;
return proto_getqid(pb, qid);
}
int
proto_expect_stat(struct puffs_framebuf *pb, struct vattr *va)
{
uint16_t dummy;
int rv;
if (p9pbuf_get_type(pb) != P9PROTO_R_STAT)
return EPROTO;
if ((rv = p9pbuf_get_2(pb, &dummy)))
return rv;
return proto_getstat(pb, va, NULL, NULL);
}

View File

@ -0,0 +1,93 @@
/* $NetBSD: nineproto.h,v 1.1 2007/04/21 14:21:43 pooka Exp $ */
/*
* Copyright (c) 2007 Antti Kantee. 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 AUTHOR ``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 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.
*/
#ifndef PUFFS9P_9PROTO_H_
#define PUFFS9P_9PROTO_H_
#include <stdint.h>
#define P9PROTO_VERSION "9P2000"
#define P9PROTO_T_VERSION 100
#define P9PROTO_R_VERSION 101
#define P9PROTO_T_AUTH 102
#define P9PROTO_R_AUTH 103
#define P9PROTO_T_ATTACH 104
#define P9PROTO_R_ATTACH 105
#define P9PROTO_T_ERROR 106
#define P9PROTO_R_ERROR 107
#define P9PROTO_T_FLUSH 108
#define P9PROTO_R_FLUSH 109
#define P9PROTO_T_WALK 110
#define P9PROTO_R_WALK 111
#define P9PROTO_T_OPEN 112
#define P9PROTO_R_OPEN 113
#define P9PROTO_T_CREATE 114
#define P9PROTO_R_CREATE 115
#define P9PROTO_T_READ 116
#define P9PROTO_R_READ 117
#define P9PROTO_T_WRITE 118
#define P9PROTO_R_WRITE 119
#define P9PROTO_T_CLUNK 120
#define P9PROTO_R_CLUNK 121
#define P9PROTO_T_REMOVE 122
#define P9PROTO_R_REMOVE 123
#define P9PROTO_T_STAT 124
#define P9PROTO_R_STAT 125
#define P9PROTO_T_WSTAT 126
#define P9PROTO_R_WSTAT 127
#define P9PROTO_MIN 9PROTO_T_VERSION
#define P9PROTO_MAX 9PROTO_R_MAX
#define P9PROTO_NOFID (uint32_t)~0
#define P9PROTO_NOTAG (uint16_t)~0
/* type field in a qid */
#define P9PROTO_QID_TYPE_DIR 0x80
#define P9PROTO_QID_TYPE_APPEND 0x40
#define P9PROTO_QID_TYPE_EXCL 0x20
#define P9PROTO_QID_TYPE_MOUNT 0x10
#define P9PROTO_QID_TYPE_AUTH 0x08
/* mode in open */
#define P9PROTO_OMODE_READ 0x00
#define P9PROTO_OMODE_WRITE 0x01
#define P9PROTO_OMODE_RDWR 0x02
#define P9PROTO_OMODE_EXEC 0x03
#define P9PROTO_OMODE_TRUNC 0x10
#define P9PROTO_OMODE_RMCLOSE 0x40
/* for creating directories */
#define P9PROTO_CPERM_DIR 0x80000000
/* stat non-values */
#define P9PROTO_STAT_NOVAL1 (uint8_t)~0
#define P9PROTO_STAT_NOVAL2 (uint16_t)~0
#define P9PROTO_STAT_NOVAL4 (uint32_t)~0
#define P9PROTO_STAT_NOVAL8 (uint64_t)~0
#endif /* PUFFS9P_PROTO_H_ */

View File

@ -0,0 +1,231 @@
/* $NetBSD: ninepuffs.c,v 1.24 2011/08/31 13:32:39 joerg Exp $ */
/*
* Copyright (c) 2007 Antti Kantee. 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 AUTHOR ``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 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.
*/
/*
* 9puffs: access a 9P file server as a vfs via puffs
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: ninepuffs.c,v 1.24 2011/08/31 13:32:39 joerg Exp $");
#endif /* !lint */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <netinet/in.h>
#include <assert.h>
#include <err.h>
#include <netdb.h>
#include <pwd.h>
#include <puffs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "ninepuffs.h"
#define DEFPORT_9P 564
__dead static void
usage(void)
{
fprintf(stderr, "usage: %s [-s] [-o mntopts] [-p port] "
"[user@]server[:path] mountpoint\n", getprogname());
exit(1);
}
/*
* TCPv4 connection to 9P file server, forget IL and IPv6 for now.
* Return connected socket or exit with error.
*/
static int
serverconnect(const char *addr, unsigned short port)
{
struct sockaddr_in mysin;
struct hostent *he;
int s;
he = gethostbyname2(addr, AF_INET);
if (he == NULL) {
herror("gethostbyname");
exit(1);
}
s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s == -1)
err(1, "socket");
memset(&mysin, 0, sizeof(struct sockaddr_in));
mysin.sin_family = AF_INET;
mysin.sin_port = htons(port);
memcpy(&mysin.sin_addr, he->h_addr, sizeof(struct in_addr));
if (connect(s, (struct sockaddr *)&mysin, sizeof(mysin)) == -1)
err(1, "connect");
return s;
}
int
main(int argc, char *argv[])
{
struct puffs9p p9p;
struct puffs_usermount *pu;
struct puffs_ops *pops;
struct puffs_node *pn_root;
mntoptparse_t mp;
const char *user, *srvhost, *srvpath;
char *p;
unsigned short port;
int mntflags, pflags, ch;
int detach;
setprogname(argv[0]);
if (argc < 2)
usage();
mntflags = pflags = 0;
detach = 1;
port = DEFPORT_9P;
while ((ch = getopt(argc, argv, "o:p:s")) != -1) {
switch (ch) {
case 'o':
mp = getmntopts(optarg, puffsmopts, &mntflags, &pflags);
if (mp == NULL)
err(1, "getmntopts");
freemntopts(mp);
break;
case 'p':
port = atoi(optarg);
break;
case 's':
detach = 0;
break;
default:
usage();
/*NOTREACHED*/
}
}
argc -= optind;
argv += optind;
if (argc != 2)
usage();
if (pflags & PUFFS_FLAG_OPDUMP)
detach = 0;
pflags |= PUFFS_KFLAG_WTCACHE | PUFFS_KFLAG_IAONDEMAND;
PUFFSOP_INIT(pops);
PUFFSOP_SET(pops, puffs9p, fs, unmount);
PUFFSOP_SETFSNOP(pops, sync);
PUFFSOP_SETFSNOP(pops, statvfs);
PUFFSOP_SET(pops, puffs9p, node, lookup);
PUFFSOP_SET(pops, puffs9p, node, readdir);
PUFFSOP_SET(pops, puffs9p, node, getattr);
PUFFSOP_SET(pops, puffs9p, node, setattr);
PUFFSOP_SET(pops, puffs9p, node, create);
PUFFSOP_SET(pops, puffs9p, node, open);
PUFFSOP_SET(pops, puffs9p, node, mkdir);
PUFFSOP_SET(pops, puffs9p, node, remove);
PUFFSOP_SET(pops, puffs9p, node, rmdir);
PUFFSOP_SET(pops, puffs9p, node, read);
PUFFSOP_SET(pops, puffs9p, node, write);
PUFFSOP_SET(pops, puffs9p, node, rename);
PUFFSOP_SET(pops, puffs9p, node, inactive);
PUFFSOP_SET(pops, puffs9p, node, reclaim);
#if 0
PUFFSOP_SET(pops, puffs9p, node, mknod);
#endif
pu = puffs_init(pops, argv[0], "9p", &p9p, pflags);
if (pu == NULL)
err(1, "puffs_init");
memset(&p9p, 0, sizeof(p9p));
p9p.maxreq = P9P_DEFREQLEN;
p9p.nextfid = 1;
/* user@ */
if ((p = strchr(argv[0], '@')) != NULL) {
*p = '\0';
srvhost = p+1;
user = argv[0];
} else {
struct passwd *pw;
srvhost = argv[0];
pw = getpwuid(getuid());
if (pw == NULL)
err(1, "getpwuid");
user = pw->pw_name;
}
/* :/mountpath */
if ((p = strchr(srvhost, ':')) != NULL) {
*p = '\0';
srvpath = p+1;
if (*srvpath != '/')
errx(1, "%s is not an absolute path", srvpath);
} else {
srvpath = "/";
}
p9p.servsock = serverconnect(srvhost, port);
if ((pn_root = p9p_handshake(pu, user, srvpath)) == NULL) {
puffs_exit(pu, 1);
exit(1);
}
puffs_framev_init(pu, p9pbuf_read, p9pbuf_write, p9pbuf_cmp, NULL,
puffs_framev_unmountonclose);
if (puffs_framev_addfd(pu, p9p.servsock,
PUFFS_FBIO_READ | PUFFS_FBIO_WRITE) == -1)
err(1, "puffs_framebuf_addfd");
if (detach)
if (puffs_daemon(pu, 1, 1) == -1)
err(1, "puffs_daemon");
if (puffs_mount(pu, argv[1], mntflags, pn_root) == -1)
err(1, "puffs_mount");
if (puffs_setblockingmode(pu, PUFFSDEV_NONBLOCK) == -1)
err(1, "setblockingmode");
if (puffs_mainloop(pu) == -1)
err(1, "mainloop");
return 0;
}

View File

@ -0,0 +1,178 @@
/* $NetBSD: ninepuffs.h,v 1.12 2007/11/30 19:02:38 pooka Exp $ */
/*
* Copyright (c) 2007 Antti Kantee. 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 AUTHOR ``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 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.
*/
#ifndef PUFFS9P_H_
#define PUFFS9P_H_
#include <sys/queue.h>
#include <puffs.h>
PUFFSOP_PROTOS(puffs9p);
/* Qid structure. optimized for in-mem. different order on-wire */
struct qid9p {
uint64_t qidpath;
uint32_t qidvers;
uint8_t qidtype;
};
typedef uint16_t p9ptag_t;
typedef uint32_t p9pfid_t;
/*
* refuse (no, not *that* refuse) to play if the server doesn't
* support requests of at least the following size. It would only
* make life difficult
*/
#define P9P_MINREQLEN 512
#define P9P_DEFREQLEN (16*1024)
#define P9P_INVALFID 0
#define P9P_ROOTFID 1
#define NEXTTAG(p9p) \
((++(p9p->nexttag)) == P9PROTO_NOTAG ? p9p->nexttag = 0 : p9p->nexttag)
#define NEXTFID(p9p) \
((++(p9p->nextfid)) == P9P_INVALFID ? p9p->nextfid = 2 : p9p->nextfid)
#define AUTOVAR(pu) \
struct puffs_cc *pcc = puffs_cc_getcc(pu); \
struct puffs9p *p9p = puffs_getspecific(pu); \
uint16_t tag = NEXTTAG(p9p); \
struct puffs_framebuf *pb = p9pbuf_makeout(); \
int rv = 0
#define RETURN(rv) \
puffs_framebuf_destroy(pb); \
return (rv)
#define GETRESPONSE(pb) \
do { \
if (puffs_framev_enqueue_cc(pcc, p9p->servsock, pb, 0) == -1) { \
rv = errno; \
goto out; \
} \
} while (/*CONSTCOND*/0)
#define JUSTSEND(pb) \
do { \
if (puffs_framev_enqueue_justsend(pu,p9p->servsock,pb,1,0)==-1){\
rv = errno; \
goto out; \
} \
} while (/*CONSTCOND*/0)
#define SENDCB(pb, f, a) \
do { \
if (puffs_framev_enqueue_cb(pu, p9p->servsock,pb,f,a,0) == -1) {\
rv = errno; \
goto out; \
} \
} while (/*CONSTCOND*/0)
struct puffs9p {
int servsock;
p9ptag_t nexttag;
p9pfid_t nextfid;
size_t maxreq; /* negotiated with server */
};
struct dirfid {
p9pfid_t fid;
off_t seekoff;
LIST_ENTRY(dirfid) entries;
};
struct p9pnode {
p9pfid_t fid_base;
p9pfid_t fid_read;
p9pfid_t fid_write;
LIST_HEAD(,dirfid) dir_openlist;
};
struct puffs_framebuf *p9pbuf_makeout(void);
void p9pbuf_recycleout(struct puffs_framebuf *);
int p9pbuf_read(struct puffs_usermount *, struct puffs_framebuf *,int,int*);
int p9pbuf_write(struct puffs_usermount *, struct puffs_framebuf*,int,int*);
int p9pbuf_cmp(struct puffs_usermount *,
struct puffs_framebuf *, struct puffs_framebuf *, int *);
void p9pbuf_put_1(struct puffs_framebuf *, uint8_t);
void p9pbuf_put_2(struct puffs_framebuf *, uint16_t);
void p9pbuf_put_4(struct puffs_framebuf *, uint32_t);
void p9pbuf_put_8(struct puffs_framebuf *, uint64_t);
void p9pbuf_put_str(struct puffs_framebuf *, const char *);
void p9pbuf_put_data(struct puffs_framebuf *, const void *, uint16_t);
void p9pbuf_write_data(struct puffs_framebuf *, uint8_t *, uint32_t);
int p9pbuf_get_1(struct puffs_framebuf *, uint8_t *);
int p9pbuf_get_2(struct puffs_framebuf *, uint16_t *);
int p9pbuf_get_4(struct puffs_framebuf *, uint32_t *);
int p9pbuf_get_8(struct puffs_framebuf *, uint64_t *);
int p9pbuf_get_str(struct puffs_framebuf *, char **, uint16_t *);
int p9pbuf_get_data(struct puffs_framebuf *, uint8_t **, uint16_t *);
int p9pbuf_read_data(struct puffs_framebuf *, uint8_t *, uint32_t);
uint8_t p9pbuf_get_type(struct puffs_framebuf *);
uint16_t p9pbuf_get_tag(struct puffs_framebuf *);
int proto_getqid(struct puffs_framebuf *, struct qid9p *);
int proto_getstat(struct puffs_framebuf *, struct vattr *,
char **, uint16_t *);
int proto_expect_walk_nqids(struct puffs_framebuf *, uint16_t *);
int proto_expect_stat(struct puffs_framebuf *, struct vattr *);
int proto_expect_qid(struct puffs_framebuf *, uint8_t, struct qid9p *);
int proto_cc_dupfid(struct puffs_usermount *, p9pfid_t, p9pfid_t);
int proto_cc_clunkfid(struct puffs_usermount *, p9pfid_t, int);
int proto_cc_open(struct puffs_usermount *, p9pfid_t, p9pfid_t, int);
void proto_make_stat(struct puffs_framebuf *, const struct vattr *,
const char *, enum vtype);
struct puffs_node *p9p_handshake(struct puffs_usermount *,
const char *, const char *);
void qid2vattr(struct vattr *, const struct qid9p *);
struct puffs_node *newp9pnode_va(struct puffs_usermount *,
const struct vattr *, p9pfid_t);
struct puffs_node *newp9pnode_qid(struct puffs_usermount *,
const struct qid9p *, p9pfid_t);
int getdfwithoffset(struct puffs_usermount *, struct p9pnode *, off_t,
struct dirfid **);
void storedf(struct p9pnode *, struct dirfid *);
void releasedf(struct puffs_usermount *, struct dirfid *);
void nukealldf(struct puffs_usermount *, struct p9pnode *);
#endif /* PUFFS9P_H_ */

View File

@ -0,0 +1,616 @@
/* $NetBSD: node.c,v 1.21 2009/01/18 10:10:47 lukem Exp $ */
/*
* Copyright (c) 2007 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: node.c,v 1.21 2009/01/18 10:10:47 lukem Exp $");
#endif /* !lint */
#include <assert.h>
#include <errno.h>
#include <puffs.h>
#include <stdio.h>
#include <stdlib.h>
#include "ninepuffs.h"
#include "nineproto.h"
static void *
nodecmp(struct puffs_usermount *pu, struct puffs_node *pn, void *arg)
{
struct vattr *vap = &pn->pn_va;
struct qid9p *qid = arg;
if (vap->va_fileid == qid->qidpath && vap->va_gen == qid->qidvers)
return pn;
return NULL;
}
static int
do_getattr(struct puffs_usermount *pu, struct puffs_node *pn, struct vattr *vap)
{
AUTOVAR(pu);
struct p9pnode *p9n = pn->pn_data;
p9pbuf_put_1(pb, P9PROTO_T_STAT);
p9pbuf_put_2(pb, tag);
p9pbuf_put_4(pb, p9n->fid_base);
GETRESPONSE(pb);
rv = proto_expect_stat(pb, vap);
out:
RETURN(rv);
}
int
puffs9p_node_getattr(struct puffs_usermount *pu, void *opc, struct vattr *vap,
const struct puffs_cred *pcr)
{
struct puffs_node *pn = opc;
int rv;
rv = do_getattr(pu, pn, &pn->pn_va);
if (rv == 0)
memcpy(vap, &pn->pn_va, sizeof(struct vattr));
return rv;
}
int
puffs9p_node_lookup(struct puffs_usermount *pu, void *opc, struct puffs_newinfo *pni,
const struct puffs_cn *pcn)
{
AUTOVAR(pu);
struct vattr va;
struct puffs_node *pn, *pn_dir = opc;
struct p9pnode *p9n_dir = pn_dir->pn_data;
p9ptag_t tfid = NEXTFID(p9p);
struct qid9p newqid;
uint16_t nqid;
p9pbuf_put_1(pb, P9PROTO_T_WALK);
p9pbuf_put_2(pb, tag);
p9pbuf_put_4(pb, p9n_dir->fid_base);
p9pbuf_put_4(pb, tfid);
p9pbuf_put_2(pb, 1);
p9pbuf_put_str(pb, pcn->pcn_name);
GETRESPONSE(pb);
rv = proto_expect_walk_nqids(pb, &nqid);
if (rv) {
rv = ENOENT;
goto out;
}
if (nqid != 1) {
rv = EPROTO;
goto out;
}
if ((rv = proto_getqid(pb, &newqid)))
goto out;
/* we get the parent vers in walk(?) compensate */
p9pbuf_recycleout(pb);
tag = NEXTTAG(p9p);
p9pbuf_put_1(pb, P9PROTO_T_STAT);
p9pbuf_put_2(pb, tag);
p9pbuf_put_4(pb, tfid);
GETRESPONSE(pb);
if ((rv = proto_expect_stat(pb, &va)) != 0) {
proto_cc_clunkfid(pu, tfid, 0);
rv = ENOENT;
goto out;
}
if (newqid.qidpath != va.va_fileid) {
proto_cc_clunkfid(pu, tfid, 0);
rv = EPROTO;
goto out;
}
newqid.qidvers = va.va_gen;
pn = puffs_pn_nodewalk(pu, nodecmp, &newqid);
if (pn == NULL)
pn = newp9pnode_qid(pu, &newqid, tfid);
else
proto_cc_clunkfid(pu, tfid, 0);
/* assert pn */
memcpy(&pn->pn_va, &va, sizeof(va));
puffs_newinfo_setcookie(pni, pn);
puffs_newinfo_setvtype(pni, pn->pn_va.va_type);
puffs_newinfo_setsize(pni, pn->pn_va.va_size);
puffs_newinfo_setrdev(pni, pn->pn_va.va_rdev);
out:
RETURN(rv);
}
/*
* Problem is that 9P doesn't allow seeking into a directory. So we
* maintain a list of active fids for any given directory. They
* start living at the first read and exist either until the directory
* is closed or until they reach the end.
*/
int
puffs9p_node_readdir(struct puffs_usermount *pu, void *opc, struct dirent *dent,
off_t *readoff, size_t *reslen, const struct puffs_cred *pcr,
int *eofflag, off_t *cookies, size_t *ncookies)
{
AUTOVAR(pu);
struct puffs_node *pn = opc;
struct p9pnode *p9n = pn->pn_data;
struct vattr va;
struct dirfid *dfp;
char *name;
uint32_t count;
uint16_t statsize;
rv = getdfwithoffset(pu, p9n, *readoff, &dfp);
if (rv)
goto out;
tag = NEXTTAG(p9p);
p9pbuf_put_1(pb, P9PROTO_T_READ);
p9pbuf_put_2(pb, tag);
p9pbuf_put_4(pb, dfp->fid);
p9pbuf_put_8(pb, *readoff);
p9pbuf_put_4(pb, *reslen); /* XXX */
GETRESPONSE(pb);
p9pbuf_get_4(pb, &count);
/*
* if count is 0, assume we at end-of-dir. dfp is no longer
* useful, so nuke it
*/
if (count == 0) {
*eofflag = 1;
releasedf(pu, dfp);
goto out;
}
while (count > 0) {
if ((rv = proto_getstat(pb, &va, &name, &statsize))) {
/*
* If there was an error, it's unlikely we'll be
* coming back, so just nuke the dfp. If we do
* come back for some strange reason, we'll just
* regen it.
*/
releasedf(pu, dfp);
goto out;
}
puffs_nextdent(&dent, name, va.va_fileid,
puffs_vtype2dt(va.va_type), reslen);
count -= statsize;
*readoff += statsize;
dfp->seekoff += statsize;
free(name);
}
storedf(p9n, dfp);
out:
RETURN(rv);
}
int
puffs9p_node_setattr(struct puffs_usermount *pu, void *opc,
const struct vattr *va, const struct puffs_cred *pcr)
{
AUTOVAR(pu);
struct puffs_node *pn = opc;
struct p9pnode *p9n = pn->pn_data;
p9pbuf_put_1(pb, P9PROTO_T_WSTAT);
p9pbuf_put_2(pb, tag);
p9pbuf_put_4(pb, p9n->fid_base);
proto_make_stat(pb, va, NULL, pn->pn_va.va_type);
GETRESPONSE(pb);
if (p9pbuf_get_type(pb) != P9PROTO_R_WSTAT)
rv = EPROTO;
out:
RETURN(rv);
}
/*
* Ok, time to get clever. There are two possible cases: we are
* opening a file or we are opening a directory.
*
* If it's a directory, don't bother opening it here, but rather
* wait until readdir, since it's probable we need to be able to
* open a directory there in any case.
*
* If it's a regular file, open it here with whatever credentials
* we happen to have. Let the upper layers of the kernel worry
* about permission control.
*/
int
puffs9p_node_open(struct puffs_usermount *pu, void *opc, int mode,
const struct puffs_cred *pcr)
{
struct puffs_cc *pcc = puffs_cc_getcc(pu);
struct puffs9p *p9p = puffs_getspecific(pu);
struct puffs_node *pn = opc;
struct p9pnode *p9n = pn->pn_data;
p9pfid_t nfid;
int error = 0;
puffs_setback(pcc, PUFFS_SETBACK_INACT_N1);
if (pn->pn_va.va_type != VDIR) {
if (mode & FREAD && p9n->fid_read == P9P_INVALFID) {
nfid = NEXTFID(p9p);
error = proto_cc_open(pu, p9n->fid_base, nfid,
P9PROTO_OMODE_READ);
if (error)
return error;
p9n->fid_read = nfid;
}
if (mode & FWRITE && p9n->fid_write == P9P_INVALFID) {
nfid = NEXTFID(p9p);
error = proto_cc_open(pu, p9n->fid_base, nfid,
P9PROTO_OMODE_WRITE);
if (error)
return error;
p9n->fid_write = nfid;
}
}
return 0;
}
int
puffs9p_node_inactive(struct puffs_usermount *pu, void *opc)
{
struct puffs_node *pn = opc;
struct p9pnode *p9n = pn->pn_data;
if (pn->pn_va.va_type == VDIR) {
nukealldf(pu, p9n);
} else {
if (p9n->fid_read != P9P_INVALFID) {
proto_cc_clunkfid(pu, p9n->fid_read, 0);
p9n->fid_read = P9P_INVALFID;
}
if (p9n->fid_write != P9P_INVALFID) {
proto_cc_clunkfid(pu, p9n->fid_write, 0);
p9n->fid_write = P9P_INVALFID;
}
}
return 0;
}
int
puffs9p_node_read(struct puffs_usermount *pu, void *opc, uint8_t *buf,
off_t offset, size_t *resid, const struct puffs_cred *pcr,
int ioflag)
{
AUTOVAR(pu);
struct puffs_node *pn = opc;
struct p9pnode *p9n = pn->pn_data;
uint32_t count;
size_t nread;
nread = 0;
while (*resid > 0 && (uint64_t)(offset+nread) < pn->pn_va.va_size) {
p9pbuf_put_1(pb, P9PROTO_T_READ);
p9pbuf_put_2(pb, tag);
p9pbuf_put_4(pb, p9n->fid_read);
p9pbuf_put_8(pb, offset+nread);
p9pbuf_put_4(pb, MIN((uint32_t)*resid,p9p->maxreq-24));
GETRESPONSE(pb);
if (p9pbuf_get_type(pb) != P9PROTO_R_READ) {
rv = EPROTO;
break;
}
p9pbuf_get_4(pb, &count);
if ((rv = p9pbuf_read_data(pb, buf + nread, count)))
break;
if (count == 0)
break;
*resid -= count;
nread += count;
p9pbuf_recycleout(pb);
}
out:
RETURN(rv);
}
int
puffs9p_node_write(struct puffs_usermount *pu, void *opc, uint8_t *buf,
off_t offset, size_t *resid, const struct puffs_cred *cred,
int ioflag)
{
AUTOVAR(pu);
struct puffs_node *pn = opc;
struct p9pnode *p9n = pn->pn_data;
uint32_t chunk, count;
size_t nwrite;
if (ioflag & PUFFS_IO_APPEND)
offset = pn->pn_va.va_size;
nwrite = 0;
while (*resid > 0) {
chunk = MIN(*resid, p9p->maxreq-32);
p9pbuf_put_1(pb, P9PROTO_T_WRITE);
p9pbuf_put_2(pb, tag);
p9pbuf_put_4(pb, p9n->fid_write);
p9pbuf_put_8(pb, offset+nwrite);
p9pbuf_put_4(pb, chunk);
p9pbuf_write_data(pb, buf+nwrite, chunk);
GETRESPONSE(pb);
if (p9pbuf_get_type(pb) != P9PROTO_R_WRITE) {
rv = EPROTO;
break;
}
p9pbuf_get_4(pb, &count);
*resid -= count;
nwrite += count;
if (count != chunk) {
rv = EPROTO;
break;
}
p9pbuf_recycleout(pb);
}
out:
RETURN(rv);
}
static int
nodecreate(struct puffs_usermount *pu, struct puffs_node *pn,
struct puffs_newinfo *pni, const char *name,
const struct vattr *vap, uint32_t dirbit)
{
AUTOVAR(pu);
struct puffs_node *pn_new;
struct p9pnode *p9n = pn->pn_data;
p9pfid_t nfid = NEXTFID(p9p);
struct qid9p nqid;
int tries = 0;
again:
if (++tries > 5) {
rv = EPROTO;
goto out;
}
rv = proto_cc_dupfid(pu, p9n->fid_base, nfid);
if (rv)
goto out;
p9pbuf_put_1(pb, P9PROTO_T_CREATE);
p9pbuf_put_2(pb, tag);
p9pbuf_put_4(pb, nfid);
p9pbuf_put_str(pb, name);
p9pbuf_put_4(pb, dirbit | (vap->va_mode & 0777));
p9pbuf_put_1(pb, 0);
GETRESPONSE(pb);
rv = proto_expect_qid(pb, P9PROTO_R_CREATE, &nqid);
if (rv)
goto out;
/*
* Now, little problem here: create returns an *open* fid.
* So, clunk it and walk the parent directory to get a fid
* which is not open for I/O yet.
*/
proto_cc_clunkfid(pu, nfid, 0);
nfid = NEXTFID(p9p);
p9pbuf_recycleout(pb);
p9pbuf_put_1(pb, P9PROTO_T_WALK);
p9pbuf_put_2(pb, tag);
p9pbuf_put_4(pb, p9n->fid_base);
p9pbuf_put_4(pb, nfid);
p9pbuf_put_2(pb, 1);
p9pbuf_put_str(pb, name);
GETRESPONSE(pb);
/*
* someone removed it already? try again
* note: this is kind of lose/lose
*/
if (p9pbuf_get_type(pb) != P9PROTO_R_WALK)
goto again;
pn_new = newp9pnode_va(pu, vap, nfid);
qid2vattr(&pn_new->pn_va, &nqid);
puffs_newinfo_setcookie(pni, pn_new);
out:
RETURN(rv);
}
int
puffs9p_node_create(struct puffs_usermount *pu, void *opc, struct puffs_newinfo *pni,
const struct puffs_cn *pcn, const struct vattr *va)
{
return nodecreate(pu, opc, pni, pcn->pcn_name, va, 0);
}
int
puffs9p_node_mkdir(struct puffs_usermount *pu, void *opc, struct puffs_newinfo *pni,
const struct puffs_cn *pcn, const struct vattr *va)
{
return nodecreate(pu, opc, pni, pcn->pcn_name,
va, P9PROTO_CPERM_DIR);
}
/*
* Need to be a bit clever again: the fid is clunked no matter if
* the remove succeeds or not. Re-getting a fid would be way too
* difficult in case the remove failed for a valid reason (directory
* not empty etcetc.). So walk ourselves another fid to prod the
* ice with.
*/
static int
noderemove(struct puffs_usermount *pu, struct puffs_node *pn)
{
AUTOVAR(pu);
struct p9pnode *p9n = pn->pn_data;
p9pfid_t testfid = NEXTFID(p9p);
rv = proto_cc_dupfid(pu, p9n->fid_base, testfid);
if (rv)
goto out;
p9pbuf_put_1(pb, P9PROTO_T_REMOVE);
p9pbuf_put_2(pb, tag);
p9pbuf_put_4(pb, testfid);
/*
* XXX: error handling isn't very robust, but doom is impending
* anyway, so just accept we're going belly up and play dead
*/
GETRESPONSE(pb);
if (p9pbuf_get_type(pb) != P9PROTO_R_REMOVE) {
rv = EPROTO;
} else {
proto_cc_clunkfid(pu, p9n->fid_base, 0);
p9n->fid_base = P9P_INVALFID;
puffs_pn_remove(pn);
}
out:
if (rv == 0)
puffs_setback(pcc, PUFFS_SETBACK_NOREF_N2);
RETURN(rv);
}
int
puffs9p_node_remove(struct puffs_usermount *pu, void *opc, void *targ,
const struct puffs_cn *pcn)
{
struct puffs_node *pn = targ;
if (pn->pn_va.va_type == VDIR)
return EISDIR;
return noderemove(pu, pn);
}
int
puffs9p_node_rmdir(struct puffs_usermount *pu, void *opc, void *targ,
const struct puffs_cn *pcn)
{
struct puffs_node *pn = targ;
if (pn->pn_va.va_type != VDIR)
return ENOTDIR;
return noderemove(pu, pn);
}
/*
* 9P supports renames only for files within a directory
* from what I could tell. So just support in-directory renames
* for now.
*/
int
puffs9p_node_rename(struct puffs_usermount *pu, void *opc, void *src,
const struct puffs_cn *pcn_src, void *targ_dir, void *targ,
const struct puffs_cn *pcn_targ)
{
AUTOVAR(pu);
struct puffs_node *pn_src = src;
struct p9pnode *p9n_src = pn_src->pn_data;
if (opc != targ_dir) {
rv = EOPNOTSUPP;
goto out;
}
/* 9P doesn't allow to overwrite in rename */
if (targ) {
struct puffs_node *pn_targ = targ;
rv = noderemove(pu, pn_targ->pn_data);
if (rv)
goto out;
}
p9pbuf_put_1(pb, P9PROTO_T_WSTAT);
p9pbuf_put_2(pb, tag);
p9pbuf_put_4(pb, p9n_src->fid_base);
proto_make_stat(pb, NULL, pcn_targ->pcn_name, pn_src->pn_va.va_type);
GETRESPONSE(pb);
if (p9pbuf_get_type(pb) != P9PROTO_R_WSTAT)
rv = EPROTO;
out:
RETURN(rv);
}
/*
* - "here's one"
* - "9P"
* ~ "i'm not dead"
* - "you're not fooling anyone you know, you'll be stone dead in a minute
* - "he says he's not quite dead"
* - "isn't there anything you could do?"
* - *clunk*!
* - "thanks"
*/
int
puffs9p_node_reclaim(struct puffs_usermount *pu, void *opc)
{
struct puffs_node *pn = opc;
struct p9pnode *p9n = pn->pn_data;
assert(LIST_EMPTY(&p9n->dir_openlist));
assert(p9n->fid_read == P9P_INVALFID && p9n->fid_write == P9P_INVALFID);
proto_cc_clunkfid(pu, p9n->fid_base, 0);
free(p9n);
puffs_pn_put(pn);
return 0;
}

View File

@ -0,0 +1,197 @@
/* $NetBSD: subr.c,v 1.6 2007/11/30 19:02:39 pooka Exp $ */
/*
* Copyright (c) 2007 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: subr.c,v 1.6 2007/11/30 19:02:39 pooka Exp $");
#endif /* !lint */
#include <sys/types.h>
#include <errno.h>
#include <puffs.h>
#include <stdlib.h>
#include <util.h>
#include "ninepuffs.h"
#include "nineproto.h"
void
qid2vattr(struct vattr *vap, const struct qid9p *qid)
{
vap->va_fileid = qid->qidpath;
vap->va_gen = qid->qidvers;
if (qid->qidtype & P9PROTO_QID_TYPE_DIR)
vap->va_type = VDIR;
else
vap->va_type = VREG;
}
static struct puffs_node *
makep9pnode(struct puffs_usermount *pu, p9pfid_t fid)
{
struct p9pnode *p9n;
struct puffs_node *pn;
p9n = emalloc(sizeof(struct p9pnode));
memset(p9n, 0, sizeof(struct p9pnode));
p9n->fid_base = fid;
LIST_INIT(&p9n->dir_openlist);
pn = puffs_pn_new(pu, p9n);
if (pn == NULL)
abort();
return pn;
}
struct puffs_node *
newp9pnode_va(struct puffs_usermount *pu, const struct vattr *va, p9pfid_t fid)
{
struct puffs_node *pn;
pn = makep9pnode(pu, fid);
pn->pn_va = *va;
return pn;
}
struct puffs_node *
newp9pnode_qid(struct puffs_usermount *pu, const struct qid9p *qid,
p9pfid_t fid)
{
struct puffs_node *pn;
pn = makep9pnode(pu, fid);
puffs_vattr_null(&pn->pn_va);
qid2vattr(&pn->pn_va, qid);
return pn;
}
/*
* search list of fids, or if none is found, walk a fid for a new one
* and issue dummy readdirs until we get the result we want
*/
int
getdfwithoffset(struct puffs_usermount *pu, struct p9pnode *p9n, off_t wantoff,
struct dirfid **rfid)
{
struct puffs_cc *pcc = puffs_cc_getcc(pu);
struct puffs9p *p9p = puffs_getspecific(pu);
struct puffs_framebuf *pb;
struct dirfid *dfp = NULL;
p9ptag_t tag = NEXTTAG(p9p);
off_t curoff, advance;
uint32_t count;
int rv;
LIST_FOREACH(dfp, &p9n->dir_openlist, entries) {
if (dfp->seekoff == wantoff) {
LIST_REMOVE(dfp, entries);
*rfid = dfp;
return 0;
}
}
/* didn't get off easy? damn, do manual labour */
pb = p9pbuf_makeout();
dfp = ecalloc(1, sizeof(struct dirfid));
dfp->fid = NEXTFID(p9p);
rv = proto_cc_open(pu, p9n->fid_base, dfp->fid, P9PROTO_OMODE_READ);
if (rv)
goto out;
for (curoff = 0;;) {
advance = wantoff - curoff;
tag = NEXTTAG(p9p);
p9pbuf_put_1(pb, P9PROTO_T_READ);
p9pbuf_put_2(pb, tag);
p9pbuf_put_4(pb, dfp->fid);
p9pbuf_put_8(pb, 0);
p9pbuf_put_4(pb, advance);
GETRESPONSE(pb);
if (p9pbuf_get_type(pb) != P9PROTO_R_READ) {
rv = EPROTO;
goto out;
}
/*
* Check how many bytes we got. If we got the amount we
* wanted, we are at the correct position. If we got
* zero bytes, either the directory doesn't "support" the
* seek offset we want (someone has probably inserted an
* entry meantime) or we at the end of directory. Either
* way, let the upper layer deal with it.
*/
p9pbuf_get_4(pb, &count);
curoff += count;
if (count == advance || count == 0)
break;
p9pbuf_recycleout(pb);
}
puffs_framebuf_destroy(pb);
dfp->seekoff = curoff;
*rfid = dfp;
return 0;
out:
puffs_framebuf_destroy(pb);
free(dfp);
return rv;
}
void
releasedf(struct puffs_usermount *pu, struct dirfid *dfp)
{
proto_cc_clunkfid(pu, dfp->fid, 0);
free(dfp);
}
void
storedf(struct p9pnode *p9n, struct dirfid *dfp)
{
LIST_INSERT_HEAD(&p9n->dir_openlist, dfp, entries);
}
void
nukealldf(struct puffs_usermount *pu, struct p9pnode *p9n)
{
struct dirfid *dfp;
while ((dfp = LIST_FIRST(&p9n->dir_openlist)) != NULL) {
LIST_REMOVE(dfp, entries);
releasedf(pu, dfp);
}
}

View File

@ -0,0 +1,9 @@
# $NetBSD: Makefile,v 1.4 2009/04/22 15:23:07 lukem Exp $
PROG= mount_psshfs
SRCS= psshfs.c fs.c node.c psbuf.c subr.c
LDADD+= -lpuffs -lutil
MAN= mount_psshfs.8
.include <bsd.prog.mk>

View File

@ -0,0 +1,279 @@
/* $NetBSD: fs.c,v 1.24 2011/06/22 04:03:23 mrg Exp $ */
/*
* Copyright (c) 2006-2009 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: fs.c,v 1.24 2011/06/22 04:03:23 mrg Exp $");
#endif /* !lint */
#include <err.h>
#include <errno.h>
#include <puffs.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "psshfs.h"
#include "sftp_proto.h"
#define DO_IO(fname, a1, a2, a3, a4, rv) \
do { \
puffs_framebuf_seekset(a2, 0); \
*(a4) = 0; \
rv = fname(a1, a2, a3, a4); \
if (rv) { \
return rv ? rv : EPROTO; \
} \
} while (/*CONSTCOND*/0)
#define reterr(str, rv) \
do { \
fprintf str; \
return rv; \
} while (/*CONSTCOND*/0)
/* openssh extensions */
static const struct extunit {
const char *ext;
const char *val;
int extflag;
} exttable[] = {
{
"posix-rename@openssh.com",
"1",
SFTP_EXT_POSIX_RENAME,
},{
"statvfs@openssh.com",
"2",
SFTP_EXT_STATVFS,
},{
"fstatvfs@openssh.com",
"2",
SFTP_EXT_FSTATVFS,
},{
NULL,
NULL,
0
}};
int
psshfs_handshake(struct puffs_usermount *pu, int fd)
{
struct psshfs_ctx *pctx = puffs_getspecific(pu);
struct puffs_framebuf *pb;
struct puffs_pathobj *po_root;
struct puffs_node *pn_root;
struct vattr va, *rva;
const struct extunit *extu;
char *rootpath;
char *ext, *val;
uint32_t count;
int rv, done;
pb = psbuf_makeout();
psbuf_put_1(pb, SSH_FXP_INIT);
psbuf_put_4(pb, SFTP_PROTOVERSION);
DO_IO(psbuf_write, pu, pb, fd, &done, rv);
puffs_framebuf_recycle(pb);
DO_IO(psbuf_read, pu, pb, fd, &done, rv);
if (psbuf_get_type(pb) != SSH_FXP_VERSION)
reterr((stderr, "invalid server response: %d",
psbuf_get_type(pb)), EPROTO);
pctx->protover = psbuf_get_reqid(pb);
/*
* Check out which extensions are available. Currently
* we are only interested in the openssh statvfs extension.
*/
for (;;) {
if (psbuf_get_str(pb, &ext, NULL) != 0)
break;
if (psbuf_get_str(pb, &val, NULL) != 0)
break;
for (extu = exttable; extu->ext; extu++)
if (strcmp(ext, extu->ext) == 0
&& strcmp(val, extu->val) == 0)
pctx->extensions |= extu->extflag;
}
/* scope out our rootpath */
psbuf_recycleout(pb);
psbuf_put_1(pb, SSH_FXP_REALPATH);
psbuf_put_4(pb, NEXTREQ(pctx));
psbuf_put_str(pb, pctx->mountpath);
DO_IO(psbuf_write, pu, pb, fd, &done, rv);
puffs_framebuf_recycle(pb);
DO_IO(psbuf_read, pu, pb, fd, &done, rv);
if (psbuf_get_type(pb) != SSH_FXP_NAME)
reterr((stderr, "invalid server realpath response for \"%s\"",
pctx->mountpath), EPROTO);
if (psbuf_get_4(pb, &count) == -1)
reterr((stderr, "invalid realpath response: count"), EPROTO);
if (psbuf_get_str(pb, &rootpath, NULL) == -1)
reterr((stderr, "invalid realpath response: rootpath"), EPROTO);
/* stat the rootdir so that we know it's a dir */
psbuf_recycleout(pb);
psbuf_req_str(pb, SSH_FXP_LSTAT, NEXTREQ(pctx), rootpath);
DO_IO(psbuf_write, pu, pb, fd, &done, rv);
puffs_framebuf_recycle(pb);
DO_IO(psbuf_read, pu, pb, fd, &done, rv);
rv = psbuf_expect_attrs(pb, &va);
if (rv)
reterr((stderr, "couldn't stat rootpath"), rv);
puffs_framebuf_destroy(pb);
if (puffs_mode2vt(va.va_mode) != VDIR)
reterr((stderr, "remote path (%s) not a directory", rootpath),
ENOTDIR);
pn_root = puffs_getroot(pu);
rva = &pn_root->pn_va;
puffs_setvattr(rva, &va);
po_root = puffs_getrootpathobj(pu);
if (po_root == NULL)
err(1, "getrootpathobj");
po_root->po_path = rootpath;
po_root->po_len = strlen(rootpath);
return 0;
}
int
psshfs_fs_statvfs(struct puffs_usermount *pu, struct statvfs *sbp)
{
PSSHFSAUTOVAR(pu);
uint64_t tmpval;
uint8_t type;
memset(sbp, 0, sizeof(*sbp));
sbp->f_bsize = sbp->f_frsize = sbp->f_iosize = 512;
if ((pctx->extensions & SFTP_EXT_STATVFS) == 0)
goto out;
psbuf_req_str(pb, SSH_FXP_EXTENDED, reqid, "statvfs@openssh.com");
psbuf_put_str(pb, pctx->mountpath);
GETRESPONSE(pb, pctx->sshfd);
type = psbuf_get_type(pb);
if (type != SSH_FXP_EXTENDED_REPLY) {
/* use the default */
goto out;
}
psbuf_get_8(pb, &tmpval);
sbp->f_bsize = tmpval;
psbuf_get_8(pb, &tmpval);
sbp->f_frsize = tmpval;
psbuf_get_8(pb, &sbp->f_blocks);
psbuf_get_8(pb, &sbp->f_bfree);
psbuf_get_8(pb, &sbp->f_bavail);
psbuf_get_8(pb, &sbp->f_files);
psbuf_get_8(pb, &sbp->f_ffree);
psbuf_get_8(pb, &sbp->f_favail);
psbuf_get_8(pb, &tmpval); /* fsid */
psbuf_get_8(pb, &tmpval); /* flag */
psbuf_get_8(pb, &tmpval);
sbp->f_namemax = tmpval;
sbp->f_bresvd = sbp->f_bfree - sbp->f_bavail;
sbp->f_fresvd = sbp->f_ffree - sbp->f_favail;
out:
PSSHFSRETURN(rv);
}
int
psshfs_fs_unmount(struct puffs_usermount *pu, int flags)
{
struct psshfs_ctx *pctx = puffs_getspecific(pu);
kill(pctx->sshpid, SIGTERM);
close(pctx->sshfd);
if (pctx->numconnections == 2) {
kill(pctx->sshpid_data, SIGTERM);
close(pctx->sshfd_data);
}
return 0;
}
int
psshfs_fs_nodetofh(struct puffs_usermount *pu, puffs_cookie_t cookie,
void *fid, size_t *fidsize)
{
struct psshfs_ctx *pctx = puffs_getspecific(pu);
struct puffs_node *pn = cookie;
struct psshfs_node *psn = pn->pn_data;
struct psshfs_fid *pf = fid;
pf->mounttime = pctx->mounttime;
pf->node = pn;
psn->stat |= PSN_HASFH;
return 0;
}
int
psshfs_fs_fhtonode(struct puffs_usermount *pu, void *fid, size_t fidsize,
struct puffs_newinfo *pni)
{
struct psshfs_ctx *pctx = puffs_getspecific(pu);
struct psshfs_fid *pf = fid;
struct puffs_node *pn = pf->node;
struct psshfs_node *psn;
int rv;
if (pf->mounttime != pctx->mounttime)
return EINVAL;
if (pn == 0)
return EINVAL;
psn = pn->pn_data;
if ((psn->stat & PSN_HASFH) == 0)
return EINVAL;
/* update node attributes */
rv = getnodeattr(pu, pn, NULL);
if (rv)
return EINVAL;
puffs_newinfo_setcookie(pni, pn);
puffs_newinfo_setvtype(pni, pn->pn_va.va_type);
puffs_newinfo_setsize(pni, pn->pn_va.va_size);
return 0;
}

View File

@ -0,0 +1,205 @@
.\" $NetBSD: mount_psshfs.8,v 1.27 2014/06/25 23:22:18 szptvlfn Exp $
.\"
.\" Copyright (c) 2007-2009 Antti Kantee. 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 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 THE 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.
.\"
.Dd January 7, 2010
.Dt MOUNT_PSSHFS 8
.Os
.Sh NAME
.Nm mount_psshfs
.Nd sshfs implementation for puffs
.Sh SYNOPSIS
.Nm
.Op Ar options
.Ar user@host[:path]
.Ar mount_point
.Sh DESCRIPTION
The
.Nm
utility can be used to mount a file system using the ssh sftp
subprotocol, making a remote directory hierarchy appear in the
local directory tree.
This functionality is commonly known as
.Em sshfs .
.Pp
The mandatory parameters are the target host name and local mount
point.
The target host parameter can optionally contain a username whose
credentials will be used by the remote sshd, and a relative or
absolute path for the remote mount point's root.
If no user is given, the credentials of the user issuing the mount
command are used.
If no path is given, the user's home directory on the remote machine
will be used.
.Pp
The following command line options are available:
.Pp
.Bl -tag -width xxx
.It Fl c Ar nconnect
Opens
.Ar nconnect
connections to the server.
Currently, the value has to be 1 or 2.
If 2 is specified, a second connection is opened for the reading
and writing of data, while directory operations are performed on
their own connection.
This can greatly increase directory operation performance (ls,
mkdir, etc.) if
.Nm
completely saturates the available bandwidth by doing bulk data copying.
The default is 1.
.It Fl e
Makes the mounted file system NFS exportable.
If this option is used, it is very important to understand that
.Nm
can not provide complete support for NFS due to the limitations in
the backend.
Files are valid only for the time that
.Nm
is running and in the event of e.g. a server crash, all client retries
to access files will fail.
.It Fl F Ar configfile
Pass a configuration file to
.Xr ssh 1 .
This will make it ignore the system-wide
.Pa /etc/ssh/ssh_config
configuration file and use
.Pa configfile
instead of
.Pa ~/.ssh/config .
.It Fl g Ar manglegid
Converts remote
.Ar manglegid
to the effective gid of the file server and vice versa.
See
.Fl u .
.It Fl o Ar [no]option
This flag can be used to give standard mount options and options
to puffs.
.It Fl O Ar sshopt=value
Pass an option to
.Xr ssh 1 ,
for example
.Fl O Ar Port=22 .
For a list of valid options, see
.Xr ssh_config 5 .
.It Fl p
Preserve connection.
This option makes
.Nm
to try to reconnect to the server if the connection fails.
The option is very experimental and does not preserve open files
or retry current requests and should generally only be used if the
trade-offs are well understood.
.It Fl r Ar max_reads
Limits maximum outstanding read requests for each node to
.Ar max_reads .
This can be used to improve interactive performance on low-bandwidth links
when also performing bulk data reads.
.It Fl s
This flag can be used to make the program stay on top.
The default is to detach from the terminal and run in the background.
.It Fl t Ar timeout
By default
.Nm
caches directory contents and node attributes for 30 seconds before
re-fetching from the server to check if anything has changed on
the server.
This option is used to adjust the timeout period to
.Ar timeout
seconds.
A value of 0 means the cache is never valid; \-1 means it is
valid indefinitely.
It is possible to force a re-read regardless of timeout status by sending
.Dv SIGHUP
to the
.Nm
process.
.Pp
Note: the file system will still free nodes when requested by the
kernel and will lose all cached information in doing so.
How frequently this happens depends on system activity and the total
number of available vnodes in the system (kern.maxvnodes).
.It Fl u Ar mangleuid
Converts remote
.Ar mangleuid
to the effective uid of the file server and vice versa.
This is a simple special case of the functionality of
.Xr mount_umap 8 .
For example: you mount remote me@darkmoon as the local user "me".
If the uid of "me" on the local system is 101 and on
darkmoon it is 202, you would use
.Fl u
.Ar 202
to see files owned by 202 on darkmoon as owned by 101 when browsing the
mount point.
Apart from the cosmetic effect, this makes things like
"chown me file" work.
See
.Fl g .
.El
.Sh EXAMPLES
The following example illustrates how to mount the directory
.Em /usr
on server
.Em bigiron
as user
.Em abc
on local directory
.Em /mnt
with ssh transport compression enabled:
.Bd -literal -offset indent
mount_psshfs -O Compression=yes abc@bigiron:/usr /mnt
.Ed
.Pp
It is possible to use
.Xr fstab 5
for psshfs mounts, with SSH public key authentication:
.Pp
.Dl "abc@bigiron:/usr /mnt psshfs rw,noauto,-O=BatchMode=yes,-O=IdentityFile=/root/.ssh/id_rsa,-t=-1"
.Sh SEE ALSO
.Xr sftp 1 ,
.Xr puffs 3 ,
.Xr puffs 4 ,
.Xr fstab 5 ,
.Xr ssh_config 5 ,
.Xr mount 8 ,
.Xr sshd 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 5.0 .
It was inspired by FUSE sshfs.
.Sh CAVEATS
Permissions are not handled.
Do not expect the file system to behave except for a single user.
.Pp
Depending on if the server supports the
.Xr sftp 1
statvfs protocol extension,
free disk space may be displayed for the mount by
.Xr df 1 .
This information reflects the status at the server's mountpoint
and may differ for subdirectories under the mount root.

View File

@ -0,0 +1,949 @@
/* $NetBSD: node.c,v 1.64 2012/01/20 22:07:58 jakllsch Exp $ */
/*
* Copyright (c) 2006-2009 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: node.c,v 1.64 2012/01/20 22:07:58 jakllsch Exp $");
#endif /* !lint */
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "psshfs.h"
#include "sftp_proto.h"
int
psshfs_node_lookup(struct puffs_usermount *pu, puffs_cookie_t opc,
struct puffs_newinfo *pni, const struct puffs_cn *pcn)
{
struct psshfs_ctx *pctx = puffs_getspecific(pu);
struct puffs_node *pn_dir = opc;
struct psshfs_node *psn, *psn_dir = pn_dir->pn_data;
struct puffs_node *pn;
struct psshfs_dir *pd;
struct vattr va;
int rv;
if (PCNISDOTDOT(pcn)) {
psn = psn_dir->parent->pn_data;
psn->stat &= ~PSN_RECLAIMED;
puffs_newinfo_setcookie(pni, psn_dir->parent);
puffs_newinfo_setvtype(pni, VDIR);
return 0;
}
rv = sftp_readdir(pu, pctx, pn_dir);
if (rv) {
if (rv != EPERM)
return rv;
/*
* Can't read the directory. We still might be
* able to find the node with getattr in -r+x dirs
*/
rv = getpathattr(pu, PCNPATH(pcn), &va);
if (rv)
return rv;
/* guess */
if (va.va_type == VDIR)
va.va_nlink = 2;
else
va.va_nlink = 1;
pn = allocnode(pu, pn_dir, pcn->pcn_name, &va);
psn = pn->pn_data;
psn->attrread = time(NULL);
} else {
pd = lookup(psn_dir->dir, psn_dir->dentnext, pcn->pcn_name);
if (!pd) {
return ENOENT;
}
if (pd->entry)
pn = pd->entry;
else
pd->entry = pn = makenode(pu, pn_dir, pd, &pd->va);
/*
* sure sure we have fresh attributes. most likely we will
* have them cached. we might not if we go through:
* create - reclaim - lookup (this).
*/
rv = getnodeattr(pu, pn, PCNPATH(pcn));
if (rv)
return rv;
psn = pn->pn_data;
}
psn->stat &= ~PSN_RECLAIMED;
puffs_newinfo_setcookie(pni, pn);
puffs_newinfo_setvtype(pni, pn->pn_va.va_type);
puffs_newinfo_setsize(pni, pn->pn_va.va_size);
return 0;
}
int
psshfs_node_getattr(struct puffs_usermount *pu, puffs_cookie_t opc,
struct vattr *vap, const struct puffs_cred *pcr)
{
struct puffs_node *pn = opc;
int rv;
rv = getnodeattr(pu, pn, NULL);
if (rv)
return rv;
memcpy(vap, &pn->pn_va, sizeof(struct vattr));
return 0;
}
int
psshfs_node_setattr(struct puffs_usermount *pu, puffs_cookie_t opc,
const struct vattr *va, const struct puffs_cred *pcr)
{
struct puffs_cc *pcc = puffs_cc_getcc(pu);
struct psshfs_ctx *pctx = puffs_getspecific(pu);
uint32_t reqid;
struct puffs_framebuf *pb;
struct vattr kludgeva;
struct puffs_node *pn = opc;
struct psshfs_node *psn = pn->pn_data;
int rv;
/*
* If we cached the remote attributes recently enough, and this
* setattr operation would change nothing that sftp actually
* records, then we can skip the sftp request. So first check
* whether we have the attributes cached, and then compare
* every field that we might send to the sftp server.
*/
if (!psn->attrread || REFRESHTIMEOUT(pctx, time(NULL)-psn->attrread))
goto setattr;
#define CHECK(FIELD, TYPE) do { \
if ((va->FIELD != (TYPE)PUFFS_VNOVAL) && \
(va->FIELD != pn->pn_va.FIELD)) \
goto setattr; \
} while (0)
#define CHECKID(FIELD, TYPE, DOMANGLE, MINE, MANGLED) do { \
if ((va->FIELD != (TYPE)PUFFS_VNOVAL) && \
(pn->pn_va.FIELD != \
((pctx->DOMANGLE && (va->FIELD == pctx->MINE)) \
? pctx->MANGLED \
: va->FIELD))) \
goto setattr; \
} while (0)
CHECK(va_size, uint64_t);
CHECKID(va_uid, uid_t, domangleuid, myuid, mangleuid);
CHECKID(va_gid, gid_t, domanglegid, mygid, manglegid);
CHECK(va_mode, mode_t);
CHECK(va_atime.tv_sec, time_t);
CHECK(va_mtime.tv_sec, time_t);
/* Nothing to change. */
return 0;
#undef CHECK
#undef CHECKID
setattr:
reqid = NEXTREQ(pctx);
pb = psbuf_makeout();
psbuf_req_str(pb, SSH_FXP_SETSTAT, reqid, PNPATH(pn));
memcpy(&kludgeva, va, sizeof(struct vattr));
/* XXX: kludge due to openssh server implementation */
if (va->va_atime.tv_sec != PUFFS_VNOVAL
&& va->va_mtime.tv_sec == PUFFS_VNOVAL) {
if (pn->pn_va.va_mtime.tv_sec != PUFFS_VNOVAL)
kludgeva.va_mtime.tv_sec = pn->pn_va.va_mtime.tv_sec;
else
kludgeva.va_mtime.tv_sec = va->va_atime.tv_sec;
}
if (va->va_mtime.tv_sec != PUFFS_VNOVAL
&& va->va_atime.tv_sec == PUFFS_VNOVAL) {
if (pn->pn_va.va_atime.tv_sec != PUFFS_VNOVAL)
kludgeva.va_atime.tv_sec = pn->pn_va.va_atime.tv_sec;
else
kludgeva.va_atime.tv_sec = va->va_mtime.tv_sec;
}
psbuf_put_vattr(pb, &kludgeva, pctx);
GETRESPONSE(pb, pctx->sshfd);
rv = psbuf_expect_status(pb);
if (rv == 0) {
puffs_setvattr(&pn->pn_va, &kludgeva);
psn->attrread = time(NULL);
}
out:
puffs_framebuf_destroy(pb);
return rv;
}
int
psshfs_node_create(struct puffs_usermount *pu, puffs_cookie_t opc,
struct puffs_newinfo *pni, const struct puffs_cn *pcn,
const struct vattr *va)
{
PSSHFSAUTOVAR(pu);
struct puffs_node *pn = opc;
struct puffs_node *pn_new;
char *fhand = NULL;
uint32_t fhandlen;
/* Create node on server first */
psbuf_req_str(pb, SSH_FXP_OPEN, reqid, PCNPATH(pcn));
psbuf_put_4(pb, SSH_FXF_WRITE | SSH_FXF_CREAT | SSH_FXF_TRUNC);
psbuf_put_vattr(pb, va, pctx);
GETRESPONSE(pb, pctx->sshfd);
rv = psbuf_expect_handle(pb, &fhand, &fhandlen);
if (rv)
goto out;
/*
* Do *not* create the local node before getting a response
* from the server. Otherwise we might screw up consistency,
* namely that the node can be looked up before create has
* returned (mind you, the kernel will unlock the directory
* before the create call from userspace returns).
*/
pn_new = allocnode(pu, pn, pcn->pcn_name, va);
if (!pn_new) {
struct puffs_framebuf *pb2 = psbuf_makeout();
reqid = NEXTREQ(pctx);
psbuf_req_str(pb2, SSH_FXP_REMOVE, reqid, PCNPATH(pcn));
JUSTSEND(pb2, pctx->sshfd);
rv = ENOMEM;
}
if (pn_new)
puffs_newinfo_setcookie(pni, pn_new);
reqid = NEXTREQ(pctx);
psbuf_recycleout(pb);
psbuf_req_data(pb, SSH_FXP_CLOSE, reqid, fhand, fhandlen);
JUSTSEND(pb, pctx->sshfd);
free(fhand);
return rv;
out:
free(fhand);
PSSHFSRETURN(rv);
}
/*
* Open a file handle. This is used for read and write. We do not
* wait here for the success or failure of this operation. This is
* because otherwise opening and closing file handles would block
* reading potentially cached information. Rather, we defer the wait
* to read/write and therefore allow cached access without a wait.
*
* If we have not yet succesfully opened a type of handle, we do wait
* here. Also, if a lazy open fails, we revert back to the same
* state of waiting.
*/
int
psshfs_node_open(struct puffs_usermount *pu, puffs_cookie_t opc, int mode,
const struct puffs_cred *pcr)
{
struct puffs_cc *pcc = puffs_cc_getcc(pu);
struct psshfs_ctx *pctx = puffs_getspecific(pu);
struct puffs_framebuf *pb, *pb2;
struct vattr va;
struct puffs_node *pn = opc;
struct psshfs_node *psn = pn->pn_data;
uint32_t reqid;
int didread, didwrite;
int rv = 0;
if (pn->pn_va.va_type == VDIR)
return 0;
puffs_setback(pcc, PUFFS_SETBACK_INACT_N1);
puffs_vattr_null(&va);
didread = didwrite = 0;
if (mode & FREAD && psn->fhand_r == NULL && psn->lazyopen_r == NULL) {
pb = psbuf_makeout();
reqid = NEXTREQ(pctx);
psbuf_req_str(pb, SSH_FXP_OPEN, reqid, PNPATH(pn));
psbuf_put_4(pb, SSH_FXF_READ);
psbuf_put_vattr(pb, &va, pctx);
if (puffs_framev_enqueue_cb(pu, pctx->sshfd_data, pb,
lazyopen_rresp, psn, 0) == -1) {
rv = errno;
puffs_framebuf_destroy(pb);
goto out;
}
psn->lazyopen_r = pb;
didread = 1;
}
if (mode & FWRITE && psn->fhand_w == NULL && psn->lazyopen_w == NULL) {
pb2 = psbuf_makeout();
reqid = NEXTREQ(pctx);
psbuf_req_str(pb2, SSH_FXP_OPEN, reqid, PNPATH(pn));
psbuf_put_4(pb2, SSH_FXF_WRITE);
psbuf_put_vattr(pb2, &va, pctx);
if (puffs_framev_enqueue_cb(pu, pctx->sshfd_data, pb2,
lazyopen_wresp, psn, 0) == -1) {
rv = errno;
puffs_framebuf_destroy(pb2);
goto out;
}
psn->lazyopen_w = pb2;
didwrite = 1;
}
psn->stat &= ~PSN_HANDLECLOSE;
out:
/* wait? */
if (didread && (psn->stat & PSN_DOLAZY_R) == 0) {
assert(psn->lazyopen_r);
rv = puffs_framev_framebuf_ccpromote(psn->lazyopen_r, pcc);
lazyopen_rresp(pu, psn->lazyopen_r, psn, rv);
if (psn->fhand_r) {
psn->stat |= PSN_DOLAZY_R;
} else {
if (psn->lazyopen_err_r)
return psn->lazyopen_err_r;
return EINVAL;
}
}
/* wait? */
if (didwrite && (psn->stat & PSN_DOLAZY_W) == 0) {
assert(psn->lazyopen_w);
rv = puffs_framev_framebuf_ccpromote(psn->lazyopen_w, pcc);
lazyopen_wresp(pu, psn->lazyopen_w, psn, rv);
if (psn->fhand_w) {
psn->stat |= PSN_DOLAZY_W;
} else {
if (psn->lazyopen_err_w)
return psn->lazyopen_err_w;
return EINVAL;
}
}
return rv;
}
int
psshfs_node_inactive(struct puffs_usermount *pu, puffs_cookie_t opc)
{
struct puffs_node *pn = opc;
closehandles(pu, pn->pn_data, HANDLE_READ | HANDLE_WRITE);
return 0;
}
int
psshfs_node_readdir(struct puffs_usermount *pu, puffs_cookie_t opc,
struct dirent *dent, off_t *readoff, size_t *reslen,
const struct puffs_cred *pcr, int *eofflag,
off_t *cookies, size_t *ncookies)
{
struct puffs_cc *pcc = puffs_cc_getcc(pu);
struct psshfs_ctx *pctx = puffs_getspecific(pu);
struct puffs_node *pn = opc;
struct psshfs_node *psn = pn->pn_data;
struct psshfs_dir *pd;
size_t i;
int rv, set_readdir;
restart:
if (psn->stat & PSN_READDIR) {
struct psshfs_wait pw;
set_readdir = 0;
pw.pw_cc = pcc;
pw.pw_type = PWTYPE_READDIR;
TAILQ_INSERT_TAIL(&psn->pw, &pw, pw_entries);
puffs_cc_yield(pcc);
goto restart;
} else {
psn->stat |= PSN_READDIR;
set_readdir = 1;
}
*ncookies = 0;
rv = sftp_readdir(pu, pctx, pn);
if (rv) {
goto out;
}
/* find next dirent */
for (i = *readoff;;i++) {
if (i >= psn->dentnext)
goto out;
pd = &psn->dir[i];
if (pd->valid)
break;
}
for (;;) {
*readoff = i;
if (!puffs_nextdent(&dent, pd->entryname,
pd->va.va_fileid, puffs_vtype2dt(pd->va.va_type), reslen)) {
rv = 0;
goto out;
}
/* find next entry, store possible nfs key */
do {
if (++i >= psn->dentnext)
goto out;
pd = &psn->dir[i];
} while (pd->valid == 0);
PUFFS_STORE_DCOOKIE(cookies, ncookies, (off_t)i);
}
out:
if (rv == 0) {
if (i >= psn->dentnext)
*eofflag = 1;
*readoff = i;
}
if (set_readdir) {
struct psshfs_wait *pw;
/* all will likely run to completion because of cache */
TAILQ_FOREACH(pw, &psn->pw, pw_entries) {
assert(pw->pw_type == PWTYPE_READDIR);
puffs_cc_schedule(pw->pw_cc);
TAILQ_REMOVE(&psn->pw, pw, pw_entries);
}
psn->stat &= ~PSN_READDIR;
}
return rv;
}
int
psshfs_node_read(struct puffs_usermount *pu, puffs_cookie_t opc, uint8_t *buf,
off_t offset, size_t *resid, const struct puffs_cred *pcr,
int ioflag)
{
PSSHFSAUTOVAR(pu);
struct puffs_node *pn = opc;
struct psshfs_node *psn = pn->pn_data;
struct psshfs_wait *pwp;
uint32_t readlen;
if (pn->pn_va.va_type == VDIR) {
rv = EISDIR;
goto farout;
}
/* check that a lazyopen didn't fail */
if (!psn->fhand_r && !psn->lazyopen_r) {
rv = psn->lazyopen_err_r;
goto farout;
}
/* if someone is already waiting for the lazyopen, "just" wait */
if (psn->stat & PSN_LAZYWAIT_R) {
struct psshfs_wait pw;
assert(psn->lazyopen_r);
pw.pw_cc = pcc;
pw.pw_type = PWTYPE_READ1;
TAILQ_INSERT_TAIL(&psn->pw, &pw, pw_entries);
puffs_cc_yield(pcc);
}
/* if lazyopening, wait for the result */
if (psn->lazyopen_r) {
psn->stat |= PSN_LAZYWAIT_R;
rv = puffs_framev_framebuf_ccpromote(psn->lazyopen_r, pcc);
lazyopen_rresp(pu, psn->lazyopen_r, psn, rv);
/* schedule extra waiters */
TAILQ_FOREACH(pwp, &psn->pw, pw_entries)
if (pwp->pw_type == PWTYPE_READ1) {
puffs_cc_schedule(pwp->pw_cc);
TAILQ_REMOVE(&psn->pw, pwp, pw_entries);
}
psn->stat &= ~PSN_LAZYWAIT_R;
if ((rv = psn->lazyopen_err_r) != 0)
goto farout;
}
/* if there is still no handle, just refuse to live with this */
if (!psn->fhand_r) {
rv = EINVAL;
goto farout;
}
again:
readlen = *resid;
psbuf_req_data(pb, SSH_FXP_READ, reqid, psn->fhand_r, psn->fhand_r_len);
psbuf_put_8(pb, offset);
psbuf_put_4(pb, readlen);
/*
* Do this *after* accessing the file, the handle might not
* exist after blocking.
*/
if (max_reads && ++psn->readcount > max_reads) {
struct psshfs_wait pw;
pw.pw_cc = pcc;
pw.pw_type = PWTYPE_READ2;
TAILQ_INSERT_TAIL(&psn->pw, &pw, pw_entries);
puffs_cc_yield(pcc);
}
GETRESPONSE(pb, pctx->sshfd_data);
rv = psbuf_do_data(pb, buf, &readlen);
if (rv == 0) {
*resid -= readlen;
buf += readlen;
offset += readlen;
}
out:
if (max_reads && --psn->readcount >= max_reads) {
TAILQ_FOREACH(pwp, &psn->pw, pw_entries)
if (pwp->pw_type == PWTYPE_READ2)
break;
assert(pwp != NULL);
puffs_cc_schedule(pwp->pw_cc);
TAILQ_REMOVE(&psn->pw, pwp, pw_entries);
}
if (rv == 0 && *resid > 0) {
reqid = NEXTREQ(pctx);
psbuf_recycleout(pb);
goto again;
}
farout:
/* check if we need a lazyclose */
if (psn->stat & PSN_HANDLECLOSE && psn->fhand_r) {
TAILQ_FOREACH(pwp, &psn->pw, pw_entries)
if (pwp->pw_type == PWTYPE_READ1)
break;
if (pwp == NULL)
closehandles(pu, psn, HANDLE_READ);
}
PSSHFSRETURN(rv);
}
/* XXX: we should getattr for size */
int
psshfs_node_write(struct puffs_usermount *pu, puffs_cookie_t opc, uint8_t *buf,
off_t offset, size_t *resid, const struct puffs_cred *cred,
int ioflag)
{
PSSHFSAUTOVAR(pu);
struct psshfs_wait *pwp;
struct puffs_node *pn = opc;
struct psshfs_node *psn = pn->pn_data;
uint32_t writelen;
if (pn->pn_va.va_type == VDIR) {
rv = EISDIR;
goto out;
}
/* check that a lazyopen didn't fail */
if (!psn->fhand_w && !psn->lazyopen_w) {
rv = psn->lazyopen_err_w;
goto out;
}
if (psn->stat & PSN_LAZYWAIT_W) {
struct psshfs_wait pw;
assert(psn->lazyopen_w);
pw.pw_cc = pcc;
pw.pw_type = PWTYPE_WRITE;
TAILQ_INSERT_TAIL(&psn->pw, &pw, pw_entries);
puffs_cc_yield(pcc);
}
/*
* If lazyopening, wait for the result.
* There can still be more than oen writer at a time in case
* the kernel issues write FAFs.
*/
if (psn->lazyopen_w) {
psn->stat |= PSN_LAZYWAIT_W;
rv = puffs_framev_framebuf_ccpromote(psn->lazyopen_w, pcc);
lazyopen_wresp(pu, psn->lazyopen_w, psn, rv);
/* schedule extra waiters */
TAILQ_FOREACH(pwp, &psn->pw, pw_entries)
if (pwp->pw_type == PWTYPE_WRITE) {
puffs_cc_schedule(pwp->pw_cc);
TAILQ_REMOVE(&psn->pw, pwp, pw_entries);
}
psn->stat &= ~PSN_LAZYWAIT_W;
if ((rv = psn->lazyopen_err_w) != 0)
goto out;
}
if (!psn->fhand_w) {
abort();
rv = EINVAL;
goto out;
}
writelen = *resid;
psbuf_req_data(pb, SSH_FXP_WRITE, reqid, psn->fhand_w,psn->fhand_w_len);
psbuf_put_8(pb, offset);
psbuf_put_data(pb, buf, writelen);
GETRESPONSE(pb, pctx->sshfd_data);
rv = psbuf_expect_status(pb);
if (rv == 0)
*resid = 0;
if (pn->pn_va.va_size < (uint64_t)offset + writelen)
pn->pn_va.va_size = offset + writelen;
out:
/* check if we need a lazyclose */
if (psn->stat & PSN_HANDLECLOSE && psn->fhand_w) {
TAILQ_FOREACH(pwp, &psn->pw, pw_entries)
if (pwp->pw_type == PWTYPE_WRITE)
break;
if (pwp == NULL)
closehandles(pu, psn, HANDLE_WRITE);
}
PSSHFSRETURN(rv);
}
int
psshfs_node_readlink(struct puffs_usermount *pu, puffs_cookie_t opc,
const struct puffs_cred *cred, char *linkvalue, size_t *linklen)
{
PSSHFSAUTOVAR(pu);
struct puffs_node *pn = opc;
struct psshfs_node *psn = pn->pn_data;
uint32_t count;
if (pctx->protover < 3) {
rv = EOPNOTSUPP;
goto out;
}
/*
* check if we can use a cached version
*
* XXX: we might end up reading the same link multiple times
* from the server if we get many requests at once, but that's
* quite harmless as this routine is reentrant.
*/
if (psn->symlink && !REFRESHTIMEOUT(pctx, time(NULL) - psn->slread))
goto copy;
if (psn->symlink) {
free(psn->symlink);
psn->symlink = NULL;
psn->slread = 0;
}
psbuf_req_str(pb, SSH_FXP_READLINK, reqid, PNPATH(pn));
GETRESPONSE(pb, pctx->sshfd);
rv = psbuf_expect_name(pb, &count);
if (rv)
goto out;
if (count != 1) {
rv = EPROTO;
goto out;
}
rv = psbuf_get_str(pb, &psn->symlink, NULL);
if (rv)
goto out;
psn->slread = time(NULL);
copy:
*linklen = strlen(psn->symlink);
(void) memcpy(linkvalue, psn->symlink, *linklen);
out:
PSSHFSRETURN(rv);
}
static int
doremove(struct puffs_usermount *pu, struct puffs_node *pn_dir,
struct puffs_node *pn, const char *name)
{
PSSHFSAUTOVAR(pu);
int op;
if (pn->pn_va.va_type == VDIR)
op = SSH_FXP_RMDIR;
else
op = SSH_FXP_REMOVE;
psbuf_req_str(pb, op, reqid, PNPATH(pn));
GETRESPONSE(pb, pctx->sshfd);
rv = psbuf_expect_status(pb);
if (rv == 0)
nukenode(pn, name, 0);
out:
PSSHFSRETURN(rv);
}
int
psshfs_node_remove(struct puffs_usermount *pu, puffs_cookie_t opc,
puffs_cookie_t targ, const struct puffs_cn *pcn)
{
struct puffs_node *pn_targ = targ;
int rv;
assert(pn_targ->pn_va.va_type != VDIR);
rv = doremove(pu, opc, targ, pcn->pcn_name);
if (rv == 0)
puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N2);
return rv;
}
int
psshfs_node_rmdir(struct puffs_usermount *pu, puffs_cookie_t opc,
puffs_cookie_t targ, const struct puffs_cn *pcn)
{
struct puffs_node *pn_targ = targ;
int rv;
assert(pn_targ->pn_va.va_type == VDIR);
rv = doremove(pu, opc, targ, pcn->pcn_name);
if (rv == 0)
puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N2);
return rv;
}
int
psshfs_node_mkdir(struct puffs_usermount *pu, puffs_cookie_t opc,
struct puffs_newinfo *pni, const struct puffs_cn *pcn,
const struct vattr *va)
{
PSSHFSAUTOVAR(pu);
struct puffs_node *pn = opc;
struct puffs_node *pn_new;
psbuf_req_str(pb, SSH_FXP_MKDIR, reqid, PCNPATH(pcn));
psbuf_put_vattr(pb, va, pctx);
GETRESPONSE(pb, pctx->sshfd);
rv = psbuf_expect_status(pb);
if (rv)
goto out;
pn_new = allocnode(pu, pn, pcn->pcn_name, va);
if (pn_new) {
puffs_newinfo_setcookie(pni, pn_new);
} else {
struct puffs_framebuf *pb2 = psbuf_makeout();
reqid = NEXTREQ(pctx);
psbuf_recycleout(pb2);
psbuf_req_str(pb2, SSH_FXP_RMDIR, reqid, PCNPATH(pcn));
JUSTSEND(pb2, pctx->sshfd);
rv = ENOMEM;
}
out:
PSSHFSRETURN(rv);
}
int
psshfs_node_symlink(struct puffs_usermount *pu, puffs_cookie_t opc,
struct puffs_newinfo *pni, const struct puffs_cn *pcn,
const struct vattr *va, const char *link_target)
{
PSSHFSAUTOVAR(pu);
struct puffs_node *pn = opc;
struct puffs_node *pn_new;
if (pctx->protover < 3) {
rv = EOPNOTSUPP;
goto out;
}
/*
* XXX: ietf says: source, target. openssh says: ietf who?
* Let's go with openssh and build quirk tables later if we care
*/
psbuf_req_str(pb, SSH_FXP_SYMLINK, reqid, link_target);
psbuf_put_str(pb, PCNPATH(pcn));
GETRESPONSE(pb, pctx->sshfd);
rv = psbuf_expect_status(pb);
if (rv)
goto out;
pn_new = allocnode(pu, pn, pcn->pcn_name, va);
if (pn_new) {
puffs_newinfo_setcookie(pni, pn_new);
} else {
struct puffs_framebuf *pb2 = psbuf_makeout();
reqid = NEXTREQ(pctx);
psbuf_recycleout(pb2);
psbuf_req_str(pb2, SSH_FXP_REMOVE, reqid, PCNPATH(pcn));
JUSTSEND(pb2, pctx->sshfd);
rv = ENOMEM;
}
out:
PSSHFSRETURN(rv);
}
int
psshfs_node_rename(struct puffs_usermount *pu, puffs_cookie_t opc,
puffs_cookie_t src, const struct puffs_cn *pcn_src,
puffs_cookie_t targ_dir, puffs_cookie_t targ,
const struct puffs_cn *pcn_targ)
{
PSSHFSAUTOVAR(pu);
struct puffs_node *pn_sf = src;
struct puffs_node *pn_td = targ_dir, *pn_tf = targ;
struct psshfs_node *psn_src = pn_sf->pn_data;
struct psshfs_node *psn_targdir = pn_td->pn_data;
if (pctx->protover < 2) {
rv = EOPNOTSUPP;
goto out;
}
if (pn_tf) {
rv = doremove(pu, targ_dir, pn_tf, pcn_targ->pcn_name);
if (rv)
goto out;
}
psbuf_req_str(pb, SSH_FXP_RENAME, reqid, PCNPATH(pcn_src));
psbuf_put_str(pb, PCNPATH(pcn_targ));
GETRESPONSE(pb, pctx->sshfd);
rv = psbuf_expect_status(pb);
if (rv == 0) {
struct psshfs_dir *pd;
/*
* XXX: interfaces didn't quite work with rename..
* the song remains the same. go figure .. ;)
*/
nukenode(pn_sf, pcn_src->pcn_name, 0);
pd = direnter(pn_td, pcn_targ->pcn_name);
pd->entry = pn_sf;
puffs_setvattr(&pd->va, &pn_sf->pn_va);
if (opc != targ_dir) {
psn_targdir->childcount++;
psn_src->parent = pn_td;
if (pn_sf->pn_va.va_type == VDIR)
pn_td->pn_va.va_nlink++;
}
}
out:
PSSHFSRETURN(rv);
}
/*
* So this file system happened to be written in such a way that
* lookup for ".." is hard if we lose the in-memory node. We'd
* need to recreate the entire directory structure from the root
* node up to the ".." node we're looking up.
*
* And since our entire fs structure is purely fictional (i.e. it's
* only in-memory, not fetchable from the server), the easiest way
* to deal with it is to not allow nodes with children to be
* reclaimed.
*
* If a node with children is being attempted to be reclaimed, we
* just mark it "reclaimed" but leave it as is until all its children
* have been reclaimed. If a lookup for that node is done meanwhile,
* it will be found by lookup() and we just remove the "reclaimed"
* bit.
*/
int
psshfs_node_reclaim(struct puffs_usermount *pu, puffs_cookie_t opc)
{
struct puffs_node *pn = opc, *pn_next, *pn_root;
struct psshfs_node *psn = pn->pn_data;
/*
* don't reclaim if we have file handle issued, otherwise
* we can't do fhtonode
*/
if (psn->stat & PSN_HASFH)
return 0;
psn->stat |= PSN_RECLAIMED;
pn_root = puffs_getroot(pu);
for (; pn != pn_root; pn = pn_next) {
psn = pn->pn_data;
if ((psn->stat & PSN_RECLAIMED) == 0 || psn->childcount != 0)
break;
pn_next = psn->parent;
doreclaim(pn);
}
return 0;
}

View File

@ -0,0 +1,590 @@
/* $NetBSD: psbuf.c,v 1.19 2012/11/04 22:46:08 christos Exp $ */
/*
* Copyright (c) 2006-2009 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: psbuf.c,v 1.19 2012/11/04 22:46:08 christos Exp $");
#endif /* !lint */
/*
* buffering functions for network input/output. slightly different
* from the average joe buffer routines, as is usually the case ...
* these use efuns for now.
*/
#include <sys/types.h>
#include <sys/time.h>
#include <sys/vnode.h>
#include <sys/socket.h>
#include <err.h>
#include <errno.h>
#include <stdlib.h>
#include <util.h>
#include <unistd.h>
#include "psshfs.h"
#include "sftp_proto.h"
#define FAILRV(x) do { int rv; if ((rv=x)) return (rv); } while (/*CONSTCOND*/0)
#define READSTATE_LENGTH(off) (off < 4)
#define SFTP_LENOFF 0
#define SFTP_TYPEOFF 4
#define SFTP_REQIDOFF 5
#define CHECK(v) if (!(v)) abort()
uint8_t
psbuf_get_type(struct puffs_framebuf *pb)
{
uint8_t type;
puffs_framebuf_getdata_atoff(pb, SFTP_TYPEOFF, &type, 1);
return type;
}
uint32_t
psbuf_get_len(struct puffs_framebuf *pb)
{
uint32_t len;
puffs_framebuf_getdata_atoff(pb, SFTP_LENOFF, &len, 4);
return be32toh(len);
}
uint32_t
psbuf_get_reqid(struct puffs_framebuf *pb)
{
uint32_t req;
puffs_framebuf_getdata_atoff(pb, SFTP_REQIDOFF, &req, 4);
return be32toh(req);
}
#define CUROFF(pb) (puffs_framebuf_telloff(pb))
int
psbuf_read(struct puffs_usermount *pu, struct puffs_framebuf *pb,
int fd, int *done)
{
void *win;
ssize_t n;
size_t howmuch, winlen;
int lenstate;
the_next_level:
if ((lenstate = READSTATE_LENGTH(CUROFF(pb))))
howmuch = 4 - CUROFF(pb);
else
howmuch = psbuf_get_len(pb) - (CUROFF(pb) - 4);
if (puffs_framebuf_reserve_space(pb, howmuch) == -1)
return errno;
while (howmuch) {
winlen = howmuch;
if (puffs_framebuf_getwindow(pb, CUROFF(pb), &win, &winlen)==-1)
return errno;
n = recv(fd, win, winlen, MSG_NOSIGNAL);
switch (n) {
case 0:
return ECONNRESET;
case -1:
if (errno == EAGAIN)
return 0;
return errno;
default:
howmuch -= n;
puffs_framebuf_seekset(pb, CUROFF(pb) + n);
break;
}
}
if (!lenstate) {
/* XXX: initial exchange shorter.. but don't worry, be happy */
puffs_framebuf_seekset(pb, 9);
*done = 1;
return 0;
} else
goto the_next_level;
}
int
psbuf_write(struct puffs_usermount *pu, struct puffs_framebuf *pb,
int fd, int *done)
{
void *win;
ssize_t n;
size_t winlen, howmuch;
/* finalize buffer.. could be elsewhere ... */
if (CUROFF(pb) == 0) {
uint32_t len;
len = htobe32(puffs_framebuf_tellsize(pb) - 4);
puffs_framebuf_putdata_atoff(pb, 0, &len, 4);
}
howmuch = puffs_framebuf_tellsize(pb) - CUROFF(pb);
while (howmuch) {
winlen = howmuch;
if (puffs_framebuf_getwindow(pb, CUROFF(pb), &win, &winlen)==-1)
return errno;
n = send(fd, win, winlen, MSG_NOSIGNAL);
switch (n) {
case 0:
return ECONNRESET;
case -1:
if (errno == EAGAIN)
return 0;
return errno;
default:
howmuch -= n;
puffs_framebuf_seekset(pb, CUROFF(pb) + n);
break;
}
}
*done = 1;
return 0;
}
#undef CUROFF
int
psbuf_cmp(struct puffs_usermount *pu,
struct puffs_framebuf *cmp1, struct puffs_framebuf *cmp2, int *notresp)
{
return psbuf_get_reqid(cmp1) != psbuf_get_reqid(cmp2);
}
struct puffs_framebuf *
psbuf_makeout()
{
struct puffs_framebuf *pb;
pb = puffs_framebuf_make();
puffs_framebuf_seekset(pb, 4);
return pb;
}
void
psbuf_recycleout(struct puffs_framebuf *pb)
{
puffs_framebuf_recycle(pb);
puffs_framebuf_seekset(pb, 4);
}
void
psbuf_put_1(struct puffs_framebuf *pb, uint8_t val)
{
int rv;
rv = puffs_framebuf_putdata(pb, &val, 1);
CHECK(rv == 0);
}
void
psbuf_put_2(struct puffs_framebuf *pb, uint16_t val)
{
int rv;
HTOBE16(val);
rv = puffs_framebuf_putdata(pb, &val, 2);
CHECK(rv == 0);
}
void
psbuf_put_4(struct puffs_framebuf *pb, uint32_t val)
{
int rv;
HTOBE32(val);
rv = puffs_framebuf_putdata(pb, &val, 4);
CHECK(rv == 0);
}
void
psbuf_put_8(struct puffs_framebuf *pb, uint64_t val)
{
int rv;
HTOBE64(val);
rv = puffs_framebuf_putdata(pb, &val, 8);
CHECK(rv == 0);
}
void
psbuf_put_data(struct puffs_framebuf *pb, const void *data, uint32_t dlen)
{
int rv;
psbuf_put_4(pb, dlen);
rv = puffs_framebuf_putdata(pb, data, dlen);
CHECK(rv == 0);
}
void
psbuf_put_str(struct puffs_framebuf *pb, const char *str)
{
psbuf_put_data(pb, str, strlen(str));
}
void
psbuf_put_vattr(struct puffs_framebuf *pb, const struct vattr *va,
const struct psshfs_ctx *pctx)
{
uint32_t flags;
uint32_t theuid = -1, thegid = -1;
flags = 0;
if (va->va_size != (uint64_t)PUFFS_VNOVAL)
flags |= SSH_FILEXFER_ATTR_SIZE;
if (va->va_uid != (uid_t)PUFFS_VNOVAL) {
theuid = va->va_uid;
if (pctx->domangleuid && theuid == pctx->myuid)
theuid = pctx->mangleuid;
flags |= SSH_FILEXFER_ATTR_UIDGID;
}
if (va->va_gid != (gid_t)PUFFS_VNOVAL) {
thegid = va->va_gid;
if (pctx->domanglegid && thegid == pctx->mygid)
thegid = pctx->manglegid;
flags |= SSH_FILEXFER_ATTR_UIDGID;
}
if (va->va_mode != (mode_t)PUFFS_VNOVAL)
flags |= SSH_FILEXFER_ATTR_PERMISSIONS;
if (va->va_atime.tv_sec != PUFFS_VNOVAL)
flags |= SSH_FILEXFER_ATTR_ACCESSTIME;
psbuf_put_4(pb, flags);
if (flags & SSH_FILEXFER_ATTR_SIZE)
psbuf_put_8(pb, va->va_size);
if (flags & SSH_FILEXFER_ATTR_UIDGID) {
psbuf_put_4(pb, theuid);
psbuf_put_4(pb, thegid);
}
if (flags & SSH_FILEXFER_ATTR_PERMISSIONS)
psbuf_put_4(pb, va->va_mode);
/* XXX: this is totally wrong for protocol v3, see OpenSSH */
if (flags & SSH_FILEXFER_ATTR_ACCESSTIME) {
psbuf_put_4(pb, va->va_atime.tv_sec);
psbuf_put_4(pb, va->va_mtime.tv_sec);
}
}
#define ERETURN(rv) return ((rv) == -1 ? errno : 0)
int
psbuf_get_1(struct puffs_framebuf *pb, uint8_t *val)
{
ERETURN(puffs_framebuf_getdata(pb, val, 1));
}
int
psbuf_get_2(struct puffs_framebuf *pb, uint16_t *val)
{
int rv;
rv = puffs_framebuf_getdata(pb, val, 2);
BE16TOH(*val);
ERETURN(rv);
}
int
psbuf_get_4(struct puffs_framebuf *pb, uint32_t *val)
{
int rv;
rv = puffs_framebuf_getdata(pb, val, 4);
BE32TOH(*val);
ERETURN(rv);
}
int
psbuf_get_8(struct puffs_framebuf *pb, uint64_t *val)
{
int rv;
rv = puffs_framebuf_getdata(pb, val, 8);
BE64TOH(*val);
ERETURN(rv);
}
int
psbuf_get_str(struct puffs_framebuf *pb, char **strp, uint32_t *strlenp)
{
char *str;
uint32_t len;
FAILRV(psbuf_get_4(pb, &len));
if (puffs_framebuf_remaining(pb) < len)
return EPROTO;
str = emalloc(len+1);
puffs_framebuf_getdata(pb, str, len);
str[len] = '\0';
*strp = str;
if (strlenp)
*strlenp = len;
return 0;
}
int
psbuf_get_vattr(struct puffs_framebuf *pb, struct vattr *vap)
{
uint32_t flags;
uint32_t val;
puffs_vattr_null(vap);
FAILRV(psbuf_get_4(pb, &flags));
if (flags & SSH_FILEXFER_ATTR_SIZE) {
FAILRV(psbuf_get_8(pb, &vap->va_size));
vap->va_bytes = vap->va_size;
}
if (flags & SSH_FILEXFER_ATTR_UIDGID) {
FAILRV(psbuf_get_4(pb, &vap->va_uid));
FAILRV(psbuf_get_4(pb, &vap->va_gid));
}
if (flags & SSH_FILEXFER_ATTR_PERMISSIONS) {
FAILRV(psbuf_get_4(pb, &vap->va_mode));
vap->va_type = puffs_mode2vt(vap->va_mode);
}
if (flags & SSH_FILEXFER_ATTR_ACCESSTIME) {
/*
* XXX: this is utterly wrong if we want to speak
* protocol version 3, but it seems like the
* "internet standard" for doing this
*/
FAILRV(psbuf_get_4(pb, &val));
vap->va_atime.tv_sec = val;
FAILRV(psbuf_get_4(pb, &val));
vap->va_mtime.tv_sec = val;
/* make ctime the same as mtime */
vap->va_ctime.tv_sec = val;
vap->va_atime.tv_nsec = 0;
vap->va_ctime.tv_nsec = 0;
vap->va_mtime.tv_nsec = 0;
}
return 0;
}
/*
* Buffer content helpers. Caller frees all data.
*/
/*
* error mapping.. most are not expected for a file system, but
* should help with diagnosing a possible error
*/
static int emap[] = {
0, /* OK */
0, /* EOF */
ENOENT, /* NO_SUCH_FILE */
EPERM, /* PERMISSION_DENIED */
EIO, /* FAILURE */
EBADMSG, /* BAD_MESSAGE */
ENOTCONN, /* NO_CONNECTION */
ECONNRESET, /* CONNECTION_LOST */
EOPNOTSUPP, /* OP_UNSUPPORTED */
EINVAL, /* INVALID_HANDLE */
ENXIO, /* NO_SUCH_PATH */
EEXIST, /* FILE_ALREADY_EXISTS */
ENODEV /* WRITE_PROTECT */
};
#define NERRORS ((int)(sizeof(emap) / sizeof(emap[0])))
static int
sftperr_to_errno(int error)
{
if (!error)
return 0;
if (error >= NERRORS || error < 0)
return EPROTO;
return emap[error];
}
#define INVALRESPONSE EPROTO
static int
expectcode(struct puffs_framebuf *pb, int value)
{
uint32_t error;
uint8_t type;
type = psbuf_get_type(pb);
if (type == value)
return 0;
if (type != SSH_FXP_STATUS)
return INVALRESPONSE;
FAILRV(psbuf_get_4(pb, &error));
return sftperr_to_errno(error);
}
#define CHECKCODE(pb,val) \
do { \
int rv; \
rv = expectcode(pb, val); \
if (rv) \
return rv; \
} while (/*CONSTCOND*/0)
int
psbuf_expect_status(struct puffs_framebuf *pb)
{
uint32_t error;
if (psbuf_get_type(pb) != SSH_FXP_STATUS)
return INVALRESPONSE;
FAILRV(psbuf_get_4(pb, &error));
return sftperr_to_errno(error);
}
int
psbuf_expect_handle(struct puffs_framebuf *pb, char **hand, uint32_t *handlen)
{
CHECKCODE(pb, SSH_FXP_HANDLE);
FAILRV(psbuf_get_str(pb, hand, handlen));
return 0;
}
/* no memory allocation, direct copy */
int
psbuf_do_data(struct puffs_framebuf *pb, uint8_t *data, uint32_t *dlen)
{
void *win;
size_t bufoff, winlen;
uint32_t len, dataoff;
if (psbuf_get_type(pb) != SSH_FXP_DATA) {
uint32_t val;
if (psbuf_get_type(pb) != SSH_FXP_STATUS)
return INVALRESPONSE;
if (psbuf_get_4(pb, &val) != 0)
return INVALRESPONSE;
if (val != SSH_FX_EOF)
return sftperr_to_errno(val);
*dlen = 0;
return 0;
}
if (psbuf_get_4(pb, &len) != 0)
return INVALRESPONSE;
if (*dlen < len)
return EINVAL;
*dlen = 0;
dataoff = 0;
while (dataoff < len) {
winlen = len-dataoff;
bufoff = puffs_framebuf_telloff(pb);
if (puffs_framebuf_getwindow(pb, bufoff,
&win, &winlen) == -1)
return EINVAL;
if (winlen == 0)
break;
memcpy(data + dataoff, win, winlen);
dataoff += winlen;
}
*dlen = dataoff;
return 0;
}
int
psbuf_expect_name(struct puffs_framebuf *pb, uint32_t *count)
{
CHECKCODE(pb, SSH_FXP_NAME);
FAILRV(psbuf_get_4(pb, count));
return 0;
}
int
psbuf_expect_attrs(struct puffs_framebuf *pb, struct vattr *vap)
{
CHECKCODE(pb, SSH_FXP_ATTRS);
FAILRV(psbuf_get_vattr(pb, vap));
return 0;
}
/*
* More helpers: larger-scale put functions
*/
void
psbuf_req_data(struct puffs_framebuf *pb, int type, uint32_t reqid,
const void *data, uint32_t dlen)
{
psbuf_put_1(pb, type);
psbuf_put_4(pb, reqid);
psbuf_put_data(pb, data, dlen);
}
void
psbuf_req_str(struct puffs_framebuf *pb, int type, uint32_t reqid,
const char *str)
{
psbuf_req_data(pb, type, reqid, str, strlen(str));
}

View File

@ -0,0 +1,501 @@
/* $NetBSD: psshfs.c,v 1.66 2012/11/04 22:46:08 christos Exp $ */
/*
* Copyright (c) 2006-2009 Antti Kantee. 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 AUTHOR ``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 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.
*/
/*
* psshfs: puffs sshfs
*
* psshfs implements sshfs functionality on top of puffs making it
* possible to mount a filesystme through the sftp service.
*
* psshfs can execute multiple operations in "parallel" by using the
* puffs_cc framework for continuations.
*
* Concurrency control is handled currently by vnode locking (this
* will change in the future). Context switch locations are easy to
* find by grepping for puffs_framebuf_enqueue_cc().
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: psshfs.c,v 1.66 2012/11/04 22:46:08 christos Exp $");
#endif /* !lint */
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <stdio.h>
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <mntopts.h>
#include <paths.h>
#include <poll.h>
#include <puffs.h>
#include <signal.h>
#include <stdlib.h>
#include <util.h>
#include <unistd.h>
#include "psshfs.h"
static int pssh_connect(struct puffs_usermount *, int);
static void psshfs_loopfn(struct puffs_usermount *);
__dead static void usage(void);
static char * cleanhostname(char *);
static char * colon(char *);
static void add_ssharg(char ***, int *, const char *);
static void psshfs_notify(struct puffs_usermount *, int, int);
#define SSH_PATH "/usr/bin/ssh"
unsigned int max_reads;
static int sighup;
static char *
cleanhostname(char *host)
{
if (*host == '[' && host[strlen(host) - 1] == ']') {
host[strlen(host) - 1] = '\0';
return (host + 1);
} else
return host;
}
static char *
colon(char *cp)
{
int flag = 0;
if (*cp == '[')
flag = 1;
for (; *cp; ++cp) {
if (*cp == '@' && *(cp+1) == '[')
flag = 1;
if (*cp == ']' && *(cp+1) == ':' && flag)
return (cp+1);
if (*cp == ':' && !flag)
return (cp);
if (*cp == '/')
return NULL;
}
return NULL;
}
static void
add_ssharg(char ***sshargs, int *nargs, const char *arg)
{
*sshargs = realloc(*sshargs, (*nargs + 2) * sizeof(char*));
if (!*sshargs)
err(1, "realloc");
(*sshargs)[(*nargs)++] = estrdup(arg);
(*sshargs)[*nargs] = NULL;
}
static void
usage(void)
{
fprintf(stderr, "usage: %s "
"[-ceprst] [-F configfile] [-O sshopt=value] [-o opts] "
"user@host:path mountpath\n",
getprogname());
exit(1);
}
static void
takehup(int sig)
{
sighup = 1;
}
int
main(int argc, char *argv[])
{
struct psshfs_ctx pctx;
struct puffs_usermount *pu;
struct puffs_ops *pops;
struct psshfs_node *root = &pctx.psn_root;
struct puffs_node *pn_root;
puffs_framev_fdnotify_fn notfn;
struct vattr *rva;
mntoptparse_t mp;
char **sshargs;
char *user;
char *host;
char *path;
int mntflags, pflags, ch;
int detach;
int exportfs, refreshival, numconnections;
int nargs;
setprogname(argv[0]);
puffs_unmountonsignal(SIGINT, true);
puffs_unmountonsignal(SIGTERM, true);
if (argc < 3)
usage();
memset(&pctx, 0, sizeof(pctx));
mntflags = pflags = exportfs = nargs = 0;
numconnections = 1;
detach = 1;
refreshival = DEFAULTREFRESH;
notfn = puffs_framev_unmountonclose;
sshargs = NULL;
add_ssharg(&sshargs, &nargs, SSH_PATH);
add_ssharg(&sshargs, &nargs, "-axs");
add_ssharg(&sshargs, &nargs, "-oClearAllForwardings=yes");
while ((ch = getopt(argc, argv, "c:eF:g:o:O:pr:st:u:")) != -1) {
switch (ch) {
case 'c':
numconnections = atoi(optarg);
if (numconnections < 1 || numconnections > 2) {
fprintf(stderr, "%s: only 1 or 2 connections "
"permitted currently\n", getprogname());
usage();
/*NOTREACHED*/
}
break;
case 'e':
exportfs = 1;
break;
case 'F':
add_ssharg(&sshargs, &nargs, "-F");
add_ssharg(&sshargs, &nargs, optarg);
break;
case 'g':
pctx.domanglegid = 1;
pctx.manglegid = atoi(optarg);
if (pctx.manglegid == (gid_t)-1)
errx(1, "-1 not allowed for -g");
pctx.mygid = getegid();
break;
case 'O':
add_ssharg(&sshargs, &nargs, "-o");
add_ssharg(&sshargs, &nargs, optarg);
break;
case 'o':
mp = getmntopts(optarg, puffsmopts, &mntflags, &pflags);
if (mp == NULL)
err(1, "getmntopts");
freemntopts(mp);
break;
case 'p':
notfn = psshfs_notify;
break;
case 'r':
max_reads = atoi(optarg);
break;
case 's':
detach = 0;
break;
case 't':
refreshival = atoi(optarg);
if (refreshival < 0 && refreshival != -1)
errx(1, "invalid timeout %d", refreshival);
break;
case 'u':
pctx.domangleuid = 1;
pctx.mangleuid = atoi(optarg);
if (pctx.mangleuid == (uid_t)-1)
errx(1, "-1 not allowed for -u");
pctx.myuid = geteuid();
break;
default:
usage();
/*NOTREACHED*/
}
}
argc -= optind;
argv += optind;
if (pflags & PUFFS_FLAG_OPDUMP)
detach = 0;
pflags |= PUFFS_FLAG_BUILDPATH;
pflags |= PUFFS_KFLAG_WTCACHE | PUFFS_KFLAG_IAONDEMAND;
if (argc != 2)
usage();
PUFFSOP_INIT(pops);
PUFFSOP_SET(pops, psshfs, fs, unmount);
PUFFSOP_SETFSNOP(pops, sync); /* XXX */
PUFFSOP_SET(pops, psshfs, fs, statvfs);
PUFFSOP_SET(pops, psshfs, fs, nodetofh);
PUFFSOP_SET(pops, psshfs, fs, fhtonode);
PUFFSOP_SET(pops, psshfs, node, lookup);
PUFFSOP_SET(pops, psshfs, node, create);
PUFFSOP_SET(pops, psshfs, node, open);
PUFFSOP_SET(pops, psshfs, node, inactive);
PUFFSOP_SET(pops, psshfs, node, readdir);
PUFFSOP_SET(pops, psshfs, node, getattr);
PUFFSOP_SET(pops, psshfs, node, setattr);
PUFFSOP_SET(pops, psshfs, node, mkdir);
PUFFSOP_SET(pops, psshfs, node, remove);
PUFFSOP_SET(pops, psshfs, node, readlink);
PUFFSOP_SET(pops, psshfs, node, rmdir);
PUFFSOP_SET(pops, psshfs, node, symlink);
PUFFSOP_SET(pops, psshfs, node, rename);
PUFFSOP_SET(pops, psshfs, node, read);
PUFFSOP_SET(pops, psshfs, node, write);
PUFFSOP_SET(pops, psshfs, node, reclaim);
pu = puffs_init(pops, argv[0], "psshfs", &pctx, pflags);
if (pu == NULL)
err(1, "puffs_init");
pctx.mounttime = time(NULL);
pctx.refreshival = refreshival;
pctx.numconnections = numconnections;
user = strdup(argv[0]);
if ((host = strrchr(user, '@')) == NULL) {
host = user;
} else {
*host++ = '\0'; /* break at the '@' */
if (user[0] == '\0') {
fprintf(stderr, "Missing username\n");
usage();
}
add_ssharg(&sshargs, &nargs, "-l");
add_ssharg(&sshargs, &nargs, user);
}
if ((path = colon(host)) != NULL) {
*path++ = '\0'; /* break at the ':' */
pctx.mountpath = path;
} else {
pctx.mountpath = ".";
}
host = cleanhostname(host);
if (host[0] == '\0') {
fprintf(stderr, "Missing hostname\n");
usage();
}
add_ssharg(&sshargs, &nargs, host);
add_ssharg(&sshargs, &nargs, "sftp");
pctx.sshargs = sshargs;
pctx.nextino = 2;
memset(root, 0, sizeof(struct psshfs_node));
TAILQ_INIT(&root->pw);
pn_root = puffs_pn_new(pu, root);
if (pn_root == NULL)
return errno;
puffs_setroot(pu, pn_root);
puffs_framev_init(pu, psbuf_read, psbuf_write, psbuf_cmp, NULL, notfn);
signal(SIGHUP, takehup);
puffs_ml_setloopfn(pu, psshfs_loopfn);
if (pssh_connect(pu, PSSHFD_META) == -1)
err(1, "can't connect meta");
if (puffs_framev_addfd(pu, pctx.sshfd,
PUFFS_FBIO_READ | PUFFS_FBIO_WRITE) == -1)
err(1, "framebuf addfd meta");
if (numconnections == 2) {
if (pssh_connect(pu, PSSHFD_DATA) == -1)
err(1, "can't connect data");
if (puffs_framev_addfd(pu, pctx.sshfd_data,
PUFFS_FBIO_READ | PUFFS_FBIO_WRITE) == -1)
err(1, "framebuf addfd data");
} else {
pctx.sshfd_data = pctx.sshfd;
}
if (exportfs)
puffs_setfhsize(pu, sizeof(struct psshfs_fid),
PUFFS_FHFLAG_NFSV2 | PUFFS_FHFLAG_NFSV3);
rva = &pn_root->pn_va;
rva->va_fileid = pctx.nextino++;
/*
* For root link count, just guess something ridiculously high.
* Guessing too high has no known adverse effects, but fts(3)
* doesn't like too low values. This guess will be replaced
* with the real value when readdir is first called for
* the root directory.
*/
rva->va_nlink = 8811;
if (detach)
if (puffs_daemon(pu, 1, 1) == -1)
err(1, "puffs_daemon");
if (puffs_mount(pu, argv[1], mntflags, puffs_getroot(pu)) == -1)
err(1, "puffs_mount");
if (puffs_setblockingmode(pu, PUFFSDEV_NONBLOCK) == -1)
err(1, "setblockingmode");
if (puffs_mainloop(pu) == -1)
err(1, "mainloop");
puffs_exit(pu, 1);
return 0;
}
#define RETRY_MAX 100
void
psshfs_notify(struct puffs_usermount *pu, int fd, int what)
{
struct psshfs_ctx *pctx = puffs_getspecific(pu);
int nretry, which, newfd, dummy;
if (fd == pctx->sshfd) {
which = PSSHFD_META;
} else {
assert(fd == pctx->sshfd_data);
which = PSSHFD_DATA;
}
if (puffs_getstate(pu) != PUFFS_STATE_RUNNING)
return;
if (what != (PUFFS_FBIO_READ | PUFFS_FBIO_WRITE)) {
puffs_framev_removefd(pu, fd, ECONNRESET);
return;
}
close(fd);
/* deal with zmobies, beware of half-eaten brain */
while (waitpid(-1, &dummy, WNOHANG) > 0)
continue;
for (nretry = 0;;nretry++) {
if ((newfd = pssh_connect(pu, which)) == -1)
goto retry2;
if (puffs_framev_addfd(pu, newfd,
PUFFS_FBIO_READ | PUFFS_FBIO_WRITE) == -1)
goto retry1;
break;
retry1:
fprintf(stderr, "reconnect failed... ");
close(newfd);
retry2:
if (nretry < RETRY_MAX) {
fprintf(stderr, "retry (%d left)\n", RETRY_MAX-nretry);
sleep(nretry);
} else {
fprintf(stderr, "retry count exceeded, going south\n");
exit(1); /* XXXXXXX */
}
}
}
static int
pssh_connect(struct puffs_usermount *pu, int which)
{
struct psshfs_ctx *pctx = puffs_getspecific(pu);
char * const *sshargs = pctx->sshargs;
int fds[2];
pid_t pid;
int dnfd, x;
int *sshfd;
pid_t *sshpid;
if (which == PSSHFD_META) {
sshfd = &pctx->sshfd;
sshpid = &pctx->sshpid;
} else {
assert(which == PSSHFD_DATA);
sshfd = &pctx->sshfd_data;
sshpid = &pctx->sshpid_data;
}
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == -1)
return -1;
pid = fork();
switch (pid) {
case -1:
return -1;
/*NOTREACHED*/
case 0: /* child */
if (dup2(fds[0], STDIN_FILENO) == -1)
err(1, "child dup2");
if (dup2(fds[0], STDOUT_FILENO) == -1)
err(1, "child dup2");
close(fds[0]);
close(fds[1]);
dnfd = open(_PATH_DEVNULL, O_RDWR);
if (dnfd != -1)
dup2(dnfd, STDERR_FILENO);
execvp(sshargs[0], sshargs);
/*NOTREACHED*/
break;
default:
*sshpid = pid;
*sshfd = fds[1];
close(fds[0]);
break;
}
if (psshfs_handshake(pu, *sshfd) != 0)
errx(1, "handshake failed, server does not support sftp?");
x = 1;
if (ioctl(*sshfd, FIONBIO, &x) == -1)
err(1, "nonblocking descriptor %d", which);
return *sshfd;
}
static void *
invalone(struct puffs_usermount *pu, struct puffs_node *pn, void *arg)
{
struct psshfs_node *psn = pn->pn_data;
psn->attrread = 0;
psn->dentread = 0;
psn->slread = 0;
return NULL;
}
static void
psshfs_loopfn(struct puffs_usermount *pu)
{
if (sighup) {
puffs_pn_nodewalk(pu, invalone, NULL);
sighup = 0;
}
}

View File

@ -0,0 +1,248 @@
/* $NetBSD: psshfs.h,v 1.40 2010/04/01 02:34:09 pooka Exp $ */
/*
* Copyright (c) 2006-2009 Antti Kantee. 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 AUTHOR ``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 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.
*/
#ifndef PSSHFS_H_
#define PSSHFS_H_
#include <sys/queue.h>
#include <puffs.h>
extern unsigned int max_reads;
/*
* Later protocol versions would have some advantages (such as link count
* supported directly as a part of stat), but since proto version 3 seems
* to be the only widely available version, let's not try to jump through
* too many hoops to be compatible with all versions.
*/
#define SFTP_PROTOVERSION 3
/* extensions, held in psshfs_ctx extensions */
#define SFTP_EXT_POSIX_RENAME 0x01
#define SFTP_EXT_STATVFS 0x02
#define SFTP_EXT_FSTATVFS 0x04
#define DEFAULTREFRESH 30
#define REFRESHTIMEOUT(pctx, t) \
(!(pctx)->refreshival || ((pctx->refreshival!=-1) && ((t)>pctx->refreshival)))
PUFFSOP_PROTOS(psshfs);
#define NEXTREQ(pctx) ((pctx->nextreq)++)
#define PSSHFSAUTOVAR(pu) \
struct puffs_cc *pcc = puffs_cc_getcc(pu); \
struct psshfs_ctx *pctx = puffs_getspecific(pu); \
uint32_t reqid = NEXTREQ(pctx); \
struct puffs_framebuf *pb = psbuf_makeout(); \
int rv = 0
#define PSSHFSRETURN(rv) \
puffs_framebuf_destroy(pb); \
return (rv)
#define GETRESPONSE(pb, fd) \
do { \
if (puffs_framev_enqueue_cc(pcc, fd, pb, 0) == -1) { \
rv = errno; \
goto out; \
} \
} while (/*CONSTCOND*/0)
#define JUSTSEND(pb,fd) \
do { \
if (puffs_framev_enqueue_justsend(pu, fd, pb, 1, 0) == -1) { \
rv = errno; \
goto out; \
} \
} while (/*CONSTCOND*/0)
#define SENDCB(pb, fd, f, a) \
do { \
if (puffs_framev_enqueue_cb(pu, fd, pb, f, a, 0) == -1) { \
rv = errno; \
goto out; \
} \
} while (/*CONSTCOND*/0)
struct psshfs_dir {
int valid;
struct puffs_node *entry;
char *entryname;
struct vattr va;
time_t attrread;
};
struct psshfs_fid {
time_t mounttime;
struct puffs_node *node;
};
struct psshfs_wait {
struct puffs_cc *pw_cc;
int pw_type;
TAILQ_ENTRY(psshfs_wait) pw_entries;
};
#define PWTYPE_READDIR 1
#define PWTYPE_READ1 2
#define PWTYPE_READ2 3
#define PWTYPE_WRITE 4
struct psshfs_node {
struct puffs_node *parent;
struct psshfs_dir *dir; /* only valid if we're of type VDIR */
size_t denttot;
size_t dentnext;
time_t dentread;
int childcount;
int stat;
unsigned readcount;
time_t attrread;
char *symlink;
time_t slread;
char *fhand_r;
char *fhand_w;
uint32_t fhand_r_len;
uint32_t fhand_w_len;
struct puffs_framebuf *lazyopen_r;
struct puffs_framebuf *lazyopen_w;
int lazyopen_err_r, lazyopen_err_w;
TAILQ_HEAD(, psshfs_wait) pw;
};
#define PSN_RECLAIMED 0x01
#define PSN_HASFH 0x02
#define PSN_READDIR 0x04
#define PSN_DOLAZY_R 0x08
#define PSN_DOLAZY_W 0x10
#define PSN_LAZYWAIT_R 0x20
#define PSN_LAZYWAIT_W 0x40
#define PSN_HANDLECLOSE 0x80
#define HANDLE_READ 0x1
#define HANDLE_WRITE 0x2
struct psshfs_ctx {
int numconnections;
int sshfd;
int sshfd_data;
pid_t sshpid;
pid_t sshpid_data;
const char *mountpath;
char **sshargs;
int protover;
int extensions;
uint32_t nextreq;
struct puffs_framebuf *curpb;
struct psshfs_node psn_root;
ino_t nextino;
int canexport;
time_t mounttime;
int refreshival;
int domangleuid, domanglegid;
uid_t mangleuid, myuid;
gid_t manglegid, mygid;
};
#define PSSHFD_META 0
#define PSSHFD_DATA 1
int psshfs_handshake(struct puffs_usermount *, int);
int psbuf_read(struct puffs_usermount *, struct puffs_framebuf *,int,int*);
int psbuf_write(struct puffs_usermount *, struct puffs_framebuf *,int,int*);
int psbuf_cmp(struct puffs_usermount *,
struct puffs_framebuf *, struct puffs_framebuf *, int *);
struct puffs_framebuf *psbuf_makeout(void);
void psbuf_recycleout(struct puffs_framebuf *);
void psbuf_put_1(struct puffs_framebuf *, uint8_t);
void psbuf_put_2(struct puffs_framebuf *, uint16_t);
void psbuf_put_4(struct puffs_framebuf *, uint32_t);
void psbuf_put_8(struct puffs_framebuf *, uint64_t);
void psbuf_put_str(struct puffs_framebuf *, const char *);
void psbuf_put_data(struct puffs_framebuf *, const void *, uint32_t);
void psbuf_put_vattr(struct puffs_framebuf *, const struct vattr *,
const struct psshfs_ctx *);
uint8_t psbuf_get_type(struct puffs_framebuf *);
uint32_t psbuf_get_len(struct puffs_framebuf *);
uint32_t psbuf_get_reqid(struct puffs_framebuf *);
int psbuf_get_1(struct puffs_framebuf *, uint8_t *);
int psbuf_get_2(struct puffs_framebuf *, uint16_t *);
int psbuf_get_4(struct puffs_framebuf *, uint32_t *);
int psbuf_get_8(struct puffs_framebuf *, uint64_t *);
int psbuf_get_str(struct puffs_framebuf *, char **, uint32_t *);
int psbuf_get_vattr(struct puffs_framebuf *, struct vattr *);
int psbuf_expect_status(struct puffs_framebuf *);
int psbuf_expect_handle(struct puffs_framebuf *, char **, uint32_t *);
int psbuf_expect_name(struct puffs_framebuf *, uint32_t *);
int psbuf_expect_attrs(struct puffs_framebuf *, struct vattr *);
int psbuf_do_data(struct puffs_framebuf *, uint8_t *, uint32_t *);
void psbuf_req_data(struct puffs_framebuf *, int, uint32_t,
const void *, uint32_t);
void psbuf_req_str(struct puffs_framebuf *, int, uint32_t, const char *);
int sftp_readdir(struct puffs_usermount *, struct psshfs_ctx *,
struct puffs_node *);
struct psshfs_dir *lookup(struct psshfs_dir *, size_t, const char *);
struct puffs_node *makenode(struct puffs_usermount *, struct puffs_node *,
const struct psshfs_dir *, const struct vattr *);
struct puffs_node *allocnode(struct puffs_usermount *, struct puffs_node *,
const char *, const struct vattr *);
struct psshfs_dir *direnter(struct puffs_node *, const char *);
void nukenode(struct puffs_node *, const char *, int);
void doreclaim(struct puffs_node *);
int getpathattr(struct puffs_usermount *, const char *, struct vattr *);
int getnodeattr(struct puffs_usermount *, struct puffs_node *, const char *);
void closehandles(struct puffs_usermount *, struct psshfs_node *, int);
void lazyopen_rresp(struct puffs_usermount *, struct puffs_framebuf *,
void *, int);
void lazyopen_wresp(struct puffs_usermount *, struct puffs_framebuf *,
void *, int);
#endif /* PSSHFS_H_ */

View File

@ -0,0 +1,122 @@
/* $NetBSD: sftp_proto.h,v 1.2 2007/06/06 01:55:03 pooka Exp $ */
/*
* Copyright (c) 2006 Antti Kantee. 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 AUTHOR ``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 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.
*/
/*
* copypaste from draft-ietf-secsh-filexfer-03.txt
*
* XXX: we only implement protocol version 03. We should *definitely*
* support a later version, since it maps to the vnode interface much
* better. the problem is that most sftp servers only implement v3
* and I don't currently have the energy to deal with compat-fuddling
* in the code.
*/
#ifndef PSSHFS_SFTPPROTO_H_
#define PSSHFS_SFTPPROTO_H_
/* 3 General Packet Format */
#define SSH_FXP_INIT 1
#define SSH_FXP_VERSION 2
#define SSH_FXP_OPEN 3
#define SSH_FXP_CLOSE 4
#define SSH_FXP_READ 5
#define SSH_FXP_WRITE 6
#define SSH_FXP_LSTAT 7
#define SSH_FXP_FSTAT 8
#define SSH_FXP_SETSTAT 9
#define SSH_FXP_FSETSTAT 10
#define SSH_FXP_OPENDIR 11
#define SSH_FXP_READDIR 12
#define SSH_FXP_REMOVE 13
#define SSH_FXP_MKDIR 14
#define SSH_FXP_RMDIR 15
#define SSH_FXP_REALPATH 16
#define SSH_FXP_STAT 17
#define SSH_FXP_RENAME 18
#define SSH_FXP_READLINK 19
#define SSH_FXP_SYMLINK 20
#define SSH_FXP_STATUS 101
#define SSH_FXP_HANDLE 102
#define SSH_FXP_DATA 103
#define SSH_FXP_NAME 104
#define SSH_FXP_ATTRS 105
#define SSH_FXP_EXTENDED 200
#define SSH_FXP_EXTENDED_REPLY 201
/* 5.1 Flags */
/* XXX: UIDGID is obsoleted *AND NOT VALID* for version 3 of the protocol */
#define SSH_FILEXFER_ATTR_SIZE 0x00000001
#define SSH_FILEXFER_ATTR_UIDGID 0x00000002
#define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004
#define SSH_FILEXFER_ATTR_ACCESSTIME 0x00000008
#define SSH_FILEXFER_ATTR_CREATETIME 0x00000010
#define SSH_FILEXFER_ATTR_MODIFYTIME 0x00000020
#define SSH_FILEXFER_ATTR_ACL 0x00000040
#define SSH_FILEXFER_ATTR_OWNERGROUP 0x00000080
#define SSH_FILEXFER_ATTR_EXTENDED 0x80000000
/* 5.2 Type */
#define SSH_FILEXFER_TYPE_REGULAR 1
#define SSH_FILEXFER_TYPE_DIRECTORY 2
#define SSH_FILEXFER_TYPE_SYMLINK 3
#define SSH_FILEXFER_TYPE_SPECIAL 4
#define SSH_FILEXFER_TYPE_UNKNOWN 5
/* 6.3 Opening, Creating, and Closing Files */
#define SSH_FXF_READ 0x00000001
#define SSH_FXF_WRITE 0x00000002
#define SSH_FXF_APPEND 0x00000004
#define SSH_FXF_CREAT 0x00000008
#define SSH_FXF_TRUNC 0x00000010
#define SSH_FXF_EXCL 0x00000020
#define SSH_FXF_TEXT 0x00000040
/* 7. Responses from the Server to the Client */
#define SSH_FX_OK 0
#define SSH_FX_EOF 1
#define SSH_FX_NO_SUCH_FILE 2
#define SSH_FX_PERMISSION_DENIED 3
#define SSH_FX_FAILURE 4
#define SSH_FX_BAD_MESSAGE 5
#define SSH_FX_NO_CONNECTION 6
#define SSH_FX_CONNECTION_LOST 7
#define SSH_FX_OP_UNSUPPORTED 8
#define SSH_FX_INVALID_HANDLE 9
#define SSH_FX_NO_SUCH_PATH 10
#define SSH_FX_FILE_ALREADY_EXISTS 11
#define SSH_FX_WRITE_PROTECT 12
#endif /* PSSHFS_SFTPPROTO_H_ */

View File

@ -0,0 +1,548 @@
/* $NetBSD: subr.c,v 1.51 2012/11/04 22:46:08 christos Exp $ */
/*
* Copyright (c) 2006 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: subr.c,v 1.51 2012/11/04 22:46:08 christos Exp $");
#endif /* !lint */
#include <stdio.h>
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <puffs.h>
#include <stdlib.h>
#include <util.h>
#include "psshfs.h"
#include "sftp_proto.h"
static void
freedircache(struct psshfs_dir *base, size_t count)
{
size_t i;
for (i = 0; i < count; i++) {
free(base[i].entryname);
base[i].entryname = NULL;
}
free(base);
}
#define ENTRYCHUNK 16
static void
allocdirs(struct psshfs_node *psn)
{
size_t oldtot = psn->denttot;
psn->denttot += ENTRYCHUNK;
psn->dir = erealloc(psn->dir,
psn->denttot * sizeof(struct psshfs_dir));
memset(psn->dir + oldtot, 0, ENTRYCHUNK * sizeof(struct psshfs_dir));
}
static void
setpnva(struct puffs_usermount *pu, struct puffs_node *pn,
const struct vattr *vap)
{
struct psshfs_ctx *pctx = puffs_getspecific(pu);
struct psshfs_node *psn = pn->pn_data;
struct vattr modva;
/*
* Check if the file was modified from below us.
* If so, invalidate page cache. This is the only
* sensible place we can do this in.
*/
if (pn->pn_va.va_mtime.tv_sec != PUFFS_VNOVAL)
if (pn->pn_va.va_mtime.tv_sec != vap->va_mtime.tv_sec
&& pn->pn_va.va_type == VREG)
puffs_inval_pagecache_node(pu, pn);
modva = *vap;
if (pctx->domangleuid && modva.va_uid == pctx->mangleuid)
modva.va_uid = pctx->myuid;
if (pctx->domanglegid && modva.va_gid == pctx->manglegid)
modva.va_gid = pctx->mygid;
puffs_setvattr(&pn->pn_va, &modva);
psn->attrread = time(NULL);
}
struct psshfs_dir *
lookup(struct psshfs_dir *bdir, size_t ndir, const char *name)
{
struct psshfs_dir *test;
size_t i;
for (i = 0; i < ndir; i++) {
test = &bdir[i];
if (test->valid != 1)
continue;
if (strcmp(test->entryname, name) == 0)
return test;
}
return NULL;
}
static struct psshfs_dir *
lookup_by_entry(struct psshfs_dir *bdir, size_t ndir, struct puffs_node *entry)
{
struct psshfs_dir *test;
size_t i;
for (i = 0; i < ndir; i++) {
test = &bdir[i];
if (test->valid != 1)
continue;
if (test->entry == entry)
return test;
}
return NULL;
}
void
closehandles(struct puffs_usermount *pu, struct psshfs_node *psn, int which)
{
struct psshfs_ctx *pctx = puffs_getspecific(pu);
struct puffs_framebuf *pb1, *pb2;
uint32_t reqid;
if (psn->fhand_r && (which & HANDLE_READ)) {
assert(psn->lazyopen_r == NULL);
pb1 = psbuf_makeout();
reqid = NEXTREQ(pctx);
psbuf_req_data(pb1, SSH_FXP_CLOSE, reqid,
psn->fhand_r, psn->fhand_r_len);
puffs_framev_enqueue_justsend(pu, pctx->sshfd_data, pb1, 1, 0);
free(psn->fhand_r);
psn->fhand_r = NULL;
}
if (psn->fhand_w && (which & HANDLE_WRITE)) {
assert(psn->lazyopen_w == NULL);
pb2 = psbuf_makeout();
reqid = NEXTREQ(pctx);
psbuf_req_data(pb2, SSH_FXP_CLOSE, reqid,
psn->fhand_w, psn->fhand_w_len);
puffs_framev_enqueue_justsend(pu, pctx->sshfd_data, pb2, 1, 0);
free(psn->fhand_w);
psn->fhand_w = NULL;
}
psn->stat |= PSN_HANDLECLOSE;
}
void
lazyopen_rresp(struct puffs_usermount *pu, struct puffs_framebuf *pb,
void *arg, int error)
{
struct psshfs_node *psn = arg;
/* XXX: this is not enough */
if (psn->stat & PSN_RECLAIMED) {
error = ENOENT;
goto moreout;
}
if (error)
goto out;
error = psbuf_expect_handle(pb, &psn->fhand_r, &psn->fhand_r_len);
out:
psn->lazyopen_err_r = error;
psn->lazyopen_r = NULL;
if (error)
psn->stat &= ~PSN_DOLAZY_R;
if (psn->stat & PSN_HANDLECLOSE && (psn->stat & PSN_LAZYWAIT_R) == 0)
closehandles(pu, psn, HANDLE_READ);
moreout:
puffs_framebuf_destroy(pb);
}
void
lazyopen_wresp(struct puffs_usermount *pu, struct puffs_framebuf *pb,
void *arg, int error)
{
struct psshfs_node *psn = arg;
/* XXX: this is not enough */
if (psn->stat & PSN_RECLAIMED) {
error = ENOENT;
goto moreout;
}
if (error)
goto out;
error = psbuf_expect_handle(pb, &psn->fhand_w, &psn->fhand_w_len);
out:
psn->lazyopen_err_w = error;
psn->lazyopen_w = NULL;
if (error)
psn->stat &= ~PSN_DOLAZY_W;
if (psn->stat & PSN_HANDLECLOSE && (psn->stat & PSN_LAZYWAIT_W) == 0)
closehandles(pu, psn, HANDLE_WRITE);
moreout:
puffs_framebuf_destroy(pb);
}
struct readdirattr {
struct psshfs_node *psn;
int idx;
char entryname[MAXPATHLEN+1];
};
int
getpathattr(struct puffs_usermount *pu, const char *path, struct vattr *vap)
{
PSSHFSAUTOVAR(pu);
psbuf_req_str(pb, SSH_FXP_LSTAT, reqid, path);
GETRESPONSE(pb, pctx->sshfd);
rv = psbuf_expect_attrs(pb, vap);
out:
PSSHFSRETURN(rv);
}
int
getnodeattr(struct puffs_usermount *pu, struct puffs_node *pn, const char *path)
{
struct psshfs_ctx *pctx = puffs_getspecific(pu);
struct psshfs_node *psn = pn->pn_data;
struct vattr va;
int rv;
if (!psn->attrread || REFRESHTIMEOUT(pctx, time(NULL)-psn->attrread)) {
rv = getpathattr(pu, path ? path : PNPATH(pn), &va);
if (rv)
return rv;
setpnva(pu, pn, &va);
}
return 0;
}
int
sftp_readdir(struct puffs_usermount *pu, struct psshfs_ctx *pctx,
struct puffs_node *pn)
{
struct puffs_cc *pcc = puffs_cc_getcc(pu);
struct psshfs_node *psn = pn->pn_data;
struct psshfs_dir *olddir, *testd;
struct puffs_framebuf *pb;
uint32_t reqid = NEXTREQ(pctx);
uint32_t count, dhandlen;
char *dhand = NULL;
size_t nent;
char *longname = NULL;
size_t idx;
int rv;
assert(pn->pn_va.va_type == VDIR);
idx = 0;
olddir = psn->dir;
nent = psn->dentnext;
if (psn->dir && psn->dentread
&& !REFRESHTIMEOUT(pctx, time(NULL) - psn->dentread))
return 0;
if (psn->dentread) {
if ((rv = puffs_inval_namecache_dir(pu, pn)))
warn("readdir: dcache inval fail %p", pn);
}
pb = psbuf_makeout();
psbuf_req_str(pb, SSH_FXP_OPENDIR, reqid, PNPATH(pn));
if (puffs_framev_enqueue_cc(pcc, pctx->sshfd, pb, 0) == -1) {
rv = errno;
goto wayout;
}
rv = psbuf_expect_handle(pb, &dhand, &dhandlen);
if (rv)
goto wayout;
/*
* Well, the following is O(n^2), so feel free to improve if it
* gets too taxing on your system.
*/
/*
* note: for the "getattr in batch" to work, this must be before
* the attribute-getting. Otherwise times for first entries in
* large directories might expire before the directory itself and
* result in one-by-one attribute fetching.
*/
psn->dentread = time(NULL);
psn->dentnext = 0;
psn->denttot = 0;
psn->dir = NULL;
for (;;) {
reqid = NEXTREQ(pctx);
psbuf_recycleout(pb);
psbuf_req_data(pb, SSH_FXP_READDIR, reqid, dhand, dhandlen);
GETRESPONSE(pb, pctx->sshfd);
/* check for EOF */
if (psbuf_get_type(pb) == SSH_FXP_STATUS) {
rv = psbuf_expect_status(pb);
goto out;
}
rv = psbuf_expect_name(pb, &count);
if (rv)
goto out;
for (; count--; idx++) {
if (idx == psn->denttot)
allocdirs(psn);
if ((rv = psbuf_get_str(pb,
&psn->dir[idx].entryname, NULL)))
goto out;
if ((rv = psbuf_get_str(pb, &longname, NULL)) != 0)
goto out;
if ((rv = psbuf_get_vattr(pb, &psn->dir[idx].va)) != 0)
goto out;
if (sscanf(longname, "%*s%d",
&psn->dir[idx].va.va_nlink) != 1) {
rv = EPROTO;
goto out;
}
free(longname);
longname = NULL;
/*
* In case of DOT, copy the attributes (mostly
* because we want the link count for the root dir).
*/
if (strcmp(psn->dir[idx].entryname, ".") == 0) {
setpnva(pu, pn, &psn->dir[idx].va);
}
/*
* Check if we already have a psshfs_dir for the
* name we are processing. If so, use the old one.
* If not, create a new one
*/
testd = lookup(olddir, nent, psn->dir[idx].entryname);
if (testd) {
psn->dir[idx].entry = testd->entry;
/*
* Has entry. Update attributes to what
* we just got from the server.
*/
if (testd->entry) {
setpnva(pu, testd->entry,
&psn->dir[idx].va);
psn->dir[idx].va.va_fileid
= testd->entry->pn_va.va_fileid;
/*
* No entry. This can happen in two cases:
* 1) the file was created "behind our back"
* on the server
* 2) we do two readdirs before we instantiate
* the node (or run with -t 0).
*
* Cache attributes from the server in
* case we want to instantiate this node
* soon. Also preserve the old inode number
* which was given when the dirent was created.
*/
} else {
psn->dir[idx].va.va_fileid
= testd->va.va_fileid;
testd->va = psn->dir[idx].va;
}
/* No previous entry? Initialize this one. */
} else {
psn->dir[idx].entry = NULL;
psn->dir[idx].va.va_fileid = pctx->nextino++;
}
psn->dir[idx].attrread = psn->dentread;
psn->dir[idx].valid = 1;
}
}
out:
/* XXX: rv */
psn->dentnext = idx;
freedircache(olddir, nent);
reqid = NEXTREQ(pctx);
psbuf_recycleout(pb);
psbuf_req_data(pb, SSH_FXP_CLOSE, reqid, dhand, dhandlen);
puffs_framev_enqueue_justsend(pu, pctx->sshfd, pb, 1, 0);
free(dhand);
free(longname);
return rv;
wayout:
free(dhand);
PSSHFSRETURN(rv);
}
struct puffs_node *
makenode(struct puffs_usermount *pu, struct puffs_node *parent,
const struct psshfs_dir *pd, const struct vattr *vap)
{
struct psshfs_node *psn_parent = parent->pn_data;
struct psshfs_node *psn;
struct puffs_node *pn;
psn = emalloc(sizeof(struct psshfs_node));
memset(psn, 0, sizeof(struct psshfs_node));
pn = puffs_pn_new(pu, psn);
if (!pn) {
free(psn);
return NULL;
}
setpnva(pu, pn, &pd->va);
setpnva(pu, pn, vap);
psn->attrread = pd->attrread;
psn->parent = parent;
psn_parent->childcount++;
TAILQ_INIT(&psn->pw);
return pn;
}
struct puffs_node *
allocnode(struct puffs_usermount *pu, struct puffs_node *parent,
const char *entryname, const struct vattr *vap)
{
struct psshfs_ctx *pctx = puffs_getspecific(pu);
struct psshfs_dir *pd;
struct puffs_node *pn;
pd = direnter(parent, entryname);
pd->va.va_fileid = pctx->nextino++;
if (vap->va_type == VDIR) {
pd->va.va_nlink = 2;
parent->pn_va.va_nlink++;
} else {
pd->va.va_nlink = 1;
}
pn = makenode(pu, parent, pd, vap);
if (pn) {
pd->va.va_fileid = pn->pn_va.va_fileid;
pd->entry = pn;
}
return pn;
}
struct psshfs_dir *
direnter(struct puffs_node *parent, const char *entryname)
{
struct psshfs_node *psn_parent = parent->pn_data;
struct psshfs_dir *pd;
int i;
/* create directory entry */
if (psn_parent->denttot == psn_parent->dentnext)
allocdirs(psn_parent);
i = psn_parent->dentnext;
pd = &psn_parent->dir[i];
pd->entryname = estrdup(entryname);
pd->valid = 1;
pd->attrread = 0;
puffs_vattr_null(&pd->va);
psn_parent->dentnext++;
return pd;
}
void
doreclaim(struct puffs_node *pn)
{
struct psshfs_node *psn = pn->pn_data;
struct psshfs_node *psn_parent;
struct psshfs_dir *dent;
psn_parent = psn->parent->pn_data;
psn_parent->childcount--;
/*
* Null out entry from directory. Do not treat a missing entry
* as an invariant error, since the node might be removed from
* under us, and we might do a readdir before the reclaim resulting
* in no directory entry in the parent directory.
*/
dent = lookup_by_entry(psn_parent->dir, psn_parent->dentnext, pn);
if (dent)
dent->entry = NULL;
if (pn->pn_va.va_type == VDIR) {
freedircache(psn->dir, psn->dentnext);
psn->denttot = psn->dentnext = 0;
}
if (psn->symlink)
free(psn->symlink);
puffs_pn_put(pn);
}
void
nukenode(struct puffs_node *node, const char *entryname, int reclaim)
{
struct psshfs_node *psn, *psn_parent;
struct psshfs_dir *pd;
psn = node->pn_data;
psn_parent = psn->parent->pn_data;
pd = lookup(psn_parent->dir, psn_parent->dentnext, entryname);
assert(pd != NULL);
pd->valid = 0;
free(pd->entryname);
pd->entryname = NULL;
if (node->pn_va.va_type == VDIR)
psn->parent->pn_va.va_nlink--;
if (reclaim)
doreclaim(node);
}

View File

@ -0,0 +1,16 @@
# $NetBSD: Makefile,v 1.4 2010/08/06 15:04:13 pooka Exp $
PROG= mount_sysctlfs
SRCS= sysctlfs.c
DPAPP+= ${LIBPUFFS} ${LIBUTIL}
LDADD+= -lpuffs -lutil
MAN= mount_sysctlfs.8
.ifdef RUMP_ACTION
CPPFLAGS+= -DRUMP_ACTION
LDADD+= -lrump -lrumpuser -lpthread
.endif
.include <bsd.prog.mk>

View File

@ -0,0 +1,63 @@
.\" $NetBSD: mount_sysctlfs.8,v 1.3 2010/04/11 21:34:18 wiz Exp $
.\"
.\" Copyright (c) 2007 Antti Kantee. 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 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 THE 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.
.\"
.Dd April 11, 2010
.Dt MOUNT_SYSCTLFS 8
.Os
.Sh NAME
.Nm mount_sysctlfs
.Nd mount sysctl namespace as a directory hierarchy
.Sh SYNOPSIS
.Nm
.Op Fl r
.Op Fl o Ar mntopts
.Ar sysctlfs
.Ar mount_point
.Sh DESCRIPTION
The
.Nm
program provides the
.Xr sysctl 8
hierarchy through the file system namespace.
It is possible to browse the tree, query node values and modify them.
By default, the node contents are interpreted as ASCII.
If the
.Fl r
flag is given, the server uses raw mode and displays node contents as
they are received from the kernel (binary).
.Sh SEE ALSO
.Xr puffs 3 ,
.Xr puffs 4 ,
.Xr mount 8 ,
.Xr sysctl 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 5.0 .
.Sh CAVEATS
Raw mode
.Op Fl r
does not currently support node modification.

View File

@ -0,0 +1,799 @@
/* $NetBSD: sysctlfs.c,v 1.17 2012/11/04 22:47:21 christos Exp $ */
/*-
* Copyright (c) 2006, 2007 Antti Kantee. 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 AUTHOR ``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 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.
*/
/*
* sysctlfs: mount sysctls as a file system tree. Supports query and
* modify of nodes in the sysctl namespace in addition to namespace
* traversal.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: sysctlfs.c,v 1.17 2012/11/04 22:47:21 christos Exp $");
#endif /* !lint */
#include <sys/types.h>
#include <sys/sysctl.h>
#include <stdio.h>
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <mntopts.h>
#include <paths.h>
#include <puffs.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <util.h>
#ifdef RUMP_ACTION
#include <rump/rump.h>
#include <rump/rump_syscalls.h>
#define sysctl(a,b,c,d,e,f) rump_sys___sysctl(a,b,c,d,e,f)
#endif
PUFFSOP_PROTOS(sysctlfs)
struct sfsnode {
int sysctl_flags;
ino_t myid;
};
#define SFSPATH_DOTDOT 0
#define SFSPATH_NORMAL 1
#define N_HIERARCHY 10
typedef int SfsName[N_HIERARCHY];
struct sfsfid {
int len;
SfsName path;
};
static struct sfsnode rn;
static SfsName sname_root;
static struct timespec fstime;
static ino_t nextid = 3;
static mode_t fileperms;
static uid_t fileuid;
static gid_t filegid;
static int rflag;
#define ISADIR(a) ((SYSCTL_TYPE(a->sysctl_flags) == CTLTYPE_NODE))
#define SFS_MAXFILE 32768
#define SFS_NODEPERDIR 128
static int sysctlfs_domount(struct puffs_usermount *);
/*
* build paths. doesn't support rename (but neither does the fs)
*/
static int
sysctlfs_pathbuild(struct puffs_usermount *pu,
const struct puffs_pathobj *parent, const struct puffs_pathobj *comp,
size_t offset, struct puffs_pathobj *res)
{
SfsName *sname;
size_t clen;
assert(parent->po_len < N_HIERARCHY); /* code uses +1 */
sname = malloc(sizeof(SfsName));
assert(sname != NULL);
clen = parent->po_len;
if (comp->po_len == SFSPATH_DOTDOT) {
assert(clen != 0);
clen--;
}
memcpy(sname, parent->po_path, clen * sizeof(int));
res->po_path = sname;
res->po_len = clen;
return 0;
}
static int
sysctlfs_pathtransform(struct puffs_usermount *pu,
const struct puffs_pathobj *p, const struct puffs_cn *pcn,
struct puffs_pathobj *res)
{
res->po_path = NULL;
/*
* XXX: overload. prevents us from doing rename, but the fs
* (and sysctl(3)) doesn't support it, so no biggie
*/
if (PCNISDOTDOT(pcn)) {
res->po_len = SFSPATH_DOTDOT;
}else {
res->po_len = SFSPATH_NORMAL;
}
return 0;
}
static int
sysctlfs_pathcmp(struct puffs_usermount *pu, struct puffs_pathobj *po1,
struct puffs_pathobj *po2, size_t clen, int checkprefix)
{
if (memcmp(po1->po_path, po2->po_path, clen * sizeof(int)) == 0)
return 0;
return 1;
}
static void
sysctlfs_pathfree(struct puffs_usermount *pu, struct puffs_pathobj *po)
{
free(po->po_path);
}
static struct puffs_node *
getnode(struct puffs_usermount *pu, struct puffs_pathobj *po, int nodetype)
{
struct sysctlnode sn[SFS_NODEPERDIR];
struct sysctlnode qnode;
struct puffs_node *pn;
struct sfsnode *sfs;
SfsName myname, *sname;
size_t sl, i;
/*
* Check if we need to create a new in-memory node or if we
* already have one for this path. Shortcut for the rootnode.
* Also, memcmp against zero-length would be quite true always.
*/
if (po->po_len == 0)
pn = puffs_getroot(pu);
else
pn = puffs_pn_nodewalk(pu, puffs_path_walkcmp, po);
if (pn == NULL) {
/*
* don't know nodetype? query...
*
* XXX1: nothing really guarantees 0 is an invalid nodetype
* XXX2: is there really no easier way of doing this? we
* know the whole mib path
*/
if (!nodetype) {
sname = po->po_path;
memcpy(myname, po->po_path, po->po_len * sizeof(int));
memset(&qnode, 0, sizeof(qnode));
qnode.sysctl_flags = SYSCTL_VERSION;
myname[po->po_len-1] = CTL_QUERY;
sl = sizeof(sn);
if (sysctl(myname, po->po_len, sn, &sl,
&qnode, sizeof(qnode)) == -1)
abort();
for (i = 0; i < sl / sizeof(struct sysctlnode); i++) {
if (sn[i].sysctl_num==(*sname)[po->po_len-1]) {
nodetype = sn[i].sysctl_flags;
break;
}
}
if (!nodetype)
return NULL;
}
sfs = emalloc(sizeof(struct sfsnode));
sfs->sysctl_flags = nodetype;
sfs->myid = nextid++;
pn = puffs_pn_new(pu, sfs);
assert(pn);
}
return pn;
}
int
main(int argc, char *argv[])
{
struct puffs_usermount *pu;
struct puffs_ops *pops;
mntoptparse_t mp;
int mntflags, pflags;
int detach;
int ch;
setprogname(argv[0]);
if (argc < 2)
errx(1, "usage: %s sysctlfs [-o mntopts] mountpath",
getprogname());
mntflags = pflags = 0;
detach = 1;
while ((ch = getopt(argc, argv, "o:rs")) != -1) {
switch (ch) {
case 'o':
mp = getmntopts(optarg, puffsmopts, &mntflags, &pflags);
if (mp == NULL)
err(1, "getmntopts");
freemntopts(mp);
break;
case 'r':
rflag = 1;
break;
case 's':
detach = 0;
break;
}
}
argv += optind;
argc -= optind;
pflags |= PUFFS_FLAG_BUILDPATH | PUFFS_KFLAG_NOCACHE;
if (pflags & PUFFS_FLAG_OPDUMP)
detach = 0;
if (argc != 2)
errx(1, "usage: %s [-o mntopts] mountpath", getprogname());
PUFFSOP_INIT(pops);
PUFFSOP_SETFSNOP(pops, unmount);
PUFFSOP_SETFSNOP(pops, sync);
PUFFSOP_SETFSNOP(pops, statvfs);
PUFFSOP_SET(pops, sysctlfs, fs, nodetofh);
PUFFSOP_SET(pops, sysctlfs, fs, fhtonode);
PUFFSOP_SET(pops, sysctlfs, node, lookup);
PUFFSOP_SET(pops, sysctlfs, node, getattr);
PUFFSOP_SET(pops, sysctlfs, node, setattr);
PUFFSOP_SET(pops, sysctlfs, node, readdir);
PUFFSOP_SET(pops, sysctlfs, node, read);
PUFFSOP_SET(pops, sysctlfs, node, write);
PUFFSOP_SET(pops, puffs_genfs, node, reclaim);
pu = puffs_init(pops, _PATH_PUFFS, "sysctlfs", NULL, pflags);
if (pu == NULL)
err(1, "puffs_init");
puffs_set_pathbuild(pu, sysctlfs_pathbuild);
puffs_set_pathtransform(pu, sysctlfs_pathtransform);
puffs_set_pathcmp(pu, sysctlfs_pathcmp);
puffs_set_pathfree(pu, sysctlfs_pathfree);
puffs_setfhsize(pu, sizeof(struct sfsfid), PUFFS_FHFLAG_NFSV3);
if (sysctlfs_domount(pu) != 0)
errx(1, "domount");
if (detach)
if (puffs_daemon(pu, 1, 1) == -1)
err(1, "puffs_daemon");
#ifdef RUMP_ACTION
{
extern int puffs_fakecc;
puffs_fakecc = 1;
rump_init();
}
#endif
if (puffs_mount(pu, argv[1], mntflags, puffs_getroot(pu)) == -1)
err(1, "puffs_mount");
if (puffs_mainloop(pu) == -1)
err(1, "mainloop");
return 0;
}
static int
sysctlfs_domount(struct puffs_usermount *pu)
{
struct puffs_pathobj *po_root;
struct puffs_node *pn_root;
struct timeval tv_now;
rn.myid = 2;
rn.sysctl_flags = CTLTYPE_NODE;
gettimeofday(&tv_now, NULL);
TIMEVAL_TO_TIMESPEC(&tv_now, &fstime);
pn_root = puffs_pn_new(pu, &rn);
assert(pn_root != NULL);
puffs_setroot(pu, pn_root);
po_root = puffs_getrootpathobj(pu);
po_root->po_path = &sname_root;
po_root->po_len = 0;
fileuid = geteuid();
filegid = getegid();
if (fileuid == 0)
fileperms = 0755;
else
fileperms = 0555;
return 0;
}
int
sysctlfs_fs_fhtonode(struct puffs_usermount *pu, void *fid, size_t fidsize,
struct puffs_newinfo *pni)
{
struct puffs_pathobj po;
struct puffs_node *pn;
struct sfsnode *sfs;
struct sfsfid *sfid;
sfid = fid;
po.po_len = sfid->len;
po.po_path = &sfid->path;
pn = getnode(pu, &po, 0);
if (pn == NULL)
return EINVAL;
sfs = pn->pn_data;
puffs_newinfo_setcookie(pni, pn);
if (ISADIR(sfs))
puffs_newinfo_setvtype(pni, VDIR);
else
puffs_newinfo_setvtype(pni, VREG);
return 0;
}
int
sysctlfs_fs_nodetofh(struct puffs_usermount *pu, void *cookie,
void *fid, size_t *fidsize)
{
struct puffs_node *pn = cookie;
struct sfsfid *sfid;
sfid = fid;
sfid->len = PNPLEN(pn);
memcpy(&sfid->path, PNPATH(pn), sfid->len * sizeof(int));
return 0;
}
static void
getnodedata(struct sfsnode *sfs, struct puffs_pathobj *po,
char *buf, size_t *bufsize)
{
size_t sz;
int error = 0;
assert(!ISADIR(sfs));
memset(buf, 0, *bufsize);
switch (SYSCTL_TYPE(sfs->sysctl_flags)) {
case CTLTYPE_BOOL: {
bool b;
sz = sizeof(bool);
assert(sz <= *bufsize);
if (sysctl(po->po_path, po->po_len, &b, &sz, NULL, 0) == -1) {
error = errno;
break;
}
if (rflag)
memcpy(buf, &b, sz);
else
snprintf(buf, *bufsize, "%s", b ? "true" : "false");
break;
}
case CTLTYPE_INT: {
int i;
sz = sizeof(int);
assert(sz <= *bufsize);
if (sysctl(po->po_path, po->po_len, &i, &sz, NULL, 0) == -1) {
error = errno;
break;
}
if (rflag)
memcpy(buf, &i, sz);
else
snprintf(buf, *bufsize, "%d", i);
break;
}
case CTLTYPE_QUAD: {
quad_t q;
sz = sizeof(q);
assert(sz <= *bufsize);
if (sysctl(po->po_path, po->po_len, &q, &sz, NULL, 0) == -1) {
error = errno;
break;
}
if (rflag)
memcpy(buf, &q, sz);
else
snprintf(buf, *bufsize, "%" PRId64, q);
break;
}
case CTLTYPE_STRUCT: {
uint8_t snode[SFS_MAXFILE/2-1];
unsigned i;
sz = sizeof(snode);
assert(sz <= *bufsize);
if (sysctl(po->po_path, po->po_len, snode, &sz, NULL, 0) == -1){
error = errno;
break;
}
if (rflag) {
memcpy(buf, &snode, sz);
} else {
for (i = 0; i < sz && 2*i < *bufsize; i++) {
sprintf(&buf[2*i], "%02x", snode[i]);
}
buf[2*i] = '\0';
}
break;
}
case CTLTYPE_STRING: {
sz = *bufsize;
assert(sz <= *bufsize);
if (sysctl(po->po_path, po->po_len, buf, &sz, NULL, 0) == -1) {
error = errno;
break;
}
break;
}
default:
snprintf(buf, *bufsize, "invalid sysctl CTLTYPE %d",
SYSCTL_TYPE(sfs->sysctl_flags));
break;
}
if (error) {
*bufsize = 0;
return;
}
if (rflag)
*bufsize = sz;
else
*bufsize = strlen(buf);
}
static int
getlinks(struct sfsnode *sfs, struct puffs_pathobj *po)
{
struct sysctlnode sn[SFS_NODEPERDIR];
struct sysctlnode qnode;
SfsName *sname;
size_t sl;
if (!ISADIR(sfs))
return 1;
memset(&qnode, 0, sizeof(qnode));
sl = sizeof(sn);
qnode.sysctl_flags = SYSCTL_VERSION;
sname = po->po_path;
(*sname)[po->po_len] = CTL_QUERY;
if (sysctl(*sname, po->po_len + 1, sn, &sl,
&qnode, sizeof(qnode)) == -1)
return 0;
return (sl / sizeof(sn[0])) + 2;
}
static int
getsize(struct sfsnode *sfs, struct puffs_pathobj *po)
{
char buf[SFS_MAXFILE];
size_t sz = sizeof(buf);
if (ISADIR(sfs))
return getlinks(sfs, po) * 16; /* totally arbitrary */
getnodedata(sfs, po, buf, &sz);
if (rflag)
return sz;
else
return sz + 1; /* for \n, not \0 */
}
int
sysctlfs_node_lookup(struct puffs_usermount *pu, void *opc,
struct puffs_newinfo *pni, const struct puffs_cn *pcn)
{
struct puffs_cn *p2cn = __UNCONST(pcn); /* XXX: fix the interface */
struct sysctlnode sn[SFS_NODEPERDIR];
struct sysctlnode qnode;
struct puffs_node *pn_dir = opc;
struct puffs_node *pn_new;
struct sfsnode *sfs_dir = pn_dir->pn_data, *sfs_new;
SfsName *sname = PCNPATH(pcn);
size_t sl, i;
int nodetype;
assert(ISADIR(sfs_dir));
/*
* If we're looking for dotdot, we already have the entire pathname
* in sname, courtesy of pathbuild, so we can skip this step.
*/
if (!PCNISDOTDOT(pcn)) {
memset(&qnode, 0, sizeof(qnode));
sl = SFS_NODEPERDIR * sizeof(struct sysctlnode);
qnode.sysctl_flags = SYSCTL_VERSION;
(*sname)[PCNPLEN(pcn)] = CTL_QUERY;
if (sysctl(*sname, PCNPLEN(pcn) + 1, sn, &sl,
&qnode, sizeof(qnode)) == -1)
return ENOENT;
for (i = 0; i < sl / sizeof(struct sysctlnode); i++)
if (strcmp(sn[i].sysctl_name, pcn->pcn_name) == 0)
break;
if (i == sl / sizeof(struct sysctlnode))
return ENOENT;
(*sname)[PCNPLEN(pcn)] = sn[i].sysctl_num;
p2cn->pcn_po_full.po_len++;
nodetype = sn[i].sysctl_flags;
} else
nodetype = CTLTYPE_NODE;
pn_new = getnode(pu, &p2cn->pcn_po_full, nodetype);
sfs_new = pn_new->pn_data;
puffs_newinfo_setcookie(pni, pn_new);
if (ISADIR(sfs_new))
puffs_newinfo_setvtype(pni, VDIR);
else
puffs_newinfo_setvtype(pni, VREG);
return 0;
}
int
sysctlfs_node_getattr(struct puffs_usermount *pu, void *opc, struct vattr *va,
const struct puffs_cred *pcr)
{
struct puffs_node *pn = opc;
struct sfsnode *sfs = pn->pn_data;
memset(va, 0, sizeof(struct vattr));
if (ISADIR(sfs)) {
va->va_type = VDIR;
va->va_mode = 0555;
} else {
va->va_type = VREG;
va->va_mode = fileperms;
}
va->va_uid = fileuid;
va->va_gid = filegid;
va->va_nlink = getlinks(sfs, &pn->pn_po);
va->va_fileid = sfs->myid;
va->va_size = getsize(sfs, &pn->pn_po);
va->va_gen = 1;
va->va_rdev = PUFFS_VNOVAL;
va->va_blocksize = 512;
va->va_filerev = 1;
va->va_atime = va->va_mtime = va->va_ctime = va->va_birthtime = fstime;
return 0;
}
int
sysctlfs_node_setattr(struct puffs_usermount *pu, void *opc,
const struct vattr *va, const struct puffs_cred *pcr)
{
/* dummy, but required for write */
/* XXX: we could return EOPNOTSUPP or something */
return 0;
}
int
sysctlfs_node_readdir(struct puffs_usermount *pu, void *opc,
struct dirent *dent, off_t *readoff, size_t *reslen,
const struct puffs_cred *pcr, int *eofflag,
off_t *cookies, size_t *ncookies)
{
struct sysctlnode sn[SFS_NODEPERDIR];
struct sysctlnode qnode;
struct puffs_node *pn_dir = opc;
struct puffs_node *pn_res;
struct puffs_pathobj po;
struct sfsnode *sfs_dir = pn_dir->pn_data, *sfs_ent;
SfsName *sname;
size_t sl, i;
enum vtype vt;
ino_t id;
*ncookies = 0;
again:
if (*readoff == DENT_DOT || *readoff == DENT_DOTDOT) {
puffs_gendotdent(&dent, sfs_dir->myid, *readoff, reslen);
(*readoff)++;
PUFFS_STORE_DCOOKIE(cookies, ncookies, *readoff);
goto again;
}
memset(&qnode, 0, sizeof(qnode));
sl = SFS_NODEPERDIR * sizeof(struct sysctlnode);
qnode.sysctl_flags = SYSCTL_VERSION;
sname = PNPATH(pn_dir);
(*sname)[PNPLEN(pn_dir)] = CTL_QUERY;
if (sysctl(*sname, PNPLEN(pn_dir) + 1, sn, &sl,
&qnode, sizeof(qnode)) == -1)
return ENOENT;
po.po_path = sname;
po.po_len = PNPLEN(pn_dir)+1;
for (i = DENT_ADJ(*readoff); i < sl / sizeof(struct sysctlnode); i++) {
if (SYSCTL_TYPE(sn[i].sysctl_flags) == CTLTYPE_NODE)
vt = VDIR;
else
vt = VREG;
/*
* check if the node exists. if so, give it the real
* inode number. otherwise just fake it.
*/
(*sname)[PNPLEN(pn_dir)] = sn[i].sysctl_num;
pn_res = puffs_pn_nodewalk(pu, puffs_path_walkcmp, &po);
if (pn_res) {
sfs_ent = pn_res->pn_data;
id = sfs_ent->myid;
} else {
id = nextid++;
}
if (!puffs_nextdent(&dent, sn[i].sysctl_name, id,
puffs_vtype2dt(vt), reslen))
return 0;
(*readoff)++;
PUFFS_STORE_DCOOKIE(cookies, ncookies, *readoff);
}
*eofflag = 1;
return 0;
}
int
sysctlfs_node_read(struct puffs_usermount *pu, void *opc, uint8_t *buf,
off_t offset, size_t *resid, const struct puffs_cred *pcr,
int ioflag)
{
char localbuf[SFS_MAXFILE];
struct puffs_node *pn = opc;
struct sfsnode *sfs = pn->pn_data;
size_t sz = sizeof(localbuf);
int xfer;
if (ISADIR(sfs))
return EISDIR;
getnodedata(sfs, &pn->pn_po, localbuf, &sz);
if ((ssize_t)sz < offset)
xfer = 0;
else
xfer = MIN(*resid, sz - offset);
if (xfer <= 0)
return 0;
memcpy(buf, localbuf + offset, xfer);
*resid -= xfer;
if (*resid && !rflag) {
buf[xfer] = '\n';
(*resid)--;
}
return 0;
}
int
sysctlfs_node_write(struct puffs_usermount *pu, void *opc, uint8_t *buf,
off_t offset, size_t *resid, const struct puffs_cred *cred,
int ioflag)
{
struct puffs_node *pn = opc;
struct sfsnode *sfs = pn->pn_data;
long long ll;
int i, rv;
bool b;
/*
* I picked the wrong day to ... um, the wrong place to return errors
*/
/* easy to support, but just unavailable now */
if (rflag)
return EOPNOTSUPP;
if (puffs_cred_isjuggernaut(cred) == 0)
return EACCES;
if (ISADIR(sfs))
return EISDIR;
if (offset != 0)
return EINVAL;
if (ioflag & PUFFS_IO_APPEND)
return EINVAL;
switch (SYSCTL_TYPE(sfs->sysctl_flags)) {
case CTLTYPE_BOOL:
if (strcasestr((const char *)buf, "true"))
b = true;
else if (strcasestr((const char *)buf, "false"))
b = false;
else
return EINVAL;
rv = sysctl(PNPATH(pn), PNPLEN(pn), NULL, NULL,
&b, sizeof(b));
break;
case CTLTYPE_INT:
if (sscanf((const char *)buf, "%d", &i) != 1)
return EINVAL;
rv = sysctl(PNPATH(pn), PNPLEN(pn), NULL, NULL,
&i, sizeof(int));
break;
case CTLTYPE_QUAD:
if (sscanf((const char *)buf, "%lld", &ll) != 1)
return EINVAL;
rv = sysctl(PNPATH(pn), PNPLEN(pn), NULL, NULL,
&ll, sizeof(long long));
break;
case CTLTYPE_STRING:
rv = sysctl(PNPATH(pn), PNPLEN(pn), NULL, NULL, buf, *resid);
break;
default:
rv = EINVAL;
break;
}
if (rv)
return rv;
*resid = 0;
return 0;
}

View File

@ -0,0 +1,14 @@
# $NetBSD: Makefile,v 1.1 2010/04/29 22:42:48 pooka Exp $
#
PROG= rump_au-naturel
NOMAN=
ISRUMP= # persuadertron
# Link in components to see which devices they create. The
# following is an example. You should see /dev/bpf.
#
#LDADD+= -lrumpdev_bpf -lrumpdev -lrumpnet_net -lrumpnet
.include <bsd.prog.mk>

View File

@ -0,0 +1,66 @@
/* $NetBSD: rump_au-naturel.c,v 1.1 2010/04/29 22:42:48 pooka Exp $ */
/*
* Copyright (c) 2010 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/types.h>
#include <sys/mount.h>
#include <err.h>
#include <puffs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <rump/p2k.h>
/* NetBSD-5 compat */
#ifndef MOUNT_RUMPFS
#define MOUNT_RUMPFS "rumpfs"
#endif
static void
usage(void)
{
fprintf(stderr, "usage: %s rump /mountpoint\n", getprogname());
exit(1);
}
int
main(int argc, char *argv[])
{
int rv;
setprogname(argv[0]);
if (argc != 3)
usage();
rv = p2k_run_fs(MOUNT_RUMPFS, argv[1], argv[2], 0, NULL, 0, 0);
if (rv == -1)
err(1, "p2k_run_fs");
return 0;
}

View File

@ -0,0 +1,9 @@
# $NetBSD: Makefile,v 1.3 2010/01/25 15:55:36 pooka Exp $
#
MOUNTNAME= cd9660
ISRUMP= # yes
RUMP_DISKFS=
.include <bsd.prog.mk>

View File

@ -0,0 +1,134 @@
.\" $NetBSD: rump_cd9660.8,v 1.13 2011/07/24 09:00:06 uch Exp $
.\"
.\" WARNING: GENERATED FILE, DO NOT EDIT
.\" INSTEAD, EDIT makerumpmanpages.sh AND REGEN
.\" from: NetBSD: makerumpmanpages.sh,v 1.12 2010/11/22 07:56:31 pooka Exp
.\"
.\" Copyright (c) 2008-2010 Antti Kantee. 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 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 THE 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.
.\"
.Dd November 21, 2010
.Dt RUMP_CD9660 8
.Os
.Sh NAME
.Nm rump_cd9660
.Nd mount a cd9660 image with a userspace server
.Sh SYNOPSIS
.Cd "file-system PUFFS"
.Cd "pseudo-device putter"
.Pp
.Nm
.Op options
.Ar image
.Ar mountpoint
.Sh DESCRIPTION
.Em NOTE!
This manual page describes features specific to the
.Xr rump 3
file server.
Please see
.Xr mount_cd9660 8
for a full description of the available command line options.
.Pp
The
.Nm
utility can be used to mount cd9660 file systems.
It uses
.Xr rump 3
and
.Xr p2k 3
to facilitate running the file system as a server in userspace.
As opposed to
.Xr mount_cd9660 8 ,
.Nm
does not use file system code within the kernel and therefore does
not require kernel support except
.Xr puffs 4 .
Apart from a minor speed penalty there is no downside with respect to
in-kernel code.
.Pp
.Nm
does not require using
.Xr vnconfig 8
for mounts from regular files and the file path can be passed
directly as the
.Ar image
parameter.
In fact, the use of
.Xr vnconfig 8
is discouraged, since it is unable to properly deal with images on
sparse files.
.Pp
In case the image contains multiple partitions, the desired partition
must be indicated by appending the token
.Dq %DISKLABEL:p%
to the
.Ar image
path.
The letter
.Dq p
specifies the partition as obtained via
.Xr disklabel 8 .
For example, to mount partition
.Dq e
from image
.Pa /tmp/wd0.img ,
use
.Dq /tmp/wd0.img%DISKLABEL:e% .
.Pp
It is recommended that untrusted file system images be mounted with
.Nm
instead of
.Xr mount_cd9660 8 .
Corrupt file system images commonly cause the file system
to crash the entire kernel, but with
.Nm
only the userspace server process will dump core.
.Pp
To use
.Nm
via
.Xr mount 8 ,
the flags
.Fl o Ar rump
and
.Fl t Ar cd9660
should be given.
Similarly,
.Nm
is used instead of
.Xr mount_cd9660 8
if
.Dq rump
is added to the options field of
.Xr fstab 5 .
.Sh SEE ALSO
.Xr p2k 3 ,
.Xr puffs 3 ,
.Xr rump 3 ,
.Xr mount_cd9660 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 5.0 .

View File

@ -0,0 +1,64 @@
/* $NetBSD: rump_cd9660.c,v 1.8 2010/05/30 04:32:09 dholland Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/mount.h>
#include <isofs/cd9660/cd9660_mount.h>
#include <rump/p2k.h>
#include <rump/ukfs.h>
#include <err.h>
#include <stdlib.h>
#include <string.h>
#include "mount_cd9660.h"
int
main(int argc, char *argv[])
{
struct iso_args args;
char canon_dev[UKFS_DEVICE_MAXPATHLEN], canon_dir[MAXPATHLEN];
struct ukfs_part *part;
int mntflags;
int rv;
setprogname(argv[0]);
UKFS_DEVICE_ARGVPROBE(&part);
mount_cd9660_parseargs(argc, argv, &args, &mntflags,
canon_dev, canon_dir);
rv = p2k_run_diskfs(MOUNT_CD9660, canon_dev, part, canon_dir, mntflags,
&args, sizeof(args), 0);
ukfs_part_release(part);
if (rv)
err(1, "mount");
return 0;
}

View File

@ -0,0 +1,9 @@
# $NetBSD: Makefile,v 1.3 2010/01/25 15:55:36 pooka Exp $
#
MOUNTNAME= efs
ISRUMP= # gracie, padre
RUMP_DISKFS=
.include <bsd.prog.mk>

View File

@ -0,0 +1,134 @@
.\" $NetBSD: rump_efs.8,v 1.13 2011/07/24 09:00:06 uch Exp $
.\"
.\" WARNING: GENERATED FILE, DO NOT EDIT
.\" INSTEAD, EDIT makerumpmanpages.sh AND REGEN
.\" from: NetBSD: makerumpmanpages.sh,v 1.12 2010/11/22 07:56:31 pooka Exp
.\"
.\" Copyright (c) 2008-2010 Antti Kantee. 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 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 THE 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.
.\"
.Dd November 21, 2010
.Dt RUMP_EFS 8
.Os
.Sh NAME
.Nm rump_efs
.Nd mount a efs image with a userspace server
.Sh SYNOPSIS
.Cd "file-system PUFFS"
.Cd "pseudo-device putter"
.Pp
.Nm
.Op options
.Ar image
.Ar mountpoint
.Sh DESCRIPTION
.Em NOTE!
This manual page describes features specific to the
.Xr rump 3
file server.
Please see
.Xr mount_efs 8
for a full description of the available command line options.
.Pp
The
.Nm
utility can be used to mount efs file systems.
It uses
.Xr rump 3
and
.Xr p2k 3
to facilitate running the file system as a server in userspace.
As opposed to
.Xr mount_efs 8 ,
.Nm
does not use file system code within the kernel and therefore does
not require kernel support except
.Xr puffs 4 .
Apart from a minor speed penalty there is no downside with respect to
in-kernel code.
.Pp
.Nm
does not require using
.Xr vnconfig 8
for mounts from regular files and the file path can be passed
directly as the
.Ar image
parameter.
In fact, the use of
.Xr vnconfig 8
is discouraged, since it is unable to properly deal with images on
sparse files.
.Pp
In case the image contains multiple partitions, the desired partition
must be indicated by appending the token
.Dq %DISKLABEL:p%
to the
.Ar image
path.
The letter
.Dq p
specifies the partition as obtained via
.Xr disklabel 8 .
For example, to mount partition
.Dq e
from image
.Pa /tmp/wd0.img ,
use
.Dq /tmp/wd0.img%DISKLABEL:e% .
.Pp
It is recommended that untrusted file system images be mounted with
.Nm
instead of
.Xr mount_efs 8 .
Corrupt file system images commonly cause the file system
to crash the entire kernel, but with
.Nm
only the userspace server process will dump core.
.Pp
To use
.Nm
via
.Xr mount 8 ,
the flags
.Fl o Ar rump
and
.Fl t Ar efs
should be given.
Similarly,
.Nm
is used instead of
.Xr mount_efs 8
if
.Dq rump
is added to the options field of
.Xr fstab 5 .
.Sh SEE ALSO
.Xr p2k 3 ,
.Xr puffs 3 ,
.Xr rump 3 ,
.Xr mount_efs 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 5.0 .

View File

@ -0,0 +1,63 @@
/* $NetBSD: rump_efs.c,v 1.6 2009/12/13 21:16:54 pooka Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/types.h>
#include <sys/mount.h>
#include <fs/efs/efs_mount.h>
#include <err.h>
#include <puffs.h>
#include <stdlib.h>
#include <unistd.h>
#include <rump/p2k.h>
#include <rump/ukfs.h>
#include "mount_efs.h"
int
main(int argc, char *argv[])
{
struct efs_args args;
char canon_dev[UKFS_DEVICE_MAXPATHLEN], canon_dir[MAXPATHLEN];
struct ukfs_part *part;
int mntflags;
int rv;
setprogname(argv[0]);
UKFS_DEVICE_ARGVPROBE(&part);
mount_efs_parseargs(argc, argv, &args, &mntflags, canon_dev, canon_dir);
rv = p2k_run_diskfs(MOUNT_EFS, canon_dev, part, canon_dir, mntflags,
&args, sizeof(args), 0);
ukfs_part_release(part);
if (rv)
err(1, "mount");
return 0;
}

View File

@ -0,0 +1,14 @@
# $NetBSD: Makefile,v 1.6 2010/01/25 15:55:36 pooka Exp $
#
.include <bsd.own.mk>
MOUNTNAME= ext2fs
LDADD+= -lrumpfs_ffs
DPADD+= ${LIBRUMPFS_FFS}
ISRUMP= # yea baby
RUMP_DISKFS=
.include <bsd.prog.mk>

View File

@ -0,0 +1,134 @@
.\" $NetBSD: rump_ext2fs.8,v 1.13 2011/07/24 09:00:06 uch Exp $
.\"
.\" WARNING: GENERATED FILE, DO NOT EDIT
.\" INSTEAD, EDIT makerumpmanpages.sh AND REGEN
.\" from: NetBSD: makerumpmanpages.sh,v 1.12 2010/11/22 07:56:31 pooka Exp
.\"
.\" Copyright (c) 2008-2010 Antti Kantee. 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 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 THE 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.
.\"
.Dd November 21, 2010
.Dt RUMP_EXT2FS 8
.Os
.Sh NAME
.Nm rump_ext2fs
.Nd mount a ext2fs image with a userspace server
.Sh SYNOPSIS
.Cd "file-system PUFFS"
.Cd "pseudo-device putter"
.Pp
.Nm
.Op options
.Ar image
.Ar mountpoint
.Sh DESCRIPTION
.Em NOTE!
This manual page describes features specific to the
.Xr rump 3
file server.
Please see
.Xr mount_ext2fs 8
for a full description of the available command line options.
.Pp
The
.Nm
utility can be used to mount ext2fs file systems.
It uses
.Xr rump 3
and
.Xr p2k 3
to facilitate running the file system as a server in userspace.
As opposed to
.Xr mount_ext2fs 8 ,
.Nm
does not use file system code within the kernel and therefore does
not require kernel support except
.Xr puffs 4 .
Apart from a minor speed penalty there is no downside with respect to
in-kernel code.
.Pp
.Nm
does not require using
.Xr vnconfig 8
for mounts from regular files and the file path can be passed
directly as the
.Ar image
parameter.
In fact, the use of
.Xr vnconfig 8
is discouraged, since it is unable to properly deal with images on
sparse files.
.Pp
In case the image contains multiple partitions, the desired partition
must be indicated by appending the token
.Dq %DISKLABEL:p%
to the
.Ar image
path.
The letter
.Dq p
specifies the partition as obtained via
.Xr disklabel 8 .
For example, to mount partition
.Dq e
from image
.Pa /tmp/wd0.img ,
use
.Dq /tmp/wd0.img%DISKLABEL:e% .
.Pp
It is recommended that untrusted file system images be mounted with
.Nm
instead of
.Xr mount_ext2fs 8 .
Corrupt file system images commonly cause the file system
to crash the entire kernel, but with
.Nm
only the userspace server process will dump core.
.Pp
To use
.Nm
via
.Xr mount 8 ,
the flags
.Fl o Ar rump
and
.Fl t Ar ext2fs
should be given.
Similarly,
.Nm
is used instead of
.Xr mount_ext2fs 8
if
.Dq rump
is added to the options field of
.Xr fstab 5 .
.Sh SEE ALSO
.Xr p2k 3 ,
.Xr puffs 3 ,
.Xr rump 3 ,
.Xr mount_ext2fs 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 5.0 .

View File

@ -0,0 +1,66 @@
/* $NetBSD: rump_ext2fs.c,v 1.9 2010/01/12 18:43:37 pooka Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/types.h>
#include <sys/mount.h>
#include <ufs/ufs/ufsmount.h>
#include <err.h>
#include <puffs.h>
#include <stdlib.h>
#include <unistd.h>
#include <rump/p2k.h>
#include <rump/ukfs.h>
#include "mount_ext2fs.h"
int
main(int argc, char *argv[])
{
struct ufs_args args;
char canon_dev[UKFS_DEVICE_MAXPATHLEN], canon_dir[MAXPATHLEN];
struct ukfs_part *part;
int mntflags;
int rv;
setprogname(argv[0]);
puffs_unmountonsignal(SIGINT, true);
puffs_unmountonsignal(SIGTERM, true);
UKFS_DEVICE_ARGVPROBE(&part);
mount_ext2fs_parseargs(argc, argv, &args, &mntflags,
canon_dev, canon_dir);
rv = p2k_run_diskfs(MOUNT_EXT2FS, canon_dev, part, canon_dir, mntflags,
&args, sizeof(args), 0);
ukfs_part_release(part);
if (rv)
err(1, "mount");
return 0;
}

View File

@ -0,0 +1,8 @@
# $NetBSD: Makefile,v 1.1 2009/07/31 19:18:46 pooka Exp $
#
MOUNTNAME= fdesc
ISRUMP= # descualified
.include <bsd.prog.mk>

View File

@ -0,0 +1,96 @@
.\" $NetBSD: rump_fdesc.8,v 1.6 2011/07/24 09:00:06 uch Exp $
.\"
.\" WARNING: GENERATED FILE, DO NOT EDIT
.\" INSTEAD, EDIT makerumpmanpages.sh AND REGEN
.\" from: NetBSD: makerumpmanpages.sh,v 1.12 2010/11/22 07:56:31 pooka Exp
.\"
.\" Copyright (c) 2008-2010 Antti Kantee. 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 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 THE 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.
.\"
.Dd November 21, 2010
.Dt RUMP_FDESC 8
.Os
.Sh NAME
.Nm rump_fdesc
.Nd mount a fdesc fictional fs with a userspace server
.Sh SYNOPSIS
.Cd "file-system PUFFS"
.Cd "pseudo-device putter"
.Pp
.Nm
.Op options
.Ar fdesc
.Ar mountpoint
.Sh DESCRIPTION
.Em NOTE!
This manual page describes features specific to the
.Xr rump 3
file server.
Please see
.Xr mount_fdesc 8
for a full description of the available command line options.
.Pp
The
.Nm
utility can be used to mount fdesc file systems.
It uses
.Xr rump 3
and
.Xr p2k 3
to facilitate running the file system as a server in userspace.
As opposed to
.Xr mount_fdesc 8 ,
.Nm
does not use file system code within the kernel and therefore does
not require kernel support except
.Xr puffs 4 .
Apart from a minor speed penalty there is no downside with respect to
in-kernel code.
.Pp
To use
.Nm
via
.Xr mount 8 ,
the flags
.Fl o Ar rump
and
.Fl t Ar fdesc
should be given.
Similarly,
.Nm
is used instead of
.Xr mount_fdesc 8
if
.Dq rump
is added to the options field of
.Xr fstab 5 .
.Sh SEE ALSO
.Xr p2k 3 ,
.Xr puffs 3 ,
.Xr rump 3 ,
.Xr mount_fdesc 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 6.0 .

View File

@ -0,0 +1,59 @@
/* $NetBSD: rump_fdesc.c,v 1.1 2009/07/31 19:18:46 pooka Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/types.h>
#include <sys/mount.h>
#include <miscfs/fdesc/fdesc.h>
#include <err.h>
#include <puffs.h>
#include <stdlib.h>
#include <unistd.h>
#include <rump/p2k.h>
#include "mount_fdesc.h"
int
main(int argc, char *argv[])
{
char canon_dev[MAXPATHLEN], canon_dir[MAXPATHLEN];
int mntflags;
int rv;
setprogname(argv[0]);
mount_fdesc_parseargs(argc, argv, NULL, &mntflags,
canon_dev, canon_dir);
rv = p2k_run_fs(MOUNT_FDESC, canon_dev, canon_dir, mntflags,
NULL, 0, PUFFS_KFLAG_NOCACHE_PAGE);
if (rv)
err(1, "mount");
return 0;
}

View File

@ -0,0 +1,11 @@
# $NetBSD: Makefile,v 1.5 2010/01/25 15:55:36 pooka Exp $
#
.include <bsd.own.mk>
MOUNTNAME= ffs
ISRUMP= # affirmative
RUMP_DISKFS=
.include <bsd.prog.mk>

View File

@ -0,0 +1,134 @@
.\" $NetBSD: rump_ffs.8,v 1.13 2011/07/24 09:00:06 uch Exp $
.\"
.\" WARNING: GENERATED FILE, DO NOT EDIT
.\" INSTEAD, EDIT makerumpmanpages.sh AND REGEN
.\" from: NetBSD: makerumpmanpages.sh,v 1.12 2010/11/22 07:56:31 pooka Exp
.\"
.\" Copyright (c) 2008-2010 Antti Kantee. 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 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 THE 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.
.\"
.Dd November 21, 2010
.Dt RUMP_FFS 8
.Os
.Sh NAME
.Nm rump_ffs
.Nd mount a ffs image with a userspace server
.Sh SYNOPSIS
.Cd "file-system PUFFS"
.Cd "pseudo-device putter"
.Pp
.Nm
.Op options
.Ar image
.Ar mountpoint
.Sh DESCRIPTION
.Em NOTE!
This manual page describes features specific to the
.Xr rump 3
file server.
Please see
.Xr mount_ffs 8
for a full description of the available command line options.
.Pp
The
.Nm
utility can be used to mount ffs file systems.
It uses
.Xr rump 3
and
.Xr p2k 3
to facilitate running the file system as a server in userspace.
As opposed to
.Xr mount_ffs 8 ,
.Nm
does not use file system code within the kernel and therefore does
not require kernel support except
.Xr puffs 4 .
Apart from a minor speed penalty there is no downside with respect to
in-kernel code.
.Pp
.Nm
does not require using
.Xr vnconfig 8
for mounts from regular files and the file path can be passed
directly as the
.Ar image
parameter.
In fact, the use of
.Xr vnconfig 8
is discouraged, since it is unable to properly deal with images on
sparse files.
.Pp
In case the image contains multiple partitions, the desired partition
must be indicated by appending the token
.Dq %DISKLABEL:p%
to the
.Ar image
path.
The letter
.Dq p
specifies the partition as obtained via
.Xr disklabel 8 .
For example, to mount partition
.Dq e
from image
.Pa /tmp/wd0.img ,
use
.Dq /tmp/wd0.img%DISKLABEL:e% .
.Pp
It is recommended that untrusted file system images be mounted with
.Nm
instead of
.Xr mount_ffs 8 .
Corrupt file system images commonly cause the file system
to crash the entire kernel, but with
.Nm
only the userspace server process will dump core.
.Pp
To use
.Nm
via
.Xr mount 8 ,
the flags
.Fl o Ar rump
and
.Fl t Ar ffs
should be given.
Similarly,
.Nm
is used instead of
.Xr mount_ffs 8
if
.Dq rump
is added to the options field of
.Xr fstab 5 .
.Sh SEE ALSO
.Xr p2k 3 ,
.Xr puffs 3 ,
.Xr rump 3 ,
.Xr mount_ffs 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 5.0 .

View File

@ -0,0 +1,65 @@
/* $NetBSD: rump_ffs.c,v 1.7 2010/01/12 18:43:37 pooka Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/types.h>
#include <sys/mount.h>
#include <ufs/ufs/ufsmount.h>
#include <err.h>
#include <puffs.h>
#include <stdlib.h>
#include <unistd.h>
#include <rump/p2k.h>
#include <rump/ukfs.h>
#include "mount_ffs.h"
int
main(int argc, char *argv[])
{
struct ufs_args args;
char canon_dev[UKFS_DEVICE_MAXPATHLEN], canon_dir[MAXPATHLEN];
struct ukfs_part *part;
int mntflags;
int rv;
setprogname(argv[0]);
puffs_unmountonsignal(SIGINT, true);
puffs_unmountonsignal(SIGTERM, true);
UKFS_DEVICE_ARGVPROBE(&part);
mount_ffs_parseargs(argc, argv, &args, &mntflags, canon_dev, canon_dir);
rv = p2k_run_diskfs(MOUNT_FFS, canon_dev, part, canon_dir,
mntflags, &args, sizeof(args), 0);
ukfs_part_release(part);
if (rv)
err(1, "mount");
return 0;
}

View File

@ -0,0 +1,9 @@
# $NetBSD: Makefile,v 1.4 2010/01/25 15:55:36 pooka Exp $
#
MOUNTNAME= hfs
ISRUMP= # rump roast
RUMP_DISKFS=
.include <bsd.prog.mk>

View File

@ -0,0 +1,134 @@
.\" $NetBSD: rump_hfs.8,v 1.13 2011/07/24 09:00:07 uch Exp $
.\"
.\" WARNING: GENERATED FILE, DO NOT EDIT
.\" INSTEAD, EDIT makerumpmanpages.sh AND REGEN
.\" from: NetBSD: makerumpmanpages.sh,v 1.12 2010/11/22 07:56:31 pooka Exp
.\"
.\" Copyright (c) 2008-2010 Antti Kantee. 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 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 THE 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.
.\"
.Dd November 21, 2010
.Dt RUMP_HFS 8
.Os
.Sh NAME
.Nm rump_hfs
.Nd mount a hfs image with a userspace server
.Sh SYNOPSIS
.Cd "file-system PUFFS"
.Cd "pseudo-device putter"
.Pp
.Nm
.Op options
.Ar image
.Ar mountpoint
.Sh DESCRIPTION
.Em NOTE!
This manual page describes features specific to the
.Xr rump 3
file server.
Please see
.Xr mount_hfs 8
for a full description of the available command line options.
.Pp
The
.Nm
utility can be used to mount hfs file systems.
It uses
.Xr rump 3
and
.Xr p2k 3
to facilitate running the file system as a server in userspace.
As opposed to
.Xr mount_hfs 8 ,
.Nm
does not use file system code within the kernel and therefore does
not require kernel support except
.Xr puffs 4 .
Apart from a minor speed penalty there is no downside with respect to
in-kernel code.
.Pp
.Nm
does not require using
.Xr vnconfig 8
for mounts from regular files and the file path can be passed
directly as the
.Ar image
parameter.
In fact, the use of
.Xr vnconfig 8
is discouraged, since it is unable to properly deal with images on
sparse files.
.Pp
In case the image contains multiple partitions, the desired partition
must be indicated by appending the token
.Dq %DISKLABEL:p%
to the
.Ar image
path.
The letter
.Dq p
specifies the partition as obtained via
.Xr disklabel 8 .
For example, to mount partition
.Dq e
from image
.Pa /tmp/wd0.img ,
use
.Dq /tmp/wd0.img%DISKLABEL:e% .
.Pp
It is recommended that untrusted file system images be mounted with
.Nm
instead of
.Xr mount_hfs 8 .
Corrupt file system images commonly cause the file system
to crash the entire kernel, but with
.Nm
only the userspace server process will dump core.
.Pp
To use
.Nm
via
.Xr mount 8 ,
the flags
.Fl o Ar rump
and
.Fl t Ar hfs
should be given.
Similarly,
.Nm
is used instead of
.Xr mount_hfs 8
if
.Dq rump
is added to the options field of
.Xr fstab 5 .
.Sh SEE ALSO
.Xr p2k 3 ,
.Xr puffs 3 ,
.Xr rump 3 ,
.Xr mount_hfs 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 5.0 .

View File

@ -0,0 +1,63 @@
/* $NetBSD: rump_hfs.c,v 1.6 2009/12/13 21:16:54 pooka Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/types.h>
#include <sys/mount.h>
#include <fs/hfs/hfs.h>
#include <err.h>
#include <puffs.h>
#include <stdlib.h>
#include <unistd.h>
#include <rump/p2k.h>
#include <rump/ukfs.h>
#include "mount_hfs.h"
int
main(int argc, char *argv[])
{
struct hfs_args args;
char canon_dev[UKFS_DEVICE_MAXPATHLEN], canon_dir[MAXPATHLEN];
struct ukfs_part *part;
int mntflags;
int rv;
setprogname(argv[0]);
UKFS_DEVICE_ARGVPROBE(&part);
mount_hfs_parseargs(argc, argv, &args, &mntflags, canon_dev, canon_dir);
rv = p2k_run_diskfs(MOUNT_HFS, canon_dev, part, canon_dir, mntflags,
&args, sizeof(args), 0);
ukfs_part_release(part);
if (rv)
err(1, "mount");
return 0;
}

View File

@ -0,0 +1,8 @@
# $NetBSD: Makefile,v 1.1 2010/03/31 14:22:27 pooka Exp $
#
MOUNTNAME= kernfs
ISRUMP= # syndicate
.include <bsd.prog.mk>

View File

@ -0,0 +1,96 @@
.\" $NetBSD: rump_kernfs.8,v 1.6 2011/07/24 09:00:07 uch Exp $
.\"
.\" WARNING: GENERATED FILE, DO NOT EDIT
.\" INSTEAD, EDIT makerumpmanpages.sh AND REGEN
.\" from: NetBSD: makerumpmanpages.sh,v 1.12 2010/11/22 07:56:31 pooka Exp
.\"
.\" Copyright (c) 2008-2010 Antti Kantee. 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 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 THE 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.
.\"
.Dd November 21, 2010
.Dt RUMP_KERNFS 8
.Os
.Sh NAME
.Nm rump_kernfs
.Nd mount a kernfs fictional fs with a userspace server
.Sh SYNOPSIS
.Cd "file-system PUFFS"
.Cd "pseudo-device putter"
.Pp
.Nm
.Op options
.Ar kernfs
.Ar mountpoint
.Sh DESCRIPTION
.Em NOTE!
This manual page describes features specific to the
.Xr rump 3
file server.
Please see
.Xr mount_kernfs 8
for a full description of the available command line options.
.Pp
The
.Nm
utility can be used to mount kernfs file systems.
It uses
.Xr rump 3
and
.Xr p2k 3
to facilitate running the file system as a server in userspace.
As opposed to
.Xr mount_kernfs 8 ,
.Nm
does not use file system code within the kernel and therefore does
not require kernel support except
.Xr puffs 4 .
Apart from a minor speed penalty there is no downside with respect to
in-kernel code.
.Pp
To use
.Nm
via
.Xr mount 8 ,
the flags
.Fl o Ar rump
and
.Fl t Ar kernfs
should be given.
Similarly,
.Nm
is used instead of
.Xr mount_kernfs 8
if
.Dq rump
is added to the options field of
.Xr fstab 5 .
.Sh SEE ALSO
.Xr p2k 3 ,
.Xr puffs 3 ,
.Xr rump 3 ,
.Xr mount_kernfs 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 6.0 .

View File

@ -0,0 +1,57 @@
/* $NetBSD: rump_kernfs.c,v 1.1 2010/03/31 14:22:27 pooka Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/types.h>
#include <sys/mount.h>
#include <err.h>
#include <puffs.h>
#include <stdlib.h>
#include <unistd.h>
#include <rump/p2k.h>
#include "mount_kernfs.h"
int
main(int argc, char *argv[])
{
char canon_dev[MAXPATHLEN], canon_dir[MAXPATHLEN];
int mntflags;
int rv;
setprogname(argv[0]);
mount_kernfs_parseargs(argc, argv, NULL, &mntflags,
canon_dev, canon_dir);
rv = p2k_run_fs(MOUNT_KERNFS, canon_dev, canon_dir, mntflags,
NULL, 0, PUFFS_KFLAG_NOCACHE);
if (rv)
err(1, "mount");
return 0;
}

View File

@ -0,0 +1,22 @@
# $NetBSD: Makefile,v 1.10 2014/03/04 21:06:47 joerg Exp $
#
.include <bsd.own.mk>
MOUNTNAME= lfs
LDADD+= -lrumpfs_ffs
DPADD+= ${LIBRUMPFS_FFS}
ISRUMP= # don't deny it
RUMP_DISKFS=
CPPFLAGS+= -DUSE_RUMP -DLFS_CLEANER_AS_LIB
CWARNFLAGS.clang+= -Wno-error=absolute-value
.include "../../../libexec/lfs_cleanerd/Makefile.inc"
#DBG=-g
.include <bsd.prog.mk>

View File

@ -0,0 +1,134 @@
.\" $NetBSD: rump_lfs.8,v 1.13 2011/07/24 09:00:07 uch Exp $
.\"
.\" WARNING: GENERATED FILE, DO NOT EDIT
.\" INSTEAD, EDIT makerumpmanpages.sh AND REGEN
.\" from: NetBSD: makerumpmanpages.sh,v 1.12 2010/11/22 07:56:31 pooka Exp
.\"
.\" Copyright (c) 2008-2010 Antti Kantee. 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 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 THE 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.
.\"
.Dd November 21, 2010
.Dt RUMP_LFS 8
.Os
.Sh NAME
.Nm rump_lfs
.Nd mount a lfs image with a userspace server
.Sh SYNOPSIS
.Cd "file-system PUFFS"
.Cd "pseudo-device putter"
.Pp
.Nm
.Op options
.Ar image
.Ar mountpoint
.Sh DESCRIPTION
.Em NOTE!
This manual page describes features specific to the
.Xr rump 3
file server.
Please see
.Xr mount_lfs 8
for a full description of the available command line options.
.Pp
The
.Nm
utility can be used to mount lfs file systems.
It uses
.Xr rump 3
and
.Xr p2k 3
to facilitate running the file system as a server in userspace.
As opposed to
.Xr mount_lfs 8 ,
.Nm
does not use file system code within the kernel and therefore does
not require kernel support except
.Xr puffs 4 .
Apart from a minor speed penalty there is no downside with respect to
in-kernel code.
.Pp
.Nm
does not require using
.Xr vnconfig 8
for mounts from regular files and the file path can be passed
directly as the
.Ar image
parameter.
In fact, the use of
.Xr vnconfig 8
is discouraged, since it is unable to properly deal with images on
sparse files.
.Pp
In case the image contains multiple partitions, the desired partition
must be indicated by appending the token
.Dq %DISKLABEL:p%
to the
.Ar image
path.
The letter
.Dq p
specifies the partition as obtained via
.Xr disklabel 8 .
For example, to mount partition
.Dq e
from image
.Pa /tmp/wd0.img ,
use
.Dq /tmp/wd0.img%DISKLABEL:e% .
.Pp
It is recommended that untrusted file system images be mounted with
.Nm
instead of
.Xr mount_lfs 8 .
Corrupt file system images commonly cause the file system
to crash the entire kernel, but with
.Nm
only the userspace server process will dump core.
.Pp
To use
.Nm
via
.Xr mount 8 ,
the flags
.Fl o Ar rump
and
.Fl t Ar lfs
should be given.
Similarly,
.Nm
is used instead of
.Xr mount_lfs 8
if
.Dq rump
is added to the options field of
.Xr fstab 5 .
.Sh SEE ALSO
.Xr p2k 3 ,
.Xr puffs 3 ,
.Xr rump 3 ,
.Xr mount_lfs 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 5.0 .

View File

@ -0,0 +1,130 @@
/* $NetBSD: rump_lfs.c,v 1.18 2015/08/02 18:11:57 dholland Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/types.h>
#include <sys/mount.h>
#include <ufs/ufs/ufsmount.h>
#include <err.h>
#include <pthread.h>
#include <puffs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <rump/rump.h>
#include <rump/p2k.h>
#include <rump/ukfs.h>
#include "mount_lfs.h"
static void *
cleaner(void *arg)
{
const char *the_argv[7];
the_argv[0] = "megamaid";
the_argv[1] = "-D"; /* don't fork() & detach */
the_argv[2] = arg;
lfs_cleaner_main(3, __UNCONST(the_argv));
return NULL;
}
int
main(int argc, char *argv[])
{
struct ulfs_args args;
char canon_dev[UKFS_DEVICE_MAXPATHLEN], canon_dir[MAXPATHLEN];
char rawdev[MAXPATHLEN];
struct p2k_mount *p2m;
pthread_t cleanerthread;
struct ukfs_part *part;
int mntflags;
int rv;
setprogname(argv[0]);
puffs_unmountonsignal(SIGINT, true);
puffs_unmountonsignal(SIGTERM, true);
if (argc >= 3) {
UKFS_DEVICE_ARGVPROBE(&part);
if (part != ukfs_part_none) {
errx(1, "lfs does not currently support "
"embedded partitions");
}
}
mount_lfs_parseargs(argc, argv, &args, &mntflags, canon_dev, canon_dir);
/* Reset getopt for lfs_cleaner_main. */
optreset = 1;
optind = 1;
p2m = p2k_init(0);
if (!p2m)
err(1, "init p2k");
/*
* XXX: this particular piece inspired by the cleaner code.
* obviously FIXXXME along with the cleaner.
*/
sprintf(rawdev, "/dev/r%s", canon_dev+5);
rump_pub_etfs_register(rawdev, canon_dev, RUMP_ETFS_CHR);
/*
* We basically have two choices:
* 1) run the cleaner in another process and do rump ipc syscalls
* 2) run it off a thread in this process and do rump syscalls
* as function calls.
*
* opt for "2" for now
*/
#ifdef CLEANER_TESTING
ukfs_mount(MOUNT_LFS, canon_dev, canon_dir, mntflags,
&args, sizeof(args));
cleaner(canon_dir);
#endif
if (p2k_setup_diskfs(p2m, MOUNT_LFS, canon_dev, part, canon_dir,
mntflags, &args, sizeof(args)) == -1)
err(1, "mount");
ukfs_part_release(part);
#ifndef CLEANER_TESTING
if ((mntflags & MNT_RDONLY) == 0) {
if (pthread_create(&cleanerthread, NULL,
cleaner, canon_dir) == -1)
err(1, "cannot start cleaner");
}
#endif
rv = p2k_mainloop(p2m);
if (rv == -1)
err(1, "fs service");
return 0;
}

View File

@ -0,0 +1,9 @@
# $NetBSD: Makefile,v 1.4 2010/01/25 15:55:36 pooka Exp $
#
MOUNTNAME= msdos
ISRUMP= # rump, si
RUMP_DISKFS= # si2
.include <bsd.prog.mk>

View File

@ -0,0 +1,134 @@
.\" $NetBSD: rump_msdos.8,v 1.13 2011/07/24 09:00:07 uch Exp $
.\"
.\" WARNING: GENERATED FILE, DO NOT EDIT
.\" INSTEAD, EDIT makerumpmanpages.sh AND REGEN
.\" from: NetBSD: makerumpmanpages.sh,v 1.12 2010/11/22 07:56:31 pooka Exp
.\"
.\" Copyright (c) 2008-2010 Antti Kantee. 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 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 THE 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.
.\"
.Dd November 21, 2010
.Dt RUMP_MSDOS 8
.Os
.Sh NAME
.Nm rump_msdos
.Nd mount a msdos image with a userspace server
.Sh SYNOPSIS
.Cd "file-system PUFFS"
.Cd "pseudo-device putter"
.Pp
.Nm
.Op options
.Ar image
.Ar mountpoint
.Sh DESCRIPTION
.Em NOTE!
This manual page describes features specific to the
.Xr rump 3
file server.
Please see
.Xr mount_msdos 8
for a full description of the available command line options.
.Pp
The
.Nm
utility can be used to mount msdos file systems.
It uses
.Xr rump 3
and
.Xr p2k 3
to facilitate running the file system as a server in userspace.
As opposed to
.Xr mount_msdos 8 ,
.Nm
does not use file system code within the kernel and therefore does
not require kernel support except
.Xr puffs 4 .
Apart from a minor speed penalty there is no downside with respect to
in-kernel code.
.Pp
.Nm
does not require using
.Xr vnconfig 8
for mounts from regular files and the file path can be passed
directly as the
.Ar image
parameter.
In fact, the use of
.Xr vnconfig 8
is discouraged, since it is unable to properly deal with images on
sparse files.
.Pp
In case the image contains multiple partitions, the desired partition
must be indicated by appending the token
.Dq %DISKLABEL:p%
to the
.Ar image
path.
The letter
.Dq p
specifies the partition as obtained via
.Xr disklabel 8 .
For example, to mount partition
.Dq e
from image
.Pa /tmp/wd0.img ,
use
.Dq /tmp/wd0.img%DISKLABEL:e% .
.Pp
It is recommended that untrusted file system images be mounted with
.Nm
instead of
.Xr mount_msdos 8 .
Corrupt file system images commonly cause the file system
to crash the entire kernel, but with
.Nm
only the userspace server process will dump core.
.Pp
To use
.Nm
via
.Xr mount 8 ,
the flags
.Fl o Ar rump
and
.Fl t Ar msdos
should be given.
Similarly,
.Nm
is used instead of
.Xr mount_msdos 8
if
.Dq rump
is added to the options field of
.Xr fstab 5 .
.Sh SEE ALSO
.Xr p2k 3 ,
.Xr puffs 3 ,
.Xr rump 3 ,
.Xr mount_msdos 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 5.0 .

View File

@ -0,0 +1,66 @@
/* $NetBSD: rump_msdos.c,v 1.8 2010/01/12 18:43:37 pooka Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/types.h>
#include <sys/mount.h>
#include <msdosfs/msdosfsmount.h>
#include <err.h>
#include <puffs.h>
#include <stdlib.h>
#include <unistd.h>
#include <rump/p2k.h>
#include <rump/ukfs.h>
#include "mount_msdos.h"
int
main(int argc, char *argv[])
{
struct msdosfs_args args;
char canon_dev[UKFS_DEVICE_MAXPATHLEN], canon_dir[MAXPATHLEN];
struct ukfs_part *part;
int mntflags;
int rv;
setprogname(argv[0]);
puffs_unmountonsignal(SIGINT, true);
puffs_unmountonsignal(SIGTERM, true);
UKFS_DEVICE_ARGVPROBE(&part);
mount_msdos_parseargs(argc, argv, &args, &mntflags,
canon_dev, canon_dir);
rv = p2k_run_diskfs(MOUNT_MSDOS, canon_dev, part, canon_dir, mntflags,
&args, sizeof(args), 0);
ukfs_part_release(part);
if (rv)
err(1, "mount");
return 0;
}

View File

@ -0,0 +1,14 @@
# $NetBSD: Makefile,v 1.6 2010/07/20 14:42:03 pooka Exp $
#
.include <bsd.own.mk>
MOUNTNAME= nfs
SRCS+= getnfsargs.c
LDADD+= -lrumpfs_nfs -lrumpnet -lrumpnet_sockin
ISRUMP= # gives me nightmares
#CPPFLAGS+= -DINET6 # for getnfsargs?
.include <bsd.prog.mk>

View File

@ -0,0 +1,110 @@
.\" $NetBSD: rump_nfs.8,v 1.11 2011/07/24 09:00:07 uch Exp $
.\"
.\" WARNING: GENERATED FILE, DO NOT EDIT
.\" INSTEAD, EDIT makerumpmanpages.sh AND REGEN
.\" from: NetBSD: makerumpmanpages.sh,v 1.12 2010/11/22 07:56:31 pooka Exp
.\"
.\" Copyright (c) 2008-2010 Antti Kantee. 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 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 THE 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.
.\"
.Dd November 21, 2010
.Dt RUMP_NFS 8
.Os
.Sh NAME
.Nm rump_nfs
.Nd mount a nfs share with a userspace server
.Sh SYNOPSIS
.Cd "file-system PUFFS"
.Cd "pseudo-device putter"
.Pp
.Nm
.Op options
.Ar share
.Ar mountpoint
.Sh DESCRIPTION
.Em NOTE!
This manual page describes features specific to the
.Xr rump 3
file server.
Please see
.Xr mount_nfs 8
for a full description of the available command line options.
.Pp
The
.Nm
utility can be used to mount nfs file systems.
It uses
.Xr rump 3
and
.Xr p2k 3
to facilitate running the file system as a server in userspace.
As opposed to
.Xr mount_nfs 8 ,
.Nm
does not use file system code within the kernel and therefore does
not require kernel support except
.Xr puffs 4 .
Apart from a minor speed penalty there is no downside with respect to
in-kernel code.
.Pp
Even though the
.Nm
file system client runs within a virtual rump kernel in userspace,
it uses host network services
.Pq by means of Dq rump sockin .
This means that regardless of whether using
.Nm
or
.Xr mount_nfs 8 ,
the same network configurations will be used.
Currently,
.Dq sockin
supports IPv4.
.Pp
To use
.Nm
via
.Xr mount 8 ,
the flags
.Fl o Ar rump
and
.Fl t Ar nfs
should be given.
Similarly,
.Nm
is used instead of
.Xr mount_nfs 8
if
.Dq rump
is added to the options field of
.Xr fstab 5 .
.Sh SEE ALSO
.Xr p2k 3 ,
.Xr puffs 3 ,
.Xr rump 3 ,
.Xr mount_nfs 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 5.0 .

View File

@ -0,0 +1,62 @@
/* $NetBSD: rump_nfs.c,v 1.10 2010/01/12 18:43:37 pooka Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/types.h>
#include <sys/mount.h>
#include <nfs/nfsmount.h>
#include <rump/rump.h>
#include <rump/p2k.h>
#include <err.h>
#include <puffs.h>
#include <stdlib.h>
#include <string.h>
#include "mount_nfs.h"
int
main(int argc, char *argv[])
{
struct nfs_args args;
char canon_dev[MAXPATHLEN], canon_dir[MAXPATHLEN];
int rv, mntflags;
setprogname(argv[0]);
puffs_unmountonsignal(SIGINT, true);
puffs_unmountonsignal(SIGTERM, true);
mount_nfs_parseargs(argc, argv, &args, &mntflags, canon_dev, canon_dir);
rv = p2k_run_fs(MOUNT_NFS, canon_dev, canon_dir, mntflags, &args,
sizeof(args), PUFFS_KFLAG_WTCACHE);
if (rv == -1)
err(1, "mount");
return 0;
}

View File

@ -0,0 +1,12 @@
# $NetBSD: Makefile,v 1.1 2010/03/08 12:46:33 pooka Exp $
#
PROG= rump_nqmfs
LDADD+= -lrumpfs_mfs -lrumpfs_ffs
ISRUMP= # affirmative
NOMAN= # si, signor
RUMP_DISKFS= # well, uh, yea, but there's ffs
.include <bsd.prog.mk>

View File

@ -0,0 +1,131 @@
/* $NetBSD: rump_nqmfs.c,v 1.3 2010/03/31 14:54:07 pooka Exp $ */
/*
* Copyright (c) 2010 Antti Kantee. 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 AUTHOR ``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 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.
*/
/*
* Not Quite MFS. Instead of allocating memory and creating a FFS file system
* there, mmap a file (which should contain ffs) and use that as the backend.
* You can also give a newly created image as the file ...
*/
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <ufs/ufs/ufsmount.h>
#include <err.h>
#include <mntopts.h>
#include <puffs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <rump/p2k.h>
#include <rump/ukfs.h>
const struct mntopt mopts[] = {
MOPT_STDOPTS,
MOPT_NULL,
};
static void
usage(void)
{
fprintf(stderr, "%s: [-o args] fspec mountpoint\n", getprogname());
exit(1);
}
static struct mfs_args args;
static char *mntpath, *mntfile;
static int mntflags, altflags;
int
main(int argc, char *argv[])
{
struct stat sb;
mntoptparse_t mp;
void *membase;
int ch, fd, rdonly, shared;
setprogname(argv[0]);
puffs_unmountonsignal(SIGINT, true);
puffs_unmountonsignal(SIGTERM, true);
shared = mntflags = altflags = 0;
memset(&args, 0, sizeof(args));
while ((ch = getopt(argc, argv, "o:s")) != -1) {
switch (ch) {
case 'o':
mp = getmntopts(optarg, mopts, &mntflags, &altflags);
if (mp == NULL)
err(1, "getmntopts");
freemntopts(mp);
break;
case 's':
shared = 1;
break;
default:
usage();
break;
}
}
argc -= optind;
argv += optind;
if (argc != 2)
usage();
mntfile = argv[0];
mntpath = argv[1];
rdonly = mntflags & MNT_RDONLY;
if (stat(mntfile, &sb) == -1)
err(1, "stat fspec");
if (!S_ISREG(sb.st_mode))
errx(1, "fspec must be a regular file");
fd = open(mntfile, rdonly ? O_RDONLY: O_RDWR);
if (fd == -1)
err(1, "open fspec");
membase = mmap(NULL, sb.st_size, PROT_READ | (rdonly ? 0 : PROT_WRITE),
MAP_FILE | (shared ? MAP_SHARED : MAP_PRIVATE), fd, 0);
if (membase == MAP_FAILED)
err(1, "cannot mmap fspec");
args.fspec = mntfile;
args.base = membase;
args.size = sb.st_size;
if (p2k_run_fs(MOUNT_MFS, "/swabbie", mntpath,
0, &args, sizeof(args), 0) == -1)
err(1, "p2k");
return 0;
}

View File

@ -0,0 +1,9 @@
# $NetBSD: Makefile,v 1.3 2010/01/25 15:55:37 pooka Exp $
#
MOUNTNAME= ntfs
ISRUMP= # only for you sir, only for you
RUMP_DISKFS=
.include <bsd.prog.mk>

View File

@ -0,0 +1,134 @@
.\" $NetBSD: rump_ntfs.8,v 1.13 2011/07/24 09:00:07 uch Exp $
.\"
.\" WARNING: GENERATED FILE, DO NOT EDIT
.\" INSTEAD, EDIT makerumpmanpages.sh AND REGEN
.\" from: NetBSD: makerumpmanpages.sh,v 1.12 2010/11/22 07:56:31 pooka Exp
.\"
.\" Copyright (c) 2008-2010 Antti Kantee. 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 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 THE 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.
.\"
.Dd November 21, 2010
.Dt RUMP_NTFS 8
.Os
.Sh NAME
.Nm rump_ntfs
.Nd mount a ntfs image with a userspace server
.Sh SYNOPSIS
.Cd "file-system PUFFS"
.Cd "pseudo-device putter"
.Pp
.Nm
.Op options
.Ar image
.Ar mountpoint
.Sh DESCRIPTION
.Em NOTE!
This manual page describes features specific to the
.Xr rump 3
file server.
Please see
.Xr mount_ntfs 8
for a full description of the available command line options.
.Pp
The
.Nm
utility can be used to mount ntfs file systems.
It uses
.Xr rump 3
and
.Xr p2k 3
to facilitate running the file system as a server in userspace.
As opposed to
.Xr mount_ntfs 8 ,
.Nm
does not use file system code within the kernel and therefore does
not require kernel support except
.Xr puffs 4 .
Apart from a minor speed penalty there is no downside with respect to
in-kernel code.
.Pp
.Nm
does not require using
.Xr vnconfig 8
for mounts from regular files and the file path can be passed
directly as the
.Ar image
parameter.
In fact, the use of
.Xr vnconfig 8
is discouraged, since it is unable to properly deal with images on
sparse files.
.Pp
In case the image contains multiple partitions, the desired partition
must be indicated by appending the token
.Dq %DISKLABEL:p%
to the
.Ar image
path.
The letter
.Dq p
specifies the partition as obtained via
.Xr disklabel 8 .
For example, to mount partition
.Dq e
from image
.Pa /tmp/wd0.img ,
use
.Dq /tmp/wd0.img%DISKLABEL:e% .
.Pp
It is recommended that untrusted file system images be mounted with
.Nm
instead of
.Xr mount_ntfs 8 .
Corrupt file system images commonly cause the file system
to crash the entire kernel, but with
.Nm
only the userspace server process will dump core.
.Pp
To use
.Nm
via
.Xr mount 8 ,
the flags
.Fl o Ar rump
and
.Fl t Ar ntfs
should be given.
Similarly,
.Nm
is used instead of
.Xr mount_ntfs 8
if
.Dq rump
is added to the options field of
.Xr fstab 5 .
.Sh SEE ALSO
.Xr p2k 3 ,
.Xr puffs 3 ,
.Xr rump 3 ,
.Xr mount_ntfs 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 5.0 .

View File

@ -0,0 +1,64 @@
/* $NetBSD: rump_ntfs.c,v 1.6 2009/12/13 21:16:55 pooka Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/types.h>
#include <sys/mount.h>
#include <ntfs/ntfsmount.h>
#include <err.h>
#include <puffs.h>
#include <stdlib.h>
#include <unistd.h>
#include <rump/p2k.h>
#include <rump/ukfs.h>
#include "mount_ntfs.h"
int
main(int argc, char *argv[])
{
struct ntfs_args args;
char canon_dev[UKFS_DEVICE_MAXPATHLEN], canon_dir[MAXPATHLEN];
struct ukfs_part *part;
int mntflags;
int rv;
setprogname(argv[0]);
UKFS_DEVICE_ARGVPROBE(&part);
mount_ntfs_parseargs(argc, argv, &args, &mntflags,
canon_dev, canon_dir);
rv = p2k_run_diskfs(MOUNT_NTFS, canon_dev, part, canon_dir, mntflags,
&args, sizeof(args), 0);
ukfs_part_release(part);
if (rv)
err(1, "mount");
return 0;
}

View File

@ -0,0 +1,20 @@
# $NetBSD: Makefile,v 1.7 2013/12/25 23:35:17 christos Exp $
#
SMBROOT=${.CURDIR}/../../../external/bsd/smbfs
MOUNTNAME= smbfs
SRCS+= smb_rumpops.c
PROGDPLIBS+= smb ${SMBROOT}/lib/libsmb
LDADD+= -lrumpnet_sockin -lrumpnet
LDADD+= -lrumpkern_crypto -lrumpdev_netsmb -lrumpdev
ISRUMP= # it is
.include "${SMBROOT}/Makefile.inc"
CPPFLAGS+=-I${SMBDIST}/mount_smbfs
.PATH: ${SMBDIST}/mount_smbfs
.include <bsd.prog.mk>

View File

@ -0,0 +1,110 @@
.\" $NetBSD: rump_smbfs.8,v 1.6 2011/07/24 09:00:07 uch Exp $
.\"
.\" WARNING: GENERATED FILE, DO NOT EDIT
.\" INSTEAD, EDIT makerumpmanpages.sh AND REGEN
.\" from: NetBSD: makerumpmanpages.sh,v 1.12 2010/11/22 07:56:31 pooka Exp
.\"
.\" Copyright (c) 2008-2010 Antti Kantee. 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 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 THE 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.
.\"
.Dd November 21, 2010
.Dt RUMP_SMBFS 8
.Os
.Sh NAME
.Nm rump_smbfs
.Nd mount a smbfs share with a userspace server
.Sh SYNOPSIS
.Cd "file-system PUFFS"
.Cd "pseudo-device putter"
.Pp
.Nm
.Op options
.Ar share
.Ar mountpoint
.Sh DESCRIPTION
.Em NOTE!
This manual page describes features specific to the
.Xr rump 3
file server.
Please see
.Xr mount_smbfs 8
for a full description of the available command line options.
.Pp
The
.Nm
utility can be used to mount smbfs file systems.
It uses
.Xr rump 3
and
.Xr p2k 3
to facilitate running the file system as a server in userspace.
As opposed to
.Xr mount_smbfs 8 ,
.Nm
does not use file system code within the kernel and therefore does
not require kernel support except
.Xr puffs 4 .
Apart from a minor speed penalty there is no downside with respect to
in-kernel code.
.Pp
Even though the
.Nm
file system client runs within a virtual rump kernel in userspace,
it uses host network services
.Pq by means of Dq rump sockin .
This means that regardless of whether using
.Nm
or
.Xr mount_smbfs 8 ,
the same network configurations will be used.
Currently,
.Dq sockin
supports IPv4.
.Pp
To use
.Nm
via
.Xr mount 8 ,
the flags
.Fl o Ar rump
and
.Fl t Ar smbfs
should be given.
Similarly,
.Nm
is used instead of
.Xr mount_smbfs 8
if
.Dq rump
is added to the options field of
.Xr fstab 5 .
.Sh SEE ALSO
.Xr p2k 3 ,
.Xr puffs 3 ,
.Xr rump 3 ,
.Xr mount_smbfs 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 6.0 .

View File

@ -0,0 +1,80 @@
/* $NetBSD: rump_smbfs.c,v 1.6 2010/01/12 18:43:37 pooka Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/types.h>
#include <sys/mount.h>
#include <fs/smbfs/smbfs.h>
#include <rump/rump.h>
#include <rump/p2k.h>
#include <err.h>
#include <puffs.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "mount_smbfs.h"
struct p2k_mount *docancel;
static void
pcancel(void)
{
if (docancel)
p2k_cancel(docancel, 0);
}
int
main(int argc, char *argv[])
{
struct smbfs_args args;
char canon_dev[MAXPATHLEN], canon_dir[MAXPATHLEN];
struct p2k_mount *p2m;
int mntflags;
setprogname(argv[0]);
puffs_unmountonsignal(SIGINT, true);
puffs_unmountonsignal(SIGTERM, true);
p2m = p2k_init(PUFFS_KFLAG_WTCACHE);
atexit(pcancel);
docancel = p2m;
/* XXX: this will exit upon error. therefore kludge with atexit */
mount_smbfs_parseargs(argc, argv, &args, &mntflags,
canon_dev, canon_dir);
docancel = NULL;
if (p2k_setup_fs(p2m, MOUNT_SMBFS, canon_dev, canon_dir, mntflags,
&args, sizeof(args)) == -1)
err(1, "mount");
if (p2k_mainloop(p2m) == -1)
err(1, "fs service");
return 0;
}

View File

@ -0,0 +1,52 @@
/* $NetBSD: smb_rumpops.c,v 1.1 2009/09/06 20:26:47 pooka Exp $ */
/*
* Copyright (c) 2009 The NetBSD Foundation, Inc.
* 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 <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: smb_rumpops.c,v 1.1 2009/09/06 20:26:47 pooka Exp $");
#endif /* !lint */
#include <sys/types.h>
#include <sys/socket.h>
#include <rump/rump.h>
#include <rump/rump_syscalls.h>
#include "smb_kernelops.h"
const struct smb_kernelops smb_kops = {
.ko_open = rump_sys_open,
.ko_ioctl = rump_sys_ioctl,
.ko_close = rump_sys_close,
.ko_socket = rump_sys_socket,
.ko_setsockopt = rump_sys_setsockopt,
.ko_bind = rump_sys_bind,
.ko_sendto = rump_sys_sendto,
.ko_recvfrom = rump_sys_recvfrom,
};

View File

@ -0,0 +1,13 @@
# $NetBSD: Makefile,v 1.4 2010/06/30 16:22:49 pooka Exp $
#
PROG= rump_syspuffs
LDADD+= -lrumpfs_syspuffs -lrumpdev_putter
DPADD+= ${LIBRUMPFS_SYSPUFFS}
ISRUMP= # indubitably
CPPFLAGS+= -I${.CURDIR}/../../../sys/rump/fs/lib/libsyspuffs
MAN= rump_syspuffs.8
.include <bsd.prog.mk>

View File

@ -0,0 +1,73 @@
.\" $NetBSD: rump_syspuffs.8,v 1.4 2012/11/14 23:11:27 njoly Exp $
.\"
.\" Copyright (c) 2008 Antti Kantee. 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 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 THE 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.
.\"
.Dd June 9, 2009
.Dt RUMP_SYSPUFFS 8
.Os
.Sh NAME
.Nm rump_syspuffs
.Nd mount a puffs file server with a userspace puffs loop
.Sh SYNOPSIS
.Cd "file-system PUFFS"
.Cd "pseudo-device putter"
.Pp
.Nm
.Ar "file_server"
.Ar arguments
.Sh DESCRIPTION
The
.Nm
utility can be used to mount any
.Xr puffs 3
file server so that the requests are passed through the kernel
puffs code in userspace as well.
Therefore the approximate callgraph looks a little like the following,
where k and u denote code running in the kernel space and userspace,
respectively:
puffs vfs (k) \(-> libpuffs (u) \(-> p2k (u) \(-> puffs vfs (u) \(->
libpuffs (u) \(-> file server (u).
The response path is the same, but in reverse.
.Pp
In its current state,
.Nm
is most useful as a proof of concept for file system distribution
and for developing and debugging the kernel portion of puffs.
.Sh EXAMPLES
Mount a file system with sshfs:
.Dl rump_syspuffs mount_psshfs server.address /mnt
.Pp
Mount an ntfs file system using ntfs-3g (from pkgsrc/filesystems/fuse-ntfs-3g),
set the default uid to 1323:
.Dl rump_syspuffs ntfs-3g -o uid=1323 /path/to/filesystem /mnt
.Sh SEE ALSO
.Xr p2k 3 ,
.Xr puffs 3 ,
.Xr rump 3 ,
.Xr puffs 4
.Sh HISTORY
The
.Nm
debugging utility first appeared in
.Nx 5.0 .

View File

@ -0,0 +1,155 @@
/* $NetBSD: rump_syspuffs.c,v 1.12 2011/08/31 13:32:39 joerg Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. All Rights Reserved.
*
* Development of this software was supported by the
* Research Foundation of Helsinki University of Technology
*
* 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 AUTHOR ``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 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.
*/
#include <sys/types.h>
#include <sys/mount.h>
#include <sys/socket.h>
#include <sys/syslimits.h>
#include <assert.h>
#include <err.h>
#include <paths.h>
#include <puffs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <rump/rump.h>
#include "rump_syspuffs.h"
#ifndef MOUNT_NOMAIN
#include <rump/p2k.h>
int
main(int argc, char *argv[])
{
char canon_dev[MAXPATHLEN], canon_dir[MAXPATHLEN];
struct syspuffs_args args;
int mntflags, rv;
#if 0
extern int rumpns_puffsdebug;
extern int rumpns_putterdebug;
rumpns_puffsdebug = rumpns_putterdebug = 1;
#endif
setprogname(argv[0]);
mount_syspuffs_parseargs(argc, argv, &args, &mntflags,
canon_dev, canon_dir);
rv = p2k_run_fs(MOUNT_PUFFS, canon_dev, canon_dir, mntflags,
&args.us_kargs, sizeof(args.us_kargs), args.us_pflags);
if (rv)
err(1, "mount");
return 0;
}
#endif /* MOUNT_NOMAIN */
__dead static void
usage(void)
{
errx(1, "%s: server server_parameters", getprogname());
}
void
mount_syspuffs_parseargs(int argc, char *argv[],
struct syspuffs_args *args, int *mntflags,
char *canon_dev, char *canon_dir)
{
struct puffs_kargs *kargs = &args->us_kargs;
int *pflags = &args->us_pflags;
char comfd[16];
int sv[2];
size_t len;
int rv;
if (argc < 2)
usage();
/* Create sucketpair for communication with the real file server */
if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sv) == -1)
err(1, "socketpair");
if ((rv = rump_init()) == -1)
err(1, "rump_init");
switch (fork()) {
case 0:
close(sv[1]);
snprintf(comfd, sizeof(sv[0]), "%d", sv[0]);
if (setenv("PUFFS_COMFD", comfd, 1) == -1)
err(1, "setenv");
argv++;
if (execvp(argv[0], argv) == -1)
err(1, "execvp");
/*NOTREACHED*/
case -1:
err(1, "fork");
/*NOTREACHED*/
default:
close(sv[0]);
break;
}
/* read args */
if (read(sv[1], &len, sizeof(len)) != sizeof(len))
err(1, "mp 1");
if (len > MAXPATHLEN)
err(1, "mntpath > MAXPATHLEN");
if ((size_t)read(sv[1], canon_dir, len) != len)
err(1, "mp 2");
if (read(sv[1], &len, sizeof(len)) != sizeof(len))
err(1, "fn 1");
if (len > MAXPATHLEN)
err(1, "devpath > MAXPATHLEN");
if ((size_t)read(sv[1], canon_dev, len) != len)
err(1, "fn 2");
if (read(sv[1], mntflags, sizeof(*mntflags)) != sizeof(*mntflags))
err(1, "mntflags");
if (read(sv[1], kargs, sizeof(len)) != sizeof(len)) /* unused now */
err(1, "unused len");
if (read(sv[1], kargs, sizeof(*kargs)) != sizeof(*kargs))
err(1, "puffs_args");
if (read(sv[1], pflags, sizeof(*pflags)) != sizeof(*pflags))
err(1, "pflags");
/* XXX: some adjustments */
*pflags |= PUFFS_KFLAG_NOCACHE;
*pflags &= ~PUFFS_FLAG_BUILDPATH;
rv = rump_pub_syspuffs_glueinit(sv[1], &kargs->pa_fd);
assert(rv == 0);
}

View File

@ -0,0 +1,45 @@
/* $NetBSD: rump_syspuffs.h,v 1.1 2008/09/02 21:14:32 pooka Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. 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 AUTHOR ``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 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.
*/
#ifndef _USR_SBIN_PUFFS_RUMP_SYSPUFFS_MOUNT_SYSPUFFS_H_
#define _USR_SBIN_PUFFS_RUMP_SYSPUFFS_MOUNT_SYSPUFFS_H_
#include <puffs.h>
struct syspuffs_args {
struct puffs_kargs us_kargs;
int us_pflags;
};
__BEGIN_DECLS
void mount_syspuffs_parseargs(int, char **, struct syspuffs_args *,
int *, char *, char *);
__END_DECLS
#endif /* _USR_SBIN_PUFFS_RUMP_SYSPUFFS_MOUNT_SYSPUFFS_H_ */

View File

@ -0,0 +1,8 @@
# $NetBSD: Makefile,v 1.3 2009/01/05 15:39:34 pooka Exp $
#
MOUNTNAME= sysvbfs
ISRUMP= # oui
.include <bsd.prog.mk>

View File

@ -0,0 +1,134 @@
.\" $NetBSD: rump_sysvbfs.8,v 1.13 2011/07/24 09:00:07 uch Exp $
.\"
.\" WARNING: GENERATED FILE, DO NOT EDIT
.\" INSTEAD, EDIT makerumpmanpages.sh AND REGEN
.\" from: NetBSD: makerumpmanpages.sh,v 1.12 2010/11/22 07:56:31 pooka Exp
.\"
.\" Copyright (c) 2008-2010 Antti Kantee. 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 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 THE 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.
.\"
.Dd November 21, 2010
.Dt RUMP_SYSVBFS 8
.Os
.Sh NAME
.Nm rump_sysvbfs
.Nd mount a sysvbfs image with a userspace server
.Sh SYNOPSIS
.Cd "file-system PUFFS"
.Cd "pseudo-device putter"
.Pp
.Nm
.Op options
.Ar image
.Ar mountpoint
.Sh DESCRIPTION
.Em NOTE!
This manual page describes features specific to the
.Xr rump 3
file server.
Please see
.Xr mount_sysvbfs 8
for a full description of the available command line options.
.Pp
The
.Nm
utility can be used to mount sysvbfs file systems.
It uses
.Xr rump 3
and
.Xr p2k 3
to facilitate running the file system as a server in userspace.
As opposed to
.Xr mount_sysvbfs 8 ,
.Nm
does not use file system code within the kernel and therefore does
not require kernel support except
.Xr puffs 4 .
Apart from a minor speed penalty there is no downside with respect to
in-kernel code.
.Pp
.Nm
does not require using
.Xr vnconfig 8
for mounts from regular files and the file path can be passed
directly as the
.Ar image
parameter.
In fact, the use of
.Xr vnconfig 8
is discouraged, since it is unable to properly deal with images on
sparse files.
.Pp
In case the image contains multiple partitions, the desired partition
must be indicated by appending the token
.Dq %DISKLABEL:p%
to the
.Ar image
path.
The letter
.Dq p
specifies the partition as obtained via
.Xr disklabel 8 .
For example, to mount partition
.Dq e
from image
.Pa /tmp/wd0.img ,
use
.Dq /tmp/wd0.img%DISKLABEL:e% .
.Pp
It is recommended that untrusted file system images be mounted with
.Nm
instead of
.Xr mount_sysvbfs 8 .
Corrupt file system images commonly cause the file system
to crash the entire kernel, but with
.Nm
only the userspace server process will dump core.
.Pp
To use
.Nm
via
.Xr mount 8 ,
the flags
.Fl o Ar rump
and
.Fl t Ar sysvbfs
should be given.
Similarly,
.Nm
is used instead of
.Xr mount_sysvbfs 8
if
.Dq rump
is added to the options field of
.Xr fstab 5 .
.Sh SEE ALSO
.Xr p2k 3 ,
.Xr puffs 3 ,
.Xr rump 3 ,
.Xr mount_sysvbfs 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 5.0 .

View File

@ -0,0 +1,64 @@
/* $NetBSD: rump_sysvbfs.c,v 1.5 2010/01/12 18:43:38 pooka Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/types.h>
#include <sys/mount.h>
#include <rump/p2k.h>
#include <rump/ukfs.h>
#include <err.h>
#include <puffs.h>
#include <stdlib.h>
#include <string.h>
#include "mount_sysvbfs.h"
int
main(int argc, char *argv[])
{
struct sysvbfs_args args;
char canon_dev[UKFS_DEVICE_MAXPATHLEN], canon_dir[MAXPATHLEN];
struct ukfs_part *part;
int mntflags;
int rv;
setprogname(argv[0]);
puffs_unmountonsignal(SIGINT, true);
puffs_unmountonsignal(SIGTERM, true);
UKFS_DEVICE_ARGVPROBE(&part);
mount_sysvbfs_parseargs(argc, argv, &args, &mntflags,
canon_dev, canon_dir);
rv = p2k_run_diskfs(MOUNT_SYSVBFS, canon_dev, part, canon_dir, mntflags,
&args, sizeof(args), 0);
ukfs_part_release(part);
if (rv)
err(1, "mount");
return 0;
}

View File

@ -0,0 +1,8 @@
# $NetBSD: Makefile,v 1.2 2008/08/05 20:57:46 pooka Exp $
#
MOUNTNAME= tmpfs
ISRUMP= # the cock of the walk, baby
.include <bsd.prog.mk>

View File

@ -0,0 +1,96 @@
.\" $NetBSD: rump_tmpfs.8,v 1.13 2011/07/24 09:00:08 uch Exp $
.\"
.\" WARNING: GENERATED FILE, DO NOT EDIT
.\" INSTEAD, EDIT makerumpmanpages.sh AND REGEN
.\" from: NetBSD: makerumpmanpages.sh,v 1.12 2010/11/22 07:56:31 pooka Exp
.\"
.\" Copyright (c) 2008-2010 Antti Kantee. 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 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 THE 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.
.\"
.Dd November 21, 2010
.Dt RUMP_TMPFS 8
.Os
.Sh NAME
.Nm rump_tmpfs
.Nd mount a tmpfs fictional fs with a userspace server
.Sh SYNOPSIS
.Cd "file-system PUFFS"
.Cd "pseudo-device putter"
.Pp
.Nm
.Op options
.Ar tmpfs
.Ar mountpoint
.Sh DESCRIPTION
.Em NOTE!
This manual page describes features specific to the
.Xr rump 3
file server.
Please see
.Xr mount_tmpfs 8
for a full description of the available command line options.
.Pp
The
.Nm
utility can be used to mount tmpfs file systems.
It uses
.Xr rump 3
and
.Xr p2k 3
to facilitate running the file system as a server in userspace.
As opposed to
.Xr mount_tmpfs 8 ,
.Nm
does not use file system code within the kernel and therefore does
not require kernel support except
.Xr puffs 4 .
Apart from a minor speed penalty there is no downside with respect to
in-kernel code.
.Pp
To use
.Nm
via
.Xr mount 8 ,
the flags
.Fl o Ar rump
and
.Fl t Ar tmpfs
should be given.
Similarly,
.Nm
is used instead of
.Xr mount_tmpfs 8
if
.Dq rump
is added to the options field of
.Xr fstab 5 .
.Sh SEE ALSO
.Xr p2k 3 ,
.Xr puffs 3 ,
.Xr rump 3 ,
.Xr mount_tmpfs 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 5.0 .

View File

@ -0,0 +1,71 @@
/* $NetBSD: rump_tmpfs.c,v 1.4 2009/12/17 14:06:38 pooka Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/types.h>
#include <sys/mount.h>
#include <fs/tmpfs/tmpfs_args.h>
#include <err.h>
#include <puffs.h>
#include <stdlib.h>
#include <unistd.h>
#include <rump/p2k.h>
#include "mount_tmpfs.h"
/*
* tmpfs has a slight "issue" with file content storage. Since it
* stores data in memory, we will end up using 2x the RAM for
* storage if we cache in puffs vfs. If we don't, we need to take
* the slow path from the kernel to the file server every time the
* file is accessed. It's either suck or suck. However, rump_tmpfs
* will not be used in real life, so this is hardly a release-stopping
* issue of catastrophic proportions. For now we opt for un-double
* storage (PUFFS_KFLAG_NOCACHE_PAGE).
*/
int
main(int argc, char *argv[])
{
struct tmpfs_args args;
char canon_dev[MAXPATHLEN], canon_dir[MAXPATHLEN];
int mntflags;
int rv;
setprogname(argv[0]);
mount_tmpfs_parseargs(argc, argv, &args, &mntflags,
canon_dev, canon_dir);
rv = p2k_run_fs(MOUNT_TMPFS, canon_dev, canon_dir, mntflags,
&args, sizeof(args), PUFFS_KFLAG_NOCACHE_PAGE);
if (rv)
err(1, "mount");
return 0;
}

View File

@ -0,0 +1,9 @@
# $NetBSD: Makefile,v 1.3 2010/01/25 15:55:37 pooka Exp $
#
MOUNTNAME= udf
ISRUMP= # more cowbell
RUMP_DISKFS=
.include <bsd.prog.mk>

View File

@ -0,0 +1,134 @@
.\" $NetBSD: rump_udf.8,v 1.13 2011/07/24 09:00:08 uch Exp $
.\"
.\" WARNING: GENERATED FILE, DO NOT EDIT
.\" INSTEAD, EDIT makerumpmanpages.sh AND REGEN
.\" from: NetBSD: makerumpmanpages.sh,v 1.12 2010/11/22 07:56:31 pooka Exp
.\"
.\" Copyright (c) 2008-2010 Antti Kantee. 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 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 THE 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.
.\"
.Dd November 21, 2010
.Dt RUMP_UDF 8
.Os
.Sh NAME
.Nm rump_udf
.Nd mount a udf image with a userspace server
.Sh SYNOPSIS
.Cd "file-system PUFFS"
.Cd "pseudo-device putter"
.Pp
.Nm
.Op options
.Ar image
.Ar mountpoint
.Sh DESCRIPTION
.Em NOTE!
This manual page describes features specific to the
.Xr rump 3
file server.
Please see
.Xr mount_udf 8
for a full description of the available command line options.
.Pp
The
.Nm
utility can be used to mount udf file systems.
It uses
.Xr rump 3
and
.Xr p2k 3
to facilitate running the file system as a server in userspace.
As opposed to
.Xr mount_udf 8 ,
.Nm
does not use file system code within the kernel and therefore does
not require kernel support except
.Xr puffs 4 .
Apart from a minor speed penalty there is no downside with respect to
in-kernel code.
.Pp
.Nm
does not require using
.Xr vnconfig 8
for mounts from regular files and the file path can be passed
directly as the
.Ar image
parameter.
In fact, the use of
.Xr vnconfig 8
is discouraged, since it is unable to properly deal with images on
sparse files.
.Pp
In case the image contains multiple partitions, the desired partition
must be indicated by appending the token
.Dq %DISKLABEL:p%
to the
.Ar image
path.
The letter
.Dq p
specifies the partition as obtained via
.Xr disklabel 8 .
For example, to mount partition
.Dq e
from image
.Pa /tmp/wd0.img ,
use
.Dq /tmp/wd0.img%DISKLABEL:e% .
.Pp
It is recommended that untrusted file system images be mounted with
.Nm
instead of
.Xr mount_udf 8 .
Corrupt file system images commonly cause the file system
to crash the entire kernel, but with
.Nm
only the userspace server process will dump core.
.Pp
To use
.Nm
via
.Xr mount 8 ,
the flags
.Fl o Ar rump
and
.Fl t Ar udf
should be given.
Similarly,
.Nm
is used instead of
.Xr mount_udf 8
if
.Dq rump
is added to the options field of
.Xr fstab 5 .
.Sh SEE ALSO
.Xr p2k 3 ,
.Xr puffs 3 ,
.Xr rump 3 ,
.Xr mount_udf 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 5.0 .

View File

@ -0,0 +1,65 @@
/* $NetBSD: rump_udf.c,v 1.7 2010/01/12 18:43:38 pooka Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/types.h>
#include <sys/mount.h>
#include <fs/udf/udf_mount.h>
#include <err.h>
#include <puffs.h>
#include <stdlib.h>
#include <unistd.h>
#include <rump/p2k.h>
#include <rump/ukfs.h>
#include "mount_udf.h"
int
main(int argc, char *argv[])
{
struct udf_args args;
char canon_dev[UKFS_DEVICE_MAXPATHLEN], canon_dir[MAXPATHLEN];
struct ukfs_part *part;
int mntflags;
int rv;
setprogname(argv[0]);
puffs_unmountonsignal(SIGINT, true);
puffs_unmountonsignal(SIGTERM, true);
UKFS_DEVICE_ARGVPROBE(&part);
mount_udf_parseargs(argc, argv, &args, &mntflags, canon_dev, canon_dir);
rv = p2k_run_diskfs(MOUNT_UDF, canon_dev, part, canon_dir, mntflags,
&args, sizeof(args), 0);
ukfs_part_release(part);
if (rv)
err(1, "mount");
return 0;
}

View File

@ -0,0 +1,9 @@
# $NetBSD: Makefile,v 1.2 2011/11/14 11:28:05 njoly Exp $
#
MOUNTNAME= v7fs
ISRUMP= # oui
RUMP_DISKFS=
.include <bsd.prog.mk>

View File

@ -0,0 +1,134 @@
.\" $NetBSD: rump_v7fs.8,v 1.1 2011/07/24 08:55:31 uch Exp $
.\"
.\" WARNING: GENERATED FILE, DO NOT EDIT
.\" INSTEAD, EDIT makerumpmanpages.sh AND REGEN
.\" from: NetBSD: makerumpmanpages.sh,v 1.12 2010/11/22 07:56:31 pooka Exp
.\"
.\" Copyright (c) 2008-2010 Antti Kantee. 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 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 THE 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.
.\"
.Dd November 21, 2010
.Dt RUMP_V7FS 8
.Os
.Sh NAME
.Nm rump_v7fs
.Nd mount a v7fs image with a userspace server
.Sh SYNOPSIS
.Cd "file-system PUFFS"
.Cd "pseudo-device putter"
.Pp
.Nm
.Op options
.Ar image
.Ar mountpoint
.Sh DESCRIPTION
.Em NOTE!
This manual page describes features specific to the
.Xr rump 3
file server.
Please see
.Xr mount_v7fs 8
for a full description of the available command line options.
.Pp
The
.Nm
utility can be used to mount v7fs file systems.
It uses
.Xr rump 3
and
.Xr p2k 3
to facilitate running the file system as a server in userspace.
As opposed to
.Xr mount_v7fs 8 ,
.Nm
does not use file system code within the kernel and therefore does
not require kernel support except
.Xr puffs 4 .
Apart from a minor speed penalty there is no downside with respect to
in-kernel code.
.Pp
.Nm
does not require using
.Xr vnconfig 8
for mounts from regular files and the file path can be passed
directly as the
.Ar image
parameter.
In fact, the use of
.Xr vnconfig 8
is discouraged, since it is unable to properly deal with images on
sparse files.
.Pp
In case the image contains multiple partitions, the desired partition
must be indicated by appending the token
.Dq %DISKLABEL:p%
to the
.Ar image
path.
The letter
.Dq p
specifies the partition as obtained via
.Xr disklabel 8 .
For example, to mount partition
.Dq e
from image
.Pa /tmp/wd0.img ,
use
.Dq /tmp/wd0.img%DISKLABEL:e% .
.Pp
It is recommended that untrusted file system images be mounted with
.Nm
instead of
.Xr mount_v7fs 8 .
Corrupt file system images commonly cause the file system
to crash the entire kernel, but with
.Nm
only the userspace server process will dump core.
.Pp
To use
.Nm
via
.Xr mount 8 ,
the flags
.Fl o Ar rump
and
.Fl t Ar v7fs
should be given.
Similarly,
.Nm
is used instead of
.Xr mount_v7fs 8
if
.Dq rump
is added to the options field of
.Xr fstab 5 .
.Sh SEE ALSO
.Xr p2k 3 ,
.Xr puffs 3 ,
.Xr rump 3 ,
.Xr mount_v7fs 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 6.0 .

View File

@ -0,0 +1,64 @@
/* $NetBSD: rump_v7fs.c,v 1.1 2011/07/24 08:55:31 uch Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. 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 AUTHOR ``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 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.
*/
#include <sys/types.h>
#include <sys/mount.h>
#include <rump/p2k.h>
#include <rump/ukfs.h>
#include <err.h>
#include <puffs.h>
#include <stdlib.h>
#include <string.h>
#include "mount_v7fs.h"
int
main(int argc, char *argv[])
{
struct v7fs_args args;
char canon_dev[UKFS_DEVICE_MAXPATHLEN], canon_dir[MAXPATHLEN];
struct ukfs_part *part;
int mntflags;
int rv;
setprogname(argv[0]);
puffs_unmountonsignal(SIGINT, true);
puffs_unmountonsignal(SIGTERM, true);
UKFS_DEVICE_ARGVPROBE(&part);
mount_v7fs_parseargs(argc, argv, &args, &mntflags,
canon_dev, canon_dir);
rv = p2k_run_diskfs(MOUNT_V7FS, canon_dev, part, canon_dir, mntflags,
&args, sizeof(args), 0);
ukfs_part_release(part);
if (rv)
err(1, "mount");
return 0;
}