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 static int
00085 read_modalias(const char *dir, const char *file, void *arg)
00086 {
00087 char path[PATH_MAX];
00088 int fd;
00089 ssize_t len;
00090 char modalias[PATH_MAX];
00091 struct modalias_list **list = (struct modalias_list **)arg, *entry;
00092
00093 snprintf(path, sizeof(path), "%s/%s/modalias", dir, file);
00094 if ((fd = open(path, O_RDONLY)) == -1)
00095 return 0;
00096 len = read(fd, modalias, sizeof(modalias) - 1);
00097 if (len < 0)
00098 goto out;
00099 while (len > 0 && modalias[len - 1] == '\n')
00100 len--;
00101 modalias[len] = 0;
00102
00103 if ((entry = (struct modalias_list *)malloc(sizeof(*entry))) == NULL)
00104 goto out;
00105 if ((entry->modalias = strdup(modalias)) == NULL) {
00106 free(entry);
00107 goto out;
00108 }
00109 entry->next = *list;
00110 *list = entry;
00111 XXX << "system modalias: " << entry->modalias << endl;
00112
00113 out:
00114 (void) close(fd);
00115 return 0;
00116 }
00117
00118
00119
00120
00121
00122
00123 static int
00124 iterate_bus(const char *dir, const char *file, void *arg)
00125 {
00126 char path[PATH_MAX];
00127
00128 snprintf(path, sizeof(path), "%s/%s/devices", dir, file);
00129 (void) foreach_file(path, read_modalias, arg);
00130
00131 return 0;
00132 }
00133
00134
00135
00136
00137
00138
00139 static int
00140 iterate_class(const char *dir, const char *file, void *arg)
00141 {
00142 char path[PATH_MAX];
00143
00144 snprintf(path, sizeof(path), "%s/%s", dir, file);
00145 (void) foreach_file(path, read_modalias, arg);
00146
00147 return 0;
00148 }
00149
00151
00152
00153
00155 struct Modalias::Impl
00156 {
00157 struct modalias_list *_modaliases;
00158
00160 Impl()
00161 : _modaliases(0)
00162 {
00163 const char *dir;
00164 char path[PATH_MAX];
00165
00166 dir = getenv("ZYPP_MODALIAS_SYSFS");
00167 if (!dir)
00168 dir = "/sys";
00169 DBG << "Using /sys directory : " << dir << endl;
00170
00171 snprintf(path, sizeof(path), "%s/bus", dir);
00172 foreach_file( path, iterate_bus, &_modaliases );
00173
00174 snprintf(path, sizeof(path), "%s/class", dir);
00175 foreach_file( path, iterate_class, &_modaliases );
00176 }
00177
00179 ~Impl()
00180 {
00181 while (_modaliases != NULL) {
00182 struct modalias_list *l = _modaliases;
00183 _modaliases = _modaliases->next;
00184 free(l->modalias);
00185 free(l);
00186 }
00187 }
00188
00193 bool query( const std::string & cap_r ) const
00194 { return query( cap_r, Rel::ANY, std::string() ); }
00195
00199 bool query( const std::string & cap_r,
00200 Rel op_r,
00201 const std::string & val_r ) const
00202 {
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 struct modalias_list *l;
00220 for (l = _modaliases; l; l = l->next) {
00221 if ( fnmatch( cap_r.c_str(), l->modalias, 0 ) == 0 )
00222 return true;
00223 }
00224 return false;
00225
00226 #if 0 // once we get a capabilities values, we can compare it ...
00227 if (value) {
00228 string lhs (value);
00229 int cmp = (lhs != rhs) ? ((lhs < rhs) ? -1 : 1) : 0;
00230
00231 switch ( relation.inSwitch() )
00232 {
00233 case Rel::EQ_e:
00234 res = (cmp == 0);
00235 break;
00236 case Rel::NE_e:
00237 res = (cmp != 0);
00238 break;
00239 case Rel::LT_e:
00240 res = (cmp == -1);
00241 break;
00242 case Rel::LE_e:
00243 res = (cmp != 1);
00244 break;
00245 case Rel::GT_e:
00246 res = (cmp == 1);
00247 break;
00248 case Rel::GE_e:
00249 res = (cmp != -1);
00250 break;
00251 case Rel::ANY_e:
00252 res = true;
00253 break;
00254 case Rel::NONE_e:
00255 res = false;
00256 break;
00257 default:
00258
00259 INT << "Unknown relational opertor '" << relation << "' treated as 'NONE'" << endl;
00260 break;
00261 }
00262 }
00263 #endif
00264
00265 }
00266
00267 public:
00269 static shared_ptr<Impl> nullimpl()
00270 {
00271 static shared_ptr<Impl> _nullimpl( new Impl );
00272 return _nullimpl;
00273 }
00274
00275 };
00276
00278
00283 inline std::ostream & operator<<( std::ostream & str, const Modalias::Impl & obj )
00284 {
00285 return str << "Modalias::Impl";
00286 }
00287
00289
00290
00291
00293
00295
00296
00297
00298
00299 Modalias::Modalias()
00300 : _pimpl( Impl::nullimpl() )
00301 {}
00302
00304
00305
00306
00307
00308 Modalias::~Modalias()
00309 {}
00310
00312
00313
00314
00315
00316 Modalias & Modalias::instance()
00317 {
00318 static Modalias _singleton;
00319 return _singleton;
00320 }
00321
00323
00325
00326 bool Modalias::query( const std::string & cap_r ) const
00327 { return _pimpl->query( cap_r ); }
00328
00329 bool Modalias::query( const std::string & cap_r,
00330 Rel op_r,
00331 const std::string & val_r ) const
00332 { return _pimpl->query( cap_r, op_r, val_r ); }
00333
00334
00335
00336
00337
00338
00339 std::ostream & operator<<( std::ostream & str, const Modalias & obj )
00340 {
00341 return str << *obj._pimpl;
00342 }
00343
00345 }
00348 }
00351 }
00353