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
|
LIB= 9p
|
||||||
SHLIB_MAJOR= 1
|
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
|
INCS= lib9p.h fcall.h log.h backend/fs.h
|
||||||
CFLAGS= -g -O0
|
CFLAGS= -g -O0
|
||||||
|
|
||||||
|
LIBADD= sbuf
|
||||||
|
|
||||||
.include <bsd.lib.mk>
|
.include <bsd.lib.mk>
|
||||||
|
|
63
backend/fs.c
63
backend/fs.c
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -53,6 +54,7 @@ static void fs_wstat(void *, struct l9p_request *);
|
||||||
struct fs_softc
|
struct fs_softc
|
||||||
{
|
{
|
||||||
const char *fs_rootpath;
|
const char *fs_rootpath;
|
||||||
|
bool fs_readonly;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct openfile
|
struct openfile
|
||||||
|
@ -67,7 +69,7 @@ open_fid(const char *path)
|
||||||
{
|
{
|
||||||
struct openfile *ret;
|
struct openfile *ret;
|
||||||
|
|
||||||
ret = malloc(sizeof(*ret));
|
ret = calloc(1, sizeof(*ret));
|
||||||
ret->fd = -1;
|
ret->fd = -1;
|
||||||
ret->name = strdup(path);
|
ret->name = strdup(path);
|
||||||
return (ret);
|
return (ret);
|
||||||
|
@ -79,7 +81,7 @@ dostat(struct l9p_stat *s, char *name, struct stat *buf)
|
||||||
char *user = getenv("USER");
|
char *user = getenv("USER");
|
||||||
s->type = 0;
|
s->type = 0;
|
||||||
s->dev = 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.path = buf->st_ino;
|
||||||
s->qid.version = 0;
|
s->qid.version = 0;
|
||||||
s->mode = buf->st_mode & 0777;
|
s->mode = buf->st_mode & 0777;
|
||||||
|
@ -112,6 +114,19 @@ fs_attach(void *softc, struct l9p_request *req)
|
||||||
static void
|
static void
|
||||||
fs_clunk(void *softc, struct l9p_request *req)
|
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);
|
l9p_respond(req, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,12 +139,13 @@ fs_create(void *softc, struct l9p_request *req)
|
||||||
static void
|
static void
|
||||||
fs_flush(void *softc, struct l9p_request *req)
|
fs_flush(void *softc, struct l9p_request *req)
|
||||||
{
|
{
|
||||||
|
l9p_respond(req, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fs_open(void *softc, struct l9p_request *req)
|
fs_open(void *softc, struct l9p_request *req)
|
||||||
{
|
{
|
||||||
|
struct l9p_connection *conn = req->lr_conn;
|
||||||
struct openfile *file;
|
struct openfile *file;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
|
@ -142,12 +158,12 @@ fs_open(void *softc, struct l9p_request *req)
|
||||||
} else {
|
} else {
|
||||||
file->fd = open(file->name, O_RDONLY);
|
file->fd = open(file->name, O_RDONLY);
|
||||||
if (file->fd < 0) {
|
if (file->fd < 0) {
|
||||||
l9p_respond(req, "ENOPERM");
|
l9p_respond(req, "Permission denied");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
req->lr_resp.ropen.iounit = 512;
|
req->lr_resp.ropen.iounit = conn->lc_max_io_size;
|
||||||
l9p_respond(req, NULL);
|
l9p_respond(req, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,6 +171,7 @@ static void
|
||||||
fs_read(void *softc, struct l9p_request *req)
|
fs_read(void *softc, struct l9p_request *req)
|
||||||
{
|
{
|
||||||
struct openfile *file;
|
struct openfile *file;
|
||||||
|
struct l9p_connection *conn = req->lr_conn;
|
||||||
struct l9p_stat l9stat;
|
struct l9p_stat l9stat;
|
||||||
|
|
||||||
file = req->lr_fid->lo_aux;
|
file = req->lr_fid->lo_aux;
|
||||||
|
@ -163,15 +180,24 @@ fs_read(void *softc, struct l9p_request *req)
|
||||||
struct dirent *d;
|
struct dirent *d;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
d = readdir(file->dir);
|
for (;;) {
|
||||||
if (d) {
|
d = readdir(file->dir);
|
||||||
stat(d->d_name, &st);
|
if (d) {
|
||||||
dostat(&l9stat, d->d_name, &st);
|
stat(d->d_name, &st);
|
||||||
l9p_pack_stat(req, &l9stat);
|
dostat(&l9stat, d->d_name, &st);
|
||||||
|
if (l9p_pack_stat(req, &l9stat) != 0) {
|
||||||
|
seekdir(file->dir, -1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
req->lr_resp.io.data = malloc(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 = read(file->fd, req->lr_resp.io.data, req->lr_req.io.count);
|
req->lr_resp.io.count = readv(file->fd, req->lr_data_iov, niov);
|
||||||
}
|
}
|
||||||
|
|
||||||
l9p_respond(req, NULL);
|
l9p_respond(req, NULL);
|
||||||
|
@ -186,7 +212,16 @@ fs_remove(void *softc, struct l9p_request *req)
|
||||||
static void
|
static void
|
||||||
fs_stat(void *softc, struct l9p_request *req)
|
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
|
static void
|
||||||
|
@ -200,11 +235,11 @@ fs_walk(void *softc, struct l9p_request *req)
|
||||||
strcpy(name, file->name);
|
strcpy(name, file->name);
|
||||||
|
|
||||||
/* build full path. Stat full path. Done */
|
/* 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, "/");
|
||||||
strcat(name, req->lr_req.twalk.wname[i]);
|
strcat(name, req->lr_req.twalk.wname[i]);
|
||||||
if (stat(name, &buf) < 0){
|
if (stat(name, &buf) < 0){
|
||||||
l9p_respond(req, "no such file");
|
l9p_respond(req, "No such file or directory");
|
||||||
free(name);
|
free(name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
79
connection.c
79
connection.c
|
@ -26,6 +26,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
#include "lib9p.h"
|
#include "lib9p.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
@ -35,7 +37,7 @@ l9p_server_init(struct l9p_server **serverp, struct l9p_backend *backend)
|
||||||
{
|
{
|
||||||
struct l9p_server *server;
|
struct l9p_server *server;
|
||||||
|
|
||||||
server = malloc(sizeof(*server));
|
server = calloc(1, sizeof(*server));
|
||||||
server->ls_backend = backend;
|
server->ls_backend = backend;
|
||||||
LIST_INIT(&server->ls_conns);
|
LIST_INIT(&server->ls_conns);
|
||||||
|
|
||||||
|
@ -48,8 +50,11 @@ l9p_connection_init(struct l9p_server *server, struct l9p_connection **conn)
|
||||||
{
|
{
|
||||||
struct l9p_connection *newconn;
|
struct l9p_connection *newconn;
|
||||||
|
|
||||||
newconn = malloc(sizeof(*newconn));
|
newconn = calloc(1, sizeof(*newconn));
|
||||||
newconn->lc_server = server;
|
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);
|
LIST_INSERT_HEAD(&server->ls_conns, newconn, lc_link);
|
||||||
*conn = newconn;
|
*conn = newconn;
|
||||||
|
|
||||||
|
@ -63,29 +68,48 @@ l9p_connection_free(struct l9p_connection *conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
l9p_connection_on_send_request(struct l9p_connection *conn,
|
l9p_connection_on_send_response(struct l9p_connection *conn,
|
||||||
void (*cb)(void *, size_t, void *), void *softc)
|
l9p_send_response_t cb, void *aux)
|
||||||
{
|
{
|
||||||
|
|
||||||
conn->lc_send_request = cb;
|
conn->lc_send_response = cb;
|
||||||
conn->lc_send_request_aux = softc;
|
conn->lc_send_response_aux = aux;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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;
|
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;
|
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) {
|
req->lr_req_msg.lm_mode = L9P_UNPACK;
|
||||||
l9p_logf(L9P_WARNING, "cannot unpack received message");
|
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);
|
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 *
|
struct l9p_openfile *
|
||||||
l9p_connection_find_fid(struct l9p_connection *conn, uint32_t fid)
|
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);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
l9p_connection_remove_fid(struct l9p_connection *conn, struct l9p_openfile *fid)
|
||||||
|
{
|
||||||
|
|
||||||
|
LIST_REMOVE(fid, lo_link);
|
||||||
|
}
|
||||||
|
|
||||||
struct l9p_request *
|
struct l9p_request *
|
||||||
l9p_connection_find_tag(struct l9p_connection *conn, uint32_t tag)
|
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_f_rstat
|
||||||
{
|
{
|
||||||
struct l9p_hdr hdr;
|
struct l9p_hdr hdr;
|
||||||
uint16_t nstat;
|
struct l9p_stat stat;
|
||||||
uint8_t *stat;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct l9p_f_twstat
|
struct l9p_f_twstat
|
||||||
|
@ -224,4 +223,4 @@ union l9p_fcall
|
||||||
struct l9p_f_io io;
|
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
|
#ifndef LIB9P_LIB9P_H
|
||||||
#define LIB9P_LIB9P_H
|
#define LIB9P_LIB9P_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#include <sys/sbuf.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include "fcall.h"
|
#include "fcall.h"
|
||||||
|
|
||||||
#define L9P_ENOFID "FID does not exist"
|
#define L9P_DEFAULT_MSIZE 8192
|
||||||
#define L9P_ENOFUNC "Function not implemented"
|
#define L9P_MAX_IOV 8
|
||||||
#define L9P_EINTR "Interrupted"
|
|
||||||
|
#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
|
enum l9p_pack_mode
|
||||||
{
|
{
|
||||||
|
@ -52,23 +66,38 @@ enum l9p_integer_type
|
||||||
L9P_QWORD = 8
|
L9P_QWORD = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum l9p_version
|
||||||
|
{
|
||||||
|
L9P_2000 = 1,
|
||||||
|
L9P_2000U = 2,
|
||||||
|
L9P_2000L = 3
|
||||||
|
};
|
||||||
|
|
||||||
struct l9p_message
|
struct l9p_message
|
||||||
{
|
{
|
||||||
enum l9p_pack_mode lm_mode;
|
enum l9p_pack_mode lm_mode;
|
||||||
uint8_t *lm_buffer;
|
struct iovec lm_iov[L9P_MAX_IOV];
|
||||||
uint8_t *lm_pos;
|
size_t lm_niov;
|
||||||
uint8_t *lm_end;
|
size_t lm_cursor_iov;
|
||||||
|
size_t lm_cursor_offset;
|
||||||
|
size_t lm_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct l9p_request
|
struct l9p_request
|
||||||
{
|
{
|
||||||
uint32_t lr_tag;
|
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_req;
|
||||||
union l9p_fcall lr_resp;
|
union l9p_fcall lr_resp;
|
||||||
struct l9p_openfile *lr_fid;
|
struct l9p_openfile *lr_fid;
|
||||||
struct l9p_openfile *lr_newfid;
|
struct l9p_openfile *lr_newfid;
|
||||||
struct l9p_connection *lr_conn;
|
struct l9p_connection *lr_conn;
|
||||||
pthread_t lr_thread;
|
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;
|
LIST_ENTRY(l9p_request) lr_link;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -85,9 +114,14 @@ struct l9p_openfile
|
||||||
struct l9p_connection
|
struct l9p_connection
|
||||||
{
|
{
|
||||||
struct l9p_server *lc_server;
|
struct l9p_server *lc_server;
|
||||||
|
enum l9p_version lc_version;
|
||||||
pthread_mutex_t lc_send_lock;
|
pthread_mutex_t lc_send_lock;
|
||||||
void (*lc_send_request)(const void *, const size_t, void *);
|
uint32_t lc_msize;
|
||||||
void *lc_send_request_aux;
|
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;
|
void *lc_softc;
|
||||||
LIST_HEAD(, l9p_request) lc_requests;
|
LIST_HEAD(, l9p_request) lc_requests;
|
||||||
LIST_HEAD(, l9p_openfile) lc_files;
|
LIST_HEAD(, l9p_openfile) lc_files;
|
||||||
|
@ -97,6 +131,7 @@ struct l9p_connection
|
||||||
struct l9p_server
|
struct l9p_server
|
||||||
{
|
{
|
||||||
struct l9p_backend *ls_backend;
|
struct l9p_backend *ls_backend;
|
||||||
|
enum l9p_version ls_max_version;
|
||||||
LIST_HEAD(, l9p_connection) ls_conns;
|
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_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);
|
uint16_t l9p_sizeof_stat(struct l9p_stat *stat);
|
||||||
int l9p_pack_stat(struct l9p_request *req, struct l9p_stat *s);
|
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_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_on_send_response(struct l9p_connection *conn,
|
||||||
void l9p_connection_recv(struct l9p_connection *conn, void *buf, size_t len);
|
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);
|
void l9p_connection_close(struct l9p_connection *conn);
|
||||||
struct l9p_openfile *l9p_connection_find_fid(struct l9p_connection *conn, uint32_t fid);
|
struct l9p_openfile *l9p_connection_alloc_fid(struct l9p_connection *conn,
|
||||||
struct l9p_request *l9p_connection_find_tag(struct l9p_connection *conn, uint32_t tag);
|
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);
|
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
|
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_list ap;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
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);
|
vfprintf(stderr, fmt, ap);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
4
log.h
4
log.h
|
@ -36,6 +36,8 @@ enum l9p_log_level
|
||||||
L9P_ERROR
|
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 */
|
#endif /* LIB9P_LOG_H */
|
||||||
|
|
299
lib9p.c → pack.c
299
lib9p.c → pack.c
|
@ -31,124 +31,119 @@
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
#include "lib9p.h"
|
#include "lib9p.h"
|
||||||
|
|
||||||
#define N(ary) (sizeof(ary) / sizeof(*ary))
|
#define N(ary) (sizeof(ary) / sizeof(*ary))
|
||||||
#define STRING_SIZE(s) (L9P_WORD + strlen(s))
|
#define STRING_SIZE(s) (L9P_WORD + strlen(s))
|
||||||
#define QID_SIZE (L9P_BYTE + L9P_DWORD + L9P_QWORD)
|
#define QID_SIZE (L9P_BYTE + L9P_DWORD + L9P_QWORD)
|
||||||
|
|
||||||
static void l9p_puint(struct l9p_message *, enum l9p_integer_type, uint32_t *);
|
static int l9p_iov_io(struct l9p_message *, void *, size_t);
|
||||||
static inline void l9p_pu8(struct l9p_message *, uint8_t *);
|
static int l9p_puint(struct l9p_message *, enum l9p_integer_type, uint32_t *);
|
||||||
static inline void l9p_pu16(struct l9p_message *, uint16_t *);
|
static inline int l9p_pu8(struct l9p_message *, uint8_t *);
|
||||||
static inline void l9p_pu32(struct l9p_message *, uint32_t *);
|
static inline int l9p_pu16(struct l9p_message *, uint16_t *);
|
||||||
static inline void l9p_pu64(struct l9p_message *, uint64_t *);
|
static inline int l9p_pu32(struct l9p_message *, uint32_t *);
|
||||||
static void l9p_pustring(struct l9p_message *, char **s);
|
static inline int l9p_pu64(struct l9p_message *, uint64_t *);
|
||||||
static void l9p_pustrings(struct l9p_message *, uint16_t *,char *[], size_t);
|
static int l9p_pustring(struct l9p_message *, char **s);
|
||||||
static void l9p_pudata(struct l9p_message *, uint8_t **, size_t);
|
static int l9p_pustrings(struct l9p_message *, uint16_t *,char *[], size_t);
|
||||||
static void l9p_puqid(struct l9p_message *, struct l9p_qid *);
|
static int l9p_pudata(struct l9p_message *, uint8_t **, size_t);
|
||||||
static void l9p_puqids(struct l9p_message *, uint16_t *, struct l9p_qid *q,
|
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);
|
size_t);
|
||||||
|
|
||||||
|
static int
|
||||||
static void
|
l9p_iov_io(struct l9p_message *msg, void *buffer, size_t len)
|
||||||
l9p_puint(struct l9p_message *msg, enum l9p_integer_type size, uint32_t *val)
|
|
||||||
{
|
{
|
||||||
uint8_t *pos;
|
size_t done = 0;
|
||||||
int v;
|
size_t left = len;
|
||||||
|
|
||||||
if(msg->lm_pos + size <= msg->lm_end) {
|
assert(msg != NULL);
|
||||||
pos = (uint8_t*)msg->lm_pos;
|
assert(buffer != NULL);
|
||||||
switch (msg->lm_mode) {
|
|
||||||
case L9P_PACK:
|
if (len == 0)
|
||||||
v = *val;
|
return (0);
|
||||||
switch (size) {
|
|
||||||
case L9P_DWORD:
|
if (msg->lm_cursor_iov >= msg->lm_niov)
|
||||||
pos[3] = v>>24;
|
return (-1);
|
||||||
pos[2] = v>>16;
|
|
||||||
case L9P_WORD:
|
while (left > 0) {
|
||||||
pos[1] = v>>8;
|
size_t idx = msg->lm_cursor_iov;
|
||||||
case L9P_BYTE:
|
size_t space = msg->lm_iov[idx].iov_len - msg->lm_cursor_offset;
|
||||||
pos[0] = v;
|
size_t towrite = MIN(space, left);
|
||||||
break;
|
|
||||||
}
|
if (msg->lm_mode == L9P_PACK)
|
||||||
case L9P_UNPACK:
|
memcpy(msg->lm_iov[idx].iov_base + msg->lm_cursor_offset,
|
||||||
v = 0;
|
buffer + done, towrite);
|
||||||
switch (size) {
|
|
||||||
case L9P_DWORD:
|
if (msg->lm_mode == L9P_UNPACK)
|
||||||
v |= pos[3]<<24;
|
memcpy(buffer + done, msg->lm_iov[idx].iov_base +
|
||||||
v |= pos[2]<<16;
|
msg->lm_cursor_offset, towrite);
|
||||||
case L9P_WORD:
|
|
||||||
v |= pos[1]<<8;
|
msg->lm_cursor_offset += towrite;
|
||||||
case L9P_BYTE:
|
|
||||||
v |= pos[0];
|
if (space - towrite == 0) {
|
||||||
break;
|
/* Advance to next iov */
|
||||||
}
|
msg->lm_cursor_iov++;
|
||||||
*val = v;
|
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)
|
l9p_pu8(struct l9p_message *msg, uint8_t *val)
|
||||||
{
|
{
|
||||||
uint32_t v;
|
return (l9p_iov_io(msg, val, sizeof(uint8_t)));
|
||||||
|
|
||||||
v = *val;
|
|
||||||
l9p_puint(msg, L9P_BYTE, &v);
|
|
||||||
*val = (uint8_t)v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline int
|
||||||
l9p_pu16(struct l9p_message *msg, uint16_t *val)
|
l9p_pu16(struct l9p_message *msg, uint16_t *val)
|
||||||
{
|
{
|
||||||
uint32_t v;
|
return (l9p_iov_io(msg, val, sizeof(uint16_t)));
|
||||||
|
|
||||||
v = *val;
|
|
||||||
l9p_puint(msg, L9P_WORD, &v);
|
|
||||||
*val = (uint16_t)v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline int
|
||||||
l9p_pu32(struct l9p_message *msg, uint32_t *val)
|
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)
|
l9p_pu64(struct l9p_message *msg, uint64_t *val)
|
||||||
{
|
{
|
||||||
uint32_t vl, vb;
|
return(l9p_iov_io(msg, val, sizeof(uint64_t)));
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
l9p_pustring(struct l9p_message *msg, char **s)
|
l9p_pustring(struct l9p_message *msg, char **s)
|
||||||
{
|
{
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
|
|
||||||
if(msg->lm_mode == L9P_PACK)
|
if (msg->lm_mode == L9P_PACK)
|
||||||
len = strlen(*s);
|
len = strlen(*s);
|
||||||
l9p_pu16(msg, &len);
|
|
||||||
|
|
||||||
if (msg->lm_pos + len <= msg->lm_end) {
|
if (l9p_pu16(msg, &len) < 0)
|
||||||
if (msg->lm_mode == L9P_UNPACK) {
|
return (-1);
|
||||||
*s = malloc(len + 1);
|
|
||||||
memcpy(*s, msg->lm_pos, len);
|
if (msg->lm_mode == L9P_UNPACK)
|
||||||
(*s)[len] = '\0';
|
*s = calloc(1, len + 1);
|
||||||
} else
|
|
||||||
memcpy(msg->lm_pos, *s, len);
|
if (l9p_iov_io(msg, *s, len) < 0)
|
||||||
}
|
return (-1);
|
||||||
msg->lm_pos += len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
l9p_pustrings(struct l9p_message *msg, uint16_t *num, char *strings[],
|
l9p_pustrings(struct l9p_message *msg, uint16_t *num, char *strings[],
|
||||||
size_t max)
|
size_t max)
|
||||||
{
|
{
|
||||||
|
@ -157,105 +152,78 @@ l9p_pustrings(struct l9p_message *msg, uint16_t *num, char *strings[],
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
|
|
||||||
l9p_pu16(msg, num);
|
l9p_pu16(msg, num);
|
||||||
if (*num > max) {
|
|
||||||
msg->lm_pos = msg->lm_end+1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
s = NULL;
|
for (i = 0; i < MIN(*num, max); i++) {
|
||||||
|
if (l9p_pustring(msg, &strings[i]) < 0)
|
||||||
if (msg->lm_mode == L9P_UNPACK) {
|
return (-1);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
l9p_pudata(struct l9p_message *msg, uint8_t **data, size_t len)
|
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)
|
||||||
if (msg->lm_mode == L9P_UNPACK) {
|
*data = malloc(len);
|
||||||
*data = malloc(len);
|
|
||||||
memcpy(*data, msg->lm_pos, len);
|
return (l9p_iov_io(msg, *data, len));
|
||||||
} else
|
|
||||||
memcpy(msg->lm_pos, *data, len);
|
|
||||||
}
|
|
||||||
msg->lm_pos += len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
l9p_puqid(struct l9p_message *msg, struct l9p_qid *qid)
|
l9p_puqid(struct l9p_message *msg, struct l9p_qid *qid)
|
||||||
{
|
{
|
||||||
l9p_pu8(msg, &qid->type);
|
int r = 0;
|
||||||
l9p_pu32(msg, &qid->version);
|
|
||||||
l9p_pu64(msg, &qid->path);
|
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,
|
l9p_puqids(struct l9p_message *msg, uint16_t *num, struct l9p_qid *qids,
|
||||||
size_t max)
|
size_t max)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
l9p_pu16(msg, num);
|
l9p_pu16(msg, num);
|
||||||
if (*num > max) {
|
|
||||||
msg->lm_pos = msg->lm_end + 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < *num; i++)
|
for (i = 0; i < *num; i++) {
|
||||||
l9p_puqid(msg, &qids[i]);
|
if (l9p_puqid(msg, &qids[i]) < 0)
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
l9p_pustat(struct l9p_message *msg, struct l9p_stat *stat)
|
l9p_pustat(struct l9p_message *msg, struct l9p_stat *stat)
|
||||||
{
|
{
|
||||||
|
int r = 0;
|
||||||
uint16_t size;
|
uint16_t size;
|
||||||
|
|
||||||
if(msg->lm_mode == L9P_PACK)
|
if (msg->lm_mode == L9P_PACK)
|
||||||
size = l9p_sizeof_stat(stat) - 2;
|
size = l9p_sizeof_stat(stat) - 2;
|
||||||
|
|
||||||
l9p_pu16(msg, &size);
|
r += l9p_pu16(msg, &size);
|
||||||
l9p_pu16(msg, &stat->type);
|
r += l9p_pu16(msg, &stat->type);
|
||||||
l9p_pu32(msg, &stat->dev);
|
r += l9p_pu32(msg, &stat->dev);
|
||||||
l9p_puqid(msg, &stat->qid);
|
r += l9p_puqid(msg, &stat->qid);
|
||||||
l9p_pu32(msg, &stat->mode);
|
r += l9p_pu32(msg, &stat->mode);
|
||||||
l9p_pu32(msg, &stat->atime);
|
r += l9p_pu32(msg, &stat->atime);
|
||||||
l9p_pu32(msg, &stat->mtime);
|
r += l9p_pu32(msg, &stat->mtime);
|
||||||
l9p_pu64(msg, &stat->length);
|
r += l9p_pu64(msg, &stat->length);
|
||||||
l9p_pustring(msg, &stat->name);
|
r += l9p_pustring(msg, &stat->name);
|
||||||
l9p_pustring(msg, &stat->uid);
|
r += l9p_pustring(msg, &stat->uid);
|
||||||
l9p_pustring(msg, &stat->gid);
|
r += l9p_pustring(msg, &stat->gid);
|
||||||
l9p_pustring(msg, &stat->muid);
|
r += l9p_pustring(msg, &stat->muid);
|
||||||
|
|
||||||
|
return (r);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
l9p_pufcall(struct l9p_message *msg, union l9p_fcall *fcall)
|
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_pu8(msg, &fcall->hdr.type);
|
||||||
l9p_pu16(msg, &fcall->hdr.tag);
|
l9p_pu16(msg, &fcall->hdr.tag);
|
||||||
|
|
||||||
|
@ -320,13 +288,11 @@ l9p_pufcall(struct l9p_message *msg, union l9p_fcall *fcall)
|
||||||
break;
|
break;
|
||||||
case L9P_RREAD:
|
case L9P_RREAD:
|
||||||
l9p_pu32(msg, &fcall->io.count);
|
l9p_pu32(msg, &fcall->io.count);
|
||||||
l9p_pudata(msg, &fcall->io.data, fcall->io.count);
|
|
||||||
break;
|
break;
|
||||||
case L9P_TWRITE:
|
case L9P_TWRITE:
|
||||||
l9p_pu32(msg, &fcall->hdr.fid);
|
l9p_pu32(msg, &fcall->hdr.fid);
|
||||||
l9p_pu64(msg, &fcall->io.offset);
|
l9p_pu64(msg, &fcall->io.offset);
|
||||||
l9p_pu32(msg, &fcall->io.count);
|
l9p_pu32(msg, &fcall->io.count);
|
||||||
l9p_pudata(msg, &fcall->io.data, fcall->io.count);
|
|
||||||
break;
|
break;
|
||||||
case L9P_RWRITE:
|
case L9P_RWRITE:
|
||||||
l9p_pu32(msg, &fcall->io.count);
|
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);
|
l9p_pu32(msg, &fcall->hdr.fid);
|
||||||
break;
|
break;
|
||||||
case L9P_RSTAT:
|
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;
|
break;
|
||||||
case L9P_TWSTAT: {
|
case L9P_TWSTAT:
|
||||||
uint16_t size;
|
{
|
||||||
l9p_pu32(msg, &fcall->hdr.fid);
|
uint16_t size;
|
||||||
l9p_pu16(msg, &size);
|
l9p_pu32(msg, &fcall->hdr.fid);
|
||||||
l9p_pustat(msg, &fcall->twstat.stat);
|
l9p_pu16(msg, &size);
|
||||||
|
l9p_pustat(msg, &fcall->twstat.stat);
|
||||||
|
}
|
||||||
break;
|
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);
|
return (0);
|
||||||
|
@ -358,7 +341,7 @@ l9p_sizeof_stat(struct l9p_stat *stat) {
|
||||||
+ L9P_DWORD /* dev */
|
+ L9P_DWORD /* dev */
|
||||||
+ QID_SIZE /* qid */
|
+ QID_SIZE /* qid */
|
||||||
+ 3 * L9P_DWORD /* mode, atime, mtime */
|
+ 3 * L9P_DWORD /* mode, atime, mtime */
|
||||||
+ L9P_DWORD /* length */
|
+ L9P_QWORD /* length */
|
||||||
+ STRING_SIZE(stat->name)
|
+ STRING_SIZE(stat->name)
|
||||||
+ STRING_SIZE(stat->uid)
|
+ STRING_SIZE(stat->uid)
|
||||||
+ STRING_SIZE(stat->gid)
|
+ STRING_SIZE(stat->gid)
|
138
request.c
138
request.c
|
@ -25,8 +25,11 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#include <sys/sbuf.h>
|
||||||
#include "lib9p.h"
|
#include "lib9p.h"
|
||||||
#include "fcall.h"
|
#include "fcall.h"
|
||||||
#include "log.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_twrite(struct l9p_request *req);
|
||||||
static void l9p_dispatch_twstat(struct l9p_request *req);
|
static void l9p_dispatch_twstat(struct l9p_request *req);
|
||||||
|
|
||||||
static struct
|
static const struct
|
||||||
{
|
{
|
||||||
enum l9p_ftype type;
|
enum l9p_ftype type;
|
||||||
void (*handler)(struct l9p_request *);
|
void (*handler)(struct l9p_request *);
|
||||||
|
@ -65,13 +68,25 @@ static struct
|
||||||
{L9P_TWSTAT, l9p_dispatch_twstat}
|
{L9P_TWSTAT, l9p_dispatch_twstat}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char *l9p_versions[] = {
|
||||||
|
"9P2000",
|
||||||
|
"9P2000.u",
|
||||||
|
"9P2000.L"
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
l9p_dispatch_request(struct l9p_request *req)
|
l9p_dispatch_request(struct l9p_request *req)
|
||||||
{
|
{
|
||||||
struct l9p_connection *conn = req->lr_conn;
|
struct l9p_connection *conn = req->lr_conn;
|
||||||
|
struct sbuf *sb = sbuf_new_auto();
|
||||||
int i;
|
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;
|
req->lr_tag = req->lr_req.hdr.tag;
|
||||||
|
|
||||||
for (i = 0; i < N(l9p_handlers); i++) {
|
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);
|
l9p_respond(req, L9P_ENOFUNC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,19 +104,12 @@ void
|
||||||
l9p_respond(struct l9p_request *req, const char *error)
|
l9p_respond(struct l9p_request *req, const char *error)
|
||||||
{
|
{
|
||||||
struct l9p_connection *conn = req->lr_conn;
|
struct l9p_connection *conn = req->lr_conn;
|
||||||
struct l9p_message msg;
|
struct sbuf *sb = sbuf_new_auto();
|
||||||
void *buf = malloc(1024 * 1024);
|
size_t iosize;
|
||||||
|
|
||||||
msg.lm_buffer = buf;
|
|
||||||
msg.lm_pos = buf;
|
|
||||||
msg.lm_end = buf + (1024 * 1024);
|
|
||||||
msg.lm_mode = L9P_PACK;
|
|
||||||
|
|
||||||
switch (req->lr_req.hdr.type) {
|
switch (req->lr_req.hdr.type) {
|
||||||
case L9P_TVERSION:
|
case L9P_TCLUNK:
|
||||||
break;
|
l9p_connection_remove_fid(conn, req->lr_fid);
|
||||||
|
|
||||||
case L9P_TWALK:
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,43 +122,66 @@ l9p_respond(struct l9p_request *req, const char *error)
|
||||||
req->lr_resp.error.ename = 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,
|
iosize = req->lr_resp_msg.lm_size;
|
||||||
conn->lc_send_request_aux);
|
|
||||||
|
/* 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
|
int
|
||||||
l9p_pack_stat(struct l9p_request *req, struct l9p_stat *st)
|
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);
|
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.count += size;
|
||||||
req->lr_resp.io.data = realloc(req->lr_resp.io.data,
|
return (0);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
l9p_dispatch_tversion(struct l9p_request *req)
|
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"))
|
if (!strcmp(req->lr_req.version.version, "9P"))
|
||||||
req->lr_resp.version.version = "9P";
|
req->lr_resp.version.version = "9P";
|
||||||
else if (!strcmp(req->lr_req.version.version, "9P2000"))
|
else if (!strcmp(req->lr_req.version.version, "9P2000"))
|
||||||
req->lr_resp.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
|
else
|
||||||
req->lr_resp.version.version = "unknown";
|
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);
|
l9p_respond(req, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,11 +190,7 @@ l9p_dispatch_tattach(struct l9p_request *req)
|
||||||
{
|
{
|
||||||
struct l9p_connection *conn = req->lr_conn;
|
struct l9p_connection *conn = req->lr_conn;
|
||||||
|
|
||||||
req->lr_fid = malloc(sizeof(struct l9p_openfile));
|
req->lr_fid = l9p_connection_alloc_fid(conn, req->lr_req.hdr.fid);
|
||||||
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);
|
|
||||||
|
|
||||||
conn->lc_server->ls_backend->attach(conn->lc_server->ls_backend->softc, req);
|
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;
|
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);
|
conn->lc_server->ls_backend->clunk(conn->lc_server->ls_backend->softc, req);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
l9p_dispatch_tflush(struct l9p_request *req)
|
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
|
static void
|
||||||
|
@ -187,15 +228,11 @@ l9p_dispatch_tcreate(struct l9p_request *req)
|
||||||
struct l9p_openfile *fid;
|
struct l9p_openfile *fid;
|
||||||
|
|
||||||
if (l9p_connection_find_fid(conn, req->lr_req.tcreate.hdr.fid) != NULL) {
|
if (l9p_connection_find_fid(conn, req->lr_req.tcreate.hdr.fid) != NULL) {
|
||||||
l9p_respond(req, "x");
|
l9p_respond(req, L9P_ENOFID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fid = malloc(sizeof(struct l9p_openfile));
|
req->lr_fid = l9p_connection_alloc_fid(conn, req->lr_req.tattach.afid);
|
||||||
fid->lo_fid = req->lr_req.tcreate.hdr.fid;
|
|
||||||
fid->lo_conn = conn;
|
|
||||||
LIST_INSERT_HEAD(&conn->lc_files, fid, lo_link);
|
|
||||||
|
|
||||||
conn->lc_server->ls_backend->create(conn->lc_server->ls_backend->softc, req);
|
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;
|
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);
|
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_connection *conn = req->lr_conn;
|
||||||
struct l9p_openfile *fid;
|
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
|
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) {
|
if (req->lr_req.twalk.hdr.fid != req->lr_req.twalk.newfid) {
|
||||||
req->lr_newfid = malloc(sizeof(struct l9p_openfile));
|
req->lr_newfid = l9p_connection_alloc_fid(conn, req->lr_req.twalk.newfid);
|
||||||
req->lr_newfid->lo_fid = req->lr_req.twalk.newfid;
|
if (req->lr_newfid == NULL) {
|
||||||
req->lr_newfid->lo_conn = conn;
|
l9p_respond(req, L9P_ENOFID);
|
||||||
LIST_INSERT_HEAD(&conn->lc_files, req->lr_newfid, lo_link);
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!conn->lc_server->ls_backend->walk) {
|
if (!conn->lc_server->ls_backend->walk) {
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/event.h>
|
#include <sys/event.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include "../lib9p.h"
|
#include "../lib9p.h"
|
||||||
#include "../log.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 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 void *l9p_socket_thread(void *);
|
||||||
static int xread(int, void *, size_t);
|
static int xread(int, void *, size_t);
|
||||||
static int xwrite(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);
|
&client_addr_len);
|
||||||
|
|
||||||
if (news < 0) {
|
if (news < 0) {
|
||||||
l9p_logf(L9P_WARNING, "accept(): %s", strerror(errno));
|
L9P_LOG(L9P_WARNING, "accept(): %s", strerror(errno));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,20 +134,22 @@ l9p_socket_accept(struct l9p_server *server, int conn_fd,
|
||||||
NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
|
NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
|
||||||
|
|
||||||
if (err != 0) {
|
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));
|
gai_strerror(err));
|
||||||
} else
|
} 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) {
|
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_conn = conn;
|
||||||
sc->ls_fd = conn_fd;
|
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);
|
pthread_create(&sc->ls_thread, NULL, l9p_socket_thread, sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,6 +157,7 @@ static void *
|
||||||
l9p_socket_thread(void *arg)
|
l9p_socket_thread(void *arg)
|
||||||
{
|
{
|
||||||
struct l9p_socket_softc *sc = (struct l9p_socket_softc *)arg;
|
struct l9p_socket_softc *sc = (struct l9p_socket_softc *)arg;
|
||||||
|
struct iovec iov;
|
||||||
void *buf;
|
void *buf;
|
||||||
size_t length;
|
size_t length;
|
||||||
|
|
||||||
|
@ -158,10 +165,12 @@ l9p_socket_thread(void *arg)
|
||||||
if (l9p_socket_readmsg(sc, &buf, &length) != 0)
|
if (l9p_socket_readmsg(sc, &buf, &length) != 0)
|
||||||
break;
|
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);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,46 +178,63 @@ static int
|
||||||
l9p_socket_readmsg(struct l9p_socket_softc *sc, void **buf, size_t *size)
|
l9p_socket_readmsg(struct l9p_socket_softc *sc, void **buf, size_t *size)
|
||||||
{
|
{
|
||||||
uint32_t msize;
|
uint32_t msize;
|
||||||
|
uint32_t toread;
|
||||||
void *buffer;
|
void *buffer;
|
||||||
int fd = sc->ls_fd;
|
int fd = sc->ls_fd;
|
||||||
|
|
||||||
if (xread(fd, &msize, sizeof(uint32_t)) != sizeof(uint32_t)) {
|
buffer = malloc(sizeof(uint32_t));
|
||||||
l9p_logf(L9P_ERROR, "short read: %s", strerror(errno));
|
|
||||||
|
if (xread(fd, buffer, sizeof(uint32_t)) != sizeof(uint32_t)) {
|
||||||
|
L9P_LOG(L9P_ERROR, "short read: %s", strerror(errno));
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
msize -= sizeof(msize);
|
msize = *(uint32_t *)buffer;
|
||||||
buffer = malloc(msize);
|
toread = msize - sizeof(uint32_t);
|
||||||
|
buffer = realloc(buffer, msize);
|
||||||
|
|
||||||
if (xread(fd, buffer, msize) != msize) {
|
if (xread(fd, buffer + sizeof(uint32_t), toread) != toread) {
|
||||||
l9p_logf(L9P_ERROR, "short read: %s", strerror(errno));
|
L9P_LOG(L9P_ERROR, "short read: %s", strerror(errno));
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
*size = msize;
|
*size = msize;
|
||||||
*buf = buffer;
|
*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);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
l9p_socket_sendmsg(void *buf, size_t len, void *arg)
|
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;
|
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)) {
|
if (xwrite(sc->ls_fd, iov[0].iov_base, iolen) != iolen) {
|
||||||
l9p_logf(L9P_ERROR, "short write: %s", strerror(errno));
|
L9_LOG(L9P_ERROR, "short write: %s", strerror(errno));
|
||||||
return;
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xwrite(sc->ls_fd, buf, len) != len) {
|
return (0);
|
||||||
l9p_logf(L9P_ERROR, "short write: %s", strerror(errno));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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