From 325c6c25d7d7e14083f35be8ca3ec927343f52b2 Mon Sep 17 00:00:00 2001 From: GenZmeY Date: Wed, 29 Apr 2020 05:31:19 +0300 Subject: [PATCH] release: 0.2.1 fix "rename invalid cross-device link" --- Makefile | 2 +- writer.go | 55 +++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index a291400..d954407 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ NAME=multini -VERSION=0.2 +VERSION=0.2.1 GOCMD=go LDFLAGS:="$(LDFLAGS) -X 'main.Version=$(VERSION)'" GOBUILD=$(GOCMD) build -ldflags=$(LDFLAGS) diff --git a/writer.go b/writer.go index f0d10d3..3b9c35b 100644 --- a/writer.go +++ b/writer.go @@ -2,6 +2,7 @@ package main import ( "bufio" + "io" "io/ioutil" "os" "path/filepath" @@ -9,6 +10,47 @@ import ( "multini/types" ) +// Source: https://gist.github.com/var23rav/23ae5d0d4d830aff886c3c970b8f6c6b +/* + GoLang: os.Rename() give error "invalid cross-device link" for Docker container with Volumes. + MoveFile(source, destination) will work moving file between folders +*/ +func tryMoveFile(sourcePath, destPath string) error { + inputFile, err := os.Open(sourcePath) + if err != nil { + return err + } + outputFile, err := os.Create(destPath) + if err != nil { + inputFile.Close() + return err + } + defer outputFile.Close() + _, err = io.Copy(outputFile, inputFile) + inputFile.Close() + if err != nil { + return err + } + // The copy was successful, so now delete the original file + err = os.Remove(sourcePath) + if err != nil { + return err + } + return nil +} + +func tryRemoveRenameFile(sourcePath, destPath string) bool { + err := os.Remove(destPath) + if err != nil { + return false + } + err = os.Rename(sourcePath, destPath) + if err != nil { + return false + } + return true +} + func replaceOriginal(oldFile, newFile string) error { realOldFile, err := filepath.EvalSymlinks(oldFile) if err != nil { @@ -23,14 +65,11 @@ func replaceOriginal(oldFile, newFile string) error { var uid, gid int = GetUidGid(infoOldFile) - err = os.Remove(realOldFile) - if err != nil { - return err - } - - err = os.Rename(newFile, realOldFile) - if err != nil { - return err + if !tryRemoveRenameFile(newFile, realOldFile) { + err = tryMoveFile(newFile, realOldFile) + if err != nil { + return err + } } err = os.Chmod(realOldFile, mode)