14 #include <unordered_set>
31 #undef ZYPP_BASE_LOGGER_LOGGROUP
32 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::misc"
51 typedef std::pair<std::string,std::unordered_set<std::string>> CacheEntry;
57 inline void addDataIf( std::vector<CheckAccessDeleted::ProcInfo> & data_r,
const CacheEntry & cache_r )
59 const auto & filelist( cache_r.second );
61 if ( filelist.empty() )
65 data_r.push_back( CheckAccessDeleted::ProcInfo() );
66 CheckAccessDeleted::ProcInfo & pinfo( data_r.back() );
67 pinfo.files.insert( pinfo.files.begin(), filelist.begin(), filelist.end() );
69 const std::string & pline( cache_r.first );
70 std::string commandname;
71 for_( ch, pline.begin(), pline.end() )
79 pinfo.ppid = &*(ch+1);
82 pinfo.puid = &*(ch+1);
85 pinfo.login = &*(ch+1);
88 if ( pinfo.command.empty() )
89 commandname = &*(ch+1);
92 if ( *ch ==
'\n' )
break;
93 do { ++ch; }
while ( *ch !=
'\0' );
96 if ( pinfo.command.empty() )
100 if ( pinfo.command.empty() )
101 pinfo.command = std::move(commandname);
111 inline void addCacheIf( CacheEntry & cache_r,
const std::string & line_r,
bool verbose_r )
117 for_( ch, line_r.c_str(), ch+line_r.size() )
122 if ( *(ch+1) !=
'0' )
135 if ( *ch ==
'\n' )
break;
136 do { ++ch; }
while ( *ch !=
'\0' );
139 if ( !t || !f || !n )
142 if ( !( ( *t ==
'R' && *(t+1) ==
'E' && *(t+2) ==
'G' && *(t+3) ==
'\0' )
143 || ( *t ==
'D' && *(t+1) ==
'E' && *(t+2) ==
'L' && *(t+3) ==
'\0' ) ) )
146 if ( !( ( *f ==
'm' && *(f+1) ==
'e' && *(f+2) ==
'm' && *(f+3) ==
'\0' )
147 || ( *f ==
't' && *(f+1) ==
'x' && *(f+2) ==
't' && *(f+3) ==
'\0' )
148 || ( *f ==
'D' && *(f+1) ==
'E' && *(f+2) ==
'L' && *(f+3) ==
'\0' )
149 || ( *f ==
'l' && *(f+1) ==
't' && *(f+2) ==
'x' && *(f+3) ==
'\0' ) ) )
161 if ( *f ==
'm' || *f ==
'D' )
163 static const char * black[] = {
177 cache_r.second.insert( n );
186 struct FilterRunsInLXC
188 bool operator()( pid_t pid_r )
const
189 {
return( nsIno( pid_r,
"pid" ) !=
pidNS ); }
192 :
pidNS( nsIno(
"self",
"pid" ) )
195 static inline ino_t nsIno(
const std::string & pid_r,
const std::string & ns_r )
196 {
return PathInfo(
"/proc/"+pid_r+
"/ns/"+ns_r).ino(); }
198 static inline ino_t nsIno( pid_t pid_r,
const std::string & ns_r )
199 {
return nsIno(
asString(pid_r), ns_r ); }
205 void lsofdebug(
const Pathname & file_r )
207 std::ifstream infile( file_r.c_str() );
208 USR << infile << endl;
209 std::vector<std::string> fields;
211 for( iostr::EachLine in( infile ); in; in.next() )
213 std::string field( *in );
214 if ( field[0] ==
'f' || field[0] ==
'p' )
216 if ( !fields.empty() )
219 std::string line(
str::join( fields,
"\n" ) );
220 for (
char & c : line )
221 {
if ( c ==
'\n' ) c =
'\0'; }
222 line.push_back(
'\n' );
224 size_t sze = cache.second.size();
225 addCacheIf( cache, line,
false );
226 if ( sze != cache.second.size() )
227 USR << fields << endl;
231 if ( field[0] ==
'p' )
233 fields.push_back( field );
235 else if ( !fields.empty() )
237 fields.push_back( field );
250 using target::rpm::librpmDb;
255 : _wasBlocked( librpmDb::isBlocked() )
256 {
if ( _wasBlocked ) librpmDb::unblockAccess(); }
258 {
if ( _wasBlocked ) librpmDb::blockAccess(); }
263 librpmDb::db_const_iterator it;
264 return( it.findPackage(
"lsof" ) && it->tag_edition() < Edition(
"4.90") && !it->tag_provides().count( Capability(
"backported-option-Ki") ) );
275 static const char* argv[] = {
"lsof",
"-n",
"-FpcuLRftkn0",
"-K",
"i", NULL };
282 std::map<pid_t,CacheEntry> cachemap;
284 FilterRunsInLXC runsInLXC;
288 if ( line[0] ==
'p' )
291 if ( !runsInLXC( cachepid ) )
292 cachemap[cachepid].first.swap( line );
298 addCacheIf( cachemap[cachepid], line, verbose_r );
302 int ret = prog.
close();
314 std::vector<ProcInfo> data;
315 for (
const auto & cached : cachemap )
317 addDataIf( data, cached.second );
339 static const str::regex rx(
"[0-9]+:name=systemd:/system.slice/(.*/)?(.*).service$" );
343 [&](
int num_r, std::string line_r )->
bool
362 return dumpRange( str <<
"CheckAccessDeleted ",
374 if ( obj.
pid.empty() )
375 return str <<
"<NoProc>";
Data about one running process accessing deleted files.
bool contains(const C_Str &str_r, const C_Str &val_r)
Locate substring case sensitive.
std::string asString(const DefaultIntegral< Tp, TInitial > &obj)
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
int readlink(const Pathname &symlink_r, Pathname &target_r)
Like 'readlink'.
std::string join(TIterator begin, TIterator end, const C_Str &sep_r=" ")
Join strings using separator sep_r (defaults to BLANK).
std::vector< ProcInfo > _data
const std::string & execError() const
Some detail telling why the execution failed, if it failed.
std::string service() const
Guess if command was started by a systemd service script.
std::string command
process command name
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
std::ostream & operator<<(std::ostream &str, const CheckAccessDeleted &obj)
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
void remember(const Exception &old_r)
Store an other Exception as history.
size_type check(bool verbose_r=false)
Check for running processes which access deleted executables or libraries.
int simpleParseFile(std::istream &str_r, ParseFlags flags_r, function< bool(int, std::string)> consume_r)
Simple lineparser optionally trimming and skipping comments.
std::string pid
process ID
std::ostream & dumpRange(std::ostream &str, TIterator begin, TIterator end, const std::string &intro="{", const std::string &pfx="\n ", const std::string &sep="\n ", const std::string &sfx="\n", const std::string &extro="}")
Print range defined by iterators (multiline style).
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
TInt strtonum(const C_Str &str)
Parsing numbers from string.
std::string puid
process user ID
std::string receiveLine()
Read one line from the input stream.
std::string numstring(char n, int w=0)
int close()
Wait for the progamm to complete.
#define arrayBegin(A)
Simple C-array iterator.
Regular expression match result.
Base class for Exception.
Check for running processes which access deleted executables or libraries.
const_iterator end() const
std::ostream & dumpRangeLine(std::ostream &str, TIterator begin, TIterator end)
Print range defined by iterators (single line style).
bool regex_match(const std::string &s, smatch &matches, const regex ®ex)
regex ZYPP_STR_REGEX regex ZYPP_STR_REGEX
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
const_iterator begin() const
std::string login
process login name
std::vector< std::string > files
list of deleted executables or libraries accessed
std::string ppid
parent process ID
static std::string findService(pid_t pid_r)
Guess if pid was started by a systemd service script.