Hello,
I call readv() and writev() in several spots of a program which I run
under Linux, OpenBSD and Cygwin. Since it always the same way
(check the return value; then check errno and retry if EAGAIN/EINTR),
I've written a wrapper function (full source code on the bottom)
to call those functions and just pass the function pointer to it:
do {
...
} while ((n = transmit_iov(writev, cfg->fd, iov, iovcnt)) <= 0);
-OR-
if (transmit_iov(writev, pkid->fd, iov, 2) <= 0) {
...
}
It has always worked until I switched to FC5 Linux which uses:
$ gcc -v
Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man
--infodir=/usr/share/info --enable-shared --enable-threads=posix
--enable-checking=release --with-system-zlib --enable-__cxa_atexit
--disable-libunwind-exceptions --enable-libgcj-multifile
--enable-languages=c,c++,objc,obj-c++,java,fortran,ada
--enable-java-awt=gtk --disable-dssi
--with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre
--with-cpu=generic --host=i386-redhat-linux
Thread model: posix
gcc version 4.1.1 20060525 (Red Hat 4.1.1-1)
Now my compilation fails with:
$ gcc -Wall -I common -ggdb -O0 -DQUEUE_MACRO_DEBUG -D_GNU_SOURCE
-I openbsd-compat -I /usr/include -c common/common.c -o build/common.o
common/common.c: In function 'transmit_iov':
common/common.c:58: error: invalid lvalue in assignment
My problem is that I have an array struct iovec iov[], which is:
struct iovec {
void *iov_base; /* Starting address */
size_t iov_len; /* Number of bytes */
};
In my code I'm trying to advance the iov_base by the number of
bytes I have successfully transmitted in the previous readv/writev
call:
/* only part of iov[i].iov_base transmitted */
if (n < iov[i].iov_len) {
/* the troublesome line 58 */
(char *)iov[i].iov_base += n;
iov[i].iov_len -= n;
break;
}
And that's where gcc 4.x (or my code) is failing.
Does anybody please have a hint or solution for this probably
frequent problem: How to advance a void-pointer by few bytes?
Thank you
Alex
PS: and here is my wraper function for readv/writev():
/* The fp is either readv or writev; the iov array is not const */
int
transmit_iov(ssize_t (*fp)(int, const struct iovec*, int),
int fd, struct iovec iov[], int iovcnt)
{
int n;
unsigned i = 0;
while (i < iovcnt) {
/* skip eventual elements with iov_len=0
at the end of iov */
if (0 == iov[i].iov_len) {
i++;
continue;
}
/* keep retrying if interrupted by a signal
or would block */
do
n = (*fp)(fd, &iov[i], iovcnt - i);
while (-1 == n && (EINTR == errno || EAGAIN == errno));
/* give up on real failure or terminated connection */
if (n <= 0)
return n;
/* n bytes successfully transmitted, adjust iov[] */
while (n 0) {
/* only part of iov[i].iov_base transmitted */
if (n < iov[i].iov_len) {
(char *)iov[i].iov_base += n; /* line 58 */
iov[i].iov_len -= n;
break;
/* one array element transmitted completely */
} else {
n -= iov[i].iov_len;
i++;
}
}
}
return i;
}
--
http://preferans.de