Subversion Repositories HelenOS

Rev

Rev 4192 | Rev 4708 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2009 Lukas Mejdrech
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup net
  30.  *  @{
  31.  */
  32.  
  33. /** @file
  34.  *  Character string with measured length implementation.
  35.  *  @see measured_strings.h
  36.  */
  37.  
  38. #include <errno.h>
  39. #include <malloc.h>
  40. #include <mem.h>
  41. #include <unistd.h>
  42.  
  43. #include <ipc/ipc.h>
  44.  
  45. #include "../err.h"
  46. #include "../modules.h"
  47.  
  48. #include "measured_strings.h"
  49.  
  50. /** Computes the lengths of the measured strings in the given array.
  51.  *  @param strings The measured strings array to be processed. Input parameter.
  52.  *  @param count The measured strings array size. Input parameter.
  53.  *  @returns The computed sizes array.
  54.  *  @returns NULL if there is not enough memory left.
  55.  */
  56. size_t *    prepare_lengths( const measured_string_ref strings, size_t count );
  57.  
  58. measured_string_ref measured_string_create_bulk( const char * string, size_t length ){
  59.     measured_string_ref new;
  60.  
  61.     if( length == 0 ){
  62.         while( string[ length ] ) ++ length;
  63.     }
  64.     new = ( measured_string_ref ) malloc( sizeof( measured_string_t ) + ( sizeof( char ) * ( length + 1 )));
  65.     if( ! new ) return NULL;
  66.     new->length = length;
  67.     new->value = (( char * ) new ) + sizeof( measured_string_t );
  68.     // append terminating zero explicitly - to be safe
  69.     memcpy( new->value, string, new->length );
  70.     new->value[ new->length ] = '\0';
  71.     return new;
  72. }
  73.  
  74. int measured_strings_receive( measured_string_ref * strings, char ** data, size_t count ){
  75.     ERROR_DECLARE;
  76.  
  77.     size_t *        lengths;
  78.     size_t          index;
  79.     size_t          length;
  80.     char *          next;
  81.     ipc_callid_t    callid;
  82.  
  83.     if(( ! strings ) || ( ! data ) || ( count <= 0 )){
  84.         return EINVAL;
  85.     }
  86.     lengths = ( size_t * ) malloc( sizeof( size_t ) * ( count + 1 ));
  87.     if( ! lengths ) return ENOMEM;
  88.     if(( ! ipc_data_write_receive( & callid, & length ))
  89.     || ( length != sizeof( size_t ) * ( count + 1 ))){
  90.         free( lengths );
  91.         return EINVAL;
  92.     }
  93.     if( ERROR_OCCURRED( ipc_data_write_finalize( callid, lengths, sizeof( size_t ) * ( count + 1 )))){
  94.         free( lengths );
  95.         return ERROR_CODE;
  96.     }
  97.     * data = malloc( lengths[ count ] );
  98.     if( !( * data )) return ENOMEM;
  99.     ( * data )[ lengths[ count ] - 1 ] = '\0';
  100.     * strings = ( measured_string_ref ) malloc( sizeof( measured_string_t ) * count );
  101.     if( !( * strings )){
  102.         free( lengths );
  103.         free( * data );
  104.         return ENOMEM;
  105.     }
  106.     next = * data;
  107.     for( index = 0; index < count; ++ index ){
  108.         ( * strings)[ index ].length = lengths[ index ];
  109.         if( lengths[ index ] > 0 ){
  110.             if(( ! ipc_data_write_receive( & callid, & length ))
  111.             || ( length != lengths[ index ] )){
  112.                 free( * data );
  113.                 free( * strings );
  114.                 free( lengths );
  115.                 return EINVAL;
  116.             }
  117.             ERROR_PROPAGATE( ipc_data_write_finalize( callid, next, lengths[ index ] ));
  118.             ( * strings)[ index ].value = next;
  119.             next += lengths[ index ];
  120.             * next = '\0';
  121.             ++ next;
  122.         }else{
  123.             ( * strings )[ index ].value = NULL;
  124.         }
  125.     }
  126.     free( lengths );
  127.     return EOK;
  128. }
  129.  
  130. int measured_strings_reply( const measured_string_ref strings, size_t count ){
  131.     ERROR_DECLARE;
  132.  
  133.     size_t *        lengths;
  134.     size_t          index;
  135.     size_t          length;
  136.     ipc_callid_t    callid;
  137.  
  138.     if(( ! strings ) || ( count <= 0 )){
  139.         return EINVAL;
  140.     }
  141.     lengths = prepare_lengths( strings, count );
  142.     if( ! lengths ) return ENOMEM;
  143.     if(( ! ipc_data_read_receive( & callid, & length ))
  144.     || ( length != sizeof( size_t ) * ( count + 1 ))){
  145.         free( lengths );
  146.         return EINVAL;
  147.     }
  148.     if( ERROR_OCCURRED( ipc_data_read_finalize( callid, lengths, sizeof( size_t ) * ( count + 1 )))){
  149.         free( lengths );
  150.         return ERROR_CODE;
  151.     }
  152.     free( lengths );
  153.     for( index = 0; index < count; ++ index ){
  154.         if( strings[ index ].length > 0 ){
  155.             if(( ! ipc_data_read_receive( & callid, & length ))
  156.             || ( length != strings[ index ].length )){
  157.                 return EINVAL;
  158.             }
  159.             ERROR_PROPAGATE( ipc_data_read_finalize( callid, strings[ index ].value, strings[ index ].length ));
  160.         }
  161.     }
  162.     return EOK;
  163. }
  164.  
  165. int measured_strings_return( int phone, measured_string_ref * strings, char ** data, size_t count ){
  166.     ERROR_DECLARE;
  167.  
  168.     size_t *    lengths;
  169.     size_t      index;
  170.     char *      next;
  171.  
  172.     if(( phone <= 0 ) || ( ! strings ) || ( ! data ) || ( count <= 0 )){
  173.         return EINVAL;
  174.     }
  175.     lengths = ( size_t * ) malloc( sizeof( size_t ) * ( count + 1 ));
  176.     if( ! lengths ) return ENOMEM;
  177.     if( ERROR_OCCURRED( ipc_data_read_start( phone, lengths, sizeof( size_t ) * ( count + 1 )))){
  178.         free( lengths );
  179.         return ERROR_CODE;
  180.     }
  181.     * data = malloc( lengths[ count ] );
  182.     if( !( * data )) return ENOMEM;
  183.     * strings = ( measured_string_ref ) malloc( sizeof( measured_string_t ) * count );
  184.     if( !( * strings )){
  185.         free( lengths );
  186.         free( * data );
  187.         return ENOMEM;
  188.     }
  189.     next = * data;
  190.     for( index = 0; index < count; ++ index ){
  191.         ( * strings )[ index ].length = lengths[ index ];
  192.         if( lengths[ index ] > 0 ){
  193.             ERROR_PROPAGATE( ipc_data_read_start( phone, next, lengths[ index ] ));
  194.             ( * strings )[ index ].value = next;
  195.             next += lengths[ index ];
  196.             * next = '\0';
  197.             ++ next;
  198.         }else{
  199.             ( * strings )[ index ].value = NULL;
  200.         }
  201.     }
  202.     free( lengths );
  203.     return EOK;
  204. }
  205.  
  206. int measured_strings_send( int phone, const measured_string_ref strings, size_t count ){
  207.     ERROR_DECLARE;
  208.  
  209.     size_t *    lengths;
  210.     size_t      index;
  211.  
  212.     if(( phone <= 0 ) || ( ! strings ) || ( count <= 0 )){
  213.         return EINVAL;
  214.     }
  215.     lengths = prepare_lengths( strings, count );
  216.     if( ! lengths ) return ENOMEM;
  217.     if( ERROR_OCCURRED( ipc_data_write_start( phone, lengths, sizeof( size_t ) * ( count + 1 )))){
  218.         free( lengths );
  219.         return ERROR_CODE;
  220.     }
  221.     free( lengths );
  222.     for( index = 0; index < count; ++ index ){
  223.         if( strings[ index ].length > 0 ){
  224.             ERROR_PROPAGATE( ipc_data_write_start( phone, strings[ index ].value, strings[ index ].length ));
  225.         }
  226.     }
  227.     return EOK;
  228. }
  229.  
  230. size_t * prepare_lengths( const measured_string_ref strings, size_t count ){
  231.     size_t *    lengths;
  232.     int         index;
  233.     size_t      length;
  234.  
  235.     lengths = ( size_t * ) malloc( sizeof( size_t ) * ( count + 1 ));
  236.     if( ! lengths ) return NULL;
  237.     length = 0;
  238.     for( index = 0; index < count; ++ index ){
  239.         lengths[ index ] = strings[ index ].length;
  240.         length += lengths[ index ] + 1;
  241.     }
  242.     lengths[ count ] = length;
  243.     return lengths;
  244. }
  245.  
  246. /** @}
  247.  */
  248.  
  249.