libzypp 17.25.7
IOTools.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
13#include <errno.h>
14#include <fcntl.h>
15#include <iostream>
16#include <glib.h>
17
18#include <zypp/AutoDispose.h>
19#include <zypp/base/IOTools.h>
20#include <zypp/base/LogTools.h>
21
22namespace zypp::io {
23
24 BlockingMode setFILEBlocking (FILE * file, bool mode )
25 {
26 if ( !file ) return BlockingMode::FailedToSetMode;
27
28 int fd = ::fileno( file );
29
30 if ( fd == -1 )
31 { ERR << strerror( errno ) << std::endl; return BlockingMode::FailedToSetMode; }
32
33 int flags = ::fcntl( fd, F_GETFL );
34
35 if ( flags == -1 )
36 { ERR << strerror( errno ) << std::endl; return BlockingMode::FailedToSetMode; }
37
38 BlockingMode oldMode = ( flags & O_NONBLOCK ) == O_NONBLOCK ? BlockingMode::WasNonBlocking : BlockingMode::WasBlocking;
39 if ( !mode )
40 flags = flags | O_NONBLOCK;
41 else if ( flags & O_NONBLOCK )
42 flags = flags ^ O_NONBLOCK;
43
44 flags = ::fcntl( fd,F_SETFL,flags );
45
46 if ( flags == -1 )
47 { ERR << strerror(errno) << std::endl; return BlockingMode::FailedToSetMode; }
48
49 return oldMode;
50 }
51
52 std::pair<ReceiveUpToResult, std::string> receiveUpto(FILE *file, char c, timeout_type timeout, bool failOnUnblockError )
53 {
54 FILE * inputfile = file;
55 if ( !file )
56 return std::make_pair( ReceiveUpToResult::Error, std::string() );
57
58 int inputfileFd = ::fileno( inputfile );
59
60 size_t linebuffer_size = 0;
62
63 const auto prevMode = setFILEBlocking( file, false );
64 if ( prevMode == BlockingMode::FailedToSetMode && failOnUnblockError )
65 return std::make_pair( ReceiveUpToResult::Error, std::string() );
66
67 // reset the blocking mode when we are done
68 zypp::OnScopeExit resetMode([ prevMode, fd = file ]( ){
69 if ( prevMode == BlockingMode::WasBlocking )
70 setFILEBlocking( fd, true );
71 });
72
73 bool haveTimeout = (timeout != no_timeout);
74 int remainingTimeout = static_cast<int>( timeout );
75 zypp::AutoDispose<GTimer *> timer( nullptr );
76 if ( haveTimeout )
77 timer = zypp::AutoDispose<GTimer *>( g_timer_new(), &g_free );
78
79 std::string line;
80 do
81 {
82 /* Watch inputFile to see when it has input. */
83
84 GPollFD fd;
85 fd.fd = inputfileFd;
86 fd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
87 fd.revents = 0;
88
89 if ( timer )
90 g_timer_start( timer );
91
92 clearerr( inputfile );
93
94 int retval = g_poll( &fd, 1, remainingTimeout );
95 if ( retval == -1 )
96 {
97 if ( errno != EINTR ) {
98 ERR << "select error: " << strerror(errno) << std::endl;
99 return std::make_pair( ReceiveUpToResult::Error, std::string() );
100 }
101 }
102 else if ( retval )
103 {
104 // Data is available now.
105 ssize_t nread = getdelim( &linebuf.value(), &linebuffer_size, c, inputfile );
106 if ( nread == -1 ) {
107 if ( ::feof( inputfile ) )
108 return std::make_pair( ReceiveUpToResult::EndOfFile, line );
109 }
110 else
111 {
112 if ( nread > 0 )
113 line += std::string( linebuf, nread );
114
115 if ( ! ::ferror( inputfile ) || ::feof( inputfile ) ) {
116 return std::make_pair( ReceiveUpToResult::Success, line ); // complete line
117 }
118 }
119 }
120
121 // we timed out, or were interrupted for some reason
122 // check if we can wait more
123 if ( timer ) {
124 remainingTimeout -= g_timer_elapsed( timer, nullptr ) * 1000;
125 if ( remainingTimeout <= 0 )
126 return std::make_pair( ReceiveUpToResult::Timeout, line );
127 }
128 } while ( true );
129 }
130
132 { }
133}
#define ERR
Definition: Logger.h:81
time_t timeout
Definition: MediaCurl.cc:67
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition: AutoDispose.h:93
reference value() const
Reference to the Tp object.
Definition: AutoDispose.h:133
virtual ~TimeoutException() noexcept override
Dtor.
Definition: IOTools.cc:131
BlockingMode setFILEBlocking(FILE *file, bool mode)
Enables or disabled non blocking mode on a file descriptor.
Definition: IOTools.cc:24
static const timeout_type no_timeout
Definition: IOTools.h:62
std::pair< ReceiveUpToResult, std::string > receiveUpto(FILE *file, char c, timeout_type timeout, bool failOnUnblockError)
Definition: IOTools.cc:52
BlockingMode
Definition: IOTools.h:22
@ WasBlocking
FD was blocking before.
@ FailedToSetMode
Failed to block or unblock the fd.
@ WasNonBlocking
FD was non blocking before.
@ Timeout
Definition: IOTools.h:56
@ Success
Definition: IOTools.h:55
@ Error
Definition: IOTools.h:58
@ EndOfFile
Definition: IOTools.h:57
size_t timeout_type
Definition: IOTools.h:61
std::string strerror(int errno_r)
Return string describing the error_r code.
Definition: String.cc:53