chiark / gitweb /
From Peter Maydell (/u2/pmaydell/iwjbackup/) as per <E156bwm-0005xq-00@watchdragon...
[chiark-utils.git] / backup / readbuffer.c
1 /*
2  * readbuffer.c
3  *
4  * Copyright (C) 1997,1998 Ian Jackson <ian@chiark.greenend.org.uk>
5  *
6  * This is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2,
9  * or (at your option) any later version.
10  *
11  * This is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public
17  * License along with this file; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  *
20  */
21
22 #include <sys/time.h>
23 #include <sys/types.h>
24 #include <assert.h>
25 #include <fcntl.h>
26 #include <stdio.h>
27 #include <errno.h>
28 #include <unistd.h>
29
30 /* was 16MB -- PMM */
31 #define BUFFER 6*1024*1024
32 #define WAITEMPTY ((BUFFER*1)/4)
33
34 static inline int min(int a, int b) { return a<=b ? a : b; }
35
36 static void nonblock(int fd) {
37   int r;
38   r= fcntl(fd,F_GETFL,0); if (r == -1) { perror("fcntl getfl"); exit(1); }
39   r |= O_NDELAY;
40   if (fcntl(fd,F_SETFL,r) == -1) { perror("fcntl setfl"); exit(1); }
41 }
42
43 int main(void) {
44   static unsigned char buf[BUFFER];
45   
46   unsigned char *wp, *rp;
47   int used,r,reading,seeneof;
48   fd_set readfds;
49   fd_set writefds;
50
51   used=0; wp=rp=buf; reading=1; seeneof=0;
52   nonblock(0); nonblock(1);
53   while (!seeneof || used) {
54     FD_ZERO(&readfds);
55     if (reading) {
56       if (used<BUFFER-1) {
57         FD_SET(0,&readfds);
58       } else {
59 /*fprintf(stderr,"\t buffers full - stopping\n");*/
60         reading=0;
61       }
62     }
63     FD_ZERO(&writefds); if (used) FD_SET(1,&writefds);
64 /*fprintf(stderr,"used %6d reading %d seeneof %d wp %8lx rp %8lx read %d write %d\n",
65         used,reading,seeneof,(unsigned long)(wp-buf),(unsigned long)(rp-buf),
66         FD_ISSET(0,&readfds),FD_ISSET(1,&writefds));*/
67     r= select(2,&readfds,&writefds,0,0);
68 /*fprintf(stderr,"\t readable %d writeable %d\n",
69         FD_ISSET(0,&readfds),FD_ISSET(1,&writefds));*/
70     if (r == -1) {
71       if (errno == EINTR) continue;
72       perror("select"); exit(1);
73     }
74     if (FD_ISSET(0,&readfds)) {
75       r= read(0,rp,min(BUFFER-1-used,buf+BUFFER-rp));
76       if (!r) {
77 /*fprintf(stderr,"\t eof detected\n");*/
78         seeneof=1; reading=0;
79       } else if (r<0) {
80         if (!(errno == EAGAIN || errno == EINTR)) { perror("read"); exit(1); }
81 /*fprintf(stderr,"\t read transient error\n");*/
82       } else {
83 /*fprintf(stderr,"\t read %d\n",r);*/
84         used+= r;
85         rp+= r;
86         if (rp == buf+BUFFER) rp=buf;
87       }
88     }
89     if (FD_ISSET(1,&writefds)) {
90       assert(used);
91       r= write(1,wp,min(used,buf+BUFFER-wp));
92       if (r<=0) {
93         if (!(errno == EAGAIN || errno == EINTR)) { perror("write"); exit(1); }
94 /*fprintf(stderr,"\t write transient error\n");*/
95       } else {
96 /*fprintf(stderr,"\t wrote %d\n",r);*/
97         used-= r;
98         wp+= r;
99         if (wp == buf+BUFFER) wp=buf;
100       }
101       if (used < WAITEMPTY && !seeneof) {
102 /*fprintf(stderr,"\t starting writes\n");*/
103         reading=1;
104       }
105     }
106   }
107   exit(0);
108 }