#include "config.h" #include "conf.h" #include "lock.h" #include "tapeio.h" #include "strutil.h" #include #include #include #include #include #include #include #include #include RCSID("$Id: restore.c,v 1.1.1.1 1999/02/02 23:29:39 shmit Exp $"); char *progname; void err(const char *fmt, ...) { va_list ap; va_start(ap, fmt); fprintf(stderr, "Error: "); vfprintf(stderr, fmt, ap); va_end(ap); } void warn(const char *fmt, ...) { va_list ap; va_start(ap, fmt); fprintf(stderr, "Warning: "); vfprintf(stderr, fmt, ap); va_end(ap); } void sig_pipe(int signo) { return; } int skip(int tapefd, int count) { if (mt_fsf(tapefd, count) == -1) { err("couldn't fast-forward to next file header: %s.\n", strerror(errno)); return -1; } return 0; } int restore(int tapefd, fileheader_t *header, int pipeflag) { char buffer[BUFFSIZE]; struct tm *tm; ssize_t readb, total_read = 0; int outfd; tm = localtime(&header->date); fprintf(stderr, "Restoring %s:%s dumped on %02d-%02d-%04d.\n", header->host, header->vol, tm->tm_mday, tm->tm_mon+1, tm->tm_year+1900); if (pipeflag) outfd = STDOUT_FILENO; else outfd = STDOUT_FILENO; do { ssize_t wroteb = 0; readb = read(tapefd, buffer, sizeof(buffer)); if (readb == -1) { err("couldn't read dump from tape: %s.\n", strerror(errno)); return -1; } total_read += readb; while (wroteb < readb) { ssize_t n; n = write(outfd, buffer+wroteb, readb - wroteb); if (n == -1) { if (errno == EAGAIN) continue; else if (errno == EPIPE) { warn("pipe reader has quit, skipping" " to next file.\n"); return skip(tapefd, 1); } err("couldn't write dump to disk: %s.\n", strerror(errno)); return -1; } wroteb += readb; } } while (readb); return skip(tapefd, 0); } void usage() { fprintf(stderr, "Usage: %s [-h] [-p] hostname [volume]\n", progname); exit(1); } int main(int argc, char *argv[]) { struct tm *tm; const config_t *option; char *labelstr, *tapedev, *hostname = NULL, *volume = NULL; tapelabel_t label; int pipeflag = 0; int tapefd; progname = argv[0]; if (argc < 2 || argc > 4) usage(); while (--argc) { if (*argv[argc] == '-') { switch (*(argv[argc]+1)) { case 'h': usage(); break; case 'p': pipeflag = 1; break; default: usage(); } } else { if (!volume) volume = argv[argc]; else if (!hostname) hostname = argv[argc]; else usage(); } } /* Re-order arguments if only one was given. */ if (!hostname) { if (volume) { hostname = volume; volume = NULL; } else usage(); } if (read_config(SERVER_CONFIG_FILE) == -1) return 1; option = findopt(LABELSTR); if (!option) { err(LABELSTR " hasn't been set.\n"); return 1; } labelstr = option->strvalue; option = findopt(TAPEDEV); if (!option) { err(TAPEDEV " hasn't been set.\n"); return 1; } tapedev = option->strvalue; tapefd = open(tapedev, O_RDONLY); if (tapefd == -1) { err("couldn't open tape device %s: %s.\n", tapedev, strerror(errno)); return -1; } if (mt_rewind(tapefd) == -1) { err("couldn't rewind tape: %s.\n", strerror(errno)); return 1; } if (readlabel(tapefd, &label) == -1) return 2; if (memcmp(label.labelstr, labelstr, sizeof(labelstr))) { err("label `%s' doesn't match expected `%s'.\n", label.labelstr, labelstr); return 2; } tm = localtime(&label.date); fprintf(stderr, "Tape `%s' created on %02d-%02d-%04d.\n", label.labelstr, tm->tm_mday, tm->tm_mon+1, tm->tm_year+1900); for (;;) { fileheader_t header; if (readheader(tapefd, &header) == -1) { err("couldn't read header from tape: %s.\n", strerror(errno)); break; } if (header.type == STOPMARK) break; if (!strcmp(header.host, hostname)) { if (volume && strcmp(header.vol, volume)) { fprintf(stderr, "Skipping %s:%s.\n", header.host, header.vol); if (skip(tapefd, 1) == -1) break; continue; } if (restore(tapefd, &header, pipeflag) == -1) break; } else { fprintf(stderr, "Skipping %s:%s.\n", header.host, header.vol); if (skip(tapefd, 1) == -1) break; } } close(tapefd); return 0; }