home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 108_01 / disk.c < prev    next >
Text File  |  1985-11-14  |  9KB  |  286 lines

  1. /*
  2.     DISK UTILITY PROGRAM
  3.  
  4.     Written by Richard Damon
  5.     Version 1.0 May 1980
  6.  
  7.     This program allows the operator to examine and modify
  8. a CPM diskette.
  9.  
  10.     The commands available in this package are :
  11.  
  12. Tn  set current track to n (0-76)
  13. Sn  set current sector to n (1-26)
  14. Dn  set current disk number to n (0-3)
  15. Bn  set current track and sector to point to block n (0-F2)
  16. N   set current track and sector to next sector/block
  17.     next sector if last set command was for track or sector
  18.     next block if last set command was for block
  19. I   increment sector, if sector>26 set to 1 and increment track
  20. R   read sector/block into buffer
  21. W   write sector/block from buffer
  22. P   print out contents of buffer, allong with track/sector/block information
  23. Ea n n n n
  24.     edit buffer starting from location a filling with values n n n.
  25. Fn  Fill buffer with value n
  26. X   exit program
  27. M   print disk allocation map
  28.  
  29. Notes:
  30.     1)  Multiple commands may be specified on a line except for X
  31. which must be the only command on the line followed by return.
  32.     2)  Commands may be in upper or lower case letters
  33.     3)  Spaces are ignored except in the E command where they are used
  34.     as separaters for the numbers
  35.  
  36. Typical commands:
  37. d0t0s1rp    read in the track 0 sector 1 of disk 0 (Drive A) and print it
  38. e1A 4F 20 11    set buffer location 1A to 4F, 1B to 20, and 1C to 11.
  39. e0a 00w        set buffer location 0a to 0 and write buffer
  40.             Note no space after last data byte
  41. nrp        get next buffer and print it
  42.  
  43. Disk Allocation Map
  44.     The M command is designed to allow the directory blocks (blocks 0 and 1)
  45. to be printed out in a convient format. The directory is print out in the
  46. following format:
  47.  
  48.  Section 1:
  49.     The top half of the directory listing is a listing of the name
  50.     inforamtion of the directory entries.  Each line corresponds to 1 sector
  51.     of the directory.  A typical entry would be f=DISKTESTCOM/1 4c
  52.     The first letter is a code letter used to referance into section 2.
  53.     The equal sign indicats that the file exists, a star here indicates
  54.       that this entry is a deleted file.
  55.     Next comes the filename and extension.
  56.     The following /n is printed if this is other then the first extent 
  57.       (extent 0) of a file where n is the extent number of this entry.
  58.     The following number is the hex record count for this extent.
  59.  
  60.  Section 2:
  61.     The bottom half of the directory listing is a disk allocation map
  62.     showing which blocks are in use and by which file. Free blocks are
  63.     indicated by a dot while used blocks are marked by the file control
  64.     letter asigned to a file in section 1.  This listing has been blocked off
  65.     in groups of 8 and 16 to ease reading.
  66.  
  67. CPM FILE STRUCTURE
  68.  
  69.     To help the user of this program the following is a brief description
  70. of the format used in CPM.  The first 2 tracks of a disk are reserved
  71. for the bootstrap and the copy of the CPM operating system.  Tracks 2
  72. through 76 store the data.  To speed up disk access CPM does not store
  73. consecutive data in consecutive sectors.  Insteed it uses every 6th sector
  74. for data. Thus to read logical consecutive sectors you must read the
  75. sectors in the following order:
  76.  1 7 13 19 25 5 11 17 23 3 9 15 21 2 8 14 20 26 6 12 18 24 4 10 16 22
  77. This interleaving is taken care of when reading in multiple sectors
  78. or when incrementing the disk address with the N command.  To simplify
  79. the disk allocation scheme the sectors are the collected into groups of
  80. 8 sectors forming a 1k block.  These blocks are numbered from 0 starting
  81. at the begining of the dirctory. (track 2 sector 1).  Block numbers range
  82. from 0 to F2.
  83.     The directory is organized to use 2 block of storage (16 sectors) to
  84. store information on 64 file extensions.  A file extension is a part of a
  85. file up to 16k bytes long.  The directory entry for a file extension is
  86. as follows:
  87.  
  88. byte  0   : file code : 0 if file exists, E5 if file is deleted
  89. byte  1- 8: file name : ascii representation of file name
  90. byte  9-11: file type : ascii representation of file type
  91. byte 12   : file ext  : binary number for extent number
  92. byte 13,14: unused
  93. byte 15   : rec count : count of number of sectors in extent
  94. byte 16-31: map       : list of block numbers used by this extent
  95.  
  96. */
  97. main(){
  98.     int track,sector,disk,nsect,t,s,i,j,k,block;
  99.     char buffer[1024],buff[80],*bufp,c,d,mc,dir[2048],map[256];
  100.     disk=0;
  101.     track=0;
  102.     sector=1;
  103.     nsect=1;
  104.     while(tolower(*(bufp=gets(buff))) != 'x' || *(bufp+1) != '\0'){
  105.         while((c=*bufp++) != '\0')
  106.         switch(toupper(c)){
  107.             case 'T' : track=getnum(&bufp,0,76,10);
  108.                 nsect=1;
  109.                 break;
  110.             case 'S' : sector=getnum(&bufp,1,26,10);
  111.                 nsect=1;
  112.                 break;
  113.             case 'D' : disk=getnum(&bufp,0,3,10);
  114.                 break;
  115.             case 'B' : block=getnum(&bufp,0,0xf2,16);
  116.                 nsect=8;
  117.                 track=2+block*8/26;
  118.                  s=block*8%26;
  119.                 sector=s*6%26+1;
  120.                 if(s>12)sector++;
  121.                 break;
  122.             case 'N' : for(i=0;i<nsect;i++){
  123.                     sector+=6;
  124.                     if(sector>26)sector-=26;
  125.                     if(sector==2){
  126.                         sector=1;
  127.                         track++;
  128.                     }
  129.                     else if(sector==1) sector=2;
  130.                 }
  131.                 break;
  132.             case 'I' : sector+=nsect;
  133.                 if(sector>26){
  134.                     sector-=26;
  135.                     track++;
  136.                 }
  137.                 break;
  138.             case 'R' : bios(9,disk);
  139.                 t=track;
  140.                 s=sector;
  141.                 for(i=0;i<nsect;i++){
  142.                     bios(10,t);
  143.                     bios(11,s);
  144.                     bios(12,&buffer[i*128]);
  145.                     bios(13);
  146.                     s+=6;
  147.                     if(s>26) s-=26;
  148.                     if(s==2){
  149.                         s=1;
  150.                         t++;
  151.                     }
  152.                     else if(s==1) s=2;
  153.                 }
  154.                 break;
  155.             case 'W' : bios(9,disk);
  156.                 t=track;
  157.                 s=sector;
  158.                 for(i=0;i<nsect;i++){
  159.                     bios(10,t);
  160.                     bios(11,s);
  161.                     bios(12,&buffer[i*128]);
  162.                     bios(14);
  163.                     s+=6;
  164.                     if(s>26) s-=26;
  165.                     if(s==2){
  166.                         s=1;
  167.                         t++;
  168.                     }
  169.                     else if(s==1) s=2;
  170.                 }
  171.                 break;
  172.             case 'P' : switch (sector%6){
  173.                     case 0: block=17+sector/6; break;
  174.                     case 1: block= 0+sector/6; break;
  175.                     case 2: block=13+sector/6; break;
  176.                     case 3: block= 9+sector/6; break;
  177.                     case 4: block=22+sector/6; break;
  178.                     case 5: block= 5+sector/6; break;
  179.                 }
  180.                 block=block+26*(track-2);
  181.                 printf("track %d  sector %d ",track,sector);
  182.                 printf(" block %x.%d ",block/8,block%8);
  183.                 for(i=0;i<128*nsect;i+=16){
  184.                     printf("\n %4x  ",i);
  185.                     for(j=0;j<16;j++){
  186.                         printf("%2x ",buffer[i+j]);
  187.                         if(j%4 == 3) printf(" ");
  188.                     }
  189.                     for(j=0;j<16;j++){
  190.                         c=buffer[i+j]&0x7f;
  191.                         c=c<' '||c==0x7f ? '.' : c;
  192.                         putchar(c);
  193.                     }
  194.                 if(kbhit()) break;
  195.                 }
  196.                 putchar('\n');
  197.                 break;
  198.             case 'E' : i=getnum(&bufp,0,nsect*128-1,16);
  199.                 while(*bufp==' '){
  200.                     buffer[i++]=getnum(&bufp,0,255,16);
  201.                     if(i>=nsect*128) break;
  202.                 }
  203.                 break;
  204.             case 'F' : i=getnum(&bufp,0,255,16);
  205.                 for(j=0;j<nsect*128;j++) buffer[j]=i;
  206.                 break;
  207.             case 'M' : bios(9,disk);
  208.                 bios(10,2);
  209.                 s=1;
  210.                 for(i=0;i<16;i++){
  211.                     bios(11,s);
  212.                     bios(12,&dir[i*128]);
  213.                     bios(13);
  214.                     s+=6;
  215.                     if(s>26)s-=26;
  216.                     if(s==1)s=2;
  217.                 }
  218.                 setmem(&map,256,0);
  219.                 for(i=0;i<64;i++){
  220.                     if(i%4==0) putchar('\n');
  221.                     j=32*i;
  222.                     c=(dir[j]==0) ? '=' : '*';
  223.                     d=dir[j+12];
  224.                     mc=mapchar(i);
  225.                     if(d==0xe5){
  226.                         printf("%c%19s",mc,"");
  227.                         continue;
  228.                     }
  229.                     dir[j+12]=0;
  230.                     printf("%c%c%s",mc,c,&dir[j+1]);
  231.                     if(d != 0) printf("/%x",d%0x10);
  232.                         else printf("  ");
  233.                     printf(" %2x  ",dir[j+15]);
  234.                     if(c=='*')mc+=128;
  235.                     for(k=16;k<32 && dir[j+k];k++){
  236.                         d=dir[j+k];
  237.                         if(mc<128) map[d]=mc;
  238.                     }
  239.                 }
  240.                 for(i=0;i<0xf3;i++){
  241.                     if(i%64==0) putchar('\n');
  242.                     else if(i%16==0) printf("  ");
  243.                     else if(i%8==0) printf(" ");
  244.                     putchar(map[i] ? map[i] : '.');
  245.                 }
  246.                 putchar('\n');
  247.                 break;
  248.             case ' ' : break;
  249.             default : printf("%c ??????\n",c);
  250.                 *bufp='\0';
  251.                 break;
  252.         }
  253.     if(kbhit()) getchar();
  254.     }
  255. }
  256. getnum(pntr,low,high,base)
  257. int low,high,base;
  258. char **pntr;
  259. {
  260.     int number;
  261.     char c,buffer[50],*bp;
  262.     number=0;
  263.     while( **pntr== ' ') (*pntr)++ ;
  264.     while( (c=toupper(*(*pntr)++))>='0' && c<= '9' ||
  265.         base==16 && (c-=7) > '9' && c <= ('F'-7) )
  266.             number=base*number+c-'0';
  267.     (*pntr)--;
  268.     if (number<low || number>high){
  269.         printf("bad number %d ",number);
  270.         bp=gets(buffer);
  271.         number=getnum(&bp,low,high,base);
  272.     }
  273.     return (number);
  274. }
  275. mapchar(i)
  276. char i;
  277. {    if(i<10) return(i+'0');
  278.     if(i<36) return(i-10+'a');
  279.     return(i-36+'A');
  280. }
  281. putchar(c)
  282. char c;
  283. {
  284.     putch(c);
  285. }
  286.