2005-11-18 18:54:58 +03:00
|
|
|
/*
|
2006-01-30 21:08:58 +03:00
|
|
|
*(C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
|
|
|
*See LICENSE file for license details.
|
2005-11-18 18:54:58 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
2006-01-30 21:08:58 +03:00
|
|
|
#ifndef nil
|
|
|
|
#define nil 0
|
|
|
|
#endif
|
2005-11-18 18:54:58 +03:00
|
|
|
|
2006-01-30 21:08:58 +03:00
|
|
|
#define IXP_VERSION "9P2000"
|
|
|
|
#define IXP_MAX_VERSION 32
|
|
|
|
#define IXP_MAX_ERROR 128
|
|
|
|
#define IXP_MAX_CACHE 32
|
|
|
|
#define IXP_MAX_MSG 8192
|
|
|
|
#define IXP_MAX_FLEN 128
|
|
|
|
#define IXP_MAX_ULEN 32
|
|
|
|
#define IXP_MAX_STAT 64
|
|
|
|
#define IXP_MAX_WELEM 16 /*MAXWELEM */
|
|
|
|
#define IXP_MAX_TFUNCS 14
|
2005-11-18 18:54:58 +03:00
|
|
|
|
2006-01-30 21:08:58 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
size[4] Tversion tag[2] msize[4] version[s]
|
|
|
|
size[4] Rversion tag[2] msize[4] version[s]
|
|
|
|
size[4] Tauth tag[2] afid[4] uname[s] aname[s]
|
|
|
|
size[4] Rauth tag[2] aqid[13]
|
|
|
|
size[4] Rerror tag[2] ename[s]
|
|
|
|
size[4] Tflush tag[2] oldtag[2]
|
|
|
|
size[4] Rflush tag[2]
|
|
|
|
size[4] Tattach tag[2] fid[4] afid[4] uname[s] aname[s]
|
|
|
|
size[4] Rattach tag[2] qid[13]
|
|
|
|
size[4] Twalk tag[2] fid[4] newfid[4] nwname[2] nwname*(wname[s])
|
|
|
|
size[4] Rwalk tag[2] nwqid[2] nwqid*(wqid[13])
|
|
|
|
size[4] Topen tag[2] fid[4] mode[1]
|
|
|
|
size[4] Ropen tag[2] qid[13] iounit[4]
|
|
|
|
size[4] Tcreate tag[2] fid[4] name[s] perm[4] mode[1]
|
|
|
|
size[4] Rcreate tag[2] qid[13] iounit[4]
|
|
|
|
size[4] Tread tag[2] fid[4] offset[8] count[4]
|
|
|
|
size[4] Rread tag[2] count[4] data[count]
|
|
|
|
size[4] Twrite tag[2] fid[4] offset[8] count[4] data[count]
|
|
|
|
size[4] Rwrite tag[2] count[4]
|
|
|
|
size[4] Tclunk tag[2] fid[4]
|
|
|
|
size[4] Rclunk tag[2]
|
|
|
|
size[4] Tremove tag[2] fid[4]
|
|
|
|
size[4] Rremove tag[2]
|
|
|
|
size[4] Tstat tag[2] fid[4]
|
|
|
|
size[4] Rstat tag[2] stat[n]
|
|
|
|
size[4] Twstat tag[2] fid[4] stat[n]
|
|
|
|
size[4] Rwstat tag[2]
|
|
|
|
|
|
|
|
stat[n]:
|
|
|
|
size[2] total byte count of the following data
|
|
|
|
type[2] for kernel use
|
|
|
|
dev[4] for kernel use
|
|
|
|
qid.type[1] the type of the file (directory, etc.),
|
|
|
|
represented as a bit vector corresponding to the high 8 bits of the file's mode word.
|
|
|
|
qid.vers[4] version number for given path
|
|
|
|
qid.path[8] the file server's unique identification for the file
|
|
|
|
mode[4] permissions and flags
|
|
|
|
atime[4] last access time
|
|
|
|
mtime[4] last modification time
|
|
|
|
length[8] length of file in bytes
|
|
|
|
name[ s ] file name; must be / if the file is the root directory of the server
|
|
|
|
uid[ s ] owner name
|
|
|
|
gid[ s ] group name
|
|
|
|
muid[ s ]
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*9P message types */
|
2005-11-18 18:54:58 +03:00
|
|
|
enum {
|
2006-01-30 21:08:58 +03:00
|
|
|
TVERSION = 100,
|
|
|
|
RVERSION,
|
|
|
|
TAUTH = 102,
|
|
|
|
RAUTH,
|
|
|
|
TATTACH = 104,
|
|
|
|
RATTACH,
|
|
|
|
TERROR = 106,
|
|
|
|
RERROR,
|
|
|
|
TFLUSH = 108,
|
|
|
|
RFLUSH,
|
|
|
|
TWALK = 110,
|
|
|
|
RWALK,
|
|
|
|
TOPEN = 112,
|
|
|
|
ROPEN,
|
|
|
|
TCREATE = 114,
|
|
|
|
RCREATE,
|
|
|
|
TREAD = 116,
|
|
|
|
RREAD,
|
|
|
|
TWRITE = 118,
|
|
|
|
RWRITE,
|
|
|
|
TCLUNK = 120,
|
|
|
|
RCLUNK,
|
|
|
|
TREMOVE = 122,
|
|
|
|
RREMOVE,
|
|
|
|
TSTAT = 124,
|
|
|
|
RSTAT,
|
|
|
|
TWSTAT = 126,
|
|
|
|
RWSTAT,
|
2005-11-18 18:54:58 +03:00
|
|
|
};
|
|
|
|
|
2006-03-10 18:49:13 +03:00
|
|
|
/* borrowed from libc.h of Plan 9 */
|
2006-01-30 21:08:58 +03:00
|
|
|
#define DMDIR 0x80000000 /*mode bit for directories */
|
|
|
|
#define DMAPPEND 0x40000000 /*mode bit for append only files */
|
|
|
|
#define DMEXCL 0x20000000 /*mode bit for exclusive use files */
|
|
|
|
#define DMMOUNT 0x10000000 /*mode bit for mounted channel */
|
|
|
|
#define DMAUTH 0x08000000 /*mode bit for authentication file */
|
|
|
|
#define DMTMP 0x04000000 /*mode bit for non-backed-up file */
|
|
|
|
|
|
|
|
#define DMREAD 0x4<<6 /*mode bit for read permission */
|
|
|
|
#define DMWRITE 0x2<<6 /*mode bit for write permission */
|
|
|
|
#define DMEXEC 0x1<<6 /*mode bit for execute permission */
|
2005-11-18 18:54:58 +03:00
|
|
|
|
2006-03-10 18:49:13 +03:00
|
|
|
/* modes */
|
2006-01-30 21:08:58 +03:00
|
|
|
enum {
|
|
|
|
IXP_OREAD = 0x00,
|
|
|
|
IXP_OWRITE = 0x01,
|
|
|
|
IXP_ORDWR = 0x02,
|
|
|
|
IXP_OEXEC = 0x03,
|
|
|
|
IXP_OEXCL = 0x04,
|
|
|
|
IXP_OTRUNC = 0x10,
|
|
|
|
IXP_OREXEC = 0x20,
|
|
|
|
IXP_ORCLOSE = 0x40,
|
|
|
|
IXP_OAPPEND = 0x80,
|
2005-11-18 18:54:58 +03:00
|
|
|
};
|
|
|
|
|
2006-03-10 18:49:13 +03:00
|
|
|
/* qid.types */
|
2006-01-30 21:08:58 +03:00
|
|
|
enum {
|
|
|
|
IXP_QTDIR = 0x80,
|
|
|
|
IXP_QTAPPEND = 0x40,
|
|
|
|
IXP_QTEXCL = 0x20,
|
|
|
|
IXP_QTMOUNT = 0x10,
|
|
|
|
IXP_QTAUTH = 0x08,
|
|
|
|
IXP_QTTMP = 0x04,
|
|
|
|
IXP_QTSYMLINK = 0x02,
|
|
|
|
IXP_QTLINK = 0x01,
|
|
|
|
IXP_QTFILE = 0x00,
|
2005-11-18 18:54:58 +03:00
|
|
|
};
|
|
|
|
|
2006-01-30 21:08:58 +03:00
|
|
|
#define IXP_NOTAG (unsigned short)~0U /*Dummy tag */
|
|
|
|
#define IXP_NOFID (unsigned int)~0 /*No auth */
|
|
|
|
|
2006-02-01 16:25:02 +03:00
|
|
|
typedef struct Qid Qid;
|
|
|
|
struct Qid {
|
2006-01-30 21:08:58 +03:00
|
|
|
unsigned char type;
|
|
|
|
unsigned int version;
|
|
|
|
unsigned long long path;
|
2006-02-01 16:25:02 +03:00
|
|
|
/* internal use only */
|
2006-02-10 17:59:30 +03:00
|
|
|
unsigned char dir_type;
|
2006-02-01 16:25:02 +03:00
|
|
|
};
|
2006-01-30 21:08:58 +03:00
|
|
|
|
|
|
|
/*stat structure */
|
|
|
|
typedef struct {
|
|
|
|
unsigned short type;
|
|
|
|
unsigned int dev;
|
|
|
|
Qid qid;
|
|
|
|
unsigned int mode;
|
|
|
|
unsigned int atime;
|
|
|
|
unsigned int mtime;
|
|
|
|
unsigned long long length;
|
|
|
|
char name[IXP_MAX_FLEN];
|
|
|
|
char uid[IXP_MAX_ULEN];
|
|
|
|
char gid[IXP_MAX_ULEN];
|
|
|
|
char muid[IXP_MAX_ULEN];
|
|
|
|
} Stat;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
unsigned char id;
|
|
|
|
unsigned short tag;
|
|
|
|
unsigned int fid;
|
|
|
|
unsigned int maxmsg; /*Tversion, Rversion */
|
|
|
|
char version[IXP_MAX_VERSION]; /*Tversion, Rversion */
|
|
|
|
unsigned short oldtag; /*Tflush */
|
|
|
|
char errstr[IXP_MAX_ERROR]; /*Rerror */
|
|
|
|
Qid qid; /*Rattach, Ropen, Rcreate */
|
|
|
|
unsigned int iounit; /*Ropen, Rcreate */
|
|
|
|
Qid aqid; /*Rauth */
|
|
|
|
unsigned int afid; /*Tauth, Tattach */
|
|
|
|
char uname[IXP_MAX_ULEN]; /*Tauth, Tattach */
|
|
|
|
char aname[IXP_MAX_FLEN]; /*Tauth, Tattach */
|
|
|
|
unsigned int perm; /*Tcreate */
|
|
|
|
char name[IXP_MAX_FLEN]; /*Tcreate */
|
|
|
|
unsigned char mode; /*Tcreate, Topen */
|
|
|
|
unsigned int newfid; /*Twalk */
|
|
|
|
unsigned short nwname; /*Twalk */
|
|
|
|
char wname[IXP_MAX_WELEM][IXP_MAX_FLEN]; /*Twalk */
|
|
|
|
unsigned short nwqid; /*Rwalk */
|
|
|
|
Qid wqid[IXP_MAX_WELEM]; /*Rwalk */
|
|
|
|
unsigned long long offset; /*Tread, Twrite */
|
|
|
|
unsigned int count; /*Tread, Twrite, Rread */
|
|
|
|
Stat stat; /*Rstat */
|
|
|
|
unsigned short nstat; /*Twstat, Rstat */
|
2006-02-07 19:55:33 +03:00
|
|
|
unsigned char data[IXP_MAX_MSG]; /*Twrite, Rread, Twstat, *Rstat */
|
2006-01-30 21:08:58 +03:00
|
|
|
} Fcall;
|
|
|
|
|
|
|
|
typedef struct IXPServer IXPServer;
|
|
|
|
typedef struct IXPConn IXPConn;
|
|
|
|
typedef struct IXPMap IXPMap;
|
|
|
|
|
|
|
|
struct IXPMap {
|
|
|
|
unsigned int fid;
|
|
|
|
Qid qid;
|
2005-11-18 18:54:58 +03:00
|
|
|
};
|
|
|
|
|
2006-01-30 21:08:58 +03:00
|
|
|
struct IXPConn {
|
|
|
|
int fd;
|
2006-02-03 18:15:36 +03:00
|
|
|
IXPServer *srv;
|
|
|
|
void (*read) (IXPConn *);
|
|
|
|
void (*close) (IXPConn *);
|
2006-01-30 21:08:58 +03:00
|
|
|
IXPMap **map;
|
2006-03-01 13:55:46 +03:00
|
|
|
unsigned int mapsz;
|
2006-02-12 02:49:38 +03:00
|
|
|
Fcall pending;
|
|
|
|
int is_pending;
|
2005-11-18 18:54:58 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
struct IXPServer {
|
2006-01-30 21:08:58 +03:00
|
|
|
int running;
|
|
|
|
IXPConn **conn;
|
2006-03-01 13:55:46 +03:00
|
|
|
unsigned int connsz;
|
2006-01-30 21:08:58 +03:00
|
|
|
int maxfd;
|
|
|
|
fd_set rd;
|
2005-11-18 18:54:58 +03:00
|
|
|
};
|
|
|
|
|
2006-01-30 21:08:58 +03:00
|
|
|
typedef struct {
|
|
|
|
int fd;
|
|
|
|
unsigned int root_fid;
|
|
|
|
Qid root_qid;
|
|
|
|
Fcall fcall;
|
|
|
|
char *errstr;
|
|
|
|
} IXPClient;
|
|
|
|
|
|
|
|
/* client.c */
|
2006-02-12 03:49:33 +03:00
|
|
|
int ixp_client_dial(IXPClient *c, char *address, unsigned int rootfid);
|
|
|
|
void ixp_client_hangup(IXPClient *c);
|
2006-01-30 21:08:58 +03:00
|
|
|
int ixp_client_remove(IXPClient *c, unsigned int newfid, char *filepath);
|
|
|
|
int ixp_client_create(IXPClient *c, unsigned int dirfid, char *name,
|
|
|
|
unsigned int perm, unsigned char mode);
|
|
|
|
int ixp_client_walk(IXPClient *c, unsigned int newfid, char *filepath);
|
|
|
|
int ixp_client_open(IXPClient *c, unsigned int newfid, char *filepath,
|
|
|
|
unsigned char mode);
|
|
|
|
int ixp_client_read(IXPClient *c, unsigned int fid,
|
|
|
|
unsigned long long offset, void *result,
|
|
|
|
unsigned int res_len);
|
|
|
|
int ixp_client_write(IXPClient *c, unsigned int fid,
|
|
|
|
unsigned long long offset,
|
|
|
|
unsigned int count, unsigned char *data);
|
|
|
|
int ixp_client_close(IXPClient *c, unsigned int fid);
|
2006-02-07 02:32:57 +03:00
|
|
|
int ixp_client_do_fcall(IXPClient * c);
|
2006-01-30 21:08:58 +03:00
|
|
|
|
|
|
|
/* convert.c */
|
|
|
|
void *ixp_enc_u8(unsigned char *msg, unsigned char val);
|
|
|
|
void *ixp_dec_u8(unsigned char *msg, unsigned char *val);
|
|
|
|
void *ixp_enc_u16(unsigned char *msg, unsigned short val);
|
|
|
|
void *ixp_dec_u16(unsigned char *msg, unsigned short *val);
|
|
|
|
void *ixp_enc_u32(unsigned char *msg, unsigned int val);
|
|
|
|
void *ixp_dec_u32(unsigned char *msg, unsigned int *val);
|
|
|
|
void *ixp_enc_u64(unsigned char *msg, unsigned long long val);
|
|
|
|
void *ixp_dec_u64(unsigned char *msg, unsigned long long *val);
|
|
|
|
void *ixp_enc_string(unsigned char *msg, const char *s);
|
|
|
|
void *ixp_dec_string(unsigned char *msg, char *string,
|
|
|
|
unsigned short stringlen, unsigned short *len);
|
|
|
|
void *ixp_enc_data(unsigned char *msg, unsigned char *data,
|
|
|
|
unsigned int datalen);
|
|
|
|
void *ixp_dec_data(unsigned char *msg, unsigned char *data,
|
|
|
|
unsigned int datalen);
|
|
|
|
void *ixp_enc_prefix(unsigned char *msg, unsigned int size,
|
|
|
|
unsigned char id, unsigned short tag);
|
|
|
|
void *ixp_dec_prefix(unsigned char *msg, unsigned int *size,
|
|
|
|
unsigned char *id, unsigned short *tag);
|
|
|
|
void *ixp_enc_qid(unsigned char *msg, Qid *qid);
|
|
|
|
void *ixp_dec_qid(unsigned char *msg, Qid *qid);
|
|
|
|
void *ixp_enc_stat(unsigned char *msg, Stat *stat);
|
|
|
|
void *ixp_dec_stat(unsigned char *msg, Stat *stat);
|
2005-11-18 18:54:58 +03:00
|
|
|
|
|
|
|
/* message.c */
|
2006-01-30 21:08:58 +03:00
|
|
|
unsigned short ixp_sizeof_stat(Stat *stat);
|
2006-03-01 09:51:04 +03:00
|
|
|
unsigned int ixp_fcall2msg(void *msg, Fcall *fcall, unsigned int msglen);
|
|
|
|
unsigned int ixp_msg2fcall(Fcall *call, void *msg, unsigned int msglen);
|
2006-01-30 21:08:58 +03:00
|
|
|
|
|
|
|
/* server.c */
|
2006-02-03 18:15:36 +03:00
|
|
|
IXPConn *ixp_server_open_conn(IXPServer *s, int fd,
|
|
|
|
void (*read)(IXPConn *c), void (*close)(IXPConn *c));
|
|
|
|
void ixp_server_close_conn(IXPConn *c);
|
2006-01-30 21:08:58 +03:00
|
|
|
char *ixp_server_loop(IXPServer *s);
|
|
|
|
IXPMap *ixp_server_fid2map(IXPConn *c, unsigned int fid);
|
2006-02-03 18:15:36 +03:00
|
|
|
unsigned int ixp_server_receive_fcall(IXPConn *c, Fcall *fcall);
|
|
|
|
int ixp_server_respond_fcall(IXPConn *c, Fcall *fcall);
|
|
|
|
int ixp_server_respond_error(IXPConn *c, Fcall *fcall, char *errstr);
|
2006-02-03 18:42:59 +03:00
|
|
|
void ixp_server_close(IXPServer *s);
|
2006-01-30 21:08:58 +03:00
|
|
|
|
|
|
|
/* socket.c */
|
|
|
|
int ixp_connect_sock(char *address);
|
|
|
|
int ixp_accept_sock(int fd);
|
|
|
|
int ixp_create_sock(char *address, char **errstr);
|
|
|
|
|
|
|
|
/* transport.c */
|
|
|
|
unsigned int ixp_send_message(int fd, void *msg, unsigned int msize, char **errstr);
|
|
|
|
unsigned int ixp_recv_message(int fd, void *msg, unsigned int msglen, char **errstr);
|