irods  4.2.8
About: iRODS (the integrated Rule Oriented Data System) is a distributed data-management system for creating data grids, digital libraries, persistent archives, and real-time data systems.
  Fossies Dox: irods-4.2.8.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

mid_level_routines.cpp
Go to the documentation of this file.
1 
3 
17 #include "mid_level.hpp"
18 #include "low_level.hpp"
19 #include "irods_stacktrace.hpp"
20 #include "irods_log.hpp"
21 #include "irods_virtual_path.hpp"
22 
23 #include "rcMisc.h"
24 
25 #include <vector>
26 #include <string>
27 
28 #include "boost/filesystem.hpp"
29 
30 /* Size of the R_OBJT_AUDIT comment field;must match table column definition */
31 #define AUDIT_COMMENT_MAX_SIZE 1000
32 
33 extern int logSQL_CML;
34 extern int auditEnabled; /* Set this to 2 and rebuild to enable iRODS
35  auditing (non-zero means auditing but 1 will
36  allow cmlDebug to modify it, so 2 means
37  permanently enabled). We plan to change this
38  sometime to have better control. */
39 
40 int checkObjIdByTicket( const char *dataId, const char *accessLevel,
41  const char *ticketStr, const char *ticketHost,
42  const char *userName, const char *userZone,
44 
45 /*
46  Convert the intput arrays to a string and add bind variables
47 */
48 char *cmlArraysToStrWithBind( char* str,
49  const char* preStr,
50  const char* arr[],
51  const char* arr2[],
52  int arrLen,
53  const char* sep,
54  const char* sep2,
55  int maxLen ) {
56  int i;
57 
58  rstrcpy( str, preStr, maxLen );
59 
60  for ( i = 0; i < arrLen; i++ ) {
61  if ( i > 0 ) {
62  rstrcat( str, sep2, maxLen );
63  }
64  rstrcat( str, arr[i], maxLen );
65  rstrcat( str, sep, maxLen );
66  rstrcat( str, "?", maxLen );
67  cllBindVars[cllBindVarCount++] = arr2[i];
68  }
69 
70  return str;
71 
72 }
73 
74 int cmlDebug( int mode ) {
75  logSQL_CML = mode;
76  if ( mode > 1 ) {
77  if ( auditEnabled == 0 ) {
78  auditEnabled = 1;
79  }
80  /* This is needed for testing each sql form, which is needed for
81  the 'irodsctl devtest' to pass */
82  }
83  else {
84  if ( auditEnabled == 1 ) {
85  auditEnabled = 0;
86  }
87  }
88  return 0;
89 }
90 
92  int i;
93 
94  /* Initialize the icss statement pointers */
95  for ( i = 0; i < MAX_NUM_OF_CONCURRENT_STMTS; i++ ) {
96  icss->stmtPtr[i] = 0;
97  }
98 
99  /*
100  Set the ICAT DBMS type. The Low Level now uses this instead of the
101  ifdefs so it can interact with either at the same time.
102  */
104 #ifdef ORA_ICAT
106 #endif
107 #ifdef MY_ICAT
109 #endif
110 
111 
112  /* Open Environment */
113  i = cllOpenEnv( icss );
114  if ( i != 0 ) {
115  return CAT_ENV_ERR;
116  }
117 
118  /* Connect to the DBMS */
119  i = cllConnect( icss );
120  if ( i != 0 ) {
121  return CAT_CONNECT_ERR;
122  }
123 
124  return 0;
125 }
126 
128  int status, stat2;
129  static int pending = 0;
130 
131  if ( pending == 1 ) {
132  return ( 0 ); /* avoid hang if stuck doing this */
133  }
134  pending = 1;
135 
137 
138  stat2 = cllCloseEnv( icss );
139 
140  pending = 0;
141  if ( status ) {
142  return CAT_DISCONNECT_ERR;
143  }
144  if ( stat2 ) {
145  return CAT_CLOSE_ENV_ERR;
146  }
147  return 0;
148 }
149 
150 
151 int cmlExecuteNoAnswerSql( const char *sql,
153  int i;
154  i = cllExecSqlNoResult( icss, sql );
155  if ( i ) {
156  if ( i <= CAT_ENV_ERR ) {
157  return ( i ); /* already an iRODS error code */
158  }
159  return CAT_SQL_ERR;
160  }
161  return 0;
162 
163 }
164 
165 int cmlGetOneRowFromSqlBV( const char *sql,
166  char *cVal[],
167  int cValSize[],
168  int numOfCols,
169  std::vector<std::string> &bindVars,
171  int stmtNum = UNINITIALIZED_STATEMENT_NUMBER;
172  char updatedSql[MAX_SQL_SIZE + 1];
173 
174 //TODO: this should be a function, probably inside low-level icat
175 #ifdef ORA_ICAT
176  strncpy( updatedSql, sql, MAX_SQL_SIZE );
177  updatedSql[MAX_SQL_SIZE] = '\0';
178 #else
179  strncpy( updatedSql, sql, MAX_SQL_SIZE );
180  updatedSql[MAX_SQL_SIZE] = '\0';
181  /* Verify there no limit or offset statement */
182  if ( ( strstr( updatedSql, "limit " ) == NULL ) && ( strstr( updatedSql, "offset " ) == NULL ) ) {
183  /* add 'limit 1' for performance improvement */
184  strncat( updatedSql, " limit 1", MAX_SQL_SIZE );
185  rodsLog( LOG_DEBUG10, "cmlGetOneRowFromSqlBV %s", updatedSql );
186  }
187 #endif
188  int status = cllExecSqlWithResultBV( icss, &stmtNum, updatedSql,
189  bindVars );
190  if ( status != 0 ) {
191  cllFreeStatement(icss, stmtNum);
192  if ( status <= CAT_ENV_ERR ) {
193  return status; /* already an iRODS error code */
194  }
195  return CAT_SQL_ERR;
196  }
197 
198  if ( cllGetRow( icss, stmtNum ) != 0 ) {
199  cllFreeStatement( icss, stmtNum );
200  return CAT_GET_ROW_ERR;
201  }
202  if ( icss->stmtPtr[stmtNum]->numOfCols == 0 ) {
203  cllFreeStatement( icss, stmtNum );
204  return CAT_NO_ROWS_FOUND;
205  }
206  int numCVal = std::min( numOfCols, icss->stmtPtr[stmtNum]->numOfCols );
207  for ( int j = 0; j < numCVal ; j++ ) {
208  rstrcpy( cVal[j], icss->stmtPtr[stmtNum]->resultValue[j], cValSize[j] );
209  }
210 
211  cllFreeStatement( icss, stmtNum );
212  return numCVal;
213 
214 }
215 
216 int cmlGetOneRowFromSql( const char *sql,
217  char *cVal[],
218  int cValSize[],
219  int numOfCols,
221  int i, j, stmtNum = UNINITIALIZED_STATEMENT_NUMBER;
222  char updatedSql[MAX_SQL_SIZE + 1];
223 
224 //TODO: this should be a function, probably inside low-level icat
225 #ifdef ORA_ICAT
226  strncpy( updatedSql, sql, MAX_SQL_SIZE );
227  updatedSql[MAX_SQL_SIZE] = '\0';
228 #else
229  strncpy( updatedSql, sql, MAX_SQL_SIZE );
230  updatedSql[MAX_SQL_SIZE] = '\0';
231  /* Verify there no limit or offset statement */
232  if ( ( strstr( updatedSql, "limit " ) == NULL ) && ( strstr( updatedSql, "offset " ) == NULL ) ) {
233  /* add 'limit 1' for performance improvement */
234  strncat( updatedSql, " limit 1", MAX_SQL_SIZE );
235  rodsLog( LOG_DEBUG10, "cmlGetOneRowFromSql %s", updatedSql );
236  }
237 #endif
238 
239  std::vector<std::string> emptyBindVars;
240  i = cllExecSqlWithResultBV( icss, &stmtNum, updatedSql,
241  emptyBindVars );
242  if ( i != 0 ) {
243  cllFreeStatement( icss, stmtNum );
244  if ( i <= CAT_ENV_ERR ) {
245  return ( i ); /* already an iRODS error code */
246  }
247  return CAT_SQL_ERR;
248  }
249  i = cllGetRow( icss, stmtNum );
250  if ( i != 0 ) {
251  cllFreeStatement( icss, stmtNum );
252  return CAT_GET_ROW_ERR;
253  }
254  if ( icss->stmtPtr[stmtNum]->numOfCols == 0 ) {
255  cllFreeStatement( icss, stmtNum );
256  return CAT_NO_ROWS_FOUND;
257  }
258  for ( j = 0; j < numOfCols && j < icss->stmtPtr[stmtNum]->numOfCols ; j++ ) {
259  rstrcpy( cVal[j], icss->stmtPtr[stmtNum]->resultValue[j], cValSize[j] );
260  }
261 
262  i = cllFreeStatement( icss, stmtNum );
263  return j;
264 
265 }
266 
267 /* like cmlGetOneRowFromSql but cVal uses space from query
268  and then caller frees it later (via cmlFreeStatement).
269  This is simplier for the caller, in some cases. */
270 int cmlGetOneRowFromSqlV2( const char *sql,
271  char *cVal[],
272  int maxCols,
273  std::vector<std::string> &bindVars,
275  int i, j, stmtNum = UNINITIALIZED_STATEMENT_NUMBER;
276  char updatedSql[MAX_SQL_SIZE + 1];
277 
278 //TODO: this should be a function, probably inside low-level icat
279 #ifdef ORA_ICAT
280  strncpy( updatedSql, sql, MAX_SQL_SIZE );
281  updatedSql[MAX_SQL_SIZE] = '\0';
282 #else
283  strncpy( updatedSql, sql, MAX_SQL_SIZE );
284  updatedSql[MAX_SQL_SIZE] = '\0';
285  /* Verify there no limit or offset statement */
286  if ( ( strstr( updatedSql, "limit " ) == NULL ) && ( strstr( updatedSql, "offset " ) == NULL ) ) {
287  /* add 'limit 1' for performance improvement */
288  strncat( updatedSql, " limit 1", MAX_SQL_SIZE );
289  rodsLog( LOG_DEBUG10, "cmlGetOneRowFromSqlV2 %s", updatedSql );
290  }
291 #endif
292 
293  i = cllExecSqlWithResultBV( icss, &stmtNum, updatedSql,
294  bindVars );
295 
296  if ( i != 0 ) {
297  cllFreeStatement( icss, stmtNum );
298  if ( i <= CAT_ENV_ERR ) {
299  return ( i ); /* already an iRODS error code */
300  }
301  return CAT_SQL_ERR;
302  }
303  i = cllGetRow( icss, stmtNum );
304  if ( i != 0 ) {
305  cllFreeStatement( icss, stmtNum );
306  return CAT_GET_ROW_ERR;
307  }
308  if ( icss->stmtPtr[stmtNum]->numOfCols == 0 ) {
309  return CAT_NO_ROWS_FOUND;
310  }
311  for ( j = 0; j < maxCols && j < icss->stmtPtr[stmtNum]->numOfCols ; j++ ) {
312  cVal[j] = icss->stmtPtr[stmtNum]->resultValue[j];
313  }
314 
315  return ( stmtNum ); /* 0 or positive is the statement number */
316 }
317 
318 /*
319  Like cmlGetOneRowFromSql but uses bind variable array (via
320  cllExecSqlWithResult).
321  */
322 static
323 int cmlGetOneRowFromSqlV3( const char *sql,
324  char *cVal[],
325  int cValSize[],
326  int numOfCols,
328  int i, j, stmtNum = UNINITIALIZED_STATEMENT_NUMBER;
329  char updatedSql[MAX_SQL_SIZE + 1];
330 
331 //TODO: this should be a function, probably inside low-level icat
332 #ifdef ORA_ICAT
333  strncpy( updatedSql, sql, MAX_SQL_SIZE );
334  updatedSql[MAX_SQL_SIZE] = '\0';
335 #else
336  strncpy( updatedSql, sql, MAX_SQL_SIZE );
337  updatedSql[MAX_SQL_SIZE] = '\0';
338  /* Verify there no limit or offset statement */
339  if ( ( strstr( updatedSql, "limit " ) == NULL ) && ( strstr( updatedSql, "offset " ) == NULL ) ) {
340  /* add 'limit 1' for performance improvement */
341  strncat( updatedSql, " limit 1", MAX_SQL_SIZE );
342  rodsLog( LOG_DEBUG10, "cmlGetOneRowFromSqlV3 %s", updatedSql );
343  }
344 #endif
345 
346  i = cllExecSqlWithResult( icss, &stmtNum, updatedSql );
347 
348  if ( i != 0 ) {
349  cllFreeStatement( icss, stmtNum );
350  if ( i <= CAT_ENV_ERR ) {
351  return ( i ); /* already an iRODS error code */
352  }
353  return CAT_SQL_ERR;
354  }
355  i = cllGetRow( icss, stmtNum );
356  if ( i != 0 ) {
357  cllFreeStatement( icss, stmtNum );
358  return CAT_GET_ROW_ERR;
359  }
360  if ( icss->stmtPtr[stmtNum]->numOfCols == 0 ) {
361  cllFreeStatement( icss, stmtNum );
362  return CAT_NO_ROWS_FOUND;
363  }
364  for ( j = 0; j < numOfCols && j < icss->stmtPtr[stmtNum]->numOfCols ; j++ ) {
365  rstrcpy( cVal[j], icss->stmtPtr[stmtNum]->resultValue[j], cValSize[j] );
366  }
367 
368  i = cllFreeStatement( icss, stmtNum );
369  return j;
370 
371 }
372 
373 
374 int cmlFreeStatement( int statementNumber, icatSessionStruct *icss ) {
375  int i;
376  i = cllFreeStatement( icss, statementNumber );
377  return i;
378 }
379 
380 /*
381  * caller must free on success */
382 int cmlGetFirstRowFromSql( const char *sql,
383  int *statement,
384  int skipCount,
386 
387  int i = cllExecSqlWithResult( icss, statement, sql );
388 
389  if ( i != 0 ) {
390  cllFreeStatement( icss, *statement );
391  *statement = UNINITIALIZED_STATEMENT_NUMBER;
392  if ( i <= CAT_ENV_ERR ) {
393  return ( i ); /* already an iRODS error code */
394  }
395  return CAT_SQL_ERR;
396  }
397 
398 #ifdef ORA_ICAT
399  if ( skipCount > 0 ) {
400  for ( int j = 0; j < skipCount; j++ ) {
401  i = cllGetRow( icss, *statement );
402  if ( i != 0 ) {
403  cllFreeStatement( icss, *statement );
404  *statement = UNINITIALIZED_STATEMENT_NUMBER;
405  return CAT_GET_ROW_ERR;
406  }
407  if ( icss->stmtPtr[*statement]->numOfCols == 0 ) {
408  cllFreeStatement( icss, *statement );
409  *statement = UNINITIALIZED_STATEMENT_NUMBER;
410  return CAT_NO_ROWS_FOUND;
411  }
412  }
413  }
414 #endif
415 
416  i = cllGetRow( icss, *statement );
417  if ( i != 0 ) {
418  cllFreeStatement( icss, *statement );
419  *statement = UNINITIALIZED_STATEMENT_NUMBER;
420  return CAT_GET_ROW_ERR;
421  }
422  if ( icss->stmtPtr[*statement]->numOfCols == 0 ) {
423  cllFreeStatement( icss, *statement );
424  *statement = UNINITIALIZED_STATEMENT_NUMBER;
425  return CAT_NO_ROWS_FOUND;
426  }
427 
428  return 0;
429 }
430 
431 /* with bind-variables
432  * caller must free on success */
433 int cmlGetFirstRowFromSqlBV( const char *sql,
434  std::vector<std::string> &bindVars,
435  int *statement,
437  if ( int status = cllExecSqlWithResultBV( icss, statement, sql, bindVars ) ) {
438  *statement = UNINITIALIZED_STATEMENT_NUMBER;
439  if ( status <= CAT_ENV_ERR ) {
440  return status; /* already an iRODS error code */
441  }
442  return CAT_SQL_ERR;
443  }
444  if ( cllGetRow( icss, *statement ) ) {
445  cllFreeStatement( icss, *statement );
446  *statement = UNINITIALIZED_STATEMENT_NUMBER;
447  return CAT_GET_ROW_ERR;
448  }
449  if ( icss->stmtPtr[*statement]->numOfCols == 0 ) {
450  cllFreeStatement( icss, *statement );
451  *statement = UNINITIALIZED_STATEMENT_NUMBER;
452  return CAT_NO_ROWS_FOUND;
453  }
454  return 0;
455 }
456 
457 /*
458  * caller must free on success */
459 int cmlGetNextRowFromStatement( int stmtNum,
461  int i;
462 
463  i = cllGetRow( icss, stmtNum );
464  if ( i != 0 ) {
465  cllFreeStatement( icss, stmtNum );
466  return CAT_GET_ROW_ERR;
467  }
468  if ( icss->stmtPtr[stmtNum]->numOfCols == 0 ) {
469  i = cllFreeStatement( icss, stmtNum );
470  return CAT_NO_ROWS_FOUND;
471  }
472  return 0;
473 }
474 
475 int cmlGetStringValueFromSql( const char *sql,
476  char *cVal,
477  int cValSize,
478  std::vector<std::string> &bindVars,
480  int status;
481  char *cVals[2];
482  int iVals[2];
483 
484  cVals[0] = cVal;
485  iVals[0] = cValSize;
486 
487  status = cmlGetOneRowFromSqlBV( sql, cVals, iVals, 1,
488  bindVars, icss );
489  if ( status == 1 ) {
490  return 0;
491  }
492  else {
493  return status;
494  }
495 
496 }
497 
498 int cmlGetStringValuesFromSql( const char *sql,
499  char *cVal[],
500  int cValSize[],
501  int numberOfStringsToGet,
502  std::vector<std::string> &bindVars,
504 
505  int i = cmlGetOneRowFromSqlBV( sql, cVal, cValSize, numberOfStringsToGet,
506  bindVars, icss );
507  if ( i == numberOfStringsToGet ) {
508  return 0;
509  }
510  else {
511  return i;
512  }
513 
514 }
515 
517  char *returnedStrings,
518  int maxStringLen,
519  int maxNumberOfStringsToGet,
520  std::vector<std::string> &bindVars,
522 
523  int i, j, stmtNum = UNINITIALIZED_STATEMENT_NUMBER;
524  int tsg; /* total strings gotten */
525  char *pString;
526 
527  if ( maxNumberOfStringsToGet <= 0 ) {
528  return CAT_INVALID_ARGUMENT;
529  }
530 
531  i = cllExecSqlWithResultBV( icss, &stmtNum, sql, bindVars );
532  if ( i != 0 ) {
533  cllFreeStatement( icss, stmtNum );
534  if ( i <= CAT_ENV_ERR ) {
535  return ( i ); /* already an iRODS error code */
536  }
537  return CAT_SQL_ERR;
538  }
539  tsg = 0;
540  pString = returnedStrings;
541  for ( ;; ) {
542  i = cllGetRow( icss, stmtNum );
543  if ( i != 0 ) {
544  cllFreeStatement( icss, stmtNum );
545  if ( tsg > 0 ) {
546  return tsg;
547  }
548  return CAT_GET_ROW_ERR;
549  }
550  if ( icss->stmtPtr[stmtNum]->numOfCols == 0 ) {
551  cllFreeStatement( icss, stmtNum );
552  if ( tsg > 0 ) {
553  return tsg;
554  }
555  return CAT_NO_ROWS_FOUND;
556  }
557  for ( j = 0; j < icss->stmtPtr[stmtNum]->numOfCols; j++ ) {
558  rstrcpy( pString, icss->stmtPtr[stmtNum]->resultValue[j],
559  maxStringLen );
560  tsg++;
561  pString += maxStringLen;
562  if ( tsg >= maxNumberOfStringsToGet ) {
563  i = cllFreeStatement( icss, stmtNum );
564  return tsg;
565  }
566  }
567  }
568  cllFreeStatement( icss, stmtNum );
569  return 0;
570 }
571 
572 
573 int cmlGetIntegerValueFromSql( const char *sql,
574  rodsLong_t *iVal,
575  std::vector<std::string> &bindVars,
577  int i, cValSize;
578  char *cVal[2];
579  char cValStr[MAX_INTEGER_SIZE + 10];
580 
581  cVal[0] = cValStr;
582  cValSize = MAX_INTEGER_SIZE;
583 
584  i = cmlGetOneRowFromSqlBV( sql, cVal, &cValSize, 1,
585  bindVars, icss );
586  if ( i == 1 ) {
587  if ( *cVal[0] == '\0' ) {
588  return CAT_NO_ROWS_FOUND;
589  }
590  *iVal = strtoll( *cVal, NULL, 0 );
591  return 0;
592  }
593  return i;
594 }
595 
596 /* Like cmlGetIntegerValueFromSql but uses bind-variable array */
597 int cmlGetIntegerValueFromSqlV3( const char *sql,
598  rodsLong_t *iVal,
600  int i, cValSize;
601  char *cVal[2];
602  char cValStr[MAX_INTEGER_SIZE + 10];
603 
604  cVal[0] = cValStr;
605  cValSize = MAX_INTEGER_SIZE;
606 
607  i = cmlGetOneRowFromSqlV3( sql, cVal, &cValSize, 1, icss );
608  if ( i == 1 ) {
609  if ( *cVal[0] == '\0' ) {
610  return CAT_NO_ROWS_FOUND;
611  }
612  *iVal = strtoll( *cVal, NULL, 0 );
613  return 0;
614  }
615  return i;
616 }
617 
618 int cmlCheckNameToken( const char *nameSpace, const char *tokenName, icatSessionStruct *icss ) {
619 
620  rodsLong_t iVal;
621  int status;
622 
623  if ( logSQL_CML != 0 ) {
624  rodsLog( LOG_SQL, "cmlCheckNameToken SQL 1 " );
625  }
626  std::vector<std::string> bindVars;
627  bindVars.push_back( nameSpace );
628  bindVars.push_back( tokenName );
630  "select token_id from R_TOKN_MAIN where token_namespace=? and token_name=?",
631  &iVal, bindVars, icss );
632  return status;
633 
634 }
635 
637  const char *updateCols[],
638  const char *updateValues[],
639  const char *whereColsAndConds[],
640  const char *whereValues[],
641  int numOfUpdates,
642  int numOfConds,
644  char tsql[MAX_SQL_SIZE];
645  int i, l;
646  char *rsql;
647 
648  if ( logSQL_CML != 0 ) {
649  rodsLog( LOG_SQL, "cmlModifySingleTable SQL 1 " );
650  }
651 
652  snprintf( tsql, MAX_SQL_SIZE, "update %s set ", tableName );
653  l = strlen( tsql );
654  rsql = tsql + l;
655 
656  cmlArraysToStrWithBind( rsql, "", updateCols, updateValues, numOfUpdates, " = ", ", ", MAX_SQL_SIZE - l );
657  l = strlen( tsql );
658  rsql = tsql + l;
659 
660  cmlArraysToStrWithBind( rsql, " where ", whereColsAndConds, whereValues, numOfConds, "", " and ", MAX_SQL_SIZE - l );
661 
662  i = cmlExecuteNoAnswerSql( tsql, icss );
663  return i;
664 
665 }
666 
667 #define STR_LEN 100
670  char nextStr[STR_LEN];
671  char sql[STR_LEN];
672  int status;
673  rodsLong_t iVal{};
674 
675  if ( logSQL_CML != 0 ) {
676  rodsLog( LOG_SQL, "cmlGetNextSeqVal SQL 1 " );
677  }
678 
679  nextStr[0] = '\0';
680 
681  cllNextValueString( "R_ObjectID", nextStr, STR_LEN );
682  /* R_ObjectID is created in icatSysTables.sql as
683  the sequence item for objects */
684 
685 #ifdef ORA_ICAT
686  /* For Oracle, use the built-in one-row table */
687  snprintf( sql, STR_LEN, "select %s from DUAL", nextStr );
688 #else
689  /* Postgres can just get the next value without a table */
690  snprintf( sql, STR_LEN, "select %s", nextStr );
691 #endif
692 
693  std::vector<std::string> emptyBindVars;
694  status = cmlGetIntegerValueFromSql( sql, &iVal, emptyBindVars, icss );
695  if ( status < 0 ) {
697  "cmlGetNextSeqVal cmlGetIntegerValueFromSql failure %d", status );
698  return status;
699  }
700  return iVal;
701 }
702 
705  char nextStr[STR_LEN];
706  char sql[STR_LEN];
707  int status;
708  rodsLong_t iVal;
709 
710  if ( logSQL_CML != 0 ) {
711  rodsLog( LOG_SQL, "cmlGetCurrentSeqVal S-Q-L 1 " );
712  }
713 
714  nextStr[0] = '\0';
715 
716  cllCurrentValueString( "R_ObjectID", nextStr, STR_LEN );
717  /* R_ObjectID is created in icatSysTables.sql as
718  the sequence item for objects */
719 
720 #ifdef ORA_ICAT
721  /* For Oracle, use the built-in one-row table */
722  snprintf( sql, STR_LEN, "select %s from DUAL", nextStr );
723 #else
724  /* Postgres can just get the next value without a table */
725  snprintf( sql, STR_LEN, "select %s", nextStr );
726 #endif
727 
728  std::vector<std::string> emptyBindVars;
729  status = cmlGetIntegerValueFromSql( sql, &iVal, emptyBindVars, icss );
730  if ( status < 0 ) {
732  "cmlGetCurrentSeqVal cmlGetIntegerValueFromSql failure %d",
733  status );
734  return status;
735  }
736  return iVal;
737 }
738 
739 int
740 cmlGetNextSeqStr( char *seqStr, int maxSeqStrLen, icatSessionStruct *icss ) {
741  char nextStr[STR_LEN];
742  char sql[STR_LEN];
743  int status;
744 
745  if ( logSQL_CML != 0 ) {
746  rodsLog( LOG_SQL, "cmlGetNextSeqStr SQL 1 " );
747  }
748 
749  nextStr[0] = '\0';
750  cllNextValueString( "R_ObjectID", nextStr, STR_LEN );
751  /* R_ObjectID is created in icatSysTables.sql as
752  the sequence item for objects */
753 
754 #ifdef ORA_ICAT
755  snprintf( sql, STR_LEN, "select %s from DUAL", nextStr );
756 #else
757  snprintf( sql, STR_LEN, "select %s", nextStr );
758 #endif
759 
760  std::vector<std::string> emptyBindVars;
761  status = cmlGetStringValueFromSql( sql, seqStr, maxSeqStrLen, emptyBindVars, icss );
762  if ( status < 0 ) {
764  "cmlGetNextSeqStr cmlGetStringValueFromSql failure %d", status );
765  }
766  return status;
767 }
768 
769 /* modifed for various tests */
771  int i, cValSize;
772  char *cVal[2];
773  char cValStr[MAX_INTEGER_SIZE + 10];
774  char sql[100];
775 
776  strncpy( icss->databaseUsername, "schroede", DB_USERNAME_LEN );
777  strncpy( icss->databasePassword, "", DB_PASSWORD_LEN );
778  i = cmlOpen( icss );
779  if ( i != 0 ) {
780  return i;
781  }
782 
783  cVal[0] = cValStr;
784  cValSize = MAX_INTEGER_SIZE;
785  snprintf( sql, sizeof sql,
786  "select coll_id from R_COLL_MAIN where coll_name='a'" );
787 
788  i = cmlGetOneRowFromSql( sql, cVal, &cValSize, 1, icss );
789  if ( i == 1 ) {
790  printf( "result = %s\n", cValStr );
791  i = 0;
792  }
793  else {
794  return i;
795  }
796 
797  snprintf( sql, sizeof sql,
798  "select data_id from R_DATA_MAIN where coll_id='1' and data_name='a'" );
799  i = cmlGetOneRowFromSql( sql, cVal, &cValSize, 1, icss );
800  if ( i == 1 ) {
801  printf( "result = %s\n", cValStr );
802  i = 0;
803  }
804 
806 
807  return i;
808 
809 }
810 
811 /*
812  Check that a resource exists and user has 'accessLevel' permission.
813  Return code is either an iRODS error code (< 0) or the collectionId.
814 */
816 cmlCheckResc( const char *rescName, const char *userName, const char *userZone, const char *accessLevel,
818  int status;
819  rodsLong_t iVal{};
820 
821  if ( logSQL_CML != 0 ) {
822  rodsLog( LOG_SQL, "cmlCheckResc SQL 1 " );
823  }
824 
825  std::vector<std::string> bindVars;
826  bindVars.push_back( rescName );
827  bindVars.push_back( userName );
828  bindVars.push_back( userZone );
829  bindVars.push_back( accessLevel );
831  "select resc_id from R_RESC_MAIN RM, R_OBJT_ACCESS OA, R_USER_GROUP UG, R_USER_MAIN UM, R_TOKN_MAIN TM where RM.resc_name=? and UM.user_name=? and UM.zone_name=? and UM.user_type_name!='rodsgroup' and UM.user_id = UG.user_id and OA.object_id = RM.resc_id and UG.group_user_id = OA.user_id and OA.access_type_id >= TM.token_id and TM.token_namespace ='access_type' and TM.token_name = ?",
832  &iVal, bindVars, icss );
833  if ( status ) {
834  /* There was an error, so do another sql to see which
835  of the two likely cases is problem. */
836 
837  if ( logSQL_CML != 0 ) {
838  rodsLog( LOG_SQL, "cmlCheckResc SQL 2 " );
839  }
840 
841  bindVars.clear();
842  bindVars.push_back( rescName );
844  "select resc_id from R_RESC_MAIN where resc_name=?",
845  &iVal, bindVars, icss );
846  if ( status ) {
847  return CAT_UNKNOWN_RESOURCE;
848  }
850  }
851 
852  return iVal;
853 
854 }
855 
856 
857 /*
858  Check that a collection exists and user has 'accessLevel' permission.
859  Return code is either an iRODS error code (< 0) or the collectionId.
860 */
862 cmlCheckDir( const char *dirName, const char *userName, const char *userZone, const char *accessLevel,
864  int status;
865  rodsLong_t iVal{};
866 
867  if ( logSQL_CML != 0 ) {
868  rodsLog( LOG_SQL, "cmlCheckDir SQL 1 " );
869  }
870 
871  std::vector<std::string> bindVars;
872  bindVars.push_back( dirName );
873  bindVars.push_back( userName );
874  bindVars.push_back( userZone );
875  bindVars.push_back( accessLevel );
877  "select coll_id from R_COLL_MAIN CM, R_OBJT_ACCESS OA, R_USER_GROUP UG, R_USER_MAIN UM, R_TOKN_MAIN TM where CM.coll_name=? and UM.user_name=? and UM.zone_name=? and UM.user_type_name!='rodsgroup' and UM.user_id = UG.user_id and OA.object_id = CM.coll_id and UG.group_user_id = OA.user_id and OA.access_type_id >= TM.token_id and TM.token_namespace ='access_type' and TM.token_name = ?",
878  &iVal, bindVars, icss );
879  if ( status ) {
880  /* There was an error, so do another sql to see which
881  of the two likely cases is problem. */
882 
883  if ( logSQL_CML != 0 ) {
884  rodsLog( LOG_SQL, "cmlCheckDir SQL 2 " );
885  }
886 
887  bindVars.clear();
888  bindVars.push_back( dirName );
890  "select coll_id from R_COLL_MAIN where coll_name=?",
891  &iVal, bindVars, icss );
892  if ( status ) {
893  return CAT_UNKNOWN_COLLECTION;
894  }
896  }
897 
898  return iVal;
899 
900 }
901 
902 
903 /*
904  Check that a collection exists and user has 'accessLevel' permission.
905  Return code is either an iRODS error code (< 0) or the collectionId.
906  While at it, get the inheritance flag.
907 */
909 cmlCheckDirAndGetInheritFlag( const char *dirName, const char *userName, const char *userZone,
910  const char *accessLevel, int *inheritFlag,
911  const char *ticketStr, const char *ticketHost,
913  int status;
914  rodsLong_t iVal = 0;
915 
916  int cValSize[2];
917  char *cVal[3];
918  char cValStr1[MAX_INTEGER_SIZE + 10];
919  char cValStr2[MAX_INTEGER_SIZE + 10];
920 
921  cVal[0] = cValStr1;
922  cVal[1] = cValStr2;
923  cValSize[0] = MAX_INTEGER_SIZE;
924  cValSize[1] = MAX_INTEGER_SIZE;
925 
926  *inheritFlag = 0;
927 
928  if ( ticketStr != NULL && *ticketStr != '\0' ) {
929  if ( logSQL_CML != 0 ) {
930  rodsLog( LOG_SQL, "cmlCheckDirAndGetInheritFlag SQL 1 " );
931  }
932  std::vector<std::string> bindVars;
933  bindVars.push_back( dirName );
934  bindVars.push_back( ticketStr );
935  status = cmlGetOneRowFromSqlBV( "select coll_id, coll_inheritance from R_COLL_MAIN CM, R_TICKET_MAIN TM where CM.coll_name=? and TM.ticket_string=? and TM.ticket_type = 'write' and TM.object_id = CM.coll_id",
936  cVal, cValSize, 2, bindVars, icss );
937  }
938  else {
939  if ( logSQL_CML != 0 ) {
940  rodsLog( LOG_SQL, "cmlCheckDirAndGetInheritFlag SQL 2 " );
941  }
942  std::vector<std::string> bindVars;
943  bindVars.push_back( dirName );
944  bindVars.push_back( userName );
945  bindVars.push_back( userZone );
946  bindVars.push_back( accessLevel );
947  status = cmlGetOneRowFromSqlBV( "select coll_id, coll_inheritance from R_COLL_MAIN CM, R_OBJT_ACCESS OA, R_USER_GROUP UG, R_USER_MAIN UM, R_TOKN_MAIN TM where CM.coll_name=? and UM.user_name=? and UM.zone_name=? and UM.user_type_name!='rodsgroup' and UM.user_id = UG.user_id and OA.object_id = CM.coll_id and UG.group_user_id = OA.user_id and OA.access_type_id >= TM.token_id and TM.token_namespace ='access_type' and TM.token_name = ?",
948  cVal, cValSize, 2, bindVars, icss );
949  }
950  if ( status == 2 ) {
951  if ( *cVal[0] == '\0' ) {
952  return CAT_NO_ROWS_FOUND;
953  }
954  iVal = strtoll( *cVal, NULL, 0 );
955  if ( cValStr2[0] == '1' ) {
956  *inheritFlag = 1;
957  }
958  status = 0;
959  }
960 
961  if ( status ) {
962  /* There was an error, so do another sql to see which
963  of the two likely cases is problem. */
964 
965  if ( logSQL_CML != 0 ) {
966  rodsLog( LOG_SQL, "cmlCheckDirAndGetInheritFlag SQL 3 " );
967  }
968 
969  std::vector<std::string> bindVars;
970  bindVars.push_back( dirName );
972  "select coll_id from R_COLL_MAIN where coll_name=?",
973  &iVal, bindVars, icss );
974  if ( status ) {
975  return CAT_UNKNOWN_COLLECTION;
976  }
978  }
979 
980  /*
981  Also check the other aspects ticket at this point.
982  */
983  if ( ticketStr != NULL && *ticketStr != '\0' ) {
984  status = checkObjIdByTicket( cValStr1, accessLevel, ticketStr,
985  ticketHost, userName, userZone,
986  icss );
987  if ( status != 0 ) {
988  return status;
989  }
990  }
991 
992  return iVal;
993 
994 }
995 
996 
997 /*
998  Check that a collection exists and user has 'accessLevel' permission.
999  Return code is either an iRODS error code (< 0) or the collectionId.
1000 */
1001 rodsLong_t
1002 cmlCheckDirId( const char *dirId, const char *userName, const char *userZone,
1003  const char *accessLevel, icatSessionStruct *icss ) {
1004  int status;
1005  rodsLong_t iVal;
1006 
1007  if ( logSQL_CML != 0 ) {
1008  rodsLog( LOG_SQL, "cmlCheckDirId S-Q-L 1 " );
1009  }
1010 
1011  std::vector<std::string> bindVars;
1012  bindVars.push_back( userName );
1013  bindVars.push_back( userZone );
1014  bindVars.push_back( dirId );
1015  bindVars.push_back( accessLevel );
1017  "select object_id from R_OBJT_ACCESS OA, R_USER_GROUP UG, R_USER_MAIN UM, R_TOKN_MAIN TM where UM.user_name=? and UM.zone_name=? and UM.user_type_name!='rodsgroup' and UM.user_id = UG.user_id and OA.object_id = ? and UG.group_user_id = OA.user_id and OA.access_type_id >= TM.token_id and TM.token_namespace ='access_type' and TM.token_name = ?",
1018  &iVal, bindVars, icss );
1019  if ( status ) {
1020  /* There was an error, so do another sql to see which
1021  of the two likely cases is problem. */
1022 
1023  if ( logSQL_CML != 0 ) {
1024  rodsLog( LOG_SQL, "cmlCheckDirId S-Q-L 2 " );
1025  }
1026 
1027  std::vector<std::string> bindVars;
1028  bindVars.push_back( dirId );
1030  "select coll_id from R_COLL_MAIN where coll_id=?",
1031  &iVal, bindVars, icss );
1032  if ( status ) {
1033  return CAT_UNKNOWN_COLLECTION;
1034  }
1035  return CAT_NO_ACCESS_PERMISSION;
1036  }
1037 
1038  return 0;
1039 }
1040 
1041 /*
1042  Check that a collection exists and user owns it
1043 */
1044 rodsLong_t
1045 cmlCheckDirOwn( const char *dirName, const char *userName, const char *userZone,
1046  icatSessionStruct *icss ) {
1047  int status;
1048  rodsLong_t iVal{};
1049 
1050  if ( logSQL_CML != 0 ) {
1051  rodsLog( LOG_SQL, "cmlCheckDirOwn SQL 1 " );
1052  }
1053 
1054  std::vector<std::string> bindVars;
1055  bindVars.push_back( dirName );
1056  bindVars.push_back( userName );
1057  bindVars.push_back( userZone );
1059  "select coll_id from R_COLL_MAIN where coll_name=? and coll_owner_name=? and coll_owner_zone=?",
1060  &iVal, bindVars, icss );
1061  if ( status < 0 ) {
1062  return status;
1063  }
1064  return iVal;
1065 }
1066 
1067 
1068 /*
1069  Check that a dataObj (iRODS file) exists and user has specified permission
1070  (but don't check the collection access, only its existance).
1071  Return code is either an iRODS error code (< 0) or the dataId.
1072 */
1073 rodsLong_t
1074 cmlCheckDataObjOnly( const char *dirName, const char *dataName,
1075  const char *userName, const char *userZone,
1076  const char *accessLevel, icatSessionStruct *icss ) {
1077  int status;
1078  rodsLong_t iVal{};
1079 
1080  if ( logSQL_CML != 0 ) {
1081  rodsLog( LOG_SQL, "cmlCheckDataObjOnly SQL 1 " );
1082  }
1083 
1084  std::vector<std::string> bindVars;
1085  bindVars.push_back( dataName );
1086  bindVars.push_back( dirName );
1087  bindVars.push_back( userName );
1088  bindVars.push_back( userZone );
1089  bindVars.push_back( accessLevel );
1091  "select data_id from R_DATA_MAIN DM, R_OBJT_ACCESS OA, R_USER_GROUP UG, R_USER_MAIN UM, R_TOKN_MAIN TM, R_COLL_MAIN CM where DM.data_name=? and DM.coll_id=CM.coll_id and CM.coll_name=? and UM.user_name=? and UM.zone_name=? and UM.user_type_name!='rodsgroup' and UM.user_id = UG.user_id and OA.object_id = DM.data_id and UG.group_user_id = OA.user_id and OA.access_type_id >= TM.token_id and TM.token_namespace ='access_type' and TM.token_name = ?",
1092  &iVal, bindVars, icss );
1093 
1094  if ( status ) {
1095  /* There was an error, so do another sql to see which
1096  of the two likely cases is problem. */
1097  if ( logSQL_CML != 0 ) {
1098  rodsLog( LOG_SQL, "cmlCheckDataObjOnly SQL 2 " );
1099  }
1100 
1101  bindVars.clear();
1102  bindVars.push_back( dataName );
1103  bindVars.push_back( dirName );
1105  "select data_id from R_DATA_MAIN DM, R_COLL_MAIN CM where DM.data_name=? and DM.coll_id=CM.coll_id and CM.coll_name=?",
1106  &iVal, bindVars, icss );
1107  if ( status ) {
1108  return CAT_UNKNOWN_FILE;
1109  }
1110  return CAT_NO_ACCESS_PERMISSION;
1111  }
1112 
1113  return iVal;
1114 
1115 }
1116 
1117 /*
1118  Check that a dataObj (iRODS file) exists and user owns it
1119 */
1120 rodsLong_t
1121 cmlCheckDataObjOwn( const char *dirName, const char *dataName, const char *userName,
1122  const char *userZone, icatSessionStruct *icss ) {
1123  int status;
1124  rodsLong_t iVal, collId;
1125  char collIdStr[MAX_NAME_LEN];
1126 
1127  if ( logSQL_CML != 0 ) {
1128  rodsLog( LOG_SQL, "cmlCheckDataObjOwn SQL 1 " );
1129  }
1130  std::vector<std::string> bindVars;
1131  bindVars.push_back( dirName );
1133  "select coll_id from R_COLL_MAIN where coll_name=?",
1134  &iVal, bindVars, icss );
1135  if ( status < 0 ) {
1136  return status;
1137  }
1138  collId = iVal;
1139  snprintf( collIdStr, MAX_NAME_LEN, "%lld", collId );
1140 
1141  if ( logSQL_CML != 0 ) {
1142  rodsLog( LOG_SQL, "cmlCheckDataObjOwn SQL 2 " );
1143  }
1144  bindVars.clear();
1145  bindVars.push_back( dataName );
1146  bindVars.push_back( collIdStr );
1147  bindVars.push_back( userName );
1148  bindVars.push_back( userZone );
1150  "select data_id from R_DATA_MAIN where data_name=? and coll_id=? and data_owner_name=? and data_owner_zone=?",
1151  &iVal, bindVars, icss );
1152 
1153  if ( status ) {
1154  return status;
1155  }
1156  return iVal;
1157 }
1158 
1159 
1160 int cmlCheckUserInGroup( const char *userName, const char *userZone,
1161  const char *groupName, icatSessionStruct *icss ) {
1162  int status;
1163  char sVal[MAX_NAME_LEN];
1164  rodsLong_t iVal;
1165 
1166  if ( logSQL_CML != 0 ) {
1167  rodsLog( LOG_SQL, "cmlCheckUserInGroup SQL 1 " );
1168  }
1169 
1170  std::vector<std::string> bindVars;
1171  bindVars.push_back( userName );
1172  bindVars.push_back( userZone );
1174  "select user_id from R_USER_MAIN where user_name=? and zone_name=? and user_type_name!='rodsgroup'",
1175  sVal, MAX_NAME_LEN, bindVars, icss );
1176  if ( status == CAT_NO_ROWS_FOUND ) {
1177  return CAT_INVALID_USER;
1178  }
1179  if ( status ) {
1180  return status;
1181  }
1182 
1183  if ( logSQL_CML != 0 ) {
1184  rodsLog( LOG_SQL, "cmlCheckUserInGroup SQL 2 " );
1185  }
1186 
1187  bindVars.clear();
1188  bindVars.push_back( sVal );
1189  bindVars.push_back( groupName );
1191  "select group_user_id from R_USER_GROUP where user_id=? and group_user_id = (select user_id from R_USER_MAIN where user_type_name='rodsgroup' and user_name=?)",
1192  &iVal, bindVars, icss );
1193  if ( status ) {
1194  return status;
1195  }
1196  return 0;
1197 }
1198 
1199 /* check on additional restrictions on a ticket, return error if not
1200  * allowed */
1201 int
1202 cmlCheckTicketRestrictions( const char *ticketId, const char *ticketHost,
1203  const char *userName, const char *userZone,
1204  icatSessionStruct *icss ) {
1205  int status;
1206  int stmtNum = UNINITIALIZED_STATEMENT_NUMBER;
1207  int hostOK = 0;
1208  int userOK = 0;
1209  int groupOK = 0;
1210 
1211  /* first, check if there are any host restrictions, and if so
1212  return error if the connected client host is not in the list */
1213  if ( logSQL_CML != 0 ) {
1214  rodsLog( LOG_SQL, "cmlCheckTicketRestrictions SQL 1" );
1215  }
1216  std::vector<std::string> bindVars;
1217  bindVars.push_back( ticketId );
1219  "select host from R_TICKET_ALLOWED_HOSTS where ticket_id=?",
1220  bindVars, &stmtNum, icss );
1221  if ( status == CAT_NO_ROWS_FOUND ) {
1222  hostOK = 1;
1223  }
1224  else {
1225  if ( status != 0 ) {
1226  cllFreeStatement(icss, stmtNum);
1227  return status;
1228  }
1229  }
1230 
1231  for ( ; status != CAT_NO_ROWS_FOUND; ) {
1232  if ( strncmp( ticketHost,
1233  icss->stmtPtr[stmtNum]->resultValue[0],
1234  NAME_LEN ) == 0 ) {
1235  hostOK = 1;
1236  }
1237  status = cmlGetNextRowFromStatement( stmtNum, icss );
1238  if ( status != 0 && status != CAT_NO_ROWS_FOUND ) {
1239  cllFreeStatement(icss, stmtNum);
1240  return status;
1241  }
1242  }
1243  if ( hostOK == 0 ) {
1244  cllFreeStatement(icss, stmtNum);
1245  return CAT_TICKET_HOST_EXCLUDED;
1246  }
1247  cllFreeStatement(icss, stmtNum);
1248 
1249  /* Now check on user restrictions */
1250  if ( logSQL_CML != 0 ) {
1251  rodsLog( LOG_SQL, "cmlCheckTicketRestrictions SQL 2" );
1252  }
1253  bindVars.clear();
1254  bindVars.push_back( ticketId );
1256  "select user_name from R_TICKET_ALLOWED_USERS where ticket_id=?",
1257  bindVars, &stmtNum, icss );
1258  if ( status == CAT_NO_ROWS_FOUND ) {
1259  cllFreeStatement(icss, stmtNum);
1260  userOK = 1;
1261  }
1262  else {
1263  if ( status != 0 ) {
1264  cllFreeStatement(icss, stmtNum);
1265  return status;
1266  }
1267  }
1268  std::string myUser( userName );
1269  myUser += "#";
1270  myUser += userZone;
1271  for ( ; status != CAT_NO_ROWS_FOUND; ) {
1272  if ( strncmp( userName,
1273  icss->stmtPtr[stmtNum]->resultValue[0],
1274  NAME_LEN ) == 0 ) {
1275  userOK = 1;
1276  }
1277  else {
1278  /* try user#zone */
1279  if ( strncmp( myUser.c_str(),
1280  icss->stmtPtr[stmtNum]->resultValue[0],
1281  NAME_LEN ) == 0 ) {
1282  userOK = 1;
1283  }
1284  }
1285  status = cmlGetNextRowFromStatement( stmtNum, icss );
1286  if ( status != 0 && status != CAT_NO_ROWS_FOUND ) {
1287  cllFreeStatement(icss, stmtNum);
1288  return status;
1289  }
1290  }
1291  if ( userOK == 0 ) {
1292  cllFreeStatement(icss, stmtNum);
1293  return CAT_TICKET_USER_EXCLUDED;
1294  }
1295  cllFreeStatement(icss, stmtNum);
1296 
1297  /* Now check on group restrictions */
1298  if ( logSQL_CML != 0 ) {
1299  rodsLog( LOG_SQL, "cmlCheckTicketRestrictions SQL 3" );
1300  }
1301  bindVars.clear();
1302  bindVars.push_back( ticketId );
1304  "select group_name from R_TICKET_ALLOWED_GROUPS where ticket_id=?",
1305  bindVars, &stmtNum, icss );
1306  if ( status == CAT_NO_ROWS_FOUND ) {
1307  groupOK = 1;
1308  }
1309  else {
1310  if ( status != 0 ) {
1311  cllFreeStatement(icss, stmtNum);
1312  return status;
1313  }
1314  }
1315  for ( ; status != CAT_NO_ROWS_FOUND; ) {
1316  int status2;
1317  status2 = cmlCheckUserInGroup( userName, userZone,
1318  icss->stmtPtr[stmtNum]->resultValue[0],
1319  icss );
1320  if ( status2 == 0 ) {
1321  groupOK = 1;
1322  }
1323  status = cmlGetNextRowFromStatement( stmtNum, icss );
1324  if ( status != 0 && status != CAT_NO_ROWS_FOUND ) {
1325  cllFreeStatement(icss, stmtNum);
1326  return status;
1327  }
1328  }
1329  if ( groupOK == 0 ) {
1330  cllFreeStatement(icss, stmtNum);
1332  }
1333  cllFreeStatement(icss, stmtNum);
1334  return 0;
1335 }
1336 
1337 /* Check access via a Ticket to a data-object or collection */
1338 int checkObjIdByTicket( const char *dataId, const char *accessLevel,
1339  const char *ticketStr, const char *ticketHost,
1340  const char *userName, const char *userZone,
1341  icatSessionStruct *icss ) {
1342 
1343  char original_collection_name[MAX_NAME_LEN];
1344  std::vector<std::string> bindVars;
1345  bindVars.push_back( dataId );
1346  int cml_error = cmlGetStringValueFromSql(
1347  "select coll_name from R_COLL_MAIN where coll_id in (select coll_id from R_DATA_MAIN where data_id=?)",
1348  original_collection_name, MAX_NAME_LEN, bindVars, icss );
1349  if(0 != cml_error) {
1350  rodsLog(
1351  LOG_ERROR,
1352  "failed to determine collection name for object id [%s]",
1353  dataId);
1354  return cml_error;
1355  }
1356 
1357  int status, i;
1358  char *cVal[10];
1359  int iVal[10];
1360  char ticketId[NAME_LEN] = "";
1361  char usesCount[NAME_LEN] = "";
1362  char usesLimit[NAME_LEN] = "";
1363  char ticketExpiry[NAME_LEN] = "";
1364  char restrictions[NAME_LEN] = "";
1365  char writeFileCount[NAME_LEN] = "";
1366  char writeFileLimit[NAME_LEN] = "";
1367  char writeByteCount[NAME_LEN] = "";
1368  char writeByteLimit[NAME_LEN] = "";
1369  int iUsesCount = 0;
1370  int iUsesLimit = 0;
1371  int iWriteFileCount = 0;
1372  int iWriteFileLimit = 0;
1373  int iWriteByteCount = 0;
1374  int iWriteByteLimit = 0;
1375  char myUsesCount[NAME_LEN];
1376  char myWriteFileCount[NAME_LEN];
1377  rodsLong_t intDataId;
1378  static rodsLong_t previousDataId1 = 0;
1379  static rodsLong_t previousDataId2 = 0;
1380 
1381  static char prevTicketId[50] = "";
1382 
1383  for ( i = 0; i < 10; i++ ) {
1384  iVal[i] = NAME_LEN;
1385  }
1386 
1387  cVal[0] = ticketId;
1388  cVal[1] = usesLimit;
1389  cVal[2] = usesCount;
1390  cVal[3] = ticketExpiry;
1391  cVal[4] = restrictions;
1392  if ( strncmp( accessLevel, "modify", 6 ) == 0 ) {
1393  if ( logSQL_CML != 0 ) {
1394  rodsLog( LOG_SQL, "checkObjIdByTicket SQL 1 " );
1395  }
1396  /* ticket must also be of type 'write', and get the
1397  writeFileCount and writeFileLimit */
1398  cVal[5] = writeFileCount;
1399  cVal[6] = writeFileLimit;
1400  cVal[7] = writeByteCount;
1401  cVal[8] = writeByteLimit;
1402  const std::string zone_path{boost::str(boost::format("/%s") % userZone)};
1403  boost::filesystem::path coll_path{original_collection_name};
1404  while(coll_path != zone_path) {
1405  std::vector<std::string> bindVars;
1406  bindVars.push_back( ticketStr );
1407  bindVars.push_back( dataId );
1408  bindVars.push_back( coll_path.string() );
1410  "select ticket_id, uses_limit, uses_count, ticket_expiry_ts, restrictions, write_file_count, write_file_limit, write_byte_count, write_byte_limit from R_TICKET_MAIN where ticket_type = 'write' and ticket_string = ? and (object_id = ? or object_id in (select coll_id from R_COLL_MAIN where coll_name = ?))",
1411  cVal, iVal, 9, bindVars, icss );
1412  if(0 == status) {
1413  break;
1414  }
1415 
1416  coll_path = coll_path.parent_path();
1417  }
1418  }
1419  else {
1420  /* don't check ticket type, 'read' or 'write' is fine */
1421  if ( logSQL_CML != 0 ) {
1422  rodsLog( LOG_SQL, "checkObjIdByTicket SQL 2 " );
1423  }
1424 
1425  const std::string zone_path{boost::str(boost::format("/%s") % userZone)};
1426  boost::filesystem::path coll_path{original_collection_name};
1427  while(coll_path != zone_path) {
1428  std::vector<std::string> bindVars;
1429  bindVars.push_back( ticketStr );
1430  bindVars.push_back( dataId );
1431  bindVars.push_back( coll_path.string() );
1433  "select ticket_id, uses_limit, uses_count, ticket_expiry_ts, restrictions from R_TICKET_MAIN where ticket_string = ? and (object_id = ? or object_id in (select coll_id from R_COLL_MAIN where coll_name = ?))",
1434  cVal, iVal, 5, bindVars, icss );
1435  if(0 == status) {
1436  break;
1437  }
1438 
1439  coll_path = coll_path.parent_path();
1440  }
1441  }
1442 
1443  if ( status != 0 ) {
1444  return CAT_TICKET_INVALID;
1445  }
1446 
1447  if ( strncmp( ticketId, prevTicketId, sizeof( prevTicketId ) ) != 0 ) {
1448  snprintf( prevTicketId, sizeof( prevTicketId ), "%s", ticketId );
1449  status = cmlAudit3( AU_USE_TICKET, ticketId, userName, userZone,
1450  ticketStr, icss );
1451  if ( status != 0 ) {
1452  return status;
1453  }
1454  }
1455 
1456  if ( ticketExpiry[0] != '\0' ) {
1457  rodsLong_t ticketExp, now;
1458  char myTime[50];
1459 
1460  ticketExp = atoll( ticketExpiry );
1461  if ( ticketExp > 0 ) {
1462  getNowStr( myTime );
1463  now = atoll( myTime );
1464  if ( now > ticketExp ) {
1465  return CAT_TICKET_EXPIRED;
1466  }
1467  }
1468  }
1469 
1470  status = cmlCheckTicketRestrictions( ticketId, ticketHost,
1471  userName, userZone, icss );
1472  if ( status != 0 ) {
1473  return status;
1474  }
1475 
1476  if ( strncmp( accessLevel, "modify", 6 ) == 0 ) {
1477  iWriteByteLimit = atoi( writeByteLimit );
1478  if ( iWriteByteLimit > 0 ) {
1479  iWriteByteCount = atoi( writeByteCount );
1480  if ( iWriteByteCount > iWriteByteLimit ) {
1482  }
1483  }
1484 
1485  iWriteFileLimit = atoi( writeFileLimit );
1486  if ( iWriteFileLimit > 0 ) {
1487  iWriteFileCount = atoi( writeFileCount );
1488  if ( iWriteFileCount > iWriteFileLimit ) {
1490  }
1491  intDataId = atoll( dataId );
1492  /* Don't update a second time if this id matches the last one */
1493  if ( previousDataId1 != intDataId ) {
1494  iWriteFileCount++;
1495  snprintf( myWriteFileCount, sizeof myWriteFileCount, "%d",
1496  iWriteFileCount );
1497  cllBindVars[cllBindVarCount++] = myWriteFileCount;
1498  cllBindVars[cllBindVarCount++] = ticketId;
1499  if ( logSQL_CML != 0 ) {
1500  rodsLog( LOG_SQL, "checkObjIdByTicket SQL 3 " );
1501  }
1503  "update R_TICKET_MAIN set write_file_count=? where ticket_id=?",
1504  icss );
1505  if ( status != 0 ) {
1506  return status;
1507  }
1508 #ifndef ORA_ICAT
1509  /* as with auditing, do a commit on disconnect if needed */
1510  cllCheckPending( "", 2, icss->databaseType );
1511 #endif
1512  }
1513  previousDataId1 = intDataId;
1514  }
1515  }
1516 
1517  iUsesLimit = atoi( usesLimit );
1518  if ( iUsesLimit > 0 ) {
1519  iUsesCount = atoi( usesCount );
1520  if ( iUsesCount > iUsesLimit ) {
1521  return CAT_TICKET_USES_EXCEEDED;
1522  }
1523  intDataId = atoll( dataId );
1524  /* Don't update a second time if this id matches the last one */
1525  if ( previousDataId2 != intDataId ) {
1526  iUsesCount++;
1527  snprintf( myUsesCount, sizeof myUsesCount, "%d", iUsesCount );
1528  cllBindVars[cllBindVarCount++] = myUsesCount;
1529  cllBindVars[cllBindVarCount++] = ticketId;
1530  if ( logSQL_CML != 0 ) {
1531  rodsLog( LOG_SQL, "checkObjIdByTicket SQL 4 " );
1532  }
1534  "update R_TICKET_MAIN set uses_count=? where ticket_id=?", icss );
1535  if ( status != 0 ) {
1536  return status;
1537  }
1538 #ifndef ORA_ICAT
1539  /* as with auditing, do a commit on disconnect if needed*/
1540  cllCheckPending( "", 2, icss->databaseType );
1541 #endif
1542  }
1543  previousDataId2 = intDataId;
1544  }
1545  return 0;
1546 }
1547 
1548 int
1549 cmlTicketUpdateWriteBytes( const char *ticketStr,
1550  const char *dataSize, const char *objectId,
1551  icatSessionStruct *icss ) {
1552 
1553  char original_collection_name[MAX_NAME_LEN];
1554  std::vector<std::string> bindVars;
1555  bindVars.push_back( objectId );
1556  int cml_error = cmlGetStringValueFromSql(
1557  "select coll_name from R_COLL_MAIN where coll_id in (select coll_id from R_DATA_MAIN where data_id=?)",
1558  original_collection_name, MAX_NAME_LEN, bindVars, icss );
1559  if(0 != cml_error) {
1560  rodsLog(
1561  LOG_ERROR,
1562  "failed to determine collection name for object id [%s]",
1563  objectId);
1564  return cml_error;
1565  }
1566 
1567  int status, i;
1568  char *cVal[10];
1569  int iVal[10];
1570  char ticketId[NAME_LEN] = "";
1571  char writeByteCount[NAME_LEN] = "";
1572  char writeByteLimit[NAME_LEN] = "";
1573  rodsLong_t iWriteByteCount = 0;
1574  rodsLong_t iWriteByteLimit = 0;
1575  rodsLong_t iDataSize;
1576  char myWriteByteCount[NAME_LEN];
1577  rodsLong_t iNewByteCount;
1578 
1579  iDataSize = atoll( dataSize );
1580  if ( iDataSize == 0 ) {
1581  return 0;
1582  }
1583 
1584  for ( i = 0; i < 10; i++ ) {
1585  iVal[i] = NAME_LEN;
1586  }
1587 
1588  cVal[0] = ticketId;
1589  cVal[1] = writeByteCount;
1590  cVal[2] = writeByteLimit;
1591 
1592  if ( logSQL_CML != 0 ) {
1593  rodsLog( LOG_SQL, "cmlTicketUpdateWriteBytes SQL 1 " );
1594  }
1595 
1596  boost::filesystem::path coll_path{original_collection_name};
1597  while(coll_path != irods::get_virtual_path_separator()) {
1598  std::vector<std::string> bindVars;
1599  bindVars.push_back( ticketStr );
1600  bindVars.push_back( objectId );
1601  bindVars.push_back( objectId );
1603  "select ticket_id, write_byte_count, write_byte_limit from R_TICKET_MAIN where ticket_type = 'write' and ticket_string = ? and (object_id = ? or object_id in (select coll_id from R_DATA_MAIN where data_id = ?))",
1604  cVal, iVal, 3, bindVars, icss );
1605  if(0 == status) {
1606  break;
1607  }
1608 
1609  coll_path = coll_path.parent_path();
1610  }
1611 
1612  if ( status != 0 ) {
1613  return status;
1614  }
1615  iWriteByteLimit = atoll( writeByteLimit );
1616  iWriteByteCount = atoll( writeByteCount );
1617 
1618  if ( iWriteByteLimit == 0 ) {
1619  return 0;
1620  }
1621 
1622  iNewByteCount = iWriteByteCount + iDataSize;
1623  snprintf( myWriteByteCount, sizeof myWriteByteCount, "%lld", iNewByteCount );
1624  cllBindVars[cllBindVarCount++] = myWriteByteCount;
1625  cllBindVars[cllBindVarCount++] = ticketId;
1626  if ( logSQL_CML != 0 ) {
1627  rodsLog( LOG_SQL, "cmlTicketUpdateWriteBytes SQL 2 " );
1628  }
1630  "update R_TICKET_MAIN set write_byte_count=? where ticket_id=?", icss );
1631  if ( status != 0 ) {
1632  return status;
1633  }
1634 #ifndef ORA_ICAT
1635  /* as with auditing, do a commit on disconnect if needed */
1636  cllCheckPending( "", 2, icss->databaseType );
1637 #endif
1638  return 0;
1639 }
1640 
1641 
1642 /*
1643  Check that a user has the specified permission or better to a dataObj.
1644  Return value is either an iRODS error code (< 0) or success (0).
1645  TicketStr is an optional ticket for ticket-based access,
1646  TicketHost is an optional host (the connected client IP) for ticket checks.
1647 */
1648 int cmlCheckDataObjId( const char *dataId, const char *userName, const char *zoneName,
1649  const char *accessLevel, const char *ticketStr, const char *ticketHost,
1650  icatSessionStruct *icss ) {
1651  int status;
1652  rodsLong_t iVal;
1653 
1654  iVal = 0;
1655  if ( ticketStr != NULL && *ticketStr != '\0' ) {
1656  status = checkObjIdByTicket( dataId, accessLevel, ticketStr,
1657  ticketHost, userName, zoneName,
1658  icss );
1659  if ( status != 0 ) {
1660  return status;
1661  }
1662  }
1663  else {
1664  if ( logSQL_CML != 0 ) {
1665  rodsLog( LOG_SQL, "cmlCheckDataObjId SQL 1 " );
1666  }
1667  std::vector<std::string> bindVars;
1668  bindVars.push_back( dataId );
1669  bindVars.push_back( userName );
1670  bindVars.push_back( zoneName );
1671  bindVars.push_back( accessLevel );
1673  "select object_id from R_OBJT_ACCESS OA, R_DATA_MAIN DM, R_USER_GROUP UG, R_USER_MAIN UM, R_TOKN_MAIN TM where OA.object_id=? and UM.user_name=? and UM.zone_name=? and UM.user_type_name!='rodsgroup' and UM.user_id = UG.user_id and OA.object_id = DM.data_id and UG.group_user_id = OA.user_id and OA.access_type_id >= TM.token_id and TM.token_namespace ='access_type' and TM.token_name = ?",
1674  &iVal,
1675  bindVars,
1676  icss );
1677  if ( iVal == 0 ) {
1678  return CAT_NO_ACCESS_PERMISSION;
1679  }
1680  }
1681  if ( status != 0 ) {
1682  return CAT_NO_ACCESS_PERMISSION;
1683  }
1684  cmlAudit2( AU_ACCESS_GRANTED, dataId, userName, zoneName, accessLevel, icss );
1685  return status;
1686 }
1687 
1688 /*
1689  * Check that the user has group-admin permission. The user must be of
1690  * type 'groupadmin' and in some cases a member of the specified group.
1691  */
1692 int cmlCheckGroupAdminAccess( const char *userName, const char *userZone,
1693  const char *groupName, icatSessionStruct *icss ) {
1694  int status;
1695  char sVal[MAX_NAME_LEN];
1696  rodsLong_t iVal;
1697 
1698  if ( logSQL_CML != 0 ) {
1699  rodsLog( LOG_SQL, "cmlCheckGroupAdminAccess SQL 1 " );
1700  }
1701 
1702  std::vector<std::string> bindVars;
1703  bindVars.push_back( userName );
1704  bindVars.push_back( userZone );
1706  "select user_id from R_USER_MAIN where user_name=? and zone_name=? and user_type_name='groupadmin'",
1707  sVal, MAX_NAME_LEN, bindVars, icss );
1708  if ( status == CAT_NO_ROWS_FOUND ) {
1710  }
1711  if ( status ) {
1712  return status;
1713  }
1714 
1715  // =-=-=-=-=-=-=-
1716  // JMC - backport 4772
1717  if ( groupName == NULL ) {
1719  }
1720  if ( *groupName == '\0' ) {
1721  return ( 0 ); /* caller is requesting no check for a particular group,
1722  so if the above check passed, the user is OK */
1723  }
1724  // =-=-=-=-=-=-=-
1725  if ( logSQL_CML != 0 ) {
1726  rodsLog( LOG_SQL, "cmlCheckGroupAdminAccess SQL 2 " );
1727  }
1728 
1729  bindVars.clear();
1730  bindVars.push_back( sVal );
1731  bindVars.push_back( groupName );
1733  "select group_user_id from R_USER_GROUP where user_id=? and group_user_id = (select user_id from R_USER_MAIN where user_type_name='rodsgroup' and user_name=?)",
1734  &iVal, bindVars, icss );
1735  if ( status == CAT_NO_ROWS_FOUND ) {
1737  }
1738  if ( status ) {
1739  return status;
1740  }
1741  return 0;
1742 }
1743 
1744 /*
1745  Get the number of users who are members of a user group.
1746  This is used in some groupadmin access checks.
1747  */
1748 int cmlGetGroupMemberCount( const char *groupName, icatSessionStruct *icss ) {
1749 
1750  rodsLong_t iVal;
1751  int status;
1752  std::vector<std::string> bindVars;
1753  bindVars.push_back( groupName );
1755  "select count(user_id) from R_USER_GROUP where group_user_id != user_id and group_user_id in (select user_id from R_USER_MAIN where user_name=? and user_type_name='rodsgroup')",
1756  &iVal, bindVars, icss );
1757  if ( status == 0 ) {
1758  status = iVal;
1759  }
1760  return status;
1761 }
1762 
1763 
1764 
1765 
1771 /*
1772  Audit - record auditing information, form 1
1773  */
1774 int
1775 cmlAudit1( int actionId, const char *clientUser, const char *zone, const char *targetUser,
1776  const char *comment, icatSessionStruct *icss ) {
1777  char myTime[50];
1778  char actionIdStr[50];
1779  int status;
1780 
1781  if ( auditEnabled == 0 ) {
1782  return 0;
1783  }
1784 
1785  if ( logSQL_CML != 0 ) {
1786  rodsLog( LOG_SQL, "cmlAudit1 SQL 1 " );
1787  }
1788 
1789  getNowStr( myTime );
1790 
1791  snprintf( actionIdStr, sizeof actionIdStr, "%d", actionId );
1792 
1793  cllBindVars[0] = targetUser;
1794  cllBindVars[1] = zone;
1795  cllBindVars[2] = clientUser;
1796  cllBindVars[3] = zone;
1797  cllBindVars[4] = actionIdStr;
1798  cllBindVars[5] = comment;
1799  cllBindVars[6] = myTime;
1800  cllBindVars[7] = myTime;
1801  cllBindVarCount = 8;
1802 
1804  "insert into R_OBJT_AUDIT (object_id, user_id, action_id, r_comment, create_ts, modify_ts) values ((select user_id from R_USER_MAIN where user_name=? and zone_name=?), (select user_id from R_USER_MAIN where user_name=? and zone_name=?), ?, ?, ?, ?)", icss );
1805  if ( status != 0 ) {
1806  rodsLog( LOG_NOTICE, "cmlAudit1 insert failure %d", status );
1807  }
1808 #ifdef ORA_ICAT
1809 #else
1810  else {
1811  cllCheckPending( "", 2, icss->databaseType );
1812  /* Indicate that this was an audit SQL and so should be
1813  committed on disconnect if still pending. */
1814  }
1815 #endif
1816  return status;
1817 }
1818 
1819 int
1820 cmlAudit2( int actionId, const char *dataId, const char *userName, const char *zoneName,
1821  const char *accessLevel, icatSessionStruct *icss ) {
1822  char myTime[50];
1823  char actionIdStr[50];
1824  int status;
1825 
1826  if ( auditEnabled == 0 ) {
1827  return 0;
1828  }
1829 
1830  if ( logSQL_CML != 0 ) {
1831  rodsLog( LOG_SQL, "cmlAudit2 SQL 1 " );
1832  }
1833 
1834  getNowStr( myTime );
1835 
1836  snprintf( actionIdStr, sizeof actionIdStr, "%d", actionId );
1837 
1838  cllBindVars[0] = dataId;
1839  cllBindVars[1] = userName;
1840  cllBindVars[2] = zoneName;
1841  cllBindVars[3] = actionIdStr;
1842  cllBindVars[4] = accessLevel;
1843  cllBindVars[5] = myTime;
1844  cllBindVars[6] = myTime;
1845  cllBindVarCount = 7;
1846 
1848  "insert into R_OBJT_AUDIT (object_id, user_id, action_id, r_comment, create_ts, modify_ts) values (?, (select user_id from R_USER_MAIN where user_name=? and zone_name=?), ?, ?, ?, ?)", icss );
1849  if ( status != 0 ) {
1850  rodsLog( LOG_NOTICE, "cmlAudit2 insert failure %d", status );
1851  }
1852 #ifdef ORA_ICAT
1853 #else
1854  else {
1855  cllCheckPending( "", 2, icss->databaseType );
1856  /* Indicate that this was an audit SQL and so should be
1857  committed on disconnect if still pending. */
1858  }
1859 #endif
1860 
1861  return status;
1862 }
1863 
1864 
1865 int
1866 cmlAudit3( int actionId, const char *dataId, const char *userName, const char *zoneName,
1867  const char *comment, icatSessionStruct *icss ) {
1868  char myTime[50];
1869  char actionIdStr[50];
1870  int status;
1871  char myComment[AUDIT_COMMENT_MAX_SIZE + 10];
1872 
1873  if ( auditEnabled == 0 ) {
1874  return 0;
1875  }
1876 
1877  getNowStr( myTime );
1878 
1879  snprintf( actionIdStr, sizeof actionIdStr, "%d", actionId );
1880 
1881  /* Truncate the comment if necessary (or else SQL will fail)*/
1882  myComment[AUDIT_COMMENT_MAX_SIZE - 1] = '\0';
1883  strncpy( myComment, comment, AUDIT_COMMENT_MAX_SIZE - 1 );
1884 
1885  if ( zoneName[0] == '\0' ) {
1886  /* This no longer seems to occur. I'm leaving the code in place
1887  (just in case) but I'm removing the rodsLog call so the ICAT
1888  test suite does not require it to be tested.
1889  */
1890  /* if (logSQL_CML!=0) rodsLog(LOG_SQL, "cmlAu---dit3 S--QL 1 "); */
1891  cllBindVars[0] = dataId;
1892  cllBindVars[1] = userName;
1893  cllBindVars[2] = actionIdStr;
1894  cllBindVars[3] = myComment;
1895  cllBindVars[4] = myTime;
1896  cllBindVars[5] = myTime;
1897  cllBindVarCount = 6;
1899  "insert into R_OBJT_AUDIT (object_id, user_id, action_id, r_comment, create_ts, modify_ts) values (?, (select user_id from R_USER_MAIN where user_name=? and zone_name=(select zone_name from R_ZONE_MAIN where zone_type_name='local')), ?, ?, ?, ?)", icss );
1900  }
1901  else {
1902  if ( logSQL_CML != 0 ) {
1903  rodsLog( LOG_SQL, "cmlAudit3 SQL 2 " );
1904  }
1905  cllBindVars[0] = dataId;
1906  cllBindVars[1] = userName;
1907  cllBindVars[2] = zoneName;
1908  cllBindVars[3] = actionIdStr;
1909  cllBindVars[4] = myComment;
1910  cllBindVars[5] = myTime;
1911  cllBindVars[6] = myTime;
1912  cllBindVarCount = 7;
1914  "insert into R_OBJT_AUDIT (object_id, user_id, action_id, r_comment, create_ts, modify_ts) values (?, (select user_id from R_USER_MAIN where user_name=? and zone_name=?), ?, ?, ?, ?)", icss );
1915  }
1916 
1917  if ( status != 0 ) {
1918  rodsLog( LOG_NOTICE, "cmlAudit3 insert failure %d", status );
1919  }
1920 #ifdef ORA_ICAT
1921 #else
1922  else {
1923  cllCheckPending( "", 2, icss->databaseType );
1924  /* Indicate that this was an audit SQL and so should be
1925  committed on disconnect if still pending. */
1926  }
1927 #endif
1928 
1929  return status;
1930 }
1931 
1932 
1933 int
1934 cmlAudit4( int actionId, const char *sql, const char *sqlParm, const char *userName,
1935  const char *zoneName, const char *comment, icatSessionStruct *icss ) {
1936  char myTime[50];
1937  char actionIdStr[50];
1938  char myComment[AUDIT_COMMENT_MAX_SIZE + 10];
1939  char mySQL[MAX_SQL_SIZE];
1940  int status;
1941  int i;
1942 
1943  if ( auditEnabled == 0 ) {
1944  return 0;
1945  }
1946 
1947  getNowStr( myTime );
1948 
1949  snprintf( actionIdStr, sizeof actionIdStr, "%d", actionId );
1950 
1951  /* Truncate the comment if necessary (or else SQL will fail)*/
1952  myComment[AUDIT_COMMENT_MAX_SIZE - 1] = '\0';
1953  strncpy( myComment, comment, AUDIT_COMMENT_MAX_SIZE - 1 );
1954 
1955  if ( zoneName[0] == '\0' ) {
1956  /* This no longer seems to occur. I'm leaving the code in place
1957  (just in case) but I'm removing the rodsLog call so the ICAT
1958  test suite does not require it to be tested.
1959  */
1960  /*
1961  if (logSQL_CML!=0) rodsLog(LOG_SQL, "cmlA---udit4 S--QL 1 ");
1962  */
1963  snprintf( mySQL, MAX_SQL_SIZE,
1964  "insert into R_OBJT_AUDIT (object_id, user_id, action_id, r_comment, create_ts, modify_ts) values ((%s), (select user_id from R_USER_MAIN where user_name=? and zone_name=(select zone_name from R_ZONE_MAIN where zone_type_name='local')), ?, ?, ?, ?)",
1965  sql );
1966  i = 0;
1967  if ( sqlParm[0] != '\0' ) {
1968  cllBindVars[i++] = sqlParm;
1969  }
1970  cllBindVars[i++] = userName;
1971  cllBindVars[i++] = actionIdStr;
1972  cllBindVars[i++] = myComment;
1973  cllBindVars[i++] = myTime;
1974  cllBindVars[i++] = myTime;
1975  cllBindVarCount = i;
1976  status = cmlExecuteNoAnswerSql( mySQL, icss );
1977  }
1978  else {
1979  if ( logSQL_CML != 0 ) {
1980  rodsLog( LOG_SQL, "cmlAudit4 SQL 2 " );
1981  }
1982  snprintf( mySQL, MAX_SQL_SIZE,
1983  "insert into R_OBJT_AUDIT (object_id, user_id, action_id, r_comment, create_ts, modify_ts) values ((%s), (select user_id from R_USER_MAIN where user_name=? and zone_name=?), ?, ?, ?, ?)",
1984  sql );
1985  i = 0;
1986  if ( sqlParm[0] != '\0' ) {
1987  cllBindVars[i++] = sqlParm;
1988  }
1989  cllBindVars[i++] = userName;
1990  cllBindVars[i++] = zoneName;
1991  cllBindVars[i++] = actionIdStr;
1992  cllBindVars[i++] = myComment;
1993  cllBindVars[i++] = myTime;
1994  cllBindVars[i++] = myTime;
1995  cllBindVarCount = i;
1996  status = cmlExecuteNoAnswerSql( mySQL, icss );
1997  }
1998 
1999  if ( status != 0 ) {
2000  rodsLog( LOG_NOTICE, "cmlAudit4 insert failure %d", status );
2001  }
2002 #ifdef ORA_ICAT
2003 #else
2004  else {
2005  cllCheckPending( "", 2, icss->databaseType );
2006  /* Indicate that this was an audit SQL and so should be
2007  committed on disconnect if still pending. */
2008  }
2009 #endif
2010 
2011  return status;
2012 }
2013 
2014 
2015 /*
2016  Audit - record auditing information
2017  */
2018 int
2019 cmlAudit5( int actionId, const char *objId, const char *userId, const char *comment,
2020  icatSessionStruct *icss ) {
2021  char myTime[50];
2022  char actionIdStr[50];
2023  int status;
2024 
2025  if ( auditEnabled == 0 ) {
2026  return 0;
2027  }
2028 
2029  getNowStr( myTime );
2030 
2031  snprintf( actionIdStr, sizeof actionIdStr, "%d", actionId );
2032 
2033  cllBindVars[0] = objId;
2034  cllBindVars[1] = userId;
2035  cllBindVars[2] = actionIdStr;
2036  cllBindVars[3] = comment;
2037  cllBindVars[4] = myTime;
2038  cllBindVars[5] = myTime;
2039  cllBindVarCount = 6;
2040 
2042  "insert into R_OBJT_AUDIT (object_id, user_id, action_id, r_comment, create_ts, modify_ts) values (?,?,?,?,?,?)",
2043  icss );
2044  if ( status != 0 ) {
2045  rodsLog( LOG_NOTICE, "cmlAudit5 insert failure %d", status );
2046  }
2047 #ifdef ORA_ICAT
2048 #else
2049  else {
2050  cllCheckPending( "", 2, icss->databaseType );
2051  /* Indicate that this was an audit SQL and so should be
2052  committed on disconnect if still pending. */
2053  }
2054 #endif
2055  return status;
2056 }
rodsLog
void rodsLog(int level, const char *formatStr,...)
Definition: rodsLog.cpp:86
cmlGetIntegerValueFromSql
int cmlGetIntegerValueFromSql(const char *sql, rodsLong_t *iVal, std::vector< std::string > &bindVars, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:573
NULL
#define NULL
Definition: rodsDef.h:70
rstrcat
char * rstrcat(char *dest, const char *src, int maxLen)
Definition: stringOpr.cpp:75
irods.pyparsing.tableName
def tableName
Definition: pyparsing.py:3817
cmlCheckUserInGroup
int cmlCheckUserInGroup(const char *userName, const char *userZone, const char *groupName, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:1160
cmlGetOneRowFromSql
int cmlGetOneRowFromSql(const char *sql, char *cVal[], int cValSize[], int numOfCols, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:216
CAT_TICKET_USER_EXCLUDED
@ CAT_TICKET_USER_EXCLUDED
Definition: rodsErrorTable.h:481
cmlTicketUpdateWriteBytes
int cmlTicketUpdateWriteBytes(const char *ticketStr, const char *dataSize, const char *objectId, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:1549
cmlGetOneRowFromSqlV2
int cmlGetOneRowFromSqlV2(const char *sql, char *cVal[], int maxCols, std::vector< std::string > &bindVars, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:270
cmlAudit1
int cmlAudit1(int actionId, const char *clientUser, const char *zone, const char *targetUser, const char *comment, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:1775
CAT_NO_ACCESS_PERMISSION
@ CAT_NO_ACCESS_PERMISSION
Definition: rodsErrorTable.h:433
cllExecSqlNoResult
int cllExecSqlNoResult(icatSessionStruct *icss, const char *sql)
Definition: low_level_odbc.cpp:373
checkObjIdByTicket
int checkObjIdByTicket(const char *dataId, const char *accessLevel, const char *ticketStr, const char *ticketHost, const char *userName, const char *userZone, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:1338
cmlCheckGroupAdminAccess
int cmlCheckGroupAdminAccess(const char *userName, const char *userZone, const char *groupName, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:1692
cmlClose
int cmlClose(icatSessionStruct *icss)
Definition: mid_level_routines.cpp:127
irods_stacktrace.hpp
cmlGetStringValuesFromSql
int cmlGetStringValuesFromSql(const char *sql, char *cVal[], int cValSize[], int numberOfStringsToGet, std::vector< std::string > &bindVars, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:498
cmlGetMultiRowStringValuesFromSql
int cmlGetMultiRowStringValuesFromSql(const char *sql, char *returnedStrings, int maxStringLen, int maxNumberOfStringsToGet, std::vector< std::string > &bindVars, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:516
cllCheckPending
int cllCheckPending(const char *sql, int option, int dbType)
Definition: low_level_odbc.cpp:250
CAT_CLOSE_ENV_ERR
@ CAT_CLOSE_ENV_ERR
Definition: rodsErrorTable.h:420
cmlTest
int cmlTest(icatSessionStruct *icss)
Definition: mid_level_routines.cpp:770
cllCloseEnv
int cllCloseEnv(icatSessionStruct *icss)
Definition: low_level_odbc.cpp:152
DB_USERNAME_LEN
#define DB_USERNAME_LEN
Definition: icatDefines.h:21
cllCurrentValueString
int cllCurrentValueString(const char *itemName, char *outString, int maxSize)
Definition: low_level_odbc.cpp:958
cmlArraysToStrWithBind
char * cmlArraysToStrWithBind(char *str, const char *preStr, const char *arr[], const char *arr2[], int arrLen, const char *sep, const char *sep2, int maxLen)
Definition: mid_level_routines.cpp:48
cmlCheckResc
rodsLong_t cmlCheckResc(const char *rescName, const char *userName, const char *userZone, const char *accessLevel, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:816
MAX_INTEGER_SIZE
#define MAX_INTEGER_SIZE
Definition: icatDefines.h:19
rcMisc.h
auditEnabled
int auditEnabled
Definition: icatHighLevelRoutines.cpp:42
cmlGetOneRowFromSqlV3
static int cmlGetOneRowFromSqlV3(const char *sql, char *cVal[], int cValSize[], int numOfCols, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:323
AU_USE_TICKET
#define AU_USE_TICKET
Definition: icatDefines.h:139
cmlCheckDataObjId
int cmlCheckDataObjId(const char *dataId, const char *userName, const char *zoneName, const char *accessLevel, const char *ticketStr, const char *ticketHost, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:1648
cllBindVarCount
int cllBindVarCount
Definition: low_level_odbc.cpp:47
CAT_TICKET_WRITE_USES_EXCEEDED
@ CAT_TICKET_WRITE_USES_EXCEEDED
Definition: rodsErrorTable.h:484
getNowStr
void getNowStr(char *timeStr)
Definition: rcMisc.cpp:1590
cmlOpen
int cmlOpen(icatSessionStruct *icss)
Definition: mid_level_routines.cpp:91
icatSessionStruct::databaseUsername
char databaseUsername[64]
Definition: icatStructs.hpp:31
LOG_ERROR
#define LOG_ERROR
Definition: rodsLog.h:43
cmlCheckDir
rodsLong_t cmlCheckDir(const char *dirName, const char *userName, const char *userZone, const char *accessLevel, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:862
cllOpenEnv
int cllOpenEnv(icatSessionStruct *icss)
Definition: low_level_odbc.cpp:135
CAT_GET_ROW_ERR
@ CAT_GET_ROW_ERR
Definition: rodsErrorTable.h:422
cllDisconnect
int cllDisconnect(icatSessionStruct *icss)
Definition: low_level_odbc.cpp:340
AUDIT_COMMENT_MAX_SIZE
#define AUDIT_COMMENT_MAX_SIZE
Definition: mid_level_routines.cpp:31
CAT_UNKNOWN_COLLECTION
@ CAT_UNKNOWN_COLLECTION
Definition: rodsErrorTable.h:429
cllFreeStatement
int cllFreeStatement(icatSessionStruct *icss, int &statementNumber)
Definition: low_level_odbc.cpp:974
cllGetRow
int cllGetRow(icatSessionStruct *icss, int statementNumber)
Definition: low_level_odbc.cpp:905
cmlGetNextRowFromStatement
int cmlGetNextRowFromStatement(int stmtNum, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:459
CAT_INSUFFICIENT_PRIVILEGE_LEVEL
@ CAT_INSUFFICIENT_PRIVILEGE_LEVEL
Definition: rodsErrorTable.h:445
cllNextValueString
int cllNextValueString(const char *itemName, char *outString, int maxSize)
Definition: low_level_odbc.cpp:928
irods::get_virtual_path_separator
std::string get_virtual_path_separator()
Definition: irods_virtual_path.cpp:11
logSQL_CML
int logSQL_CML
Definition: icatHighLevelRoutines.cpp:41
CAT_TICKET_WRITE_BYTES_EXCEEDED
@ CAT_TICKET_WRITE_BYTES_EXCEEDED
Definition: rodsErrorTable.h:485
cmlGetFirstRowFromSqlBV
int cmlGetFirstRowFromSqlBV(const char *sql, std::vector< std::string > &bindVars, int *statement, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:433
icatSessionStruct::databasePassword
char databasePassword[64]
Definition: icatStructs.hpp:32
cmlCheckDataObjOwn
rodsLong_t cmlCheckDataObjOwn(const char *dirName, const char *dataName, const char *userName, const char *userZone, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:1121
cmlAudit2
int cmlAudit2(int actionId, const char *dataId, const char *userName, const char *zoneName, const char *accessLevel, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:1820
MAX_NAME_LEN
#define MAX_NAME_LEN
Definition: rodsDef.h:61
cmlGetIntegerValueFromSqlV3
int cmlGetIntegerValueFromSqlV3(const char *sql, rodsLong_t *iVal, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:597
CAT_TICKET_GROUP_EXCLUDED
@ CAT_TICKET_GROUP_EXCLUDED
Definition: rodsErrorTable.h:483
CAT_UNKNOWN_FILE
@ CAT_UNKNOWN_FILE
Definition: rodsErrorTable.h:432
mid_level.hpp
low_level.hpp
icatSessionStruct::stmtPtr
icatStmtStrct * stmtPtr[50]
Definition: icatStructs.hpp:30
CAT_DISCONNECT_ERR
@ CAT_DISCONNECT_ERR
Definition: rodsErrorTable.h:419
icatStmtStrct::resultValue
char * resultValue[30]
Definition: icatStructs.hpp:21
irods.pypyodbc.status
status
Definition: pypyodbc.py:467
cmlCheckDataObjOnly
rodsLong_t cmlCheckDataObjOnly(const char *dirName, const char *dataName, const char *userName, const char *userZone, const char *accessLevel, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:1074
cmlAudit5
int cmlAudit5(int actionId, const char *objId, const char *userId, const char *comment, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:2019
LOG_NOTICE
#define LOG_NOTICE
Definition: rodsLog.h:33
icss
icatSessionStruct icss
Definition: db_plugin.cpp:97
CAT_TICKET_INVALID
@ CAT_TICKET_INVALID
Definition: rodsErrorTable.h:478
cmlCheckNameToken
int cmlCheckNameToken(const char *nameSpace, const char *tokenName, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:618
CAT_ENV_ERR
@ CAT_ENV_ERR
Definition: rodsErrorTable.h:417
cmlModifySingleTable
int cmlModifySingleTable(const char *tableName, const char *updateCols[], const char *updateValues[], const char *whereColsAndConds[], const char *whereValues[], int numOfUpdates, int numOfConds, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:636
CAT_CONNECT_ERR
@ CAT_CONNECT_ERR
Definition: rodsErrorTable.h:418
get_db_schema_version.l
l
Definition: get_db_schema_version.py:19
cmlGetOneRowFromSqlBV
int cmlGetOneRowFromSqlBV(const char *sql, char *cVal[], int cValSize[], int numOfCols, std::vector< std::string > &bindVars, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:165
cmlGetGroupMemberCount
int cmlGetGroupMemberCount(const char *groupName, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:1748
UNINITIALIZED_STATEMENT_NUMBER
const int UNINITIALIZED_STATEMENT_NUMBER
Definition: mid_level.hpp:18
icatStmtStrct::numOfCols
int numOfCols
Definition: icatStructs.hpp:17
cmlFreeStatement
int cmlFreeStatement(int statementNumber, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:374
icatSessionStruct::databaseType
int databaseType
Definition: icatStructs.hpp:33
CAT_SQL_ERR
@ CAT_SQL_ERR
Definition: rodsErrorTable.h:421
irods_virtual_path.hpp
CAT_NO_ROWS_FOUND
@ CAT_NO_ROWS_FOUND
Definition: rodsErrorTable.h:423
cmlCheckTicketRestrictions
int cmlCheckTicketRestrictions(const char *ticketId, const char *ticketHost, const char *userName, const char *userZone, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:1202
cmlGetStringValueFromSql
int cmlGetStringValueFromSql(const char *sql, char *cVal, int cValSize, std::vector< std::string > &bindVars, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:475
CAT_TICKET_HOST_EXCLUDED
@ CAT_TICKET_HOST_EXCLUDED
Definition: rodsErrorTable.h:482
MAX_NUM_OF_CONCURRENT_STMTS
#define MAX_NUM_OF_CONCURRENT_STMTS
Definition: icatDefines.h:14
cllExecSqlWithResult
int cllExecSqlWithResult(icatSessionStruct *icss, int *stmtNum, const char *sql)
Definition: low_level_odbc.cpp:560
cmlDebug
int cmlDebug(int mode)
Definition: mid_level_routines.cpp:74
cmlGetCurrentSeqVal
rodsLong_t cmlGetCurrentSeqVal(icatSessionStruct *icss)
Definition: mid_level_routines.cpp:704
DB_PASSWORD_LEN
#define DB_PASSWORD_LEN
Definition: icatDefines.h:22
LOG_SQL
#define LOG_SQL
Definition: rodsLog.h:9
CAT_INVALID_ARGUMENT
@ CAT_INVALID_ARGUMENT
Definition: rodsErrorTable.h:431
cmlAudit3
int cmlAudit3(int actionId, const char *dataId, const char *userName, const char *zoneName, const char *comment, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:1866
LOG_DEBUG10
#define LOG_DEBUG10
Definition: rodsLog.h:19
DB_TYPE_ORACLE
#define DB_TYPE_ORACLE
Definition: icatDefines.h:26
CAT_TICKET_EXPIRED
@ CAT_TICKET_EXPIRED
Definition: rodsErrorTable.h:479
cmlCheckDirAndGetInheritFlag
rodsLong_t cmlCheckDirAndGetInheritFlag(const char *dirName, const char *userName, const char *userZone, const char *accessLevel, int *inheritFlag, const char *ticketStr, const char *ticketHost, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:909
cmlCheckDirOwn
rodsLong_t cmlCheckDirOwn(const char *dirName, const char *userName, const char *userZone, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:1045
cmlExecuteNoAnswerSql
int cmlExecuteNoAnswerSql(const char *sql, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:151
STR_LEN
#define STR_LEN
Definition: mid_level_routines.cpp:667
cllBindVars
const char * cllBindVars[32000]
Definition: low_level_odbc.cpp:48
mode
int mode
Definition: filesystem.cpp:104
cmlGetNextSeqStr
int cmlGetNextSeqStr(char *seqStr, int maxSeqStrLen, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:740
rstrcpy
char * rstrcpy(char *dest, const char *src, int maxLen)
Definition: stringOpr.cpp:51
cmlCheckDirId
rodsLong_t cmlCheckDirId(const char *dirId, const char *userName, const char *userZone, const char *accessLevel, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:1002
cmlAudit4
int cmlAudit4(int actionId, const char *sql, const char *sqlParm, const char *userName, const char *zoneName, const char *comment, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:1934
NAME_LEN
#define NAME_LEN
Definition: rodsDef.h:55
cmlGetFirstRowFromSql
int cmlGetFirstRowFromSql(const char *sql, int *statement, int skipCount, icatSessionStruct *icss)
Definition: mid_level_routines.cpp:382
CAT_INVALID_USER
@ CAT_INVALID_USER
Definition: rodsErrorTable.h:442
CAT_UNKNOWN_RESOURCE
@ CAT_UNKNOWN_RESOURCE
Definition: rodsErrorTable.h:458
icatSessionStruct
Definition: icatStructs.hpp:26
DB_TYPE_MYSQL
#define DB_TYPE_MYSQL
Definition: icatDefines.h:27
irods_log.hpp
cllConnect
int cllConnect(icatSessionStruct *icss)
Definition: low_level_odbc.cpp:169
DB_TYPE_POSTGRES
#define DB_TYPE_POSTGRES
Definition: icatDefines.h:25
cllExecSqlWithResultBV
int cllExecSqlWithResultBV(icatSessionStruct *icss, int *stmtNum, const char *sql, std::vector< std::string > &bindVars)
Definition: low_level_odbc.cpp:737
CAT_TICKET_USES_EXCEEDED
@ CAT_TICKET_USES_EXCEEDED
Definition: rodsErrorTable.h:480
rodsLong_t
long long rodsLong_t
Definition: rodsType.h:32
cmlGetNextSeqVal
rodsLong_t cmlGetNextSeqVal(icatSessionStruct *icss)
Definition: mid_level_routines.cpp:669
MAX_SQL_SIZE
#define MAX_SQL_SIZE
Definition: icatDefines.h:16
AU_ACCESS_GRANTED
#define AU_ACCESS_GRANTED
Definition: icatDefines.h:72