Files
Ayush RanjanandgVisor bot a941d15831 Move HostConnectedEndpoint and SCMConnectedEndpoint to transport package.
This is needed so that connectioned endpoint in the transport package can use
this endpoint to implement host FD based binded endpoints.

I had to simplify some other dependencies to make this possible.
- Removed uniqueid's dependency on transport package completely.
- Removed SCMConnectedEndpoint and HostConnectedEndpoint's dependency on
  control package so they could be moved to transport. control already depends
  on transport.
- scmRights struct from fsimpl/host/control.go had to be moved into transport
  so that  HostConnectedEndpoint could be implemented. But scmRights.Fill()
  could not be moved because it inherently depends on making
  vfs.FileDescriptions which depends on vfs which in turn depends on transport.
  So now that scmRights -> vfs.FD conversion happens in the syscall package.

PiperOrigin-RevId: 413839350
2021-12-02 21:16:58 -08:00

110 lines
2.6 KiB
Go

// Copyright 2020 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package transport
import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/hostfd"
)
// copyToMulti copies as many bytes from src to dst as possible.
func copyToMulti(dst [][]byte, src []byte) {
for _, d := range dst {
done := copy(d, src)
src = src[done:]
if len(src) == 0 {
break
}
}
}
// copyFromMulti copies as many bytes from src to dst as possible.
func copyFromMulti(dst []byte, src [][]byte) {
for _, s := range src {
done := copy(dst, s)
dst = dst[done:]
if len(dst) == 0 {
break
}
}
}
// buildIovec builds an iovec slice from the given []byte slice.
//
// If truncate, truncate bufs > maxlen. Otherwise, immediately return an error.
//
// If length < the total length of bufs, err indicates why, even when returning
// a truncated iovec.
//
// If intermediate != nil, iovecs references intermediate rather than bufs and
// the caller must copy to/from bufs as necessary.
func buildIovec(bufs [][]byte, maxlen int64, truncate bool) (length int64, iovecs []unix.Iovec, intermediate []byte, err error) {
var iovsRequired int
for _, b := range bufs {
length += int64(len(b))
if len(b) > 0 {
iovsRequired++
}
}
stopLen := length
if length > maxlen {
if truncate {
stopLen = maxlen
err = linuxerr.EAGAIN
} else {
return 0, nil, nil, linuxerr.EMSGSIZE
}
}
if iovsRequired > hostfd.MaxSendRecvMsgIov {
// The kernel will reject our call if we pass this many iovs.
// Use a single intermediate buffer instead.
b := make([]byte, stopLen)
return stopLen, []unix.Iovec{{
Base: &b[0],
Len: uint64(stopLen),
}}, b, err
}
var total int64
iovecs = make([]unix.Iovec, 0, iovsRequired)
for i := range bufs {
l := len(bufs[i])
if l == 0 {
continue
}
stop := int64(l)
if total+stop > stopLen {
stop = stopLen - total
}
iovecs = append(iovecs, unix.Iovec{
Base: &bufs[i][0],
Len: uint64(stop),
})
total += stop
if total >= stopLen {
break
}
}
return total, iovecs, nil, err
}