Files
teleport/lib/sshutils/sftp/utils.go
T
Edoardo Spadolini bcffdcbfd6 session-helper: move the sftp subcommand to reexec.RunAndExit (#65392)
* Split the approver map away from FileTransferRequest

* Move or copy files in session/reexec/sftputils and session/reexec/reexecsftp

* Split up copied files and clean up the new session packages

* Use custom types for SFTP audit log events

* Clean up imports and run sftp in RunAndExit

* Finish renaming types and functions

* Streamline reexec in main and tests

* Add test with the legacy SFTP event implementation
2026-04-15 13:28:27 +00:00

76 lines
1.9 KiB
Go

/*
* Teleport
* Copyright (C) 2023 Gravitational, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package sftp
import (
"context"
"errors"
"io"
"io/fs"
"os"
)
// fileStreamReader is a thin wrapper around fs.File with additional streams.
type fileStreamReader struct {
ctx context.Context
streams []io.Reader
file fs.File
}
// Stat returns file stats.
func (r *fileStreamReader) Stat() (os.FileInfo, error) {
return r.file.Stat()
}
// Read reads the data from a file and passes the read data to all readers.
// All errors from stream are returned except io.EOF.
func (r *fileStreamReader) Read(b []byte) (int, error) {
if err := r.ctx.Err(); err != nil {
return 0, err
}
n, err := r.file.Read(b)
// Create a copy as not whole buffer can be filled.
readBuff := b[:n]
for _, stream := range r.streams {
if _, innerError := stream.Read(readBuff); innerError != nil {
// Ignore EOF
if !errors.Is(err, io.EOF) {
return 0, innerError
}
}
}
return n, err
}
// cancelWriter implements io.Writer interface with context cancellation.
type cancelWriter struct {
ctx context.Context
stream io.Writer
}
func (c *cancelWriter) Write(b []byte) (int, error) {
if err := c.ctx.Err(); err != nil {
return 0, err
}
return c.stream.Write(b)
}