...

Source file src/github.com/Microsoft/hcsshim/internal/guest/runtime/runc/ioutils.go

Documentation: github.com/Microsoft/hcsshim/internal/guest/runtime/runc

     1  //go:build linux
     2  // +build linux
     3  
     4  package runc
     5  
     6  import (
     7  	"net"
     8  	"os"
     9  	"path/filepath"
    10  
    11  	"github.com/pkg/errors"
    12  	"golang.org/x/sys/unix"
    13  )
    14  
    15  // createConsoleSocket creates a unix socket in the given process directory and
    16  // returns its path and a listener to it. This socket can then be used to
    17  // receive the container's terminal master file descriptor.
    18  func (*runcRuntime) createConsoleSocket(processDir string) (listener *net.UnixListener, socketPath string, err error) {
    19  	socketPath = filepath.Join(processDir, "master.sock")
    20  	addr, err := net.ResolveUnixAddr("unix", socketPath)
    21  	if err != nil {
    22  		return nil, "", errors.Wrapf(err, "failed to resolve unix socket at address %s", socketPath)
    23  	}
    24  	listener, err = net.ListenUnix("unix", addr)
    25  	if err != nil {
    26  		return nil, "", errors.Wrapf(err, "failed to listen on unix socket at address %s", socketPath)
    27  	}
    28  	return listener, socketPath, nil
    29  }
    30  
    31  // getMasterFromSocket blocks on the given listener's socket until a message is
    32  // sent, then parses the file descriptor representing the terminal master out
    33  // of the message and returns it as a file.
    34  func (*runcRuntime) getMasterFromSocket(listener *net.UnixListener) (master *os.File, err error) {
    35  	// Accept the listener's connection.
    36  	conn, err := listener.Accept()
    37  	if err != nil {
    38  		return nil, errors.Wrap(err, "failed to get terminal master file descriptor from socket")
    39  	}
    40  	defer conn.Close()
    41  	unixConn, ok := conn.(*net.UnixConn)
    42  	if !ok {
    43  		return nil, errors.New("connection returned from Accept was not a unix socket")
    44  	}
    45  
    46  	const maxNameLen = 4096
    47  	var oobSpace = unix.CmsgSpace(4)
    48  
    49  	name := make([]byte, maxNameLen)
    50  	oob := make([]byte, oobSpace)
    51  
    52  	// Read a message from the unix socket. This blocks until the message is
    53  	// sent.
    54  	n, oobn, _, _, err := unixConn.ReadMsgUnix(name, oob)
    55  	if err != nil {
    56  		return nil, errors.Wrap(err, "failed to read message from unix socket")
    57  	}
    58  	if n >= maxNameLen || oobn != oobSpace {
    59  		return nil, errors.Errorf("read an invalid number of bytes (n=%d oobn=%d)", n, oobn)
    60  	}
    61  
    62  	// Truncate the data returned from the message.
    63  	name = name[:n]
    64  	oob = oob[:oobn]
    65  
    66  	// Parse the out-of-band data in the message.
    67  	messages, err := unix.ParseSocketControlMessage(oob)
    68  	if err != nil {
    69  		return nil, errors.Wrapf(err, "failed to parse socket control message for oob %v", oob)
    70  	}
    71  	if len(messages) == 0 {
    72  		return nil, errors.New("did not receive any socket control messages")
    73  	}
    74  	if len(messages) > 1 {
    75  		return nil, errors.Errorf("received more than one socket control message: received %d", len(messages))
    76  	}
    77  	message := messages[0]
    78  
    79  	// Parse the file descriptor out of the out-of-band data in the message.
    80  	fds, err := unix.ParseUnixRights(&message)
    81  	if err != nil {
    82  		return nil, errors.Wrapf(err, "failed to parse file descriptors out of message %v", message)
    83  	}
    84  	if len(fds) == 0 {
    85  		return nil, errors.New("did not receive any file descriptors")
    86  	}
    87  	if len(fds) > 1 {
    88  		return nil, errors.Errorf("received more than one file descriptor: received %d", len(fds))
    89  	}
    90  	fd := uintptr(fds[0])
    91  
    92  	return os.NewFile(fd, string(name)), nil
    93  }
    94  
    95  // pathExists returns true if the given path exists, false if not.
    96  //
    97  //nolint:unused
    98  func (*runcRuntime) pathExists(pathToCheck string) (bool, error) {
    99  	_, err := os.Stat(pathToCheck)
   100  	if err != nil {
   101  		if os.IsNotExist(err) {
   102  			return false, nil
   103  		}
   104  		return false, errors.Wrapf(err, "failed call to Stat for path %s", pathToCheck)
   105  	}
   106  	return true, nil
   107  }
   108  

View as plain text