SQLDA *mr_sqlda;
EXEC SQL BEGIN DECLARE SECTION;
-int mr_sig_length;
char stmt_buf[MR_STMTBUF_LEN];
int proxy_acl;
EXEC SQL END DECLARE SECTION;
extern struct query Queries[];
/* Put this in a variable so that we can patch it if necessary */
-int max_row_count = 4096;
+int max_row_count = 8192;
int mr_verify_query(client *cl, struct query *q, int argc, char *argv_ro[]);
int do_retrieve(struct query *q, char *pqual,
sqlglm(err_msg, &bufsize, &msglength);
err_msg[msglength] = 0;
com_err(whoami, 0, "SQL error text = %s", err_msg);
- critical_alert("MOIRA", "Moira server encountered DBMS ERROR %d\n%s",
+ critical_alert(whoami, "MOIRA", "Moira server encountered DBMS ERROR %d\n%s",
dbms_errno, err_msg);
}
mr_sqlda = mr_alloc_sqlda();
incremental_init();
- flush_cache();
}
dbms_errno = 0;
if (dbms_errno)
return mr_errcode;
- EXEC SQL SELECT data_length INTO :mr_sig_length FROM user_tab_columns
- WHERE table_name = 'USERS' and column_name = 'SIGNATURE';
- if (dbms_errno)
- return mr_errcode;
EXEC SQL SELECT list_id INTO :proxy_acl FROM capacls
WHERE capability = 'proxy';
if (dbms_errno)
void mr_close_database(void)
{
- flush_cache();
EXEC SQL COMMIT RELEASE;
}
switch (q->type)
{
- case RETRIEVE:
+ case MR_Q_RETRIEVE:
/* for queries that do not permit wildcarding, check if row
uniquely exists */
if (v && v->field)
break;
- case UPDATE:
+ case MR_Q_UPDATE:
/* see if row already exists */
if (v->field)
{
incremental_after(q->rtable, qual, argv_ro);
if (status != MR_SUCCESS)
break;
- flush_name(argv_ro[0], q->rtable);
table = table_name[q->rtable];
if (strcmp(q->shortname, "sshi") && strcmp(q->shortname, "ssif"))
{
break;
- case APPEND:
+ case MR_Q_APPEND:
/* see if row already exists */
if (v->field)
{
status = (*v->post_rtn)(q, Argv, cl);
break;
- case DELETE:
+ case MR_Q_DELETE:
/* see if row already exists */
if (v->field)
{
incremental_clear_after();
if (status != MR_SUCCESS)
break;
- flush_name(argv_ro[0], q->rtable);
EXEC SQL UPDATE tblstats
SET deletes = deletes + 1, modtime = SYSDATE
WHERE table_name = :table;
status = (*v->post_rtn)(q, Argv, cl);
break;
- case SPECIAL:
+ case MR_Q_SPECIAL:
break;
}
status = mr_errcode;
}
- if (q->type == RETRIEVE)
+ if (q->type == MR_Q_RETRIEVE)
EXEC SQL COMMIT WORK;
else
{
}
else
{
- cache_abort();
EXEC SQL ROLLBACK WORK;
incremental_flush();
}
}
- cache_commit(); /* commit following abort is safe */
if (status != MR_SUCCESS)
com_err(whoami, status, " (Query failed)");
while (*fmt)
{
- if (!like && !arg)
+
+ if ((!like && !arg) || argc == 0)
{
/* only plain text remains */
strcpy(res, fmt);
/* check argument count */
argreq = q->argc;
- if (q->type == UPDATE || q->type == APPEND)
+ if (q->type == MR_Q_UPDATE || q->type == MR_Q_APPEND)
argreq += q->vcnt;
if (argc != argreq)
return MR_ARGS;
if (*fr)
return MR_ARG_TOO_LONG;
*to = '\0';
-
- if (to > Argv[i] && *--to == '\\')
- return MR_BAD_CHAR;
}
- /* check initial query access, unless we're acting as a proxy */
- if (!cl->proxy_id)
- {
- status = check_query_access(q, Argv, cl);
- if (status != MR_SUCCESS && status != MR_PERM)
- return status;
- if (status == MR_SUCCESS)
- privileged++;
- }
+ /* Check initial query access. If we're acting as a proxy, only allow
+ * access if the query has "default" as a capacl.
+ */
+ status = check_query_access(q, Argv, cl);
+ if (status != MR_SUCCESS && status != MR_PERM)
+ return status;
+ if (status == MR_SUCCESS && (!cl->proxy_id || q->everybody))
+ privileged++;
/* validate arguments */
if (v && v->valobj)
return privileged ? MR_SUCCESS : MR_PERM;
}
-
-/* This routine caches info from the database. Each query acl is stored
- * in the query structure, and whether that acl contains everybody.
- */
-
int check_query_access(struct query *q, char *argv[], client *cl)
{
EXEC SQL BEGIN DECLARE SECTION;
if (def_uid == 0)
EXEC SQL SELECT users_id INTO :def_uid FROM users WHERE login = 'default';
- /* get query access control list */
- if (q->acl != 0)
- acl_id = q->acl;
+ name = q->shortname;
+ EXEC SQL SELECT list_id INTO :acl_id FROM capacls WHERE tag = :name;
+ if (sqlca.sqlcode < 0)
+ return MR_DBMS_ERR;
+ if (sqlca.sqlcode == SQL_NO_MATCH)
+ return MR_PERM;
+ q->acl = acl_id;
+
+ /* check for default access */
+ EXEC SQL SELECT member_id INTO :acl_id FROM imembers
+ WHERE list_id = :acl_id AND member_type = 'USER'
+ AND member_id = :def_uid;
+ if (sqlca.sqlerrd[2] == 0)
+ q->everybody = 0;
else
- {
- name = q->shortname;
- EXEC SQL SELECT list_id INTO :acl_id FROM capacls WHERE tag = :name;
- if (sqlca.sqlcode < 0)
- return MR_DBMS_ERR;
- if (sqlca.sqlcode == SQL_NO_MATCH)
- return MR_PERM;
- q->acl = acl_id;
-
- /* check for default access */
- EXEC SQL SELECT member_id INTO :acl_id FROM imembers
- WHERE list_id = :acl_id AND member_type = 'USER'
- AND member_id = :def_uid;
- if (sqlca.sqlerrd[2] == 0)
- q->everybody = 0;
- else
- q->everybody = 1;
- }
+ q->everybody = 1;
if (q->everybody)
return MR_SUCCESS;
** table - name of table objects are found in
** limit - should the ID be range limited
**
- ** - called before an APPEND operation to set the next object id to
+ ** - called before an MR_Q_APPEND operation to set the next object id to
** be used for the new record to the next free value
**
**/
return mr_errcode;
if (rowcount == max_row_count)
{
- critical_alert("moirad", "attempted query with too many rows");
+ critical_alert(whoami, "moirad", "attempted query with too many rows");
return MR_NO_MEM;
}
else if (rowcount == 0)
return MR_SUCCESS;
}
+/* Do a name to ID translation. Moved from cache.pc because we did away
+ * with the cache, but what this function does is still useful to us.
+ */
+
+int name_to_id(char *name, enum tables type, int *id)
+{
+ EXEC SQL BEGIN DECLARE SECTION;
+ char *iname;
+ int j;
+ EXEC SQL END DECLARE SECTION;
+
+ iname = name;
+
+ switch (type)
+ {
+ case USERS_TABLE:
+ if (strchr(iname, '@') || (strlen(iname) > 8))
+ {
+ sqlca.sqlcode = SQL_NO_MATCH;
+ break;
+ }
+ EXEC SQL SELECT users_id INTO :j FROM users WHERE login = :iname;
+ break;
+ case LIST_TABLE:
+ EXEC SQL SELECT list_id INTO :j FROM list WHERE name = :iname;
+ break;
+ case MACHINE_TABLE:
+ EXEC SQL SELECT mach_id INTO :j FROM machine WHERE name = UPPER(:iname);
+ break;
+ case SUBNET_TABLE:
+ EXEC SQL SELECT snet_id INTO :j FROM subnet WHERE name = UPPER(:iname);
+ break;
+ case CLUSTERS_TABLE:
+ EXEC SQL SELECT clu_id INTO :j FROM clusters WHERE name = :iname;
+ break;
+ case FILESYS_TABLE:
+ EXEC SQL SELECT filsys_id INTO :j FROM filesys WHERE label = :iname;
+ break;
+ case STRINGS_TABLE:
+ if (!iname[0]) /* special-case empty string */
+ {
+ *id = 0;
+ return MR_SUCCESS;
+ }
+ EXEC SQL SELECT string_id INTO :j FROM strings WHERE string = :iname;
+ break;
+ case CONTAINERS_TABLE:
+ EXEC SQL SELECT cnt_id INTO :j FROM containers WHERE LOWER(name) =
+ LOWER(:iname);
+ break;
+ default:
+ return MR_INTERNAL;
+ }
+ if (sqlca.sqlcode == SQL_NO_MATCH)
+ return MR_NO_MATCH;
+ if (sqlca.sqlerrd[2] > 1)
+ return MR_NOT_UNIQUE;
+ if (sqlca.sqlcode)
+ return MR_DBMS_ERR;
+ *id = j;
+
+ return MR_SUCCESS;
+}
+
+/* Perform an ID to name mapping. name should be a pointer to a pointer to
+ * malloc'ed data. The buffer it refers to will be freed, and a new buffer
+ * allocated with the answer.
+ *
+ * This used to be in cache.pc, but we've removed the cache, and this function
+ * is still useful to us.
+ */
+
+int id_to_name(int id, enum tables type, char **name)
+{
+ EXEC SQL BEGIN DECLARE SECTION;
+ char iname[MAX_FIELD_WIDTH];
+ int j;
+ EXEC SQL END DECLARE SECTION;
+
+ j = id;
+
+ switch (type)
+ {
+ case USERS_TABLE:
+ EXEC SQL SELECT login INTO :iname FROM users WHERE users_id = :j;
+ break;
+ case LIST_TABLE:
+ EXEC SQL SELECT name INTO :iname FROM list WHERE list_id = :j;
+ break;
+ case MACHINE_TABLE:
+ EXEC SQL SELECT name INTO :iname FROM machine WHERE mach_id = :j;
+ break;
+ case SUBNET_TABLE:
+ EXEC SQL SELECT name INTO :iname FROM subnet WHERE snet_id = :j;
+ break;
+ case CLUSTERS_TABLE:
+ EXEC SQL SELECT name INTO :iname FROM clusters WHERE clu_id = :j;
+ break;
+ case FILESYS_TABLE:
+ EXEC SQL SELECT label INTO :iname FROM filesys WHERE filsys_id = :j;
+ break;
+ case STRINGS_TABLE:
+ EXEC SQL SELECT string INTO :iname FROM strings WHERE string_id = :j;
+ break;
+ case CONTAINERS_TABLE:
+ EXEC SQL SELECT name INTO :iname FROM containers WHERE cnt_id = :j;
+ break;
+ default:
+ return MR_INTERNAL;
+ }
+ if (sqlca.sqlcode == SQL_NO_MATCH)
+ {
+ free(*name);
+ sprintf(iname, "#%d", j);
+ *name = xstrdup(iname);
+ return MR_NO_MATCH;
+ }
+ if (sqlca.sqlerrd[2] > 1)
+ return MR_INTERNAL;
+ if (sqlca.sqlcode)
+ return MR_DBMS_ERR;
+ free(*name);
+ *name = xstrdup(strtrim(iname));
+
+ return MR_SUCCESS;
+}
/* eof:qrtn.dc */