Пример #1
0
func (fifo *FIFOReader) Run(dest chan<- Message) {
	var err error

	syscall.Mkfifo(fifo.Source, 0644)
	fifo.fi_des, err = os.OpenFile(fifo.Source, os.O_RDONLY, 0644)
	if err != nil {
		fifo.errchan <- &InputError{fifo.Driver, fifo.Id, "FIFO " + fifo.Source, err}
		return
	}

	data := make(chan string, 100)
	defer fifo.fi_des.Close()

	go reader_to_channel(fifo.fi_des, data)

	for {
		select {
		case line := <-data:
			dest <- packmsg(fifo.Id, syslog5424.CreateMessage(fifo.AppName, *fifo.prio, line))

		case <-fifo.end:
			return
		}
	}
}
Пример #2
0
func PreparePipe() string {

	path := "/tmp/" + RandStringBytes(10)

	pipeExists := false
	fileInfo, err := os.Stat(path)

	if err == nil {
		if (fileInfo.Mode() & os.ModeNamedPipe) > 0 {
			pipeExists = true
		} else {
			log.Printf("%d != %d\n", os.ModeNamedPipe, fileInfo.Mode())
			panic(path + " exists, but it's not a named pipe (FIFO)")
		}
	}

	// Try to create pipe if needed
	if !pipeExists {
		err := syscall.Mkfifo(path, 0666)
		if err != nil {
			panic(err.Error())
		}
	}
	return path
}
Пример #3
0
// Create a signaling named pipe and feed offers from it into
// makePeerConnectionFromOffer.
func receiveSignalsFIFO(filename string, config *webrtc.Configuration) error {
	err := syscall.Mkfifo(filename, 0600)
	if err != nil {
		if err.(syscall.Errno) != syscall.EEXIST {
			return err
		}
	}
	signalFile, err := os.OpenFile(filename, os.O_RDONLY, 0600)
	if err != nil {
		return err
	}
	defer signalFile.Close()

	s := bufio.NewScanner(signalFile)
	for s.Scan() {
		msg := s.Text()
		sdp := webrtc.DeserializeSessionDescription(msg)
		if sdp == nil {
			log.Printf("ignoring invalid signal message %+q", msg)
			continue
		}

		pc, err := makePeerConnectionFromOffer(sdp, config)
		if err != nil {
			log.Printf("makePeerConnectionFromOffer: %s", err)
			continue
		}
		// Write offer to log for manual signaling.
		log.Printf("----------------")
		fmt.Fprintln(logFile, pc.LocalDescription().Serialize())
		log.Printf("----------------")
	}
	return s.Err()
}
func NewContainerProcess(cs *ContainerdSuite, bundle *Bundle, cid, pid string) (c *containerProcess, err error) {
	c = &containerProcess{
		containerId: cid,
		pid:         "init",
		bundle:      bundle,
		eventsCh:    make(chan *types.Event, 8),
		cs:          cs,
		hasExited:   false,
	}

	for name, path := range map[string]*string{
		"stdin":  &c.io.stdin,
		"stdout": &c.io.stdout,
		"stderr": &c.io.stderr,
	} {
		*path = filepath.Join(bundle.Path, "io", cid+"-"+pid+"-"+name)
		if err = syscall.Mkfifo(*path, 0755); err != nil && !os.IsExist(err) {
			return nil, err
		}
	}

	if err = c.openIo(); err != nil {
		return nil, err
	}

	return c, nil
}
Пример #5
0
func Open() (*Fifo, error) {
	var pipe Fifo
	pipe.path = defaultPath
	if config.Has("global.fifo") {
		pipe.path, _ = config.String("config.fifo")
	}

	if _, err := os.Stat(pipe.path); err == nil {
		err = os.Remove(pipe.path)
		if err != nil {
			return nil, err
		}
	}

	if err := syscall.Mkfifo(pipe.path, 0777); err != nil {
		return nil, err
	}

	fd, err := syscall.Open(pipe.path, syscall.O_RDONLY|syscall.O_NONBLOCK, 0777)
	if err != nil {
		return nil, err
	}

	pipe.fd = fdReader(fd)
	pipe.rd = bufio.NewReader(pipe.fd)
	pipe.cmds = make([]Command, 0, 5)
	return &pipe, nil
}
Пример #6
0
// openGStreamer runs a gstreamer subcommand and pipes it's output.
func openGStreamer() (io.Reader, error) {
	fifo := "fifo" + path.Base(*flagSrc)
	if err := syscall.Mkfifo(fifo, 0666); err != nil {
		fmt.Fprintln(os.Stderr, "mkfifo", fifo, ":", err)
	}

	bin := "gst-launch-1.0"
	args := fmt.Sprintf(`v4l2src device=%s ! video/x-raw,framerate=%d/1,width=%d,height=%d ! jpegenc quality=%d ! filesink buffer-size=0 location=%v`, *flagSrc, *flagFPS, *flagWidth, *flagHeight, *flagQuality, fifo)

	fmt.Println(bin, args)
	cmd := exec.Command(bin, strings.Split(args, " ")...)

	stderr, err := cmd.StderrPipe()
	if err != nil {
		return nil, err
	}
	go io.Copy(os.Stderr, stderr)

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}
	go io.Copy(os.Stderr, stdout)

	if err := cmd.Start(); err != nil {
		return nil, err
	}

	f, err := os.Open(fifo)
	if err != nil {
		return nil, err
	}
	return f, nil
}
Пример #7
0
func mkfifo(t *testing.T) {
	_ = syscall.Unlink(fifo)
	err := syscall.Mkfifo(fifo, 0666)
	if err != nil {
		t.Fatal("mkfifo:", err)
	}
}
Пример #8
0
// createFDProxies creates pipes at /dev/stdout and /dev/stderr and copies data
// written to them to the job's stdout and stderr streams respectively.
//
// This is necessary (rather than just symlinking those paths to /proc/self/fd/{1,2})
// because the standard streams are sockets, and calling open(2) on a socket
// leads to an ENXIO error (see http://marc.info/?l=ast-users&m=120978595414993).
func createFDProxies(cmd *exec.Cmd) error {
	for path, dst := range map[string]*os.File{
		"/dev/stdout": cmd.Stdout.(*os.File),
		"/dev/stderr": cmd.Stderr.(*os.File),
	} {
		os.Remove(path)
		if err := syscall.Mkfifo(path, 0666); err != nil {
			return err
		}
		pipe, err := os.OpenFile(path, os.O_RDWR, os.ModeNamedPipe)
		if err != nil {
			return err
		}
		go func(dst *os.File) {
			defer pipe.Close()
			for {
				// copy data from the pipe to dst using splice(2) (rather than io.Copy)
				// to avoid a needless copy through user space
				n, err := syscall.Splice(int(pipe.Fd()), nil, int(dst.Fd()), nil, 65535, 0)
				if err != nil || n == 0 {
					return
				}
			}
		}(dst)
	}
	return nil
}
Пример #9
0
func (fifo *FIFOReader) Run(dest chan<- Message, errchan chan<- error) {
	var err error
	fifo.end = make(chan bool, 1)
	fifo.prio, err = message.PriorityDecode(fifo.Priority)
	if err != nil {
		errchan <- &InputError{fifo.Driver, fifo.Id, "Priority " + fifo.Priority, err}
		return
	}

	syscall.Mkfifo(fifo.Source, 0644)
	fifo.fi_des, err = os.OpenFile(fifo.Source, os.O_RDONLY, 0644)
	if err != nil {
		errchan <- &InputError{fifo.Driver, fifo.Id, "FIFO " + fifo.Source, err}
		return
	}

	data := make(chan string)
	defer fifo.fi_des.Close()

	go reader_to_channel(fifo.fi_des, data)

	for {
		select {
		case line := <-data:
			dest <- packmsg(fifo.Id, *message.CreateMessage(line, fifo.AppName, fifo.prio))

		case <-fifo.end:
			return
		}
	}
}
Пример #10
0
func mkFifo(t *testing.T, i int) {
	name := fifoName(i)
	syscall.Unlink(name)
	err := syscall.Mkfifo(name, 0666)
	if err != nil {
		t.Fatalf("mkfifo %s: %v", name, err)
	}
}
Пример #11
0
func getExitPipe(path string) (*os.File, error) {
	if err := syscall.Mkfifo(path, 0755); err != nil && !os.IsExist(err) {
		return nil, err
	}
	// add NONBLOCK in case the other side has already closed or else
	// this function would never return
	return os.OpenFile(path, syscall.O_RDONLY|syscall.O_NONBLOCK, 0)
}
Пример #12
0
func (inode *SpecialInode) make(name string) error {
	if inode.Mode&syscall.S_IFBLK != 0 || inode.Mode&syscall.S_IFCHR != 0 {
		return syscall.Mknod(name, uint32(inode.Mode), int(inode.Rdev))
	} else if inode.Mode&syscall.S_IFIFO != 0 {
		return syscall.Mkfifo(name, uint32(inode.Mode))
	} else {
		return errors.New("unsupported mode")
	}
}
Пример #13
0
func (p *process) mkfifos() error {
	for _, pipe := range []string{p.stdin, p.stdout, p.stderr, p.winsz, p.exit} {
		if err := syscall.Mkfifo(pipe, 0); err != nil {
			return err
		}
	}

	return nil
}
Пример #14
0
func TempFifo(t *testing.T) *Fifo {

	name := os.TempDir() + "/fifo2kinesis-" + RandomString(8) + ".pipe"
	err := syscall.Mkfifo(name, 0600)
	if err != nil {
		t.Errorf("error creating fifo: %s", err)
	}

	return &Fifo{name}
}
Пример #15
0
func (s *BuildTestSuite) TestBuildFailsForUnknownType(c *C) {
	sourceDir := makeExampleSnapSourceDir(c, `name: hello
version: 1.0.1
`)
	err := syscall.Mkfifo(filepath.Join(sourceDir, "fifo"), 0644)
	c.Assert(err, IsNil)

	_, err = BuildSquashfsSnap(sourceDir, "")
	c.Assert(err, ErrorMatches, "can not handle type of file .*")
}
Пример #16
0
func (s *ClickDebTestSuite) TestTarCreateUnknownTypeFailsWithError(c *C) {

	builddir := c.MkDir()
	err := syscall.Mkfifo(filepath.Join(builddir, "fifo"), 0644)
	c.Assert(err, IsNil)

	tempdir := c.MkDir()
	tarfile := filepath.Join(tempdir, "data.tar.xz")

	err = tarCreate(tarfile, builddir, nil)
	c.Assert(err, ErrorMatches, "unsupported file type for.*")
}
Пример #17
0
func (l *LinuxFactory) Create(id string, config *configs.Config) (Container, error) {
	if l.Root == "" {
		return nil, newGenericError(fmt.Errorf("invalid root"), ConfigInvalid)
	}
	if err := l.validateID(id); err != nil {
		return nil, err
	}
	if err := l.Validator.Validate(config); err != nil {
		return nil, newGenericError(err, ConfigInvalid)
	}
	uid, err := config.HostUID()
	if err != nil {
		return nil, newGenericError(err, SystemError)
	}
	gid, err := config.HostGID()
	if err != nil {
		return nil, newGenericError(err, SystemError)
	}
	containerRoot := filepath.Join(l.Root, id)
	if _, err := os.Stat(containerRoot); err == nil {
		return nil, newGenericError(fmt.Errorf("container with id exists: %v", id), IdInUse)
	} else if !os.IsNotExist(err) {
		return nil, newGenericError(err, SystemError)
	}
	if err := os.MkdirAll(containerRoot, 0711); err != nil {
		return nil, newGenericError(err, SystemError)
	}
	if err := os.Chown(containerRoot, uid, gid); err != nil {
		return nil, newGenericError(err, SystemError)
	}
	fifoName := filepath.Join(containerRoot, execFifoFilename)
	oldMask := syscall.Umask(0000)
	if err := syscall.Mkfifo(fifoName, 0622); err != nil {
		syscall.Umask(oldMask)
		return nil, newGenericError(err, SystemError)
	}
	syscall.Umask(oldMask)
	if err := os.Chown(fifoName, uid, gid); err != nil {
		return nil, newGenericError(err, SystemError)
	}
	c := &linuxContainer{
		id:            id,
		root:          containerRoot,
		config:        config,
		initPath:      l.InitPath,
		initArgs:      l.InitArgs,
		criuPath:      l.CriuPath,
		cgroupManager: l.NewCgroupsManager(config.Cgroups, nil),
	}
	c.state = &stoppedState{c: c}
	return c, nil
}
Пример #18
0
func extractArchive() int {
	archive := tar.NewReader(input)

	for {
		hdr, err := archive.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Fprintf(os.Stderr, "An error occured while reading archive: %v\n", err)
			return 1
		}

		if verbose {
			fmt.Fprintf(os.Stderr, "%s\n", hdr.Name)
		}

		switch hdr.Typeflag {
		case tar.TypeReg, tar.TypeRegA:
			var f *os.File
			if f, err = os.OpenFile(hdr.Name, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, os.FileMode(hdr.Mode)); err == nil {
				io.Copy(f, archive)
				f.Close()
				err = os.Chtimes(hdr.Name, hdr.ModTime, hdr.ModTime)
			}
		case tar.TypeDir:
			err = os.Mkdir(hdr.Name, os.FileMode(hdr.Mode))
			if err != nil {
				patherr, ok := err.(*os.PathError)
				if ok && patherr.Err == syscall.EEXIST {
					err = nil
				}
			}
		case tar.TypeSymlink:
			err = os.Link(hdr.Name, hdr.Linkname)
		case tar.TypeFifo:
			err = syscall.Mkfifo(hdr.Name, uint32(hdr.Mode))
		case tar.TypeChar:
			err = errors.New("character devices unsupported")
			err = syscall.Mknod(hdr.Name, syscall.S_IFCHR, makedev(hdr.Devmajor, hdr.Devminor))
		case tar.TypeBlock:
			err = errors.New("block devices unsupported")
			err = syscall.Mknod(hdr.Name, syscall.S_IFBLK, makedev(hdr.Devmajor, hdr.Devminor))
		}

		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		}
	}

	return 0
}
Пример #19
0
func (s *cpSuite) TestCopySpecialFileSimple(c *C) {
	src := filepath.Join(c.MkDir(), "fifo")
	err := syscall.Mkfifo(src, 0644)
	c.Assert(err, IsNil)
	dst := filepath.Join(c.MkDir(), "copied-fifo")

	err = CopySpecialFile(src, dst)
	c.Assert(err, IsNil)

	st, err := os.Stat(dst)
	c.Assert(err, IsNil)
	c.Assert((st.Mode() & os.ModeNamedPipe), Equals, os.ModeNamedPipe)
}
Пример #20
0
// createFakeDevices creates regular files or pipes in place of the char devices used
// in a full VM
func createFakeDevices() error {
	var err error
	// create control channel
	path := fmt.Sprintf("%s/ttyS0", pathPrefix)
	err = syscall.Mkfifo(path+"s", uint32(backchannelMode))
	if err != nil {
		detail := fmt.Sprintf("failed to create fifo pipe %ss for com0: %s", path, err)
		return errors.New(detail)
	}
	err = syscall.Mkfifo(path+"c", uint32(backchannelMode))
	if err != nil {
		detail := fmt.Sprintf("failed to create fifo pipe %sc for com0: %s", path, err)
		return errors.New(detail)
	}
	log.Debugf("created %s/ttyS0{c,s} as raw conn pipes", pathPrefix)

	// others are non-interactive
	for i := 1; i < 3; i++ {
		path = fmt.Sprintf("%s/ttyS%d", pathPrefix, i)
		_, err = os.Create(path)
		if err != nil {
			detail := fmt.Sprintf("failed to create %s for com%d: %s", path, i+1, err)
			return errors.New(detail)
		}
		log.Debugf("created %s as persistent log destinations", path)
	}

	// make an access to urandom
	path = fmt.Sprintf("%s/urandom", pathPrefix)
	err = os.Symlink("/dev/urandom", path)
	if err != nil {
		detail := fmt.Sprintf("failed to create urandom access: %s", err)
		return errors.New(detail)
	}

	return nil
}
Пример #21
0
// Attempts to create the FIFO automatically. Can return an error if it failed,
// for instance if permission failures occur (no permission to write to path).
func (m *Mplayer) CreateFifo() (err error) {
	err = m.FifoOk()
	if err != nil {
		err = syscall.Mkfifo(m.PathFifo, 0644)
		if err != nil {
			log.Printf("Could not create FIFO: `%s'", m.PathFifo)
			return err
		} else {
			log.Printf("FIFO created: `%s'", m.PathFifo)
			return nil
		}
	}

	return err
}
Пример #22
0
func attachStdio(stdins, stdout, stderr *string) error {
	dir, err := ioutil.TempDir("", "ctr-")
	if err != nil {
		return err
	}
	for _, p := range []struct {
		path string
		flag int
		done func(f *os.File)
	}{
		{
			path: filepath.Join(dir, "stdin"),
			flag: syscall.O_RDWR,
			done: func(f *os.File) {
				*stdins = filepath.Join(dir, "stdin")
				stdin = f
			},
		},
		{
			path: filepath.Join(dir, "stdout"),
			flag: syscall.O_RDWR,
			done: func(f *os.File) {
				*stdout = filepath.Join(dir, "stdout")
				go io.Copy(os.Stdout, f)
			},
		},
		{
			path: filepath.Join(dir, "stderr"),
			flag: syscall.O_RDWR,
			done: func(f *os.File) {
				*stderr = filepath.Join(dir, "stderr")
				go io.Copy(os.Stderr, f)
			},
		},
	} {
		if err := syscall.Mkfifo(p.path, 0755); err != nil {
			return fmt.Errorf("mkfifo: %s %v", p.path, err)
		}
		f, err := os.OpenFile(p.path, p.flag, 0)
		if err != nil {
			return fmt.Errorf("open: %s %v", p.path, err)
		}
		p.done(f)
	}
	return nil
}
Пример #23
0
func (s *cpSuite) TestCopySpecialFileSimple(c *C) {
	sync := testutil.MockCommand(c, "sync", "")
	defer sync.Restore()

	src := filepath.Join(c.MkDir(), "fifo")
	err := syscall.Mkfifo(src, 0644)
	c.Assert(err, IsNil)
	dir := c.MkDir()
	dst := filepath.Join(dir, "copied-fifo")

	err = CopySpecialFile(src, dst)
	c.Assert(err, IsNil)

	st, err := os.Stat(dst)
	c.Assert(err, IsNil)
	c.Check((st.Mode() & os.ModeNamedPipe), Equals, os.ModeNamedPipe)
	c.Check(sync.Calls(), DeepEquals, [][]string{{"sync", dir}})
}
Пример #24
0
func generate(s *source) {
	fmt.Println("generate")
	outfilename := s.filename + "." + outputext
	basename := path.Base(outfilename)
	outfilename = path.Join(outputdir, basename)
	fifos := make([]string, 0, bands)
	for i := uint(0); i < bands; i++ {
		// make a fifo
		fifoname := path.Join(tmpdir, basename+strconv.Uitoa(i))
		fmt.Fprintf(os.Stderr, "making fifo %d\n", i)
		err := os.RemoveAll(fifoname)
		if err != nil {
			panic(err)
		}
		errno := syscall.Mkfifo(fifoname, 0600)
		if errno != 0 {
			panic(os.NewSyscallError("Mkfifo", errno))
		}
		fifos = append(fifos, fifoname)
		// make a goroutine to read from the channel with processinputband and write to the fifo
		// open the fifo inside the goroutine so the call to open doesn't block the main thread
		go processinputband(s, fifoname, i, openinputband(i))
	}

	// start sox with all the fifos
	// bands is number of files to read from
	// +1 output file
	// +1 for "-m"
	// +1 for "sox" at start
	opts := make([]string, 0, uint(len(soxformatopts))+bands+3)
	opts = append(opts, "sox", "-m")
	for _, f := range fifos {
		opts = append(opts, soxformatopts...)
		opts = append(opts, f)
	}
	opts = append(opts, outfilename)
	cmd := startsox(soxpath, opts, false)
	msg, err := cmd.Wait(0)
	if err != nil {
		panic(err)
	}
	fmt.Println(msg.String())
}
Пример #25
0
func createStdio() (s stdio, err error) {
	tmp, err := ioutil.TempDir("", "ctr-")
	if err != nil {
		return s, err
	}
	// create fifo's for the process
	for name, fd := range map[string]*string{
		"stdin":  &s.stdin,
		"stdout": &s.stdout,
		"stderr": &s.stderr,
	} {
		path := filepath.Join(tmp, name)
		if err := syscall.Mkfifo(path, 0755); err != nil && !os.IsExist(err) {
			return s, err
		}
		*fd = path
	}
	return s, nil
}
Пример #26
0
func (s *Sampler) Init() {
	s.outOfRangeErrors = 0
	s.histogram = hdrhistogram.New(s.Min, s.Max, s.Sigint)

	// we need to know the bucket Quantiles, for this we just add every possible value to the histogram..
	for i := s.Min; i < s.Max; i++ {
		s.histogram.RecordValue(i)
	}

	//We then extract hdrhistograms own bucket range
	distribution := s.histogram.CumulativeDistribution()
	s.bucketQuantiles = make([]float64, 0, len(distribution))

	//and save it for later use
	for _, d := range distribution {
		s.bucketQuantiles = append(s.bucketQuantiles, d.Quantile)
	}

	s.histogram.Reset()

	// Pipe stuff
	// Check if pipe already exists
	pipeExists := false
	fileInfo, err := os.Stat(s.Path)

	if err == nil {
		if (fileInfo.Mode() & os.ModeNamedPipe) > 0 {
			pipeExists = true
		} else {
			fmt.Printf("%d != %d\n", os.ModeNamedPipe, fileInfo.Mode())
			panic(s.Path + " exists, but it's not a named pipe (FIFO)")
		}
	}

	// Try to create pipe if needed
	if !pipeExists {
		err := syscall.Mkfifo(s.Path, 0666)
		if err != nil {
			panic(err.Error())
		}
	}

}
Пример #27
0
func (wm *WriterManager) newNamedPipe(id int, prefix string, suffix string) (*os.File, error) {
	//filename := wm.tmpDir + "/" + prefix + "_" + wm.pid + "_" + strconv.Itoa(wm.startTime.Nanosecond()) + suffix
	filename := wm.tmpDir + "/" + prefix + "_" + wm.pid + "_" + strconv.Itoa(id) + "_" + strconv.FormatInt(time.Since(*wm.startTime).Nanoseconds(), 10) + suffix

	err := syscall.Mkfifo(filename, 0600)
	if err != nil {
		return nil, err
	}
	writeComment("")
	writeNamedPipeName(filename)

	file, err := os.OpenFile(filename, os.O_WRONLY, os.ModeNamedPipe)
	_, _ = os.Stdout.Write([]byte("NewFifo \n"))
	if err != nil {
		log.Fatal(err)
		return nil, err
	}
	_, _ = os.Stdout.Write([]byte("NewFifo \n"))
	return file, nil
}
Пример #28
0
func (s *Server) build_fifo() error {
	for {
		err := syscall.Mkfifo(fmt.Sprint(s.path, "/in"), syscall.S_IRWXU)

		if err != nil {
			if os.IsExist(err) {
				err := os.Remove(fmt.Sprint(s.path, "/in"))
				if err != nil {
					return err
				}
				continue
			}
			return err
		}

		break
	}

	return nil
}
Пример #29
0
// Creates the pipe if it does not exist, and then opens it. If the file exists, it ensures that the existing file is a pipe. Returns the file if it could be successfully opened.
func OpenPipe(pipename string) (*os.File, error) {
	if !osutil.FileExists(pipename) {
		syscall.Mkfifo(pipename, 0644)
	}

	finfo, err := os.Stat(pipename)
	if err != nil {
		return nil, errors.New(fmt.Sprint("Error stating pipe ", pipename, ": ", err))
	}

	if finfo.Mode()&os.ModeNamedPipe != os.ModeNamedPipe {
		return nil, errors.New(fmt.Sprint("Specified pipe file ", pipename, " is not a named pipe type file! Remove it to have a pipe file created in it's place."))
	}

	file, err := os.OpenFile(pipename, os.O_RDWR, 0644)
	if err != nil {
		return nil, errors.New(fmt.Sprint("Error opening pipe ", pipename, ": ", err))
	}
	return file, nil
}
Пример #30
0
func Listen(path string) (*Listener, error) {
	rname := ".ftrig-" + randomName()
	tmpfifo := filepath.Join(path, rname)
	err := syscall.Mkfifo(tmpfifo, syscall.S_IRUSR|syscall.S_IWUSR|syscall.S_IWGRP|syscall.S_IWOTH)
	if err != nil {
		return nil, err
	}

	fd, fdw, name := C.int(0), C.int(0), filepath.Join(path, rname[1:])
	fd, err = C.open_read(C.CString(tmpfifo))
	if fd == -1 {
		goto err1
	}

	fdw, err = C.open_write(C.CString(tmpfifo))
	if fd == -1 {
		C.fd_close(fd)
		goto err1
	}

	err = os.Rename(tmpfifo, name)
	if err != nil {
		C.fd_close(fdw)
		C.fd_close(fd)
		goto err1
	}

	err = syscall.SetNonblock(int(fd), false)
	if err != nil {
		goto err1
	}

	return subscribe(name, uintptr(fd), uintptr(fdw))
err1:
	os.Remove(tmpfifo)
	if errno, ok := err.(syscall.Errno); ok {
		return nil, errno
	}
	return nil, fmt.Errorf("unknown error opening fifo at %q", tmpfifo)
}