Annotation of embedaddon/libpdel/io/boundary_fp.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * Copyright (c) 2001-2002 Packet Design, LLC.
! 4: * All rights reserved.
! 5: *
! 6: * Subject to the following obligations and disclaimer of warranty,
! 7: * use and redistribution of this software, in source or object code
! 8: * forms, with or without modifications are expressly permitted by
! 9: * Packet Design; provided, however, that:
! 10: *
! 11: * (i) Any and all reproductions of the source or object code
! 12: * must include the copyright notice above and the following
! 13: * disclaimer of warranties; and
! 14: * (ii) No rights are granted, in any manner or form, to use
! 15: * Packet Design trademarks, including the mark "PACKET DESIGN"
! 16: * on advertising, endorsements, or otherwise except as such
! 17: * appears in the above copyright notice or in the software.
! 18: *
! 19: * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
! 20: * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
! 21: * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
! 22: * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
! 23: * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
! 24: * OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
! 25: * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
! 26: * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
! 27: * RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE
! 28: * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
! 29: * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
! 30: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
! 31: * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
! 32: * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
! 33: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 34: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
! 35: * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
! 36: * THE POSSIBILITY OF SUCH DAMAGE.
! 37: *
! 38: * Author: Archie Cobbs <archie@freebsd.org>
! 39: */
! 40:
! 41: #include <sys/types.h>
! 42: #include <sys/param.h>
! 43:
! 44: #include <stdio.h>
! 45: #include <stdlib.h>
! 46: #include <stdarg.h>
! 47: #include <string.h>
! 48: #include <assert.h>
! 49: #include <errno.h>
! 50:
! 51: #include "structs/structs.h"
! 52: #include "structs/type/array.h"
! 53:
! 54: #include "util/typed_mem.h"
! 55: #include "io/boundary_fp.h"
! 56:
! 57: #define MEM_TYPE "boundary_fp"
! 58:
! 59: #define MAX_BOUNDARY 255 /* must be less than 256 */
! 60:
! 61: /* Internal state per stream */
! 62: struct boundary_fp {
! 63: FILE *fp;
! 64: char bdry[MAX_BOUNDARY]; /* boundary string */
! 65: u_char fail[MAX_BOUNDARY]; /* failure function */
! 66: u_char buf[MAX_BOUNDARY]; /* input buffer data */
! 67: int closeit; /* close underlying stream */
! 68: int blen; /* boundary string length */
! 69: int nbuf; /* number chars in buffer */
! 70: int nmatch; /* length of the longest suffix
! 71: of buffer data that matches
! 72: a prefix of the boundary */
! 73: };
! 74:
! 75: /*
! 76: * Internal functions
! 77: */
! 78: static int boundary_read(void *cookie, char *buf, int len);
! 79: static int boundary_close(void *cookie);
! 80:
! 81: /*
! 82: * Create a FILE * that reads from another FILE *, stopping
! 83: * just after it reads in the supplied boundary string.
! 84: */
! 85: FILE *
! 86: boundary_fopen(FILE *fp, const char *boundary, int closeit)
! 87: {
! 88: struct boundary_fp *m;
! 89: int blen;
! 90: int i, j;
! 91:
! 92: /* Sanity check */
! 93: if ((blen = strlen(boundary)) > MAX_BOUNDARY) {
! 94: errno = EINVAL;
! 95: return (NULL);
! 96: }
! 97:
! 98: /* Create state structure */
! 99: if ((m = MALLOC(MEM_TYPE, sizeof(*m))) == NULL)
! 100: return (NULL);
! 101: memset(m, 0, sizeof(*m));
! 102: m->fp = fp;
! 103: m->blen = blen;
! 104: m->closeit = closeit;
! 105: memcpy(m->bdry, boundary, m->blen);
! 106:
! 107: /* Generate failure function (linear algorithms exist; this isn't) */
! 108: for (i = 2; i < m->blen; i++) {
! 109: for (j = 1; j < i && strncmp(m->bdry, m->bdry + j, i - j); j++);
! 110: m->fail[i] = i - j;
! 111: }
! 112:
! 113: /* Create new stream using methods below */
! 114: if ((fp = funopen(m, boundary_read,
! 115: NULL, NULL, boundary_close)) == NULL) {
! 116: FREE(MEM_TYPE, m);
! 117: return (NULL);
! 118: }
! 119:
! 120: /* Done */
! 121: return (fp);
! 122: }
! 123:
! 124: /*
! 125: * Read method.
! 126: */
! 127: static int
! 128: boundary_read(void *cookie, char *buf, int len)
! 129: {
! 130: struct boundary_fp *const m = cookie;
! 131: int nr;
! 132: int i;
! 133:
! 134: /* Sanity */
! 135: assert(m->nmatch <= m->nbuf);
! 136:
! 137: /* Have we got a complete boundary sitting in the buffer? */
! 138: if (m->nmatch == m->blen)
! 139: return (0);
! 140:
! 141: /* Return available data, if any (and shift buffer) */
! 142: if (m->nbuf > m->nmatch) {
! 143: len = MIN(len, m->nbuf - m->nmatch);
! 144: memcpy(buf, m->buf, len);
! 145: m->nbuf -= len;
! 146: memmove(m->buf, m->buf + len, m->nbuf);
! 147: return (len);
! 148: }
! 149:
! 150: /*
! 151: * Try to fill up the buffer from underlying stream. It is not
! 152: * possible to read past the end of a boundary at this point.
! 153: */
! 154: nr = fread(m->buf + m->nbuf, 1, m->blen - m->nbuf, m->fp);
! 155:
! 156: /* Check for EOF/error on underlying stream */
! 157: if (nr == 0) {
! 158: if (!ferror(m->fp))
! 159: errno = EFTYPE; /* no final boundary seen */
! 160: return (-1);
! 161: }
! 162:
! 163: /* Recompute match counter using failure links and new data */
! 164: for (i = m->nbuf; i < m->nbuf + nr; i++) {
! 165: while (m->nmatch > 0 && m->buf[i] != m->bdry[m->nmatch])
! 166: m->nmatch = m->fail[m->nmatch];
! 167: if (m->buf[i] == m->bdry[m->nmatch])
! 168: m->nmatch++;
! 169: }
! 170: m->nbuf += nr;
! 171:
! 172: /* Try again */
! 173: return (boundary_read(cookie, buf, len));
! 174: }
! 175:
! 176: /*
! 177: * Close method.
! 178: */
! 179: static int
! 180: boundary_close(void *cookie)
! 181: {
! 182: struct boundary_fp *const m = cookie;
! 183:
! 184: if (m->closeit)
! 185: fclose(m->fp);
! 186: FREE(MEM_TYPE, m);
! 187: return (0);
! 188: }
! 189:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>