shithub: mq

Download patch

ref: b5b18746789b3bbf976af847d66d7818fb06d87e
parent: 4886a2a57f50dddca2c79af22ea428bc0d9f8be6
author: kvik <kvik@a-b.xyz>
date: Tue Sep 15 04:48:25 EDT 2020

mq: implement Twstat handling

--- a/src/mq.c
+++ b/src/mq.c
@@ -434,6 +434,74 @@
 }
 
 void
+xwstat(Req *r)
+{
+	File *w, *f = r->fid->file;
+	char *uid = r->fid->uid;
+
+	/* To change name, must have write permission in parent. */
+	if(r->d.name[0] != '\0' && strcmp(r->d.name, f->name) != 0){
+		if((w = f->parent) == nil)
+			goto perm;
+		incref(w);
+	 	if(!hasperm(w, uid, AWRITE)){
+			closefile(w);
+			goto perm;
+		}
+		if((w = walkfile(w, r->d.name)) != nil){
+			closefile(w);
+			respond(r, "file already exists");
+			return;
+		}
+	}
+
+	/* To change group, must be owner and member of new group,
+	 * or leader of current group and leader of new group.
+	 * Second case cannot happen, but we check anyway. */
+	while(r->d.gid[0] != '\0' && strcmp(f->gid, r->d.gid) != 0){
+		if(strcmp(uid, f->uid) == 0)
+			break;
+		if(strcmp(uid, f->gid) == 0)
+		if(strcmp(uid, r->d.gid) == 0)
+			break;
+		respond(r, "not owner");
+		return;
+	}
+
+	/* To change mode, must be owner or group leader.
+	 * Because of lack of users file, leader=>group itself. */
+	if(r->d.mode != ~0 && f->mode != r->d.mode){
+		if(strcmp(uid, f->uid) != 0)
+		if(strcmp(uid, f->gid) != 0){
+			respond(r, "not owner");
+			return;
+		}
+	}
+
+	if(r->d.name[0] != '\0'){
+		free(f->name);
+		f->name = estrdup(r->d.name);
+	}
+	if(r->d.uid[0] != '\0'){
+		free(f->uid);
+		f->uid = estrdup(r->d.uid);
+	}
+	if(r->d.gid[0] != '\0'){
+		free(f->gid);
+		f->gid = estrdup(r->d.gid);
+	}
+	if(r->d.mode != ~0){
+		f->mode = r->d.mode;
+		f->qid.type = f->mode >> 24;
+	}
+
+	respond(r, nil);
+	return;
+perm:
+	respond(r, "permission denied");
+}
+
+void
 xdestroyfid(Fid *fid)
 {
 	Client *f = fid->aux;
@@ -461,6 +529,7 @@
 	.write = xwrite,
 	.read = xread,
 	.flush = xflush,
+	.wstat = xwstat,
 	.destroyfid = xdestroyfid,
 };