data.c 3.8 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0
2 3 4 5
#include <linux/compiler.h>
#include <linux/kernel.h>
#include <sys/types.h>
#include <sys/stat.h>
6
#include <errno.h>
7
#include <fcntl.h>
8 9 10 11 12
#include <unistd.h>
#include <string.h>

#include "data.h"
#include "util.h"
13
#include "debug.h"
14

15
static bool check_pipe(struct perf_data *data)
16 17 18
{
	struct stat st;
	bool is_pipe = false;
19
	int fd = perf_data__is_read(data) ?
20 21
		 STDIN_FILENO : STDOUT_FILENO;

J
Jiri Olsa 已提交
22
	if (!data->path) {
23 24 25
		if (!fstat(fd, &st) && S_ISFIFO(st.st_mode))
			is_pipe = true;
	} else {
J
Jiri Olsa 已提交
26
		if (!strcmp(data->path, "-"))
27 28 29 30
			is_pipe = true;
	}

	if (is_pipe)
J
Jiri Olsa 已提交
31
		data->file.fd = fd;
32

33
	return data->is_pipe = is_pipe;
34 35
}

36
static int check_backup(struct perf_data *data)
37 38 39
{
	struct stat st;

J
Jiri Olsa 已提交
40
	if (!stat(data->path, &st) && st.st_size) {
41 42 43
		/* TODO check errors properly */
		char oldname[PATH_MAX];
		snprintf(oldname, sizeof(oldname), "%s.old",
J
Jiri Olsa 已提交
44
			 data->path);
45
		unlink(oldname);
J
Jiri Olsa 已提交
46
		rename(data->path, oldname);
47 48 49 50 51
	}

	return 0;
}

52
static int open_file_read(struct perf_data *data)
53 54 55
{
	struct stat st;
	int fd;
56
	char sbuf[STRERR_BUFSIZE];
57

J
Jiri Olsa 已提交
58
	fd = open(data->file.path, O_RDONLY);
59 60 61
	if (fd < 0) {
		int err = errno;

J
Jiri Olsa 已提交
62
		pr_err("failed to open %s: %s", data->file.path,
63
			str_error_r(err, sbuf, sizeof(sbuf)));
J
Jiri Olsa 已提交
64
		if (err == ENOENT && !strcmp(data->file.path, "perf.data"))
65 66 67 68 69 70 71 72
			pr_err("  (try 'perf record' first)");
		pr_err("\n");
		return -err;
	}

	if (fstat(fd, &st) < 0)
		goto out_close;

73
	if (!data->force && st.st_uid && (st.st_uid != geteuid())) {
74
		pr_err("File %s not owned by current user or root (use -f to override)\n",
J
Jiri Olsa 已提交
75
		       data->file.path);
76 77 78 79
		goto out_close;
	}

	if (!st.st_size) {
80
		pr_info("zero-sized data (%s), nothing to do!\n",
J
Jiri Olsa 已提交
81
			data->file.path);
82 83 84
		goto out_close;
	}

85
	data->file.size = st.st_size;
86 87 88 89 90 91 92
	return fd;

 out_close:
	close(fd);
	return -1;
}

93
static int open_file_write(struct perf_data *data)
94
{
A
Adrien BAK 已提交
95
	int fd;
96
	char sbuf[STRERR_BUFSIZE];
A
Adrien BAK 已提交
97

98
	if (check_backup(data))
99 100
		return -1;

J
Jiri Olsa 已提交
101
	fd = open(data->file.path, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC,
102
		  S_IRUSR|S_IWUSR);
A
Adrien BAK 已提交
103 104

	if (fd < 0)
J
Jiri Olsa 已提交
105
		pr_err("failed to open %s : %s\n", data->file.path,
106
			str_error_r(errno, sbuf, sizeof(sbuf)));
A
Adrien BAK 已提交
107 108

	return fd;
109 110
}

111
static int open_file(struct perf_data *data)
112 113 114
{
	int fd;

115 116
	fd = perf_data__is_read(data) ?
	     open_file_read(data) : open_file_write(data);
117

J
Jiri Olsa 已提交
118 119 120 121 122
	if (fd < 0) {
		free(data->file.path);
		return -1;
	}

J
Jiri Olsa 已提交
123
	data->file.fd = fd;
J
Jiri Olsa 已提交
124 125 126 127 128 129 130 131 132 133
	return 0;
}

static int open_file_dup(struct perf_data *data)
{
	data->file.path = strdup(data->path);
	if (!data->file.path)
		return -ENOMEM;

	return open_file(data);
134 135
}

136
int perf_data__open(struct perf_data *data)
137
{
138
	if (check_pipe(data))
139 140
		return 0;

J
Jiri Olsa 已提交
141 142
	if (!data->path)
		data->path = "perf.data";
143

J
Jiri Olsa 已提交
144
	return open_file_dup(data);
145 146
}

147
void perf_data__close(struct perf_data *data)
148
{
J
Jiri Olsa 已提交
149
	free(data->file.path);
J
Jiri Olsa 已提交
150
	close(data->file.fd);
151
}
152

153 154 155 156 157 158
ssize_t perf_data_file__write(struct perf_data_file *file,
			      void *buf, size_t size)
{
	return writen(file->fd, buf, size);
}

159
ssize_t perf_data__write(struct perf_data *data,
160 161
			      void *buf, size_t size)
{
162
	return perf_data_file__write(&data->file, buf, size);
163
}
164

165
int perf_data__switch(struct perf_data *data,
166 167 168 169 170 171
			   const char *postfix,
			   size_t pos, bool at_exit)
{
	char *new_filepath;
	int ret;

172
	if (check_pipe(data))
173
		return -EINVAL;
174
	if (perf_data__is_read(data))
175 176
		return -EINVAL;

J
Jiri Olsa 已提交
177
	if (asprintf(&new_filepath, "%s.%s", data->path, postfix) < 0)
178 179 180 181 182 183
		return -ENOMEM;

	/*
	 * Only fire a warning, don't return error, continue fill
	 * original file.
	 */
J
Jiri Olsa 已提交
184 185
	if (rename(data->path, new_filepath))
		pr_warning("Failed to rename %s to %s\n", data->path, new_filepath);
186 187

	if (!at_exit) {
J
Jiri Olsa 已提交
188
		close(data->file.fd);
189
		ret = perf_data__open(data);
190 191 192
		if (ret < 0)
			goto out;

J
Jiri Olsa 已提交
193
		if (lseek(data->file.fd, pos, SEEK_SET) == (off_t)-1) {
194 195 196 197 198 199
			ret = -errno;
			pr_debug("Failed to lseek to %zu: %s",
				 pos, strerror(errno));
			goto out;
		}
	}
J
Jiri Olsa 已提交
200
	ret = data->file.fd;
201 202 203 204
out:
	free(new_filepath);
	return ret;
}