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-03-01 15:35:05 Functions: 27 28 96.4 %

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

Generated by: LCOV version 1.0