Semi-functional file listing and reading.

This commit is contained in:
Jakub Klama 2016-01-23 22:57:40 +01:00
parent f46d2136e9
commit 080c92c18f
9 changed files with 186 additions and 32 deletions

View file

@ -31,9 +31,12 @@
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#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);
}

View file

@ -28,6 +28,7 @@
#include <stdlib.h>
#include <sys/queue.h>
#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);

15
fcall.h
View file

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

10
lib9p.c
View file

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

View file

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

8
log.c
View file

@ -29,12 +29,20 @@
#include <stdarg.h>
#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);

2
log.h
View file

@ -38,4 +38,4 @@ enum l9p_log_level
void l9p_logf(enum l9p_log_level level, const char *fmt, ...);
#endif /* LIB9P_LOG_H */
#endif /* LIB9P_LOG_H */

View file

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

View file

@ -36,13 +36,7 @@
#include <netdb.h>
#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;
}