at v4.14 3.7 kB view raw
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 <unistd.h> 8#include <string.h> 9 10#include "data.h" 11#include "util.h" 12#include "debug.h" 13 14#ifndef O_CLOEXEC 15#ifdef __sparc__ 16#define O_CLOEXEC 0x400000 17#elif defined(__alpha__) || defined(__hppa__) 18#define O_CLOEXEC 010000000 19#else 20#define O_CLOEXEC 02000000 21#endif 22#endif 23 24static bool check_pipe(struct perf_data_file *file) 25{ 26 struct stat st; 27 bool is_pipe = false; 28 int fd = perf_data_file__is_read(file) ? 29 STDIN_FILENO : STDOUT_FILENO; 30 31 if (!file->path) { 32 if (!fstat(fd, &st) && S_ISFIFO(st.st_mode)) 33 is_pipe = true; 34 } else { 35 if (!strcmp(file->path, "-")) 36 is_pipe = true; 37 } 38 39 if (is_pipe) 40 file->fd = fd; 41 42 return file->is_pipe = is_pipe; 43} 44 45static int check_backup(struct perf_data_file *file) 46{ 47 struct stat st; 48 49 if (!stat(file->path, &st) && st.st_size) { 50 /* TODO check errors properly */ 51 char oldname[PATH_MAX]; 52 snprintf(oldname, sizeof(oldname), "%s.old", 53 file->path); 54 unlink(oldname); 55 rename(file->path, oldname); 56 } 57 58 return 0; 59} 60 61static int open_file_read(struct perf_data_file *file) 62{ 63 struct stat st; 64 int fd; 65 char sbuf[STRERR_BUFSIZE]; 66 67 fd = open(file->path, O_RDONLY); 68 if (fd < 0) { 69 int err = errno; 70 71 pr_err("failed to open %s: %s", file->path, 72 str_error_r(err, sbuf, sizeof(sbuf))); 73 if (err == ENOENT && !strcmp(file->path, "perf.data")) 74 pr_err(" (try 'perf record' first)"); 75 pr_err("\n"); 76 return -err; 77 } 78 79 if (fstat(fd, &st) < 0) 80 goto out_close; 81 82 if (!file->force && st.st_uid && (st.st_uid != geteuid())) { 83 pr_err("File %s not owned by current user or root (use -f to override)\n", 84 file->path); 85 goto out_close; 86 } 87 88 if (!st.st_size) { 89 pr_info("zero-sized file (%s), nothing to do!\n", 90 file->path); 91 goto out_close; 92 } 93 94 file->size = st.st_size; 95 return fd; 96 97 out_close: 98 close(fd); 99 return -1; 100} 101 102static int open_file_write(struct perf_data_file *file) 103{ 104 int fd; 105 char sbuf[STRERR_BUFSIZE]; 106 107 if (check_backup(file)) 108 return -1; 109 110 fd = open(file->path, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC, 111 S_IRUSR|S_IWUSR); 112 113 if (fd < 0) 114 pr_err("failed to open %s : %s\n", file->path, 115 str_error_r(errno, sbuf, sizeof(sbuf))); 116 117 return fd; 118} 119 120static int open_file(struct perf_data_file *file) 121{ 122 int fd; 123 124 fd = perf_data_file__is_read(file) ? 125 open_file_read(file) : open_file_write(file); 126 127 file->fd = fd; 128 return fd < 0 ? -1 : 0; 129} 130 131int perf_data_file__open(struct perf_data_file *file) 132{ 133 if (check_pipe(file)) 134 return 0; 135 136 if (!file->path) 137 file->path = "perf.data"; 138 139 return open_file(file); 140} 141 142void perf_data_file__close(struct perf_data_file *file) 143{ 144 close(file->fd); 145} 146 147ssize_t perf_data_file__write(struct perf_data_file *file, 148 void *buf, size_t size) 149{ 150 return writen(file->fd, buf, size); 151} 152 153int perf_data_file__switch(struct perf_data_file *file, 154 const char *postfix, 155 size_t pos, bool at_exit) 156{ 157 char *new_filepath; 158 int ret; 159 160 if (check_pipe(file)) 161 return -EINVAL; 162 if (perf_data_file__is_read(file)) 163 return -EINVAL; 164 165 if (asprintf(&new_filepath, "%s.%s", file->path, postfix) < 0) 166 return -ENOMEM; 167 168 /* 169 * Only fire a warning, don't return error, continue fill 170 * original file. 171 */ 172 if (rename(file->path, new_filepath)) 173 pr_warning("Failed to rename %s to %s\n", file->path, new_filepath); 174 175 if (!at_exit) { 176 close(file->fd); 177 ret = perf_data_file__open(file); 178 if (ret < 0) 179 goto out; 180 181 if (lseek(file->fd, pos, SEEK_SET) == (off_t)-1) { 182 ret = -errno; 183 pr_debug("Failed to lseek to %zu: %s", 184 pos, strerror(errno)); 185 goto out; 186 } 187 } 188 ret = file->fd; 189out: 190 free(new_filepath); 191 return ret; 192}