//
// loadsys.c
//
//  This module restores a system saved with the savesys command.
//


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>

#define MAXSTRING             200
#define MAXDISKS              10
#define MAXFILESYSTEMS   50

/*
Template looks like this:

slice          file-system         mount-point
*/

// Structure definitions
struct file_system
     {
     char slice[ MAXSTRING ];
     char type[ MAXSTRING ];
     char mount[ MAXSTRING ];
     };

// Prototypes
void sys( char *command );
void readinfo( char *file );
void status( char *message );

// Global declarations
struct file_system fs[ MAXFILESYSTEMS ];
int fs_count = 0;

char disk[ MAXDISKS ][ MAXSTRING ];
int disk_count = 0;
static int bad[ MAXFILESYSTEMS ];

char *tape;
char boot[ MAXSTRING ];
char buffer[ MAXSTRING ];
int noclear = 0;

int main( int argc, char **argv )
     {
     time_t start_time;
     time_t end_time;
     int index;
     char cwd[ MAXSTRING ];
     float version;
     FILE *fp;
     int result;

     start_time = time( NULL );

     if(( argc != 2 ) && ( argc != 3 ))
          {
          printf( "Use: loadsys description-file\n" );
          exit( -1 );
          }

     if(( argc == 3 ) && ( ! strcmp( argv[ 1 ], "-n" )))
          noclear = 1;

     readinfo( argv[ argc - 1 ] );

     fp = fopen( "description", "r" );
     if( fp )
          {
          fscanf( fp, "%s %f", buffer, &version );
          fclose( fp );

          printf( "loadsys v1.0 from savesys image v%.1f\n", version );
          if( version > 1.0 )
               exit( -2 );
          }
     else
          printf( "loadsys v1.0 from savesys image v?.??\n" );

     // Get cwd
     getcwd( cwd, MAXSTRING );

     // Recreate all device nodes
     sys( "./makenodes >>/install.log 2>>/install.log" );

     // Format any hard disks which may require it
     for( index = 0; index < disk_count; ++index )
          {
          if( ! noclear )
               {
               sprintf( buffer, "dklayout -pd /dev/rdsk/%s 
                       >/dev/null 2>&1", disk[ index ] );
               if( system( buffer ))
                    // Disk is not formatted
                    {
                    sprintf( buffer, "Formating hard disk %s", 
                            disk[ index ] );
                    status( buffer );

                    sprintf( buffer, "dkformat -s -c 0 -d 
                            /dev/rdsk/%s >>/install.log
                            2>>/install.log", disk[ index ] );
                    sys( buffer );
                    }
               }
          }

     // Repartition all disks to 100% UNIX
     for( index = 0; index < disk_count; ++index )
          {
          sprintf( buffer, "Partitioning disk %s", disk[ index ] );
          status( buffer );

          if(( ! strncmp( boot, disk[ index ], strlen( boot ))) && 
              ( noclear ))
               {
               // This is the boot disk-- fdisk differently
               sprintf( buffer, "fdisk -a -u 98 /dev/rdsk/%s 
                       >>/install.log 2>>/install.log", disk[ index ] );
               result = system( buffer );
               }
          else
               {
               // All other disks- wipe out all other partitions
               sprintf( buffer, "fdisk -c -a -u 100 /dev/rdsk/%s 
                       >>/install.log 2>>/install.log", disk[ index ] );
               sys( buffer );
               }

          sprintf( buffer, "dklayout -pvd /dev/rdsk/%s 
                  >>/install.log 2>>/install.log", disk[index ] );
          sys( buffer );
          }

     // Rebuild vtoc tables
     for( index = 0; index < disk_count; ++index )
          {
          sprintf( buffer, "Slicing disk %s", disk[ index ] );
          status( buffer );

          sprintf( buffer, "edvtoc -n -f %s /dev/rdsk/%s 
                  >>/install.log 2>>/install.log", 
                  disk[index ], disk[ index ] );
          sys( buffer );
          }

     // Recreate all file systems
     for( index = 0; index < fs_count; ++index )
          {
          if( strcmp( fs[ index ].type, "raw" ))
               {
               sprintf( buffer, "Creating file system %s",
                       fs[ index ].mount );
               status( buffer );

               sprintf( buffer, "./%s.fs >>/install.log 
                       2>>/install.log", fs[ index ].slice );
               if( system( buffer ))
                    bad[ index ] = 1;
               }
          }

     // Repair file systems, if necessary
     for( index = 0; index < fs_count; ++index )
          {
          if( strcmp( fs[ index ].type, "raw" ) && ( ! bad[ index ] ))
               {
               sprintf( buffer, "Checking file system %s", 
                       fs[ index ].mount );
               status( buffer );

               sprintf( buffer, "fsck -F %s -y /dev/rdsk/%s 
                       >>/dev/null 2>>/dev/null", fs[
                       index ].type, fs[ index ].slice );
               system( buffer );
               }
          }


     // Restore contents of all file systems
     for( index = 0; index < fs_count; ++index )
          {
          if( ! strcmp( fs[ index ].type, "raw" ))
               sprintf( buffer, "Restoring raw slice %s", 
                       fs[ index ].slice );
          else
               sprintf( buffer, "Restoring file system %s", 
                       fs[ index ].mount );
          status( buffer );

          if( tape )
               {
               // Do dd for raw and uncompress it
               if( bad[ index ] && strcmp( fs[ index ].mount, "/tmp" ))
                    {
                    sprintf( buffer, "dd if=%s of=/dev/null bs=5120 
                            >>/install.log 2>>/install.log", tape );
                    sys( buffer );
                    }
               else if( ! strcmp( fs[ index ].type, "raw" ))
                    {
                    sprintf( buffer, "dd if=%s of=/dev/dsk/%s 
                            bs=5120 >>/install.log 2>>/install.log", 
                            tape, fs[ index ].slice );
                    sys( buffer );
                    }
               // some sort of file system
               else if( strcmp( fs[ index ].mount, "/tmp" ))
                    {
                    sprintf( buffer, "mkdir /mnt%s >>/install.log 
                            2>>/install.log", fs[index ].mount );
                    system( buffer );

                    sprintf( buffer, "mount -F %s /dev/dsk/%s /mnt%s 
                            >>/install.log 2>>/install.log", 
                            fs[ index ].type, fs[ index ].slice,
                            fs[ index ].mount );
                    sys( buffer );

                    sprintf( buffer, "/mnt%s", fs[ index ].mount );
                    chdir( buffer );
                    sprintf( buffer, "cpio -icdumB -I %s 
                            >>/install.log 2>>/install.log", tape );
                    sys( buffer );
                    }
               }
          else
               {
               if( bad[ index ] && strcmp( fs[ index ].mount, "/tmp" ))
                    ;
               else if( ! strcmp( fs[ index ].type, "raw" ))
                    {
                    sprintf( buffer, "dd if=%s/%s.backup 
                            of=/dev/rds0/%s bs=512k >>/install.log 
                            2>>/install.log", cwd, fs[ index ].slice,
                            fs[ index ].slice );
                    sys( buffer );
                    }
               // Do dd for raw and uncompress it
               else if( strcmp( fs[ index ].mount, "/tmp" ))
                    {
                    sprintf( buffer, "mkdir /mnt%s >>/install.log 
                            2>>/install.log", fs[ index ].mount );
                    system( buffer );

                    sprintf( buffer, "mount -F %s /dev/dsk/%s /mnt%s 
                            >>/install.log 2>>/install.log", 
                            fs[ index ].type, fs[ index ].slice,
                            fs[ index ].mount );
                    sys( buffer );

                    sprintf( buffer, "/mnt%s", fs[ index ].mount );
                    chdir( buffer );
                    sprintf( buffer, "cpio -icdumB -I %s/%s.backup 
                            >>/install.log 2>>/install.log", cwd, 
                            fs[ index ].slice );
                    sys( buffer );
                    }
               }
          }

     chdir( cwd );

     if( strcmp( boot, "unknown" ))
          {
          // Rebuild boot slice on c0t6d0sa
          status( "Restoring boot kernal" );

          sprintf( buffer, "dklayout -b -f /mnt/etc/boot -d 
                  /dev/rdsk/%ssa >>/install.log
                  2>>/install.log", boot );
          sys( buffer );
          }
     
     sprintf( buffer, "cp vfstab /mnt/etc >>/install.log 
             2>>/install.log" );
     system( buffer );
     sprintf( buffer, "cp sassign /mnt/etc/conf/cf.d
             >>/install.log 2>>/install.log" );
     system( buffer );
     sprintf( buffer, "cp dktab /mnt/etc >>/install.log 
             2>>/install.log" );
     system( buffer );
     sprintf( buffer, "cp dktab /mnt/etc/dktab.orig >>/install.log 
             2>>/install.log" );
     system( buffer );
     sprintf( buffer, "cp /install/S01shrink2 /mnt/etc/rc2.d 
             >>/install.log 2>>/install.log" );
     system( buffer );

     // Perform file system checks on all file systems
     for( index = fs_count - 1; index >= 0; --index )
          {
          sprintf( buffer, "Checking file system %s", fs[ index ].mount );
          status( buffer );

          if(( ! strcmp( fs[ index ].type, "raw" )) || ( bad[ index ] ))
               ; // Do no checking for raw partitions
          else if( strcmp( fs[ index ].mount, "/tmp" ))
               {
               sprintf( buffer, "umount /mnt%s >>/install.log 
                       2>>/install.log", fs[ index ].mount );
               sys( buffer );

               sprintf( buffer, "fsck -F %s -y /dev/rdsk/%s 
                       >>/install.log 2>>/install.log",
                       fs[ index ].type, fs[ index ].slice );
               system( buffer );
               }
          }

     end_time = time( NULL );
     index = end_time - start_time;
     system( "tput cup 22 0" );
     fp = fopen( "/install.log", "a" );
     fprintf( fp, "Elapsed time: %d mins %d secs\n", index / 60, 
             index % 60 );
     fprintf( fp, "loadsys completed successfully.\n" );
     fclose( fp );

     printf( "Elapsed time: %d mins %d secs\n", index / 60, index % 60 );
     printf( "loadsys completed successfully.\n" );

     return( 0 );
     }

void status( char *message )
     {
     static char line[ 81 ];
     int index;

     for( index = 0; index < 79; ++index )
          line[ index ] = ' ';
     line[ index ] = 0;

     strcpy( line, message );
     line[ strlen( line ) ] = ' ';
     system( "tput cup 22 0" );
     printf( "%s\n", line );
     }

void sys( char *command )
     {
     FILE *fp;
     int result = 0;

     
     fp = fopen( "/install.log", "a" );
     fprintf( fp, "# %s\n", command );
     fclose( fp );

     result = system( command );
     if( result )
          {
          fp = fopen( "/install.log", "a" );
          fprintf( fp, "loadsys: '%s' command failed error number 
                  %d\n", command, errno );
          fclose( fp );
          exit( -3 );
          }
     }

void readinfo( char *file )
        {
        FILE *fp;
        int index;
        int i;
     static char device[ MAXSTRING ];

     strcpy( boot, "unknown" );

        // Get file system descriptions
        fp = fopen( file, "r" );
        if( ! fp )
                {
                printf( "loadsys: Could not open file system
                       description file '%s'\n", file );
                exit( -2 );
                }

        while( fgets( buffer, MAXSTRING, fp ))
                {
                if( buffer[ 0 ] == '#' )
                        continue;

                i = sscanf( buffer, "%s %s %s\n", 
                           fs[ fs_count ].slice, 
                           fs[ fs_count ].type, fs[ fs_count ].mount );
                switch( i )
                        {
                case 1:
                        strcpy( disk[ disk_count ],
                               fs[ fs_count ].slice );
                        disk_count++;
                        break;
                case 2:
                        fs[ fs_count ].mount[ 0 ] = 0;
                case 3:
                        if( ! strcmp( "/", fs[ fs_count ].mount ))
                                {
                                strcpy( boot, fs[ fs_count ].slice );
                                boot[ strlen( boot ) - 2 ] = 0;
                                }

                        fs_count++;
                        break;
                        }
                }
        fclose( fp );

        // Display results
        printf( "Disks:\n" );
        for( index = 0; index < disk_count; ++index )
                printf( "\t%s\n", disk[ index ] );

        printf( "\nSlices:\n" );
        for( index = 0; index < fs_count; ++index )
                printf( "\t%s\t%s\t%s\n", fs[ index ].slice, 
                       fs[ index ].type, fs[ index ].mount );
        printf( "\n" );

        // Try to read in storage device
        fp = fopen( "/install/tape", "r" );
        if( fp )
                {
                fscanf( fp, "%s", device );
                fclose( fp );
                tape = device;
                }

        if( tape )
                printf( "Tape device: %s\n\n", tape );
        else
                printf( "CD ROM load\n\n" );

        printf( "Boot device is %ss0\n\n", boot );
        }

// End of File


