code: plan9front

Download patch

ref: de1a460fa13ed2bffbdc3cb046cc8831c1d22008
parent: 0196ca7536c295b42e1d27ab8187a3d8e1bda328
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Tue Apr 2 16:52:14 EDT 2024

ext4srv: add append-only and temp files support

--- a/sys/src/cmd/ext4srv/ext4.c
+++ b/sys/src/cmd/ext4srv/ext4.c
@@ -792,7 +792,9 @@
 	}
 
 	if (is_goal) {
-		if ((f->flags & O_TRUNC) && (imode == EXT4_INODE_MODE_FILE)) {
+		if (f->flags != O_RDONLY && !ext4_inode_can_truncate(sb, ref.inode))
+			f->flags |= O_APPEND;
+		if ((f->flags & (O_TRUNC|O_APPEND)) == O_TRUNC && imode == EXT4_INODE_MODE_FILE) {
 			r = ext4_trunc_inode(mp, ref.index, 0);
 			if (r != 0) {
 				ext4_fs_put_inode_ref(&ref);
@@ -803,10 +805,7 @@
 		f->mp = mp;
 		f->fsize = ext4_inode_get_size(sb, ref.inode);
 		f->inode = ref.index;
-		f->fpos = 0;
-
-		if (f->flags & O_APPEND)
-			f->fpos = f->fsize;
+		f->fpos = (f->flags & O_APPEND) ? f->fsize : 0;
 	}
 
 	return ext4_fs_put_inode_ref(&ref);
@@ -1164,6 +1163,7 @@
 	/*Link count will be zero, the inode should be freed. */
 	if (ext4_inode_get_links_cnt(child.inode) == 1) {
 		ext4_block_cache_write_back(mp->fs.bdev, 1);
+		ext4_inode_clear_flag(child.inode, EXT4_INODE_FLAG_APPEND);
 		r = ext4_trunc_inode(mp, child.index, 0);
 		if (r != 0) {
 			ext4_fs_put_inode_ref(&parent);
@@ -1806,7 +1806,7 @@
 	return r;
 }
 
-int ext4_mode_set(struct ext4_mountpoint *mp, const char *path, u32int mode)
+int ext4_mode_set(struct ext4_mountpoint *mp, const char *path, u32int mode, u32int iflags)
 {
 	int r;
 	u32int orig_mode;
@@ -1827,6 +1827,10 @@
 	orig_mode &= ~0xFFF;
 	orig_mode |= mode & 0xFFF;
 	ext4_inode_set_mode(&mp->fs.sb, inode_ref.inode, orig_mode);
+	iflags &= EXT4_INODE_FLAG_APPEND | EXT4_INODE_FLAG_NODUMP;
+	ext4_inode_set_flag(inode_ref.inode, iflags);
+	iflags ^= EXT4_INODE_FLAG_APPEND | EXT4_INODE_FLAG_NODUMP;
+	ext4_inode_clear_flag(inode_ref.inode, iflags);
 
 	inode_ref.dirty = true;
 	r = ext4_trans_put_inode_ref(mp, &inode_ref);
--- a/sys/src/cmd/ext4srv/ext4srv.c
+++ b/sys/src/cmd/ext4srv/ext4srv.c
@@ -243,8 +243,8 @@
 static void
 rcreate(Req *r)
 {
+	u32int perm, dirperm, t, iflags;
 	struct ext4_mountpoint *mp;
-	u32int perm, dirperm, t;
 	struct ext4_inode inode;
 	int mkdir, isroot;
 	long tm;
@@ -306,7 +306,12 @@
 		}
 	}
 
-	if(ext4_mode_set(mp, s, perm) < 0)
+	iflags = 0;
+	if(r->ifcall.perm & DMAPPEND)
+		iflags |= EXT4_INODE_FLAG_APPEND;
+	if(r->ifcall.perm & DMTMP)
+		iflags |= EXT4_INODE_FLAG_NODUMP;
+	if(ext4_mode_set(mp, s, perm, iflags) < 0)
 		goto ext4errorrm;
 	ext4_owner_set(mp, s, a->uid, a->uid);
 	tm = time(nil);
@@ -338,8 +343,8 @@
 dirfill(Dir *dir, Aux *a, char *path)
 {
 	struct ext4_mountpoint *mp;
+	u32int t, ino, id, iflags;
 	struct ext4_inode inode;
-	u32int t, ino, id;
 	char tmp[16];
 	Group *g;
 	char *s;
@@ -360,7 +365,7 @@
 		return -1;
 	}
 
-	dir->mode = ext4_inode_get_mode(a->p->sb, &inode) & 0x1ff;
+	dir->mode = ext4_inode_get_mode(a->p->sb, &inode) & 0777;
 	dir->qid.path = a->p->qidmask.path | ino;
 	dir->qid.vers = ext4_inode_get_generation(&inode);
 	dir->qid.type = 0;
@@ -370,10 +375,16 @@
 		dir->mode |= DMDIR;
 	}else
 		dir->length = ext4_inode_get_size(a->p->sb, &inode);
-	if(ext4_inode_get_flags(&inode) & EXT4_INODE_FLAG_APPEND){
+
+	iflags = ext4_inode_get_flags(&inode);
+	if(iflags & EXT4_INODE_FLAG_APPEND){
 		dir->qid.type |= QTAPPEND;
 		dir->mode |= DMAPPEND;
 	}
+	if(iflags & EXT4_INODE_FLAG_NODUMP){
+		dir->qid.type |= QTTMP;
+		dir->mode |= DMTMP;
+	}
 
 	if(path != nil && (s = strrchr(path, '/')) != nil)
 		path = s+1;
@@ -458,11 +469,13 @@
 			if(ext4_fwrite(a->file, zero, sz, &n) < 0)
 				goto error;
 		}
-		if(ext4_fseek(a->file, r->ifcall.offset, 0) < 0)
-			goto error;
-		if(ext4_ftell(a->file) != r->ifcall.offset){
-			werrstr("could not seek");
-			goto error;
+		if((a->file->flags & O_APPEND) == 0){
+			if(ext4_fseek(a->file, r->ifcall.offset, 0) < 0)
+				goto error;
+			if(ext4_ftell(a->file) != r->ifcall.offset){
+				werrstr("could not seek");
+				goto error;
+			}
 		}
 		if(ext4_fwrite(a->file, r->ifcall.data, r->ifcall.count, &n) < 0)
 			goto error;
@@ -472,7 +485,7 @@
 		respond(r, nil);
 		return;
 	}else{
-		werrstr("can only write to files");
+		werrstr(Eperm);
 	}
 
 error:
@@ -543,7 +556,7 @@
 	int res, isdir, wrperm, isowner, n;
 	struct ext4_mountpoint *mp;
 	struct ext4_inode inode;
-	u32int uid, gid;
+	u32int uid, gid, iflags;
 	ext4_file f;
 	Aux *a, o;
 	Group *g;
@@ -564,7 +577,7 @@
 
 	/* permission to truncate */
 	isdir = ext4_inode_type(a->p->sb, &inode) == EXT4_INODE_MODE_DIRECTORY;
-	if(r->d.length >= 0 && (!wrperm || isdir || !ext4_inode_can_truncate(a->p->sb, &inode))){
+	if(r->d.length >= 0 && (!wrperm || isdir)){
 		werrstr(Eperm);
 		goto error;
 	}
@@ -622,7 +635,7 @@
 	}
 
 	/* truncate */
-	if(r->d.length >= 0){
+	if(r->d.length >= 0 && ext4_inode_can_truncate(a->p->sb, &inode)){
 		if(ext4_fopen2(mp, &f, a->path, toext4mode(OWRITE, 0, 0)) < 0)
 			goto error;
 		res = ext4_ftruncate(&f, r->d.length);
@@ -632,8 +645,15 @@
 	}
 
 	/* mode */
-	if(r->d.mode != ~0 && ext4_mode_set(mp, a->path, r->d.mode & 0x1ff) < 0)
-		goto error;
+	if(r->d.mode != ~0){
+		iflags = 0;
+		if(r->d.mode & DMAPPEND)
+			iflags |= EXT4_INODE_FLAG_APPEND;
+		if(r->d.mode & DMTMP)
+			iflags |= EXT4_INODE_FLAG_NODUMP;
+		if(ext4_mode_set(mp, a->path, r->d.mode & 0777, iflags) < 0)
+			goto error;
+	}
 
 	/* mtime */
 	if(r->d.mtime != ~0 && ext4_mtime_set(mp, a->path, r->d.mtime) < 0)
--- a/sys/src/cmd/ext4srv/include/ext4.h
+++ b/sys/src/cmd/ext4srv/include/ext4.h
@@ -263,7 +263,7 @@
  * @param mode New mode bits (for example 0777).
  *
  * @return  Standard error code.*/
-int ext4_mode_set(struct ext4_mountpoint *mp, const char *path, u32int mode);
+int ext4_mode_set(struct ext4_mountpoint *mp, const char *path, u32int mode, u32int iflags);
 
 
 /**@brief Get file/directory/link mode bits.