186470930SIngo Molnar /* 286470930SIngo Molnar * I'm tired of doing "vsnprintf()" etc just to open a 386470930SIngo Molnar * file, so here's a "return static buffer with printf" 486470930SIngo Molnar * interface for paths. 586470930SIngo Molnar * 686470930SIngo Molnar * It's obviously not thread-safe. Sue me. But it's quite 786470930SIngo Molnar * useful for doing things like 886470930SIngo Molnar * 986470930SIngo Molnar * f = open(mkpath("%s/%s.perf", base, name), O_RDONLY); 1086470930SIngo Molnar * 1186470930SIngo Molnar * which is what it's designed for. 1286470930SIngo Molnar */ 1386470930SIngo Molnar #include "cache.h" 14*9a3993d4SArnaldo Carvalho de Melo #include "path.h" 15*9a3993d4SArnaldo Carvalho de Melo #include <linux/kernel.h> 16175729fcSArnaldo Carvalho de Melo #include <limits.h> 17*9a3993d4SArnaldo Carvalho de Melo #include <stdio.h> 18*9a3993d4SArnaldo Carvalho de Melo #include <sys/types.h> 19*9a3993d4SArnaldo Carvalho de Melo #include <sys/stat.h> 20*9a3993d4SArnaldo Carvalho de Melo #include <unistd.h> 2186470930SIngo Molnar 2286470930SIngo Molnar static char bad_path[] = "/bad-path/"; 2386470930SIngo Molnar /* 24814b3f51SArnaldo Carvalho de Melo * One hack: 2586470930SIngo Molnar */ 2686470930SIngo Molnar static char *get_pathname(void) 2786470930SIngo Molnar { 2886470930SIngo Molnar static char pathname_array[4][PATH_MAX]; 2983a0944fSIngo Molnar static int idx; 3083a0944fSIngo Molnar 3183a0944fSIngo Molnar return pathname_array[3 & ++idx]; 3286470930SIngo Molnar } 3386470930SIngo Molnar 3486470930SIngo Molnar static char *cleanup_path(char *path) 3586470930SIngo Molnar { 3686470930SIngo Molnar /* Clean it up */ 3786470930SIngo Molnar if (!memcmp(path, "./", 2)) { 3886470930SIngo Molnar path += 2; 3986470930SIngo Molnar while (*path == '/') 4086470930SIngo Molnar path++; 4186470930SIngo Molnar } 4286470930SIngo Molnar return path; 4386470930SIngo Molnar } 4486470930SIngo Molnar 4586470930SIngo Molnar char *mkpath(const char *fmt, ...) 4686470930SIngo Molnar { 4786470930SIngo Molnar va_list args; 4886470930SIngo Molnar unsigned len; 4986470930SIngo Molnar char *pathname = get_pathname(); 5086470930SIngo Molnar 5186470930SIngo Molnar va_start(args, fmt); 5286470930SIngo Molnar len = vsnprintf(pathname, PATH_MAX, fmt, args); 5386470930SIngo Molnar va_end(args); 5486470930SIngo Molnar if (len >= PATH_MAX) 5586470930SIngo Molnar return bad_path; 5686470930SIngo Molnar return cleanup_path(pathname); 5786470930SIngo Molnar } 58*9a3993d4SArnaldo Carvalho de Melo 59*9a3993d4SArnaldo Carvalho de Melo int path__join(char *bf, size_t size, const char *path1, const char *path2) 60*9a3993d4SArnaldo Carvalho de Melo { 61*9a3993d4SArnaldo Carvalho de Melo return scnprintf(bf, size, "%s%s%s", path1, path1[0] ? "/" : "", path2); 62*9a3993d4SArnaldo Carvalho de Melo } 63*9a3993d4SArnaldo Carvalho de Melo 64*9a3993d4SArnaldo Carvalho de Melo int path__join3(char *bf, size_t size, const char *path1, const char *path2, const char *path3) 65*9a3993d4SArnaldo Carvalho de Melo { 66*9a3993d4SArnaldo Carvalho de Melo return scnprintf(bf, size, "%s%s%s%s%s", path1, path1[0] ? "/" : "", 67*9a3993d4SArnaldo Carvalho de Melo path2, path2[0] ? "/" : "", path3); 68*9a3993d4SArnaldo Carvalho de Melo } 69*9a3993d4SArnaldo Carvalho de Melo 70*9a3993d4SArnaldo Carvalho de Melo bool is_regular_file(const char *file) 71*9a3993d4SArnaldo Carvalho de Melo { 72*9a3993d4SArnaldo Carvalho de Melo struct stat st; 73*9a3993d4SArnaldo Carvalho de Melo 74*9a3993d4SArnaldo Carvalho de Melo if (stat(file, &st)) 75*9a3993d4SArnaldo Carvalho de Melo return false; 76*9a3993d4SArnaldo Carvalho de Melo 77*9a3993d4SArnaldo Carvalho de Melo return S_ISREG(st.st_mode); 78*9a3993d4SArnaldo Carvalho de Melo } 79