mirror of
https://github.com/stashapp/stash.git
synced 2025-12-15 21:03:22 +01:00
Close input file so SafeMove can delete it (#3714)
* Close input file so SafeMove can delete it This is happening on Windows and over the network but at the end of SafeMove it fails the move with an error that it can't remove the input because it is in use. It turns out it is in use by the SafeMove itself :) * Copy the src file mod time
This commit is contained in:
parent
e7abeeb4df
commit
61c0098ae6
1 changed files with 44 additions and 18 deletions
|
|
@ -11,29 +11,55 @@ import (
|
|||
"github.com/stashapp/stash/pkg/logger"
|
||||
)
|
||||
|
||||
// CopyFile copies the contents of the file at srcpath to a regular file at dstpath.
|
||||
// It will copy the last modified timestamp
|
||||
// If dstpath already exists the function will fail.
|
||||
func CopyFile(srcpath, dstpath string) (err error) {
|
||||
r, err := os.Open(srcpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w, err := os.OpenFile(dstpath, os.O_CREATE|os.O_EXCL, 0666)
|
||||
if err != nil {
|
||||
r.Close() // We need to close the input file as the defer below would not be called.
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
r.Close() // ok to ignore error: file was opened read-only.
|
||||
e := w.Close()
|
||||
// Report the error from w.Close, if any.
|
||||
// But do so only if there isn't already an outgoing error.
|
||||
if e != nil && err == nil {
|
||||
err = e
|
||||
}
|
||||
// Copy modified time
|
||||
if err == nil {
|
||||
// io.Copy succeeded, we should fix the dstpath timestamp
|
||||
srcFileInfo, e := os.Stat(srcpath)
|
||||
if e != nil {
|
||||
err = e
|
||||
return
|
||||
}
|
||||
|
||||
e = os.Chtimes(dstpath, srcFileInfo.ModTime(), srcFileInfo.ModTime())
|
||||
if e != nil {
|
||||
err = e
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
_, err = io.Copy(w, r)
|
||||
return err
|
||||
}
|
||||
|
||||
// SafeMove attempts to move the file with path src to dest using os.Rename. If this fails, then it copies src to dest, then deletes src.
|
||||
func SafeMove(src, dst string) error {
|
||||
err := os.Rename(src, dst)
|
||||
|
||||
if err != nil {
|
||||
in, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer in.Close()
|
||||
|
||||
out, err := os.Create(dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
_, err = io.Copy(out, in)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = out.Close()
|
||||
err = CopyFile(src, dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue