/* 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; }
/* 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 */ gx_io_device *iodev = iodev_default(mem); gs_main_instance *minst = get_minst_from_memory(mem); int code; /* 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 (minst->search_here_first) { if (search_with_no_combine) { code = lib_file_open_search_with_no_combine(lib_path, mem, i_ctx_p, fname, flen, buffer, blen, pclen, pfile, iodev, starting_arg_file, fmode); if (code <= 0) /* +ve means continue continue */ return code; } if (search_with_combine) { code = lib_file_open_search_with_combine(lib_path, mem, i_ctx_p, fname, flen, buffer, blen, pclen, pfile, iodev, starting_arg_file, fmode); if (code <= 0) /* +ve means continue searching */ return code; } } else { if (search_with_combine) { code = lib_file_open_search_with_combine(lib_path, mem, i_ctx_p, fname, flen, buffer, blen, pclen, pfile, iodev, starting_arg_file, fmode); if (code <= 0) /* +ve means continue searching */ return code; } if (search_with_no_combine) { code = lib_file_open_search_with_no_combine(lib_path, mem, i_ctx_p, fname, flen, buffer, blen, pclen, pfile, iodev, starting_arg_file, fmode); if (code <= 0) /* +ve means continue searching */ return code; } } return_error(e_undefinedfilename); }
/* <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; }
/* <string1> <string2> renamefile - */ static int zrenamefile(i_ctx_t *i_ctx_p) { int code; os_ptr op = osp; gs_parsed_file_name_t pname1, pname2; code = parse_real_file_name(op, &pname2, imemory, "renamefile(to)"); if (code < 0) return code; pname1.fname = 0; code = parse_real_file_name(op - 1, &pname1, imemory, "renamefile(from)"); if (code >= 0) { gx_io_device *iodev_dflt = iodev_default(imemory); if (pname1.iodev != pname2.iodev ) { if (pname1.iodev == iodev_dflt) pname1.iodev = pname2.iodev; if (pname2.iodev == iodev_dflt) pname2.iodev = pname1.iodev; } if (pname1.iodev != pname2.iodev || (pname1.iodev == iodev_dflt && /* * We require FileControl permissions on the source path * unless it is a temporary file. Also, we require FileControl * and FileWriting permissions to the destination file/path. */ ((check_file_permissions(i_ctx_p, pname1.fname, pname1.len, "PermitFileControl") < 0 && !file_is_tempfile(i_ctx_p, op[-1].value.bytes, r_size(op - 1))) || (check_file_permissions(i_ctx_p, pname2.fname, pname2.len, "PermitFileControl") < 0 || check_file_permissions(i_ctx_p, pname2.fname, pname2.len, "PermitFileWriting") < 0 )))) { code = gs_note_error(e_invalidfileaccess); } else { code = (*pname1.iodev->procs.rename_file)(pname1.iodev, pname1.fname, pname2.fname); } } gs_free_file_name(&pname2, "renamefile(to)"); gs_free_file_name(&pname1, "renamefile(from)"); if (code < 0) return code; pop(2); return 0; }
static int zfilenameforall(i_ctx_t *i_ctx_p) { os_ptr op = osp; file_enum *pfen; gx_io_device *iodev = NULL; gs_parsed_file_name_t pname; int code = 0; check_write_type(*op, t_string); check_proc(op[-1]); check_read_type(op[-2], t_string); /* Push a mark, the iodev, devicenamelen, the scratch string, the enumerator, */ /* and the procedure, and invoke the continuation. */ check_estack(7); /* Get the iodevice */ code = parse_file_name(op-2, &pname, i_ctx_p->LockFilePermissions, imemory); if (code < 0) return code; iodev = (pname.iodev == NULL) ? iodev_default(imemory) : pname.iodev; /* Check for several conditions that just cause us to return success */ if (pname.len == 0 || iodev->procs.enumerate_files == iodev_no_enumerate_files) { pop(3); return 0; /* no pattern, or device not found -- just return */ } pfen = iodev->procs.enumerate_files(iodev, (const char *)pname.fname, pname.len, imemory); if (pfen == 0) return_error(e_VMerror); push_mark_estack(es_for, file_cleanup); ++esp; make_istruct(esp, 0, iodev); ++esp; make_int(esp, r_size(op-2) - pname.len); *++esp = *op; ++esp; make_istruct(esp, 0, pfen); *++esp = op[-1]; pop(3); code = file_continue(i_ctx_p); return (code == o_pop_estack ? o_push_estack : code); }
/* Convert a file name to a C string by adding a null terminator. */ int gs_terminate_file_name(gs_parsed_file_name_t * pfn, gs_memory_t *mem, client_name_t cname) { uint len = pfn->len; char *fname; if (pfn->iodev == NULL) /* no device */ pfn->iodev = iodev_default(mem); if (pfn->memory) return 0; /* already copied */ /* Copy the file name to a C string. */ fname = (char *)gs_alloc_string(mem, len + 1, cname); if (fname == 0) return_error(gs_error_VMerror); memcpy(fname, pfn->fname, len); fname[len] = 0; pfn->memory = mem; pfn->fname = fname; pfn->len = len + 1; /* null terminator */ return 0; }
/* <string> deletefile - */ static int zdeletefile(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_parsed_file_name_t pname; int code = parse_real_file_name(op, &pname, imemory, "deletefile"); if (code < 0) return code; if (pname.iodev == iodev_default(imemory)) { if ((code = check_file_permissions(i_ctx_p, pname.fname, pname.len, "PermitFileControl")) < 0 && !file_is_tempfile(i_ctx_p, op->value.bytes, r_size(op))) { return code; } } code = (*pname.iodev->procs.delete_file)(pname.iodev, pname.fname); gs_free_file_name(&pname, "deletefile"); if (code < 0) return code; pop(1); return 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, *sbody; 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(imemory, pstr, fname, fmode); if (sfile == 0) { gs_free_object(imemory, buf, "ztempfile(buffer)"); return_error(e_invalidfileaccess); } fnlen = strlen(fname); sbody = ialloc_string(fnlen, ".tempfile(fname)"); if (sbody == 0) { gs_free_object(imemory, buf, "ztempfile(buffer)"); return_error(e_VMerror); } memcpy(sbody, fname, fnlen); file_init_stream(s, sfile, fmode, buf, file_default_buffer_size); code = ssetfilename(s, (const unsigned char*) fname, fnlen); if (code < 0) { gx_io_device *iodev_dflt = iodev_default(imemory); sclose(s); iodev_dflt->procs.delete_file(iodev_dflt, fname); ifree_string(sbody, fnlen, ".tempfile(fname)"); return_error(e_VMerror); } make_string(op - 1, a_readonly | icurrent_space, fnlen, sbody); make_stream_file(op, s, fmode); return code; }
/* <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, imemory); 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(imemory, (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(imemory); 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; }