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

Generated by: LCOV version 1.0