static NTSTATUS rpcint_dispatch(struct pipes_struct *p, TALLOC_CTX *mem_ctx, uint32_t opnum, const DATA_BLOB *in_data, DATA_BLOB *out_data) { struct pipe_rpc_fns *fns = find_pipe_fns_by_context(p->contexts, 0); uint32_t num_cmds = fns->n_cmds; const struct api_struct *cmds = fns->cmds; uint32_t i; bool ok; /* set opnum */ p->opnum = opnum; for (i = 0; i < num_cmds; i++) { if (cmds[i].opnum == opnum && cmds[i].fn != NULL) { break; } } if (i == num_cmds) { return NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE; } p->in_data.data = *in_data; p->out_data.rdata = data_blob_null; ok = cmds[i].fn(p); p->in_data.data = data_blob_null; if (!ok) { data_blob_free(&p->out_data.rdata); talloc_free_children(p->mem_ctx); return NT_STATUS_RPC_CALL_FAILED; } if (p->fault_state) { NTSTATUS status; status = NT_STATUS(p->fault_state); p->fault_state = 0; data_blob_free(&p->out_data.rdata); talloc_free_children(p->mem_ctx); return status; } *out_data = p->out_data.rdata; talloc_steal(mem_ctx, out_data->data); p->out_data.rdata = data_blob_null; talloc_free_children(p->mem_ctx); return NT_STATUS_OK; }
static void free_pipe_context(struct pipes_struct *p) { data_blob_free(&p->out_data.frag); data_blob_free(&p->out_data.rdata); data_blob_free(&p->in_data.data); DEBUG(3, ("free_pipe_context: " "destroying talloc pool of size %lu\n", (unsigned long)talloc_total_size(p->mem_ctx))); talloc_free_children(p->mem_ctx); }
static bool test_free_children(void) { void *root; const char *p1, *p2, *name, *name2; talloc_enable_null_tracking(); root = talloc_new(NULL); p1 = talloc_strdup(root, "foo1"); p2 = talloc_strdup(p1, "foo2"); talloc_set_name(p1, "%s", "testname"); talloc_free_children(p1); /* check its still a valid talloc ptr */ talloc_get_size(talloc_get_name(p1)); if (strcmp(talloc_get_name(p1), "testname") != 0) { return false; } talloc_set_name(p1, "%s", "testname"); name = talloc_get_name(p1); talloc_free_children(p1); /* check its still a valid talloc ptr */ talloc_get_size(talloc_get_name(p1)); torture_assert("name", name == talloc_get_name(p1), "name ptr changed"); torture_assert("namecheck", strcmp(talloc_get_name(p1), "testname") == 0, "wrong name"); CHECK_BLOCKS("name1", p1, 2); /* note that this does not free the old child name */ talloc_set_name_const(p1, "testname2"); name2 = talloc_get_name(p1); /* but this does */ talloc_free_children(p1); torture_assert("namecheck", strcmp(talloc_get_name(p1), "testname2") == 0, "wrong name"); CHECK_BLOCKS("name1", p1, 1); talloc_report_full(root, stdout); talloc_free(root); return true; }
static void free_pipe_context(pipes_struct *p) { if (p->mem_ctx) { DEBUG(3,("free_pipe_context: destroying talloc pool of size " "%lu\n", (unsigned long)talloc_total_size(p->mem_ctx) )); talloc_free_children(p->mem_ctx); } else { p->mem_ctx = talloc_init("pipe %s %p", p->name, p); if (p->mem_ctx == NULL) { p->fault_state = True; } } }
static void gen_inst(CTX *ctx, struct ir_inst *in) { struct ir_type res_t = in->result_type; bool is_void = type_is_void(res_t); // Don't write anything not needed. Note that void values are never actually // "used" by the generated C code, and instead are replaced with VOID_VAL. if (!ir_op_writes_side_effects(in->op) && !ir_op_is_branch(in->op)) { if (is_void) return; if (in->users_count == 0) return; // If it has 1 use, it can be generated inline. if (write_inline && in->users_count == 1) { // But if it crosses side effects, it must be generated earlier. // NOTE: if there are any not yet generated instructions with read // side-effects, we must generate the code before crossing // write side-effects as well. // Consider: t1=read; t2=neg(t1); call a(); call b(t2); // Mustn't turn into: call a(); call b(neg(read)); bool crosses_sideffects = false; if (has_outstanding_sideffect_reads(in)) { struct ir_inst *user= in->users[0]; for (struct ir_inst *cur = in; cur; cur = cur->next) { if (cur == user) break; if (ir_op_writes_side_effects(cur->op)) { crosses_sideffects = true; break; } } } if (!crosses_sideffects) return; } } set_loc(ctx, in->loc); indent(ctx); if (!TEST_UNION0(IR_TYPE, any, &res_t) && !is_void && in->users_count > 0) { if (in->scratch1_i == -1) in->scratch1_i = ctx->reg++; P(ctx, "%s %s = ", type(ctx, res_t), get_temp(ctx, in->scratch1_i)); } write_inst(ctx, in, false); fprintf(ctx->f, ";\n"); talloc_free_children(ctx->tmp); }
void print_notify_send_messages(struct messaging_context *msg_ctx, unsigned int timeout) { if (!print_notify_messages_pending()) return; if (!create_send_ctx()) return; while (print_notify_messages_pending()) print_notify_send_messages_to_printer( msg_ctx, notify_queue_head->msg->printer, timeout); talloc_free_children(send_ctx); num_messages = 0; }
/** Retrieve any errors from the SQL driver * * Retrieves errors from the driver from the last operation and writes them to * to request/global log, in the ERROR, WARN, INFO and DEBUG categories. * * @param inst Instance of rlm_sql. * @param request Current request, may be NULL. * @param handle Handle to retrieve errors for. * @param force_debug Force all errors to be logged as debug messages. */ void rlm_sql_print_error(rlm_sql_t *inst, REQUEST *request, rlm_sql_handle_t *handle, bool force_debug) { char const *driver; sql_log_entry_t log[20]; size_t num, i; num = (inst->module->sql_error)(handle->log_ctx, log, (sizeof(log) / sizeof(*log)), handle, inst->config); if (num == 0) { ROPTIONAL(RERROR, ERROR, "Unknown error"); return; } driver = inst->config->sql_driver_name; for (i = 0; i < num; i++) { if (force_debug) goto debug; switch (log[i].type) { case L_ERR: ROPTIONAL(RERROR, ERROR, "%s: %s", driver, log[i].msg); break; case L_WARN: ROPTIONAL(RWARN, WARN, "%s: %s", driver, log[i].msg); break; case L_INFO: ROPTIONAL(RINFO, INFO, "%s: %s", driver, log[i].msg); break; case L_DBG: default: debug: ROPTIONAL(RDEBUG, DEBUG, "%s: %s", driver, log[i].msg); break; } } talloc_free_children(handle->log_ctx); }
static int mod_detach(void *instance) { rlm_sql_t *inst = instance; if (inst->pool) fr_connection_pool_delete(inst->pool); /* * We need to explicitly free all children, so if the driver * parented any memory off the instance, their destructors * run before we unload the bytecode for them. * * If we don't do this, we get a SEGV deep inside the talloc code * when it tries to call a destructor that no longer exists. */ talloc_free_children(inst); /* * Decrements the reference count. The driver object won't be unloaded * until all instances of rlm_sql that use it have been destroyed. */ if (inst->handle) dlclose(inst->handle); return 0; }
struct vo *init_best_video_out(struct MPOpts *opts, struct vo_x11_state *x11, struct mp_fifo *key_fifo, struct input_ctx *input_ctx) { char **vo_list = opts->video_driver_list; int i; struct vo *vo = talloc_ptrtype(NULL, vo); struct vo initial_values = { .opts = opts, .x11 = x11, .key_fifo = key_fifo, .input_ctx = input_ctx, .event_fd = -1, .registered_fd = -1, }; // first try the preferred drivers, with their optional subdevice param: if (vo_list && vo_list[0]) while (vo_list[0][0]) { char *name = strdup(vo_list[0]); vo_subdevice = strchr(name,':'); if (!strcmp(name, "pgm")) mp_tmsg(MSGT_CPLAYER, MSGL_ERR, "The pgm video output driver has been replaced by -vo pnm:pgmyuv.\n"); if (!strcmp(name, "md5")) mp_tmsg(MSGT_CPLAYER, MSGL_ERR, "The md5 video output driver has been replaced by -vo md5sum.\n"); if (vo_subdevice) { vo_subdevice[0] = 0; ++vo_subdevice; } for (i = 0; video_out_drivers[i]; i++) { const struct vo_driver *video_driver = video_out_drivers[i]; const vo_info_t *info = video_driver->info; if (!strcmp(info->short_name, name)) { // name matches, try it *vo = initial_values; vo->driver = video_driver; if (!vo_preinit(vo, vo_subdevice)) { free(name); return vo; // success! } talloc_free_children(vo); } } // continue... free(name); ++vo_list; if (!(vo_list[0])) return NULL; // do NOT fallback to others } // now try the rest... vo_subdevice = NULL; for (i = 0; video_out_drivers[i]; i++) { const struct vo_driver *video_driver = video_out_drivers[i]; *vo = initial_values; vo->driver = video_driver; if (!vo_preinit(vo, vo_subdevice)) return vo; // success! talloc_free_children(vo); } free(vo); return NULL; } static int event_fd_callback(void *ctx, int fd) { struct vo *vo = ctx; vo_check_events(vo); return MP_INPUT_NOTHING; } int vo_config(struct vo *vo, uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t flags, char *title, uint32_t format) { struct MPOpts *opts = vo->opts; panscan_init(vo); aspect_save_orig(vo, width, height); aspect_save_prescale(vo, d_width, d_height); if (vo_control(vo, VOCTRL_UPDATE_SCREENINFO, NULL) == VO_TRUE) { aspect(vo, &d_width, &d_height, A_NOZOOM); vo->dx = (int)(opts->vo_screenwidth - d_width) / 2; vo->dy = (int)(opts->vo_screenheight - d_height) / 2; geometry(&vo->dx, &vo->dy, &d_width, &d_height, opts->vo_screenwidth, opts->vo_screenheight); geometry_xy_changed |= xinerama_screen >= 0; vo->dx += xinerama_x; vo->dy += xinerama_y; vo->dwidth = d_width; vo->dheight = d_height; } int ret = vo->driver->config(vo, width, height, d_width, d_height, flags, title, format); vo->config_ok = (ret == 0); vo->config_count += vo->config_ok; if (vo->registered_fd == -1 && vo->event_fd != -1 && vo->config_ok) { mp_input_add_key_fd(vo->input_ctx, vo->event_fd, 1, event_fd_callback, NULL, vo); vo->registered_fd = vo->event_fd; } return ret; } /** * \brief lookup an integer in a table, table must have 0 as the last key * \param key key to search for * \result translation corresponding to key or "to" value of last mapping * if not found. */ int lookup_keymap_table(const struct mp_keymap *map, int key) { while (map->from && map->from != key) map++; return map->to; } /** * \brief helper function for the kind of panscan-scaling that needs a source * and destination rectangle like Direct3D and VDPAU */ static void src_dst_split_scaling(int src_size, int dst_size, int scaled_src_size, int *src_start, int *src_end, int *dst_start, int *dst_end) { if (scaled_src_size > dst_size) { int border = src_size * (scaled_src_size - dst_size) / scaled_src_size; // round to a multiple of 2, this is at least needed for vo_direct3d and ATI cards border = (border / 2 + 1) & ~1; *src_start = border; *src_end = src_size - border; *dst_start = 0; *dst_end = dst_size; } else { *src_start = 0; *src_end = src_size; *dst_start = (dst_size - scaled_src_size) / 2; *dst_end = *dst_start + scaled_src_size; } } /** * Calculate the appropriate source and destination rectangle to * get a correctly scaled picture, including pan-scan. * Can be extended to take future cropping support into account. * * \param crop specifies the cropping border size in the left, right, top and bottom members, may be NULL * \param borders the border values as e.g. EOSD (ASS) and properly placed DVD highlight support requires, * may be NULL and only left and top are currently valid. */ void calc_src_dst_rects(struct vo *vo, int src_width, int src_height, struct vo_rect *src, struct vo_rect *dst, struct vo_rect *borders, const struct vo_rect *crop) { static const struct vo_rect no_crop = {0, 0, 0, 0, 0, 0}; int scaled_width = 0; int scaled_height = 0; if (!crop) crop = &no_crop; src_width -= crop->left + crop->right; src_height -= crop->top + crop->bottom; if (src_width < 2) src_width = 2; if (src_height < 2) src_height = 2; dst->left = 0; dst->right = vo->dwidth; dst->top = 0; dst->bottom = vo->dheight; src->left = 0; src->right = src_width; src->top = 0; src->bottom = src_height; if (borders) { borders->left = 0; borders->top = 0; } if (aspect_scaling()) { aspect(vo, &scaled_width, &scaled_height, A_WINZOOM); panscan_calc_windowed(vo); scaled_width += vo->panscan_x; scaled_height += vo->panscan_y; if (borders) { borders->left = (vo->dwidth - scaled_width ) / 2; borders->top = (vo->dheight - scaled_height) / 2; } src_dst_split_scaling(src_width, vo->dwidth, scaled_width, &src->left, &src->right, &dst->left, &dst->right); src_dst_split_scaling(src_height, vo->dheight, scaled_height, &src->top, &src->bottom, &dst->top, &dst->bottom); } src->left += crop->left; src->right += crop->left; src->top += crop->top; src->bottom += crop->top; src->width = src->right - src->left; src->height = src->bottom - src->top; dst->width = dst->right - dst->left; dst->height = dst->bottom - dst->top; } /** * Generates a mouse movement message if those are enable and sends it * to the "main" MPlayer. * * \param posx new x position of mouse * \param posy new y position of mouse */ void vo_mouse_movement(struct vo *vo, int posx, int posy) { char cmd_str[40]; if (!enable_mouse_movements) return; snprintf(cmd_str, sizeof(cmd_str), "set_mouse_pos %i %i", posx, posy); mp_input_queue_cmd(vo->input_ctx, mp_input_parse_cmd(cmd_str)); }
/** Create and insert a cache entry * * @return * - #RLM_MODULE_OK on success. * - #RLM_MODULE_UPDATED if we merged the cache entry. * - #RLM_MODULE_FAIL on failure. */ static rlm_rcode_t cache_insert(rlm_cache_t const *inst, REQUEST *request, rlm_cache_handle_t **handle, uint8_t const *key, size_t key_len, int ttl) { vp_map_t const *map; vp_map_t **last, *c_map; VALUE_PAIR *vp; bool merge = false; rlm_cache_entry_t *c; size_t len; TALLOC_CTX *pool; if ((inst->config.max_entries > 0) && inst->driver->count && (inst->driver->count(&inst->config, inst->driver_inst->data, request, handle) > inst->config.max_entries)) { RWDEBUG("Cache is full: %d entries", inst->config.max_entries); return RLM_MODULE_FAIL; } c = cache_alloc(inst, request); if (!c) return RLM_MODULE_FAIL; c->key = talloc_memdup(c, key, key_len); c->key_len = key_len; c->created = c->expires = request->packet->timestamp.tv_sec; c->expires += ttl; last = &c->maps; RDEBUG2("Creating new cache entry"); /* * Alloc a pool so we don't have excessive allocs when * gathering VALUE_PAIRs to cache. */ pool = talloc_pool(NULL, 2048); for (map = inst->maps; map != NULL; map = map->next) { VALUE_PAIR *to_cache = NULL; fr_cursor_t cursor; rad_assert(map->lhs && map->rhs); /* * Calling map_to_vp gives us exactly the same result, * as if this were an update section. */ if (map_to_vp(pool, &to_cache, request, map, NULL) < 0) { RDEBUG2("Skipping %s", map->rhs->name); continue; } for (vp = fr_cursor_init(&cursor, &to_cache); vp; vp = fr_cursor_next(&cursor)) { /* * Prevent people from accidentally caching * cache control attributes. */ if (map->rhs->type == TMPL_TYPE_LIST) switch (vp->da->attr) { case FR_CACHE_TTL: case FR_CACHE_STATUS_ONLY: case FR_CACHE_MERGE_NEW: case FR_CACHE_ENTRY_HITS: RDEBUG2("Skipping %s", vp->da->name); continue; default: break; } RINDENT(); if (RDEBUG_ENABLED2) map_debug_log(request, map, vp); REXDENT(); MEM(c_map = talloc_zero(c, vp_map_t)); c_map->op = map->op; /* * Now we turn the VALUE_PAIRs into maps. */ switch (map->lhs->type) { /* * Attributes are easy, reuse the LHS, and create a new * RHS with the fr_value_box_t from the VALUE_PAIR. */ case TMPL_TYPE_ATTR: c_map->lhs = map->lhs; /* lhs shouldn't be touched, so this is ok */ do_rhs: MEM(c_map->rhs = tmpl_init(talloc(c_map, vp_tmpl_t), TMPL_TYPE_DATA, map->rhs->name, map->rhs->len, T_BARE_WORD)); if (fr_value_box_copy(c_map->rhs, &c_map->rhs->tmpl_value, &vp->data) < 0) { REDEBUG("Failed copying attribute value"); error: talloc_free(pool); talloc_free(c); return RLM_MODULE_FAIL; } c_map->rhs->tmpl_value_type = vp->vp_type; if (vp->vp_type == FR_TYPE_STRING) { c_map->rhs->quote = is_printable(vp->vp_strvalue, vp->vp_length) ? T_SINGLE_QUOTED_STRING : T_DOUBLE_QUOTED_STRING; } break; /* * Lists are weird... We need to fudge a new LHS template, * which is a combination of the LHS list and the attribute. */ case TMPL_TYPE_LIST: { char attr[256]; MEM(c_map->lhs = tmpl_init(talloc(c_map, vp_tmpl_t), TMPL_TYPE_ATTR, map->lhs->name, map->lhs->len, T_BARE_WORD)); c_map->lhs->tmpl_da = vp->da; if (vp->da->flags.is_unknown) { /* for tmpl_verify() */ c_map->lhs->tmpl_unknown = fr_dict_unknown_acopy(c_map->lhs, vp->da); c_map->lhs->tmpl_da = c_map->lhs->tmpl_unknown; } c_map->lhs->tmpl_tag = vp->tag; c_map->lhs->tmpl_list = map->lhs->tmpl_list; c_map->lhs->tmpl_num = map->lhs->tmpl_num; c_map->lhs->tmpl_request = map->lhs->tmpl_request; /* * We need to rebuild the attribute name, to be the * one we copied from the source list. */ len = tmpl_snprint(attr, sizeof(attr), c_map->lhs); if (is_truncated(len, sizeof(attr))) { REDEBUG("Serialized attribute too long. Must be < " STRINGIFY(sizeof(attr)) " bytes, got %zu bytes", len); goto error; } c_map->lhs->len = len; c_map->lhs->name = talloc_typed_strdup(c_map->lhs, attr); } goto do_rhs; default: rad_assert(0); } *last = c_map; last = &(*last)->next; } talloc_free_children(pool); /* reset pool state */ } talloc_free(pool); /* * Check to see if we need to merge the entry into the request */ vp = fr_pair_find_by_da(request->control, attr_cache_merge_new, TAG_ANY); if (vp && vp->vp_bool) merge = true; if (merge) cache_merge(inst, request, c); for (;;) { cache_status_t ret; ret = inst->driver->insert(&inst->config, inst->driver_inst->data, request, *handle, c); switch (ret) { case CACHE_RECONNECT: if (cache_reconnect(handle, inst, request) == 0) continue; return RLM_MODULE_FAIL; case CACHE_OK: RDEBUG2("Committed entry, TTL %d seconds", ttl); cache_free(inst, &c); return merge ? RLM_MODULE_UPDATED : RLM_MODULE_OK; default: talloc_free(c); /* Failed insertion - use talloc_free not the driver free */ return RLM_MODULE_FAIL; } } }
static void print_notify_send_messages_to_printer(struct messaging_context *msg_ctx, const char *printer, unsigned int timeout) { char *buf; struct notify_queue *pq, *pq_next; size_t msg_count = 0, offset = 0; size_t num_pids = 0; size_t i; pid_t *pid_list = NULL; struct timeval end_time = timeval_zero(); /* Count the space needed to send the messages. */ for (pq = notify_queue_head; pq; pq = pq->next) { if (strequal(printer, pq->msg->printer)) { if (!flatten_message(pq)) { DEBUG(0,("print_notify_send_messages: Out of memory\n")); talloc_free_children(send_ctx); num_messages = 0; return; } offset += (pq->buflen + 4); msg_count++; } } offset += 4; /* For count. */ buf = (char *)TALLOC(send_ctx, offset); if (!buf) { DEBUG(0,("print_notify_send_messages: Out of memory\n")); talloc_free_children(send_ctx); num_messages = 0; return; } offset = 0; SIVAL(buf,offset,msg_count); offset += 4; for (pq = notify_queue_head; pq; pq = pq_next) { pq_next = pq->next; if (strequal(printer, pq->msg->printer)) { SIVAL(buf,offset,pq->buflen); offset += 4; memcpy(buf + offset, pq->buf, pq->buflen); offset += pq->buflen; /* Remove from list. */ DLIST_REMOVE(notify_queue_head, pq); } } DEBUG(5, ("print_notify_send_messages_to_printer: sending %lu print notify message%s to printer %s\n", (unsigned long)msg_count, msg_count != 1 ? "s" : "", printer)); /* * Get the list of PID's to send to. */ if (!print_notify_pid_list(printer, send_ctx, &num_pids, &pid_list)) return; if (timeout != 0) { end_time = timeval_current_ofs(timeout, 0); } for (i = 0; i < num_pids; i++) { messaging_send_buf(msg_ctx, pid_to_procid(pid_list[i]), MSG_PRINTER_NOTIFY2 | MSG_FLAG_LOWPRIORITY, (uint8 *)buf, offset); if ((timeout != 0) && timeval_expired(&end_time)) { break; } } }
int m_config_parse(m_config_t *config, const char *location, bstr data, char *initial_section, int flags) { m_profile_t *profile = m_config_add_profile(config, initial_section); void *tmp = talloc_new(NULL); int line_no = 0; int errors = 0; bstr_eatstart0(&data, "\xEF\xBB\xBF"); // skip BOM while (data.len) { talloc_free_children(tmp); bool ok = false; line_no++; char loc[512]; snprintf(loc, sizeof(loc), "%s:%d:", location, line_no); bstr line = bstr_strip_linebreaks(bstr_getline(data, &data)); if (!skip_ws(&line)) continue; // Profile declaration if (bstr_eatstart0(&line, "[")) { bstr profilename; if (!bstr_split_tok(line, "]", &profilename, &line)) { MP_ERR(config, "%s missing closing ]\n", loc); goto error; } if (skip_ws(&line)) { MP_ERR(config, "%s unparseable extra characters: '%.*s'\n", loc, BSTR_P(line)); goto error; } profile = m_config_add_profile(config, bstrto0(tmp, profilename)); continue; } bstr_eatstart0(&line, "--"); bstr option = line; while (line.len && (mp_isalnum(line.start[0]) || line.start[0] == '_' || line.start[0] == '-')) line = bstr_cut(line, 1); option.len = option.len - line.len; skip_ws(&line); bstr value = {0}; if (bstr_eatstart0(&line, "=")) { skip_ws(&line); if (line.len && (line.start[0] == '"' || line.start[0] == '\'')) { // Simple quoting, like "value" char term[2] = {line.start[0], 0}; line = bstr_cut(line, 1); if (!bstr_split_tok(line, term, &value, &line)) { MP_ERR(config, "%s unterminated quote\n", loc); goto error; } } else if (bstr_eatstart0(&line, "%")) { // Quoting with length, like %5%value bstr rest; long long len = bstrtoll(line, &rest, 10); if (rest.len == line.len || !bstr_eatstart0(&rest, "%") || len > rest.len) { MP_ERR(config, "%s fixed-length quoting expected - put " "\"quotes\" around the option value if you did not " "intend to use this, but your option value starts " "with '%%'\n", loc); goto error; } value = bstr_splice(rest, 0, len); line = bstr_cut(rest, len); } else { // No quoting; take everything until the comment or end of line int end = bstrchr(line, '#'); value = bstr_strip(end < 0 ? line : bstr_splice(line, 0, end)); line.len = 0; } } if (skip_ws(&line)) { MP_ERR(config, "%s unparseable extra characters: '%.*s'\n", loc, BSTR_P(line)); goto error; } int res; if (profile) { if (bstr_equals0(option, "profile-desc")) { m_profile_set_desc(profile, value); res = 0; } else { res = m_config_set_profile_option(config, profile, option, value); } } else { res = m_config_set_option_ext(config, option, value, flags); } if (res < 0) { MP_ERR(config, "%s setting option %.*s='%.*s' failed.\n", loc, BSTR_P(option), BSTR_P(value)); goto error; } ok = true; error: if (!ok) errors++; if (errors > 16) { MP_ERR(config, "%s: too many errors, stopping.\n", location); break; } } talloc_free(tmp); return 1; }
errno_t nss_protocol_fill_pwent(struct nss_ctx *nss_ctx, struct nss_cmd_ctx *cmd_ctx, struct sss_packet *packet, struct cache_req_result *result) { TALLOC_CTX *tmp_ctx; struct ldb_message *msg; struct sized_string pwfield; struct sized_string *name; struct sized_string gecos; struct sized_string homedir; struct sized_string shell; uint32_t gid; uint32_t uid; uint32_t num_results; size_t rp; size_t body_len; uint8_t *body; int i; errno_t ret; tmp_ctx = talloc_new(NULL); if (tmp_ctx == NULL) { return ENOMEM; } /* First two fields (length and reserved), filled up later. */ ret = sss_packet_grow(packet, 2 * sizeof(uint32_t)); if (ret != EOK) { return ret; } rp = 2 * sizeof(uint32_t); num_results = 0; for (i = 0; i < result->count; i++) { talloc_free_children(tmp_ctx); msg = result->msgs[i]; /* Password field content. */ to_sized_string(&pwfield, nss_get_pwfield(nss_ctx, result->domain)); ret = nss_get_pwent(tmp_ctx, nss_ctx, result->domain, msg, &uid, &gid, &name, &gecos, &homedir, &shell); if (ret != EOK) { continue; } /* Adjust packet size: uid, gid + string fields. */ ret = sss_packet_grow(packet, 2 * sizeof(uint32_t) + name->len + gecos.len + homedir.len + shell.len + pwfield.len); if (ret != EOK) { goto done; } sss_packet_get_body(packet, &body, &body_len); /* Fill packet. */ SAFEALIGN_SET_UINT32(&body[rp], uid, &rp); SAFEALIGN_SET_UINT32(&body[rp], gid, &rp); SAFEALIGN_SET_STRING(&body[rp], name->str, name->len, &rp); SAFEALIGN_SET_STRING(&body[rp], pwfield.str, pwfield.len, &rp); SAFEALIGN_SET_STRING(&body[rp], gecos.str, gecos.len, &rp); SAFEALIGN_SET_STRING(&body[rp], homedir.str, homedir.len, &rp); SAFEALIGN_SET_STRING(&body[rp], shell.str, shell.len, &rp); num_results++; /* Do not store entry in memory cache during enumeration or when * requested. */ if (!cmd_ctx->enumeration && (cmd_ctx->flags & SSS_NSS_EX_FLAG_INVALIDATE_CACHE) == 0) { ret = sss_mmap_cache_pw_store(&nss_ctx->pwd_mc_ctx, name, &pwfield, uid, gid, &gecos, &homedir, &shell); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, "Failed to store user %s (%s) in mmap cache [%d]: %s!\n", name->str, result->domain->name, ret, sss_strerror(ret)); } } } ret = EOK; done: talloc_free(tmp_ctx); if (ret != EOK) { sss_packet_set_size(packet, 0); return ret; } sss_packet_get_body(packet, &body, &body_len); SAFEALIGN_COPY_UINT32(body, &num_results, NULL); SAFEALIGN_SETMEM_UINT32(body + sizeof(uint32_t), 0, NULL); /* reserved */ return EOK; }
/* measure the speed of talloc versus malloc */ static bool test_speed(void) { void *ctx = talloc_new(NULL); unsigned count; const int loop = 1000; int i; struct timeval tv; printf("test: speed\n# TALLOC VS MALLOC SPEED\n"); tv = timeval_current(); count = 0; do { void *p1, *p2, *p3; for (i=0;i<loop;i++) { p1 = talloc_size(ctx, loop % 100); p2 = talloc_strdup(p1, "foo bar"); p3 = talloc_size(p1, 300); talloc_free(p1); } count += 3 * loop; } while (timeval_elapsed(&tv) < 5.0); fprintf(stderr, "talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv)); talloc_free(ctx); ctx = talloc_pool(NULL, 1024); tv = timeval_current(); count = 0; do { void *p1, *p2, *p3; for (i=0;i<loop;i++) { p1 = talloc_size(ctx, loop % 100); p2 = talloc_strdup(p1, "foo bar"); p3 = talloc_size(p1, 300); talloc_free_children(ctx); } count += 3 * loop; } while (timeval_elapsed(&tv) < 5.0); talloc_free(ctx); fprintf(stderr, "talloc_pool: %.0f ops/sec\n", count/timeval_elapsed(&tv)); tv = timeval_current(); count = 0; do { void *p1, *p2, *p3; for (i=0;i<loop;i++) { p1 = malloc(loop % 100); p2 = strdup("foo bar"); p3 = malloc(300); free(p1); free(p2); free(p3); } count += 3 * loop; } while (timeval_elapsed(&tv) < 5.0); fprintf(stderr, "malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv)); printf("success: speed\n"); return true; }
/** Create and insert a cache entry. * * @return * - #RLM_MODULE_OK on success. * - #RLM_MODULE_UPDATED if we merged the cache entry. * - #RLM_MODULE_FAIL on failure. */ static rlm_rcode_t cache_insert(rlm_cache_t *inst, REQUEST *request, rlm_cache_handle_t **handle, char const *key, int ttl) { vp_map_t const *map; vp_map_t **last, *c_map; VALUE_PAIR *vp; bool merge = false; rlm_cache_entry_t *c; TALLOC_CTX *pool; if ((inst->max_entries > 0) && inst->module->count && (inst->module->count(inst, request, handle) > inst->max_entries)) { RWDEBUG("Cache is full: %d entries", inst->max_entries); return RLM_MODULE_FAIL; } c = cache_alloc(inst, request); if (!c) return RLM_MODULE_FAIL; c->key = talloc_typed_strdup(c, key); c->created = c->expires = request->timestamp; c->expires += ttl; last = &c->maps; RDEBUG("Creating new cache entry"); /* * Alloc a pool so we don't have excessive mallocs when * gathering VALUE_PAIRs to cache. */ pool = talloc_pool(NULL, 1024); for (map = inst->maps; map != NULL; map = map->next) { VALUE_PAIR *to_cache = NULL; vp_cursor_t cursor; rad_assert(map->lhs && map->rhs); /* * Calling map_to_vp gives us exactly the same result, * as if this were an update section. */ if (map_to_vp(pool, &to_cache, request, map, NULL) < 0) { RDEBUG("Skipping %s", map->rhs->name); continue; } for (vp = fr_cursor_init(&cursor, &to_cache); vp; vp = fr_cursor_next(&cursor)) { /* * Prevent people from accidentally caching * cache control attributes. */ if (map->rhs->type == TMPL_TYPE_LIST) switch (vp->da->attr) { case PW_CACHE_TTL: case PW_CACHE_STATUS_ONLY: case PW_CACHE_READ_ONLY: case PW_CACHE_MERGE: case PW_CACHE_ENTRY_HITS: RDEBUG2("Skipping %s", vp->da->name); continue; default: break; } RINDENT(); if (RDEBUG_ENABLED2) map_debug_log(request, map, vp); REXDENT(); MEM(c_map = talloc_zero(c, vp_map_t)); c_map->op = map->op; /* * Now we turn the VALUE_PAIRs into maps. */ switch (map->lhs->type) { /* * Attributes are easy, reuse the LHS, and create a new * RHS with the value_data_t from the VALUE_PAIR. */ case TMPL_TYPE_ATTR: c_map->lhs = map->lhs; /* lhs shouldn't be touched, so this is ok */ do_rhs: MEM(c_map->rhs = tmpl_init(talloc(c_map, vp_tmpl_t), TMPL_TYPE_DATA, map->rhs->name, map->rhs->len)); if (value_data_copy(c_map->rhs, &c_map->rhs->tmpl_data_value, vp->da->type, &vp->data) < 0) { REDEBUG("Failed copying attribute value"); talloc_free(pool); talloc_free(c); return RLM_MODULE_FAIL; } c_map->rhs->tmpl_data_type = vp->da->type; break; /* * Lists are weird... We need to fudge a new LHS template, * which is a combination of the LHS list and the attribute. */ case TMPL_TYPE_LIST: { char attr[256]; MEM(c_map->lhs = tmpl_init(talloc(c_map, vp_tmpl_t), TMPL_TYPE_ATTR, map->lhs->name, map->lhs->len)); c_map->lhs->tmpl_da = vp->da; c_map->lhs->tmpl_tag = vp->tag; c_map->lhs->tmpl_list = map->lhs->tmpl_list; c_map->lhs->tmpl_num = map->lhs->tmpl_num; c_map->lhs->tmpl_request = map->lhs->tmpl_request; /* * We need to rebuild the attribute name, to be the * one we copied from the source list. */ c_map->lhs->len = tmpl_prints(attr, sizeof(attr), c_map->lhs, NULL); c_map->lhs->name = talloc_strdup(map->lhs, attr); } goto do_rhs; default: rad_assert(0); } *last = c_map; last = &(*last)->next; } talloc_free_children(pool); /* reset pool state */ } talloc_free(pool); /* * Check to see if we need to merge the entry into the request */ vp = pairfind(request->config, PW_CACHE_MERGE, 0, TAG_ANY); if (vp && (vp->vp_integer > 0)) merge = true; if (merge) cache_merge(inst, request, c); for (;;) { cache_status_t ret; ret = inst->module->insert(inst, request, handle, c); switch (ret) { case CACHE_RECONNECT: if (cache_reconnect(inst, request, handle) == 0) continue; return RLM_MODULE_FAIL; case CACHE_OK: RDEBUG("Commited entry, TTL %d seconds", ttl); cache_free(inst, &c); return merge ? RLM_MODULE_UPDATED : RLM_MODULE_OK; default: talloc_free(c); /* Failed insertion - use talloc_free not the driver free */ return RLM_MODULE_FAIL; } } }