aboutsummaryrefslogtreecommitdiffstats
path: root/restore.c
diff options
context:
space:
mode:
Diffstat (limited to 'restore.c')
-rw-r--r--restore.c240
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;
+}