1#include "syshdrs.h" 2#ifdef PRAGMA_HDRSTOP 3# pragma hdrstop 4#endif 5 6static const char UNUSED(gSioVersion[]) = kSioVersion; 7static const char UNUSED(gCopyright[]) = "@(#) libsio Copyright 1992-2011, by Mike Gleason. All rights reserved."; 8 9 10/* Read up to "size" bytes on sfd before "tlen" seconds. 11 * 12 * If "retry" is on, after a successful read of less than "size" 13 * bytes, it will attempt to read more, upto "size." 14 * 15 * If the timer elapses and one or more bytes were read, it returns 16 * that number, otherwise a timeout error is returned. 17 * 18 * Although "retry" would seem to indicate you may want to always 19 * read "size" bytes or else it is an error, even with that on you 20 * may get back a value < size. Set "retry" to 0 when you want to 21 * return as soon as there is a chunk of data whose size is <= "size". 22 */ 23 24int 25SRead(int sfd, char *const buf0, size_t size, int tlen, int retry) 26{ 27 read_return_t nread; 28 read_size_t nleft; 29 char *buf = buf0; 30 int tleft; 31 time_t done, now; 32 fd_set ss; 33 struct timeval tv; 34 int result, firstRead; 35 DECL_SIGPIPE_VARS 36 37 if ((buf == NULL) || (size == 0) || (tlen <= 0)) { 38 errno = EINVAL; 39 return (-1); 40 } 41 42 IGNORE_SIGPIPE 43 errno = 0; 44 45 nleft = (read_size_t) size; 46 time(&now); 47 done = now + tlen; 48 firstRead = 1; 49 50 forever { 51 tleft = (done > now) ? ((int) (done - now)) : 0; 52 if (tleft < 1) { 53 nread = (read_return_t) size - (read_return_t) nleft; 54 if ((nread == 0) || ((retry & (kFullBufferRequired|kFullBufferRequiredExceptLast)) != 0)) { 55 nread = kTimeoutErr; 56 errno = ETIMEDOUT; 57 SETWSATIMEOUTERR 58 } 59 goto done; 60 } 61 62 if (!firstRead || ((retry & kNoFirstSelect) == 0)) { 63 forever { 64 errno = 0; 65 MY_FD_ZERO(&ss); 66#if defined(__DECC) || defined(__DECCXX) 67#pragma message save 68#pragma message disable trunclongint 69#endif 70 MY_FD_SET(sfd, &ss); 71#if defined(__DECC) || defined(__DECCXX) 72#pragma message restore 73#endif 74 tv.tv_sec = (tv_sec_t) tleft; 75 tv.tv_usec = 0; 76 result = select(sfd + 1, SELECT_TYPE_ARG234 &ss, NULL, NULL, SELECT_TYPE_ARG5 &tv); 77 if (result >= 1) { 78 /* ready */ 79 break; 80 } else if (result == 0) { 81 /* timeout */ 82 nread = (read_return_t) size - (read_return_t) nleft; 83 if ((nread > 0) && ((retry & (kFullBufferRequired|kFullBufferRequiredExceptLast)) == 0)) { 84 RESTORE_SIGPIPE 85 return ((int) nread); 86 } 87 errno = ETIMEDOUT; 88 SETWSATIMEOUTERR 89 RESTORE_SIGPIPE 90 return (kTimeoutErr); 91 } else if (errno != EINTR) { 92 RESTORE_SIGPIPE 93 return (-1); 94 } 95 } 96 firstRead = 0; 97 } 98 99#if (defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__) 100 nread = recv(sfd, (char *) buf, (recv_size_t) nleft, 0); 101#else 102 nread = read(sfd, (char *) buf, nleft); 103#endif 104 105 if (nread <= 0) { 106 if (nread == 0) { 107 /* EOF */ 108 if (retry == ((retry & (kFullBufferRequiredExceptLast)) != 0)) 109 nread = (read_return_t) size - (read_return_t) nleft; 110 goto done; 111 } else if (errno != EINTR) { 112 nread = (read_return_t) size - (read_return_t) nleft; 113 if (nread == 0) 114 nread = (read_return_t) -1; 115 goto done; 116 } else { 117 errno = 0; 118 nread = 0; 119 /* Try again. */ 120 121 /* Ignore these two lines */ 122 LIBSIO_USE_VAR(gSioVersion); 123 LIBSIO_USE_VAR(gCopyright); 124 } 125 } 126 nleft -= (read_size_t) nread; 127 if ((nleft == 0) || (((retry & (kFullBufferRequired|kFullBufferRequiredExceptLast)) == 0) && (nleft != (read_size_t) size))) 128 break; 129 buf += nread; 130 time(&now); 131 } 132 nread = (read_return_t) size - (read_return_t) nleft; 133 134done: 135 RESTORE_SIGPIPE 136 return ((int) nread); 137} /* SRead */ 138