chiark / gitweb /
consolidate changelog
[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
34 int writing;
35
36 void wrbufcore_startup(void) {
37   waitfill= (buffersize*3)/4;
38   writing=0;
39   maxselfd=0;
40 }
41
42 void fdsetset(int fd, fd_set *set) {
43   FD_SET(fd,set);
44   if (fd >= maxselfd) maxselfd= fd+1;
45 }
46
47 void wrbufcore_prepselect(int rdfd, int wrfd) {
48   FD_ZERO(&readfds);
49   if (rdfd>=0 && !seeneof && used+1<buffersize) fdsetset(rdfd,&readfds);
50   
51   FD_ZERO(&writefds);
52   if (writing) fdsetset(wrfd,&writefds);
53 }
54
55 void wrbufcore_afterselect(int rdfd, int wrfd) {
56   int r;
57     
58   if (FD_ISSET(wrfd,&writefds) &&
59       !(rdfd>=0 && FD_ISSET(rdfd,&readfds)) &&
60       !used) {
61     wrbuf_report("stopping");
62     writing= 0;
63     FD_CLR(wrfd,&writefds);
64   }
65
66   if (rdfd>=0 && FD_ISSET(rdfd,&readfds)) {
67     r= read(rdfd,rp,min(buffersize-1-used,buf+buffersize-rp));
68     if (!r) {
69       seeneof=1; writing=1;
70       wrbuf_report("seeneof");
71     } else if (r<0) {
72       if (!(errno == EAGAIN || errno == EINTR)) { perror("read"); exit(1); }
73     } else {
74       used+= r;
75       rp+= r;
76       if (rp == buf+buffersize) rp=buf;
77     }
78     if (used > waitfill) {
79       if (!writing) wrbuf_report("starting");
80       writing=1;
81     }
82   }
83
84   if (FD_ISSET(wrfd,&writefds) && used) {
85     r= write(wrfd,wp,min(used,buf+buffersize-wp));
86     if (r<=0) {
87       if (!(errno == EAGAIN || errno == EINTR)) { perror("write"); exit(1); }
88     } else {
89       used-= r;
90       wp+= r;
91       if (wp == buf+buffersize) wp=buf;
92     }
93   }
94 }