diff options
-rw-r--r-- | trace-cmd.h | 3 | ||||
-rw-r--r-- | trace-util.c | 185 |
2 files changed, 188 insertions, 0 deletions
diff --git a/trace-cmd.h b/trace-cmd.h index 22b45cc..ea6c356 100644 --- a/trace-cmd.h +++ b/trace-cmd.h | |||
@@ -35,6 +35,9 @@ struct plugin_list; | |||
35 | struct plugin_list *tracecmd_load_plugins(struct pevent *pevent); | 35 | struct plugin_list *tracecmd_load_plugins(struct pevent *pevent); |
36 | void tracecmd_unload_plugins(struct plugin_list *list); | 36 | void tracecmd_unload_plugins(struct plugin_list *list); |
37 | 37 | ||
38 | char **tracecmd_event_systems(const char *tracing_dir); | ||
39 | char **tracecmd_system_events(const char *tracing_dir, const char *system); | ||
40 | |||
38 | enum { | 41 | enum { |
39 | RINGBUF_TYPE_PADDING = 29, | 42 | RINGBUF_TYPE_PADDING = 29, |
40 | RINGBUF_TYPE_TIME_EXTEND = 30, | 43 | RINGBUF_TYPE_TIME_EXTEND = 30, |
diff --git a/trace-util.c b/trace-util.c index b8b6faf..456687c 100644 --- a/trace-util.c +++ b/trace-util.c | |||
@@ -227,6 +227,191 @@ char *tracecmd_find_tracing_dir(void) | |||
227 | return tracing_dir; | 227 | return tracing_dir; |
228 | } | 228 | } |
229 | 229 | ||
230 | static char *append_file(const char *dir, const char *name) | ||
231 | { | ||
232 | char *file; | ||
233 | |||
234 | file = malloc_or_die(strlen(dir) + strlen(name) + 2); | ||
235 | if (!file) | ||
236 | return NULL; | ||
237 | |||
238 | sprintf(file, "%s/%s", dir, name); | ||
239 | return file; | ||
240 | } | ||
241 | |||
242 | static char **add_list(char **list, const char *name, int len) | ||
243 | { | ||
244 | if (!list) | ||
245 | list = malloc_or_die(sizeof(*list) * 2); | ||
246 | else { | ||
247 | list = realloc(list, sizeof(*list) * (len + 2)); | ||
248 | if (!list) | ||
249 | die("Can not allocate list"); | ||
250 | } | ||
251 | |||
252 | list[len] = strdup(name); | ||
253 | if (!list[len]) | ||
254 | die("Can not allocate list"); | ||
255 | |||
256 | list[len + 1] = NULL; | ||
257 | |||
258 | return list; | ||
259 | } | ||
260 | |||
261 | /** | ||
262 | * tracecmd_event_systems - return list of systems for tracing | ||
263 | * @tracing_dir: directory holding the "events" directory | ||
264 | * | ||
265 | * Returns an allocated list of system names. Both the names and | ||
266 | * the list must be freed with free(). | ||
267 | * The list returned ends with a "NULL" pointer. | ||
268 | */ | ||
269 | char **tracecmd_event_systems(const char *tracing_dir) | ||
270 | { | ||
271 | struct dirent *dent; | ||
272 | char **systems = NULL; | ||
273 | char *events_dir; | ||
274 | struct stat st; | ||
275 | DIR *dir; | ||
276 | int len = 0; | ||
277 | int ret; | ||
278 | |||
279 | if (!tracing_dir) | ||
280 | return NULL; | ||
281 | |||
282 | events_dir = append_file(tracing_dir, "events"); | ||
283 | if (!events_dir) | ||
284 | return NULL; | ||
285 | |||
286 | /* | ||
287 | * Search all the directories in the events directory, | ||
288 | * and collect the ones that have the "enable" file. | ||
289 | */ | ||
290 | ret = stat(events_dir, &st); | ||
291 | if (ret < 0 || !S_ISDIR(st.st_mode)) | ||
292 | goto out_free; | ||
293 | |||
294 | dir = opendir(events_dir); | ||
295 | if (!dir) | ||
296 | goto out_free; | ||
297 | |||
298 | while ((dent = readdir(dir))) { | ||
299 | const char *name = dent->d_name; | ||
300 | char *enable; | ||
301 | char *sys; | ||
302 | |||
303 | if (strcmp(name, ".") == 0 || | ||
304 | strcmp(name, "..") == 0) | ||
305 | continue; | ||
306 | |||
307 | sys = append_file(events_dir, name); | ||
308 | ret = stat(sys, &st); | ||
309 | if (ret < 0 || !S_ISDIR(st.st_mode)) { | ||
310 | free(sys); | ||
311 | continue; | ||
312 | } | ||
313 | |||
314 | enable = append_file(sys, "enable"); | ||
315 | |||
316 | ret = stat(enable, &st); | ||
317 | if (ret >= 0) | ||
318 | systems = add_list(systems, name, len++); | ||
319 | |||
320 | free(enable); | ||
321 | free(sys); | ||
322 | } | ||
323 | |||
324 | closedir(dir); | ||
325 | |||
326 | out_free: | ||
327 | free(events_dir); | ||
328 | return systems; | ||
329 | } | ||
330 | |||
331 | /** | ||
332 | * tracecmd_system_events - return list of events for system | ||
333 | * @tracing_dir: directory holding the "events" directory | ||
334 | * @system: the system to return the events for | ||
335 | * | ||
336 | * Returns an allocated list of event names. Both the names and | ||
337 | * the list must be freed with free(). | ||
338 | * The list returned ends with a "NULL" pointer. | ||
339 | */ | ||
340 | char **tracecmd_system_events(const char *tracing_dir, const char *system) | ||
341 | { | ||
342 | struct dirent *dent; | ||
343 | char **events = NULL; | ||
344 | char *events_dir; | ||
345 | char *system_dir; | ||
346 | struct stat st; | ||
347 | DIR *dir; | ||
348 | int len = 0; | ||
349 | int ret; | ||
350 | |||
351 | if (!tracing_dir || !system) | ||
352 | return NULL; | ||
353 | |||
354 | events_dir = append_file(tracing_dir, "events"); | ||
355 | if (!events_dir) | ||
356 | return NULL; | ||
357 | |||
358 | /* | ||
359 | * Search all the directories in the systems directory, | ||
360 | * and collect the ones that have the "enable" file. | ||
361 | */ | ||
362 | ret = stat(events_dir, &st); | ||
363 | if (ret < 0 || !S_ISDIR(st.st_mode)) | ||
364 | goto out_free; | ||
365 | |||
366 | system_dir = append_file(events_dir, system); | ||
367 | if (!system_dir) | ||
368 | goto out_free; | ||
369 | |||
370 | ret = stat(system_dir, &st); | ||
371 | if (ret < 0 || !S_ISDIR(st.st_mode)) | ||
372 | goto out_free_sys; | ||
373 | |||
374 | dir = opendir(system_dir); | ||
375 | if (!dir) | ||
376 | goto out_free_sys; | ||
377 | |||
378 | while ((dent = readdir(dir))) { | ||
379 | const char *name = dent->d_name; | ||
380 | char *enable; | ||
381 | char *event; | ||
382 | |||
383 | if (strcmp(name, ".") == 0 || | ||
384 | strcmp(name, "..") == 0) | ||
385 | continue; | ||
386 | |||
387 | event = append_file(system_dir, name); | ||
388 | ret = stat(event, &st); | ||
389 | if (ret < 0 || !S_ISDIR(st.st_mode)) { | ||
390 | free(event); | ||
391 | continue; | ||
392 | } | ||
393 | |||
394 | enable = append_file(event, "enable"); | ||
395 | |||
396 | ret = stat(enable, &st); | ||
397 | if (ret >= 0) | ||
398 | events = add_list(events, name, len++); | ||
399 | |||
400 | free(enable); | ||
401 | free(event); | ||
402 | } | ||
403 | |||
404 | closedir(dir); | ||
405 | |||
406 | out_free_sys: | ||
407 | free(system_dir); | ||
408 | |||
409 | out_free: | ||
410 | free(events_dir); | ||
411 | |||
412 | return events; | ||
413 | } | ||
414 | |||
230 | static void | 415 | static void |
231 | trace_util_load_plugins_dir(struct pevent *pevent, const char *suffix, | 416 | trace_util_load_plugins_dir(struct pevent *pevent, const char *suffix, |
232 | const char *path, | 417 | const char *path, |