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