shithub: ext4srv

Download patch

ref: 3c3627dae0b3dc59dbe56f59ac6e4c4aa26349d3
parent: b473117350fbb8c292231befcd8987d7eed042e6
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Thu Nov 12 12:30:48 EST 2020

add Tcreate support

--- a/ext4srv.c
+++ b/ext4srv.c
@@ -30,6 +30,8 @@
 
 static Opts opts;
 
+static char Eperm[] = "permission denied";
+
 static char *
 linkresolve(Aux *a, char *s, char **value)
 {
@@ -77,7 +79,7 @@
 }
 
 static int
-haveperm(Aux *a, int p)
+haveperm(Aux *a, int p, struct ext4_inode *inodeout)
 {
 	struct ext4_inode inode;
 	u32int ino, id;
@@ -111,6 +113,9 @@
 	}
 	free(s);
 
+	if(inodeout != nil)
+		memmove(inodeout, &inode, sizeof(inode));
+
 	fm = ext4_inode_get_mode(a->p->sb, &inode);
 
 	/* other */
@@ -201,8 +206,8 @@
 	a = r->fid->aux;
 	switch(a->type){
 	case Adir:
-		if(r->ifcall.mode != OREAD || !haveperm(a, r->ifcall.mode)){
-			respond(r, "permission denied");
+		if(r->ifcall.mode != OREAD || !haveperm(a, r->ifcall.mode, nil)){
+			respond(r, Eperm);
 			return;
 		}
 		if(a->dir != nil){
@@ -227,8 +232,8 @@
 		break;
 
 	case Afile:
-		if(!haveperm(a, r->ifcall.mode)){
-			respond(r, "permission denied");
+		if(!haveperm(a, r->ifcall.mode, nil)){
+			respond(r, Eperm);
 			return;
 		}
 		if(a->file != nil){
@@ -263,7 +268,95 @@
 static void
 rcreate(Req *r)
 {
-	respond(r, "nope");
+	struct ext4_inode inode;
+	u32int perm, dirperm, t;
+	char *s, *err, *q;
+	int mkdir, res;
+	Aux *a;
+
+	a = r->fid->aux;
+	err = nil;
+	s = nil;
+
+	if(!haveperm(a, OWRITE, &inode)){
+		err = Eperm;
+		goto error;
+	}
+
+	/* first make sure this is a directory */
+	t = ext4_inode_type(a->p->sb, &inode);
+	if((t & EXT4_INODE_MODE_DIRECTORY) == 0){
+		err = "create in non-directory";
+		goto error;
+	}
+
+	if((s = fullpath(a)) == nil){
+		fprint(2, "%M/%s: not found\n", a->p, a->path);
+		goto error;
+	}
+	ext4_mode_get(s, &dirperm);
+
+	/* check if the entry already exists */
+	if((q = smprint("%s/%s", s, r->ifcall.name)) == nil){
+Nomem:
+		err = "memory";
+		goto error;
+	}
+	free(s);
+	s = q;
+	if(ext4_inode_exist(s, EXT4_DE_UNKNOWN) == 0){
+		err = "already exists";
+		goto error;
+	}
+
+	mkdir = r->ifcall.perm & DMDIR;
+	perm = mkdir ? 0666 : 0777;
+	perm = r->ifcall.perm & (~perm | (dirperm & perm));
+
+	if(mkdir){
+		if((res = ext4_dir_mk(s)) != 0){
+			fprint(2, "mkdir %s failed\n", s);
+			goto ext4error;
+		}
+		if((a->dir = malloc(sizeof(*a->dir))) == nil)
+			goto Nomem;
+		if((res = ext4_dir_open(a->dir, s)) != 0){
+			free(a->dir);
+			a->dir = nil;
+			goto ext4errorrm;
+		}
+	}else{
+		if((a->file = malloc(sizeof(*a->file))) == nil)
+			goto Nomem;
+		if((res = ext4_fopen2(a->file, s, toext4mode(r->ifcall.mode, perm, 1))) != 0){
+			fprint(2, "fopen2 %s failed\n", s);
+			free(a->file);
+			a->file = nil;
+			goto ext4error;
+		}
+	}
+
+	if((res = ext4_mode_set(s, perm)) != 0){
+		fprint(2, "mode_set %s failed\n", s);
+		goto ext4errorrm;
+	}
+	ext4_owner_set(s, a->uid, ext4_inode_get_gid(&inode));
+
+	a->path = strdup(strchr(s+1, '/')+1);
+	free(s);
+	respond(r, nil);
+	return;
+
+ext4errorrm:
+	if(mkdir)
+		ext4_dir_rm(s);
+	else
+		ext4_fremove(s);
+ext4error:
+	err = errno2s(res);
+error:
+	free(s);
+	respond(r, err);
 }
 
 static int
@@ -439,7 +532,7 @@
 		}else if((res = ext4_fremove(s)) != 0)
 			goto ext4error;
 	}else{
-		err = "permission denied";
+		err = Eperm;
 	}
 
 end:
@@ -497,9 +590,9 @@
 	}
 	dir = *a;
 	dir.path = s;
-	if(!haveperm(&dir, OEXEC)){
+	if(!haveperm(&dir, OEXEC, nil)){
 		free(s);
-		return "permission denied";
+		return Eperm;
 	}
 
 	q = s;
--- a/group.c
+++ b/group.c
@@ -5,8 +5,8 @@
 int
 loadgroups(Groups *gs, char *raw)
 {
-	Group *g, *memb;
 	char *m, *s, *e, *a[5], *ide;
+	Group *g, *memb;
 	int line, n, k;
 	vlong id;
 
@@ -79,8 +79,8 @@
 Group *
 findgroup(Groups *gs, char *name, u32int *id)
 {
-	int i;
 	Group *g;
+	int i;
 
 	g = gs->g;
 	for(i = 0; i < gs->ng; i++, g++){
@@ -100,8 +100,8 @@
 Group *
 findgroupid(Groups *gs, u32int id)
 {
-	int i;
 	Group *g;
+	int i;
 
 	g = gs->g;
 	for(i = 0; i < gs->ng; i++, g++){