blob: b96ab61c86b781fad0bae624c0dbad355051baba [file] [log] [blame]
// SPDX-License-Identifier: LGPL-2.1
/*
* Copyright (C) 2008, 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
*
* Updates:
* Copyright (C) 2019, VMware, Tzvetomir Stoyanov <tz.stoyanov@gmail.com>
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "tracefs.h"
#include "tracefs-local.h"
struct tracefs_instance {
char *name;
};
/**
* tracefs_instance_alloc - allocate a new ftrace instance
* @name: The name of the instance (instance will point to this)
*
* Returns a newly allocated instance, or NULL in case of an error.
*/
struct tracefs_instance *tracefs_instance_alloc(const char *name)
{
struct tracefs_instance *instance;
instance = calloc(1, sizeof(*instance));
if (instance && name) {
instance->name = strdup(name);
if (!instance->name) {
free(instance);
instance = NULL;
}
}
return instance;
}
/**
* tracefs_instance_free - Free an instance, previously allocated by
tracefs_instance_alloc()
* @instance: Pointer to the instance to be freed
*
*/
void tracefs_instance_free(struct tracefs_instance *instance)
{
if (!instance)
return;
free(instance->name);
free(instance);
}
/**
* tracefs_instance_create - Create a new ftrace instance
* @instance: Pointer to the instance to be created
*
* Returns 1 if the instance already exist, 0 if the instance
* is created successful or -1 in case of an error
*/
int tracefs_instance_create(struct tracefs_instance *instance)
{
struct stat st;
char *path;
int ret;
path = tracefs_instance_get_dir(instance);
ret = stat(path, &st);
if (ret < 0)
ret = mkdir(path, 0777);
else
ret = 1;
tracefs_put_tracing_file(path);
return ret;
}
/**
* tracefs_instance_destroy - Remove a ftrace instance
* @instance: Pointer to the instance to be removed
*
* Returns -1 in case of an error, or 0 otherwise.
*/
int tracefs_instance_destroy(struct tracefs_instance *instance)
{
char *path;
int ret = -1;
if (!instance || !instance->name) {
warning("Cannot remove top instance");
return -1;
}
path = tracefs_instance_get_dir(instance);
if (path)
ret = rmdir(path);
tracefs_put_tracing_file(path);
return ret;
}
/**
* tracefs_instance_get_file - return the path to an instance file.
* @instance: ftrace instance, can be NULL for the top instance
* @file: name of file to return
*
* Returns the path of the @file for the given @instance, or NULL in
* case of an error.
*
* Must use tracefs_put_tracing_file() to free the returned string.
*/
char *
tracefs_instance_get_file(struct tracefs_instance *instance, const char *file)
{
char *path;
char *buf;
int ret;
if (instance && instance->name) {
ret = asprintf(&buf, "instances/%s/%s", instance->name, file);
if (ret < 0)
return NULL;
path = tracefs_get_tracing_file(buf);
free(buf);
} else
path = tracefs_get_tracing_file(file);
return path;
}
/**
* tracefs_instance_get_dir - return the path to the instance directory.
* @instance: ftrace instance, can be NULL for the top instance
*
* Returns the full path to the instance directory
*
* Must use tracefs_put_tracing_file() to free the returned string.
*/
char *tracefs_instance_get_dir(struct tracefs_instance *instance)
{
char *buf;
char *path;
int ret;
if (instance && instance->name) {
ret = asprintf(&buf, "instances/%s", instance->name);
if (ret < 0) {
warning("Failed to allocate path for instance %s",
instance->name);
return NULL;
}
path = tracefs_get_tracing_file(buf);
free(buf);
} else
path = tracefs_find_tracing_dir();
return path;
}
/**
* tracefs_instance_get_name - return the name of an instance
* @instance: ftrace instance
*
* Returns the name of the given @instance.
* The returned string must *not* be freed.
*/
char *tracefs_instance_get_name(struct tracefs_instance *instance)
{
if (instance)
return instance->name;
return NULL;
}
static int write_file(const char *file, const char *str)
{
int ret;
int fd;
fd = open(file, O_WRONLY | O_TRUNC);
if (fd < 0) {
warning("Failed to open '%s'", file);
return -1;
}
ret = write(fd, str, strlen(str));
close(fd);
return ret;
}
/**
* tracefs_instance_file_write - Write in trace file of specific instance.
* @instance: ftrace instance, can be NULL for the top instance
* @file: name of the file
* @str: nul terminated string, that will be written in the file.
*
* Returns the number of written bytes, or -1 in case of an error
*/
int tracefs_instance_file_write(struct tracefs_instance *instance,
const char *file, const char *str)
{
struct stat st;
char *path;
int ret;
path = tracefs_instance_get_file(instance, file);
if (!path)
return -1;
ret = stat(path, &st);
if (ret == 0)
ret = write_file(path, str);
tracefs_put_tracing_file(path);
return ret;
}
/**
* tracefs_instance_file_read - Read from a trace file of specific instance.
* @instance: ftrace instance, can be NULL for the top instance
* @file: name of the file
* @psize: returns the number of bytes read
*
* Returns a pointer to a nul terminated string, read from the file, or NULL in
* case of an error.
* The return string must be freed by free()
*/
char *tracefs_instance_file_read(struct tracefs_instance *instance,
char *file, int *psize)
{
char *buf = NULL;
int size = 0;
char *path;
path = tracefs_instance_get_file(instance, file);
if (!path)
return NULL;
size = str_read_file(path, &buf);
tracefs_put_tracing_file(path);
if (buf && psize)
*psize = size;
return buf;
}