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 (k *PosixKernel) Dup(oldFd co.Fd) uint64 { if newFd, err := syscall.Dup(int(oldFd)); err != nil { return Errno(err) } else { return uint64(newFd) } }
func (t *FlushErrorTest) Dup() { var err error // Open the file. t.f1, err = os.OpenFile(path.Join(t.Dir, "foo"), os.O_WRONLY, 0) AssertEq(nil, err) fd1 := t.f1.Fd() // Use dup(2) to get another copy. fd2, err := syscall.Dup(int(fd1)) AssertEq(nil, err) t.f2 = os.NewFile(uintptr(fd2), t.f1.Name()) // Close by the first handle. On OS X, where the semantics of file handles // are different (cf. https://github.com/osxfuse/osxfuse/issues/199), this // does not result in an error. err = t.f1.Close() t.f1 = nil if isDarwin { AssertEq(nil, err) } else { ExpectThat(err, Error(HasSubstr("no such file"))) } // Close by the second handle. err = t.f2.Close() t.f2 = nil ExpectThat(err, Error(HasSubstr("no such file"))) }
func (fd *netFD) file(f *os.File, s string) (*os.File, error) { dfd, err := syscall.Dup(int(f.Fd()), -1) if err != nil { return nil, os.NewSyscallError("dup", err) } return os.NewFile(uintptr(dfd), s), nil }
func (sf *StateFile) Lock(create bool) (*Lock, error) { sf.lockFdMutex.Lock() defer sf.lockFdMutex.Unlock() if sf.lockFd != nil { return &Lock{sf.lockFd}, nil } flags := os.O_RDWR if create { flags |= os.O_CREATE | os.O_EXCL } file, err := os.OpenFile(sf.Path, flags, 0600) if err != nil { return nil, err } defer file.Close() fd := int(file.Fd()) newFd, err := syscall.Dup(fd) if err != nil { return nil, err } if syscall.Flock(newFd, syscall.LOCK_EX|syscall.LOCK_NB) != nil { syscall.Close(newFd) return nil, nil } sf.lockFd = &newFd return &Lock{sf.lockFd}, nil }
func CaptureStream(file *os.File) (*os.File, func(), error) { pipeR, pipeW, err := os.Pipe() if err != nil { return nil, nil, err } bkupFD, err := syscall.Dup(int(file.Fd())) if err != nil { pipeW.Close() pipeR.Close() return nil, nil, err } err = syscall.Dup2(int(pipeW.Fd()), int(file.Fd())) if err != nil { syscall.Close(bkupFD) pipeW.Close() pipeR.Close() } cleanFunc := func() { syscall.Dup2(bkupFD, int(file.Fd())) syscall.Close(bkupFD) pipeW.Close() pipeR.Close() } return pipeR, cleanFunc, nil }
func mount(mountPoint string, opts *MountOptions, ready chan<- error) (fd int, err error) { f, err := openFUSEDevice() if err != nil { return 0, err } cmd := exec.Command(bin, "-o", strings.Join(opts.optionsStrings(), ","), "-o", fmt.Sprintf("iosize=%d", opts.MaxWrite), "3", mountPoint) cmd.ExtraFiles = []*os.File{f} cmd.Env = append(os.Environ(), "MOUNT_FUSEFS_CALL_BY_LIB=", "MOUNT_OSXFUSE_CALL_BY_LIB=", "MOUNT_OSXFUSE_DAEMON_PATH="+os.Args[0], "MOUNT_FUSEFS_DAEMON_PATH="+os.Args[0]) var out, errOut bytes.Buffer cmd.Stdout = &out cmd.Stderr = &errOut if err := cmd.Start(); err != nil { f.Close() return 0, err } go func() { err := cmd.Wait() if err != nil { err = fmt.Errorf("mount_osxfusefs failed: %v. Stderr: %s, Stdout: %s", err, errOut.String(), out.String()) } ready <- err close(ready) }() // The finalizer for f will close its fd so we return a dup. defer f.Close() return syscall.Dup(int(f.Fd())) }
func TestSendErrorFromChild(t *testing.T) { pipe, err := NewSyncPipe() if err != nil { t.Fatal(err) } defer func() { if err := pipe.Close(); err != nil { t.Fatal(err) } }() childfd, err := syscall.Dup(int(pipe.Child().Fd())) if err != nil { t.Fatal(err) } childPipe, _ := NewSyncPipeFromFd(0, uintptr(childfd)) pipe.CloseChild() pipe.SendToChild(nil) expected := "something bad happened" childPipe.ReportChildError(fmt.Errorf(expected)) childError := pipe.ReadFromChild() if childError == nil { t.Fatal("expected an error to be returned but did not receive anything") } if childError.Error() != expected { t.Fatalf("expected %q but received error message %q", expected, childError.Error()) } }
// NewBufferFile maps a file to shared memory and returns a handle to the shared memory buffer func NewBufferFile(file *os.File, size, prot int) (Buffer, error) { fi, err := file.Stat() if err != nil { return nil, err } sys := fi.Sys().(*syscall.Stat_t) if sys.Size != int64(size) { return nil, errWrongSize } // Dup to allow file parameter to be closed regardless fd, err := syscall.Dup(int(file.Fd())) if err != nil { return nil, err } const flags = syscall.MAP_SHARED b, err := syscall.Mmap(fd, 0, size, prot, flags) if err != nil { return nil, err } // localFile is nil because fd is from somewhere else buf := &sharedBuffer{os.NewFile(uintptr(fd), ""), nil, b, stackToKeep()} runtime.SetFinalizer(buf, (*sharedBuffer).finalize) return buf, nil }
// Get topology data using blkid APIs. In case of an error getting any of the // topology properties the field will be set to 0 func getBlockDeviceTopology(file File) (DeviceTopology, error) { var res DeviceTopology probe := C.blkid_new_probe() if probe == nil { return res, fmt.Errorf("Could not probe device") } C.blkid_reset_probe(probe) fd, err := syscall.Dup(int(file.Fd())) if err != nil { return res, fmt.Errorf("Could not dup FD as part of device probing: %s", err) } rv := C.blkid_probe_set_device(probe, C.int(fd), 0, 0) if rv != 0 { syscall.Close(fd) } defer C.blkid_free_probe(probe) topology := C.blkid_probe_get_topology(probe) if topology == nil { return res, fmt.Errorf("Could not get topology for device") } res.AlignmentOffset = uint64(C.blkid_topology_get_alignment_offset(topology)) res.MinimumIOSize = uint64(C.blkid_topology_get_minimum_io_size(topology)) res.OptimalIOSize = uint64(C.blkid_topology_get_optimal_io_size(topology)) res.LogicalSectorSize = uint64(C.blkid_topology_get_logical_sector_size(topology)) res.PhysicalSectorSize = uint64(C.blkid_topology_get_physical_sector_size(topology)) return res, nil }
func dup(file *os.File, name string) (newfile *os.File, err error) { fd, err := syscall.Dup(int(file.Fd())) if err != nil { return nil, err } return os.NewFile(uintptr(fd), "<stdin>"), nil }
// DupFd returns the integer Unix file descriptor duplicated from Listener. // This method can't invoke simultaneously. func (l *Listener) DupFd() (int, error) { f, err := l.fileListener.File() if err != nil { return 0, err } return syscall.Dup(int(f.Fd())) }
func newFileFD(f *os.File) (*netFD, error) { syscall.ForkLock.RLock() fd, err := syscall.Dup(int(f.Fd())) if err != nil { syscall.ForkLock.RUnlock() return nil, os.NewSyscallError("dup", err) } syscall.CloseOnExec(fd) syscall.ForkLock.RUnlock() sotype, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_TYPE) if err != nil { closesocket(fd) return nil, os.NewSyscallError("getsockopt", err) } family := syscall.AF_UNSPEC toAddr := sockaddrToTCP sa, _ := syscall.Getsockname(fd) switch sa.(type) { default: closesocket(fd) return nil, syscall.EINVAL case *syscall.SockaddrInet4: family = syscall.AF_INET if sotype == syscall.SOCK_DGRAM { toAddr = sockaddrToUDP } else if sotype == syscall.SOCK_RAW { toAddr = sockaddrToIP } case *syscall.SockaddrInet6: family = syscall.AF_INET6 if sotype == syscall.SOCK_DGRAM { toAddr = sockaddrToUDP } else if sotype == syscall.SOCK_RAW { toAddr = sockaddrToIP } case *syscall.SockaddrUnix: family = syscall.AF_UNIX toAddr = sockaddrToUnix if sotype == syscall.SOCK_DGRAM { toAddr = sockaddrToUnixgram } else if sotype == syscall.SOCK_SEQPACKET { toAddr = sockaddrToUnixpacket } } laddr := toAddr(sa) sa, _ = syscall.Getpeername(fd) raddr := toAddr(sa) netfd, err := newFD(fd, family, sotype, laddr.Network()) if err != nil { closesocket(fd) return nil, err } netfd.setAddr(laddr, raddr) return netfd, nil }
func (fd *netFD) file(f *os.File, s string) (*os.File, error) { syscall.ForkLock.RLock() dfd, err := syscall.Dup(int(f.Fd()), -1) syscall.ForkLock.RUnlock() if err != nil { return nil, &OpError{"dup", s, fd.laddr, err} } return os.NewFile(uintptr(dfd), s), nil }
func newFileFD(f *os.File) (net *netFD, err error) { var ctl *os.File close := func(fd int) { if err != nil { syscall.Close(fd) } } path, err := syscall.Fd2path(int(f.Fd())) if err != nil { return nil, os.NewSyscallError("fd2path", err) } comp := splitAtBytes(path, "/") n := len(comp) if n < 3 || comp[0] != "net" { return nil, syscall.EPLAN9 } name := comp[2] switch file := comp[n-1]; file { case "ctl", "clone": syscall.ForkLock.RLock() fd, err := syscall.Dup(int(f.Fd()), -1) syscall.ForkLock.RUnlock() if err != nil { return nil, os.NewSyscallError("dup", err) } defer close(fd) dir := "/net/" + comp[n-2] ctl = os.NewFile(uintptr(fd), dir+"/"+file) ctl.Seek(0, 0) var buf [16]byte n, err := ctl.Read(buf[:]) if err != nil { return nil, err } name = string(buf[:n]) default: if len(comp) < 4 { return nil, errors.New("could not find control file for connection") } dir := "/net/" + comp[1] + "/" + name ctl, err = os.OpenFile(dir+"/ctl", os.O_RDWR, 0) if err != nil { return nil, err } defer close(int(ctl.Fd())) } dir := "/net/" + comp[1] + "/" + name laddr, err := readPlan9Addr(comp[1], dir+"/local") if err != nil { return nil, err } return newFD(comp[1], name, ctl, nil, laddr, nil), nil }
// dupCloseOnExecUnixOld is the traditional way to dup an fd and // set its O_CLOEXEC bit, using two system calls. func dupCloseOnExecOld(fd int) (newfd int, err error) { syscall.ForkLock.RLock() defer syscall.ForkLock.RUnlock() newfd, err = syscall.Dup(fd) if err != nil { return -1, os.NewSyscallError("dup", err) } syscall.CloseOnExec(newfd) return }
func Test_println(t *testing.T) { cleanup1 := testutils.Chtemp() defer cleanup1() rfile, err := os.Create("stdout") if err != nil { panic(err) } // save a copy of stdout in another fd stdout_fd := int(os.Stdout.Fd()) save_stdout, err := syscall.Dup(stdout_fd) if err != nil { panic(err) } // redirect stdout to rfile err = syscall.Dup2(int(rfile.Fd()), stdout_fd) if err != nil { panic(err) } cleanup2 := func() { rfile.Close() err = syscall.Dup2(save_stdout, stdout_fd) if err != nil { panic(err) } syscall.Close(save_stdout) } defer cleanup2() args := RuntimeArgs{ BasicArgs: types.MakeBasicArgs(nil, []types.FuObject{}, nil), } result, errs := fn_println(args) assert.Nil(t, result) assert.Equal(t, 0, len(errs)) data, err := ioutil.ReadFile("stdout") assert.Nil(t, err) assert.Equal(t, "\n", string(data)) rfile.Truncate(0) rfile.Seek(0, 0) args.SetArgs(types.MakeStringList("hello", "world").List()) fn_println(args) data, err = ioutil.ReadFile("stdout") assert.Nil(t, err) assert.Equal(t, "hello world\n", string(data)) rfile.Truncate(0) rfile.Seek(0, 0) }
// LockStateFile attempts to lock the given file. If successful, it returns // true and the lock persists for the lifetime of the process. func LockStateFile(stateFile *os.File) (*Lock, bool) { fd := int(stateFile.Fd()) newFd, err := syscall.Dup(fd) if err != nil { panic(err) } if syscall.Flock(newFd, syscall.LOCK_EX|syscall.LOCK_NB) != nil { syscall.Close(newFd) return nil, false } return &Lock{newFd}, true }
// Test double close func TestReadFileDoubleClose(t *testing.T) { run.skipIfNoFUSE(t) run.createFile(t, "testdoubleclose", "hello") in, err := os.Open(run.path("testdoubleclose")) assert.NoError(t, err) fd := in.Fd() fd1, err := syscall.Dup(int(fd)) assert.NoError(t, err) fd2, err := syscall.Dup(int(fd)) assert.NoError(t, err) // close one of the dups - should produce no error err = syscall.Close(fd1) assert.NoError(t, err) // read from the file buf := make([]byte, 1) _, err = in.Read(buf) assert.NoError(t, err) // close it err = in.Close() assert.NoError(t, err) // read from the other dup - should produce no error as this // file is now buffered n, err := syscall.Read(fd2, buf) assert.NoError(t, err) assert.Equal(t, 1, n) // close the dup - should not produce an error err = syscall.Close(fd2) assert.NoError(t, err, "input/output error") run.rm(t, "testdoubleclose") }
func (k *PosixKernel) Mmap(addrHint, size uint64, prot, flags int, fd co.Fd, off co.Off) uint64 { addr, _ := k.U.Mmap(addrHint, size) if fd > 0 { fd2, _ := syscall.Dup(int(fd)) f := os.NewFile(uintptr(fd2), "") f.Seek(int64(off), 0) tmp := make([]byte, size) n, _ := f.Read(tmp) k.U.MemWrite(addr, tmp[:n]) syscall.Close(fd2) } return addr }
func (f *AzukiFile) Flush() fuse.Status { f.lock.Lock() newFd, err := syscall.Dup(int(f.File.Fd())) f.lock.Unlock() if err != nil { return fuse.ToStatus(err) } err = syscall.Close(newFd) return fuse.ToStatus(err) }
func (fd *netFD) dup() (f *os.File, err os.Error) { ns, e := syscall.Dup(fd.sysfd) if e != 0 { return nil, &OpError{"dup", fd.net, fd.laddr, os.Errno(e)} } // We want blocking mode for the new fd, hence the double negative. if e = syscall.SetNonblock(ns, false); e != 0 { return nil, &OpError{"setnonblock", fd.net, fd.laddr, os.Errno(e)} } return os.NewFile(ns, fd.sysfile.Name()), nil }
func (fd *netFD) dup() (f *os.File, err error) { ns, err := syscall.Dup(fd.sysfd) if err != nil { return nil, &OpError{"dup", fd.net, fd.laddr, err} } // We want blocking mode for the new fd, hence the double negative. if err = syscall.SetNonblock(ns, false); err != nil { return nil, &OpError{"setnonblock", fd.net, fd.laddr, err} } return os.NewFile(uintptr(ns), fd.sysfile.Name()), nil }
func newFileFD(f *os.File) (nfd *netFD, err error) { fd, errno := syscall.Dup(f.Fd()) if errno != 0 { return nil, os.NewSyscallError("dup", errno) } proto, errno := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_TYPE) if errno != 0 { return nil, os.NewSyscallError("getsockopt", errno) } family := syscall.AF_UNSPEC toAddr := sockaddrToTCP sa, _ := syscall.Getsockname(fd) switch sa.(type) { default: closesocket(fd) return nil, os.EINVAL case *syscall.SockaddrInet4: family = syscall.AF_INET if proto == syscall.SOCK_DGRAM { toAddr = sockaddrToUDP } else if proto == syscall.SOCK_RAW { toAddr = sockaddrToIP } case *syscall.SockaddrInet6: family = syscall.AF_INET6 if proto == syscall.SOCK_DGRAM { toAddr = sockaddrToUDP } else if proto == syscall.SOCK_RAW { toAddr = sockaddrToIP } case *syscall.SockaddrUnix: family = syscall.AF_UNIX toAddr = sockaddrToUnix if proto == syscall.SOCK_DGRAM { toAddr = sockaddrToUnixgram } else if proto == syscall.SOCK_SEQPACKET { toAddr = sockaddrToUnixpacket } } laddr := toAddr(sa) sa, _ = syscall.Getpeername(fd) raddr := toAddr(sa) if nfd, err = newFD(fd, family, proto, laddr.Network()); err != nil { return nil, err } nfd.setAddr(laddr, raddr) return nfd, nil }
func mmap(u U, a []uint64) uint64 { addr_hint, size, prot, flags, fd, off := a[0], a[1], a[2], a[3], int(int32(a[4])), int64(a[5]) prot, flags = flags, prot // ignore go error addr, _ := u.Mmap(addr_hint, size) if fd > 0 { fd2, _ := syscall.Dup(fd) f := os.NewFile(uintptr(fd2), "") f.Seek(off, 0) tmp := make([]byte, size) n, _ := f.Read(tmp) u.MemWrite(addr, tmp[:n]) } return uint64(addr) }
// Test double close func TestWriteFileDoubleClose(t *testing.T) { run.skipIfNoFUSE(t) out, err := os.Create(run.path("testdoubleclose")) assert.NoError(t, err) fd := out.Fd() fd1, err := syscall.Dup(int(fd)) assert.NoError(t, err) fd2, err := syscall.Dup(int(fd)) assert.NoError(t, err) // close one of the dups - should produce no error err = syscall.Close(fd1) assert.NoError(t, err) // write to the file buf := []byte("hello") n, err := out.Write(buf) assert.NoError(t, err) assert.Equal(t, 5, n) // close it err = out.Close() assert.NoError(t, err) // write to the other dup - should produce an error n, err = syscall.Write(fd2, buf) assert.Error(t, err, "input/output error") // close the dup - should produce an error err = syscall.Close(fd2) assert.Error(t, err, "input/output error") run.rm(t, "testdoubleclose") }
func (f *loopbackFile) Flush() fuse.Status { f.lock.Lock() // Since Flush() may be called for each dup'd fd, we don't // want to really close the file, we just want to flush. This // is achieved by closing a dup'd fd. newFd, err := syscall.Dup(int(f.File.Fd())) f.lock.Unlock() if err != nil { return fuse.ToStatus(err) } err = syscall.Close(newFd) return fuse.ToStatus(err) }
func (_entity *Entity) HashData(_hasher1 hasher.Hasher) (_hash []byte, _error Error) { if !_entity.IsRegular() { return nil, newError("dup", _entity.Path, -1, syscall.EBADF) } var _descriptor, _errno int _descriptor = _entity.Descriptor if _descriptor < 0 { return nil, newError("dup", _entity.Path, _entity.Descriptor, syscall.EBADF) } _descriptor, _errno = syscall.Dup(_descriptor) if _errno != 0 { return nil, newError("dup", _entity.Path, _entity.Descriptor, _errno) } defer syscall.Close(_descriptor) _, _errno = syscall.Seek(_descriptor, 0, 0 /* syscall.SEEK_SET */) if _errno != 0 { return nil, newError("seek", _entity.Path, _descriptor, _errno) } _hasher := _hasher1.Create() _buffer := make([]byte, _bufferSize) for { var _limit int _limit, _errno = syscall.Read(_descriptor, _buffer) if _errno != 0 { return nil, newError("read", _entity.Path, _descriptor, _errno) } if _limit == 0 { break } _error = hasher.HashUpdate(_hasher, _buffer[:_limit]) if _error != nil { return nil, newError("hash", _entity.Path, _descriptor, syscall.EIO) } } _hash, _error = hasher.HashFinalize(_hasher) if _error != nil { return nil, newError("hash", _entity.Path, _descriptor, syscall.EIO) } if _entity.Hashes == nil { _entity.Hashes = make(map[string][]byte, 1) } _entity.Hashes[_hasher1.Identifier()] = _hash return _hash, nil }
func (file *File) readdirnames(n int) (names []string, err error) { size := n if size <= 0 { size = 100 n = -1 } names = make([]string, 0, size) // Empty with room to grow. dirfd, err := syscall.Dup(file.fd) if err != nil { return names, err } dir, err := syscall.Fdopendir(dirfd) if err != nil { return names, err } defer syscall.Closedir(dir) var result *syscall.Dirent = nil entry := syscall.Dirent{} for n != 0 { status := syscall.Readdir_r(dir, &entry, &result) if status != 0 { return names, syscall.Errno(status) } if result == nil { break } if result.Ino == 0 { // File absent in directory continue } bytes := (*[10000]byte)(unsafe.Pointer(&result.Name[0])) name := string(bytes[0:clen(bytes[:])]) if name == "." || name == ".." { // considered "Useless names" by ParseDirent continue } names = append(names, name) n-- } return names, err }
func (fd *netFD) dup() (f *os.File, err error) { syscall.ForkLock.RLock() ns, err := syscall.Dup(fd.sysfd) if err != nil { syscall.ForkLock.RUnlock() return nil, &OpError{"dup", fd.net, fd.laddr, err} } syscall.CloseOnExec(ns) syscall.ForkLock.RUnlock() // We want blocking mode for the new fd, hence the double negative. // This also puts the old fd into blocking mode, meaning that // I/O will block the thread instead of letting us use the epoll server. // Everything will still work, just with more threads. if err = syscall.SetNonblock(ns, false); err != nil { return nil, &OpError{"setnonblock", fd.net, fd.laddr, err} } return os.NewFile(uintptr(ns), fd.name()), nil }