at v3.13 2.2 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 <unistd.h> 6#include <string.h> 7 8#include "data.h" 9#include "util.h" 10 11static bool check_pipe(struct perf_data_file *file) 12{ 13 struct stat st; 14 bool is_pipe = false; 15 int fd = perf_data_file__is_read(file) ? 16 STDIN_FILENO : STDOUT_FILENO; 17 18 if (!file->path) { 19 if (!fstat(fd, &st) && S_ISFIFO(st.st_mode)) 20 is_pipe = true; 21 } else { 22 if (!strcmp(file->path, "-")) 23 is_pipe = true; 24 } 25 26 if (is_pipe) 27 file->fd = fd; 28 29 return file->is_pipe = is_pipe; 30} 31 32static int check_backup(struct perf_data_file *file) 33{ 34 struct stat st; 35 36 if (!stat(file->path, &st) && st.st_size) { 37 /* TODO check errors properly */ 38 char oldname[PATH_MAX]; 39 snprintf(oldname, sizeof(oldname), "%s.old", 40 file->path); 41 unlink(oldname); 42 rename(file->path, oldname); 43 } 44 45 return 0; 46} 47 48static int open_file_read(struct perf_data_file *file) 49{ 50 struct stat st; 51 int fd; 52 53 fd = open(file->path, O_RDONLY); 54 if (fd < 0) { 55 int err = errno; 56 57 pr_err("failed to open %s: %s", file->path, strerror(err)); 58 if (err == ENOENT && !strcmp(file->path, "perf.data")) 59 pr_err(" (try 'perf record' first)"); 60 pr_err("\n"); 61 return -err; 62 } 63 64 if (fstat(fd, &st) < 0) 65 goto out_close; 66 67 if (!file->force && st.st_uid && (st.st_uid != geteuid())) { 68 pr_err("file %s not owned by current user or root\n", 69 file->path); 70 goto out_close; 71 } 72 73 if (!st.st_size) { 74 pr_info("zero-sized file (%s), nothing to do!\n", 75 file->path); 76 goto out_close; 77 } 78 79 file->size = st.st_size; 80 return fd; 81 82 out_close: 83 close(fd); 84 return -1; 85} 86 87static int open_file_write(struct perf_data_file *file) 88{ 89 if (check_backup(file)) 90 return -1; 91 92 return open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR); 93} 94 95static int open_file(struct perf_data_file *file) 96{ 97 int fd; 98 99 fd = perf_data_file__is_read(file) ? 100 open_file_read(file) : open_file_write(file); 101 102 file->fd = fd; 103 return fd < 0 ? -1 : 0; 104} 105 106int perf_data_file__open(struct perf_data_file *file) 107{ 108 if (check_pipe(file)) 109 return 0; 110 111 if (!file->path) 112 file->path = "perf.data"; 113 114 return open_file(file); 115} 116 117void perf_data_file__close(struct perf_data_file *file) 118{ 119 close(file->fd); 120}