mirror of
https://github.com/containers/podman.git
synced 2025-11-29 17:48:05 +08:00
This includes two new hidden commands: a 9p server, `podman machine server9p`, and a 9p client, `podman machine client9p` with `server9p` currently only configured to run on Windows and serve 9p via HyperV vsock, and `client9p` only configured to run on Linux. The server is run by `podman machine start` and has the same lifespan as gvproxy (waits for the gvproxy PID to die before shutting down). The client is run inside the VM, also by `podman machine start`, and mounts uses kernel 9p mount code to complete the mount. It's unfortunately not possible to use mount directly without the wrapper; we need to set up the vsock and pass it to mount as an FD. In theory this can be generalized so that the server can run anywhere and over almost any transport, but I haven't done this here as I don't think we have a usecase other than HyperV right now. [NO NEW TESTS NEEDED] This requires changes to Podman in the VM, so we need to wait until a build with this lands in FCOS to test. Signed-off-by: Matthew Heon <matthew.heon@pm.me>
172 lines
5.1 KiB
Go
172 lines
5.1 KiB
Go
package hvsock
|
|
|
|
/*
|
|
Most of this code was derived from: https://github.com/Microsoft/go-winio
|
|
which has the following license:
|
|
|
|
The MIT License (MIT)
|
|
|
|
Copyright (c) 2015 Microsoft
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
SOFTWARE.
|
|
*/
|
|
|
|
import (
|
|
"syscall"
|
|
"unsafe"
|
|
)
|
|
|
|
var (
|
|
modws2_32 = syscall.NewLazyDLL("ws2_32.dll")
|
|
modwinmm = syscall.NewLazyDLL("winmm.dll")
|
|
modkernel32 = syscall.NewLazyDLL("kernel32.dll")
|
|
|
|
procConnect = modws2_32.NewProc("connect")
|
|
procBind = modws2_32.NewProc("bind")
|
|
procAccept = modws2_32.NewProc("accept")
|
|
|
|
procCancelIoEx = modkernel32.NewProc("CancelIoEx")
|
|
procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort")
|
|
procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus")
|
|
procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes")
|
|
proctimeBeginPeriod = modwinmm.NewProc("timeBeginPeriod")
|
|
)
|
|
|
|
// Do the interface allocations only once for common
|
|
// Errno values.
|
|
const (
|
|
errnoERROR_IO_PENDING = 997
|
|
socketError = uintptr(^uint32(0))
|
|
|
|
cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS = 1
|
|
cFILE_SKIP_SET_EVENT_ON_HANDLE = 2
|
|
)
|
|
|
|
var (
|
|
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
|
|
)
|
|
|
|
// errnoErr returns common boxed Errno values, to prevent
|
|
// allocations at runtime.
|
|
func errnoErr(e syscall.Errno) error {
|
|
switch e {
|
|
case 0:
|
|
return nil
|
|
case errnoERROR_IO_PENDING:
|
|
return errERROR_IO_PENDING
|
|
}
|
|
// TODO: add more here, after collecting data on the common
|
|
// error values see on Windows. (perhaps when running
|
|
// all.bat?)
|
|
return e
|
|
}
|
|
|
|
func sys_connect(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) {
|
|
r1, _, e1 := syscall.Syscall(procConnect.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
|
|
if r1 == socketError {
|
|
if e1 != 0 {
|
|
err = errnoErr(e1)
|
|
} else {
|
|
err = syscall.EINVAL
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func sys_bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) {
|
|
r1, _, e1 := syscall.Syscall(procBind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
|
|
if r1 == socketError {
|
|
if e1 != 0 {
|
|
err = errnoErr(e1)
|
|
} else {
|
|
err = syscall.EINVAL
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func sys_accept(s syscall.Handle, rsa *rawSockaddrHyperv, addrlen *int32) (handle syscall.Handle, err error) {
|
|
r1, _, e1 := syscall.Syscall(procAccept.Addr(), 3, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
|
|
handle = syscall.Handle(r1)
|
|
if r1 == socketError {
|
|
if e1 != 0 {
|
|
err = errnoErr(e1)
|
|
} else {
|
|
err = syscall.EINVAL
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) {
|
|
r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(file), uintptr(unsafe.Pointer(o)), 0)
|
|
if r1 == 0 {
|
|
if e1 != 0 {
|
|
err = errnoErr(e1)
|
|
} else {
|
|
err = syscall.EINVAL
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) {
|
|
r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount), 0, 0)
|
|
newport = syscall.Handle(r0)
|
|
if newport == 0 {
|
|
if e1 != 0 {
|
|
err = errnoErr(e1)
|
|
} else {
|
|
err = syscall.EINVAL
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) {
|
|
r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(port), uintptr(unsafe.Pointer(bytes)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(o)), uintptr(timeout), 0)
|
|
if r1 == 0 {
|
|
if e1 != 0 {
|
|
err = errnoErr(e1)
|
|
} else {
|
|
err = syscall.EINVAL
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) {
|
|
r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(h), uintptr(flags), 0)
|
|
if r1 == 0 {
|
|
if e1 != 0 {
|
|
err = errnoErr(e1)
|
|
} else {
|
|
err = syscall.EINVAL
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func timeBeginPeriod(period uint32) (n int32) {
|
|
r0, _, _ := syscall.Syscall(proctimeBeginPeriod.Addr(), 1, uintptr(period), 0, 0)
|
|
n = int32(r0)
|
|
return
|
|
}
|