/* 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; }
/* 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; }
/* Parse a real (non-device) file name and convert to a C string. */ int gs_parse_real_file_name(gs_parsed_file_name_t * pfn, const char *pname, uint len, gs_memory_t *mem, client_name_t cname) { int code = gs_parse_file_name(pfn, pname, len); if (code < 0) return code; if (pfn->len == 0) return_error(gs_error_invalidfileaccess); /* device only */ return gs_terminate_file_name(pfn, mem, cname); }
/* Parse a real (non-device) file name and convert to a C string. */ int gs_parse_real_file_name(gs_parsed_file_name_t * pfn, const char *pname, uint len, gs_memory_t *mem, client_name_t cname) { int code = gs_parse_file_name(pfn, pname, len, mem); if (code < 0) return code; if (pfn->len == 0) /* device only */ return_error(gs_error_undefinedfilename); /* for CET 23-23.ps */ return gs_terminate_file_name(pfn, mem, cname); }
/* * Open a stream using a filename that can include a PS style IODevice prefix * If iodev_default is the '%os' device, then the file will be on the host * file system transparently to the caller. The "%os%" prefix can be used * to explicilty access the host file system. */ stream * sfopen(const char *path, const char *mode, gs_memory_t *memory) { gs_parsed_file_name_t pfn; stream *s; iodev_proc_open_file((*open_file)); gs_memory_t *mem = (memory == NULL) ? gs_lib_ctx_get_non_gc_memory_t() : memory; int code = gs_parse_file_name(&pfn, path, strlen(path)); if (code < 0) { # define EMSG "sfopen: gs_parse_file_name failed.\n" errwrite(EMSG, strlen(EMSG)); # undef EMSG return NULL; } if (pfn.fname == NULL) { /* just a device */ # define EMSG "sfopen: not allowed with %device only.\n" errwrite(EMSG, strlen(EMSG)); # undef EMSG return NULL; } if (pfn.iodev == NULL) pfn.iodev = iodev_default; open_file = pfn.iodev->procs.open_file; if (open_file == 0) code = file_open_stream(pfn.fname, pfn.len, mode, 2048, &s, pfn.iodev, pfn.iodev->procs.fopen, mem); else code = open_file(pfn.iodev, pfn.fname, pfn.len, mode, &s, mem); if (code < 0) return NULL; s->position = 0; code = ssetfilename(s, (const byte *)path, strlen(path)); if (code < 0) { /* Only error is e_VMerror */ sclose(s); gs_free_object(s->memory, s, "sfopen: allocation error"); # define EMSG "sfopen: allocation error setting path name into stream.\n" errwrite(EMSG, strlen(EMSG)); # undef EMSG return NULL; } return s; }
/* See gsfname.c for details. */ static int parse_file_name(const ref * op, gs_parsed_file_name_t * pfn, bool safemode) { int code; check_read_type(*op, t_string); code = gs_parse_file_name(pfn, (const char *)op->value.const_bytes, r_size(op)); if (code < 0) return code; /* * Check here for the %pipe device which is illegal when * LockFilePermissions is true. In the future we might want to allow * the %pipe device to be included on the PermitFile... paths, but * for now it is simply disallowed. */ if (pfn->iodev && safemode && strcmp(pfn->iodev->dname, "%pipe%") == 0) return e_invalidfileaccess; return code; }
/* 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); }