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