First pass at 9P2000.u support.
This commit is contained in:
parent
91ad441d73
commit
d3e4c06341
8 changed files with 192 additions and 73 deletions
63
backend/fs.c
63
backend/fs.c
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
36
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
|
||||
|
|
25
lib9p.h
25
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);
|
||||
|
|
79
pack.c
79
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);
|
||||
}
|
||||
|
|
53
request.c
53
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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue