Writer *FileRead(const char *filename, size_t max_size, bool *truncated) { int fd = safe_open(filename, O_RDONLY); if (fd == -1) { return NULL; } Writer *w = FileReadFromFd(fd, max_size, truncated); close(fd); return w; }
static PromiseResult RenderTemplateMustache(EvalContext *ctx, const Promise *pp, Attributes a, EditContext *edcontext) { PromiseResult result = PROMISE_RESULT_NOOP; if (!FileCanOpen(a.edit_template, "r")) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Template file '%s' could not be opened for reading", a.edit_template); return PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } unsigned char existing_output_digest[EVP_MAX_MD_SIZE + 1] = { 0 }; if (access(pp->promiser, R_OK) == 0) { HashFile(pp->promiser, existing_output_digest, CF_DEFAULT_DIGEST); } int template_fd = safe_open(a.edit_template, O_RDONLY | O_TEXT); Writer *template_writer = NULL; if (template_fd >= 0) { template_writer = FileReadFromFd(template_fd, SIZE_MAX, NULL); close(template_fd); } if (!template_writer) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Could not read template file '%s'", a.edit_template); return PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } JsonElement *default_template_data = NULL; if (!a.template_data) { a.template_data = default_template_data = DefaultTemplateData(ctx); } Buffer *output_buffer = BufferNew(); if (MustacheRender(output_buffer, StringWriterData(template_writer), a.template_data)) { unsigned char rendered_output_digest[EVP_MAX_MD_SIZE + 1] = { 0 }; HashString(BufferData(output_buffer), BufferSize(output_buffer), rendered_output_digest, CF_DEFAULT_DIGEST); if (!HashesMatch(existing_output_digest, rendered_output_digest, CF_DEFAULT_DIGEST)) { if (SaveAsFile(SaveBufferCallback, output_buffer, edcontext->filename, a, edcontext->new_line_mode)) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Updated rendering of '%s' from template mustache template '%s'", pp->promiser, a.edit_template); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_FAIL, pp, a, "Updated rendering of '%s' from template mustache template '%s'", pp->promiser, a.edit_template); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } } JsonDestroy(default_template_data); WriterClose(template_writer); BufferDestroy(output_buffer); return result; } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Error rendering mustache template '%s'", a.edit_template); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); JsonDestroy(default_template_data); WriterClose(template_writer); BufferDestroy(output_buffer); return PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } }