/* compute the cache index file's path */ static char * gp_cache_indexfilename(const char *prefix) { const char *fn = "gs_cache"; char *path; unsigned int len; gp_file_name_combine_result result; len = strlen(prefix) + strlen(fn) + 2; path = malloc(len); result = gp_file_name_combine(prefix, strlen(prefix), fn, strlen(fn), true, path, &len); if (result == gp_combine_small_buffer) { /* handle the case when the combination requires more than one extra character */ free(path); path = malloc(++len); result = gp_file_name_combine(prefix, strlen(prefix), fn, strlen(fn), true, path, &len); } if (result != gp_combine_success) { dlprintf1("pcache: file_name_combine for indexfilename failed with code %d\n", result); free(path); return NULL; } return path; }
/* 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; }
/* get the cache directory's path */ static char *gp_cache_prefix(void) { char *prefix = NULL; int plen = 0; /* get the cache directory path */ if (gp_getenv("GS_CACHE_DIR", (char *)NULL, &plen) < 0) { prefix = malloc(plen); gp_getenv("GS_CACHE_DIR", prefix, &plen); plen--; } else { #ifdef GS_CACHE_DIR prefix = strdup(GS_CACHE_DIR); #else prefix = strdup(".cache"); #endif plen = strlen(prefix); } /* substitute $HOME for '~' */ if (plen >= 1 && prefix[0] == '~') { char *home, *path; int hlen = 0; unsigned int pathlen = 0; gp_file_name_combine_result result; if (gp_getenv("HOME", (char *)NULL, &hlen) < 0) { home = malloc(hlen); if (home == NULL) return prefix; gp_getenv("HOME", home, &hlen); hlen--; if (plen == 1) { /* only "~" */ free(prefix); return home; } /* substitue for the initial '~' */ pathlen = hlen + plen + 1; path = malloc(pathlen); if (path == NULL) { free(home); return prefix; } result = gp_file_name_combine(home, hlen, prefix+2, plen-2, false, path, &pathlen); if (result == gp_combine_success) { free(prefix); prefix = path; } else { dlprintf1("file_name_combine failed with code %d\n", result); } free(home); } } #ifdef DEBUG_CACHE dlprintf1("cache dir read as '%s'\n", prefix); #endif return prefix; }
/* generate an access path for a cache item */ static char *gp_cache_itempath(const char *prefix, gp_cache_entry *item) { const char *fn = item->filename; gp_file_name_combine_result result; char *path; unsigned int len; len = strlen(prefix) + strlen(fn) + 2; path = malloc(len); result = gp_file_name_combine(prefix, strlen(prefix), fn, strlen(fn), false, path, &len); if (result != gp_combine_success) { dlprintf1("pcache: file_name_combine failed on cache item filename with code %d\n", result); } return path; }
/* 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); }
/* * Reduces parent references and current directory references when possible. * The trailing zero byte is being added. * * Examples : * "/gs/lib/../Resource/CMap/H" --> "/gs/Resource/CMap/H" * "C:/gs/lib/../Resource/CMap/H" --> "C:/gs/Resource/CMap/H" * "hard disk:gs:lib::Resource:CMap:H" --> * "hard disk:gs:Resource:CMap:H" * "DUA1:[GHOSTSCRIPT.LIB.-.RESOURCE.CMAP]H" --> * "DUA1:[GHOSTSCRIPT.RESOURCE.CMAP]H" * "\\server\share/a/b///c/../d.e/./../x.e/././/../../y.z/v.v" --> * "\\server\share/a/y.z/v.v" * */ gp_file_name_combine_result gp_file_name_reduce(const char *fname, uint flen, char *buffer, uint *blen) { return gp_file_name_combine(fname, flen, fname + flen, 0, false, buffer, blen); }