compat: add writev() replacement

This commit is contained in:
Rémi Denis-Courmont 2022-07-02 17:23:34 +03:00 committed by Felix Paul Kühne
parent 543d179d87
commit a29ba2f99a
3 changed files with 78 additions and 1 deletions

72
compat/writev.c Normal file
View File

@ -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 <config.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
# include <io.h>
#else
# include <unistd.h>
#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;
}

View File

@ -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.])

View File

@ -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 *);