github.com/simpleiot/simpleiot@v0.18.3/test/fifo.go (about)

     1  //go:build !windows
     2  
     3  package test
     4  
     5  import (
     6  	"fmt"
     7  	"io"
     8  	"log"
     9  	"os"
    10  	"syscall"
    11  )
    12  
    13  // Fifo uses unix named pipes or fifos to emulate a UART type channel
    14  // the A side manages the channel, creates the fifos, cleans up, etc. The
    15  // B side only opens the fifos for read/write. Fifo implements the io.ReadWriteCloser interface.
    16  // The Close() on the B side does not do anything.
    17  type Fifo struct {
    18  	fread  io.ReadCloser
    19  	fwrite io.WriteCloser
    20  	a2b    string
    21  	b2a    string
    22  }
    23  
    24  // NewFifoA creates the A side interface. This must be called first to create the fifo files.
    25  func NewFifoA(name string) (*Fifo, error) {
    26  	ret := &Fifo{}
    27  	ret.a2b = name + "a2b"
    28  	ret.b2a = name + "b2a"
    29  
    30  	os.Remove(ret.a2b)
    31  	os.Remove(ret.b2a)
    32  
    33  	err := syscall.Mknod(ret.a2b, syscall.S_IFIFO|0666, 0)
    34  	if err != nil {
    35  		return nil, fmt.Errorf("Mknod a2b failed: %v", err)
    36  	}
    37  	err = syscall.Mknod(ret.b2a, syscall.S_IFIFO|0666, 0)
    38  	if err != nil {
    39  		return nil, fmt.Errorf("Mknod b2a failed: %v", err)
    40  	}
    41  
    42  	ret.fread, err = os.OpenFile(ret.b2a, os.O_RDWR, 0600)
    43  	if err != nil {
    44  		return nil, fmt.Errorf("Error opening read file: %v", err)
    45  	}
    46  
    47  	ret.fwrite, err = os.OpenFile(ret.a2b, os.O_RDWR, 0600)
    48  	if err != nil {
    49  		return nil, fmt.Errorf("Error opening write file: %v", err)
    50  	}
    51  
    52  	return ret, nil
    53  }
    54  
    55  // NewFifoB creates the B side interface. This must be called after NewFifoB
    56  func NewFifoB(name string) (*Fifo, error) {
    57  	ret := &Fifo{}
    58  
    59  	a2b := name + "a2b"
    60  	b2a := name + "b2a"
    61  
    62  	var err error
    63  
    64  	ret.fread, err = os.OpenFile(a2b, os.O_RDWR, 0600)
    65  	if err != nil {
    66  		return nil, fmt.Errorf("Error opening read file: %v", err)
    67  	}
    68  
    69  	ret.fwrite, err = os.OpenFile(b2a, os.O_RDWR, 0600)
    70  	if err != nil {
    71  		return nil, fmt.Errorf("Error opening write file: %v", err)
    72  	}
    73  
    74  	return ret, nil
    75  }
    76  
    77  func (f *Fifo) Read(b []byte) (int, error) {
    78  	return f.fread.Read(b)
    79  }
    80  
    81  func (f *Fifo) Write(b []byte) (int, error) {
    82  	return f.fwrite.Write(b)
    83  }
    84  
    85  // Close and delete fifos
    86  func (f *Fifo) Close() error {
    87  	if err := f.fwrite.Close(); err != nil {
    88  		log.Println("Error closing write file")
    89  	}
    90  
    91  	if err := f.fread.Close(); err != nil {
    92  		log.Println("Error closing read file")
    93  	}
    94  
    95  	if f.a2b != "" {
    96  		os.Remove(f.a2b)
    97  	}
    98  
    99  	if f.b2a != "" {
   100  		os.Remove(f.b2a)
   101  	}
   102  
   103  	return nil
   104  }