home *** CD-ROM | disk | FTP | other *** search
- /*
- * Getback - retrieve files stored away by the incremental backup mechanism.
- *
- * Based on an original program by Larry Philps. This reimplementation is
- * Copyright 1988 by Rayan Zachariassen, solely to prevent you from selling
- * it or putting your name on it. Free (gratis) redistribution is encouraged.
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <signal.h>
- #include <sys/param.h>
- #include <sys/types.h>
- #include <sys/file.h>
- #include <sys/stat.h>
- #include <sys/dir.h>
-
- #define BACKUP "/backup" /* root of backup hierarchy */
-
- struct copy {
- char *file;
- struct stat stbuf;
- struct copy *next;
- };
-
- #define EMSG(x) (errno < sys_nerr ? sys_errlist[x] : \
- (sprintf(errmsgbuf, "unknown error %d", errno), errmsgbuf))
-
- extern int errno, sys_nerr;
- extern char *sys_errlist[];
- char errmsgbuf[30];
-
- char *progname;
-
- extern int optind;
- extern char *optarg;
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int c, errflag, i, copyindex, copyit, ifd, ofd, myuid;
- char *backup, *buf, line[BUFSIZ];
- DIR *dirp;
- struct direct *dp;
- struct copy *cep, *copyarr[1000];
- struct stat stbuf;
- char path[MAXPATHLEN], filename[MAXPATHLEN];
- extern int cmpcopy();
- extern int errno;
- extern char *emalloc(), *sbrk();
-
- progname = argv[0];
- backup = BACKUP;
- errflag = 0;
- while ((c = getopt(argc, argv, "o:")) != EOF) {
- switch (c) {
- case 'o':
- backup = optarg;
- break;
- default:
- ++errflag;
- }
- }
- if (optind != argc - 1) {
- fprintf(stderr, "%s: missing filename\n", progname);
- ++errflag;
- }
- if (errflag) {
- fprintf(stderr, "Usage: %s [ -o /backup ] filename\n",
- progname);
- exit(1);
- }
- if (argv[optind][0] == '/')
- (void) strcpy(filename, argv[optind]);
- else if (getwd(filename) == NULL) {
- fprintf(stderr, "%s: %s\n", progname, filename);
- exit(1);
- } else
- (void) sprintf(filename+strlen(filename), "/%s", argv[optind]);
- (void) sprintf(path, "%s/%s", backup, filename);
- if ((dirp = opendir(path)) == NULL) {
- printf("There are no online backups of %s\n", argv[optind]);
- exit(1);
- }
- copyindex = 0;
- myuid = getuid();
- for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
- if (dp->d_namlen == sizeof "Jan01-00:00" - 1
- && dp->d_name[5] == '-' && dp->d_name[8] == ':') {
- (void) sprintf(path, "%s/%s/%s", backup, filename, dp->d_name);
- if (stat(path, &stbuf) < 0)
- continue;
- if (myuid != 0 && myuid != stbuf.st_uid)
- continue;
- cep = (struct copy *)emalloc((u_int)sizeof (struct copy));
- cep->file = emalloc(strlen(path)+1);
- (void) strcpy(cep->file, path);
- cep->stbuf = stbuf;
- copyarr[copyindex++] = cep;
- }
- }
- (void) closedir(dirp);
- if (copyindex == 0) {
- printf("There are no online backups of \"%s\"\n", argv[optind]);
- exit(1);
- } else if (copyindex == 1) {
- printf("There is only one backup of \"%s\", dated %s",
- argv[optind], ctime(©arr[0]->stbuf.st_mtime));
- printf("Retrieve this copy [y] ? ");
- fflush(stdout);
- (void) gets(line);
- if (line[0] == '\0' || line[0] == 'y' || line[0] == 'Y') {
- copyit = 0;
- } else {
- fprintf(stderr, "%s: nothing changed\n", progname);
- exit(1);
- }
- } else {
- printf("There are %d backup versions of \"%s\" from:\n\n",
- copyindex, argv[optind]);
- qsort((char *)copyarr, copyindex, sizeof copyarr[0], cmpcopy);
- for (i = 0; i < copyindex; ++i) {
- printf("\t%2d.\t%.24s\t(%ld bytes)\n",
- i+1, ctime(©arr[i]->stbuf.st_mtime),
- copyarr[i]->stbuf.st_size);
- }
- (void) putchar('\n');
- retry:
- printf("Enter number corresponding to version you want [%d]: ",
- copyindex);
- fflush(stdout);
- if (gets(line) == NULL)
- line[0] = 'n';
- if (line[0] == '\0')
- copyit = copyindex - 1;
- else if (line[0] == 'n' || line[0] == 'N') {
- fprintf(stderr, "%s: nothing changed\n", progname);
- exit(1);
- } else if (!isdigit(line[0])
- || (i = atoi(line)) <= 0 || i > copyindex) {
- printf("Answer must be a number from 1-%d, or <cr>.\n",
- copyindex);
- goto retry;
- } else
- copyit = i-1;
- }
- if (stat(argv[optind], &stbuf) == 0) {
- if (stbuf.st_uid != myuid) {
- fprintf(stderr, "%s: you are not owner of %s\n",
- progname, argv[optind]);
- exit(1);
- }
- printf("\"%s\" exists, overwrite [y] ? ", argv[optind]);
- (void) gets(line);
- if (!(line[0] == '\0' || line[0] == 'y' || line[0] == 'Y')) {
- fprintf(stderr, "%s: nothing changed\n", progname);
- exit(1);
- }
- }
- printf("Retrieving %.24s version of \"%s\" ... ",
- ctime(©arr[copyit]->stbuf.st_mtime),
- argv[optind]);
- if ((buf = sbrk(copyarr[copyit]->stbuf.st_blksize)) == NULL) {
- fprintf(stderr, "%s: sbrk(%d): %s\n",
- progname, copyarr[copyit]->stbuf.st_blksize,
- EMSG(errno));
- exit(1);
- }
- if ((ifd = open(copyarr[copyit]->file, O_RDONLY, 0)) < 0) {
- fprintf(stderr, "%s: open(%s): %s\n",
- progname, copyarr[copyit]->file, EMSG(errno));
- exit(1);
- }
-
- (void) sigsetmask(sigmask(SIGHUP)
- | sigmask(SIGINT)
- | sigmask(SIGQUIT)
- | sigmask(SIGTERM)
- | sigmask(SIGTSTP));
-
- if ((ofd = open(argv[optind], O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) {
- fprintf(stderr, "%s: open(%s): %s\n",
- progname, argv[optind], EMSG(errno));
- exit(1);
- }
- (void) umask(0);
- (void) fchmod(ofd, copyarr[copyit]->stbuf.st_mode);
- (void) fchown(ofd, copyarr[copyit]->stbuf.st_uid,
- copyarr[copyit]->stbuf.st_gid);
- while ((i = read(ifd, buf, copyarr[copyit]->stbuf.st_blksize)) > 0)
- if (write(ofd, buf, i) < i) {
- fprintf(stderr, "%s: write of %d bytes: %s\n",
- progname, i, EMSG(errno));
- exit(1);
- }
- (void) close(ofd);
- (void) close(ifd);
- printf("done!\n");
- exit(0);
- }
-
- int
- cmpcopy(a, b)
- struct copy **a, **b;
- {
- return (*a)->stbuf.st_mtime - (*b)->stbuf.st_mtime;
- }
-
- char *
- emalloc(n)
- u_int n;
- {
- char *cp;
- extern char *malloc();
-
- if ((cp = malloc(n)) == NULL) {
- fprintf(stderr, "%s: malloc(%u) failed!\n", progname, n);
- exit(1);
- }
- return cp;
- }
-