move "link or copy" functionality to moxio

and add a bit more logging for unexpected failures when closing files.
and make tests pass with a TMPDIR on a different filesystem than the testdata directory.
This commit is contained in:
Mechiel Lukkien
2023-07-23 12:15:29 +02:00
parent 4a4d337ab4
commit 3e9b4107fd
12 changed files with 165 additions and 144 deletions

View File

@ -693,13 +693,11 @@ func (a *Account) DeliverMessage(log *mlog.Log, tx *bstore.Tx, m *Message, msgFi
if consumeFile {
if err := os.Rename(msgFile.Name(), msgPath); err != nil {
// Could be due to cross-filesystem rename. Users shouldn't configure their systems that way.
return fmt.Errorf("moving msg file to destination directory: %w", err)
}
} else if err := os.Link(msgFile.Name(), msgPath); err != nil {
// Assume file system does not support hardlinks. Copy it instead.
if err := writeFile(msgPath, &moxio.AtReader{R: msgFile}); err != nil {
return fmt.Errorf("copying message to new file: %w", err)
}
} else if err := moxio.LinkOrCopy(log, msgPath, msgFile.Name(), &moxio.AtReader{R: msgFile}, true); err != nil {
return fmt.Errorf("linking/copying message to new file: %w", err)
}
if sync {
@ -719,28 +717,6 @@ func (a *Account) DeliverMessage(log *mlog.Log, tx *bstore.Tx, m *Message, msgFi
return nil
}
// write contents of r to new file dst, for delivering a message.
func writeFile(dst string, r io.Reader) error {
df, err := os.OpenFile(dst, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0660)
if err != nil {
return fmt.Errorf("create: %w", err)
}
defer func() {
if df != nil {
df.Close()
}
}()
if _, err := io.Copy(df, r); err != nil {
return fmt.Errorf("copy: %s", err)
} else if err := df.Sync(); err != nil {
return fmt.Errorf("sync: %s", err)
} else if err := df.Close(); err != nil {
return fmt.Errorf("close: %s", err)
}
df = nil
return nil
}
// SetPassword saves a new password for this account. This password is used for
// IMAP, SMTP (submission) sessions and the HTTP account web page.
func (a *Account) SetPassword(password string) error {