at v4.13 3.5 kB view raw
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 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; 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 91static 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 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} 134 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} 140 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}