00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013
00014 #undef ZYPP_BASE_LOGGER_LOGGROUP
00015 #define ZYPP_BASE_LOGGER_LOGGROUP "MODALIAS"
00016 #include "zypp/base/Logger.h"
00017
00018 #include "zypp/target/modalias/Modalias.h"
00019
00020 #include <cstdlib>
00021 #include <stdio.h>
00022 #include <sys/types.h>
00023 #include <sys/stat.h>
00024 #include <fcntl.h>
00025 #include <unistd.h>
00026 #include <dirent.h>
00027 #include <fnmatch.h>
00028 #include <cstring>
00029 #include <cerrno>
00030
00031 using std::endl;
00032 using std::string;
00033
00034
00036 namespace zypp
00037 {
00038
00039 namespace target
00040 {
00041
00042 namespace modalias
00043 {
00044
00045
00046
00047
00048
00049
00050
00051
00052 static int
00053 foreach_file(const char *path, int (*func)(const char *, const char *, void *),
00054 void *arg)
00055 {
00056 DIR *dir;
00057 struct dirent *dirent;
00058 int ret = 0;
00059
00060 if (!(dir = opendir(path)))
00061 return -1;
00062 while ((dirent = readdir(dir)) != NULL) {
00063
00064 if (strcmp(dirent->d_name, ".") == 0 ||
00065 strcmp(dirent->d_name, "..") == 0)
00066 continue;
00067 if ((ret = func(path, dirent->d_name, arg)) != 0)
00068 break;
00069 }
00070 if (closedir(dir) != 0)
00071 return -1;
00072 return ret;
00073 }
00074
00075 struct modalias_list {
00076 char *modalias;
00077 struct modalias_list *next;
00078 };
00079
00080
00081
00082
00083
00084
00085 static int
00086 iterate_devices(const char *dir, const char *file, void *arg)
00087 {
00088 char path[PATH_MAX];
00089 int fd;
00090 ssize_t len;
00091 char modalias[PATH_MAX];
00092 struct modalias_list **list = (struct modalias_list **)arg, *entry;
00093 int ret = 0;
00094
00095 snprintf(path, sizeof(path), "%s/%s/modalias", dir, file);
00096 if ((fd = open(path, O_RDONLY)) == -1)
00097 return 0;
00098 len = read(fd, modalias, sizeof(modalias) - 1);
00099 if (len < 0)
00100 goto out;
00101 while (len > 0 && modalias[len - 1] == '\n')
00102 len--;
00103 modalias[len] = 0;
00104
00105 if ((entry = (struct modalias_list *)malloc(sizeof(*entry))) == NULL) {
00106 ret = -1;
00107 goto out;
00108 }
00109 if ((entry->modalias = strdup(modalias)) == NULL) {
00110 free(entry);
00111 ret = -1;
00112 goto out;
00113 }
00114 entry->next = *list;
00115 *list = entry;
00116 XXX << "system modalias: " << entry->modalias << endl;
00117
00118 out:
00119 (void) close(fd);
00120 return 0;
00121 }
00122
00123
00124
00125
00126
00127
00128 static int
00129 iterate_busses(const char *dir, const char *file, void *arg)
00130 {
00131 char path[PATH_MAX];
00132
00133 snprintf(path, sizeof(path), "%s/%s/devices", dir, file);
00134 (void) foreach_file(path, iterate_devices, arg);
00135 return 0;
00136 }
00137
00139
00140
00141
00143 struct Modalias::Impl
00144 {
00145 struct modalias_list *_modaliases;
00146
00148 Impl()
00149 : _modaliases(0)
00150 {
00151 foreach_file( "/sys/bus", iterate_busses, &_modaliases );
00152 char path[PATH_MAX];
00153 const char *dir = getenv("ZYPP_MODALIAS_SYSFS");
00154 snprintf(path, sizeof(path), "%s/bus", dir ? dir : "/sys");
00155 DBG << "Using /sys path : " << path << endl;
00156 foreach_file( path, iterate_busses, &_modaliases );
00157 }
00158
00160 ~Impl()
00161 {
00162 while (_modaliases != NULL) {
00163 struct modalias_list *l = _modaliases;
00164 _modaliases = _modaliases->next;
00165 free(l->modalias);
00166 free(l);
00167 }
00168 }
00169
00174 bool query( const std::string & cap_r ) const
00175 { return query( cap_r, Rel::ANY, std::string() ); }
00176
00180 bool query( const std::string & cap_r,
00181 Rel op_r,
00182 const std::string & val_r ) const
00183 {
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 struct modalias_list *l;
00201 for (l = _modaliases; l; l = l->next) {
00202 if ( fnmatch( cap_r.c_str(), l->modalias, 0 ) == 0 )
00203 return true;
00204 }
00205 return false;
00206
00207 #if 0 // once we get a capabilities values, we can compare it ...
00208 if (value) {
00209 string lhs (value);
00210 int cmp = (lhs != rhs) ? ((lhs < rhs) ? -1 : 1) : 0;
00211
00212 switch ( relation.inSwitch() )
00213 {
00214 case Rel::EQ_e:
00215 res = (cmp == 0);
00216 break;
00217 case Rel::NE_e:
00218 res = (cmp != 0);
00219 break;
00220 case Rel::LT_e:
00221 res = (cmp == -1);
00222 break;
00223 case Rel::LE_e:
00224 res = (cmp != 1);
00225 break;
00226 case Rel::GT_e:
00227 res = (cmp == 1);
00228 break;
00229 case Rel::GE_e:
00230 res = (cmp != -1);
00231 break;
00232 case Rel::ANY_e:
00233 res = true;
00234 break;
00235 case Rel::NONE_e:
00236 res = false;
00237 break;
00238 default:
00239
00240 INT << "Unknown relational opertor '" << relation << "' treated as 'NONE'" << endl;
00241 break;
00242 }
00243 }
00244 #endif
00245
00246 }
00247
00248 public:
00250 static shared_ptr<Impl> nullimpl()
00251 {
00252 static shared_ptr<Impl> _nullimpl( new Impl );
00253 return _nullimpl;
00254 }
00255
00256 };
00257
00259
00264 inline std::ostream & operator<<( std::ostream & str, const Modalias::Impl & obj )
00265 {
00266 return str << "Modalias::Impl";
00267 }
00268
00270
00271
00272
00274
00276
00277
00278
00279
00280 Modalias::Modalias()
00281 : _pimpl( Impl::nullimpl() )
00282 {}
00283
00285
00286
00287
00288
00289 Modalias::~Modalias()
00290 {}
00291
00293
00294
00295
00296
00297 Modalias & Modalias::instance()
00298 {
00299 static Modalias _singleton;
00300 return _singleton;
00301 }
00302
00304
00306
00307 bool Modalias::query( const std::string & cap_r ) const
00308 { return _pimpl->query( cap_r ); }
00309
00310 bool Modalias::query( const std::string & cap_r,
00311 Rel op_r,
00312 const std::string & val_r ) const
00313 { return _pimpl->query( cap_r, op_r, val_r ); }
00314
00315
00316
00317
00318
00319
00320 std::ostream & operator<<( std::ostream & str, const Modalias & obj )
00321 {
00322 return str << *obj._pimpl;
00323 }
00324
00326 }
00329 }
00332 }
00334