libzypp  17.28.8
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-core/AutoDispose.h>
19 #include <zypp-core/base/IOTools.h>
20 #include <zypp-core/base/LogTools.h>
21 #include <zypp-core/zyppng/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 = ::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 = ::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 = ( 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 = (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 = g_poll( &fd, 1, remainingTimeout );
128  if ( retval == -1 )
129  {
130  if ( errno != EINTR ) {
131  ERR << "select error: " << strerror(errno) << std::endl;
132  return std::make_pair( ReceiveUpToResult::Error, std::string() );
133  }
134  }
135  else if ( retval )
136  {
137  // Data is available now.
138  ssize_t nread = getdelim( &linebuf.value(), &linebuffer_size, c, inputfile );
139  if ( nread == -1 ) {
140  if ( ::feof( inputfile ) )
141  return std::make_pair( ReceiveUpToResult::EndOfFile, line );
142  }
143  else
144  {
145  if ( nread > 0 )
146  line += std::string( linebuf, nread );
147 
148  if ( ! ::ferror( inputfile ) || ::feof( inputfile ) ) {
149  return std::make_pair( ReceiveUpToResult::Success, line ); // complete line
150  }
151  }
152  }
153 
154  // we timed out, or were interrupted for some reason
155  // check if we can wait more
156  if ( timer ) {
157  remainingTimeout -= g_timer_elapsed( timer, nullptr ) * 1000;
158  if ( remainingTimeout <= 0 )
159  return std::make_pair( ReceiveUpToResult::Timeout, line );
160  }
161  } while ( true );
162  }
163 
165  { }
166 
167 }
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition: AutoDispose.h:94
reference value() const
Reference to the Tp object.
Definition: AutoDispose.h:135
virtual ~TimeoutException() noexcept override
Dtor.
Definition: IOTools.cc:164
std::map< std::string, std::string > read(const Pathname &_path)
Read sysconfig file path_r and return (key,valye) pairs.
Definition: Sysconfig.cc:34
bool write(const Pathname &path_r, const std::string &key_r, const std::string &val_r, const std::string &newcomment_r)
Add or change a value in sysconfig file path_r.
Definition: Sysconfig.cc:80
ReadAllResult
Definition: IOTools.h:43
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
static const timeout_type no_timeout
Definition: IOTools.h:77
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.
@ FailedToSetMode
Failed to block or unblock the fd.
@ WasNonBlocking
FD was non blocking before.
@ Timeout
Definition: IOTools.h:71
@ Success
Definition: IOTools.h:70
@ Error
Definition: IOTools.h:73
@ EndOfFile
Definition: IOTools.h:72
ReadAllResult readAll(int fd, void *buf, size_t size)
Definition: IOTools.cc:69
BlockingMode setFDBlocking(int fd, bool mode)
Definition: IOTools.cc:31
size_t timeout_type
Definition: IOTools.h:76
std::string strerror(int errno_r)
Return string describing the error_r code.
Definition: String.cc:53
#define ERR
Definition: Logger.h:98