18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include "util.h" 38c2ecf20Sopenharmony_ci#include "debug.h" 48c2ecf20Sopenharmony_ci#include "event.h" 58c2ecf20Sopenharmony_ci#include <api/fs/fs.h> 68c2ecf20Sopenharmony_ci#include <sys/stat.h> 78c2ecf20Sopenharmony_ci#include <sys/utsname.h> 88c2ecf20Sopenharmony_ci#include <dirent.h> 98c2ecf20Sopenharmony_ci#include <fcntl.h> 108c2ecf20Sopenharmony_ci#include <inttypes.h> 118c2ecf20Sopenharmony_ci#include <signal.h> 128c2ecf20Sopenharmony_ci#include <stdio.h> 138c2ecf20Sopenharmony_ci#include <stdlib.h> 148c2ecf20Sopenharmony_ci#include <string.h> 158c2ecf20Sopenharmony_ci#include <errno.h> 168c2ecf20Sopenharmony_ci#include <limits.h> 178c2ecf20Sopenharmony_ci#include <linux/capability.h> 188c2ecf20Sopenharmony_ci#include <linux/kernel.h> 198c2ecf20Sopenharmony_ci#include <linux/log2.h> 208c2ecf20Sopenharmony_ci#include <linux/time64.h> 218c2ecf20Sopenharmony_ci#include <unistd.h> 228c2ecf20Sopenharmony_ci#include "cap.h" 238c2ecf20Sopenharmony_ci#include "strlist.h" 248c2ecf20Sopenharmony_ci#include "string2.h" 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci/* 278c2ecf20Sopenharmony_ci * XXX We need to find a better place for these things... 288c2ecf20Sopenharmony_ci */ 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cibool perf_singlethreaded = true; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_civoid perf_set_singlethreaded(void) 338c2ecf20Sopenharmony_ci{ 348c2ecf20Sopenharmony_ci perf_singlethreaded = true; 358c2ecf20Sopenharmony_ci} 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_civoid perf_set_multithreaded(void) 388c2ecf20Sopenharmony_ci{ 398c2ecf20Sopenharmony_ci perf_singlethreaded = false; 408c2ecf20Sopenharmony_ci} 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ciint sysctl_perf_event_max_stack = PERF_MAX_STACK_DEPTH; 438c2ecf20Sopenharmony_ciint sysctl_perf_event_max_contexts_per_stack = PERF_MAX_CONTEXTS_PER_STACK; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ciint sysctl__max_stack(void) 468c2ecf20Sopenharmony_ci{ 478c2ecf20Sopenharmony_ci int value; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci if (sysctl__read_int("kernel/perf_event_max_stack", &value) == 0) 508c2ecf20Sopenharmony_ci sysctl_perf_event_max_stack = value; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci if (sysctl__read_int("kernel/perf_event_max_contexts_per_stack", &value) == 0) 538c2ecf20Sopenharmony_ci sysctl_perf_event_max_contexts_per_stack = value; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci return sysctl_perf_event_max_stack; 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cibool sysctl__nmi_watchdog_enabled(void) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci static bool cached; 618c2ecf20Sopenharmony_ci static bool nmi_watchdog; 628c2ecf20Sopenharmony_ci int value; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci if (cached) 658c2ecf20Sopenharmony_ci return nmi_watchdog; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci if (sysctl__read_int("kernel/nmi_watchdog", &value) < 0) 688c2ecf20Sopenharmony_ci return false; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci nmi_watchdog = (value > 0) ? true : false; 718c2ecf20Sopenharmony_ci cached = true; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci return nmi_watchdog; 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_cibool test_attr__enabled; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cibool perf_host = true; 798c2ecf20Sopenharmony_cibool perf_guest = false; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_civoid event_attr_init(struct perf_event_attr *attr) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci if (!perf_host) 848c2ecf20Sopenharmony_ci attr->exclude_host = 1; 858c2ecf20Sopenharmony_ci if (!perf_guest) 868c2ecf20Sopenharmony_ci attr->exclude_guest = 1; 878c2ecf20Sopenharmony_ci /* to capture ABI version */ 888c2ecf20Sopenharmony_ci attr->size = sizeof(*attr); 898c2ecf20Sopenharmony_ci} 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ciint mkdir_p(char *path, mode_t mode) 928c2ecf20Sopenharmony_ci{ 938c2ecf20Sopenharmony_ci struct stat st; 948c2ecf20Sopenharmony_ci int err; 958c2ecf20Sopenharmony_ci char *d = path; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci if (*d != '/') 988c2ecf20Sopenharmony_ci return -1; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci if (stat(path, &st) == 0) 1018c2ecf20Sopenharmony_ci return 0; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci while (*++d == '/'); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci while ((d = strchr(d, '/'))) { 1068c2ecf20Sopenharmony_ci *d = '\0'; 1078c2ecf20Sopenharmony_ci err = stat(path, &st) && mkdir(path, mode); 1088c2ecf20Sopenharmony_ci *d++ = '/'; 1098c2ecf20Sopenharmony_ci if (err) 1108c2ecf20Sopenharmony_ci return -1; 1118c2ecf20Sopenharmony_ci while (*d == '/') 1128c2ecf20Sopenharmony_ci ++d; 1138c2ecf20Sopenharmony_ci } 1148c2ecf20Sopenharmony_ci return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0; 1158c2ecf20Sopenharmony_ci} 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_cistatic bool match_pat(char *file, const char **pat) 1188c2ecf20Sopenharmony_ci{ 1198c2ecf20Sopenharmony_ci int i = 0; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci if (!pat) 1228c2ecf20Sopenharmony_ci return true; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci while (pat[i]) { 1258c2ecf20Sopenharmony_ci if (strglobmatch(file, pat[i])) 1268c2ecf20Sopenharmony_ci return true; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci i++; 1298c2ecf20Sopenharmony_ci } 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci return false; 1328c2ecf20Sopenharmony_ci} 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci/* 1358c2ecf20Sopenharmony_ci * The depth specify how deep the removal will go. 1368c2ecf20Sopenharmony_ci * 0 - will remove only files under the 'path' directory 1378c2ecf20Sopenharmony_ci * 1 .. x - will dive in x-level deep under the 'path' directory 1388c2ecf20Sopenharmony_ci * 1398c2ecf20Sopenharmony_ci * If specified the pat is array of string patterns ended with NULL, 1408c2ecf20Sopenharmony_ci * which are checked upon every file/directory found. Only matching 1418c2ecf20Sopenharmony_ci * ones are removed. 1428c2ecf20Sopenharmony_ci * 1438c2ecf20Sopenharmony_ci * The function returns: 1448c2ecf20Sopenharmony_ci * 0 on success 1458c2ecf20Sopenharmony_ci * -1 on removal failure with errno set 1468c2ecf20Sopenharmony_ci * -2 on pattern failure 1478c2ecf20Sopenharmony_ci */ 1488c2ecf20Sopenharmony_cistatic int rm_rf_depth_pat(const char *path, int depth, const char **pat) 1498c2ecf20Sopenharmony_ci{ 1508c2ecf20Sopenharmony_ci DIR *dir; 1518c2ecf20Sopenharmony_ci int ret; 1528c2ecf20Sopenharmony_ci struct dirent *d; 1538c2ecf20Sopenharmony_ci char namebuf[PATH_MAX]; 1548c2ecf20Sopenharmony_ci struct stat statbuf; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci /* Do not fail if there's no file. */ 1578c2ecf20Sopenharmony_ci ret = lstat(path, &statbuf); 1588c2ecf20Sopenharmony_ci if (ret) 1598c2ecf20Sopenharmony_ci return 0; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci /* Try to remove any file we get. */ 1628c2ecf20Sopenharmony_ci if (!(statbuf.st_mode & S_IFDIR)) 1638c2ecf20Sopenharmony_ci return unlink(path); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci /* We have directory in path. */ 1668c2ecf20Sopenharmony_ci dir = opendir(path); 1678c2ecf20Sopenharmony_ci if (dir == NULL) 1688c2ecf20Sopenharmony_ci return -1; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci while ((d = readdir(dir)) != NULL && !ret) { 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) 1738c2ecf20Sopenharmony_ci continue; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci if (!match_pat(d->d_name, pat)) { 1768c2ecf20Sopenharmony_ci ret = -2; 1778c2ecf20Sopenharmony_ci break; 1788c2ecf20Sopenharmony_ci } 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci scnprintf(namebuf, sizeof(namebuf), "%s/%s", 1818c2ecf20Sopenharmony_ci path, d->d_name); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci /* We have to check symbolic link itself */ 1848c2ecf20Sopenharmony_ci ret = lstat(namebuf, &statbuf); 1858c2ecf20Sopenharmony_ci if (ret < 0) { 1868c2ecf20Sopenharmony_ci pr_debug("stat failed: %s\n", namebuf); 1878c2ecf20Sopenharmony_ci break; 1888c2ecf20Sopenharmony_ci } 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci if (S_ISDIR(statbuf.st_mode)) 1918c2ecf20Sopenharmony_ci ret = depth ? rm_rf_depth_pat(namebuf, depth - 1, pat) : 0; 1928c2ecf20Sopenharmony_ci else 1938c2ecf20Sopenharmony_ci ret = unlink(namebuf); 1948c2ecf20Sopenharmony_ci } 1958c2ecf20Sopenharmony_ci closedir(dir); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci if (ret < 0) 1988c2ecf20Sopenharmony_ci return ret; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci return rmdir(path); 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_cistatic int rm_rf_kcore_dir(const char *path) 2048c2ecf20Sopenharmony_ci{ 2058c2ecf20Sopenharmony_ci char kcore_dir_path[PATH_MAX]; 2068c2ecf20Sopenharmony_ci const char *pat[] = { 2078c2ecf20Sopenharmony_ci "kcore", 2088c2ecf20Sopenharmony_ci "kallsyms", 2098c2ecf20Sopenharmony_ci "modules", 2108c2ecf20Sopenharmony_ci NULL, 2118c2ecf20Sopenharmony_ci }; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci snprintf(kcore_dir_path, sizeof(kcore_dir_path), "%s/kcore_dir", path); 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci return rm_rf_depth_pat(kcore_dir_path, 0, pat); 2168c2ecf20Sopenharmony_ci} 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ciint rm_rf_perf_data(const char *path) 2198c2ecf20Sopenharmony_ci{ 2208c2ecf20Sopenharmony_ci const char *pat[] = { 2218c2ecf20Sopenharmony_ci "data", 2228c2ecf20Sopenharmony_ci "data.*", 2238c2ecf20Sopenharmony_ci NULL, 2248c2ecf20Sopenharmony_ci }; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci rm_rf_kcore_dir(path); 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci return rm_rf_depth_pat(path, 0, pat); 2298c2ecf20Sopenharmony_ci} 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ciint rm_rf(const char *path) 2328c2ecf20Sopenharmony_ci{ 2338c2ecf20Sopenharmony_ci return rm_rf_depth_pat(path, INT_MAX, NULL); 2348c2ecf20Sopenharmony_ci} 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci/* A filter which removes dot files */ 2378c2ecf20Sopenharmony_cibool lsdir_no_dot_filter(const char *name __maybe_unused, struct dirent *d) 2388c2ecf20Sopenharmony_ci{ 2398c2ecf20Sopenharmony_ci return d->d_name[0] != '.'; 2408c2ecf20Sopenharmony_ci} 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci/* lsdir reads a directory and store it in strlist */ 2438c2ecf20Sopenharmony_cistruct strlist *lsdir(const char *name, 2448c2ecf20Sopenharmony_ci bool (*filter)(const char *, struct dirent *)) 2458c2ecf20Sopenharmony_ci{ 2468c2ecf20Sopenharmony_ci struct strlist *list = NULL; 2478c2ecf20Sopenharmony_ci DIR *dir; 2488c2ecf20Sopenharmony_ci struct dirent *d; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci dir = opendir(name); 2518c2ecf20Sopenharmony_ci if (!dir) 2528c2ecf20Sopenharmony_ci return NULL; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci list = strlist__new(NULL, NULL); 2558c2ecf20Sopenharmony_ci if (!list) { 2568c2ecf20Sopenharmony_ci errno = ENOMEM; 2578c2ecf20Sopenharmony_ci goto out; 2588c2ecf20Sopenharmony_ci } 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci while ((d = readdir(dir)) != NULL) { 2618c2ecf20Sopenharmony_ci if (!filter || filter(name, d)) 2628c2ecf20Sopenharmony_ci strlist__add(list, d->d_name); 2638c2ecf20Sopenharmony_ci } 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ciout: 2668c2ecf20Sopenharmony_ci closedir(dir); 2678c2ecf20Sopenharmony_ci return list; 2688c2ecf20Sopenharmony_ci} 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_cisize_t hex_width(u64 v) 2718c2ecf20Sopenharmony_ci{ 2728c2ecf20Sopenharmony_ci size_t n = 1; 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci while ((v >>= 4)) 2758c2ecf20Sopenharmony_ci ++n; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci return n; 2788c2ecf20Sopenharmony_ci} 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ciint perf_event_paranoid(void) 2818c2ecf20Sopenharmony_ci{ 2828c2ecf20Sopenharmony_ci int value; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci if (sysctl__read_int("kernel/perf_event_paranoid", &value)) 2858c2ecf20Sopenharmony_ci return INT_MAX; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci return value; 2888c2ecf20Sopenharmony_ci} 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_cibool perf_event_paranoid_check(int max_level) 2918c2ecf20Sopenharmony_ci{ 2928c2ecf20Sopenharmony_ci return perf_cap__capable(CAP_SYS_ADMIN) || 2938c2ecf20Sopenharmony_ci perf_cap__capable(CAP_PERFMON) || 2948c2ecf20Sopenharmony_ci perf_event_paranoid() <= max_level; 2958c2ecf20Sopenharmony_ci} 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_cistatic int 2988c2ecf20Sopenharmony_cifetch_ubuntu_kernel_version(unsigned int *puint) 2998c2ecf20Sopenharmony_ci{ 3008c2ecf20Sopenharmony_ci ssize_t len; 3018c2ecf20Sopenharmony_ci size_t line_len = 0; 3028c2ecf20Sopenharmony_ci char *ptr, *line = NULL; 3038c2ecf20Sopenharmony_ci int version, patchlevel, sublevel, err; 3048c2ecf20Sopenharmony_ci FILE *vsig; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci if (!puint) 3078c2ecf20Sopenharmony_ci return 0; 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci vsig = fopen("/proc/version_signature", "r"); 3108c2ecf20Sopenharmony_ci if (!vsig) { 3118c2ecf20Sopenharmony_ci pr_debug("Open /proc/version_signature failed: %s\n", 3128c2ecf20Sopenharmony_ci strerror(errno)); 3138c2ecf20Sopenharmony_ci return -1; 3148c2ecf20Sopenharmony_ci } 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci len = getline(&line, &line_len, vsig); 3178c2ecf20Sopenharmony_ci fclose(vsig); 3188c2ecf20Sopenharmony_ci err = -1; 3198c2ecf20Sopenharmony_ci if (len <= 0) { 3208c2ecf20Sopenharmony_ci pr_debug("Reading from /proc/version_signature failed: %s\n", 3218c2ecf20Sopenharmony_ci strerror(errno)); 3228c2ecf20Sopenharmony_ci goto errout; 3238c2ecf20Sopenharmony_ci } 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci ptr = strrchr(line, ' '); 3268c2ecf20Sopenharmony_ci if (!ptr) { 3278c2ecf20Sopenharmony_ci pr_debug("Parsing /proc/version_signature failed: %s\n", line); 3288c2ecf20Sopenharmony_ci goto errout; 3298c2ecf20Sopenharmony_ci } 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci err = sscanf(ptr + 1, "%d.%d.%d", 3328c2ecf20Sopenharmony_ci &version, &patchlevel, &sublevel); 3338c2ecf20Sopenharmony_ci if (err != 3) { 3348c2ecf20Sopenharmony_ci pr_debug("Unable to get kernel version from /proc/version_signature '%s'\n", 3358c2ecf20Sopenharmony_ci line); 3368c2ecf20Sopenharmony_ci goto errout; 3378c2ecf20Sopenharmony_ci } 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci *puint = (version << 16) + (patchlevel << 8) + sublevel; 3408c2ecf20Sopenharmony_ci err = 0; 3418c2ecf20Sopenharmony_cierrout: 3428c2ecf20Sopenharmony_ci free(line); 3438c2ecf20Sopenharmony_ci return err; 3448c2ecf20Sopenharmony_ci} 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ciint 3478c2ecf20Sopenharmony_cifetch_kernel_version(unsigned int *puint, char *str, 3488c2ecf20Sopenharmony_ci size_t str_size) 3498c2ecf20Sopenharmony_ci{ 3508c2ecf20Sopenharmony_ci struct utsname utsname; 3518c2ecf20Sopenharmony_ci int version, patchlevel, sublevel, err; 3528c2ecf20Sopenharmony_ci bool int_ver_ready = false; 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci if (access("/proc/version_signature", R_OK) == 0) 3558c2ecf20Sopenharmony_ci if (!fetch_ubuntu_kernel_version(puint)) 3568c2ecf20Sopenharmony_ci int_ver_ready = true; 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci if (uname(&utsname)) 3598c2ecf20Sopenharmony_ci return -1; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci if (str && str_size) { 3628c2ecf20Sopenharmony_ci strncpy(str, utsname.release, str_size); 3638c2ecf20Sopenharmony_ci str[str_size - 1] = '\0'; 3648c2ecf20Sopenharmony_ci } 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci if (!puint || int_ver_ready) 3678c2ecf20Sopenharmony_ci return 0; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci err = sscanf(utsname.release, "%d.%d.%d", 3708c2ecf20Sopenharmony_ci &version, &patchlevel, &sublevel); 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci if (err != 3) { 3738c2ecf20Sopenharmony_ci pr_debug("Unable to get kernel version from uname '%s'\n", 3748c2ecf20Sopenharmony_ci utsname.release); 3758c2ecf20Sopenharmony_ci return -1; 3768c2ecf20Sopenharmony_ci } 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci *puint = (version << 16) + (patchlevel << 8) + sublevel; 3798c2ecf20Sopenharmony_ci return 0; 3808c2ecf20Sopenharmony_ci} 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ciint perf_tip(char **strp, const char *dirpath) 3838c2ecf20Sopenharmony_ci{ 3848c2ecf20Sopenharmony_ci struct strlist *tips; 3858c2ecf20Sopenharmony_ci struct str_node *node; 3868c2ecf20Sopenharmony_ci struct strlist_config conf = { 3878c2ecf20Sopenharmony_ci .dirname = dirpath, 3888c2ecf20Sopenharmony_ci .file_only = true, 3898c2ecf20Sopenharmony_ci }; 3908c2ecf20Sopenharmony_ci int ret = 0; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci *strp = NULL; 3938c2ecf20Sopenharmony_ci tips = strlist__new("tips.txt", &conf); 3948c2ecf20Sopenharmony_ci if (tips == NULL) 3958c2ecf20Sopenharmony_ci return -errno; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci if (strlist__nr_entries(tips) == 0) 3988c2ecf20Sopenharmony_ci goto out; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci node = strlist__entry(tips, random() % strlist__nr_entries(tips)); 4018c2ecf20Sopenharmony_ci if (asprintf(strp, "Tip: %s", node->s) < 0) 4028c2ecf20Sopenharmony_ci ret = -ENOMEM; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ciout: 4058c2ecf20Sopenharmony_ci strlist__delete(tips); 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci return ret; 4088c2ecf20Sopenharmony_ci} 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_cichar *perf_exe(char *buf, int len) 4118c2ecf20Sopenharmony_ci{ 4128c2ecf20Sopenharmony_ci int n = readlink("/proc/self/exe", buf, len); 4138c2ecf20Sopenharmony_ci if (n > 0) { 4148c2ecf20Sopenharmony_ci buf[n] = 0; 4158c2ecf20Sopenharmony_ci return buf; 4168c2ecf20Sopenharmony_ci } 4178c2ecf20Sopenharmony_ci return strcpy(buf, "perf"); 4188c2ecf20Sopenharmony_ci} 419