18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * I'm tired of doing "vsnprintf()" etc just to open a 48c2ecf20Sopenharmony_ci * file, so here's a "return static buffer with printf" 58c2ecf20Sopenharmony_ci * interface for paths. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * It's obviously not thread-safe. Sue me. But it's quite 88c2ecf20Sopenharmony_ci * useful for doing things like 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * f = open(mkpath("%s/%s.perf", base, name), O_RDONLY); 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * which is what it's designed for. 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci#include "path.h" 158c2ecf20Sopenharmony_ci#include "cache.h" 168c2ecf20Sopenharmony_ci#include <linux/kernel.h> 178c2ecf20Sopenharmony_ci#include <limits.h> 188c2ecf20Sopenharmony_ci#include <stdio.h> 198c2ecf20Sopenharmony_ci#include <string.h> 208c2ecf20Sopenharmony_ci#include <sys/types.h> 218c2ecf20Sopenharmony_ci#include <sys/stat.h> 228c2ecf20Sopenharmony_ci#include <dirent.h> 238c2ecf20Sopenharmony_ci#include <unistd.h> 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistatic char bad_path[] = "/bad-path/"; 268c2ecf20Sopenharmony_ci/* 278c2ecf20Sopenharmony_ci * One hack: 288c2ecf20Sopenharmony_ci */ 298c2ecf20Sopenharmony_cistatic char *get_pathname(void) 308c2ecf20Sopenharmony_ci{ 318c2ecf20Sopenharmony_ci static char pathname_array[4][PATH_MAX]; 328c2ecf20Sopenharmony_ci static int idx; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci return pathname_array[3 & ++idx]; 358c2ecf20Sopenharmony_ci} 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_cistatic char *cleanup_path(char *path) 388c2ecf20Sopenharmony_ci{ 398c2ecf20Sopenharmony_ci /* Clean it up */ 408c2ecf20Sopenharmony_ci if (!memcmp(path, "./", 2)) { 418c2ecf20Sopenharmony_ci path += 2; 428c2ecf20Sopenharmony_ci while (*path == '/') 438c2ecf20Sopenharmony_ci path++; 448c2ecf20Sopenharmony_ci } 458c2ecf20Sopenharmony_ci return path; 468c2ecf20Sopenharmony_ci} 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cichar *mkpath(const char *fmt, ...) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci va_list args; 518c2ecf20Sopenharmony_ci unsigned len; 528c2ecf20Sopenharmony_ci char *pathname = get_pathname(); 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci va_start(args, fmt); 558c2ecf20Sopenharmony_ci len = vsnprintf(pathname, PATH_MAX, fmt, args); 568c2ecf20Sopenharmony_ci va_end(args); 578c2ecf20Sopenharmony_ci if (len >= PATH_MAX) 588c2ecf20Sopenharmony_ci return bad_path; 598c2ecf20Sopenharmony_ci return cleanup_path(pathname); 608c2ecf20Sopenharmony_ci} 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ciint path__join(char *bf, size_t size, const char *path1, const char *path2) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci return scnprintf(bf, size, "%s%s%s", path1, path1[0] ? "/" : "", path2); 658c2ecf20Sopenharmony_ci} 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ciint path__join3(char *bf, size_t size, const char *path1, const char *path2, const char *path3) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci return scnprintf(bf, size, "%s%s%s%s%s", path1, path1[0] ? "/" : "", 708c2ecf20Sopenharmony_ci path2, path2[0] ? "/" : "", path3); 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cibool is_regular_file(const char *file) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci struct stat st; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci if (stat(file, &st)) 788c2ecf20Sopenharmony_ci return false; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci return S_ISREG(st.st_mode); 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci/* Helper function for filesystems that return a dent->d_type DT_UNKNOWN */ 848c2ecf20Sopenharmony_cibool is_directory(const char *base_path, const struct dirent *dent) 858c2ecf20Sopenharmony_ci{ 868c2ecf20Sopenharmony_ci char path[PATH_MAX]; 878c2ecf20Sopenharmony_ci struct stat st; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci sprintf(path, "%s/%s", base_path, dent->d_name); 908c2ecf20Sopenharmony_ci if (stat(path, &st)) 918c2ecf20Sopenharmony_ci return false; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci return S_ISDIR(st.st_mode); 948c2ecf20Sopenharmony_ci} 95