First pass at 9P2000.u support.

This commit is contained in:
Jakub Klama 2016-01-28 15:18:55 +01:00
parent 91ad441d73
commit d3e4c06341
8 changed files with 192 additions and 73 deletions

View file

@ -31,11 +31,16 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <pwd.h>
#include <grp.h>
#include "../lib9p.h"
#include "../log.h"
@ -81,21 +86,24 @@ 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 >> 8;
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;
if (S_ISDIR(buf->st_mode)) {
s->mode |= P9_DMDIR;
s->mode |= L9P_DMDIR;
s->qid.type |= L9P_QTDIR;
}
s->atime = buf->st_atime;
s->mtime = buf->st_mtime;
s->length = buf->st_size;
s->name =name;
s->name = name;
s->uid = user;
s->gid = user;
s->muid = user;
s->n_uid = buf->st_uid;
s->n_gid = buf->st_gid;
s->n_muid = buf->st_uid;
}
static void
@ -119,6 +127,7 @@ fs_clunk(void *softc, struct l9p_request *req)
struct stat st;
file = req->lr_fid->lo_aux;
assert(file != NULL);
if (file->dir)
closedir(file->dir);
@ -127,44 +136,60 @@ fs_clunk(void *softc, struct l9p_request *req)
file->fd = -1;
}
l9p_respond(req, NULL);
l9p_respond(req, 0);
}
static void
fs_create(void *softc, struct l9p_request *req)
{
struct l9p_connection *conn = req->lr_conn;
struct openfile *file = req->lr_fid->lo_aux;
struct stat st;
assert(file != NULL);
if (stat(file->name, &st) != 0) {
l9p_respond(req, errno);
return;
}
if (req->lr_req.tcreate.mode & L9P_DMDIR) {
mkdir(file->name, 0777);
l9p_respond(req, 0);
} else {
}
}
static void
fs_flush(void *softc, struct l9p_request *req)
{
l9p_respond(req, NULL);
l9p_respond(req, 0);
}
static void
fs_open(void *softc, struct l9p_request *req)
{
struct l9p_connection *conn = req->lr_conn;
struct openfile *file;
struct openfile *file = req->lr_fid->lo_aux;
struct stat st;
file = req->lr_fid->lo_aux;
assert(file != NULL);
stat(file->name, &st);
if (S_ISDIR(st.st_mode)) {
if (S_ISDIR(st.st_mode))
file->dir = opendir(file->name);
} else {
else {
file->fd = open(file->name, O_RDONLY);
if (file->fd < 0) {
l9p_respond(req, "Permission denied");
l9p_respond(req, EACCES);
return;
}
}
req->lr_resp.ropen.iounit = conn->lc_max_io_size;
l9p_respond(req, NULL);
l9p_respond(req, 0);
}
static void
@ -175,6 +200,7 @@ fs_read(void *softc, struct l9p_request *req)
struct l9p_stat l9stat;
file = req->lr_fid->lo_aux;
assert(file != NULL);
if (file->dir != NULL) {
struct dirent *d;
@ -196,11 +222,12 @@ fs_read(void *softc, struct l9p_request *req)
break;
}
} else {
size_t niov = l9p_truncate_iov(req->lr_data_iov, req->lr_data_niov, 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);
l9p_respond(req, 0);
}
static void
@ -221,7 +248,7 @@ fs_stat(void *softc, struct l9p_request *req)
stat(file->name, &st);
dostat(&req->lr_resp.rstat.stat, file->name, &st);
l9p_respond(req, NULL);
l9p_respond(req, 0);
}
static void
@ -239,18 +266,18 @@ fs_walk(void *softc, struct l9p_request *req)
strcat(name, "/");
strcat(name, req->lr_req.twalk.wname[i]);
if (stat(name, &buf) < 0){
l9p_respond(req, "No such file or directory");
l9p_respond(req, ENOENT);
free(name);
return;
}
req->lr_resp.rwalk.wqid[i].type = buf.st_mode&S_IFMT >> 8;
req->lr_resp.rwalk.wqid[i].type = buf.st_mode & S_IFMT >> 8;
req->lr_resp.rwalk.wqid[i].path = buf.st_ino;
}
req->lr_newfid->lo_aux = open_fid(name);
req->lr_resp.rwalk.nwqid = i;
free(name);
l9p_respond(req, NULL);
l9p_respond(req, 0);
}
static void

View file

@ -38,6 +38,7 @@ l9p_server_init(struct l9p_server **serverp, struct l9p_backend *backend)
struct l9p_server *server;
server = calloc(1, sizeof(*server));
server->ls_max_version = L9P_2000;
server->ls_backend = backend;
LIST_INIT(&server->ls_conns);
@ -65,6 +66,8 @@ void
l9p_connection_free(struct l9p_connection *conn)
{
LIST_REMOVE(conn, lc_link);
free(conn);
}
void
@ -94,6 +97,7 @@ l9p_connection_recv(struct l9p_connection *conn, const struct iovec *iov,
req = calloc(1, sizeof(struct l9p_request));
req->lr_aux = aux;
req->lr_conn = conn;
LIST_INSERT_HEAD(&conn->lc_requests, req, lr_link);
req->lr_req_msg.lm_mode = L9P_UNPACK;
req->lr_req_msg.lm_niov = niov;
@ -101,7 +105,7 @@ l9p_connection_recv(struct l9p_connection *conn, const struct iovec *iov,
req->lr_resp_msg.lm_mode = L9P_PACK;
if (l9p_pufcall(&req->lr_req_msg, &req->lr_req) != 0){
if (l9p_pufcall(&req->lr_req_msg, &req->lr_req, conn->lc_version) != 0) {
L9P_LOG(L9P_WARNING, "cannot unpack received message");
return;
}

View file

@ -44,5 +44,6 @@ main(int argc, const char *argv[])
if (l9p_server_init(&server, fs_backend) != 0)
errx(1, "Cannot create server:");
server->ls_max_version = L9P_2000U;
l9p_start_server(server, "0.0.0.0", "564");
}

36
fcall.h
View file

@ -77,22 +77,25 @@ enum l9p_qid_type
L9P_QTFILE = 0x00 /* type bits for plain file */
};
#define P9_DMDIR 0x80000000 /* mode bit for directories */
#define P9_DMAPPEND 0x40000000 /* mode bit for append only files */
#define P9_DMEXCL 0x20000000 /* mode bit for exclusive use files */
#define P9_DMMOUNT 0x10000000 /* mode bit for mounted channel */
#define P9_DMAUTH 0x08000000 /* mode bit for authentication file */
#define P9_DMTMP 0x04000000 /* mode bit for non-backed-up file */
#define P9_DMSYMLINK 0x02000000 /* mode bit for symbolic link (Unix, 9P2000.u) */
#define P9_DMDEVICE 0x00800000 /* mode bit for device file (Unix, 9P2000.u) */
#define P9_DMNAMEDPIPE 0x00200000 /* mode bit for named pipe (Unix, 9P2000.u) */
#define P9_DMSOCKET 0x00100000 /* mode bit for socket (Unix, 9P2000.u) */
#define P9_DMSETUID 0x00080000 /* mode bit for setuid (Unix, 9P2000.u) */
#define P9_DMSETGID 0x00040000 /* mode bit for setgid (Unix, 9P2000.u) */
enum {
L9P_DMDIR = 0x80000000,
L9P_DMAPPEND = 0x40000000,
L9P_DMEXCL = 0x20000000,
L9P_DMMOUNT = 0x10000000,
L9P_DMAUTH = 0x08000000,
L9P_DMTMP = 0x04000000,
L9P_DMSYMLINK = 0x02000000,
/* 9P2000.u extensions */
L9P_DMDEVICE = 0x00800000,
L9P_DMNAMEDPIPE = 0x00200000,
L9P_DMSOCKET = 0x00100000,
L9P_DMSETUID = 0x00080000,
L9P_DMSETGID = 0x00040000,
};
struct l9p_hdr
{
uint8_t type;
uint8_t type;
uint16_t tag;
uint32_t fid;
};
@ -117,6 +120,10 @@ struct l9p_stat
char *uid;
char *gid;
char *muid;
char *extension;
uid_t n_uid;
gid_t n_gid;
uid_t n_muid;
};
struct l9p_f_version
@ -136,6 +143,7 @@ struct l9p_f_error
{
struct l9p_hdr hdr;
char *ename;
uint32_t errnum;
};
struct l9p_f_ropen
@ -157,6 +165,7 @@ struct l9p_f_attach
uint32_t afid;
char *uname;
char *aname;
uid_t n_uname;
};
struct l9p_f_tcreate
@ -165,6 +174,7 @@ struct l9p_f_tcreate
uint32_t perm;
char *name;
uint8_t mode; /* +Topen */
char *extension;
};
struct l9p_f_twalk

25
lib9p.h
View file

@ -40,9 +40,9 @@
#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"
#define L9P_ENOFID "FID does not exist"
#define L9P_ENOFUNC "Function not implemented"
#define L9P_EINTR "Interrupted"
struct l9p_request;
@ -68,9 +68,10 @@ enum l9p_integer_type
enum l9p_version
{
L9P_2000 = 1,
L9P_2000U = 2,
L9P_2000L = 3
L9P_2000 = 0,
L9P_2000U = 1,
L9P_2000L = 2,
L9P_INVALID_VERSION = 3
};
struct l9p_message
@ -152,9 +153,11 @@ struct l9p_backend
void (*freefid)(void *, struct l9p_openfile *);
};
int l9p_pufcall(struct l9p_message *msg, union l9p_fcall *fcall);
int l9p_pustat(struct l9p_message *msg, struct l9p_stat *s);
uint16_t l9p_sizeof_stat(struct l9p_stat *stat);
int l9p_pufcall(struct l9p_message *msg, union l9p_fcall *fcall,
enum l9p_version version);
int l9p_pustat(struct l9p_message *msg, struct l9p_stat *s,
enum l9p_version version);
uint16_t l9p_sizeof_stat(struct l9p_stat *stat, enum l9p_version version);
int l9p_pack_stat(struct l9p_request *req, struct l9p_stat *s);
int l9p_server_init(struct l9p_server **serverp, struct l9p_backend *backend);
@ -177,7 +180,9 @@ 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_dispatch_request(struct l9p_request *req);
void l9p_respond(struct l9p_request *req, int errnum);
void l9p_seek_iov(struct iovec *iov1, size_t niov1, struct iovec *iov2,
size_t *niov2, size_t seek);

79
pack.c
View file

@ -38,7 +38,7 @@
#include "lib9p.h"
#define N(ary) (sizeof(ary) / sizeof(*ary))
#define STRING_SIZE(s) (L9P_WORD + strlen(s))
#define STRING_SIZE(s) (L9P_WORD + (s != NULL ? strlen(s) : 0))
#define QID_SIZE (L9P_BYTE + L9P_DWORD + L9P_QWORD)
static int l9p_iov_io(struct l9p_message *, void *, size_t);
@ -61,13 +61,14 @@ l9p_iov_io(struct l9p_message *msg, void *buffer, size_t len)
size_t left = len;
assert(msg != NULL);
assert(buffer != NULL);
if (len == 0)
return (0);
if (msg->lm_cursor_iov >= msg->lm_niov)
return (-1);
assert(buffer != NULL);
while (left > 0) {
size_t idx = msg->lm_cursor_iov;
@ -104,24 +105,28 @@ l9p_iov_io(struct l9p_message *msg, void *buffer, size_t len)
static inline int
l9p_pu8(struct l9p_message *msg, uint8_t *val)
{
return (l9p_iov_io(msg, val, sizeof(uint8_t)));
}
static inline int
l9p_pu16(struct l9p_message *msg, uint16_t *val)
{
return (l9p_iov_io(msg, val, sizeof(uint16_t)));
}
static inline int
l9p_pu32(struct l9p_message *msg, uint32_t *val)
{
return(l9p_iov_io(msg, val, sizeof(uint32_t)));
}
static inline int
l9p_pu64(struct l9p_message *msg, uint64_t *val)
{
return(l9p_iov_io(msg, val, sizeof(uint64_t)));
}
@ -131,8 +136,8 @@ l9p_pustring(struct l9p_message *msg, char **s)
uint16_t len;
if (msg->lm_mode == L9P_PACK)
len = strlen(*s);
len = *s != NULL ? strlen(*s) : 0;
if (l9p_pu16(msg, &len) < 0)
return (-1);
@ -141,6 +146,8 @@ l9p_pustring(struct l9p_message *msg, char **s)
if (l9p_iov_io(msg, *s, len) < 0)
return (-1);
return (len + 2);
}
static int
@ -150,6 +157,7 @@ l9p_pustrings(struct l9p_message *msg, uint16_t *num, char *strings[],
char *s;
uint i, size;
uint16_t len;
int r = 0;
l9p_pu16(msg, num);
@ -194,13 +202,14 @@ l9p_puqids(struct l9p_message *msg, uint16_t *num, struct l9p_qid *qids,
}
int
l9p_pustat(struct l9p_message *msg, struct l9p_stat *stat)
l9p_pustat(struct l9p_message *msg, struct l9p_stat *stat,
enum l9p_version version)
{
int r = 0;
uint16_t size;
if (msg->lm_mode == L9P_PACK)
size = l9p_sizeof_stat(stat) - 2;
size = l9p_sizeof_stat(stat, version) - 2;
r += l9p_pu16(msg, &size);
r += l9p_pu16(msg, &stat->type);
@ -215,11 +224,19 @@ l9p_pustat(struct l9p_message *msg, struct l9p_stat *stat)
r += l9p_pustring(msg, &stat->gid);
r += l9p_pustring(msg, &stat->muid);
if (version == L9P_2000U) {
r += l9p_pustring(msg, &stat->extension);
r += l9p_pu32(msg, &stat->n_uid);
r += l9p_pu32(msg, &stat->n_gid);
r += l9p_pu32(msg, &stat->n_muid);
}
return (r);
}
int
l9p_pufcall(struct l9p_message *msg, union l9p_fcall *fcall)
l9p_pufcall(struct l9p_message *msg, union l9p_fcall *fcall,
enum l9p_version version)
{
uint32_t length = 0;
@ -233,87 +250,111 @@ l9p_pufcall(struct l9p_message *msg, union l9p_fcall *fcall)
l9p_pu32(msg, &fcall->version.msize);
l9p_pustring(msg, &fcall->version.version);
break;
case L9P_TAUTH:
l9p_pu32(msg, &fcall->tauth.afid);
l9p_pustring(msg, &fcall->tauth.uname);
l9p_pustring(msg, &fcall->tauth.aname);
if (version == L9P_2000U)
l9p_pu32(msg, &fcall->tauth.n_uname);
break;
case L9P_RAUTH:
l9p_puqid(msg, &fcall->rauth.aqid);
break;
case L9P_RATTACH:
l9p_puqid(msg, &fcall->rattach.qid);
break;
case L9P_TATTACH:
l9p_pu32(msg, &fcall->hdr.fid);
l9p_pu32(msg, &fcall->tattach.afid);
l9p_pustring(msg, &fcall->tattach.uname);
l9p_pustring(msg, &fcall->tattach.aname);
break;
case L9P_RERROR:
l9p_pustring(msg, &fcall->error.ename);
if (version == L9P_2000U)
l9p_pu32(msg, &fcall->error.errnum);
break;
case L9P_TFLUSH:
l9p_pu16(msg, &fcall->tflush.oldtag);
break;
case L9P_TWALK:
l9p_pu32(msg, &fcall->hdr.fid);
l9p_pu32(msg, &fcall->twalk.newfid);
l9p_pustrings(msg, &fcall->twalk.nwname, fcall->twalk.wname,
N(fcall->twalk.wname));
break;
case L9P_RWALK:
l9p_puqids(msg, &fcall->rwalk.nwqid, fcall->rwalk.wqid,
N(fcall->rwalk.wqid));
break;
case L9P_TOPEN:
l9p_pu32(msg, &fcall->hdr.fid);
l9p_pu8(msg, &fcall->topen.mode);
break;
case L9P_ROPEN:
case L9P_RCREATE:
l9p_puqid(msg, &fcall->ropen.qid);
l9p_pu32(msg, &fcall->ropen.iounit);
break;
case L9P_TCREATE:
l9p_pu32(msg, &fcall->hdr.fid);
l9p_pustring(msg, &fcall->tcreate.name);
l9p_pu32(msg, &fcall->tcreate.perm);
l9p_pu8(msg, &fcall->tcreate.mode);
if (version == L9P_2000U)
l9p_pustring(msg, &fcall->tcreate.extension);
break;
case L9P_TREAD:
l9p_pu32(msg, &fcall->hdr.fid);
l9p_pu64(msg, &fcall->io.offset);
l9p_pu32(msg, &fcall->io.count);
break;
case L9P_RREAD:
l9p_pu32(msg, &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);
break;
case L9P_RWRITE:
l9p_pu32(msg, &fcall->io.count);
break;
case L9P_TCLUNK:
case L9P_TSTAT:
l9p_pu32(msg, &fcall->hdr.fid);
break;
case L9P_RSTAT:
{
uint16_t size = l9p_sizeof_stat(&fcall->rstat.stat);
uint16_t size = l9p_sizeof_stat(&fcall->rstat.stat, version);
l9p_pu16(msg, &size);
l9p_pustat(msg, &fcall->rstat.stat);
l9p_pustat(msg, &fcall->rstat.stat, version);
}
break;
case L9P_TWSTAT:
{
uint16_t size;
l9p_pu32(msg, &fcall->hdr.fid);
l9p_pu16(msg, &size);
l9p_pustat(msg, &fcall->twstat.stat);
l9p_pustat(msg, &fcall->twstat.stat, version);
}
break;
}
@ -323,6 +364,12 @@ l9p_pufcall(struct l9p_message *msg, union l9p_fcall *fcall)
uint32_t len = msg->lm_size;
msg->lm_cursor_offset = 0;
msg->lm_cursor_iov = 0;
/*
* Subtract 4 bytes from message size, becase we're
* overwriting size (rewinding message to the beginning)
* and writing again.
*/
msg->lm_size -= sizeof(uint32_t);
if (fcall->hdr.type == L9P_RREAD)
@ -335,8 +382,9 @@ l9p_pufcall(struct l9p_message *msg, union l9p_fcall *fcall)
}
uint16_t
l9p_sizeof_stat(struct l9p_stat *stat) {
return L9P_WORD /* size */
l9p_sizeof_stat(struct l9p_stat *stat, enum l9p_version version)
{
uint16_t size = L9P_WORD /* size */
+ L9P_WORD /* type */
+ L9P_DWORD /* dev */
+ QID_SIZE /* qid */
@ -346,4 +394,11 @@ l9p_sizeof_stat(struct l9p_stat *stat) {
+ STRING_SIZE(stat->uid)
+ STRING_SIZE(stat->gid)
+ STRING_SIZE(stat->muid);
if (version == L9P_2000U) {
size += STRING_SIZE(stat->extension)
+ 3 * L9P_DWORD;
}
return (size);
}

View file

@ -101,7 +101,7 @@ l9p_dispatch_request(struct l9p_request *req)
}
void
l9p_respond(struct l9p_request *req, const char *error)
l9p_respond(struct l9p_request *req, int errnum)
{
struct l9p_connection *conn = req->lr_conn;
struct sbuf *sb = sbuf_new_auto();
@ -115,11 +115,12 @@ l9p_respond(struct l9p_request *req, const char *error)
req->lr_resp.hdr.tag = req->lr_req.hdr.tag;
if (error == NULL)
if (errnum == 0)
req->lr_resp.hdr.type = req->lr_req.hdr.type + 1;
else {
req->lr_resp.hdr.type = L9P_RERROR;
req->lr_resp.error.ename = error;
req->lr_resp.error.ename = strerror(errnum);
req->lr_resp.error.errnum = errnum;
}
l9p_describe_fcall(&req->lr_resp, L9P_2000, sb);
@ -128,9 +129,9 @@ l9p_respond(struct l9p_request *req, const char *error)
L9P_LOG(L9P_DEBUG, "%s", sbuf_data(sb));
sbuf_delete(sb);
if (l9p_pufcall(&req->lr_resp_msg, &req->lr_resp) != 0) {
if (l9p_pufcall(&req->lr_resp_msg, &req->lr_resp, conn->lc_version) != 0) {
L9P_LOG(L9P_ERROR, "cannot pack response");
return;
goto out;
}
iosize = req->lr_resp_msg.lm_size;
@ -139,8 +140,12 @@ l9p_respond(struct l9p_request *req, const char *error)
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);
conn->lc_send_response(req, req->lr_resp_msg.lm_iov,
req->lr_resp_msg.lm_niov, iosize, conn->lc_send_response_aux);
out:
LIST_REMOVE(req, lr_link);
free(req);
}
int
@ -148,7 +153,7 @@ l9p_pack_stat(struct l9p_request *req, struct l9p_stat *st)
{
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, conn->lc_version);
if (msg->lm_size == 0) {
/* Initialize message */
@ -157,7 +162,7 @@ l9p_pack_stat(struct l9p_request *req, struct l9p_stat *st)
memcpy(msg->lm_iov, req->lr_data_iov, sizeof(struct iovec) * req->lr_data_niov);
}
if (l9p_pustat(msg, st) < 0)
if (l9p_pustat(msg, st, conn->lc_version) < 0)
return (-1);
req->lr_resp.io.count += size;
@ -168,19 +173,31 @@ static void
l9p_dispatch_tversion(struct l9p_request *req)
{
struct l9p_connection *conn = req->lr_conn;
enum l9p_version remote_version;
enum l9p_version remote_version = L9P_INVALID_VERSION;
int i;
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";
for (i = 0; i < N(l9p_versions); i++) {
if (strcmp(req->lr_req.version.version, l9p_versions[i]) == 0) {
remote_version = (enum l9p_version)i;
break;
}
}
if (remote_version == L9P_INVALID_VERSION) {
L9P_LOG(L9P_ERROR, "unsupported remote version: %s",
req->lr_req.version.version);
l9p_respond(req, L9P_ENOFUNC);
return;
}
L9P_LOG(L9P_INFO, "remote version: %s", l9p_versions[remote_version]);
L9P_LOG(L9P_INFO, "local version: %s",
l9p_versions[conn->lc_server->ls_max_version]);
conn->lc_version = MIN(remote_version, conn->lc_server->ls_max_version);
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.version = strdup(l9p_versions[conn->lc_version]);
req->lr_resp.version.msize = conn->lc_msize;
l9p_respond(req, NULL);
}

View file

@ -230,7 +230,7 @@ l9p_socket_send_response(struct l9p_request *req, const struct iovec *iov,
iov[0].iov_base, iolen);
if (xwrite(sc->ls_fd, iov[0].iov_base, iolen) != iolen) {
L9_LOG(L9P_ERROR, "short write: %s", strerror(errno));
L9P_LOG(L9P_ERROR, "short write: %s", strerror(errno));
return (-1);
}