diff options
author | Eric Wong <e@80x24.org> | 2021-10-21 21:10:32 +0000 |
---|---|---|
committer | Eric Wong <e@80x24.org> | 2021-10-22 00:54:51 +0000 |
commit | 4cd7a78f3b8c03670e2d77675229472506eee1eb (patch) | |
tree | 2a0e89de3e77b70962e509d41883518fb6574dde /lib/PublicInbox/LeiToMail.pm | |
parent | 2c354e17694da744c6dc1ab19c14af3d456b28bb (diff) | |
download | public-inbox-4cd7a78f3b8c03670e2d77675229472506eee1eb.tar.gz |
One syscall is better than two for atomicity in Maildirs. This means there's no window where another process can see both the old and new file at the same time (link && unlink), nor a window where we might inadvertantly clobber an existing file if we were to do `stat && rename'.
Diffstat (limited to 'lib/PublicInbox/LeiToMail.pm')
-rw-r--r-- | lib/PublicInbox/LeiToMail.pm | 7 |
1 files changed, 3 insertions, 4 deletions
diff --git a/lib/PublicInbox/LeiToMail.pm b/lib/PublicInbox/LeiToMail.pm index ca4e92de..d33d27ae 100644 --- a/lib/PublicInbox/LeiToMail.pm +++ b/lib/PublicInbox/LeiToMail.pm @@ -12,6 +12,7 @@ use PublicInbox::Spawn qw(spawn); use Symbol qw(gensym); use IO::Handle; # ->autoflush use Fcntl qw(SEEK_SET SEEK_END O_CREAT O_EXCL O_WRONLY); +use PublicInbox::Syscall qw(rename_noreplace); my %kw2char = ( # Maildir characters draft => 'D', @@ -262,10 +263,8 @@ sub _buf2maildir ($$$$) { $rand = ''; do { $base = $rand.$common.':2,'.kw2suffix($kw); - } while (!($ok = link($tmp, $dst.$base)) && $!{EEXIST} && - ($rand = _rand.',')); - die "link($tmp, $dst$base): $!" unless $ok; - unlink($tmp) or warn "W: failed to unlink $tmp: $!\n"; + } while (!($ok = rename_noreplace($tmp, $dst.$base)) && + $!{EEXIST} && ($rand = _rand.',')); \$base; } else { my $err = "Error writing $smsg->{blob} to $dst: $!\n"; |