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 11 static 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 32 static 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 48 static 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 87 static 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 95 static 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 106 int 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 117 void perf_data_file__close(struct perf_data_file *file) 118 { 119 close(file->fd); 120 } 121