/* Only the type of *op has been checked. */ int zcopy_dict(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr op1 = op - 1; int code; check_type(*op1, t_dictionary); check_dict_read(*op1); check_dict_write(*op); if (!imemory->gs_lib_ctx->dict_auto_expand && (dict_length(op) != 0 || dict_maxlength(op) < dict_length(op1)) ) return_error(e_rangecheck); code = idict_copy(op1, op); if (code < 0) return code; /* * In Level 1 systems, we must copy the access attributes too. * The only possible effect this can have is to make the * copy read-only if the original dictionary is read-only. */ if (!level2_enabled) r_copy_attrs(dict_access_ref(op), a_write, dict_access_ref(op1)); ref_assign(op1, op); pop(1); return 0; }
/* * If the new save level is zero, fix up the contents of a stack * by clearing the l_new bit in all the entries (since we can't tolerate * values with l_new set if the save level is zero). * Also, in any case, fix up the e-stack by replacing empty executable * strings and closed executable files that are newer than the save * with canonical ones that aren't. * * Note that this procedure is only called if restore_check_stack succeeded. */ static void restore_fix_stack(ref_stack_t * pstack, const alloc_save_t * asave, bool is_estack) { ref_stack_enum_t rsenum; ref_stack_enum_begin(&rsenum, pstack); do { ref *stkp = rsenum.ptr; uint size = rsenum.size; for (; size; stkp++, size--) { r_clear_attrs(stkp, l_new); /* always do it, no harm */ if (is_estack) { ref ofile; ref_assign(&ofile, stkp); switch (r_type(stkp)) { case t_string: if (r_size(stkp) == 0 && alloc_is_since_save(stkp->value.bytes, asave) ) { make_empty_const_string(stkp, avm_foreign); break; } continue; case t_file: if (alloc_is_since_save(stkp->value.pfile, asave) ) { make_invalid_file(stkp); break; } continue; default: continue; } r_copy_attrs(stkp, a_all | a_executable, &ofile); } } } while (ref_stack_enum_next(&rsenum)); }