#include <zypp/KeyRing.h>
#include <zypp/ZYppFactory.h>
#include <zypp/ZConfig.h>
+#include <zypp/base/IOTools.h>
using std::endl;
using namespace zypp::filesystem;
if ( root_r.empty() )
root_r = "/";
- // NOTE: Former argument, but now locked to "/var/lib/rpm".
- // A custom dbPath is not actually needed and would only work
- // reliably if libsolv also supports it. By now no further
- // cleanup in the code.
- const Pathname & dbPath_r { librpmDb::defaultDbPath() };
+ const Pathname & dbPath_r { librpmDb::suggestedDbPath( root_r ) }; // also asserts root_r is absolute
- if ( ! root_r.absolute() )
+ // The rpmdb compat symlink.
+ // Required at least until rpmdb2solv takes a dppath argument.
+ // Otherwise it creates a db at "/var/lib/rpm".
+ if ( dbPath_r != "/var/lib/rpm" && ! PathInfo( root_r/"/var/lib/rpm" ).isExist() )
{
- ERR << "Illegal root or dbPath: " << stringPath( root_r, dbPath_r ) << endl;
- ZYPP_THROW(RpmInvalidRootException(root_r, dbPath_r));
+ WAR << "Inject missing /var/lib/rpm compat symlink to " << dbPath_r << endl;
+ filesystem::assert_dir( root_r/"/var/lib" );
+ filesystem::symlink( "../../"/dbPath_r, root_r/"/var/lib/rpm" );
}
- if ( ! PathInfo( root_r/"/var/lib/rpm" ).isExist()
- && PathInfo( root_r/"/usr/lib/sysimage/rpm" ).isDir() )
- {
- WAR << "Rpm package was deleted? Injecting missing rpmdb compat symlink." << endl;
- filesystem::symlink( "../../usr/lib/sysimage/rpm", root_r/"/var/lib/rpm" );
- }
-
- MIL << "Calling initDatabase: " << stringPath( root_r, dbPath_r )
- << ( doRebuild_r ? " (rebuilddb)" : "" )
- << ( quickinit ? " (quickinit)" : "" ) << endl;
-
///////////////////////////////////////////////////////////////////
// Check whether already initialized
///////////////////////////////////////////////////////////////////
if ( initialized() )
{
- if ( root_r == _root && dbPath_r == _dbPath )
- {
+ // Just check for a changing root because the librpmDb::suggestedDbPath
+ // may indeed change: rpm %post moving the db from /var/lib/rpm
+ // to /usr/lib/sysimage/rpm. We continue to use the old dbpath
+ // (via the compat symlink) until a re-init.
+ if ( root_r == _root ) {
+ MIL << "Calling initDatabase: already initialized at " << stringPath( _root, _dbPath ) << endl;
return;
}
else
- {
ZYPP_THROW(RpmDbAlreadyOpenException(_root, _dbPath, root_r, dbPath_r));
- }
}
+ MIL << "Calling initDatabase: " << stringPath( root_r, dbPath_r )
+ << ( doRebuild_r ? " (rebuilddb)" : "" )
+ << ( quickinit ? " (quickinit)" : "" ) << endl;
+
///////////////////////////////////////////////////////////////////
// init database
///////////////////////////////////////////////////////////////////
{ lineres = RpmDb::CHK_NOTFOUND; }
else if ( line.find( ": NOTRUSTED" ) != std::string::npos )
{ lineres = RpmDb::CHK_NOTTRUSTED; }
+ else if ( line.find( ": NOTFOUND" ) != std::string::npos )
+ { continue; } // just collect details for signatures found (#229)
++count[lineres];
detail_r.push_back( RpmDb::CheckPackageDetail::value_type( lineres, std::move(line) ) );
{
process->setBlocking( false );
FILE * inputfile = process->inputFile();
- int inputfileFd = ::fileno( inputfile );
- do
- {
- /* Watch inputFile to see when it has input. */
- fd_set rfds;
- FD_ZERO( &rfds );
- FD_SET( inputfileFd, &rfds );
-
- /* Wait up to 5 seconds. */
- struct timeval tv;
- tv.tv_sec = 5;
- tv.tv_usec = 0;
+ do {
+ // Check every 5 seconds if the process is still running to prevent against
+ // daemons launched in rpm %post that do not close their filedescriptors,
+ // causing us to block for infinity. (bnc#174548)
+ const auto &readResult = io::receiveUpto( inputfile, '\n', 5 * 1000, false );
+ switch ( readResult.first ) {
+ case io::ReceiveUpToResult::Timeout: {
+ if ( !process->running() )
+ return false;
+
+ // we might have received a partial line, lets not forget about it
+ line += readResult.second;
+ }
+ case io::ReceiveUpToResult::Error:
+ case io::ReceiveUpToResult::EndOfFile: {
+ line += readResult.second;
+ if ( line.size() && line.back() == '\n')
+ line.pop_back();
+ return line.size(); // in case of pending output
+ }
+ case io::ReceiveUpToResult::Success: {
+ line += readResult.second;
- int retval = select( inputfileFd+1, &rfds, NULL, NULL, &tv );
+ if ( line.size() && line.back() == '\n')
+ line.pop_back();
- if ( retval == -1 )
- {
- ERR << "select error: " << strerror(errno) << endl;
- if ( errno != EINTR )
- return false;
- }
- else if ( retval )
- {
- // Data is available now.
- static size_t linebuffer_size = 0; // static because getline allocs
- static char * linebuffer = 0; // and reallocs if buffer is too small
- ssize_t nread = getline( &linebuffer, &linebuffer_size, inputfile );
- if ( nread == -1 )
- {
- if ( ::feof( inputfile ) )
- return line.size(); // in case of pending output
- }
- else
- {
- if ( nread > 0 )
- {
- if ( linebuffer[nread-1] == '\n' )
- --nread;
- line += std::string( linebuffer, nread );
- }
-
- if ( ! ::ferror( inputfile ) || ::feof( inputfile ) )
- {
- if ( env::ZYPP_RPM_DEBUG() )
- L_DBG("RPM_DEBUG") << line << endl;
- return true; // complete line
- }
- }
- clearerr( inputfile );
- }
- else
- {
- // No data within time.
- if ( ! process->running() )
- return false;
+ if ( env::ZYPP_RPM_DEBUG() )
+ L_DBG("RPM_DEBUG") << line << endl;
+ return true; // complete line
+ }
}
- } while ( true );
+ } while( true );
}
-
return false;
}