Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 167 additions & 0 deletions libr/main/r2pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#endif

static int r2pm_install(RList *targets, bool uninstall, bool clean, bool force, bool global);
static bool r2pm_bindir_in_path = false;

static const char *helpmsg =
"Usage: r2pm [-flags] [pkgs...]\n"
Expand Down Expand Up @@ -208,6 +209,139 @@ static char *r2pm_dbdir(void) {
return res;
}

static bool path_has_dir(const char *path, const char *dir) {
char *ptr, *path_copy, *entry;
if (R_STR_ISEMPTY (path) || R_STR_ISEMPTY (dir)) {
return false;
}
path_copy = strdup (path);
if (!path_copy) {
return false;
}
entry = path_copy;
do {
ptr = strchr (entry, R_SYS_ENVSEP[0]);
if (ptr) {
*ptr = '\0';
}
if (!strcmp (entry, dir)) {
free (path_copy);
return true;
}
if (ptr) {
entry = ptr + 1;
}
} while (ptr);
free (path_copy);
return false;
}

static const char *r2pm_shellrc_name(void) {
char *shell = r_sys_getenv ("SHELL");
const char *res = ".profile";
if (R_STR_ISNOTEMPTY (shell)) {
const char *shell_name = r_str_lchr (shell, '/');
shell_name = shell_name? shell_name + 1: shell;
if (!strcmp (shell_name, "bash")) {
res = ".bashrc";
} else if (!strcmp (shell_name, "zsh")) {
res = ".zshrc";
}
}
free (shell);
return res;
}

static void r2pm_suggest_bindir_in_shellrc(void) {
char *bindir = r_sys_getenv ("R2PM_BINDIR");
const char *shellrc;
if (R_STR_ISEMPTY (bindir)) {
free (bindir);
return;
}
shellrc = r2pm_shellrc_name ();
R_LOG_INFO ("Your shell PATH does not include %s", bindir);
R_LOG_INFO ("Add it to ~/%s with:", shellrc);
R_LOG_INFO (" echo 'export PATH=\"$PATH:%s\"' >> ~/%s", bindir, shellrc);
free (bindir);
}

static bool list_has_string(RList *list, const char *name) {
RListIter *iter;
const char *entry;
if (!list || !name) {
return false;
}
r_list_foreach (list, iter, entry) {
if (!strcmp (entry, name)) {
return true;
}
}
return false;
}

static RList *r2pm_bindir_snapshot(void) {
char *bindir = r_sys_getenv ("R2PM_BINDIR");
if (R_STR_ISEMPTY (bindir)) {
free (bindir);
return NULL;
}
RList *files = r_sys_dir (bindir);
free (bindir);
return files;
}

static RList *r2pm_bindir_new_files(RList *before, RList *after) {
RListIter *iter;
const char *file;
RList *res = r_list_newf (free);
if (!res || !after) {
r_list_free (res);
return NULL;
}
r_list_foreach (after, iter, file) {
if (*file == '.') {
continue;
}
if (!list_has_string (before, file)) {
r_list_append (res, strdup (file));
}
}
return res;
}

static void r2pm_report_new_bindir_files(const char *pkg, RList *new_files) {
RListIter *iter;
const char *file;
char *bindir = r_sys_getenv ("R2PM_BINDIR");
RStrBuf *sb;
char *files;
if (R_STR_ISEMPTY (bindir) || !new_files || r_list_empty (new_files)) {
free (bindir);
return;
}
sb = r_strbuf_new ("");
if (!sb) {
free (bindir);
return;
}
r_list_foreach (new_files, iter, file) {
if (!r_strbuf_length (sb)) {
r_strbuf_appendf (sb, "%s", file);
} else {
r_strbuf_appendf (sb, ", %s", file);
}
}
files = r_strbuf_drain (sb);
R_LOG_INFO ("New files in %s after installing %s: %s", bindir, pkg, files);
R_LOG_INFO ("Run them from your shell with 'r2pm -r <programname>'");
if (!r2pm_bindir_in_path) {
r2pm_suggest_bindir_in_shellrc ();
}
free (files);
free (bindir);
}

static char *r2pm_pkgdir(void) {
return r_xdg_datadir ("r2pm/pkg");
}
Expand Down Expand Up @@ -572,6 +706,9 @@ static void r2pm_setenv(R2Pm *r2pm) {
free (pkgcfg);

char *r2pm_bindir = r_str_newf ("%s/bin", r2_prefix);
char *path = r_sys_getenv ("PATH");
r2pm_bindir_in_path = path_has_dir (path, r2pm_bindir);
free (path);
r_sys_mkdirp (r2pm_bindir);
r_sys_setenv ("R2PM_BINDIR", r2pm_bindir);
r_sys_setenv_sep ("PATH", r2pm_bindir, false);
Expand Down Expand Up @@ -988,6 +1125,7 @@ static int r2pm_install_pkg(const char *pkg, bool clean, bool global) {
}
char *srcdir = r2pm_gitdir ();
R_LOG_DEBUG ("Entering %s", srcdir);
RList *bindir_before = r2pm_bindir_snapshot ();
char *qjs_script = r2pm_get (pkg, "\nR2PM_INSTALL_QJS() {\n", TT_CODEBLOCK);
if (qjs_script) {
int res = 0;
Expand All @@ -998,6 +1136,9 @@ static int r2pm_install_pkg(const char *pkg, bool clean, bool global) {
int child = fork ();
if (child == -1) {
R_LOG_ERROR ("Cannot find radare2 in PATH");
free (qjs_script);
r_list_free (bindir_before);
free (srcdir);
return -1;
}
if (child) {
Expand All @@ -1011,15 +1152,24 @@ static int r2pm_install_pkg(const char *pkg, bool clean, bool global) {
R_LOG_WARN ("r2pm.qjs support is experimental");
res = 1;
#endif
if (res == 0) {
RList *bindir_after = r2pm_bindir_snapshot ();
RList *new_files = r2pm_bindir_new_files (bindir_before, bindir_after);
r2pm_report_new_bindir_files (pkg, new_files);
r_list_free (new_files);
r_list_free (bindir_after);
}
// run script!
free (qjs_script);
r_list_free (bindir_before);
free (srcdir);
return res;
}
#if R2__WINDOWS__
char *script = r2pm_get (pkg, "\nR2PM_INSTALL_WINDOWS() {\n", TT_CODEBLOCK);
if (!script) {
R_LOG_ERROR ("This package does not have R2PM_INSTALL_WINDOWS instructions");
r_list_free (bindir_before);
return 1;
}
script = r_str_replace_all (script, "\r\n", " & ");
Expand All @@ -1035,10 +1185,20 @@ static int r2pm_install_pkg(const char *pkg, bool clean, bool global) {
free (etarget);
int res = r_sandbox_system (s, 1);
free (s);
if (res == 0) {
r2pm_register (pkg, global);
RList *bindir_after = r2pm_bindir_snapshot ();
RList *new_files = r2pm_bindir_new_files (bindir_before, bindir_after);
r2pm_report_new_bindir_files (pkg, new_files);
r_list_free (new_files);
r_list_free (bindir_after);
}
r_list_free (bindir_before);
#else
char *script = r2pm_get (pkg, "\nR2PM_INSTALL() {\n", TT_CODEBLOCK);
if (!script) {
R_LOG_ERROR ("Cannot find '%s' package or missing R2PM_INSTALL block", pkg);
r_list_free (bindir_before);
free (srcdir);
return 1;
}
Expand All @@ -1054,6 +1214,7 @@ static int r2pm_install_pkg(const char *pkg, bool clean, bool global) {
if (have_builddir && !r_file_is_directory (pkgdir)) {
R_LOG_ERROR ("Cannot find directory: %s", pkgdir);
free (pkgdir);
r_list_free (bindir_before);
return 1;
}
char *epkgdir = r_str_escape_sh (pkgdir);
Expand All @@ -1067,7 +1228,13 @@ static int r2pm_install_pkg(const char *pkg, bool clean, bool global) {
free (s);
if (res == 0) {
r2pm_register (pkg, global);
RList *bindir_after = r2pm_bindir_snapshot ();
RList *new_files = r2pm_bindir_new_files (bindir_before, bindir_after);
r2pm_report_new_bindir_files (pkg, new_files);
r_list_free (new_files);
r_list_free (bindir_after);
}
r_list_free (bindir_before);
#endif
free (script);
free (srcdir);
Expand Down
6 changes: 3 additions & 3 deletions test/fuzz/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@

## Setup

Get libFuzzer-capable clang
In macOS:

```shell
brew install llvm@22 meson ninja
eval $(make env)
make setup
make b
```

Running with the provided Makefile

```shell
cd test/fuzz
make setup
make build
make run-fuzzer T=fuzz_types_parser
```
Expand Down
Loading