mirror of
https://github.com/mjl-/mox.git
synced 2025-07-15 04:54:35 +03:00
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:
@ -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 {
|
||||
|
@ -231,20 +231,6 @@ func TestMailbox(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteFile(t *testing.T) {
|
||||
name := "../testdata/account.test"
|
||||
os.Remove(name)
|
||||
defer os.Remove(name)
|
||||
err := writeFile(name, strings.NewReader("test"))
|
||||
if err != nil {
|
||||
t.Fatalf("writeFile, unexpected error %v", err)
|
||||
}
|
||||
buf, err := os.ReadFile(name)
|
||||
if err != nil || string(buf) != "test" {
|
||||
t.Fatalf("writeFile, read file, got err %v, data %q", err, buf)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMessageRuleset(t *testing.T) {
|
||||
f, err := os.Open("/dev/null")
|
||||
tcheck(t, err, "open")
|
||||
|
@ -30,7 +30,7 @@ func TestExport(t *testing.T) {
|
||||
|
||||
log := mlog.New("export")
|
||||
|
||||
msgFile, err := os.CreateTemp("", "mox-test-export")
|
||||
msgFile, err := CreateMessageTemp("mox-test-export")
|
||||
tcheck(t, err, "create temp")
|
||||
defer os.Remove(msgFile.Name()) // To be sure.
|
||||
const msg = "test: test\r\n\r\ntest\r\n"
|
||||
|
10
store/tmp.go
10
store/tmp.go
@ -6,10 +6,12 @@ import (
|
||||
"github.com/mjl-/mox/mox-"
|
||||
)
|
||||
|
||||
// CreateMessageTemp creates a temporary file for a message to be delivered.
|
||||
// Caller is responsible for removing the temporary file on error, and for closing the file.
|
||||
// Caller should ensure the contents of the file are synced to disk before
|
||||
// attempting to deliver the message.
|
||||
// CreateMessageTemp creates a temporary file, e.g. for delivery. The is created in
|
||||
// subdirectory tmp of the data directory, so the file is on the same file system
|
||||
// as the accounts directory, so renaming files can succeed. The caller is
|
||||
// responsible for closing and possibly removing the file. The caller should ensure
|
||||
// the contents of the file are synced to disk before attempting to deliver the
|
||||
// message.
|
||||
func CreateMessageTemp(pattern string) (*os.File, error) {
|
||||
dir := mox.DataDirPath("tmp")
|
||||
os.MkdirAll(dir, 0770)
|
||||
|
Reference in New Issue
Block a user