Modalias.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
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  * For each file in the directory PATH other than . and .., call
00047  * FUNC with the arguments PATH, the file's name, and ARG.
00048  *
00049  * If FUNC returns a non-zero return value, stop reading the directory
00050  * and return that value. Returns -1 if an error occurs.
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  * If DIR/FILE/modalias exists, remember this modalias on the linked modalias list
00082  * passed in in ARG. Never returns an error.
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  * Iterate over all devices on a bus (/sys/bus/BUS/devices/<*>)
00120  * and remembers all module aliases for those devices on
00121  * the linked modalias list passed in in ARG.
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  * Iterate over all devices in a class (/sys/class/CLASS/<*>)
00136  * and remembers all module aliases for those devices on
00137  * the linked modalias list passed in in ARG.
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 //      CLASS NAME : Modalias::Impl
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          * Check if a device on the system matches a modalias PATTERN.
00206          *
00207          * Returns NULL if no matching device is found, and the modalias
00208          * of the first matching device otherwise. (More than one device
00209          * may match a given pattern.)
00210          *
00211          * On a system that has the following device,
00212          *
00213          *   pci:v00008086d0000265Asv00008086sd00004556bc0Csc03i00
00214          *
00215          * modalias_matches("pci:v00008086d0000265Asv*sd*bc*sc*i*") will
00216          * return a non-NULL value.
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                         // We shouldn't get here.
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 };  // struct Modalias::Impl
00276 
00278 
00283 inline std::ostream & operator<<( std::ostream & str, const Modalias::Impl & obj )
00284 {
00285   return str << "Modalias::Impl";
00286 }
00287 
00289 //
00290 //      CLASS NAME : Modalias
00291 //
00293 
00295 //
00296 //      METHOD NAME : Modalias::Modalias
00297 //      METHOD TYPE : Ctor
00298 //
00299 Modalias::Modalias()
00300 : _pimpl( Impl::nullimpl() )
00301 {}
00302 
00304 //
00305 //      METHOD NAME : Modalias::~Modalias
00306 //      METHOD TYPE : Dtor
00307 //
00308 Modalias::~Modalias()
00309 {}
00310 
00312 //
00313 //      METHOD NAME : Modalias::instance
00314 //      METHOD TYPE : Modalias &
00315 //
00316 Modalias & Modalias::instance()
00317 {
00318   static Modalias _singleton;
00319   return _singleton;
00320 }
00321 
00323 // Foreward to implenemtation
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 **      FUNCTION NAME : operator<<
00337 **      FUNCTION TYPE : std::ostream &
00338 */
00339 std::ostream & operator<<( std::ostream & str, const Modalias & obj )
00340 {
00341   return str << *obj._pimpl;
00342 }
00343 
00345     } // namespace modalias
00348   } // namespace target
00351 } // namespace zypp
00353 

Generated on Thu Dec 20 01:09:33 2007 for libzypp by  doxygen 1.5.3