chiark / gitweb /
417cb01ac0cef44f7cc03c80f04f0120152fc857
[chiark-utils.git] / cprogs / wrbufcore.c
1 /*
2  * wrbufcore.c
3  *
4  * Core of algorithm for writing output to devices which don't like
5  * constant stopping and starting, such as tape drives.  This is:
6  *  Copyright (C) 1997-1998,2000-2001 Ian Jackson <ian@chiark.greenend.org.uk>
7  *
8  * writebuffer is part of chiark backup, a system for backing up GNU/Linux
9  * and other UN*X-compatible machines, as used on chiark.greenend.org.uk.
10  * chiark backup is:
11  *  Copyright (C) 1997-1998,2000-2001 Ian Jackson <ian@chiark.greenend.org.uk>
12  *  Copyright (C) 1999 Peter Maydell <pmaydell@chiark.greenend.org.uk>
13  *
14  * This is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as
16  * published by the Free Software Foundation; either version 2,
17  * or (at your option) any later version.
18  *
19  * This is distributed in the hope that it will be useful, but
20  * WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public
25  * License along with this file; if not, write to the Free Software
26  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27  *
28  */
29
30 #include "rwbuffer.h"
31
32 static size_t waitfill;
33 static int writing;
34
35 void wrbufcore_startup(void) {
36   waitfill= (buffersize*3)/4;
37   writing=0;
38 }
39
40 void wrbufcore_prepselect(int rdfd, int wrfd) {
41   FD_ZERO(&readfds);
42   if (rdfd>=0 && !seeneof && used+1<buffersize) FD_SET(rdfd,&readfds);
43
44   FD_ZERO(&writefds);
45   if (writing) FD_SET(wrfd,&writefds);
46 }
47
48 void wrbufcore_afterselect(int rdfd, int wrfd) {
49   int r;
50     
51   if (FD_ISSET(wrfd,&writefds) &&
52       !(rdfd>=0 && FD_ISSET(rdfd,&readfds)) &&
53       !used) {
54     writing= 0;
55     FD_CLR(wrfd,&writefds);
56   }
57
58   if (rdfd>=0 && FD_ISSET(rdfd,&readfds)) {
59     r= read(rdfd,rp,min(buffersize-1-used,buf+buffersize-rp));
60     if (!r) {
61       seeneof=1; writing=1;
62     } else if (r<0) {
63       if (!(errno == EAGAIN || errno == EINTR)) { perror("read"); exit(1); }
64     } else {
65       used+= r;
66       rp+= r;
67       if (rp == buf+buffersize) rp=buf;
68     }
69     if (used > waitfill) writing=1;
70   }
71
72   if (FD_ISSET(wrfd,&writefds) && used) {
73     r= write(wrfd,wp,min(used,buf+buffersize-wp));
74     if (r<=0) {
75       if (!(errno == EAGAIN || errno == EINTR)) { perror("write"); exit(1); }
76     } else {
77       used-= r;
78       wp+= r;
79       if (wp == buf+buffersize) wp=buf;
80     }
81   }
82 }