2015-12-23 12:59:29 +00:00
|
|
|
// 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.
|
|
|
|
|
2017-07-03 12:00:47 +00:00
|
|
|
package osutil
|
2015-12-23 12:59:29 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
)
|
|
|
|
|
2017-06-19 17:45:39 +00:00
|
|
|
// CopyFile atomically copies oldFile to newFile preserving permissions and modification time.
|
2017-06-01 13:56:07 +00:00
|
|
|
func CopyFile(oldFile, newFile string) error {
|
2015-12-23 12:59:29 +00:00
|
|
|
oldf, err := os.Open(oldFile)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer oldf.Close()
|
2017-06-19 14:35:52 +00:00
|
|
|
stat, err := oldf.Stat()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-06-19 17:45:39 +00:00
|
|
|
tmpFile := newFile + ".tmp"
|
|
|
|
newf, err := os.OpenFile(tmpFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, stat.Mode()&os.ModePerm)
|
2015-12-23 12:59:29 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer newf.Close()
|
|
|
|
_, err = io.Copy(newf, oldf)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-06-19 14:35:52 +00:00
|
|
|
if err := newf.Close(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-06-19 17:45:39 +00:00
|
|
|
if err := os.Chtimes(tmpFile, stat.ModTime(), stat.ModTime()); err != nil {
|
2017-06-19 14:35:52 +00:00
|
|
|
return err
|
|
|
|
}
|
2017-06-19 17:45:39 +00:00
|
|
|
return os.Rename(tmpFile, newFile)
|
2015-12-23 12:59:29 +00:00
|
|
|
}
|
|
|
|
|
2018-12-17 15:56:39 +00:00
|
|
|
// Rename is similar to os.Rename but handles cross-device renaming (by copying).
|
|
|
|
func Rename(oldFile, newFile string) error {
|
|
|
|
err := os.Rename(oldFile, newFile)
|
|
|
|
if err != nil {
|
|
|
|
// Can't use syscall.EXDEV because this is used in appengine app.
|
2018-12-20 10:45:42 +00:00
|
|
|
err = CopyFile(oldFile, newFile)
|
|
|
|
os.Remove(oldFile)
|
2018-12-17 15:56:39 +00:00
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2015-12-23 12:59:29 +00:00
|
|
|
// WriteTempFile writes data to a temp file and returns its name.
|
|
|
|
func WriteTempFile(data []byte) (string, error) {
|
2017-12-12 12:29:45 +00:00
|
|
|
// Note: pkg/report knows about "syzkaller" prefix as it appears in crashes as process name.
|
2015-12-23 12:59:29 +00:00
|
|
|
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
|
|
|
|
}
|