libzypp
10.5.0
|
00001 /*---------------------------------------------------------------------\ 00002 | ____ _ __ __ ___ | 00003 | |__ / \ / / . \ . \ | 00004 | / / \ V /| _/ _/ | 00005 | / /__ | | | | | | | 00006 | /_____||_| |_| |_| | 00007 | | 00008 \---------------------------------------------------------------------*/ 00012 extern "C" 00013 { 00014 #include <sys/types.h> 00015 #include <sys/stat.h> 00016 #include <fcntl.h> 00017 #include <unistd.h> 00018 #include <dirent.h> 00019 #include <fnmatch.h> 00020 } 00021 #include <cstdlib> 00022 #include <cstdio> 00023 #include <cstring> 00024 #include <cerrno> 00025 00026 #include <iostream> 00027 00028 #undef ZYPP_BASE_LOGGER_LOGGROUP 00029 #define ZYPP_BASE_LOGGER_LOGGROUP "MODALIAS" 00030 #include "zypp/base/Logger.h" 00031 00032 #include "zypp/target/modalias/Modalias.h" 00033 #include "zypp/PathInfo.h" 00034 00035 00036 using std::endl; 00037 using std::string; 00038 00039 00041 namespace zypp 00042 { 00043 00044 namespace target 00045 { 00046 00047 struct modalias_list { 00048 char *modalias; 00049 struct modalias_list *next; 00050 }; 00051 00053 namespace 00054 { 00055 00056 /* 00057 * For each file in the directory PATH other than . and .., call 00058 * FUNC with the arguments PATH, the file's name, and ARG. 00059 * 00060 * If FUNC returns a non-zero return value, stop reading the directory 00061 * and return that value. Returns -1 if an error occurs. 00062 */ 00063 00064 int 00065 foreach_file_recursive(const char *path_rec, int (*func)(const char *, const char *, void *), 00066 void *arg) 00067 { 00068 DIR *dir; 00069 struct dirent *dirent; 00070 char path_tmp[PATH_MAX]; 00071 int ret = 0; 00072 00073 if (!(dir = opendir(path_rec))) 00074 return -1; 00075 while ((dirent = readdir(dir)) != NULL) { 00076 00077 if (strcmp(dirent->d_name, ".") == 0 || 00078 strcmp(dirent->d_name, "..") == 0) 00079 continue; 00080 snprintf(path_tmp, sizeof(path_tmp), "%s/%s", path_rec, dirent->d_name); 00081 00082 PathInfo path(path_tmp, PathInfo::LSTAT); 00083 00084 if (path.isLink ()) { 00085 continue; 00086 } 00087 if (path.isDir ()){ 00088 (void) foreach_file_recursive(path_tmp, func, arg); 00089 }else if (path.isFile ()){ 00090 if ((ret = func(path_rec, dirent->d_name, arg)) != 0) 00091 break; 00092 }else{ 00093 continue; 00094 } 00095 } 00096 if (closedir(dir) != 0) 00097 return -1; 00098 return ret; 00099 } 00100 00101 /* 00102 * If DIR/FILE/modalias exists, remember this modalias on the linked modalias list 00103 * passed in in ARG. Never returns an error. 00104 */ 00105 int 00106 read_modalias(const char *dir, const char *file, void *arg) 00107 { 00108 char path[PATH_MAX]; 00109 int fd; 00110 ssize_t len; 00111 char modalias[PATH_MAX]; 00112 struct modalias_list **list = (struct modalias_list **)arg, *entry; 00113 00114 if (strcmp(file, "modalias") != 0){ 00115 return 0; 00116 } 00117 snprintf(path, sizeof(path), "%s/%s", dir, file); 00118 if ((fd = open(path, O_RDONLY|O_CLOEXEC)) == -1) 00119 return 0; 00120 len = read(fd, modalias, sizeof(modalias) - 1); 00121 if (len < 0) 00122 goto out; 00123 while (len > 0 && modalias[len - 1] == '\n') 00124 len--; 00125 modalias[len] = 0; 00126 00127 if ((entry = (struct modalias_list *)malloc(sizeof(*entry))) == NULL) 00128 goto out; 00129 if ((entry->modalias = strdup(modalias)) == NULL) { 00130 free(entry); 00131 goto out; 00132 } 00133 entry->next = *list; 00134 *list = entry; 00135 XXX << "system modalias: " << entry->modalias << endl; 00136 00137 out: 00138 (void) close(fd); 00139 return 0; 00140 } 00141 00143 } // namespace 00145 00147 // 00148 // CLASS NAME : Modalias::Impl 00149 // 00151 struct Modalias::Impl 00152 { 00153 struct modalias_list *_modaliases; 00154 00156 Impl() 00157 : _modaliases(0) 00158 { 00159 const char *dir; 00160 char path[PATH_MAX]; 00161 00162 dir = getenv("ZYPP_MODALIAS_SYSFS"); 00163 if (!dir) 00164 dir = "/sys"; 00165 DBG << "Using /sys directory : " << dir << endl; 00166 00167 snprintf(path, sizeof(path), "%s", dir); 00168 foreach_file_recursive( path, read_modalias, &_modaliases ); 00169 00170 } 00171 00173 ~Impl() 00174 { 00175 while (_modaliases != NULL) { 00176 struct modalias_list *l = _modaliases; 00177 _modaliases = _modaliases->next; 00178 free(l->modalias); 00179 free(l); 00180 } 00181 } 00182 00183 /* 00184 * Check if a device on the system matches a modalias PATTERN. 00185 * 00186 * Returns NULL if no matching device is found, and the modalias 00187 * of the first matching device otherwise. (More than one device 00188 * may match a given pattern.) 00189 * 00190 * On a system that has the following device, 00191 * 00192 * pci:v00008086d0000265Asv00008086sd00004556bc0Csc03i00 00193 * 00194 * modalias_matches("pci:v00008086d0000265Asv*sd*bc*sc*i*") will 00195 * return a non-NULL value. 00196 */ 00197 bool query( const char * cap_r ) const 00198 { 00199 if ( cap_r ) 00200 { 00201 struct modalias_list *l; 00202 for (l = _modaliases; l; l = l->next) { 00203 if ( fnmatch( cap_r, l->modalias, 0 ) == 0 ) 00204 return true; 00205 } 00206 } 00207 return false; 00208 } 00209 00210 public: 00212 static shared_ptr<Impl> nullimpl() 00213 { 00214 static shared_ptr<Impl> _nullimpl( new Impl ); 00215 return _nullimpl; 00216 } 00217 00218 }; // struct Modalias::Impl 00219 00221 00226 inline std::ostream & operator<<( std::ostream & str, const Modalias::Impl & obj ) 00227 { 00228 return str << "Modalias::Impl"; 00229 } 00230 00232 // 00233 // CLASS NAME : Modalias 00234 // 00236 00238 // 00239 // METHOD NAME : Modalias::Modalias 00240 // METHOD TYPE : Ctor 00241 // 00242 Modalias::Modalias() 00243 : _pimpl( Impl::nullimpl() ) 00244 {} 00245 00247 // 00248 // METHOD NAME : Modalias::~Modalias 00249 // METHOD TYPE : Dtor 00250 // 00251 Modalias::~Modalias() 00252 {} 00253 00255 // 00256 // METHOD NAME : Modalias::instance 00257 // METHOD TYPE : Modalias & 00258 // 00259 Modalias & Modalias::instance() 00260 { 00261 static Modalias _singleton; 00262 return _singleton; 00263 } 00264 00266 // Foreward to implenemtation 00268 00269 bool Modalias::query( const char * cap_r ) const 00270 { return _pimpl->query( cap_r ); } 00271 00272 /****************************************************************** 00273 ** 00274 ** FUNCTION NAME : operator<< 00275 ** FUNCTION TYPE : std::ostream & 00276 */ 00277 std::ostream & operator<<( std::ostream & str, const Modalias & obj ) 00278 { 00279 return str << *obj._pimpl; 00280 } 00281 00283 } // namespace target 00286 } // namespace zypp 00288