home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume19 / backup / getback.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-06-29  |  5.7 KB  |  223 lines

  1. /*
  2.  * Getback - retrieve files stored away by the incremental backup mechanism.
  3.  *
  4.  * Based on an original program by Larry Philps.  This reimplementation is
  5.  * Copyright 1988 by Rayan Zachariassen, solely to prevent you from selling
  6.  * it or putting your name on it.  Free (gratis) redistribution is encouraged.
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <ctype.h>
  11. #include <signal.h>
  12. #include <sys/param.h>
  13. #include <sys/types.h>
  14. #include <sys/file.h>
  15. #include <sys/stat.h>
  16. #include <sys/dir.h>
  17.  
  18. #define    BACKUP        "/backup"    /* root of backup hierarchy */
  19.  
  20. struct copy {
  21.     char        *file;
  22.     struct stat    stbuf;
  23.     struct copy    *next;
  24. };
  25.  
  26. #define    EMSG(x)    (errno < sys_nerr ? sys_errlist[x] : \
  27.            (sprintf(errmsgbuf, "unknown error %d", errno), errmsgbuf))
  28.  
  29. extern int    errno, sys_nerr;
  30. extern char    *sys_errlist[];
  31. char        errmsgbuf[30];
  32.  
  33. char        *progname;
  34.  
  35. extern int    optind;
  36. extern char    *optarg;
  37.  
  38. main(argc, argv)
  39.     int    argc;
  40.     char    *argv[];
  41. {
  42.     int        c, errflag, i, copyindex, copyit, ifd, ofd, myuid;
  43.     char        *backup, *buf, line[BUFSIZ];
  44.     DIR        *dirp;
  45.     struct direct    *dp;
  46.     struct copy    *cep, *copyarr[1000];
  47.     struct stat    stbuf;
  48.     char        path[MAXPATHLEN], filename[MAXPATHLEN];
  49.     extern int    cmpcopy();
  50.     extern int    errno;
  51.     extern char    *emalloc(), *sbrk();
  52.  
  53.     progname = argv[0];
  54.     backup = BACKUP;
  55.     errflag = 0;
  56.     while ((c = getopt(argc, argv, "o:")) != EOF) {
  57.         switch (c) {
  58.         case 'o':
  59.             backup = optarg;
  60.             break;
  61.         default:
  62.             ++errflag;
  63.         }
  64.     }
  65.     if (optind != argc - 1) {
  66.         fprintf(stderr, "%s: missing filename\n", progname);
  67.         ++errflag;
  68.     }
  69.     if (errflag) {
  70.         fprintf(stderr, "Usage: %s [ -o /backup ] filename\n",
  71.                 progname);
  72.         exit(1);
  73.     }
  74.     if (argv[optind][0] == '/')
  75.         (void) strcpy(filename, argv[optind]);
  76.     else if (getwd(filename) == NULL) {
  77.         fprintf(stderr, "%s: %s\n", progname, filename);
  78.         exit(1);
  79.     } else
  80.         (void) sprintf(filename+strlen(filename), "/%s", argv[optind]);
  81.     (void) sprintf(path, "%s/%s", backup, filename);
  82.     if ((dirp = opendir(path)) == NULL) {
  83.         printf("There are no online backups of %s\n", argv[optind]);
  84.         exit(1);
  85.     }
  86.     copyindex = 0;
  87.     myuid = getuid();
  88.     for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
  89.         if (dp->d_namlen == sizeof "Jan01-00:00" - 1
  90.             && dp->d_name[5] == '-' && dp->d_name[8] == ':') {
  91.             (void) sprintf(path, "%s/%s/%s", backup, filename, dp->d_name);
  92.             if (stat(path, &stbuf) < 0)
  93.                 continue;
  94.             if (myuid != 0 && myuid != stbuf.st_uid)
  95.                 continue;
  96.             cep = (struct copy *)emalloc((u_int)sizeof (struct copy));
  97.             cep->file = emalloc(strlen(path)+1);
  98.             (void) strcpy(cep->file, path);
  99.             cep->stbuf = stbuf;
  100.             copyarr[copyindex++] = cep;
  101.         }
  102.     }
  103.     (void) closedir(dirp);
  104.     if (copyindex == 0) {
  105.         printf("There are no online backups of \"%s\"\n", argv[optind]);
  106.         exit(1);
  107.     } else if (copyindex == 1) {
  108.         printf("There is only one backup of \"%s\", dated %s",
  109.                   argv[optind], ctime(©arr[0]->stbuf.st_mtime));
  110.         printf("Retrieve this copy [y] ? ");
  111.         fflush(stdout);
  112.         (void) gets(line);
  113.         if (line[0] == '\0' || line[0] == 'y' || line[0] == 'Y') {
  114.             copyit = 0;
  115.         } else {
  116.             fprintf(stderr, "%s: nothing changed\n", progname);
  117.             exit(1);
  118.         }
  119.     } else {
  120.         printf("There are %d backup versions of \"%s\" from:\n\n",
  121.                   copyindex, argv[optind]);
  122.         qsort((char *)copyarr, copyindex, sizeof copyarr[0], cmpcopy);
  123.         for (i = 0; i < copyindex; ++i) {
  124.             printf("\t%2d.\t%.24s\t(%ld bytes)\n",
  125.                    i+1, ctime(©arr[i]->stbuf.st_mtime),
  126.                    copyarr[i]->stbuf.st_size);
  127.         }
  128.         (void) putchar('\n');
  129.     retry:
  130.         printf("Enter number corresponding to version you want [%d]: ",
  131.                 copyindex);
  132.         fflush(stdout);
  133.         if (gets(line) == NULL)
  134.             line[0] = 'n';
  135.         if (line[0] == '\0')
  136.             copyit = copyindex - 1;
  137.         else if (line[0] == 'n' || line[0] == 'N') {
  138.             fprintf(stderr, "%s: nothing changed\n", progname);
  139.             exit(1);
  140.         } else if (!isdigit(line[0])
  141.                  || (i = atoi(line)) <= 0 || i > copyindex) {
  142.             printf("Answer must be a number from 1-%d, or <cr>.\n",
  143.                        copyindex);
  144.             goto retry;
  145.         } else
  146.             copyit = i-1;
  147.     }
  148.     if (stat(argv[optind], &stbuf) == 0) {
  149.         if (stbuf.st_uid != myuid) {
  150.             fprintf(stderr, "%s: you are not owner of %s\n",
  151.                     progname, argv[optind]);
  152.             exit(1);
  153.         }
  154.         printf("\"%s\" exists, overwrite [y] ? ", argv[optind]);
  155.         (void) gets(line);
  156.         if (!(line[0] == '\0' || line[0] == 'y' || line[0] == 'Y')) {
  157.             fprintf(stderr, "%s: nothing changed\n", progname);
  158.             exit(1);
  159.         }
  160.     }
  161.     printf("Retrieving %.24s version of \"%s\" ... ",
  162.                ctime(©arr[copyit]->stbuf.st_mtime),
  163.                argv[optind]);
  164.     if ((buf = sbrk(copyarr[copyit]->stbuf.st_blksize)) == NULL) {
  165.         fprintf(stderr, "%s: sbrk(%d): %s\n",
  166.                 progname, copyarr[copyit]->stbuf.st_blksize,
  167.                 EMSG(errno));
  168.         exit(1);
  169.     }
  170.     if ((ifd = open(copyarr[copyit]->file, O_RDONLY, 0)) < 0) {
  171.         fprintf(stderr, "%s: open(%s): %s\n",
  172.                 progname, copyarr[copyit]->file, EMSG(errno));
  173.         exit(1);
  174.     }
  175.  
  176.     (void) sigsetmask(sigmask(SIGHUP)
  177.             | sigmask(SIGINT)
  178.             | sigmask(SIGQUIT)
  179.             | sigmask(SIGTERM)
  180.             | sigmask(SIGTSTP));
  181.  
  182.     if ((ofd = open(argv[optind], O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) {
  183.         fprintf(stderr, "%s: open(%s): %s\n",
  184.                 progname, argv[optind], EMSG(errno));
  185.         exit(1);
  186.     }
  187.     (void) umask(0);
  188.     (void) fchmod(ofd, copyarr[copyit]->stbuf.st_mode);
  189.     (void) fchown(ofd, copyarr[copyit]->stbuf.st_uid,
  190.                copyarr[copyit]->stbuf.st_gid);
  191.     while ((i = read(ifd, buf, copyarr[copyit]->stbuf.st_blksize)) > 0)
  192.         if (write(ofd, buf, i) < i) {
  193.             fprintf(stderr, "%s: write of %d bytes: %s\n",
  194.                     progname, i, EMSG(errno));
  195.             exit(1);
  196.         }
  197.     (void) close(ofd);
  198.     (void) close(ifd);
  199.     printf("done!\n");
  200.     exit(0);
  201. }
  202.  
  203. int
  204. cmpcopy(a, b)
  205.     struct copy **a, **b;
  206. {
  207.     return (*a)->stbuf.st_mtime - (*b)->stbuf.st_mtime;
  208. }
  209.  
  210. char *
  211. emalloc(n)
  212.     u_int    n;
  213. {
  214.     char *cp;
  215.     extern char *malloc();
  216.  
  217.     if ((cp = malloc(n)) == NULL) {
  218.         fprintf(stderr, "%s: malloc(%u) failed!\n", progname, n);
  219.         exit(1);
  220.     }
  221.     return cp;
  222. }
  223.