libzypp 17.31.1
Modalias.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
12extern "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
32using std::endl;
33
35namespace 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, 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
154 {}
155
156 /*
157 * Check if a device on the system matches a modalias PATTERN.
158 *
159 * Returns NULL if no matching device is found, and the modalias
160 * of the first matching device otherwise. (More than one device
161 * may match a given pattern.)
162 *
163 * On a system that has the following device,
164 *
165 * pci:v00008086d0000265Asv00008086sd00004556bc0Csc03i00
166 *
167 * modalias_matches("pci:v00008086d0000265Asv*sd*bc*sc*i*") will
168 * return a non-NULL value.
169 */
170 bool query( const char * cap_r ) const
171 {
172 if ( cap_r && *cap_r )
173 {
174 for_( it, _modaliases.begin(), _modaliases.end() )
175 {
176 if ( fnmatch( cap_r, (*it).c_str(), 0 ) == 0 )
177 return true;
178 }
179 }
180 return false;
181 }
182
183 public:
185
186 public:
188 static shared_ptr<Impl> nullimpl()
189 {
190 static shared_ptr<Impl> _nullimpl( new Impl );
191 return _nullimpl;
192 }
193
194 };
196
201 inline std::ostream & operator<<( std::ostream & str, const Modalias::Impl & obj )
202 {
203 return dumpRange( str << "Modaliases: (" << obj._modaliases.size() << ") ", obj._modaliases.begin(), obj._modaliases.end() );
204 }
205
207 //
208 // CLASS NAME : Modalias
209 //
211
213 : _pimpl( Impl::nullimpl() )
214 {}
215
217 {}
218
220 {
221 static Modalias _singleton;
222 return _singleton;
223 }
224
225 bool Modalias::query( const char * cap_r ) const
226 { return _pimpl->query( cap_r ); }
227
229 { return _pimpl->_modaliases; }
230
232 { _pimpl->_modaliases.swap( newlist_r ); }
233
234 std::ostream & operator<<( std::ostream & str, const Modalias & obj )
235 { return str << *obj._pimpl; }
236
237 } // namespace target
239} // namespace zypp
241
#define PATH_IS(D, F)
Helper to create and pass std::istream.
Definition: inputstream.h:57
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:221
const Pathname & path() const
Return current Pathname.
Definition: PathInfo.h:246
Hardware abstaction layer singleton.
Definition: Modalias.h:36
Modalias()
Singleton ctor.
Definition: Modalias.cc:212
bool query(IdString cap_r) const
Checks if a device on the system matches a modalias pattern.
Definition: Modalias.h:69
static Modalias & instance()
Singleton access.
Definition: Modalias.cc:219
std::vector< std::string > ModaliasList
Definition: Modalias.h:41
const ModaliasList & modaliasList() const
List of modaliases found on system.
Definition: Modalias.cc:228
RW_pointer< Impl > _pimpl
Pointer to implementation.
Definition: Modalias.h:88
String related utilities and Regular expression matching.
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
Definition: PathInfo.cc:605
int forEachLine(std::istream &str_r, function< bool(int, std::string)> consume_r)
Simple lineparser: Call functor consume_r for each line.
Definition: IOStream.cc:100
std::string getline(std::istream &str)
Read one line from stream.
Definition: IOStream.cc:33
std::ostream & operator<<(std::ostream &str, const CommitPackageCache &obj)
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2
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).
Definition: LogTools.h:91
Modalias implementation.
Definition: Modalias.cc:119
bool query(const char *cap_r) const
Definition: Modalias.cc:170
std::ostream & operator<<(std::ostream &str, const Modalias::Impl &obj)
Stream output And maybe std::ostream & operator<< Modalias::Impl below too.
Definition: Modalias.cc:201
static shared_ptr< Impl > nullimpl()
Offer default Impl.
Definition: Modalias.cc:188
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:28
#define DBG
Definition: Logger.h:95