home *** CD-ROM | disk | FTP | other *** search
/ PC Open 19 / pcopen19.iso / Msdos / PartMana / SOURCES.ZIP / PART.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-12  |  38.7 KB  |  1,395 lines

  1. #define _PART_C
  2.  
  3. #include "part.h"
  4.  
  5. #define TMP_SZ 100
  6.  
  7. struct event ev;
  8. int  hd, ext_level, recursive_opt;
  9. struct part_long pseudo_part;
  10. struct mbr  mbr, mbr2, mbr_orig;
  11. char   tmp[TMP_SZ], tmp2[TMP_SZ];
  12.  
  13. extern struct mbr IPL, EXT, STD_IPL;
  14. extern unsigned int IPL_SELECTOR, ENTRY_S, ENTRY_V;
  15.  
  16.  
  17. void main(int argc, char **argv)
  18. {
  19.  int i;
  20.  hd=0x80;
  21.  messages_eng();
  22.  
  23.  argc--;
  24.  argv++;
  25.  
  26.  if( argc>=2 && (argv[0][0]=='-' || argv[0][0]=='/')
  27.              && (argv[0][1]=='L' || argv[0][1]=='l') )
  28.    {
  29.     if( strcmp(argv[1],"US")==0 ) messages_eng();
  30. /*  if( strcmp(argv[1],"xx")==0 ) messages_xxx(); */
  31.     else usage();
  32.     argc-=2;
  33.     argv+=2;
  34.   }
  35.  
  36.  if( argc>=2 && (argv[0][0]=='-' || argv[0][0]=='/')
  37.              && (argv[0][1]=='D' || argv[0][1]=='d') )
  38.    {
  39.     i=atoi(argv[1]);
  40.     if( i<1 || i>16 ) usage();
  41.     hd+=i-1;
  42.     argc-=2;
  43.     argv+=2;
  44.   }
  45.  
  46.  conio_init();
  47.  diskio_init();
  48.  
  49.  if( detected_os==SYS_WIN_NT )
  50.    {
  51.     fprintf(stderr,"This program will not run under Windows NT.\n");
  52.     exit(1);
  53.    }
  54.  
  55.  if( argc==0 )
  56.    {
  57.     interactive=1;
  58.     start_gui();
  59.    }
  60.  else
  61.    {
  62.     interactive=0;
  63.     command_line(argc,argv);
  64.    }
  65.  
  66.  diskio_exit();
  67.  conio_exit();
  68.  exit(0);
  69. }/* main */
  70.  
  71.  
  72. void start_gui(void)
  73. {
  74.  struct disk_info dinfo;
  75.  
  76.  border_window( Yellow+BakBlue, 1, 1, 80, 25, Border22f );
  77.  write_string( BrWhite+BakBlue, 4, 2, HEADER_MAIN );
  78.  write_string( Yellow+BakBlue, 3, 3, "────────────────────────────────────────────────────────────────────────────" );
  79.  
  80.  write_string( Yellow+BakBlue, 4, 24,"F1");
  81.  write_string( BrCyan+BakBlue, 6, 24, MENU_HELP );
  82.  
  83.  write_string( Yellow+BakBlue, 15, 24,"F2");
  84.  write_string( BrCyan+BakBlue, 17, 24, MENU_SAVE );
  85.  
  86.  write_string( Yellow+BakBlue, 34, 24,"F3");
  87.  write_string( BrCyan+BakBlue, 36, 24, MENU_UNDO );
  88.  
  89.  write_string( Yellow+BakBlue, 45, 24,"F4");
  90.  write_string( BrCyan+BakBlue, 47, 24, MENU_MODE );
  91.  
  92.  write_string( Yellow+BakBlue, 67, 24,"ESC");
  93.  write_string( BrCyan+BakBlue, 70, 24, MENU_QUIT );
  94.  
  95.  write_string( Yellow+BakBlue, 11, 19,"H)");
  96.  write_string( BrCyan+BakBlue, 13, 19, MENU_HIDE );
  97.  write_string( Yellow+BakBlue, 11, 20,"F)");
  98.  write_string( BrCyan+BakBlue, 13, 20, MENU_FORMAT );
  99.  write_string( Yellow+BakBlue, 11, 21,"V)");
  100.  write_string( BrCyan+BakBlue, 13, 21, MENU_VERIFY );
  101.  
  102.  write_string( Yellow+BakBlue, 42, 19,"S)");
  103.  write_string( BrCyan+BakBlue, 44, 19, MENU_SAVE_FILE );
  104.  write_string( Yellow+BakBlue, 42, 20,"L)");
  105.  write_string( BrCyan+BakBlue, 44, 20, MENU_LOAD_FILE );
  106.  write_string( Yellow+BakBlue, 42, 21,"X)");
  107.  write_string( BrCyan+BakBlue, 44, 21, MENU_INST_CODE );
  108.  
  109.  setup_mbr(&dinfo,0);
  110.  
  111.  clear_window( White+BakBlack, 1, 1, 80, 25 );
  112.  move_cursor(1,1);
  113. }/* start_gui */
  114.  
  115.  
  116. void write_mbr_menu(void)
  117. {
  118.  write_string( Yellow+BakBlue, 11, 16,"I)");
  119.  write_string( BrCyan+BakBlue, 13, 16, MENU_INSTALL );
  120.  write_string( Yellow+BakBlue, 50, 16,"w");
  121.  write_string( Yellow+BakBlue, 11, 17,"U)");
  122.  write_string( BrCyan+BakBlue, 13, 17, MENU_UNINSTALL );
  123.  
  124.  write_string( Yellow+BakBlue, 56, 24,"F5");
  125.  write_string( BrCyan+BakBlue, 58, 24, MENU_DISK );
  126. }/* write_mbr_menu */
  127.  
  128.  
  129. void write_embr_menu(void)
  130. {
  131.  write_string( Yellow+BakBlue, 11, 16,"I)");
  132.  write_string( BrCyan+BakBlue, 13, 16, MENU_INST_EXT );
  133.  
  134.  write_string( Yellow+BakBlue, 11, 17,"M)");
  135.  write_string( BrCyan+BakBlue, 13, 17, MENU_MOVE_PRI );
  136.  
  137.  write_string( Brown+BakBlue, 56, 24,"F5");
  138.  write_string(  Cyan+BakBlue, 58, 24, MENU_DISK );
  139. }/* write_embr_menu */
  140.  
  141.  
  142. int setup_mbr(struct disk_info *dinfo, struct part_long *p)
  143. {
  144.  int row, field, new_row, new_field;
  145.  int i, changed, extended, num_disks, valid;
  146.  int force_redraw, force_redraw_header, force_redraw_menu;
  147.  int force_reload, force_unpack, force_recalculate, force_initial_test;
  148.  char *hint=0, *mesg=0, *warn=0, *help_target=0;
  149.  unsigned long *edit_target, edit_limit;
  150.  
  151.  struct disk_addr daddr;
  152.  struct part_long part[4];
  153.  
  154.  static struct field_desc
  155.      {
  156.       unsigned long edit_limit;
  157.       int pos;
  158.       int len;
  159.      }*fd,
  160.  fd_chs[8]={ {0},{0}, {1023,37,4}, {255,42,4}, {63,47,4},
  161.                       {1023,53,4}, {255,58,4}, {63,63,4} },
  162.  fd_lba[4]={ {0},{0}, {16777215,36,9},{16777215,46,10} };
  163.       
  164.  ext_level++;
  165.  
  166.  if( p==0 )
  167.    {
  168.     extended=0;
  169.     ext_level=0;
  170.     p=&pseudo_part;
  171.    }
  172.  else
  173.    {
  174.     extended=1;
  175.    }
  176.  
  177.  row=0;
  178.  field=0;
  179.  new_row=0;
  180.  new_field=0;
  181.  force_reload=1;
  182.  force_unpack=1;
  183.  force_redraw=1;
  184.  force_redraw_menu=1;
  185.  force_recalculate=0;
  186.  force_redraw_header=1;
  187.  force_initial_test=0;
  188.  
  189.  changed=0;
  190.  
  191.  while(1)
  192.     {
  193.      help_target=0;
  194.      
  195.      if( extended==1 ) help_target="extended";
  196.  
  197.      if( force_redraw_menu==1 )
  198.        {
  199.         if( extended==0 ) write_mbr_menu();
  200.                      else write_embr_menu();
  201.         force_redraw_menu=0;
  202.        }
  203.  
  204.      if( force_reload==1 )         /* Read disk parameters and MBR from (hd) */
  205.        {
  206.         if( extended==0 )
  207.           {
  208.            write_string(BrCyan+BakBlue,4,4, HEADER_GET );
  209.  
  210.            write_int(BrWhite+BakBlue,14,4,2, hd-0x80+1 );
  211.  
  212.            if( (num_disks=get_disk_info(hd,dinfo))==-1 )
  213.              {
  214.               show_error(ERROR_DISK_INFO);
  215.               if( hd!=0x80 ) { hd=0x80; force_reload=1; continue; }
  216.               break;
  217.              }
  218.  
  219.            p->container_base=0;
  220.         
  221.            p->start_cyl=0;     p->end_cyl=dinfo->num_cyls-1;
  222.            p->start_head=0;    p->end_head=dinfo->num_heads-1;
  223.            p->start_sect=1;    p->end_sect=dinfo->num_sects;
  224.            
  225.            p->rel_sect=0;
  226.            p->num_sect=dinfo->total_sects;
  227.           }
  228.  
  229.         daddr.disk=dinfo->disk;
  230.         daddr.cyl =p->start_cyl;
  231.         daddr.head=p->start_head;
  232.         daddr.sect=p->start_sect;
  233.  
  234.         clear_window(Yellow+BakBlue,4,9,74,7);
  235.         write_string(Yellow+BakBlue,25,10,HEADER_READ);
  236.  
  237.         if( disk_read(&daddr,&mbr,1)==-1 )
  238.           {
  239.            show_error(ERROR_READ_MBR);
  240.            if( extended==0 && hd!=0x80 ) { hd=0x80; force_reload=1; continue; }
  241.            break;
  242.           }
  243.  
  244.         memmove(&mbr_orig,&mbr,sizeof(struct mbr));
  245.  
  246.         force_redraw_header=1;
  247.         force_unpack=1;
  248.         force_reload=0;
  249.        }
  250.      
  251.      if( force_redraw_header==1 )
  252.        {
  253.         clear_window(BrCyan+BakBlue,4,4,76,4);
  254.         
  255.         if( extended==0 )
  256.           {
  257.            write_string(BrCyan+BakBlue,4,4, HEADER_HD );
  258.            write_int(BrWhite+BakBlue,14,4,2,dinfo->disk-0x80+1 );
  259.           }
  260.         else
  261.           {
  262.            write_string(BrCyan+BakBlue,4,4, HEADER_EXT );
  263.            write_string(BrCyan+BakBlue,4,5, HEADER_EXT2 );
  264.            write_int(BrWhite+BakBlue,14,5,2, ext_level );
  265.           }
  266.  
  267.         if( mode==MODE_CHS )
  268.           {
  269.            write_string(BrCyan+BakBlue,18,4,HEADER_CHS );
  270.            write_int(BrWhite+BakBlue,19,4,4,p->num_sect/2048);
  271.            write_int(BrWhite+BakBlue,34,4,4,p->end_cyl-p->start_cyl+1);
  272.            write_int(BrWhite+BakBlue,52,4,3,dinfo->num_heads);
  273.            write_int(BrWhite+BakBlue,65,4,3,dinfo->num_sects);
  274.            write_string(BrCyan+BakBlue,4,6, HEADER_CHS2 );
  275.            write_string(BrCyan+BakBlue,4,7, HEADER_CHS3 );
  276.           }
  277.         else /* mode==MODE_LBA */
  278.           {
  279.            write_string(BrCyan+BakBlue,18,4,HEADER_LBA );
  280.            write_int(BrWhite+BakBlue,19,4,4,p->num_sect/2048);
  281.            sprintf(tmp2,"%10s",sprintf_long(tmp,p->num_sect));
  282.            write_string(BrWhite+BakBlue,57,4,tmp2);
  283.            write_string(BrCyan+BakBlue,4,6, HEADER_LBA2 );
  284.            write_string(BrCyan+BakBlue,4,7, HEADER_LBA3 );
  285.           }
  286.         force_redraw_header=0;
  287.         force_redraw=1;
  288.        }
  289.  
  290.      if( force_unpack==1 ) /* Unpack mbr records into easy to use structures */
  291.        {
  292.         for( i=0 ; i<4 ; i++ )
  293.            {
  294.             unpack_part( &mbr.part_rec[i], &part[i] );
  295.             part[i].num=i;
  296.             part[i].daddr=&daddr;
  297.             part[i].container_base=p->container_base+p->rel_sect;
  298.            }
  299.         force_initial_test=1;
  300.         force_redraw=1;
  301.         force_unpack=0;
  302.        }
  303.  
  304.      if( force_recalculate==1  || force_initial_test==1 )
  305.        {
  306.         if( force_initial_test==1 )
  307.           {
  308.            if( !(valid=validate_table(dinfo,part,p,-1)) )
  309.              warn=WARN_CONFLICT;
  310.           }
  311.         else
  312.           valid=validate_table(dinfo,part,p,row);
  313.  
  314.         force_initial_test=0;
  315.         force_recalculate=0;
  316.         force_redraw=1;
  317.        }
  318.  
  319.      if( row!=new_row || field!=new_field || force_redraw )  /* Redraw table */
  320.        {
  321.         for( i=0 ; i<4 ; i++ )
  322.           {
  323.            sprintf_partrec(tmp, &part[i]);  tmp[76]=0;
  324.            if( part[i].empty || part[i].valid ) 
  325.               write_string(BrWhite+BakBlue,3,i+9,tmp);
  326.            else
  327.               write_string(BrRed+BakBlue,3,i+9,tmp);
  328.           }
  329.         row=new_row;
  330.         field=new_field;
  331.         force_redraw=0;
  332.        }
  333.      
  334.      for( i=0 ; i<4 ; i++ ) pack_part( &part[i], &mbr.part_rec[i] );
  335.      
  336.      if( memcmp(&mbr,&mbr_orig,sizeof(struct mbr))!=0 )
  337.           { changed=1; write_string( Blink+Yellow+BakBlue, 15, 24,"F2"); }
  338.      else { changed=0; write_string(       Yellow+BakBlue, 15, 24,"F2"); }
  339.      
  340.      if( field==0 )                        /* Active: Yes/No */
  341.        {
  342.         write_string(BrWhite,7,row+9,(part[row].active)?" Yes ":" No  ");
  343.         move_cursor(8,row+9);
  344.         hint=HINT_ACTIVE;
  345.        }
  346.      else if( field==1 )                /* Partition Type */
  347.        {
  348.         write_string(BrWhite,13,row+9, sprintf_os_name(tmp,&part[row]) );
  349.         move_cursor(13,row+9);
  350.         hint=HINT_SYSTYPE;
  351.        }
  352.      else if( mode==MODE_CHS && field==2 ) edit_target=&part[row].start_cyl;
  353.      else if( mode==MODE_CHS && field==3 ) edit_target=&part[row].start_head;
  354.      else if( mode==MODE_CHS && field==4 ) edit_target=&part[row].start_sect;
  355.      else if( mode==MODE_CHS && field==5 ) edit_target=&part[row].end_cyl;
  356.      else if( mode==MODE_CHS && field==6 ) edit_target=&part[row].end_head;
  357.      else if( mode==MODE_CHS && field==7 ) edit_target=&part[row].end_sect;
  358.      else if( mode==MODE_LBA && field==2 ) edit_target=&part[row].rel_sect;
  359.      else if( mode==MODE_LBA && field==3 ) edit_target=&part[row].num_sect;
  360.  
  361.      if( field>1 )
  362.        {
  363.         fd = ( mode==MODE_CHS ) ? &fd_chs[field] : &fd_lba[field];
  364.         edit_limit = fd->edit_limit;
  365.         write_int( BrWhite, fd->pos, row+9, fd->len, *edit_target );
  366.         move_cursor( fd->pos+fd->len-1, row+9 );
  367.         
  368.         if( mode==MODE_CHS )
  369.           sprintf(tmp, HINT_LOC_CHS, p->start_cyl, p->end_cyl, dinfo->num_heads-1, dinfo->num_sects );
  370.         else
  371.           sprintf(tmp, HINT_LOC_LBA, p->num_sect-1, p->num_sect-1 );
  372.  
  373.         hint=tmp;
  374.         help_target="create";
  375.        }
  376.  
  377.      clear_window(BakBlue,4,14,75,1);
  378.      
  379.           if( warn!=0 )  write_string(BrRed+BakWhite,4,14,warn);
  380.      else if( mesg!=0 )  write_string(Black+BakWhite,4,14,mesg);
  381.      else if( hint!=0 )  write_string(Yellow+BakBlue,4,14,hint);
  382.  
  383.      if( !valid ) help_target="conflict";
  384.  
  385.      get_event( &ev, EV_KEY );
  386.      
  387.      hint=mesg=warn=0;
  388.      
  389.      if( ev.key==27 )                      /* ESC - Quit */
  390.        {
  391.         if( !changed ) break;
  392.         mesg=MESG_NOT_SAVED;
  393.         continue;
  394.        }
  395.      
  396.      if( field==0 || field==1 )                 /* Active: Yes/No */
  397.        {
  398.         if( ev.key=='Y' || ev.key=='y' || ev.key==' ' && part[row].active==0 )
  399.           {
  400.            for( i=0 ; i<4 ; i++ )
  401.              part[i].active=0;
  402.            part[row].active=1;
  403.            force_redraw=1;
  404.            continue;
  405.           }
  406.         if( ev.key=='N' || ev.key=='n' || ev.key==' ' && part[row].active==1 )
  407.           {
  408.            part[row].active=0;
  409.            continue;
  410.           }
  411.                              /* Partition Type */
  412.         if( ev.scan==0x52E0 || ev.scan==0x5200 )         /* Insert */
  413.           {
  414.            int part_was_empty=part[row].empty;
  415.            
  416.            select_system_type(&part[row]);
  417.  
  418.            if( part_was_empty && part[row].os_num!=0 )
  419.              {
  420.               if( mode==MODE_CHS )
  421.                 {
  422.                  part[row].start_cyl = part[row].end_cyl = p->start_cyl;
  423.                  part[row].start_head=0; part[row].end_head=dinfo->num_heads-1;
  424.                  part[row].start_sect=1; part[row].end_sect=dinfo->num_sects;
  425.                 }
  426.               else
  427.                 {
  428.                  part[row].num_sect=1;
  429.                 }
  430.               force_recalculate=1;
  431.              }
  432.            force_redraw=1;
  433.            continue;
  434.           }
  435.        }
  436.              /* Now it must be field >= 2  - long integers */ 
  437.                                 /* Back Space  or  Delete */
  438.      else if( ev.key == 8 || ev.scan==0x53E0 || ev.scan==0x5300 )
  439.        {
  440.         *edit_target/=10;
  441.         force_recalculate=1;
  442.         continue;
  443.        }
  444.      else if( ev.key>='0' && ev.key<='9' )
  445.        {
  446.         int x=ev.key-'0';
  447.         
  448.         if( edit_limit>x && (edit_limit-x)/10>=*edit_target )
  449.           {
  450.            *edit_target = *edit_target*10 + x;
  451.            force_recalculate=1;
  452.           }
  453.         
  454.         continue;
  455.        }
  456.      else if( mode==MODE_CHS && ev.key=='+' )
  457.        {
  458.         if( *edit_target<edit_limit )
  459.           {
  460.            (*edit_target)++;
  461.            force_recalculate=1;
  462.           }
  463.         continue;
  464.        }
  465.      else if( mode==MODE_CHS && ev.key=='-' )
  466.        {
  467.         if( *edit_target>0 )
  468.           {
  469.            (*edit_target)--;
  470.            force_recalculate=1;
  471.           }
  472.         continue;
  473.        }
  474.      else if( mode==MODE_LBA && ev.key=='+' )
  475.        {
  476.         unsigned long x=*edit_target-*edit_target%dinfo->num_sects;
  477.  
  478.         if( edit_limit>dinfo->num_sects && edit_limit-dinfo->num_sects>x )
  479.           {
  480.            *edit_target=x+dinfo->num_sects;
  481.            force_recalculate=1;
  482.           }
  483.  
  484.         continue;
  485.        }
  486.      else if( mode==MODE_LBA && ev.key=='-' )
  487.        {
  488.         if( *edit_target>0 )
  489.           {
  490.            (*edit_target)--;
  491.            *edit_target-=*edit_target%dinfo->num_sects;
  492.            force_recalculate=1;
  493.           }
  494.  
  495.         continue;
  496.        }
  497.  
  498.  
  499.      if( ev.scan==0x50E0 || ev.scan==0x5000 )         /* down */
  500.        {
  501.         if( row<3 ) new_row=row+1;
  502.        }
  503.      else if( ev.scan==0x48E0 || ev.scan==0x4800 )     /* up */
  504.        {
  505.         if( row>0 ) new_row=row-1;
  506.        }
  507.      else if( ev.scan==0x51E0 || ev.scan==0x5100 ||     /* PgDn/End */
  508.               ev.scan==0x4FE0 || ev.scan==0x4F00  )
  509.        {
  510.         if( row<3 ) new_row=3;
  511.        }
  512.      else if( ev.scan==0x49E0 || ev.scan==0x4900 ||    /* PgUp/Home */
  513.               ev.scan==0x47E0 || ev.scan==0x4700  )
  514.        {
  515.         if( row>0 ) new_row=0;
  516.        }
  517.      else if( ev.scan==0x4BE0 || ev.scan==0x4B00 )     /* left */
  518.        {
  519.         if( field>0 ) new_field=field-1;
  520.        }
  521.      else if( ev.scan==0x4DE0 || ev.scan==0x4D00 )     /* right */
  522.        {
  523.         if( mode==MODE_CHS && field<7 ) new_field=field+1;
  524.         if( mode==MODE_LBA && field<3 ) new_field=field+1;
  525.        }
  526.      else if( ev.scan==0x53E0 || ev.scan==0x5300 )     /* Delete */
  527.        {
  528.         part[row].empty=1;
  529.         part[row].valid=0;
  530.         part[row].active=0;
  531.         part[row].os_id=0;
  532.         part[row].os_num=0;
  533.         part[row].start_cyl=0;   part[row].end_cyl=0;
  534.         part[row].start_head=0;  part[row].end_head=0;
  535.         part[row].start_sect=0;  part[row].end_sect=0;
  536.         part[row].rel_sect=0;
  537.         part[row].num_sect=0;
  538.         force_recalculate=1;
  539.         force_redraw=1;
  540.        }
  541.      else if( ev.scan==0x3B00 )                        /* F1 - Help */
  542.        {
  543.         html_view(HELP_TEXT,help_target);
  544.        }
  545.      else if( ev.scan==0x3C00 )                        /* F2 - Save */
  546.        {
  547.         disk_lock(daddr.disk);
  548.         mbr.magic=0xAA55;
  549.         if( disk_write(&daddr,&mbr,1)==-1 )
  550.           warn=WARN_WRITE_MBR;
  551.         else
  552.           {
  553.            mesg=MESG_MBR_SAVED;
  554.            memmove(&mbr_orig,&mbr,sizeof(struct mbr));
  555.           }
  556.         disk_unlock(daddr.disk);
  557.        }
  558.      else if( ev.scan==0x3D00 )                        /* F3 - Undo */
  559.        {
  560.         memmove(&mbr,&mbr_orig,sizeof(struct mbr));
  561.         force_unpack=1;
  562.        }
  563.      else if( ev.scan==0x3E00 )                /* F4 - Mode */
  564.        {
  565.         if( mode==MODE_CHS )
  566.           {
  567.            mode=MODE_LBA;
  568.            if( field==2 || field==3 || field==4 ) new_field=2;
  569.            if( field==5 || field==6 || field==7 ) new_field=3;
  570.           }
  571.         else
  572.           {
  573.            mode=MODE_CHS;
  574.            if( field==2 ) new_field=2;
  575.            if( field==3 ) new_field=5;
  576.           }
  577.         force_redraw_header=1;
  578.        }
  579.      else if( extended==0 && ev.scan==0x3F00 )        /* F5 - Select HD */
  580.        {
  581.         if( changed )       { mesg=MESG_NOT_SAVED; continue; }
  582.         if( num_disks==+1 ) { mesg=MESG_ONLY_1HD; continue; }
  583.  
  584.         hd = (hd-0x80+1) % num_disks + 0x80;
  585.         force_reload=1;
  586.        }
  587.      else if( (field==0 || field==1) && ev.key==0x0D )    /* Enter - Setup */
  588.        {
  589.         if( part[row].empty ) continue;
  590.  
  591.         if( os_desc[part[row].os_num].setup==0 )
  592.           { show_error(ERROR_NO_SETUP); continue; }
  593.  
  594.         if( part[row].valid==0 )
  595.           { show_error(ERROR_FIX_FIRST); }
  596.  
  597.         if( changed ) { mesg=MESG_NOT_SAVED; continue; }
  598.  
  599.         os_desc[part[row].os_num].setup(dinfo,&part[row]);
  600.         force_redraw_header=1;
  601.         force_redraw_menu=1;
  602.         force_reload=1;
  603.        }
  604.      else if( ev.key=='H' || ev.key=='h' )            /* Hide */
  605.        {
  606.         part[row].os_id=OS_HIDDEN;
  607.         detect_os_type(&part[row]);
  608.         force_redraw=1;
  609.        }
  610.      else if( ev.key=='F' || ev.key=='f' )            /* Format */
  611.        {
  612.         int fstatus;
  613.  
  614. #define NUM_ARGS  10
  615.  
  616.         char *argv[NUM_ARGS];
  617.         
  618.         if(  part[row].empty ) continue;
  619.  
  620.         if( os_desc[part[row].os_num].format==0 )
  621.           { show_error(ERROR_NO_FORMAT); continue; }
  622.  
  623.         if( part[row].valid==0 )
  624.           { show_error(ERROR_FIX_FIRST); continue; }
  625.  
  626.         if( changed ) { mesg=MESG_NOT_SAVED; continue; }
  627.  
  628.         sprintf(tmp2,"os_id 0x%02X",part[row].os_id);
  629.  
  630.         if( enter_string(4,14,PROMPT_FORMAT,TMP_SZ,tmp,tmp2)==0 ) continue;
  631.         
  632.         parse_arg(tmp,argv,NUM_ARGS);
  633.         
  634.         format_progress_init();
  635.         fstatus=os_desc[part[row].os_num].format(dinfo,&part[row],argv,format_progress);
  636.              if( fstatus==FORMAT_OK ) mesg=MESG_FORMAT_OK;
  637.         else if( fstatus==FORMAT_CANCEL ) mesg=WARN_FORMAT_CANCEL;
  638.         else if( fstatus==FORMAT_FAILED ) show_error(ERROR_FORMAT_FAILED);
  639.         format_progress_done();
  640.         force_reload=1;
  641.        }
  642.      else if( ev.key=='V' || ev.key=='v' )            /* Verify */
  643.        {
  644.         int fstatus;
  645.         
  646.         if(  part[row].empty ) continue;
  647.  
  648.         if( part[row].valid==0 )
  649.           { show_error(ERROR_FIX_FIRST); continue; }
  650.  
  651.         if( changed ) { mesg=MESG_NOT_SAVED; continue; }
  652.  
  653.         format_progress_init();
  654.         fstatus=generic_verify(dinfo,&part[row],0,0,format_progress);
  655.              if( fstatus==FORMAT_OK ) mesg=MESG_VERIFY_OK;
  656.         else if( fstatus==FORMAT_CANCEL ) mesg=WARN_VERIFY_CANCEL;
  657.         else if( fstatus==FORMAT_FAILED ) show_error(ERROR_VERIFY_FAILED);
  658.         format_progress_done();
  659.         force_reload=1;
  660.        }
  661.      else if( extended==1 && (ev.key=='I' || ev.key=='i') ) /* Install dummy */
  662.        {
  663.         copy_xcode( &EXT, &mbr );
  664.         mesg=MESG_INSTALL;
  665.        }
  666.      else if( extended==1 && (ev.key=='M' || ev.key=='m') ) /* Move to primary */
  667.        {
  668.         mesg="This option will be available in the next program release.";
  669.        }
  670.      else if( extended==0 && (ev.key=='I' || ev.key=='i') )    /* Install */
  671.        {
  672.         IPL_SELECTOR = (char*)&ENTRY_V - (char*)&IPL + 0x600;
  673.         copy_xcode( &IPL, &mbr );
  674.         mesg=MESG_INSTALL;
  675.        }
  676.      else if( extended==0 && (ev.key=='W' || ev.key=='w') )    /* Install-W */
  677.        {
  678.         IPL_SELECTOR = (char*)&ENTRY_S - (char*)&IPL + 0x600;
  679.         copy_xcode( &IPL, &mbr );
  680.         mesg=MESG_INSTALL;
  681.        }
  682.      else if( extended==0 && (ev.key=='U' || ev.key=='u') )    /* Uninstall */
  683.        {
  684.         copy_xcode( &STD_IPL, &mbr );
  685.         mesg=MESG_UNINSTALL;
  686.        }
  687.      else if( ev.key=='S' || ev.key=='s' )        /* Save */
  688.        {
  689.         if( enter_string(20,10,PROMPT_FILE,TMP_SZ,tmp,"save") == 0 )
  690.            continue;
  691.         if( save_to_file(tmp,&mbr,sizeof(struct mbr))==-1 )
  692.           warn=WARN_SAVE_FILE;
  693.         else
  694.           mesg=MESG_FILE_SAVED;
  695.        }
  696.      else if( ev.key=='L' || ev.key=='l' )        /* Load */
  697.        {
  698.         if( enter_string(20,10,PROMPT_FILE,TMP_SZ,tmp,"restore") == 0 )
  699.            continue;
  700.         if( load_from_file(tmp,&mbr2,sizeof(struct mbr))==-1 )
  701.           warn=WARN_LOAD_FILE;
  702.         else
  703.           {
  704.            mesg=MESG_FILE_LOADED;
  705.            memmove(&mbr,&mbr2,sizeof(struct mbr));
  706.            force_unpack=1;
  707.            force_initial_test=1;
  708.           }
  709.        }
  710.      else if( ev.key=='X' || ev.key=='x' )        /* Load IPL Code */
  711.        {
  712.         if( enter_string(20,10,PROMPT_FILE,TMP_SZ,tmp,"install") == 0 )
  713.            continue;
  714.         if( load_from_file(tmp,&mbr2,sizeof(struct mbr))==-1 )
  715.           warn=WARN_LOAD_FILE;
  716.         else
  717.           {
  718.            copy_xcode( &mbr2, &mbr );
  719.            mesg=MESG_INSTALL;
  720.           }
  721.        }
  722.      
  723.     }/* while(1) */
  724.  
  725.  ext_level--;
  726.  
  727.  return 0;
  728. }/* setup_mbr */
  729.  
  730.  
  731. int write_int(int attr, int x, int y, int w, unsigned long xx)
  732. {
  733.  char tmp[30];
  734.  
  735.  sprintf(tmp,"%*ld",w,xx);
  736.  write_string(attr,x,y,tmp);
  737.  
  738.  return 0;
  739. }/* write_int */
  740.  
  741.  
  742. char *sprintf_long(char *tmp, unsigned long num)
  743. {
  744.  int i=13;    // 1,111,111,111
  745.  tmp[i--]=0;    // 0 234 678 012
  746.  
  747.  while( num!=0 )
  748.     {
  749.      if( i==9 || i==5 || i==1 ) tmp[i--]=',';
  750.      tmp[i--]=num%10+'0';
  751.      num/=10;
  752.     }
  753.  
  754.  return tmp+i+1;
  755. }/* sprintf_long */
  756.  
  757.  
  758. char *sprintf_systype(char *tmp, int i)
  759. {
  760.  sprintf(tmp," 0x%02X   %-23s     %s     %s      %s ",
  761.                os_desc[i].os_id, os_desc[i].name,
  762.               (os_desc[i].setup!=0)?"Yes":" - ",
  763.               (os_desc[i].format!=0)?"Yes":" - ",
  764.               (os_desc[i].printinfo!=0)?"Yes":" - " );
  765.  return tmp;
  766. }/* sprintf_systype */
  767.  
  768.  
  769. char *sprintf_os_name(char *tmp, struct part_long *p)
  770. {
  771.  if( os_desc[p->os_num].os_id != OS_UNKN )
  772.     sprintf(tmp,"%-23s",os_desc[p->os_num].name );
  773.  else
  774.     sprintf(tmp,"Unknown code (0x%02X)    ", p->os_id );
  775.  
  776.  return tmp;
  777. }/* sprintf_os_name */
  778.  
  779.  
  780.  
  781. char *sprintf_partrec(char *tmp, struct part_long *p)
  782. {
  783.  char tmp1[30], tmp2[30];
  784.  
  785.  if( mode==MODE_CHS )
  786.    {
  787.     sprintf(tmp," %d   %-3s  %s %4ld %4ld %4ld  %4ld %4ld %4ld %10s ",
  788.          p->num+1,
  789.          p->active ? "Yes" : "No",
  790.          sprintf_os_name(tmp1,p),
  791.          p->start_cyl,
  792.          p->start_head,
  793.          p->start_sect,
  794.          p->end_cyl,
  795.          p->end_head,
  796.          p->end_sect,
  797.          sprintf_long(tmp2,p->num_sect/2) );
  798.    }
  799.  else /* MODE_LBA */
  800.    {
  801.     sprintf(tmp," %d   %-3s  %s%9lu %10lu %10lu %10s ",
  802.          p->num+1,
  803.          p->active ? "Yes" : "No",
  804.          sprintf_os_name(tmp1,p),
  805.          p->rel_sect,
  806.          p->num_sect,
  807.          (p->num_sect==0)?(0):(p->rel_sect+p->num_sect-1),
  808.          sprintf_long(tmp2,p->num_sect/2) );
  809.    }
  810.  
  811.  return tmp;         
  812. }/* sprintf_part */
  813.  
  814.  
  815. void pack_part(struct part_long *prl, struct part_rec *pr)
  816. {
  817.  if( prl->active==0 )
  818.    {
  819.     if( pr->boot_flag!=0 ) pr->boot_flag=0;
  820.    }
  821.  else
  822.    {
  823.     if( pr->boot_flag==0 ) pr->boot_flag=0x80;
  824.    }
  825.  
  826.  pr->start_cylL = prl->start_cyl & 0xFF;
  827.  pr->start_cylH = prl->start_cyl >> 8;
  828.  pr->start_head = prl->start_head;
  829.  pr->start_sect = prl->start_sect;
  830.  
  831.  pr->end_cylL   = prl->end_cyl & 0xFF;
  832.  pr->end_cylH   = prl->end_cyl >> 8;
  833.  pr->end_head   = prl->end_head;
  834.  pr->end_sect   = prl->end_sect;
  835.  
  836.  pr->rel_sect   = prl->rel_sect;
  837.  pr->num_sect   = prl->num_sect;
  838.  
  839.  pr->os_id  =  prl->os_id;
  840. }/* pack_part */
  841.  
  842.  
  843. void unpack_part(struct part_rec *pr, struct part_long *prl)
  844. {
  845.  prl->active = (pr->boot_flag==0)?0:1;
  846.  
  847.  prl->start_cyl  = pr->start_cylL+(pr->start_cylH<<8);
  848.  prl->start_head = pr->start_head;
  849.  prl->start_sect = pr->start_sect;
  850.  
  851.  prl->end_cyl    = pr->end_cylL+(pr->end_cylH<<8);
  852.  prl->end_head   = pr->end_head;
  853.  prl->end_sect   = pr->end_sect;
  854.  
  855.  prl->rel_sect   = pr->rel_sect;
  856.  prl->num_sect   = pr->num_sect;
  857.  
  858.  prl->os_id  = pr->os_id;
  859.  
  860.  detect_os_type( prl );
  861. }/* unpack_part */
  862.  
  863.  
  864. void detect_os_type(struct part_long *p)
  865. {
  866.  int i=0;
  867.  
  868.  while( os_desc[i].os_id!=p->os_id && os_desc[i].os_id!=OS_UNKN ) i++;
  869.  
  870.  p->os_num=i;
  871. }/* detect_os_type */
  872.  
  873.  
  874. int validate_table(struct disk_info *dinfo, struct part_long *part,
  875.                                             struct part_long *container, int x)
  876. {
  877.  int i, j;
  878.  struct part_long *p, *q;
  879.  unsigned long sect, rel_sect, num_sect;
  880.  unsigned long sect_per_side = dinfo->num_sects;
  881.  unsigned long sect_per_cyl  = dinfo->num_heads * dinfo->num_sects;
  882.  
  883.  if( x!=-1 ) /* we have to recalculate partition x */
  884.    {
  885.     p=&part[x];
  886.     
  887.     if( mode==MODE_CHS )
  888.       { 
  889.        p->rel_sect=0;
  890.        p->num_sect=0;
  891.  
  892.        if( p->start_cyl!=0 || p->start_head!=0 || p->start_sect!=0 )
  893.          {
  894.           p->rel_sect = p->start_cyl*sect_per_cyl +
  895.                         p->start_head*sect_per_side +
  896.                         p->start_sect - 1 - p->container_base;
  897.          }
  898.  
  899.       if( p->end_cyl!=0 || p->end_head!=0 || p->end_sect!=0  )
  900.         {
  901.          p->num_sect = p->end_cyl*sect_per_cyl +
  902.                        p->end_head*sect_per_side +
  903.                        p->end_sect - 1 - p->rel_sect - p->container_base + 1;
  904.         }
  905.      } /* CHS */
  906.    else /* mode==MODE_LBA */
  907.      {
  908.       p->start_cyl=0;    p->end_cyl=0;
  909.       p->start_head=0;    p->end_head=0;
  910.       p->start_sect=0;    p->end_sect=0;
  911.       
  912.       sect = p->container_base + p->rel_sect;
  913.  
  914.       if( p->rel_sect!=0 || p->num_sect!=0 )
  915.         {
  916.          p->start_cyl =(sect)/(sect_per_cyl);
  917.          p->start_head=(sect)%(sect_per_cyl)/(sect_per_side);
  918.          p->start_sect=(sect)%(sect_per_cyl)%(sect_per_side)+1;
  919.         }
  920.       
  921.       sect = p->container_base + p->rel_sect + p->num_sect - 1;
  922.  
  923.       if( p->num_sect!=0 )
  924.         {
  925.          p->end_cyl =(sect)/(sect_per_cyl);
  926.          p->end_head=(sect)%(sect_per_cyl)/(sect_per_side);
  927.          p->end_sect=(sect)%(sect_per_cyl)%(sect_per_side)+1;
  928.         }
  929.      }/* LBA */
  930.    }/* recalculate */
  931.  
  932.  
  933.  for( p=part, i=0 ; i<4 ; i++, p++ )
  934.     {
  935.      p->empty=1;
  936.      
  937.           if( p->start_cyl!=0  ) p->empty=0;
  938.      else if( p->start_head!=0 ) p->empty=0;
  939.      else if( p->start_sect!=0 ) p->empty=0;
  940.  
  941.      else if( p->end_cyl!=0  ) p->empty=0;
  942.      else if( p->end_head!=0 ) p->empty=0;
  943.      else if( p->end_sect!=0 ) p->empty=0;
  944.  
  945.      else if( p->rel_sect!=0 ) p->empty=0;
  946.      else if( p->num_sect!=0 ) p->empty=0;
  947.     }
  948.  
  949.  
  950.  for(  p=part, i=0 ; i<4 ; i++, p++ )
  951.     {
  952.      if( p->empty ) continue;
  953.      
  954.      p->valid=1;
  955.      
  956.           if( p->start_cyl  >= dinfo->num_cyls  ) p->valid=0;
  957.      else if( p->start_head >= dinfo->num_heads ) p->valid=0;
  958.      else if( p->start_sect == 0                ) p->valid=0;
  959.      else if( p->start_sect >  dinfo->num_sects ) p->valid=0;
  960.  
  961.      else if( p->end_cyl  >= dinfo->num_cyls  ) p->valid=0;
  962.      else if( p->end_head >= dinfo->num_heads ) p->valid=0;
  963.      else if( p->end_sect == 0                ) p->valid=0;
  964.      else if( p->end_sect >  dinfo->num_sects ) p->valid=0;
  965.  
  966.      else if( p->end_cyl <  p->start_cyl ) p->valid=0;
  967.      else if( p->end_cyl == p->start_cyl && p->end_head <  p->start_head  ) p->valid=0;
  968.      else if( p->end_cyl == p->start_cyl && p->end_head == p->start_head && p->end_sect < p->start_sect ) p->valid=0;
  969.      else
  970.        {
  971.         rel_sect = p->start_cyl*sect_per_cyl +
  972.                    p->start_head*sect_per_side +
  973.                    p->start_sect - 1 - p->container_base;
  974.  
  975.         num_sect = p->end_cyl*sect_per_cyl +
  976.                    p->end_head*sect_per_side +
  977.                    p->end_sect - 1 - p->container_base - rel_sect + 1;
  978.      
  979.         if( rel_sect != p->rel_sect ) p->valid=0;
  980.         if( num_sect != p->num_sect ) p->valid=0;
  981.         
  982.         if( rel_sect == 0 ) p->valid=0;
  983.         if( rel_sect >= container->num_sect ) p->valid=0;
  984.         if( rel_sect + num_sect - 1 >= container->num_sect ) p->valid=0;
  985.        }
  986.  
  987.      for( q=part, j=0 ; j<4 ; j++, q++ )
  988.         {
  989.          if( i==j || q->empty ) continue;
  990.          
  991.          if( p->rel_sect >= q->rel_sect &&
  992.              p->rel_sect <= q->rel_sect + q->num_sect - 1 ) p->valid=0;
  993.  
  994.          if( q->rel_sect >= p->rel_sect &&
  995.              q->rel_sect <= p->rel_sect + p->num_sect - 1 ) p->valid=0;
  996.         }/* q */
  997.     }/* p */
  998.  
  999.  for( i=0 ; i<4 ; i++ )
  1000.   if( part[i].empty==0 && part[i].valid==0 )
  1001.      return 0;
  1002.  
  1003.  return 1;
  1004. }/* validate_table */
  1005.  
  1006.  
  1007.  
  1008. void copy_xcode(struct mbr *from, struct mbr *to)
  1009. {
  1010.  memmove( &to->xcode, &from->xcode, sizeof(from->xcode) );
  1011. }/* copy_xcode */
  1012.  
  1013.  
  1014. void usage(void)
  1015. {
  1016.  html_dump(stderr,HELP_TEXT,"usage");
  1017.  exit(1);
  1018. }
  1019.  
  1020. void cmd_error(char *msg)
  1021. {
  1022.  fprintf(stderr,"\nError: %s\n",msg);
  1023.  exit(1);
  1024. }
  1025.  
  1026.  
  1027. void command_line(int argc, char **argv)
  1028. {
  1029.  char ch;
  1030.  int i, x, valid;
  1031.  unsigned long total;
  1032.  struct disk_info dinfo;
  1033.  struct disk_addr daddr;
  1034.  struct part_long p, part[4];
  1035.  
  1036.  if( argv[0][0]=='H' || argv[0][0]=='h' )         /* Help */
  1037.    {
  1038.     html_dump(stdout,HELP_TEXT,0);
  1039.     return;
  1040.    }
  1041.  
  1042.  if( argv[0][0]=='M' || argv[0][0]=='m' )        /* Modules */
  1043.    {
  1044.     printf("\n%s\n\n",HEADER_SYSTYPE);
  1045.  
  1046.     for( i=1 ; os_desc[i].os_id!=OS_UNKN ; i++ )
  1047.         printf("%s\n",sprintf_systype(tmp,i));
  1048.  
  1049.     return;
  1050.    }
  1051.  
  1052.  if( strcmpi(argv[0],"Reboot")==0 )  reboot();
  1053.  
  1054.  for( i=0 ; (ch="PpAaDdVvSsLlXxIiWwUuFf"[i])!=0 ; i++ )
  1055.    if( argv[0][0]==ch ) break;
  1056.  
  1057.  if( ch==0 )
  1058.    {
  1059.     usage();
  1060.     return;
  1061.    }
  1062.  
  1063.  if( get_disk_info(hd,&dinfo)==-1 )  cmd_error(ERROR_DISK_INFO);
  1064.  
  1065.  p.container_base=0;
  1066.         
  1067.  p.start_cyl=0;     p.end_cyl=dinfo.num_cyls-1;
  1068.  p.start_head=0;    p.end_head=dinfo.num_heads-1;
  1069.  p.start_sect=1;    p.end_sect=dinfo.num_sects;
  1070.            
  1071.  p.rel_sect=0;
  1072.  p.num_sect=dinfo.total_sects;
  1073.  
  1074.  if( argv[0][0]=='P' || argv[0][0]=='p' )    /* Print partition table */
  1075.    {
  1076.     ext_level=0;
  1077.     recursive_opt = (strncmpi(argv[1],"/r",2)==0)?1:0;
  1078.  
  1079.           /*   HardDisk 1   1236 MB  [ 1023 cyl x 255 heads x 63 sects = 11,111,111 sects ] */
  1080.     printf("   HardDisk %d  %5lu MB  [ %4d cyl x %3d heads x %2d sects = %10s sects ]\n\n",
  1081.            dinfo.disk-127, dinfo.total_sects/2048, dinfo.num_cyls,
  1082.            dinfo.num_heads, dinfo.num_sects, sprintf_long(tmp,dinfo.total_sects) );
  1083.  
  1084.     print_mbr(&dinfo, &p);
  1085.     return;
  1086.    }/* print */
  1087.  
  1088.  daddr.disk=hd;
  1089.  daddr.cyl=0;
  1090.  daddr.head=0;
  1091.  daddr.sect=1;
  1092.  
  1093.  if( disk_read(&daddr,&mbr,1)==-1 )  cmd_error(ERROR_READ_MBR);
  1094.  
  1095.   for( i=0 ; i<4 ; i++ )
  1096.      {
  1097.       unpack_part( &mbr.part_rec[i], &part[i] );
  1098.       part[i].num=i;
  1099.       part[i].daddr=&daddr;
  1100.       part[i].container_base=p.container_base+p.rel_sect;
  1101.      }
  1102.  
  1103.  valid=validate_table(&dinfo,part,&p,-1);
  1104.  
  1105.  if( argv[0][0]=='S' || argv[0][0]=='s' )        /* Save */
  1106.    {
  1107.     if( argc<2 ) usage();
  1108.     if( save_to_file(argv[1],&mbr,sizeof(struct mbr))==-1 )
  1109.        cmd_error(WARN_SAVE_FILE);
  1110.     printf("%s\n",MESG_FILE_SAVED);
  1111.     if( !valid )
  1112.        fprintf(stderr,"Warning: %s\n",ERROR_INVALID);
  1113.     return;
  1114.    }
  1115.  
  1116.  if( argv[0][0]=='L' || argv[0][0]=='l' )        /* Load */
  1117.    {
  1118.     if( argc<2 ) usage();
  1119.     if( load_from_file(argv[1],&mbr,sizeof(struct mbr))==-1 )
  1120.        cmd_error(WARN_LOAD_FILE);
  1121.     for( i=0 ; i<4 ; i++ )
  1122.        unpack_part( &mbr.part_rec[i], &part[i] );
  1123.     valid=validate_table(&dinfo,part,&p,-1);
  1124.    }
  1125.  
  1126.  if( !valid ) cmd_error(ERROR_INVALID);
  1127.  
  1128.  if( argv[0][0]=='I' || argv[0][0]=='i' )        /* Install */
  1129.    {
  1130.     IPL_SELECTOR = (char*)&ENTRY_V - (char*)&IPL + 0x600;
  1131.     copy_xcode( &IPL, &mbr );
  1132.    }
  1133.  else if( argv[0][0]=='W' || argv[0][0]=='w' )        /* Install-W */
  1134.    {
  1135.     IPL_SELECTOR = (char*)&ENTRY_S - (char*)&IPL + 0x600;
  1136.     copy_xcode( &IPL, &mbr );
  1137.    }
  1138.  else if( argv[0][0]=='U' || argv[0][0]=='u' )        /* Uninstall */
  1139.    {
  1140.     copy_xcode( &STD_IPL, &mbr );
  1141.    }
  1142.  else if( argv[0][0]=='X' || argv[0][0]=='x' )        /* Install IPL code */
  1143.    {
  1144.     if( argc<2 ) usage();
  1145.     if( load_from_file(argv[1],&mbr2,sizeof(struct mbr))==-1 )
  1146.       cmd_error(WARN_LOAD_FILE);
  1147.     copy_xcode( &mbr2, &mbr );
  1148.    }
  1149.  else if( argv[0][0]=='A' || argv[0][0]=='a' )            /* Activate */
  1150.    {
  1151.     if( argc<2 ) usage();
  1152.     i=atoi(argv[1])-1;
  1153.     if( i<0 || i>3 ) usage();
  1154.  
  1155.     for( x=0 ; x<4 ; x++ )
  1156.        part[x].active=0;
  1157.     part[i].active=1;
  1158.  
  1159.     for( i=0 ; i<4 ; i++ ) pack_part( &part[i], &mbr.part_rec[i] );
  1160.    }
  1161.  else if( argv[0][0]=='F' || argv[0][0]=='f' )            /* Format */
  1162.    {
  1163.     if( argc<2 ) usage();
  1164.     i=atoi(argv[1])-1;
  1165.     if( i<0 || i>3 ) usage();
  1166.         
  1167.     if( part[i].empty ) cmd_error(ERROR_FORMAT_EMPTY);
  1168.  
  1169.     if( os_desc[part[i].os_num].format==0 ) cmd_error(ERROR_NO_FORMAT);
  1170.     
  1171.     format_progress_init();
  1172.     x=os_desc[part[i].os_num].format(&dinfo,&part[i],argv+2,format_progress);
  1173.          if( x==FORMAT_FAILED ) cmd_error(ERROR_FORMAT_FAILED);
  1174.     else if( x==FORMAT_CANCEL ) cmd_error(WARN_FORMAT_CANCEL);
  1175.     else printf("\n%s\n",MESG_FORMAT_OK);
  1176.     format_progress_done();
  1177.     return;
  1178.    }
  1179.  else if( argv[0][0]=='V' || argv[0][0]=='v' )            /* Verify */
  1180.    {
  1181.     if( argc<2 ) usage();
  1182.     i=atoi(argv[1])-1;
  1183.     if( i<0 || i>3 ) usage();
  1184.         
  1185.     if( part[i].empty ) cmd_error(ERROR_FORMAT_EMPTY);
  1186.  
  1187.     printf("%50s%s\r","",PRESS_ESC);
  1188.  
  1189.     format_progress_init();
  1190.     x=generic_verify(&dinfo,&part[i],0,0,format_progress);
  1191.          if( x==FORMAT_FAILED ) cmd_error(ERROR_VERIFY_FAILED);
  1192.     else if( x==FORMAT_CANCEL ) cmd_error(WARN_VERIFY_CANCEL);
  1193.     else printf("\n%s\n",MESG_VERIFY_OK);
  1194.     format_progress_done();
  1195.     return;
  1196.    }
  1197.  
  1198.  disk_lock(hd);
  1199.      
  1200.  if( disk_write(&daddr,&mbr,1)==-1 )
  1201.    {
  1202.     disk_unlock(hd);
  1203.     cmd_error(WARN_WRITE_MBR);
  1204.    }
  1205.  
  1206.  printf("%s\n",MESG_MBR_SAVED);
  1207.  
  1208.  disk_unlock(hd);
  1209. }/* command_line */
  1210.  
  1211.  
  1212.  
  1213.  
  1214. int save_to_file(char *filename, void *buf, int len)
  1215. {
  1216.  FILE *f;
  1217.  
  1218.  if( (f=fopen(filename,"wb"))==0 ) return -1;
  1219.  
  1220.  if( fwrite(buf,1,len,f)!=len ) return -1;
  1221.  
  1222.  fclose(f);
  1223.  return 0;
  1224. }/* save_to_file */
  1225.  
  1226.  
  1227.  
  1228. int load_from_file(char *filename, void *buf, int len)
  1229. {
  1230.  FILE *f;
  1231.  
  1232.  if( (f=fopen(filename,"rb"))==0 ) return -1;
  1233.  
  1234.  if( fread(buf,1,len,f)!=len ) return -1;
  1235.  
  1236.  fclose(f);
  1237.  return 0;
  1238. }/* load_from_file */
  1239.  
  1240.  
  1241.  
  1242. void parse_arg(char *str, char **argv, int argv_size)
  1243. {
  1244.  int i=0;
  1245.  char *p=str;
  1246.  
  1247.  while(1)
  1248.     {
  1249.      while( *p==' ' || *p=='\t' ) p++;
  1250.      if( *p==0 ) break;
  1251.      if( i>=argv_size-1 ) break;
  1252.      argv[i++]=p;
  1253.      while( *p!=' ' && *p!='\t' && *p!=0 ) p++;
  1254.      if( *p==0 ) break;
  1255.      *p=0;
  1256.      p++;
  1257.     }
  1258.  
  1259.  argv[i]=0;
  1260. }/* parse_arg */
  1261.  
  1262.  
  1263.  
  1264. int print_mbr(struct disk_info *dinfo, struct part_long *p)
  1265. {
  1266.  int i;
  1267.  struct disk_addr daddr;
  1268.  struct part_long part[4];
  1269.  
  1270.  daddr.disk=dinfo->disk;
  1271.  daddr.cyl =p->start_cyl;
  1272.  daddr.head=p->start_head;
  1273.  daddr.sect=p->start_sect;
  1274.  
  1275.  if( disk_read(&daddr,&mbr,1)==-1 )
  1276.    {
  1277.     fprintf(stderr,"%s\n",ERROR_READ_MBR);
  1278.     return 0;
  1279.    }
  1280.  
  1281.  for( i=0 ; i<4 ; i++ )
  1282.     {
  1283.      unpack_part( &mbr.part_rec[i], &part[i] );
  1284.      part[i].num=i;
  1285.      part[i].daddr=&daddr;
  1286.      part[i].container_base=p->container_base+p->rel_sect;
  1287.     }
  1288.  
  1289.  validate_table(dinfo,part,p,-1);
  1290.  
  1291. /*
  1292.    HardDisk 1   1236 MB  [ 1023 cyl x 255 heads x 63 sects = 11,111,111 sects ] 
  1293.  
  1294.     Active      Starting        Ending    Starting  Sectors   Ending  Partition
  1295.    #  !   ID   Cyl Head Sct  Cyl Head Sct   sector  in part   sector  Size [KB]
  1296. OK 1  Y  0xFF 1023  255  63 1023  255  63 12345678 12345678 12345678  1,111,111
  1297.  X 2  -  0xFF 1023  255  63 1023  255  63 12345678 12345678 12345678  1,111,111
  1298.    3  -  0x00    0    0   0    0    0   0        0        0
  1299.    4  -  0x00    0    0   0    0    0   0        0        0
  1300. */
  1301.  printf("    Active      Starting        Ending    Starting  Sectors   Ending  Partition\n"
  1302.         "   #  !   ID   Cyl Head Sct  Cyl Head Sct   sector  in part   sector  Size [KB]\n");
  1303.  
  1304.  for( i=0 ; i<4 ; i++ )
  1305.     {
  1306.      printf("%s %d %s 0x%02X %4lu  %3lu  %2lu %4lu  %3lu  %2lu %8lu %8lu %8lu %10s\n",
  1307.           (part[i].empty)?"  ":((part[i].valid)?"OK":" X"), i+1,
  1308.           (part[i].active)?"Yes":" - ",
  1309.            part[i].os_id,
  1310.            part[i].start_cyl, part[i].start_head, part[i].start_sect,
  1311.            part[i].end_cyl,   part[i].end_head,   part[i].end_sect,
  1312.            part[i].rel_sect,  part[i].num_sect,
  1313.           (part[i].num_sect==0)?(0):(part[i].rel_sect+part[i].num_sect-1),
  1314.            sprintf_long(tmp,part[i].num_sect/2) );
  1315.     }
  1316.  
  1317.  for( i=0 ; i<4 ; i++ )
  1318.   if( !part[i].empty )
  1319.     {
  1320.      printf("\n # Active%s  Size [KB]\n",HEADER_SYSTYPE);
  1321.      break;
  1322.     }
  1323.  
  1324.  for( i=0 ; i<4 ; i++ )
  1325.   if( !part[i].empty )
  1326.     {
  1327.      printf(" %d  %s  %s   %10s\n", i+1, 
  1328.             (part[i].active)?"Yes":" - ",
  1329.              sprintf_systype(tmp,part[i].os_num),
  1330.              sprintf_long(tmp2,part[i].num_sect/2));
  1331.     }
  1332.  
  1333.  printf("\n");
  1334.  
  1335.  if( recursive_opt==0 ) return 0;
  1336.  
  1337.  if( ext_level>10 )
  1338.    {
  1339.     printf("Warning: Recursion is too deep.\n");
  1340.     return 0;
  1341.    }
  1342.  
  1343.  ext_level++;
  1344.  
  1345.  for( i=0 ; i<4 ; i++ )
  1346.   if( !part[i].empty )
  1347.    if( os_desc[ part[i].os_num ].printinfo!=0 )
  1348.      {
  1349.       if( part[i].os_id==5 )
  1350.           printf("\nExtended DOS    %4lu MB   [ %s sectors ] at [ Cyl=%lu, Head=%lu, Sect=%lu ]\n"
  1351.                    "MBR  Level %d\n\n",
  1352.                     part[i].num_sect/2048, sprintf_long(tmp,part[i].num_sect),
  1353.                     part[i].start_cyl, part[i].start_head, part[i].start_sect,
  1354.                     ext_level  );
  1355.       else
  1356.           printf("\nPartition       %4lu MB   [ %s sectors ] at [ Cyl=%lu, Head=%lu, Sect=%lu ]\n"
  1357.                    "Type: %s\n\n",
  1358.                     part[i].num_sect/2048, sprintf_long(tmp,part[i].num_sect),
  1359.                     part[i].start_cyl, part[i].start_head, part[i].start_sect,
  1360.                     sprintf_os_name(tmp2,&part[i]) );
  1361.  
  1362.       os_desc[ part[i].os_num ].printinfo(dinfo,&part[i]);
  1363.      }
  1364.  
  1365.  ext_level--;
  1366.  
  1367.  printf("\n");
  1368.  
  1369.  return 0;
  1370. }/* print_mbr */
  1371.  
  1372.  
  1373. int format_ext(struct disk_info *dinfo, struct part_long *p, char **argv, int (*progress)(char*) )
  1374. {
  1375.  disk_lock(dinfo->disk);
  1376.  progress("^Initializing Extended DOS partition ...");
  1377.  
  1378.  progress("Writing Extended Master Boot Record ...");
  1379.  
  1380.  if( disk_write_rel(dinfo,p,0,&EXT,1)==-1 )
  1381.    {
  1382.     progress("Error Writing Extended Master Boot Record.");
  1383.     disk_unlock(dinfo->disk);
  1384.     return FORMAT_FAILED;
  1385.    }
  1386.  
  1387.  argv++; /* so compiler will not show warning */
  1388.  
  1389.  sleep(2);
  1390.  
  1391.  disk_unlock(dinfo->disk);
  1392.  return FORMAT_OK;
  1393. }/* format_ext */
  1394.  
  1395.