1// Copyright 2015 syzkaller project authors. All rights reserved. 2// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4package osutil 5 6import ( 7 "fmt" 8 "io" 9 "io/ioutil" 10 "os" 11) 12 13// CopyFile atomically copies oldFile to newFile preserving permissions and modification time. 14func CopyFile(oldFile, newFile string) error { 15 oldf, err := os.Open(oldFile) 16 if err != nil { 17 return err 18 } 19 defer oldf.Close() 20 stat, err := oldf.Stat() 21 if err != nil { 22 return err 23 } 24 tmpFile := newFile + ".tmp" 25 newf, err := os.OpenFile(tmpFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, stat.Mode()&os.ModePerm) 26 if err != nil { 27 return err 28 } 29 defer newf.Close() 30 _, err = io.Copy(newf, oldf) 31 if err != nil { 32 return err 33 } 34 if err := newf.Close(); err != nil { 35 return err 36 } 37 if err := os.Chtimes(tmpFile, stat.ModTime(), stat.ModTime()); err != nil { 38 return err 39 } 40 return os.Rename(tmpFile, newFile) 41} 42 43// WriteTempFile writes data to a temp file and returns its name. 44func WriteTempFile(data []byte) (string, error) { 45 // Note: pkg/report knows about "syzkaller" prefix as it appears in crashes as process name. 46 f, err := ioutil.TempFile("", "syzkaller") 47 if err != nil { 48 return "", fmt.Errorf("failed to create a temp file: %v", err) 49 } 50 if _, err := f.Write(data); err != nil { 51 f.Close() 52 os.Remove(f.Name()) 53 return "", fmt.Errorf("failed to write a temp file: %v", err) 54 } 55 f.Close() 56 return f.Name(), nil 57} 58