/*{ ** Name: psy_dpermit - Define a permit. ** ** INTERNAL PSF call format: status = psy_dpermit(&psy_cb, sess_cb); ** ** EXTERNAL call format: status = psy_call(PSY_DPERMIT, &psy_cb, sess_cb); ** ** Description: ** Given all of the parameters necessary to CREATE/DEFINE a permit on a ** table or view, this function will store the permission in the system ** catalogs. This will include storing the query tree in the tree table, ** storing the text of the query in the iiqrytext table (really done by ** QEF), storing a row in the protect table, and issuing an "alter table" ** operation to DMF to indicate that there are permissions on the given ** table. ** ** Inputs: ** psy_cb ** .psy_qrytext Id of query text as stored in QSF. ** .psy_cols[] Array of columns on which to grant ** permission ** .psy_numcols Number of columns listed above; 0 means ** give permission on all columns ** .psy_intree QSF id of query tree representing the ** where clause in the permit ** .psy_opctl Bit map of defined operations ** .psy_opmap Bit map of permitted operations ** .psy_user Name of user who will get permission ** .psy_terminal Terminal at which permission is given ** (blank if none specified) ** .psy_timbgn Time of day at which the permission ** begins (minutes since 00:00) ** .psy_timend Time of day at which the permission ends ** (minutes since 00:00) ** .psy_daybgn Day of week at which the permission ** begins (0 = Sunday) ** .psy_dayend Day of week at which the permission ends ** (0 = Sunday) ** .psy_grant ** PSY_CPERM CREATE/DEFINE PERMIT ** .psy_tblq head of table queue ** .psy_colq head of column queue ** .psy_usrq head of user queue ** .psy_qlen length of first iiqrytext ** .psy_flags useful info ** PSY_EXCLUDE_COLUMNS user specified a list of columns to ** which privilege should not apply ** sess_cb Pointer to session control block ** (Can be NULL) ** ** Outputs: ** psy_cb ** .psy_txtid Id of query text as stored in the ** iiqrytext system relation. ** .psy_error Filled in if error happens ** Returns: ** E_DB_OK Function completed normally. ** E_DB_WARN Function completed with warning(s); ** E_DB_ERROR Function failed; non-catastrophic error ** E_DB_FATAL Function failed; catastrophic error ** Exceptions: ** none ** ** Side Effects: ** Stores text of query in iiqrytext relation, query tree in tree ** relation, row in protect relation identifying the permit. Does ** an alter table DMF operation to indicate that there are permissions ** on the table. ** ** History: ** 02-oct-85 (jeff) ** written ** 03-sep-86 (seputis) ** changed some psy_cb. to psy_cb-> ** added .db_att_id reference ** changed rdr_cb. rdr_cb-> ** 02-dec-86 (daved) ** bug fixing. check for permit on tables owned by user and not ** view. ** 29-apr-87 (stec) ** Implemented changes for GRANT statement. ** 10-may-88 (stec) ** Make changes for db procs. ** 03-oct-88 (andre) ** Modified call to pst_rgent to pass 0 as a query mode since it is ** clearly not PSQ_DESTROY ** 06-feb-89 (ralph) ** Added support for 300 attributes: ** Use DB_COL_BITS in place of DB_MAX_COLS ** Loop over domset array using DB_COL_WORDS ** 06-mar-89 (ralph) ** GRANT Enhancements, Phase 1: ** Initialize new DB_PROTECTION fields, dbp_seq and dbp_gtype ** 03-apr-89 (ralph) ** GRANT Enhancements, Phase 2: ** Use DBGR_USER when initializing dbp_gtype ** 08-may-89 (ralph) ** Initialize reserved field to blanks (was \0) ** 04-jun-89 (ralph) ** Initialize dbp_fill1 to zero ** Fix unix portability problems ** 02-nov-89 (neil) ** Alerters: Allowed privileges for events. ** 1-mar-90 (andre) ** If processing a GRANT on tables, check if ** ALL-TO-ALL or RETRIEVE-TO-ALL has already been granted, and if so, ** mark psy_mask appropriately. ** If user tried to CREATE ALL/RETRIEVE-TO-ALL, and one already exists, ** skip to the exit. ** 12-mar-90 (andre) ** set rdr_2types_mask to 0. ** 22-may-90 (teg) ** init rdr_instr to RDF_NO_INSTR ** 08-aug-90 (ralph) ** Initialize new fields in iiprotect tuple ** 14-dec-90 (ralph) ** Disallow use of GRANT by non-DBA if xORANGE ** 11-jan-90 (ralph) ** Allow user "$ingres" to use GRANT if xORANGE. ** This was done for CREATEDB (UPGRADEFE). ** 20-feb-91 (andre) ** For CREATE/DEFINE PERMIT, grantee type was stored in ** psy_cb->psy_gtype. ** 24-jun-91 (andre) ** IIPROTECT tuples for table permits will contain exactly one ** privilege. IIQRYTEXT template built for table-wide privileges ** contains a placeholder for a privilege name which will be filled in ** with each of the table-wide privileges being granted, one at a time. ** PSY_CB.psy_opmap will be set to correspond with privilege name ** stored in the IIQRYTEXT permit. ** 16-jul-91 (andre) ** responsibility for splitting permit tuples will passed on to ** qeu_cprot(). If a permit specified only one privilege, we will ** substitute the appropriate privilege name here and will not ask ** qeu_cprot() to split tuples. ** 06-aug-91 (andre) ** before proceeding to CREATE a permit on a view owned by the current ** user, we will call psy_tbl_grant_check() to ensure that this user ** may create a permit on his view. If the object is not owned by the ** current user, we will not try to verify that the user may ** CREATE/DEFINE a permit since (until the relevant FE changes are ** made) we intend to continue allowing any user with CATUPD to ** CREATE/DEFINE permits on catalogs and the dba will be allowed to ** CREATE/DEFINE permits on extended catalogs ** 11-nov-91 (rblumer) ** merged from 6.4: 26-feb-91 (andre) ** PST_QTREE was changed to store the range table as an array of ** pointers to PST_RNGENTRY structure. ** 14-feb-92 (andre) ** we will no longer have to fill in privilege name for permits ** specifying one privilege - it will be handled in respective ** grammars. ** 15-jun-92 (barbara) ** For Sybil, change interface to pst_rgent(), Star returns from ** psy_dpermit before permits get stored. ** 07-jul-92 (andre) ** DB_PROTECTION tuple will contain an indicator of how the permit was ** created, i.e. whether it was created using SQL or QUEL and if the ** former, then whether it was created using GRANT statement. Having ** this information will facilitate merging similar and identical ** permit tuples. ** 14-jul-92 (andre) ** semantics of GRANT ALL [PRIVILEGES] is different from that of ** CREATE PERMIT ALL in that the former (as dictated by SQL92) means ** "grant all privileges which the current auth id posesses WGO" ** whereas the latter (as is presently interpreted) means "grant all ** privileges that can be defined on the object" which in case of ** tables and views means SELECT, INSERT, DELETE, UPDATE. ** psy_tbl_grant_check() (function responsible for determining whether ** a user may grant specified privilege on a specified table or view) ** will have to be notified whether we are processing GRANT ALL. Its ** behaviour will change as follows: ** - if processing GRANT ALL and psy_tbl_grant_check() determines ** that the user does not possess some (but not all) of the ** privileges passed to it by the caller it will not treat it as an ** error, but will instead inform the caller of privileges that the ** user does not posess, ** - if processing GRANT ALL and psy_tbl_grant_check() determines ** that the user does not possess any of the privileges passed to ** it by the caller it will treat it as an error ** - if processing a statement other than GRANT ALL and ** psy_tbl_grant_check() determines that the user does not possess ** some of the privileges passed to it by the caller it will treat ** it as an error ** 16-jul-92 (andre) ** if a permit being created depends on some privileges, build a ** structure describing these privileges and store its address in ** rdf_cb->rdr_indep. ** 18-jul-92 (andre) ** we will no longer be telling QEF to turn off DMT_ALL_PROT or ** DMT_RETRIEVE_PRO when a user creates ALL/RETRIEVE TO ALL permit. ** QEF will figure out on its own whether PUBLIC now has RETRIEVE or ** ALL on a table/view ** 20-jul-92 (andre) ** if user specified a list of columns to which privilege(s) should ** not apply, set dbp_domset correctly ** 03-aug-92 (barbara) ** Invalidate base table infoblk from RDF cache for CREATE PERMIT ** and CREATE SEC_ALARM. ** 16-sep-92 (andre) ** privilege maps are build using bitwise ops, so care should be ** exercised when accessing it using BT*() functions ** 17-jun-93 (andre) ** changed interface of psy_secaudit() to accept PSS_SESBLK ** 5-jul-93 (robf) ** changed interface of psy_secaudit() to accept security label ** 7-jan-94 (swm) ** Bug #58635 ** Added PTR cast for qsf_owner which has changed type to PTR. ** 06-mar-96 (nanpr01) ** Move the QSF request block initialization up. because if ** pst_rgnent returns a failure status code, subsequent QSF ** calls get bad control block error. */ DB_STATUS psy_dpermit( PSY_CB *psy_cb, PSS_SESBLK *sess_cb) { RDF_CB rdf_cb; register RDR_RB *rdf_rb = &rdf_cb.rdf_rb; QSF_RCB qsf_rb; DB_STATUS status; DB_STATUS stat; DB_PROTECTION ptuple; register DB_PROTECTION *protup = &ptuple; i4 *domset = ptuple.dbp_domset; register i4 i, j; i4 err_code; PSS_RNGTAB *rngvar; PSS_USRRANGE *rngtab; PST_PROCEDURE *pnode; PST_QTREE *qtree; DB_ERROR *err_blk = &psy_cb->psy_error; i4 textlen; i4 tree_lock = 0; i4 text_lock = 0; DB_TAB_ID tabids[PST_NUMVARS]; PSQ_INDEP_OBJECTS indep_objs; PSQ_OBJPRIV obj_priv; /* space for independent DELETE */ PSQ_COLPRIV col_privs[2]; /* ** space for independent INSERT and ** UPDATE */ PST_VRMAP varmap; PSY_TBL *psy_tbl; DB_TIME_ID timeid; DB_NAME *objname; /* ** For CREATE/DEFINE PERMIT execute code below. */ /* initialize the QSF control block */ qsf_rb.qsf_type = QSFRB_CB; qsf_rb.qsf_ascii_id = QSFRB_ASCII_ID; qsf_rb.qsf_length = sizeof(qsf_rb); qsf_rb.qsf_owner = (PTR)DB_PSF_ID; qsf_rb.qsf_sid = sess_cb->pss_sessid; rngtab = &sess_cb->pss_auxrng; /* table info is stored in the only entry in the table queue */ psy_tbl = (PSY_TBL *) psy_cb->psy_tblq.q_next; status = pst_rgent(sess_cb, rngtab, -1, "", PST_SHWID, (DB_TAB_NAME *) NULL, (DB_TAB_OWN *) NULL, &psy_tbl->psy_tabid, TRUE, &rngvar, (i4) 0, err_blk); if (DB_FAILURE_MACRO(status)) goto exit; /* In STAR, we do not actually store permits */ if (sess_cb->pss_distrib & DB_3_DDB_SESS) { qsf_rb.qsf_lk_state = QSO_EXLOCK; goto exit; } /* Fill in the RDF request block */ pst_rdfcb_init(&rdf_cb, sess_cb); /* The table which is receiving the permit */ STRUCT_ASSIGN_MACRO(psy_tbl->psy_tabid, rdf_rb->rdr_tabid); /* Tell RDF we're doing a permit definition */ rdf_rb->rdr_update_op = RDR_APPEND; rdf_rb->rdr_types_mask = RDR_PROTECT; rdf_rb->rdr_qrytuple = (PTR) protup; /* initialize independent object structure */ indep_objs.psq_objs = (PSQ_OBJ *) NULL; indep_objs.psq_objprivs = (PSQ_OBJPRIV *) NULL; indep_objs.psq_colprivs = (PSQ_COLPRIV *) NULL; indep_objs.psq_grantee = &sess_cb->pss_user; rdf_rb->rdr_indep = (PTR) &indep_objs; /* ** populate the IIPROTECT tuple */ /* Zero out the template */ (VOID)MEfill(sizeof(ptuple), (u_char) 0, (PTR) protup); /* store grantee type */ protup->dbp_gtype = psy_cb->psy_gtype; /* Init reserved block */ (VOID)MEfill(sizeof(protup->dbp_reserve), (u_char) ' ', (PTR) protup->dbp_reserve); /* Init obj name */ STRUCT_ASSIGN_MACRO(psy_tbl->psy_tabnm, protup->dbp_obname); /*@FIX_ME@ Where does this come from? */ protup->dbp_obstat = ' '; /* store the object type indicator */ if (psy_tbl->psy_mask & PSY_OBJ_IS_TABLE) { protup->dbp_obtype = DBOB_TABLE; } else if (psy_tbl->psy_mask & PSY_OBJ_IS_VIEW) { protup->dbp_obtype = DBOB_VIEW; } else { protup->dbp_obtype = DBOB_INDEX; } STRUCT_ASSIGN_MACRO(psy_tbl->psy_owner, protup->dbp_obown); STRUCT_ASSIGN_MACRO(sess_cb->pss_user, protup->dbp_grantor); TMnow((SYSTIME *)&timeid); protup->dbp_timestamp.db_tim_high_time = timeid.db_tim_high_time; protup->dbp_timestamp.db_tim_low_time = timeid.db_tim_low_time; /* The table on which we're giving permission */ STRUCT_ASSIGN_MACRO(psy_tbl->psy_tabid, protup->dbp_tabid); /* Beginning and ending times of day */ protup->dbp_pdbgn = psy_cb->psy_timbgn; protup->dbp_pdend = psy_cb->psy_timend; /* Beginning and ending days of week */ protup->dbp_pwbgn = psy_cb->psy_daybgn; protup->dbp_pwend = psy_cb->psy_dayend; if (psy_cb->psy_numcols != 0 && ~psy_cb->psy_flags & PSY_EXCLUDE_COLUMNS) { /* user specified a list of columns to which privilege(s) will apply */ /* Bit map of permitted columns */ psy_fill_attmap(domset, ((i4) 0)); for (i = 0; i < psy_cb->psy_numcols; i++) { BTset((i4)psy_cb->psy_cols[i].db_att_id, (char *) domset); } } else { /* ** user specified table-wide privilege(s) or a list of columns L s.t. ** privilege(s) will apply to the entire table except for columns in L */ psy_fill_attmap(domset, ~((i4) 0)); if (psy_cb->psy_flags & PSY_EXCLUDE_COLUMNS) { /* ** exclude specified columns from the list of columns to which ** privilege(s) will apply */ for (i = 0; i < psy_cb->psy_numcols; i++) { BTclear((i4) psy_cb->psy_cols[i].db_att_id, (char *) domset); } } } if (rngvar->pss_tabdesc->tbl_status_mask & DMT_VIEW) { /* ** if view is owned by the current user, psy_tbl_grant_check() will ** determine if the permit can, indeed, be created; as long as we are ** preserving the kludge that allows users with CATUPD create permits on ** catalogs and DBAs to create permits on extended catalogs, we shall ** not call psy_tbl_grant_check() on view not owned by the current user, ** since it is likely to result in psy_tbl_grant_check() complaining ** about inadequate permissions */ if (!MEcmp((PTR) &rngvar->pss_ownname, (PTR) &sess_cb->pss_user, sizeof(sess_cb->pss_user))) { i4 tbl_wide_privs; PSY_COL_PRIVS col_specific_privs, *csp, indep_col_specific_privs; DB_TAB_ID indep_id; i4 indep_tbl_wide_privs; bool insuf_privs, quel_view; i4 val1, val2; /* ** build maps of table-wide and column-specific privileges for ** psy_tbl_grant_check() ** if a column list was specified with CREATE PERMIT and ** privileges specified in the statement include a set of ** privileges S s.t. for all P in S, P can only be specified as ** table-wide with GRANT statement (currently this includes ** SELECT, INSERT, DELETE), we will make ** psy_tbl_grant_check() think that privileges in S are ** table-wide. ** This will work correctly since if the view was defined over ** some objects owned by other user(s), for every P in S we ** would need table-wide privilege WGO on the underlying object. ** ** For the purposes of providing more descriptive output for ** trace point ps131, if column-list was specified, we will pass ** the map of attributes even if column-specific UPDATE was not ** specified */ if (psy_cb->psy_numcols != 0 && (psy_cb->psy_opmap & DB_REPLACE || ult_check_macro(&sess_cb->pss_trace, 3, &val1, &val2) ) ) { i4 *ip; csp = &col_specific_privs; /* ** column-specific UPDATE privilege will not be translated into ** a table-wide privilege since GRANT allows for specification ** of column-specific UPDATE privilege */ csp->psy_col_privs = psy_cb->psy_opmap & DB_REPLACE; tbl_wide_privs = psy_cb->psy_opmap & ~DB_REPLACE; /* ** if creating a permit on a set of columns and UPDATE is not ** one of the privileges named in the statement, store the ** attribute map in the first element of the attribute map list */ ip = (csp->psy_col_privs) ? csp->psy_attmap[PSY_UPDATE_ATTRMAP].map : csp->psy_attmap->map; /* copy the attribute map */ for (i = 0; i < DB_COL_WORDS; i++, ip++) { *ip = domset[i]; } } else { tbl_wide_privs = psy_cb->psy_opmap; csp = (PSY_COL_PRIVS *) NULL; } status = psy_tbl_grant_check(sess_cb, (i4) PSQ_PROT, &rngvar->pss_tabid, &tbl_wide_privs, csp, &indep_id, &indep_tbl_wide_privs, &indep_col_specific_privs, psy_cb->psy_flags, &insuf_privs, &quel_view, &psy_cb->psy_error); if (DB_FAILURE_MACRO(status)) { goto exit; } if (insuf_privs) { /* must audit failure to create a permit */ if ( Psf_srvblk->psf_capabilities & PSF_C_C2SECURE ) { DB_ERROR e_error; /* Must audit CREATE PERMIT failure. */ status = psy_secaudit(FALSE, sess_cb, (char *)&rngvar->pss_tabdesc->tbl_name, &rngvar->pss_tabdesc->tbl_owner, sizeof(DB_TAB_NAME), SXF_E_TABLE, I_SX2016_PROT_TAB_CREATE, SXF_A_FAIL | SXF_A_CREATE, &e_error); status = (status > E_DB_ERROR) ? status : E_DB_ERROR; } goto exit; } else if (quel_view) { goto exit; } /* ** If user is trying to grant one or more of ** INSERT/DELETE/UPDATE on his/her view whose underlying table ** or view is owned by another user, psy_tbl_grant_check() will ** return id of the underlying object along with map of ** privileges. We will convert maps of independent privileges ** into elements of independent privilege list and pass them ** along to QEF */ if ( indep_id.db_tab_base != (i4) 0 && ( indep_id.db_tab_base != rngvar->pss_tabid.db_tab_base || indep_id.db_tab_index != rngvar->pss_tabid.db_tab_index ) ) { if (indep_tbl_wide_privs & DB_DELETE) { /* ** the only expected independent table-wide privilege ** is DELETE */ obj_priv.psq_next = (PSQ_OBJPRIV *) NULL; obj_priv.psq_objtype = PSQ_OBJTYPE_IS_TABLE; obj_priv.psq_privmap = (i4) DB_DELETE; obj_priv.psq_objid.db_tab_base = indep_id.db_tab_base; obj_priv.psq_objid.db_tab_index = indep_id.db_tab_index; indep_objs.psq_objprivs = &obj_priv; } if (indep_col_specific_privs.psy_col_privs) { i4 i, j; PSQ_COLPRIV *csp; i4 *att_map, *p; i4 priv_map = 0; /* ** privilege map is built using bitwise operators, but ** here using BTnext() makes code much more palatable, ** so convert a privilege map */ if (indep_col_specific_privs.psy_col_privs & DB_APPEND) BTset(DB_APPP, (char *) &priv_map); if (indep_col_specific_privs.psy_col_privs & DB_REPLACE) BTset(DB_REPP, (char *) &priv_map); for (i = -1, csp = col_privs; (i = BTnext(i, (char *) &priv_map, BITS_IN(priv_map))) != -1; csp++ ) { csp->psq_next = indep_objs.psq_colprivs; indep_objs.psq_colprivs = csp; csp->psq_objtype = PSQ_OBJTYPE_IS_TABLE; csp->psq_tabid.db_tab_base = indep_id.db_tab_base; csp->psq_tabid.db_tab_index = indep_id.db_tab_index; switch (i) { case DB_APPP: /* INSERT privilege */ { csp->psq_privmap = (i4) DB_APPEND; att_map = indep_col_specific_privs. psy_attmap[PSY_INSERT_ATTRMAP].map; break; } case DB_REPP: { csp->psq_privmap = (i4) DB_REPLACE; att_map = indep_col_specific_privs. psy_attmap[PSY_UPDATE_ATTRMAP].map; break; } } for (p = csp->psq_attrmap, j = 0; j < DB_COL_WORDS; j++) { *p++ = *att_map++; } } } } } else { /* ** either this is a catalog and the user has CATUPD or ** this is an extended catalog and the user is the DBA; ** since we may be allowing a user to create a permit by ** circumventing the permit system, we only need to ascertain that ** this is an SQL view */ i4 issql = 0; status = psy_sqlview(rngvar, sess_cb, err_blk, &issql); if (status) { goto exit; } if (!issql) { /* can only have permits on SQL views */ psf_error(3598L, 0L, PSF_USERERR, &err_code, err_blk, 1, psf_trmwhite(sizeof(rngvar->pss_tabname), (char *) &rngvar->pss_tabname), &rngvar->pss_tabname); status = E_DB_ERROR; goto exit; } } } /* Name of user getting permission */ STRUCT_ASSIGN_MACRO(psy_cb->psy_user, protup->dbp_owner); /* Terminal at which permission given */ STRUCT_ASSIGN_MACRO(psy_cb->psy_terminal, protup->dbp_term); /* Give RDF pointer to query tree, if any */ if (!psy_cb->psy_istree) { rdf_rb->rdr_qry_root_node = (PTR) NULL; } else { PST_VRMAP varset; i4 j; STRUCT_ASSIGN_MACRO(psy_cb->psy_intree, qsf_rb.qsf_obj_id); qsf_rb.qsf_lk_state = QSO_EXLOCK; status = qsf_call(QSO_LOCK, &qsf_rb); if (DB_FAILURE_MACRO(status)) { (VOID) psf_error(E_PS0D19_QSF_INFO, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, err_blk, 0); goto exit; } tree_lock = qsf_rb.qsf_lk_id; pnode = (PST_PROCEDURE *) qsf_rb.qsf_root; qtree = (PST_QTREE *) pnode->pst_stmts->pst_specific.pst_tree; rdf_rb->rdr_qry_root_node = (PTR) pnode; /* check for no views in the qualification. */ (VOID)psy_varset(qtree->pst_qtree, &varset); j = BTnext(-1, (char *) &varset, BITS_IN(varset)); for ( ; j >= 0; j = BTnext(j, (char *) &varset, BITS_IN(varset))) { status = pst_rgent(sess_cb, rngtab, -1, "", PST_SHWID, (DB_TAB_NAME *) NULL, (DB_TAB_OWN *) NULL, &qtree->pst_rangetab[j]->pst_rngvar, TRUE, &rngvar, (i4) 0, err_blk); if (status) goto exit; if (rngvar->pss_tabdesc->tbl_status_mask & DMT_VIEW) { psf_error(3597L, 0L, PSF_USERERR, &err_code, err_blk, 1, psf_trmwhite(sizeof(rngvar->pss_tabname), (char *) &rngvar->pss_tabname), &rngvar->pss_tabname); status = E_DB_ERROR; goto exit; } } } /* Give RDF a pointer to the query text to be stored in iiqrytext */ STRUCT_ASSIGN_MACRO(psy_cb->psy_qrytext, qsf_rb.qsf_obj_id); qsf_rb.qsf_lk_state = QSO_EXLOCK; status = qsf_call(QSO_LOCK, &qsf_rb); if (DB_FAILURE_MACRO(status)) { (VOID) psf_error(E_PS0D19_QSF_INFO, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, err_blk, 0); goto exit; } text_lock = qsf_rb.qsf_lk_id; MEcopy((char *) qsf_rb.qsf_root, sizeof(i4), (char *) &textlen); rdf_rb->rdr_l_querytext = textlen; rdf_rb->rdr_querytext = ((char *) qsf_rb.qsf_root) + sizeof(i4); rdf_rb->rdr_status = (sess_cb->pss_lang == DB_SQL) ? DB_SQL : 0; /* determine if the permit specifies exactly one privilege */ if (BTcount((char *) &psy_cb->psy_opmap, BITS_IN(psy_cb->psy_opmap)) > 1) { /* ** if permit specified more than one privilege, notify QEF that it will ** have to split the permit into multiple IIPROTECT tuples */ rdf_rb->rdr_instr |= RDF_SPLIT_PERM; } else if (psy_cb->psy_opmap & DB_RETRIEVE) { /* ** if qeu_cprot() will not be splitting the permit into multiple tuples ** and RETRIEVE is the privilege mentioned in it, set the two bits ** associated with DB_RETRIEVE */ psy_cb->psy_opmap |= DB_TEST | DB_AGGREGATE; psy_cb->psy_opctl |= DB_TEST | DB_AGGREGATE; } /* Null out the DMU control block pointer, just in case */ rdf_rb->rdr_dmu_cb = (PTR) NULL; /* produce list of dependent tables */ rdf_rb->rdr_cnt_base_id = 0; if (psy_cb->psy_istree && qtree->pst_qtree) { j = 0; (VOID)psy_varset(qtree->pst_qtree, &varmap); for (i = -1; (i = BTnext(i, (char*) &varmap, PST_NUMVARS)) > -1;) { /* if this is the table that is getting the permit, ignore */ if (qtree->pst_rangetab[i]->pst_rngvar.db_tab_base != psy_tbl->psy_tabid.db_tab_base || qtree->pst_rangetab[i]->pst_rngvar.db_tab_index != psy_tbl->psy_tabid.db_tab_index ) { rdf_rb->rdr_cnt_base_id++; STRUCT_ASSIGN_MACRO(qtree->pst_rangetab[i]->pst_rngvar, tabids[j++]); } } rdf_rb->rdr_base_id = tabids; } protup->dbp_popctl = psy_cb->psy_opctl; protup->dbp_popset = psy_cb->psy_opmap; /* ** store an indication of whether this permit is being created using SQL or ** QUEL */ protup->dbp_flags = (sess_cb->pss_lang == DB_SQL) ? DBP_SQL_PERM : (i2) 0; protup->dbp_flags |= DBP_65_PLUS_PERM; /* Now let RDF do all the work of the permit definition */ status = rdf_call(RDF_UPDATE, (PTR) &rdf_cb); if (DB_FAILURE_MACRO(status)) { if (rdf_cb.rdf_error.err_code == E_RD0002_UNKNOWN_TBL) { (VOID) psf_error(E_PS0903_TAB_NOTFOUND, 0L, PSF_USERERR, &err_code, err_blk, 1, psf_trmwhite(sizeof(psy_tbl->psy_tabnm), (char *) &psy_tbl->psy_tabnm), &psy_tbl->psy_tabnm); } else { (VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error, &psy_cb->psy_error); } goto exit; } /* ** Invalidate base object's infoblk from RDF cache. */ pst_rdfcb_init(&rdf_cb, sess_cb); STRUCT_ASSIGN_MACRO(psy_cb->psy_tables[0], rdf_rb->rdr_tabid); status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_cb); if (DB_FAILURE_MACRO(status)) { (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_cb.rdf_error, &psy_cb->psy_error); } exit: qsf_rb.qsf_lk_state = QSO_EXLOCK; if (psy_cb->psy_istree) { /* Destroy query tree */ STRUCT_ASSIGN_MACRO(psy_cb->psy_intree, qsf_rb.qsf_obj_id); if ((qsf_rb.qsf_lk_id = tree_lock) == 0) { stat = qsf_call(QSO_LOCK, &qsf_rb); if (DB_FAILURE_MACRO(stat)) { (VOID) psf_error(E_PS0D18_QSF_LOCK, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psy_cb->psy_error, 0); if (!status || stat == E_DB_FATAL) status = stat; } tree_lock = qsf_rb.qsf_lk_id; } stat = qsf_call(QSO_DESTROY, &qsf_rb); if (DB_FAILURE_MACRO(stat)) { (VOID) psf_error(E_PS0D1A_QSF_DESTROY, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psy_cb->psy_error, 0); if (!status || stat == E_DB_FATAL) status = stat; } tree_lock = 0; } /* Destroy query text */ STRUCT_ASSIGN_MACRO(psy_cb->psy_qrytext, qsf_rb.qsf_obj_id); if ((qsf_rb.qsf_lk_id = text_lock) == 0) { stat = qsf_call(QSO_LOCK, &qsf_rb); if (DB_FAILURE_MACRO(stat)) { (VOID) psf_error(E_PS0D18_QSF_LOCK, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psy_cb->psy_error, 0); if (!status || stat == E_DB_FATAL) status = stat; } text_lock = qsf_rb.qsf_lk_id; } stat = qsf_call(QSO_DESTROY, &qsf_rb); if (DB_FAILURE_MACRO(stat)) { (VOID) psf_error(E_PS0D1A_QSF_DESTROY, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psy_cb->psy_error, 0); if (!status || stat == E_DB_FATAL) status = stat; } return (status); }
/*{ ** Name: psy_kpermit - Destroy one or more permits on a database object ** (a table or a procedure or an event). ** ** INTERNAL PSF call format: status = psy_kpermit(&psy_cb, &sess_cb); ** ** EXTERNAL call format: status = psy_call(PSY_KPERMIT, &psy_cb, &sess_cb); ** ** Description: ** The psy_kpermit function removes the definition of one or more permits ** on a table, a procedure, or an event from all system relations ** (protect, tree, and iiqrytext). ** Optionally, one can tell this function to destroy all of the permits ** on a given table, procedure or event. ** ** Dropping all permits on a table is similar enough to dropping those on ** a procedure, so we will handle them together. On the other hand, when ** permit numbers are specified, processing is somewhat differen, e.g. ** we (at least for now) disallow dropping 0 and 1 on a dbproc. ** Events follow exactly the same model as procedures. ** Inputs: ** psy_cb ** .psy_tables[0] Id of table for which to destroy ** permit(s) ** .psy_numbs[] Id numbers of the permits to destroy ** (20 maximum) ** .psy_numnms Number of permit numbers given. Zero ** means to destroy all of the permits on ** the given table. ** .psy_tabname[0] Name of the table for which to destroy ** permit(s) ** .psy_grant PSY_PDROP if dropping permits on ** dbproc(s); ** PSY_TDROP if dropping permits on ** table(s). ** PSY_SDROP if dropping security alarms. ** PSY_EVDROP if dropping permits on ** event(s). ** sess_cb Pointer to session control block. ** ** Outputs: ** psy_cb ** .psy_error Filled in if an error happens ** .err_code What the error was ** E_PS0000_OK Success ** E_PS0001_USER_ERROR User made a mistake ** E_PS0002_INTERNAL_ERROR Internal inconsistency in PSF ** Returns: ** E_DB_OK Function completed normally. ** E_DB_WARN Function completed with warning(s) ** E_DB_ERROR Function failed; non-catastrophic error ** E_DB_FATAL Function failed; catastrophic error ** Exceptions: ** none ** ** Side Effects: ** Deletes query tree representing predicate of permit from tree ** relation, query text of permit definition from iiqrytext relation, ** does a dmf alter table on the base table to indicate that there ** are no more permissions on it should that happen to be the case. ** ** History: ** 02-oct-85 (jeff) ** written ** 05-aug-88 (andre) ** modified for DROPping permits on dbprocs. ** 03-oct-88 (andre) ** Modify call to pst_rgent to pass 0 as a query mode since it is ** clearly not PSQ_DESTROY. ** 04-oct-88 (andre) ** Make sure that the highest status received is reported to caller ** 02-nov-89 (neil) ** Alerters: Changes for dropping permits on events. ** 16-jan-90 (ralph) ** Add integrity check for DROP PERMIT/SECURITY_ALARM: ** don't allow drop permit to drop a security alarm; ** don't allow drop security_alarm to drop a permit. ** Initialise status to E_DB_OK. ** 12-mar-90 (andre) ** set rdr_2types_mask to 0. ** 22-may-90 (teg) ** init rdr_instr to RDF_NO_INSTR ** 04-feb-91 (neil) ** Fix 2 error cases: ** 1. If pst_rgent returns E_PS0903_TAB_NOTFOUND then return this ** error to the user. Can happen through Dynamic SQL where you ** drop the table before you exec the statement that drops grant. ** 2. Allow E_RD0025_USER_ERROR from RDF_UPDATE and continue. ** 29-aug-91 (andre) ** Do not call RDF to destroy permits if the object is a QUEL view ** owned by the DBA. ** ** Until now we could safely assume that if a view is non-grantable and ** there are permits defined on it, then the view is a QUEL view owned ** by the DBA and the only permit defined on it is an access permit. ** With advent of GRANT WGO, there may be permits defined on views ** marked as non-grantable (since "grantable" means that the view is ** defined on top of the objects owned by its owner so that its owner ** can always grant access to the view) and grantable QUEL views will ** be marked as such (this way if a user creates an SQL view on top of ** his grantable QUEL view we are guaranteed that the new view is also ** grantable). By not trying to destroy permits on QUEL views owned by ** the DBA we will ensure that a user cannot destroy an access permit ** which gets created for QUEL views owned by the DBA. ** 16-jun-92 (barbara) ** Change interface to pst_rgent. ** 22-jul-92 (andre) ** permits 0 and 1 will no longer hold special meaning for tables; in ** the past they meant ALL/RETRIEVE TO ALL, but with introduction of ** grantable privileges, they will no longer be created. Whether ** permit numbers 0 and 1 will become available for regular permits ** needs to be decided, but one thing is for sure, psy_kpermit() will ** not need to know about it. ** ** If user is destroying all permits or security_alarms, set ** RDR_DROP_ALL over rdr_types_mask ** 27-jul-92 (andre) ** we may be told that we may not drop a permit or all permits because ** it would render some permit or object abandoned ** 03-aug-92 (barbara) ** Invalidate base table info from RDF cache. ** 07-aug-92 (teresa) ** RDF_INVALID must be called to invalidate the base object from RDF's ** relation cache as well as to remove any permit trees from RDF's ** qtree cache. ** 08-nov-92 (andre) ** having dropped ALL permits on PROCEDURE, remember to set ** RDR_PROCEDURE in rdf_inv_cb.rdf_rb.rdr_types_mask before calling ** RDF_INVALIDATE ** 26-apr-93 (markg) ** Fixed bug which caused AV when attempting to drop a ** security_alarm. The problem was caused by incorrectly ** referencing a NULL pointer when initializing a local variable. ** 10-aug-93 (andre) ** fixed cause of compiler warning ** 13-sep-93 (andre) ** PSF will no longer be in business of altering timestamps of tables ** (or underlying base tables of views) on which permit(s) or ** security_alarm(s) have been dropped - responsibility for this has ** been assumed by QEF */ DB_STATUS psy_kpermit( PSY_CB *psy_cb, PSS_SESBLK *sess_cb) { RDF_CB rdf_cb; RDF_CB rdf_inv_cb; register RDR_RB *rdf_rb = &rdf_cb.rdf_rb; DB_STATUS status = E_DB_OK; i4 err_code; i4 msgid; register i4 i; PSS_RNGTAB *rngvar; /* Fill in RDF control block */ pst_rdfcb_init(&rdf_cb, sess_cb); pst_rdfcb_init(&rdf_inv_cb, sess_cb); STRUCT_ASSIGN_MACRO(psy_cb->psy_tables[0], rdf_rb->rdr_tabid); STRUCT_ASSIGN_MACRO(psy_cb->psy_tables[0], rdf_inv_cb.rdf_rb.rdr_tabid); rdf_inv_cb.rdf_rb.rdr_types_mask = RDR_PROTECT; rdf_rb->rdr_update_op = RDR_DELETE; if (psy_cb->psy_grant == PSY_TDROP) /* dropping perm on a table */ { /* get range table entry for this table */ status = pst_rgent(sess_cb, &sess_cb->pss_auxrng, -1, "", PST_SHWID, (DB_TAB_NAME*) NULL, (DB_TAB_OWN*) NULL, &psy_cb->psy_tables[0], TRUE, &rngvar, (i4) 0, &psy_cb->psy_error); if (DB_FAILURE_MACRO(status)) { if (psy_cb->psy_error.err_code == E_PS0903_TAB_NOTFOUND) { (VOID) psf_error(E_PS0903_TAB_NOTFOUND, 0L, PSF_USERERR, &err_code, &psy_cb->psy_error, 1, psf_trmwhite(sizeof(psy_cb->psy_tabname[0]), (char *) &psy_cb->psy_tabname[0]), &psy_cb->psy_tabname[0]); } return (status); } rdf_rb->rdr_types_mask = RDR_PROTECT; } else if (psy_cb->psy_grant == PSY_SDROP) /* dropping security alarm */ { rdf_rb->rdr_types_mask = RDR_SECALM; } else if (psy_cb->psy_grant == PSY_PDROP) /* dropping perm on a dbproc */ { DB_DBP_NAME *dbpname = (DB_DBP_NAME *) psy_cb->psy_tabname; /* save dbproc name and owner for RDF */ STRUCT_ASSIGN_MACRO(*dbpname, rdf_rb->rdr_name.rdr_prcname); STRUCT_ASSIGN_MACRO(sess_cb->pss_user, rdf_rb->rdr_owner); rdf_rb->rdr_types_mask = RDR_PROTECT | RDR_PROCEDURE; rdf_inv_cb.rdf_rb.rdr_types_mask |= RDR_PROCEDURE; } else if (psy_cb->psy_grant == PSY_EVDROP) /* dropping perm on event */ { DB_EVENT_NAME *evname = (DB_EVENT_NAME *)psy_cb->psy_tabname; /* Save event name and owner for RDF */ STRUCT_ASSIGN_MACRO(*evname, rdf_rb->rdr_name.rdr_evname); STRUCT_ASSIGN_MACRO(sess_cb->pss_user, rdf_rb->rdr_owner); rdf_rb->rdr_types_mask = RDR_PROTECT | RDR_EVENT; } /* Zero permit numbers means destroy all permits */ if (psy_cb->psy_numnms == 0) { /* ** Note that this block handles destroying all permits on ** a dbproc, event or a table or all security_alarms on a table */ /* ** check if user may drop permits (access permits get special ** treatment). If not, we are done. */ if (psy_cb->psy_grant == PSY_TDROP) { /* ** if this is a QUEL view owned by the DBA, avoid calling RDF since ** we need to rpevent a user from destroying access permit which is ** created on such views. */ if ( rngvar->pss_tabdesc->tbl_status_mask & DMT_VIEW && !MEcmp((PTR) &sess_cb->pss_dba, (PTR) &rngvar->pss_ownname, sizeof(DB_OWN_NAME)) ) { /* check if this is a QUEL view */ i4 issql = 0; status = psy_sqlview(rngvar, sess_cb, &psy_cb->psy_error, &issql); if (DB_FAILURE_MACRO(status)) { return(status); } if (!issql) { return(E_DB_OK); } } } /* tell RDF that we are dropping ALL permits or security_alarms */ rdf_rb->rdr_types_mask |= RDR_DROP_ALL; status = rdf_call(RDF_UPDATE, (PTR) &rdf_cb); if (DB_FAILURE_MACRO(status)) { switch (rdf_cb.rdf_error.err_code) { case E_RD0002_UNKNOWN_TBL: { (VOID) psf_error(E_PS0903_TAB_NOTFOUND, 0L, PSF_USERERR, &err_code, &psy_cb->psy_error, 1, psf_trmwhite(sizeof(psy_cb->psy_tabname[0]), (char *) &psy_cb->psy_tabname[0]), &psy_cb->psy_tabname[0]); break; } case E_RD0201_PROC_NOT_FOUND: { (VOID) psf_error(E_PS0905_DBP_NOTFOUND, 0L, PSF_USERERR, &err_code, &psy_cb->psy_error, 1, psf_trmwhite(sizeof(psy_cb->psy_tabname[0]), (char *) &psy_cb->psy_tabname[0]), &psy_cb->psy_tabname[0]); break; } case E_RD0210_ABANDONED_OBJECTS: { char *obj_type; i4 type_len; switch (psy_cb->psy_grant) { case PSY_TDROP: obj_type = "table"; type_len = sizeof("table") - 1; break; case PSY_PDROP: obj_type = "database procedure"; type_len = sizeof("database procedure") - 1; break; case PSY_EVDROP: obj_type = "dbevent"; type_len = sizeof("dbevent") - 1; break; default: obj_type = "UNKNOWN OBJECT TYPE"; type_len = sizeof("UNKNOWN OBJECT TYPE") - 1; break; } (VOID) psf_error(E_PS0564_ALLPROT_ABANDONED_OBJ, 0L, PSF_USERERR, &err_code, &psy_cb->psy_error, 2, type_len, obj_type, psf_trmwhite(sizeof(psy_cb->psy_tabname[0]), (char *) psy_cb->psy_tabname), psy_cb->psy_tabname); break; } default: { /* Event errors are handled in QEF */ (VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error, &psy_cb->psy_error); } } return (status); } /* ** Invalidate base object's infoblk from RDF cache; rdr_tabid ** already contains base table id; Call RDF to invalidate the ** base object. Then call again to invalidate any permit trees, ** set rdr_2_types mask for tree. */ status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_inv_cb); /* drop infoblk */ if (DB_FAILURE_MACRO(status)) { (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_inv_cb.rdf_error, &psy_cb->psy_error); return(status); } rdf_inv_cb.rdf_rb.rdr_2types_mask |= RDR2_CLASS; /* drop permit trees */ status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_inv_cb); if (DB_FAILURE_MACRO(status)) { (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_inv_cb.rdf_error, &psy_cb->psy_error); return(status); } } else if (psy_cb->psy_grant == PSY_PDROP || psy_cb->psy_grant == PSY_EVDROP) { DB_STATUS stat; /* Run through permit numbers, destroying each one */ for (i = 0; i < psy_cb->psy_numnms; i++) { rdf_rb->rdr_qrymod_id = psy_cb->psy_numbs[i]; stat = rdf_call(RDF_UPDATE, (PTR) &rdf_cb); /* remember the error to report later */ status = (status > stat) ? status : stat; if (DB_FAILURE_MACRO(status)) { switch (rdf_cb.rdf_error.err_code) { case E_RD0201_PROC_NOT_FOUND: { (VOID) psf_error(E_PS0905_DBP_NOTFOUND, 0L, PSF_USERERR, &err_code, &psy_cb->psy_error, 1, psf_trmwhite(sizeof(psy_cb->psy_tabname[0]), (char *) &psy_cb->psy_tabname[0]), &psy_cb->psy_tabname[0]); break; } case E_RD0210_ABANDONED_OBJECTS: { char *obj_type; i4 type_len; if (psy_cb->psy_grant == PSY_PDROP) { obj_type = "database procedure"; type_len = sizeof("database procedure") - 1; } else { obj_type = "dbevent"; type_len = sizeof("dbevent") - 1; } (VOID) psf_error(E_PS0565_PROT_ABANDONED_OBJ, 0L, PSF_USERERR, &err_code, &psy_cb->psy_error, 3, sizeof(psy_cb->psy_numbs[i]), psy_cb->psy_numbs + i, type_len, obj_type, psf_trmwhite(sizeof(psy_cb->psy_tabname[0]), (char *) psy_cb->psy_tabname), psy_cb->psy_tabname); break; } case E_RD0013_NO_TUPLE_FOUND: { (VOID) psf_error((i4) 5204, 0L, PSF_USERERR, &err_code, &psy_cb->psy_error, 1, sizeof (rdf_rb->rdr_qrymod_id), &rdf_rb->rdr_qrymod_id); continue; } case E_RD0025_USER_ERROR: /* ** Warning already handled - may be repeated when ** we try some more updates (if this is a multi- ** permit drop). */ if (psy_cb->psy_grant == PSY_EVDROP) { status = E_DB_OK; continue; } /* else fall through */ default: { /* Event-specific errors are reported through QEF */ (VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error, &psy_cb->psy_error); break; } } return (status); } /* ** Invalidate base object's infoblk from RDF cache: rdr_tabid ** already contains base table id; rdr_sequence contains ** permit number; set rdr_2_types mask. */ rdf_inv_cb.rdf_rb.rdr_sequence = psy_cb->psy_numbs[i]; rdf_inv_cb.rdf_rb.rdr_2types_mask |= RDR2_ALIAS; status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_inv_cb); if (DB_FAILURE_MACRO(status)) { (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_inv_cb.rdf_error, &psy_cb->psy_error); return(status); } } /* ** invalidate the relation cache entry that the permit was defined on */ rdf_inv_cb.rdf_rb.rdr_2types_mask &= ~RDR2_ALIAS; status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_inv_cb); if (DB_FAILURE_MACRO(status)) { (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_inv_cb.rdf_error, &psy_cb->psy_error); return(status); } } else /* drop permit or security alarm on a table */ { DB_STATUS stat; bool cant_drop_perms = FALSE; if (psy_cb->psy_grant == PSY_TDROP) { i4 mask = rngvar->pss_tabdesc->tbl_status_mask; /* ** if this is a QUEL view owned by the DBA, avoid calling RDF since ** we need to rpevent a user from destroying access permit which is ** created on such views. Instead, we will act as if the tuple was ** not found by QEF (without actually calling it.) */ if ( mask & DMT_VIEW && !MEcmp((PTR) &sess_cb->pss_dba, (PTR) &rngvar->pss_ownname, sizeof(DB_OWN_NAME)) ) { /* check if this is a QUEL view */ i4 issql = 0; status = psy_sqlview(rngvar, sess_cb, &psy_cb->psy_error, &issql); if (DB_FAILURE_MACRO(status)) { return(status); } if (!issql) { cant_drop_perms = TRUE; /* errors will be reported later */ status = E_DB_ERROR; } } } /* Run through permit or security_alarm numbers, destroying each one */ for (i = 0; i < psy_cb->psy_numnms; i++) { if (cant_drop_perms) { (VOID) psf_error(5204L, 0L, PSF_USERERR, &err_code, &psy_cb->psy_error, 1, sizeof (psy_cb->psy_numbs[i]), (PTR) &psy_cb->psy_numbs[i]); continue; } else { rdf_rb->rdr_qrymod_id = psy_cb->psy_numbs[i]; } stat = rdf_call(RDF_UPDATE, (PTR) &rdf_cb); /* remember the error to report later */ status = (status > stat) ? status : stat; if (DB_FAILURE_MACRO(stat)) { switch (rdf_cb.rdf_error.err_code) { case E_RD0002_UNKNOWN_TBL: { (VOID) psf_error(E_PS0903_TAB_NOTFOUND, 0L, PSF_USERERR, &err_code, &psy_cb->psy_error, 1, psf_trmwhite(sizeof(psy_cb->psy_tabname[0]), (char *) &psy_cb->psy_tabname[0]), &psy_cb->psy_tabname[0]); break; } case E_RD0210_ABANDONED_OBJECTS: { (VOID) psf_error(E_PS0565_PROT_ABANDONED_OBJ, 0L, PSF_USERERR, &err_code, &psy_cb->psy_error, 3, sizeof(psy_cb->psy_numbs[i]), psy_cb->psy_numbs + i, sizeof("table") - 1, "table", psf_trmwhite(sizeof(psy_cb->psy_tabname[0]), (char *) psy_cb->psy_tabname), psy_cb->psy_tabname); break; } case E_RD0013_NO_TUPLE_FOUND: { if (psy_cb->psy_grant == PSY_SDROP) msgid = (i4)5213; else msgid = (i4)5204; (VOID) psf_error(msgid, 0L, PSF_USERERR, &err_code, &psy_cb->psy_error, 1, sizeof (rdf_rb->rdr_qrymod_id), &rdf_rb->rdr_qrymod_id); continue; } default: { (VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error, &psy_cb->psy_error); break; } } return (status); } /* ** Invalidate base object's infoblk from RDF cache: rdr_tabid ** already contains base table id; rdr_sequence contains ** permit number (if not drop security alarm); set rdr_2_types mask. */ if (psy_cb->psy_grant == PSY_SDROP) { rdf_inv_cb.rdf_rb.rdr_2types_mask |= RDR2_KILLTREES; } else { rdf_inv_cb.rdf_rb.rdr_2types_mask |= RDR2_ALIAS; rdf_inv_cb.rdf_rb.rdr_types_mask = RDR_PROTECT; } status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_inv_cb); if (DB_FAILURE_MACRO(status)) { (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_inv_cb.rdf_error, &psy_cb->psy_error); return(status); } } /* now invalidate the base object that the permit was defined on */ rdf_inv_cb.rdf_rb.rdr_2types_mask &= ~(RDR2_ALIAS | RDR2_KILLTREES); status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_inv_cb); if (DB_FAILURE_MACRO(status)) { (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_inv_cb.rdf_error, &psy_cb->psy_error); return(status); } } return (status); }