Commit 6d9daf7d authored by Jakub Wojciech Klama's avatar Jakub Wojciech Klama
Browse files

Import lib9p 7ddb1164407da19b9b1afb83df83ae65a71a9a66.

Approved by:	trasz (mentor)
MFC after:	1 month
Sponsored by:	Conclusive Engineering
parents
# Object files
*.o
*.ko
*.obj
*.elf
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
/build/
*.po
*.pico
*.depend
Copyright 2016 Jakub Klama <jceel@FreeBSD.org>
All rights reserved
Redistribution and use in source and binary forms, with or without
modification, are permitted providing 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 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.
Some parts of the code are based on libixp (http://libs.suckless.org/libixp)
library code released under following license:
© 2005-2006 Anselm R. Garbe <garbeam@gmail.com>
© 2006-2010 Kris Maglione <maglione.k at Gmail>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
CC_VERSION := $(shell $(CC) --version | \
sed -n -e '/clang-/s/.*clang-\([0-9][0-9]*\).*/\1/p')
ifeq ($(CC_VERSION),)
# probably not clang
CC_VERSION := 0
endif
WFLAGS :=
# Warnings are version-dependent, unfortunately,
# so test for version before adding a -W flag.
# Note: gnu make requires $(shell test ...) for "a > b" type tests.
ifeq ($(shell test $(CC_VERSION) -gt 0; echo $$?),0)
WFLAGS += -Weverything
WFLAGS += -Wno-padded
WFLAGS += -Wno-gnu-zero-variadic-macro-arguments
WFLAGS += -Wno-format-nonliteral
WFLAGS += -Wno-unused-macros
WFLAGS += -Wno-disabled-macro-expansion
WFLAGS += -Werror
endif
ifeq ($(shell test $(CC_VERSION) -gt 600; echo $$?),0)
WFLAGS += -Wno-reserved-id-macro
endif
CFLAGS := $(WFLAGS) \
-g \
-O0 \
-DL9P_DEBUG=L9P_DEBUG
# Note: to turn on debug, use -DL9P_DEBUG=L9P_DEBUG,
# and set env variable LIB9P_LOGGING to stderr or to
# the (preferably full path name of) the debug log file.
LIB_SRCS := \
pack.c \
connection.c \
request.c \
genacl.c \
log.c \
hashtable.c \
utils.c \
rfuncs.c \
threadpool.c \
sbuf/sbuf.c \
transport/socket.c \
backend/fs.c
SERVER_SRCS := \
example/server.c
BUILD_DIR := build
LIB_OBJS := $(addprefix build/,$(LIB_SRCS:.c=.o))
SERVER_OBJS := $(SERVER_SRCS:.c=.o)
LIB := lib9p.dylib
SERVER := server
all: build $(LIB) $(SERVER)
$(LIB): $(LIB_OBJS)
cc -dynamiclib $^ -o build/$@
$(SERVER): $(SERVER_OBJS) $(LIB)
cc $< -o build/$(SERVER) -Lbuild/ -l9p
clean:
rm -rf build
rm -f $(SERVER_OBJS)
build:
mkdir build
mkdir build/sbuf
mkdir build/transport
mkdir build/backend
build/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
# Note: to turn on debug, use -DL9P_DEBUG=L9P_DEBUG,
# and set env variable LIB9P_LOGGING to stderr or to
# the (preferably full path name of) the debug log file.
LIB= 9p
SHLIB_MAJOR= 1
SRCS= pack.c \
connection.c \
request.c log.c \
hashtable.c \
genacl.c \
utils.c \
rfuncs.c \
threadpool.c \
transport/socket.c \
backend/fs.c
INCS= lib9p.h
CC= clang
CFLAGS= -g -O0 -DL9P_DEBUG=L9P_DEBUG -DWITH_CASPER
LIBADD= sbuf libcasper libcap_pwd libcap_grp
SUBDIR= example
cscope: .PHONY
cd ${.CURDIR}; cscope -buq $$(find . -name '*.[ch]' -print)
.include <bsd.lib.mk>
# lib9p
lib9p is a server library implementing 9p2000, 9p2000.u and 9p2000.L revisions
of 9P protocol. It is being developed primarily as a backend for virtio-9p in
BHyVe, the FreeBSD hypervisor.
# Features
* 9p2000, 9p2000.u and 9p2000.L protocol support
* Built-in TCP transport
# Supported operating systems
* FreeBSD (>=10)
* macOS (>=10.9)
# Authors
* Jakub Klama [jceel](https://github.com/jceel)
* Chris Torek [chris3torek](https://github.com/chris3torek)
#ifndef _APPLE_ENDIAN_H
#define _APPLE_ENDIAN_H
/*
* Shims to make Apple's endian headers and macros compatible
* with <sys/endian.h> (which is awful).
*/
# include <libkern/OSByteOrder.h>
# define _LITTLE_ENDIAN 0x12345678
# define _BIG_ENDIAN 0x87654321
# ifdef __LITTLE_ENDIAN__
# define _BYTE_ORDER _LITTLE_ENDIAN
# endif
# ifdef __BIG_ENDIAN__
# define _BYTE_ORDER _BIG_ENDIAN
# endif
# define htole32(x) OSSwapHostToLittleInt32(x)
# define le32toh(x) OSSwapLittleToHostInt32(x)
# define htobe32(x) OSSwapHostToBigInt32(x)
# define be32toh(x) OSSwapBigToHostInt32(x)
#endif /* _APPLE_ENDIAN_H */
/*
* Copyright 2016 Jakub Klama <jceel@FreeBSD.org>
* All rights reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted providing 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 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 LIB9P_BACKEND_H
#define LIB9P_BACKEND_H
struct l9p_backend {
void *softc;
void (*freefid)(void *, struct l9p_fid *);
int (*attach)(void *, struct l9p_request *);
int (*clunk)(void *, struct l9p_fid *);
int (*create)(void *, struct l9p_request *);
int (*open)(void *, struct l9p_request *);
int (*read)(void *, struct l9p_request *);
int (*remove)(void *, struct l9p_fid *);
int (*stat)(void *, struct l9p_request *);
int (*walk)(void *, struct l9p_request *);
int (*write)(void *, struct l9p_request *);
int (*wstat)(void *, struct l9p_request *);
int (*statfs)(void *, struct l9p_request *);
int (*lopen)(void *, struct l9p_request *);
int (*lcreate)(void *, struct l9p_request *);
int (*symlink)(void *, struct l9p_request *);
int (*mknod)(void *, struct l9p_request *);
int (*rename)(void *, struct l9p_request *);
int (*readlink)(void *, struct l9p_request *);
int (*getattr)(void *, struct l9p_request *);
int (*setattr)(void *, struct l9p_request *);
int (*xattrwalk)(void *, struct l9p_request *);
int (*xattrcreate)(void *, struct l9p_request *);
int (*xattrread)(void *, struct l9p_request *);
int (*xattrwrite)(void *, struct l9p_request *);
int (*xattrclunk)(void *, struct l9p_fid *);
int (*readdir)(void *, struct l9p_request *);
int (*fsync)(void *, struct l9p_request *);
int (*lock)(void *, struct l9p_request *);
int (*getlock)(void *, struct l9p_request *);
int (*link)(void *, struct l9p_request *);
int (*mkdir)(void *, struct l9p_request *);
int (*renameat)(void *, struct l9p_request *);
int (*unlinkat)(void *, struct l9p_request *);
};
#endif /* LIB9P_BACKEND_H */
This diff is collapsed.
/*
* Copyright 2016 Chris Torek <torek@ixsystems.com>
* All rights reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted providing 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 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 LIB9P_BACKEND_FS_H
#define LIB9P_BACKEND_FS_H
#include <stdbool.h>
#include "backend.h"
int l9p_backend_fs_init(struct l9p_backend **backendp, int rootfd, bool ro);
#endif /* LIB9P_BACKEND_FS_H */
/*
* Copyright 2016 Jakub Klama <jceel@FreeBSD.org>
* All rights reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted providing 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 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 <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <sys/queue.h>
#include "lib9p.h"
#include "lib9p_impl.h"
#include "fid.h"
#include "hashtable.h"
#include "log.h"
#include "threadpool.h"
#include "backend/backend.h"
int
l9p_server_init(struct l9p_server **serverp, struct l9p_backend *backend)
{
struct l9p_server *server;
server = l9p_calloc(1, sizeof (*server));
server->ls_max_version = L9P_2000L;
server->ls_backend = backend;
LIST_INIT(&server->ls_conns);
*serverp = server;
return (0);
}
int
l9p_connection_init(struct l9p_server *server, struct l9p_connection **conn)
{
struct l9p_connection *newconn;
assert(server != NULL);
assert(conn != NULL);
newconn = calloc(1, sizeof (*newconn));
if (newconn == NULL)
return (-1);
newconn->lc_server = server;
newconn->lc_msize = L9P_DEFAULT_MSIZE;
if (l9p_threadpool_init(&newconn->lc_tp, L9P_NUMTHREADS)) {
free(newconn);
return (-1);
}
ht_init(&newconn->lc_files, 100);
ht_init(&newconn->lc_requests, 100);
LIST_INSERT_HEAD(&server->ls_conns, newconn, lc_link);
*conn = newconn;
return (0);
}
void
l9p_connection_free(struct l9p_connection *conn)
{
LIST_REMOVE(conn, lc_link);
free(conn);
}
void
l9p_connection_recv(struct l9p_connection *conn, const struct iovec *iov,
const size_t niov, void *aux)
{
struct l9p_request *req;
int error;
req = l9p_calloc(1, sizeof (struct l9p_request));
req->lr_aux = aux;
req->lr_conn = conn;
req->lr_req_msg.lm_mode = L9P_UNPACK;
req->lr_req_msg.lm_niov = niov;
memcpy(req->lr_req_msg.lm_iov, iov, sizeof (struct iovec) * niov);
req->lr_resp_msg.lm_mode = L9P_PACK;
if (l9p_pufcall(&req->lr_req_msg, &req->lr_req, conn->lc_version) != 0) {
L9P_LOG(L9P_WARNING, "cannot unpack received message");
l9p_freefcall(&req->lr_req);
free(req);
return;
}
if (ht_add(&conn->lc_requests, req->lr_req.hdr.tag, req)) {
L9P_LOG(L9P_WARNING, "client reusing outstanding tag %d",
req->lr_req.hdr.tag);
l9p_freefcall(&req->lr_req);
free(req);
return;
}
error = conn->lc_lt.lt_get_response_buffer(req,
req->lr_resp_msg.lm_iov,
&req->lr_resp_msg.lm_niov,
conn->lc_lt.lt_aux);
if (error) {
L9P_LOG(L9P_WARNING, "cannot obtain buffers for response");
ht_remove(&conn->lc_requests, req->lr_req.hdr.tag);
l9p_freefcall(&req->lr_req);
free(req);
return;
}
/*
* NB: it's up to l9p_threadpool_run to decide whether
* to queue the work or to run it immediately and wait
* (it must do the latter for Tflush requests).
*/
l9p_threadpool_run(&conn->lc_tp, req);
}
void
l9p_connection_close(struct l9p_connection *conn)
{
struct ht_iter iter;
struct l9p_fid *fid;
struct l9p_request *req;
L9P_LOG(L9P_DEBUG, "waiting for thread pool to shut down");
l9p_threadpool_shutdown(&conn->lc_tp);
/* Drain pending requests (if any) */
L9P_LOG(L9P_DEBUG, "draining pending requests");
ht_iter(&conn->lc_requests, &iter);
while ((req = ht_next(&iter)) != NULL) {
#ifdef notyet
/* XXX would be good to know if there is anyone listening */
if (anyone listening) {
/* XXX crude - ops like Tclunk should succeed */
req->lr_error = EINTR;
l9p_respond(req, false, false);
} else
#endif
l9p_respond(req, true, false); /* use no-answer path */
ht_remove_at_iter(&iter);
}
/* Close opened files (if any) */
L9P_LOG(L9P_DEBUG, "closing opened files");
ht_iter(&conn->lc_files, &iter);
while ((fid = ht_next(&iter)) != NULL) {
conn->lc_server->ls_backend->freefid(
conn->lc_server->ls_backend->softc, fid);
free(fid);
ht_remove_at_iter(&iter);
}
ht_destroy(&conn->lc_requests);
ht_destroy(&conn->lc_files);
}
struct l9p_fid *
l9p_connection_alloc_fid(struct l9p_connection *conn, uint32_t fid)
{
struct l9p_fid *file;
file = l9p_calloc(1, sizeof (struct l9p_fid));
file->lo_fid = fid;
/*
* Note that the new fid is not marked valid yet.
* The insert here will fail if the fid number is
* in use, otherwise we have an invalid fid in the
* table (as desired).
*/
if (ht_add(&conn->lc_files, fid, file) != 0) {
free(file);
return (NULL);
}
return (file);
}
void
l9p_connection_remove_fid(struct l9p_connection *conn, struct l9p_fid *fid)
{
struct l9p_backend *be;
/* fid should be marked invalid by this point */
assert(!l9p_fid_isvalid(fid));
be = conn->lc_server->ls_backend;
be->freefid(be->softc, fid);
ht_remove(&conn->lc_files, fid->lo_fid);
free(fid);
}
PROG= server
SRCS= server.c
MAN=
CFLAGS= -pthread -g -O0
LDFLAGS=-L..
LDADD= -lsbuf -l9p -lcasper -lcap_pwd -lcap_grp
.include <bsd.prog.mk>
/*
* Copyright 2016 Jakub Klama <jceel@FreeBSD.org>
* All rights reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted providing 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 BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <err.h>
#include <unistd.h>
#include "../lib9p.h"
#include "../backend/fs.h"
#include "../transport/socket.h"
int
main(int argc, char **argv)
{
struct l9p_backend *fs_backend;
struct l9p_server *server;
char *host = "0.0.0.0";
char *port = "564";
char *path;
bool ro = false;
int rootfd;
int opt;
while ((opt = getopt(argc, argv, "h:p:r")) != -1) {
switch (opt) {
case 'h':
host = optarg;
break;
case 'p':