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