commit 7477765db204689787ff26151d59c43cc0fbc803
parent 7497a4c48a1db5f92e2a007eb2f3f91f07b85d66
Author: sqweek <sqweek@gmail.com>
Date:   Sat, 20 Sep 2008 22:51:02 +0800
Add wstat support.
Diffstat:
3 files changed, 65 insertions(+), 25 deletions(-)
diff --git a/include/ixp.h b/include/ixp.h
@@ -7,7 +7,7 @@
 #include <sys/types.h>
 #include <sys/select.h>
 
-#define IXP_API 97
+#define IXP_API 105
 
 /* Gunk */
 #if defined(IXP_NEEDAPI) && IXP_API < IXP_NEEDAPI
@@ -271,6 +271,21 @@ struct IxpQid {
 	uchar	dir_type;
 };
 
+/* stat structure */
+struct IxpStat {
+	ushort	type;
+	ulong	dev;
+	IxpQid	qid;
+	ulong	mode;
+	ulong	atime;
+	ulong	mtime;
+	uvlong	length;
+	char*	name;
+	char*	uid;
+	char*	gid;
+	char*	muid;
+};
+
 typedef struct IxpFHdr		IxpFHdr;
 typedef struct IxpFError	IxpFError;
 typedef struct IxpFROpen	IxpFRAttach;
@@ -290,7 +305,7 @@ typedef struct IxpFIO		IxpFTRead;
 typedef struct IxpFVersion	IxpFTVersion;
 typedef struct IxpFTWalk	IxpFTWalk;
 typedef struct IxpFIO		IxpFTWrite;
-typedef struct IxpFRStat	IxpFTWstat;
+typedef struct IxpFTWStat	IxpFTWStat;
 typedef struct IxpFAttach	IxpFAttach;
 typedef struct IxpFIO		IxpFIO;
 typedef struct IxpFVersion	IxpFVersion;
@@ -356,6 +371,10 @@ struct IxpFRStat {
 	ushort	nstat;
 	uchar*	stat;
 };
+struct IxpFTWStat {
+	IxpFHdr	hdr;
+	IxpStat	stat;
+};
 #if defined(IXP_NEEDAPI) && IXP_NEEDAPI <= 89
 /* from fcall(3) in plan9port */
 typedef struct IxpFcall IxpFcall;
@@ -406,10 +425,13 @@ struct IxpFcall {
 			ulong	count; /* Tread, Twrite, Rread */
 			char	*data; /* Twrite, Rread */
 		)
-		STRUCT ( /* Twstat, Rstat */
+		STRUCT ( /* Rstat */
 			ushort	nstat;
 			uchar	*stat;
 		)
+		STRUCT ( /* Twstat */
+			IxpStat	st;
+		)
 	)
 };
 #else
@@ -431,7 +453,7 @@ union IxpFcall {
 	IxpFTCreate	topen;
 	IxpFTWalk	twalk;
 	IxpFRWalk	rwalk;
-	IxpFRStat	twstat;
+	IxpFTWStat	twstat;
 	IxpFRStat	rstat;
 	IxpFIO		twrite;
 	IxpFIO		rwrite;
@@ -441,21 +463,6 @@ union IxpFcall {
 };
 #endif
 
-/* stat structure */
-struct IxpStat {
-	ushort	type;
-	ulong	dev;
-	IxpQid	qid;
-	ulong	mode;
-	ulong	atime;
-	ulong	mtime;
-	uvlong	length;
-	char*	name;
-	char*	uid;
-	char*	gid;
-	char*	muid;
-};
-
 struct IxpConn {
 	IxpServer*	srv;
 	void*		aux;
@@ -564,6 +571,7 @@ struct Ixp9Srv {
 	void (*stat)(Ixp9Req *r);
 	void (*walk)(Ixp9Req *r);
 	void (*write)(Ixp9Req *r);
+	void (*wstat)(Ixp9Req *r);
 	void (*freefid)(IxpFid *f);
 };
 
diff --git a/libixp/message.c b/libixp/message.c
@@ -159,11 +159,13 @@ ixp_pfcall(IxpMsg *msg, Fcall *fcall) {
 		ixp_pu16(msg, &fcall->rstat.nstat);
 		ixp_pdata(msg, (char**)&fcall->rstat.stat, fcall->rstat.nstat);
 		break;
-	case TWStat:
+	case TWStat: {
+		ushort size;
 		ixp_pu32(msg, &fcall->hdr.fid);
-		ixp_pu16(msg, &fcall->twstat.nstat);
-		ixp_pdata(msg, (char**)&fcall->twstat.stat, fcall->twstat.nstat);
+		ixp_pu16(msg, &size);
+		ixp_pstat(msg, &fcall->twstat.stat);
 		break;
+		}
 	}
 }
 
diff --git a/libixp/request.c b/libixp/request.c
@@ -310,7 +310,34 @@ handlereq(Ixp9Req *r) {
 		}
 		pc->srv->write(r);
 		break;
-	/* Still to be implemented: wstat, auth */
+	case TWStat:
+		if(!(r->fid = lookupkey(&pc->fidmap, r->ifcall.hdr.fid))) {
+			respond(r, Enofid);
+			return;
+		}
+		if((ushort)~r->ifcall.twstat.stat.type) {
+			respond(r, "wstat of type");
+			return;
+		}
+		if((uint)~r->ifcall.twstat.stat.dev) {
+			respond(r, "wstat of dev");
+			return;
+		}
+		if((uchar)~r->ifcall.twstat.stat.qid.type || (ulong)~r->ifcall.twstat.stat.qid.version || (uvlong)~r->ifcall.twstat.stat.qid.path) {
+			respond(r, "wstat of qid");
+			return;
+		}
+		if(r->ifcall.twstat.stat.muid && r->ifcall.twstat.stat.muid[0]) {
+			respond(r, "wstat of muid");
+			return;
+		}
+		if((ulong)~r->ifcall.twstat.stat.mode && ((r->ifcall.twstat.stat.mode&DMDIR)>>24) != r->fid->qid.type&QTDIR) {
+			respond(r, "wstat on DMDIR bit");
+			return;
+		}
+		pc->srv->wstat(r);
+		break;
+	/* Still to be implemented: auth */
 	}
 }
 
@@ -386,10 +413,13 @@ respond(Ixp9Req *r, const char *error) {
 		if((r->oldreq = lookupkey(&pc->tagmap, r->ifcall.tflush.oldtag)))
 			respond(r->oldreq, Eintr);
 		break;
+	case TWStat:
+		ixp_freestat(&r->ifcall.twstat.stat);
+		break;
 	case TRead:
 	case TStat:
-		break;
-	/* Still to be implemented: wstat, auth */
+		break;		
+	/* Still to be implemented: auth */
 	}
 
 	r->ofcall.hdr.tag = r->ifcall.hdr.tag;