e flag, not c flag
[unix-history] / usr / src / old / dump.4.1 / dumptape.c
CommitLineData
76797561
DF
1/*
2 * Copyright (c) 1980 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7#ifndef lint
8static char sccsid[] = "@(#)dumptape.c 5.1 (Berkeley) %G%";
9#endif not lint
10
ae4b153c
BJ
11#include "dump.h"
12
13char tblock[NTREC][BSIZE];
14daddr_t tdaddr[NTREC];
15int trecno;
16
17taprec(dp)
18char *dp;
19{
20 register i;
21
22 for(i=0; i<BSIZE; i++)
23 tblock[trecno][i] = *dp++;
24 tdaddr[trecno] = 0;
25 trecno++;
26 spcl.c_tapea++;
27 if(trecno >= NTREC)
28 flusht();
29}
30
31tapsrec(d)
32daddr_t d;
33{
34
35 if(d == 0)
36 return;
37 tdaddr[trecno] = d;
38 trecno++;
39 spcl.c_tapea++;
40 if(trecno >= NTREC)
41 flusht();
42}
43
44int nogripe = 0;
45
46flusht()
47{
48 register i, si;
49 daddr_t d;
50
51 while(trecno < NTREC)
52 tdaddr[trecno++] = 1;
53
54loop:
55 d = 0;
56 for(i=0; i<NTREC; i++)
57 if(tdaddr[i] != 0)
58 if(d == 0 || tdaddr[i] < d) {
59 si = i;
60 d = tdaddr[i];
61 }
62 if(d != 0) {
63 bread(d, tblock[si], BSIZE);
64 tdaddr[si] = 0;
65 goto loop;
66 }
67 trecno = 0;
68 if (write(to, tblock[0], sizeof(tblock)) != sizeof(tblock) ){
2a729b17
KM
69 if (pipeout) {
70 msg("Tape write error on %s\n", tape);
71 msg("Cannot recover\n");
72 dumpabort();
73 /*NOTREACHED*/
74 }
ae4b153c
BJ
75 msg("Tape write error on tape %d\n", tapeno);
76 broadcast("TAPE ERROR!\n");
77 if (query("Do you want to restart?")){
78 msg("This tape will rewind. After it is rewound,\n");
79 msg("replace the faulty tape with a new one;\n");
ed7c701e 80 msg("this dump volume will be rewritten.\n");
ae4b153c
BJ
81 /*
82 * Temporarily change the tapeno identification
83 */
84 tapeno--;
85 nogripe = 1;
86 close_rewind();
87 nogripe = 0;
88 tapeno++;
89 Exit(X_REWRITE);
90 } else {
91 dumpabort();
92 /*NOTREACHED*/
93 }
94 }
95
96 asize += sizeof(tblock)/density;
97 asize += 7;
98 blockswritten += NTREC;
2a729b17 99 if (!pipeout && asize > tsize) {
ae4b153c
BJ
100 close_rewind();
101 otape();
102 }
103 timeest();
104}
105
106rewind()
107{
108 int secs;
109#ifdef DEBUG
110 msg("Waiting 10 seconds to rewind.\n");
111 sleep(10);
112#else
113 /*
114 * It takes about 3 minutes, 25secs to rewind 2300' of tape
115 */
116 secs = (( (60*3) + 25)*asize)/(2300L*12L*10L);
117 msg("Waiting %d seconds to rewind.\n", secs);
118 sleep(secs);
119#endif
120}
121
122close_rewind()
123{
2a729b17
KM
124 if (pipeout)
125 return;
ae4b153c
BJ
126 close(to);
127 if (!nogripe){
128 rewind();
129 msg("Change Tapes: Mount tape #%d\n", tapeno+1);
130 broadcast("CHANGE TAPES!\7\7\n");
131 }
132 do{
133 if (query ("Is the new tape mounted and ready to go?"))
134 break;
135 if (query ("Do you want to abort?")){
136 dumpabort();
137 /*NOTREACHED*/
138 }
139 } while (1);
140}
141
142/*
143 * We implement taking and restoring checkpoints on
144 * the tape level.
145 * When each tape is opened, a new process is created by forking; this
146 * saves all of the necessary context in the parent. The child
147 * continues the dump; the parent waits around, saving the context.
148 * If the child returns X_REWRITE, then it had problems writing that tape;
149 * this causes the parent to fork again, duplicating the context, and
150 * everything continues as if nothing had happened.
151 */
152
153otape()
154{
155 int parentpid;
156 int childpid;
157 int status;
158 int waitpid;
159 int sig_ign_parent();
160 int interrupt();
161
162 /*
163 * Force the tape to be closed
164 */
2a729b17
KM
165 if (!pipeout)
166 close(to);
ae4b153c
BJ
167 parentpid = getpid();
168
169 restore_check_point:
170 signal(SIGINT, interrupt);
171 /*
172 * All signals are inherited...
173 */
174 childpid = fork();
175 if (childpid < 0){
176 msg("Context save fork fails in parent %d\n", parentpid);
177 Exit(X_ABORT);
178 }
179 if (childpid != 0){
180 /*
181 * PARENT:
182 * save the context by waiting
183 * until the child doing all of the work returns.
184 * don't catch the interrupt
185 */
186 signal(SIGINT, SIG_IGN);
187#ifdef TDEBUG
188 msg("Tape: %d; parent process: %d child process %d\n",
189 tapeno+1, parentpid, childpid);
190#endif TDEBUG
191 for (;;){
192 waitpid = wait(&status);
193 if (waitpid != childpid){
194 msg("Parent %d waiting for child %d has another child %d return\n",
195 parentpid, childpid, waitpid);
196 } else
197 break;
198 }
199 if (status & 0xFF){
200 msg("Child %d returns LOB status %o\n",
201 childpid, status&0xFF);
202 }
203 status = (status >> 8) & 0xFF;
204#ifdef TDEBUG
205 switch(status){
206 case X_FINOK:
207 msg("Child %d finishes X_FINOK\n", childpid);
208 break;
209 case X_ABORT:
210 msg("Child %d finishes X_ABORT\n", childpid);
211 break;
212 case X_REWRITE:
213 msg("Child %d finishes X_REWRITE\n", childpid);
214 break;
215 default:
216 msg("Child %d finishes unknown %d\n", childpid,status);
217 break;
218 }
219#endif TDEBUG
220 switch(status){
221 case X_FINOK:
222 Exit(X_FINOK);
223 case X_ABORT:
224 Exit(X_ABORT);
225 case X_REWRITE:
226 goto restore_check_point;
227 default:
228 msg("Bad return code from dump: %d\n", status);
229 Exit(X_ABORT);
230 }
231 /*NOTREACHED*/
232 } else { /* we are the child; just continue */
233#ifdef TDEBUG
234 sleep(4); /* allow time for parent's message to get out */
235 msg("Child on Tape %d has parent %d, my pid = %d\n",
236 tapeno+1, parentpid, getpid());
237#endif
238 do{
2a729b17
KM
239 if (pipeout)
240 to = 1;
241 else
242 to = creat(tape, 0666);
ae4b153c
BJ
243 if (to < 0) {
244 if (!query("Cannot open tape. Do you want to retry the open?"))
245 dumpabort();
246 } else break;
247 } while (1);
248
249 asize = 0;
250 tapeno++; /* current tape sequence */
251 newtape++; /* new tape signal */
252 spcl.c_volume++;
253 spcl.c_type = TS_TAPE;
254 spclrec();
255 if (tapeno > 1)
256 msg("Tape %d begins with blocks from ino %d\n",
257 tapeno, ino);
258 }
259}
260
261/*
262 * The parent still catches interrupts, but does nothing with them
263 */
264sig_ign_parent()
265{
266 msg("Waiting parent receives interrupt\n");
267 signal(SIGINT, sig_ign_parent);
268}
269
270dumpabort()
271{
ed7c701e 272 msg("The ENTIRE dump is aborted.\n");
ae4b153c
BJ
273 Exit(X_ABORT);
274}
275
276Exit(status)
277{
278#ifdef TDEBUG
279 msg("pid = %d exits with status %d\n", getpid(), status);
280#endif TDEBUG
ed7c701e 281 exit(status);
ae4b153c 282}