#include "dir.h" #include "backup.h" extern char *strsave (); extern char *pop (); extern int push (); extern char *build_name (); extern int in_dir (); extern int out_of_date (); extern struct FileLock *CreateDir (); void *stack = NULL; char sprbuf[ 1024 ]; struct DateStamp bdate; int first_time; main ( argc , argv ) int argc; char **argv; { FILE *fp; #define LINE_SIZE 100 char linebuf[ LINE_SIZE ]; char *p , *parm1 , *parm2; first_time = FALSE; argc--; argv++; while ( argc > 0 && argv[0][0] == '-' ) { switch ( argv[0][1] ) { case 'f' : first_time = TRUE; break; default : puts ( "Unknown option %s\n" , argv[0] ); exit ( 1 ); } argc--; argv++; } if ( argc == 2 ) { backup ( argv[0] , argv[1] ); } else if ( argc == 1 ) { /* read from DO_BACKUP file on destination drive. */ /* it should contain lines containing two parameters for the */ /* backup command (eg: h2:thai thai-backup:) */ fp = fopen ( build_name ( argv[0] , DO_BACKUP ) , "r" ); if ( fp == NULL ) { printf ( "usage: unable to find %s file on destination disk\n" , DO_BACKUP ); } else { while ( fgets ( linebuf , LINE_SIZE , fp ) != NULL ) { p = linebuf; while ( isspace ( *p ) ) p++; if ( *p == '\0' ) continue; parm1 = p; while ( !isspace ( *p ) ) p++; *p++ = '\0'; while ( isspace ( *p ) ) p++; if ( *p == '\0' ) continue; parm2 = p; while ( !isspace ( *p ) ) p++; *p++ = '\0'; while ( isspace ( *p ) ) p++; if ( *p != '\0' ) { printf ( "illegal syntax in %s file\n" , DO_BACKUP ); break; } printf ( "\nbackup %s %s\n\n" , parm1 , parm2 ); backup ( parm1 , parm2 ); } fclose ( fp ); } } else { printf ( "usage: backup from to\n" ); printf ( "or backup todisk\n" ); } } backup ( from , to ) char *from , *to; { struct dir_st *dir , *todir; char *path; struct dir_st *p; int isdir; struct DPTR *dptr; struct FileLock *lock; FILE *fp; struct FileInfoBlock *fib; int checkdir; lock = Lock ( build_name ( to , BACKUP_FILE_NAME ) , (LONG)ACCESS_READ ); if ( lock == NULL ) { if ( ! first_time ) { puts ( ".backup not found: use -f for first time backup" ); exit ( 1 ); } bdate.ds_Days = 0; bdate.ds_Minute = 0; bdate.ds_Tick = 0; } else { fib = (struct FileInfoBlock *) AllocMem ( (LONG) sizeof ( struct FileInfoBlock ) , (LONG) MEMF_PUBLIC ); if ( fib != NULL && Examine ( lock , fib ) ) bdate = fib->fib_Date; else { bdate.ds_Days = 0; bdate.ds_Minute = 0; bdate.ds_Tick = 0; } if ( fib != NULL ) FreeMem ( fib , (LONG) sizeof ( struct FileInfoBlock ) ); UnLock ( lock ); } fp = fopen ( build_name ( to , BACKUP_FILE_NAME ) , "w" ); if ( fp == NULL ) { puts ( "Failed to create .backup file for time stamp" ); return ( 0 ); } fclose ( fp ); if ( ! push ( &stack , "" ) ) { puts ( "Aborting" ); return ( 0 ); } while ( path = pop ( &stack ) ) { printf ( "Searching %s\n" , build_name ( from , path ) ); dir = getdir ( build_name ( from , path ) ); if ( dir == NULL ) { puts ( "Aborting" ); return ( 0 ); } /* if original directory changed since last backup, a file */ /* may have been deleted. If this is so, must do dir on dest too */ checkdir = FALSE; dptr = dopen ( build_name ( from , path ) , &isdir ); if ( dptr == NULL || ! isdir ) { puts ( "Internal error!!!" ); freedir ( dir ); return ( 0 ); } if ( out_of_date ( &dptr->fib->fib_Date ) ) checkdir = TRUE; dclose ( dptr ); /* ok, must also check destination disk in case files there */ /* have been added */ dptr = dopen ( build_name ( to , path ) , &isdir ); if ( dptr == NULL || ! isdir ) { if ( dptr != NULL && ! isdir ) { /* Found a file where we want a directory */ rm_file ( to , "" , path , isdir ); } printf ( "Creating %s\n" , build_name ( to , path ) ); lock = CreateDir ( build_name ( to , path ) ); if ( lock == NULL ) { printf ( "Failed to create %s\n" , build_name ( to , path ) ); freedir ( dir ); dclose ( dptr ); return ( 0 ); } UnLock ( lock ); } else { /* now, check date on destination directory. if changed, then */ /* files may have been created (which will have to be deleted) */ if ( out_of_date ( &dptr->fib->fib_Date ) ) checkdir = TRUE; } dclose ( dptr ); if ( checkdir ) { /* Have to check if files have been deleted. */ /* To do this, must do a dir on destination drive. */ printf ( "Searching %s\n" , build_name ( to , path ) ); todir = getdir ( build_name ( to , path ) ); if ( todir == NULL ) { puts ( "Aborting" ); freedir ( dir ); return ( 0 ); } for ( p = todir->next; p != NULL; p = p->next ) { if ( ! in_dir ( p->filename , dir ) ) rm_file ( to , path , p->filename , p->dir ); } freedir ( todir ); } for ( p = dir->next; p != NULL; p = p->next ) { if ( p->dir ) { if ( ! push ( &stack , build_name ( path , p->filename ) ) ) { freedir ( dir ); puts ( "Aborting" ); return ( 0 ); } } else { if ( out_of_date ( &p->date ) ) copy_file ( from , to , path , p->filename ); } } } return ( 1 ); } #define BSIZE 10000 copy_file ( from , to , path , filename ) char *from , *to , *path , *filename; { FILE *fromfp , *tofp; static char buf[ BSIZE ]; int bytes; if ( path == NULL || path[0] == '\0' ) strcpy ( sprbuf , filename ); else sprintf ( sprbuf , "%s/%s" , path , filename ); fromfp = fopen ( build_name ( from , sprbuf ) , "r" ); if ( fromfp == NULL ) { printf ( "Failed to open '%s' for copying\n" , build_name ( from , sprbuf ) ); return; } tofp = fopen ( build_name ( to , sprbuf ) , "w" ); if ( tofp == NULL ) { fclose ( fromfp ); printf ( "Failed to create '%s' to copy to\n" , build_name ( to , sprbuf ) ); return; } printf ( "Copying %s ... " , sprbuf ); fflush ( stdout ); while ( ( bytes = fread ( buf , 1 , BSIZE , fromfp ) ) > 0 ) { if ( fwrite ( buf , 1 , bytes , tofp ) != bytes ) { printf ( "write error, " ); break; } } fclose ( tofp ); fclose ( fromfp ); puts ( "done" ); } rm_file ( root , path , filename , isdir ) char *root; char *path; char *filename; int isdir; { struct dir_st *p , *dir; char *buf; if ( path == NULL || path[0] == '\0' ) { strcpy ( sprbuf , filename ); buf = strsave ( sprbuf ); } else { sprintf ( sprbuf , "%s/%s" , path , filename ); buf = strsave ( sprbuf ); } if ( strcmp ( buf , BACKUP_FILE_NAME ) == 0 ) return; if ( buf == NULL ) { puts ( "Out of memory!\n" ); return; } printf ( "Deleting %s %s\n" , isdir ? "directory" : "file" , build_name ( root , buf ) ); if ( isdir ) { printf ( "Searching %s\n" , build_name ( root , buf ) ); dir = getdir ( build_name ( root , buf ) ); if ( dir == NULL ) { printf ( "Failed to open directory %s\n" , build_name ( root , buf ) ); } else { for ( p = dir->next; p != NULL; p = p->next ) rm_file ( root , build_name ( path , filename ) , p->filename , p->dir ); freedir ( dir ); /* Delete the directory */ DeleteFile ( build_name ( root , buf ) ); } } else DeleteFile ( build_name ( root , buf ) ); free ( buf ); } int in_dir ( filename , dir ) char *filename; struct dir_st *dir; { struct dir_st *p; for ( p = dir->next; p != NULL; p = p->next ) if ( strcmp ( p->filename , filename ) == 0 ) return ( 1 ); return ( 0 ); } char * build_name ( root , filename ) char *root , *filename; { static char buf[ 512 ]; strcpy ( buf , root ); if ( buf[0] != '\0' && buf[ strlen ( buf ) - 1 ] != ':' ) strcat ( buf , "/" ); strcat ( buf , filename ); return ( buf ); } char * strsave ( s ) char *s; { char *p; p = malloc ( strlen ( s ) + 1 ); if ( p != NULL ) strcpy ( p , s ); return ( p ); } int out_of_date ( date ) struct DateStamp *date; { if ( date->ds_Days < bdate.ds_Days ) return ( 0 ); if ( date->ds_Days > bdate.ds_Days ) return ( 1 ); if ( date->ds_Minute < bdate.ds_Minute ) return ( 0 ); if ( date->ds_Minute > bdate.ds_Minute ) return ( 1 ); if ( date->ds_Tick < bdate.ds_Tick ) return ( 0 ); if ( date->ds_Tick > bdate.ds_Tick ) return ( 1 ); return ( 1 ); } /* Aztec C playing up! Used by perror() */ int sys_nerr = -1; char *sys_errlist[1];