static int stderr_open(gx_io_device * iodev, const char *access, stream ** ps, gs_memory_t * mem) { i_ctx_t *i_ctx_p = (i_ctx_t *)iodev->state; /* see above */ stream *s; if (!streq1(access, 'w')) return_error(e_invalidfileaccess); if (file_is_invalid(s, &ref_stderr)) { gs_memory_t *mem = imemory_system; byte *buf; s = file_alloc_stream(mem, "stderr_open(stream)"); buf = gs_alloc_bytes(mem, STDERR_BUF_SIZE, "stderr_open(buffer)"); if (s == 0 || buf == 0) return_error(e_VMerror); swrite_file(s, gs_stderr, buf, STDERR_BUF_SIZE); s->save_close = s->procs.flush; s->procs.close = file_close_file; make_file(&ref_stderr, a_write | avm_system, s->write_id, s); *ps = s; return 1; } *ps = s; return 0; }
static int stdin_open(gx_io_device * iodev, const char *access, stream ** ps, gs_memory_t * mem) { i_ctx_t *i_ctx_p = (i_ctx_t *)iodev->state; /* see above */ stream *s; if (!streq1(access, 'r')) return_error(e_invalidfileaccess); if (file_is_invalid(s, &ref_stdin)) { /****** stdin SHOULD NOT LINE-BUFFER ******/ gs_memory_t *mem = imemory_system; byte *buf; s = file_alloc_stream(mem, "stdin_open(stream)"); /* We want stdin to read only one character at a time, */ /* but it must have a substantial buffer, in case it is used */ /* by a stream that requires more than one input byte */ /* to make progress. */ buf = gs_alloc_bytes(mem, STDIN_BUF_SIZE, "stdin_open(buffer)"); if (s == 0 || buf == 0) return_error(e_VMerror); sread_file(s, gs_stdin, buf, STDIN_BUF_SIZE); s->procs.process = s_stdin_read_process; s->save_close = s_std_null; s->procs.close = file_close_file; make_file(&ref_stdin, a_readonly | avm_system, s->read_id, s); *ps = s; return 1; } *ps = s; return 0; }
/* <file> flushfile - */ static int zflushfile(i_ctx_t *i_ctx_p) { os_ptr op = osp; stream *s; int status; check_type(*op, t_file); /* * We think flushfile is a no-op on closed input files, but causes an * error on closed output files. */ if (file_is_invalid(s, op)) { if (r_has_attr(op, a_write)) return_error(e_invalidaccess); pop(1); return 0; } status = sflush(s); if (status == 0 || status == EOFC) { pop(1); return 0; } return (s_is_writing(s) ? handle_write_status(i_ctx_p, status, op, NULL, zflushfile) : handle_read_status(i_ctx_p, status, op, NULL, zflushfile)); }
/* Write a buffer to stdout, potentially writing to callback */ static int s_stdout_write_process(stream_state * st, stream_cursor_read * ignore_pr, stream_cursor_write * pw, bool last) { uint count = pr->limit - pr->ptr; int written; if (count == 0) return 0; written = outwrite(st->memory, pr->ptr + 1, count); if (written < count) { return ERRC; pr->ptr += written; return 0; } static int stdout_open(gx_io_device * iodev, const char *access, stream ** ps, gs_memory_t * mem) { i_ctx_t *i_ctx_p = (i_ctx_t *)iodev->state; /* see above */ stream *s; if (!streq1(access, 'w')) return_error(e_invalidfileaccess); if (file_is_invalid(s, &ref_stdout)) { gs_memory_t *mem = imemory_system; byte *buf; s = file_alloc_stream(mem, "stdout_open(stream)"); buf = gs_alloc_bytes(mem, STDOUT_BUF_SIZE, "stdout_open(buffer)"); if (s == 0 || buf == 0) return_error(e_VMerror); swrite_file(s, gs_stdout, buf, STDOUT_BUF_SIZE); s->save_close = s->procs.flush; s->procs.close = file_close_file; s->procs.process = s_stdout_write_process; make_file(&ref_stdout, a_write | avm_system, s->write_id, s); *ps = s; return 1; } *ps = s; return 0; }
/* Check a stack to make sure all its elements are older than a save. */ static int restore_check_stack(const i_ctx_t *i_ctx_p, const ref_stack_t * pstack, const alloc_save_t * asave, bool is_estack) { ref_stack_enum_t rsenum; ref_stack_enum_begin(&rsenum, pstack); do { const ref *stkp = rsenum.ptr; uint size = rsenum.size; for (; size; stkp++, size--) { const void *ptr; switch (r_type(stkp)) { case t_array: /* * Zero-length arrays are a special case: see the * t_*array case (label rr:) in igc.c:gc_trace. */ if (r_size(stkp) == 0) { /*stkp->value.refs = (void *)0;*/ continue; } ptr = stkp->value.refs; break; case t_dictionary: ptr = stkp->value.pdict; break; case t_file: /* Don't check executable or closed literal */ /* files on the e-stack. */ { stream *s; if (is_estack && (r_has_attr(stkp, a_executable) || file_is_invalid(s, stkp)) ) continue; } ptr = stkp->value.pfile; break; case t_name: /* Names are special because of how they are allocated. */ if (alloc_name_is_since_save((const gs_memory_t *)pstack->memory, stkp, asave)) return_error(e_invalidrestore); continue; case t_string: /* Don't check empty executable strings */ /* on the e-stack. */ if (r_size(stkp) == 0 && r_has_attr(stkp, a_executable) && is_estack ) continue; ptr = stkp->value.bytes; break; case t_mixedarray: case t_shortarray: /* See the t_array case above. */ if (r_size(stkp) == 0) { /*stkp->value.packed = (void *)0;*/ continue; } ptr = stkp->value.packed; break; case t_device: ptr = stkp->value.pdevice; break; case t_fontID: case t_struct: case t_astruct: ptr = stkp->value.pstruct; break; case t_save: /* See the comment in isave.h regarding the following. */ if (i_ctx_p->language_level <= 2) continue; ptr = alloc_find_save(&gs_imemory, stkp->value.saveid); /* * Invalid save objects aren't supposed to be possible * in LL3, but just in case.... */ if (ptr == 0) return_error(e_invalidrestore); if (ptr == asave) continue; break; default: continue; } if (alloc_is_since_save(ptr, asave)) return_error(e_invalidrestore); } } while (ref_stack_enum_next(&rsenum)); return 0; /* OK */ }