Skip to content

Instantly share code, notes, and snippets.

@alberts
Last active December 15, 2015 20:09
Show Gist options
  • Save alberts/5317022 to your computer and use it in GitHub Desktop.
Save alberts/5317022 to your computer and use it in GitHub Desktop.
package io
import (
"os"
"syscall"
)
func dup(oldFile *os.File, flag int) (int, error) {
// Temporary file descriptor for /dev/null.
devNull, err := os.OpenFile(os.DevNull, flag, 0)
if err != nil {
return -1, err
}
defer devNull.Close()
// Make a copy of the old file descriptor with a new file
// descriptor number.
newfd, err := syscall.Dup(int(oldFile.Fd()))
if err != nil {
return -1, err
}
// Make sure this new file descriptor is closed if this process
// execs another process, because the close-on-exec flag for the
// duplicate descriptor is off.
syscall.CloseOnExec(newfd)
// Replace old file descriptor with a copy of the file descriptor
// for /dev/null.
if err := syscall.Dup2(int(devNull.Fd()), int(oldFile.Fd())); err != nil {
syscall.Close(newfd)
return -1, err
}
syscall.CloseOnExec(int(oldFile.Fd()))
return newfd, nil
}
func DupReader(file *os.File) (*os.File, error) {
fd, err := dup(file, os.O_RDONLY)
if err != nil {
return nil, err
}
return os.NewFile(uintptr(fd), file.Name()), nil
}
// DupWriter duplicates the given file descriptor, changes the
// original file descriptor to point to /dev/null. Processes that do this
// on many file descriptors (as opposed to just, e.g., os.Stdout) must
// remember to close the returned WriteCloser.
func DupWriter(file *os.File) (*os.File, error) {
fd, err := dup(file, os.O_WRONLY)
if err != nil {
return nil, err
}
return os.NewFile(uintptr(fd), file.Name()), nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment