From 66fd442d487da7e9853eb467ff908ff0c1971756 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Thu, 1 Jun 2017 15:59:37 +0200 Subject: pkg/fileutil: move from fileutil --- csource/csource_test.go | 2 +- fileutil/fileutil.go | 110 ------------------------------------------ fileutil/fileutil_test.go | 65 ------------------------- ipc/ipc.go | 2 +- ipc/ipc_test.go | 2 +- pkg/fileutil/fileutil.go | 110 ++++++++++++++++++++++++++++++++++++++++++ pkg/fileutil/fileutil_test.go | 65 +++++++++++++++++++++++++ repro/repro.go | 2 +- syz-manager/config/config.go | 2 +- vm/kvm/kvm.go | 2 +- vm/local/local.go | 2 +- 11 files changed, 182 insertions(+), 182 deletions(-) delete mode 100644 fileutil/fileutil.go delete mode 100644 fileutil/fileutil_test.go create mode 100644 pkg/fileutil/fileutil.go create mode 100644 pkg/fileutil/fileutil_test.go diff --git a/csource/csource_test.go b/csource/csource_test.go index 78998a32f..abff96f72 100644 --- a/csource/csource_test.go +++ b/csource/csource_test.go @@ -10,7 +10,7 @@ import ( "testing" "time" - "github.com/google/syzkaller/fileutil" + "github.com/google/syzkaller/pkg/fileutil" "github.com/google/syzkaller/prog" ) diff --git a/fileutil/fileutil.go b/fileutil/fileutil.go deleted file mode 100644 index c244204a9..000000000 --- a/fileutil/fileutil.go +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2015 syzkaller project authors. All rights reserved. -// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. - -package fileutil - -import ( - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "strconv" - "syscall" - "unsafe" -) - -// CopyFile copies oldFile to newFile. -func CopyFile(oldFile, newFile string) error { - oldf, err := os.Open(oldFile) - if err != nil { - return err - } - defer oldf.Close() - newf, err := os.Create(newFile) - if err != nil { - return err - } - defer newf.Close() - _, err = io.Copy(newf, oldf) - if err != nil { - return err - } - return nil -} - -// WriteTempFile writes data to a temp file and returns its name. -func WriteTempFile(data []byte) (string, error) { - f, err := ioutil.TempFile("", "syzkaller") - if err != nil { - return "", fmt.Errorf("failed to create a temp file: %v", err) - } - if _, err := f.Write(data); err != nil { - f.Close() - os.Remove(f.Name()) - return "", fmt.Errorf("failed to write a temp file: %v", err) - } - f.Close() - return f.Name(), nil -} - -// ProcessTempDir creates a new temp dir in where and returns its path and an unique index. -// It also cleans up old, unused temp dirs after dead processes. -func ProcessTempDir(where string) (string, error) { - lk := filepath.Join(where, "instance-lock") - lkf, err := syscall.Open(lk, syscall.O_RDWR|syscall.O_CREAT, 0600) - if err != nil { - return "", err - } - defer syscall.Close(lkf) - if err := syscall.Flock(lkf, syscall.LOCK_EX); err != nil { - return "", err - } - defer syscall.Flock(lkf, syscall.LOCK_UN) - - for i := 0; i < 1e3; i++ { - path := filepath.Join(where, fmt.Sprintf("instance-%v", i)) - pidfile := filepath.Join(path, ".pid") - err := os.Mkdir(path, 0700) - if os.IsExist(err) { - // Try to clean up. - data, err := ioutil.ReadFile(pidfile) - if err == nil && len(data) > 0 { - pid, err := strconv.Atoi(string(data)) - if err == nil && pid > 1 { - if err := syscall.Kill(pid, 0); err == syscall.ESRCH { - if os.Remove(pidfile) == nil { - if os.RemoveAll(path) == nil { - i-- - continue - } - } - } - } - } - // If err != nil, assume that the pid file is not created yet. - continue - } - if err != nil { - return "", err - } - if err := ioutil.WriteFile(pidfile, []byte(strconv.Itoa(syscall.Getpid())), 0600); err != nil { - return "", err - } - return path, nil - } - return "", fmt.Errorf("too many live instances") -} - -// UmountAll recurusively unmounts all mounts in dir. -func UmountAll(dir string) { - files, _ := ioutil.ReadDir(dir) - for _, f := range files { - name := filepath.Join(dir, f.Name()) - if f.IsDir() { - UmountAll(name) - } - fn := []byte(name + "\x00") - syscall.Syscall(syscall.SYS_UMOUNT2, uintptr(unsafe.Pointer(&fn[0])), syscall.MNT_FORCE, 0) - } -} diff --git a/fileutil/fileutil_test.go b/fileutil/fileutil_test.go deleted file mode 100644 index d432ef5e7..000000000 --- a/fileutil/fileutil_test.go +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2015 syzkaller project authors. All rights reserved. -// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. - -package fileutil - -import ( - "io/ioutil" - "os" - "path/filepath" - "strconv" - "sync" - "testing" -) - -func TestProcessTempDir(t *testing.T) { - for try := 0; try < 10; try++ { - func() { - tmp, err := ioutil.TempDir("", "syz") - if err != nil { - t.Fatalf("failed to create a temp dir: %v", err) - } - defer os.RemoveAll(tmp) - const P = 16 - // Pre-create half of the instances with stale pid. - var dirs []string - for i := 0; i < P/2; i++ { - dir, err := ProcessTempDir(tmp) - if err != nil { - t.Fatalf("failed to create process temp dir") - } - dirs = append(dirs, dir) - } - for _, dir := range dirs { - if err := ioutil.WriteFile(filepath.Join(dir, ".pid"), []byte(strconv.Itoa(999999999)), 0600); err != nil { - t.Fatalf("failed to write pid file: %v", err) - } - } - // Now request a bunch of instances concurrently. - done := make(chan bool) - allDirs := make(map[string]bool) - var mu sync.Mutex - for p := 0; p < P; p++ { - go func() { - defer func() { - done <- true - }() - dir, err := ProcessTempDir(tmp) - if err != nil { - t.Fatalf("failed to create process temp dir") - } - mu.Lock() - present := allDirs[dir] - allDirs[dir] = true - mu.Unlock() - if present { - t.Fatalf("duplicate dir %v", dir) - } - }() - } - for p := 0; p < P; p++ { - <-done - } - }() - } -} diff --git a/ipc/ipc.go b/ipc/ipc.go index 5d579b479..6c68433b6 100644 --- a/ipc/ipc.go +++ b/ipc/ipc.go @@ -18,7 +18,7 @@ import ( "time" "unsafe" - "github.com/google/syzkaller/fileutil" + "github.com/google/syzkaller/pkg/fileutil" "github.com/google/syzkaller/prog" ) diff --git a/ipc/ipc_test.go b/ipc/ipc_test.go index 726da8485..6dc019f87 100644 --- a/ipc/ipc_test.go +++ b/ipc/ipc_test.go @@ -10,7 +10,7 @@ import ( "time" "github.com/google/syzkaller/csource" - "github.com/google/syzkaller/fileutil" + "github.com/google/syzkaller/pkg/fileutil" "github.com/google/syzkaller/prog" ) diff --git a/pkg/fileutil/fileutil.go b/pkg/fileutil/fileutil.go new file mode 100644 index 000000000..c244204a9 --- /dev/null +++ b/pkg/fileutil/fileutil.go @@ -0,0 +1,110 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package fileutil + +import ( + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "syscall" + "unsafe" +) + +// CopyFile copies oldFile to newFile. +func CopyFile(oldFile, newFile string) error { + oldf, err := os.Open(oldFile) + if err != nil { + return err + } + defer oldf.Close() + newf, err := os.Create(newFile) + if err != nil { + return err + } + defer newf.Close() + _, err = io.Copy(newf, oldf) + if err != nil { + return err + } + return nil +} + +// WriteTempFile writes data to a temp file and returns its name. +func WriteTempFile(data []byte) (string, error) { + f, err := ioutil.TempFile("", "syzkaller") + if err != nil { + return "", fmt.Errorf("failed to create a temp file: %v", err) + } + if _, err := f.Write(data); err != nil { + f.Close() + os.Remove(f.Name()) + return "", fmt.Errorf("failed to write a temp file: %v", err) + } + f.Close() + return f.Name(), nil +} + +// ProcessTempDir creates a new temp dir in where and returns its path and an unique index. +// It also cleans up old, unused temp dirs after dead processes. +func ProcessTempDir(where string) (string, error) { + lk := filepath.Join(where, "instance-lock") + lkf, err := syscall.Open(lk, syscall.O_RDWR|syscall.O_CREAT, 0600) + if err != nil { + return "", err + } + defer syscall.Close(lkf) + if err := syscall.Flock(lkf, syscall.LOCK_EX); err != nil { + return "", err + } + defer syscall.Flock(lkf, syscall.LOCK_UN) + + for i := 0; i < 1e3; i++ { + path := filepath.Join(where, fmt.Sprintf("instance-%v", i)) + pidfile := filepath.Join(path, ".pid") + err := os.Mkdir(path, 0700) + if os.IsExist(err) { + // Try to clean up. + data, err := ioutil.ReadFile(pidfile) + if err == nil && len(data) > 0 { + pid, err := strconv.Atoi(string(data)) + if err == nil && pid > 1 { + if err := syscall.Kill(pid, 0); err == syscall.ESRCH { + if os.Remove(pidfile) == nil { + if os.RemoveAll(path) == nil { + i-- + continue + } + } + } + } + } + // If err != nil, assume that the pid file is not created yet. + continue + } + if err != nil { + return "", err + } + if err := ioutil.WriteFile(pidfile, []byte(strconv.Itoa(syscall.Getpid())), 0600); err != nil { + return "", err + } + return path, nil + } + return "", fmt.Errorf("too many live instances") +} + +// UmountAll recurusively unmounts all mounts in dir. +func UmountAll(dir string) { + files, _ := ioutil.ReadDir(dir) + for _, f := range files { + name := filepath.Join(dir, f.Name()) + if f.IsDir() { + UmountAll(name) + } + fn := []byte(name + "\x00") + syscall.Syscall(syscall.SYS_UMOUNT2, uintptr(unsafe.Pointer(&fn[0])), syscall.MNT_FORCE, 0) + } +} diff --git a/pkg/fileutil/fileutil_test.go b/pkg/fileutil/fileutil_test.go new file mode 100644 index 000000000..d432ef5e7 --- /dev/null +++ b/pkg/fileutil/fileutil_test.go @@ -0,0 +1,65 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package fileutil + +import ( + "io/ioutil" + "os" + "path/filepath" + "strconv" + "sync" + "testing" +) + +func TestProcessTempDir(t *testing.T) { + for try := 0; try < 10; try++ { + func() { + tmp, err := ioutil.TempDir("", "syz") + if err != nil { + t.Fatalf("failed to create a temp dir: %v", err) + } + defer os.RemoveAll(tmp) + const P = 16 + // Pre-create half of the instances with stale pid. + var dirs []string + for i := 0; i < P/2; i++ { + dir, err := ProcessTempDir(tmp) + if err != nil { + t.Fatalf("failed to create process temp dir") + } + dirs = append(dirs, dir) + } + for _, dir := range dirs { + if err := ioutil.WriteFile(filepath.Join(dir, ".pid"), []byte(strconv.Itoa(999999999)), 0600); err != nil { + t.Fatalf("failed to write pid file: %v", err) + } + } + // Now request a bunch of instances concurrently. + done := make(chan bool) + allDirs := make(map[string]bool) + var mu sync.Mutex + for p := 0; p < P; p++ { + go func() { + defer func() { + done <- true + }() + dir, err := ProcessTempDir(tmp) + if err != nil { + t.Fatalf("failed to create process temp dir") + } + mu.Lock() + present := allDirs[dir] + allDirs[dir] = true + mu.Unlock() + if present { + t.Fatalf("duplicate dir %v", dir) + } + }() + } + for p := 0; p < P; p++ { + <-done + } + }() + } +} diff --git a/repro/repro.go b/repro/repro.go index 1d7f39518..c89a914f3 100644 --- a/repro/repro.go +++ b/repro/repro.go @@ -12,8 +12,8 @@ import ( "time" "github.com/google/syzkaller/csource" - "github.com/google/syzkaller/fileutil" . "github.com/google/syzkaller/log" + "github.com/google/syzkaller/pkg/fileutil" "github.com/google/syzkaller/prog" "github.com/google/syzkaller/report" "github.com/google/syzkaller/syz-manager/config" diff --git a/syz-manager/config/config.go b/syz-manager/config/config.go index 12db5696d..16c8143fc 100644 --- a/syz-manager/config/config.go +++ b/syz-manager/config/config.go @@ -10,8 +10,8 @@ import ( "regexp" "strings" - "github.com/google/syzkaller/fileutil" pkgconfig "github.com/google/syzkaller/pkg/config" + "github.com/google/syzkaller/pkg/fileutil" "github.com/google/syzkaller/sys" "github.com/google/syzkaller/vm" ) diff --git a/vm/kvm/kvm.go b/vm/kvm/kvm.go index f0b0386b3..b0361e8de 100644 --- a/vm/kvm/kvm.go +++ b/vm/kvm/kvm.go @@ -15,7 +15,7 @@ import ( "syscall" "time" - "github.com/google/syzkaller/fileutil" + "github.com/google/syzkaller/pkg/fileutil" "github.com/google/syzkaller/vm" ) diff --git a/vm/local/local.go b/vm/local/local.go index ae397a5c9..09226c251 100644 --- a/vm/local/local.go +++ b/vm/local/local.go @@ -12,7 +12,7 @@ import ( "syscall" "time" - "github.com/google/syzkaller/fileutil" + "github.com/google/syzkaller/pkg/fileutil" "github.com/google/syzkaller/vm" ) -- cgit mrf-deployment