Rewrite how rz_cons_pipe_open/close behave to remove globals (#4223)

This commit is contained in:
Giovanni 2024-02-14 09:05:17 +08:00 committed by GitHub
parent fa455f8b52
commit 2886608d59
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 164 additions and 67 deletions

View file

@ -1,62 +1,151 @@
// SPDX-FileCopyrightText: 2009-2020 pancake <pancake@nopcode.org>
// SPDX-FileCopyrightText: 2024 RizinOrg <info@rizin.re>
// SPDX-FileCopyrightText: 2024 deroad <wargio@libero.it>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_cons.h>
#include <limits.h>
// TODO: remove globals, and make this stackable
// cons_pipe should be using a stack pipe_push, pipe_pop
static int backup_fd = -1;
static int backup_fdn = 1;
#ifndef O_BINARY
#define O_BINARY 0
#endif
static bool __dupDescriptor(int fd, int fdn) {
#if __WINDOWS__
backup_fd = 2002 - (fd - 2); // windows xp has 2048 as limit fd
return _dup2(fdn, backup_fd) != -1;
#else
backup_fd = sysconf(_SC_OPEN_MAX) - (fd - 2); // portable getdtablesize()
if (backup_fd < 2) {
backup_fd = 2002 - (fd - 2); // fallback
#include <io.h>
/**
* \brief Duplicates a file descriptor and returns the new one.
*
* \param old_fd File descriptor to duplicate
* \return On success is a positive integer, otherwise -1
*/
static int pipe_dup_fd(int old_fd) {
int new_fd = _dup(old_fd);
if (new_fd < 0) {
return -1;
}
return dup2(fdn, backup_fd) != -1;
#endif
return new_fd;
}
RZ_API int rz_cons_pipe_open(const char *file, int fdn, int append) {
if (fdn < 1) {
return -1;
/**
* \brief Duplicates a file descriptor by assigning a given one.
*
* \param old_fd Old file descriptor to duplicate
* \param new_fd New file descriptor
* \return true on success, otherwise false.
*/
static bool pipe_dup2_fd(int old_fd, int new_fd) {
if (!_dup2(old_fd, new_fd)) {
return true;
}
const int fd_flags = O_BINARY | O_RDWR | O_CREAT | (append ? O_APPEND : O_TRUNC);
int fd = rz_sys_open(file, fd_flags, 0644);
if (fd == -1) {
eprintf("rz_cons_pipe_open: Cannot open file '%s'\n", file);
return -1;
}
if (backup_fd != -1) {
close(backup_fd);
// already set in __dupDescriptor // backup_fd = -1;
}
backup_fdn = fdn;
if (!__dupDescriptor(fd, fdn)) {
eprintf("Cannot dup stdout to %d\n", fdn);
return -1;
}
close(fdn);
dup2(fd, fdn);
return fd;
return false;
}
RZ_API void rz_cons_pipe_close(int fd) {
if (fd != -1) {
close(fd);
if (backup_fd != -1) {
dup2(backup_fd, backup_fdn);
close(backup_fd);
backup_fd = -1;
}
#else /* !__WINDOWS__ */
/**
* \brief Duplicates a file descriptor and returns the new one.
*
* \param old_fd File descriptor to duplicate
* \return On success is a positive integer, otherwise -1
*/
static int pipe_dup_fd(int old_fd) {
int new_fd = dup(old_fd);
if (new_fd < 0) {
return -1;
}
return new_fd;
}
/**
* \brief Duplicates a file descriptor by assigning a given one.
*
* \param old_fd Old file descriptor to duplicate
* \param new_fd New file descriptor
* \return true on success, otherwise false.
*/
static bool pipe_dup2_fd(int old_fd, int new_fd) {
if (dup2(old_fd, new_fd) == new_fd) {
return true;
}
return false;
}
#endif /* __WINDOWS__ */
struct rz_cons_pipe_t {
int fd; ///< File descriptor number to override.
int copy_fd; ///< Copy of the file descriptor.
int file_fd; ///< File descriptor of the opened file.
};
/**
* \brief Redirects the data flow from a file descriptor to a file.
*
* \param file File name to open where to redirect the file descriptor.
* \param fd The file descriptor to pipe
* \param append When true, the data written to the file is appended.
* \return On success a valid pointer, otherwise NULL.
*/
RZ_API RZ_OWN RzConsPipe *rz_cons_pipe_open(RZ_NONNULL const char *file, int fd, bool append) {
rz_return_val_if_fail(RZ_STR_ISNOTEMPTY(file), NULL);
if (fd < 1) {
RZ_LOG_ERROR("cpipe: invalid file descriptor '%d'\n", fd);
return NULL;
}
RzConsPipe *cpipe = RZ_NEW0(RzConsPipe);
if (!cpipe) {
RZ_LOG_ERROR("cpipe: cannot allocate RzConsPipe\n");
return NULL;
}
// open file to which we pipe all the data from fd
const int file_flags = O_BINARY | O_RDWR | O_CREAT | (append ? O_APPEND : O_TRUNC);
int file_fd = rz_sys_open(file, file_flags, 0644);
if (file_fd < 0) {
RZ_LOG_ERROR("cpipe: Cannot open file '%s'\n", file);
free(cpipe);
return NULL;
}
// save the original file descriptor by making a copy
int copy_fd = pipe_dup_fd(fd);
if (copy_fd < 0) {
RZ_LOG_ERROR("cpipe: Cannot duplicate %d\n", fd);
close(file_fd);
free(cpipe);
return NULL;
}
// override file descriptor with the opened file one.
if (!pipe_dup2_fd(file_fd, fd)) {
RZ_LOG_ERROR("cpipe: Cannot duplicate %d to %d\n", file_fd, fd);
close(copy_fd);
close(file_fd);
free(cpipe);
return NULL;
}
cpipe->fd = fd;
cpipe->copy_fd = copy_fd;
cpipe->file_fd = file_fd;
return cpipe;
}
/**
* \brief Closes a given RzConsPipe and restores the file descriptor.
*
* \param cpipe The console pipe to close.
*/
RZ_API void rz_cons_pipe_close(RZ_NULLABLE RzConsPipe *cpipe) {
if (!cpipe) {
return;
}
// restore file descriptor from copy.
if (!pipe_dup2_fd(cpipe->copy_fd, cpipe->fd)) {
RZ_LOG_ERROR("cpipe: Cannot duplicate %d to %d\n", cpipe->copy_fd, cpipe->fd);
}
// close the opened file descriptors
close(cpipe->copy_fd);
close(cpipe->file_fd);
free(cpipe);
}

View file

@ -1442,7 +1442,8 @@ static int rz_core_cmd_subst_i(RzCore *core, char *cmd, char *colon, bool *tmpse
char *grep = NULL;
RzIODesc *tmpdesc = NULL;
int pamode = !core->io->va;
int i, ret = 0, pipefd;
int i, ret = 0;
RzConsPipe *cpipe = NULL;
bool usemyblock = false;
int scr_html = -1;
int scr_color = -1;
@ -1482,7 +1483,7 @@ static int rz_core_cmd_subst_i(RzCore *core, char *cmd, char *colon, bool *tmpse
break;
case '"':
for (; *cmd;) {
int pipefd = -1;
RzConsPipe *cpipe = NULL;
ut64 oseek = UT64_MAX;
char *line, *p;
haveQuote = *cmd == '"';
@ -1543,7 +1544,8 @@ static int rz_core_cmd_subst_i(RzCore *core, char *cmd, char *colon, bool *tmpse
str = (char *)rz_str_trim_head_ro(str);
rz_cons_flush();
const bool append = p[2] == '>';
pipefd = rz_cons_pipe_open(str, 1, append);
/* pipe stdout */
cpipe = rz_cons_pipe_open(str, 1, append);
}
}
line = strdup(cmd);
@ -1558,9 +1560,10 @@ static int rz_core_cmd_subst_i(RzCore *core, char *cmd, char *colon, bool *tmpse
if (oseek != UT64_MAX) {
rz_core_seek(core, oseek, true);
}
if (pipefd != -1) {
if (cpipe) {
rz_cons_flush();
rz_cons_pipe_close(pipefd);
rz_cons_pipe_close(cpipe);
cpipe = NULL;
}
if (!p) {
break;
@ -1813,14 +1816,14 @@ escape_pipe:
free(o);
} else if (fdn > 0) {
// pipe to file (or append)
pipefd = rz_cons_pipe_open(str, fdn, appendResult);
if (pipefd != -1) {
cpipe = rz_cons_pipe_open(str, fdn, appendResult);
if (cpipe) {
if (!pipecolor) {
rz_config_set_i(core->config, "scr.color", COLOR_MODE_DISABLED);
}
ret = rz_core_cmd_subst(core, cmd);
rz_cons_flush();
rz_cons_pipe_close(pipefd);
rz_cons_pipe_close(cpipe);
}
}
rz_cons_set_last_interactive();
@ -3884,17 +3887,17 @@ DEFINE_HANDLE_TS_FCN_AND_SYMBOL(redirect_stmt) {
} else {
rz_cons_flush();
RZ_LOG_DEBUG("redirect_stmt: fdn = %d, is_append = %d\n", fdn, is_append);
int pipefd = rz_cons_pipe_open(arg_str, fdn, is_append);
if (pipefd != -1) {
RzConsPipe *cpipe = rz_cons_pipe_open(arg_str, fdn, is_append);
if (cpipe) {
if (!pipecolor) {
rz_config_set_i(state->core->config, "scr.color", COLOR_MODE_DISABLED);
}
TSNode command = ts_node_child_by_field_name(node, "command", strlen("command"));
res = handle_ts_stmt(state, command);
rz_cons_flush();
rz_cons_pipe_close(pipefd);
rz_cons_pipe_close(cpipe);
} else {
RZ_LOG_WARN("Could not open pipe to %d", fdn);
RZ_LOG_WARN("Could not open pipe to %d\n", fdn);
}
}
free(arg_str);
@ -5533,8 +5536,8 @@ RZ_API char *rz_core_cmd_str_pipe(RzCore *core, const char *cmd) {
}
rz_cons_reset();
if (rz_file_mkstemp("cmd", &tmp) != -1) {
int pipefd = rz_cons_pipe_open(tmp, 1, 0);
if (pipefd == -1) {
RzConsPipe *cpipe = rz_cons_pipe_open(tmp, 1, 0);
if (!cpipe) {
rz_file_rm(tmp);
free(tmp);
return rz_core_cmd_str(core, cmd);
@ -5542,7 +5545,7 @@ RZ_API char *rz_core_cmd_str_pipe(RzCore *core, const char *cmd) {
char *_cmd = strdup(cmd);
rz_core_cmd(core, _cmd, 0);
rz_cons_flush();
rz_cons_pipe_close(pipefd);
rz_cons_pipe_close(cpipe);
if (rz_file_exists(tmp)) {
char *s = rz_file_slurp(tmp, NULL);
rz_file_rm(tmp);

View file

@ -50,10 +50,14 @@ static int __rap_detach(RzDebug *dbg, int pid) {
static char *__rap_reg_profile(RzDebug *dbg) {
char *out, *tf = rz_file_temp("rap.XXXXXX");
int fd = rz_cons_pipe_open(tf, 1, 0);
RzConsPipe *cpipe = rz_cons_pipe_open(tf, 1, 0);
if (!cpipe) {
rz_file_rm(tf);
return NULL;
}
rz_io_system(dbg->iob.io, "drp");
rz_cons_flush();
rz_cons_pipe_close(fd);
rz_cons_pipe_close(cpipe);
out = rz_file_slurp(tf, NULL);
rz_file_rm(tf);
free(tf);

View file

@ -904,8 +904,9 @@ RZ_API void rz_cons_break_end(void);
RZ_API void rz_cons_break_timeout(int timeout);
/* pipe */
RZ_API int rz_cons_pipe_open(const char *file, int fdn, int append);
RZ_API void rz_cons_pipe_close(int fd);
typedef struct rz_cons_pipe_t RzConsPipe;
RZ_API RZ_OWN RzConsPipe *rz_cons_pipe_open(RZ_NONNULL const char *file, int old_fd, bool append);
RZ_API void rz_cons_pipe_close(RZ_NULLABLE RzConsPipe *cpipe);
#if __WINDOWS__
RZ_API RzVirtTermMode rz_cons_detect_vt_mode(void);