$ cat goodfilename
coincoin

$ perl -pi -e 's/toto/tutu/' goodfilename
works

$ cp goodfilename /tmp
$ perl -pi -e 's/toto/tutu/' /tmp/goodfilename
Can't do inplace edit on goodfilename: File exists.
$ cat /tmp/goodfilename
cat: /tmp/goodfilename: No such file or directory.

ktrace shows a disturbing lack of Unix semantics:
....
15350 perl     CALL  open(0x1850b9e863f0,0<O_RDONLY>)
15350 perl     NAMI  "goodfilename"
15350 perl     RET   open 3
...
15350 perl     CALL  unlink(0x1850b9e86a00)
15350 perl     NAMI  "goodfilename"
15350 perl     RET   unlink 0
15350 perl     CALL  
open(0x1850b9e868e0,0xa01<O_WRONLY|O_CREAT|O_EXCL>,0x180<S_IRUSR|S_IWUSR>)
15350 perl     NAMI  "goodfilename"
15350 perl     RET   open -1 errno 17 File exists


err...

simply put:

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

int
main()
{
        if (open("fucked_up", O_RDWR|O_CREAT|O_TRUNC, 0666) == -1)
                perror("open");
        if (unlink("fucked_up") != 0)
                perror("unlink");
        if (open("fucked_up", O_WRONLY|O_CREAT|O_EXCL, 0666) == -1)
                perror("reopen");
        return 0;
}

Thank you very much for spotting this. The problem was a missing check
when calling cache_enter() from tmpfs_lookup(). I have fixed the glitch
in version 4 of the diff:

http://block.io/tmpfs/tmpfs4.diff

Alternatively, you might want to ammend the source code directly, since
it is a one-line change. In tmpfs_vnops.c, replace the following check
in line 289

        if (cnp->cn_nameiop != CREATE) {
                cache_enter(dvp, *vpp, cnp);
        }

with

        if ((cnp->cn_flags & MAKEENTRY) && cnp->cn_nameiop != CREATE) {
                cache_enter(dvp, *vpp, cnp);
        }

-p.

Reply via email to