xref: /openbmc/gpioplus/src/gpioplus/internal/fd.cpp (revision 7ba248ad685c8a2029f9cfdbae98d161e9664a3b)
1  #include <fcntl.h>
2  
3  #include <gpioplus/internal/fd.hpp>
4  
5  #include <cerrno>
6  #include <cstdlib>
7  #include <system_error>
8  #include <utility>
9  
10  namespace gpioplus
11  {
12  namespace internal
13  {
14  
Fd(const char * pathname,int flags,const Sys * sys)15  Fd::Fd(const char* pathname, int flags, const Sys* sys) :
16      sys(sys), fd(sys->open(pathname, flags))
17  {
18      if (fd < 0)
19      {
20          throw std::system_error(errno, std::generic_category(), "Opening FD");
21      }
22  }
23  
dup(int oldfd,const Sys * sys)24  static int dup(int oldfd, const Sys* sys)
25  {
26      int fd = sys->dup(oldfd);
27      if (fd < 0)
28      {
29          throw std::system_error(errno, std::generic_category(), "Duping FD");
30      }
31      return fd;
32  }
33  
Fd(int fd,const Sys * sys)34  Fd::Fd(int fd, const Sys* sys) : sys(sys), fd(dup(fd, sys)) {}
35  
Fd(int fd,std::false_type,const Sys * sys)36  Fd::Fd(int fd, std::false_type, const Sys* sys) : sys(sys), fd(fd) {}
37  
~Fd()38  Fd::~Fd()
39  {
40      try
41      {
42          reset();
43      }
44      catch (...)
45      {
46          std::abort();
47      }
48  }
49  
Fd(const Fd & other)50  Fd::Fd(const Fd& other) : sys(other.sys), fd(dup(other.fd, sys)) {}
51  
operator =(const Fd & other)52  Fd& Fd::operator=(const Fd& other)
53  {
54      if (this != &other)
55      {
56          reset();
57          sys = other.sys;
58          fd = dup(other.fd, sys);
59      }
60      return *this;
61  }
62  
Fd(Fd && other)63  Fd::Fd(Fd&& other) : sys(other.sys), fd(std::move(other.fd))
64  {
65      other.fd = -1;
66  }
67  
operator =(Fd && other)68  Fd& Fd::operator=(Fd&& other)
69  {
70      if (this != &other)
71      {
72          reset();
73          sys = other.sys;
74          fd = std::move(other.fd);
75          other.fd = -1;
76      }
77      return *this;
78  }
79  
operator *() const80  int Fd::operator*() const
81  {
82      return fd;
83  }
84  
getSys() const85  const Sys* Fd::getSys() const
86  {
87      return sys;
88  }
89  
setBlocking(bool enabled) const90  void Fd::setBlocking(bool enabled) const
91  {
92      if (enabled)
93      {
94          setFlags(getFlags() & ~O_NONBLOCK);
95      }
96      else
97      {
98          setFlags(getFlags() | O_NONBLOCK);
99      }
100  }
101  
setFlags(int flags) const102  void Fd::setFlags(int flags) const
103  {
104      int r = sys->fcntl_setfl(fd, flags);
105      if (r == -1)
106      {
107          throw std::system_error(errno, std::generic_category(), "fcntl_setfl");
108      }
109  }
110  
getFlags() const111  int Fd::getFlags() const
112  {
113      int flags = sys->fcntl_getfl(fd);
114      if (flags == -1)
115      {
116          throw std::system_error(errno, std::generic_category(), "fcntl_getfl");
117      }
118      return flags;
119  }
120  
reset()121  void Fd::reset()
122  {
123      if (fd < 0)
124      {
125          return;
126      }
127  
128      int ret = sys->close(fd);
129      fd = -1;
130      if (ret != 0)
131      {
132          throw std::system_error(errno, std::generic_category(), "Closing FD");
133      }
134  }
135  
136  } // namespace internal
137  } // namespace gpioplus
138