]> git.karo-electronics.de Git - karo-tx-linux.git/blob - tools/perf/util/data.c
Merge tag 'perf-core-for-mingo-4.12-20170503' of git://git.kernel.org/pub/scm/linux...
[karo-tx-linux.git] / tools / perf / util / data.c
1 #include <linux/compiler.h>
2 #include <linux/kernel.h>
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <errno.h>
6 #include <unistd.h>
7 #include <string.h>
8
9 #include "data.h"
10 #include "util.h"
11 #include "debug.h"
12
13 static 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
34 static 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
50 static int open_file_read(struct perf_data_file *file)
51 {
52         struct stat st;
53         int fd;
54         char sbuf[STRERR_BUFSIZE];
55
56         fd = open(file->path, O_RDONLY);
57         if (fd < 0) {
58                 int err = errno;
59
60                 pr_err("failed to open %s: %s", file->path,
61                         str_error_r(err, sbuf, sizeof(sbuf)));
62                 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())) {
72                 pr_err("File %s not owned by current user or root (use -f to override)\n",
73                        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
91 static int open_file_write(struct perf_data_file *file)
92 {
93         int fd;
94         char sbuf[STRERR_BUFSIZE];
95
96         if (check_backup(file))
97                 return -1;
98
99         fd = open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR);
100
101         if (fd < 0)
102                 pr_err("failed to open %s : %s\n", file->path,
103                         str_error_r(errno, sbuf, sizeof(sbuf)));
104
105         return fd;
106 }
107
108 static 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
119 int 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
130 void perf_data_file__close(struct perf_data_file *file)
131 {
132         close(file->fd);
133 }
134
135 ssize_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 }
140
141 int 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;
177 out:
178         free(new_filepath);
179         return ret;
180 }