From d3e4c06341a533b2767548aef5c489e6294e2455 Mon Sep 17 00:00:00 2001 From: Jakub Klama Date: Thu, 28 Jan 2016 15:18:55 +0100 Subject: [PATCH] First pass at 9P2000.u support. --- backend/fs.c | 63 +++++++++++++++++++++++++----------- connection.c | 6 +++- example/server.c | 1 + fcall.h | 36 +++++++++++++-------- lib9p.h | 25 +++++++++------ pack.c | 79 +++++++++++++++++++++++++++++++++++++++------- request.c | 53 ++++++++++++++++++++----------- transport/socket.c | 2 +- 8 files changed, 192 insertions(+), 73 deletions(-) diff --git a/backend/fs.c b/backend/fs.c index 34df344..b6782e3 100644 --- a/backend/fs.c +++ b/backend/fs.c @@ -31,11 +31,16 @@ #include #include +#include #include #include +#include +#include #include #include #include +#include +#include #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 diff --git a/connection.c b/connection.c index bac8343..f7822fc 100644 --- a/connection.c +++ b/connection.c @@ -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; } diff --git a/example/server.c b/example/server.c index 7e5c530..c797512 100644 --- a/example/server.c +++ b/example/server.c @@ -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"); } diff --git a/fcall.h b/fcall.h index efa49ff..5fe4149 100644 --- a/fcall.h +++ b/fcall.h @@ -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 diff --git a/lib9p.h b/lib9p.h index e180b0b..1998f0c 100644 --- a/lib9p.h +++ b/lib9p.h @@ -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); diff --git a/pack.c b/pack.c index 8c06a70..0895625 100644 --- a/pack.c +++ b/pack.c @@ -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); } diff --git a/request.c b/request.c index 40bb038..2188b9e 100644 --- a/request.c +++ b/request.c @@ -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); } diff --git a/transport/socket.c b/transport/socket.c index f746288..3207d32 100644 --- a/transport/socket.c +++ b/transport/socket.c @@ -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); }