1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/target/modalias/Modalias.cc
21 #undef ZYPP_BASE_LOGGER_LOGGROUP
22 #define ZYPP_BASE_LOGGER_LOGGROUP "MODALIAS"
24 #include "zypp/base/LogTools.h"
25 #include "zypp/base/IOStream.h"
26 #include "zypp/base/InputStream.h"
27 #include "zypp/AutoDispose.h"
28 #include "zypp/PathInfo.h"
30 #include "zypp/target/modalias/Modalias.h"
34 ///////////////////////////////////////////////////////////////////
37 ///////////////////////////////////////////////////////////////////
40 ///////////////////////////////////////////////////////////////////
43 /** Filter subtrees known to contain no modalias files */
44 inline bool isBlackListed( const Pathname & dir_r, const char * file_r )
46 #define PATH_IS( D, F ) ( ::strcmp( file_r, F ) == 0 && ::strcmp( dir_r.c_str(), D ) == 0 )
50 return PATH_IS( "/sys/devices/system", "memory" ); // bnc#824110: huge tree for systems with large RAM
57 /** Recursively scan for modalias files and scan them to \a arg. */
58 void foreach_file_recursive( const Pathname & dir_r, Modalias::ModaliasList & arg )
60 AutoDispose<DIR *> dir( ::opendir( dir_r.c_str() ), ::closedir );
64 struct dirent * dirent = NULL;
65 while ( (dirent = ::readdir(dir)) != NULL )
67 if ( dirent->d_name[0] == '.' )
70 if ( isBlackListed( dir_r, dirent->d_name ) )
73 PathInfo pi( dir_r / dirent->d_name, PathInfo::LSTAT );
77 foreach_file_recursive( pi.path(), arg );
79 else if ( pi.isFile() && ::strcmp( dirent->d_name, "modalias" ) == 0 )
81 // read modalias line from file
82 std::ifstream str( pi.path().c_str() );
83 std::string line( iostr::getline( str ) );
85 arg.push_back( line );
90 ///////////////////////////////////////////////////////////////////
92 ///////////////////////////////////////////////////////////////////
94 // CLASS NAME : Modalias::Impl
96 /** Modalias implementation. */
102 const char * dir = getenv("ZYPP_MODALIAS_SYSFS");
109 // find /sys/ -type f -name modalias -print0 | xargs -0 cat >/tmp/modaliases
110 // ZYPP_MODALIAS_SYSFS=/tmp/modaliases
111 DBG << "Using $ZYPP_MODALIAS_SYSFS modalias file: " << dir << endl;
112 iostr::forEachLine( InputStream( pi.path() ),
113 [&]( int num_r, std::string line_r )->bool
115 this->_modaliases.push_back( line_r );
120 DBG << "Using $ZYPP_MODALIAS_SYSFS: " << dir << endl;
125 DBG << "Using /sys directory." << endl;
128 foreach_file_recursive( dir, _modaliases );
136 * Check if a device on the system matches a modalias PATTERN.
138 * Returns NULL if no matching device is found, and the modalias
139 * of the first matching device otherwise. (More than one device
140 * may match a given pattern.)
142 * On a system that has the following device,
144 * pci:v00008086d0000265Asv00008086sd00004556bc0Csc03i00
146 * modalias_matches("pci:v00008086d0000265Asv*sd*bc*sc*i*") will
147 * return a non-NULL value.
149 bool query( const char * cap_r ) const
151 if ( cap_r && *cap_r )
153 for_( it, _modaliases.begin(), _modaliases.end() )
155 if ( fnmatch( cap_r, (*it).c_str(), 0 ) == 0 )
163 ModaliasList _modaliases;
166 /** Offer default Impl. */
167 static shared_ptr<Impl> nullimpl()
169 static shared_ptr<Impl> _nullimpl( new Impl );
174 ///////////////////////////////////////////////////////////////////
176 /** \relates Modalias::Impl Stream output
177 * And maybe std::ostream & operator<< Modalias::Impl below too.
178 * return libhal version or something like that.
180 inline std::ostream & operator<<( std::ostream & str, const Modalias::Impl & obj )
182 return dumpRange( str << "Modaliases: (" << obj._modaliases.size() << ") ", obj._modaliases.begin(), obj._modaliases.end() );
185 ///////////////////////////////////////////////////////////////////
187 // CLASS NAME : Modalias
189 ///////////////////////////////////////////////////////////////////
192 : _pimpl( Impl::nullimpl() )
195 Modalias::~Modalias()
198 Modalias & Modalias::instance()
200 static Modalias _singleton;
204 bool Modalias::query( const char * cap_r ) const
205 { return _pimpl->query( cap_r ); }
207 const Modalias::ModaliasList & Modalias::modaliasList() const
208 { return _pimpl->_modaliases; }
210 void Modalias::modaliasList( ModaliasList newlist_r )
211 { _pimpl->_modaliases.swap( newlist_r ); }
213 std::ostream & operator<<( std::ostream & str, const Modalias & obj )
214 { return str << *obj._pimpl; }
216 } // namespace target
217 ///////////////////////////////////////////////////////////////////
219 ///////////////////////////////////////////////////////////////////