libzypp: zypp-core/base/IOTools.cc Source File

libzypp 17.38.14

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
18#include <zypp-core/AutoDispose.h>
19#include <zypp-core/base/IOTools.h>
20#include <zypp-core/base/LogTools.h>
21#include <zypp-core/ng/base/private/linuxhelpers_p.h>
22
23 namespace 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 )
78 return ReadAllResult::Error;
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;
94 zypp::AutoFREE<char> linebuf;
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
168 TimeoutException::~TimeoutException() noexcept
169 { }
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}
AutoDispose.h
IOTools.h
LogTools.h
ERR
#define ERR
Definition Logger.h:105
GPollFD
struct _GPollFD GPollFD
Definition ZYppImpl.h:26
zypp::AutoDispose
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition AutoDispose.h:95
zypp::AutoDispose::value
reference value() const
Reference to the Tp object.
Definition AutoDispose.h:138
zypp::io::TimeoutException::~TimeoutException
~TimeoutException() noexcept override
Dtor.
Definition IOTools.cc:168
linuxhelpers_p.h
zypp::io
Definition IOTools.cc:23
zypp::io::ReadAllResult
ReadAllResult
Definition IOTools.h:44
zypp::io::ReadAllResult::Eof
@ Eof
Definition IOTools.h:46
zypp::io::ReadAllResult::Error
@ Error
Definition IOTools.h:45
zypp::io::ReadAllResult::Ok
@ Ok
Definition IOTools.h:47
zypp::io::writeAll
bool writeAll(int fd, void *buf, size_t size)
Definition IOTools.cc:55
zypp::io::setFILEBlocking
BlockingMode setFILEBlocking(FILE *file, bool mode)
Enables or disabled non blocking mode on a file descriptor.
Definition IOTools.cc:25
zypp::io::receiveUpto
std::pair< ReceiveUpToResult, std::string > receiveUpto(FILE *file, char c, timeout_type timeout, bool failOnUnblockError)
Definition IOTools.cc:85
zypp::io::BlockingMode
BlockingMode
Definition IOTools.h:22
zypp::io::BlockingMode::WasBlocking
@ WasBlocking
FD was blocking before.
Definition IOTools.h:24
zypp::io::BlockingMode::FailedToSetMode
@ FailedToSetMode
Failed to block or unblock the fd.
Definition IOTools.h:23
zypp::io::BlockingMode::WasNonBlocking
@ WasNonBlocking
FD was non blocking before.
Definition IOTools.h:25
zypp::io::Timeout
@ Timeout
Definition IOTools.h:72
zypp::io::Success
@ Success
Definition IOTools.h:71
zypp::io::Error
@ Error
Definition IOTools.h:74
zypp::io::EndOfFile
@ EndOfFile
Definition IOTools.h:73
zypp::io::readAll
ReadAllResult readAll(int fd, void *buf, size_t size)
Definition IOTools.cc:69
zypp::io::setFDBlocking
BlockingMode setFDBlocking(int fd, bool mode)
Definition IOTools.cc:31
zypp::io::peek_data_fd
std::vector< char > peek_data_fd(FILE *fd, off_t offset, size_t count)
Definition IOTools.cc:171
zypp::io::timeout_type
size_t timeout_type
Definition IOTools.h:77
zypp::OnScopeExit
AutoDispose< void > OnScopeExit
Definition AutoDispose.h:276
zyppng::eintrSafeCallEx
auto eintrSafeCallEx(const Fun &function, const RestartCb &restartCb, Args &&... args)
Definition linuxhelpers_p.h:35
zyppng::eintrSafeCall
auto eintrSafeCall(Fun &&function, Args &&... args)
Definition linuxhelpers_p.h:50
zyppng::strerr_cxx
std::string strerr_cxx(const int err=-1)
Definition linuxhelpers_p.h:14
zypp::AutoFREE
Definition AutoDispose.h:332