/* $NetBSD: funopen.c,v 1.14 2012/03/28 15:21:11 christos Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Christos Zoulas. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <sys/cdefs.h> #if defined(LIBC_SCCS) && !defined(lint) __RCSID("$NetBSD: funopen.c,v 1.14 2012/03/28 15:21:11 christos Exp $"); #endif /* LIBC_SCCS and not lint */ #include <stdio.h> #include <string.h> #include <errno.h> #include <stdlib.h> #include <unistd.h> #include <stddef.h> #ifndef HAVE_NBTOOL_CONFIG_H #include "reentrant.h" #include "local.h" #endif struct str { const char *buf; size_t len; off_t off; }; static ssize_t readfn(void *c, void *buf, size_t len) { struct str *s = c; size_t avail = s->len - (size_t)s->off; if (len > avail) len = avail; memcpy(buf, s->buf + s->off, len); return (ssize_t)len; } static off_t seekfn(void *c, off_t off, int whence) { struct str *s = c; switch (whence) { case SEEK_SET: s->off = off; break; case SEEK_END: s->off = s->len; break; case SEEK_CUR: s->off += off; break; default: errno = EINVAL; return -1; } if (s->off < 0) s->off = 0; else if ((size_t)s->off > s->len) s->off = s->len; return s->off; } static int closefn(void *c) { free(c); return 0; } FILE * stropen(const char *str) { struct str *c = malloc(sizeof(*c)); if (c == NULL) return NULL; c->buf = str; c->off = 0; c->len = strlen(str); return funopen2(c, readfn, NULL, seekfn, NULL, closefn); }