libzypp  12.16.5
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/AutoDispose.h"
27 #include "zypp/PathInfo.h"
28 
30 
31 using std::endl;
32 
34 namespace zypp
35 {
37  namespace target
38  {
40  namespace
41  {
43  inline bool isBlackListed( const Pathname & dir_r, const char * file_r )
44  {
45 #define PATH_IS( D, F ) ( ::strcmp( file_r, F ) == 0 && ::strcmp( dir_r.c_str(), D ) == 0 )
46  switch ( file_r[0] )
47  {
48  case 'm':
49  return PATH_IS( "/sys/devices/system", "memory" ); // bnc#824110: huge tree for systems with large RAM
50  break;
51  }
52  return false;
53 #undef PATH_IS
54  }
55 
57  void foreach_file_recursive( const Pathname & dir_r, Modalias::ModaliasList & arg )
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  PathInfo pi( dir_r / dirent->d_name, PathInfo::LSTAT );
73 
74  if ( pi.isDir() )
75  {
76  foreach_file_recursive( pi.path(), arg );
77  }
78  else if ( pi.isFile() && ::strcmp( dirent->d_name, "modalias" ) == 0 )
79  {
80  // read modalias line from file
81  std::ifstream str( pi.path().c_str() );
82  std::string line( iostr::getline( str ) );
83  if ( ! line.empty() )
84  arg.push_back( line );
85  }
86  }
87  }
88  } // namespace
90 
92  //
93  // CLASS NAME : Modalias::Impl
94  //
97  {
99  Impl()
100  {
101  const char * dir = getenv("ZYPP_MODALIAS_SYSFS");
102  if ( !dir )
103  dir = "/sys";
104  DBG << "Using /sys directory : " << dir << endl;
105 
106  foreach_file_recursive( dir, _modaliases );
107  }
108 
111  {}
112 
113  /*
114  * Check if a device on the system matches a modalias PATTERN.
115  *
116  * Returns NULL if no matching device is found, and the modalias
117  * of the first matching device otherwise. (More than one device
118  * may match a given pattern.)
119  *
120  * On a system that has the following device,
121  *
122  * pci:v00008086d0000265Asv00008086sd00004556bc0Csc03i00
123  *
124  * modalias_matches("pci:v00008086d0000265Asv*sd*bc*sc*i*") will
125  * return a non-NULL value.
126  */
127  bool query( const char * cap_r ) const
128  {
129  if ( cap_r && *cap_r )
130  {
131  for_( it, _modaliases.begin(), _modaliases.end() )
132  {
133  if ( fnmatch( cap_r, (*it).c_str(), 0 ) == 0 )
134  return true;
135  }
136  }
137  return false;
138  }
139 
140  public:
142 
143  public:
145  static shared_ptr<Impl> nullimpl()
146  {
147  static shared_ptr<Impl> _nullimpl( new Impl );
148  return _nullimpl;
149  }
150 
151  };
153 
158  inline std::ostream & operator<<( std::ostream & str, const Modalias::Impl & obj )
159  {
160  return dumpRange( str << "Modaliases: (" << obj._modaliases.size() << ") ", obj._modaliases.begin(), obj._modaliases.end() );
161  }
162 
164  //
165  // CLASS NAME : Modalias
166  //
168 
170  : _pimpl( Impl::nullimpl() )
171  {}
172 
174  {}
175 
177  {
178  static Modalias _singleton;
179  return _singleton;
180  }
181 
182  bool Modalias::query( const char * cap_r ) const
183  { return _pimpl->query( cap_r ); }
184 
186  { return _pimpl->_modaliases; }
187 
188  std::ostream & operator<<( std::ostream & str, const Modalias & obj )
189  { return str << *obj._pimpl; }
190 
191  } // namespace target
193 } // namespace zypp
195