xref: /openbmc/gpioplus/src/gpioplus/internal/fd.cpp (revision 7ba248ad)
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