func listenStream(netw, addr string) (l net.Listener, err error) { var ( file *os.File ) fd, err := listen(netw, addr) if err != nil { return nil, err } // Set backlog size to the maximum if err = syscall.Listen(fd, syscall.SOMAXCONN); err != nil { syscall.Close(fd) return nil, err } file = os.NewFile(uintptr(fd), filePrefix+strconv.Itoa(os.Getpid())) if l, err = net.FileListener(file); err != nil { syscall.Close(fd) return nil, err } if err = file.Close(); err != nil { syscall.Close(fd) l.Close() return nil, err } return l, err }
func newfile(fd uintptr, name string) *os.File { p, err := winPath(name) if err != nil { return os.NewFile(fd, name) } return os.NewFile(fd, p) }
func newPipeFd() (*Pipe, error) { r2pipeIn := os.Getenv("R2PIPE_IN") r2pipeOut := os.Getenv("R2PIPE_OUT") if r2pipeIn == "" || r2pipeOut == "" { return nil, errors.New("missing R2PIPE_{IN,OUT} vars") } r2pipeInFd, err := strconv.Atoi(r2pipeIn) if err != nil { return nil, err } r2pipeOutFd, err := strconv.Atoi(r2pipeOut) if err != nil { return nil, err } stdout := os.NewFile(uintptr(r2pipeInFd), "R2PIPE_IN") stdin := os.NewFile(uintptr(r2pipeOutFd), "R2PIPE_OUT") r2p := &Pipe{ File: "", r2cmd: nil, stdin: stdin, stdout: stdout, } return r2p, nil }
func newSocketPair(name string) (*os.File, *os.File, error) { pair, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0) if err != nil { return nil, nil, err } return os.NewFile(uintptr(pair[0]), name), os.NewFile(uintptr(pair[1]), name), nil }
// Pty returns a UNIX 98 pseudoterminal device. // Pty returns a pair of fds representing the master and slave pair. func Pty() (*os.File, *os.File, error) { open := func(path string) (uintptr, error) { fd, err := syscall.Open(path, syscall.O_NOCTTY|syscall.O_RDWR|syscall.O_CLOEXEC, 0666) if err != nil { return 0, fmt.Errorf("unable to open %q: %v", path, err) } return uintptr(fd), nil } ptm, err := open("/dev/ptmx") if err != nil { return nil, nil, err } sname, err := ptsname(ptm) if err != nil { return nil, nil, err } err = grantpt(ptm) if err != nil { return nil, nil, err } err = unlockpt(ptm) if err != nil { return nil, nil, err } pts, err := open(sname) if err != nil { return nil, nil, err } return os.NewFile(uintptr(ptm), "ptm"), os.NewFile(uintptr(pts), sname), nil }
// Pty returns a UNIX 98 pseudoterminal device. // Pty returns a pair of fds representing the master and slave pair. func Pty() (*os.File, *os.File, error) { ptm, err := open_pty_master() if err != nil { return nil, nil, err } sname, err := Ptsname(ptm) if err != nil { return nil, nil, err } err = grantpt(ptm) if err != nil { return nil, nil, err } err = unlockpt(ptm) if err != nil { return nil, nil, err } pts, err := open_device(sname) if err != nil { return nil, nil, err } return os.NewFile(uintptr(ptm), "ptm"), os.NewFile(uintptr(pts), sname), nil }
// Opens a pseudo-terminal, forks, sets up the pty slave as the new child process's controlling terminal and // stdin/stdout/stderr, and execs the given command in the child process. Returns the master // terminal control, the child pid, and an Error if any. func ForkPty(name string, argv []string, attr *Attributes, size *WindowSize) (*Terminal, int, os.Error) { master, slave, err := OpenPty(attr, size) if err != nil { return nil, -1, err } procattr := &os.ProcAttr{ Dir: "", Env: nil, Files: []*os.File{ os.NewFile(slave.Fd(), "/dev/stdin"), os.NewFile(slave.Fd(), "/dev/stdout"), os.NewFile(slave.Fd(), "/dev/stderr"), }, Sys: &syscall.SysProcAttr{ Setsid: true, Setctty: true, }, } proc, err := os.StartProcess(name, argv, procattr) if err != nil { return nil, -1, err } return master, proc.Pid, nil }
func newPipe() (parent *os.File, child *os.File, err error) { fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0) if err != nil { return nil, nil, err } return os.NewFile(uintptr(fds[1]), "parent"), os.NewFile(uintptr(fds[0]), "child"), nil }
func newFakeVTYServer() (*fakeVTYServer, error) { fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0) if err != nil { return nil, err } vtyClientFile := os.NewFile(uintptr(fds[1]), "vty-client") vtyClientConn, err := net.FileConn(vtyClientFile) if err != nil { return nil, err } vtyServerFile := os.NewFile(uintptr(fds[0]), "vty-server") vtyServerConn, err := net.FileConn(vtyServerFile) if err != nil { return nil, err } syscall.SetNonblock(fds[0], false) vs := &fakeVTYServer{ clientConn: vtyClientConn, serverConn: vtyServerConn, clientFile: vtyClientFile, serverFile: vtyServerFile, send: make(chan []byte), received: make(chan []byte), } go vs.read() go vs.write() return vs, nil }
func createAttachment(stream *spdystream.Stream) (*os.File, error) { if stream.IsFinished() { return nil, fmt.Errorf("stream already finished") } socketFds, socketErr := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM|syscall.FD_CLOEXEC, 0) if socketErr != nil { return nil, socketErr } pipe := os.NewFile(uintptr(socketFds[1]), "") defer pipe.Close() conn, connErr := net.FileConn(pipe) if connErr != nil { return nil, connErr } go func() { io.Copy(conn, stream) conn.Close() }() go func() { io.Copy(stream, conn) }() return os.NewFile(uintptr(socketFds[0]), ""), nil }
func socketPair() (sock1 *os.File, sock2 *os.File, err error) { var fds [2]int fds, err = syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM, 0) if err != nil { fmt.Println(err.Error()) } return os.NewFile(uintptr(fds[0]), "|0"), os.NewFile(uintptr(fds[1]), "|1"), err }
func mount(dir string, ready chan<- struct{}, errp *error) (fusefd *os.File, err error) { // linux mount is never delayed close(ready) fds, err := syscall.Socketpair(syscall.AF_FILE, syscall.SOCK_STREAM, 0) if err != nil { return nil, fmt.Errorf("socketpair error: %v", err) } defer syscall.Close(fds[0]) defer syscall.Close(fds[1]) cmd := exec.Command("fusermount", "--", dir) cmd.Env = append(os.Environ(), "_FUSE_COMMFD=3") writeFile := os.NewFile(uintptr(fds[0]), "fusermount-child-writes") defer writeFile.Close() cmd.ExtraFiles = []*os.File{writeFile} out, err := cmd.CombinedOutput() if len(out) > 0 || err != nil { return nil, fmt.Errorf("fusermount: %q, %v", out, err) } readFile := os.NewFile(uintptr(fds[1]), "fusermount-parent-reads") defer readFile.Close() c, err := net.FileConn(readFile) if err != nil { return nil, fmt.Errorf("FileConn from fusermount socket: %v", err) } defer c.Close() uc, ok := c.(*net.UnixConn) if !ok { return nil, fmt.Errorf("unexpected FileConn type; expected UnixConn, got %T", c) } buf := make([]byte, 32) // expect 1 byte oob := make([]byte, 32) // expect 24 bytes _, oobn, _, _, err := uc.ReadMsgUnix(buf, oob) scms, err := syscall.ParseSocketControlMessage(oob[:oobn]) if err != nil { return nil, fmt.Errorf("ParseSocketControlMessage: %v", err) } if len(scms) != 1 { return nil, fmt.Errorf("expected 1 SocketControlMessage; got scms = %#v", scms) } scm := scms[0] gotFds, err := syscall.ParseUnixRights(&scm) if err != nil { return nil, fmt.Errorf("syscall.ParseUnixRights: %v", err) } if len(gotFds) != 1 { return nil, fmt.Errorf("wanted 1 fd; got %#v", gotFds) } f := os.NewFile(uintptr(gotFds[0]), "/dev/fuse") return f, nil }
func newCtlSockets() (*os.File, *os.File, error) { fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_SEQPACKET, 0) if err != nil { return nil, nil, err } f1 := os.NewFile(uintptr(fds[0]), "ctl") f2 := os.NewFile(uintptr(fds[1]), "ctl") return f1, f2, nil }
func unixgramSocketpair() (l, r *os.File, err error) { fd, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_SEQPACKET, 0) if err != nil { return nil, nil, os.NewSyscallError("socketpair", err.(syscall.Errno)) } l = os.NewFile(uintptr(fd[0]), "socketpair-half1") r = os.NewFile(uintptr(fd[1]), "socketpair-half2") return }
// either gets a pipe off the pool or returns a brand new one func initPipe() (p *pipe, err error) { var pp [2]int32 _, _, e := syscall.RawSyscall(syscall.SYS_PIPE2, uintptr(unsafe.Pointer(&pp)), syscall.O_CLOEXEC, 0) if e != 0 { return nil, os.NewSyscallError("pipe", e) } fmt.Printf("Got new pipe, read fd %d, write fd %d\n", pp[0], pp[1]) return &pipe{os.NewFile(uintptr(pp[0]), "|0"), os.NewFile(uintptr(pp[1]), "|1"), 0}, nil }
func (c *Client) GetStdout() (*os.File, *os.File, error) { var fds []fdrpc.FD if err := c.c.Call("ContainerInit.GetStdout", struct{}{}, &fds); err != nil { return nil, nil, err } if len(fds) != 2 { return nil, nil, fmt.Errorf("containerinit: got %d fds, expected 2", len(fds)) } return os.NewFile(uintptr(fds[0].FD), "stdout"), os.NewFile(uintptr(fds[1].FD), "stderr"), nil }
func run() int { flag.Parse() runtime := flag.Args()[1] // e.g. runc dir := flag.Args()[2] // bundlePath for run, processPath for exec containerId := flag.Args()[3] signals := make(chan os.Signal, 100) signal.Notify(signals, syscall.SIGCHLD) fd3 := os.NewFile(3, "/proc/self/fd/3") logFile := fmt.Sprintf("/proc/%d/fd/4", os.Getpid()) logFD := os.NewFile(4, "/proc/self/fd/4") syncPipe := os.NewFile(5, "/proc/self/fd/5") pidFilePath := filepath.Join(dir, "pidfile") stdin, stdout, stderr, winsz := openPipes(dir) syncPipe.Write([]byte{0}) var runcStartCmd *exec.Cmd if *tty { ttySlave := setupTty(stdin, stdout, pidFilePath, winsz, garden.WindowSize{Rows: *rows, Columns: *cols}) runcStartCmd = exec.Command(runtime, "-debug", "-log", logFile, "exec", "-d", "-tty", "-console", ttySlave.Name(), "-p", fmt.Sprintf("/proc/%d/fd/0", os.Getpid()), "-pid-file", pidFilePath, containerId) } else { runcStartCmd = exec.Command(runtime, "-debug", "-log", logFile, "exec", "-p", fmt.Sprintf("/proc/%d/fd/0", os.Getpid()), "-d", "-pid-file", pidFilePath, containerId) runcStartCmd.Stdin = stdin runcStartCmd.Stdout = stdout runcStartCmd.Stderr = stderr } // we need to be the subreaper so we can wait on the detached container process system.SetSubreaper(os.Getpid()) if err := runcStartCmd.Start(); err != nil { fd3.Write([]byte{2}) return 2 } var status syscall.WaitStatus var rusage syscall.Rusage _, err := syscall.Wait4(runcStartCmd.Process.Pid, &status, 0, &rusage) check(err) // Start succeeded but Wait4 failed, this can only be a programmer error logFD.Close() // No more logs from runc so close fd fd3.Write([]byte{byte(status.ExitStatus())}) if status.ExitStatus() != 0 { return 3 // nothing to wait for, container didn't launch } containerPid, err := parsePid(pidFilePath) check(err) return waitForContainerToExit(dir, containerPid, signals) }
func Socketpair(typ int) (a, b *os.File, err error) { fd, err := syscall.Socketpair(syscall.AF_UNIX, typ, 0) if err != nil { e := os.NewSyscallError("socketpair", err.(syscall.Errno)) return nil, nil, e } a = os.NewFile(uintptr(fd[0]), "socketpair-a") b = os.NewFile(uintptr(fd[1]), "socketpair-b") return }
func (sp *SocketPair) init() { fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0) if err != nil { fmt.Println(err) return } sp.LocalFile = os.NewFile(uintptr(fds[0]), "sp-0") sp.RemoteFile = os.NewFile(uintptr(fds[1]), "sp-1") }
func NewSyncPipeFromFd(parendFd, childFd uintptr) (*SyncPipe, error) { s := &SyncPipe{} if parendFd > 0 { s.parent = os.NewFile(parendFd, "parendPipe") } else if childFd > 0 { s.child = os.NewFile(childFd, "childPipe") } else { return nil, fmt.Errorf("no valid sync pipe fd specified") } return s, nil }
// initd listens on a socket, spawns requested processes and reaps their // exit statuses. func main() { defer func() { if r := recover(); r != nil { fmt.Fprintf(os.Stderr, "initd: panicked: %s\n", r) os.Exit(4) } }() dropCaps := flag.Bool("dropCapabilities", false, "drop capabilities before running processes") flag.Parse() container_daemon.Detach("/dev/null", "/dev/null") logger := lager.NewLogger("initd") syncWriter := os.NewFile(uintptr(4), "/dev/sync_writer") syscall.RawSyscall(syscall.SYS_FCNTL, uintptr(4), syscall.F_SETFD, syscall.FD_CLOEXEC) defer syncWriter.Close() sync := &containerizer.PipeSynchronizer{ Writer: syncWriter, } reaper := system.StartReaper(logger) defer reaper.Stop() daemon := &container_daemon.ContainerDaemon{ CmdPreparer: &container_daemon.ProcessSpecPreparer{ Users: container_daemon.LibContainerUser{}, Rlimits: &container_daemon.RlimitsManager{}, ProcStarterPath: "/sbin/proc_starter", AlwaysDropCapabilities: *dropCaps, }, Spawner: &container_daemon.Spawn{ Runner: reaper, PTY: system.KrPty, }, } socketFile := os.NewFile(uintptr(5), "/dev/host.sock") listener, err := unix_socket.NewListenerFromFile(socketFile) if err != nil { fail(fmt.Sprintf("initd: failed to create listener: %s\n", err), 5) } socketFile.Close() if err := sync.SignalSuccess(); err != nil { fail(fmt.Sprintf("signal host: %s", err), 6) } if err := daemon.Run(listener); err != nil { fail(fmt.Sprintf("run daemon: %s", err), 7) } }
// Gets a channel on which to publish events. // // Returns a file on which the process is supposed to write data, which then // translate into these events. func startProcessNotifier(ready chan<- bool) (w *os.File, err error) { fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_DGRAM, 0) if err != nil { return } r := os.NewFile(uintptr(fds[0]), "notify:r") // File name is arbitrary w = os.NewFile(uintptr(fds[1]), "notify:w") go runProcessNotifier(r, ready) return w, nil }
func NewSyncPipe() (s *SyncPipe, err error) { s = &SyncPipe{} fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0) if err != nil { return nil, err } s.child = os.NewFile(uintptr(fds[0]), "child syncpipe") s.parent = os.NewFile(uintptr(fds[1]), "parent syncpipe") return s, nil }
func main() { // I assume that in is 0 in2, err := syscall.Dup(0) if err != nil { log.Fatal("dupping 0", err) } out2, err := syscall.Dup(1) if err != nil { log.Fatal("dupping 1", err) } os.Stdin.Close() os.Stdout.Close() os.Stdout = os.NewFile(uintptr(2), "/dev/stdout") /* Connections to the application. */ cin := os.NewFile(uintptr(in2), "fromapp") cout := os.NewFile(uintptr(out2), "toapp") modifyEnvironment() // Fire up a new devdraw here devdraw, err := drawfcall.New() if err != nil { log.Fatal("making a Conn", err) } // There is probably a nicer way to do this. // TODO(rjkroege): do it the nicer way. var app App app.o = cout app.i = cin json := NewJsonRecorder() for { // read crap from cin log.Print("about to read from host") inbuffy, err := drawfcall.ReadMsg(cin) log.Print("read from host") if err != nil { devdraw.Close() break } go marshalsxtx(inbuffy, &app, devdraw, json) } log.Print("waiting on completion") json.WaitToComplete() }
func createStreamMessage(stream *spdystream.Stream, mode int, streamChans streamChanProvider, ret libchan.Sender) (*libchan.Message, error) { dataString := stream.Headers()["Data"] if len(dataString) != 1 { if len(dataString) == 0 { return nil, fmt.Errorf("Stream(%s) is missing data header", stream) } else { return nil, fmt.Errorf("Stream(%s) has multiple data headers", stream) } } data, decodeErr := base64.URLEncoding.DecodeString(dataString[0]) if decodeErr != nil { return nil, decodeErr } var attach *os.File if !stream.IsFinished() { socketFds, socketErr := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM|syscall.FD_CLOEXEC, 0) if socketErr != nil { return nil, socketErr } attach = os.NewFile(uintptr(socketFds[0]), "") conn, connErr := net.FileConn(os.NewFile(uintptr(socketFds[1]), "")) if connErr != nil { return nil, connErr } go func() { io.Copy(conn, stream) }() go func() { io.Copy(stream, conn) }() } retSender := ret if retSender == nil || libchan.RetPipe.Equals(retSender) { retSender = &StreamSender{stream: stream, streamChans: streamChans} } if mode&libchan.Ret == 0 { retSender.Close() } return &libchan.Message{ Data: data, Fd: attach, Ret: retSender, }, nil }
// DeserializeFDMessageStream takes a string description of the form // "tao::FDMessageStream(X, Y)" and returns a MessageStream that uses file // descriptor X as the reader and file descriptor Y as the writer. func DeserializeFDMessageStream(s string) (*MessageStream, error) { var readfd, writefd uintptr _, err := fmt.Sscanf(s, "tao::FDMessageChannel(%d, %d)", &readfd, &writefd) if err != nil { return nil, errors.New("unrecognized channel spec " + s) } if readfd == writefd { rw := os.NewFile(readfd, "read/write pipe") return NewMessageStream(rw), nil } r := os.NewFile(readfd, "read pipe") w := os.NewFile(writefd, "write pipe") rw := NewPairReadWriteCloser(r, w) return NewMessageStream(rw), nil }
func Pipe() (master *os.File, slave *os.File, err error) { fd_master := C.int(-1) fd_slave := C.int(-1) C.create_pipe(&fd_master, &fd_slave) if fd_master == -1 || fd_slave == -1 { return nil, nil, errors.New("Failed to create a new pipe") } master = os.NewFile(uintptr(fd_master), "master") slave = os.NewFile(uintptr(fd_slave), "slave") return master, slave, nil }
func makeFlushFS() (server fuse.Server, err error) { // Check the flags. if *fFlushesFile == 0 || *fFsyncsFile == 0 { err = fmt.Errorf("You must set the flushfs flags.") return } // Set up the files. flushes := os.NewFile(uintptr(*fFlushesFile), "(flushes file)") fsyncs := os.NewFile(uintptr(*fFsyncsFile), "(fsyncs file)") // Set up errors. var flushErr error var fsyncErr error if *fFlushError != 0 { flushErr = bazilfuse.Errno(*fFlushError) } if *fFsyncError != 0 { fsyncErr = bazilfuse.Errno(*fFsyncError) } // Report flushes and fsyncs by writing the contents followed by a newline. report := func(f *os.File, outErr error) func(string) error { return func(s string) (err error) { buf := []byte(s) buf = append(buf, '\n') _, err = f.Write(buf) if err != nil { err = fmt.Errorf("Write: %v", err) return } err = outErr return } } reportFlush := report(flushes, flushErr) reportFsync := report(fsyncs, fsyncErr) // Create the file system. server, err = flushfs.NewFileSystem(reportFlush, reportFsync) return }
// TestLinuxSendfileChild isn't a real test. It's used as a helper process // for TestLinuxSendfile. func TestLinuxSendfileChild(*testing.T) { if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" { return } defer os.Exit(0) fd3 := os.NewFile(3, "ephemeral-port-listener") ln, err := net.FileListener(fd3) if err != nil { panic(err) } mux := http.NewServeMux() fs := &FileServer{ http.Dir("testdata"), inject.CopyInject{}, ricetemp.MustMakeTemplates(rice.MustFindBox("../templates")), } mux.Handle("/", fs) mux.HandleFunc("/quit", func(http.ResponseWriter, *http.Request) { os.Exit(0) }) s := &http.Server{Handler: mux} err = s.Serve(ln) if err != nil { panic(err) } }
func (r *trServiceManager) run(gracefulProtos string) error { // TODO If a listen-spec changes in the config and a graceful // restart is issued, the new config will not take effect as the // open file is reused. if gracefulProtos == "" { for _, service := range r.services { if err := service.Start(nil); err != nil { return err } } } else { protos := strings.Split(gracefulProtos, ",") for n, p := range protos { f := os.NewFile(uintptr(n+3), "") if r.services[p] != nil { if err := r.services[p].Start(f); err != nil { return err } } } } return nil }