LCOV - code coverage report
Current view: top level - cmdline - stream.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 289 319 90.6 %
Date: 2026-04-29 15:04:44 Functions: 27 28 96.4 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-3.0-or-later
       2             : // Copyright (C) 2011 Andrea Mazzoleni
       3             : 
       4             : #include "portable.h"
       5             : 
       6             : #include "support.h"
       7             : #include "util.h"
       8             : #include "stream.h"
       9             : 
      10             : /****************************************************************************/
      11             : /* stream */
      12             : 
      13             : unsigned STREAM_SIZE = 64 * 1024;
      14             : 
      15        2098 : STREAM* sopen_read(const char* file, int flags)
      16             : {
      17             : #if HAVE_POSIX_FADVISE
      18             :         int ret;
      19             : #endif
      20        2098 :         STREAM* s = malloc_nofail(sizeof(STREAM));
      21             :         struct stat st;
      22             : 
      23        2098 :         s->handle_size = 1;
      24        2098 :         s->handle = malloc_nofail(sizeof(struct stream_handle));
      25        2098 :         s->flags = flags;
      26             : 
      27        2098 :         int open_flags = O_RDONLY | O_BINARY;
      28        2098 :         if (s->flags & STREAM_FLAGS_SEQUENTIAL)
      29        1460 :                 open_flags |= O_SEQUENTIAL;
      30             : 
      31        2098 :         pathcpy(s->handle[0].path, sizeof(s->handle[0].path), file);
      32        2098 :         s->handle[0].f = open(file, open_flags);
      33        2098 :         if (s->handle[0].f == -1) {
      34          52 :                 free(s->handle);
      35          52 :                 free(s);
      36          52 :                 return 0;
      37             :         }
      38             : 
      39             :         /* get file info */
      40        2046 :         if (fstat(s->handle[0].f, &st) != 0) {
      41           0 :                 close(s->handle[0].f);
      42           0 :                 free(s->handle);
      43           0 :                 free(s);
      44           0 :                 return 0;
      45             :         }
      46             : 
      47        2046 :         s->size = st.st_size;
      48             : 
      49             : #if HAVE_POSIX_FADVISE
      50        2046 :         if (s->flags & STREAM_FLAGS_SEQUENTIAL) {
      51             :                 /* advise sequential access */
      52        1408 :                 ret = posix_fadvise_wrapper(s->handle[0].f, 0, 0, POSIX_FADV_SEQUENTIAL);
      53        1408 :                 if (ret == ENOSYS) {
      54           0 :                         log_error(errno, "WARNING! fadvise() is not supported in this platform. Performance may not be optimal!\n");
      55             :                         /* call is not supported, like in armhf, see posix_fadvise manpage */
      56           0 :                         ret = 0;
      57             :                 }
      58        1408 :                 if (ret != 0) {
      59             :                         /* LCOV_EXCL_START */
      60             :                         close(s->handle[0].f);
      61             :                         free(s->handle);
      62             :                         free(s);
      63             :                         errno = ret; /* posix_fadvise return the error code */
      64             :                         return 0;
      65             :                         /* LCOV_EXCL_STOP */
      66             :                 }
      67             :         }
      68             : #endif
      69             : 
      70        2046 :         s->buffer_size = STREAM_SIZE;
      71        2046 :         if (s->buffer_size > s->size)
      72         577 :                 s->buffer_size = s->size; /* allocate only what is necessary */
      73        2046 :         s->buffer = malloc_nofail_test(s->buffer_size);
      74        2046 :         s->pos = s->buffer;
      75        2046 :         s->end = s->buffer;
      76        2046 :         s->state = STREAM_STATE_READ;
      77        2046 :         s->state_index = 0;
      78        2046 :         s->offset = 0;
      79        2046 :         s->offset_uncached = 0;
      80        2046 :         s->crc = 0;
      81        2046 :         s->crc_uncached = 0;
      82        2046 :         s->crc_stream = CRC_IV;
      83             : 
      84        2046 :         return s;
      85             : }
      86             : 
      87         195 : STREAM* sopen_multi_write(unsigned count, int flags)
      88             : {
      89             :         unsigned i;
      90             : 
      91         195 :         STREAM* s = malloc_nofail(sizeof(STREAM));
      92             : 
      93         195 :         s->handle_size = count;
      94         195 :         s->handle = malloc_nofail(count * sizeof(struct stream_handle));
      95         195 :         s->flags = flags;
      96             : 
      97        1436 :         for (i = 0; i < count; ++i)
      98        1241 :                 s->handle[i].f = -1;
      99             : 
     100         195 :         s->buffer_size = STREAM_SIZE;
     101         195 :         s->buffer = malloc_nofail_test(s->buffer_size);
     102         195 :         s->pos = s->buffer;
     103         195 :         s->end = s->buffer + s->buffer_size;
     104         195 :         s->state = STREAM_STATE_WRITE;
     105         195 :         s->state_index = 0;
     106         195 :         s->size = 0;
     107         195 :         s->offset = 0;
     108         195 :         s->offset_uncached = 0;
     109         195 :         s->crc = 0;
     110         195 :         s->crc_uncached = 0;
     111         195 :         s->crc_stream = CRC_IV;
     112             : 
     113         195 :         return s;
     114             : }
     115             : 
     116        1241 : int sopen_multi_file(STREAM* s, unsigned i, const char* file)
     117             : {
     118             : #if HAVE_POSIX_FADVISE
     119             :         int ret;
     120             : #endif
     121             :         int f;
     122             : 
     123        1241 :         pathcpy(s->handle[i].path, sizeof(s->handle[i].path), file);
     124             : 
     125        1241 :         int open_flags = O_WRONLY | O_CREAT | O_EXCL | O_BINARY;
     126        1241 :         if (s->flags & STREAM_FLAGS_SEQUENTIAL)
     127        1113 :                 open_flags |= O_SEQUENTIAL; ;
     128             : 
     129             :         /* O_EXCL to be resilient ensure to always create a new file and not use a stale link to the original file */
     130        1241 :         f = open(file, open_flags, 0600);
     131        1241 :         if (f == -1) {
     132             :                 /* LCOV_EXCL_START */
     133             :                 return -1;
     134             :                 /* LCOV_EXCL_STOP */
     135             :         }
     136             : 
     137             : #if HAVE_POSIX_FADVISE
     138        1241 :         if (s->flags & STREAM_FLAGS_SEQUENTIAL) {
     139             :                 /* advise sequential access */
     140        1113 :                 ret = posix_fadvise_wrapper(f, 0, 0, POSIX_FADV_SEQUENTIAL);
     141        1113 :                 if (ret == ENOSYS) {
     142             :                         /* call is not supported, like in armhf, see posix_fadvise manpage */
     143           0 :                         ret = 0;
     144             :                 }
     145        1113 :                 if (ret != 0) {
     146             :                         /* LCOV_EXCL_START */
     147             :                         close(f);
     148             :                         errno = ret; /* posix_fadvise return the error code */
     149             :                         return -1;
     150             :                         /* LCOV_EXCL_STOP */
     151             :                 }
     152             :         }
     153             : #endif
     154             : 
     155        1241 :         s->handle[i].f = f;
     156             : 
     157        1241 :         return 0;
     158             : }
     159             : 
     160           0 : STREAM* sopen_write(const char* file, int flags)
     161             : {
     162           0 :         STREAM* s = sopen_multi_write(1, flags);
     163             : 
     164           0 :         if (sopen_multi_file(s, 0, file) != 0) {
     165           0 :                 sclose(s);
     166           0 :                 return 0;
     167             :         }
     168             : 
     169           0 :         return s;
     170             : }
     171             : 
     172        2239 : int sclose(STREAM* s)
     173             : {
     174        2239 :         int fail = 0;
     175             :         unsigned i;
     176             : 
     177        2239 :         if (s->state == STREAM_STATE_WRITE) {
     178         195 :                 if (sflush(s) != 0) {
     179             :                         /* LCOV_EXCL_START */
     180             :                         fail = 1;
     181             :                         /* LCOV_EXCL_STOP */
     182             :                 }
     183             :         }
     184             : 
     185        5524 :         for (i = 0; i < s->handle_size; ++i) {
     186        3285 :                 if (close(s->handle[i].f) != 0) {
     187             :                         /* LCOV_EXCL_START */
     188             :                         fail = 1;
     189             :                         /* LCOV_EXCL_STOP */
     190             :                 }
     191             :         }
     192             : 
     193        2239 :         free(s->handle);
     194        2239 :         free(s->buffer);
     195        2239 :         free(s);
     196             : 
     197        2239 :         if (fail) {
     198             :                 /* LCOV_EXCL_START */
     199             :                 return -1;
     200             :                 /* LCOV_EXCL_STOP */
     201             :         }
     202             : 
     203        2239 :         return 0;
     204             : }
     205             : 
     206         295 : int shandle(STREAM* s)
     207             : {
     208         295 :         if (!s->handle_size) {
     209             :                 /* LCOV_EXCL_START */
     210             :                 return -1;
     211             :                 /* LCOV_EXCL_STOP */
     212             :         }
     213             : 
     214         295 :         return s->handle[0].f;
     215             : }
     216             : 
     217             : /**
     218             :  * Fill the read stream buffer.
     219             :  * \return 0 if at least on char is read, or EOF on error.
     220             :  */
     221      609716 : static int sfill(STREAM* s)
     222             : {
     223             :         ssize_t ret;
     224             : 
     225      609716 :         if (s->state != STREAM_STATE_READ) {
     226             :                 /* LCOV_EXCL_START */
     227             :                 return EOF;
     228             :                 /* LCOV_EXCL_STOP */
     229             :         }
     230             : 
     231             :         /* if we reached the end, doesn't try to read */
     232      609716 :         if (s->offset >= s->size) {
     233        3309 :                 return EOF;
     234             :         }
     235             : 
     236      606407 :         ret = read(s->handle[0].f, s->buffer, s->buffer_size);
     237             : 
     238      606407 :         if (ret < 0) {
     239             :                 /* LCOV_EXCL_START */
     240             :                 s->state = STREAM_STATE_ERROR;
     241             :                 return EOF;
     242             :                 /* LCOV_EXCL_STOP */
     243             :         }
     244      606407 :         if (ret == 0) {
     245             :                 /* nothing mode to read */
     246           0 :                 s->state = STREAM_STATE_EOF;
     247           0 :                 return EOF;
     248             :         }
     249             :         /* assume that it can be a shorter read, so ret < s->buffer_size doesn't mean that we reached EOF */
     250             : 
     251             :         /* update the crc */
     252      606407 :         if (s->flags & STREAM_FLAGS_CRC) {
     253      606025 :                 s->crc_uncached = s->crc;
     254      606025 :                 s->crc = crc32c(s->crc, s->buffer, ret);
     255             :         }
     256             : 
     257             :         /* update the offset */
     258      606407 :         s->offset_uncached = s->offset;
     259      606407 :         s->offset += ret;
     260             : 
     261      606407 :         s->pos = s->buffer;
     262      606407 :         s->end = s->buffer + ret;
     263             : 
     264      606407 :         return 0;
     265             : }
     266             : 
     267        1242 : int sdeplete(STREAM* s, unsigned char* last)
     268             : {
     269             :         /* last four bytes */
     270        1242 :         last[0] = 0;
     271        1242 :         last[1] = 0;
     272        1242 :         last[2] = 0;
     273        1242 :         last[3] = 0;
     274             : 
     275             :         while (1) {
     276             :                 /* increase the position up to 4 bytes before the end */
     277      309872 :                 if (s->pos + 4 <= s->end)
     278      149895 :                         s->pos = s->end - 4;
     279             : 
     280             :                 /* insert the last 4 bytes */
     281     1169220 :                 while (s->pos < s->end) {
     282      859348 :                         last[0] = last[1];
     283      859348 :                         last[1] = last[2];
     284      859348 :                         last[2] = last[3];
     285      859348 :                         last[3] = *s->pos++;
     286             :                 }
     287             : 
     288             :                 /* fill again the buffer until the end of the file */
     289      309872 :                 if (sfill(s) != 0) {
     290             :                         /* on error fail */
     291        1242 :                         if (serror(s)) {
     292             :                                 /* LCOV_EXCL_START */
     293             :                                 return EOF;
     294             :                                 /* LCOV_EXCL_STOP */
     295             :                         }
     296             : 
     297             :                         /* on EOF terminate */
     298        1242 :                         break;
     299             :                 }
     300             :         }
     301             : 
     302        1242 :         return 0;
     303             : }
     304             : 
     305       39372 : int sflush(STREAM* s)
     306             : {
     307             :         ssize_t ret;
     308             :         ssize_t size;
     309             :         unsigned i;
     310             : 
     311       39372 :         if (s->state != STREAM_STATE_WRITE) {
     312             :                 /* LCOV_EXCL_START */
     313             :                 return EOF;
     314             :                 /* LCOV_EXCL_STOP */
     315             :         }
     316             : 
     317       39372 :         size = s->pos - s->buffer;
     318       39372 :         if (!size)
     319         179 :                 return 0;
     320             : 
     321      348923 :         for (i = 0; i < s->handle_size; ++i) {
     322      309730 :                 ret = write(s->handle[i].f, s->buffer, size);
     323             : 
     324      309730 :                 if (ret != size) {
     325             :                         /* LCOV_EXCL_START */
     326             :                         s->state = STREAM_STATE_ERROR;
     327             :                         s->state_index = i;
     328             :                         return EOF;
     329             :                         /* LCOV_EXCL_STOP */
     330             :                 }
     331             :         }
     332             : 
     333             :         /*
     334             :          * Update the crc *after* writing the data.
     335             :          *
     336             :          * This must be done after the file write,
     337             :          * to be able to detect memory errors on the buffer,
     338             :          * happening during the write.
     339             :          */
     340       39193 :         if (s->flags & STREAM_FLAGS_CRC) {
     341       39193 :                 s->crc = crc32c(s->crc, s->buffer, size);
     342       39193 :                 s->crc_uncached = s->crc;
     343             :         }
     344             : 
     345             :         /* update the offset */
     346       39193 :         s->offset += size;
     347       39193 :         s->offset_uncached = s->offset;
     348             : 
     349       39193 :         s->pos = s->buffer;
     350             : 
     351       39193 :         return 0;
     352             : }
     353             : 
     354           1 : int64_t stell(STREAM* s)
     355             : {
     356           1 :         return s->offset_uncached + (s->pos - s->buffer);
     357             : }
     358             : 
     359        1859 : uint32_t scrc(STREAM* s)
     360             : {
     361        1859 :         assert(s->flags & STREAM_FLAGS_CRC);
     362        1859 :         return crc32c(s->crc_uncached, s->buffer, s->pos - s->buffer);
     363             : }
     364             : 
     365         195 : uint32_t scrc_stream(STREAM* s)
     366             : {
     367         195 :         assert(s->flags & STREAM_FLAGS_CRC);
     368         195 :         return s->crc_stream ^ CRC_IV;
     369             : }
     370             : 
     371      299844 : int sgetc_uncached(STREAM* s)
     372             : {
     373             :         /* if at the end of the buffer, fill it */
     374      299844 :         if (s->pos == s->end && sfill(s) != 0)
     375        2067 :                 return EOF;
     376      297777 :         return *s->pos++;
     377             : }
     378             : 
     379       10880 : int sgettok(STREAM* f, char* str, int size)
     380             : {
     381       10880 :         char* i = str;
     382       10880 :         char* send = str + size;
     383             :         int c;
     384             : 
     385             :         while (1) {
     386       71018 :                 c = sgetc(f);
     387       71018 :                 if (c == EOF) {
     388         315 :                         break;
     389             :                 }
     390       70703 :                 if (c == ' ' || c == '\t') {
     391        9657 :                         sungetc(c, f);
     392        9657 :                         break;
     393             :                 }
     394       61046 :                 if (c == '\n') {
     395             :                         /* remove ending carriage return to support the Windows CR+LF format */
     396         908 :                         if (i != str && i[-1] == '\r')
     397           0 :                                 --i;
     398         908 :                         sungetc(c, f);
     399         908 :                         break;
     400             :                 }
     401             : 
     402       60138 :                 *i++ = c;
     403             : 
     404       60138 :                 if (i == send) {
     405             :                         /* LCOV_EXCL_START */
     406             :                         return -1;
     407             :                         /* LCOV_EXCL_STOP */
     408             :                 }
     409             :         }
     410             : 
     411       10880 :         *i = 0;
     412             : 
     413       10880 :         return i - str;
     414             : }
     415             : 
     416    13860625 : int sread(STREAM* f, void* void_data, unsigned size)
     417             : {
     418    13860625 :         unsigned char* data = void_data;
     419             : 
     420             :         /* if there is enough space in memory */
     421    13860625 :         if (sptrlookup(f, size)) {
     422             :                 /* optimized version with all the data in memory */
     423    13834236 :                 unsigned char* pos = sptrget(f);
     424             : 
     425             :                 /* copy it */
     426   221540336 :                 while (size--)
     427   207706100 :                         *data++ = *pos++;
     428             : 
     429    13834236 :                 sptrset(f, pos);
     430             :         } else {
     431             :                 /* standard version using sgetc() */
     432     1352953 :                 while (size--) {
     433     1326564 :                         int c = sgetc(f);
     434     1326564 :                         if (c == EOF) {
     435             :                                 /* LCOV_EXCL_START */
     436             :                                 return -1;
     437             :                                 /* LCOV_EXCL_STOP */
     438             :                         }
     439             : 
     440     1326564 :                         *data++ = c;
     441             :                 }
     442             :         }
     443             : 
     444    13860625 :         return 0;
     445             : }
     446             : 
     447        6388 : int sgetline(STREAM* f, char* str, int size)
     448             : {
     449        6388 :         char* i = str;
     450        6388 :         char* send = str + size;
     451             :         int c;
     452             : 
     453             :         /* if there is enough data in memory */
     454        6388 :         if (sptrlookup(f, size)) {
     455             :                 /* optimized version with all the data in memory */
     456           0 :                 unsigned char* pos = sptrget(f);
     457             : 
     458             :                 while (1) {
     459           0 :                         c = *pos++;
     460           0 :                         if (c == '\n') {
     461             :                                 /* remove ending carriage return to support the Windows CR+LF format */
     462           0 :                                 if (i != str && i[-1] == '\r')
     463           0 :                                         --i;
     464           0 :                                 --pos;
     465           0 :                                 break;
     466             :                         }
     467             : 
     468           0 :                         if (i + 1 >= send) {
     469             :                                 /* LCOV_EXCL_START */
     470             :                                 *i = 0;
     471             :                                 --pos;
     472             :                                 sptrset(f, pos);
     473             :                                 return -1;
     474             :                                 /* LCOV_EXCL_STOP */
     475             :                         }
     476             : 
     477           0 :                         *i++ = c;
     478             :                 }
     479             : 
     480           0 :                 sptrset(f, pos);
     481             :         } else {
     482             :                 while (1) {
     483      156806 :                         c = sgetc(f);
     484      156806 :                         if (c == EOF) {
     485             :                                 /* LCOV_EXCL_START */
     486             :                                 break;
     487             :                                 /* LCOV_EXCL_STOP */
     488             :                         }
     489             : 
     490      156740 :                         if (c == '\n') {
     491             :                                 /* remove ending carriage return to support the Windows CR+LF format */
     492        6322 :                                 if (i != str && i[-1] == '\r')
     493           0 :                                         --i;
     494        6322 :                                 sungetc(c, f);
     495        6322 :                                 break;
     496             :                         }
     497             : 
     498      150418 :                         if (i + 1 >= send) {
     499             :                                 /* LCOV_EXCL_START */
     500             :                                 *i = 0;
     501             :                                 sungetc(c, f);
     502             :                                 return -1;
     503             :                                 /* LCOV_EXCL_STOP */
     504             :                         }
     505             : 
     506      150418 :                         *i++ = c;
     507             :                 }
     508             :         }
     509             : 
     510        6388 :         *i = 0;
     511             : 
     512        6388 :         return i - str;
     513             : }
     514             : 
     515        6141 : int sgetlasttok(STREAM* f, char* str, int size)
     516             : {
     517             :         int ret;
     518             : 
     519        6141 :         ret = sgetline(f, str, size);
     520        6141 :         if (ret < 0) {
     521             :                 /* LCOV_EXCL_START */
     522             :                 return ret;
     523             :                 /* LCOV_EXCL_STOP */
     524             :         }
     525             : 
     526        6141 :         while (ret > 0 && (str[ret - 1] == ' ' || str[ret - 1] == '\t'))
     527           0 :                 --ret;
     528             : 
     529        6141 :         str[ret] = 0;
     530             : 
     531        6141 :         return ret;
     532             : }
     533             : 
     534         377 : int sgetu32(STREAM* f, uint32_t* value)
     535             : {
     536             :         int c;
     537             : 
     538         377 :         c = sgetc(f);
     539         377 :         if (c == '0') {
     540           0 :                 *value = 0;
     541           0 :                 return 0;
     542         377 :         } else if (c >= '1' && c <= '9') {
     543             :                 uint32_t v;
     544             : 
     545         377 :                 v = c - '0';
     546             : 
     547         377 :                 c = sgetc(f);
     548         467 :                 while (c >= '0' && c <= '9') {
     549             :                         uint32_t digit;
     550          90 :                         if (v > 0xFFFFFFFFU / 10) {
     551             :                                 /* LCOV_EXCL_START */
     552             :                                 /* overflow */
     553             :                                 return -1;
     554             :                                 /* LCOV_EXCL_STOP */
     555             :                         }
     556          90 :                         v *= 10;
     557             : 
     558          90 :                         digit = c - '0';
     559          90 :                         if (v > 0xFFFFFFFFU - digit) {
     560             :                                 /* LCOV_EXCL_START */
     561             :                                 /* overflow */
     562             :                                 return -1;
     563             :                                 /* LCOV_EXCL_STOP */
     564             :                         }
     565          90 :                         v += digit;
     566             : 
     567          90 :                         c = sgetc(f);
     568             :                 }
     569             : 
     570         377 :                 *value = v;
     571             : 
     572         377 :                 sungetc(c, f);
     573         377 :                 return 0;
     574             :         } else {
     575             :                 /* LCOV_EXCL_START */
     576             :                 /* nothing read */
     577             :                 return -1;
     578             :                 /* LCOV_EXCL_STOP */
     579             :         }
     580             : }
     581             : 
     582    20145488 : int sgetb32(STREAM* f, uint32_t* value)
     583             : {
     584             :         uint32_t v;
     585             :         unsigned char b;
     586             :         unsigned char s;
     587             :         int c;
     588             : 
     589    20145488 :         v = 0;
     590    20145488 :         s = 0;
     591    38522022 : loop:
     592    38522022 :         c = sgetc(f);
     593    38522022 :         if (c == EOF) {
     594             :                 /* LCOV_EXCL_START */
     595             :                 return -1;
     596             :                 /* LCOV_EXCL_STOP */
     597             :         }
     598             : 
     599    38522022 :         b = (unsigned char)c;
     600    38522022 :         if ((b & 0x80) == 0) {
     601    18376534 :                 v |= (uint32_t)b << s;
     602    18376534 :                 s += 7;
     603    18376534 :                 if (s >= 32) {
     604             :                         /* LCOV_EXCL_START */
     605             :                         return -1;
     606             :                         /* LCOV_EXCL_STOP */
     607             :                 }
     608    18376534 :                 goto loop;
     609             :         }
     610             : 
     611    20145488 :         v |= (uint32_t)(b & 0x7f) << s;
     612             : 
     613    20145488 :         *value = v;
     614             : 
     615    20145488 :         return 0;
     616             : }
     617             : 
     618    11830108 : int sgetb64(STREAM* f, uint64_t* value)
     619             : {
     620             :         uint64_t v;
     621             :         unsigned char b;
     622             :         unsigned char s;
     623             :         int c;
     624             : 
     625    11830108 :         v = 0;
     626    11830108 :         s = 0;
     627    43003600 : loop:
     628    43003600 :         c = sgetc(f);
     629    43003600 :         if (c == EOF) {
     630             :                 /* LCOV_EXCL_START */
     631             :                 return -1;
     632             :                 /* LCOV_EXCL_STOP */
     633             :         }
     634             : 
     635    43003600 :         b = (unsigned char)c;
     636    43003600 :         if ((b & 0x80) == 0) {
     637    31173492 :                 v |= (uint64_t)b << s;
     638    31173492 :                 s += 7;
     639    31173492 :                 if (s >= 64) {
     640             :                         /* LCOV_EXCL_START */
     641             :                         return -1;
     642             :                         /* LCOV_EXCL_STOP */
     643             :                 }
     644    31173492 :                 goto loop;
     645             :         }
     646             : 
     647    11830108 :         v |= (uint64_t)(b & 0x7f) << s;
     648             : 
     649    11830108 :         *value = v;
     650             : 
     651    11830108 :         return 0;
     652             : }
     653             : 
     654         422 : int sgetble32(STREAM* f, uint32_t* value)
     655             : {
     656             :         unsigned char buf[4];
     657             : 
     658         422 :         if (sread(f, buf, 4) != 0) {
     659             :                 /* LCOV_EXCL_START */
     660             :                 return -1;
     661             :                 /* LCOV_EXCL_STOP */
     662             :         }
     663             : 
     664         422 :         *value = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24;
     665             : 
     666         422 :         return 0;
     667             : }
     668             : 
     669     4218408 : int sgetbs(STREAM* f, char* str, int size)
     670             : {
     671             :         uint32_t len;
     672             : 
     673     4218408 :         if (sgetb32(f, &len) < 0) {
     674             :                 /* LCOV_EXCL_START */
     675             :                 return -1;
     676             :                 /* LCOV_EXCL_STOP */
     677             :         }
     678             : 
     679     4218408 :         if (len + 1 > (uint32_t)size) {
     680             :                 /* LCOV_EXCL_START */
     681             :                 return -1;
     682             :                 /* LCOV_EXCL_STOP */
     683             :         }
     684             : 
     685     4218408 :         str[len] = 0;
     686             : 
     687     4218408 :         return sread(f, str, (int)len);
     688             : }
     689             : 
     690    23232273 : int swrite(const void* void_data, unsigned size, STREAM* f)
     691             : {
     692    23232273 :         const unsigned char* data = void_data;
     693             : 
     694             :         /* if there is enough space in memory */
     695    23232273 :         if (sptrlookup(f, size)) {
     696             :                 /* optimized version with all the data in memory */
     697    23225887 :                 unsigned char* pos = sptrget(f);
     698             : 
     699             :                 /**
     700             :                  * Update the crc *before* writing the data in the buffer
     701             :                  *
     702             :                  * This must be done before the memory write,
     703             :                  * to be able to detect memory errors on the buffer,
     704             :                  * happening before we write it on the file.
     705             :                  */
     706    23225887 :                 if (f->flags & STREAM_FLAGS_CRC) {
     707    23225887 :                         f->crc_stream = crc32c_plain(f->crc_stream, data, size);
     708             :                 }
     709             : 
     710             :                 /* copy it */
     711   170478904 :                 while (size--)
     712   147253017 :                         *pos++ = *data++;
     713             : 
     714    23225887 :                 sptrset(f, pos);
     715             :         } else {
     716             :                 /* standard version using sputc() */
     717      197962 :                 while (size--) {
     718      191576 :                         if (sputc(*data++, f) != 0) {
     719             :                                 /* LCOV_EXCL_START */
     720             :                                 return -1;
     721             :                                 /* LCOV_EXCL_STOP */
     722             :                         }
     723             :                 }
     724             :         }
     725             : 
     726    23232273 :         return 0;
     727             : }
     728             : 
     729    10174833 : int sputb32(uint32_t value, STREAM* s)
     730             : {
     731             :         unsigned char b;
     732             :         unsigned char buf[16];
     733             :         unsigned i;
     734             : 
     735    10174833 :         i = 0;
     736    19538540 : loop:
     737    19538540 :         b = value & 0x7f;
     738    19538540 :         value >>= 7;
     739             : 
     740    19538540 :         if (value) {
     741     9363707 :                 buf[i++] = b;
     742     9363707 :                 goto loop;
     743             :         }
     744             : 
     745    10174833 :         buf[i++] = b | 0x80;
     746             : 
     747    10174833 :         return swrite(buf, i, s);
     748             : }
     749             : 
     750     5999401 : int sputb64(uint64_t value, STREAM* s)
     751             : {
     752             :         unsigned char b;
     753             :         unsigned char buf[16];
     754             :         unsigned i;
     755             : 
     756     5999401 :         i = 0;
     757    21781169 : loop:
     758    21781169 :         b = value & 0x7f;
     759    21781169 :         value >>= 7;
     760             : 
     761    21781169 :         if (value) {
     762    15781768 :                 buf[i++] = b;
     763    15781768 :                 goto loop;
     764             :         }
     765             : 
     766     5999401 :         buf[i++] = b | 0x80;
     767             : 
     768     5999401 :         return swrite(buf, i, s);
     769             : }
     770             : 
     771         195 : int sputble32(uint32_t value, STREAM* s)
     772             : {
     773             :         unsigned char buf[4];
     774             : 
     775         195 :         buf[0] = value & 0xFF;
     776         195 :         buf[1] = (value >> 8) & 0xFF;
     777         195 :         buf[2] = (value >> 16) & 0xFF;
     778         195 :         buf[3] = (value >> 24) & 0xFF;
     779             : 
     780         195 :         return swrite(buf, 4, s);
     781             : }
     782             : 
     783     2147739 : int sputbs(const char* str, STREAM* f)
     784             : {
     785     2147739 :         size_t len = strlen(str);
     786             : 
     787     2147739 :         if (sputb32(len, f) != 0) {
     788             :                 /* LCOV_EXCL_START */
     789             :                 return -1;
     790             :                 /* LCOV_EXCL_STOP */
     791             :         }
     792             : 
     793     2147739 :         return swrite(str, len, f);
     794             : }
     795             : 
     796             : #if HAVE_FSYNC
     797         179 : int ssync(STREAM* s)
     798             : {
     799             :         unsigned i;
     800             : 
     801        1292 :         for (i = 0; i < s->handle_size; ++i) {
     802        1113 :                 if (fsync(s->handle[i].f) != 0) {
     803             :                         /* LCOV_EXCL_START */
     804             :                         s->state = STREAM_STATE_ERROR;
     805             :                         s->state_index = i;
     806             :                         return -1;
     807             :                         /* LCOV_EXCL_STOP */
     808             :                 }
     809             :         }
     810             : 
     811         179 :         return 0;
     812             : }
     813             : #endif
     814             : 

Generated by: LCOV version 1.0