1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/compiler.h>
3 #include <linux/kernel.h>
11 #include <sys/types.h>
18 static void close_dir(struct perf_data_file *files, int nr)
27 void perf_data__close_dir(struct perf_data *data)
29 close_dir(data->dir.files, data->dir.nr);
32 int perf_data__create_dir(struct perf_data *data, int nr)
34 struct perf_data_file *files = NULL;
37 files = zalloc(nr * sizeof(*files));
41 data->dir.files = files;
44 for (i = 0; i < nr; i++) {
45 struct perf_data_file *file = &files[i];
47 if (asprintf(&file->path, "%s/data.%d", data->path, i) < 0)
50 ret = open(file->path, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
64 int perf_data__open_dir(struct perf_data *data)
66 struct perf_data_file *files = NULL;
72 dir = opendir(data->path);
76 while ((dent = readdir(dir)) != NULL) {
77 struct perf_data_file *file;
81 snprintf(path, sizeof(path), "%s/%s", data->path, dent->d_name);
85 if (!S_ISREG(st.st_mode) || strncmp(dent->d_name, "data", 4))
90 file = realloc(files, (nr + 1) * sizeof(*files));
97 file->path = strdup(path);
101 ret = open(file->path, O_RDONLY);
106 file->size = st.st_size;
112 data->dir.files = files;
117 close_dir(files, nr);
121 static bool check_pipe(struct perf_data *data)
124 bool is_pipe = false;
125 int fd = perf_data__is_read(data) ?
126 STDIN_FILENO : STDOUT_FILENO;
129 if (!fstat(fd, &st) && S_ISFIFO(st.st_mode))
132 if (!strcmp(data->path, "-"))
139 return data->is_pipe = is_pipe;
142 static int check_backup(struct perf_data *data)
146 if (perf_data__is_read(data))
149 if (!stat(data->path, &st) && st.st_size) {
150 char oldname[PATH_MAX];
153 snprintf(oldname, sizeof(oldname), "%s.old",
156 ret = rm_rf_perf_data(oldname);
158 pr_err("Can't remove old data: %s (%s)\n",
160 "Unknown file found" : strerror(errno),
165 if (rename(data->path, oldname)) {
166 pr_err("Can't move data: %s (%s to %s)\n",
168 data->path, oldname);
176 static int open_file_read(struct perf_data *data)
180 char sbuf[STRERR_BUFSIZE];
182 fd = open(data->file.path, O_RDONLY);
186 pr_err("failed to open %s: %s", data->file.path,
187 str_error_r(err, sbuf, sizeof(sbuf)));
188 if (err == ENOENT && !strcmp(data->file.path, "perf.data"))
189 pr_err(" (try 'perf record' first)");
194 if (fstat(fd, &st) < 0)
197 if (!data->force && st.st_uid && (st.st_uid != geteuid())) {
198 pr_err("File %s not owned by current user or root (use -f to override)\n",
204 pr_info("zero-sized data (%s), nothing to do!\n",
209 data->file.size = st.st_size;
217 static int open_file_write(struct perf_data *data)
220 char sbuf[STRERR_BUFSIZE];
222 fd = open(data->file.path, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC,
226 pr_err("failed to open %s : %s\n", data->file.path,
227 str_error_r(errno, sbuf, sizeof(sbuf)));
232 static int open_file(struct perf_data *data)
236 fd = perf_data__is_read(data) ?
237 open_file_read(data) : open_file_write(data);
240 zfree(&data->file.path);
248 static int open_file_dup(struct perf_data *data)
250 data->file.path = strdup(data->path);
251 if (!data->file.path)
254 return open_file(data);
257 int perf_data__open(struct perf_data *data)
259 if (check_pipe(data))
263 data->path = "perf.data";
265 if (check_backup(data))
268 return open_file_dup(data);
271 void perf_data__close(struct perf_data *data)
273 zfree(&data->file.path);
274 close(data->file.fd);
277 ssize_t perf_data_file__write(struct perf_data_file *file,
278 void *buf, size_t size)
280 return writen(file->fd, buf, size);
283 ssize_t perf_data__write(struct perf_data *data,
284 void *buf, size_t size)
286 return perf_data_file__write(&data->file, buf, size);
289 int perf_data__switch(struct perf_data *data,
291 size_t pos, bool at_exit)
296 if (check_pipe(data))
298 if (perf_data__is_read(data))
301 if (asprintf(&new_filepath, "%s.%s", data->path, postfix) < 0)
305 * Only fire a warning, don't return error, continue fill
308 if (rename(data->path, new_filepath))
309 pr_warning("Failed to rename %s to %s\n", data->path, new_filepath);
312 close(data->file.fd);
313 ret = perf_data__open(data);
317 if (lseek(data->file.fd, pos, SEEK_SET) == (off_t)-1) {
319 pr_debug("Failed to lseek to %zu: %s",
320 pos, strerror(errno));