mirror of
https://github.com/rclone/rclone.git
synced 2025-01-05 05:49:33 +01:00
log: update windows redirection code to use x/sys/windows and include dup
This modernises the Windows redirect code to use x/sys/windows and to dup os.Stderr for use in the terminal.
This commit is contained in:
parent
16b383e18f
commit
3450d049b5
@ -12,29 +12,43 @@ package log
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
|
||||||
|
"github.com/rclone/rclone/lib/terminal"
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// dup oldfd creating a functional copy as newfd
|
||||||
|
// conceptually the same as the unix `dup()` function
|
||||||
|
func dup(oldfd uintptr) (newfd uintptr, err error) {
|
||||||
var (
|
var (
|
||||||
kernel32 = syscall.MustLoadDLL("kernel32.dll")
|
newfdHandle windows.Handle
|
||||||
procSetStdHandle = kernel32.MustFindProc("SetStdHandle")
|
processHandle = windows.CurrentProcess()
|
||||||
)
|
)
|
||||||
|
err = windows.DuplicateHandle(
|
||||||
func setStdHandle(stdhandle int32, handle syscall.Handle) error {
|
processHandle, // hSourceProcessHandle
|
||||||
r0, _, e1 := syscall.Syscall(procSetStdHandle.Addr(), 2, uintptr(stdhandle), uintptr(handle), 0)
|
windows.Handle(oldfd), // hSourceHandle
|
||||||
if r0 == 0 {
|
processHandle, // hTargetProcessHandle
|
||||||
if e1 != 0 {
|
&newfdHandle, // lpTargetHandle
|
||||||
return error(e1)
|
0, // dwDesiredAccess
|
||||||
|
true, // bInheritHandle
|
||||||
|
windows.DUPLICATE_SAME_ACCESS, // dwOptions
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
}
|
}
|
||||||
return syscall.EINVAL
|
return uintptr(newfdHandle), nil
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// redirectStderr to the file passed in
|
// redirectStderr to the file passed in
|
||||||
func redirectStderr(f *os.File) {
|
func redirectStderr(f *os.File) {
|
||||||
err := setStdHandle(syscall.STD_ERROR_HANDLE, syscall.Handle(f.Fd()))
|
termFd, err := dup(os.Stderr.Fd())
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to duplicate stderr: %v", err)
|
||||||
|
}
|
||||||
|
terminal.RawOut = os.NewFile(termFd, "termOut")
|
||||||
|
err = windows.SetStdHandle(windows.STD_ERROR_HANDLE, windows.Handle(f.Fd()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to redirect stderr to file: %v", err)
|
log.Fatalf("Failed to redirect stderr to file: %v", err)
|
||||||
}
|
}
|
||||||
|
os.Stderr = f
|
||||||
}
|
}
|
||||||
|
@ -81,8 +81,11 @@ func Start() {
|
|||||||
// If output is not a tty then remove escape codes
|
// If output is not a tty then remove escape codes
|
||||||
Out = colorable.NewNonColorable(f)
|
Out = colorable.NewNonColorable(f)
|
||||||
} else if runtime.GOOS == "windows" && os.Getenv("TERM") != "" {
|
} else if runtime.GOOS == "windows" && os.Getenv("TERM") != "" {
|
||||||
// If TERM is set just use stdout
|
// If TERM is set on Windows then we should just send output
|
||||||
Out = os.Stdout
|
// straight to the terminal for cygwin/git bash environments.
|
||||||
|
// We don't want to use NewColorable here because it will
|
||||||
|
// use Windows console calls which cygwin/git bash don't support.
|
||||||
|
Out = f
|
||||||
} else {
|
} else {
|
||||||
Out = colorable.NewColorable(f)
|
Out = colorable.NewColorable(f)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user