Subversion Repositories HelenOS

Rev

Rev 4708 | 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[in] strings The measured strings array to be processed.
  52.  *  @param[in] count The measured strings array size.
  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. measured_string_ref measured_string_copy( measured_string_ref source ){
  75.     measured_string_ref new;
  76.  
  77.     if( ! source ) return NULL;
  78.     new = ( measured_string_ref ) malloc( sizeof( measured_string_t ));
  79.     if( new ){
  80.         new->value = ( char * ) malloc( source->length + 1 );
  81.         if( new->value ){
  82.             new->length = source->length;
  83.             memcpy( new->value, source->value, new->length );
  84.             new->value[ new->length ] = '\0';
  85.             return new;
  86.         }else{
  87.             free( new );
  88.         }
  89.     }
  90.     return NULL;
  91. }
  92.  
  93. int measured_strings_receive( measured_string_ref * strings, char ** data, size_t count ){
  94.     ERROR_DECLARE;
  95.  
  96.     size_t *        lengths;
  97.     size_t          index;
  98.     size_t          length;
  99.     char *          next;
  100.     ipc_callid_t    callid;
  101.  
  102.     if(( ! strings ) || ( ! data ) || ( count <= 0 )){
  103.         return EINVAL;
  104.     }
  105.     lengths = ( size_t * ) malloc( sizeof( size_t ) * ( count + 1 ));
  106.     if( ! lengths ) return ENOMEM;
  107.     if(( ! ipc_data_write_receive( & callid, & length ))
  108.     || ( length != sizeof( size_t ) * ( count + 1 ))){
  109.         free( lengths );
  110.         return EINVAL;
  111.     }
  112.     if( ERROR_OCCURRED( ipc_data_write_finalize( callid, lengths, sizeof( size_t ) * ( count + 1 )))){
  113.         free( lengths );
  114.         return ERROR_CODE;
  115.     }
  116.     * data = malloc( lengths[ count ] );
  117.     if( !( * data )) return ENOMEM;
  118.     ( * data )[ lengths[ count ] - 1 ] = '\0';
  119.     * strings = ( measured_string_ref ) malloc( sizeof( measured_string_t ) * count );
  120.     if( !( * strings )){
  121.         free( lengths );
  122.         free( * data );
  123.         return ENOMEM;
  124.     }
  125.     next = * data;
  126.     for( index = 0; index < count; ++ index ){
  127.         ( * strings)[ index ].length = lengths[ index ];
  128.         if( lengths[ index ] > 0 ){
  129.             if(( ! ipc_data_write_receive( & callid, & length ))
  130.             || ( length != lengths[ index ] )){
  131.                 free( * data );
  132.                 free( * strings );
  133.                 free( lengths );
  134.                 return EINVAL;
  135.             }
  136.             ERROR_PROPAGATE( ipc_data_write_finalize( callid, next, lengths[ index ] ));
  137.             ( * strings)[ index ].value = next;
  138.             next += lengths[ index ];
  139.             * next = '\0';
  140.             ++ next;
  141.         }else{
  142.             ( * strings )[ index ].value = NULL;
  143.         }
  144.     }
  145.     free( lengths );
  146.     return EOK;
  147. }
  148.  
  149. int measured_strings_reply( const measured_string_ref strings, size_t count ){
  150.     ERROR_DECLARE;
  151.  
  152.     size_t *        lengths;
  153.     size_t          index;
  154.     size_t          length;
  155.     ipc_callid_t    callid;
  156.  
  157.     if(( ! strings ) || ( count <= 0 )){
  158.         return EINVAL;
  159.     }
  160.     lengths = prepare_lengths( strings, count );
  161.     if( ! lengths ) return ENOMEM;
  162.     if(( ! ipc_data_read_receive( & callid, & length ))
  163.     || ( length != sizeof( size_t ) * ( count + 1 ))){
  164.         free( lengths );
  165.         return EINVAL;
  166.     }
  167.     if( ERROR_OCCURRED( ipc_data_read_finalize( callid, lengths, sizeof( size_t ) * ( count + 1 )))){
  168.         free( lengths );
  169.         return ERROR_CODE;
  170.     }
  171.     free( lengths );
  172.     for( index = 0; index < count; ++ index ){
  173.         if( strings[ index ].length > 0 ){
  174.             if(( ! ipc_data_read_receive( & callid, & length ))
  175.             || ( length != strings[ index ].length )){
  176.                 return EINVAL;
  177.             }
  178.             ERROR_PROPAGATE( ipc_data_read_finalize( callid, strings[ index ].value, strings[ index ].length ));
  179.         }
  180.     }
  181.     return EOK;
  182. }
  183.  
  184. int measured_strings_return( int phone, measured_string_ref * strings, char ** data, size_t count ){
  185.     ERROR_DECLARE;
  186.  
  187.     size_t *    lengths;
  188.     size_t      index;
  189.     char *      next;
  190.  
  191.     if(( phone <= 0 ) || ( ! strings ) || ( ! data ) || ( count <= 0 )){
  192.         return EINVAL;
  193.     }
  194.     lengths = ( size_t * ) malloc( sizeof( size_t ) * ( count + 1 ));
  195.     if( ! lengths ) return ENOMEM;
  196.     if( ERROR_OCCURRED( ipc_data_read_start( phone, lengths, sizeof( size_t ) * ( count + 1 )))){
  197.         free( lengths );
  198.         return ERROR_CODE;
  199.     }
  200.     * data = malloc( lengths[ count ] );
  201.     if( !( * data )) return ENOMEM;
  202.     * strings = ( measured_string_ref ) malloc( sizeof( measured_string_t ) * count );
  203.     if( !( * strings )){
  204.         free( lengths );
  205.         free( * data );
  206.         return ENOMEM;
  207.     }
  208.     next = * data;
  209.     for( index = 0; index < count; ++ index ){
  210.         ( * strings )[ index ].length = lengths[ index ];
  211.         if( lengths[ index ] > 0 ){
  212.             ERROR_PROPAGATE( ipc_data_read_start( phone, next, lengths[ index ] ));
  213.             ( * strings )[ index ].value = next;
  214.             next += lengths[ index ];
  215.             * next = '\0';
  216.             ++ next;
  217.         }else{
  218.             ( * strings )[ index ].value = NULL;
  219.         }
  220.     }
  221.     free( lengths );
  222.     return EOK;
  223. }
  224.  
  225. int measured_strings_send( int phone, const measured_string_ref strings, size_t count ){
  226.     ERROR_DECLARE;
  227.  
  228.     size_t *    lengths;
  229.     size_t      index;
  230.  
  231.     if(( phone <= 0 ) || ( ! strings ) || ( count <= 0 )){
  232.         return EINVAL;
  233.     }
  234.     lengths = prepare_lengths( strings, count );
  235.     if( ! lengths ) return ENOMEM;
  236.     if( ERROR_OCCURRED( ipc_data_write_start( phone, lengths, sizeof( size_t ) * ( count + 1 )))){
  237.         free( lengths );
  238.         return ERROR_CODE;
  239.     }
  240.     free( lengths );
  241.     for( index = 0; index < count; ++ index ){
  242.         if( strings[ index ].length > 0 ){
  243.             ERROR_PROPAGATE( ipc_data_write_start( phone, strings[ index ].value, strings[ index ].length ));
  244.         }
  245.     }
  246.     return EOK;
  247. }
  248.  
  249. size_t * prepare_lengths( const measured_string_ref strings, size_t count ){
  250.     size_t *    lengths;
  251.     size_t      index;
  252.     size_t      length;
  253.  
  254.     lengths = ( size_t * ) malloc( sizeof( size_t ) * ( count + 1 ));
  255.     if( ! lengths ) return NULL;
  256.     length = 0;
  257.     for( index = 0; index < count; ++ index ){
  258.         lengths[ index ] = strings[ index ].length;
  259.         length += lengths[ index ] + 1;
  260.     }
  261.     lengths[ count ] = length;
  262.     return lengths;
  263. }
  264.  
  265. /** @}
  266.  */
  267.  
  268.