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 :
|