ref: de1a460fa13ed2bffbdc3cb046cc8831c1d22008
parent: 0196ca7536c295b42e1d27ab8187a3d8e1bda328
author: Sigrid Solveig Haflínudóttir <[email protected]>
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.