libzypp  17.34.1
Modalias.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 extern "C"
13 {
14 #include <fnmatch.h>
15 }
16 
17 #include <iostream>
18 #include <fstream>
19 #include <vector>
20 
21 #undef ZYPP_BASE_LOGGER_LOGGROUP
22 #define ZYPP_BASE_LOGGER_LOGGROUP "MODALIAS"
23 
24 #include <zypp/base/LogTools.h>
25 #include <zypp/base/IOStream.h>
26 #include <zypp-core/base/InputStream>
27 #include <zypp/AutoDispose.h>
28 #include <zypp/PathInfo.h>
29 
31 
32 using std::endl;
33 
35 namespace zypp
36 {
38  namespace target
39  {
41  namespace
42  {
44  inline bool isBlackListed( const Pathname & dir_r, const char * file_r )
45  {
46 #define PATH_IS( D, F ) ( ::strcmp( file_r, F ) == 0 && ::strcmp( dir_r.c_str(), D ) == 0 )
47  switch ( file_r[0] )
48  {
49  case 'm':
50  return PATH_IS( "/sys/devices/system", "memory" ); // bnc#824110: huge tree for systems with large RAM
51  break;
52  }
53  return false;
54 #undef PATH_IS
55  }
56 
57  void foreach_file_recursive( const Pathname & dir_r, std::set<std::string> & arg_r )
58  {
59  AutoDispose<DIR *> dir( ::opendir( dir_r.c_str() ), ::closedir );
60  if ( ! dir )
61  return;
62 
63  struct dirent * dirent = NULL;
64  while ( (dirent = ::readdir(dir)) != NULL )
65  {
66  if ( dirent->d_name[0] == '.' )
67  continue;
68 
69  if ( isBlackListed( dir_r, dirent->d_name ) )
70  continue;
71 
72  Pathname path; // lazy init as needed
73  unsigned char d_type = dirent->d_type;
74  if ( d_type == DT_UNKNOWN )
75  {
76  path = dir_r/dirent->d_name;
77  PathInfo pi( path, PathInfo::LSTAT );
78  if ( pi.isDir() )
79  d_type = DT_DIR;
80  else if ( pi.isFile() )
81  d_type = DT_REG;
82  }
83 
84  if ( d_type == DT_DIR )
85  {
86  if ( path.empty() )
87  path = dir_r/dirent->d_name;
88  foreach_file_recursive( path, arg_r );
89  }
90  else if ( d_type == DT_REG && ::strcmp( dirent->d_name, "modalias" ) == 0 )
91  {
92  if ( path.empty() )
93  path = dir_r/dirent->d_name;
94  // read modalias line from file
95  std::ifstream str( path.c_str() );
96  std::string line( iostr::getline( str ) );
97  if ( ! line.empty() )
98  arg_r.insert( line );
99  }
100  }
101  }
102 
104  void foreach_file_recursive( const Pathname & dir_r, Modalias::ModaliasList & arg_r )
105  {
106  std::set<std::string> arg; // we want the aliases to be unified (the public API uses a vector)
107  foreach_file_recursive( dir_r, arg );
108  arg_r.insert( arg_r.end(), arg.begin(), arg.end() );
109  }
110  } // namespace
112 
114  //
115  // CLASS NAME : Modalias::Impl
116  //
119  {
122  {
123  const char * dir = getenv("ZYPP_MODALIAS_SYSFS");
124  if ( dir )
125  {
126  PathInfo pi( dir );
127  if ( pi.isFile() )
128  {
129  // Debug/testcases:
130  // find /sys/ -type f -name modalias -print0 | xargs -0 cat >/tmp/modaliases
131  // ZYPP_MODALIAS_SYSFS=/tmp/modaliases
132  DBG << "Using $ZYPP_MODALIAS_SYSFS modalias file: " << dir << endl;
134  [&]( int num_r, const std::string& line_r )->bool
135  {
136  this->_modaliases.push_back( line_r );
137  return true;
138  } );
139  return;
140  }
141  DBG << "Using $ZYPP_MODALIAS_SYSFS: " << dir << endl;
142  }
143  else
144  {
145  dir = "/sys";
146  DBG << "Using /sys directory." << endl;
147  }
148 
149  foreach_file_recursive( dir, _modaliases );
150  }
151 
152  Impl(const Impl &) = delete;
153  Impl(Impl &&) = delete;
154  Impl &operator=(const Impl &) = delete;
155  Impl &operator=(Impl &&) = delete;
156 
158  ~Impl() = default;
159 
160  /*
161  * Check if a device on the system matches a modalias PATTERN.
162  *
163  * Returns NULL if no matching device is found, and the modalias
164  * of the first matching device otherwise. (More than one device
165  * may match a given pattern.)
166  *
167  * On a system that has the following device,
168  *
169  * pci:v00008086d0000265Asv00008086sd00004556bc0Csc03i00
170  *
171  * modalias_matches("pci:v00008086d0000265Asv*sd*bc*sc*i*") will
172  * return a non-NULL value.
173  */
174  bool query( const char * cap_r ) const
175  {
176  if ( cap_r && *cap_r )
177  {
178  for_( it, _modaliases.begin(), _modaliases.end() )
179  {
180  if ( fnmatch( cap_r, (*it).c_str(), 0 ) == 0 )
181  return true;
182  }
183  }
184  return false;
185  }
186 
187  public:
189 
190  public:
192  static shared_ptr<Impl> nullimpl()
193  {
194  static shared_ptr<Impl> _nullimpl( new Impl );
195  return _nullimpl;
196  }
197 
198  };
200 
205  inline std::ostream & operator<<( std::ostream & str, const Modalias::Impl & obj )
206  {
207  return dumpRange( str << "Modaliases: (" << obj._modaliases.size() << ") ", obj._modaliases.begin(), obj._modaliases.end() );
208  }
209 
211  //
212  // CLASS NAME : Modalias
213  //
215 
217  : _pimpl( Impl::nullimpl() )
218  {}
219 
221  {}
222 
224  {
225  static Modalias _singleton;
226  return _singleton;
227  }
228 
229  bool Modalias::query( const char * cap_r ) const
230  { return _pimpl->query( cap_r ); }
231 
233  { return _pimpl->_modaliases; }
234 
236  { _pimpl->_modaliases.swap( newlist_r ); }
237 
238  std::ostream & operator<<( std::ostream & str, const Modalias & obj )
239  { return str << *obj._pimpl; }
240 
241  } // namespace target
243 } // namespace zypp
245 
const ModaliasList & modaliasList() const
List of modaliases found on system.
Definition: Modalias.cc:232
const Pathname & path() const
Return current Pathname.
Definition: PathInfo.h:247
Modalias()
Singleton ctor.
Definition: Modalias.cc:216
RW_pointer< Impl > _pimpl
Pointer to implementation.
Definition: Modalias.h:89
bool query(const char *cap_r) const
Definition: Modalias.cc:174
std::ostream & dumpRange(std::ostream &str, TIterator begin, TIterator end, const std::string &intro="{", const std::string &pfx="\ ", const std::string &sep="\ ", const std::string &sfx="\, const std::string &extro="}")
Print range defined by iterators (multiline style).
Definition: LogTools.h:120
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:28
int forEachLine(std::istream &str_r, const function< bool(int, std::string)> &consume_r)
Simple lineparser: Call functor consume_r for each line.
Definition: IOStream.cc:100
String related utilities and Regular expression matching.
std::string getline(std::istream &str)
Read one line from stream.
Definition: IOStream.cc:33
Helper to create and pass std::istream.
Definition: inputstream.h:56
std::ostream & operator<<(std::ostream &str, const CommitPackageCache &obj)
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
Definition: PathInfo.cc:610
bool query(IdString cap_r) const
Checks if a device on the system matches a modalias pattern.
Definition: Modalias.h:70
Impl & operator=(const Impl &)=delete
static Modalias & instance()
Singleton access.
Definition: Modalias.cc:223
static shared_ptr< Impl > nullimpl()
Offer default Impl.
Definition: Modalias.cc:192
std::ostream & operator<<(std::ostream &str, const Modalias::Impl &obj)
Definition: Modalias.cc:205
std::vector< std::string > ModaliasList
Definition: Modalias.h:45
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:221
Modalias implementation.
Definition: Modalias.cc:118
Easy-to use interface to the ZYPP dependency resolver.
Definition: Application.cc:19
Hardware abstaction layer singleton.
Definition: Modalias.h:36
#define DBG
Definition: Logger.h:97
#define PATH_IS(D, F)