diff options
author | Brian Cully <bjc@kublai.com> | 2022-03-09 21:10:26 -0500 |
---|---|---|
committer | Brian Cully <bjc@kublai.com> | 2022-03-09 21:37:48 -0500 |
commit | 720864f2a76d4ee3ed75cb99298b8e94c01f1b29 (patch) | |
tree | 7a163efe3d699725a9e9dd2c17aebaa6a6feadc7 /restore.c | |
download | ticra-main.tar.gz ticra-main.zip |
I used to really hate AMANDA.
Diffstat (limited to 'restore.c')
-rw-r--r-- | restore.c | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/restore.c b/restore.c new file mode 100644 index 0000000..3133c89 --- /dev/null +++ b/restore.c @@ -0,0 +1,240 @@ +#include "config.h" +#include "conf.h" +#include "lock.h" +#include "tapeio.h" +#include "strutil.h" + +#include <errno.h> +#include <fcntl.h> +#include <stdarg.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/uio.h> +#include <time.h> +#include <unistd.h> + +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; +} |