samperi@dasys1.UUCP (Dominick Samperi) (11/30/87)
The following shell archive contains a floppy backup program for System V UNIX systems. It is based on cpio and find. It has been tested with Xenix and Microport's System V/AT. Delete the header to the cut line, and shell the rest. ----- cut ------- cut -------- cut ----------- #!/bin/sh # to extract, remove the header and type "sh filename" if `test ! -s ./README` then echo "writing ./README" cat > ./README << '\Rogue\Monster\' dbackup/drestore - Multi-floppy Directory Backup/Restore Utility. (For UNIX System V and XENIX) Copyright 1987 Dominick Samperi LISCENSE AGREEMENT. This software may be freely copied and distributed for personal use only. DISCLAIMER OF WARRANTY. This software is distributed "as is" and without warranties as to performance of merchantability or any other warranties whether expressed or implied. In no event shall the author (the copyright holder) be held liable for any loss of profit or any other commercial damage resulting from the use or misuse of this software, including but not limited to special, incidental, consequential or other damages. No warranty of fitness for a particular purpose is offered. The user must assume the entire risk of using the program. INTRODUCTION. These utilities can be used to backup and restore directory hierarchies, typically by copying them to a set of floppy diskettes. They were designed to facilitate the process of backing up selected files and directories, so that a complete file system backup (requiring many floppies) is rarely needed (if you keep backup copies of the distribution floppies, then it may not be necessary to do a complete file system backup at all). Floppies are prompted for automatically, as they are needed. NOTE: This program is based on the versions of find and cpio that are shipped with AT&T/Microport System V UNIX, Release 2.0. It will also work with SCO Xenix. A version for PC's running MS-DOS is also available. FILES. README - This file. dbackup.c - dbackup source. dbackup.doc - Formatted man page. dbackup.conf - Sample local configuration file list. dbackup.bu - Used to backup dbackup and drestore. backup - Sample backup shell script. makefile - Makefile for compilation/installation. INSTALLATION. After setting the variable BIN in makefile equal to the full path name of your local binary directory, select the appropriate CFLAGS line, and type make. NOTE: In order for the program to be able to restore the default operation of special function key F1, the default string that is emitted when this key is pressed must be assigned to the preprocessor symbol F1_str. If you are running SCO XENIX or Microport's System V/AT, then this is done automatically, provided that you choose the correct CFLAGS definition in makefile. Another parameter that may need to be changed is BU_dev, which should equal the default device file to use for backups (it is /dev/rdsk/fd for Microport, and /dev/rfd096 for XENIX). USAGE. In order to enjoy the benefits of these utilities, you should partition all files that need to be backed up into a collection of directories of moderate size (say, 5-7 megs). For example, many systems have a /usr/src directory that may contain 10 Megs or more of source files. In this situation the source directory should be partitioned into subdirectories of moderate size that can be backed up separately (e.g., /usr/src/news, /usr/src/misc, etc.). You can use the command 'du -s dirname' to determine the size of dirname in blocks (twice the number of megs). All files under /usr/src/news can then be backed up (onto one or more high-density floppies) by using: dbackup /usr/src/news You will be prompted for floppies as they are needed; be sure to label them, and number them so they can be restored in the correct order. Several smaller directory hierarchies can be backed up onto one floppy set by supplying the full path names of the root directories on the command line. For example, user directories /usr/smith, /usr/james, and /usr/rogers can be backed up with: dbackup /usr/smith /usr/james /usr/rogers Dbackup writes a time stamp file named .dbackup_time into the first directory that appears on the command line (/usr/smith in the last example). This file can be used to display the names of all files in the directory hierarchies that have changed since the last dbackup. For example, all files under /usr/smith and /usr/james that have changed since the dbackup command above was executed can be displayed with: find /usr/smith /usr/james -newer /usr/smith/.dbackup_time -print You can use this information to decide whether or not a new dbackup is necessary (a shell script can be used to save some typing here). The time stamp file is also used by dbackup to do incremental backups (see the man page for more information). Essential local configuration files that would need to be restored after a hard disk crash or system reinstallation can be backed up as follows. First, put the names of files like /etc/passwd, /etc/group, /etc/profile, /usr/lib/uucp/L.sys, /usr/lib/uucp/USERFILE, etc. into a file named /etc/dbackup.conf. Place each file name on a separate line, and use full path names (beginning with /). Don't forget to include the name /etc/dbackup.conf! Look at the sample dbackup.conf that is included with this software. Now, assuming that your local binary directory is named /usr/lbin, you can backup your essential configuration files, as well as your local binary directory, as follows: dbackup /etc/dbackup.conf /usr/lbin Be sure to label the floppy set, and number the floppies. You can backup other local directories (like /usr/src/news) as we did above. Remember that each dbackup command generates a new floppy set, and that the floppies in each set must be restored in the correct order. The process of backing up multiple directories onto one or more dbackup floppy sets can be automated by using a shell script. An example of such a shell script is included with this software. It is named backup. All files in a dbackup set of floppies can be restored by typing: drestore You will be prompted for floppies by number as they are needed. Since drestore is not included on your distribution floppies, dbackup and drestore should be (d)backed up separately onto a dedicated floppy as follows. First insert the names /usr/lbin/dbackup and /usr/lbin/drestore (change /usr/lbin to your local binary directory) into a file named /etc/dbackup.bu. Then dump dbackup and drestore to a dedicated floppy as follows: dbackup /etc/dbackup.bu Now, if you must do a complete restore, first reload the system from your distribution floppies, and then restore dbackup and drestore from the dedicated floppy by typing (as root, with Microport): cd / cpio -icvduma < /dev/rdsk/fd For SCO Xenix, replace the cpio command line above with cpio -icvdumaB < /dev/rfd096 (a different cpio command line may have to be used for other systems). Once you have restored dbackup and drestore, you can proceed to restore each of your dbackup floppy sets by using drestore, as we did above. If you only want to list the names of the files in a dbackup floppy set (without restoring the files), use: drestore -l You can also use drestore to restore a dbackup floppy set under an user-specified root directory (other than the default, /). See the man page for more information. Please send comments, enhancements, etc., to: Dominick Samperi 430 East 13th Street New York, N.Y. 10009 UUCP: ...!ihnp4!cmcl2!manhat!samperi ARPA: manhat!samperi@NYU.EDU \Rogue\Monster\ else echo "will not over write ./README" fi if `test ! -s ./backup` then echo "writing ./backup" cat > ./backup << '\Rogue\Monster\' # # File backup script. D. Samperi, September 1987. # if [ $# -eq 0 ] then echo "\n\tUsage: backup class ..." echo "\n\t(class can be: conf, src, samperi, or all)\n" exit fi for class in $* do case $class in conf | all) \ echo "\n\007Starting backup of conf. files...\n" ; \ dbackup /etc/dbackup.conf /usr/lbin ;; src | all) \ echo "\n\007Starting backup of /usr/src...\n" ; \ dbackup /usr/src ;; samperi | all) \ echo "\n\007Starting backup of /usr/samperi...\n" ; \ dbackup /usr/samperi ;; esac done \Rogue\Monster\ else echo "will not over write ./backup" fi if `test ! -s ./dbackup.bu` then echo "writing ./dbackup.bu" cat > ./dbackup.bu << '\Rogue\Monster\' /usr/lbin/dbackup /usr/lbin/drestore \Rogue\Monster\ else echo "will not over write ./dbackup.bu" fi if `test ! -s ./dbackup.c` then echo "writing ./dbackup.c" cat > ./dbackup.c << '\Rogue\Monster\' /* * dbackup.c - Multi-floppy Directory Backup/Restore Utility * (For UNIX System V and XENIX) * * Copyright 1987 Dominick Samperi * * INSTALLATION. Compile and install the program in your local binary * directory as follows: * * cc -O dbackup.c -o dbackup * mv dbackup /usr/lbin (or whatever you call your local binary dir.) * ln /usr/lbin/dbackup /usr/lbin/drestore * * XENIX users should replace the cc command line above with * * cc -O -DXENIX dbackup.c -o dbackup * * USAGE. * * dbackup Full-pathname(s) [-nh] [-t Template] [-d Bkup-device] [-f listing] * drestore [-hl] [-r Root-dir] [-t Template] [-d Bkup-device] [-f listing] * * WARNING: Typing ENTER while a backup or restore is in progress will * probably terminate the program prematurely! This is due to * a bug in cpio. For this reason, all user input (while the * program is running) is through special function key F1. * Extra keystrokes other than ENTER may cause the program to * prompt again for a new floppy, but with the incorrect floppy * number. This shouldn't cause any problems, provided it is kept * in mind that the correct floppy sequence number is determined * by the order in which floppies are written or read. * * NOTES. Dbackup pipes the output of find into cpio, and monitors the * standard error output of the resulting pipeline to provide a more * user-friendly backup procedure than the one based on find and * cpio alone. * * Note that zero-length (empty) files are copied, but their names * are not displayed. * * F1_defstr is the default value of the string that is generated * by pressing special function key F1. * * Finally, note that the final blocks count that is printed after * a drestore is equal to the total number of blocks in the cpio * backup set, so it may not equal the number of blocks restored * if the -t flag is used. * * Please send any comments, enhancements, etc. to: * * Dominick Samperi * 430 East 13th Street * New York, N.Y. 10009 * * UUCP: ...!{ihnp4|rutgers|philabs}!cmcl2!manhat!samperi * ...!ihnp4!{pur-ee|iuvax}!bsu-cs!zoo-hq!magpie!samperi * */ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/signal.h> #define TRUE 1 #define FALSE 0 #define not ! #define BACKUP 1 #define RESTORE 0 /* Set the default backup device to use. */ #ifdef BU_dev static char bu_dev[40] = BU_dev ; #else #ifdef XENIX static char bu_dev[40] = "/dev/rfd096" ; #else static char bu_dev[40] = "/dev/rdsk/fd" ; #endif #endif /* Set special function key F1 default string. */ #ifdef F1_str static char *F1_defstr = F1_str ; #else #ifdef XENIX static char *F1_defstr = "\033[M" ; #else static char *F1_defstr = "^[OP" ; #endif #endif /* * There is probably a system call to fetch F1_defstr, but it is not * documented? Using the shell to fetch it via `setkey f1` and a temporary * file seems too clumsy (this method was used in an earlier version of * this program). */ /* Globals... */ static int mode, pid ; /* mode = BACKUP or RESTORE, pid = child process id. */ static int list_files = FALSE ; /* Only list file names if TRUE. */ static FILE *listing = NULL ; /* Listing file. */ static FILE *keybrd ; /* Used to flush the keyboard buffer. */ main(argc, argv) int argc ; char *argv[] ; { char cmd[512], cmd2[80], root_dir[80] ; char *fname = NULL, *progname, *param, *template = NULL ; char bu_dirs[256], bu_misc[256], bu_dir1[80] ; char *strrchr(), *ctime() ; long unix_time, time() ; extern char *optarg ; int i, c, p[2], fstatus, ftype ; int newer = FALSE, bad_arg = FALSE, first_dir = TRUE ; int print_help = FALSE ; struct stat Buf ; void watch_stderr(), clean_up() ; /* Get name part of program path. */ progname = strrchr(argv[0], '/') ; if(progname == NULL) progname = argv[0] ; else progname++ ; /* How was program invoked? As dbackup or drestore? */ if(strcmp(progname, "drestore") == 0) mode = RESTORE ; else if(strcmp(progname, "dbackup") == 0) mode = BACKUP ; else { fprintf(stderr, "\nMust name program dbackup, or drestore.\n\n") ; exit(1) ; } bu_dirs[0] = '\0' ; /* Directories to backup. */ bu_misc[0] = '\0' ; /* Miscellaneous files to backup. */ /* If BACKUP mode, is Full-pathname a directory or an ordinary file? */ if(mode == BACKUP) { if(argc < 2) bad_arg = TRUE ; else if(strcmp(argv[1], "-h") == 0) print_help = TRUE ; else { while(not bad_arg && argc > 1 && argv[1][0] != '-') { param = *++argv ; argc-- ; if(param[0] != '/') { fprintf(stderr, "\nMust specify full path names") ; fprintf(stderr, " (starting with /).\n\n") ; exit(1) ; } fstatus = stat(param, &Buf) ; if(fstatus == -1) bad_arg = TRUE ; else if((ftype = (Buf.st_mode & 0170000)) == 0 || ftype == 0100000) { /* Ordinary file. */ strcat(bu_misc, param) ; strcat(bu_misc, " ") ; } else if(ftype == 040000) { /* Directory. */ strcat(bu_dirs, ".") ; strcat(bu_dirs, param) ; strcat(bu_dirs, " ") ; if(first_dir) { strcpy(bu_dir1, param) ; first_dir = FALSE ; } } else { bad_arg == TRUE ; break ; } } } } strcpy(root_dir, "/") ; /* Default drestore root directory. */ /* Look for command line flags. */ while((c = getopt(argc, argv, "lhnf:r:t:d:")) != EOF) { switch(c) { case 'h': /* Print some help. */ print_help = TRUE ; break ; case 'l': /* Just list file names. */ if(mode == RESTORE) list_files = TRUE ; else bad_arg = TRUE ; break ; case 'f': /* Generate a listing file. */ fname = optarg ; break ; case 'n': /* Only backup if newer than last dbackup. */ if(mode == BACKUP) newer = TRUE ; else bad_arg = TRUE ; break ; case 'r': /* Restore under this root directory. */ if(mode == RESTORE) strcpy(root_dir, optarg) ; else bad_arg = TRUE ; break ; case 'd': /* Alternative backup device file. */ strcpy(bu_dev, optarg) ; break ; case 't': /* Backup/Restore using template. */ template = optarg ; break ; case '?': bad_arg = TRUE ; break ; } } if(list_files && fname) { fprintf(stderr, "\nMust use I/O redirection to send -l ") ; fprintf(stderr, "output to a file.\n\n") ; exit(1) ; } else if(fname) { listing = fopen(fname, "w") ; if(listing == NULL) bad_arg = TRUE ; } /* Check for bad arguments. */ if((bad_arg || print_help) && mode == BACKUP) { fprintf(stderr, "\nUsage: %s Full-pathname(s) %s\n\n", progname, "[-hn] [-t template] [-d backup-dev] [-f listing]") ; exit(1) ; } else if(bad_arg || print_help) { fprintf(stderr, "\nUsage: %s %s\n\n", progname, "[-hl] [-r root-dir] [-t template] [-d backup-dev] [-f listing]") ; exit(1) ; } /* Build find/cpio command... */ strcpy(cmd, "trap 'exit 1' 1 2 3 ; cd ") ; if(mode == BACKUP) { /* do_both is TRUE when there are directories AND miscellaneous files to backup... */ int do_both = (bu_dirs[0] != '\0' && bu_misc[0] != '\0') ; strcat(cmd, "/ ; ") ; if(do_both) strcat(cmd, "(") ; if(bu_misc[0] != '\0') /* Miscellaneous files to backup. */ { /* Make sure all paths are of the form ./... */ strcat(cmd, " sed ") ; strcat(cmd, "-e \"s/^\\//\\.\\//\" ") ; strcat(cmd, "-e \"s/^[^/.]/\\.\\/&/\" ") ; strcat(cmd, bu_misc) ; } if(do_both) strcat(cmd, " ; ") ; if(bu_dirs[0] != '\0') /* Directories to backup. */ { strcat(cmd, " find ") ; strcat(cmd, bu_dirs) ; strcat(cmd, " -depth ") ; if(newer) { strcat(cmd, " -newer .") ; strcat(cmd, bu_dir1) ; strcat(cmd, "/.dbackup_time ") ; } if(template != NULL) { strcat(cmd, " -name ") ; strcat(cmd, "'") ; strcat(cmd, template) ; strcat(cmd, "' ") ; } strcat(cmd, " -print ") ; } if(do_both) strcat(cmd, ")") ; #ifdef XENIX strcat(cmd, " | cpio -ocdvB > ") ; #else strcat(cmd, " | cpio -ocdv > ") ; #endif strcat(cmd, bu_dev) ; } else /* RESTORE */ { strcat(cmd, root_dir) ; if(list_files) #ifdef XENIX strcat(cmd, " ; cpio -ictvB ") ; #else strcat(cmd, " ; cpio -ictv ") ; #endif else #ifdef XENIX strcat(cmd, " ; cpio -icdumvaB ") ; #else strcat(cmd, " ; cpio -icdumva ") ; #endif if(template != NULL) strcat(cmd, template) ; strcat(cmd, " < ") ; strcat(cmd, bu_dev) ; } #ifdef XENIX strcat(cmd, " ; setkey 1 \"") ; #else strcat(cmd, " ; /etc/setkey f1 \"") ; #endif strcat(cmd, F1_defstr) ; strcat(cmd, "\" ; stty echo ") ; if(mode == BACKUP && not newer && bu_dirs[0] != '\0') { strcat(cmd, " ; touch ") ; strcat(cmd, bu_dir1) ; strcat(cmd, "/.dbackup_time") ; } /* Arrange for the standard error output from the command to go to the standard input of a spawned child process... */ pipe(p) ; pid = fork() ; if(pid < 0) { perror("fork error") ; exit(1) ; } else if(pid == 0) /* The child. */ { /* Child process monitors stderr output from parent... */ close(0) ; dup(p[0]) ; close(p[0]) ; close(p[1]) ; watch_stderr() ; } /* Parent code. */ /* Catch interrupts and hangups. */ signal(SIGINT, clean_up) ; signal(SIGHUP, clean_up) ; /* * A system call equivalent to setkey would have avoided the need to * shell a command here... */ /* Set string for special function key F1. */ #ifdef XENIX strcpy(cmd2, "setkey 1 \"") ; strcat(cmd2, bu_dev) ; strcat(cmd2, "\n\" ; stty -echo") ; #else strcpy(cmd2, "/etc/setkey f1 \"") ; strcat(cmd2, bu_dev) ; strcat(cmd2, "^M\" ; stty -echo") ; #endif system(cmd2) ; /* Send ready message to console, wait for F1. */ if(mode == BACKUP) { fprintf(stderr, "\nReady to begin backup of \n") ; if(bu_dirs[0] != '\0') fprintf(stderr, "Directories: %s\n", bu_dirs) ; if(bu_misc[0] != '\0') fprintf(stderr, "Miscellaneous files: %s\n", bu_misc) ; if(template != NULL) fprintf(stderr, "Template: %s\n", template) ; } else { if(list_files) fprintf(stderr, "\nReady to list files") ; else fprintf(stderr, "\nReady to restore") ; if(template != NULL) fprintf(stderr, " (%s)", template) ; if(list_files) fprintf(stderr, ".\n") ; else fprintf(stderr, " under %s.\n", root_dir) ; } fprintf(stderr, "\n\tInsert floppy #1.\n\n\tHit F1 when ready,") ; fprintf(stderr, " or CTRL-C to quit...\n\n") ; while(getchar() != '\n') ; time(&unix_time) ; if(mode == BACKUP) { printf("\ndbackup started on %s\n", ctime(&unix_time)) ; if(listing) { fprintf(listing, "\ndbackup started on %s\n", ctime(&unix_time)) ; if(bu_dirs[0] != '\0') fprintf(listing, "Directories: %s\n", bu_dirs) ; if(bu_misc[0] != '\0') fprintf(listing, "Miscellaneous files: %s\n", bu_misc) ; fprintf(listing, "\n") ; } } else if(not list_files) { printf("\ndrestore started on %s\n", ctime(&unix_time)) ; if(listing) fprintf(listing, "\ndrestore started on %s\n", ctime(&unix_time)) ; } else printf("\nListing started on %s\n", ctime(&unix_time)) ; fflush(stdout) ; if(listing) fflush(listing) ; /* Send stderr to child's stdin. */ close(2) ; dup(p[1]) ; close(p[0]) ; close(p[1]) ; /* Shell the command, and call clean_up() if there is a problem. */ if(system(cmd) != 0) clean_up() ; } void watch_stderr() /* * Monitors the stderr output from the cpio command, prompting * for a new floppy when the string " ready\n" is found, and terminating when * the string " blocks\n" is found. The strange error number information that * is printed by cpio when the floppy is full is suppressed. */ { char buf[2][80], *cp ; /* Output is "double buffered." */ static char *edge = " ready\nblocks\n" ; /* Used to drive automaton. */ int state, nfiles, bufp, k, c, fcount ; void flush_keybrd() ; /* Flushes the keyboard buffer. */ state = 0 ; /* State of automaton used to recognize strings. */ fcount = 1 ; /* Number of current floppy. */ nfiles = 0 ; /* Number of files copied to floppy. */ bufp = 0 ; /* Points to current buffer containing file name. */ k = 0 ; /* Current position in this buffer. */ keybrd = fopen("/dev/tty", "r") ; if(keybrd == NULL) { fprintf("Can't open your tty\n") ; exit(1) ; } /* Begin automaton... */ while((c = getchar()) != NULL) { switch(state) { case 0: if(c == ' ') state = 1 ; break ; case 1: if(c == 'r') state = 2 ; else if(c == 'b') state = 8 ; else if(c != ' ') state = 0 ; break ; case 2: case 3: case 4: case 5: case 8: case 9: case 10: case 11: case 12: if(c == edge[state]) state++ ; else state = 0 ; break ; case 6: if(c == '\n') { fcount++ ; /* New floppy number. */ nfiles = 0 ; /* Number files written so far. */ fflush(stdout) ; if(listing) fflush(listing) ; fprintf(stderr, "\n\t\007Done with floppy #%d, insert", fcount-1) ; fprintf(stderr, " floppy #%d.\n\n\tHit F1 when ready,", fcount) ; fprintf(stderr, " or CTRL-C to quit...\n") ; buf[0][0] = buf[1][0] = '\0' ; k = 0 ; } else state = 0 ; break ; case 13: if(c == '\n') { buf[bufp][k] = '\0' ; cp = buf[!bufp] ; if(*cp != '\0') { printf("%s\n", cp) ; fflush(stdout) ; if(listing) { fprintf(listing, "%s\n", cp) ; fflush(listing) ; } } if(mode == BACKUP) fprintf(stderr, "\n\007Backup done, %s total.\n", buf[bufp]) ; else fprintf(stderr, "\n\007Restore done, %s total.\n", buf[bufp]) ; exit(0) ; } else state = 0 ; } if(c == '\n') { if(state != 6) { buf[bufp][k] = '\0' ; cp = buf[!bufp] ; if(*cp != '\0') { printf("%s\n", cp) ; if(nfiles == 0) flush_keybrd() ; if(listing) fprintf(listing, "%s\n", cp) ; nfiles++ ; } bufp = !bufp ; k = 0 ; } } else buf[bufp][k++] = c ; } } static int done ; /* Used for communication between the following two functions. */ void flush_keybrd() { void handler() ; done = FALSE ; signal(SIGALRM, handler) ; alarm(1) ; while(not done) fgetc(keybrd) ; } void handler(sig) int sig ; { done = TRUE ; } void clean_up(sig) int sig ; { char cmd[80] ; signal(SIGINT, SIG_IGN) ; signal(SIGHUP, SIG_IGN) ; kill(pid, SIGKILL) ; /* * A system call equivalent to setkey would have avoided the need to * shell a command here... */ /* Set string for special function key F1. */ strcpy(cmd, "echo \"\\nBackup or Restore Aborted, Cleaning up...\"") ; #ifdef XENIX strcat(cmd, " | cat > /dev/tty ; stty echo ; setkey 1 \"") ; #else strcat(cmd, " | cat > /dev/tty ; stty echo ; /etc/setkey f1 \"") ; #endif strcat(cmd, F1_defstr) ; strcat(cmd, "\" ; echo \"Done, Goodbye!\" | cat > /dev/tty") ; system(cmd) ; exit(1) ; } \Rogue\Monster\ else echo "will not over write ./dbackup.c" fi if `test ! -s ./dbackup.conf` then echo "writing ./dbackup.conf" cat > ./dbackup.conf << '\Rogue\Monster\' /etc/dbackup.conf /etc/dbackup.bu /etc/passwd /etc/group /etc/profile /etc/inittab /etc/gettydefs /etc/bsetdate /etc/fstab /etc/checklist /.profile \Rogue\Monster\ else echo "will not over write ./dbackup.conf" fi if `test ! -s ./dbackup.doc` then echo "writing ./dbackup.doc" cat > ./dbackup.doc << '\Rogue\Monster\' DBACKUP(1) UNIX 5.0 (SAMPERI) DBACKUP(1) NAME dbackup, drestore - directory backup and restore utilities SYNOPSIS dbackup Path(s) [-hn] [-t Temp] [-d Bu-Dev] [-f Lsfile] drestore [-hl] [-r Root] [-t Temp] [-d Bu-Dev] [-f Lsfile] DESCRIPTION These utilities can be used to backup and restore directory hierarchies, typically by copying them to a set of floppy diskettes. They were designed to facilitate the process of backing up selected files and directories, so that a complete file system backup (requiring many floppies) is rarely needed (if you keep backup copies of the distribution floppies, then it may not be necessary to do a complete file system backup at all). Dbackup and drestore will prompt for floppies as they are needed. Dbackup is used to backup one or more directory hierarchies, and/or to backup files whose names are contained in one or more text files. The parameter Path(s) represents one or more full pathnames, each of which may correspond to a directory, or to a text file. Each directory that appears is taken to be the root of a directory hierarchy to be backed up, and each text file that appears must contain a list of (full) pathnames of files to be backed up, one per line. The -t flag can be used to back up only those files in a directory hierarchy with names that that match the file name template Temp, and the -n flag can be used to backup only those files in a directory hierarchy that have changed since the last full (d)backup (that is, one for which the -n flag was NOT used). Note that if more than one directory appears in Path(s), a time stamp file named .dbackup_time is written to the FIRST directory that appears, and this directory must appear first if you want this time stamp file to be used for a subsequent incremental backup (one for which the -n flag is used). ALL files whose names are contained in text files will be backed up (the -t and -n flags only effect directory backups), and no time stamp file is written when Path(s) does not include any directories. Drestore can be used to restore files from a (numbered) set of floppies that was created by a previous dbackup. By default, files will be restored under /, which will cause them to have the same full pathnames that they had when they were backed up. The -r flag can be used to restore files under an alternative root directory. For example, if "-r /tmp" is specified, then a file that had the full path name /usr/joe when it was backed up will be restored as /tmp/usr/joe. Page 1 (printed 11/30/87) DBACKUP(1) UNIX 5.0 (SAMPERI) DBACKUP(1) Files may be restored only if their names match a template that is specified with the -t flag. The -l drestore flag can be used to generate an "ls -l" style listing of the files in a backup set generated by dbackup (no files are copied). An alternative backup device may be specified by means of the -d flag. The default backup device file for Microport is /dev/rdsk/fd, corresponding to the (first) high density floppy drive. For example, in order to backup onto low density floppies using the high density drive, use "-d /dev/rdsk/fd048". (Warning: backing up onto low density floppies is very slow.) The -f flag may be used to generate a listing file containing a log of the backup or restore. Note that the -f flag may not be used with the -l drestore flag; if you want a printed listing of the output from drestore -l, use I/O redirection, as in: drestore -l > files.ls. The -h flag will cause a (very terse) help message to be printed. EXAMPLES In order to backup all files (and recursively, all subdirectories) in the directories /usr/joe and /usr/lbin, use: dbackup /usr/joe /usr/lbin To backup only files with names that end in .c or .h, use: dbackup /usr/joe /usr/lbin -t '*.[ch]' To backup only the files that have changed since the last dbackup: dbackup /usr/joe /usr/lbin -n Assuming that the file /etc/dbackup.misc contains the full pathnames of miscellaneous files (like /etc/passwd, /etc/group, /usr/lib/uucp/L.sys, /usr/spool/lp/interface/lp, etc.) to be backed up, important system-level files might be backed up as follows: dbackup /etc/dbackup.misc All files can be restored from a dbackup floppy set to their original locations by using: Page 2 (printed 11/30/87) DBACKUP(1) UNIX 5.0 (SAMPERI) DBACKUP(1) drestore The names of all C source files in a dbackup floppy set can be written to a file named cfiles.ls as follows: drestore -l -t '*.c' > cfiles.ls No files are actually restored in this example. BUGS Typing ENTER while a backup or restore is in progress will probably terminate the program prematurely. This is due to a bug in cpio. For this reason, all user input (while the program is running) is through special function key F1. Extra keystrokes other than ENTER may cause the program to prompt for a floppy again, before writing anything, and the floppy sequence number displayed will no longer be correct. This should not cause any problems, provided it is kept in mind that the correct sequence number is determined by the order in which floppies are written or read. Empty files are backed up by dbackup, but their names are not displayed during the backup procedure. (They are displayed via drestore -l.) Page 3 (printed 11/30/87) \Rogue\Monster\ else echo "will not over write ./dbackup.doc" fi if `test ! -s ./makefile` then echo "writing ./makefile" cat > ./makefile << '\Rogue\Monster\' # # Makefile for dbackup/drestore. By Dominick J. Samperi, November 1987. # # Insure that your local binary directory appears below. BIN=/usr/lbin # Now choose the appropriate CFLAGS definition below. # # C flags for Microport System V/AT: CFLAGS=-O -DF1_str=\"`/etc/setkey f1`\" -DBU_dev=\"/dev/rdsk/fd\" # # C flags for SCO XENIX: # CFLAGS=-O -DXENIX -DF1_str=\"\\033[M\" -DBU_dev=\"/dev/rfd096\" # # C flags for generic System V (F1_str and BU_dev should be defined here): # CFLAGS=-O (F1_str and BU_dev should be defined here) # # OK, now type 'make install'. install: dbackup strip dbackup mv dbackup $(BIN) chmod 0755 $(BIN)/dbackup ln $(BIN)/dbackup $(BIN)/drestore dbackup: dbackup.o cc dbackup.o -o dbackup \Rogue\Monster\ else echo "will not over write ./makefile" fi echo "Finished archive 1 of 1" exit -- Dominick Samperi, Manhattan College, New York, NY ...!ihnp4!cmcl2!manhat!samperi ...!ihnp4!cmcl2!phri!dasys1!samperi