experiment: zync: an rsync-like tool for ZFS datasets (re-uses zrepl abstractions)
Local sync and sync over SSH seems to work. The sshdirect transport might be interesting / re-usable for zrepl as well, although we'd still need some kind of locking in that case.
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
package sshdirect
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/yamux"
|
||||
)
|
||||
|
||||
type ServeConn struct {
|
||||
stdin, stdout *os.File
|
||||
}
|
||||
|
||||
var _ net.Conn = (*ServeConn)(nil)
|
||||
|
||||
func ServeStdin() (net.Listener, error) {
|
||||
|
||||
conn := &ServeConn{
|
||||
stdin: os.Stdin,
|
||||
stdout: os.Stdout,
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
buf.Write(banner_msg)
|
||||
if _, err := io.Copy(conn, &buf); err != nil {
|
||||
log.Printf("error sending confirm message: %s", err)
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
buf.Reset()
|
||||
if _, err := io.CopyN(&buf, conn, int64(len(begin_msg))); err != nil {
|
||||
log.Printf("error reading begin message: %s", err)
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return yamux.Server(conn, nil)
|
||||
}
|
||||
|
||||
func (c *ServeConn) Read(p []byte) (int, error) {
|
||||
return c.stdin.Read(p)
|
||||
}
|
||||
|
||||
func (c *ServeConn) Write(p []byte) (int, error) {
|
||||
return c.stdout.Write(p)
|
||||
}
|
||||
|
||||
func (f *ServeConn) Close() (err error) {
|
||||
e1 := f.stdin.Close()
|
||||
e2 := f.stdout.Close()
|
||||
// FIXME merge errors
|
||||
if e1 != nil {
|
||||
return e1
|
||||
}
|
||||
return e2
|
||||
}
|
||||
|
||||
func (f *ServeConn) SetReadDeadline(t time.Time) error {
|
||||
return f.stdin.SetReadDeadline(t)
|
||||
}
|
||||
|
||||
func (f *ServeConn) SetWriteDeadline(t time.Time) error {
|
||||
return f.stdout.SetReadDeadline(t)
|
||||
}
|
||||
|
||||
func (f *ServeConn) SetDeadline(t time.Time) error {
|
||||
// try both...
|
||||
werr := f.SetWriteDeadline(t)
|
||||
rerr := f.SetReadDeadline(t)
|
||||
if werr != nil {
|
||||
return werr
|
||||
}
|
||||
if rerr != nil {
|
||||
return rerr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type serveAddr struct{}
|
||||
|
||||
const GoNetwork string = "sshdirect"
|
||||
|
||||
func (serveAddr) Network() string { return GoNetwork }
|
||||
func (serveAddr) String() string { return "???" }
|
||||
|
||||
func (f *ServeConn) LocalAddr() net.Addr { return serveAddr{} }
|
||||
func (f *ServeConn) RemoteAddr() net.Addr { return serveAddr{} }
|
||||
Reference in New Issue
Block a user