libzypp 17.37.17
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, 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:
193 {
194 static shared_ptr<Impl> _nullimpl( new Impl );
195 return _nullimpl;
196 }
197
198 };
199
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
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
#define PATH_IS(D, F)
Helper to create and pass std::istream.
Definition inputstream.h:57
Wrapper class for stat/lstat.
Definition PathInfo.h:226
const Pathname & path() const
Return current Pathname.
Definition PathInfo.h:251
std::vector< std::string > ModaliasList
Definition Modalias.h:45
Modalias()
Singleton ctor.
Definition Modalias.cc:216
bool query(IdString cap_r) const
Checks if a device on the system matches a modalias pattern.
Definition Modalias.h:70
static Modalias & instance()
Singleton access.
Definition Modalias.cc:223
const ModaliasList & modaliasList() const
List of modaliases found on system.
Definition Modalias.cc:232
RW_pointer< Impl > _pimpl
Pointer to implementation.
Definition Modalias.h:89
String related utilities and Regular expression matching.
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
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.
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:120
Modalias implementation.
Definition Modalias.cc:119
Impl(const Impl &)=delete
bool query(const char *cap_r) const
Definition Modalias.cc:174
std::ostream & operator<<(std::ostream &str, const Modalias::Impl &obj)
Stream output And maybe std::ostream & operator<< Modalias::Impl below too.
Definition Modalias.cc:205
Impl & operator=(Impl &&)=delete
Impl & operator=(const Impl &)=delete
static shared_ptr< Impl > nullimpl()
Offer default Impl.
Definition Modalias.cc:192
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition Easy.h:27
#define DBG
Definition Logger.h:99