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 } 181