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