LCOV - code coverage report
Current view: top level - u8stream/source/u8stream - universal_file_input_stream.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.57.0_covts Lines: 75 75 100.0 %
Date: 2024-04-07 11:14:42 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /* File: universal_file_input_stream.c; Copyright and License: see below */
       2             : 
       3             : #include "u8stream/universal_file_input_stream.h"
       4             : #include "u8stream/universal_input_stream_if.h"
       5             : #include "u8_test_cond.h"
       6             : #include "u8/u8_fault_inject.h"
       7             : #include "u8/u8_trace.h"
       8             : #include "u8/u8_log.h"
       9             : #include <errno.h>
      10             : #include <string.h>
      11             : #include <stdbool.h>
      12             : #include <assert.h>
      13             : 
      14             : /* the vmt implementing the interface */
      15             : static const universal_input_stream_if_t universal_file_input_stream_private_if
      16             :     = {
      17             :         .read = (u8_error_t (*)(universal_input_stream_impl_t*, void*, size_t, size_t*)) &universal_file_input_stream_read,
      18             :         .reset = (u8_error_t (*)(universal_input_stream_impl_t*)) &universal_file_input_stream_reset
      19             :     };
      20             : 
      21          11 : void universal_file_input_stream_init ( universal_file_input_stream_t *this_ )
      22             : {
      23          11 :     U8_TRACE_BEGIN();
      24             : 
      25          11 :     (*this_).input = NULL;
      26          11 :     universal_input_stream_private_init( &((*this_).input_stream), &universal_file_input_stream_private_if, this_ );
      27             : 
      28          11 :     U8_TRACE_END();
      29          11 : }
      30             : 
      31          10 : u8_error_t universal_file_input_stream_destroy( universal_file_input_stream_t *this_ )
      32             : {
      33          10 :     U8_TRACE_BEGIN();
      34          10 :     u8_error_t err = U8_ERROR_NONE;
      35             : 
      36          10 :     if ( (*this_).input != NULL )
      37             :     {
      38           2 :         err = universal_file_input_stream_close( this_ );
      39             :     }
      40          10 :     (*this_).input = NULL;
      41          10 :     universal_input_stream_private_destroy( &((*this_).input_stream) );
      42             : 
      43          10 :     U8_TRACE_END_ERR(err);
      44          10 :     return err;
      45             : }
      46             : 
      47          13 : u8_error_t universal_file_input_stream_open ( universal_file_input_stream_t *this_, const char *path )
      48             : {
      49          13 :     U8_TRACE_BEGIN();
      50          13 :     assert( path != NULL );
      51          13 :     u8_error_t err = 0;
      52             : 
      53          13 :     if ( (*this_).input != NULL )
      54             :     {
      55           1 :         U8_LOG_ERROR("cannot open a file that is already open.");
      56           1 :         err = U8_ERROR_WRONG_STATE;
      57           1 :         err |= universal_file_input_stream_close( this_ );
      58             :     }
      59          13 :     (*this_).input = fopen( path, "r" );
      60          13 :     if ( NULL == (*this_).input )
      61             :     {
      62             :         /* Note: This need not be an error, could be intentionally to avoid TOCTOU issues. */
      63           4 :         U8_LOG_EVENT_STR("could not open file for reading:", strerror(errno) );
      64           4 :         err |= U8_ERROR_AT_FILE_READ;
      65             :     }
      66             : 
      67          13 :     U8_TRACE_END_ERR(err);
      68          13 :     return err;
      69             : }
      70             : 
      71          10 : u8_error_t universal_file_input_stream_read ( universal_file_input_stream_t *this_,
      72             :                                               void *out_buffer,
      73             :                                               size_t max_size,
      74             :                                               size_t *out_length )
      75             : {
      76             :     /*U8_TRACE_BEGIN();*/
      77          10 :     assert( out_buffer != NULL );
      78          10 :     u8_error_t err = U8_ERROR_NONE;
      79             : 
      80          10 :     if ( (*this_).input != NULL )
      81             :     {
      82           9 :         size_t read_bytes = fread( out_buffer, 1, max_size, (*this_).input );
      83           9 :         if ( read_bytes != 0 )
      84             :         {
      85           7 :             *out_length = read_bytes;
      86             :         }
      87             :         else
      88             :         {
      89           2 :             err = U8_ERROR_END_OF_STREAM;  /* finished, no more bytes to read or other error */
      90           2 :             *out_length = 0;
      91             :         }
      92             :     }
      93             :     else
      94             :     {
      95           1 :         U8_LOG_ERROR("cannot read from a file that is not open.");
      96           1 :         err = U8_ERROR_WRONG_STATE;
      97             :     }
      98             : 
      99             :     /*U8_TRACE_END_ERR(err);*/
     100          10 :     return err;
     101             : }
     102             : 
     103           3 : u8_error_t universal_file_input_stream_reset ( universal_file_input_stream_t *this_ )
     104             : {
     105           3 :     U8_TRACE_BEGIN();
     106           3 :     u8_error_t err = U8_ERROR_NONE;
     107             : 
     108           3 :     if ( (*this_).input != NULL )
     109             :     {
     110           2 :         int seek_err = fseek( (*this_).input, 0, SEEK_SET );
     111           2 :         assert( seek_err == 0 );  /* this should not happen, but do not take this for granted */
     112           2 :         seek_err = U8_FAULT_INJECT_COND( U8_TEST_COND_FSEEK, -1, seek_err );
     113           2 :         if ( seek_err != 0 )
     114             :         {
     115           1 :             U8_LOG_ERROR("error at resetting the read-cursor in a file.");
     116           1 :             err = U8_ERROR_AT_FILE_READ;
     117             :         }
     118             :     }
     119             :     else
     120             :     {
     121           1 :         U8_LOG_ERROR("cannot reset/seek a file that is not open.");
     122           1 :         err = U8_ERROR_WRONG_STATE;
     123             :     }
     124             : 
     125           3 :     U8_TRACE_END_ERR(err);
     126           3 :     return err;
     127             : }
     128             : 
     129          10 : u8_error_t universal_file_input_stream_close( universal_file_input_stream_t *this_ )
     130             : {
     131          10 :     U8_TRACE_BEGIN();
     132          10 :     u8_error_t err = U8_ERROR_NONE;
     133             : 
     134          10 :     if ( (*this_).input != NULL )
     135             :     {
     136           9 :         int close_err = fclose( (*this_).input );
     137           9 :         assert( close_err == 0 );  /* this should not happen, but do not take this for granted */
     138           9 :         close_err = U8_FAULT_INJECT_COND( U8_TEST_COND_FCLOSE, EOF, close_err );
     139           9 :         if ( 0 != close_err )
     140             :         {
     141           1 :             U8_LOG_ERROR_INT( "error at closing file:", close_err );
     142           1 :             err = U8_ERROR_AT_FILE_READ;
     143             :         }
     144           9 :         (*this_).input = NULL;
     145             :     }
     146             :     else
     147             :     {
     148           1 :         U8_LOG_ERROR("cannot close a file that is not open.");
     149           1 :         err = U8_ERROR_WRONG_STATE;
     150             :     }
     151             : 
     152          10 :     U8_TRACE_END_ERR(err);
     153          10 :     return err;
     154             : }
     155             : 
     156           2 : universal_input_stream_t* universal_file_input_stream_get_input_stream( universal_file_input_stream_t *this_ )
     157             : {
     158           2 :     U8_TRACE_BEGIN();
     159             : 
     160           2 :     universal_input_stream_t* result = &((*this_).input_stream);
     161             : 
     162           2 :     U8_TRACE_END();
     163           2 :     return result;
     164             : }
     165             : 
     166             : 
     167             : /*
     168             : Copyright 2021-2024 Andreas Warnke
     169             : 
     170             : Licensed under the Apache License, Version 2.0 (the "License");
     171             : you may not use this file except in compliance with the License.
     172             : You may obtain a copy of the License at
     173             : 
     174             :     http://www.apache.org/licenses/LICENSE-2.0
     175             : 
     176             : Unless required by applicable law or agreed to in writing, software
     177             : distributed under the License is distributed on an "AS IS" BASIS,
     178             : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     179             : See the License for the specific language governing permissions and
     180             : limitations under the License.
     181             : */

Generated by: LCOV version 1.16