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:
Jakub Klama 2016-01-28 00:40:43 +01:00
parent 080c92c18f
commit 91ad441d73
11 changed files with 729 additions and 280 deletions

View file

@ -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>

View file

@ -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;
}

View file

@ -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)
{

View file

@ -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
View file

@ -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
View file

@ -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
View file

@ -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 */

View file

@ -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
View file

@ -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) {

View file

@ -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
View 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;
}
}