2018-03-13 21:30:51 +00:00
|
|
|
package rclone
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net"
|
|
|
|
"os"
|
|
|
|
"os/exec"
|
2018-03-15 20:22:14 +00:00
|
|
|
"sync"
|
2020-02-26 19:29:36 +00:00
|
|
|
"time"
|
2018-03-13 21:30:51 +00:00
|
|
|
|
|
|
|
"github.com/restic/restic/internal/debug"
|
|
|
|
)
|
|
|
|
|
|
|
|
// StdioConn implements a net.Conn via stdin/stdout.
|
|
|
|
type StdioConn struct {
|
2020-07-24 21:27:47 +00:00
|
|
|
stdin *os.File
|
|
|
|
stdout *os.File
|
|
|
|
cmd *exec.Cmd
|
|
|
|
closeIn sync.Once
|
|
|
|
closeOut sync.Once
|
2018-03-13 21:30:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *StdioConn) Read(p []byte) (int, error) {
|
|
|
|
n, err := s.stdin.Read(p)
|
|
|
|
return n, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *StdioConn) Write(p []byte) (int, error) {
|
|
|
|
n, err := s.stdout.Write(p)
|
|
|
|
return n, err
|
|
|
|
}
|
|
|
|
|
2020-07-24 21:27:47 +00:00
|
|
|
// Close closes the stream to the child process.
|
2018-03-15 20:22:14 +00:00
|
|
|
func (s *StdioConn) Close() (err error) {
|
2020-07-24 21:27:47 +00:00
|
|
|
s.closeOut.Do(func() {
|
|
|
|
debug.Log("close stdio send connection")
|
|
|
|
err = s.stdout.Close()
|
|
|
|
})
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// CloseAll closes both streams.
|
|
|
|
func (s *StdioConn) CloseAll() (err error) {
|
|
|
|
err = s.Close()
|
2018-03-13 21:30:51 +00:00
|
|
|
|
2020-07-24 21:27:47 +00:00
|
|
|
s.closeIn.Do(func() {
|
|
|
|
debug.Log("close stdio receive connection")
|
|
|
|
err2 := s.stdin.Close()
|
|
|
|
if err == nil {
|
|
|
|
err = err2
|
2018-03-15 20:22:14 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
return err
|
2018-03-13 21:30:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// LocalAddr returns nil.
|
|
|
|
func (s *StdioConn) LocalAddr() net.Addr {
|
|
|
|
return Addr{}
|
|
|
|
}
|
|
|
|
|
|
|
|
// RemoteAddr returns nil.
|
|
|
|
func (s *StdioConn) RemoteAddr() net.Addr {
|
|
|
|
return Addr{}
|
|
|
|
}
|
|
|
|
|
2020-02-26 19:29:36 +00:00
|
|
|
// SetDeadline sets the read/write deadline.
|
|
|
|
func (s *StdioConn) SetDeadline(t time.Time) error {
|
|
|
|
err1 := s.stdin.SetReadDeadline(t)
|
|
|
|
err2 := s.stdout.SetWriteDeadline(t)
|
|
|
|
if err1 != nil {
|
|
|
|
return err1
|
|
|
|
}
|
|
|
|
return err2
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetReadDeadline sets the read/write deadline.
|
|
|
|
func (s *StdioConn) SetReadDeadline(t time.Time) error {
|
|
|
|
return s.stdin.SetReadDeadline(t)
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetWriteDeadline sets the read/write deadline.
|
|
|
|
func (s *StdioConn) SetWriteDeadline(t time.Time) error {
|
|
|
|
return s.stdout.SetWriteDeadline(t)
|
|
|
|
}
|
|
|
|
|
2018-03-13 21:30:51 +00:00
|
|
|
// make sure StdioConn implements net.Conn
|
|
|
|
var _ net.Conn = &StdioConn{}
|
|
|
|
|
|
|
|
// Addr implements net.Addr for stdin/stdout.
|
|
|
|
type Addr struct{}
|
|
|
|
|
|
|
|
// Network returns the network type as a string.
|
|
|
|
func (a Addr) Network() string {
|
|
|
|
return "stdio"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a Addr) String() string {
|
|
|
|
return "stdio"
|
|
|
|
}
|