* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
static char sccsid
[] = "@(#)dumptape.c 5.1 (Berkeley) %G%";
char tblock
[NTREC
][BSIZE
];
tblock
[trecno
][i
] = *dp
++;
if(d
== 0 || tdaddr
[i
] < d
) {
bread(d
, tblock
[si
], BSIZE
);
if (write(to
, tblock
[0], sizeof(tblock
)) != sizeof(tblock
) ){
msg("Tape write error on %s\n", tape
);
msg("Tape write error on tape %d\n", tapeno
);
broadcast("TAPE ERROR!\n");
if (query("Do you want to restart?")){
msg("This tape will rewind. After it is rewound,\n");
msg("replace the faulty tape with a new one;\n");
msg("this dump volume will be rewritten.\n");
* Temporarily change the tapeno identification
asize
+= sizeof(tblock
)/density
;
if (!pipeout
&& asize
> tsize
) {
msg("Waiting 10 seconds to rewind.\n");
* It takes about 3 minutes, 25secs to rewind 2300' of tape
secs
= (( (60*3) + 25)*asize
)/(2300L*12L*10L);
msg("Waiting %d seconds to rewind.\n", secs
);
msg("Change Tapes: Mount tape #%d\n", tapeno
+1);
broadcast("CHANGE TAPES!\7\7\n");
if (query ("Is the new tape mounted and ready to go?"))
if (query ("Do you want to abort?")){
* We implement taking and restoring checkpoints on
* When each tape is opened, a new process is created by forking; this
* saves all of the necessary context in the parent. The child
* continues the dump; the parent waits around, saving the context.
* If the child returns X_REWRITE, then it had problems writing that tape;
* this causes the parent to fork again, duplicating the context, and
* everything continues as if nothing had happened.
* Force the tape to be closed
signal(SIGINT
, interrupt
);
* All signals are inherited...
msg("Context save fork fails in parent %d\n", parentpid
);
* save the context by waiting
* until the child doing all of the work returns.
* don't catch the interrupt
msg("Tape: %d; parent process: %d child process %d\n",
tapeno
+1, parentpid
, childpid
);
if (waitpid
!= childpid
){
msg("Parent %d waiting for child %d has another child %d return\n",
parentpid
, childpid
, waitpid
);
msg("Child %d returns LOB status %o\n",
status
= (status
>> 8) & 0xFF;
msg("Child %d finishes X_FINOK\n", childpid
);
msg("Child %d finishes X_ABORT\n", childpid
);
msg("Child %d finishes X_REWRITE\n", childpid
);
msg("Child %d finishes unknown %d\n", childpid
,status
);
goto restore_check_point
;
msg("Bad return code from dump: %d\n", status
);
} else { /* we are the child; just continue */
sleep(4); /* allow time for parent's message to get out */
msg("Child on Tape %d has parent %d, my pid = %d\n",
tapeno
+1, parentpid
, getpid());
if (!query("Cannot open tape. Do you want to retry the open?"))
tapeno
++; /* current tape sequence */
newtape
++; /* new tape signal */
msg("Tape %d begins with blocks from ino %d\n",
* The parent still catches interrupts, but does nothing with them
msg("Waiting parent receives interrupt\n");
signal(SIGINT
, sig_ign_parent
);
msg("The ENTIRE dump is aborted.\n");
msg("pid = %d exits with status %d\n", getpid(), status
);