mirror of
https://github.com/Leonmmcoset/cleonos.git
synced 2026-04-21 18:44:01 +00:00
fd子系统2
This commit is contained in:
@@ -5,6 +5,8 @@
|
|||||||
#define USH_COPY_MAX 65536U
|
#define USH_COPY_MAX 65536U
|
||||||
#define USH_PIPELINE_MAX_STAGES 8ULL
|
#define USH_PIPELINE_MAX_STAGES 8ULL
|
||||||
#define USH_PIPE_CAPTURE_MAX USH_COPY_MAX
|
#define USH_PIPE_CAPTURE_MAX USH_COPY_MAX
|
||||||
|
#define USH_PIPE_TMP_A "/temp/.ush_pipe_a.bin"
|
||||||
|
#define USH_PIPE_TMP_B "/temp/.ush_pipe_b.bin"
|
||||||
#define USH_SORT_MAX_LINES 4096ULL
|
#define USH_SORT_MAX_LINES 4096ULL
|
||||||
|
|
||||||
typedef struct ush_pipeline_stage {
|
typedef struct ush_pipeline_stage {
|
||||||
@@ -2724,16 +2726,89 @@ static int ush_pipeline_parse(const char *line,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ush_pipeline_write_redirect(const ush_state *sh, const ush_pipeline_stage *stage, const char *data, u64 len) {
|
static int ush_pipeline_open_write_fd(const char *path, u64 flags, u64 *out_fd) {
|
||||||
char abs_path[USH_PATH_MAX];
|
u64 fd;
|
||||||
u64 ok;
|
|
||||||
|
|
||||||
if (sh == (const ush_state *)0 || stage == (const ush_pipeline_stage *)0) {
|
if (path == (const char *)0 || out_fd == (u64 *)0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = cleonos_sys_fd_open(path, flags, 0ULL);
|
||||||
|
|
||||||
|
if (fd == (u64)-1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_fd = fd;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ush_pipeline_read_path_into_buffer(const char *path, char *buffer, u64 buffer_size, u64 *out_len) {
|
||||||
|
u64 fd;
|
||||||
|
u64 total = 0ULL;
|
||||||
|
int truncated = 0;
|
||||||
|
char drain[256];
|
||||||
|
|
||||||
|
if (path == (const char *)0 || buffer == (char *)0 || buffer_size < 2ULL || out_len == (u64 *)0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_len = 0ULL;
|
||||||
|
buffer[0] = '\0';
|
||||||
|
|
||||||
|
fd = cleonos_sys_fd_open(path, CLEONOS_O_RDONLY, 0ULL);
|
||||||
|
|
||||||
|
if (fd == (u64)-1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
u64 got;
|
||||||
|
u64 room;
|
||||||
|
|
||||||
|
if (total + 1ULL < buffer_size) {
|
||||||
|
room = (buffer_size - 1ULL) - total;
|
||||||
|
got = cleonos_sys_fd_read(fd, buffer + total, room);
|
||||||
|
} else {
|
||||||
|
got = cleonos_sys_fd_read(fd, drain, (u64)sizeof(drain));
|
||||||
|
truncated = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (got == (u64)-1) {
|
||||||
|
(void)cleonos_sys_fd_close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (got == 0ULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (total + got < buffer_size) {
|
||||||
|
total += got;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)cleonos_sys_fd_close(fd);
|
||||||
|
buffer[total] = '\0';
|
||||||
|
*out_len = total;
|
||||||
|
|
||||||
|
if (truncated != 0) {
|
||||||
|
ush_writeln("[pipe] input truncated");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ush_pipeline_open_redirect_fd(const ush_state *sh, const ush_pipeline_stage *stage, u64 *out_fd) {
|
||||||
|
char abs_path[USH_PATH_MAX];
|
||||||
|
u64 flags = CLEONOS_O_WRONLY | CLEONOS_O_CREAT;
|
||||||
|
|
||||||
|
if (sh == (const ush_state *)0 || stage == (const ush_pipeline_stage *)0 || out_fd == (u64 *)0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stage->redirect_mode == 0) {
|
if (stage->redirect_mode == 0) {
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ush_resolve_path(sh, stage->redirect_path, abs_path, (u64)sizeof(abs_path)) == 0) {
|
if (ush_resolve_path(sh, stage->redirect_path, abs_path, (u64)sizeof(abs_path)) == 0) {
|
||||||
@@ -2741,14 +2816,19 @@ static int ush_pipeline_write_redirect(const ush_state *sh, const ush_pipeline_s
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stage->redirect_mode == 1) {
|
if (ush_path_is_under_temp(abs_path) == 0) {
|
||||||
ok = cleonos_sys_fs_write(abs_path, data, len);
|
ush_writeln("redirect: path must be under /temp");
|
||||||
} else {
|
return 0;
|
||||||
ok = cleonos_sys_fs_append(abs_path, data, len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ok == 0ULL) {
|
if (stage->redirect_mode == 1) {
|
||||||
ush_writeln("redirect: write failed");
|
flags |= CLEONOS_O_TRUNC;
|
||||||
|
} else {
|
||||||
|
flags |= CLEONOS_O_APPEND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ush_pipeline_open_write_fd(abs_path, flags, out_fd) == 0) {
|
||||||
|
ush_writeln("redirect: open failed");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2762,12 +2842,12 @@ static int ush_execute_pipeline(ush_state *sh,
|
|||||||
ush_pipeline_stage stages[USH_PIPELINE_MAX_STAGES];
|
ush_pipeline_stage stages[USH_PIPELINE_MAX_STAGES];
|
||||||
u64 stage_count = 0ULL;
|
u64 stage_count = 0ULL;
|
||||||
u64 i;
|
u64 i;
|
||||||
const char *pipe_in = (const char *)0;
|
const char *pipe_input_path = (const char *)0;
|
||||||
u64 pipe_in_len = 0ULL;
|
char *pipe_input_buffer = ush_pipeline_capture_a;
|
||||||
char *capture_out = ush_pipeline_capture_a;
|
u64 pipe_input_len = 0ULL;
|
||||||
u64 capture_len = 0ULL;
|
|
||||||
int known = 1;
|
int known = 1;
|
||||||
int success = 1;
|
int success = 1;
|
||||||
|
int pipe_output_toggle = 0;
|
||||||
|
|
||||||
if (out_known != (int *)0) {
|
if (out_known != (int *)0) {
|
||||||
*out_known = 1;
|
*out_known = 1;
|
||||||
@@ -2777,6 +2857,9 @@ static int ush_execute_pipeline(ush_state *sh,
|
|||||||
*out_success = 0;
|
*out_success = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(void)cleonos_sys_fs_remove(USH_PIPE_TMP_A);
|
||||||
|
(void)cleonos_sys_fs_remove(USH_PIPE_TMP_B);
|
||||||
|
|
||||||
if (ush_pipeline_parse(line, stages, USH_PIPELINE_MAX_STAGES, &stage_count) == 0) {
|
if (ush_pipeline_parse(line, stages, USH_PIPELINE_MAX_STAGES, &stage_count) == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -2784,7 +2867,9 @@ static int ush_execute_pipeline(ush_state *sh,
|
|||||||
for (i = 0ULL; i < stage_count; i++) {
|
for (i = 0ULL; i < stage_count; i++) {
|
||||||
int stage_known = 1;
|
int stage_known = 1;
|
||||||
int stage_success = 0;
|
int stage_success = 0;
|
||||||
int mirror_to_tty = ((i + 1ULL) == stage_count && stages[i].redirect_mode == 0) ? 1 : 0;
|
int use_fd_output = 0;
|
||||||
|
u64 stage_fd = (u64)-1;
|
||||||
|
const char *stage_pipe_out = (const char *)0;
|
||||||
|
|
||||||
if (i + 1ULL < stage_count && stages[i].redirect_mode != 0) {
|
if (i + 1ULL < stage_count && stages[i].redirect_mode != 0) {
|
||||||
ush_writeln("pipe: redirection is only supported on final stage");
|
ush_writeln("pipe: redirection is only supported on final stage");
|
||||||
@@ -2793,13 +2878,51 @@ static int ush_execute_pipeline(ush_state *sh,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ush_pipeline_set_stdin(pipe_in, pipe_in_len);
|
if (pipe_input_path != (const char *)0) {
|
||||||
ush_output_capture_begin(capture_out, (u64)USH_PIPE_CAPTURE_MAX + 1ULL, mirror_to_tty);
|
if (ush_pipeline_read_path_into_buffer(pipe_input_path,
|
||||||
(void)ush_execute_single_command(sh, stages[i].cmd, stages[i].arg, 0, &stage_known, &stage_success);
|
pipe_input_buffer,
|
||||||
capture_len = ush_output_capture_end();
|
(u64)USH_PIPE_CAPTURE_MAX + 1ULL,
|
||||||
|
&pipe_input_len) == 0) {
|
||||||
|
ush_writeln("pipe: failed to read stage input");
|
||||||
|
success = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (ush_output_capture_truncated() != 0) {
|
ush_pipeline_set_stdin(pipe_input_buffer, pipe_input_len);
|
||||||
ush_writeln("[pipe] captured output truncated");
|
} else {
|
||||||
|
ush_pipeline_set_stdin((const char *)0, 0ULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i + 1ULL < stage_count) {
|
||||||
|
stage_pipe_out = (pipe_output_toggle == 0) ? USH_PIPE_TMP_A : USH_PIPE_TMP_B;
|
||||||
|
|
||||||
|
if (ush_pipeline_open_write_fd(stage_pipe_out,
|
||||||
|
CLEONOS_O_WRONLY | CLEONOS_O_CREAT | CLEONOS_O_TRUNC,
|
||||||
|
&stage_fd) == 0) {
|
||||||
|
ush_writeln("pipe: failed to open temp stream");
|
||||||
|
success = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
use_fd_output = 1;
|
||||||
|
} else if (stages[i].redirect_mode != 0) {
|
||||||
|
if (ush_pipeline_open_redirect_fd(sh, &stages[i], &stage_fd) == 0) {
|
||||||
|
success = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
use_fd_output = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (use_fd_output != 0) {
|
||||||
|
ush_output_fd_begin(stage_fd, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)ush_execute_single_command(sh, stages[i].cmd, stages[i].arg, 0, &stage_known, &stage_success);
|
||||||
|
|
||||||
|
if (use_fd_output != 0) {
|
||||||
|
ush_output_fd_end();
|
||||||
|
(void)cleonos_sys_fd_close(stage_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stage_known == 0) {
|
if (stage_known == 0) {
|
||||||
@@ -2811,19 +2934,17 @@ static int ush_execute_pipeline(ush_state *sh,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stages[i].redirect_mode != 0) {
|
if (i + 1ULL < stage_count) {
|
||||||
if (ush_pipeline_write_redirect(sh, &stages[i], capture_out, capture_len) == 0) {
|
pipe_input_path = stage_pipe_out;
|
||||||
success = 0;
|
pipe_input_buffer = (pipe_input_buffer == ush_pipeline_capture_a) ? ush_pipeline_capture_b
|
||||||
break;
|
: ush_pipeline_capture_a;
|
||||||
|
pipe_output_toggle = (pipe_output_toggle == 0) ? 1 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pipe_in = capture_out;
|
|
||||||
pipe_in_len = capture_len;
|
|
||||||
capture_out = (capture_out == ush_pipeline_capture_a) ? ush_pipeline_capture_b : ush_pipeline_capture_a;
|
|
||||||
}
|
|
||||||
|
|
||||||
ush_pipeline_set_stdin((const char *)0, 0ULL);
|
ush_pipeline_set_stdin((const char *)0, 0ULL);
|
||||||
|
(void)cleonos_sys_fs_remove(USH_PIPE_TMP_A);
|
||||||
|
(void)cleonos_sys_fs_remove(USH_PIPE_TMP_B);
|
||||||
|
|
||||||
if (out_known != (int *)0) {
|
if (out_known != (int *)0) {
|
||||||
*out_known = known;
|
*out_known = known;
|
||||||
|
|||||||
@@ -88,6 +88,8 @@ void ush_writeln(const char *text);
|
|||||||
void ush_output_capture_begin(char *buffer, u64 buffer_size, int mirror_to_tty);
|
void ush_output_capture_begin(char *buffer, u64 buffer_size, int mirror_to_tty);
|
||||||
u64 ush_output_capture_end(void);
|
u64 ush_output_capture_end(void);
|
||||||
int ush_output_capture_truncated(void);
|
int ush_output_capture_truncated(void);
|
||||||
|
void ush_output_fd_begin(u64 fd, int mirror_to_tty);
|
||||||
|
void ush_output_fd_end(void);
|
||||||
void ush_prompt(const ush_state *sh);
|
void ush_prompt(const ush_state *sh);
|
||||||
void ush_write_hex_u64(u64 value);
|
void ush_write_hex_u64(u64 value);
|
||||||
void ush_print_kv_hex(const char *label, u64 value);
|
void ush_print_kv_hex(const char *label, u64 value);
|
||||||
|
|||||||
@@ -225,6 +225,9 @@ static u64 ush_out_capture_length = 0ULL;
|
|||||||
static int ush_out_capture_active = 0;
|
static int ush_out_capture_active = 0;
|
||||||
static int ush_out_capture_mirror_tty = 1;
|
static int ush_out_capture_mirror_tty = 1;
|
||||||
static int ush_out_capture_truncated = 0;
|
static int ush_out_capture_truncated = 0;
|
||||||
|
static u64 ush_out_fd = (u64)-1;
|
||||||
|
static int ush_out_fd_active = 0;
|
||||||
|
static int ush_out_fd_mirror_tty = 1;
|
||||||
|
|
||||||
static void ush_output_capture_append(const char *text, u64 len) {
|
static void ush_output_capture_append(const char *text, u64 len) {
|
||||||
u64 writable;
|
u64 writable;
|
||||||
@@ -295,8 +298,21 @@ int ush_output_capture_truncated(void) {
|
|||||||
return ush_out_capture_truncated;
|
return ush_out_capture_truncated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ush_output_fd_begin(u64 fd, int mirror_to_tty) {
|
||||||
|
ush_out_fd = fd;
|
||||||
|
ush_out_fd_active = 1;
|
||||||
|
ush_out_fd_mirror_tty = (mirror_to_tty != 0) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ush_output_fd_end(void) {
|
||||||
|
ush_out_fd = (u64)-1;
|
||||||
|
ush_out_fd_active = 0;
|
||||||
|
ush_out_fd_mirror_tty = 1;
|
||||||
|
}
|
||||||
|
|
||||||
void ush_write(const char *text) {
|
void ush_write(const char *text) {
|
||||||
u64 len;
|
u64 len;
|
||||||
|
int should_write_tty = 1;
|
||||||
|
|
||||||
if (text == (const char *)0) {
|
if (text == (const char *)0) {
|
||||||
return;
|
return;
|
||||||
@@ -312,24 +328,46 @@ void ush_write(const char *text) {
|
|||||||
ush_output_capture_append(text, len);
|
ush_output_capture_append(text, len);
|
||||||
|
|
||||||
if (ush_out_capture_mirror_tty == 0) {
|
if (ush_out_capture_mirror_tty == 0) {
|
||||||
return;
|
should_write_tty = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ush_out_fd_active != 0 && ush_out_fd != (u64)-1) {
|
||||||
|
(void)cleonos_sys_fd_write(ush_out_fd, text, len);
|
||||||
|
|
||||||
|
if (ush_out_fd_mirror_tty == 0) {
|
||||||
|
should_write_tty = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (should_write_tty != 0) {
|
||||||
(void)cleonos_sys_tty_write(text, len);
|
(void)cleonos_sys_tty_write(text, len);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ush_write_char(char ch) {
|
void ush_write_char(char ch) {
|
||||||
|
int should_write_tty = 1;
|
||||||
|
|
||||||
if (ush_out_capture_active != 0) {
|
if (ush_out_capture_active != 0) {
|
||||||
ush_output_capture_append(&ch, 1ULL);
|
ush_output_capture_append(&ch, 1ULL);
|
||||||
|
|
||||||
if (ush_out_capture_mirror_tty == 0) {
|
if (ush_out_capture_mirror_tty == 0) {
|
||||||
return;
|
should_write_tty = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ush_out_fd_active != 0 && ush_out_fd != (u64)-1) {
|
||||||
|
(void)cleonos_sys_fd_write(ush_out_fd, &ch, 1ULL);
|
||||||
|
|
||||||
|
if (ush_out_fd_mirror_tty == 0) {
|
||||||
|
should_write_tty = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (should_write_tty != 0) {
|
||||||
(void)cleonos_sys_tty_write_char(ch);
|
(void)cleonos_sys_tty_write_char(ch);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ush_writeln(const char *text) {
|
void ush_writeln(const char *text) {
|
||||||
ush_write(text);
|
ush_write(text);
|
||||||
|
|||||||
Reference in New Issue
Block a user