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 /taper.c | |
download | ticra-main.tar.gz ticra-main.zip |
I used to really hate AMANDA.
Diffstat (limited to 'taper.c')
-rw-r--r-- | taper.c | 297 |
1 files changed, 297 insertions, 0 deletions
@@ -0,0 +1,297 @@ +#include "config.h" +#include "conf.h" +#include "err.h" +#include "lock.h" +#include "tapeio.h" + +#include <errno.h> +#include <fcntl.h> +#include <setjmp.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mtio.h> +#include <sys/types.h> +#include <sys/uio.h> +#include <sys/wait.h> +#include <time.h> +#include <unistd.h> + +#ifdef NEED_LIBUTIL +#include <libutil.h> +#endif + +#ifdef NEED_STRINGS +#include <strings.h> +#endif + +RCSID("$Id: taper.c,v 1.1.1.1 1999/02/02 23:29:39 shmit Exp $"); + +struct tapelist { + char filen[MAXPATHLEN]; + struct tapelist *next; +}; + +int canjmp = 0; +int taperunning = 0; +sigjmp_buf child_buf; + +void +sig_child(int signo) +{ + int status; + + (void)wait(&status); + + taperunning = 0; + if (canjmp) + siglongjmp(child_buf, 1); +} + +void +tapefile(int tapefd, const char *filen) +{ + char buffer[BUFFSIZE]; + char *vol; + fileheader_t header; + ssize_t total = 0, readb; + time_t start; + int fd; + + setproctitle("Dumping %s to tape", filen); + + fd = open(filen, O_RDONLY); + if (fd == -1) { + err("%s: couldn't open: %s.\n", filen, strerror(errno)); + return; + } + + /* Write the header. */ + header.type = FILEMARK; + header.date = time(NULL); + + /* Extract host and volume names from filename. */ + vol = (char *)rindex(filen, '/'); + if (vol) + strncpy(buffer, vol+1, sizeof(buffer)); + else + strncpy(buffer, filen, sizeof(buffer)); + + vol = index(buffer, ':'); + if (vol) { + *vol = '\0'; + strncpy(header.vol, vol+1, sizeof(header.vol)); + } else + header.vol[0] = '\0'; + strncpy(header.host, buffer, sizeof(header.host)); + + if (writeheader(tapefd, &header) == -1) { + err("%s: couldn't write file header: %s.\n", + filen, strerror(errno)); + return; + } + + /* Write the data. */ + start = time(NULL); + while ((readb = read(fd, buffer, sizeof(buffer))) > 0) { + ssize_t wrote = 0, n; + + total += readb; + while (wrote < readb) { + n = write(tapefd, buffer, readb); + if (n == -1) { + err("%s: couldn't write to tape: %s.\n", + filen, strerror(errno)); + close(fd); + return; + } + wrote += n; + } + } + if (readb == -1) + err("%s: couldn't read from dump: %s.\n", filen, + strerror(errno)); + + if (mt_weof(tapefd, 1) == -1) + err("%s: couldn't write EOF marker: %s.\n", + filen, strerror(errno)); + + printf("DEBUG: wrote %d bytes in %ld seconds.\n", + total, time(NULL)-start); + + close(fd); +} + +int +main(int argc, char *argv[]) +{ + struct tapelist *list = NULL; + const config_t *option; + char *labelstr, *tapedev; + struct sigaction sa; + fileheader_t header; + tapelabel_t label; + sigset_t set, oset; + int tapefd; + + if (read_config(SERVER_CONFIG_FILE) == -1) + return 1; + + option = findopt(LABELSTR); + if (!option) { + err("Taper: " LABELSTR " hasn't been set.\n"); + return 1; + } + labelstr = option->strvalue; + + option = findopt(TAPEDEV); + if (!option) { + err("Taper: " TAPEDEV " hasn't been set.\n"); + return 1; + } + tapedev = option->strvalue; + + tapefd = open(tapedev, O_RDWR); + if (tapefd == -1) { + err("Taper: Couldn't open tape device %s: %s.\n", + tapedev, strerror(errno)); + return 1; + } + + if (mt_rewind(tapefd) == -1) { + err("Taper: couldn't rewind tape: %s.\n", strerror(errno)); + return 1; + } + + if (readlabel(tapefd, &label) == -1) { + close(tapefd); + return 1; + } + if (memcmp(label.labelstr, labelstr, sizeof(labelstr))) { + err("Taper: label `%s' doesn't match expected label `%s'.\n", + label.labelstr, labelstr); + return 1; + } + + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sa.sa_handler = sig_child; + sigaction(SIGCHLD, &sa, NULL); + + /* Loop waiting for input from the dumper. */ + for (;;) { + char buffer[MAXLINE]; + + if (!canjmp && sigsetjmp(child_buf, 1)) { + if (list) { + struct tapelist *p = list; + pid_t pid; + + taperunning = 1; + pid = fork(); + if (pid == -1) { + err("Taper: couldn't fork: %s.\n", + strerror(errno)); + return 1; + } else if (!pid) { + tapefile(tapefd, p->filen); + exit(0); + } + list = list->next; + free(p); + } + } + canjmp = 1; + + if (!fgets(buffer, sizeof(buffer), stdin)) { + err("Taper: dumper died abnormally.\n"); + break; + } + + sigemptyset(&set); + sigaddset(&set, SIGCHLD); + sigprocmask(SIG_BLOCK, &set, &oset); + + if (!memcmp(buffer, DISK_REQ, sizeof(DISK_REQ)-1)) { + char *index = buffer+sizeof(DISK_REQ)-1; + + /* + * Special case the event when the taper isn't + * running and the list is NULL so we can start + * the process and continue it when we've dumped + * everything so far to tape. + */ + index[strlen(index)-1] = '\0'; + if (!list && !taperunning) { + pid_t pid; + + taperunning = 1; + pid = fork(); + if (pid == -1) { + err("Taper: couldn't fork: %s.\n", + strerror(errno)); + break; + } else if (!pid) { + tapefile(tapefd, index); + exit(0); + } + } else { + struct tapelist *p, *q = list; + + p = malloc(sizeof(struct tapelist)); + if (!p) { + err("Taper: couldn't malloc: %s.\n", + strerror(errno)); + break; + } + strncpy(p->filen, index, sizeof(p->filen)); + p->next = NULL; + + if (q) { + while (q->next) + q = q->next; + q->next = p; + } else + list = p; + } + } + if (!memcmp(buffer, DUMP_DONE, sizeof(DUMP_DONE)-1)) + break; + + sigprocmask(SIG_SETMASK, &oset, NULL); + } + + if (list || taperunning) { + /* + * Make sig_child exit without a siglongjmp, then unblock + * the signal. + */ + canjmp = 0; + sigprocmask(SIG_SETMASK, &oset, NULL); + + /* Wait for the first child to exit. */ + sigemptyset(&set); + sigsuspend(&set); + + /* Then run through the pending files. */ + while (list) { + struct tapelist *p = list; + + tapefile(tapefd, list->filen); + list = list->next; + free(p); + } + } + + header.type = STOPMARK; + if (writeheader(tapefd, &header) == -1) { + err("Taper: couldn't write end-of-tape marker: %s.\n", + strerror(errno)); + close(tapefd); + return 1; + } + + close(tapefd); + return 0; +} |