Strange behaviour with sappend flag set on ZFS
    Michael Naef 
    cal at linu.gs
       
    Thu Sep 23 18:03:25 UTC 2010
    
    
  
Hi fs people
Background: When moving from pre-8.0 to FreeBSD 8.1 on ZFS I 
realised that the bash history is no longer beeing written if the 
file has the sappend flag set. Other programs like script (1) 
however are surprisingly still able to write to such files. So it 
seemed that they handle file IO differently.
(Looking at the source code of both I learned that bash uses write 
(2) while script uses fwrite (3)... After some more testing and 
investigation,) it seems that zfs behaves differently to ufs in one 
point.
If I open (2) a file with O_APPEND the fd position pointer is set 
to the start of the file. When I then write to an fd on a ufs FS in 
FB6.4, it is automatically moved to the end and the bytes are 
appended. No problems appear with write to the sappend-flages file.
However if I do the same on FB8.1/ZFS, the write fails as "not 
permitted". When I manually move the position pointer to the end of 
the file, it works as axpected:
FreeBSD 6.4/UFS:
root at fb64 [~/michi]# touch gaga
root at fb64 [~/michi]# chflags sappend gaga 
root at fb64 [~/michi]# ./write 
fd: 3
pos: 0
bytes written: 6
pos: 50
bytes written: 6
FreeBSD 8.1/ZFS:
root at server52 [~/michi]# chflags sappend gaga 
root at fb81 [~/michi]# touch gaga
root at fb81 [~/michi]# chflags sappend gaga 
root at fb81 [~/michi]# ./write
fd: 3
pos: 0
ERROR: Operation not permitted
pos: 147
bytes written: 6
The source code is:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
int main(void){
        int file= open("gaga",O_WRONLY|O_APPEND|O_CREAT,0666);
        int bytes_written= 0;
        printf("fd: %i\n",file);
        printf("pos: %i\n",lseek(file,0,SEEK_CUR));
        if ((bytes_written= write(file,"write\n",6)) == -1){
                printf("ERROR: %s\n",strerror(errno));
        }else{
                printf("bytes written: %i\n",bytes_written);
        }
        lseek(file,0,SEEK_END);
        printf("pos: %i\n",lseek(file,0,SEEK_CUR));
        if ((bytes_written= write(file,"write\n",6)) == -1){
                printf("ERROR: %s\n",strerror(errno));
        }else{
                printf("bytes written: %i\n",bytes_written);
        }
        close(file);
}
Am I missing something or is this a bug (or feature or watsoever 
;-) in ZFS?
thanks a lot you (z)fs guys and cheers, Michi
    
    
More information about the freebsd-fs
mailing list