Loading fldb/diff.go +53 −4 Original line number Diff line number Diff line package fldb import ( "bytes" "rsync-os/rsync" bolt "go.etcd.io/bbolt" "google.golang.org/protobuf/proto" ) // Diff two sorted list // Return two lists: new files, deleted files func (cache *Cache) Diff(list *rsync.FileList) (*rsync.FileList, *rsync.FileList) { func (cache *Cache) Diff(list *rsync.FileList) { db, err := bolt.Open("test.db", 0666, nil) if err != nil { return } defer db.Close() // Iterate cache.module(A) & list(B), both A & B must be sorted lexicographically before i := 0 downloadList := make([]int, 1000) deleteList := make([]string, 1000) db.View(func(tx *bolt.Tx) error { // Assume bucket exists and has keys c := tx.Bucket([]byte("MyBucket")).Cursor() prefix := []byte(cache.prepath) // for k, v := c.Seek(prefix); k != nil && bytes.HasPrefix(k, prefix); k, v = c.Next() { // } k, v := c.Seek(prefix) for i < list.Len() && k != nil && bytes.HasPrefix(k, prefix) { switch bytes.Compare([]byte((*list)[i].Path), k) { case 0: info := &FInfo{} err := proto.Unmarshal(v, info) if err != nil { } if (*list)[i].Mtime != info.Mtime || (*list)[i].Size != info.Size { downloadList = append(downloadList, i) } i++ k, v = c.Next() break case 1: deleteList = append(deleteList, string(k)) k, v = c.Next() break case -1: downloadList = append(downloadList, i) i++ break } } // Interate cache.module(A) & list(B), both A & B must be sorted lexicographically before return nil }) // Compare their path Loading @@ -22,5 +72,4 @@ func (cache *Cache) Diff(list *rsync.FileList) (*rsync.FileList, *rsync.FileList // If < 0, A doesn't have return nil, nil } main.go +5 −1 Original line number Diff line number Diff line Loading @@ -36,7 +36,11 @@ func Socket(uri string) { defer conn.Close() rsync.HandShake(conn, module, path) c := &rsync.Client{ Conn: conn, } c.HandShake(module, path) // fmt.Println(readInteger(conn)) log.Println("HandShake OK") Loading rsync/receiver.go +59 −14 Original line number Diff line number Diff line Loading @@ -12,39 +12,56 @@ import ( "github.com/minio/minio-go/v6" ) type Client struct { Conn net.Conn DemuxIn chan byte CksSeed int32 // Options } // Header: '@RSYNCD: 31.0\n' + ? + '\n' + arguments + '\0' // Header len 8 AUTHREQD: 18 "@RSYNCD: EXIT" 13 RSYNC_MODULE_LIST_QUERY "\n" // See clienserver.c start_inband_exchange func HandShake(conn net.Conn, module string, path string) { func (c *Client) HandShake(module string, path string) { // send my version // send("@RSYNCD: 31.0\n"); conn.Write([]byte("@RSYNCD: 27.0\n")) c.Conn.Write([]byte("@RSYNCD: 27.0\n")) // receive server's protocol version and seed version_str, _ := ReadLine(conn) versionStr, _ := ReadLine(c.Conn) // recv(version) var remote_protocol, remote_sub int fmt.Sscanf(version_str, "@RSYNCD: %d.%d", remote_protocol, remote_sub) log.Println(version_str) var remoteProtocol, remoteProtocolSub int fmt.Sscanf(versionStr, "@RSYNCD: %d.%d", remoteProtocol, remoteProtocolSub) log.Println(versionStr) // send mod name // send("Foo\n") conn.Write([]byte(module)) conn.Write([]byte("\n")) c.Conn.Write([]byte(module)) c.Conn.Write([]byte("\n")) //conn.Write([]byte("epel\n")) // conn.Write([]byte("\n")) for { // Wait for '@RSYNCD: OK': until \n, then add \0 res, _ := ReadLine(conn) res, _ := ReadLine(c.Conn) log.Print(res) if strings.Contains(res, "@RSYNCD: OK") { break } } c.SendArgs(module, path) // read int32 as seed c.CksSeed = ReadInteger(c.Conn) log.Println("SEED", c.CksSeed) c.SendEmptyExclusion() } func (c *Client) SendArgs(module string, path string) { // send parameters list //conn.Write([]byte("--server\n--sender\n-g\n-l\n-o\n-p\n-D\n-r\n-t\n.\nepel/7/SRPMS\n\n")) //conn.Write([]byte("--server\n--sender\n-l\n-p\n-r\n-t\n.\nepel/7/SRPMS\n\n")) // without gid, uid, mdev Loading @@ -53,14 +70,42 @@ func HandShake(conn net.Conn, module string, path string) { args.Write([]byte(module)) args.Write([]byte(path)) args.Write([]byte("\n\n")) conn.Write(args.Bytes()) c.Conn.Write(args.Bytes()) } // read int32 as seed bseed := ReadInteger(conn) log.Println("SEED", bseed) func (c *Client) ListOnly(module string, path string) { c.Conn.Write([]byte("@RSYNCD: 27.0\n")) versionStr, _ := ReadLine(c.Conn) // var remoteProtocol, remoteProtocolSub int // fmt.Sscanf(versionStr, "@RSYNCD: %d.%d", remoteProtocol, remoteProtocolSub) log.Println(versionStr) c.Conn.Write([]byte(module)) c.Conn.Write([]byte("\n")) for { // Wait for '@RSYNCD: OK': until \n, then add \0 res, _ := ReadLine(c.Conn) log.Print(res) if strings.Contains(res, "@RSYNCD: OK") { break } } args := new(bytes.Buffer) args.Write([]byte("--server\n--sender\n-l\n-p\n-r\n-t\n.\n")) args.Write([]byte(module)) args.Write([]byte(path)) args.Write([]byte("\n\n")) c.Conn.Write(args.Bytes()) seed := ReadInteger(c.Conn) log.Println("SEED", seed) c.Conn.Write(make([]byte, 4)) } func (c *Client) SendEmptyExclusion() { // send filter_list, empty is 32-bit zero conn.Write([]byte("\x00\x00\x00\x00")) c.Conn.Write([]byte("\x00\x00\x00\x00")) } type FileInfo struct { Loading Loading
fldb/diff.go +53 −4 Original line number Diff line number Diff line package fldb import ( "bytes" "rsync-os/rsync" bolt "go.etcd.io/bbolt" "google.golang.org/protobuf/proto" ) // Diff two sorted list // Return two lists: new files, deleted files func (cache *Cache) Diff(list *rsync.FileList) (*rsync.FileList, *rsync.FileList) { func (cache *Cache) Diff(list *rsync.FileList) { db, err := bolt.Open("test.db", 0666, nil) if err != nil { return } defer db.Close() // Iterate cache.module(A) & list(B), both A & B must be sorted lexicographically before i := 0 downloadList := make([]int, 1000) deleteList := make([]string, 1000) db.View(func(tx *bolt.Tx) error { // Assume bucket exists and has keys c := tx.Bucket([]byte("MyBucket")).Cursor() prefix := []byte(cache.prepath) // for k, v := c.Seek(prefix); k != nil && bytes.HasPrefix(k, prefix); k, v = c.Next() { // } k, v := c.Seek(prefix) for i < list.Len() && k != nil && bytes.HasPrefix(k, prefix) { switch bytes.Compare([]byte((*list)[i].Path), k) { case 0: info := &FInfo{} err := proto.Unmarshal(v, info) if err != nil { } if (*list)[i].Mtime != info.Mtime || (*list)[i].Size != info.Size { downloadList = append(downloadList, i) } i++ k, v = c.Next() break case 1: deleteList = append(deleteList, string(k)) k, v = c.Next() break case -1: downloadList = append(downloadList, i) i++ break } } // Interate cache.module(A) & list(B), both A & B must be sorted lexicographically before return nil }) // Compare their path Loading @@ -22,5 +72,4 @@ func (cache *Cache) Diff(list *rsync.FileList) (*rsync.FileList, *rsync.FileList // If < 0, A doesn't have return nil, nil }
main.go +5 −1 Original line number Diff line number Diff line Loading @@ -36,7 +36,11 @@ func Socket(uri string) { defer conn.Close() rsync.HandShake(conn, module, path) c := &rsync.Client{ Conn: conn, } c.HandShake(module, path) // fmt.Println(readInteger(conn)) log.Println("HandShake OK") Loading
rsync/receiver.go +59 −14 Original line number Diff line number Diff line Loading @@ -12,39 +12,56 @@ import ( "github.com/minio/minio-go/v6" ) type Client struct { Conn net.Conn DemuxIn chan byte CksSeed int32 // Options } // Header: '@RSYNCD: 31.0\n' + ? + '\n' + arguments + '\0' // Header len 8 AUTHREQD: 18 "@RSYNCD: EXIT" 13 RSYNC_MODULE_LIST_QUERY "\n" // See clienserver.c start_inband_exchange func HandShake(conn net.Conn, module string, path string) { func (c *Client) HandShake(module string, path string) { // send my version // send("@RSYNCD: 31.0\n"); conn.Write([]byte("@RSYNCD: 27.0\n")) c.Conn.Write([]byte("@RSYNCD: 27.0\n")) // receive server's protocol version and seed version_str, _ := ReadLine(conn) versionStr, _ := ReadLine(c.Conn) // recv(version) var remote_protocol, remote_sub int fmt.Sscanf(version_str, "@RSYNCD: %d.%d", remote_protocol, remote_sub) log.Println(version_str) var remoteProtocol, remoteProtocolSub int fmt.Sscanf(versionStr, "@RSYNCD: %d.%d", remoteProtocol, remoteProtocolSub) log.Println(versionStr) // send mod name // send("Foo\n") conn.Write([]byte(module)) conn.Write([]byte("\n")) c.Conn.Write([]byte(module)) c.Conn.Write([]byte("\n")) //conn.Write([]byte("epel\n")) // conn.Write([]byte("\n")) for { // Wait for '@RSYNCD: OK': until \n, then add \0 res, _ := ReadLine(conn) res, _ := ReadLine(c.Conn) log.Print(res) if strings.Contains(res, "@RSYNCD: OK") { break } } c.SendArgs(module, path) // read int32 as seed c.CksSeed = ReadInteger(c.Conn) log.Println("SEED", c.CksSeed) c.SendEmptyExclusion() } func (c *Client) SendArgs(module string, path string) { // send parameters list //conn.Write([]byte("--server\n--sender\n-g\n-l\n-o\n-p\n-D\n-r\n-t\n.\nepel/7/SRPMS\n\n")) //conn.Write([]byte("--server\n--sender\n-l\n-p\n-r\n-t\n.\nepel/7/SRPMS\n\n")) // without gid, uid, mdev Loading @@ -53,14 +70,42 @@ func HandShake(conn net.Conn, module string, path string) { args.Write([]byte(module)) args.Write([]byte(path)) args.Write([]byte("\n\n")) conn.Write(args.Bytes()) c.Conn.Write(args.Bytes()) } // read int32 as seed bseed := ReadInteger(conn) log.Println("SEED", bseed) func (c *Client) ListOnly(module string, path string) { c.Conn.Write([]byte("@RSYNCD: 27.0\n")) versionStr, _ := ReadLine(c.Conn) // var remoteProtocol, remoteProtocolSub int // fmt.Sscanf(versionStr, "@RSYNCD: %d.%d", remoteProtocol, remoteProtocolSub) log.Println(versionStr) c.Conn.Write([]byte(module)) c.Conn.Write([]byte("\n")) for { // Wait for '@RSYNCD: OK': until \n, then add \0 res, _ := ReadLine(c.Conn) log.Print(res) if strings.Contains(res, "@RSYNCD: OK") { break } } args := new(bytes.Buffer) args.Write([]byte("--server\n--sender\n-l\n-p\n-r\n-t\n.\n")) args.Write([]byte(module)) args.Write([]byte(path)) args.Write([]byte("\n\n")) c.Conn.Write(args.Bytes()) seed := ReadInteger(c.Conn) log.Println("SEED", seed) c.Conn.Write(make([]byte, 4)) } func (c *Client) SendEmptyExclusion() { // send filter_list, empty is 32-bit zero conn.Write([]byte("\x00\x00\x00\x00")) c.Conn.Write([]byte("\x00\x00\x00\x00")) } type FileInfo struct { Loading