/* 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); }
/* 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); }
/* <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; }
/* strings of the permitgroup array. */ static int check_file_permissions_reduced(i_ctx_t *i_ctx_p, const char *fname, int len, const char *permitgroup) { long i; ref *permitlist = NULL; /* an empty string (first character == 0) if '\' character is */ /* recognized as a file name separator as on DOS & Windows */ const char *win_sep2 = "\\"; bool use_windows_pathsep = (gs_file_name_check_separator(win_sep2, 1, win_sep2) == 1); uint plen = gp_file_name_parents(fname, len); /* Assuming a reduced file name. */ if (dict_find_string(&(i_ctx_p->userparams), permitgroup, &permitlist) <= 0) return 0; /* if Permissions not found, just allow access */ for (i=0; i<r_size(permitlist); i++) { ref permitstring; const string_match_params win_filename_params = { '*', '?', '\\', true, true /* ignore case & '/' == '\\' */ }; const byte *permstr; uint permlen; int cwd_len = 0; if (array_get(imemory, permitlist, i, &permitstring) < 0 || r_type(&permitstring) != t_string ) break; /* any problem, just fail */ permstr = permitstring.value.bytes; permlen = r_size(&permitstring); /* * Check if any file name is permitted with "*". */ if (permlen == 1 && permstr[0] == '*') return 0; /* success */ /* * If the filename starts with parent references, * the permission element must start with same number of parent references. */ if (plen != 0 && plen != gp_file_name_parents((const char *)permstr, permlen)) continue; cwd_len = gp_file_name_cwds((const char *)permstr, permlen); /* * If the permission starts with "./", absolute paths * are not permitted. */ if (cwd_len > 0 && gp_file_name_is_absolute(fname, len)) continue; /* * If the permission starts with "./", relative paths * with no "./" are allowed as well as with "./". * 'fname' has no "./" because it is reduced. */ if (string_match( (const unsigned char*) fname, len, permstr + cwd_len, permlen - cwd_len, use_windows_pathsep ? &win_filename_params : NULL)) return 0; /* success */ } /* not found */ return e_invalidfileaccess; }
/* Write the actual file name at fname. */ static FILE * gp_open_scratch_file_generic(const gs_memory_t *mem, const char *prefix, char fname[gp_file_name_sizeof], const char *mode, bool b64) { /* The -8 is for XXXXXX plus a possible final / and -. */ int prefix_length = strlen(prefix); int len = gp_file_name_sizeof - prefix_length - 8; FILE *fp; if (gp_file_name_is_absolute(prefix, prefix_length)) *fname = 0; else if (gp_gettmpdir(fname, &len) != 0) strcpy(fname, "/tmp/"); else { if (strlen(fname) != 0 && fname[strlen(fname) - 1] != '/') strcat(fname, "/"); } if (strlen(fname) + prefix_length + 8 >= gp_file_name_sizeof) return 0; /* file name too long */ strcat(fname, prefix); /* Prevent trailing X's in path from being converted by mktemp. */ if (*fname != 0 && fname[strlen(fname) - 1] == 'X') strcat(fname, "-"); strcat(fname, "XXXXXX"); #ifdef HAVE_MKSTEMP { int file; char ofname[gp_file_name_sizeof]; /* save the old filename template in case mkstemp fails */ memcpy(ofname, fname, gp_file_name_sizeof); #ifdef HAVE_MKSTEMP64 if (b64) file = mkstemp64(fname); else file = mkstemp(fname); #else file = mkstemp(fname); #endif if (file < -1) { emprintf1(mem, "**** Could not open temporary file %s\n", ofname); return NULL; } #if defined(O_LARGEFILE) && defined(__hpux) if (b64) fcntl(file, F_SETFD, fcntl(file, F_GETFD) | O_LARGEFILE); #else /* Fixme : what to do with b64 and 32-bit mkstemp? Unimplemented. */ #endif fp = fdopen(file, mode); if (fp == NULL) close(file); } #else mktemp(fname); fp = (b64 ? gp_fopentemp : gp_fopentemp_64)(fname, mode); #endif if (fp == NULL) emprintf1(mem, "**** Could not open temporary file %s\n", fname); return fp; }
/* Write the actual file name at fname. */ FILE * gp_open_scratch_file(const char *prefix, char *fname, const char *mode) { UINT n; DWORD l; HANDLE hfile = INVALID_HANDLE_VALUE; int fd = -1; FILE *f = NULL; char sTempDir[_MAX_PATH]; char sTempFileName[_MAX_PATH]; memset(fname, 0, gp_file_name_sizeof); if (!gp_file_name_is_absolute(prefix, strlen(prefix))) { int plen = sizeof(sTempDir); if (gp_gettmpdir(sTempDir, &plen) != 0) l = GetTempPath(sizeof(sTempDir), sTempDir); else l = strlen(sTempDir); } else { strncpy(sTempDir, prefix, sizeof(sTempDir)); prefix = ""; l = strlen(sTempDir); } /* Fix the trailing terminator so GetTempFileName doesn't get confused */ if (sTempDir[l-1] == '/') sTempDir[l-1] = '\\'; /* What Windoze prefers */ if (l <= sizeof(sTempDir)) { n = GetTempFileName(sTempDir, prefix, 0, sTempFileName); if (n == 0) { /* If 'prefix' is not a directory, it is a path prefix. */ int l = strlen(sTempDir), i; for (i = l - 1; i > 0; i--) { uint slen = gs_file_name_check_separator(sTempDir + i, l, sTempDir + l); if (slen > 0) { sTempDir[i] = 0; i += slen; break; } } if (i > 0) n = GetTempFileName(sTempDir, sTempDir + i, 0, sTempFileName); } if (n != 0) { hfile = CreateFile(sTempFileName, GENERIC_READ | GENERIC_WRITE | DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL /* | FILE_FLAG_DELETE_ON_CLOSE */, NULL); /* * Can't apply FILE_FLAG_DELETE_ON_CLOSE due to * the logics of clist_fclose. Also note that * gdev_prn_render_pages requires multiple temporary files * to exist simultaneousely, so that keeping all them opened * may exceed available CRTL file handles. */ } } if (hfile != INVALID_HANDLE_VALUE) { /* Associate a C file handle with an OS file handle. */ fd = _open_osfhandle((long)hfile, 0); if (fd == -1) CloseHandle(hfile); else { /* Associate a C file stream with C file handle. */ f = fdopen(fd, mode); if (f == NULL) _close(fd); } } if (f != NULL) { if ((strlen(sTempFileName) < gp_file_name_sizeof)) strncpy(fname, sTempFileName, gp_file_name_sizeof - 1); else { /* The file name is too long. */ fclose(f); f = NULL; } } if (f == NULL) eprintf1("**** Could not open temporary file '%s'\n", fname); return f; }