@@ -5276,38 +5276,21 @@ static FnCallResult FnCallFold(EvalContext *ctx,
5276
5276
5277
5277
/*********************************************************************/
5278
5278
5279
- static FnCallResult FnCallDatatype (EvalContext * ctx , ARG_UNUSED const Policy * policy , const FnCall * fp , const Rlist * finalargs )
5279
+ static char * DataTypeStringFromVarName (EvalContext * ctx , const char * var_name , bool detail )
5280
5280
{
5281
- assert (fp != NULL );
5282
- assert (fp -> name != NULL );
5281
+ assert (var_name != NULL );
5283
5282
5284
- if (finalargs == NULL )
5285
- {
5286
- Log (LOG_LEVEL_ERR ,
5287
- "Function %s requires variable identifier as first argument" ,
5288
- fp -> name );
5289
- return FnFailure ();
5290
- }
5291
- const char * const var_name = RlistScalarValue (finalargs );
5292
-
5293
- VarRef * const var_ref = VarRefParse (var_name );
5283
+ VarRef * const var_ref = VarRefParse (var_name );
5294
5284
DataType type ;
5295
5285
const void * value = EvalContextVariableGet (ctx , var_ref , & type );
5296
5286
VarRefDestroy (var_ref );
5297
5287
5298
- /* detail argument defaults to false */
5299
- bool detail = false;
5300
- if (finalargs -> next != NULL )
5301
- {
5302
- detail = BooleanFromString (RlistScalarValue (finalargs -> next ));
5303
- }
5304
-
5305
5288
const char * const type_str =
5306
5289
(type == CF_DATA_TYPE_NONE ) ? "none" : DataTypeToString (type );
5307
5290
5308
5291
if (!detail )
5309
5292
{
5310
- return FnReturn (type_str );
5293
+ return SafeStringDuplicate (type_str );
5311
5294
}
5312
5295
5313
5296
if (type == CF_DATA_TYPE_CONTAINER )
@@ -5339,15 +5322,87 @@ static FnCallResult FnCallDatatype(EvalContext *ctx, ARG_UNUSED const Policy *po
5339
5322
subtype_str = "null" ;
5340
5323
break ;
5341
5324
default :
5342
- Log (LOG_LEVEL_ERR ,
5343
- "Function %s failed to get subtype of type data" , fp -> name );
5344
- return FnFailure ();
5325
+ return NULL ;
5345
5326
}
5346
5327
5347
- return FnReturnF ("%s %s" , type_str , subtype_str );
5328
+ return StringConcatenate (3 , type_str , " " , subtype_str );
5329
+ }
5330
+ return StringConcatenate (2 , "policy " , type_str );
5331
+ }
5332
+
5333
+ static FnCallResult FnCallDatatype (EvalContext * ctx , ARG_UNUSED const Policy * policy , const FnCall * fp , const Rlist * finalargs )
5334
+ {
5335
+ assert (fp != NULL );
5336
+ assert (fp -> name != NULL );
5337
+
5338
+ if (finalargs == NULL )
5339
+ {
5340
+ Log (LOG_LEVEL_ERR ,
5341
+ "Function %s requires variable identifier as first argument" ,
5342
+ fp -> name );
5343
+ return FnFailure ();
5344
+ }
5345
+ const char * const var_name = RlistScalarValue (finalargs );
5346
+
5347
+ /* detail argument defaults to false */
5348
+ bool detail = false;
5349
+ if (finalargs -> next != NULL )
5350
+ {
5351
+ detail = BooleanFromString (RlistScalarValue (finalargs -> next ));
5352
+ }
5353
+ char * const output_string = DataTypeStringFromVarName (ctx , var_name , detail );
5354
+
5355
+ if (output_string == NULL )
5356
+ {
5357
+ Log (LOG_LEVEL_ERR , "Function %s could not parse var type" ,
5358
+ fp -> name );
5359
+ return FnFailure ();
5360
+ }
5361
+
5362
+ return FnReturnNoCopy (output_string );
5363
+ }
5364
+
5365
+ /*********************************************************************/
5366
+
5367
+ static FnCallResult FnCallIsDatatype (EvalContext * ctx , ARG_UNUSED const Policy * policy , const FnCall * fp , const Rlist * finalargs )
5368
+ {
5369
+ assert (fp != NULL );
5370
+ assert (fp -> name != NULL );
5371
+
5372
+ // check args
5373
+ const Rlist * const var_arg = finalargs ;
5374
+ if (var_arg == NULL )
5375
+ {
5376
+ Log (LOG_LEVEL_ERR , "Function %s requires a variable as first argument" ,
5377
+ fp -> name );
5378
+ return FnFailure ();
5379
+ }
5380
+
5381
+ assert (finalargs != NULL ); // assumes finalargs is already checked by var_arg
5382
+ const Rlist * const type_arg = finalargs -> next ;
5383
+ if (type_arg == NULL )
5384
+ {
5385
+ Log (LOG_LEVEL_ERR , "Function %s requires a type as second argument" ,
5386
+ fp -> name );
5387
+ return FnFailure ();
5348
5388
}
5349
5389
5350
- return FnReturnF ("policy %s" , type_str );
5390
+ const char * const var_name = RlistScalarValue (var_arg );
5391
+ const char * const type_name = RlistScalarValue (type_arg );
5392
+ bool detail = StringContainsChar (type_name , ' ' );
5393
+
5394
+ char * const type_string = DataTypeStringFromVarName (ctx , var_name , detail );
5395
+
5396
+ if (type_string == NULL )
5397
+ {
5398
+ Log (LOG_LEVEL_ERR , "Function %s could not determine type of the variable '%s'" ,
5399
+ fp -> name , var_name );
5400
+ return FnFailure ();
5401
+ }
5402
+ const bool matching = StringEqual (type_name , type_string );
5403
+ free (type_string );
5404
+
5405
+ return FnReturnContext (matching );
5351
5406
}
5352
5407
5353
5408
/*********************************************************************/
@@ -10303,6 +10358,12 @@ static const FnCallArg DATATYPE_ARGS[] =
10303
10358
{CF_BOOL , CF_DATA_TYPE_OPTION , "Enable detailed type decription" },
10304
10359
{NULL , CF_DATA_TYPE_NONE , NULL }
10305
10360
};
10361
+ static const FnCallArg IS_DATATYPE_ARGS [] =
10362
+ {
10363
+ {CF_ANYSTRING , CF_DATA_TYPE_STRING , "Variable identifier" },
10364
+ {CF_ANYSTRING , CF_DATA_TYPE_STRING , "Type" },
10365
+ {NULL , CF_DATA_TYPE_NONE , NULL }
10366
+ };
10306
10367
10307
10368
10308
10369
/*********************************************************/
@@ -10715,6 +10776,8 @@ const FnCallType CF_FNCALL_TYPES[] =
10715
10776
// Datatype functions
10716
10777
FnCallTypeNew ("type" , CF_DATA_TYPE_STRING , DATATYPE_ARGS , & FnCallDatatype , "Get type description as string" ,
10717
10778
FNCALL_OPTION_VARARG , FNCALL_CATEGORY_DATA , SYNTAX_STATUS_NORMAL ),
10779
+ FnCallTypeNew ("is_type" , CF_DATA_TYPE_STRING , IS_DATATYPE_ARGS , & FnCallIsDatatype , "Compare type of variable with type" ,
10780
+ FNCALL_OPTION_VARARG , FNCALL_CATEGORY_DATA , SYNTAX_STATUS_NORMAL ),
10718
10781
10719
10782
FnCallTypeNewNull ()
10720
10783
};
0 commit comments