2009-02-13 15:43:04 +01:00
/*
Unix SMB / CIFS implementation .
Infrastructure for async requests
Copyright ( C ) Volker Lendecke 2008
2009-02-13 15:37:35 +01:00
Copyright ( C ) Stefan Metzmacher 2009
2009-02-13 15:43:04 +01:00
2009-02-16 08:52:06 +01:00
* * NOTE ! The following LGPL license applies to the tevent
* * library . This does NOT imply that all of Samba is released
* * under the LGPL
2009-02-13 15:43:04 +01:00
2009-02-16 08:52:06 +01:00
This library is free software ; you can redistribute it and / or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation ; either
version 3 of the License , or ( at your option ) any later version .
This library is distributed in the hope that it will be useful ,
2009-02-13 15:43:04 +01:00
but WITHOUT ANY WARRANTY ; without even the implied warranty of
2009-02-16 08:52:06 +01:00
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
Lesser General Public License for more details .
2009-02-13 15:43:04 +01:00
2009-02-16 08:52:06 +01:00
You should have received a copy of the GNU Lesser General Public
License along with this library ; if not , see < http : //www.gnu.org/licenses/>.
2009-02-13 15:43:04 +01:00
*/
2009-02-13 15:37:35 +01:00
# include "replace.h"
# include "tevent.h"
# include "tevent_internal.h"
# include "tevent_util.h"
2009-02-13 15:43:04 +01:00
2023-04-24 15:04:06 +02:00
# undef tevent_req_set_callback
2023-05-23 06:38:27 +02:00
# undef tevent_req_set_cancel_fn
2023-05-23 06:39:06 +02:00
# undef tevent_req_set_cleanup_fn
2023-04-24 15:04:06 +02:00
2009-02-25 14:29:31 +01:00
char * tevent_req_default_print ( struct tevent_req * req , TALLOC_CTX * mem_ctx )
2009-02-13 15:43:04 +01:00
{
2009-02-13 15:37:35 +01:00
return talloc_asprintf ( mem_ctx ,
" tevent_req[%p/%s]: state[%d] error[%lld (0x%llX)] "
2017-06-14 16:59:10 +02:00
" state[%s (%p)] timer[%p] finish[%s] " ,
2009-03-17 20:13:34 +01:00
req , req - > internal . create_location ,
2009-02-13 15:37:35 +01:00
req - > internal . state ,
( unsigned long long ) req - > internal . error ,
( unsigned long long ) req - > internal . error ,
2017-07-20 14:16:44 +02:00
req - > internal . private_type ,
2009-02-28 15:44:30 -05:00
req - > data ,
2017-06-14 16:59:10 +02:00
req - > internal . timer ,
req - > internal . finish_location
2009-02-13 15:37:35 +01:00
) ;
2009-02-13 15:43:04 +01:00
}
2009-02-25 14:29:31 +01:00
char * tevent_req_print ( TALLOC_CTX * mem_ctx , struct tevent_req * req )
{
2017-07-20 14:20:03 +02:00
if ( req = = NULL ) {
return talloc_strdup ( mem_ctx , " tevent_req[NULL] " ) ;
}
2009-02-25 14:29:31 +01:00
if ( ! req - > private_print ) {
return tevent_req_default_print ( req , mem_ctx ) ;
}
return req - > private_print ( req , mem_ctx ) ;
}
2013-09-27 03:41:29 +02:00
static int tevent_req_destructor ( struct tevent_req * req ) ;
2009-02-13 15:37:35 +01:00
struct tevent_req * _tevent_req_create ( TALLOC_CTX * mem_ctx ,
2009-02-28 15:44:30 -05:00
void * pdata ,
size_t data_size ,
2009-02-13 15:37:35 +01:00
const char * type ,
const char * location )
2022-06-18 10:57:11 +02:00
{
return __tevent_req_create ( mem_ctx ,
pdata ,
data_size ,
type ,
NULL ,
location ) ;
}
struct tevent_req * __tevent_req_create ( TALLOC_CTX * mem_ctx ,
void * pdata ,
size_t data_size ,
const char * type ,
const char * func ,
const char * location )
2009-02-13 15:43:04 +01:00
{
2009-02-13 15:37:35 +01:00
struct tevent_req * req ;
2018-05-02 14:01:56 +02:00
struct tevent_req * parent ;
2009-02-28 15:44:30 -05:00
void * * ppdata = ( void * * ) pdata ;
void * data ;
2016-07-22 16:12:25 +02:00
size_t payload ;
payload = sizeof ( struct tevent_immediate ) + data_size ;
if ( payload < sizeof ( struct tevent_immediate ) ) {
/* overflow */
return NULL ;
}
2009-02-13 15:37:35 +01:00
2013-09-06 15:37:56 -07:00
req = talloc_pooled_object (
mem_ctx , struct tevent_req , 2 ,
sizeof ( struct tevent_immediate ) + data_size ) ;
2009-02-13 15:37:35 +01:00
if ( req = = NULL ) {
return NULL ;
}
2016-07-22 16:06:45 +02:00
* req = ( struct tevent_req ) {
2019-01-14 11:59:59 +01:00
. internal = {
. private_type = type ,
. create_location = location ,
. state = TEVENT_REQ_IN_PROGRESS ,
. trigger = tevent_create_immediate ( req ) ,
} ,
2016-07-22 16:06:45 +02:00
} ;
2009-07-14 16:54:01 -07:00
data = talloc_zero_size ( req , data_size ) ;
2016-07-22 16:06:45 +02:00
/*
* No need to check for req - > internal . trigger ! = NULL or
* data ! = NULL , this can ' t fail : talloc_pooled_object has
* already allocated sufficient memory .
*/
2009-02-28 15:44:30 -05:00
talloc_set_name_const ( data , type ) ;
2009-02-13 15:37:35 +01:00
2009-02-28 15:44:30 -05:00
req - > data = data ;
2009-02-13 15:37:35 +01:00
2013-09-27 03:41:29 +02:00
talloc_set_destructor ( req , tevent_req_destructor ) ;
2018-05-02 14:01:56 +02:00
parent = talloc_get_type ( talloc_parent ( mem_ctx ) , struct tevent_req ) ;
if ( ( parent ! = NULL ) & & ( parent - > internal . profile ! = NULL ) ) {
bool ok = tevent_req_set_profile ( req ) ;
if ( ! ok ) {
TALLOC_FREE ( req ) ;
return NULL ;
}
req - > internal . profile - > parent = parent - > internal . profile ;
DLIST_ADD_END ( parent - > internal . profile - > subprofiles ,
req - > internal . profile ) ;
}
2009-02-28 15:44:30 -05:00
* ppdata = data ;
2022-06-16 16:23:22 +02:00
/* Initially, talloc_zero_size() sets internal.call_depth to 0 */
2023-05-02 21:57:16 +02:00
if ( parent ! = NULL ) {
2022-06-16 16:23:22 +02:00
req - > internal . call_depth = parent - > internal . call_depth + 1 ;
}
2023-05-02 21:57:16 +02:00
tevent_thread_call_depth_notify ( TEVENT_CALL_FLOW_REQ_CREATE ,
req ,
req - > internal . call_depth ,
func ) ;
2022-06-16 16:23:22 +02:00
2009-02-13 15:37:35 +01:00
return req ;
2009-02-13 15:43:04 +01:00
}
2013-09-27 03:41:29 +02:00
static int tevent_req_destructor ( struct tevent_req * req )
{
tevent_req_received ( req ) ;
return 0 ;
}
2009-06-04 17:26:23 +02:00
void _tevent_req_notify_callback ( struct tevent_req * req , const char * location )
2009-02-13 15:43:04 +01:00
{
2009-03-17 20:13:34 +01:00
req - > internal . finish_location = location ;
2011-07-08 15:54:51 +02:00
if ( req - > internal . defer_callback_ev ) {
( void ) tevent_req_post ( req , req - > internal . defer_callback_ev ) ;
req - > internal . defer_callback_ev = NULL ;
return ;
}
2009-02-13 15:43:04 +01:00
if ( req - > async . fn ! = NULL ) {
2022-06-16 16:23:22 +02:00
/* Calling back the parent code, decrement the call depth. */
2023-05-02 21:57:16 +02:00
size_t new_depth = req - > internal . call_depth > 0 ?
req - > internal . call_depth - 1 : 0 ;
tevent_thread_call_depth_notify ( TEVENT_CALL_FLOW_REQ_NOTIFY_CB ,
req ,
new_depth ,
req - > async . fn_name ) ;
2009-02-13 15:43:04 +01:00
req - > async . fn ( req ) ;
}
}
2013-09-27 02:29:57 +02:00
static void tevent_req_cleanup ( struct tevent_req * req )
{
if ( req - > private_cleanup . state > = req - > internal . state ) {
/*
* Don ' t call the cleanup_function multiple times for the same
* state recursively
*/
return ;
}
2023-05-02 21:57:16 +02:00
tevent_thread_call_depth_notify ( TEVENT_CALL_FLOW_REQ_CLEANUP ,
req ,
req - > internal . call_depth ,
req - > private_cleanup . fn_name ) ;
if ( req - > private_cleanup . fn = = NULL ) {
return ;
}
2013-09-27 02:29:57 +02:00
req - > private_cleanup . state = req - > internal . state ;
req - > private_cleanup . fn ( req , req - > internal . state ) ;
}
2009-06-04 17:26:23 +02:00
static void tevent_req_finish ( struct tevent_req * req ,
enum tevent_req_state state ,
const char * location )
{
2018-05-02 14:01:56 +02:00
struct tevent_req_profile * p ;
2011-09-17 19:53:55 +02:00
/*
* make sure we do not timeout after
* the request was already finished
*/
TALLOC_FREE ( req - > internal . timer ) ;
2009-06-04 17:26:23 +02:00
req - > internal . state = state ;
2013-09-27 02:29:57 +02:00
req - > internal . finish_location = location ;
tevent_req_cleanup ( req ) ;
2018-05-02 14:01:56 +02:00
p = req - > internal . profile ;
if ( p ! = NULL ) {
p - > stop_location = location ;
p - > stop_time = tevent_timeval_current ( ) ;
p - > state = state ;
p - > user_error = req - > internal . error ;
if ( p - > parent ! = NULL ) {
talloc_steal ( p - > parent , p ) ;
req - > internal . profile = NULL ;
}
}
2009-06-04 17:26:23 +02:00
_tevent_req_notify_callback ( req , location ) ;
}
2009-03-17 20:13:34 +01:00
void _tevent_req_done ( struct tevent_req * req ,
const char * location )
2009-02-13 15:43:04 +01:00
{
2009-03-17 20:13:34 +01:00
tevent_req_finish ( req , TEVENT_REQ_DONE , location ) ;
2009-02-13 15:43:04 +01:00
}
2009-03-17 20:13:34 +01:00
bool _tevent_req_error ( struct tevent_req * req ,
uint64_t error ,
const char * location )
2009-02-13 15:43:04 +01:00
{
2009-02-13 15:37:35 +01:00
if ( error = = 0 ) {
return false ;
2009-02-13 15:43:04 +01:00
}
2009-02-13 15:37:35 +01:00
req - > internal . error = error ;
2009-03-17 20:13:34 +01:00
tevent_req_finish ( req , TEVENT_REQ_USER_ERROR , location ) ;
2009-02-13 15:37:35 +01:00
return true ;
2009-02-13 15:43:04 +01:00
}
2011-06-19 20:55:46 +02:00
void _tevent_req_oom ( struct tevent_req * req , const char * location )
{
tevent_req_finish ( req , TEVENT_REQ_NO_MEMORY , location ) ;
}
2009-03-17 20:13:34 +01:00
bool _tevent_req_nomem ( const void * p ,
struct tevent_req * req ,
const char * location )
2009-02-13 15:43:04 +01:00
{
if ( p ! = NULL ) {
return false ;
}
2011-06-19 20:55:46 +02:00
_tevent_req_oom ( req , location ) ;
2009-02-13 15:43:04 +01:00
return true ;
}
/**
2010-01-14 14:41:49 +01:00
* @ internal
*
* @ brief Immediate event callback .
*
* @ param [ in ] ev The event context to use .
*
* @ param [ in ] im The immediate event .
*
* @ param [ in ] priv The async request to be finished .
2009-02-13 15:37:35 +01:00
*/
static void tevent_req_trigger ( struct tevent_context * ev ,
2009-03-17 10:18:34 +01:00
struct tevent_immediate * im ,
2009-02-13 15:37:35 +01:00
void * private_data )
{
2013-12-05 08:47:27 +01:00
struct tevent_req * req =
talloc_get_type_abort ( private_data ,
struct tevent_req ) ;
2009-02-13 15:37:35 +01:00
2009-03-17 20:13:34 +01:00
tevent_req_finish ( req , req - > internal . state ,
req - > internal . finish_location ) ;
2009-02-13 15:37:35 +01:00
}
struct tevent_req * tevent_req_post ( struct tevent_req * req ,
struct tevent_context * ev )
2009-02-13 15:43:04 +01:00
{
2009-03-17 10:18:34 +01:00
tevent_schedule_immediate ( req - > internal . trigger ,
ev , tevent_req_trigger , req ) ;
2009-02-13 15:37:35 +01:00
return req ;
2009-02-13 15:43:04 +01:00
}
2011-07-08 15:54:51 +02:00
void tevent_req_defer_callback ( struct tevent_req * req ,
struct tevent_context * ev )
{
req - > internal . defer_callback_ev = ev ;
}
2009-02-13 15:37:35 +01:00
bool tevent_req_is_in_progress ( struct tevent_req * req )
2009-02-13 15:43:04 +01:00
{
2009-02-13 15:37:35 +01:00
if ( req - > internal . state = = TEVENT_REQ_IN_PROGRESS ) {
return true ;
}
2009-02-13 15:43:04 +01:00
2009-02-13 15:37:35 +01:00
return false ;
2009-02-13 15:43:04 +01:00
}
2009-03-10 13:54:57 +01:00
void tevent_req_received ( struct tevent_req * req )
{
2013-09-27 03:41:29 +02:00
talloc_set_destructor ( req , NULL ) ;
2009-03-10 13:54:57 +01:00
req - > private_print = NULL ;
2023-05-23 06:38:27 +02:00
req - > private_cancel . fn = NULL ;
req - > private_cancel . fn_name = NULL ;
2009-03-10 13:54:57 +01:00
2009-03-17 10:17:50 +01:00
TALLOC_FREE ( req - > internal . trigger ) ;
TALLOC_FREE ( req - > internal . timer ) ;
2009-03-10 13:54:57 +01:00
req - > internal . state = TEVENT_REQ_RECEIVED ;
2013-09-27 03:41:29 +02:00
2013-09-27 02:29:57 +02:00
tevent_req_cleanup ( req ) ;
2013-09-27 03:41:29 +02:00
TALLOC_FREE ( req - > data ) ;
2009-03-10 13:54:57 +01:00
}
2009-02-25 13:53:19 +01:00
bool tevent_req_poll ( struct tevent_req * req ,
struct tevent_context * ev )
{
while ( tevent_req_is_in_progress ( req ) ) {
int ret ;
ret = tevent_loop_once ( ev ) ;
if ( ret ! = 0 ) {
return false ;
}
}
return true ;
}
2009-02-13 15:37:35 +01:00
bool tevent_req_is_error ( struct tevent_req * req , enum tevent_req_state * state ,
uint64_t * error )
2009-02-13 15:43:04 +01:00
{
2009-02-13 15:37:35 +01:00
if ( req - > internal . state = = TEVENT_REQ_DONE ) {
return false ;
2009-02-13 15:43:04 +01:00
}
2009-02-13 15:37:35 +01:00
if ( req - > internal . state = = TEVENT_REQ_USER_ERROR ) {
* error = req - > internal . error ;
2009-02-13 15:43:04 +01:00
}
2009-02-13 15:37:35 +01:00
* state = req - > internal . state ;
2009-02-13 15:43:04 +01:00
return true ;
}
2009-02-13 15:37:35 +01:00
static void tevent_req_timedout ( struct tevent_context * ev ,
struct tevent_timer * te ,
struct timeval now ,
void * private_data )
2009-02-13 15:43:04 +01:00
{
2013-12-05 08:47:27 +01:00
struct tevent_req * req =
talloc_get_type_abort ( private_data ,
struct tevent_req ) ;
2009-02-13 15:43:04 +01:00
2009-03-17 10:17:50 +01:00
TALLOC_FREE ( req - > internal . timer ) ;
2009-02-13 15:43:04 +01:00
2009-03-17 20:13:34 +01:00
tevent_req_finish ( req , TEVENT_REQ_TIMED_OUT , __FUNCTION__ ) ;
2009-02-13 15:43:04 +01:00
}
2009-02-17 10:15:18 +01:00
bool tevent_req_set_endtime ( struct tevent_req * req ,
2009-02-13 15:37:35 +01:00
struct tevent_context * ev ,
struct timeval endtime )
2009-02-13 15:43:04 +01:00
{
2009-03-17 10:17:50 +01:00
TALLOC_FREE ( req - > internal . timer ) ;
2009-02-13 15:43:04 +01:00
2009-02-13 15:37:35 +01:00
req - > internal . timer = tevent_add_timer ( ev , req , endtime ,
tevent_req_timedout ,
req ) ;
if ( tevent_req_nomem ( req - > internal . timer , req ) ) {
2009-02-13 15:43:04 +01:00
return false ;
}
return true ;
}
2016-09-12 13:02:26 +02:00
void tevent_req_reset_endtime ( struct tevent_req * req )
{
TALLOC_FREE ( req - > internal . timer ) ;
}
2009-02-28 15:44:30 -05:00
void tevent_req_set_callback ( struct tevent_req * req , tevent_req_fn fn , void * pvt )
2023-04-24 15:04:06 +02:00
{
return _tevent_req_set_callback ( req , fn , NULL , pvt ) ;
}
void _tevent_req_set_callback ( struct tevent_req * req ,
tevent_req_fn fn ,
const char * fn_name ,
void * pvt )
2009-02-28 15:44:30 -05:00
{
req - > async . fn = fn ;
2023-04-24 15:04:06 +02:00
req - > async . fn_name = fn_name ;
2009-02-28 15:44:30 -05:00
req - > async . private_data = pvt ;
}
void * _tevent_req_callback_data ( struct tevent_req * req )
{
return req - > async . private_data ;
}
void * _tevent_req_data ( struct tevent_req * req )
{
return req - > data ;
}
void tevent_req_set_print_fn ( struct tevent_req * req , tevent_req_print_fn fn )
{
req - > private_print = fn ;
}
2009-08-15 09:46:23 +02:00
void tevent_req_set_cancel_fn ( struct tevent_req * req , tevent_req_cancel_fn fn )
{
2023-05-23 06:38:27 +02:00
_tevent_req_set_cancel_fn ( req , fn , NULL ) ;
}
void _tevent_req_set_cancel_fn ( struct tevent_req * req ,
tevent_req_cancel_fn fn ,
const char * fn_name )
{
req - > private_cancel . fn = fn ;
req - > private_cancel . fn_name = fn ! = NULL ? fn_name : NULL ;
2009-08-15 09:46:23 +02:00
}
bool _tevent_req_cancel ( struct tevent_req * req , const char * location )
{
2023-05-02 21:57:16 +02:00
tevent_thread_call_depth_notify ( TEVENT_CALL_FLOW_REQ_CANCEL ,
req ,
req - > internal . call_depth ,
req - > private_cancel . fn_name ) ;
2023-05-23 06:38:27 +02:00
if ( req - > private_cancel . fn = = NULL ) {
2009-08-15 09:46:23 +02:00
return false ;
}
2023-05-23 06:38:27 +02:00
return req - > private_cancel . fn ( req ) ;
2009-08-15 09:46:23 +02:00
}
2013-09-27 02:29:57 +02:00
void tevent_req_set_cleanup_fn ( struct tevent_req * req , tevent_req_cleanup_fn fn )
2023-05-23 06:39:06 +02:00
{
_tevent_req_set_cleanup_fn ( req , fn , NULL ) ;
}
void _tevent_req_set_cleanup_fn ( struct tevent_req * req ,
tevent_req_cleanup_fn fn ,
const char * fn_name )
2013-09-27 02:29:57 +02:00
{
req - > private_cleanup . state = req - > internal . state ;
req - > private_cleanup . fn = fn ;
2023-05-23 06:39:06 +02:00
req - > private_cleanup . fn_name = fn ! = NULL ? fn_name : NULL ;
2013-09-27 02:29:57 +02:00
}
2018-05-02 14:01:56 +02:00
static int tevent_req_profile_destructor ( struct tevent_req_profile * p ) ;
bool tevent_req_set_profile ( struct tevent_req * req )
{
struct tevent_req_profile * p ;
if ( req - > internal . profile ! = NULL ) {
tevent_req_error ( req , EINVAL ) ;
return false ;
}
p = tevent_req_profile_create ( req ) ;
if ( tevent_req_nomem ( p , req ) ) {
return false ;
}
p - > req_name = talloc_get_name ( req - > data ) ;
p - > start_location = req - > internal . create_location ;
p - > start_time = tevent_timeval_current ( ) ;
req - > internal . profile = p ;
return true ;
}
static int tevent_req_profile_destructor ( struct tevent_req_profile * p )
{
if ( p - > parent ! = NULL ) {
DLIST_REMOVE ( p - > parent - > subprofiles , p ) ;
p - > parent = NULL ;
}
while ( p - > subprofiles ! = NULL ) {
p - > subprofiles - > parent = NULL ;
DLIST_REMOVE ( p - > subprofiles , p - > subprofiles ) ;
}
return 0 ;
}
struct tevent_req_profile * tevent_req_move_profile ( struct tevent_req * req ,
TALLOC_CTX * mem_ctx )
{
return talloc_move ( mem_ctx , & req - > internal . profile ) ;
}
const struct tevent_req_profile * tevent_req_get_profile (
struct tevent_req * req )
{
return req - > internal . profile ;
}
void tevent_req_profile_get_name ( const struct tevent_req_profile * profile ,
const char * * req_name )
{
if ( req_name ! = NULL ) {
* req_name = profile - > req_name ;
}
}
void tevent_req_profile_get_start ( const struct tevent_req_profile * profile ,
const char * * start_location ,
struct timeval * start_time )
{
if ( start_location ! = NULL ) {
* start_location = profile - > start_location ;
}
if ( start_time ! = NULL ) {
* start_time = profile - > start_time ;
}
}
void tevent_req_profile_get_stop ( const struct tevent_req_profile * profile ,
const char * * stop_location ,
struct timeval * stop_time )
{
if ( stop_location ! = NULL ) {
* stop_location = profile - > stop_location ;
}
if ( stop_time ! = NULL ) {
* stop_time = profile - > stop_time ;
}
}
void tevent_req_profile_get_status ( const struct tevent_req_profile * profile ,
pid_t * pid ,
enum tevent_req_state * state ,
uint64_t * user_error )
{
if ( pid ! = NULL ) {
* pid = profile - > pid ;
}
if ( state ! = NULL ) {
* state = profile - > state ;
}
if ( user_error ! = NULL ) {
* user_error = profile - > user_error ;
}
}
const struct tevent_req_profile * tevent_req_profile_get_subprofiles (
const struct tevent_req_profile * profile )
{
return profile - > subprofiles ;
}
const struct tevent_req_profile * tevent_req_profile_next (
const struct tevent_req_profile * profile )
{
return profile - > next ;
}
struct tevent_req_profile * tevent_req_profile_create ( TALLOC_CTX * mem_ctx )
{
struct tevent_req_profile * result ;
result = talloc_zero ( mem_ctx , struct tevent_req_profile ) ;
if ( result = = NULL ) {
return NULL ;
}
talloc_set_destructor ( result , tevent_req_profile_destructor ) ;
return result ;
}
bool tevent_req_profile_set_name ( struct tevent_req_profile * profile ,
const char * req_name )
{
profile - > req_name = talloc_strdup ( profile , req_name ) ;
return ( profile - > req_name ! = NULL ) ;
}
bool tevent_req_profile_set_start ( struct tevent_req_profile * profile ,
const char * start_location ,
struct timeval start_time )
{
profile - > start_time = start_time ;
profile - > start_location = talloc_strdup ( profile , start_location ) ;
return ( profile - > start_location ! = NULL ) ;
}
bool tevent_req_profile_set_stop ( struct tevent_req_profile * profile ,
const char * stop_location ,
struct timeval stop_time )
{
profile - > stop_time = stop_time ;
profile - > stop_location = talloc_strdup ( profile , stop_location ) ;
return ( profile - > stop_location ! = NULL ) ;
}
void tevent_req_profile_set_status ( struct tevent_req_profile * profile ,
pid_t pid ,
enum tevent_req_state state ,
uint64_t user_error )
{
profile - > pid = pid ;
profile - > state = state ;
profile - > user_error = user_error ;
}
void tevent_req_profile_append_sub ( struct tevent_req_profile * parent_profile ,
struct tevent_req_profile * * sub_profile )
{
struct tevent_req_profile * sub ;
sub = talloc_move ( parent_profile , sub_profile ) ;
sub - > parent = parent_profile ;
DLIST_ADD_END ( parent_profile - > subprofiles , sub ) ;
}