From 080c92c18f807d1336e749af209aa5b3e8ab7ce4 Mon Sep 17 00:00:00 2001 From: Jakub Klama Date: Sat, 23 Jan 2016 22:57:40 +0100 Subject: [PATCH] Semi-functional file listing and reading. --- backend/fs.c | 93 ++++++++++++++++++++++++++++++++++++++++++++-- connection.c | 4 +- fcall.h | 15 +++++++- lib9p.c | 10 ++--- lib9p.h | 4 ++ log.c | 8 ++++ log.h | 2 +- request.c | 56 +++++++++++++++++++++++----- transport/socket.c | 26 +++++++------ 9 files changed, 186 insertions(+), 32 deletions(-) diff --git a/backend/fs.c b/backend/fs.c index e4ca793..84b6b22 100644 --- a/backend/fs.c +++ b/backend/fs.c @@ -31,9 +31,12 @@ #include #include +#include #include +#include #include #include "../lib9p.h" +#include "../log.h" static void fs_attach(void *, struct l9p_request *); static void fs_clunk(void *, struct l9p_request *); @@ -70,6 +73,29 @@ open_fid(const char *path) return (ret); } +static void +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.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->qid.type |= L9P_QTDIR; + } + s->atime = buf->st_atime; + s->mtime = buf->st_mtime; + s->length = buf->st_size; + s->name =name; + s->uid = user; + s->gid = user; + s->muid = user; +} + static void fs_attach(void *softc, struct l9p_request *req) { @@ -86,7 +112,7 @@ fs_attach(void *softc, struct l9p_request *req) static void fs_clunk(void *softc, struct l9p_request *req) { - + l9p_respond(req, NULL); } static void @@ -104,13 +130,51 @@ fs_flush(void *softc, struct l9p_request *req) static void fs_open(void *softc, struct l9p_request *req) { + struct openfile *file; + struct stat st; + file = req->lr_fid->lo_aux; + + stat(file->name, &st); + + if (S_ISDIR(st.st_mode)) { + file->dir = opendir(file->name); + } else { + file->fd = open(file->name, O_RDONLY); + if (file->fd < 0) { + l9p_respond(req, "ENOPERM"); + return; + } + } + + req->lr_resp.ropen.iounit = 512; + l9p_respond(req, NULL); } static void fs_read(void *softc, struct l9p_request *req) { + struct openfile *file; + struct l9p_stat l9stat; + file = req->lr_fid->lo_aux; + + if (file->dir != NULL) { + 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); + } + } 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); + } + + l9p_respond(req, NULL); } static void @@ -129,13 +193,29 @@ static void fs_walk(void *softc, struct l9p_request *req) { int i; - char *name; + struct stat buf; + struct openfile *file = (struct openfile *)req->lr_fid->lo_aux; + char *name = malloc(1024); - for (i = 0; i < req->lr_req.twalk.nwname; i++) { + strcpy(name, file->name); + + /* build full path. Stat full path. Done */ + 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"); + free(name); + return; + } + 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); } static void @@ -154,6 +234,7 @@ int l9p_backend_fs_init(struct l9p_backend **backendp, const char *root) { struct l9p_backend *backend; + struct fs_softc *sc; backend = malloc(sizeof(*backend)); backend->attach = fs_attach; @@ -168,6 +249,10 @@ l9p_backend_fs_init(struct l9p_backend **backendp, const char *root) backend->write = fs_write; backend->wstat = fs_wstat; + sc = malloc(sizeof(*sc)); + sc->fs_rootpath = strdup(root); + backend->softc = sc; + *backendp = backend; return (0); } diff --git a/connection.c b/connection.c index 45e9162..8d213cb 100644 --- a/connection.c +++ b/connection.c @@ -28,6 +28,7 @@ #include #include #include "lib9p.h" +#include "log.h" int l9p_server_init(struct l9p_server **serverp, struct l9p_backend *backend) @@ -48,6 +49,7 @@ l9p_connection_init(struct l9p_server *server, struct l9p_connection **conn) struct l9p_connection *newconn; newconn = malloc(sizeof(*newconn)); + newconn->lc_server = server; LIST_INSERT_HEAD(&server->ls_conns, newconn, lc_link); *conn = newconn; @@ -83,7 +85,7 @@ l9p_connection_recv(struct l9p_connection *conn, void *buf, size_t len) msg.lm_mode = L9P_UNPACK; if (l9p_pufcall(&msg, &req->lr_req) != 0) { - + l9p_logf(L9P_WARNING, "cannot unpack received message"); } l9p_dispatch_request(req); diff --git a/fcall.h b/fcall.h index b639986..9117f21 100644 --- a/fcall.h +++ b/fcall.h @@ -68,7 +68,7 @@ enum l9p_ftype { enum l9p_qid_type { L9P_QTDIR = 0x80, /* type bit for directories */ - L9P_QTAPPEND = 0x40, /* type bit for append only files */ + L9P_QTAPPEND = 0x40,/* type bit for append only files */ L9P_QTEXCL = 0x20, /* type bit for exclusive use files */ L9P_QTMOUNT = 0x10, /* type bit for mounted channel */ L9P_QTAUTH = 0x08, /* type bit for authentication file */ @@ -77,6 +77,19 @@ 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) */ + struct l9p_hdr { uint8_t type; diff --git a/lib9p.c b/lib9p.c index 20b9591..c329bbc 100644 --- a/lib9p.c +++ b/lib9p.c @@ -49,8 +49,6 @@ 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, size_t); -static void l9p_pustat(struct l9p_message *, struct l9p_stat *); -static uint16_t l9p_sizeof_stat(struct l9p_stat *); static void @@ -233,7 +231,7 @@ l9p_puqids(struct l9p_message *msg, uint16_t *num, struct l9p_qid *qids, l9p_puqid(msg, &qids[i]); } -static void +void l9p_pustat(struct l9p_message *msg, struct l9p_stat *stat) { uint16_t size; @@ -315,7 +313,7 @@ l9p_pufcall(struct l9p_message *msg, union l9p_fcall *fcall) l9p_pu32(msg, &fcall->tcreate.perm); l9p_pu8(msg, &fcall->tcreate.mode); break; - case L9P_TREMOVE: + case L9P_TREAD: l9p_pu32(msg, &fcall->hdr.fid); l9p_pu64(msg, &fcall->io.offset); l9p_pu32(msg, &fcall->io.count); @@ -349,9 +347,11 @@ l9p_pufcall(struct l9p_message *msg, union l9p_fcall *fcall) break; } } + + return (0); } -static uint16_t +uint16_t l9p_sizeof_stat(struct l9p_stat *stat) { return L9P_WORD /* size */ + L9P_WORD /* type */ diff --git a/lib9p.h b/lib9p.h index bc4f828..cc67a9e 100644 --- a/lib9p.h +++ b/lib9p.h @@ -66,6 +66,7 @@ struct l9p_request 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; LIST_ENTRY(l9p_request) lr_link; @@ -117,6 +118,9 @@ 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); +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); diff --git a/log.c b/log.c index f38d99d..98cc62d 100644 --- a/log.c +++ b/log.c @@ -29,12 +29,20 @@ #include #include "log.h" +static const char *l9p_log_level_names[] = { + "DEBUG", + "INFO", + "WARN", + "ERROR" +}; + void l9p_logf(enum l9p_log_level level, const char *fmt, ...) { va_list ap; va_start(ap, fmt); + fprintf(stderr, "[%s]\t", l9p_log_level_names[level]); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); va_end(ap); diff --git a/log.h b/log.h index 1173826..9b3d1fa 100644 --- a/log.h +++ b/log.h @@ -38,4 +38,4 @@ enum l9p_log_level void l9p_logf(enum l9p_log_level level, const char *fmt, ...); -#endif /* LIB9P_LOG_H */ \ No newline at end of file +#endif /* LIB9P_LOG_H */ diff --git a/request.c b/request.c index f9b5d18..ab8c945 100644 --- a/request.c +++ b/request.c @@ -80,6 +80,8 @@ l9p_dispatch_request(struct l9p_request *req) return; } } + + l9p_respond(req, L9P_ENOFUNC); } void @@ -97,6 +99,9 @@ l9p_respond(struct l9p_request *req, const char *error) switch (req->lr_req.hdr.type) { case L9P_TVERSION: break; + + case L9P_TWALK: + break; } req->lr_resp.hdr.tag = req->lr_req.hdr.tag; @@ -112,7 +117,26 @@ l9p_respond(struct l9p_request *req, const char *error) } - conn->lc_send_request(msg.lm_buffer, msg.lm_pos - msg.lm_buffer, conn->lc_send_request_aux); + conn->lc_send_request(msg.lm_buffer, msg.lm_pos - msg.lm_buffer, + conn->lc_send_request_aux); +} + +int +l9p_pack_stat(struct l9p_request *req, struct l9p_stat *st) +{ + struct l9p_message msg; + uint16_t size = l9p_sizeof_stat(st); + + 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); } static void @@ -125,20 +149,29 @@ l9p_dispatch_tversion(struct l9p_request *req) else req->lr_resp.version.version = "unknown"; - req->lr_resp.version.msize = req->lr_resp.version.msize; + req->lr_resp.version.msize = 8192; l9p_respond(req, NULL); } static void 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); + + conn->lc_server->ls_backend->attach(conn->lc_server->ls_backend->softc, req); } static void l9p_dispatch_tclunk(struct l9p_request *req) { + struct l9p_connection *conn = req->lr_conn; + conn->lc_server->ls_backend->clunk(conn->lc_server->ls_backend->softc, req); } static void @@ -172,8 +205,8 @@ l9p_dispatch_topen(struct l9p_request *req) struct l9p_connection *conn = req->lr_conn; struct l9p_openfile *fid; - fid = l9p_connection_find_fid(conn, req->lr_req.topen.hdr.fid); - if (!fid) { + req->lr_fid = l9p_connection_find_fid(conn, req->lr_req.topen.hdr.fid); + if (!req->lr_fid) { l9p_respond(req, L9P_ENOFID); return; } @@ -192,11 +225,13 @@ l9p_dispatch_tread(struct l9p_request *req) struct l9p_connection *conn = req->lr_conn; struct l9p_openfile *fid; - fid = l9p_connection_find_fid(conn, req->lr_req.tcreate.hdr.fid); - if (!fid) { + 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->read(conn->lc_server->ls_backend->softc, req); } static void @@ -220,14 +255,17 @@ l9p_dispatch_twalk(struct l9p_request *req) struct l9p_connection *conn = req->lr_conn; struct l9p_openfile *fid; - fid = l9p_connection_find_fid(conn, req->lr_req.twalk.hdr.fid); - if (!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 (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); } if (!conn->lc_server->ls_backend->walk) { diff --git a/transport/socket.c b/transport/socket.c index 602495a..ec2af63 100644 --- a/transport/socket.c +++ b/transport/socket.c @@ -36,13 +36,7 @@ #include #include "../lib9p.h" #include "../log.h" -#include "socket.h" - -static int l9p_socket_readmsg(int, void **, size_t *); -static void l9p_socket_sendmsg(void *, size_t, void *); -static void *l9p_socket_thread(void *); -static int xread(int, void *, size_t); -static int xwrite(int, void *, size_t); +#include "socket.h" struct l9p_socket_softc { @@ -53,6 +47,12 @@ struct l9p_socket_softc int ls_fd; }; +static int l9p_socket_readmsg(struct l9p_socket_softc *, void **, size_t *); +static void l9p_socket_sendmsg(void *, size_t, void *); +static void *l9p_socket_thread(void *); +static int xread(int, void *, size_t); +static int xwrite(int, void *, size_t); + int l9p_start_server(struct l9p_server *server, const char *host, const char *port) { @@ -155,20 +155,22 @@ l9p_socket_thread(void *arg) size_t length; for (;;) { - if (l9p_socket_readmsg(sc->ls_fd, &buf, &length) != 0) + if (l9p_socket_readmsg(sc, &buf, &length) != 0) break; l9p_connection_recv(sc->ls_conn, buf, length); } + l9p_logf(L9P_INFO, "connection closed"); return (NULL); } static int -l9p_socket_readmsg(int fd, void **buf, size_t *size) +l9p_socket_readmsg(struct l9p_socket_softc *sc, void **buf, size_t *size) { uint32_t msize; 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)); @@ -185,7 +187,7 @@ l9p_socket_readmsg(int fd, void **buf, size_t *size) *size = msize; *buf = buffer; - l9p_logf(L9P_INFO, "read complete message, size=%d", msize); + l9p_logf(L9P_INFO, "%p: read complete message, buf=%p size=%d", sc->ls_conn, buffer, msize); return (0); } @@ -196,7 +198,9 @@ l9p_socket_sendmsg(void *buf, size_t len, void *arg) struct l9p_socket_softc *sc = (struct l9p_socket_softc *)arg; uint32_t msize = (uint32_t)len + sizeof(uint32_t); - if (xwrite(sc->ls_fd, &msize, sizeof(uint32_t) != sizeof(uint32_t))) { + l9p_logf(L9P_DEBUG, "%p: sending reply, buf=%p, size=%d", arg, buf, len); + + if (xwrite(sc->ls_fd, &msize, sizeof(uint32_t)) != sizeof(uint32_t)) { l9p_logf(L9P_ERROR, "short write: %s", strerror(errno)); return; }