diff options
Diffstat (limited to 'libc')
| -rw-r--r-- | libc/Android.bp | 2 | ||||
| -rw-r--r-- | libc/NOTICE | 42 | ||||
| -rw-r--r-- | libc/stdio/fmemopen.cpp | 156 | ||||
| -rw-r--r-- | libc/upstream-openbsd/lib/libc/stdio/fmemopen.c | 184 |
4 files changed, 182 insertions, 202 deletions
diff --git a/libc/Android.bp b/libc/Android.bp index be1c6f9ed..842dae408 100644 --- a/libc/Android.bp +++ b/libc/Android.bp @@ -13,6 +13,7 @@ libc_common_src_files = [ "bionic/sigblock.c", "bionic/siginterrupt.c", "bionic/sigsetmask.c", + "stdio/fmemopen.cpp", "stdio/fread.c", "stdio/parsefloat.c", "stdio/refill.c", @@ -439,7 +440,6 @@ cc_library_static { "upstream-openbsd/lib/libc/stdio/fgetwc.c", "upstream-openbsd/lib/libc/stdio/fgetws.c", "upstream-openbsd/lib/libc/stdio/flags.c", - "upstream-openbsd/lib/libc/stdio/fmemopen.c", "upstream-openbsd/lib/libc/stdio/fpurge.c", "upstream-openbsd/lib/libc/stdio/fputs.c", "upstream-openbsd/lib/libc/stdio/fputwc.c", diff --git a/libc/NOTICE b/libc/NOTICE index ae98d1ddd..90de7ef58 100644 --- a/libc/NOTICE +++ b/libc/NOTICE @@ -682,6 +682,31 @@ SUCH DAMAGE. ------------------------------------------------------------------- +Copyright (C) 2013 Pietro Cerutti <gahr@FreeBSD.org> + +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. + +THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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. + +------------------------------------------------------------------- + Copyright (C) 2013 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); @@ -5071,23 +5096,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ------------------------------------------------------------------- -Copyright (c) 2011 Martin Pieuchot <mpi@openbsd.org> -Copyright (c) 2009 Ted Unangst - -Permission to use, copy, modify, and distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -------------------------------------------------------------------- - Copyright (c) 2011 The Android Open Source Project Copyright (c) 2008 ARM Ltd All rights reserved. diff --git a/libc/stdio/fmemopen.cpp b/libc/stdio/fmemopen.cpp new file mode 100644 index 000000000..9d8c41f12 --- /dev/null +++ b/libc/stdio/fmemopen.cpp @@ -0,0 +1,156 @@ +/*- + * Copyright (C) 2013 Pietro Cerutti <gahr@FreeBSD.org> + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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> + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "local.h" + +// See http://pubs.opengroup.org/onlinepubs/9699919799/functions/fmemopen.html +// and http://man7.org/linux/man-pages/man3/fmemopen.3.html for documentation. + +struct fmemopen_cookie { + char* buf; + char* allocation; + size_t capacity; + size_t size; + size_t offset; + bool append; +}; + +static int fmemopen_read(void* cookie, char* buf, int n) { + fmemopen_cookie* ck = static_cast<fmemopen_cookie*>(cookie); + + if (static_cast<size_t>(n) > ck->size - ck->offset) n = ck->size - ck->offset; + + if (n > 0) { + memmove(buf, ck->buf + ck->offset, n); + ck->offset += n; + } + return n; +} + +static int fmemopen_write(void* cookie, const char* buf, int n) { + fmemopen_cookie* ck = static_cast<fmemopen_cookie*>(cookie); + + // We don't need to add the trailing NUL if there's already a trailing NUL + // in the data we're writing. + size_t space_for_null = (n > 0 && buf[n - 1] != '\0') ? 1 : 0; + + // Undo any seeking/reading on an append-only stream. + if (ck->append) ck->offset = ck->size; + + // How much can we actually fit? + if (static_cast<size_t>(n) + space_for_null > ck->capacity - ck->offset) { + n = ck->capacity - ck->offset - space_for_null; + // Give up if we don't even have room for one byte of userdata. + if (n <= 0) { + errno = ENOSPC; + return -1; + } + } + + if (n > 0) { + memmove(ck->buf + ck->offset, buf, n); + ck->offset += n; + // Is this the furthest we've ever been? + if (ck->offset >= ck->size) { + if (buf[n - 1] != '\0') ck->buf[ck->offset] = '\0'; + ck->size = ck->offset; + } + } + return n; +} + +static fpos_t fmemopen_seek(void* cookie, fpos_t offset, int whence) { + fmemopen_cookie* ck = static_cast<fmemopen_cookie*>(cookie); + + if (whence == SEEK_SET && (offset >= 0 && static_cast<size_t>(offset) <= ck->capacity)) { + return (ck->offset = offset); + } else if (whence == SEEK_CUR && (ck->offset + offset <= ck->capacity)) { + return (ck->offset += offset); + } else if (whence == SEEK_END && (offset <= 0 && static_cast<size_t>(-offset) <= ck->size)) { + return (ck->offset = ck->size + offset); + } + errno = EINVAL; + return -1; +} + +static int fmemopen_close(void* cookie) { + fmemopen_cookie* ck = static_cast<fmemopen_cookie*>(cookie); + free(ck->allocation); + free(ck); + return 0; +} + +FILE* fmemopen(void* buf, size_t capacity, const char* mode) { + int flags; + if (__sflags(mode, &flags) == 0) { + errno = EINVAL; + return nullptr; + } + + fmemopen_cookie* ck = static_cast<fmemopen_cookie*>(calloc(sizeof(fmemopen_cookie), 1)); + if (ck == nullptr) return nullptr; + + ck->buf = static_cast<char*>(buf); + ck->capacity = capacity; + + if (ck->buf == nullptr) ck->buf = ck->allocation = static_cast<char*>(calloc(capacity, 1)); + if (ck->buf == nullptr) { + free(ck); + return nullptr; + } + + FILE* fp = funopen(ck, + (flags & O_WRONLY) ? nullptr : fmemopen_read, + (flags & O_RDONLY) ? nullptr : fmemopen_write, + fmemopen_seek, + fmemopen_close); + if (fp == nullptr) { + fmemopen_close(ck); + return nullptr; + } + + if (mode[0] == 'a') { + ck->size = strnlen(ck->buf, ck->capacity); + ck->offset = ck->size; + ck->append = true; + } else if (mode[0] == 'r') { + ck->size = capacity; + ck->offset = 0; + } else if (mode[0] == 'w') { + ck->size = 0; + ck->offset = 0; + ck->buf[0] = '\0'; + } + + return fp; +} diff --git a/libc/upstream-openbsd/lib/libc/stdio/fmemopen.c b/libc/upstream-openbsd/lib/libc/stdio/fmemopen.c deleted file mode 100644 index 00c27646b..000000000 --- a/libc/upstream-openbsd/lib/libc/stdio/fmemopen.c +++ /dev/null @@ -1,184 +0,0 @@ -/* $OpenBSD: fmemopen.c,v 1.3 2015/08/31 02:53:57 guenther Exp $ */ - -/* - * Copyright (c) 2011 Martin Pieuchot <mpi@openbsd.org> - * Copyright (c) 2009 Ted Unangst - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "local.h" - -struct state { - char *string; /* actual stream */ - size_t pos; /* current position */ - size_t size; /* allocated size */ - size_t len; /* length of the data */ - int update; /* open for update */ -}; - -static int -fmemopen_read(void *v, char *b, int l) -{ - struct state *st = v; - int i; - - for (i = 0; i < l && i + st->pos < st->len; i++) - b[i] = st->string[st->pos + i]; - st->pos += i; - - return (i); -} - -static int -fmemopen_write(void *v, const char *b, int l) -{ - struct state *st = v; - int i; - - for (i = 0; i < l && i + st->pos < st->size; i++) - st->string[st->pos + i] = b[i]; - st->pos += i; - - if (st->pos >= st->len) { - st->len = st->pos; - - if (st->len < st->size) - st->string[st->len] = '\0'; - else if (!st->update) - st->string[st->size - 1] = '\0'; - } - - return (i); -} - -static fpos_t -fmemopen_seek(void *v, fpos_t off, int whence) -{ - struct state *st = v; - ssize_t base = 0; - - switch (whence) { - case SEEK_SET: - break; - case SEEK_CUR: - base = st->pos; - break; - case SEEK_END: - base = st->len; - break; - } - - if (off > st->size - base || off < -base) { - errno = EOVERFLOW; - return (-1); - } - - st->pos = base + off; - - return (st->pos); -} - -static int -fmemopen_close(void *v) -{ - free(v); - - return (0); -} - -static int -fmemopen_close_free(void *v) -{ - struct state *st = v; - - free(st->string); - free(st); - - return (0); -} - -FILE * -fmemopen(void *buf, size_t size, const char *mode) -{ - struct state *st; - FILE *fp; - int flags, oflags; - - if (size == 0) { - errno = EINVAL; - return (NULL); - } - - if ((flags = __sflags(mode, &oflags)) == 0) { - errno = EINVAL; - return (NULL); - } - - if (buf == NULL && ((oflags & O_RDWR) == 0)) { - errno = EINVAL; - return (NULL); - } - - if ((st = malloc(sizeof(*st))) == NULL) - return (NULL); - - if ((fp = __sfp()) == NULL) { - free(st); - return (NULL); - } - - st->pos = 0; - st->len = (oflags & O_WRONLY) ? 0 : size; - st->size = size; - st->update = oflags & O_RDWR; - - if (buf == NULL) { - if ((st->string = malloc(size)) == NULL) { - free(st); - fp->_flags = 0; - return (NULL); - } - *st->string = '\0'; - } else { - st->string = (char *)buf; - - if (oflags & O_TRUNC) - *st->string = '\0'; - - if (oflags & O_APPEND) { - char *p; - - if ((p = memchr(st->string, '\0', size)) != NULL) - st->pos = st->len = (p - st->string); - else - st->pos = st->len = size; - } - } - - fp->_flags = (short)flags; - fp->_file = -1; - fp->_cookie = (void *)st; - fp->_read = (flags & __SWR) ? NULL : fmemopen_read; - fp->_write = (flags & __SRD) ? NULL : fmemopen_write; - fp->_seek = fmemopen_seek; - fp->_close = (buf == NULL) ? fmemopen_close_free : fmemopen_close; - - return (fp); -} -DEF_WEAK(fmemopen); |
