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 DIR/FILE/modalias exists, remember this modalias on the linked modalias list
00081  * passed in in ARG. Never returns an error.
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  * Iterate over all devices on a bus (/sys/bus/BUS/devices/<*>)
00119  * and remembers all module aliases for those devices on
00120  * the linked modalias list passed in in ARG.
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  * Iterate over all devices in a class (/sys/class/CLASS/<*>)
00135  * and remembers all module aliases for those devices on
00136  * the linked modalias list passed in in ARG.
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 //      CLASS NAME : Modalias::Impl
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          * Check if a device on the system matches a modalias PATTERN.
00205          *
00206          * Returns NULL if no matching device is found, and the modalias
00207          * of the first matching device otherwise. (More than one device
00208          * may match a given pattern.)
00209          *
00210          * On a system that has the following device,
00211          *
00212          *   pci:v00008086d0000265Asv00008086sd00004556bc0Csc03i00
00213          *
00214          * modalias_matches("pci:v00008086d0000265Asv*sd*bc*sc*i*") will
00215          * return a non-NULL value.
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                         // We shouldn't get here.
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 };  // struct Modalias::Impl
00275 
00277 
00282 inline std::ostream & operator<<( std::ostream & str, const Modalias::Impl & obj )
00283 {
00284   return str << "Modalias::Impl";
00285 }
00286 
00288 //
00289 //      CLASS NAME : Modalias
00290 //
00292 
00294 //
00295 //      METHOD NAME : Modalias::Modalias
00296 //      METHOD TYPE : Ctor
00297 //
00298 Modalias::Modalias()
00299 : _pimpl( Impl::nullimpl() )
00300 {}
00301 
00303 //
00304 //      METHOD NAME : Modalias::~Modalias
00305 //      METHOD TYPE : Dtor
00306 //
00307 Modalias::~Modalias()
00308 {}
00309 
00311 //
00312 //      METHOD NAME : Modalias::instance
00313 //      METHOD TYPE : Modalias &
00314 //
00315 Modalias & Modalias::instance()
00316 {
00317   static Modalias _singleton;
00318   return _singleton;
00319 }
00320 
00322 // Foreward to implenemtation
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 **      FUNCTION NAME : operator<<
00336 **      FUNCTION TYPE : std::ostream &
00337 */
00338 std::ostream & operator<<( std::ostream & str, const Modalias & obj )
00339 {
00340   return str << *obj._pimpl;
00341 }
00342 
00344     } // namespace modalias
00347   } // namespace target
00350 } // namespace zypp
00352 

Generated on Fri Jul 4 16:58:00 2008 for zypp by  doxygen 1.5.0