"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "libpromises/evalfunction.c" between
cfengine-3.12.6.tar.gz and cfengine-3.12.7.tar.gz

About: CFEngine is a configuration management system for configuring and maintaining Unix-like computers (using an own high level policy language). Community version. Community version. LTS (Long Term Support) release.

evalfunction.c  (cfengine-3.12.6):evalfunction.c  (cfengine-3.12.7)
skipping to change at line 5049 skipping to change at line 5049
sorted = AlphaSortRListNames(sorted); sorted = AlphaSortRListNames(sorted);
} }
return (FnCallResult) { FNCALL_SUCCESS, (Rval) { sorted, RVAL_TYPE_LIST } }; return (FnCallResult) { FNCALL_SUCCESS, (Rval) { sorted, RVAL_TYPE_LIST } };
} }
/*********************************************************************/ /*********************************************************************/
static FnCallResult FnCallFormat(EvalContext *ctx, ARG_UNUSED const Policy *poli cy, const FnCall *fp, const Rlist *finalargs) static FnCallResult FnCallFormat(EvalContext *ctx, ARG_UNUSED const Policy *poli cy, const FnCall *fp, const Rlist *finalargs)
{ {
char id[CF_BUFSIZE]; const char *const id = "built-in FnCall format-arg";
snprintf(id, CF_BUFSIZE, "built-in FnCall %s-arg", fp->name);
/* We need to check all the arguments, ArgTemplate does not check varadic fu nctions */ /* We need to check all the arguments, ArgTemplate does not check varadic fu nctions */
for (const Rlist *arg = finalargs; arg; arg = arg->next) for (const Rlist *arg = finalargs; arg; arg = arg->next)
{ {
SyntaxTypeMatch err = CheckConstraintTypeMatch(id, arg->val, CF_DATA_TYP E_STRING, "", 1); SyntaxTypeMatch err = CheckConstraintTypeMatch(id, arg->val, CF_DATA_TYP E_STRING, "", 1);
if (err != SYNTAX_TYPE_MATCH_OK && err != SYNTAX_TYPE_MATCH_ERROR_UNEXPA NDED) if (err != SYNTAX_TYPE_MATCH_OK && err != SYNTAX_TYPE_MATCH_ERROR_UNEXPA NDED)
{ {
FatalError(ctx, "in %s: %s", id, SyntaxTypeMatchToString(err)); FatalError(ctx, "in %s: %s", id, SyntaxTypeMatchToString(err));
} }
} }
if (!finalargs) if (finalargs == NULL)
{ {
return FnFailure(); return FnFailure();
} }
char *format = RlistScalarValue(finalargs); char *format = RlistScalarValue(finalargs);
if (!format) if (format == NULL)
{ {
return FnFailure(); return FnFailure();
} }
const Rlist *rp = finalargs->next; const Rlist *rp = finalargs->next;
char *check = strchr(format, '%'); char *check = strchr(format, '%');
char check_buffer[CF_BUFSIZE]; char check_buffer[CF_BUFSIZE];
Buffer *buf = BufferNew(); Buffer *buf = BufferNew();
if (check) if (check != NULL)
{ {
BufferAppend(buf, format, check - format); BufferAppend(buf, format, check - format);
Seq *s; Seq *s;
while (check && while (check != NULL &&
(s = StringMatchCaptures("^(%%|%[^diouxXeEfFgGaAcsCSpnm%]*?[dioux XeEfFgGaAcsCSpnm])([^%]*)(.*)$", check, false))) (s = StringMatchCaptures("^(%%|%[^diouxXeEfFgGaAcsCSpnm%]*?[dioux XeEfFgGaAcsCSpnm])([^%]*)(.*)$", check, false)))
{ {
{ {
if (SeqLength(s) >= 2) if (SeqLength(s) >= 2)
{ {
const char *format_piece = BufferData(SeqAt(s, 1)); const char *format_piece = BufferData(SeqAt(s, 1));
bool percent = (strncmp(format_piece, "%%", 2) == 0); bool percent = (strncmp(format_piece, "%%", 2) == 0);
char *data = NULL; char *data = NULL;
if (percent) if (percent)
{ {
} }
else if (rp) else if (rp != NULL)
{ {
data = RlistScalarValue(rp); data = RlistScalarValue(rp);
rp = rp->next; rp = rp->next;
} }
else // not %% and no data else // not %% and no data
{ {
Log(LOG_LEVEL_ERR, "format() didn't have enough paramete rs"); Log(LOG_LEVEL_ERR, "format() didn't have enough paramete rs");
BufferDestroy(buf); BufferDestroy(buf);
SeqDestroy(s); SeqDestroy(s);
return FnFailure(); return FnFailure();
} }
char piece[CF_BUFSIZE]; char piece[CF_BUFSIZE];
memset(piece, 0, CF_BUFSIZE); memset(piece, 0, CF_BUFSIZE);
// CfOut(OUTPUT_LEVEL_INFORM, "", "format: processing format const char bad_modifiers[] = "hLqjzt";
piece = '%s' with data '%s'", format_piece, percent ? "%" : data); const size_t length = strlen(bad_modifiers);
for (int b = 0; b < length; b++)
char bad_modifiers[] = "hLqjzt";
for (int b = 0; b < strlen(bad_modifiers); b++)
{ {
if (strchr(format_piece, bad_modifiers[b]) != NULL) if (strchr(format_piece, bad_modifiers[b]) != NULL)
{ {
Log(LOG_LEVEL_ERR, "format() does not allow modifier character '%c' in format specifier '%s'.", Log(LOG_LEVEL_ERR, "format() does not allow modifier character '%c' in format specifier '%s'.",
bad_modifiers[b], bad_modifiers[b],
format_piece); format_piece);
BufferDestroy(buf); BufferDestroy(buf);
SeqDestroy(s); SeqDestroy(s);
return FnFailure(); return FnFailure();
} }
} }
if (strrchr(format_piece, 'd') || strrchr(format_piece, 'o') || strrchr(format_piece, 'x')) if (strrchr(format_piece, 'd') != NULL || strrchr(format_pie ce, 'o') != NULL || strrchr(format_piece, 'x') != NULL)
{ {
long x = 0; long x = 0;
sscanf(data, "%ld%s", &x, piece); // we don't care about the remainder and will overwrite it sscanf(data, "%ld", &x);
snprintf(piece, CF_BUFSIZE, format_piece, x); snprintf(piece, CF_BUFSIZE, format_piece, x);
BufferAppend(buf, piece, strlen(piece)); BufferAppend(buf, piece, strlen(piece));
// CfOut(OUTPUT_LEVEL_INFORM, "", "format: appending int format piece = '%s' with data '%s'", format_piece, data);
} }
else if (percent) else if (percent)
{ {
BufferAppend(buf, "%", 1); BufferAppend(buf, "%", 1);
// CfOut(OUTPUT_LEVEL_INFORM, "", "format: appending int format piece = '%s' with data '%s'", format_piece, data);
} }
else if (strrchr(format_piece, 'f')) else if (strrchr(format_piece, 'f') != NULL)
{ {
double x = 0; double x = 0;
sscanf(data, "%lf%s", &x, piece); // we don't care about the remainder and will overwrite it sscanf(data, "%lf", &x);
snprintf(piece, CF_BUFSIZE, format_piece, x); snprintf(piece, CF_BUFSIZE, format_piece, x);
BufferAppend(buf, piece, strlen(piece)); BufferAppend(buf, piece, strlen(piece));
// CfOut(OUTPUT_LEVEL_INFORM, "", "format: appending flo at format piece = '%s' with data '%s'", format_piece, data);
} }
else if (strrchr(format_piece, 's')) else if (strrchr(format_piece, 's') != NULL)
{ {
snprintf(piece, CF_BUFSIZE, format_piece, data); BufferAppendF(buf, format_piece, data);
BufferAppend(buf, piece, strlen(piece));
// CfOut(OUTPUT_LEVEL_INFORM, "", "format: appending str
ing format piece = '%s' with data '%s'", format_piece, data);
} }
else if (strrchr(format_piece, 'S')) else if (strrchr(format_piece, 'S') != NULL)
{ {
char *found_format_spec = NULL; char *found_format_spec = NULL;
char format_rewrite[CF_BUFSIZE]; char format_rewrite[CF_BUFSIZE];
strlcpy(format_rewrite, format_piece, CF_BUFSIZE); strlcpy(format_rewrite, format_piece, CF_BUFSIZE);
found_format_spec = strrchr(format_rewrite, 'S'); found_format_spec = strrchr(format_rewrite, 'S');
if (found_format_spec) if (found_format_spec != NULL)
{ {
*found_format_spec = 's'; *found_format_spec = 's';
} }
else else
{ {
ProgrammingError("Couldn't find the expected S forma t spec in %s", format_piece); ProgrammingError("Couldn't find the expected S forma t spec in %s", format_piece);
} }
const char* const varname = data; const char* const varname = data;
VarRef *ref = VarRefParse(varname); VarRef *ref = VarRefParse(varname);
DataType type; DataType type;
const void *value = EvalContextVariableGet(ctx, ref, &ty pe); const void *value = EvalContextVariableGet(ctx, ref, &ty pe);
VarRefDestroy(ref); VarRefDestroy(ref);
if (type == CF_DATA_TYPE_CONTAINER) if (type == CF_DATA_TYPE_CONTAINER)
{ {
Writer *w = StringWriter(); Writer *w = StringWriter();
JsonWriteCompact(w, value); JsonWriteCompact(w, value);
snprintf(piece, CF_BUFSIZE, format_rewrite, StringWr iterData(w)); BufferAppendF(buf, format_rewrite, StringWriterData( w));
WriterClose(w); WriterClose(w);
BufferAppend(buf, piece, strlen(piece));
} }
else // it might be a list reference else // it might be a list reference
{ {
DataType data_type; DataType data_type;
const Rlist *list = GetListReferenceArgument(ctx, fp , varname, &data_type); const Rlist *list = GetListReferenceArgument(ctx, fp , varname, &data_type);
if (data_type == CF_DATA_TYPE_STRING_LIST) if (data_type == CF_DATA_TYPE_STRING_LIST)
{ {
Writer *w = StringWriter(); Writer *w = StringWriter();
WriterWrite(w, "{ "); WriterWrite(w, "{ ");
for (const Rlist *rp = list; rp; rp = rp->next) for (const Rlist *rp = list; rp; rp = rp->next)
skipping to change at line 5210 skipping to change at line 5201
WriterWriteF(w, "\"%s\"", escaped); WriterWriteF(w, "\"%s\"", escaped);
free(escaped); free(escaped);
if (rp != NULL && rp->next != NULL) if (rp != NULL && rp->next != NULL)
{ {
WriterWrite(w, ", "); WriterWrite(w, ", ");
} }
} }
WriterWrite(w, " }"); WriterWrite(w, " }");
snprintf(piece, CF_BUFSIZE, format_rewrite, Stri ngWriterData(w)); BufferAppendF(buf, format_rewrite, StringWriterD ata(w));
WriterClose(w); WriterClose(w);
BufferAppend(buf, piece, strlen(piece));
} }
else // whatever this is, it's not a list ref erence or a data container else // whatever this is, it's not a list ref erence or a data container
{ {
Log(LOG_LEVEL_VERBOSE, "format() with %%S specif ier needs a data container or a list instead of '%s'.", Log(LOG_LEVEL_VERBOSE, "format() with %%S specif ier needs a data container or a list instead of '%s'.",
varname); varname);
BufferDestroy(buf); BufferDestroy(buf);
SeqDestroy(s); SeqDestroy(s);
return FnFailure(); return FnFailure();
} }
} }
} }
else else
{ {
char error[] = "(unhandled format)"; char error[] = "(unhandled format)";
BufferAppend(buf, error, strlen(error)); BufferAppend(buf, error, strlen(error));
// CfOut(OUTPUT_LEVEL_INFORM, "", "format: error appendi ng unhandled format piece = '%s' with data '%s'", format_piece, data);
} }
} }
else else
{ {
check = NULL; check = NULL;
} }
} }
{ {
if (SeqLength(s) >= 3) if (SeqLength(s) >= 3)
skipping to change at line 6718 skipping to change at line 6707
} }
else if (JsonGetElementType(json) != JSON_ELEMENT_TYPE_CONTAINER) else if (JsonGetElementType(json) != JSON_ELEMENT_TYPE_CONTAINER)
{ {
Log(LOG_LEVEL_VERBOSE, "Function '%s', argument '%s' was not a data cont ainer or list", Log(LOG_LEVEL_VERBOSE, "Function '%s', argument '%s' was not a data cont ainer or list",
fp->name, name_str); fp->name, name_str);
JsonDestroyMaybe(json, allocated); JsonDestroyMaybe(json, allocated);
return FnFailure(); return FnFailure();
} }
Writer *w = StringWriter(); Writer *w = StringWriter();
int length;
JsonWrite(w, json, 0); JsonWrite(w, json, 0);
JsonDestroyMaybe(json, allocated); JsonDestroyMaybe(json, allocated);
Log(LOG_LEVEL_DEBUG, "%s: from data container %s, got JSON data '%s'", fp->n ame, name_str, StringWriterData(w)); Log(LOG_LEVEL_DEBUG, "%s: from data container %s, got JSON data '%s'", fp->n ame, name_str, StringWriterData(w));
length = strlen(StringWriterData(w)); return FnReturnNoCopy(StringWriterClose(w));
if (length >= CF_BUFSIZE)
{
Log(LOG_LEVEL_INFO, "%s: truncating data container %s JSON data from %d
bytes to %d",
fp->name, name_str, length, CF_BUFSIZE);
}
char buf[CF_BUFSIZE];
snprintf(buf, CF_BUFSIZE, "%s", StringWriterData(w));
WriterClose(w);
return FnReturn(buf);
} }
/*********************************************************************/ /*********************************************************************/
// this function is separate so other data container readers can use it // this function is separate so other data container readers can use it
static FnCallResult DataRead(EvalContext *ctx, const FnCall *fp, const Rlist *fi nalargs) static FnCallResult DataRead(EvalContext *ctx, const FnCall *fp, const Rlist *fi nalargs)
{ {
/* 5 args: filename,comment_regex,split_regex,max number of entries,maxfiles ize */ /* 5 args: filename,comment_regex,split_regex,max number of entries,maxfiles ize */
const char *filename = RlistScalarValue(finalargs); const char *filename = RlistScalarValue(finalargs);
 End of changes. 25 change blocks. 
46 lines changed or deleted 20 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)