Rework code significantly.
- Use vectored I/O everywhere - Add routines to pretty-print 9P requests - Improve code style - Implement clunk request and so on.
This commit is contained in:
parent
080c92c18f
commit
91ad441d73
11 changed files with 729 additions and 280 deletions
4
Makefile
4
Makefile
|
@ -1,7 +1,9 @@
|
|||
LIB= 9p
|
||||
SHLIB_MAJOR= 1
|
||||
SRCS= lib9p.c connection.c request.c log.c transport/socket.c backend/fs.c
|
||||
SRCS= pack.c connection.c request.c log.c utils.c transport/socket.c backend/fs.c
|
||||
INCS= lib9p.h fcall.h log.h backend/fs.h
|
||||
CFLAGS= -g -O0
|
||||
|
||||
LIBADD= sbuf
|
||||
|
||||
.include <bsd.lib.mk>
|
||||
|
|
63
backend/fs.c
63
backend/fs.c
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
@ -53,6 +54,7 @@ static void fs_wstat(void *, struct l9p_request *);
|
|||
struct fs_softc
|
||||
{
|
||||
const char *fs_rootpath;
|
||||
bool fs_readonly;
|
||||
};
|
||||
|
||||
struct openfile
|
||||
|
@ -67,7 +69,7 @@ open_fid(const char *path)
|
|||
{
|
||||
struct openfile *ret;
|
||||
|
||||
ret = malloc(sizeof(*ret));
|
||||
ret = calloc(1, sizeof(*ret));
|
||||
ret->fd = -1;
|
||||
ret->name = strdup(path);
|
||||
return (ret);
|
||||
|
@ -79,7 +81,7 @@ dostat(struct l9p_stat *s, char *name, struct stat *buf)
|
|||
char *user = getenv("USER");
|
||||
s->type = 0;
|
||||
s->dev = 0;
|
||||
s->qid.type = buf->st_mode&S_IFMT;
|
||||
s->qid.type = buf->st_mode&S_IFMT >> 8;
|
||||
s->qid.path = buf->st_ino;
|
||||
s->qid.version = 0;
|
||||
s->mode = buf->st_mode & 0777;
|
||||
|
@ -112,6 +114,19 @@ fs_attach(void *softc, struct l9p_request *req)
|
|||
static void
|
||||
fs_clunk(void *softc, struct l9p_request *req)
|
||||
{
|
||||
struct l9p_connection *conn = req->lr_conn;
|
||||
struct openfile *file;
|
||||
struct stat st;
|
||||
|
||||
file = req->lr_fid->lo_aux;
|
||||
|
||||
if (file->dir)
|
||||
closedir(file->dir);
|
||||
else {
|
||||
close(file->fd);
|
||||
file->fd = -1;
|
||||
}
|
||||
|
||||
l9p_respond(req, NULL);
|
||||
}
|
||||
|
||||
|
@ -124,12 +139,13 @@ fs_create(void *softc, struct l9p_request *req)
|
|||
static void
|
||||
fs_flush(void *softc, struct l9p_request *req)
|
||||
{
|
||||
|
||||
l9p_respond(req, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
fs_open(void *softc, struct l9p_request *req)
|
||||
{
|
||||
struct l9p_connection *conn = req->lr_conn;
|
||||
struct openfile *file;
|
||||
struct stat st;
|
||||
|
||||
|
@ -142,12 +158,12 @@ fs_open(void *softc, struct l9p_request *req)
|
|||
} else {
|
||||
file->fd = open(file->name, O_RDONLY);
|
||||
if (file->fd < 0) {
|
||||
l9p_respond(req, "ENOPERM");
|
||||
l9p_respond(req, "Permission denied");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
req->lr_resp.ropen.iounit = 512;
|
||||
req->lr_resp.ropen.iounit = conn->lc_max_io_size;
|
||||
l9p_respond(req, NULL);
|
||||
}
|
||||
|
||||
|
@ -155,6 +171,7 @@ static void
|
|||
fs_read(void *softc, struct l9p_request *req)
|
||||
{
|
||||
struct openfile *file;
|
||||
struct l9p_connection *conn = req->lr_conn;
|
||||
struct l9p_stat l9stat;
|
||||
|
||||
file = req->lr_fid->lo_aux;
|
||||
|
@ -163,15 +180,24 @@ fs_read(void *softc, struct l9p_request *req)
|
|||
struct dirent *d;
|
||||
struct stat st;
|
||||
|
||||
d = readdir(file->dir);
|
||||
if (d) {
|
||||
stat(d->d_name, &st);
|
||||
dostat(&l9stat, d->d_name, &st);
|
||||
l9p_pack_stat(req, &l9stat);
|
||||
for (;;) {
|
||||
d = readdir(file->dir);
|
||||
if (d) {
|
||||
stat(d->d_name, &st);
|
||||
dostat(&l9stat, d->d_name, &st);
|
||||
if (l9p_pack_stat(req, &l9stat) != 0) {
|
||||
seekdir(file->dir, -1);
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
req->lr_resp.io.data = malloc(req->lr_req.io.count);
|
||||
req->lr_resp.io.count = read(file->fd, req->lr_resp.io.data, req->lr_req.io.count);
|
||||
size_t niov = l9p_truncate_iov(req->lr_data_iov, req->lr_data_niov, req->lr_req.io.count);
|
||||
req->lr_resp.io.count = readv(file->fd, req->lr_data_iov, niov);
|
||||
}
|
||||
|
||||
l9p_respond(req, NULL);
|
||||
|
@ -186,7 +212,16 @@ fs_remove(void *softc, struct l9p_request *req)
|
|||
static void
|
||||
fs_stat(void *softc, struct l9p_request *req)
|
||||
{
|
||||
struct openfile *file;
|
||||
struct stat st;
|
||||
struct l9p_stat l9stat;
|
||||
|
||||
file = req->lr_fid->lo_aux;
|
||||
|
||||
stat(file->name, &st);
|
||||
dostat(&req->lr_resp.rstat.stat, file->name, &st);
|
||||
|
||||
l9p_respond(req, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -200,11 +235,11 @@ fs_walk(void *softc, struct l9p_request *req)
|
|||
strcpy(name, file->name);
|
||||
|
||||
/* build full path. Stat full path. Done */
|
||||
for(i=0; i < req->lr_req.twalk.nwname; i++) {
|
||||
for (i = 0; i < req->lr_req.twalk.nwname; i++) {
|
||||
strcat(name, "/");
|
||||
strcat(name, req->lr_req.twalk.wname[i]);
|
||||
if (stat(name, &buf) < 0){
|
||||
l9p_respond(req, "no such file");
|
||||
l9p_respond(req, "No such file or directory");
|
||||
free(name);
|
||||
return;
|
||||
}
|
||||
|
|
79
connection.c
79
connection.c
|
@ -26,6 +26,8 @@
|
|||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/queue.h>
|
||||
#include "lib9p.h"
|
||||
#include "log.h"
|
||||
|
@ -35,7 +37,7 @@ l9p_server_init(struct l9p_server **serverp, struct l9p_backend *backend)
|
|||
{
|
||||
struct l9p_server *server;
|
||||
|
||||
server = malloc(sizeof(*server));
|
||||
server = calloc(1, sizeof(*server));
|
||||
server->ls_backend = backend;
|
||||
LIST_INIT(&server->ls_conns);
|
||||
|
||||
|
@ -48,8 +50,11 @@ l9p_connection_init(struct l9p_server *server, struct l9p_connection **conn)
|
|||
{
|
||||
struct l9p_connection *newconn;
|
||||
|
||||
newconn = malloc(sizeof(*newconn));
|
||||
newconn = calloc(1, sizeof(*newconn));
|
||||
newconn->lc_server = server;
|
||||
newconn->lc_msize = L9P_DEFAULT_MSIZE;
|
||||
LIST_INIT(&newconn->lc_requests);
|
||||
LIST_INIT(&newconn->lc_files);
|
||||
LIST_INSERT_HEAD(&server->ls_conns, newconn, lc_link);
|
||||
*conn = newconn;
|
||||
|
||||
|
@ -63,29 +68,48 @@ l9p_connection_free(struct l9p_connection *conn)
|
|||
}
|
||||
|
||||
void
|
||||
l9p_connection_on_send_request(struct l9p_connection *conn,
|
||||
void (*cb)(void *, size_t, void *), void *softc)
|
||||
l9p_connection_on_send_response(struct l9p_connection *conn,
|
||||
l9p_send_response_t cb, void *aux)
|
||||
{
|
||||
|
||||
conn->lc_send_request = cb;
|
||||
conn->lc_send_request_aux = softc;
|
||||
conn->lc_send_response = cb;
|
||||
conn->lc_send_response_aux = aux;
|
||||
}
|
||||
|
||||
void
|
||||
l9p_connection_recv(struct l9p_connection *conn, void *buf, size_t len)
|
||||
l9p_connection_on_get_response_buffer(struct l9p_connection *conn,
|
||||
l9p_get_response_buffer_t cb, void *aux)
|
||||
{
|
||||
|
||||
conn->lc_get_response_buffer = cb;
|
||||
conn->lc_get_response_buffer_aux = aux;
|
||||
}
|
||||
|
||||
void
|
||||
l9p_connection_recv(struct l9p_connection *conn, const struct iovec *iov,
|
||||
const size_t niov, void *aux)
|
||||
{
|
||||
struct l9p_message msg;
|
||||
struct l9p_request *req;
|
||||
|
||||
req = malloc(sizeof(struct l9p_request));
|
||||
req = calloc(1, sizeof(struct l9p_request));
|
||||
req->lr_aux = aux;
|
||||
req->lr_conn = conn;
|
||||
msg.lm_buffer = buf;
|
||||
msg.lm_pos = buf;
|
||||
msg.lm_end = buf + len;
|
||||
msg.lm_mode = L9P_UNPACK;
|
||||
|
||||
if (l9p_pufcall(&msg, &req->lr_req) != 0) {
|
||||
l9p_logf(L9P_WARNING, "cannot unpack received message");
|
||||
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) != 0){
|
||||
L9P_LOG(L9P_WARNING, "cannot unpack received message");
|
||||
return;
|
||||
}
|
||||
|
||||
if (conn->lc_get_response_buffer(req, req->lr_resp_msg.lm_iov,
|
||||
&req->lr_resp_msg.lm_niov, conn->lc_get_response_buffer_aux) != 0) {
|
||||
L9P_LOG(L9P_WARNING, "cannot obtain buffers for response");
|
||||
return;
|
||||
}
|
||||
|
||||
l9p_dispatch_request(req);
|
||||
|
@ -97,6 +121,24 @@ l9p_connection_close(struct l9p_connection *conn)
|
|||
|
||||
}
|
||||
|
||||
struct l9p_openfile *
|
||||
l9p_connection_alloc_fid(struct l9p_connection *conn, uint32_t fid)
|
||||
{
|
||||
struct l9p_openfile *file;
|
||||
|
||||
if (l9p_connection_find_fid(conn, fid) != NULL) {
|
||||
errno = EEXIST;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
file = calloc(1, sizeof(struct l9p_openfile));
|
||||
file->lo_fid = fid;
|
||||
file->lo_conn = conn;
|
||||
LIST_INSERT_HEAD(&conn->lc_files, file, lo_link);
|
||||
|
||||
return (file);
|
||||
}
|
||||
|
||||
struct l9p_openfile *
|
||||
l9p_connection_find_fid(struct l9p_connection *conn, uint32_t fid)
|
||||
{
|
||||
|
@ -110,6 +152,13 @@ l9p_connection_find_fid(struct l9p_connection *conn, uint32_t fid)
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
void
|
||||
l9p_connection_remove_fid(struct l9p_connection *conn, struct l9p_openfile *fid)
|
||||
{
|
||||
|
||||
LIST_REMOVE(fid, lo_link);
|
||||
}
|
||||
|
||||
struct l9p_request *
|
||||
l9p_connection_find_tag(struct l9p_connection *conn, uint32_t tag)
|
||||
{
|
||||
|
|
5
fcall.h
5
fcall.h
|
@ -193,8 +193,7 @@ struct l9p_f_io
|
|||
struct l9p_f_rstat
|
||||
{
|
||||
struct l9p_hdr hdr;
|
||||
uint16_t nstat;
|
||||
uint8_t *stat;
|
||||
struct l9p_stat stat;
|
||||
};
|
||||
|
||||
struct l9p_f_twstat
|
||||
|
@ -224,4 +223,4 @@ union l9p_fcall
|
|||
struct l9p_f_io io;
|
||||
};
|
||||
|
||||
#endif //LIB9P_FCALL_H
|
||||
#endif /* LIB9P_FCALL_H */
|
||||
|
|
84
lib9p.h
84
lib9p.h
|
@ -29,14 +29,28 @@
|
|||
#ifndef LIB9P_LIB9P_H
|
||||
#define LIB9P_LIB9P_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/sbuf.h>
|
||||
#include <pthread.h>
|
||||
#include "fcall.h"
|
||||
|
||||
#define L9P_ENOFID "FID does not exist"
|
||||
#define L9P_ENOFUNC "Function not implemented"
|
||||
#define L9P_EINTR "Interrupted"
|
||||
#define L9P_DEFAULT_MSIZE 8192
|
||||
#define L9P_MAX_IOV 8
|
||||
|
||||
#define L9P_ENOFID "FID does not exist"
|
||||
#define L9P_ENOFUNC "Function not implemented"
|
||||
#define L9P_EINTR "Interrupted"
|
||||
|
||||
struct l9p_request;
|
||||
|
||||
typedef int (l9p_get_response_buffer_t)(struct l9p_request *,
|
||||
struct iovec *, size_t *, void *);
|
||||
|
||||
typedef int (l9p_send_response_t)(struct l9p_request *, const struct iovec *,
|
||||
const size_t, const size_t, void *);
|
||||
|
||||
enum l9p_pack_mode
|
||||
{
|
||||
|
@ -52,23 +66,38 @@ enum l9p_integer_type
|
|||
L9P_QWORD = 8
|
||||
};
|
||||
|
||||
enum l9p_version
|
||||
{
|
||||
L9P_2000 = 1,
|
||||
L9P_2000U = 2,
|
||||
L9P_2000L = 3
|
||||
};
|
||||
|
||||
struct l9p_message
|
||||
{
|
||||
enum l9p_pack_mode lm_mode;
|
||||
uint8_t *lm_buffer;
|
||||
uint8_t *lm_pos;
|
||||
uint8_t *lm_end;
|
||||
struct iovec lm_iov[L9P_MAX_IOV];
|
||||
size_t lm_niov;
|
||||
size_t lm_cursor_iov;
|
||||
size_t lm_cursor_offset;
|
||||
size_t lm_size;
|
||||
};
|
||||
|
||||
struct l9p_request
|
||||
{
|
||||
uint32_t lr_tag;
|
||||
struct l9p_message lr_req_msg;
|
||||
struct l9p_message lr_resp_msg;
|
||||
struct l9p_message lr_readdir_msg;
|
||||
union l9p_fcall lr_req;
|
||||
union l9p_fcall lr_resp;
|
||||
struct l9p_openfile *lr_fid;
|
||||
struct l9p_openfile *lr_newfid;
|
||||
struct l9p_connection *lr_conn;
|
||||
pthread_t lr_thread;
|
||||
void *lr_aux;
|
||||
struct iovec lr_data_iov[L9P_MAX_IOV];
|
||||
size_t lr_data_niov;
|
||||
LIST_ENTRY(l9p_request) lr_link;
|
||||
};
|
||||
|
||||
|
@ -85,9 +114,14 @@ struct l9p_openfile
|
|||
struct l9p_connection
|
||||
{
|
||||
struct l9p_server *lc_server;
|
||||
enum l9p_version lc_version;
|
||||
pthread_mutex_t lc_send_lock;
|
||||
void (*lc_send_request)(const void *, const size_t, void *);
|
||||
void *lc_send_request_aux;
|
||||
uint32_t lc_msize;
|
||||
uint32_t lc_max_io_size;
|
||||
l9p_send_response_t *lc_send_response;
|
||||
l9p_get_response_buffer_t *lc_get_response_buffer;
|
||||
void *lc_get_response_buffer_aux;
|
||||
void *lc_send_response_aux;
|
||||
void *lc_softc;
|
||||
LIST_HEAD(, l9p_request) lc_requests;
|
||||
LIST_HEAD(, l9p_openfile) lc_files;
|
||||
|
@ -97,6 +131,7 @@ struct l9p_connection
|
|||
struct l9p_server
|
||||
{
|
||||
struct l9p_backend *ls_backend;
|
||||
enum l9p_version ls_max_version;
|
||||
LIST_HEAD(, l9p_connection) ls_conns;
|
||||
};
|
||||
|
||||
|
@ -118,19 +153,36 @@ struct l9p_backend
|
|||
};
|
||||
|
||||
int l9p_pufcall(struct l9p_message *msg, union l9p_fcall *fcall);
|
||||
int l9p_fustat(struct l9p_message *msg, struct l9p_stat *s);
|
||||
int l9p_pustat(struct l9p_message *msg, struct l9p_stat *s);
|
||||
uint16_t l9p_sizeof_stat(struct l9p_stat *stat);
|
||||
int l9p_pack_stat(struct l9p_request *req, struct l9p_stat *s);
|
||||
|
||||
int l9p_server_init(struct l9p_server **, struct l9p_backend *backend);
|
||||
int l9p_server_init(struct l9p_server **serverp, struct l9p_backend *backend);
|
||||
|
||||
int l9p_connection_init(struct l9p_server *server, struct l9p_connection **conn);
|
||||
int l9p_connection_init(struct l9p_server *server,
|
||||
struct l9p_connection **connp);
|
||||
void l9p_connection_free(struct l9p_connection *conn);
|
||||
void l9p_connection_on_send_request(struct l9p_connection *conn, void (*cb)(void *, size_t, void *), void *);
|
||||
void l9p_connection_recv(struct l9p_connection *conn, void *buf, size_t len);
|
||||
void l9p_connection_on_send_response(struct l9p_connection *conn,
|
||||
l9p_send_response_t *cb, void *aux);
|
||||
void l9p_connection_on_get_response_buffer(struct l9p_connection *conn,
|
||||
l9p_get_response_buffer_t *cb, void *aux);
|
||||
void l9p_connection_recv(struct l9p_connection *conn, const struct iovec *iov,
|
||||
size_t niov, void *aux);
|
||||
void l9p_connection_close(struct l9p_connection *conn);
|
||||
struct l9p_openfile *l9p_connection_find_fid(struct l9p_connection *conn, uint32_t fid);
|
||||
struct l9p_request *l9p_connection_find_tag(struct l9p_connection *conn, uint32_t tag);
|
||||
struct l9p_openfile *l9p_connection_alloc_fid(struct l9p_connection *conn,
|
||||
uint32_t fid);
|
||||
struct l9p_openfile *l9p_connection_find_fid(struct l9p_connection *conn,
|
||||
uint32_t fid);
|
||||
void l9p_connection_remove_fid(struct l9p_connection *conn,
|
||||
struct l9p_openfile *fid);
|
||||
struct l9p_request *l9p_connection_find_tag(struct l9p_connection *conn,
|
||||
uint32_t tag);
|
||||
void l9p_respond(struct l9p_request *req, const char *error);
|
||||
|
||||
#endif //LIB9P_LIB9P_H
|
||||
void l9p_seek_iov(struct iovec *iov1, size_t niov1, struct iovec *iov2,
|
||||
size_t *niov2, size_t seek);
|
||||
int l9p_truncate_iov(struct iovec *iov, size_t niov, size_t length);
|
||||
void l9p_describe_qid(struct l9p_qid *qid, struct sbuf *sb);
|
||||
void l9p_describe_fcall(union l9p_fcall *fcall, enum l9p_version version, struct sbuf *sb);
|
||||
|
||||
#endif /* LIB9P_LIB9P_H */
|
||||
|
|
4
log.c
4
log.c
|
@ -37,12 +37,12 @@ static const char *l9p_log_level_names[] = {
|
|||
};
|
||||
|
||||
void
|
||||
l9p_logf(enum l9p_log_level level, const char *fmt, ...)
|
||||
l9p_logf(enum l9p_log_level level, const char *func, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
fprintf(stderr, "[%s]\t", l9p_log_level_names[level]);
|
||||
fprintf(stderr, "[%s]\t %s: ", l9p_log_level_names[level], func);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(ap);
|
||||
|
|
4
log.h
4
log.h
|
@ -36,6 +36,8 @@ enum l9p_log_level
|
|||
L9P_ERROR
|
||||
};
|
||||
|
||||
void l9p_logf(enum l9p_log_level level, const char *fmt, ...);
|
||||
void l9p_logf(enum l9p_log_level level, const char *func, const char *fmt, ...);
|
||||
|
||||
#define L9P_LOG(level, fmt, ...) l9p_logf(level, __func__, fmt, ##__VA_ARGS__)
|
||||
|
||||
#endif /* LIB9P_LOG_H */
|
||||
|
|
299
lib9p.c → pack.c
299
lib9p.c → pack.c
|
@ -31,124 +31,119 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/uio.h>
|
||||
#include "lib9p.h"
|
||||
|
||||
#define N(ary) (sizeof(ary) / sizeof(*ary))
|
||||
#define STRING_SIZE(s) (L9P_WORD + strlen(s))
|
||||
#define QID_SIZE (L9P_BYTE + L9P_DWORD + L9P_QWORD)
|
||||
|
||||
static void l9p_puint(struct l9p_message *, enum l9p_integer_type, uint32_t *);
|
||||
static inline void l9p_pu8(struct l9p_message *, uint8_t *);
|
||||
static inline void l9p_pu16(struct l9p_message *, uint16_t *);
|
||||
static inline void l9p_pu32(struct l9p_message *, uint32_t *);
|
||||
static inline void l9p_pu64(struct l9p_message *, uint64_t *);
|
||||
static void l9p_pustring(struct l9p_message *, char **s);
|
||||
static void l9p_pustrings(struct l9p_message *, uint16_t *,char *[], size_t);
|
||||
static void l9p_pudata(struct l9p_message *, uint8_t **, size_t);
|
||||
static void l9p_puqid(struct l9p_message *, struct l9p_qid *);
|
||||
static void l9p_puqids(struct l9p_message *, uint16_t *, struct l9p_qid *q,
|
||||
static int l9p_iov_io(struct l9p_message *, void *, size_t);
|
||||
static int l9p_puint(struct l9p_message *, enum l9p_integer_type, uint32_t *);
|
||||
static inline int l9p_pu8(struct l9p_message *, uint8_t *);
|
||||
static inline int l9p_pu16(struct l9p_message *, uint16_t *);
|
||||
static inline int l9p_pu32(struct l9p_message *, uint32_t *);
|
||||
static inline int l9p_pu64(struct l9p_message *, uint64_t *);
|
||||
static int l9p_pustring(struct l9p_message *, char **s);
|
||||
static int l9p_pustrings(struct l9p_message *, uint16_t *,char *[], size_t);
|
||||
static int l9p_pudata(struct l9p_message *, uint8_t **, size_t);
|
||||
static int l9p_puqid(struct l9p_message *, struct l9p_qid *);
|
||||
static int l9p_puqids(struct l9p_message *, uint16_t *, struct l9p_qid *q,
|
||||
size_t);
|
||||
|
||||
|
||||
static void
|
||||
l9p_puint(struct l9p_message *msg, enum l9p_integer_type size, uint32_t *val)
|
||||
static int
|
||||
l9p_iov_io(struct l9p_message *msg, void *buffer, size_t len)
|
||||
{
|
||||
uint8_t *pos;
|
||||
int v;
|
||||
size_t done = 0;
|
||||
size_t left = len;
|
||||
|
||||
if(msg->lm_pos + size <= msg->lm_end) {
|
||||
pos = (uint8_t*)msg->lm_pos;
|
||||
switch (msg->lm_mode) {
|
||||
case L9P_PACK:
|
||||
v = *val;
|
||||
switch (size) {
|
||||
case L9P_DWORD:
|
||||
pos[3] = v>>24;
|
||||
pos[2] = v>>16;
|
||||
case L9P_WORD:
|
||||
pos[1] = v>>8;
|
||||
case L9P_BYTE:
|
||||
pos[0] = v;
|
||||
break;
|
||||
}
|
||||
case L9P_UNPACK:
|
||||
v = 0;
|
||||
switch (size) {
|
||||
case L9P_DWORD:
|
||||
v |= pos[3]<<24;
|
||||
v |= pos[2]<<16;
|
||||
case L9P_WORD:
|
||||
v |= pos[1]<<8;
|
||||
case L9P_BYTE:
|
||||
v |= pos[0];
|
||||
break;
|
||||
}
|
||||
*val = v;
|
||||
assert(msg != NULL);
|
||||
assert(buffer != NULL);
|
||||
|
||||
if (len == 0)
|
||||
return (0);
|
||||
|
||||
if (msg->lm_cursor_iov >= msg->lm_niov)
|
||||
return (-1);
|
||||
|
||||
while (left > 0) {
|
||||
size_t idx = msg->lm_cursor_iov;
|
||||
size_t space = msg->lm_iov[idx].iov_len - msg->lm_cursor_offset;
|
||||
size_t towrite = MIN(space, left);
|
||||
|
||||
if (msg->lm_mode == L9P_PACK)
|
||||
memcpy(msg->lm_iov[idx].iov_base + msg->lm_cursor_offset,
|
||||
buffer + done, towrite);
|
||||
|
||||
if (msg->lm_mode == L9P_UNPACK)
|
||||
memcpy(buffer + done, msg->lm_iov[idx].iov_base +
|
||||
msg->lm_cursor_offset, towrite);
|
||||
|
||||
msg->lm_cursor_offset += towrite;
|
||||
|
||||
if (space - towrite == 0) {
|
||||
/* Advance to next iov */
|
||||
msg->lm_cursor_iov++;
|
||||
msg->lm_cursor_offset = 0;
|
||||
|
||||
if (msg->lm_cursor_iov > msg->lm_niov)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
done += towrite;
|
||||
left -= towrite;
|
||||
}
|
||||
msg->lm_pos += size;
|
||||
|
||||
msg->lm_size += done;
|
||||
return (done);
|
||||
}
|
||||
|
||||
static inline void
|
||||
static inline int
|
||||
l9p_pu8(struct l9p_message *msg, uint8_t *val)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
v = *val;
|
||||
l9p_puint(msg, L9P_BYTE, &v);
|
||||
*val = (uint8_t)v;
|
||||
return (l9p_iov_io(msg, val, sizeof(uint8_t)));
|
||||
}
|
||||
|
||||
static inline void
|
||||
static inline int
|
||||
l9p_pu16(struct l9p_message *msg, uint16_t *val)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
v = *val;
|
||||
l9p_puint(msg, L9P_WORD, &v);
|
||||
*val = (uint16_t)v;
|
||||
return (l9p_iov_io(msg, val, sizeof(uint16_t)));
|
||||
}
|
||||
|
||||
static inline void
|
||||
static inline int
|
||||
l9p_pu32(struct l9p_message *msg, uint32_t *val)
|
||||
{
|
||||
l9p_puint(msg, L9P_DWORD, val);
|
||||
return(l9p_iov_io(msg, val, sizeof(uint32_t)));
|
||||
}
|
||||
|
||||
static inline void
|
||||
static inline int
|
||||
l9p_pu64(struct l9p_message *msg, uint64_t *val)
|
||||
{
|
||||
uint32_t vl, vb;
|
||||
|
||||
vl = (uint)*val;
|
||||
vb = (uint)(*val>>32);
|
||||
l9p_puint(msg, L9P_DWORD, &vl);
|
||||
l9p_puint(msg, L9P_DWORD, &vb);
|
||||
*val = vl | ((uint64_t)vb<<32);
|
||||
return(l9p_iov_io(msg, val, sizeof(uint64_t)));
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
l9p_pustring(struct l9p_message *msg, char **s)
|
||||
{
|
||||
uint16_t len;
|
||||
|
||||
if(msg->lm_mode == L9P_PACK)
|
||||
if (msg->lm_mode == L9P_PACK)
|
||||
len = strlen(*s);
|
||||
l9p_pu16(msg, &len);
|
||||
|
||||
if (msg->lm_pos + len <= msg->lm_end) {
|
||||
if (msg->lm_mode == L9P_UNPACK) {
|
||||
*s = malloc(len + 1);
|
||||
memcpy(*s, msg->lm_pos, len);
|
||||
(*s)[len] = '\0';
|
||||
} else
|
||||
memcpy(msg->lm_pos, *s, len);
|
||||
}
|
||||
msg->lm_pos += len;
|
||||
if (l9p_pu16(msg, &len) < 0)
|
||||
return (-1);
|
||||
|
||||
if (msg->lm_mode == L9P_UNPACK)
|
||||
*s = calloc(1, len + 1);
|
||||
|
||||
if (l9p_iov_io(msg, *s, len) < 0)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
l9p_pustrings(struct l9p_message *msg, uint16_t *num, char *strings[],
|
||||
size_t max)
|
||||
{
|
||||
|
@ -157,105 +152,78 @@ l9p_pustrings(struct l9p_message *msg, uint16_t *num, char *strings[],
|
|||
uint16_t len;
|
||||
|
||||
l9p_pu16(msg, num);
|
||||
if (*num > max) {
|
||||
msg->lm_pos = msg->lm_end+1;
|
||||
return;
|
||||
}
|
||||
|
||||
s = NULL;
|
||||
|
||||
if (msg->lm_mode == L9P_UNPACK) {
|
||||
s = msg->lm_pos;
|
||||
size = 0;
|
||||
for (i = 0; i < *num; i++) {
|
||||
l9p_pu16(msg, &len);
|
||||
msg->lm_pos += len;
|
||||
size += len;
|
||||
if (msg->lm_pos > msg->lm_end)
|
||||
return;
|
||||
}
|
||||
msg->lm_pos = s;
|
||||
size += *num;
|
||||
s = malloc(size);
|
||||
}
|
||||
|
||||
for (i = 0; i < *num; i++) {
|
||||
if (msg->lm_mode == L9P_PACK)
|
||||
len = strlen(strings[i]);
|
||||
l9p_pu16(msg, &len);
|
||||
|
||||
if (msg->lm_mode == L9P_UNPACK) {
|
||||
memcpy(s, msg->lm_pos, len);
|
||||
strings[i] = (char*)s;
|
||||
s += len;
|
||||
msg->lm_pos += len;
|
||||
*s++ = '\0';
|
||||
} else
|
||||
l9p_pudata(msg, &strings[i], len);
|
||||
for (i = 0; i < MIN(*num, max); i++) {
|
||||
if (l9p_pustring(msg, &strings[i]) < 0)
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
l9p_pudata(struct l9p_message *msg, uint8_t **data, size_t len)
|
||||
{
|
||||
if (msg->lm_pos + len <= msg->lm_end) {
|
||||
if (msg->lm_mode == L9P_UNPACK) {
|
||||
*data = malloc(len);
|
||||
memcpy(*data, msg->lm_pos, len);
|
||||
} else
|
||||
memcpy(msg->lm_pos, *data, len);
|
||||
}
|
||||
msg->lm_pos += len;
|
||||
if (msg->lm_mode == L9P_UNPACK)
|
||||
*data = malloc(len);
|
||||
|
||||
return (l9p_iov_io(msg, *data, len));
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
l9p_puqid(struct l9p_message *msg, struct l9p_qid *qid)
|
||||
{
|
||||
l9p_pu8(msg, &qid->type);
|
||||
l9p_pu32(msg, &qid->version);
|
||||
l9p_pu64(msg, &qid->path);
|
||||
int r = 0;
|
||||
|
||||
r += l9p_pu8(msg, (uint8_t *)&qid->type);
|
||||
r += l9p_pu32(msg, &qid->version);
|
||||
r += l9p_pu64(msg, &qid->path);
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
l9p_puqids(struct l9p_message *msg, uint16_t *num, struct l9p_qid *qids,
|
||||
size_t max)
|
||||
{
|
||||
int i;
|
||||
l9p_pu16(msg, num);
|
||||
if (*num > max) {
|
||||
msg->lm_pos = msg->lm_end + 1;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < *num; i++)
|
||||
l9p_puqid(msg, &qids[i]);
|
||||
for (i = 0; i < *num; i++) {
|
||||
if (l9p_puqid(msg, &qids[i]) < 0)
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
l9p_pustat(struct l9p_message *msg, struct l9p_stat *stat)
|
||||
{
|
||||
int r = 0;
|
||||
uint16_t size;
|
||||
|
||||
if(msg->lm_mode == L9P_PACK)
|
||||
if (msg->lm_mode == L9P_PACK)
|
||||
size = l9p_sizeof_stat(stat) - 2;
|
||||
|
||||
l9p_pu16(msg, &size);
|
||||
l9p_pu16(msg, &stat->type);
|
||||
l9p_pu32(msg, &stat->dev);
|
||||
l9p_puqid(msg, &stat->qid);
|
||||
l9p_pu32(msg, &stat->mode);
|
||||
l9p_pu32(msg, &stat->atime);
|
||||
l9p_pu32(msg, &stat->mtime);
|
||||
l9p_pu64(msg, &stat->length);
|
||||
l9p_pustring(msg, &stat->name);
|
||||
l9p_pustring(msg, &stat->uid);
|
||||
l9p_pustring(msg, &stat->gid);
|
||||
l9p_pustring(msg, &stat->muid);
|
||||
r += l9p_pu16(msg, &size);
|
||||
r += l9p_pu16(msg, &stat->type);
|
||||
r += l9p_pu32(msg, &stat->dev);
|
||||
r += l9p_puqid(msg, &stat->qid);
|
||||
r += l9p_pu32(msg, &stat->mode);
|
||||
r += l9p_pu32(msg, &stat->atime);
|
||||
r += l9p_pu32(msg, &stat->mtime);
|
||||
r += l9p_pu64(msg, &stat->length);
|
||||
r += l9p_pustring(msg, &stat->name);
|
||||
r += l9p_pustring(msg, &stat->uid);
|
||||
r += l9p_pustring(msg, &stat->gid);
|
||||
r += l9p_pustring(msg, &stat->muid);
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
||||
int
|
||||
l9p_pufcall(struct l9p_message *msg, union l9p_fcall *fcall)
|
||||
{
|
||||
uint32_t length = 0;
|
||||
|
||||
l9p_pu32(msg, &length);
|
||||
l9p_pu8(msg, &fcall->hdr.type);
|
||||
l9p_pu16(msg, &fcall->hdr.tag);
|
||||
|
||||
|
@ -320,13 +288,11 @@ l9p_pufcall(struct l9p_message *msg, union l9p_fcall *fcall)
|
|||
break;
|
||||
case L9P_RREAD:
|
||||
l9p_pu32(msg, &fcall->io.count);
|
||||
l9p_pudata(msg, &fcall->io.data, fcall->io.count);
|
||||
break;
|
||||
case L9P_TWRITE:
|
||||
l9p_pu32(msg, &fcall->hdr.fid);
|
||||
l9p_pu64(msg, &fcall->io.offset);
|
||||
l9p_pu32(msg, &fcall->io.count);
|
||||
l9p_pudata(msg, &fcall->io.data, fcall->io.count);
|
||||
break;
|
||||
case L9P_RWRITE:
|
||||
l9p_pu32(msg, &fcall->io.count);
|
||||
|
@ -336,16 +302,33 @@ l9p_pufcall(struct l9p_message *msg, union l9p_fcall *fcall)
|
|||
l9p_pu32(msg, &fcall->hdr.fid);
|
||||
break;
|
||||
case L9P_RSTAT:
|
||||
l9p_pu16(msg, &fcall->rstat.nstat);
|
||||
l9p_pudata(msg, (char**)&fcall->rstat.stat, fcall->rstat.nstat);
|
||||
{
|
||||
uint16_t size = l9p_sizeof_stat(&fcall->rstat.stat);
|
||||
l9p_pu16(msg, &size);
|
||||
l9p_pustat(msg, &fcall->rstat.stat);
|
||||
}
|
||||
break;
|
||||
case L9P_TWSTAT: {
|
||||
uint16_t size;
|
||||
l9p_pu32(msg, &fcall->hdr.fid);
|
||||
l9p_pu16(msg, &size);
|
||||
l9p_pustat(msg, &fcall->twstat.stat);
|
||||
case L9P_TWSTAT:
|
||||
{
|
||||
uint16_t size;
|
||||
l9p_pu32(msg, &fcall->hdr.fid);
|
||||
l9p_pu16(msg, &size);
|
||||
l9p_pustat(msg, &fcall->twstat.stat);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (msg->lm_mode == L9P_PACK) {
|
||||
/* Rewind to the beginning */
|
||||
uint32_t len = msg->lm_size;
|
||||
msg->lm_cursor_offset = 0;
|
||||
msg->lm_cursor_iov = 0;
|
||||
msg->lm_size -= sizeof(uint32_t);
|
||||
|
||||
if (fcall->hdr.type == L9P_RREAD)
|
||||
len += fcall->io.count;
|
||||
|
||||
l9p_pu32(msg, &len);
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
@ -358,7 +341,7 @@ l9p_sizeof_stat(struct l9p_stat *stat) {
|
|||
+ L9P_DWORD /* dev */
|
||||
+ QID_SIZE /* qid */
|
||||
+ 3 * L9P_DWORD /* mode, atime, mtime */
|
||||
+ L9P_DWORD /* length */
|
||||
+ L9P_QWORD /* length */
|
||||
+ STRING_SIZE(stat->name)
|
||||
+ STRING_SIZE(stat->uid)
|
||||
+ STRING_SIZE(stat->gid)
|
138
request.c
138
request.c
|
@ -25,8 +25,11 @@
|
|||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/sbuf.h>
|
||||
#include "lib9p.h"
|
||||
#include "fcall.h"
|
||||
#include "log.h"
|
||||
|
@ -46,7 +49,7 @@ static void l9p_dispatch_twalk(struct l9p_request *req);
|
|||
static void l9p_dispatch_twrite(struct l9p_request *req);
|
||||
static void l9p_dispatch_twstat(struct l9p_request *req);
|
||||
|
||||
static struct
|
||||
static const struct
|
||||
{
|
||||
enum l9p_ftype type;
|
||||
void (*handler)(struct l9p_request *);
|
||||
|
@ -65,13 +68,25 @@ static struct
|
|||
{L9P_TWSTAT, l9p_dispatch_twstat}
|
||||
};
|
||||
|
||||
static const char *l9p_versions[] = {
|
||||
"9P2000",
|
||||
"9P2000.u",
|
||||
"9P2000.L"
|
||||
};
|
||||
|
||||
void
|
||||
l9p_dispatch_request(struct l9p_request *req)
|
||||
{
|
||||
struct l9p_connection *conn = req->lr_conn;
|
||||
struct sbuf *sb = sbuf_new_auto();
|
||||
int i;
|
||||
|
||||
l9p_logf(L9P_INFO, "new request of type %d", req->lr_req.hdr.type);
|
||||
l9p_describe_fcall(&req->lr_req, L9P_2000, sb);
|
||||
sbuf_done(sb);
|
||||
|
||||
L9P_LOG(L9P_DEBUG, "%s", sbuf_data(sb));
|
||||
sbuf_delete(sb);
|
||||
|
||||
req->lr_tag = req->lr_req.hdr.tag;
|
||||
|
||||
for (i = 0; i < N(l9p_handlers); i++) {
|
||||
|
@ -81,6 +96,7 @@ l9p_dispatch_request(struct l9p_request *req)
|
|||
}
|
||||
}
|
||||
|
||||
L9P_LOG(L9P_WARNING, "unknown request of type %d", req->lr_req.hdr.type);
|
||||
l9p_respond(req, L9P_ENOFUNC);
|
||||
}
|
||||
|
||||
|
@ -88,19 +104,12 @@ void
|
|||
l9p_respond(struct l9p_request *req, const char *error)
|
||||
{
|
||||
struct l9p_connection *conn = req->lr_conn;
|
||||
struct l9p_message msg;
|
||||
void *buf = malloc(1024 * 1024);
|
||||
|
||||
msg.lm_buffer = buf;
|
||||
msg.lm_pos = buf;
|
||||
msg.lm_end = buf + (1024 * 1024);
|
||||
msg.lm_mode = L9P_PACK;
|
||||
struct sbuf *sb = sbuf_new_auto();
|
||||
size_t iosize;
|
||||
|
||||
switch (req->lr_req.hdr.type) {
|
||||
case L9P_TVERSION:
|
||||
break;
|
||||
|
||||
case L9P_TWALK:
|
||||
case L9P_TCLUNK:
|
||||
l9p_connection_remove_fid(conn, req->lr_fid);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -113,43 +122,66 @@ l9p_respond(struct l9p_request *req, const char *error)
|
|||
req->lr_resp.error.ename = error;
|
||||
}
|
||||
|
||||
if (l9p_pufcall(&msg, &req->lr_resp) != 0) {
|
||||
l9p_describe_fcall(&req->lr_resp, L9P_2000, sb);
|
||||
sbuf_done(sb);
|
||||
|
||||
L9P_LOG(L9P_DEBUG, "%s", sbuf_data(sb));
|
||||
sbuf_delete(sb);
|
||||
|
||||
if (l9p_pufcall(&req->lr_resp_msg, &req->lr_resp) != 0) {
|
||||
L9P_LOG(L9P_ERROR, "cannot pack response");
|
||||
return;
|
||||
}
|
||||
|
||||
conn->lc_send_request(msg.lm_buffer, msg.lm_pos - msg.lm_buffer,
|
||||
conn->lc_send_request_aux);
|
||||
iosize = req->lr_resp_msg.lm_size;
|
||||
|
||||
/* Include I/O size in calculation for Rread response */
|
||||
if (req->lr_resp.hdr.type == L9P_RREAD)
|
||||
iosize += req->lr_resp.io.count;
|
||||
|
||||
conn->lc_send_response(req, req->lr_resp_msg.lm_iov, req->lr_resp_msg.lm_niov,
|
||||
iosize, conn->lc_send_response_aux);
|
||||
}
|
||||
|
||||
int
|
||||
l9p_pack_stat(struct l9p_request *req, struct l9p_stat *st)
|
||||
{
|
||||
struct l9p_message msg;
|
||||
struct l9p_connection *conn = req->lr_conn;
|
||||
struct l9p_message *msg = &req->lr_readdir_msg;
|
||||
uint16_t size = l9p_sizeof_stat(st);
|
||||
|
||||
if (msg->lm_size == 0) {
|
||||
/* Initialize message */
|
||||
msg->lm_mode = L9P_PACK;
|
||||
msg->lm_niov = req->lr_data_niov;
|
||||
memcpy(msg->lm_iov, req->lr_data_iov, sizeof(struct iovec) * req->lr_data_niov);
|
||||
}
|
||||
|
||||
if (l9p_pustat(msg, st) < 0)
|
||||
return (-1);
|
||||
|
||||
req->lr_resp.io.count += size;
|
||||
req->lr_resp.io.data = realloc(req->lr_resp.io.data,
|
||||
req->lr_resp.io.count);
|
||||
|
||||
msg.lm_buffer = req->lr_resp.io.data + req->lr_resp.io.count - size;
|
||||
msg.lm_pos = req->lr_resp.io.data + req->lr_resp.io.count - size;
|
||||
msg.lm_end = req->lr_resp.io.data + req->lr_resp.io.count;
|
||||
msg.lm_mode = L9P_PACK;
|
||||
|
||||
l9p_pustat(&msg, st);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
l9p_dispatch_tversion(struct l9p_request *req)
|
||||
{
|
||||
struct l9p_connection *conn = req->lr_conn;
|
||||
enum l9p_version remote_version;
|
||||
|
||||
if (!strcmp(req->lr_req.version.version, "9P"))
|
||||
req->lr_resp.version.version = "9P";
|
||||
else if (!strcmp(req->lr_req.version.version, "9P2000"))
|
||||
req->lr_resp.version.version = "9P2000";
|
||||
else if (!strcmp(req->lr_req.version.version, "9P2000.u"))
|
||||
req->lr_resp.version.version = "9P2000.u";
|
||||
else
|
||||
req->lr_resp.version.version = "unknown";
|
||||
|
||||
req->lr_resp.version.msize = 8192;
|
||||
conn->lc_msize = MIN(req->lr_req.version.msize, conn->lc_msize);
|
||||
conn->lc_max_io_size = conn->lc_msize - 24;
|
||||
req->lr_resp.version.msize = conn->lc_msize;
|
||||
l9p_respond(req, NULL);
|
||||
}
|
||||
|
||||
|
@ -158,11 +190,7 @@ l9p_dispatch_tattach(struct l9p_request *req)
|
|||
{
|
||||
struct l9p_connection *conn = req->lr_conn;
|
||||
|
||||
req->lr_fid = malloc(sizeof(struct l9p_openfile));
|
||||
req->lr_fid->lo_fid = req->lr_req.tcreate.hdr.fid;
|
||||
req->lr_fid->lo_conn = conn;
|
||||
LIST_INSERT_HEAD(&conn->lc_files, req->lr_fid, lo_link);
|
||||
|
||||
req->lr_fid = l9p_connection_alloc_fid(conn, req->lr_req.hdr.fid);
|
||||
conn->lc_server->ls_backend->attach(conn->lc_server->ls_backend->softc, req);
|
||||
}
|
||||
|
||||
|
@ -171,13 +199,26 @@ l9p_dispatch_tclunk(struct l9p_request *req)
|
|||
{
|
||||
struct l9p_connection *conn = req->lr_conn;
|
||||
|
||||
req->lr_fid = l9p_connection_find_fid(conn, req->lr_req.hdr.fid);
|
||||
if (!req->lr_fid) {
|
||||
l9p_respond(req, L9P_ENOFID);
|
||||
return;
|
||||
}
|
||||
|
||||
conn->lc_server->ls_backend->clunk(conn->lc_server->ls_backend->softc, req);
|
||||
}
|
||||
|
||||
static void
|
||||
l9p_dispatch_tflush(struct l9p_request *req)
|
||||
{
|
||||
struct l9p_connection *conn = req->lr_conn;
|
||||
|
||||
if (!conn->lc_server->ls_backend->flush) {
|
||||
l9p_respond(req, L9P_ENOFUNC);
|
||||
return;
|
||||
}
|
||||
|
||||
conn->lc_server->ls_backend->flush(conn->lc_server->ls_backend->softc, req);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -187,15 +228,11 @@ l9p_dispatch_tcreate(struct l9p_request *req)
|
|||
struct l9p_openfile *fid;
|
||||
|
||||
if (l9p_connection_find_fid(conn, req->lr_req.tcreate.hdr.fid) != NULL) {
|
||||
l9p_respond(req, "x");
|
||||
l9p_respond(req, L9P_ENOFID);
|
||||
return;
|
||||
}
|
||||
|
||||
fid = malloc(sizeof(struct l9p_openfile));
|
||||
fid->lo_fid = req->lr_req.tcreate.hdr.fid;
|
||||
fid->lo_conn = conn;
|
||||
LIST_INSERT_HEAD(&conn->lc_files, fid, lo_link);
|
||||
|
||||
req->lr_fid = l9p_connection_alloc_fid(conn, req->lr_req.tattach.afid);
|
||||
conn->lc_server->ls_backend->create(conn->lc_server->ls_backend->softc, req);
|
||||
}
|
||||
|
||||
|
@ -231,6 +268,9 @@ l9p_dispatch_tread(struct l9p_request *req)
|
|||
return;
|
||||
}
|
||||
|
||||
l9p_seek_iov(req->lr_resp_msg.lm_iov, req->lr_resp_msg.lm_niov,
|
||||
req->lr_data_iov, &req->lr_data_niov, 11);
|
||||
|
||||
conn->lc_server->ls_backend->read(conn->lc_server->ls_backend->softc, req);
|
||||
}
|
||||
|
||||
|
@ -246,7 +286,18 @@ l9p_dispatch_tstat(struct l9p_request *req)
|
|||
struct l9p_connection *conn = req->lr_conn;
|
||||
struct l9p_openfile *fid;
|
||||
|
||||
req->lr_fid = l9p_connection_find_fid(conn, req->lr_req.twalk.hdr.fid);
|
||||
if (!req->lr_fid) {
|
||||
l9p_respond(req, L9P_ENOFID);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!conn->lc_server->ls_backend->stat) {
|
||||
l9p_respond(req, L9P_ENOFUNC);
|
||||
return;
|
||||
}
|
||||
|
||||
conn->lc_server->ls_backend->stat(conn->lc_server->ls_backend->softc, req);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -262,10 +313,11 @@ l9p_dispatch_twalk(struct l9p_request *req)
|
|||
}
|
||||
|
||||
if (req->lr_req.twalk.hdr.fid != req->lr_req.twalk.newfid) {
|
||||
req->lr_newfid = malloc(sizeof(struct l9p_openfile));
|
||||
req->lr_newfid->lo_fid = req->lr_req.twalk.newfid;
|
||||
req->lr_newfid->lo_conn = conn;
|
||||
LIST_INSERT_HEAD(&conn->lc_files, req->lr_newfid, lo_link);
|
||||
req->lr_newfid = l9p_connection_alloc_fid(conn, req->lr_req.twalk.newfid);
|
||||
if (req->lr_newfid == NULL) {
|
||||
l9p_respond(req, L9P_ENOFID);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!conn->lc_server->ls_backend->walk) {
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/uio.h>
|
||||
#include <netdb.h>
|
||||
#include "../lib9p.h"
|
||||
#include "../log.h"
|
||||
|
@ -48,7 +49,10 @@ struct l9p_socket_softc
|
|||
};
|
||||
|
||||
static int l9p_socket_readmsg(struct l9p_socket_softc *, void **, size_t *);
|
||||
static void l9p_socket_sendmsg(void *, size_t, void *);
|
||||
static int l9p_socket_get_response_buffer(struct l9p_request *,
|
||||
struct iovec *, size_t *, void *);
|
||||
static int l9p_socket_send_response(struct l9p_request *, const struct iovec *,
|
||||
const size_t, const size_t, void *);
|
||||
static void *l9p_socket_thread(void *);
|
||||
static int xread(int, void *, size_t);
|
||||
static int xwrite(int, void *, size_t);
|
||||
|
@ -105,7 +109,7 @@ l9p_start_server(struct l9p_server *server, const char *host, const char *port)
|
|||
&client_addr_len);
|
||||
|
||||
if (news < 0) {
|
||||
l9p_logf(L9P_WARNING, "accept(): %s", strerror(errno));
|
||||
L9P_LOG(L9P_WARNING, "accept(): %s", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -130,20 +134,22 @@ l9p_socket_accept(struct l9p_server *server, int conn_fd,
|
|||
NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
|
||||
|
||||
if (err != 0) {
|
||||
l9p_logf(L9P_WARNING, "cannot look up client name: %s",
|
||||
L9P_LOG(L9P_WARNING, "cannot look up client name: %s",
|
||||
gai_strerror(err));
|
||||
} else
|
||||
l9p_logf(L9P_INFO, "new connection from %s:%s", host, serv);
|
||||
L9P_LOG(L9P_INFO, "new connection from %s:%s", host, serv);
|
||||
|
||||
if (l9p_connection_init(server, &conn) != 0) {
|
||||
l9p_logf(L9P_ERROR, "cannot create new connection");
|
||||
L9P_LOG(L9P_ERROR, "cannot create new connection");
|
||||
return;
|
||||
}
|
||||
|
||||
sc = malloc(sizeof(sc));
|
||||
sc = calloc(1, sizeof(sc));
|
||||
sc->ls_conn = conn;
|
||||
sc->ls_fd = conn_fd;
|
||||
|
||||
l9p_connection_on_send_request(conn, l9p_socket_sendmsg, sc);
|
||||
l9p_connection_on_send_response(conn, l9p_socket_send_response, sc);
|
||||
l9p_connection_on_get_response_buffer(conn, l9p_socket_get_response_buffer, sc);
|
||||
pthread_create(&sc->ls_thread, NULL, l9p_socket_thread, sc);
|
||||
}
|
||||
|
||||
|
@ -151,6 +157,7 @@ static void *
|
|||
l9p_socket_thread(void *arg)
|
||||
{
|
||||
struct l9p_socket_softc *sc = (struct l9p_socket_softc *)arg;
|
||||
struct iovec iov;
|
||||
void *buf;
|
||||
size_t length;
|
||||
|
||||
|
@ -158,10 +165,12 @@ l9p_socket_thread(void *arg)
|
|||
if (l9p_socket_readmsg(sc, &buf, &length) != 0)
|
||||
break;
|
||||
|
||||
l9p_connection_recv(sc->ls_conn, buf, length);
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = length;
|
||||
l9p_connection_recv(sc->ls_conn, &iov, 1, NULL);
|
||||
}
|
||||
|
||||
l9p_logf(L9P_INFO, "connection closed");
|
||||
L9P_LOG(L9P_INFO, "connection closed");
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
@ -169,46 +178,63 @@ static int
|
|||
l9p_socket_readmsg(struct l9p_socket_softc *sc, void **buf, size_t *size)
|
||||
{
|
||||
uint32_t msize;
|
||||
uint32_t toread;
|
||||
void *buffer;
|
||||
int fd = sc->ls_fd;
|
||||
|
||||
if (xread(fd, &msize, sizeof(uint32_t)) != sizeof(uint32_t)) {
|
||||
l9p_logf(L9P_ERROR, "short read: %s", strerror(errno));
|
||||
buffer = malloc(sizeof(uint32_t));
|
||||
|
||||
if (xread(fd, buffer, sizeof(uint32_t)) != sizeof(uint32_t)) {
|
||||
L9P_LOG(L9P_ERROR, "short read: %s", strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
msize -= sizeof(msize);
|
||||
buffer = malloc(msize);
|
||||
msize = *(uint32_t *)buffer;
|
||||
toread = msize - sizeof(uint32_t);
|
||||
buffer = realloc(buffer, msize);
|
||||
|
||||
if (xread(fd, buffer, msize) != msize) {
|
||||
l9p_logf(L9P_ERROR, "short read: %s", strerror(errno));
|
||||
if (xread(fd, buffer + sizeof(uint32_t), toread) != toread) {
|
||||
L9P_LOG(L9P_ERROR, "short read: %s", strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
*size = msize;
|
||||
*buf = buffer;
|
||||
l9p_logf(L9P_INFO, "%p: read complete message, buf=%p size=%d", sc->ls_conn, buffer, msize);
|
||||
L9P_LOG(L9P_INFO, "%p: read complete message, buf=%p size=%d", sc->ls_conn, buffer, msize);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
l9p_socket_sendmsg(void *buf, size_t len, void *arg)
|
||||
static int
|
||||
l9p_socket_get_response_buffer(struct l9p_request *req, struct iovec *iov,
|
||||
size_t *niovp, void *arg)
|
||||
{
|
||||
size_t size = req->lr_conn->lc_msize;
|
||||
void *buf;
|
||||
|
||||
buf = malloc(size);
|
||||
iov[0].iov_base = buf;
|
||||
iov[0].iov_len = size;
|
||||
|
||||
*niovp = 1;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
l9p_socket_send_response(struct l9p_request *req, const struct iovec *iov,
|
||||
const size_t niov, const size_t iolen, void *arg)
|
||||
{
|
||||
struct l9p_socket_softc *sc = (struct l9p_socket_softc *)arg;
|
||||
uint32_t msize = (uint32_t)len + sizeof(uint32_t);
|
||||
|
||||
l9p_logf(L9P_DEBUG, "%p: sending reply, buf=%p, size=%d", arg, buf, len);
|
||||
L9P_LOG(L9P_DEBUG, "%p: sending reply, buf=%p, size=%d", arg,
|
||||
iov[0].iov_base, iolen);
|
||||
|
||||
if (xwrite(sc->ls_fd, &msize, sizeof(uint32_t)) != sizeof(uint32_t)) {
|
||||
l9p_logf(L9P_ERROR, "short write: %s", strerror(errno));
|
||||
return;
|
||||
if (xwrite(sc->ls_fd, iov[0].iov_base, iolen) != iolen) {
|
||||
L9_LOG(L9P_ERROR, "short write: %s", strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (xwrite(sc->ls_fd, buf, len) != len) {
|
||||
l9p_logf(L9P_ERROR, "short write: %s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
249
utils.c
Normal file
249
utils.c
Normal file
|
@ -0,0 +1,249 @@
|
|||
/*
|
||||
* 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 <assert.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/sbuf.h>
|
||||
#include "lib9p.h"
|
||||
#include "fcall.h"
|
||||
|
||||
static const char *ftype_names[] = {
|
||||
"Tversion",
|
||||
"Rversion",
|
||||
"Tauth",
|
||||
"Rauth",
|
||||
"Tattach",
|
||||
"Rattach",
|
||||
"Terror",
|
||||
"Rerror",
|
||||
"Tflush",
|
||||
"Rflush",
|
||||
"Twalk",
|
||||
"Rwalk",
|
||||
"Topen",
|
||||
"Ropen",
|
||||
"Tcreate",
|
||||
"Rcreate",
|
||||
"Tread",
|
||||
"Rread",
|
||||
"Twrite",
|
||||
"Rwrite",
|
||||
"Tclunk",
|
||||
"Rclunk",
|
||||
"Tremove",
|
||||
"Rremove",
|
||||
"Tstat",
|
||||
"Rstat",
|
||||
"Twstat",
|
||||
"Rwstat"
|
||||
};
|
||||
|
||||
void
|
||||
l9p_seek_iov(struct iovec *iov1, size_t niov1, struct iovec *iov2,
|
||||
size_t *niov2, size_t seek)
|
||||
{
|
||||
size_t remainder = 0;
|
||||
size_t left = seek;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < niov1; i++) {
|
||||
size_t toseek = MIN(left, iov1[i].iov_len);
|
||||
left -= toseek;
|
||||
|
||||
if (toseek == iov1[i].iov_len)
|
||||
continue;
|
||||
|
||||
if (left == 0) {
|
||||
remainder = toseek;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (j = i; j < niov1; j++) {
|
||||
iov2[j - i].iov_base = iov1[j].iov_base + remainder;
|
||||
iov2[j - i].iov_len = iov1[j].iov_len - remainder;
|
||||
remainder = 0;
|
||||
}
|
||||
|
||||
*niov2 = j - i;
|
||||
}
|
||||
|
||||
int
|
||||
l9p_truncate_iov(struct iovec *iov, size_t niov, size_t length)
|
||||
{
|
||||
int i;
|
||||
size_t done = 0;
|
||||
|
||||
for (i = 0; i < niov; i++) {
|
||||
size_t toseek = MIN(length - done, iov[i].iov_len);
|
||||
done += toseek;
|
||||
|
||||
if (toseek < iov[i].iov_len) {
|
||||
iov[i].iov_len = toseek;
|
||||
return (i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return (niov);
|
||||
}
|
||||
|
||||
void
|
||||
l9p_describe_qid(struct l9p_qid *qid, struct sbuf *sb)
|
||||
{
|
||||
|
||||
assert(qid != NULL);
|
||||
assert(sb != NULL);
|
||||
|
||||
sbuf_printf(sb, "<0x%02x,%u,0x%016llx>", qid->type, qid->version,
|
||||
qid->path);
|
||||
}
|
||||
|
||||
void
|
||||
l9p_describe_stat(struct l9p_stat *st, struct sbuf *sb)
|
||||
{
|
||||
|
||||
assert(st != NULL);
|
||||
assert(sb != NULL);
|
||||
|
||||
sbuf_printf(sb, "type=0x%04x dev=%d name=\"%s\" uid=\"%s\"",
|
||||
st->type, st->dev, st->name, st->uid);
|
||||
}
|
||||
|
||||
void
|
||||
l9p_describe_fcall(union l9p_fcall *fcall, enum l9p_version version,
|
||||
struct sbuf *sb)
|
||||
{
|
||||
uint8_t type;
|
||||
int i;
|
||||
|
||||
assert(fcall != NULL);
|
||||
assert(sb != NULL);
|
||||
assert(version <= L9P_2000L && version >= L9P_2000);
|
||||
|
||||
type = fcall->hdr.type;
|
||||
|
||||
if (type < 100 || type > 127) {
|
||||
sbuf_printf(sb, "<unknown request %d> tag=%d", type,
|
||||
fcall->hdr.tag);
|
||||
return;
|
||||
}
|
||||
|
||||
sbuf_printf(sb, "%s tag=%d", ftype_names[type - L9P_TVERSION],
|
||||
fcall->hdr.tag);
|
||||
|
||||
switch (type) {
|
||||
case L9P_TVERSION:
|
||||
case L9P_RVERSION:
|
||||
sbuf_printf(sb, " version=\"%s\" msize=%d", fcall->version.version,
|
||||
fcall->version.msize);
|
||||
return;
|
||||
case L9P_TAUTH:
|
||||
sbuf_printf(sb, "afid=%d uname=\"%s\" aname=\"%s\"", fcall->hdr.fid,
|
||||
fcall->tauth.uname, fcall->tauth.aname);
|
||||
return;
|
||||
case L9P_TATTACH:
|
||||
sbuf_printf(sb, " fid=%d afid=%d uname=\"%s\" aname=\"%s\"",
|
||||
fcall->hdr.fid, fcall->tattach.afid, fcall->tattach.uname,
|
||||
fcall->tattach.aname);
|
||||
return;
|
||||
case L9P_TFLUSH:
|
||||
sbuf_printf(sb, " oldtag=%d", fcall->tflush.oldtag);
|
||||
return;
|
||||
case L9P_TWALK:
|
||||
sbuf_printf(sb, " fid=%d newfid=%d wname=\"", fcall->hdr.fid,
|
||||
fcall->twalk.newfid);
|
||||
|
||||
for (i = 0; i < fcall->twalk.nwname; i++) {
|
||||
sbuf_printf(sb, "%s", fcall->twalk.wname[i]);
|
||||
if (i != fcall->twalk.nwname - 1)
|
||||
sbuf_printf(sb, "/");
|
||||
}
|
||||
sbuf_printf(sb, "\"");
|
||||
return;
|
||||
case L9P_RWALK:
|
||||
sbuf_printf(sb, " wqid=");
|
||||
for (i = 0; i < fcall->rwalk.nwqid; i++) {
|
||||
l9p_describe_qid(&fcall->rwalk.wqid[i], sb);
|
||||
if (i != fcall->rwalk.nwqid - 1)
|
||||
sbuf_printf(sb, ",");
|
||||
}
|
||||
|
||||
return;
|
||||
case L9P_TOPEN:
|
||||
sbuf_printf(sb, " fid=%d mode=%d", fcall->hdr.fid,
|
||||
fcall->tcreate.mode);
|
||||
|
||||
return;
|
||||
case L9P_ROPEN:
|
||||
sbuf_printf(sb, " qid=");
|
||||
l9p_describe_qid(&fcall->ropen.qid, sb);
|
||||
sbuf_printf(sb, " iounit=%d", fcall->ropen.iounit);
|
||||
return;
|
||||
case L9P_TCREATE:
|
||||
sbuf_printf(sb, " fid=%d name=\"%s\" perm=0x%08x mode=%d",
|
||||
fcall->hdr.fid, fcall->tcreate.name, fcall->tcreate.perm,
|
||||
fcall->tcreate.mode);
|
||||
return;
|
||||
case L9P_RCREATE:
|
||||
return;
|
||||
case L9P_TREAD:
|
||||
sbuf_printf(sb, " fid=%d offset=%lu count=%u", fcall->hdr.fid,
|
||||
fcall->io.offset, fcall->io.count);
|
||||
return;
|
||||
|
||||
case L9P_RREAD:
|
||||
case L9P_RWRITE:
|
||||
sbuf_printf(sb, " count=%d", fcall->io.count);
|
||||
return;
|
||||
case L9P_TWRITE:
|
||||
sbuf_printf(sb, " fid=%d offset=%lu count=%u", fcall->hdr.fid,
|
||||
fcall->io.offset, fcall->io.count);
|
||||
return;
|
||||
case L9P_TCLUNK:
|
||||
sbuf_printf(sb, " fid=%d ", fcall->hdr.fid);
|
||||
return;
|
||||
case L9P_TREMOVE:
|
||||
sbuf_printf(sb, " fid=%d", fcall->hdr.fid);
|
||||
return;
|
||||
case L9P_RREMOVE:
|
||||
return;
|
||||
case L9P_TSTAT:
|
||||
sbuf_printf(sb, " fid=%d", fcall->hdr.fid);
|
||||
return;
|
||||
case L9P_RSTAT:
|
||||
sbuf_printf(sb, " ");
|
||||
l9p_describe_stat(&fcall->rstat.stat, sb);
|
||||
return;
|
||||
case L9P_TWSTAT:
|
||||
sbuf_printf(sb, " fid=%d", fcall->hdr.fid);
|
||||
return;
|
||||
case L9P_RWSTAT:
|
||||
return;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue