int cf_fault_sink_context_strlist(int sink_id, char *context, cf_dyn_buf *db) { // get the sink if (sink_id > cf_fault_sinks_inuse) return(-1); cf_fault_sink *s = &cf_fault_sinks[sink_id]; // get the severity uint i; for (i=0;i<CF_FAULT_CONTEXT_UNDEF;i++) { if (0 == strcmp(cf_fault_context_strings[i],context)) break; } if (i == CF_FAULT_CONTEXT_UNDEF) { cf_dyn_buf_append_string(db, context); cf_dyn_buf_append_string(db, ":unknown"); return(0); } // get the string cf_dyn_buf_append_string(db, context); cf_dyn_buf_append_char(db, ':'); cf_dyn_buf_append_string(db, cf_fault_severity_strings[s->limit[i]]); return(0); }
/** * Populate dyn buf with endpoints info * @param endpoint_list the input list. NULL allowed. * @param db the dynamic buffer. */ void as_endpoint_list_info(const as_endpoint_list* endpoint_list, cf_dyn_buf* db) { size_t endpoint_list_size = 0; as_endpoint_list_sizeof(endpoint_list, &endpoint_list_size); // 4 chars for delimiters, 50 chars for ipv6 ip and port, rounded to 64 size_t endpoint_list_str_size = 64 * endpoint_list_size; char endpoint_list_str[endpoint_list_str_size]; as_endpoint_list_to_string_match_capabilities(endpoint_list, endpoint_list_str, sizeof(endpoint_list_str), AS_ENDPOINT_TLS_MASK, 0); cf_dyn_buf_append_string(db, "endpoint="); if (endpoint_list_str[0] != '\0') { cf_dyn_buf_append_string(db, endpoint_list_str); } cf_dyn_buf_append_string(db, ":"); as_endpoint_list_to_string_match_capabilities(endpoint_list, endpoint_list_str, sizeof(endpoint_list_str), AS_ENDPOINT_TLS_MASK, AS_ENDPOINT_TLS_MASK); cf_dyn_buf_append_string(db, "endpoint-tls="); if (endpoint_list_str[0] != '\0') { cf_dyn_buf_append_string(db, endpoint_list_str); } }
void as_namespace_get_bins_info(as_namespace *ns, cf_dyn_buf *db, bool show_ns) { if (show_ns) { cf_dyn_buf_append_string(db, ns->name); cf_dyn_buf_append_char(db, ':'); } if (ns->single_bin) { cf_dyn_buf_append_string(db, "[single-bin]"); } else { uint32_t bin_count = cf_vmapx_count(ns->p_bin_name_vmap); cf_dyn_buf_append_string(db, "num-bin-names="); cf_dyn_buf_append_uint32(db, bin_count); cf_dyn_buf_append_string(db, ",bin-names-quota="); cf_dyn_buf_append_uint32(db, BIN_NAMES_QUOTA); for (uint32_t i = 0; i < bin_count; i++) { cf_dyn_buf_append_char(db, ','); cf_dyn_buf_append_string(db, as_bin_get_name_from_id(ns, (uint16_t)i)); } } if (show_ns) { cf_dyn_buf_append_char(db, ';'); } }
void info_append_string_safe(cf_dyn_buf *db, const char *name, const char *value) { cf_dyn_buf_append_string(db, name); cf_dyn_buf_append_char(db, '='); cf_dyn_buf_append_string(db, value ? value : "null"); cf_dyn_buf_append_char(db, ';'); }
/* * Reading local directory to get specific module item's contents. * In future if needed we can change this to reading from smd metadata. */ int udf_cask_info_get(char *name, char * params, cf_dyn_buf * out) { int resp = 0; char filename[128] = {0}; int filename_len = sizeof(filename); uint8_t * content = NULL; size_t content_len = 0; unsigned char content_gen[256] = {0}; uint8_t udf_type = AS_UDF_TYPE_LUA; cf_debug(AS_INFO, "UDF CASK INFO GET"); // get (required) script filename if ( as_info_parameter_get(params, "filename", filename, &filename_len) ) { cf_info(AS_INFO, "invalid or missing filename"); cf_dyn_buf_append_string(out, "error=invalid_filename"); return 0; } mod_lua_rdlock(&mod_lua); // read the script from filesystem resp = file_read(filename, &content, &content_len, content_gen); mod_lua_unlock(&mod_lua); if ( resp ) { switch ( resp ) { case 1 : { cf_dyn_buf_append_string(out, "error=not_found"); break; } case 2 : { cf_dyn_buf_append_string(out, "error=empty"); break; } default : { cf_dyn_buf_append_string(out, "error=unknown_error"); break; // complier complains without a break; } } } else { // put back the result cf_dyn_buf_append_string(out, "gen="); cf_dyn_buf_append_string(out, (char *) content_gen); cf_dyn_buf_append_string(out, ";type="); cf_dyn_buf_append_string(out, as_udf_type_name[udf_type]); cf_dyn_buf_append_string(out, ";content="); cf_dyn_buf_append_buf(out, content, content_len); cf_dyn_buf_append_string(out, ";"); } if ( content ) { cf_free(content); content = NULL; } return 0; }
static inline void append_indexed_name(cf_dyn_buf *db, const char *name, uint32_t ix, const char *attr) { cf_dyn_buf_append_string(db, name); cf_dyn_buf_append_char(db, '['); cf_dyn_buf_append_uint32(db, ix); cf_dyn_buf_append_char(db, ']'); if (attr) { cf_dyn_buf_append_char(db, '.'); cf_dyn_buf_append_string(db, attr); } cf_dyn_buf_append_char(db, '='); }
int cf_fault_sink_context_all_strlist(int sink_id, cf_dyn_buf *db) { // get the sink if (sink_id > cf_fault_sinks_inuse) return(-1); cf_fault_sink *s = &cf_fault_sinks[sink_id]; for (uint i=0; i<CF_FAULT_CONTEXT_UNDEF; i++) { cf_dyn_buf_append_string(db, cf_fault_context_strings[i]); cf_dyn_buf_append_char(db, ':'); cf_dyn_buf_append_string(db, cf_fault_severity_strings[s->limit[i]]); cf_dyn_buf_append_char(db, ';'); } cf_dyn_buf_chomp(db); return(0); }
//------------------------------------------------ // Append a linear histogram "snapshot" to db. // void linear_hist_get_info(linear_hist *h, cf_dyn_buf *db) { pthread_mutex_lock(&h->info_lock); cf_dyn_buf_append_string(db, h->info_snapshot); pthread_mutex_unlock(&h->info_lock); }
void info_append_indexed_string(cf_dyn_buf *db, const char *name, uint32_t ix, const char *attr, const char *value) { append_indexed_name(db, name, ix, attr); cf_dyn_buf_append_string(db, value); cf_dyn_buf_append_char(db, ';'); }
void info_append_uint64_x(cf_dyn_buf *db, const char *name, uint64_t value) { cf_dyn_buf_append_string(db, name); cf_dyn_buf_append_char(db, '='); cf_dyn_buf_append_uint64_x(db, value); cf_dyn_buf_append_char(db, ';'); }
void info_append_int(cf_dyn_buf *db, const char *name, int value) { cf_dyn_buf_append_string(db, name); cf_dyn_buf_append_char(db, '='); cf_dyn_buf_append_int(db, value); cf_dyn_buf_append_char(db, ';'); }
void info_append_bool(cf_dyn_buf *db, const char *name, bool value) { cf_dyn_buf_append_string(db, name); cf_dyn_buf_append_char(db, '='); cf_dyn_buf_append_bool(db, value); cf_dyn_buf_append_char(db, ';'); }
int udf_cask_info_remove(char *name, char * params, cf_dyn_buf * out) { char filename[128] = {0}; int filename_len = sizeof(filename); char file_path[1024] = {0}; struct stat buf; cf_debug(AS_INFO, "UDF CASK INFO REMOVE"); // get (required) script filename if ( as_info_parameter_get(params, "filename", filename, &filename_len) ) { cf_info(AS_UDF, "invalid or missing filename"); cf_dyn_buf_append_string(out, "error=invalid_filename"); } // now check if such a file-name exists : if (!g_config.mod_lua.user_path) { return -1; } snprintf(file_path, 1024, "%s/%s", g_config.mod_lua.user_path, filename); cf_debug(AS_INFO, " Lua file removal full-path is : %s \n", file_path); if (stat(file_path, &buf) != 0) { cf_info(AS_UDF, "failed to read file from : %s, error : %s", file_path, cf_strerror(errno)); cf_dyn_buf_append_string(out, "error=file_not_found"); return -1; } as_smd_delete_metadata(udf_smd_module_name, filename); // this is what an error would look like // cf_dyn_buf_append_string(out, "error="); // cf_dyn_buf_append_int(out, resp); cf_dyn_buf_append_string(out, "ok"); cf_info(AS_UDF, "UDF module '%s' (%s) removed", filename, file_path); return 0; }
int cf_fault_sink_strlist(cf_dyn_buf *db) { for (int i = 0; i < cf_fault_sinks_inuse; i++) { cf_dyn_buf_append_int(db, i); cf_dyn_buf_append_char(db, ':'); cf_dyn_buf_append_string(db,cf_fault_sinks[i].path); cf_dyn_buf_append_char(db, ';'); } cf_dyn_buf_chomp(db); return(0); }
void info_append_format(cf_dyn_buf *db, const char *name, const char *form, ...) { va_list va; va_start(va, form); cf_dyn_buf_append_string(db, name); cf_dyn_buf_append_char(db, '='); cf_dyn_buf_append_format_va(db, form, va); cf_dyn_buf_append_char(db, ';'); va_end(va); }
int udf_cask_info_remove(char *name, char * params, cf_dyn_buf * out) { char filename[128] = {0}; int filename_len = sizeof(filename); cf_debug(AS_INFO, "UDF CASK INFO REMOVE"); // get (required) script filename if ( as_info_parameter_get(params, "filename", filename, &filename_len) ) { cf_info(AS_UDF, "invalid or missing filename"); cf_dyn_buf_append_string(out, "error=invalid_filename"); } as_smd_delete_metadata(udf_smd_module_name, filename); // this is what an error would look like // cf_dyn_buf_append_string(out, "error="); // cf_dyn_buf_append_int(out, resp); cf_dyn_buf_append_string(out, "ok"); return 0; }
static int file_read(char * filename, uint8_t ** content, size_t * content_len, unsigned char * hash) { char filepath[256] = {0}; FILE * file = NULL; char line[1024] = {0}; size_t line_len = sizeof(line); file_resolve(filepath, filename, NULL); cf_dyn_buf_define(buf); file = fopen(filepath, "r"); if ( file ) { while( fgets(line, line_len, file) != NULL ) { cf_dyn_buf_append_string(&buf, line); } fclose(file); file = NULL; if ( buf.used_sz > 0 ) { char *src = cf_dyn_buf_strdup(&buf); file_generation(filepath, (uint8_t *)src, buf.used_sz, hash); uint32_t src_len = (uint32_t)buf.used_sz; uint32_t out_size = cf_b64_encoded_len(src_len); *content = (uint8_t *)cf_malloc(out_size); *content_len = out_size; cf_b64_encode((const uint8_t*)src, src_len, (char*)(*content)); cf_free(src); src = NULL; return 0; } *content = NULL; *content_len = 0; return 2; } *content = NULL; *content_len = 0; return 1; }
void as_namespace_get_set_info(as_namespace *ns, const char *set_name, cf_dyn_buf *db) { as_set *p_set; if (set_name) { if (cf_vmapx_get_by_name(ns->p_sets_vmap, set_name, (void**)&p_set) == CF_VMAPX_OK) { append_set_props(p_set, db); } return; } for (uint32_t idx = 0; idx < cf_vmapx_count(ns->p_sets_vmap); idx++) { if (cf_vmapx_get_by_index(ns->p_sets_vmap, idx, (void**)&p_set) == CF_VMAPX_OK) { cf_dyn_buf_append_string(db, "ns_name="); cf_dyn_buf_append_string(db, ns->name); cf_dyn_buf_append_char(db, ':'); cf_dyn_buf_append_string(db, "set_name="); cf_dyn_buf_append_string(db, p_set->name); cf_dyn_buf_append_char(db, ':'); append_set_props(p_set, db); } } }
/* * Clear out the Lua cache. */ int udf_cask_info_clear_cache(char *name, char * params, cf_dyn_buf * out) { cf_debug(AS_INFO, "UDF CASK INFO CLEAR CACHE"); mod_lua_wrlock(&mod_lua); as_module_event e = { .type = AS_MODULE_EVENT_CLEAR_CACHE }; as_module_update(&mod_lua, &e); mod_lua_unlock(&mod_lua); cf_dyn_buf_append_string(out, "ok"); return 0; }
/* * UDF SMD get metadata items callback. */ static int udf_cask_get_metadata_cb(char *module, as_smd_item_list_t *items, void *udata) { udf_get_data_t *p_get_data = (udf_get_data_t *) udata; cf_dyn_buf *out = p_get_data->db; unsigned char hash[SHA_DIGEST_LENGTH]; // hex string to be returned to the client unsigned char sha1_hex_buff[CF_SHA_HEX_BUFF_LEN]; // Currently just return directly for LUA uint8_t udf_type = AS_UDF_TYPE_LUA; for (int index = 0; index < items->num_items; index++) { as_smd_item_t *item = items->item[index]; cf_debug(AS_UDF, "UDF metadata item[%d]: module \"%s\" ; key \"%s\" ; value \"%s\" ; generation %u ; timestamp %lu", index, item->module_name, item->key, item->value, item->generation, item->timestamp); cf_dyn_buf_append_string(out, "filename="); cf_dyn_buf_append_buf(out, (uint8_t *)item->key, strlen(item->key)); cf_dyn_buf_append_string(out, ","); SHA1((uint8_t *)item->value, strlen(item->value), hash); // Convert to a hexadecimal string cf_convert_sha1_to_hex(hash, sha1_hex_buff); cf_dyn_buf_append_string(out, "hash="); cf_dyn_buf_append_buf(out, sha1_hex_buff, CF_SHA_HEX_BUFF_LEN); cf_dyn_buf_append_string(out, ",type="); cf_dyn_buf_append_string(out, as_udf_type_name[udf_type]); cf_dyn_buf_append_string(out, ";"); } pthread_mutex_lock(p_get_data->mt); p_get_data->done = true; int retval = pthread_cond_signal(p_get_data->cv); if (retval) { cf_warning(AS_UDF, "pthread_cond_signal failed (rv %d)", retval); } pthread_mutex_unlock(p_get_data->mt); return retval; }
int udf_cask_info_list(char *name, cf_dyn_buf * out) { DIR * dir = NULL; bool not_empty = false; struct dirent * entry = NULL; int count = 0; uint8_t * content = NULL; size_t content_len = 0; unsigned char content_gen[256] = {0}; unsigned char hash[SHA_DIGEST_LENGTH]; // hex string to be returned to the client unsigned char sha1_hex_buff[CF_SHA_HEX_BUFF_LEN]; cf_debug(AS_INFO, "UDF CASK INFO LIST"); // Currently just return directly for LUA uint8_t udf_type = AS_UDF_TYPE_LUA; dir = opendir(g_config.mod_lua.user_path); if ( dir == 0 ) { cf_warning(AS_UDF, "could not open udf directory %s: %s", g_config.mod_lua.user_path, cf_strerror(errno)); return -1; } while ( (entry = readdir(dir)) && entry->d_name ) { char * name = entry->d_name; size_t len = strlen(name); // if ( len < 4 ) continue; if ( name[0] == '.' ) continue; if ( not_empty ) { cf_dyn_buf_append_char(out, ';'); } else { not_empty = true; } cf_dyn_buf_append_string(out, "filename="); cf_dyn_buf_append_buf(out, (uint8_t *) name, len); cf_dyn_buf_append_string(out, ","); mod_lua_rdlock(&mod_lua); if (file_read(name, &content, &content_len, content_gen) != 0) { cf_info(AS_UDF, "UDF-list : file not readable"); cf_dyn_buf_append_string(out, "error=file_not_readable"); mod_lua_unlock(&mod_lua); return 0; } mod_lua_unlock(&mod_lua); SHA1(content, content_len, hash); // Convert to a hexadecimal string cf_convert_sha1_to_hex(hash, sha1_hex_buff); cf_dyn_buf_append_string(out, "hash="); cf_dyn_buf_append_buf(out, sha1_hex_buff, CF_SHA_HEX_BUFF_LEN); cf_dyn_buf_append_string(out, ",type="); cf_dyn_buf_append_string(out, as_udf_type_name[udf_type]); count ++; } if (not_empty) { cf_dyn_buf_append_string(out, ";"); } closedir(dir); return 0; }
void as_namespace_get_hist_info(as_namespace *ns, char *set_name, char *hist_name, cf_dyn_buf *db, bool show_ns) { if (show_ns) { cf_dyn_buf_append_string(db, ns->name); cf_dyn_buf_append_char(db, ':'); } if (set_name == NULL || set_name[0] == 0) { if (strcmp(hist_name, "ttl") == 0) { cf_dyn_buf_append_string(db, "ttl="); linear_histogram_get_info(ns->ttl_hist, db); cf_dyn_buf_append_char(db, ';'); } else if (strcmp(hist_name, "evict") == 0) { cf_dyn_buf_append_string(db, "evict="); linear_histogram_get_info(ns->evict_hist, db); cf_dyn_buf_append_char(db, ';'); } else if (strcmp(hist_name, "evictc") == 0) { cf_dyn_buf_append_string(db, "evictc="); linear_histogram_get_info(ns->evict_coarse_hist, db); cf_dyn_buf_append_char(db, ';'); } else if (strcmp(hist_name, "objsz") == 0) { if (ns->storage_type == AS_STORAGE_ENGINE_SSD) { cf_dyn_buf_append_string(db, "objsz="); linear_histogram_get_info(ns->obj_size_hist, db); cf_dyn_buf_append_char(db, ';'); } else { cf_dyn_buf_append_string(db, "hist-not-applicable"); } } else { cf_dyn_buf_append_string(db, "error-unknown-hist-name"); } } else { uint16_t set_id = as_namespace_get_set_id(ns, set_name); if (set_id != INVALID_SET_ID) { if (strcmp(hist_name, "ttl") == 0) { if (ns->set_ttl_hists[set_id]) { cf_dyn_buf_append_string(db, "ttl="); linear_histogram_get_info(ns->set_ttl_hists[set_id], db); cf_dyn_buf_append_char(db, ';'); } else { cf_dyn_buf_append_string(db, "hist-unavailable"); } } else if (strcmp(hist_name, "objsz") == 0) { if (ns->storage_type == AS_STORAGE_ENGINE_SSD) { if (ns->set_obj_size_hists[set_id]) { cf_dyn_buf_append_string(db, "objsz="); linear_histogram_get_info(ns->set_obj_size_hists[set_id], db); cf_dyn_buf_append_char(db, ';'); } else { cf_dyn_buf_append_string(db, "hist-unavailable"); } } else { cf_dyn_buf_append_string(db, "hist-not-applicable"); } } else { cf_dyn_buf_append_string(db, "error-unknown-hist-name"); } } else { cf_dyn_buf_append_string(db, "error-unknown-set-name"); } } }
static void append_set_props(as_set *p_set, cf_dyn_buf *db) { cf_dyn_buf_append_string(db, "n_objects="); cf_dyn_buf_append_uint64(db, cf_atomic64_get(p_set->num_elements)); cf_dyn_buf_append_char(db, ':'); cf_dyn_buf_append_string(db, "n-bytes-memory="); cf_dyn_buf_append_uint64(db, cf_atomic64_get(p_set->n_bytes_memory)); cf_dyn_buf_append_char(db, ':'); cf_dyn_buf_append_string(db, "stop-writes-count="); cf_dyn_buf_append_uint64(db, cf_atomic64_get(p_set->stop_writes_count)); cf_dyn_buf_append_char(db, ':'); cf_dyn_buf_append_string(db, "set-enable-xdr="); if (cf_atomic32_get(p_set->enable_xdr) == AS_SET_ENABLE_XDR_TRUE) { cf_dyn_buf_append_string(db, "true"); } else if (cf_atomic32_get(p_set->enable_xdr) == AS_SET_ENABLE_XDR_FALSE) { cf_dyn_buf_append_string(db, "false"); } else if (cf_atomic32_get(p_set->enable_xdr) == AS_SET_ENABLE_XDR_DEFAULT) { cf_dyn_buf_append_string(db, "use-default"); } else { cf_dyn_buf_append_uint32(db, cf_atomic32_get(p_set->enable_xdr)); } cf_dyn_buf_append_char(db, ':'); cf_dyn_buf_append_string(db, "disable-eviction="); if (IS_SET_EVICTION_DISABLED(p_set)) { cf_dyn_buf_append_string(db, "true"); } else { cf_dyn_buf_append_string(db, "false"); } cf_dyn_buf_append_char(db, ':'); cf_dyn_buf_append_string(db, "set-delete="); if (IS_SET_DELETED(p_set)) { cf_dyn_buf_append_string(db, "true"); } else { cf_dyn_buf_append_string(db, "false"); } cf_dyn_buf_append_char(db, ';'); }
int udf_cask_info_put(char *name, char * params, cf_dyn_buf * out) { cf_debug(AS_INFO, "UDF CASK INFO PUT"); int rc = 0; char filename[128] = {0}; int filename_len = sizeof(filename); // Content_len from the client and its expected size char content_len[32] = {0}; int clen = sizeof(content_len); // Udf content from the client and its expected length char *udf_content = NULL; int udf_content_len = 0; // Udf type from the client and its expected size char type[8] = {0}; int type_len = sizeof(type); // get (required) script filename char *tmp_char; if ( as_info_parameter_get(params, "filename", filename, &filename_len) || !(tmp_char = strchr(filename, '.')) // No extension in filename || tmp_char == filename // '.' at the begining of filename || strlen (tmp_char) <= 1) { // '.' in filename, but no extnsion e.g. "abc." cf_info(AS_INFO, "invalid or missing filename"); cf_dyn_buf_append_string(out, "error=invalid_filename"); return 0; } if ( as_info_parameter_get(params, "content-len", content_len, &(clen)) ) { cf_info(AS_INFO, "invalid or missing content-len"); cf_dyn_buf_append_string(out, "error=invalid_content_len"); return 0; } if ( as_info_parameter_get(params, "udf-type", type, &type_len) ) { // Replace with DEFAULT IS LUA strcpy(type, as_udf_type_name[0]); } // check type field if (-1 == udf_type_getid(type)) { cf_info(AS_INFO, "invalid or missing udf-type : %s not valid", type); cf_dyn_buf_append_string(out, "error=invalid_udf_type"); return 0; } // get b64 encoded script udf_content_len = atoi(content_len) + 1; udf_content = (char *) cf_malloc(udf_content_len); if ( udf_content == NULL ) { cf_info(AS_UDF, "internal allocation error"); cf_dyn_buf_append_string(out, "error=internal_error"); // As memory is not allocated. // It should not continue. return 0; } // cf_info(AS_UDF, "content_len = %s", content_len); // cf_info(AS_UDF, "udf_content_len = %d", udf_content_len); // get (required) script content - base64 encoded here. if ( as_info_parameter_get(params, "content", udf_content, &(udf_content_len)) ) { cf_info(AS_UDF, "invalid content"); cf_dyn_buf_append_string(out, "error=invalid_content"); cf_free(udf_content); return 0; } // base 64 decode it uint32_t encoded_len = strlen(udf_content); uint32_t decoded_len = cf_b64_decoded_buf_size(encoded_len) + 1; // Don't allow UDF file size > 1MB if ( decoded_len > MAX_UDF_CONTENT_LENGTH) { cf_info(AS_INFO, "lua file size:%d > 1MB", decoded_len); cf_dyn_buf_append_string(out, "error=invalid_udf_content_len, lua file size > 1MB"); return 0; } char * decoded_str = cf_malloc(decoded_len); if ( ! cf_b64_validate_and_decode(udf_content, encoded_len, (uint8_t*)decoded_str, &decoded_len) ) { cf_info(AS_UDF, "invalid base64 content %s", filename); cf_dyn_buf_append_string(out, "error=invalid_base64_content"); cf_free(decoded_str); return 0; } decoded_str[decoded_len] = '\0'; as_module_error err; rc = as_module_validate(&mod_lua, NULL, filename, decoded_str, decoded_len, &err); cf_free(decoded_str); decoded_str = NULL; decoded_len = 0; if ( rc ) { cf_warning(AS_UDF, "udf-put: compile error: [%s:%d] %s", err.file, err.line, err.message); cf_dyn_buf_append_string(out, "error=compile_error"); cf_dyn_buf_append_string(out, ";file="); cf_dyn_buf_append_string(out, err.file); cf_dyn_buf_append_string(out, ";line="); cf_dyn_buf_append_uint32(out, err.line); uint32_t message_len = strlen(err.message); uint32_t enc_message_len = cf_b64_encoded_len(message_len); char enc_message[enc_message_len]; cf_b64_encode((const uint8_t*)err.message, message_len, enc_message); cf_dyn_buf_append_string(out, ";message="); cf_dyn_buf_append_buf(out, (uint8_t *)enc_message, enc_message_len); cf_free(udf_content); return 0; } // Create an empty JSON object json_t *udf_obj = 0; if (!(udf_obj = json_object())) { cf_warning(AS_UDF, "failed to create JSON array for receiving UDF"); if (udf_content) cf_free(udf_content); return -1; } int e = 0; e += json_object_set_new(udf_obj, "content64", json_string(udf_content)); e += json_object_set_new(udf_obj, "type", json_string(type)); e += json_object_set_new(udf_obj, "name", json_string(filename)); if (e) { cf_warning(AS_UDF, "could not encode UDF object, error %d", e); json_decref(udf_obj); if (udf_content) cf_free(udf_content); return(-1); } // make it into a string, yet another buffer copy char *udf_obj_str = json_dumps(udf_obj, 0/*flags*/); json_decref(udf_obj); udf_obj = 0; cf_debug(AS_UDF, "created json object %s", udf_obj_str); // how do I know whether to call create or add? e = as_smd_set_metadata(udf_smd_module_name, filename, udf_obj_str); if (e) { cf_warning(AS_UDF, "could not add UDF metadata, error %d", e); cf_free(udf_obj_str); if (udf_content) cf_free(udf_content); return(-1); } cf_info(AS_UDF, "UDF module '%s' (%s/%s) registered", filename, g_config.mod_lua.user_path, filename); // free the metadata cf_free(udf_obj_str); udf_obj_str = 0; if (udf_content) cf_free(udf_content); return 0; }