diff --git a/pkg/remote/remote.go b/pkg/remote/remote.go index faf0ab26..4adf9864 100644 --- a/pkg/remote/remote.go +++ b/pkg/remote/remote.go @@ -263,7 +263,7 @@ func RunCommand(ctx context.Context, cmdId string, remoteId string, remoteState DonePk: nil, RunOut: nil, } - err = sstore.AppendToCmdPtyBlob(ctx, cmd.SessionId, cmd.CmdId, nil, sstore.PosAppend) + err = sstore.AppendToCmdPtyBlob(ctx, cmd.SessionId, cmd.CmdId, nil, 0) if err != nil { return nil, err } @@ -359,6 +359,7 @@ func (runner *MShellProc) ProcessPackets() { } runner.notifyHangups_nolock() }) + var dataPos int64 for pk := range runner.ServerProc.Output.MainCh { if pk.GetType() == packet.DataPacketStr { dataPk := pk.(*packet.DataPacketType) @@ -370,12 +371,13 @@ func (runner *MShellProc) ProcessPackets() { } var ack *packet.DataAckPacketType if len(realData) > 0 { - err = sstore.AppendToCmdPtyBlob(context.Background(), dataPk.CK.GetSessionId(), dataPk.CK.GetCmdId(), realData, sstore.PosAppend) + err = sstore.AppendToCmdPtyBlob(context.Background(), dataPk.CK.GetSessionId(), dataPk.CK.GetCmdId(), realData, dataPos) if err != nil { ack = makeDataAckPacket(dataPk.CK, dataPk.FdNum, 0, err) } else { ack = makeDataAckPacket(dataPk.CK, dataPk.FdNum, len(realData), nil) } + dataPos += int64(len(realData)) } if ack != nil { runner.ServerProc.Input.SendPacket(ack) diff --git a/pkg/sstore/fileops.go b/pkg/sstore/fileops.go index e296129c..ad89f4de 100644 --- a/pkg/sstore/fileops.go +++ b/pkg/sstore/fileops.go @@ -9,41 +9,24 @@ import ( "github.com/scripthaus-dev/sh2-server/pkg/scbase" ) -const PosAppend = -1 - -// when calling with PosAppend, this is not multithread safe (since file could be modified). -// we need to know the real position of the write to send a proper pty update to the frontends -// in practice this is fine since we only use PosAppend in non-detached mode where -// we are reading/writing a stream in order with a single goroutine func AppendToCmdPtyBlob(ctx context.Context, sessionId string, cmdId string, data []byte, pos int64) error { + if pos < 0 { + return fmt.Errorf("invalid seek pos '%d' in AppendToCmdPtyBlob", pos) + } ptyOutFileName, err := scbase.PtyOutFile(sessionId, cmdId) if err != nil { return err } - var fd *os.File - var realPos int64 - if pos == PosAppend { - fd, err = os.OpenFile(ptyOutFileName, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) - if err != nil { - return err - } - finfo, err := fd.Stat() - if err != nil { - return err - } - realPos = finfo.Size() - } else { - fd, err = os.OpenFile(ptyOutFileName, os.O_WRONLY|os.O_CREATE, 0600) - if err != nil { - return err - } - realPos, err = fd.Seek(pos, 0) - if err != nil { - return err - } - if realPos != pos { - return fmt.Errorf("could not seek to pos:%d (realpos=%d)", pos, realPos) - } + fd, err := os.OpenFile(ptyOutFileName, os.O_WRONLY|os.O_CREATE, 0600) + if err != nil { + return err + } + realPos, err := fd.Seek(pos, 0) + if err != nil { + return err + } + if realPos != pos { + return fmt.Errorf("could not seek to pos:%d (realpos=%d)", pos, realPos) } defer fd.Close() if len(data) == 0 {