Esempio n. 1
0
/* return zero for success, -ve for error, +1 for continue */
static int
lib_file_open_search_with_combine(gs_file_path_ptr  lib_path, const gs_memory_t *mem, i_ctx_t *i_ctx_p,
                                  const char *fname, uint flen, char *buffer, int blen, uint *pclen, ref *pfile,
                                  gx_io_device *iodev, bool starting_arg_file, char *fmode)
{
    stream *s;
    const gs_file_path *pfpath = lib_path;
    uint pi;

    for (pi = 0; pi < r_size(&pfpath->list); ++pi) {
        const ref *prdir = pfpath->list.value.refs + pi;
        const char *pstr = (const char *)prdir->value.const_bytes;
        uint plen = r_size(prdir), blen1 = blen;
        gs_parsed_file_name_t pname;
        gp_file_name_combine_result r;

        /* We need to concatenate and parse the file name here
         * if this path has a %device% prefix.              */
        if (pstr[0] == '%') {
            int code;

            /* We concatenate directly since gp_file_name_combine_*
             * rules are not correct for other devices such as %rom% */
            code = gs_parse_file_name(&pname, pstr, plen, mem);
            if (code < 0)
                continue;
            memcpy(buffer, pname.fname, pname.len);
            memcpy(buffer+pname.len, fname, flen);
            code = pname.iodev->procs.open_file(pname.iodev, buffer, pname.len + flen, fmode,
                                          &s, (gs_memory_t *)mem);
            if (code < 0)
                continue;
            make_stream_file(pfile, s, "r");
            /* fill in the buffer with the device concatenated */
            memcpy(buffer, pstr, plen);
            memcpy(buffer+plen, fname, flen);
            *pclen = plen + flen;
            return 0;
        } else {
            r = gp_file_name_combine(pstr, plen,
                    fname, flen, false, buffer, &blen1);
            if (r != gp_combine_success)
                continue;
            if (iodev_os_open_file(iodev, (const char *)buffer, blen1, (const char *)fmode,
                                    &s, (gs_memory_t *)mem) == 0) {
                if (starting_arg_file ||
                    check_file_permissions_aux(i_ctx_p, buffer, blen1) >= 0) {
                    *pclen = blen1;
                    make_stream_file(pfile, s, "r");
                    return 0;
                }
                sclose(s);
                return_error(e_invalidfileaccess);
            }
        }
    }
    return 1;
}
Esempio n. 2
0
/* Make a reusable file stream. */
static int
make_rfs(i_ctx_t *i_ctx_p, os_ptr op, stream *fs, long offset, long length)
{
    uint save_space = icurrent_space;
    uint stream_space = imemory_space((const gs_ref_memory_t *)fs->memory);
    gs_const_string fname;
    gs_parsed_file_name_t pname;
    stream *s;
    int code;

    if (sfilename(fs, &fname) < 0)
        return_error(e_ioerror);
    code = gs_parse_file_name(&pname, (const char *)fname.data, fname.size,
                              imemory);
    if (code < 0)
        return code;
    if (pname.len == 0)		/* %stdin% etc. won't have a filename */
        return_error(e_invalidfileaccess); /* can't reopen */
    if (pname.iodev == NULL)
        pname.iodev = iodev_default(imemory);
    /* Open the file again, to be independent of the source. */
    ialloc_set_space(idmemory, stream_space);
    code = zopen_file(i_ctx_p, &pname, "r", &s, imemory);
    ialloc_set_space(idmemory, save_space);
    if (code < 0)
        return code;
    if (sread_subfile(s, offset, length) < 0) {
        sclose(s);
        return_error(e_ioerror);
    }
    s->close_at_eod = false;
    make_stream_file(op, s, "r");
    return 0;
}
Esempio n. 3
0
/* <string> print - */
static int
zprint(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    stream *s;
    int status;
    ref rstdout;
    int code;

    check_read_type(*op, t_string);
    code = zget_stdout(i_ctx_p, &s);
    if (code < 0)
	return code;
    status = write_string(op, s);
    if (status >= 0) {
	pop(1);
	return 0;
    }
    /* Convert print to writestring on the fly. */
    make_stream_file(&rstdout, s, "w");
    code = handle_write_status(i_ctx_p, status, &rstdout, NULL,
			       zwritestring);
    if (code != o_push_estack)
	return code;
    push(1);
    *op = op[-1];
    op[-1] = rstdout;
    return code;
}
Esempio n. 4
0
/* <string> .libfile <string> false */
int                             /* exported for zsysvm.c */
zlibfile(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    int code;
    byte cname[DEFAULT_BUFFER_SIZE];
    uint clen;
    gs_parsed_file_name_t pname;
    stream *s;
    gx_io_device *iodev_dflt;

    check_ostack(2);
    code = parse_file_name(op, &pname, i_ctx_p->LockFilePermissions, imemory);
    if (code < 0)
        return code;
    iodev_dflt = iodev_default(imemory);
    if (pname.iodev == NULL)
        pname.iodev = iodev_dflt;
    if (pname.iodev != iodev_dflt) { /* Non-OS devices don't have search paths (yet). */
        code = zopen_file(i_ctx_p, &pname, "r", &s, imemory);
        if (code >= 0) {
            code = ssetfilename(s, op->value.const_bytes, r_size(op));
            if (code < 0) {
                sclose(s);
                return_error(e_VMerror);
            }
        }
        if (code < 0) {
            push(1);
            make_false(op);
            return 0;
        }
        make_stream_file(op, s, "r");
    } else {
        ref fref;

        code = lib_file_open(i_ctx_p->lib_path, imemory, i_ctx_p, pname.fname, pname.len,
                             (char *)cname, sizeof(cname), &clen, &fref);
        if (code >= 0) {
            s = fptr(&fref);
            code = ssetfilename(s, cname, clen);
            if (code < 0) {
                sclose(s);
                return_error(e_VMerror);
            }
        }
        if (code < 0) {
            if (code == e_VMerror || code == e_invalidfileaccess)
                return code;
            push(1);
            make_false(op);
            return 0;
        }
        ref_assign(op, &fref);
    }
    push(1);
    make_true(op);
    return 0;
}
Esempio n. 5
0
/* Make a reusable string stream. */
int
make_rss(i_ctx_t *i_ctx_p, os_ptr op, const byte * data, uint size,
         uint string_space, long offset, long length, bool is_bytestring)
{
    uint save_space = icurrent_space;
    stream *s;
    long left = min(length, size - offset);

    ialloc_set_space(idmemory, string_space);
    s = file_alloc_stream(imemory, "make_rss");
    ialloc_set_space(idmemory, save_space);
    if (s == 0)
        return_error(e_VMerror);
    sread_string_reusable(s, data + offset, max(left, 0));
    if (is_bytestring)
        s->cbuf_string.data = 0;	/* byte array, not string */
    make_stream_file(op, s, "r");
    return 0;
}
Esempio n. 6
0
/* - flush - */
int
zflush(i_ctx_t *i_ctx_p)
{
    stream *s;
    int status;
    ref rstdout;
    int code = zget_stdout(i_ctx_p, &s);

    if (code < 0)
	return code;

    make_stream_file(&rstdout, s, "w");
    status = sflush(s);
    if (status == 0 || status == EOFC) {
	return 0;
    }
    return
	(s_is_writing(s) ?
	 handle_write_status(i_ctx_p, status, &rstdout, NULL, zflush) :
	 handle_read_status(i_ctx_p, status, &rstdout, NULL, zflush));
}
Esempio n. 7
0
/* return zero for success, -ve for error, +1 for continue */
static int
lib_file_open_search_with_no_combine(gs_file_path_ptr  lib_path, const gs_memory_t *mem, i_ctx_t *i_ctx_p,
                                     const char *fname, uint flen, char *buffer, int blen, uint *pclen, ref *pfile,
                                     gx_io_device *iodev, bool starting_arg_file, char *fmode)
{
    stream *s;
    uint blen1 = blen;
    if (gp_file_name_reduce(fname, flen, buffer, &blen1) != gp_combine_success)
      goto skip;
    if (iodev_os_open_file(iodev, (const char *)buffer, blen1,
                           (const char *)fmode, &s, (gs_memory_t *)mem) == 0) {
      if (starting_arg_file ||
          check_file_permissions_aux(i_ctx_p, buffer, blen1) >= 0) {
        *pclen = blen1;
        make_stream_file(pfile, s, "r");
        return 0;
      }
      sclose(s);
      return_error(e_invalidfileaccess);
    }
 skip:;
    return 1;
}
Esempio n. 8
0
/* The startup code also calls this to open @-files. */
int
lib_file_open(gs_file_path_ptr  lib_path, const gs_memory_t *mem, i_ctx_t *i_ctx_p,      
		       const char *fname, uint flen, char *buffer, int blen, uint *pclen, ref *pfile)
{   /* i_ctx_p is NULL running arg (@) files. 
     * lib_path and mem are never NULL 
     */
    bool starting_arg_file = (i_ctx_p == NULL) ? true : i_ctx_p->starting_arg_file;
    bool search_with_no_combine = false;
    bool search_with_combine = false;
    char fmode[4] = { 'r', 0, 0, 0 };		/* room for binary suffix */
    stream *s;
    gx_io_device *iodev = iodev_default;

    /* when starting arg files (@ files) iodev_default is not yet set */
    if (iodev == 0)
        iodev = (gx_io_device *)gx_io_device_table[0];
    
    strcat(fmode, gp_fmode_binary_suffix);
    if (gp_file_name_is_absolute(fname, flen)) {
       search_with_no_combine = true;
       search_with_combine = false;
    } else {
       search_with_no_combine = starting_arg_file;
       search_with_combine = true;
    }
    if (search_with_no_combine) {
	uint blen1 = blen;

	if (gp_file_name_reduce(fname, flen, buffer, &blen1) != gp_combine_success)
	    goto skip;
	if (iodev_os_open_file(iodev, (const char *)buffer, blen1,
				(const char *)fmode, &s, (gs_memory_t *)mem) == 0) {
	    if (starting_arg_file ||
			check_file_permissions_aux(i_ctx_p, buffer, blen1) >= 0) {
		*pclen = blen1;
		make_stream_file(pfile, s, "r");
		return 0;
	    }
	    sclose(s);
	    return_error(e_invalidfileaccess);
	}
	skip:;
    } 
    if (search_with_combine) {
	const gs_file_path *pfpath = lib_path;
	uint pi;

	for (pi = 0; pi < r_size(&pfpath->list); ++pi) {
	    const ref *prdir = pfpath->list.value.refs + pi;
	    const char *pstr = (const char *)prdir->value.const_bytes;
	    uint plen = r_size(prdir), blen1 = blen;
    	    gs_parsed_file_name_t pname;
	    gp_file_name_combine_result r;

	    /* We need to concatenate and parse the file name here
	     * if this path has a %device% prefix.		*/
	    if (pstr[0] == '%') {
		int code;

		/* We concatenate directly since gp_file_name_combine_*
		 * rules are not correct for other devices such as %rom% */
		gs_parse_file_name(&pname, pstr, plen);
		memcpy(buffer, pname.fname, pname.len);
		memcpy(buffer+pname.len, fname, flen);
		code = pname.iodev->procs.open_file(pname.iodev, buffer, pname.len + flen, fmode,
					      &s, (gs_memory_t *)mem);
		if (code < 0)
		    continue;
		make_stream_file(pfile, s, "r");
		/* fill in the buffer with the device concatenated */
		memcpy(buffer, pstr, plen);
		memcpy(buffer+plen, fname, flen);
		*pclen = plen + flen;
		return 0;
	    } else {
		r = gp_file_name_combine(pstr, plen, 
			fname, flen, false, buffer, &blen1);
		if (r != gp_combine_success)
		    continue;
		if (iodev_os_open_file(iodev, (const char *)buffer, blen1, (const char *)fmode,
					&s, (gs_memory_t *)mem) == 0) {
		    if (starting_arg_file ||
			check_file_permissions_aux(i_ctx_p, buffer, blen1) >= 0) {
			*pclen = blen1;
			make_stream_file(pfile, s, "r");
			return 0;
		    }
		    sclose(s);
		    return_error(e_invalidfileaccess);
		}
	    }
	}
    }
    return_error(e_undefinedfilename);
}
Esempio n. 9
0
/* <prefix|null> <access_string> .tempfile <name_string> <file> */
static int
ztempfile(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    const char *pstr;
    char fmode[4];
    int code = parse_file_access_string(op, fmode);
    char prefix[gp_file_name_sizeof];
    char fname[gp_file_name_sizeof];
    uint fnlen;
    FILE *sfile;
    stream *s;
    byte *buf;

    if (code < 0)
	return code;
    strcat(fmode, gp_fmode_binary_suffix);
    if (r_has_type(op - 1, t_null))
	pstr = gp_scratch_file_name_prefix;
    else {
	uint psize;

	check_read_type(op[-1], t_string);
	psize = r_size(op - 1);
	if (psize >= gp_file_name_sizeof)
	    return_error(e_rangecheck);
	memcpy(prefix, op[-1].value.const_bytes, psize);
	prefix[psize] = 0;
	pstr = prefix;
    }

    if (gp_file_name_is_absolute(pstr, strlen(pstr))) {
	if (check_file_permissions(i_ctx_p, pstr, strlen(pstr),
				   "PermitFileWriting") < 0) {
	    return_error(e_invalidfileaccess);
	}
    } else if (!prefix_is_simple(pstr)) {
	return_error(e_invalidfileaccess);
    }

    s = file_alloc_stream(imemory, "ztempfile(stream)");
    if (s == 0)
	return_error(e_VMerror);
    buf = gs_alloc_bytes(imemory, file_default_buffer_size,
			 "ztempfile(buffer)");
    if (buf == 0)
	return_error(e_VMerror);
    sfile = gp_open_scratch_file(pstr, fname, fmode);
    if (sfile == 0) {
	gs_free_object(imemory, buf, "ztempfile(buffer)");
	return_error(e_invalidfileaccess);
    }
    fnlen = strlen(fname);
    file_init_stream(s, sfile, fmode, buf, file_default_buffer_size);
    code = ssetfilename(s, (const unsigned char*) fname, fnlen);
    if (code < 0) {
	sclose(s);
	iodev_default->procs.delete_file(iodev_default, fname);
	return_error(e_VMerror);
    }
    make_const_string(op - 1, a_readonly | icurrent_space, fnlen,
		      s->file_name.data);
    make_stream_file(op, s, fmode);
    return code;
}
Esempio n. 10
0
/* <name_string> <access_string> file <file> */
int				/* exported for zsysvm.c */
zfile(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    char file_access[4];
    gs_parsed_file_name_t pname;
    int code = parse_file_access_string(op, file_access);
    stream *s;

    if (code < 0)
	return code;
    code = parse_file_name(op - 1, &pname, i_ctx_p->LockFilePermissions);
    if (code < 0)
	return code;
	/*
	 * HACK: temporarily patch the current context pointer into the
	 * state pointer for stdio-related devices.  See ziodev.c for
	 * more information.
	 */
    if (pname.iodev && pname.iodev->dtype == iodev_dtype_stdio) {
	bool statement = (strcmp(pname.iodev->dname, "%statementedit%") == 0);
	bool lineedit = (strcmp(pname.iodev->dname, "%lineedit%") == 0);
	if (pname.fname)
	    return_error(e_invalidfileaccess);
	if (statement || lineedit) {
	    /* These need special code to support callouts */
	    gx_io_device *indev = gs_findiodevice((const byte *)"%stdin", 6);
	    stream *ins;
	    if (strcmp(file_access, "r"))
		return_error(e_invalidfileaccess);
	    indev->state = i_ctx_p;
	    code = (indev->procs.open_device)(indev, file_access, &ins, imemory);
	    indev->state = 0;
	    if (code < 0)
		return code;
	    check_ostack(2);
	    push(2);
	    make_stream_file(op - 3, ins, file_access);
	    make_bool(op-2, statement);
	    make_int(op-1, 0);
	    make_string(op, icurrent_space, 0, NULL);
	    return zfilelineedit(i_ctx_p);
	}
	pname.iodev->state = i_ctx_p;
	code = (*pname.iodev->procs.open_device)(pname.iodev,
						 file_access, &s, imemory);
	pname.iodev->state = NULL;
    } else {
	if (pname.iodev == NULL)
	    pname.iodev = iodev_default;
	code = zopen_file(i_ctx_p, &pname, file_access, &s, imemory);
    }
    if (code < 0)
	return code;
    code = ssetfilename(s, op[-1].value.const_bytes, r_size(op - 1));
    if (code < 0) {
	sclose(s);
	return_error(e_VMerror);
    }
    make_stream_file(op - 1, s, file_access);
    pop(1);
    return code;
}
Esempio n. 11
0
/* This opens %statementedit% or %lineedit% and is also the 
 * continuation proc for callouts.
 * Input:
 *  string is the statement/line buffer, 
 *  int is the write index into string
 *  bool is true if %statementedit%
 *  file is stdin
 * Output:
 *  file is a string based stream
 * We store the line being read in a PostScript string.
 * This limits the size to max_string_size (64k).
 * This could be increased by storing the input line in something 
 * other than a PostScript string.
 */
int
zfilelineedit(i_ctx_t *i_ctx_p)
{
    uint count = 0;
    bool in_eol = false;
    int code;
    os_ptr op = osp;
    bool statement;
    stream *s;
    stream *ins;
    gs_string str;
    uint initial_buf_size;
    const char *filename;
    /*
     * buf exists only for stylistic parallelism: all occurrences of
     * buf-> could just as well be str. .
     */
    gs_string *const buf = &str;

    check_type(*op, t_string);		/* line assembled so far */
    buf->data = op->value.bytes;
    buf->size = op->tas.rsize;
    check_type(*(op-1), t_integer);	/* index */
    count = (op-1)->value.intval;
    check_type(*(op-2), t_boolean);	/* statementedit/lineedit */
    statement = (op-2)->value.boolval;
    check_read_file(ins, op - 3);	/* %stdin */

    /* extend string */
    initial_buf_size = statement ? STATEMENTEDIT_BUF_SIZE : LINEEDIT_BUF_SIZE;
    if (initial_buf_size > max_string_size)
	return_error(e_limitcheck);
    if (!buf->data || (buf->size < initial_buf_size)) {
	count = 0;
	buf->data = gs_alloc_string(imemory_system, initial_buf_size, 
	    "zfilelineedit(buffer)");
	if (buf->data == 0)
	    return_error(e_VMerror);
        op->value.bytes = buf->data;
	op->tas.rsize = buf->size = initial_buf_size;
    }

rd:
    code = zreadline_from(ins, buf, imemory_system, &count, &in_eol);
    if (buf->size > max_string_size) {
	/* zreadline_from reallocated the buffer larger than
	 * is valid for a PostScript string.
	 * Return an error, but first realloc the buffer
	 * back to a legal size.
	 */
	byte *nbuf = gs_resize_string(imemory_system, buf->data, buf->size, 
		max_string_size, "zfilelineedit(shrink buffer)");
	if (nbuf == 0)
	    return_error(e_VMerror);
	op->value.bytes = buf->data = nbuf;
	op->tas.rsize = buf->size = max_string_size;
	return_error(e_limitcheck);
    }

    op->value.bytes = buf->data; /* zreadline_from sometimes resizes the buffer. */
    op->tas.rsize = buf->size;

    switch (code) {
	case EOFC:
	    code = gs_note_error(e_undefinedfilename);
	    /* falls through */
	case 0:
	    break;
	default:
	    code = gs_note_error(e_ioerror);
	    break;
	case CALLC:
	    {
		ref rfile;
		(op-1)->value.intval = count;
		/* callout is for stdin */
		make_file(&rfile, a_readonly | avm_system, ins->read_id, ins);
		code = s_handle_read_exception(i_ctx_p, code, &rfile,  
		    NULL, 0, zfilelineedit);
	    }
	    break;
	case 1:		/* filled buffer */
	    {
		uint nsize = buf->size;
		byte *nbuf;

		if (nsize >= max_string_size) {
		    code = gs_note_error(e_limitcheck);
		    break;
		}
		else if (nsize >= max_string_size / 2)
		    nsize= max_string_size;
		else
		    nsize = buf->size * 2;
		nbuf = gs_resize_string(imemory_system, buf->data, buf->size, nsize,
					"zfilelineedit(grow buffer)");
		if (nbuf == 0) {
		    code = gs_note_error(e_VMerror);
		    break;
		}
		op->value.bytes = buf->data = nbuf;
		op->tas.rsize = buf->size = nsize;
		goto rd;
	    }
    }
    if (code != 0)
	return code;
    if (statement) {
	/* If we don't have a complete token, keep going. */
	stream st;
	stream *ts = &st;
	scanner_state state;
	ref ignore_value;
	uint depth = ref_stack_count(&o_stack);
	int code;

	/* Add a terminating EOL. */
	if (count + 1 > buf->size) {
	    uint nsize;
	    byte *nbuf;

	    nsize = buf->size + 1;
	    if (nsize > max_string_size) {
		return_error(gs_note_error(e_limitcheck));
	    }
	    else {
		nbuf = gs_resize_string(imemory_system, buf->data, buf->size, nsize,
					"zfilelineedit(grow buffer)");
		if (nbuf == 0) {
		    code = gs_note_error(e_VMerror);
		    return_error(code);
		}
		op->value.bytes = buf->data = nbuf;
		op->tas.rsize = buf->size = nsize;
	    }
	}
	buf->data[count++] = char_EOL;
	s_init(ts, NULL);
	sread_string(ts, buf->data, count);
sc:
	scanner_init_stream_options(&state, ts, SCAN_CHECK_ONLY);
	code = scan_token(i_ctx_p, &ignore_value, &state);
	ref_stack_pop_to(&o_stack, depth);
	if (code < 0)
	    code = scan_EOF;	/* stop on scanner error */
	switch (code) {
	    case 0:		/* read a token */
	    case scan_BOS:
		goto sc;	/* keep going until we run out of data */
	    case scan_Refill:
		goto rd;
	    case scan_EOF:
		break;
	    default:		/* error */
		return code;
	}
    }
    buf->data = gs_resize_string(imemory_system, buf->data, buf->size, count,
			   "zfilelineedit(resize buffer)");
    if (buf->data == 0)
	return_error(e_VMerror);
    op->value.bytes = buf->data;
    op->tas.rsize = buf->size;

    s = file_alloc_stream(imemory_system, "zfilelineedit(stream)");
    if (s == 0)
	return_error(e_VMerror);

    sread_string(s, buf->data, count);
    s->save_close = s->procs.close;
    s->procs.close = file_close_disable;

    filename = statement ? gs_iodev_statementedit.dname
	: gs_iodev_lineedit.dname;
    code = ssetfilename(s, (const byte *)filename, strlen(filename)+1);
    if (code < 0) {
	sclose(s);
	return_error(e_VMerror);
    }

    pop(3);
    make_stream_file(osp, s, "r");

    return code;
}