Skip to content

Commit

Permalink
Move Linux specific code for Pts to pts_linux.go (#221)
Browse files Browse the repository at this point in the history
This allows us to build and test our code on macOS for local
development. With this change, `make test` works on macOs.
  • Loading branch information
unexge committed Jul 18, 2024
1 parent 167a4d8 commit d20d66a
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 49 deletions.
49 changes: 0 additions & 49 deletions pkg/system/pts.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,7 @@
package system

import (
"fmt"
"io"
"os"
"unsafe"

"golang.org/x/sys/unix"
)

const (
Expand All @@ -19,47 +14,3 @@ const (
type Pts interface {
NewPts() (io.ReadCloser, int, error)
}

// Real os implementation of the Pts interface
type OsPts struct{}

func NewOsPts() Pts {
return &OsPts{}
}

// Create a new pseudo terminal (pts). Returns a ReaderCloser for the master device and a pts number
func (p *OsPts) NewPts() (io.ReadCloser, int, error) {
ptmxPath := os.Getenv(PtmxPathEnv)
if ptmxPath == "" {
ptmxPath = DefaultPtmxPath
}
ptsMaster, err := os.Open(ptmxPath)
if err != nil {
return nil, 0, fmt.Errorf("Failed to open tty: %w", err)
}
success := false
defer func() {
if !success {
ptsMaster.Close()
}
}()
// grantpt ioctl to allow mount-s3 process access to the pts
var n uintptr // dummy int for ioctl
if err = unix.IoctlSetInt(int(ptsMaster.Fd()), unix.TIOCGPTN, int(uintptr(unsafe.Pointer(&n)))); err != nil {
return nil, 0, fmt.Errorf("Failed grantpt: %w", err)
}
n = 0
// unlockpt ioctl
err = unix.IoctlSetInt(int(ptsMaster.Fd()), unix.TIOCSPTLCK, int(uintptr(unsafe.Pointer(&n))))
if err != nil {
return nil, 0, fmt.Errorf("Failed unlockpt: %w", err)
}
// ptsname ioctl to get pts path for systemd
ptsN, err := unix.IoctlGetInt(int(ptsMaster.Fd()), unix.TIOCGPTN)
if err != nil {
return nil, 0, fmt.Errorf("Failed to get ptsname: %w", err)
}

success = true
return ptsMaster, ptsN, err
}
8 changes: 8 additions & 0 deletions pkg/system/pts_darwin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package system

// OsPts is the mock Darwin implementation of the Pts interface.
type OsPts struct{}

func NewOsPts() Pts {
panic("not supported on darwin")
}
54 changes: 54 additions & 0 deletions pkg/system/pts_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package system

import (
"fmt"
"io"
"os"
"unsafe"

"golang.org/x/sys/unix"
)

// OsPts is the Linux implementation of the Pts interface.
type OsPts struct{}

func NewOsPts() Pts {
return &OsPts{}
}

// Create a new pseudo terminal (pts). Returns a ReaderCloser for the master device and a pts number
func (p *OsPts) NewPts() (io.ReadCloser, int, error) {
ptmxPath := os.Getenv(PtmxPathEnv)
if ptmxPath == "" {
ptmxPath = DefaultPtmxPath
}
ptsMaster, err := os.Open(ptmxPath)
if err != nil {
return nil, 0, fmt.Errorf("Failed to open tty: %w", err)
}
success := false
defer func() {
if !success {
ptsMaster.Close()
}
}()
// grantpt ioctl to allow mount-s3 process access to the pts
var n uintptr // dummy int for ioctl
if err = unix.IoctlSetInt(int(ptsMaster.Fd()), unix.TIOCGPTN, int(uintptr(unsafe.Pointer(&n)))); err != nil {
return nil, 0, fmt.Errorf("Failed grantpt: %w", err)
}
n = 0
// unlockpt ioctl
err = unix.IoctlSetInt(int(ptsMaster.Fd()), unix.TIOCSPTLCK, int(uintptr(unsafe.Pointer(&n))))
if err != nil {
return nil, 0, fmt.Errorf("Failed unlockpt: %w", err)
}
// ptsname ioctl to get pts path for systemd
ptsN, err := unix.IoctlGetInt(int(ptsMaster.Fd()), unix.TIOCGPTN)
if err != nil {
return nil, 0, fmt.Errorf("Failed to get ptsname: %w", err)
}

success = true
return ptsMaster, ptsN, err
}
2 changes: 2 additions & 0 deletions pkg/system/pts_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build linux

package system_test

import (
Expand Down

0 comments on commit d20d66a

Please sign in to comment.