libzypp  11.13.5
Modalias.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 extern "C"
13 {
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <fcntl.h>
17 #include <unistd.h>
18 #include <dirent.h>
19 #include <fnmatch.h>
20 }
21 #include <cstdlib>
22 #include <cstdio>
23 #include <cstring>
24 #include <cerrno>
25 
26 #include <iostream>
27 
28 #undef ZYPP_BASE_LOGGER_LOGGROUP
29 #define ZYPP_BASE_LOGGER_LOGGROUP "MODALIAS"
30 #include "zypp/base/Logger.h"
31 
33 #include "zypp/PathInfo.h"
34 
35 
36 using std::endl;
37 using std::string;
38 
39 
41 namespace zypp
42 {
43 
44  namespace target
45  {
46 
47 struct modalias_list {
48  char *modalias;
50 };
51 
53  namespace
54  {
55 
56 /*
57  * For each file in the directory PATH other than . and .., call
58  * FUNC with the arguments PATH, the file's name, and ARG.
59  *
60  * If FUNC returns a non-zero return value, stop reading the directory
61  * and return that value. Returns -1 if an error occurs.
62  */
63 
64 int
65 foreach_file_recursive(const char *path_rec, int (*func)(const char *, const char *, void *),
66  void *arg)
67 {
68  DIR *dir;
69  struct dirent *dirent;
70  char path_tmp[PATH_MAX];
71  int ret = 0;
72 
73  if (!(dir = opendir(path_rec)))
74  return -1;
75  while ((dirent = readdir(dir)) != NULL) {
76 
77  if (strcmp(dirent->d_name, ".") == 0 ||
78  strcmp(dirent->d_name, "..") == 0)
79  continue;
80  snprintf(path_tmp, sizeof(path_tmp), "%s/%s", path_rec, dirent->d_name);
81 
82  PathInfo path(path_tmp, PathInfo::LSTAT);
83 
84  if (path.isLink ()) {
85  continue;
86  }
87  if (path.isDir ()){
88  (void) foreach_file_recursive(path_tmp, func, arg);
89  }else if (path.isFile ()){
90  if ((ret = func(path_rec, dirent->d_name, arg)) != 0)
91  break;
92  }else{
93  continue;
94  }
95  }
96  if (closedir(dir) != 0)
97  return -1;
98  return ret;
99 }
100 
101 /*
102  * If DIR/FILE/modalias exists, remember this modalias on the linked modalias list
103  * passed in in ARG. Never returns an error.
104  */
105 int
106 read_modalias(const char *dir, const char *file, void *arg)
107 {
108  char path[PATH_MAX];
109  int fd;
110  ssize_t len;
111  char modalias[PATH_MAX];
112  struct modalias_list **list = (struct modalias_list **)arg, *entry;
113 
114  if (strcmp(file, "modalias") != 0){
115  return 0;
116  }
117  snprintf(path, sizeof(path), "%s/%s", dir, file);
118  if ((fd = open(path, O_RDONLY|O_CLOEXEC)) == -1)
119  return 0;
120  len = read(fd, modalias, sizeof(modalias) - 1);
121  if (len < 0)
122  goto out;
123  while (len > 0 && modalias[len - 1] == '\n')
124  len--;
125  modalias[len] = 0;
126 
127  if ((entry = (struct modalias_list *)malloc(sizeof(*entry))) == NULL)
128  goto out;
129  if ((entry->modalias = strdup(modalias)) == NULL) {
130  free(entry);
131  goto out;
132  }
133  entry->next = *list;
134  *list = entry;
135  XXX << "system modalias: " << entry->modalias << endl;
136 
137 out:
138  (void) close(fd);
139  return 0;
140 }
141 
143  } // namespace
145 
147 //
148 // CLASS NAME : Modalias::Impl
149 //
152 {
154 
157  : _modaliases(0)
158  {
159  const char *dir;
160  char path[PATH_MAX];
161 
162  dir = getenv("ZYPP_MODALIAS_SYSFS");
163  if (!dir)
164  dir = "/sys";
165  DBG << "Using /sys directory : " << dir << endl;
166 
167  snprintf(path, sizeof(path), "%s", dir);
168  foreach_file_recursive( path, read_modalias, &_modaliases );
169 
170  }
171 
174  {
175  while (_modaliases != NULL) {
176  struct modalias_list *l = _modaliases;
178  free(l->modalias);
179  free(l);
180  }
181  }
182 
183  /*
184  * Check if a device on the system matches a modalias PATTERN.
185  *
186  * Returns NULL if no matching device is found, and the modalias
187  * of the first matching device otherwise. (More than one device
188  * may match a given pattern.)
189  *
190  * On a system that has the following device,
191  *
192  * pci:v00008086d0000265Asv00008086sd00004556bc0Csc03i00
193  *
194  * modalias_matches("pci:v00008086d0000265Asv*sd*bc*sc*i*") will
195  * return a non-NULL value.
196  */
197  bool query( const char * cap_r ) const
198  {
199  if ( cap_r )
200  {
201  struct modalias_list *l;
202  for (l = _modaliases; l; l = l->next) {
203  if ( fnmatch( cap_r, l->modalias, 0 ) == 0 )
204  return true;
205  }
206  }
207  return false;
208  }
209 
210  public:
212  static shared_ptr<Impl> nullimpl()
213  {
214  static shared_ptr<Impl> _nullimpl( new Impl );
215  return _nullimpl;
216  }
217 
218 }; // struct Modalias::Impl
219 
221 
226 inline std::ostream & operator<<( std::ostream & str, const Modalias::Impl & obj )
227 {
228  return str << "Modalias::Impl";
229 }
230 
232 //
233 // CLASS NAME : Modalias
234 //
236 
238 //
239 // METHOD NAME : Modalias::Modalias
240 // METHOD TYPE : Ctor
241 //
243 : _pimpl( Impl::nullimpl() )
244 {}
245 
247 //
248 // METHOD NAME : Modalias::~Modalias
249 // METHOD TYPE : Dtor
250 //
252 {}
253 
255 //
256 // METHOD NAME : Modalias::instance
257 // METHOD TYPE : Modalias &
258 //
260 {
261  static Modalias _singleton;
262  return _singleton;
263 }
264 
266 // Foreward to implenemtation
268 
269 bool Modalias::query( const char * cap_r ) const
270 { return _pimpl->query( cap_r ); }
271 
272 /******************************************************************
273 **
274 ** FUNCTION NAME : operator<<
275 ** FUNCTION TYPE : std::ostream &
276 */
277 std::ostream & operator<<( std::ostream & str, const Modalias & obj )
278 {
279  return str << *obj._pimpl;
280 }
281 
283  } // namespace target
286 } // namespace zypp
288