Esempio n. 1
0
/* Balance the lists so that we can fit an object with the given size into
 * the cache. */
static inline void
arc_balance(arc_t *cache)
{
    if (!ATOMIC_READ(cache->needs_balance))
        return;

    MUTEX_LOCK(&cache->lock);
    /* First move objects from MRU/MFU to their respective ghost lists. */
    while (cache->mru.size + cache->mfu.size > cache->c) {
        if (cache->mru.size > cache->p) {
            arc_object_t *obj = arc_state_lru(&cache->mru);
            arc_move(cache, obj, &cache->mrug);
        } else if (cache->mfu.size > cache->c - cache->p) {
            arc_object_t *obj = arc_state_lru(&cache->mfu);
            arc_move(cache, obj, &cache->mfug);
        } else {
            break;
        }
    }

    /* Then start removing objects from the ghost lists. */
    while (cache->mrug.size + cache->mfug.size > cache->c) {
        if (cache->mfug.size > cache->p) {
            arc_object_t *obj = arc_state_lru(&cache->mfug);
            arc_move(cache, obj, NULL);
        } else if (cache->mrug.size > cache->c - cache->p) {
            arc_object_t *obj = arc_state_lru(&cache->mrug);
            arc_move(cache, obj, NULL);
        } else {
            break;
        }
    }

    ATOMIC_SET(cache->needs_balance, 0);
    MUTEX_UNLOCK(&cache->lock);
}
bool VDAgent::write_clipboard(VDAgentMessage* msg, uint32_t size)
{
    uint32_t pos = 0;
    bool ret = true;

    ASSERT(msg && size);
    //FIXME: do it smarter - no loop, no memcopy
    MUTEX_LOCK(_message_mutex);
    while (pos < size) {
        DWORD n = MIN(sizeof(VDIChunk) + size - pos, VD_AGENT_MAX_DATA_SIZE);
        VDIChunk* chunk = new_chunk(n);
        if (!chunk) {
            ret = false;
            break;
        }
        chunk->hdr.port = VDP_CLIENT_PORT;
        chunk->hdr.size = n - sizeof(VDIChunk);
        memcpy(chunk->data, (char*)msg + pos, n - sizeof(VDIChunk));
        enqueue_chunk(chunk);
        pos += (n - sizeof(VDIChunk));
    }
    MUTEX_UNLOCK(_message_mutex);
    return ret;
}
Esempio n. 3
0
/* check meta */
int xmap_check_meta(XMAP *xmap, int qid, int *status, XMSETS *xsets)
{
    int ret = -1, n = 0, k = 0;

    if(xmap && xsets && qid > 0)
    {
        MUTEX_LOCK(xmap->mutex);
        if(qid <= xmap->state->id_max && (ret = n = xmap->metas[qid].count) > 0)
        {
            *status = xmap->metas[qid].status;
            while(--n >= 0)
            {
                if((k = xmap->metas[qid].disks[n]) > 0 && k <= xmap->state->disk_id_max)
                {
                    xsets->lists[n].ip = xmap->disks[k].ip;
                    xsets->lists[n].port = xmap->disks[k].port;
                    xsets->lists[n].gid = xmap->disks[k].groupid;
                }
            }
        }
        MUTEX_UNLOCK(xmap->mutex);
    }
    return ret;
}
Esempio n. 4
0
static BOOL peer_info(RTP *rtp)
{
int addrlen;
struct sockaddr_in cli_addr, *cli_addrp;
struct hostent *hp;
static CHAR *fid = "peer_info";

    addrlen = sizeof(cli_addr);
    cli_addrp = &cli_addr;
    if (getpeername(rtp->sd, (struct sockaddr *)cli_addrp, &addrlen) != 0) {
        rtp_log(RTP_ERR, "%s: getpeername: %s", fid, strerror(errno));
        return FALSE;
    }
    rtp->addr = (CHAR *) strdup(inet_ntoa(cli_addrp->sin_addr));
    MUTEX_LOCK(&mutex);
        hp = gethostbyaddr(
            (char *) &cli_addrp->sin_addr,
            sizeof(struct in_addr),
            cli_addrp->sin_family
        );
        if (hp != NULL) {
            rtp->peer = (CHAR *) strdup(hp->h_name);
        } else {
            rtp->peer = (CHAR *) strdup(rtp->addr);
        }
    MUTEX_UNLOCK(&mutex);

    if (rtp->peer == (CHAR *) NULL) {
        rtp_log(RTP_ERR, "%s: strdup: %s", fid, strerror(errno));
        return FALSE;
    }

    rtp->port = (UINT16) ntohs(cli_addr.sin_port);

    return TRUE;
}
Esempio n. 5
0
int
mgcfifo_out(struct mgcfifo *pfifo, char *destbuff) //拷贝长度为一�?elements
{
  int ret = 0;
  static UINT16 i = 0;

  if (pfifo->fifo_size == 0)
    {
      while (1)
        mprintf("err fifosize == 0!\r\n");
    }

  MUTEX_LOCK ( pfifo->mutex );

  if (pfifo->nvalid == 0)
    {
      ret = -1;
      goto out;
    }

  DEBUG_FIFO("fifo out %d:", i++);
  (void) DEBUG_FIFO_ARRAY(pfifo->tail + pfifo->buff, pfifo->element_size);
  DEBUG_FIFO("\r\n");
  (void) memcpy(destbuff, pfifo->tail + pfifo->buff, pfifo->element_size);
//  if( pfifo->nvalid > 1)
  if (pfifo->tail != pfifo->head)
    {
      mgcfifo_tailinc(pfifo);
    }

  pfifo->nvalid--;

  ret = pfifo->nvalid;
  out: MUTEX_UNLOCK ( pfifo->mutex );
  return ret;
}
void run( void *arg )
{
  char *name = (char *)arg;
  char debug[20];

  while(1)
  {
    MUTEX_LOCK();
    if( g_tickets <= 0 ){
      MUTEX_UNLOCK();
      goto exit;
    }

    g_tickets--;
    sprintf( debug, "Thread %s, %d\r\n", name, g_tickets );
    MicoUartSend(STDIO_UART, debug, strlen(debug) );

    MUTEX_UNLOCK();
  } 

exit:
  os_mutex_log( "thread: %s exit now", name );
  mico_rtos_delete_thread(NULL);
}
Esempio n. 7
0
struct s_Keeper* keeper_acquire( void const* ptr)
{
	// can be 0 if this happens during main state shutdown (lanes is being GC'ed -> no keepers)
	if( GNbKeepers == 0)
	{
		return NULL;
	}
	else
	{
		/*
		* Any hashing will do that maps pointers to 0..GNbKeepers-1 
		* consistently.
		*
		* Pointers are often aligned by 8 or so - ignore the low order bits
		* have to cast to unsigned long to avoid compilation warnings about loss of data when converting pointer-to-integer
		*/
		unsigned int i = (unsigned int)(((unsigned long)(ptr) >> 3) % GNbKeepers);
		struct s_Keeper* K= &GKeepers[i];

		MUTEX_LOCK( &K->lock_);
		//++ K->count;
		return K;
	}
}
Esempio n. 8
0
static inline void mailstream_ssl_init(void)
{
#ifdef USE_SSL
  mailstream_ssl_init_lock();
  MUTEX_LOCK(&ssl_lock);
#ifndef USE_GNUTLS
  if (!openssl_init_done) {
    #if defined (HAVE_PTHREAD_H) && !defined (WIN32) && defined (USE_SSL) && defined (LIBETPAN_REENTRANT)
      mailstream_openssl_reentrant_setup();
    #endif
    
    SSL_load_error_strings();
    SSL_library_init();
    OpenSSL_add_all_algorithms();
    
    openssl_init_done = 1;
  }
#else
  if (!gnutls_init_not_required)
    gnutls_global_init();
#endif
  MUTEX_UNLOCK(&ssl_lock);
#endif
}
Esempio n. 9
0
/* Assumes buffer lock is held */
static int advance_tx_buffer(struct bladerf_sync *s, struct buffer_mgmt *b)
{
    int status;

    log_verbose("%s: Marking buf[%u] full\n", __FUNCTION__, b->prod_i);
    b->status[b->prod_i] = SYNC_BUFFER_IN_FLIGHT;

    /* This call may block and it results in a per-stream lock being held, so
     * the buffer lock must be dropped.
     *
     * A callback may occur in the meantime, but this will not touch the status
     * for this this buffer, or the producer index.
     */
    MUTEX_UNLOCK(&b->lock);
    status = async_submit_stream_buffer(s->worker->stream,
                                        b->buffers[b->prod_i],
                                        s->stream_config.timeout_ms);
    MUTEX_LOCK(&b->lock);

    if (status == 0) {
        b->prod_i = (b->prod_i + 1) % b->num_buffers;

        /* Go handle the next buffer, if we have one available.  Otherwise,
         * check up on the worker's state and restart it if needed. */
        if (b->status[b->prod_i] == SYNC_BUFFER_EMPTY) {
            s->state = SYNC_STATE_BUFFER_READY;
        } else {
            s->state = SYNC_STATE_CHECK_WORKER;
        }
    } else {
        log_debug("%s: Failed to advance buffer: %s\n",
                  __FUNCTION__, bladerf_strerror(status));
    }

    return status;
}
Esempio n. 10
0
CHAR* MikMod_InfoDriver(void)
{
	int t,len=0;
	MDRIVER *l;
	CHAR *list=NULL;

	MUTEX_LOCK(lists);
	/* compute size of buffer */
	for(l=firstdriver;l;l=l->next)
		if(l->Version)
			len+=4+(l->next?1:0)+strlen(l->Version);

	if(len)
		if((list=_mm_malloc(len*sizeof(CHAR)))) {
			list[0]=0;
			/* list all registered device drivers : */
			for(t=1,l=firstdriver;l;l=l->next,t++)
				if(l->Version)
					sprintf(list,(l->next)?"%s%2d %s\n":"%s%2d %s",
					    list,t,l->Version);
		}
	MUTEX_UNLOCK(lists);
	return list;
}
Esempio n. 11
0
/* insert new root */
int mmtree64_new_tree(void *x)
{
    int id = 0, i = 0;
    if(x)
    {
        MUTEX_LOCK(MMT(x)->mutex);
        if(MMT(x)->state->nroots == 0) MMT(x)->state->nroots = 1;
        if(MMT(x)->state && MMT(x)->state->nroots < MMTREE64_ROOT_MAX)
        {
            for(i = 1; i < MMTREE64_ROOT_MAX; i++)
            {
                if(MMT(x)->state->roots[i].status == 0)
                {
                    MMT(x)->state->roots[i].status = 1;
                    MMT(x)->state->nroots++;
                    id = i;
                    break;
                }
            }
        }
        MUTEX_UNLOCK(MMT(x)->mutex);
    }
    return id;
}
Esempio n. 12
0
void
_stage_2_ ()
{
  MUTEX_DECL (_stage_2_series_block_stmt_28_c_mutex_);
  MUTEX_LOCK (_stage_2_series_block_stmt_28_c_mutex_);
  _stage_2_inner_inarg_prep_macro__;
  _stage_2_branch_block_stmt_29_c_export_decl_macro_;
  {
// merge  file ShiftRegister.aa, line 41
    _stage_2_merge_stmt_30_c_preamble_macro_;
    _stage_2_merge_stmt_30_c_postamble_macro_;
//              tval := ($bitcast ($uint<16>) midpipe )// bits of buffering = 16 
    _stage_2_assign_stmt_34_c_macro_;
//              outpipe := tval// bits of buffering = 16 
    _stage_2_assign_stmt_37_c_macro_;
// $report (stage_2 sent                 output tval )
    _stage_2_stmt_39_c_macro_;
/* 		$place[loopback]
*/ goto loopback_29;
    _stage_2_branch_block_stmt_29_c_export_apply_macro_;
  }
  _stage_2_inner_outarg_prep_macro__;
  MUTEX_UNLOCK (_stage_2_series_block_stmt_28_c_mutex_);
}
Esempio n. 13
0
void
_stage_1_ ()
{
  MUTEX_DECL (_stage_1_series_block_stmt_13_c_mutex_);
  MUTEX_LOCK (_stage_1_series_block_stmt_13_c_mutex_);
  _stage_1_inner_inarg_prep_macro__;
  _stage_1_branch_block_stmt_14_c_export_decl_macro_;
  {
// merge  file ShiftRegister.aa, line 27
    _stage_1_merge_stmt_15_c_preamble_macro_;
    _stage_1_merge_stmt_15_c_postamble_macro_;
//              tval := ($bitcast ($uint<20>) inpipe )// bits of buffering = 20 
    _stage_1_assign_stmt_19_c_macro_;
//              midpipe := tval// bits of buffering = 20 
    _stage_1_assign_stmt_22_c_macro_;
// $report (stage_1 sent                 midpipe tval )
    _stage_1_stmt_24_c_macro_;
/* 		$place[loopback]
*/ goto loopback_14;
    _stage_1_branch_block_stmt_14_c_export_apply_macro_;
  }
  _stage_1_inner_outarg_prep_macro__;
  MUTEX_UNLOCK (_stage_1_series_block_stmt_13_c_mutex_);
}
Esempio n. 14
0
bool String::EndsWith(const String &strNeedle) const
{
	MUTEX_LOCK(str_mutex);
	MUTEX_LOCK_NAMED(wait2, strNeedle.str_mutex);

	// Get the offset
#ifdef SCRATCH_NO_UTF8
	const char* szTemp = this->str_szBuffer + strlen(this->str_szBuffer) - strlen(strNeedle);
#else
	const char* szTemp = this->str_szBuffer + (utf8size(this->str_szBuffer) - 1) - (utf8size(strNeedle) - 1);
#endif

	// Make sure the needle is found
	if (szTemp == nullptr) {
		return false;
	}

	// Then compare the offset with our needle
#ifdef SCRATCH_NO_UTF8
	return !strcmp(strNeedle, szTemp);
#else
	return !utf8cmp(strNeedle, szTemp);
#endif
}
Esempio n. 15
0
/*
 * Pushs a list_entry_t at the end of a list
 */
static inline int
push_entry(linked_list_t *list, list_entry_t *entry)
{
    list_entry_t *p;
    if(!entry)
        return -1;
    MUTEX_LOCK(list->lock);
    if(list->length == 0)
    {
        list->head = list->tail = entry;
    }
    else
    {
        p = list->tail;
        p->next = entry;
        entry->prev = p;
        entry->next = NULL;
        list->tail = entry;
    }
    list->length++;
    entry->list = list;
    MUTEX_UNLOCK(list->lock);
    return 0;
}
Esempio n. 16
0
TSS_RESULT
tcs_wrap_Extend(struct tcsd_thread_data *data)
{
	TCS_CONTEXT_HANDLE hContext;
	UINT32 pcrIndex;
	TCPA_DIGEST inDigest;
	TSS_RESULT result;
	TCPA_DIGEST outDigest;

	if (getData(TCSD_PACKET_TYPE_UINT32, 0, &hContext, 0, &data->comm))
		return TCSERR(TSS_E_INTERNAL_ERROR);

	LogDebugFn("thread %ld context %x", THREAD_ID, hContext);

	if (getData(TCSD_PACKET_TYPE_UINT32, 1, &pcrIndex, 0, &data->comm))
		return TCSERR(TSS_E_INTERNAL_ERROR);
	if (getData(TCSD_PACKET_TYPE_DIGEST, 2, &inDigest, 0, &data->comm))
		return TCSERR(TSS_E_INTERNAL_ERROR);

	MUTEX_LOCK(tcsp_lock);

	result = TCSP_Extend_Internal(hContext, pcrIndex, inDigest, &outDigest);

	MUTEX_UNLOCK(tcsp_lock);

	if (result == TSS_SUCCESS) {
		initData(&data->comm, 1);
		if (setData(TCSD_PACKET_TYPE_DIGEST, 0, &outDigest, 0, &data->comm)) {
			return TCSERR(TSS_E_INTERNAL_ERROR);
		}
	} else
		initData(&data->comm, 0);

	data->comm.hdr.u.result = result;
	return TSS_SUCCESS;
}
Esempio n. 17
0
/* new queue */
int mmqueue_new(MMQUEUE *mmq)
{
    int rootid = -1, i = 0;

    if(mmq)
    {
        MUTEX_LOCK(mmq->mutex);
        if(mmq->state && mmq->map && mmq->state->nroots < MMQ_ROOT_MAX)
        {
            i = 1;
            while(mmq->state->roots[i].status && i < MMQ_ROOT_MAX) ++i;
            if(i < MMQ_ROOT_MAX && mmq->state->roots[i].status == 0)
            {
                mmq->state->roots[i].status = 1;
                mmq->state->nroots++;
                mmq->state->roots[i].total = 0;
                mmq->state->roots[i].first = mmq->state->roots[i].last = 0;
                rootid = i;
            }
        }
        MUTEX_UNLOCK(mmq->mutex);
    }
    return rootid;
}
Esempio n. 18
0
/* returns the chan_man for the open handle passed in */
static rdpChanMan *
freerdp_chanman_find_by_open_handle(int open_handle, int * pindex)
{
	rdpChanManList * list;
	rdpChanMan * chan_man;
	int lindex;

	MUTEX_LOCK(g_mutex_list);
	for (list = g_chan_man_list; list; list = list->next)
	{
		chan_man = list->chan_man;
		for (lindex = 0; lindex < chan_man->num_chans; lindex++)
		{
			if (chan_man->chans[lindex].open_handle == open_handle)
			{
				MUTEX_UNLOCK(g_mutex_list);
				*pindex = lindex;
				return chan_man;
			}
		}
	}
	MUTEX_UNLOCK(g_mutex_list);
	return NULL;
}
static void bdata_oem_rapi_client_start_work(struct work_struct *work)
{
	struct delayed_work *dwork = container_of(work, struct delayed_work,
						  work);
	struct data_info *di = container_of(dwork, struct data_info,
					    oem_rapi_client_start_work);

	if (!di->rpc_client) {
		MUTEX_LOCK(&di->lock);
		di->rpc_client = oem_rapi_client_init();
		if (!di->rpc_client || IS_ERR(di->rpc_client)) {
			pr_err("%s: Failed initialize oem rapi client\n",
			       SEMC_BDATA_NAME);
			di->rpc_client = NULL;
			MUTEX_UNLOCK(&di->lock);
			schedule_delayed_work(&di->oem_rapi_client_start_work,
					      OEM_RAPI_RECONNECT_S * HZ);
			return;
		}
		MUTEX_UNLOCK(&di->lock);

		set_platform_callbacks(di);
	}
}
Esempio n. 20
0
TSS_RESULT
tcs_wrap_OIAP(struct tcsd_thread_data *data)
{
	TCS_CONTEXT_HANDLE hContext;
	TCS_AUTHHANDLE authHandle;
	TCPA_NONCE n0;
	TSS_RESULT result;

	if (getData(TCSD_PACKET_TYPE_UINT32, 0, &hContext, 0, &data->comm))
		return TCSERR(TSS_E_INTERNAL_ERROR);

	if ((result = ctx_verify_context(hContext)))
		goto done;

	LogDebugFn("thread %ld context %x", THREAD_ID, hContext);

	MUTEX_LOCK(tcsp_lock);

	result = auth_mgr_oiap(hContext, &authHandle, &n0);

	MUTEX_UNLOCK(tcsp_lock);

	if (result == TSS_SUCCESS) {
		initData(&data->comm, 2);
		if (setData(TCSD_PACKET_TYPE_UINT32, 0, &authHandle, 0, &data->comm)) {
			return TCSERR(TSS_E_INTERNAL_ERROR);
		}
		if (setData(TCSD_PACKET_TYPE_NONCE, 1, &n0, 0, &data->comm)) {
			return TCSERR(TSS_E_INTERNAL_ERROR);
		}
	} else
done:		initData(&data->comm, 0);

	data->comm.hdr.u.result = result;
	return TSS_SUCCESS;
}
Esempio n. 21
0
/* delete task */
int qindex_del_task(QINDEX *qindex, int taskid)
{
    int id = -1, nodeid = 0, n = 0;
    char taskstr[Q_LINE_MAX];
    QTASK *tasks = NULL;
    QTNODE *nodes = NULL;

    if(qindex && taskid >= 0 && taskid < (Q_NODE_MAX * Q_TASKS_MAX)
            && (nodeid = (taskid/Q_TASKS_MAX)) < Q_NODE_MAX
            && (nodes = qindex->state->nodes) && (tasks = nodes[nodeid].tasks))
    {
        MUTEX_LOCK(qindex->mutex);
        id = taskid % Q_TASKS_MAX;
        //fprintf(stdout, "%s::%d nodeid:%d id:%d\n", __FILE__, __LINE__, nodeid, id);
        if((n = sprintf(taskstr, "%d:%s:%d", nodes[nodeid].type, 
                        tasks[id].ip, tasks[id].port)) > 0)
                mmtrie_del(qindex->namemap, taskstr, n);
        if(tasks[id].status > 0) nodes[nodeid].ntasks--;
        if(tasks[id].mmqid > 0)mmqueue_close(MMQ(qindex->mmqueue), tasks[id].mmqid);
        memset(&(tasks[id]), 0, sizeof(QTASK));
        MUTEX_UNLOCK(qindex->mutex);
    }
    return id;
}
Esempio n. 22
0
TSS_RESULT
tcs_wrap_CMK_SetRestrictions(struct tcsd_thread_data *data)
{
	TCS_CONTEXT_HANDLE hContext;
	TSS_CMK_DELEGATE restriction;
	TPM_AUTH ownerAuth;
	TSS_RESULT result;

	if (getData(TCSD_PACKET_TYPE_UINT32, 0, &hContext, 0, &data->comm))
		return TCSERR(TSS_E_INTERNAL_ERROR);

	LogDebugFn("thread %ld context %x", THREAD_ID, hContext);

	if (getData(TCSD_PACKET_TYPE_UINT32, 1, &restriction, 0, &data->comm))
		return TCSERR(TSS_E_INTERNAL_ERROR);

	if (getData(TCSD_PACKET_TYPE_AUTH, 2, &ownerAuth, 0, &data->comm))
		return TCSERR(TSS_E_INTERNAL_ERROR);

	MUTEX_LOCK(tcsp_lock);

	result = TCSP_CMK_SetRestrictions_Internal(hContext, restriction, &ownerAuth);

	MUTEX_UNLOCK(tcsp_lock);

	if (result == TSS_SUCCESS) {
		initData(&data->comm, 1);
		if (setData(TCSD_PACKET_TYPE_AUTH, 0, &ownerAuth, 0, &data->comm))
			return TCSERR(TSS_E_INTERNAL_ERROR);
	} else
		initData(&data->comm, 0);

	data->comm.hdr.u.result = result;

	return TSS_SUCCESS;
}
Esempio n. 23
0
MIKMODAPI void Player_Free(MODULE *mf)
{
	MUTEX_LOCK(vars);
	Player_Free_internal(mf);
	MUTEX_UNLOCK(vars);
}
Esempio n. 24
0
TSS_RESULT
psfile_get_key_by_pub(int fd, TCPA_STORE_PUBKEY *pub, UINT32 *size, BYTE **ret_key)
{
        int rc;
        UINT32 file_offset = 0;
        struct key_disk_cache *tmp;
	BYTE tmp_buffer[4096];

        MUTEX_LOCK(disk_cache_lock);
        tmp = key_disk_cache_head;

        while (tmp) {
		/* if the key is of the wrong size or is invalid, try the next one */
                if (pub->keyLength != tmp->pub_data_size || !(tmp->flags & CACHE_FLAG_VALID)) {
                        tmp = tmp->next;
                        continue;
                }

		/* we have a valid key with the same key size as the one we're looking for.
		 * grab the pub key data off disk and compare it. */

                /* jump to the location of the public key */
                file_offset = TSSPS_PUB_DATA_OFFSET(tmp);

                rc = lseek(fd, file_offset, SEEK_SET);
                if (rc == ((off_t) - 1)) {
                        LogError("lseek: %s", strerror(errno));
                        MUTEX_UNLOCK(disk_cache_lock);
                        return TCSERR(TSS_E_INTERNAL_ERROR);
                }

		DBG_ASSERT(tmp->pub_data_size < 2048);
		if (tmp->pub_data_size > sizeof(tmp_buffer)) {
			LogError("Source buffer size too big! Size:  %d",
				 tmp->pub_data_size);
			MUTEX_UNLOCK(disk_cache_lock);
			return TCSERR(TSS_E_INTERNAL_ERROR);
		}

		/* read in the key */
                if ((rc = read_data(fd, tmp_buffer, tmp->pub_data_size))) {
			LogError("%s", __FUNCTION__);
                        MUTEX_UNLOCK(disk_cache_lock);
                        return rc;
                }

		/* do the compare */
		if (memcmp(tmp_buffer, pub->key, tmp->pub_data_size)) {
			tmp = tmp->next;
			continue;
		}

                /* jump to the location of the key blob */
                file_offset = TSSPS_BLOB_DATA_OFFSET(tmp);

                rc = lseek(fd, file_offset, SEEK_SET);
                if (rc == ((off_t) - 1)) {
                        LogError("lseek: %s", strerror(errno));
                        MUTEX_UNLOCK(disk_cache_lock);
                        return TCSERR(TSS_E_INTERNAL_ERROR);
                }

		DBG_ASSERT(tmp->blob_size < 4096);
		if (tmp->blob_size > sizeof(tmp_buffer)) {
			LogError("Blob size greater than 4096! Size:  %d",
				 tmp->blob_size);
			MUTEX_UNLOCK(disk_cache_lock);
			return TCSERR(TSS_E_INTERNAL_ERROR);
		}

		/* read in the key blob */
                if ((rc = read_data(fd, tmp_buffer, tmp->blob_size))) {
			LogError("%s", __FUNCTION__);
                        MUTEX_UNLOCK(disk_cache_lock);
                        return rc;
                }

		*ret_key = malloc(tmp->blob_size);
		if (*ret_key == NULL) {
			LogError("malloc of %d bytes failed.", tmp->blob_size);
                        MUTEX_UNLOCK(disk_cache_lock);
			return TCSERR(TSS_E_OUTOFMEMORY);
		}

		memcpy(*ret_key, tmp_buffer, tmp->blob_size);
		*size = tmp->blob_size;

                MUTEX_UNLOCK(disk_cache_lock);
                return rc;
        }
        MUTEX_UNLOCK(disk_cache_lock);
        /* key not found */
        return -2;
}
Esempio n. 25
0
TSS_RESULT
psfile_get_uuid_by_pub(int fd, TCPA_STORE_PUBKEY *pub, TSS_UUID **ret_uuid)
{
        int rc;
        UINT32 file_offset = 0;
        struct key_disk_cache *tmp;
	char tmp_buffer[2048];

        MUTEX_LOCK(disk_cache_lock);
        tmp = key_disk_cache_head;

        while (tmp) {
		/* if the key is of the wrong size or is invalid, try the next one */
                if (pub->keyLength != tmp->pub_data_size || !(tmp->flags & CACHE_FLAG_VALID)) {
                        tmp = tmp->next;
                        continue;
                }

		/* we have a valid key with the same key size as the one we're looking for.
		 * grab the pub key data off disk and compare it. */

                /* jump to the location of the public key */
                file_offset = TSSPS_PUB_DATA_OFFSET(tmp);

                rc = lseek(fd, file_offset, SEEK_SET);
                if (rc == ((off_t) - 1)) {
                        LogError("lseek: %s", strerror(errno));
                        MUTEX_UNLOCK(disk_cache_lock);
                        return TCSERR(TSS_E_INTERNAL_ERROR);
                }

		DBG_ASSERT(tmp->pub_data_size < 2048);

		if (tmp->pub_data_size > sizeof(tmp_buffer)) {
			LogError("Source buffer size too big! Size:  %d",
				 tmp->pub_data_size);
			MUTEX_UNLOCK(disk_cache_lock);
			return TCSERR(TSS_E_INTERNAL_ERROR);
		}
		/* read in the key */
                if ((rc = read_data(fd, tmp_buffer, tmp->pub_data_size))) {
			LogError("%s", __FUNCTION__);
                        MUTEX_UNLOCK(disk_cache_lock);
                        return rc;
                }

		/* do the compare */
		if (memcmp(tmp_buffer, pub->key, tmp->pub_data_size)) {
			tmp = tmp->next;
			continue;
		}

		*ret_uuid = (TSS_UUID *)malloc(sizeof(TSS_UUID));
		if (*ret_uuid == NULL) {
			LogError("malloc of %zd bytes failed.", sizeof(TSS_UUID));
                        MUTEX_UNLOCK(disk_cache_lock);
			return TCSERR(TSS_E_OUTOFMEMORY);
		}

		/* the key matches, copy the uuid out */
		memcpy(*ret_uuid, &tmp->uuid, sizeof(TSS_UUID));

                MUTEX_UNLOCK(disk_cache_lock);
                return TSS_SUCCESS;
        }
        MUTEX_UNLOCK(disk_cache_lock);
        /* key not found */
        return TCSERR(TSS_E_PS_KEY_NOTFOUND);
}
Esempio n. 26
0
TSS_RESULT
tcs_wrap_CMK_ConvertMigration(struct tcsd_thread_data *data)
{
	TCS_CONTEXT_HANDLE hContext;
	TCS_KEY_HANDLE hKey;
	TPM_CMK_AUTH restrictTicket;
	TPM_HMAC sigTicket;
	UINT32 keyDataSize, msaListSize, randomSize;
	BYTE *keyData, *msaList, *random;
	TPM_AUTH parentAuth, nullAuth, *pAuth;
	UINT32 outDataSize;
	BYTE *outData;
	TSS_RESULT result;
	int i;

	memset(&parentAuth, 0, sizeof(TPM_AUTH));
	memset(&nullAuth, 0, sizeof(TPM_AUTH));

	if (getData(TCSD_PACKET_TYPE_UINT32, 0, &hContext, 0, &data->comm))
		return TCSERR(TSS_E_INTERNAL_ERROR);

	LogDebugFn("thread %ld context %x", THREAD_ID, hContext);

	if (getData(TCSD_PACKET_TYPE_UINT32, 1, &hKey, 0, &data->comm))
		return TCSERR(TSS_E_INTERNAL_ERROR);

	if (getData(TCSD_PACKET_TYPE_PBYTE, 2, &restrictTicket, sizeof(restrictTicket), &data->comm))
		return TCSERR(TSS_E_INTERNAL_ERROR);

	if (getData(TCSD_PACKET_TYPE_DIGEST, 3, &sigTicket, 0, &data->comm))
		return TCSERR(TSS_E_INTERNAL_ERROR);

	if (getData(TCSD_PACKET_TYPE_UINT32, 4, &keyDataSize, 0, &data->comm))
		return TCSERR(TSS_E_INTERNAL_ERROR);

	keyData = malloc(keyDataSize);
	if (keyData == NULL) {
		LogError("malloc of %u bytes failed.", keyDataSize);
		return TCSERR(TSS_E_OUTOFMEMORY);
	}
	if (getData(TCSD_PACKET_TYPE_PBYTE, 5, keyData, keyDataSize, &data->comm)) {
		free(keyData);
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}

	if (getData(TCSD_PACKET_TYPE_UINT32, 6, &msaListSize, 0, &data->comm)) {
		free(keyData);
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}

	msaList = malloc(msaListSize);
	if (msaList == NULL) {
		LogError("malloc of %u bytes failed.", msaListSize);
		free(keyData);
		return TCSERR(TSS_E_OUTOFMEMORY);
	}
	if (getData(TCSD_PACKET_TYPE_PBYTE, 7, msaList, msaListSize, &data->comm)) {
		free(keyData);
		free(msaList);
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}

	if (getData(TCSD_PACKET_TYPE_UINT32, 8, &randomSize, 0, &data->comm)) {
		free(keyData);
		free(msaList);
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}

	random = malloc(randomSize);
	if (random == NULL) {
		LogError("malloc of %u bytes failed.", randomSize);
		free(keyData);
		free(msaList);
		return TCSERR(TSS_E_OUTOFMEMORY);
	}
	if (getData(TCSD_PACKET_TYPE_PBYTE, 9, random, randomSize, &data->comm)) {
		free(keyData);
		free(msaList);
		free(random);
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}

	if (getData(TCSD_PACKET_TYPE_AUTH, 10, &parentAuth, 0, &data->comm)) {
		free(keyData);
		free(msaList);
		free(random);
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}

	if (memcmp(&nullAuth, &parentAuth, sizeof(TPM_AUTH)))
		pAuth = &parentAuth;
	else
		pAuth = NULL;

	MUTEX_LOCK(tcsp_lock);

	result = TCSP_CMK_ConvertMigration_Internal(hContext, hKey, restrictTicket, sigTicket,
			keyDataSize, keyData, msaListSize, msaList, randomSize, random,
			pAuth, &outDataSize, &outData);

	MUTEX_UNLOCK(tcsp_lock);
	free(keyData);
	free(msaList);
	free(random);

	if (result == TSS_SUCCESS) {
		i = 0;
		initData(&data->comm, 3);
		if (pAuth) {
			if (setData(TCSD_PACKET_TYPE_AUTH, i++, pAuth, 0, &data->comm)) {
				free(outData);
				return TCSERR(TSS_E_INTERNAL_ERROR);
			}
		}

		if (setData(TCSD_PACKET_TYPE_UINT32, i++, &outDataSize, 0, &data->comm)) {
			free(outData);
			return TCSERR(TSS_E_INTERNAL_ERROR);
		}

		if (setData(TCSD_PACKET_TYPE_PBYTE, i++, outData, outDataSize, &data->comm)) {
			free(outData);
			return TCSERR(TSS_E_INTERNAL_ERROR);
		}
		free(outData);
	} else
		initData(&data->comm, 0);

	data->comm.hdr.u.result = result;

	return TSS_SUCCESS;
}
Esempio n. 27
0
TSS_RESULT
tcs_wrap_CMK_CreateBlob(struct tcsd_thread_data *data)
{
	TCS_CONTEXT_HANDLE hContext;
	TCS_KEY_HANDLE hKey;
	UINT16 migrationType;
	UINT32 migKeyAuthSize;
	BYTE *migKeyAuth;
	TPM_DIGEST pubSourceKeyDigest;
	UINT32 msaListSize, restrictTicketSize, sigTicketSize, encDataSize;
	BYTE *msaList, *restrictTicket, *sigTicket, *encData;
	TPM_AUTH parentAuth, nullAuth, *pAuth;
	UINT32 randomSize, outDataSize;
	BYTE *random, *outData;
	TSS_RESULT result;
	int i;

	memset(&parentAuth, 0, sizeof(TPM_AUTH));
	memset(&nullAuth, 0, sizeof(TPM_AUTH));

	if (getData(TCSD_PACKET_TYPE_UINT32, 0, &hContext, 0, &data->comm))
		return TCSERR(TSS_E_INTERNAL_ERROR);

	LogDebugFn("thread %ld context %x", THREAD_ID, hContext);

	if (getData(TCSD_PACKET_TYPE_UINT32, 1, &hKey, 0, &data->comm))
		return TCSERR(TSS_E_INTERNAL_ERROR);

	if (getData(TCSD_PACKET_TYPE_UINT16, 2, &migrationType, 0, &data->comm))
		return TCSERR(TSS_E_INTERNAL_ERROR);

	if (getData(TCSD_PACKET_TYPE_UINT32, 3, &migKeyAuthSize, 0, &data->comm))
		return TCSERR(TSS_E_INTERNAL_ERROR);

	migKeyAuth = malloc(migKeyAuthSize);
	if (migKeyAuth == NULL) {
		LogError("malloc of %u bytes failed.", migKeyAuthSize);
		return TCSERR(TSS_E_OUTOFMEMORY);
	}
	if (getData(TCSD_PACKET_TYPE_PBYTE, 4, migKeyAuth, migKeyAuthSize, &data->comm)) {
		free(migKeyAuth);
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}

	if (getData(TCSD_PACKET_TYPE_DIGEST, 5, &pubSourceKeyDigest, 0, &data->comm)) {
		free(migKeyAuth);
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}

	if (getData(TCSD_PACKET_TYPE_UINT32, 6, &msaListSize, 0, &data->comm)) {
		free(migKeyAuth);
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}

	msaList = malloc(msaListSize);
	if (msaList == NULL) {
		LogError("malloc of %u bytes failed.", msaListSize);
		free(migKeyAuth);
		return TCSERR(TSS_E_OUTOFMEMORY);
	}
	if (getData(TCSD_PACKET_TYPE_PBYTE, 7, msaList, msaListSize, &data->comm)) {
		free(migKeyAuth);
		free(msaList);
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}

	if (getData(TCSD_PACKET_TYPE_UINT32, 8, &restrictTicketSize, 0, &data->comm)) {
		free(migKeyAuth);
		free(msaList);
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}

	restrictTicket = malloc(restrictTicketSize);
	if (restrictTicket == NULL) {
		LogError("malloc of %u bytes failed.", restrictTicketSize);
		free(migKeyAuth);
		free(msaList);
		return TCSERR(TSS_E_OUTOFMEMORY);
	}
	if (getData(TCSD_PACKET_TYPE_PBYTE, 9, restrictTicket, restrictTicketSize, &data->comm)) {
		free(migKeyAuth);
		free(msaList);
		free(restrictTicket);
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}

	if (getData(TCSD_PACKET_TYPE_UINT32, 10, &sigTicketSize, 0, &data->comm)) {
		free(migKeyAuth);
		free(msaList);
		free(restrictTicket);
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}

	sigTicket = malloc(sigTicketSize);
	if (sigTicket == NULL) {
		LogError("malloc of %u bytes failed.", sigTicketSize);
		free(migKeyAuth);
		free(msaList);
		free(restrictTicket);
		return TCSERR(TSS_E_OUTOFMEMORY);
	}
	if (getData(TCSD_PACKET_TYPE_PBYTE, 11, sigTicket, sigTicketSize, &data->comm)) {
		free(migKeyAuth);
		free(msaList);
		free(restrictTicket);
		free(sigTicket);
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}

	if (getData(TCSD_PACKET_TYPE_UINT32, 12, &encDataSize, 0, &data->comm)) {
		free(migKeyAuth);
		free(msaList);
		free(restrictTicket);
		free(sigTicket);
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}

	encData = malloc(encDataSize);
	if (encData == NULL) {
		LogError("malloc of %u bytes failed.", encDataSize);
		free(migKeyAuth);
		free(msaList);
		free(restrictTicket);
		free(sigTicket);
		return TCSERR(TSS_E_OUTOFMEMORY);
	}
	if (getData(TCSD_PACKET_TYPE_PBYTE, 13, encData, encDataSize, &data->comm)) {
		free(migKeyAuth);
		free(msaList);
		free(restrictTicket);
		free(sigTicket);
		free(encData);
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}

	if (getData(TCSD_PACKET_TYPE_AUTH, 14, &parentAuth, 0, &data->comm)) {
		free(migKeyAuth);
		free(msaList);
		free(restrictTicket);
		free(sigTicket);
		free(encData);
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}

	if (memcmp(&nullAuth, &parentAuth, sizeof(TPM_AUTH)))
		pAuth = &parentAuth;
	else
		pAuth = NULL;

	MUTEX_LOCK(tcsp_lock);

	result = TCSP_CMK_CreateBlob_Internal(hContext, hKey, migrationType, migKeyAuthSize,
			migKeyAuth, pubSourceKeyDigest, msaListSize, msaList, restrictTicketSize,
			restrictTicket, sigTicketSize, sigTicket, encDataSize, encData, pAuth,
			&randomSize, &random, &outDataSize, &outData);

	MUTEX_UNLOCK(tcsp_lock);
	free(migKeyAuth);
	free(msaList);
	free(restrictTicket);
	free(sigTicket);
	free(encData);

	if (result == TSS_SUCCESS) {
		i = 0;
		initData(&data->comm, 5);
		if (pAuth) {
			if (setData(TCSD_PACKET_TYPE_AUTH, i++, pAuth, 0, &data->comm)) {
				free(random);
				free(outData);
				return TCSERR(TSS_E_INTERNAL_ERROR);
			}
		}

		if (setData(TCSD_PACKET_TYPE_UINT32, i++, &randomSize, 0, &data->comm)) {
			free(random);
			free(outData);
			return TCSERR(TSS_E_INTERNAL_ERROR);
		}

		if (setData(TCSD_PACKET_TYPE_PBYTE, i++, random, randomSize, &data->comm)) {
			free(random);
			free(outData);
			return TCSERR(TSS_E_INTERNAL_ERROR);
		}
		free(random);

		if (setData(TCSD_PACKET_TYPE_UINT32, i++, &outDataSize, 0, &data->comm)) {
			free(outData);
			return TCSERR(TSS_E_INTERNAL_ERROR);
		}

		if (setData(TCSD_PACKET_TYPE_PBYTE, i++, outData, outDataSize, &data->comm)) {
			free(outData);
			return TCSERR(TSS_E_INTERNAL_ERROR);
		}
		free(outData);
	} else
		initData(&data->comm, 0);

	data->comm.hdr.u.result = result;

	return TSS_SUCCESS;
}
Esempio n. 28
0
TSS_RESULT
tcs_wrap_CMK_CreateTicket(struct tcsd_thread_data *data)
{
	TCS_CONTEXT_HANDLE hContext;
	UINT32 publicVerifyKeySize;
	BYTE *publicVerifyKey;
	TPM_DIGEST signedData;
	UINT32 sigValueSize;
	BYTE *sigValue;
	TPM_AUTH ownerAuth;
	TPM_HMAC sigTicket;
	TSS_RESULT result;

	if (getData(TCSD_PACKET_TYPE_UINT32, 0, &hContext, 0, &data->comm))
		return TCSERR(TSS_E_INTERNAL_ERROR);

	LogDebugFn("thread %ld context %x", THREAD_ID, hContext);

	if (getData(TCSD_PACKET_TYPE_UINT32, 1, &publicVerifyKeySize, 0, &data->comm))
		return TCSERR(TSS_E_INTERNAL_ERROR);

	publicVerifyKey = malloc(publicVerifyKeySize);
	if (publicVerifyKey == NULL) {
		LogError("malloc of %u bytes failed.", publicVerifyKeySize);
		return TCSERR(TSS_E_OUTOFMEMORY);
	}
	if (getData(TCSD_PACKET_TYPE_PBYTE, 2, publicVerifyKey, publicVerifyKeySize, &data->comm)) {
		free(publicVerifyKey);
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}

	if (getData(TCSD_PACKET_TYPE_DIGEST, 3, &signedData, 0, &data->comm)) {
		free(publicVerifyKey);
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}

	if (getData(TCSD_PACKET_TYPE_UINT32, 4, &sigValueSize, 0, &data->comm)) {
		free(publicVerifyKey);
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}

	sigValue = malloc(sigValueSize);
	if (sigValue == NULL) {
		LogError("malloc of %u bytes failed.", sigValueSize);
		free(publicVerifyKey);
		return TCSERR(TSS_E_OUTOFMEMORY);
	}
	if (getData(TCSD_PACKET_TYPE_PBYTE, 5, sigValue, sigValueSize, &data->comm)) {
		free(publicVerifyKey);
		free(sigValue);
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}

	if (getData(TCSD_PACKET_TYPE_AUTH, 6, &ownerAuth, 0, &data->comm)) {
		free(publicVerifyKey);
		free(sigValue);
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}

	MUTEX_LOCK(tcsp_lock);

	result = TCSP_CMK_CreateTicket_Internal(hContext, publicVerifyKeySize, publicVerifyKey,
			signedData, sigValueSize, sigValue, &ownerAuth, &sigTicket);

	MUTEX_UNLOCK(tcsp_lock);
	free(publicVerifyKey);
	free(sigValue);

	if (result == TSS_SUCCESS) {
		initData(&data->comm, 2);
		if (setData(TCSD_PACKET_TYPE_AUTH, 0, &ownerAuth, 0, &data->comm))
			return TCSERR(TSS_E_INTERNAL_ERROR);

		if (setData(TCSD_PACKET_TYPE_DIGEST, 1, &sigTicket, 0, &data->comm))
			return TCSERR(TSS_E_INTERNAL_ERROR);
	} else
		initData(&data->comm, 0);

	data->comm.hdr.u.result = result;

	return TSS_SUCCESS;
}
Esempio n. 29
0
TSS_RESULT
tcs_wrap_CMK_CreateKey(struct tcsd_thread_data *data)
{
	TCS_CONTEXT_HANDLE hContext;
	TCS_KEY_HANDLE hKey;
	TPM_ENCAUTH keyUsageAuth;
	TPM_HMAC migAuthorityApproval;
	TPM_DIGEST migAuthorityDigest;
	UINT32 keyDataSize;
	BYTE *keyData;
	TPM_AUTH parentAuth, nullAuth, *pAuth;
	TSS_RESULT result;

	memset(&parentAuth, 0, sizeof(TPM_AUTH));
	memset(&nullAuth, 0, sizeof(TPM_AUTH));

	if (getData(TCSD_PACKET_TYPE_UINT32, 0, &hContext, 0, &data->comm))
		return TCSERR(TSS_E_INTERNAL_ERROR);

	LogDebugFn("thread %ld context %x", THREAD_ID, hContext);

	if (getData(TCSD_PACKET_TYPE_UINT32, 1, &hKey, 0, &data->comm))
		return TCSERR(TSS_E_INTERNAL_ERROR);

	if (getData(TCSD_PACKET_TYPE_ENCAUTH, 2, &keyUsageAuth, 0, &data->comm))
		return TCSERR(TSS_E_INTERNAL_ERROR);

	if (getData(TCSD_PACKET_TYPE_DIGEST, 3, &migAuthorityApproval, 0, &data->comm))
		return TCSERR(TSS_E_INTERNAL_ERROR);

	if (getData(TCSD_PACKET_TYPE_DIGEST, 4, &migAuthorityDigest, 0, &data->comm))
		return TCSERR(TSS_E_INTERNAL_ERROR);

	if (getData(TCSD_PACKET_TYPE_UINT32, 5, &keyDataSize, 0, &data->comm))
		return TCSERR(TSS_E_INTERNAL_ERROR);

	keyData = malloc(keyDataSize);
	if (keyData == NULL) {
		LogError("malloc of %u bytes failed.", keyDataSize);
		return TCSERR(TSS_E_OUTOFMEMORY);
	}
	if (getData(TCSD_PACKET_TYPE_PBYTE, 6, keyData, keyDataSize, &data->comm)) {
		free(keyData);
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}

	if (getData(TCSD_PACKET_TYPE_AUTH, 7, &parentAuth, 0, &data->comm)) {
		free(keyData);
		return TCSERR(TSS_E_INTERNAL_ERROR);
	}

	if (memcmp(&nullAuth, &parentAuth, sizeof(TPM_AUTH)))
		pAuth = &parentAuth;
	else
		pAuth = NULL;

	MUTEX_LOCK(tcsp_lock);

	result = TCSP_CMK_CreateKey_Internal(hContext, hKey, keyUsageAuth, migAuthorityApproval,
			migAuthorityDigest, &keyDataSize, &keyData, pAuth);

	MUTEX_UNLOCK(tcsp_lock);

	if (result == TSS_SUCCESS) {
		initData(&data->comm, 3);
		if (setData(TCSD_PACKET_TYPE_UINT32, 0, &keyDataSize, 0, &data->comm)) {
			free(keyData);
			return TCSERR(TSS_E_INTERNAL_ERROR);
		}

		if (setData(TCSD_PACKET_TYPE_PBYTE, 1, keyData, keyDataSize, &data->comm)) {
			free(keyData);
			return TCSERR(TSS_E_INTERNAL_ERROR);
		}
		free(keyData);

		if (pAuth) {
			if (setData(TCSD_PACKET_TYPE_AUTH, 2, pAuth, 0, &data->comm))
				return TCSERR(TSS_E_INTERNAL_ERROR);
		}
	} else
		initData(&data->comm, 0);

	data->comm.hdr.u.result = result;

	return TSS_SUCCESS;
}
Esempio n. 30
0
void locking_function(int mode, int n, const char *file, int line)
{ if (mode & CRYPTO_LOCK)
    MUTEX_LOCK(mutex_buf[n]);
  else
    MUTEX_UNLOCK(mutex_buf[n]);
}