From cfbb0c09fc97ea548f16cc8fa047461c6c662e2e Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Boric Date: Tue, 27 Dec 2016 23:36:19 +0100 Subject: [PATCH] wip import mount_sysvbfs --- distrib/sets/lists/minix-base/mi | 1 + distrib/sets/lists/minix-comp/mi | 2 + distrib/sets/lists/minix-man/mi | 1 + sbin/mount/pathadj.c | 46 + sbin/mount_sysvbfs/Makefile | 16 + sbin/mount_sysvbfs/mount_sysvbfs.8 | 80 ++ sbin/mount_sysvbfs/mount_sysvbfs.c | 157 +++ sbin/mount_sysvbfs/mount_sysvbfs.h | 37 + usr.sbin/Makefile | 2 +- usr.sbin/puffs/Makefile | 37 + usr.sbin/puffs/Makefile.inc | 58 ++ usr.sbin/puffs/makerumpmanpages.sh | 232 +++++ usr.sbin/puffs/mount_9p/Makefile | 10 + usr.sbin/puffs/mount_9p/fs.c | 236 +++++ usr.sbin/puffs/mount_9p/mount_9p.8 | 70 ++ usr.sbin/puffs/mount_9p/ninebuf.c | 338 +++++++ usr.sbin/puffs/mount_9p/nineproto.c | 365 +++++++ usr.sbin/puffs/mount_9p/nineproto.h | 93 ++ usr.sbin/puffs/mount_9p/ninepuffs.c | 231 +++++ usr.sbin/puffs/mount_9p/ninepuffs.h | 178 ++++ usr.sbin/puffs/mount_9p/node.c | 616 ++++++++++++ usr.sbin/puffs/mount_9p/subr.c | 197 ++++ usr.sbin/puffs/mount_psshfs/Makefile | 9 + usr.sbin/puffs/mount_psshfs/fs.c | 279 +++++ usr.sbin/puffs/mount_psshfs/mount_psshfs.8 | 205 ++++ usr.sbin/puffs/mount_psshfs/node.c | 949 ++++++++++++++++++ usr.sbin/puffs/mount_psshfs/psbuf.c | 590 +++++++++++ usr.sbin/puffs/mount_psshfs/psshfs.c | 501 +++++++++ usr.sbin/puffs/mount_psshfs/psshfs.h | 248 +++++ usr.sbin/puffs/mount_psshfs/sftp_proto.h | 122 +++ usr.sbin/puffs/mount_psshfs/subr.c | 548 ++++++++++ usr.sbin/puffs/mount_sysctlfs/Makefile | 16 + .../puffs/mount_sysctlfs/mount_sysctlfs.8 | 63 ++ usr.sbin/puffs/mount_sysctlfs/sysctlfs.c | 799 +++++++++++++++ usr.sbin/puffs/rump_au-naturel/Makefile | 14 + .../puffs/rump_au-naturel/rump_au-naturel.c | 66 ++ usr.sbin/puffs/rump_cd9660/Makefile | 9 + usr.sbin/puffs/rump_cd9660/rump_cd9660.8 | 134 +++ usr.sbin/puffs/rump_cd9660/rump_cd9660.c | 64 ++ usr.sbin/puffs/rump_efs/Makefile | 9 + usr.sbin/puffs/rump_efs/rump_efs.8 | 134 +++ usr.sbin/puffs/rump_efs/rump_efs.c | 63 ++ usr.sbin/puffs/rump_ext2fs/Makefile | 14 + usr.sbin/puffs/rump_ext2fs/rump_ext2fs.8 | 134 +++ usr.sbin/puffs/rump_ext2fs/rump_ext2fs.c | 66 ++ usr.sbin/puffs/rump_fdesc/Makefile | 8 + usr.sbin/puffs/rump_fdesc/rump_fdesc.8 | 96 ++ usr.sbin/puffs/rump_fdesc/rump_fdesc.c | 59 ++ usr.sbin/puffs/rump_ffs/Makefile | 11 + usr.sbin/puffs/rump_ffs/rump_ffs.8 | 134 +++ usr.sbin/puffs/rump_ffs/rump_ffs.c | 65 ++ usr.sbin/puffs/rump_hfs/Makefile | 9 + usr.sbin/puffs/rump_hfs/rump_hfs.8 | 134 +++ usr.sbin/puffs/rump_hfs/rump_hfs.c | 63 ++ usr.sbin/puffs/rump_kernfs/Makefile | 8 + usr.sbin/puffs/rump_kernfs/rump_kernfs.8 | 96 ++ usr.sbin/puffs/rump_kernfs/rump_kernfs.c | 57 ++ usr.sbin/puffs/rump_lfs/Makefile | 22 + usr.sbin/puffs/rump_lfs/rump_lfs.8 | 134 +++ usr.sbin/puffs/rump_lfs/rump_lfs.c | 130 +++ usr.sbin/puffs/rump_msdos/Makefile | 9 + usr.sbin/puffs/rump_msdos/rump_msdos.8 | 134 +++ usr.sbin/puffs/rump_msdos/rump_msdos.c | 66 ++ usr.sbin/puffs/rump_nfs/Makefile | 14 + usr.sbin/puffs/rump_nfs/rump_nfs.8 | 110 ++ usr.sbin/puffs/rump_nfs/rump_nfs.c | 62 ++ usr.sbin/puffs/rump_nqmfs/Makefile | 12 + usr.sbin/puffs/rump_nqmfs/rump_nqmfs.c | 131 +++ usr.sbin/puffs/rump_ntfs/Makefile | 9 + usr.sbin/puffs/rump_ntfs/rump_ntfs.8 | 134 +++ usr.sbin/puffs/rump_ntfs/rump_ntfs.c | 64 ++ usr.sbin/puffs/rump_smbfs/Makefile | 20 + usr.sbin/puffs/rump_smbfs/rump_smbfs.8 | 110 ++ usr.sbin/puffs/rump_smbfs/rump_smbfs.c | 80 ++ usr.sbin/puffs/rump_smbfs/smb_rumpops.c | 52 + usr.sbin/puffs/rump_syspuffs/Makefile | 13 + usr.sbin/puffs/rump_syspuffs/rump_syspuffs.8 | 73 ++ usr.sbin/puffs/rump_syspuffs/rump_syspuffs.c | 155 +++ usr.sbin/puffs/rump_syspuffs/rump_syspuffs.h | 45 + usr.sbin/puffs/rump_sysvbfs/Makefile | 8 + usr.sbin/puffs/rump_sysvbfs/rump_sysvbfs.8 | 134 +++ usr.sbin/puffs/rump_sysvbfs/rump_sysvbfs.c | 64 ++ usr.sbin/puffs/rump_tmpfs/Makefile | 8 + usr.sbin/puffs/rump_tmpfs/rump_tmpfs.8 | 96 ++ usr.sbin/puffs/rump_tmpfs/rump_tmpfs.c | 71 ++ usr.sbin/puffs/rump_udf/Makefile | 9 + usr.sbin/puffs/rump_udf/rump_udf.8 | 134 +++ usr.sbin/puffs/rump_udf/rump_udf.c | 65 ++ usr.sbin/puffs/rump_v7fs/Makefile | 9 + usr.sbin/puffs/rump_v7fs/rump_v7fs.8 | 134 +++ usr.sbin/puffs/rump_v7fs/rump_v7fs.c | 64 ++ 91 files changed, 11153 insertions(+), 1 deletion(-) create mode 100644 sbin/mount/pathadj.c create mode 100644 sbin/mount_sysvbfs/Makefile create mode 100644 sbin/mount_sysvbfs/mount_sysvbfs.8 create mode 100644 sbin/mount_sysvbfs/mount_sysvbfs.c create mode 100644 sbin/mount_sysvbfs/mount_sysvbfs.h create mode 100644 usr.sbin/puffs/Makefile create mode 100644 usr.sbin/puffs/Makefile.inc create mode 100644 usr.sbin/puffs/makerumpmanpages.sh create mode 100644 usr.sbin/puffs/mount_9p/Makefile create mode 100644 usr.sbin/puffs/mount_9p/fs.c create mode 100644 usr.sbin/puffs/mount_9p/mount_9p.8 create mode 100644 usr.sbin/puffs/mount_9p/ninebuf.c create mode 100644 usr.sbin/puffs/mount_9p/nineproto.c create mode 100644 usr.sbin/puffs/mount_9p/nineproto.h create mode 100644 usr.sbin/puffs/mount_9p/ninepuffs.c create mode 100644 usr.sbin/puffs/mount_9p/ninepuffs.h create mode 100644 usr.sbin/puffs/mount_9p/node.c create mode 100644 usr.sbin/puffs/mount_9p/subr.c create mode 100644 usr.sbin/puffs/mount_psshfs/Makefile create mode 100644 usr.sbin/puffs/mount_psshfs/fs.c create mode 100644 usr.sbin/puffs/mount_psshfs/mount_psshfs.8 create mode 100644 usr.sbin/puffs/mount_psshfs/node.c create mode 100644 usr.sbin/puffs/mount_psshfs/psbuf.c create mode 100644 usr.sbin/puffs/mount_psshfs/psshfs.c create mode 100644 usr.sbin/puffs/mount_psshfs/psshfs.h create mode 100644 usr.sbin/puffs/mount_psshfs/sftp_proto.h create mode 100644 usr.sbin/puffs/mount_psshfs/subr.c create mode 100644 usr.sbin/puffs/mount_sysctlfs/Makefile create mode 100644 usr.sbin/puffs/mount_sysctlfs/mount_sysctlfs.8 create mode 100644 usr.sbin/puffs/mount_sysctlfs/sysctlfs.c create mode 100644 usr.sbin/puffs/rump_au-naturel/Makefile create mode 100644 usr.sbin/puffs/rump_au-naturel/rump_au-naturel.c create mode 100644 usr.sbin/puffs/rump_cd9660/Makefile create mode 100644 usr.sbin/puffs/rump_cd9660/rump_cd9660.8 create mode 100644 usr.sbin/puffs/rump_cd9660/rump_cd9660.c create mode 100644 usr.sbin/puffs/rump_efs/Makefile create mode 100644 usr.sbin/puffs/rump_efs/rump_efs.8 create mode 100644 usr.sbin/puffs/rump_efs/rump_efs.c create mode 100644 usr.sbin/puffs/rump_ext2fs/Makefile create mode 100644 usr.sbin/puffs/rump_ext2fs/rump_ext2fs.8 create mode 100644 usr.sbin/puffs/rump_ext2fs/rump_ext2fs.c create mode 100644 usr.sbin/puffs/rump_fdesc/Makefile create mode 100644 usr.sbin/puffs/rump_fdesc/rump_fdesc.8 create mode 100644 usr.sbin/puffs/rump_fdesc/rump_fdesc.c create mode 100644 usr.sbin/puffs/rump_ffs/Makefile create mode 100644 usr.sbin/puffs/rump_ffs/rump_ffs.8 create mode 100644 usr.sbin/puffs/rump_ffs/rump_ffs.c create mode 100644 usr.sbin/puffs/rump_hfs/Makefile create mode 100644 usr.sbin/puffs/rump_hfs/rump_hfs.8 create mode 100644 usr.sbin/puffs/rump_hfs/rump_hfs.c create mode 100644 usr.sbin/puffs/rump_kernfs/Makefile create mode 100644 usr.sbin/puffs/rump_kernfs/rump_kernfs.8 create mode 100644 usr.sbin/puffs/rump_kernfs/rump_kernfs.c create mode 100644 usr.sbin/puffs/rump_lfs/Makefile create mode 100644 usr.sbin/puffs/rump_lfs/rump_lfs.8 create mode 100644 usr.sbin/puffs/rump_lfs/rump_lfs.c create mode 100644 usr.sbin/puffs/rump_msdos/Makefile create mode 100644 usr.sbin/puffs/rump_msdos/rump_msdos.8 create mode 100644 usr.sbin/puffs/rump_msdos/rump_msdos.c create mode 100644 usr.sbin/puffs/rump_nfs/Makefile create mode 100644 usr.sbin/puffs/rump_nfs/rump_nfs.8 create mode 100644 usr.sbin/puffs/rump_nfs/rump_nfs.c create mode 100644 usr.sbin/puffs/rump_nqmfs/Makefile create mode 100644 usr.sbin/puffs/rump_nqmfs/rump_nqmfs.c create mode 100644 usr.sbin/puffs/rump_ntfs/Makefile create mode 100644 usr.sbin/puffs/rump_ntfs/rump_ntfs.8 create mode 100644 usr.sbin/puffs/rump_ntfs/rump_ntfs.c create mode 100644 usr.sbin/puffs/rump_smbfs/Makefile create mode 100644 usr.sbin/puffs/rump_smbfs/rump_smbfs.8 create mode 100644 usr.sbin/puffs/rump_smbfs/rump_smbfs.c create mode 100644 usr.sbin/puffs/rump_smbfs/smb_rumpops.c create mode 100644 usr.sbin/puffs/rump_syspuffs/Makefile create mode 100644 usr.sbin/puffs/rump_syspuffs/rump_syspuffs.8 create mode 100644 usr.sbin/puffs/rump_syspuffs/rump_syspuffs.c create mode 100644 usr.sbin/puffs/rump_syspuffs/rump_syspuffs.h create mode 100644 usr.sbin/puffs/rump_sysvbfs/Makefile create mode 100644 usr.sbin/puffs/rump_sysvbfs/rump_sysvbfs.8 create mode 100644 usr.sbin/puffs/rump_sysvbfs/rump_sysvbfs.c create mode 100644 usr.sbin/puffs/rump_tmpfs/Makefile create mode 100644 usr.sbin/puffs/rump_tmpfs/rump_tmpfs.8 create mode 100644 usr.sbin/puffs/rump_tmpfs/rump_tmpfs.c create mode 100644 usr.sbin/puffs/rump_udf/Makefile create mode 100644 usr.sbin/puffs/rump_udf/rump_udf.8 create mode 100644 usr.sbin/puffs/rump_udf/rump_udf.c create mode 100644 usr.sbin/puffs/rump_v7fs/Makefile create mode 100644 usr.sbin/puffs/rump_v7fs/rump_v7fs.8 create mode 100644 usr.sbin/puffs/rump_v7fs/rump_v7fs.c diff --git a/distrib/sets/lists/minix-base/mi b/distrib/sets/lists/minix-base/mi index 2b3f160b3..4e6306852 100644 --- a/distrib/sets/lists/minix-base/mi +++ b/distrib/sets/lists/minix-base/mi @@ -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 diff --git a/distrib/sets/lists/minix-comp/mi b/distrib/sets/lists/minix-comp/mi index 55ce1c9b3..61273ba37 100644 --- a/distrib/sets/lists/minix-comp/mi +++ b/distrib/sets/lists/minix-comp/mi @@ -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 diff --git a/distrib/sets/lists/minix-man/mi b/distrib/sets/lists/minix-man/mi index 86f4ac1ba..7316f8bbb 100644 --- a/distrib/sets/lists/minix-man/mi +++ b/distrib/sets/lists/minix-man/mi @@ -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 diff --git a/sbin/mount/pathadj.c b/sbin/mount/pathadj.c new file mode 100644 index 000000000..f8f6e499f --- /dev/null +++ b/sbin/mount/pathadj.c @@ -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 + +#include +#include +#include + +#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); + } +} diff --git a/sbin/mount_sysvbfs/Makefile b/sbin/mount_sysvbfs/Makefile new file mode 100644 index 000000000..c21e53a8e --- /dev/null +++ b/sbin/mount_sysvbfs/Makefile @@ -0,0 +1,16 @@ +# $NetBSD: Makefile,v 1.2 2008/09/04 12:07:58 pooka Exp $ + +.include + +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 diff --git a/sbin/mount_sysvbfs/mount_sysvbfs.8 b/sbin/mount_sysvbfs/mount_sysvbfs.8 new file mode 100644 index 000000000..bfe0d03f6 --- /dev/null +++ b/sbin/mount_sysvbfs/mount_sysvbfs.8 @@ -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. diff --git a/sbin/mount_sysvbfs/mount_sysvbfs.c b/sbin/mount_sysvbfs/mount_sysvbfs.c new file mode 100644 index 000000000..327a58379 --- /dev/null +++ b/sbin/mount_sysvbfs/mount_sysvbfs.c @@ -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 +#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 +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#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 diff --git a/sbin/mount_sysvbfs/mount_sysvbfs.h b/sbin/mount_sysvbfs/mount_sysvbfs.h new file mode 100644 index 000000000..ac6c799cf --- /dev/null +++ b/sbin/mount_sysvbfs/mount_sysvbfs.h @@ -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 + +int mount_sysvbfs(int, char **); +void mount_sysvbfs_parseargs(int, char **, struct sysvbfs_args *, int *, + char *, char *); + +#endif /* _SBIN_MOUNT_SYSVBFS_MOUNT_SYSVBFS_H_ */ diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index bc9202c8a..c8ee775ab 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -44,7 +44,7 @@ SUBDIR+= rpc.yppasswdd ypbind yppoll ypserv ypset .endif .if (${MKRUMP} != "no") -#SUBDIR+= puffs +SUBDIR+= puffs .endif .if ${TOOLCHAIN_MISSING} != "no" diff --git a/usr.sbin/puffs/Makefile b/usr.sbin/puffs/Makefile new file mode 100644 index 000000000..f2e271474 --- /dev/null +++ b/usr.sbin/puffs/Makefile @@ -0,0 +1,37 @@ +# $NetBSD: Makefile,v 1.16 2011/07/24 08:55:30 uch Exp $ + +.include + +.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 diff --git a/usr.sbin/puffs/Makefile.inc b/usr.sbin/puffs/Makefile.inc new file mode 100644 index 000000000..64e3852b0 --- /dev/null +++ b/usr.sbin/puffs/Makefile.inc @@ -0,0 +1,58 @@ +# $NetBSD: Makefile.inc,v 1.14 2014/01/16 01:15:34 christos Exp $ + +WARNS?= 4 + +.include + +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 diff --git a/usr.sbin/puffs/makerumpmanpages.sh b/usr.sbin/puffs/makerumpmanpages.sh new file mode 100644 index 000000000..bedbfa863 --- /dev/null +++ b/usr.sbin/puffs/makerumpmanpages.sh @@ -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 diff --git a/usr.sbin/puffs/mount_9p/Makefile b/usr.sbin/puffs/mount_9p/Makefile new file mode 100644 index 000000000..bf01f89e7 --- /dev/null +++ b/usr.sbin/puffs/mount_9p/Makefile @@ -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 diff --git a/usr.sbin/puffs/mount_9p/fs.c b/usr.sbin/puffs/mount_9p/fs.c new file mode 100644 index 000000000..a58c8509e --- /dev/null +++ b/usr.sbin/puffs/mount_9p/fs.c @@ -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 +#ifndef lint +__RCSID("$NetBSD: fs.c,v 1.9 2011/06/22 04:03:23 mrg Exp $"); +#endif /* !lint */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/usr.sbin/puffs/mount_9p/mount_9p.8 b/usr.sbin/puffs/mount_9p/mount_9p.8 new file mode 100644 index 000000000..15a7dd36e --- /dev/null +++ b/usr.sbin/puffs/mount_9p/mount_9p.8 @@ -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. diff --git a/usr.sbin/puffs/mount_9p/ninebuf.c b/usr.sbin/puffs/mount_9p/ninebuf.c new file mode 100644 index 000000000..a9fe6879c --- /dev/null +++ b/usr.sbin/puffs/mount_9p/ninebuf.c @@ -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 +#ifndef lint +__RCSID("$NetBSD: ninebuf.c,v 1.8 2012/11/04 22:38:19 christos Exp $"); +#endif /* !lint */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#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); +} diff --git a/usr.sbin/puffs/mount_9p/nineproto.c b/usr.sbin/puffs/mount_9p/nineproto.c new file mode 100644 index 000000000..136454eef --- /dev/null +++ b/usr.sbin/puffs/mount_9p/nineproto.c @@ -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 +#ifndef lint +__RCSID("$NetBSD: nineproto.c,v 1.9 2007/11/30 19:02:38 pooka Exp $"); +#endif /* !lint */ + +#include + +#include +#include +#include +#include +#include +#include + +#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); +} diff --git a/usr.sbin/puffs/mount_9p/nineproto.h b/usr.sbin/puffs/mount_9p/nineproto.h new file mode 100644 index 000000000..8957c54c5 --- /dev/null +++ b/usr.sbin/puffs/mount_9p/nineproto.h @@ -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 + +#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_ */ diff --git a/usr.sbin/puffs/mount_9p/ninepuffs.c b/usr.sbin/puffs/mount_9p/ninepuffs.c new file mode 100644 index 000000000..e389fa552 --- /dev/null +++ b/usr.sbin/puffs/mount_9p/ninepuffs.c @@ -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 +#ifndef lint +__RCSID("$NetBSD: ninepuffs.c,v 1.24 2011/08/31 13:32:39 joerg Exp $"); +#endif /* !lint */ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/usr.sbin/puffs/mount_9p/ninepuffs.h b/usr.sbin/puffs/mount_9p/ninepuffs.h new file mode 100644 index 000000000..4d0400b4e --- /dev/null +++ b/usr.sbin/puffs/mount_9p/ninepuffs.h @@ -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 + +#include + +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_ */ diff --git a/usr.sbin/puffs/mount_9p/node.c b/usr.sbin/puffs/mount_9p/node.c new file mode 100644 index 000000000..6c06ce3e8 --- /dev/null +++ b/usr.sbin/puffs/mount_9p/node.c @@ -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 +#ifndef lint +__RCSID("$NetBSD: node.c,v 1.21 2009/01/18 10:10:47 lukem Exp $"); +#endif /* !lint */ + +#include +#include +#include +#include +#include + +#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; +} diff --git a/usr.sbin/puffs/mount_9p/subr.c b/usr.sbin/puffs/mount_9p/subr.c new file mode 100644 index 000000000..ca194be9b --- /dev/null +++ b/usr.sbin/puffs/mount_9p/subr.c @@ -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 +#ifndef lint +__RCSID("$NetBSD: subr.c,v 1.6 2007/11/30 19:02:39 pooka Exp $"); +#endif /* !lint */ + +#include + +#include +#include +#include +#include + +#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); + } +} diff --git a/usr.sbin/puffs/mount_psshfs/Makefile b/usr.sbin/puffs/mount_psshfs/Makefile new file mode 100644 index 000000000..b02c4f5d2 --- /dev/null +++ b/usr.sbin/puffs/mount_psshfs/Makefile @@ -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 diff --git a/usr.sbin/puffs/mount_psshfs/fs.c b/usr.sbin/puffs/mount_psshfs/fs.c new file mode 100644 index 000000000..2f3c7c460 --- /dev/null +++ b/usr.sbin/puffs/mount_psshfs/fs.c @@ -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 +#ifndef lint +__RCSID("$NetBSD: fs.c,v 1.24 2011/06/22 04:03:23 mrg Exp $"); +#endif /* !lint */ + +#include +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/usr.sbin/puffs/mount_psshfs/mount_psshfs.8 b/usr.sbin/puffs/mount_psshfs/mount_psshfs.8 new file mode 100644 index 000000000..4042bfd90 --- /dev/null +++ b/usr.sbin/puffs/mount_psshfs/mount_psshfs.8 @@ -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. diff --git a/usr.sbin/puffs/mount_psshfs/node.c b/usr.sbin/puffs/mount_psshfs/node.c new file mode 100644 index 000000000..03dccc846 --- /dev/null +++ b/usr.sbin/puffs/mount_psshfs/node.c @@ -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 +#ifndef lint +__RCSID("$NetBSD: node.c,v 1.64 2012/01/20 22:07:58 jakllsch Exp $"); +#endif /* !lint */ + +#include +#include +#include +#include + +#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; +} diff --git a/usr.sbin/puffs/mount_psshfs/psbuf.c b/usr.sbin/puffs/mount_psshfs/psbuf.c new file mode 100644 index 000000000..65b56b16c --- /dev/null +++ b/usr.sbin/puffs/mount_psshfs/psbuf.c @@ -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 +#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 +#include +#include +#include + +#include +#include +#include +#include +#include + +#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)); +} diff --git a/usr.sbin/puffs/mount_psshfs/psshfs.c b/usr.sbin/puffs/mount_psshfs/psshfs.c new file mode 100644 index 000000000..43e217b54 --- /dev/null +++ b/usr.sbin/puffs/mount_psshfs/psshfs.c @@ -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 +#ifndef lint +__RCSID("$NetBSD: psshfs.c,v 1.66 2012/11/04 22:46:08 christos Exp $"); +#endif /* !lint */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; + } +} diff --git a/usr.sbin/puffs/mount_psshfs/psshfs.h b/usr.sbin/puffs/mount_psshfs/psshfs.h new file mode 100644 index 000000000..4cbe3df62 --- /dev/null +++ b/usr.sbin/puffs/mount_psshfs/psshfs.h @@ -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 + +#include + +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_ */ diff --git a/usr.sbin/puffs/mount_psshfs/sftp_proto.h b/usr.sbin/puffs/mount_psshfs/sftp_proto.h new file mode 100644 index 000000000..9ec54e0a0 --- /dev/null +++ b/usr.sbin/puffs/mount_psshfs/sftp_proto.h @@ -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_ */ diff --git a/usr.sbin/puffs/mount_psshfs/subr.c b/usr.sbin/puffs/mount_psshfs/subr.c new file mode 100644 index 000000000..7c1b8db5b --- /dev/null +++ b/usr.sbin/puffs/mount_psshfs/subr.c @@ -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 +#ifndef lint +__RCSID("$NetBSD: subr.c,v 1.51 2012/11/04 22:46:08 christos Exp $"); +#endif /* !lint */ + +#include +#include +#include +#include +#include +#include +#include + +#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); +} diff --git a/usr.sbin/puffs/mount_sysctlfs/Makefile b/usr.sbin/puffs/mount_sysctlfs/Makefile new file mode 100644 index 000000000..61b247a68 --- /dev/null +++ b/usr.sbin/puffs/mount_sysctlfs/Makefile @@ -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 diff --git a/usr.sbin/puffs/mount_sysctlfs/mount_sysctlfs.8 b/usr.sbin/puffs/mount_sysctlfs/mount_sysctlfs.8 new file mode 100644 index 000000000..7e60ab297 --- /dev/null +++ b/usr.sbin/puffs/mount_sysctlfs/mount_sysctlfs.8 @@ -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. diff --git a/usr.sbin/puffs/mount_sysctlfs/sysctlfs.c b/usr.sbin/puffs/mount_sysctlfs/sysctlfs.c new file mode 100644 index 000000000..8ae9bd223 --- /dev/null +++ b/usr.sbin/puffs/mount_sysctlfs/sysctlfs.c @@ -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 +#ifndef lint +__RCSID("$NetBSD: sysctlfs.c,v 1.17 2012/11/04 22:47:21 christos Exp $"); +#endif /* !lint */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef RUMP_ACTION +#include +#include + +#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; +} diff --git a/usr.sbin/puffs/rump_au-naturel/Makefile b/usr.sbin/puffs/rump_au-naturel/Makefile new file mode 100644 index 000000000..ed2112064 --- /dev/null +++ b/usr.sbin/puffs/rump_au-naturel/Makefile @@ -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 diff --git a/usr.sbin/puffs/rump_au-naturel/rump_au-naturel.c b/usr.sbin/puffs/rump_au-naturel/rump_au-naturel.c new file mode 100644 index 000000000..b12062593 --- /dev/null +++ b/usr.sbin/puffs/rump_au-naturel/rump_au-naturel.c @@ -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 +#include + +#include +#include +#include +#include +#include + +#include + +/* 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; +} diff --git a/usr.sbin/puffs/rump_cd9660/Makefile b/usr.sbin/puffs/rump_cd9660/Makefile new file mode 100644 index 000000000..e62298060 --- /dev/null +++ b/usr.sbin/puffs/rump_cd9660/Makefile @@ -0,0 +1,9 @@ +# $NetBSD: Makefile,v 1.3 2010/01/25 15:55:36 pooka Exp $ +# + +MOUNTNAME= cd9660 + +ISRUMP= # yes +RUMP_DISKFS= + +.include diff --git a/usr.sbin/puffs/rump_cd9660/rump_cd9660.8 b/usr.sbin/puffs/rump_cd9660/rump_cd9660.8 new file mode 100644 index 000000000..ab2600dc3 --- /dev/null +++ b/usr.sbin/puffs/rump_cd9660/rump_cd9660.8 @@ -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 . diff --git a/usr.sbin/puffs/rump_cd9660/rump_cd9660.c b/usr.sbin/puffs/rump_cd9660/rump_cd9660.c new file mode 100644 index 000000000..641071a25 --- /dev/null +++ b/usr.sbin/puffs/rump_cd9660/rump_cd9660.c @@ -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 +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#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; +} diff --git a/usr.sbin/puffs/rump_efs/Makefile b/usr.sbin/puffs/rump_efs/Makefile new file mode 100644 index 000000000..8deb021ed --- /dev/null +++ b/usr.sbin/puffs/rump_efs/Makefile @@ -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 diff --git a/usr.sbin/puffs/rump_efs/rump_efs.8 b/usr.sbin/puffs/rump_efs/rump_efs.8 new file mode 100644 index 000000000..e3b5d7894 --- /dev/null +++ b/usr.sbin/puffs/rump_efs/rump_efs.8 @@ -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 . diff --git a/usr.sbin/puffs/rump_efs/rump_efs.c b/usr.sbin/puffs/rump_efs/rump_efs.c new file mode 100644 index 000000000..118a1e18a --- /dev/null +++ b/usr.sbin/puffs/rump_efs/rump_efs.c @@ -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 +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#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; +} diff --git a/usr.sbin/puffs/rump_ext2fs/Makefile b/usr.sbin/puffs/rump_ext2fs/Makefile new file mode 100644 index 000000000..a758cde52 --- /dev/null +++ b/usr.sbin/puffs/rump_ext2fs/Makefile @@ -0,0 +1,14 @@ +# $NetBSD: Makefile,v 1.6 2010/01/25 15:55:36 pooka Exp $ +# + +.include + +MOUNTNAME= ext2fs + +LDADD+= -lrumpfs_ffs +DPADD+= ${LIBRUMPFS_FFS} + +ISRUMP= # yea baby +RUMP_DISKFS= + +.include diff --git a/usr.sbin/puffs/rump_ext2fs/rump_ext2fs.8 b/usr.sbin/puffs/rump_ext2fs/rump_ext2fs.8 new file mode 100644 index 000000000..8bb749427 --- /dev/null +++ b/usr.sbin/puffs/rump_ext2fs/rump_ext2fs.8 @@ -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 . diff --git a/usr.sbin/puffs/rump_ext2fs/rump_ext2fs.c b/usr.sbin/puffs/rump_ext2fs/rump_ext2fs.c new file mode 100644 index 000000000..f62bb5fce --- /dev/null +++ b/usr.sbin/puffs/rump_ext2fs/rump_ext2fs.c @@ -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 +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#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; +} diff --git a/usr.sbin/puffs/rump_fdesc/Makefile b/usr.sbin/puffs/rump_fdesc/Makefile new file mode 100644 index 000000000..49fa17a09 --- /dev/null +++ b/usr.sbin/puffs/rump_fdesc/Makefile @@ -0,0 +1,8 @@ +# $NetBSD: Makefile,v 1.1 2009/07/31 19:18:46 pooka Exp $ +# + +MOUNTNAME= fdesc + +ISRUMP= # descualified + +.include diff --git a/usr.sbin/puffs/rump_fdesc/rump_fdesc.8 b/usr.sbin/puffs/rump_fdesc/rump_fdesc.8 new file mode 100644 index 000000000..d53c7e3cc --- /dev/null +++ b/usr.sbin/puffs/rump_fdesc/rump_fdesc.8 @@ -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 . diff --git a/usr.sbin/puffs/rump_fdesc/rump_fdesc.c b/usr.sbin/puffs/rump_fdesc/rump_fdesc.c new file mode 100644 index 000000000..53658ea45 --- /dev/null +++ b/usr.sbin/puffs/rump_fdesc/rump_fdesc.c @@ -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 +#include + +#include + +#include +#include +#include +#include + +#include + +#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; +} diff --git a/usr.sbin/puffs/rump_ffs/Makefile b/usr.sbin/puffs/rump_ffs/Makefile new file mode 100644 index 000000000..c565e1598 --- /dev/null +++ b/usr.sbin/puffs/rump_ffs/Makefile @@ -0,0 +1,11 @@ +# $NetBSD: Makefile,v 1.5 2010/01/25 15:55:36 pooka Exp $ +# + +.include + +MOUNTNAME= ffs + +ISRUMP= # affirmative +RUMP_DISKFS= + +.include diff --git a/usr.sbin/puffs/rump_ffs/rump_ffs.8 b/usr.sbin/puffs/rump_ffs/rump_ffs.8 new file mode 100644 index 000000000..2acc471ca --- /dev/null +++ b/usr.sbin/puffs/rump_ffs/rump_ffs.8 @@ -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 . diff --git a/usr.sbin/puffs/rump_ffs/rump_ffs.c b/usr.sbin/puffs/rump_ffs/rump_ffs.c new file mode 100644 index 000000000..0c9915aa2 --- /dev/null +++ b/usr.sbin/puffs/rump_ffs/rump_ffs.c @@ -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 +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#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; +} diff --git a/usr.sbin/puffs/rump_hfs/Makefile b/usr.sbin/puffs/rump_hfs/Makefile new file mode 100644 index 000000000..687e5b7dc --- /dev/null +++ b/usr.sbin/puffs/rump_hfs/Makefile @@ -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 diff --git a/usr.sbin/puffs/rump_hfs/rump_hfs.8 b/usr.sbin/puffs/rump_hfs/rump_hfs.8 new file mode 100644 index 000000000..b2bc7d57d --- /dev/null +++ b/usr.sbin/puffs/rump_hfs/rump_hfs.8 @@ -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 . diff --git a/usr.sbin/puffs/rump_hfs/rump_hfs.c b/usr.sbin/puffs/rump_hfs/rump_hfs.c new file mode 100644 index 000000000..1fd5c166e --- /dev/null +++ b/usr.sbin/puffs/rump_hfs/rump_hfs.c @@ -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 +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#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; +} diff --git a/usr.sbin/puffs/rump_kernfs/Makefile b/usr.sbin/puffs/rump_kernfs/Makefile new file mode 100644 index 000000000..f1db28961 --- /dev/null +++ b/usr.sbin/puffs/rump_kernfs/Makefile @@ -0,0 +1,8 @@ +# $NetBSD: Makefile,v 1.1 2010/03/31 14:22:27 pooka Exp $ +# + +MOUNTNAME= kernfs + +ISRUMP= # syndicate + +.include diff --git a/usr.sbin/puffs/rump_kernfs/rump_kernfs.8 b/usr.sbin/puffs/rump_kernfs/rump_kernfs.8 new file mode 100644 index 000000000..c5a39425e --- /dev/null +++ b/usr.sbin/puffs/rump_kernfs/rump_kernfs.8 @@ -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 . diff --git a/usr.sbin/puffs/rump_kernfs/rump_kernfs.c b/usr.sbin/puffs/rump_kernfs/rump_kernfs.c new file mode 100644 index 000000000..f141c6b10 --- /dev/null +++ b/usr.sbin/puffs/rump_kernfs/rump_kernfs.c @@ -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 +#include + +#include +#include +#include +#include + +#include + +#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; +} diff --git a/usr.sbin/puffs/rump_lfs/Makefile b/usr.sbin/puffs/rump_lfs/Makefile new file mode 100644 index 000000000..169b2dc5f --- /dev/null +++ b/usr.sbin/puffs/rump_lfs/Makefile @@ -0,0 +1,22 @@ +# $NetBSD: Makefile,v 1.10 2014/03/04 21:06:47 joerg Exp $ +# + +.include + +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 diff --git a/usr.sbin/puffs/rump_lfs/rump_lfs.8 b/usr.sbin/puffs/rump_lfs/rump_lfs.8 new file mode 100644 index 000000000..bc5ab0bf3 --- /dev/null +++ b/usr.sbin/puffs/rump_lfs/rump_lfs.8 @@ -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 . diff --git a/usr.sbin/puffs/rump_lfs/rump_lfs.c b/usr.sbin/puffs/rump_lfs/rump_lfs.c new file mode 100644 index 000000000..f65303731 --- /dev/null +++ b/usr.sbin/puffs/rump_lfs/rump_lfs.c @@ -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 +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#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; +} diff --git a/usr.sbin/puffs/rump_msdos/Makefile b/usr.sbin/puffs/rump_msdos/Makefile new file mode 100644 index 000000000..457b8bd3d --- /dev/null +++ b/usr.sbin/puffs/rump_msdos/Makefile @@ -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 diff --git a/usr.sbin/puffs/rump_msdos/rump_msdos.8 b/usr.sbin/puffs/rump_msdos/rump_msdos.8 new file mode 100644 index 000000000..bff1db65a --- /dev/null +++ b/usr.sbin/puffs/rump_msdos/rump_msdos.8 @@ -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 . diff --git a/usr.sbin/puffs/rump_msdos/rump_msdos.c b/usr.sbin/puffs/rump_msdos/rump_msdos.c new file mode 100644 index 000000000..0bd451433 --- /dev/null +++ b/usr.sbin/puffs/rump_msdos/rump_msdos.c @@ -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 +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#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; +} diff --git a/usr.sbin/puffs/rump_nfs/Makefile b/usr.sbin/puffs/rump_nfs/Makefile new file mode 100644 index 000000000..bada4d2c5 --- /dev/null +++ b/usr.sbin/puffs/rump_nfs/Makefile @@ -0,0 +1,14 @@ +# $NetBSD: Makefile,v 1.6 2010/07/20 14:42:03 pooka Exp $ +# + +.include + +MOUNTNAME= nfs + +SRCS+= getnfsargs.c +LDADD+= -lrumpfs_nfs -lrumpnet -lrumpnet_sockin + +ISRUMP= # gives me nightmares +#CPPFLAGS+= -DINET6 # for getnfsargs? + +.include diff --git a/usr.sbin/puffs/rump_nfs/rump_nfs.8 b/usr.sbin/puffs/rump_nfs/rump_nfs.8 new file mode 100644 index 000000000..92ab3663d --- /dev/null +++ b/usr.sbin/puffs/rump_nfs/rump_nfs.8 @@ -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 . diff --git a/usr.sbin/puffs/rump_nfs/rump_nfs.c b/usr.sbin/puffs/rump_nfs/rump_nfs.c new file mode 100644 index 000000000..57b0ebfe2 --- /dev/null +++ b/usr.sbin/puffs/rump_nfs/rump_nfs.c @@ -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 +#include + +#include + +#include +#include + +#include +#include +#include +#include + +#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; +} diff --git a/usr.sbin/puffs/rump_nqmfs/Makefile b/usr.sbin/puffs/rump_nqmfs/Makefile new file mode 100644 index 000000000..5102ed6a9 --- /dev/null +++ b/usr.sbin/puffs/rump_nqmfs/Makefile @@ -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 diff --git a/usr.sbin/puffs/rump_nqmfs/rump_nqmfs.c b/usr.sbin/puffs/rump_nqmfs/rump_nqmfs.c new file mode 100644 index 000000000..9f20b3789 --- /dev/null +++ b/usr.sbin/puffs/rump_nqmfs/rump_nqmfs.c @@ -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 +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +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; +} diff --git a/usr.sbin/puffs/rump_ntfs/Makefile b/usr.sbin/puffs/rump_ntfs/Makefile new file mode 100644 index 000000000..70751a3d8 --- /dev/null +++ b/usr.sbin/puffs/rump_ntfs/Makefile @@ -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 diff --git a/usr.sbin/puffs/rump_ntfs/rump_ntfs.8 b/usr.sbin/puffs/rump_ntfs/rump_ntfs.8 new file mode 100644 index 000000000..814b4e71e --- /dev/null +++ b/usr.sbin/puffs/rump_ntfs/rump_ntfs.8 @@ -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 . diff --git a/usr.sbin/puffs/rump_ntfs/rump_ntfs.c b/usr.sbin/puffs/rump_ntfs/rump_ntfs.c new file mode 100644 index 000000000..11df06880 --- /dev/null +++ b/usr.sbin/puffs/rump_ntfs/rump_ntfs.c @@ -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 +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#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; +} diff --git a/usr.sbin/puffs/rump_smbfs/Makefile b/usr.sbin/puffs/rump_smbfs/Makefile new file mode 100644 index 000000000..0e4723620 --- /dev/null +++ b/usr.sbin/puffs/rump_smbfs/Makefile @@ -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 diff --git a/usr.sbin/puffs/rump_smbfs/rump_smbfs.8 b/usr.sbin/puffs/rump_smbfs/rump_smbfs.8 new file mode 100644 index 000000000..1193ba666 --- /dev/null +++ b/usr.sbin/puffs/rump_smbfs/rump_smbfs.8 @@ -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 . diff --git a/usr.sbin/puffs/rump_smbfs/rump_smbfs.c b/usr.sbin/puffs/rump_smbfs/rump_smbfs.c new file mode 100644 index 000000000..aec622a7f --- /dev/null +++ b/usr.sbin/puffs/rump_smbfs/rump_smbfs.c @@ -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 +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#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; +} diff --git a/usr.sbin/puffs/rump_smbfs/smb_rumpops.c b/usr.sbin/puffs/rump_smbfs/smb_rumpops.c new file mode 100644 index 000000000..c71ccb5b8 --- /dev/null +++ b/usr.sbin/puffs/rump_smbfs/smb_rumpops.c @@ -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 +#ifndef lint +__RCSID("$NetBSD: smb_rumpops.c,v 1.1 2009/09/06 20:26:47 pooka Exp $"); +#endif /* !lint */ + +#include +#include + +#include +#include + +#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, +}; diff --git a/usr.sbin/puffs/rump_syspuffs/Makefile b/usr.sbin/puffs/rump_syspuffs/Makefile new file mode 100644 index 000000000..0345c4bf5 --- /dev/null +++ b/usr.sbin/puffs/rump_syspuffs/Makefile @@ -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 diff --git a/usr.sbin/puffs/rump_syspuffs/rump_syspuffs.8 b/usr.sbin/puffs/rump_syspuffs/rump_syspuffs.8 new file mode 100644 index 000000000..8787f333d --- /dev/null +++ b/usr.sbin/puffs/rump_syspuffs/rump_syspuffs.8 @@ -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 . diff --git a/usr.sbin/puffs/rump_syspuffs/rump_syspuffs.c b/usr.sbin/puffs/rump_syspuffs/rump_syspuffs.c new file mode 100644 index 000000000..2a34f21a3 --- /dev/null +++ b/usr.sbin/puffs/rump_syspuffs/rump_syspuffs.c @@ -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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "rump_syspuffs.h" + +#ifndef MOUNT_NOMAIN +#include + +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); +} diff --git a/usr.sbin/puffs/rump_syspuffs/rump_syspuffs.h b/usr.sbin/puffs/rump_syspuffs/rump_syspuffs.h new file mode 100644 index 000000000..410ba4aef --- /dev/null +++ b/usr.sbin/puffs/rump_syspuffs/rump_syspuffs.h @@ -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 + +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_ */ diff --git a/usr.sbin/puffs/rump_sysvbfs/Makefile b/usr.sbin/puffs/rump_sysvbfs/Makefile new file mode 100644 index 000000000..e6eb88493 --- /dev/null +++ b/usr.sbin/puffs/rump_sysvbfs/Makefile @@ -0,0 +1,8 @@ +# $NetBSD: Makefile,v 1.3 2009/01/05 15:39:34 pooka Exp $ +# + +MOUNTNAME= sysvbfs + +ISRUMP= # oui + +.include diff --git a/usr.sbin/puffs/rump_sysvbfs/rump_sysvbfs.8 b/usr.sbin/puffs/rump_sysvbfs/rump_sysvbfs.8 new file mode 100644 index 000000000..faed96907 --- /dev/null +++ b/usr.sbin/puffs/rump_sysvbfs/rump_sysvbfs.8 @@ -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 . diff --git a/usr.sbin/puffs/rump_sysvbfs/rump_sysvbfs.c b/usr.sbin/puffs/rump_sysvbfs/rump_sysvbfs.c new file mode 100644 index 000000000..19c9f3738 --- /dev/null +++ b/usr.sbin/puffs/rump_sysvbfs/rump_sysvbfs.c @@ -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 +#include + +#include +#include + +#include +#include +#include +#include + +#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; +} diff --git a/usr.sbin/puffs/rump_tmpfs/Makefile b/usr.sbin/puffs/rump_tmpfs/Makefile new file mode 100644 index 000000000..10d190a14 --- /dev/null +++ b/usr.sbin/puffs/rump_tmpfs/Makefile @@ -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 diff --git a/usr.sbin/puffs/rump_tmpfs/rump_tmpfs.8 b/usr.sbin/puffs/rump_tmpfs/rump_tmpfs.8 new file mode 100644 index 000000000..55a7471aa --- /dev/null +++ b/usr.sbin/puffs/rump_tmpfs/rump_tmpfs.8 @@ -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 . diff --git a/usr.sbin/puffs/rump_tmpfs/rump_tmpfs.c b/usr.sbin/puffs/rump_tmpfs/rump_tmpfs.c new file mode 100644 index 000000000..4356eac1e --- /dev/null +++ b/usr.sbin/puffs/rump_tmpfs/rump_tmpfs.c @@ -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 +#include + +#include + +#include +#include +#include +#include + +#include + +#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; +} diff --git a/usr.sbin/puffs/rump_udf/Makefile b/usr.sbin/puffs/rump_udf/Makefile new file mode 100644 index 000000000..c50e340cb --- /dev/null +++ b/usr.sbin/puffs/rump_udf/Makefile @@ -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 diff --git a/usr.sbin/puffs/rump_udf/rump_udf.8 b/usr.sbin/puffs/rump_udf/rump_udf.8 new file mode 100644 index 000000000..13b390b45 --- /dev/null +++ b/usr.sbin/puffs/rump_udf/rump_udf.8 @@ -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 . diff --git a/usr.sbin/puffs/rump_udf/rump_udf.c b/usr.sbin/puffs/rump_udf/rump_udf.c new file mode 100644 index 000000000..dfd546b2e --- /dev/null +++ b/usr.sbin/puffs/rump_udf/rump_udf.c @@ -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 +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#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; +} diff --git a/usr.sbin/puffs/rump_v7fs/Makefile b/usr.sbin/puffs/rump_v7fs/Makefile new file mode 100644 index 000000000..086b5e4a7 --- /dev/null +++ b/usr.sbin/puffs/rump_v7fs/Makefile @@ -0,0 +1,9 @@ +# $NetBSD: Makefile,v 1.2 2011/11/14 11:28:05 njoly Exp $ +# + +MOUNTNAME= v7fs + +ISRUMP= # oui +RUMP_DISKFS= + +.include diff --git a/usr.sbin/puffs/rump_v7fs/rump_v7fs.8 b/usr.sbin/puffs/rump_v7fs/rump_v7fs.8 new file mode 100644 index 000000000..becacd9ff --- /dev/null +++ b/usr.sbin/puffs/rump_v7fs/rump_v7fs.8 @@ -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 . diff --git a/usr.sbin/puffs/rump_v7fs/rump_v7fs.c b/usr.sbin/puffs/rump_v7fs/rump_v7fs.c new file mode 100644 index 000000000..86caaa6a9 --- /dev/null +++ b/usr.sbin/puffs/rump_v7fs/rump_v7fs.c @@ -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 +#include + +#include +#include + +#include +#include +#include +#include + +#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; +}