Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement vector I/O operations #66

Open
wants to merge 5 commits into
base: vita
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion newlib/libc/sys/vita/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ DIRENT_OBJS = closedir.o opendir.o readdir.o readdir_r.o rewinddir.o seekdir.o t

NET_SOURCES = net/gethostbyaddr.c net/gethostbyname.c net/getaddrinfo.c net/freeaddrinfo.c net/getservbyname.c net/inet_ntop.c net/inet_ntoa.c net/inet_netof.c net/inet_pton.c net/inet_lnaof.c net/inet_addr.c net/inet_network.c net/inet_net_ntop.c net/inet_aton.c net/inet_net_pton.c net/inet_makeaddr.c
STUB_SOURCES = chroot.c getentropy.c groups.c
lib_a_SOURCES = syscalls.c access.c sbrk.c threading.c mlock.c io.c socket.c dup.c select.c error.c dirent.c lcltime_r.c sleep.c usleep.c truncate.c fs.c clock.c pread.c ${STUB_SOURCES} ${NET_SOURCES}
lib_a_SOURCES = syscalls.c access.c sbrk.c threading.c mlock.c io.c socket.c dup.c select.c error.c dirent.c lcltime_r.c sleep.c usleep.c truncate.c fs.c clock.c pread.c uio.c ${STUB_SOURCES} ${NET_SOURCES}
lib_a_LIBADD = ${SOCKET_OBJS} ${NET_OBJS} ${DIRENT_OBJS}
lib_a_CCASFLAGS = $(AM_CCASFLAGS)
lib_a_CFLAGS = $(AM_CFLAGS)
Expand Down
12 changes: 9 additions & 3 deletions newlib/libc/sys/vita/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ am_lib_a_OBJECTS = lib_a-syscalls.$(OBJEXT) lib_a-access.$(OBJEXT) \
lib_a-dirent.$(OBJEXT) lib_a-lcltime_r.$(OBJEXT) \
lib_a-sleep.$(OBJEXT) lib_a-usleep.$(OBJEXT) \
lib_a-truncate.$(OBJEXT) lib_a-fs.$(OBJEXT) \
lib_a-clock.$(OBJEXT) lib_a-pread.$(OBJEXT) $(am__objects_1) \
$(am__objects_2)
lib_a-clock.$(OBJEXT) lib_a-pread.$(OBJEXT) \
lib_a-uio.$(OBJEXT) $(am__objects_1) $(am__objects_2)
lib_a_OBJECTS = $(am_lib_a_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp =
Expand Down Expand Up @@ -220,7 +220,7 @@ NET_OBJS = gethostbyaddr.o gethostbyname.o getaddrinfo.o freeaddrinfo.o getservb
DIRENT_OBJS = closedir.o opendir.o readdir.o readdir_r.o rewinddir.o seekdir.o telldir.o
NET_SOURCES = net/gethostbyaddr.c net/gethostbyname.c net/getaddrinfo.c net/freeaddrinfo.c net/getservbyname.c net/inet_ntop.c net/inet_ntoa.c net/inet_netof.c net/inet_pton.c net/inet_lnaof.c net/inet_addr.c net/inet_network.c net/inet_net_ntop.c net/inet_aton.c net/inet_net_pton.c net/inet_makeaddr.c
STUB_SOURCES = chroot.c getentropy.c groups.c
lib_a_SOURCES = syscalls.c access.c sbrk.c threading.c mlock.c io.c socket.c dup.c select.c error.c dirent.c lcltime_r.c sleep.c usleep.c truncate.c fs.c clock.c pread.c ${STUB_SOURCES} ${NET_SOURCES}
lib_a_SOURCES = syscalls.c access.c sbrk.c threading.c mlock.c io.c socket.c dup.c select.c error.c dirent.c lcltime_r.c sleep.c usleep.c truncate.c fs.c clock.c pread.c uio.c ${STUB_SOURCES} ${NET_SOURCES}
lib_a_LIBADD = ${SOCKET_OBJS} ${NET_OBJS} ${DIRENT_OBJS}
lib_a_CCASFLAGS = $(AM_CCASFLAGS)
lib_a_CFLAGS = $(AM_CFLAGS)
Expand Down Expand Up @@ -392,6 +392,12 @@ lib_a-pread.o: pread.c
lib_a-pread.obj: pread.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-pread.obj `if test -f 'pread.c'; then $(CYGPATH_W) 'pread.c'; else $(CYGPATH_W) '$(srcdir)/pread.c'; fi`

lib_a-uio.o: uio.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-uio.o `test -f 'uio.c' || echo '$(srcdir)/'`uio.c

lib_a-uio.obj: uio.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-uio.obj `if test -f 'uio.c'; then $(CYGPATH_W) 'uio.c'; else $(CYGPATH_W) '$(srcdir)/uio.c'; fi`

lib_a-chroot.o: chroot.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-chroot.o `test -f 'chroot.c' || echo '$(srcdir)/'`chroot.c

Expand Down
6 changes: 1 addition & 5 deletions newlib/libc/sys/vita/sys/socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ extern "C" {
#include <stdint.h>
#include <stddef.h>
#include <sys/types.h>
#include <sys/uio.h>

typedef uint8_t sa_family_t;
typedef uint32_t socklen_t;
Expand Down Expand Up @@ -245,11 +246,6 @@ struct sockaddr_storage {
#define SHUT_WR 1 /* Disallow further sends. */
#define SHUT_RDWR 2 /* Disallow further sends/receives. */

struct iovec {
void *iov_base; /* Base address. */
size_t iov_len; /* Length. */
};

struct msghdr {
void *msg_name; /* optional address */
socklen_t msg_namelen; /* size of address */
Expand Down
40 changes: 40 additions & 0 deletions newlib/libc/sys/vita/sys/uio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (C) 1991-2018 Free Software Foundation, Inc.
* This file is part of the GNU C Library.
* The GNU C Library 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.
* The GNU C Library 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 the GNU C Library; if not, see
* <http://www.gnu.org/licenses/>.
*/

#ifndef _SYS_UIO_H_
#define _SYS_UIO_H_

#include <sys/types.h>
#include <string.h>
#include <sys/cdefs.h>

__BEGIN_DECLS

#ifndef __GNU_VISIBLE
void* mempcpy(void *<[out]>, const void *<[in]>, size_t <[n]>);
#endif

struct iovec {
void *iov_base;
size_t iov_len;
};

ssize_t readv(int, const struct iovec *, int);
ssize_t writev(int, const struct iovec *, int);

__END_DECLS

#endif /* sys/uio.h */
134 changes: 134 additions & 0 deletions newlib/libc/sys/vita/uio.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* Copyright (C) 1991-2018 Free Software Foundation, Inc.
* This file is part of the GNU C Library.
* The GNU C Library 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.
* The GNU C Library 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 the GNU C Library; if not, see
* <http://www.gnu.org/licenses/>.
*/

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
#include <stdbool.h>
#include <sys/param.h>
#include <sys/uio.h>
#include <errno.h>

#ifndef SSIZE_MAX
/* ssize_t is not formally required to be the signed type
corresponding to size_t, but it is for all configurations supported
by glibc. */
# if __WORDSIZE == 64 || __WORDSIZE32_SIZE_ULONG
# define SSIZE_MAX LONG_MAX
# else
# define SSIZE_MAX INT_MAX
# endif
#endif

static void ifree (char **ptrp)
{
free (*ptrp);
}

/* Write data pointed by the buffers described by VECTOR, which
is a vector of COUNT 'struct iovec's, to file descriptor FD.
The data is written in the order specified.
Operates just like 'write' (see <unistd.h>) except that the data
are taken from VECTOR instead of a contiguous buffer. */
ssize_t writev (int fd, const struct iovec *vector, int count)
{
/* Find the total number of bytes to be written. */
size_t bytes = 0;
for (int i = 0; i < count; ++i)
{
/* Check for ssize_t overflow. */
if (SSIZE_MAX - bytes < vector[i].iov_len)
{
return -1;
}
bytes += vector[i].iov_len;
}

char *buffer;
char *malloced_buffer __attribute__ ((__cleanup__ (ifree))) = NULL;

malloced_buffer = buffer = (char *) malloc (bytes);
if (buffer == NULL)
/* XXX I don't know whether it is acceptable to try writing the data in chunks. Probably not so we just fail here. */
return -1;

/* Copy the data into BUFFER. */
size_t to_copy = bytes;
char *bp = buffer;
for (int i = 0; i < count; ++i)
{
size_t copy = MIN (vector[i].iov_len, to_copy);

bp = mempcpy ((void *) bp, (void *) vector[i].iov_base, copy);

to_copy -= copy;
if (to_copy == 0)
break;
}

ssize_t bytes_written = write (fd, buffer, bytes);

return bytes_written;
}

/* Read data from file descriptor FD, and put the result in the
buffers described by VECTOR, which is a vector of COUNT 'struct iovec's.
The buffers are filled in the order specified.
Operates just like 'read' (see <unistd.h>) except that data are
put in VECTOR instead of a contiguous buffer. */
ssize_t readv (int fd, const struct iovec *vector, int count)
{
/* Find the total number of bytes to be read. */
size_t bytes = 0;
for (int i = 0; i < count; ++i)
{
/* Check for ssize_t overflow. */
if (SSIZE_MAX - bytes < vector[i].iov_len)
{
return -1;
}
bytes += vector[i].iov_len;
}

char *buffer;
char *malloced_buffer __attribute__ ((__cleanup__ (ifree))) = NULL;

malloced_buffer = buffer = (char *) malloc (bytes);
if (buffer == NULL)
return -1;

/* Read the data. */
ssize_t bytes_read = read (fd, buffer, bytes);
if (bytes_read < 0)
return -1;

/* Copy the data from BUFFER into the memory specified by VECTOR. */
bytes = bytes_read;
for (int i = 0; i < count; ++i)
{
size_t copy = MIN (vector[i].iov_len, bytes);

(void) memcpy ((void *) vector[i].iov_base, (void *) buffer, copy);

buffer += copy;
bytes -= copy;
if (bytes == 0)
break;
}

return bytes_read;
}