mirror of https://gogs.blitter.com/RLabs/xs
Added notes on how to avoid/detect client->server copy issues (cf. issue #31)
Signed-off-by: Russ Magee <rmagee@gmail.com>
This commit is contained in:
parent
e4b69eab2d
commit
b016e3cd77
10
README.md
10
README.md
|
@ -200,6 +200,16 @@ NOTE: Renaming while copying (eg., 'cp /foo/bar/fileA ./fileB') is NOT supported
|
||||||
|
|
||||||
If the 'pv' pipeview utility is available (http://www.ivarch.com/programs/pv.shtml) file transfer progress and bandwidth control will be available (suppress the former with the -q option, set the latter with -L <bytes_per_second>).
|
If the 'pv' pipeview utility is available (http://www.ivarch.com/programs/pv.shtml) file transfer progress and bandwidth control will be available (suppress the former with the -q option, set the latter with -L <bytes_per_second>).
|
||||||
|
|
||||||
|
Special care should be taken when doing client->server copies: since the tarpipe (should) always succeed at least sending data to the remote side, a destination with no write permission will not return a nonzero status and the client closes its end after sending all data, giving the server no opportunity to send an error code to the client.
|
||||||
|
It is recommended to test beforehand if the server-side destination is writable (and optionally if the destination already exists, if one does not want to clobber an existing path) by:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ xs -x "test -w /dest/path" me@myserver ## If clobbering /dest/path is OK, or
|
||||||
|
$ xs -x "test -w /dest/path -o ! -e /dest/path" me@myserver ## To prevent clobbering
|
||||||
|
```
|
||||||
|
|
||||||
|
Perhaps in future a more complex handshake will be devised to allow the client to half-close the tarpipe, allowing the server to complete its side of the operation and send back its success or failure code, but the current connection protocol does not allow this. If this is a deal-breaking feature, please contact the maintainer.
|
||||||
|
|
||||||
### Tunnels
|
### Tunnels
|
||||||
|
|
||||||
Simple tunnels (client -> server, no reverse tunnels for now) are supported.
|
Simple tunnels (client -> server, no reverse tunnels for now) are supported.
|
||||||
|
|
12
xsd/xsd.go
12
xsd/xsd.go
|
@ -800,15 +800,15 @@ func main() {
|
||||||
log.Printf("[Client->Server copy]\n")
|
log.Printf("[Client->Server copy]\n")
|
||||||
addr := hc.RemoteAddr()
|
addr := hc.RemoteAddr()
|
||||||
hname := goutmp.GetHost(addr.String())
|
hname := goutmp.GetHost(addr.String())
|
||||||
logger.LogNotice(fmt.Sprintf("[Running copy for [%s@%s]]\n", rec.Who(), hname)) // nolint: gosec,errcheck
|
logger.LogNotice(fmt.Sprintf("[c->s copy for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck
|
||||||
cmdStatus, runErr := runClientToServerCopyAs(string(rec.Who()), string(rec.TermType()), hc, string(rec.Cmd()), chaffEnabled)
|
cmdStatus, runErr := runClientToServerCopyAs(string(rec.Who()), string(rec.TermType()), hc, string(rec.Cmd()), chaffEnabled)
|
||||||
// Returned hopefully via an EOF or exit/logout;
|
// Returned hopefully via an EOF or exit/logout;
|
||||||
// Clear current op so user can enter next, or EOF
|
// Clear current op so user can enter next, or EOF
|
||||||
rec.SetOp([]byte{0})
|
rec.SetOp([]byte{0})
|
||||||
if runErr != nil {
|
if runErr != nil {
|
||||||
logger.LogErr(fmt.Sprintf("[Error running cp for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck
|
logger.LogErr(fmt.Sprintf("[c->s copy error for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck
|
||||||
} else {
|
} else {
|
||||||
logger.LogNotice(fmt.Sprintf("[Command completed for %s@%s, status %d]\n", rec.Who(), hname, cmdStatus)) // nolint: gosec,errcheck
|
logger.LogNotice(fmt.Sprintf("[c->s copy completed for %s@%s, status %d]\n", rec.Who(), hname, cmdStatus)) // nolint: gosec,errcheck
|
||||||
}
|
}
|
||||||
// TODO: Test this with huge files.. see Bug #22 - do we need to
|
// TODO: Test this with huge files.. see Bug #22 - do we need to
|
||||||
// sync w/sender (client) that we've gotten all data?
|
// sync w/sender (client) that we've gotten all data?
|
||||||
|
@ -824,13 +824,13 @@ func main() {
|
||||||
log.Printf("[Server->Client copy]\n")
|
log.Printf("[Server->Client copy]\n")
|
||||||
addr := hc.RemoteAddr()
|
addr := hc.RemoteAddr()
|
||||||
hname := goutmp.GetHost(addr.String())
|
hname := goutmp.GetHost(addr.String())
|
||||||
logger.LogNotice(fmt.Sprintf("[Running copy for [%s@%s]]\n", rec.Who(), hname)) // nolint: gosec,errcheck
|
logger.LogNotice(fmt.Sprintf("[s->c copy for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck
|
||||||
cmdStatus, runErr := runServerToClientCopyAs(string(rec.Who()), string(rec.TermType()), hc, string(rec.Cmd()), chaffEnabled)
|
cmdStatus, runErr := runServerToClientCopyAs(string(rec.Who()), string(rec.TermType()), hc, string(rec.Cmd()), chaffEnabled)
|
||||||
if runErr != nil {
|
if runErr != nil {
|
||||||
logger.LogErr(fmt.Sprintf("[Error spawning cp for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck
|
logger.LogErr(fmt.Sprintf("[s->c copy error for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck
|
||||||
} else {
|
} else {
|
||||||
// Returned hopefully via an EOF or exit/logout;
|
// Returned hopefully via an EOF or exit/logout;
|
||||||
logger.LogNotice(fmt.Sprintf("[Command completed for %s@%s, status %d]\n", rec.Who(), hname, cmdStatus)) // nolint: gosec,errcheck
|
logger.LogNotice(fmt.Sprintf("[s->c copy completed for %s@%s, status %d]\n", rec.Who(), hname, cmdStatus)) // nolint: gosec,errcheck
|
||||||
}
|
}
|
||||||
// HACK: Bug #22: (xc) Need to wait for rcvr to get final data
|
// HACK: Bug #22: (xc) Need to wait for rcvr to get final data
|
||||||
// TODO: Await specific msg from client to inform they have gotten all data from the tarpipe
|
// TODO: Await specific msg from client to inform they have gotten all data from the tarpipe
|
||||||
|
|
Loading…
Reference in New Issue