X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=blobdiff_plain;f=libatalk%2Futil%2Fsocket.c;h=9afaa3ebe40352163f4c051f71fa8af64e82c972;hp=5dc3f81c8540924fba9b2b36f8379d500772c5c6;hb=df4786e567fddb4b238f658d43e2662f488f73ba;hpb=25c190599c010773d5738dd8c6b696c9b59a56f3 diff --git a/libatalk/util/socket.c b/libatalk/util/socket.c index 5dc3f81c..9afaa3eb 100644 --- a/libatalk/util/socket.c +++ b/libatalk/util/socket.c @@ -1,5 +1,4 @@ /* - $Id: socket.c,v 1.6 2010-01-05 19:05:52 franklahm Exp $ Copyright (c) 2009 Frank Lahm This program is free software; you can redistribute it and/or modify @@ -31,6 +30,8 @@ #include #include #include +#include +#include #include @@ -81,7 +82,7 @@ ssize_t readt(int socket, void *data, const size_t length, int setnonblocking, i { size_t stored; ssize_t len; - struct timeval tv; + struct timeval now, end, tv; fd_set rfds; int ret; @@ -92,6 +93,11 @@ ssize_t readt(int socket, void *data, const size_t length, int setnonblocking, i return -1; } + /* Calculate end time */ + (void)gettimeofday(&now, NULL); + end = now; + end.tv_sec += timeout; + while (stored < length) { len = read(socket, (char *) data + stored, length - stored); if (len == -1) { @@ -99,34 +105,51 @@ ssize_t readt(int socket, void *data, const size_t length, int setnonblocking, i case EINTR: continue; case EAGAIN: - tv.tv_usec = 0; - tv.tv_sec = timeout; - FD_ZERO(&rfds); FD_SET(socket, &rfds); + tv.tv_usec = 0; + tv.tv_sec = timeout; + while ((ret = select(socket + 1, &rfds, NULL, NULL, &tv)) < 1) { switch (ret) { case 0: - LOG(log_warning, logtype_cnid, "select timeout 1s"); + LOG(log_warning, logtype_afpd, "select timeout %d s", timeout); goto exit; default: /* -1 */ - LOG(log_error, logtype_cnid, "select: %s", strerror(errno)); + if (errno == EINTR) { + (void)gettimeofday(&now, NULL); + if (now.tv_sec >= end.tv_sec && now.tv_usec >= end.tv_usec) { + LOG(log_warning, logtype_afpd, "select timeout %d s", timeout); + goto exit; + } + if (now.tv_usec > end.tv_usec) { + tv.tv_usec = 1000000 + end.tv_usec - now.tv_usec; + tv.tv_sec = end.tv_sec - now.tv_sec - 1; + } else { + tv.tv_usec = end.tv_usec - now.tv_usec; + tv.tv_sec = end.tv_sec - now.tv_sec; + } + FD_ZERO(&rfds); + FD_SET(socket, &rfds); + continue; + } + LOG(log_error, logtype_afpd, "select: %s", strerror(errno)); stored = -1; goto exit; } - } + } /* while (select) */ continue; - } - LOG(log_error, logtype_cnid, "read: %s", strerror(errno)); + } /* switch (errno) */ + LOG(log_error, logtype_afpd, "read: %s", strerror(errno)); stored = -1; goto exit; - } + } /* (len == -1) */ else if (len > 0) stored += len; else break; - } + } /* while (stored < length) */ exit: if (setnonblocking) { @@ -134,6 +157,9 @@ exit: return -1; } + if (len == -1 && stored == 0) + /* last read or select got an error and we haven't got yet anything => return -1*/ + return -1; return stored; }