diff --git a/compat/writev.c b/compat/writev.c new file mode 100644 index 0000000000..10acccb671 --- /dev/null +++ b/compat/writev.c @@ -0,0 +1,72 @@ +/***************************************************************************** + * writev.c: POSIX writev() replacement + ***************************************************************************** + * Copyright © 2022 Rémi Denis-Courmont + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +#ifdef _WIN32 +# include +#else +# include +#endif + +ssize_t writev(int fd, const struct iovec *iov, int iovcnt) +{ + if (iovcnt == 1) + return write(fd, iov->iov_base, iov->iov_len); + + size_t size = 0; + + for (int i = 0; i < iovcnt; i++) { + /* TODO: use ckd_add() */ + size += iov[i].iov_len; + + if (iov[i].iov_len > size) { + errno = EINVAL; + return -1; + } + } + + void *buf = malloc(size ? size : 1); + if (buf == NULL) { + errno = ENOBUFS; + return -1; + } + + unsigned char *ptr = buf; + + for (int i = 0; i < iovcnt; i++) { + memcpy(ptr, iov->iov_base, iov->iov_len); + ptr += iov->iov_len; + iov++; + } + + ssize_t bytes = write(fd, buf, size); + int saved_errno = errno; + + free(buf); + errno = saved_errno; + return bytes; +} diff --git a/configure.ac b/configure.ac index 168eff4024..a76226b320 100644 --- a/configure.ac +++ b/configure.ac @@ -718,7 +718,7 @@ need_libc=false dnl Check for usual libc functions AC_CHECK_FUNCS([accept4 dup3 fcntl flock fstatat fstatvfs fork getmntent_r getenv getpwuid_r isatty memalign mkostemp mmap open_memstream newlocale pipe2 posix_fadvise setlocale stricmp uselocale wordexp]) -AC_REPLACE_FUNCS([aligned_alloc atof atoll dirfd fdopendir flockfile fsync getdelim getpid lfind lldiv memrchr nrand48 poll posix_memalign readv recvmsg rewind sendmsg setenv strcasecmp strcasestr strdup strlcpy strndup strnlen strnstr strsep strtof strtok_r strtoll swab tdestroy tfind timegm timespec_get strverscmp]) +AC_REPLACE_FUNCS([aligned_alloc atof atoll dirfd fdopendir flockfile fsync getdelim getpid lfind lldiv memrchr nrand48 poll posix_memalign readv recvmsg rewind sendmsg setenv strcasecmp strcasestr strdup strlcpy strndup strnlen strnstr strsep strtof strtok_r strtoll swab tdestroy tfind timegm timespec_get strverscmp writev]) AC_REPLACE_FUNCS([gettimeofday]) AC_CHECK_FUNC(fdatasync,, [AC_DEFINE(fdatasync, fsync, [Alias fdatasync() to fsync() if missing.]) diff --git a/include/vlc_fixups.h b/include/vlc_fixups.h index 30f649d1e5..288f0b91bb 100644 --- a/include/vlc_fixups.h +++ b/include/vlc_fixups.h @@ -232,6 +232,11 @@ struct iovec; ssize_t readv(int, const struct iovec *, int); #endif +#ifndef HAVE_WRITEV +struct iovec; +ssize_t writev(int, const struct iovec *, int); +#endif + /* time.h */ #ifndef HAVE_GMTIME_R struct tm *gmtime_r (const time_t *, struct tm *);