Rizin
unix-like reverse engineering framework and cli tools
path.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2021 Riccardo Schirone <sirmy15@gmail.com>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_util/rz_path.h>
5 #include <rz_util/rz_file.h>
6 #include <rz_util/rz_sys.h>
7 #include <rz_util/rz_str.h>
8 #include <rz_util/rz_utf8.h>
9 #include <rz_windows.h>
10 
11 #if __WINDOWS__
12 #include <rz_windows.h>
13 #endif
14 
15 #if RZ_IS_PORTABLE
16 #include <rz_constructor.h>
17 #include <rz_th.h>
18 
19 static char *portable_prefix = NULL;
20 static bool portable_prefix_searched = false;
21 static RzThreadLock *portable_prefix_mutex = NULL;
22 
23 #ifdef RZ_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
24 #pragma RZ_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(init_portable_prefix)
25 #endif
26 RZ_DEFINE_CONSTRUCTOR(init_portable_prefix)
27 static void init_portable_prefix(void) {
28  portable_prefix_mutex = rz_th_lock_new(false);
29 }
30 
31 #ifdef RZ_DEFINE_DESTRUCTOR_NEEDS_PRAGMA
32 #pragma RZ_DEFINE_DESTRUCTOR_PRAGMA_ARGS(fini_portable_prefix)
33 #endif
34 RZ_DEFINE_DESTRUCTOR(fini_portable_prefix)
35 static void fini_portable_prefix(void) {
36  RZ_FREE(portable_prefix);
37  portable_prefix_searched = false;
38  RZ_FREE_CUSTOM(portable_prefix_mutex, rz_th_lock_free);
39 }
40 
41 static char *set_portable_prefix(void) {
42  char *pid_to_path = rz_sys_pid_to_path(rz_sys_getpid());
43  if (!pid_to_path) {
44  return NULL;
45  }
46 
47  const char *filename = rz_file_basename(pid_to_path);
48  char *it = rz_file_dirname(pid_to_path);
49  free(pid_to_path);
50 
51  for (int i = 0; i < RZ_BINDIR_DEPTH && it; i++) {
52  char *tmp = it;
53  it = rz_file_dirname(tmp);
54  free(tmp);
55  }
56  if (!it) {
57  goto err;
58  }
59 
60  char *bindir = rz_file_path_join(it, RZ_BINDIR);
61  if (!bindir) {
62  goto err;
63  }
64  char *bindir_real = rz_path_realpath(bindir);
65  free(bindir);
66  bool in_bindir = bindir_real != NULL;
67  if (!in_bindir) {
68  goto err;
69  }
70 
71  char *exe_path = rz_file_path_join(bindir_real, filename);
72  free(bindir_real);
73  char *exe_path_real = rz_path_realpath(exe_path);
74  free(exe_path);
75  bool exe_exists = exe_path_real != NULL;
76  free(exe_path_real);
77 
78  if (in_bindir && exe_exists && rz_file_is_directory(it)) {
79  return it;
80  }
81 err:
82  free(it);
83  return NULL;
84 }
85 #endif
86 
98 #if RZ_IS_PORTABLE
99  rz_th_lock_enter(portable_prefix_mutex);
100  free(portable_prefix);
101  if (RZ_STR_ISNOTEMPTY(path)) {
102  portable_prefix = strdup(path);
103  } else {
104  portable_prefix = set_portable_prefix();
105  }
106  portable_prefix_searched = true;
107  rz_th_lock_leave(portable_prefix_mutex);
108 #endif
109 }
110 
122 #if RZ_IS_PORTABLE
123  rz_th_lock_enter(portable_prefix_mutex);
124  if (!portable_prefix_searched) {
125  portable_prefix = set_portable_prefix();
126  portable_prefix_searched = true;
127  }
128  rz_th_lock_leave(portable_prefix_mutex);
129 
130  if (portable_prefix) {
131  return rz_file_path_join(portable_prefix, path);
132  }
133 
134 #endif
136 }
137 
142  return rz_path_prefix(RZ_INCDIR);
143 }
144 
149  return rz_path_prefix(RZ_BINDIR);
150 }
151 
156  return rz_path_prefix(RZ_LIBDIR);
157 }
158 
163  return rz_path_prefix(path);
164 }
165 
171 }
172 
183  char *home = rz_sys_getenv(RZ_SYS_HOME);
184  if (!home) {
185  home = rz_file_tmpdir();
186  if (!home) {
187  return NULL;
188  }
189  }
190  char *res = rz_str_newf("%s" RZ_SYS_DIR "%s" RZ_SYS_DIR "%s", home, RZ_HOME_PREFIX, path);
191  free(home);
192  return res;
193 }
194 
200 }
201 
207 }
208 
214 }
215 
220  return rz_path_home(RZ_HOME_RC);
221 }
222 
228 }
229 
235 }
236 
244  char *home = rz_sys_getenv(RZ_SYS_HOME);
245  if (!home) {
246  home = rz_file_tmpdir();
247  if (!home) {
248  return NULL;
249  }
250  }
251  char *res;
252  if (path) {
253  res = rz_file_path_join(home, path);
254  free(home);
255  } else {
256  res = home;
257  }
258  return res;
259 }
260 
269  // if the path does not start with `~`, there is nothing to expand
270  if (path && path[0] != '~') {
271  return strdup(path);
272  }
273 
274  // if the path starts with `~` but it is not `~/` or just `~`, then it is a
275  // valid name (e.g. `~hello`)
276  if (path && path[0] && path[1] && path[1] != '/') {
277  return strdup(path);
278  }
279 
280  return rz_path_home(path + 1);
281 }
282 
291  if (!path) {
292  return NULL;
293  }
294 #if HAVE_REALPATH
295  char buf[PATH_MAX] = { 0 };
296  const char *rp = realpath(path, buf);
297  if (rp) {
298  return strdup(rp);
299  }
300 #elif __WINDOWS__
301  wchar_t buf[MAX_PATH] = { 0 };
302 
303  wchar_t *wpath = rz_utf8_to_utf16(path);
304  DWORD len = GetFullPathNameW(wpath, MAX_PATH, buf, NULL);
305  free(wpath);
306  if (len > 0 && len < MAX_PATH - 1) {
307  return rz_utf16_to_utf8_l(buf, len);
308  }
309 #endif
310  return NULL;
311 }
size_t len
Definition: 6502dis.c:15
lzma_index ** i
Definition: index.h:629
static bool err
Definition: armass.c:435
#define RZ_API
#define NULL
Definition: cris-opc.c:27
static static fork const void static count static fd const char const char static newpath const char static path const char path
Definition: sflib.h:35
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
static char * rp[]
Definition: i8080dis.c:36
const char * filename
Definition: ioapi.h:137
voidpf void * buf
Definition: ioapi.h:138
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
RZ_API const char * rz_file_basename(const char *path)
Definition: file.c:83
RZ_API char * rz_file_tmpdir(void)
Definition: file.c:1132
RZ_API bool rz_file_is_directory(const char *str)
Definition: file.c:167
RZ_API char * rz_file_dirname(const char *path)
Definition: file.c:120
RZ_API RZ_OWN char * rz_file_path_join(RZ_NONNULL const char *s1, RZ_NULLABLE const char *s2)
Concatenate two paths to create a new one with s1+s2 with the correct path separator.
Definition: file.c:1312
#define RZ_STR_ISNOTEMPTY(x)
Definition: rz_str.h:68
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API char * rz_sys_getenv(const char *key)
Get the value of an environment variable named key or NULL if none exists.
Definition: sys.c:483
RZ_API int rz_sys_getpid(void)
Definition: sys.c:1164
RZ_API char * rz_sys_pid_to_path(int pid)
Definition: sys.c:920
#define RZ_SYS_DIR
Definition: rz_types.h:218
#define RZ_NULLABLE
Definition: rz_types.h:65
#define RZ_OWN
Definition: rz_types.h:62
#define RZ_NONNULL
Definition: rz_types.h:64
#define RZ_SYS_HOME
Definition: rz_types.h:220
#define RZ_FREE_CUSTOM(x, y)
Definition: rz_types.h:375
#define RZ_FREE(x)
Definition: rz_types.h:369
#define RZ_HOME_CONFIGDIR
Definition: rz_userconf.h:93
#define RZ_HOME_CONFIG_RC_DIR
Definition: rz_userconf.h:103
#define RZ_PREFIX
Definition: rz_userconf.h:65
#define RZ_GLOBAL_RC
Definition: rz_userconf.h:104
#define RZ_HOME_CACHEDIR
Definition: rz_userconf.h:94
#define RZ_HOME_PREFIX
Definition: rz_userconf.h:92
#define RZ_BINDIR
Definition: rz_userconf.h:66
#define RZ_HOME_CONFIG_RC
Definition: rz_userconf.h:102
#define RZ_HOME_HISTORY
Definition: rz_userconf.h:96
#define RZ_LIBDIR
Definition: rz_userconf.h:67
#define RZ_INCDIR
Definition: rz_userconf.h:68
#define RZ_BINDIR_DEPTH
Definition: rz_userconf.h:62
#define RZ_HOME_RC
Definition: rz_userconf.h:105
RZ_API void rz_th_lock_leave(RZ_NONNULL RzThreadLock *thl)
Releases a RzThreadLock structure.
Definition: thread_lock.c:75
RZ_API void rz_th_lock_free(RZ_NULLABLE RzThreadLock *thl)
Frees a RzThreadLock structure.
Definition: thread_lock.c:89
RZ_API RZ_OWN RzThreadLock * rz_th_lock_new(bool recursive)
Allocates and initialize a RzThreadLock structure.
Definition: thread_lock.c:14
RZ_API void rz_th_lock_enter(RZ_NONNULL RzThreadLock *thl)
Acquires a RzThreadLock structure.
Definition: thread_lock.c:45
RZ_API RZ_OWN char * rz_path_home_config(void)
Return the home directory for config files (e.g. ~/.config/rizin)
Definition: path.c:198
RZ_API RZ_OWN char * rz_path_system_rc(void)
Return the system path of the global rizinrc file.
Definition: path.c:169
RZ_API RZ_OWN char * rz_path_incdir(void)
Return the directory where include files are placed.
Definition: path.c:141
RZ_API RZ_OWN char * rz_path_home_expand(RZ_NULLABLE const char *path)
Return a new path with the ~ char expanded to the home directory.
Definition: path.c:268
RZ_API RZ_OWN char * rz_path_home_config_rc(void)
Return the path of the rizinrc file in the home config directory.
Definition: path.c:226
RZ_API RZ_OWN char * rz_path_home_prefix(RZ_NULLABLE const char *path)
Return path prefixed by the home prefix.
Definition: path.c:182
RZ_API RZ_OWN char * rz_path_system(RZ_NULLABLE const char *path)
Return the full system path of the given subpath path.
Definition: path.c:162
RZ_API RZ_OWN char * rz_path_home_cache(void)
Return the home directory for cache files (e.g. ~/.cache/rizin)
Definition: path.c:205
RZ_API RZ_OWN char * rz_path_home_history(void)
Return the path for the command history file.
Definition: path.c:212
RZ_API void rz_path_set_prefix(RZ_NONNULL const char *path)
Return path prefixed by the Rizin install prefix.
Definition: path.c:97
RZ_API RZ_OWN char * rz_path_libdir(void)
Return the directory where the Rizin libraries are placed.
Definition: path.c:155
RZ_API RZ_OWN char * rz_path_bindir(void)
Return the directory where the Rizin binaries are placed.
Definition: path.c:148
RZ_API RZ_OWN char * rz_path_realpath(RZ_NULLABLE const char *path)
Return a canonicalized absolute path. Expands all symbolic links and resolves references to /....
Definition: path.c:290
RZ_API RZ_OWN char * rz_path_prefix(RZ_NULLABLE const char *path)
Return path prefixed by the Rizin install prefix.
Definition: path.c:121
RZ_API RZ_OWN char * rz_path_home_config_rcdir(void)
Return the home directory of config rizinrc.d.
Definition: path.c:233
RZ_API RZ_OWN char * rz_path_home_rc(void)
Return the path of the rizinrc file in the home directory.
Definition: path.c:219
RZ_API RZ_OWN char * rz_path_home(RZ_NULLABLE const char *path)
Return a new path relative to the home directory.
Definition: path.c:243
DWORD