Annotation of embedaddon/quagga/lib/stream.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Packet interface
3: * Copyright (C) 1999 Kunihiro Ishiguro
4: *
5: * This file is part of GNU Zebra.
6: *
7: * GNU Zebra is free software; you can redistribute it and/or modify it
8: * under the terms of the GNU General Public License as published by the
9: * Free Software Foundation; either version 2, or (at your option) any
10: * later version.
11: *
12: * GNU Zebra is distributed in the hope that it will be useful, but
13: * WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15: * General Public License for more details.
16: *
17: * You should have received a copy of the GNU General Public License
18: * along with GNU Zebra; see the file COPYING. If not, write to the Free
19: * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20: * 02111-1307, USA.
21: */
22:
23: #include <stddef.h>
24: #include <zebra.h>
25:
26: #include "stream.h"
27: #include "memory.h"
28: #include "network.h"
29: #include "prefix.h"
30: #include "log.h"
31:
32: /* Tests whether a position is valid */
33: #define GETP_VALID(S,G) \
34: ((G) <= (S)->endp)
35: #define PUT_AT_VALID(S,G) GETP_VALID(S,G)
36: #define ENDP_VALID(S,E) \
37: ((E) <= (S)->size)
38:
39: /* asserting sanity checks. Following must be true before
40: * stream functions are called:
41: *
42: * Following must always be true of stream elements
43: * before and after calls to stream functions:
44: *
45: * getp <= endp <= size
46: *
47: * Note that after a stream function is called following may be true:
48: * if (getp == endp) then stream is no longer readable
49: * if (endp == size) then stream is no longer writeable
50: *
51: * It is valid to put to anywhere within the size of the stream, but only
52: * using stream_put..._at() functions.
53: */
54: #define STREAM_WARN_OFFSETS(S) \
55: zlog_warn ("&(struct stream): %p, size: %lu, endp: %lu, getp: %lu\n", \
56: (S), \
57: (unsigned long) (S)->size, \
58: (unsigned long) (S)->getp, \
59: (unsigned long) (S)->endp)\
60:
61: #define STREAM_VERIFY_SANE(S) \
62: do { \
63: if ( !(GETP_VALID(S, (S)->getp)) && ENDP_VALID(S, (S)->endp) ) \
64: STREAM_WARN_OFFSETS(S); \
65: assert ( GETP_VALID(S, (S)->getp) ); \
66: assert ( ENDP_VALID(S, (S)->endp) ); \
67: } while (0)
68:
69: #define STREAM_BOUND_WARN(S, WHAT) \
70: do { \
71: zlog_warn ("%s: Attempt to %s out of bounds", __func__, (WHAT)); \
72: STREAM_WARN_OFFSETS(S); \
73: assert (0); \
74: } while (0)
75:
76: /* XXX: Deprecated macro: do not use */
77: #define CHECK_SIZE(S, Z) \
78: do { \
79: if (((S)->endp + (Z)) > (S)->size) \
80: { \
81: zlog_warn ("CHECK_SIZE: truncating requested size %lu\n", \
82: (unsigned long) (Z)); \
83: STREAM_WARN_OFFSETS(S); \
84: (Z) = (S)->size - (S)->endp; \
85: } \
86: } while (0);
87:
88: /* Make stream buffer. */
89: struct stream *
90: stream_new (size_t size)
91: {
92: struct stream *s;
93:
94: assert (size > 0);
95:
96: if (size == 0)
97: {
98: zlog_warn ("stream_new(): called with 0 size!");
99: return NULL;
100: }
101:
102: s = XCALLOC (MTYPE_STREAM, sizeof (struct stream));
103:
104: if (s == NULL)
105: return s;
106:
107: if ( (s->data = XMALLOC (MTYPE_STREAM_DATA, size)) == NULL)
108: {
109: XFREE (MTYPE_STREAM, s);
110: return NULL;
111: }
112:
113: s->size = size;
114: return s;
115: }
116:
117: /* Free it now. */
118: void
119: stream_free (struct stream *s)
120: {
121: if (!s)
122: return;
123:
124: XFREE (MTYPE_STREAM_DATA, s->data);
125: XFREE (MTYPE_STREAM, s);
126: }
127:
128: struct stream *
129: stream_copy (struct stream *new, struct stream *src)
130: {
131: STREAM_VERIFY_SANE (src);
132:
133: assert (new != NULL);
134: assert (STREAM_SIZE(new) >= src->endp);
135:
136: new->endp = src->endp;
137: new->getp = src->getp;
138:
139: memcpy (new->data, src->data, src->endp);
140:
141: return new;
142: }
143:
144: struct stream *
145: stream_dup (struct stream *s)
146: {
147: struct stream *new;
148:
149: STREAM_VERIFY_SANE (s);
150:
151: if ( (new = stream_new (s->endp)) == NULL)
152: return NULL;
153:
154: return (stream_copy (new, s));
155: }
156:
157: size_t
158: stream_resize (struct stream *s, size_t newsize)
159: {
160: u_char *newdata;
161: STREAM_VERIFY_SANE (s);
162:
163: newdata = XREALLOC (MTYPE_STREAM_DATA, s->data, newsize);
164:
165: if (newdata == NULL)
166: return s->size;
167:
168: s->data = newdata;
169: s->size = newsize;
170:
171: if (s->endp > s->size)
172: s->endp = s->size;
173: if (s->getp > s->endp)
174: s->getp = s->endp;
175:
176: STREAM_VERIFY_SANE (s);
177:
178: return s->size;
179: }
180:
181: size_t
182: stream_get_getp (struct stream *s)
183: {
184: STREAM_VERIFY_SANE(s);
185: return s->getp;
186: }
187:
188: size_t
189: stream_get_endp (struct stream *s)
190: {
191: STREAM_VERIFY_SANE(s);
192: return s->endp;
193: }
194:
195: size_t
196: stream_get_size (struct stream *s)
197: {
198: STREAM_VERIFY_SANE(s);
199: return s->size;
200: }
201:
202: /* Stream structre' stream pointer related functions. */
203: void
204: stream_set_getp (struct stream *s, size_t pos)
205: {
206: STREAM_VERIFY_SANE(s);
207:
208: if (!GETP_VALID (s, pos))
209: {
210: STREAM_BOUND_WARN (s, "set getp");
211: pos = s->endp;
212: }
213:
214: s->getp = pos;
215: }
216:
217: /* Forward pointer. */
218: void
219: stream_forward_getp (struct stream *s, size_t size)
220: {
221: STREAM_VERIFY_SANE(s);
222:
223: if (!GETP_VALID (s, s->getp + size))
224: {
225: STREAM_BOUND_WARN (s, "seek getp");
226: return;
227: }
228:
229: s->getp += size;
230: }
231:
232: void
233: stream_forward_endp (struct stream *s, size_t size)
234: {
235: STREAM_VERIFY_SANE(s);
236:
237: if (!ENDP_VALID (s, s->endp + size))
238: {
239: STREAM_BOUND_WARN (s, "seek endp");
240: return;
241: }
242:
243: s->endp += size;
244: }
245:
246: /* Copy from stream to destination. */
247: void
248: stream_get (void *dst, struct stream *s, size_t size)
249: {
250: STREAM_VERIFY_SANE(s);
251:
252: if (STREAM_READABLE(s) < size)
253: {
254: STREAM_BOUND_WARN (s, "get");
255: return;
256: }
257:
258: memcpy (dst, s->data + s->getp, size);
259: s->getp += size;
260: }
261:
262: /* Get next character from the stream. */
263: u_char
264: stream_getc (struct stream *s)
265: {
266: u_char c;
267:
268: STREAM_VERIFY_SANE (s);
269:
270: if (STREAM_READABLE(s) < sizeof (u_char))
271: {
272: STREAM_BOUND_WARN (s, "get char");
273: return 0;
274: }
275: c = s->data[s->getp++];
276:
277: return c;
278: }
279:
280: /* Get next character from the stream. */
281: u_char
282: stream_getc_from (struct stream *s, size_t from)
283: {
284: u_char c;
285:
286: STREAM_VERIFY_SANE(s);
287:
288: if (!GETP_VALID (s, from + sizeof (u_char)))
289: {
290: STREAM_BOUND_WARN (s, "get char");
291: return 0;
292: }
293:
294: c = s->data[from];
295:
296: return c;
297: }
298:
299: /* Get next word from the stream. */
300: u_int16_t
301: stream_getw (struct stream *s)
302: {
303: u_int16_t w;
304:
305: STREAM_VERIFY_SANE (s);
306:
307: if (STREAM_READABLE (s) < sizeof (u_int16_t))
308: {
309: STREAM_BOUND_WARN (s, "get ");
310: return 0;
311: }
312:
313: w = s->data[s->getp++] << 8;
314: w |= s->data[s->getp++];
315:
316: return w;
317: }
318:
319: /* Get next word from the stream. */
320: u_int16_t
321: stream_getw_from (struct stream *s, size_t from)
322: {
323: u_int16_t w;
324:
325: STREAM_VERIFY_SANE(s);
326:
327: if (!GETP_VALID (s, from + sizeof (u_int16_t)))
328: {
329: STREAM_BOUND_WARN (s, "get ");
330: return 0;
331: }
332:
333: w = s->data[from++] << 8;
334: w |= s->data[from];
335:
336: return w;
337: }
338:
339: /* Get next long word from the stream. */
340: u_int32_t
341: stream_getl_from (struct stream *s, size_t from)
342: {
343: u_int32_t l;
344:
345: STREAM_VERIFY_SANE(s);
346:
347: if (!GETP_VALID (s, from + sizeof (u_int32_t)))
348: {
349: STREAM_BOUND_WARN (s, "get long");
350: return 0;
351: }
352:
353: l = s->data[from++] << 24;
354: l |= s->data[from++] << 16;
355: l |= s->data[from++] << 8;
356: l |= s->data[from];
357:
358: return l;
359: }
360:
361: u_int32_t
362: stream_getl (struct stream *s)
363: {
364: u_int32_t l;
365:
366: STREAM_VERIFY_SANE(s);
367:
368: if (STREAM_READABLE (s) < sizeof (u_int32_t))
369: {
370: STREAM_BOUND_WARN (s, "get long");
371: return 0;
372: }
373:
374: l = s->data[s->getp++] << 24;
375: l |= s->data[s->getp++] << 16;
376: l |= s->data[s->getp++] << 8;
377: l |= s->data[s->getp++];
378:
379: return l;
380: }
381:
382: /* Get next quad word from the stream. */
383: uint64_t
384: stream_getq_from (struct stream *s, size_t from)
385: {
386: uint64_t q;
387:
388: STREAM_VERIFY_SANE(s);
389:
390: if (!GETP_VALID (s, from + sizeof (uint64_t)))
391: {
392: STREAM_BOUND_WARN (s, "get quad");
393: return 0;
394: }
395:
396: q = ((uint64_t) s->data[from++]) << 56;
397: q |= ((uint64_t) s->data[from++]) << 48;
398: q |= ((uint64_t) s->data[from++]) << 40;
399: q |= ((uint64_t) s->data[from++]) << 32;
400: q |= ((uint64_t) s->data[from++]) << 24;
401: q |= ((uint64_t) s->data[from++]) << 16;
402: q |= ((uint64_t) s->data[from++]) << 8;
403: q |= ((uint64_t) s->data[from++]);
404:
405: return q;
406: }
407:
408: uint64_t
409: stream_getq (struct stream *s)
410: {
411: uint64_t q;
412:
413: STREAM_VERIFY_SANE(s);
414:
415: if (STREAM_READABLE (s) < sizeof (uint64_t))
416: {
417: STREAM_BOUND_WARN (s, "get quad");
418: return 0;
419: }
420:
421: q = ((uint64_t) s->data[s->getp++]) << 56;
422: q |= ((uint64_t) s->data[s->getp++]) << 48;
423: q |= ((uint64_t) s->data[s->getp++]) << 40;
424: q |= ((uint64_t) s->data[s->getp++]) << 32;
425: q |= ((uint64_t) s->data[s->getp++]) << 24;
426: q |= ((uint64_t) s->data[s->getp++]) << 16;
427: q |= ((uint64_t) s->data[s->getp++]) << 8;
428: q |= ((uint64_t) s->data[s->getp++]);
429:
430: return q;
431: }
432:
433: /* Get next long word from the stream. */
434: u_int32_t
435: stream_get_ipv4 (struct stream *s)
436: {
437: u_int32_t l;
438:
439: STREAM_VERIFY_SANE(s);
440:
441: if (STREAM_READABLE (s) < sizeof(u_int32_t))
442: {
443: STREAM_BOUND_WARN (s, "get ipv4");
444: return 0;
445: }
446:
447: memcpy (&l, s->data + s->getp, sizeof(u_int32_t));
448: s->getp += sizeof(u_int32_t);
449:
450: return l;
451: }
452:
453: /* Copy to source to stream.
454: *
455: * XXX: This uses CHECK_SIZE and hence has funny semantics -> Size will wrap
456: * around. This should be fixed once the stream updates are working.
457: *
458: * stream_write() is saner
459: */
460: void
461: stream_put (struct stream *s, const void *src, size_t size)
462: {
463:
464: /* XXX: CHECK_SIZE has strange semantics. It should be deprecated */
465: CHECK_SIZE(s, size);
466:
467: STREAM_VERIFY_SANE(s);
468:
469: if (STREAM_WRITEABLE (s) < size)
470: {
471: STREAM_BOUND_WARN (s, "put");
472: return;
473: }
474:
475: if (src)
476: memcpy (s->data + s->endp, src, size);
477: else
478: memset (s->data + s->endp, 0, size);
479:
480: s->endp += size;
481: }
482:
483: /* Put character to the stream. */
484: int
485: stream_putc (struct stream *s, u_char c)
486: {
487: STREAM_VERIFY_SANE(s);
488:
489: if (STREAM_WRITEABLE (s) < sizeof(u_char))
490: {
491: STREAM_BOUND_WARN (s, "put");
492: return 0;
493: }
494:
495: s->data[s->endp++] = c;
496: return sizeof (u_char);
497: }
498:
499: /* Put word to the stream. */
500: int
501: stream_putw (struct stream *s, u_int16_t w)
502: {
503: STREAM_VERIFY_SANE (s);
504:
505: if (STREAM_WRITEABLE (s) < sizeof (u_int16_t))
506: {
507: STREAM_BOUND_WARN (s, "put");
508: return 0;
509: }
510:
511: s->data[s->endp++] = (u_char)(w >> 8);
512: s->data[s->endp++] = (u_char) w;
513:
514: return 2;
515: }
516:
517: /* Put long word to the stream. */
518: int
519: stream_putl (struct stream *s, u_int32_t l)
520: {
521: STREAM_VERIFY_SANE (s);
522:
523: if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
524: {
525: STREAM_BOUND_WARN (s, "put");
526: return 0;
527: }
528:
529: s->data[s->endp++] = (u_char)(l >> 24);
530: s->data[s->endp++] = (u_char)(l >> 16);
531: s->data[s->endp++] = (u_char)(l >> 8);
532: s->data[s->endp++] = (u_char)l;
533:
534: return 4;
535: }
536:
537: /* Put quad word to the stream. */
538: int
539: stream_putq (struct stream *s, uint64_t q)
540: {
541: STREAM_VERIFY_SANE (s);
542:
543: if (STREAM_WRITEABLE (s) < sizeof (uint64_t))
544: {
545: STREAM_BOUND_WARN (s, "put quad");
546: return 0;
547: }
548:
549: s->data[s->endp++] = (u_char)(q >> 56);
550: s->data[s->endp++] = (u_char)(q >> 48);
551: s->data[s->endp++] = (u_char)(q >> 40);
552: s->data[s->endp++] = (u_char)(q >> 32);
553: s->data[s->endp++] = (u_char)(q >> 24);
554: s->data[s->endp++] = (u_char)(q >> 16);
555: s->data[s->endp++] = (u_char)(q >> 8);
556: s->data[s->endp++] = (u_char)q;
557:
558: return 8;
559: }
560:
561: int
562: stream_putc_at (struct stream *s, size_t putp, u_char c)
563: {
564: STREAM_VERIFY_SANE(s);
565:
566: if (!PUT_AT_VALID (s, putp + sizeof (u_char)))
567: {
568: STREAM_BOUND_WARN (s, "put");
569: return 0;
570: }
571:
572: s->data[putp] = c;
573:
574: return 1;
575: }
576:
577: int
578: stream_putw_at (struct stream *s, size_t putp, u_int16_t w)
579: {
580: STREAM_VERIFY_SANE(s);
581:
582: if (!PUT_AT_VALID (s, putp + sizeof (u_int16_t)))
583: {
584: STREAM_BOUND_WARN (s, "put");
585: return 0;
586: }
587:
588: s->data[putp] = (u_char)(w >> 8);
589: s->data[putp + 1] = (u_char) w;
590:
591: return 2;
592: }
593:
594: int
595: stream_putl_at (struct stream *s, size_t putp, u_int32_t l)
596: {
597: STREAM_VERIFY_SANE(s);
598:
599: if (!PUT_AT_VALID (s, putp + sizeof (u_int32_t)))
600: {
601: STREAM_BOUND_WARN (s, "put");
602: return 0;
603: }
604: s->data[putp] = (u_char)(l >> 24);
605: s->data[putp + 1] = (u_char)(l >> 16);
606: s->data[putp + 2] = (u_char)(l >> 8);
607: s->data[putp + 3] = (u_char)l;
608:
609: return 4;
610: }
611:
612: int
613: stream_putq_at (struct stream *s, size_t putp, uint64_t q)
614: {
615: STREAM_VERIFY_SANE(s);
616:
617: if (!PUT_AT_VALID (s, putp + sizeof (uint64_t)))
618: {
619: STREAM_BOUND_WARN (s, "put");
620: return 0;
621: }
622: s->data[putp] = (u_char)(q >> 56);
623: s->data[putp + 1] = (u_char)(q >> 48);
624: s->data[putp + 2] = (u_char)(q >> 40);
625: s->data[putp + 3] = (u_char)(q >> 32);
626: s->data[putp + 4] = (u_char)(q >> 24);
627: s->data[putp + 5] = (u_char)(q >> 16);
628: s->data[putp + 6] = (u_char)(q >> 8);
629: s->data[putp + 7] = (u_char)q;
630:
631: return 8;
632: }
633:
634: /* Put long word to the stream. */
635: int
636: stream_put_ipv4 (struct stream *s, u_int32_t l)
637: {
638: STREAM_VERIFY_SANE(s);
639:
640: if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
641: {
642: STREAM_BOUND_WARN (s, "put");
643: return 0;
644: }
645: memcpy (s->data + s->endp, &l, sizeof (u_int32_t));
646: s->endp += sizeof (u_int32_t);
647:
648: return sizeof (u_int32_t);
649: }
650:
651: /* Put long word to the stream. */
652: int
653: stream_put_in_addr (struct stream *s, struct in_addr *addr)
654: {
655: STREAM_VERIFY_SANE(s);
656:
657: if (STREAM_WRITEABLE (s) < sizeof (u_int32_t))
658: {
659: STREAM_BOUND_WARN (s, "put");
660: return 0;
661: }
662:
663: memcpy (s->data + s->endp, addr, sizeof (u_int32_t));
664: s->endp += sizeof (u_int32_t);
665:
666: return sizeof (u_int32_t);
667: }
668:
669: /* Put prefix by nlri type format. */
670: int
671: stream_put_prefix (struct stream *s, struct prefix *p)
672: {
673: size_t psize;
674:
675: STREAM_VERIFY_SANE(s);
676:
677: psize = PSIZE (p->prefixlen);
678:
679: if (STREAM_WRITEABLE (s) < psize)
680: {
681: STREAM_BOUND_WARN (s, "put");
682: return 0;
683: }
684:
685: stream_putc (s, p->prefixlen);
686: memcpy (s->data + s->endp, &p->u.prefix, psize);
687: s->endp += psize;
688:
689: return psize;
690: }
691:
692: /* Read size from fd. */
693: int
694: stream_read (struct stream *s, int fd, size_t size)
695: {
696: int nbytes;
697:
698: STREAM_VERIFY_SANE(s);
699:
700: if (STREAM_WRITEABLE (s) < size)
701: {
702: STREAM_BOUND_WARN (s, "put");
703: return 0;
704: }
705:
706: nbytes = readn (fd, s->data + s->endp, size);
707:
708: if (nbytes > 0)
709: s->endp += nbytes;
710:
711: return nbytes;
712: }
713:
714: /* Read size from fd. */
715: int
716: stream_read_unblock (struct stream *s, int fd, size_t size)
717: {
718: int nbytes;
719: int val;
720:
721: STREAM_VERIFY_SANE(s);
722:
723: if (STREAM_WRITEABLE (s) < size)
724: {
725: STREAM_BOUND_WARN (s, "put");
726: return 0;
727: }
728:
729: val = fcntl (fd, F_GETFL, 0);
730: fcntl (fd, F_SETFL, val|O_NONBLOCK);
731: nbytes = read (fd, s->data + s->endp, size);
732: fcntl (fd, F_SETFL, val);
733:
734: if (nbytes > 0)
735: s->endp += nbytes;
736:
737: return nbytes;
738: }
739:
740: ssize_t
741: stream_read_try(struct stream *s, int fd, size_t size)
742: {
743: ssize_t nbytes;
744:
745: STREAM_VERIFY_SANE(s);
746:
747: if (STREAM_WRITEABLE(s) < size)
748: {
749: STREAM_BOUND_WARN (s, "put");
750: /* Fatal (not transient) error, since retrying will not help
751: (stream is too small to contain the desired data). */
752: return -1;
753: }
754:
755: if ((nbytes = read(fd, s->data + s->endp, size)) >= 0)
756: {
757: s->endp += nbytes;
758: return nbytes;
759: }
760: /* Error: was it transient (return -2) or fatal (return -1)? */
761: if (ERRNO_IO_RETRY(errno))
762: return -2;
763: zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
764: return -1;
765: }
766:
767: /* Read up to size bytes into the stream from the fd, using recvmsgfrom
768: * whose arguments match the remaining arguments to this function
769: */
770: ssize_t
771: stream_recvfrom (struct stream *s, int fd, size_t size, int flags,
772: struct sockaddr *from, socklen_t *fromlen)
773: {
774: ssize_t nbytes;
775:
776: STREAM_VERIFY_SANE(s);
777:
778: if (STREAM_WRITEABLE(s) < size)
779: {
780: STREAM_BOUND_WARN (s, "put");
781: /* Fatal (not transient) error, since retrying will not help
782: (stream is too small to contain the desired data). */
783: return -1;
784: }
785:
786: if ((nbytes = recvfrom (fd, s->data + s->endp, size,
787: flags, from, fromlen)) >= 0)
788: {
789: s->endp += nbytes;
790: return nbytes;
791: }
792: /* Error: was it transient (return -2) or fatal (return -1)? */
793: if (ERRNO_IO_RETRY(errno))
794: return -2;
795: zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno));
796: return -1;
797: }
798:
799: /* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting
800: * from endp.
801: * First iovec will be used to receive the data.
802: * Stream need not be empty.
803: */
804: ssize_t
805: stream_recvmsg (struct stream *s, int fd, struct msghdr *msgh, int flags,
806: size_t size)
807: {
808: int nbytes;
809: struct iovec *iov;
810:
811: STREAM_VERIFY_SANE(s);
812: assert (msgh->msg_iovlen > 0);
813:
814: if (STREAM_WRITEABLE (s) < size)
815: {
816: STREAM_BOUND_WARN (s, "put");
817: /* This is a logic error in the calling code: the stream is too small
818: to hold the desired data! */
819: return -1;
820: }
821:
822: iov = &(msgh->msg_iov[0]);
823: iov->iov_base = (s->data + s->endp);
824: iov->iov_len = size;
825:
826: nbytes = recvmsg (fd, msgh, flags);
827:
828: if (nbytes > 0)
829: s->endp += nbytes;
830:
831: return nbytes;
832: }
833:
834: /* Write data to buffer. */
835: size_t
836: stream_write (struct stream *s, const void *ptr, size_t size)
837: {
838:
839: CHECK_SIZE(s, size);
840:
841: STREAM_VERIFY_SANE(s);
842:
843: if (STREAM_WRITEABLE (s) < size)
844: {
845: STREAM_BOUND_WARN (s, "put");
846: return 0;
847: }
848:
849: memcpy (s->data + s->endp, ptr, size);
850: s->endp += size;
851:
852: return size;
853: }
854:
855: /* Return current read pointer.
856: * DEPRECATED!
857: * Use stream_get_pnt_to if you must, but decoding streams properly
858: * is preferred
859: */
860: u_char *
861: stream_pnt (struct stream *s)
862: {
863: STREAM_VERIFY_SANE(s);
864: return s->data + s->getp;
865: }
866:
867: /* Check does this stream empty? */
868: int
869: stream_empty (struct stream *s)
870: {
871: STREAM_VERIFY_SANE(s);
872:
873: return (s->endp == 0);
874: }
875:
876: /* Reset stream. */
877: void
878: stream_reset (struct stream *s)
879: {
880: STREAM_VERIFY_SANE (s);
881:
882: s->getp = s->endp = 0;
883: }
884:
885: /* Write stream contens to the file discriptor. */
886: int
887: stream_flush (struct stream *s, int fd)
888: {
889: int nbytes;
890:
891: STREAM_VERIFY_SANE(s);
892:
893: nbytes = write (fd, s->data + s->getp, s->endp - s->getp);
894:
895: return nbytes;
896: }
897:
898: /* Stream first in first out queue. */
899:
900: struct stream_fifo *
901: stream_fifo_new (void)
902: {
903: struct stream_fifo *new;
904:
905: new = XCALLOC (MTYPE_STREAM_FIFO, sizeof (struct stream_fifo));
906: return new;
907: }
908:
909: /* Add new stream to fifo. */
910: void
911: stream_fifo_push (struct stream_fifo *fifo, struct stream *s)
912: {
913: if (fifo->tail)
914: fifo->tail->next = s;
915: else
916: fifo->head = s;
917:
918: fifo->tail = s;
919:
920: fifo->count++;
921: }
922:
923: /* Delete first stream from fifo. */
924: struct stream *
925: stream_fifo_pop (struct stream_fifo *fifo)
926: {
927: struct stream *s;
928:
929: s = fifo->head;
930:
931: if (s)
932: {
933: fifo->head = s->next;
934:
935: if (fifo->head == NULL)
936: fifo->tail = NULL;
937: }
938:
939: fifo->count--;
940:
941: return s;
942: }
943:
944: /* Return first fifo entry. */
945: struct stream *
946: stream_fifo_head (struct stream_fifo *fifo)
947: {
948: return fifo->head;
949: }
950:
951: void
952: stream_fifo_clean (struct stream_fifo *fifo)
953: {
954: struct stream *s;
955: struct stream *next;
956:
957: for (s = fifo->head; s; s = next)
958: {
959: next = s->next;
960: stream_free (s);
961: }
962: fifo->head = fifo->tail = NULL;
963: fifo->count = 0;
964: }
965:
966: void
967: stream_fifo_free (struct stream_fifo *fifo)
968: {
969: stream_fifo_clean (fifo);
970: XFREE (MTYPE_STREAM_FIFO, fifo);
971: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>