libzypp 17.37.17
IOTools.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
12
13#include <errno.h>
14#include <fcntl.h>
15#include <iostream>
16#include <glib.h>
17
22
23namespace zypp::io {
24
25 BlockingMode setFILEBlocking (FILE * file, bool mode )
26 {
27 if ( !file ) return BlockingMode::FailedToSetMode;
28 return setFDBlocking( ::fileno( file ), mode );
29 }
30
31 BlockingMode setFDBlocking(int fd, bool mode)
32 {
33 if ( fd == -1 )
34 { ERR << strerror( errno ) << std::endl; return BlockingMode::FailedToSetMode; }
35
36 int flags = zyppng::eintrSafeCall( ::fcntl, fd, F_GETFL );
37
38 if ( flags == -1 )
39 { ERR << strerror( errno ) << std::endl; return BlockingMode::FailedToSetMode; }
40
41 BlockingMode oldMode = ( flags & O_NONBLOCK ) == O_NONBLOCK ? BlockingMode::WasNonBlocking : BlockingMode::WasBlocking;
42 if ( !mode )
43 flags = flags | O_NONBLOCK;
44 else if ( flags & O_NONBLOCK )
45 flags = flags ^ O_NONBLOCK;
46
47 flags = zyppng::eintrSafeCall( ::fcntl, fd,F_SETFL,flags );
48
49 if ( flags == -1 )
50 { ERR << strerror(errno) << std::endl; return BlockingMode::FailedToSetMode; }
51
52 return oldMode;
53 }
54
55 bool writeAll(int fd, void *buf, size_t size)
56 {
57 char *tmpBuf = static_cast<char*>(buf);
58
59 size_t written = 0;
60 while ( written < size ) {
61 const auto res = zyppng::eintrSafeCall( ::write, fd, tmpBuf+written, size-written );
62 if ( res < 0 ) // error
63 return false;
64 written += res;
65 }
66 return true;
67 }
68
69 ReadAllResult readAll (int fd, void *buf, size_t size )
70 {
71 char *tmpBuf = static_cast<char*>(buf);
72 size_t read = 0;
73 while ( read != size ) {
74 const auto r = zyppng::eintrSafeCall( ::read, fd, tmpBuf+read, size - read );
75 if ( r == 0 )
76 return ReadAllResult::Eof;
77 if ( r < 0 )
79
80 read += r;
81 }
82 return ReadAllResult::Ok;
83 }
84
85 std::pair<ReceiveUpToResult, std::string> receiveUpto(FILE *file, char c, timeout_type timeout, bool failOnUnblockError )
86 {
87 FILE * inputfile = file;
88 if ( !file )
89 return std::make_pair( ReceiveUpToResult::Error, std::string() );
90
91 int inputfileFd = ::fileno( inputfile );
92
93 size_t linebuffer_size = 0;
95
96 const auto prevMode = setFILEBlocking( file, false );
97 if ( prevMode == BlockingMode::FailedToSetMode && failOnUnblockError )
98 return std::make_pair( ReceiveUpToResult::Error, std::string() );
99
100 // reset the blocking mode when we are done
101 zypp::OnScopeExit resetMode([ prevMode, fd = file ]( ){
102 if ( prevMode == BlockingMode::WasBlocking )
103 setFILEBlocking( fd, true );
104 });
105
106 bool haveTimeout = (timeout != no_timeout);
107 int remainingTimeout = static_cast<int>( timeout );
108 zypp::AutoDispose<GTimer *> timer( nullptr );
109 if ( haveTimeout )
110 timer = zypp::AutoDispose<GTimer *>( g_timer_new(), &g_free );
111
112 std::string line;
113 do
114 {
115 /* Watch inputFile to see when it has input. */
116
117 GPollFD fd;
118 fd.fd = inputfileFd;
119 fd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
120 fd.revents = 0;
121
122 if ( timer )
123 g_timer_start( timer );
124
125 clearerr( inputfile );
126
127 int retval = zyppng::eintrSafeCall( g_poll, &fd, 1, remainingTimeout );
128 if ( retval == -1 )
129 {
130 ERR << "select error: " << zyppng::strerr_cxx() << std::endl;
131 return std::make_pair( ReceiveUpToResult::Error, std::string() );
132 }
133 else if ( retval )
134 {
135 // Data is available now.
136 ssize_t nread = zyppng::eintrSafeCallEx( ::getdelim, [&](){ clearerr( inputfile ); }, &linebuf.value(), &linebuffer_size, c, inputfile );
137 if ( nread == -1 ) {
138 if ( ::feof( inputfile ) ) {
139 return std::make_pair( ReceiveUpToResult::EndOfFile, std::move(line) );
140 }
141 if ( errno != EAGAIN && ( ::ferror( inputfile ) || errno != 0 ) ) {
142 if ( errno ) ERR << "getdelim error: " << zyppng::strerr_cxx() << std::endl;
143 else ERR << "Unknown getdelim error." << std::endl;
144 return std::make_pair( ReceiveUpToResult::Error, std::string() );
145 }
146 }
147 else
148 {
149 if ( nread > 0 )
150 line += std::string( linebuf, nread );
151
152 if ( ! ::ferror( inputfile ) || ::feof( inputfile ) ) {
153 return std::make_pair( ReceiveUpToResult::Success, std::move(line) ); // complete line
154 }
155 }
156 }
157
158 // we timed out, or were interrupted for some reason
159 // check if we can wait more
160 if ( timer ) {
161 remainingTimeout -= g_timer_elapsed( timer, nullptr ) * 1000;
162 if ( remainingTimeout <= 0 )
163 return std::make_pair( ReceiveUpToResult::Timeout, std::move(line) );
164 }
165 } while ( true );
166 }
167
170
171 std::vector<char> peek_data_fd( FILE *fd, off_t offset, size_t count )
172 {
173 if ( !fd )
174 return {};
175
176 fflush( fd );
177
178 std::vector<char> data( count + 1 , '\0' );
179
180 ssize_t l = zyppng::eintrSafeCall( pread, fileno( fd ), data.data(), count, offset );
181 if (l == -1)
182 return {};
183
184 return data;
185 }
186
187}
struct _GPollFD GPollFD
Definition ZYppImpl.h:26
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition AutoDispose.h:95
reference value() const
Reference to the Tp object.
~TimeoutException() noexcept override
Dtor.
Definition IOTools.cc:168
ReadAllResult
Definition IOTools.h:44
bool writeAll(int fd, void *buf, size_t size)
Definition IOTools.cc:55
BlockingMode setFILEBlocking(FILE *file, bool mode)
Enables or disabled non blocking mode on a file descriptor.
Definition IOTools.cc:25
std::pair< ReceiveUpToResult, std::string > receiveUpto(FILE *file, char c, timeout_type timeout, bool failOnUnblockError)
Definition IOTools.cc:85
BlockingMode
Definition IOTools.h:22
@ WasBlocking
FD was blocking before.
Definition IOTools.h:24
@ FailedToSetMode
Failed to block or unblock the fd.
Definition IOTools.h:23
@ WasNonBlocking
FD was non blocking before.
Definition IOTools.h:25
@ Timeout
Definition IOTools.h:72
@ Success
Definition IOTools.h:71
@ Error
Definition IOTools.h:74
@ EndOfFile
Definition IOTools.h:73
ReadAllResult readAll(int fd, void *buf, size_t size)
Definition IOTools.cc:69
BlockingMode setFDBlocking(int fd, bool mode)
Definition IOTools.cc:31
static constexpr timeout_type no_timeout
Definition IOTools.h:78
std::vector< char > peek_data_fd(FILE *fd, off_t offset, size_t count)
Definition IOTools.cc:171
size_t timeout_type
Definition IOTools.h:77
AutoDispose< void > OnScopeExit
auto eintrSafeCallEx(const Fun &function, const RestartCb &restartCb, Args &&... args)
auto eintrSafeCall(Fun &&function, Args &&... args)
std::string strerr_cxx(const int err=-1)
#define ERR
Definition Logger.h:102