Modalias.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
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  * For each file in the directory PATH other than . and .., call
00046  * FUNC with the arguments PATH, the file's name, and ARG.
00047  *
00048  * If FUNC returns a non-zero return value, stop reading the directory
00049  * and return that value. Returns -1 if an error occurs.
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  * If the device identified by /sys/bus/BUS/devices/DEVICE has a
00081  * module aliases, remember that alias on the linked modalias list
00082  * passed in in ARG.
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  * Iterate over all devices on a bus (/sys/bus/BUS/devices/<*>)
00124  * and remembers all module aliases for those devices on
00125  * the linked modalias list passed in in ARG.
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 //      CLASS NAME : Modalias::Impl
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          * Check if a device on the system matches a modalias PATTERN.
00186          *
00187          * Returns NULL if no matching device is found, and the modalias
00188          * of the first matching device otherwise. (More than one device
00189          * may match a given pattern.)
00190          *
00191          * On a system that has the following device,
00192          *
00193          *   pci:v00008086d0000265Asv00008086sd00004556bc0Csc03i00
00194          *
00195          * modalias_matches("pci:v00008086d0000265Asv*sd*bc*sc*i*") will
00196          * return a non-NULL value.
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                         // We shouldn't get here.
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 };  // struct Modalias::Impl
00256 
00258 
00263 inline std::ostream & operator<<( std::ostream & str, const Modalias::Impl & obj )
00264 {
00265   return str << "Modalias::Impl";
00266 }
00267 
00269 //
00270 //      CLASS NAME : Modalias
00271 //
00273 
00275 //
00276 //      METHOD NAME : Modalias::Modalias
00277 //      METHOD TYPE : Ctor
00278 //
00279 Modalias::Modalias()
00280 : _pimpl( Impl::nullimpl() )
00281 {}
00282 
00284 //
00285 //      METHOD NAME : Modalias::~Modalias
00286 //      METHOD TYPE : Dtor
00287 //
00288 Modalias::~Modalias()
00289 {}
00290 
00292 //
00293 //      METHOD NAME : Modalias::instance
00294 //      METHOD TYPE : Modalias &
00295 //
00296 Modalias & Modalias::instance()
00297 {
00298   static Modalias _singleton;
00299   return _singleton;
00300 }
00301 
00303 // Foreward to implenemtation
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 **      FUNCTION NAME : operator<<
00317 **      FUNCTION TYPE : std::ostream &
00318 */
00319 std::ostream & operator<<( std::ostream & str, const Modalias & obj )
00320 {
00321   return str << *obj._pimpl;
00322 }
00323 
00325     } // namespace modalias
00328   } // namespace target
00331 } // namespace zypp
00333 

Generated on Thu Jul 6 00:07:26 2006 for zypp by  doxygen 1.4.6