00001 #include "config.h"
00002
00003 #include "headers.h"
00004 #include "error.h"
00005 #include "fd.h"
00006 #include "io.h"
00007
00008
00009 IO io;
00010
00011
00012
00013
00014 int ioInit(void)
00015 {
00016
00017 io.in_path = 0;
00018
00019 io.in = STDIN_FILENO;
00020
00021 io.out = STDOUT_FILENO;
00022
00023 io.eof_in = 0;
00024 io.eof_out = 0;
00025
00026 io.buffer_used = 0;
00027 io.buffer_head = 0;
00028 io.buffer_size = DEFAULT_BUFFER_SIZE;
00029 io.buffer = 0;
00030
00031 io.last_read = 0;
00032 io.last_write = 0;
00033 io.total_size = 0;
00034 io.total_size_known = 0;
00035 io.total_read = 0;
00036 io.total_write = 0;
00037 io.continue_size = 0;
00038
00039 io.timeout = 1;
00040
00041 io.current_time = time(0);
00042 io.throttle_count = 1;
00043 io.throttle = MAX_UINT64;
00044
00045 io.block_size = 512;
00046 return(0);
00047 }
00048
00049 #ifdef HAVE_SIGNAL_H
00050
00051
00052
00053
00054 static void sig_int(int signo)
00055 {
00056
00057 fdEnd(io.in);
00058 fdEnd(io.out);
00059 exit(1);
00060 }
00061 #endif
00062
00063 #ifdef HAVE_SYSCONF
00064 # if HAVE_DECL__SC_PAGE_SIZE == 1
00065 # define PAGESIZE _SC_PAGE_SIZE
00066 # else
00067 # if HAVE_DECL__SC_PAGESIZE == 1
00068 # define PAGESIZE _SC_PAGESIZE
00069 # endif
00070 # endif
00071 # ifndef PAGESIZE
00072 # warning I dont know how to retrieve the size of a page using sysconf.
00073 # warning Assuming page size is DEFAULT_PAGE_SIZE bytes.
00074 # undef HAVE_SYSCONF
00075 # endif
00076 #endif
00077
00078
00079
00080
00081
00082 int ioBegin(void)
00083 {
00084
00085
00086
00087
00088 #if defined(USE_MEMALIGN) \
00089 && (defined(HAVE_POSIX_MEMALIGN) || defined(HAVE_MEMALIGN))
00090 long page_size = 0;
00091
00092 # ifdef HAVE_SYSCONF
00093 page_size = sysconf(PAGESIZE);
00094 # else
00095 page_size = DEFAULT_PAGE_SIZE;
00096 # endif
00097 #endif
00098
00099
00100 #undef USED_MEMALIGN
00101 #ifdef USE_MEMALIGN
00102 # if defined(HAVE_POSIX_MEMALIGN)
00103 # define USED_MEMALIGN
00104 if (
00105
00106
00107
00108 posix_memalign((void*)&io.buffer, page_size, sizeof(char) * io.buffer_size) != 0
00109 )
00110 {
00111 print_error(stderr, "Memory allocation failed");
00112 return(1);
00113 }
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 # endif
00125 #endif
00126 #ifndef USED_MEMALIGN
00127 io.buffer = (char *)malloc(sizeof(char) * io.buffer_size);
00128 #endif
00129 if (io.buffer == 0) {
00130 print_error(stderr, "Memory allocation failed");
00131 return(1);
00132 }
00133
00134
00135 #ifdef HAVE_SIGNAL_H
00136 if (signal(SIGINT, sig_int) == SIG_ERR) {
00137 print_error(stderr, "Could not install SIGINT signal handler");
00138 print_error(stderr, "Control-C events will not reset non-blocking I/O");
00139 }
00140 #endif
00141
00142 fdBegin(io.in);
00143 fdBegin(io.out);
00144 return(0);
00145 }
00146
00147
00148
00149
00150
00151 int ioEnd(void)
00152 {
00153
00154 free(io.buffer);
00155 io.buffer = 0;
00156 io.buffer_used = 0;
00157
00158 fdEnd(io.in);
00159 fdEnd(io.out);
00160 return(0);
00161 }
00162
00163
00164 void ioCheck(void)
00165 {
00166 static fd_set rset, wset;
00167 static struct timeval to;
00168
00169 to.tv_sec = 0;
00170
00171 to.tv_usec = io.timeout;
00172 io.in_ready = 1;
00173 io.out_ready = 1;
00174 FD_ZERO(&rset);
00175 FD_ZERO(&wset);
00176 if (io.buffer_used != io.buffer_size) FD_SET(io.in, &rset);
00177 if (io.buffer_used) FD_SET(io.out, &wset);
00178
00179 if (select( ((io.in<io.out)?io.out:io.in)+1,
00180 &rset, &wset, 0, &to) == -1) {
00181 if (errno != EINTR) {
00182 print_error(stderr, "select() failed");
00183 return;
00184 }
00185 }
00186
00187 if (!FD_ISSET(io.in, &rset))
00188 io.in_ready = 0;
00189 if (!FD_ISSET(io.out, &wset))
00190 io.out_ready = 0;
00191 }
00192
00193
00194
00195
00196
00197 int ioRead(void)
00198 {
00199 int num_read = 0;
00200 int end = 0;
00201 int avail = 0;
00202 #ifdef USE_IOVEC
00203 int num = 0;
00204 struct iovec vec[2] = { { 0 } };
00205 #endif
00206
00207
00208 if ((io.current_time == time(0))
00209 && (io.throttle_count >= io.throttle)) {
00210 return(0);
00211 }
00212 if (io.current_time != time(0)) {
00213 io.throttle_count = 0;
00214 io.current_time = time(0);
00215 }
00216
00217 if (!io.in_ready) return(0);
00218 io.last_read = 0;
00219
00220 if (io.eof_in) return(0);
00221
00222 if (io.buffer_used == io.buffer_size) return(0);
00223
00224 end = (io.buffer_used + io.buffer_head) % io.buffer_size;
00225 avail = io.buffer_size - io.buffer_used;
00226
00227
00228
00229 if ((io.throttle - io.throttle_count) < avail)
00230 avail = io.throttle - io.throttle_count;
00231 #ifdef USE_IOVEC
00232
00233
00234
00235 vec[num ].iov_base = io.buffer + end;
00236 if (end+avail <= io.buffer_size)
00237 vec[num++].iov_len = avail;
00238 else {
00239 vec[num++].iov_len = io.buffer_size - end;
00240 vec[num ].iov_base = io.buffer;
00241 vec[num++].iov_len = avail - (io.buffer_size - end);
00242 }
00243 num_read = readv(io.in, vec, num);
00244 #else
00245
00246
00247
00248 if (end+avail <= io.buffer_size) {
00249 num_read = read(io.in,
00250 io.buffer + end,
00251 avail);
00252 }
00253 else {
00254 num_read = read(io.in,
00255 io.buffer + end,
00256 io.buffer_size - end);
00257 }
00258 #endif
00259
00260 if (num_read == 0) {
00261 io.eof_in = 1;
00262 return(0);
00263 }
00264
00265 if ((num_read < 0) && (errno == EAGAIN))
00266 num_read = 0;
00267 if (num_read < 0) return(num_read);
00268
00269 io.buffer_used += num_read;
00270 io.last_read = num_read;
00271 io.total_read += num_read;
00272 io.throttle_count += num_read;
00273 return(0);
00274 }
00275
00276
00277
00278
00279
00280 int ioWrite(void)
00281 {
00282 int num_written = 0;
00283 #ifdef USE_IOVEC
00284 int num = 0;
00285 struct iovec vec[2] = { { 0 } };
00286 #endif
00287
00288
00289 if (!io.out_ready) return(0);
00290 io.last_write = 0;
00291 #ifdef USE_IOVEC
00292
00293
00294
00295 vec[num ].iov_base = io.buffer + io.buffer_head;
00296 if (io.buffer_head + io.buffer_used <= io.buffer_size)
00297 vec[num++].iov_len = io.buffer_used;
00298 else {
00299 vec[num++].iov_len = io.buffer_size - io.buffer_head;
00300 vec[num ].iov_base = io.buffer;
00301 vec[num++].iov_len = io.buffer_used - (io.buffer_size - io.buffer_head);
00302 }
00303 num_written = writev(io.out, vec, num);
00304 #else
00305
00306
00307
00308 if (io.buffer_head + io.buffer_used <= io.buffer_size) {
00309 num_written = write(io.out,
00310 io.buffer + io.buffer_head,
00311 io.buffer_used);
00312 }
00313 else {
00314 num_written = write(io.out,
00315 io.buffer + io.buffer_head,
00316 io.buffer_size - io.buffer_head);
00317 }
00318 #endif
00319
00320 if (num_written == 0) {
00321 io.eof_out = 1;
00322 return(0);
00323 }
00324
00325 if ((num_written < 0) && (errno == EAGAIN))
00326 num_written = 0;
00327 if (num_written < 0) return(num_written);
00328
00329 io.buffer_used -= num_written;
00330 io.buffer_head = (io.buffer_head + num_written) % io.buffer_size;
00331 io.last_write = num_written;
00332 io.total_write += num_written;
00333 return(0);
00334 }
00335
00336
00337
00338
00339
00340 int ioIsDone(void)
00341 {
00342 if ((io.eof_in && (io.buffer_used == 0)) || io.eof_out) return(1);
00343 return(0);
00344 }
00345