18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include <linux/compiler.h> 38c2ecf20Sopenharmony_ci#include <linux/kernel.h> 48c2ecf20Sopenharmony_ci#include <linux/string.h> 58c2ecf20Sopenharmony_ci#include <linux/zalloc.h> 68c2ecf20Sopenharmony_ci#include <sys/types.h> 78c2ecf20Sopenharmony_ci#include <sys/stat.h> 88c2ecf20Sopenharmony_ci#include <errno.h> 98c2ecf20Sopenharmony_ci#include <fcntl.h> 108c2ecf20Sopenharmony_ci#include <unistd.h> 118c2ecf20Sopenharmony_ci#include <string.h> 128c2ecf20Sopenharmony_ci#include <asm/bug.h> 138c2ecf20Sopenharmony_ci#include <dirent.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include "data.h" 168c2ecf20Sopenharmony_ci#include "util.h" // rm_rf_perf_data() 178c2ecf20Sopenharmony_ci#include "debug.h" 188c2ecf20Sopenharmony_ci#include "header.h" 198c2ecf20Sopenharmony_ci#include <internal/lib.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cistatic void close_dir(struct perf_data_file *files, int nr) 228c2ecf20Sopenharmony_ci{ 238c2ecf20Sopenharmony_ci while (--nr >= 0) { 248c2ecf20Sopenharmony_ci close(files[nr].fd); 258c2ecf20Sopenharmony_ci zfree(&files[nr].path); 268c2ecf20Sopenharmony_ci } 278c2ecf20Sopenharmony_ci free(files); 288c2ecf20Sopenharmony_ci} 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_civoid perf_data__close_dir(struct perf_data *data) 318c2ecf20Sopenharmony_ci{ 328c2ecf20Sopenharmony_ci close_dir(data->dir.files, data->dir.nr); 338c2ecf20Sopenharmony_ci} 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ciint perf_data__create_dir(struct perf_data *data, int nr) 368c2ecf20Sopenharmony_ci{ 378c2ecf20Sopenharmony_ci struct perf_data_file *files = NULL; 388c2ecf20Sopenharmony_ci int i, ret; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci if (WARN_ON(!data->is_dir)) 418c2ecf20Sopenharmony_ci return -EINVAL; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci files = zalloc(nr * sizeof(*files)); 448c2ecf20Sopenharmony_ci if (!files) 458c2ecf20Sopenharmony_ci return -ENOMEM; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci for (i = 0; i < nr; i++) { 488c2ecf20Sopenharmony_ci struct perf_data_file *file = &files[i]; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci ret = asprintf(&file->path, "%s/data.%d", data->path, i); 518c2ecf20Sopenharmony_ci if (ret < 0) 528c2ecf20Sopenharmony_ci goto out_err; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci ret = open(file->path, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR); 558c2ecf20Sopenharmony_ci if (ret < 0) 568c2ecf20Sopenharmony_ci goto out_err; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci file->fd = ret; 598c2ecf20Sopenharmony_ci } 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci data->dir.version = PERF_DIR_VERSION; 628c2ecf20Sopenharmony_ci data->dir.files = files; 638c2ecf20Sopenharmony_ci data->dir.nr = nr; 648c2ecf20Sopenharmony_ci return 0; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ciout_err: 678c2ecf20Sopenharmony_ci close_dir(files, i); 688c2ecf20Sopenharmony_ci return ret; 698c2ecf20Sopenharmony_ci} 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ciint perf_data__open_dir(struct perf_data *data) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci struct perf_data_file *files = NULL; 748c2ecf20Sopenharmony_ci struct dirent *dent; 758c2ecf20Sopenharmony_ci int ret = -1; 768c2ecf20Sopenharmony_ci DIR *dir; 778c2ecf20Sopenharmony_ci int nr = 0; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci /* 808c2ecf20Sopenharmony_ci * Directory containing a single regular perf data file which is already 818c2ecf20Sopenharmony_ci * open, means there is nothing more to do here. 828c2ecf20Sopenharmony_ci */ 838c2ecf20Sopenharmony_ci if (perf_data__is_single_file(data)) 848c2ecf20Sopenharmony_ci return 0; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci if (WARN_ON(!data->is_dir)) 878c2ecf20Sopenharmony_ci return -EINVAL; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci /* The version is provided by DIR_FORMAT feature. */ 908c2ecf20Sopenharmony_ci if (WARN_ON(data->dir.version != PERF_DIR_VERSION)) 918c2ecf20Sopenharmony_ci return -1; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci dir = opendir(data->path); 948c2ecf20Sopenharmony_ci if (!dir) 958c2ecf20Sopenharmony_ci return -EINVAL; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci while ((dent = readdir(dir)) != NULL) { 988c2ecf20Sopenharmony_ci struct perf_data_file *file; 998c2ecf20Sopenharmony_ci char path[PATH_MAX]; 1008c2ecf20Sopenharmony_ci struct stat st; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci snprintf(path, sizeof(path), "%s/%s", data->path, dent->d_name); 1038c2ecf20Sopenharmony_ci if (stat(path, &st)) 1048c2ecf20Sopenharmony_ci continue; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci if (!S_ISREG(st.st_mode) || strncmp(dent->d_name, "data.", 5)) 1078c2ecf20Sopenharmony_ci continue; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci ret = -ENOMEM; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci file = realloc(files, (nr + 1) * sizeof(*files)); 1128c2ecf20Sopenharmony_ci if (!file) 1138c2ecf20Sopenharmony_ci goto out_err; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci files = file; 1168c2ecf20Sopenharmony_ci file = &files[nr++]; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci file->path = strdup(path); 1198c2ecf20Sopenharmony_ci if (!file->path) 1208c2ecf20Sopenharmony_ci goto out_err; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci ret = open(file->path, O_RDONLY); 1238c2ecf20Sopenharmony_ci if (ret < 0) 1248c2ecf20Sopenharmony_ci goto out_err; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci file->fd = ret; 1278c2ecf20Sopenharmony_ci file->size = st.st_size; 1288c2ecf20Sopenharmony_ci } 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci closedir(dir); 1318c2ecf20Sopenharmony_ci if (!files) 1328c2ecf20Sopenharmony_ci return -EINVAL; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci data->dir.files = files; 1358c2ecf20Sopenharmony_ci data->dir.nr = nr; 1368c2ecf20Sopenharmony_ci return 0; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ciout_err: 1398c2ecf20Sopenharmony_ci closedir(dir); 1408c2ecf20Sopenharmony_ci close_dir(files, nr); 1418c2ecf20Sopenharmony_ci return ret; 1428c2ecf20Sopenharmony_ci} 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ciint perf_data__update_dir(struct perf_data *data) 1458c2ecf20Sopenharmony_ci{ 1468c2ecf20Sopenharmony_ci int i; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci if (WARN_ON(!data->is_dir)) 1498c2ecf20Sopenharmony_ci return -EINVAL; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci for (i = 0; i < data->dir.nr; i++) { 1528c2ecf20Sopenharmony_ci struct perf_data_file *file = &data->dir.files[i]; 1538c2ecf20Sopenharmony_ci struct stat st; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci if (fstat(file->fd, &st)) 1568c2ecf20Sopenharmony_ci return -1; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci file->size = st.st_size; 1598c2ecf20Sopenharmony_ci } 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci return 0; 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cistatic bool check_pipe(struct perf_data *data) 1658c2ecf20Sopenharmony_ci{ 1668c2ecf20Sopenharmony_ci struct stat st; 1678c2ecf20Sopenharmony_ci bool is_pipe = false; 1688c2ecf20Sopenharmony_ci int fd = perf_data__is_read(data) ? 1698c2ecf20Sopenharmony_ci STDIN_FILENO : STDOUT_FILENO; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci if (!data->path) { 1728c2ecf20Sopenharmony_ci if (!fstat(fd, &st) && S_ISFIFO(st.st_mode)) 1738c2ecf20Sopenharmony_ci is_pipe = true; 1748c2ecf20Sopenharmony_ci } else { 1758c2ecf20Sopenharmony_ci if (!strcmp(data->path, "-")) 1768c2ecf20Sopenharmony_ci is_pipe = true; 1778c2ecf20Sopenharmony_ci } 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci if (is_pipe) 1808c2ecf20Sopenharmony_ci data->file.fd = fd; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci return data->is_pipe = is_pipe; 1838c2ecf20Sopenharmony_ci} 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_cistatic int check_backup(struct perf_data *data) 1868c2ecf20Sopenharmony_ci{ 1878c2ecf20Sopenharmony_ci struct stat st; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci if (perf_data__is_read(data)) 1908c2ecf20Sopenharmony_ci return 0; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci if (!stat(data->path, &st) && st.st_size) { 1938c2ecf20Sopenharmony_ci char oldname[PATH_MAX]; 1948c2ecf20Sopenharmony_ci int ret; 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci snprintf(oldname, sizeof(oldname), "%s.old", 1978c2ecf20Sopenharmony_ci data->path); 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci ret = rm_rf_perf_data(oldname); 2008c2ecf20Sopenharmony_ci if (ret) { 2018c2ecf20Sopenharmony_ci pr_err("Can't remove old data: %s (%s)\n", 2028c2ecf20Sopenharmony_ci ret == -2 ? 2038c2ecf20Sopenharmony_ci "Unknown file found" : strerror(errno), 2048c2ecf20Sopenharmony_ci oldname); 2058c2ecf20Sopenharmony_ci return -1; 2068c2ecf20Sopenharmony_ci } 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci if (rename(data->path, oldname)) { 2098c2ecf20Sopenharmony_ci pr_err("Can't move data: %s (%s to %s)\n", 2108c2ecf20Sopenharmony_ci strerror(errno), 2118c2ecf20Sopenharmony_ci data->path, oldname); 2128c2ecf20Sopenharmony_ci return -1; 2138c2ecf20Sopenharmony_ci } 2148c2ecf20Sopenharmony_ci } 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci return 0; 2178c2ecf20Sopenharmony_ci} 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_cistatic bool is_dir(struct perf_data *data) 2208c2ecf20Sopenharmony_ci{ 2218c2ecf20Sopenharmony_ci struct stat st; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci if (stat(data->path, &st)) 2248c2ecf20Sopenharmony_ci return false; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci return (st.st_mode & S_IFMT) == S_IFDIR; 2278c2ecf20Sopenharmony_ci} 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_cistatic int open_file_read(struct perf_data *data) 2308c2ecf20Sopenharmony_ci{ 2318c2ecf20Sopenharmony_ci struct stat st; 2328c2ecf20Sopenharmony_ci int fd; 2338c2ecf20Sopenharmony_ci char sbuf[STRERR_BUFSIZE]; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci fd = open(data->file.path, O_RDONLY); 2368c2ecf20Sopenharmony_ci if (fd < 0) { 2378c2ecf20Sopenharmony_ci int err = errno; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci pr_err("failed to open %s: %s", data->file.path, 2408c2ecf20Sopenharmony_ci str_error_r(err, sbuf, sizeof(sbuf))); 2418c2ecf20Sopenharmony_ci if (err == ENOENT && !strcmp(data->file.path, "perf.data")) 2428c2ecf20Sopenharmony_ci pr_err(" (try 'perf record' first)"); 2438c2ecf20Sopenharmony_ci pr_err("\n"); 2448c2ecf20Sopenharmony_ci return -err; 2458c2ecf20Sopenharmony_ci } 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci if (fstat(fd, &st) < 0) 2488c2ecf20Sopenharmony_ci goto out_close; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci if (!data->force && st.st_uid && (st.st_uid != geteuid())) { 2518c2ecf20Sopenharmony_ci pr_err("File %s not owned by current user or root (use -f to override)\n", 2528c2ecf20Sopenharmony_ci data->file.path); 2538c2ecf20Sopenharmony_ci goto out_close; 2548c2ecf20Sopenharmony_ci } 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci if (!st.st_size) { 2578c2ecf20Sopenharmony_ci pr_info("zero-sized data (%s), nothing to do!\n", 2588c2ecf20Sopenharmony_ci data->file.path); 2598c2ecf20Sopenharmony_ci goto out_close; 2608c2ecf20Sopenharmony_ci } 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci data->file.size = st.st_size; 2638c2ecf20Sopenharmony_ci return fd; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci out_close: 2668c2ecf20Sopenharmony_ci close(fd); 2678c2ecf20Sopenharmony_ci return -1; 2688c2ecf20Sopenharmony_ci} 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_cistatic int open_file_write(struct perf_data *data) 2718c2ecf20Sopenharmony_ci{ 2728c2ecf20Sopenharmony_ci int fd; 2738c2ecf20Sopenharmony_ci char sbuf[STRERR_BUFSIZE]; 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci fd = open(data->file.path, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC, 2768c2ecf20Sopenharmony_ci S_IRUSR|S_IWUSR); 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci if (fd < 0) 2798c2ecf20Sopenharmony_ci pr_err("failed to open %s : %s\n", data->file.path, 2808c2ecf20Sopenharmony_ci str_error_r(errno, sbuf, sizeof(sbuf))); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci return fd; 2838c2ecf20Sopenharmony_ci} 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_cistatic int open_file(struct perf_data *data) 2868c2ecf20Sopenharmony_ci{ 2878c2ecf20Sopenharmony_ci int fd; 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci fd = perf_data__is_read(data) ? 2908c2ecf20Sopenharmony_ci open_file_read(data) : open_file_write(data); 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci if (fd < 0) { 2938c2ecf20Sopenharmony_ci zfree(&data->file.path); 2948c2ecf20Sopenharmony_ci return -1; 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci data->file.fd = fd; 2988c2ecf20Sopenharmony_ci return 0; 2998c2ecf20Sopenharmony_ci} 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_cistatic int open_file_dup(struct perf_data *data) 3028c2ecf20Sopenharmony_ci{ 3038c2ecf20Sopenharmony_ci data->file.path = strdup(data->path); 3048c2ecf20Sopenharmony_ci if (!data->file.path) 3058c2ecf20Sopenharmony_ci return -ENOMEM; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci return open_file(data); 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_cistatic int open_dir(struct perf_data *data) 3118c2ecf20Sopenharmony_ci{ 3128c2ecf20Sopenharmony_ci int ret; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci /* 3158c2ecf20Sopenharmony_ci * So far we open only the header, so we can read the data version and 3168c2ecf20Sopenharmony_ci * layout. 3178c2ecf20Sopenharmony_ci */ 3188c2ecf20Sopenharmony_ci if (asprintf(&data->file.path, "%s/data", data->path) < 0) 3198c2ecf20Sopenharmony_ci return -1; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci if (perf_data__is_write(data) && 3228c2ecf20Sopenharmony_ci mkdir(data->path, S_IRWXU) < 0) 3238c2ecf20Sopenharmony_ci return -1; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci ret = open_file(data); 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci /* Cleanup whatever we managed to create so far. */ 3288c2ecf20Sopenharmony_ci if (ret && perf_data__is_write(data)) 3298c2ecf20Sopenharmony_ci rm_rf_perf_data(data->path); 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci return ret; 3328c2ecf20Sopenharmony_ci} 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ciint perf_data__open(struct perf_data *data) 3358c2ecf20Sopenharmony_ci{ 3368c2ecf20Sopenharmony_ci if (check_pipe(data)) 3378c2ecf20Sopenharmony_ci return 0; 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci if (!data->path) 3408c2ecf20Sopenharmony_ci data->path = "perf.data"; 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci if (check_backup(data)) 3438c2ecf20Sopenharmony_ci return -1; 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci if (perf_data__is_read(data)) 3468c2ecf20Sopenharmony_ci data->is_dir = is_dir(data); 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci return perf_data__is_dir(data) ? 3498c2ecf20Sopenharmony_ci open_dir(data) : open_file_dup(data); 3508c2ecf20Sopenharmony_ci} 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_civoid perf_data__close(struct perf_data *data) 3538c2ecf20Sopenharmony_ci{ 3548c2ecf20Sopenharmony_ci if (perf_data__is_dir(data)) 3558c2ecf20Sopenharmony_ci perf_data__close_dir(data); 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci zfree(&data->file.path); 3588c2ecf20Sopenharmony_ci close(data->file.fd); 3598c2ecf20Sopenharmony_ci} 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_cissize_t perf_data_file__write(struct perf_data_file *file, 3628c2ecf20Sopenharmony_ci void *buf, size_t size) 3638c2ecf20Sopenharmony_ci{ 3648c2ecf20Sopenharmony_ci return writen(file->fd, buf, size); 3658c2ecf20Sopenharmony_ci} 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_cissize_t perf_data__write(struct perf_data *data, 3688c2ecf20Sopenharmony_ci void *buf, size_t size) 3698c2ecf20Sopenharmony_ci{ 3708c2ecf20Sopenharmony_ci return perf_data_file__write(&data->file, buf, size); 3718c2ecf20Sopenharmony_ci} 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ciint perf_data__switch(struct perf_data *data, 3748c2ecf20Sopenharmony_ci const char *postfix, 3758c2ecf20Sopenharmony_ci size_t pos, bool at_exit, 3768c2ecf20Sopenharmony_ci char **new_filepath) 3778c2ecf20Sopenharmony_ci{ 3788c2ecf20Sopenharmony_ci int ret; 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci if (check_pipe(data)) 3818c2ecf20Sopenharmony_ci return -EINVAL; 3828c2ecf20Sopenharmony_ci if (perf_data__is_read(data)) 3838c2ecf20Sopenharmony_ci return -EINVAL; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci if (asprintf(new_filepath, "%s.%s", data->path, postfix) < 0) 3868c2ecf20Sopenharmony_ci return -ENOMEM; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci /* 3898c2ecf20Sopenharmony_ci * Only fire a warning, don't return error, continue fill 3908c2ecf20Sopenharmony_ci * original file. 3918c2ecf20Sopenharmony_ci */ 3928c2ecf20Sopenharmony_ci if (rename(data->path, *new_filepath)) 3938c2ecf20Sopenharmony_ci pr_warning("Failed to rename %s to %s\n", data->path, *new_filepath); 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci if (!at_exit) { 3968c2ecf20Sopenharmony_ci close(data->file.fd); 3978c2ecf20Sopenharmony_ci ret = perf_data__open(data); 3988c2ecf20Sopenharmony_ci if (ret < 0) 3998c2ecf20Sopenharmony_ci goto out; 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci if (lseek(data->file.fd, pos, SEEK_SET) == (off_t)-1) { 4028c2ecf20Sopenharmony_ci ret = -errno; 4038c2ecf20Sopenharmony_ci pr_debug("Failed to lseek to %zu: %s", 4048c2ecf20Sopenharmony_ci pos, strerror(errno)); 4058c2ecf20Sopenharmony_ci goto out; 4068c2ecf20Sopenharmony_ci } 4078c2ecf20Sopenharmony_ci } 4088c2ecf20Sopenharmony_ci ret = data->file.fd; 4098c2ecf20Sopenharmony_ciout: 4108c2ecf20Sopenharmony_ci return ret; 4118c2ecf20Sopenharmony_ci} 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ciunsigned long perf_data__size(struct perf_data *data) 4148c2ecf20Sopenharmony_ci{ 4158c2ecf20Sopenharmony_ci u64 size = data->file.size; 4168c2ecf20Sopenharmony_ci int i; 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci if (perf_data__is_single_file(data)) 4198c2ecf20Sopenharmony_ci return size; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci for (i = 0; i < data->dir.nr; i++) { 4228c2ecf20Sopenharmony_ci struct perf_data_file *file = &data->dir.files[i]; 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci size += file->size; 4258c2ecf20Sopenharmony_ci } 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci return size; 4288c2ecf20Sopenharmony_ci} 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ciint perf_data__make_kcore_dir(struct perf_data *data, char *buf, size_t buf_sz) 4318c2ecf20Sopenharmony_ci{ 4328c2ecf20Sopenharmony_ci int ret; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci if (!data->is_dir) 4358c2ecf20Sopenharmony_ci return -1; 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci ret = snprintf(buf, buf_sz, "%s/kcore_dir", data->path); 4388c2ecf20Sopenharmony_ci if (ret < 0 || (size_t)ret >= buf_sz) 4398c2ecf20Sopenharmony_ci return -1; 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci return mkdir(buf, S_IRWXU); 4428c2ecf20Sopenharmony_ci} 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_cichar *perf_data__kallsyms_name(struct perf_data *data) 4458c2ecf20Sopenharmony_ci{ 4468c2ecf20Sopenharmony_ci char *kallsyms_name; 4478c2ecf20Sopenharmony_ci struct stat st; 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci if (!data->is_dir) 4508c2ecf20Sopenharmony_ci return NULL; 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci if (asprintf(&kallsyms_name, "%s/kcore_dir/kallsyms", data->path) < 0) 4538c2ecf20Sopenharmony_ci return NULL; 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci if (stat(kallsyms_name, &st)) { 4568c2ecf20Sopenharmony_ci free(kallsyms_name); 4578c2ecf20Sopenharmony_ci return NULL; 4588c2ecf20Sopenharmony_ci } 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci return kallsyms_name; 4618c2ecf20Sopenharmony_ci} 462