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 void foreach_file_recursive( const Pathname & dir_r, std::set<std::string> & arg_r )
59 AutoDispose<DIR *> dir( ::opendir( dir_r.c_str() ), ::closedir );
63 struct dirent * dirent = NULL;
64 while ( (dirent = ::readdir(dir)) != NULL )
66 if ( dirent->d_name[0] == '.' )
69 if ( isBlackListed( dir_r, dirent->d_name ) )
72 Pathname path; // lazy init as needed
73 unsigned char d_type = dirent->d_type;
74 if ( d_type == DT_UNKNOWN )
76 path = dir_r/dirent->d_name;
77 PathInfo pi( path, PathInfo::LSTAT );
80 else if ( pi.isFile() )
84 if ( d_type == DT_DIR )
87 path = dir_r/dirent->d_name;
88 foreach_file_recursive( path, arg_r );
90 else if ( d_type == DT_REG && ::strcmp( dirent->d_name, "modalias" ) == 0 )
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 ) );
103 /** Recursively scan for modalias files and scan them to \a arg. */
104 void foreach_file_recursive( const Pathname & dir_r, Modalias::ModaliasList & arg_r )
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() );
111 ///////////////////////////////////////////////////////////////////
113 ///////////////////////////////////////////////////////////////////
115 // CLASS NAME : Modalias::Impl
117 /** Modalias implementation. */
118 struct Modalias::Impl
123 const char * dir = getenv("ZYPP_MODALIAS_SYSFS");
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;
133 iostr::forEachLine( InputStream( pi.path() ),
134 [&]( int num_r, std::string line_r )->bool
136 this->_modaliases.push_back( line_r );
141 DBG << "Using $ZYPP_MODALIAS_SYSFS: " << dir << endl;
146 DBG << "Using /sys directory." << endl;
149 foreach_file_recursive( dir, _modaliases );
157 * Check if a device on the system matches a modalias PATTERN.
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.)
163 * On a system that has the following device,
165 * pci:v00008086d0000265Asv00008086sd00004556bc0Csc03i00
167 * modalias_matches("pci:v00008086d0000265Asv*sd*bc*sc*i*") will
168 * return a non-NULL value.
170 bool query( const char * cap_r ) const
172 if ( cap_r && *cap_r )
174 for_( it, _modaliases.begin(), _modaliases.end() )
176 if ( fnmatch( cap_r, (*it).c_str(), 0 ) == 0 )
184 ModaliasList _modaliases;
187 /** Offer default Impl. */
188 static shared_ptr<Impl> nullimpl()
190 static shared_ptr<Impl> _nullimpl( new Impl );
195 ///////////////////////////////////////////////////////////////////
197 /** \relates Modalias::Impl Stream output
198 * And maybe std::ostream & operator<< Modalias::Impl below too.
199 * return libhal version or something like that.
201 inline std::ostream & operator<<( std::ostream & str, const Modalias::Impl & obj )
203 return dumpRange( str << "Modaliases: (" << obj._modaliases.size() << ") ", obj._modaliases.begin(), obj._modaliases.end() );
206 ///////////////////////////////////////////////////////////////////
208 // CLASS NAME : Modalias
210 ///////////////////////////////////////////////////////////////////
213 : _pimpl( Impl::nullimpl() )
216 Modalias::~Modalias()
219 Modalias & Modalias::instance()
221 static Modalias _singleton;
225 bool Modalias::query( const char * cap_r ) const
226 { return _pimpl->query( cap_r ); }
228 const Modalias::ModaliasList & Modalias::modaliasList() const
229 { return _pimpl->_modaliases; }
231 void Modalias::modaliasList( ModaliasList newlist_r )
232 { _pimpl->_modaliases.swap( newlist_r ); }
234 std::ostream & operator<<( std::ostream & str, const Modalias & obj )
235 { return str << *obj._pimpl; }
237 } // namespace target
238 ///////////////////////////////////////////////////////////////////
240 ///////////////////////////////////////////////////////////////////