blob: e84bbc8ec058916c968ae940ae662746495efe67 [file] [log] [blame]
Jiri Olsa6a4d98d2013-10-15 16:27:33 +02001#include <linux/compiler.h>
2#include <linux/kernel.h>
3#include <sys/types.h>
4#include <sys/stat.h>
Arnaldo Carvalho de Meloa43783a2017-04-18 10:46:11 -03005#include <errno.h>
Jiri Olsa6a4d98d2013-10-15 16:27:33 +02006#include <unistd.h>
7#include <string.h>
8
9#include "data.h"
10#include "util.h"
Jiri Olsa84f5d362014-07-14 23:46:48 +020011#include "debug.h"
Jiri Olsa6a4d98d2013-10-15 16:27:33 +020012
13static bool check_pipe(struct perf_data_file *file)
14{
15 struct stat st;
16 bool is_pipe = false;
17 int fd = perf_data_file__is_read(file) ?
18 STDIN_FILENO : STDOUT_FILENO;
19
20 if (!file->path) {
21 if (!fstat(fd, &st) && S_ISFIFO(st.st_mode))
22 is_pipe = true;
23 } else {
24 if (!strcmp(file->path, "-"))
25 is_pipe = true;
26 }
27
28 if (is_pipe)
29 file->fd = fd;
30
31 return file->is_pipe = is_pipe;
32}
33
34static int check_backup(struct perf_data_file *file)
35{
36 struct stat st;
37
38 if (!stat(file->path, &st) && st.st_size) {
39 /* TODO check errors properly */
40 char oldname[PATH_MAX];
41 snprintf(oldname, sizeof(oldname), "%s.old",
42 file->path);
43 unlink(oldname);
44 rename(file->path, oldname);
45 }
46
47 return 0;
48}
49
50static int open_file_read(struct perf_data_file *file)
51{
52 struct stat st;
53 int fd;
Masami Hiramatsu6e81c742014-08-14 02:22:36 +000054 char sbuf[STRERR_BUFSIZE];
Jiri Olsa6a4d98d2013-10-15 16:27:33 +020055
56 fd = open(file->path, O_RDONLY);
57 if (fd < 0) {
58 int err = errno;
59
Masami Hiramatsu6e81c742014-08-14 02:22:36 +000060 pr_err("failed to open %s: %s", file->path,
Arnaldo Carvalho de Meloc8b5f2c2016-07-06 11:56:20 -030061 str_error_r(err, sbuf, sizeof(sbuf)));
Jiri Olsa6a4d98d2013-10-15 16:27:33 +020062 if (err == ENOENT && !strcmp(file->path, "perf.data"))
63 pr_err(" (try 'perf record' first)");
64 pr_err("\n");
65 return -err;
66 }
67
68 if (fstat(fd, &st) < 0)
69 goto out_close;
70
71 if (!file->force && st.st_uid && (st.st_uid != geteuid())) {
Arnaldo Carvalho de Melo071266b2014-07-08 12:40:11 -030072 pr_err("File %s not owned by current user or root (use -f to override)\n",
Jiri Olsa6a4d98d2013-10-15 16:27:33 +020073 file->path);
74 goto out_close;
75 }
76
77 if (!st.st_size) {
78 pr_info("zero-sized file (%s), nothing to do!\n",
79 file->path);
80 goto out_close;
81 }
82
83 file->size = st.st_size;
84 return fd;
85
86 out_close:
87 close(fd);
88 return -1;
89}
90
91static int open_file_write(struct perf_data_file *file)
92{
Adrien BAKffa91882014-04-18 11:00:43 +090093 int fd;
Masami Hiramatsu6e81c742014-08-14 02:22:36 +000094 char sbuf[STRERR_BUFSIZE];
Adrien BAKffa91882014-04-18 11:00:43 +090095
Jiri Olsa6a4d98d2013-10-15 16:27:33 +020096 if (check_backup(file))
97 return -1;
98
Adrien BAKffa91882014-04-18 11:00:43 +090099 fd = open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR);
100
101 if (fd < 0)
Masami Hiramatsu6e81c742014-08-14 02:22:36 +0000102 pr_err("failed to open %s : %s\n", file->path,
Arnaldo Carvalho de Meloc8b5f2c2016-07-06 11:56:20 -0300103 str_error_r(errno, sbuf, sizeof(sbuf)));
Adrien BAKffa91882014-04-18 11:00:43 +0900104
105 return fd;
Jiri Olsa6a4d98d2013-10-15 16:27:33 +0200106}
107
108static int open_file(struct perf_data_file *file)
109{
110 int fd;
111
112 fd = perf_data_file__is_read(file) ?
113 open_file_read(file) : open_file_write(file);
114
115 file->fd = fd;
116 return fd < 0 ? -1 : 0;
117}
118
119int perf_data_file__open(struct perf_data_file *file)
120{
121 if (check_pipe(file))
122 return 0;
123
124 if (!file->path)
125 file->path = "perf.data";
126
127 return open_file(file);
128}
129
130void perf_data_file__close(struct perf_data_file *file)
131{
132 close(file->fd);
133}
Jiri Olsa6f9a3172013-11-28 11:30:17 +0100134
135ssize_t perf_data_file__write(struct perf_data_file *file,
136 void *buf, size_t size)
137{
138 return writen(file->fd, buf, size);
139}
Wang Nan040f9912016-04-13 08:21:05 +0000140
141int perf_data_file__switch(struct perf_data_file *file,
142 const char *postfix,
143 size_t pos, bool at_exit)
144{
145 char *new_filepath;
146 int ret;
147
148 if (check_pipe(file))
149 return -EINVAL;
150 if (perf_data_file__is_read(file))
151 return -EINVAL;
152
153 if (asprintf(&new_filepath, "%s.%s", file->path, postfix) < 0)
154 return -ENOMEM;
155
156 /*
157 * Only fire a warning, don't return error, continue fill
158 * original file.
159 */
160 if (rename(file->path, new_filepath))
161 pr_warning("Failed to rename %s to %s\n", file->path, new_filepath);
162
163 if (!at_exit) {
164 close(file->fd);
165 ret = perf_data_file__open(file);
166 if (ret < 0)
167 goto out;
168
169 if (lseek(file->fd, pos, SEEK_SET) == (off_t)-1) {
170 ret = -errno;
171 pr_debug("Failed to lseek to %zu: %s",
172 pos, strerror(errno));
173 goto out;
174 }
175 }
176 ret = file->fd;
177out:
178 free(new_filepath);
179 return ret;
180}