mirror of
https://github.com/empayre/fleet.git
synced 2024-11-06 08:55:24 +00:00
fix rename tmp file (#4862)
Renaming a temporary file to the final destination does not always work. Specifically, if the source and destination paths are on different file systems, you will get the following error invalid cross-device link Instead, create temporary file in the destination directory.
This commit is contained in:
parent
3575d34507
commit
d8d582760d
1
changes/issue-4792-download-tmp
Normal file
1
changes/issue-4792-download-tmp
Normal file
@ -0,0 +1 @@
|
||||
* Fix issue when renaming temporary files to another filesystem
|
@ -18,16 +18,36 @@ import (
|
||||
|
||||
// Decompressed downloads and decompresses a file from a URL to a local path.
|
||||
//
|
||||
// It supports gz, bz2 and gz compressed files.
|
||||
// It supports gz, bz2 and xz compressed files.
|
||||
func Decompressed(client *http.Client, u url.URL, path string) error {
|
||||
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
||||
|
||||
// atomically write to file
|
||||
dir, file := filepath.Split(path)
|
||||
if dir == "" {
|
||||
// If the file is in the current working directory, then dir will be "".
|
||||
// However, this means that ioutil.TempFile will use the default directory
|
||||
// for temporary files, which is wrong.
|
||||
dir = "."
|
||||
}
|
||||
|
||||
// ensure dir exists
|
||||
if err := os.MkdirAll(dir, 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
tmpFile, err := ioutil.TempFile("", fmt.Sprintf("%s*", filepath.Base(path)))
|
||||
|
||||
tmpFile, err := ioutil.TempFile(dir, file)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("create temporary file: %w", err)
|
||||
}
|
||||
defer tmpFile.Close()
|
||||
defer tmpFile.Close() // ignore err from closing twice
|
||||
|
||||
// Clean up tmp file if not moved
|
||||
moved := false
|
||||
defer func() {
|
||||
if !moved {
|
||||
os.Remove(tmpFile.Name())
|
||||
}
|
||||
}()
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, u.String(), nil)
|
||||
if err != nil {
|
||||
@ -57,14 +77,21 @@ func Decompressed(client *http.Client, u url.URL, path string) error {
|
||||
default:
|
||||
return fmt.Errorf("unknown extension: %s", u.Path)
|
||||
}
|
||||
|
||||
if _, err := io.Copy(tmpFile, decompressor); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Writes are not synchronous. Handle errors from writes returned by Close.
|
||||
if err := tmpFile.Close(); err != nil {
|
||||
return err
|
||||
return fmt.Errorf("write and close temporary file: %w", err)
|
||||
}
|
||||
|
||||
if err := os.Rename(tmpFile.Name(), path); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
moved = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user