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