2015-07-11 15:03:40 +00:00
|
|
|
// Copyright (C) 2015 The Syncthing Authors.
|
|
|
|
//
|
|
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
2017-02-09 06:52:18 +00:00
|
|
|
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
2015-07-11 15:03:40 +00:00
|
|
|
|
|
|
|
package osutil
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"os"
|
2020-04-07 13:38:55 +00:00
|
|
|
"path/filepath"
|
2015-07-11 15:03:40 +00:00
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestCreateAtomicCreate(t *testing.T) {
|
|
|
|
os.RemoveAll("testdata")
|
|
|
|
defer os.RemoveAll("testdata")
|
|
|
|
|
|
|
|
if err := os.Mkdir("testdata", 0755); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2016-11-23 14:06:08 +00:00
|
|
|
w, err := CreateAtomic("testdata/file")
|
2015-07-11 15:03:40 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
n, err := w.Write([]byte("hello"))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if n != 5 {
|
|
|
|
t.Fatal("written bytes", n, "!= 5")
|
|
|
|
}
|
|
|
|
|
2021-11-22 07:59:47 +00:00
|
|
|
if _, err := os.ReadFile("testdata/file"); err == nil {
|
2015-07-11 15:03:40 +00:00
|
|
|
t.Fatal("file should not exist")
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := w.Close(); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2021-11-22 07:59:47 +00:00
|
|
|
bs, err := os.ReadFile("testdata/file")
|
2015-07-11 15:03:40 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if !bytes.Equal(bs, []byte("hello")) {
|
|
|
|
t.Error("incorrect data")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCreateAtomicReplace(t *testing.T) {
|
2020-04-07 13:38:55 +00:00
|
|
|
testCreateAtomicReplace(t, 0666)
|
2020-04-04 12:17:16 +00:00
|
|
|
}
|
|
|
|
func TestCreateAtomicReplaceReadOnly(t *testing.T) {
|
2020-04-07 13:38:55 +00:00
|
|
|
testCreateAtomicReplace(t, 0444) // windows compatible read-only bits
|
2020-04-04 12:17:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func testCreateAtomicReplace(t *testing.T, oldPerms os.FileMode) {
|
|
|
|
t.Helper()
|
|
|
|
|
2021-11-22 07:59:47 +00:00
|
|
|
testdir, err := os.MkdirTemp("", "syncthing")
|
2020-04-07 13:38:55 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
testfile := filepath.Join(testdir, "testfile")
|
2015-07-11 15:03:40 +00:00
|
|
|
|
2020-04-07 13:38:55 +00:00
|
|
|
os.RemoveAll(testdir)
|
|
|
|
defer os.RemoveAll(testdir)
|
|
|
|
|
|
|
|
if err := os.Mkdir(testdir, 0755); err != nil {
|
2015-07-11 15:03:40 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2021-11-22 07:59:47 +00:00
|
|
|
if err := os.WriteFile(testfile, []byte("some old data"), oldPerms); err != nil {
|
2015-07-11 15:03:40 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2020-04-07 13:38:55 +00:00
|
|
|
// Go < 1.14 has a bug in WriteFile where it does not use the requested
|
|
|
|
// permissions on Windows. Chmod to make sure.
|
|
|
|
if err := os.Chmod(testfile, oldPerms); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
// Trust, but verify.
|
|
|
|
if info, err := os.Stat(testfile); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if info.Mode() != oldPerms {
|
|
|
|
t.Fatalf("Wrong perms 0%o", info.Mode())
|
|
|
|
}
|
|
|
|
|
|
|
|
w, err := CreateAtomic(testfile)
|
2015-07-11 15:03:40 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := w.Write([]byte("hello")); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if err := w.Close(); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2021-11-22 07:59:47 +00:00
|
|
|
bs, err := os.ReadFile(testfile)
|
2015-07-11 15:03:40 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if !bytes.Equal(bs, []byte("hello")) {
|
|
|
|
t.Error("incorrect data")
|
|
|
|
}
|
2020-08-10 16:48:37 +00:00
|
|
|
|
|
|
|
if info, err := os.Stat(testfile); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if info.Mode() != oldPerms {
|
|
|
|
t.Fatalf("Perms changed during atomic write: 0%o", info.Mode())
|
|
|
|
}
|
2015-07-11 15:03:40 +00:00
|
|
|
}
|