Return to BSD News archive
Newsgroups: comp.os.386bsd.misc Path: sserve!manuel.anu.edu.au!munnari.oz.au!constellation!convex!convex!cs.utexas.edu!wupost!uunet!mnemosyne.cs.du.edu!nyx!smace From: smace@nyx.cs.du.edu (Scott Mace) Subject: diskback-0.1 multivolume backup utility Message-ID: <1993Mar4.230322.8988@mnemosyne.cs.du.edu> Sender: usenet@mnemosyne.cs.du.edu (netnews admin account) Organization: Nyx, Public Access Unix @ U. of Denver Math/CS dept. Date: Thu, 4 Mar 93 23:03:22 GMT Lines: 668 This is a simple multi-volume diskbackup utility that will accept standard input. Scott Mace emace@tenet.edu # This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # diskback/Makefile # diskback/README # diskback/README.old # diskback/diskbackup.c # diskback/diskrestore.c # echo x - diskback/Makefile sed 's/^X//' >diskback/Makefile << 'END-of-diskback/Makefile' Xall: diskbackup diskrestore Xdiskbackup: diskbackup.c X cc -O diskbackup.c -o db Xdiskrestore: diskrestore.c X cc -O diskrestore.c -o dr X Xinstall: X mv db /usr/local/bin/diskbackup X mv dr /usr/local/bin/diskrestore END-of-diskback/Makefile echo x - diskback/README sed 's/^X//' >diskback/README << 'END-of-diskback/README' X XHere are a couple of handy programs for creating archives across Xmultiple floppy disks. X XSince tar(1) cannot handle multi-volume compressed archives, I had Xto do all my backups uncompressed. dump(8) was not used becuase Xit did not handle compression either. I found these programs at Xa Linux site. They required no modifications except for redefining Xthe default temp storage. The memory temp did not work too good. XSo, I changed it to use a tmpfile in /tmp. Depending on the disksize Xyou setup, you may need as much as 1.4 megs tmpspace. XIn my mind, using the tmpfile is better, because who wants to use Xsomething that hogs 1.4 megs of RAM. X XBoth diskbackup and diskrestore work with stdin/stdout and use Xstderr for messages with the operator. This makes it possible to Xpipe tar in one end or another and avoid creating BIG files. X XNOTE: /tmp is used for the temp file by diskbackup ( A file as big as Xa floppy ) and therefore we don't want to backup /tmp X XYou must set the environment variable FLOPPDISK X Xin csh Xsetenv FLOPPYDISK /dev/fd0a X XTo create the backup set X Xtar zcvfp - bin etc dev usr ..... | diskbackup "Name of backup" X XNote: the 'z' flag is for compression X the 'p' flag is to preserve permissions (so /dev/* files are created X correctly) X X Xto restore: X Xdiskrestore | tar zxvfp - X X X XIf you want to try and use memory as the tempspace then change: X X /* By default we use /tmp/back.. as a temporary.... */ X tempstore = USEFILE; X Xto: X X /* By default we use memory as a temporary.... */ X tempstore = USEMEM; X Xin diskbackup.c Xbut be warned, you system may do strange things, as it is not a Linux system. X XDO NOT: use /dev/rfd0a it will cause you system to panic and reboot. X XIf you get tar 1.11.1 and gzip 1.0.3 you can patch tar(1) to use gzip Xor compress with your archives. In my backups gzip is about 30% better Xthan compress. X X X X XTODO: X X1. Cleanup output to screen X2. Take out Linux junk. X3. fix permissions for backup tmpfile X4. fix any bugs. X X Xsend bug reports or help questions to Xemace@tenet.edu X XScott Mace END-of-diskback/README echo x - diskback/README.old sed 's/^X//' >diskback/README.old << 'END-of-diskback/README.old' XThe GNU Copyright is applyed here and to the programs. X XThis couple of programs implement a simple split system for a floppy X XThis version is tested with Linux .95b and can use file or memory Xas a temporary storage. XDue to the behaviour of linux malloc you will know if you cannot use Xmemory as a tem storage by a memory fault. XNormally you see a message sayng: XTesting Memory XMemory OK X XIf you don't have enought memory ( Virtual memory ) then you will just see XTesting memory X XTo use the system as before, with files just call diskbackup using Xdiskbackup -f "archive name at sometime" X XI tryed to test the program, and it seems to work for me...... XIf you have sugestions just tell me ! X XThe rest of the readme is the OLD one... Informations on it may not be correct X X------------------------------------------------------------------- XThe problem is that Linux don't have a EOF in the floppy device X( This is reasonable since the EOF is the end of floppy itself) XThis create problems when you want to backup short files or files Xthat are longer than one disk. X XBoth diskbackup and diskrestore work with stdin/stdout and use Xstderr for messages with the operator. This make possible to Xpipe tar in one end or another and avoid to create BIG files X XEx: To backup a complete disk you can use XNOTE: /tmp is used for the temp file by diskbackup ( A file as big as Xa floppy ) and therefore we don't want to backup /tmp X Xcd / Xtar -cf - bin etc dev usr home var | compress | diskbackup "Backup at day one" X XNote that The variable FLOPPYDISK must be set to a valid disk XThe program assumes 1.44 disks and therefore the device to use is XFLOPPYDISK=/dev/PS0; export FLOPPYDISK X XTo restore the disk just type X Xcd / Xdiskrestore | compress -d | tar -xf - X XDamiano END-of-diskback/README.old echo x - diskback/diskbackup.c sed 's/^X//' >diskback/diskbackup.c << 'END-of-diskback/diskbackup.c' X/* This program is under the GNU copyright X * Author Damiano Bolla (Italy) X */ X X#include <stdio.h> X#include <sys/types.h> X#include <sys/stat.h> X#include <fcntl.h> X X#define BUFFSIZE 8192 /* Is 2^13 .... any meaning ? */ X#define NAMESIZE 255 /* This should be enought.... */ X#define NUMSIZE 30 /* This also should be enought... */ X#define FLOPPYSIZE 2794*512 /* How many bytes the floppy */ X#define TMPFILE "/tmp/backtmp" X#define DUMMYLEN 10 /* USed to read the ENTER */ X X#define MORE 1 X#define NOMORE 0 X X#define USEMEM 1 X#define USEFILE 2 X Xmain ( int argc, char *argv[] ) X { X char archname[NAMESIZE]; /* The name of the archive in floppy */ X char *disk; /* Name of the floppy device to use */ X char *buff; /* The I/O buffer */ X char *tbuff; /* The temp buffer */ X int outf; /* The output file Temporary file */ X int More; /* Do we have more data ? 1=yes 0=no */ X int Leng; /* The lenght of the current fdata */ X int DiskNum; /* The current disk number */ X int count; X int tempstore; /* Flag to know where to store.... */ X X /* By default we use memory as a temporary.... */ X tempstore = USEFILE; X X if ( argc < 2 ) X { X fprintf (stderr,"You must give me the name of the archive \n"); X exit (2); X } X X /* If we have three params the second is the option... */ X if ( argc == 3 ) X { X if ( strcmp( argv[1],"-f" ) == 0 ) X tempstore = USEFILE; X strncpy ( archname, argv[2], NAMESIZE ); X } X else X strncpy ( archname, argv[1], NAMESIZE ); X X disk = (char *)getenv ( "FLOPPYDISK" ); X if ( (disk == NULL) || (strlen(disk) == 0) ) X { X fprintf (stderr,"You need to set the variable FLOPPYDISK \n"); X exit (2); X } X X if ( tempstore == USEMEM ) X { X int c; X tbuff = (char *)malloc (FLOPPYSIZE); X if ( tbuff == NULL ) X { X fprintf (stderr,"Sorry can't allocate temp buffer \n"); X exit (2); X } X /* We now get all the reqired mem. Linux is a bit "strange" */ X printf ("Testing memory \n"); X for (c=0; c<FLOPPYSIZE; c++ ) tbuff[c]=0; X printf ("Memory OK \n"); X } X X /* This is the I/O buffer..... */ X buff = (char *)malloc (BUFFSIZE); X if ( buff == NULL ) X { X fprintf (stderr,"Sorry can't allocate buffer \n"); X exit (2); X } X X /* The sequence of operations is : X * Copy part of the source into the temporary file keeping the length X * Then copy the temporary file with the length informations to floppy X * Repeat until stdin is exausted. X */ X X if ( tempstore == USEFILE ) X { X outf = open (TMPFILE,O_WRONLY|O_CREAT,0777); X if ( outf < 0 ) X { X fprintf (stderr,"Sorry can't create %s \n",TMPFILE); X exit (2); X } X X /* Ok, now we have to copy from stdin to the tmpfile until size */ X Leng = 0; X DiskNum = 0; /* The first disk is 0,1,2,3,4...... */ X X while ( (count=Rread(0,buff,BUFFSIZE)) >= BUFFSIZE ) X { X Leng += count; X write (outf,buff,count); /* Write what you read */ X fprintf (stderr,"."); fflush (stderr); X if ( Leng >= FLOPPYSIZE ) X { X close ( outf ); X sync(); sync(); /* Anyway it doen't harm.... */ X CopyFilToFloppy ( disk, TMPFILE, archname, DiskNum, MORE, Leng ); X unlink (TMPFILE); sync (); X Leng = 0; /* Reset the length */ X DiskNum++; /* Set for the next floppy */ X outf = open (TMPFILE,O_WRONLY|O_CREAT,0777);/* Should work. */ X } X } X X /* we reached the end of stdin........ */ X if ( count > 0 ) X { X Leng += count; X write (outf,buff, count); /* Write what you read */ X close ( outf ); X sync(); sync(); X CopyFilToFloppy ( disk, TMPFILE, archname, DiskNum, NOMORE , Leng ); X unlink (TMPFILE); X sync (); X } X else X { X /* We don't have data.... BUT did we had an error ??? */ X if ( count < 0 ) fprintf (stderr,"Archive corrupted at last block \n"); X } X } X else X { X /* WE use memory as temporary here..... */ X char *tptr = tbuff; X X /* Ok, now we have to copy from stdin to the tbuff until size */ X Leng = 0; X DiskNum = 0; /* The first disk is 0,1,2,3,4...... */ X X while ( (count=Rread(0,tptr,BUFFSIZE)) >= BUFFSIZE ) X { X Leng += count; tptr += count; X fprintf (stderr,"."); fflush (stderr); X X if ( Leng >= FLOPPYSIZE ) X { X CopyMemToFloppy ( disk, tbuff, archname, DiskNum, MORE, Leng ); X Leng = 0; /* Reset the length */ X tptr = tbuff; /* Restore the initial pointer */ X DiskNum++; /* Set for the next floppy */ X } X } X X /* we reached the end of stdin........ */ X if ( count > 0 ) X { X Leng += count; X CopyMemToFloppy ( disk, tbuff, archname, DiskNum, NOMORE , Leng ); X sync (); X } X else X { X /* We don't have data.... BUT did we had an error ??? */ X if ( count < 0 ) fprintf (stderr,"Archive corrupted at last block \n"); X } X } X exit (0); X } X X/* ----------------------------------------------------------------- X * This function take care of writting a file to floppy X */ Xint CopyFilToFloppy ( char *Device, /* The destination device */ X char *FromFile, /* The source file */ X char *ArchName, /* The archive name */ X int DiskNum, /* The current disk number */ X int More, /* FLAG to indicate nore data */ X int Leng ) /* The lenght to write */ X { X char *buff; /* To read/write from files */ X char dummy[DUMMYLEN]; /* For the ENTER */ X int outf; /* We write the file here */ X int inf; /* We read from this file */ X char disk[NUMSIZE]; /* The current disk number */ X char archend[NUMSIZE]; /* 1=End of archive 0=More */ X char curleng[NUMSIZE]; /* The current length of data in floppy */ X int written; /* How many chars did we write .... */ X int count; /* The usual temp counter */ X X fprintf (stderr,"\n"); X fprintf (stderr,"Insert a floppy and press ENTER \n"); X read (2,dummy,2); X X fprintf (stderr,"\n"); X fprintf (stderr,"Writing archive %s \n",ArchName); X fprintf (stderr,"Writing disknum %d \n",DiskNum); X fprintf (stderr,"Writing more %d \n",More); X fprintf (stderr,"Writing Leng %d \n",Leng); X X buff = (char *)malloc (BUFFSIZE); X if ( buff == NULL ) X { X fprintf (stderr,"Sorry can't allocate buffer \n"); X return (-1); X } X X outf = open (Device,O_WRONLY); X if ( outf < 0 ) X { X fprintf (stderr,"Sorry can't open device %s \n",Device); X return (-1); X } X X inf = open (FromFile,O_RDONLY); X if ( inf < 0 ) X { X fprintf (stderr,"Sorry can't open file %s \n",FromFile); X return (-1); X } X X /* Now I need to fill the header data to be stored in disk */ X sprintf (disk,"%d",DiskNum); X sprintf (archend,"%d",More ); X sprintf (curleng,"%d",Leng ); X X /* Ok, time to start writting archive info to disk */ X write (outf,ArchName, NAMESIZE); X write (outf,disk ,NUMSIZE ); X write (outf,archend ,NUMSIZE ); X write (outf,curleng ,NUMSIZE ); X X /* and then it is time for the data from the tmpfile to floppy */ X written = 0; X while ( (count=read(inf,buff, BUFFSIZE)) > 0 ) X { X /* We have some data from file to store in floppy */ X fprintf(stderr,"#"); fflush (stderr); X written += count; X write ( outf, buff, count); /* We write what we read */ X } X X fprintf (stderr,"\n"); X if ( written != Leng ) X { X fprintf (stderr,"ERROR, written %d != Leng %d \n ",written,Leng); X return (-1); X } X X /* Ok the data should be in the floppy now, close and sync */ X close ( inf ); X close ( outf ); X sync (); sync (); sync (); X X return (0); X } X X/* -------------------------------------------------------------- X * This function will behave in a consistemt way if used over a file X * or a pipe. Thanks to Linux for pointing out the reasons of the X * pipe behaviour. X */ X Xint Rread(int chan, char *buff, int size ) X { X int err; X int requested; X requested = size; X X while ( size > 0 ) X { X err = read ( chan, buff, size ); X if ( err > 0 ) { buff += err; size -= err; } X else break; X } X X if ( requested-size > 0 ) X return ( requested - size ); X else X return (err); X } X X X/* ----------------------------------------------------------------- X * This function take care of writting a block of mem to floppy X */ Xint CopyMemToFloppy ( char *Device, /* The destination device */ X char *FromBuff, /* The source buffer */ X char *ArchName, /* The archive name */ X int DiskNum, /* The current disk number */ X int More, /* FLAG to indicate nore data */ X int Leng ) /* The lenght to write */ X { X char *tptr; X char dummy[DUMMYLEN]; /* For the ENTER */ X int outf; /* We write the file here */ X int inf; /* We read from this file */ X char disk[NUMSIZE]; /* The current disk number */ X char archend[NUMSIZE]; /* 1=End of archive 0=More */ X char curleng[NUMSIZE]; /* The current length of data in floppy */ X int written; /* How many chars did we write .... */ X int count; /* The usual temp counter */ X X fprintf (stderr,"\n"); X fprintf (stderr,"Insert a floppy and press ENTER \n"); X read (2,dummy,2); X X fprintf (stderr,"\n"); X fprintf (stderr,"Writing archive %s \n",ArchName); X fprintf (stderr,"Writing disknum %d \n",DiskNum); X fprintf (stderr,"Writing more %d \n",More); X fprintf (stderr,"Writing Leng %d \n",Leng); X X outf = open (Device,O_WRONLY); X if ( outf < 0 ) X { X fprintf (stderr,"Sorry can't open device %s \n",Device); X return (-1); X } X X /* Now I need to fill the header data to be stored in disk */ X sprintf (disk,"%d",DiskNum); X sprintf (archend,"%d",More ); X sprintf (curleng,"%d",Leng ); X X /* Ok, time to start writting archive info to disk */ X write (outf,ArchName, NAMESIZE); X write (outf,disk ,NUMSIZE ); X write (outf,archend ,NUMSIZE ); X write (outf,curleng ,NUMSIZE ); X X /* and then it is time for the data from the tmpfile to floppy */ X tptr = FromBuff; X written = 0; X while ( written < Leng ) X { X /* We have some data from file to store in floppy */ X fprintf(stderr,"#"); fflush (stderr); X if ( Leng - written > BUFFSIZE ) X count = BUFFSIZE; X else X count = Leng - written; X write ( outf, tptr, count); X written += count; X tptr += count; X } X X fprintf (stderr,"\n"); X close ( outf ); X sync (); sync (); sync (); X X return (0); X } X END-of-diskback/diskbackup.c echo x - diskback/diskrestore.c sed 's/^X//' >diskback/diskrestore.c << 'END-of-diskback/diskrestore.c' X/* This program is under the GNU copyright X * Author Damiano Bolla (Italy) X */ X#include <stdio.h> X#include <sys/types.h> X#include <sys/stat.h> X#include <fcntl.h> X X#define BUFFSIZE 8192 /* Is 2^13 .... any meaning ? */ X#define NAMESIZE 255 /* This should be enought.... */ X#define NUMSIZE 30 /* This also should be enought... */ X#define DUMMYLEN 10 X#define MORE 1 X#define NOMORE 0 X Xint More = MORE; /* We try to start with more data */ Xint DiskNum = 0; /* The current disk number */ Xchar backname[NAMESIZE] =""; /* The name of the archive in floppy */ X Xmain ( int argc, char *argv[] ) X { X char tmpname[NAMESIZE]; /* The name of the archive in floppy */ X char tmpnum[NUMSIZE]; X char dummy[DUMMYLEN]; X int tmpdisk; /* Temporary for the disk number */ X char *disk; /* Name of the floppy device to use */ X char *buff; /* IO buffer for the data */ X int Leng; /* The lenght of the current fdata */ X int count; X int TmpLeng; X int inf; X X disk = (char *)getenv ( "FLOPPYDISK" ); X if ( (disk == NULL) || (strlen(disk) == 0) ) X { X fprintf (stderr,"You need to set the variable FLOPPYDISK \n"); X exit (2); X } X X buff = (char *)malloc (BUFFSIZE); X if ( buff == NULL ) X { X fprintf (stderr,"Sorry can't allocate buffer \n"); X exit (2); X } X X /* The sequence of operations is : X * Get the informations from the disk read data, write data X */ X X while ( More == MORE ) X { X fprintf (stderr,"Insert floppy, then press ENTER \n"); X read (2,dummy,2); X X inf = open (disk,O_RDONLY); X if ( inf < 0 ) X { X fprintf (stderr,"Sorry can't open device %s \n",disk); X return (-1); X } X X /* Get the archive name from the floppy and check if OK */ X read (inf, tmpname, NAMESIZE); X if ( strlen ( backname ) <= 0 ) X strcpy ( backname, tmpname ); X else X { X if ( strcmp ( backname, tmpname ) != 0 ) X { X fprintf (stderr,"Wrong floppy, I want %s \n",backname ); X close (inf); X continue; X } X } X X /* Then I would like to know ehat floppy it is in the archive */ X read (inf, tmpnum, NUMSIZE); X tmpdisk = atoi ( tmpnum ); X if (DiskNum != tmpdisk ) X { X fprintf (stderr,"Wrong floppy, I want num %d \n",DiskNum ); X close (inf); X continue; X } X X read (inf, tmpnum, NUMSIZE); X More = atoi ( tmpnum ); X X read (inf, tmpnum, NUMSIZE); X Leng = atoi ( tmpnum ); X X fprintf (stderr,"Archive name : %s \n",backname); X fprintf (stderr,"Current disk : %d \n",DiskNum); X fprintf (stderr,"More disks : %d \n",More); X fprintf (stderr,"Cur Leng : %d \n",Leng); X X TmpLeng = 0; X while ( (count=read(inf,buff,BUFFSIZE)) > 0 ) X { X fprintf (stderr,"#"); fflush (stderr); X X /* The floppy will read MORE than needed, then TURUNCATE */ X if ( (TmpLeng+count) > Leng ) X { X write (1,buff, (Leng-TmpLeng)); X fprintf (stderr,"\n"); X fprintf (stderr,"Short write %d \n",(Leng-TmpLeng)); X TmpLeng += count; X } X else X { X write (1,buff, count); X TmpLeng += count; X } X X if ( TmpLeng >= Leng ) X { X close (inf); X sync (); sync (); X DiskNum ++; /* Want the next disk */ X break; /* Exit from this while */ X } X } X fprintf (stderr,"\n"); X /* This while exit when more == 0 ( No more disks in archive */ X } X X close (1); /* Possibly you loose chars if you exit without close */ X sync (); sync (); sync (); X exit (0); X } X END-of-diskback/diskrestore.c exit -- ********************************************************************* * Scott Mace internet: smace@nyx.cs.du.edu * * emace@tenet.edu * *********************************************************************