Linux Perf
data.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/compiler.h>
3 #include <linux/kernel.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <unistd.h>
9 #include <string.h>
10 
11 #include "data.h"
12 #include "util.h"
13 #include "debug.h"
14 
15 static bool check_pipe(struct perf_data *data)
16 {
17  struct stat st;
18  bool is_pipe = false;
19  int fd = perf_data__is_read(data) ?
20  STDIN_FILENO : STDOUT_FILENO;
21 
22  if (!data->file.path) {
23  if (!fstat(fd, &st) && S_ISFIFO(st.st_mode))
24  is_pipe = true;
25  } else {
26  if (!strcmp(data->file.path, "-"))
27  is_pipe = true;
28  }
29 
30  if (is_pipe)
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  struct stat st;
39 
40  if (!stat(data->file.path, &st) && st.st_size) {
41  /* TODO check errors properly */
42  char oldname[PATH_MAX];
43  snprintf(oldname, sizeof(oldname), "%s.old",
44  data->file.path);
45  unlink(oldname);
46  rename(data->file.path, oldname);
47  }
48 
49  return 0;
50 }
51 
52 static int open_file_read(struct perf_data *data)
53 {
54  struct stat st;
55  int fd;
56  char sbuf[STRERR_BUFSIZE];
57 
58  fd = open(data->file.path, O_RDONLY);
59  if (fd < 0) {
60  int err = errno;
61 
62  pr_err("failed to open %s: %s", data->file.path,
63  str_error_r(err, sbuf, sizeof(sbuf)));
64  if (err == ENOENT && !strcmp(data->file.path, "perf.data"))
65  pr_err(" (try 'perf record' first)");
66  pr_err("\n");
67  return -err;
68  }
69 
70  if (fstat(fd, &st) < 0)
71  goto out_close;
72 
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",
75  data->file.path);
76  goto out_close;
77  }
78 
79  if (!st.st_size) {
80  pr_info("zero-sized data (%s), nothing to do!\n",
81  data->file.path);
82  goto out_close;
83  }
84 
85  data->size = st.st_size;
86  return fd;
87 
88  out_close:
89  close(fd);
90  return -1;
91 }
92 
93 static int open_file_write(struct perf_data *data)
94 {
95  int fd;
96  char sbuf[STRERR_BUFSIZE];
97 
98  if (check_backup(data))
99  return -1;
100 
101  fd = open(data->file.path, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC,
102  S_IRUSR|S_IWUSR);
103 
104  if (fd < 0)
105  pr_err("failed to open %s : %s\n", data->file.path,
106  str_error_r(errno, sbuf, sizeof(sbuf)));
107 
108  return fd;
109 }
110 
111 static int open_file(struct perf_data *data)
112 {
113  int fd;
114 
115  fd = perf_data__is_read(data) ?
116  open_file_read(data) : open_file_write(data);
117 
118  data->file.fd = fd;
119  return fd < 0 ? -1 : 0;
120 }
121 
123 {
124  if (check_pipe(data))
125  return 0;
126 
127  if (!data->file.path)
128  data->file.path = "perf.data";
129 
130  return open_file(data);
131 }
132 
134 {
135  close(data->file.fd);
136 }
137 
139  void *buf, size_t size)
140 {
141  return writen(file->fd, buf, size);
142 }
143 
145  void *buf, size_t size)
146 {
147  return perf_data_file__write(&data->file, buf, size);
148 }
149 
151  const char *postfix,
152  size_t pos, bool at_exit)
153 {
154  char *new_filepath;
155  int ret;
156 
157  if (check_pipe(data))
158  return -EINVAL;
159  if (perf_data__is_read(data))
160  return -EINVAL;
161 
162  if (asprintf(&new_filepath, "%s.%s", data->file.path, postfix) < 0)
163  return -ENOMEM;
164 
165  /*
166  * Only fire a warning, don't return error, continue fill
167  * original file.
168  */
169  if (rename(data->file.path, new_filepath))
170  pr_warning("Failed to rename %s to %s\n", data->file.path, new_filepath);
171 
172  if (!at_exit) {
173  close(data->file.fd);
174  ret = perf_data__open(data);
175  if (ret < 0)
176  goto out;
177 
178  if (lseek(data->file.fd, pos, SEEK_SET) == (off_t)-1) {
179  ret = -errno;
180  pr_debug("Failed to lseek to %zu: %s",
181  pos, strerror(errno));
182  goto out;
183  }
184  }
185  ret = data->file.fd;
186 out:
187  free(new_filepath);
188  return ret;
189 }
static int open_file_read(struct perf_data *data)
Definition: data.c:52
size_t size
Definition: evsel.c:60
int fd
Definition: data.h:14
static bool perf_data__is_read(struct perf_data *data)
Definition: data.h:25
def strerror(nr)
Definition: Util.py:86
dictionary data
Definition: stat-cpi.py:4
int int err
Definition: 5sec.c:44
ssize_t perf_data_file__write(struct perf_data_file *file, void *buf, size_t size)
Definition: data.c:138
struct perf_data_file file
Definition: data.h:18
#define pr_err(fmt,...)
Definition: json.h:21
#define pr_debug(fmt,...)
Definition: json.h:27
int perf_data__open(struct perf_data *data)
Definition: data.c:122
static int open_file(struct perf_data *data)
Definition: data.c:111
bool is_pipe
Definition: data.h:19
#define PATH_MAX
Definition: jevents.c:1042
unsigned long size
Definition: data.h:21
static bool check_pipe(struct perf_data *data)
Definition: data.c:15
static int check_backup(struct perf_data *data)
Definition: data.c:36
Definition: data.h:17
ssize_t perf_data__write(struct perf_data *data, void *buf, size_t size)
Definition: data.c:144
#define pr_info(fmt,...)
Definition: json.h:24
#define STRERR_BUFSIZE
Definition: debug.h:43
void free(void *)
ssize_t writen(int fd, const void *buf, size_t n)
Definition: util.c:359
#define pr_warning(fmt,...)
Definition: debug.h:25
bool force
Definition: data.h:20
#define O_CLOEXEC
Definition: util.h:79
int perf_data__switch(struct perf_data *data, const char *postfix, size_t pos, bool at_exit)
Definition: data.c:150
void perf_data__close(struct perf_data *data)
Definition: data.c:133
const char * path
Definition: data.h:13
static int open_file_write(struct perf_data *data)
Definition: data.c:93