libzypp  17.25.0
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 
22 namespace 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;
61  zypp::AutoFREE<char> linebuf;
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, timeout );
95  if ( retval == -1 )
96  {
97  ERR << "select error: " << strerror(errno) << std::endl;
98  if ( errno != EINTR )
99  return std::make_pair( ReceiveUpToResult::Error, std::string() );
100  }
101  else if ( retval )
102  {
103  // Data is available now.
104  ssize_t nread = getdelim( &linebuf.value(), &linebuffer_size, c, inputfile );
105  if ( nread == -1 ) {
106  if ( ::feof( inputfile ) )
107  return std::make_pair( ReceiveUpToResult::EndOfFile, line );
108  }
109  else
110  {
111  if ( nread > 0 )
112  line += std::string( linebuf, nread );
113 
114  if ( ! ::ferror( inputfile ) || ::feof( inputfile ) ) {
115  return std::make_pair( ReceiveUpToResult::Success, line ); // complete line
116  }
117  }
118  }
119 
120  // we timed out, or were interrupted for some reason
121  // check if we can wait more
122  if ( timer ) {
123  remainingTimeout -= g_timer_elapsed( timer, nullptr );
124  if ( remainingTimeout <= 0 )
125  return std::make_pair( ReceiveUpToResult::Timeout, line );
126  }
127  } while ( true );
128  }
129 
131  { }
132 }
zypp::io::EndOfFile
Definition: IOTools.h:57
zypp::io::Timeout
Definition: IOTools.h:56
zypp::AutoDispose< void >
Definition: AutoDispose.h:192
zypp::io::TimeoutException::~TimeoutException
virtual ~TimeoutException() noexcept override
Dtor.
Definition: IOTools.cc:130
zypp::io
Definition: IOTools.cc:22
zypp::io::Error
Definition: IOTools.h:58
zypp::str::strerror
std::string strerror(int errno_r)
Return string describing the error_r code.
Definition: String.cc:51
zypp::io::receiveUpto
std::pair< ReceiveUpToResult, std::string > receiveUpto(FILE *file, char c, timeout_type timeout, bool failOnUnblockError)
Definition: IOTools.cc:52
zypp::io::timeout_type
size_t timeout_type
Definition: IOTools.h:61
LogTools.h
zypp::io::Success
Definition: IOTools.h:55
zypp::io::BlockingMode::FailedToSetMode
Failed to block or unblock the fd.
AutoDispose.h
zypp::io::BlockingMode
BlockingMode
Definition: IOTools.h:22
zypp::AutoFREE
Definition: AutoDispose.h:302
zypp::io::BlockingMode::WasBlocking
FD was blocking before.
zypp::io::BlockingMode::WasNonBlocking
FD was non blocking before.
zypp::AutoDispose
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition: AutoDispose.h:92
zypp::AutoDispose< Tp * >::value
reference value() const
Reference to the Tp object.
Definition: AutoDispose.h:133
IOTools.h
zypp::io::setFILEBlocking
BlockingMode setFILEBlocking(FILE *file, bool mode)
Enables or disabled non blocking mode on a file descriptor.
Definition: IOTools.cc:24
ERR
#define ERR
Definition: Logger.h:81
timeout
time_t timeout
Definition: MediaCurl.cc:67
zypp::io::no_timeout
static const timeout_type no_timeout
Definition: IOTools.h:62