[comp.os.minix] ST MINIX -- fixes for TOS.C

hcj@lzaz.ATT.COM (HC Johnson) (09/11/89)

Here is a recapitulation of problems with the ST-minix tos.c.
When ST-Minix was first released this program showd up some of the dreary
limitations of the C-library.  Basicly, its got a 16 bit signed interface.
only a pointer got stretched to a long for the 68000.

Some of the more obvious bugs fixed.
1. fat size larger that 32K doesnt work.
  - fix requires adding lsbrk(long) and disk_iol(,,long)
2. the PC algorithm for computing data start allow it to vary by 1 from
   what TOS wants.
  - This causes missed reads, and corruption of other files when writing.
3. Sign extension problems writes totally wrong fats if fat number is > 0x7f.
   (only if hard disk, not a floppy problem).
  - This RUINS the file system.
This works for me.  I trust it will work for you.
 
p.s. The last time I posted this, it would print some garbage numbers when
it ran into problems.  Now it should be more well behaved.

Howard C. Johnson
ATT Bell Labs
att!lzaz!hcj
hcj@lzaz.att.com

======cut here=====
*** /usr/src/commands/tos.c	Thu Oct 29 18:34:28 1988
--- tos.c	Thu Nov 18 21:01:07 1988
***************
*** 22,29 ****
  #include <sys/stat.h>
  
  
- #undef	DEBUG
- 
  
  #define MAX_CLUSTER_SIZE	1024
  #define MAX_ROOT_ENTRIES	512
--- 22,27 ----
***************
*** 107,114 ****
  
  #define READ			0
  #define WRITE			1
! #define disk_read(s, a, b)	disk_io(READ, (s), (a), (b))
! #define disk_write(s, a, b)	disk_io(WRITE, (s), (a), (b))
  #define FIND	3
  #define LABEL	4
  #define ENTRY	5
--- 105,112 ----
  
  #define READ			0
  #define WRITE			1
! #define disk_read(s, a, b)	disk_io(READ, (s), (a), (short)(b))
! #define disk_write(s, a, b)	disk_io(WRITE, (s), (a), (short)(b))
  #define FIND	3
  #define LABEL	4
  #define ENTRY	5
***************
*** 118,124 ****
  #define new_entry(d, e)		directory(d, e, ENTRY, NIL_PTR)
  
  #define is_dir(d)		((d)->d_attribute & SUB_DIR)
! #define isHardDisk		(device[5] == 'h')
  #define EOF			0400
  #define EOF_MARK		'\032'
  #define STD_OUT			1
--- 116,122 ----
  #define new_entry(d, e)		directory(d, e, ENTRY, NIL_PTR)
  
  #define is_dir(d)		((d)->d_attribute & SUB_DIR)
! #define isHardDisk		((device[5] == 'h')||(device[6] == ':'))
  #define EOF			0400
  #define EOF_MARK		'\032'
  #define STD_OUT			1
***************
*** 135,143 ****
  long		mark;
  short		total_clusters,
  		cluster_size,
! 		fat_size,
!       		root_entries,
! 		sub_entries;
  long		max_cluster;
  long		data_start;
  
--- 133,141 ----
  long		mark;
  short		total_clusters,
  		cluster_size,
!       		root_entries,
! 		sub_entries;
! long		fat_size;
  long		max_cluster;
  long		data_start;
  
***************
*** 256,261 ****
--- 254,260 ----
  	print_string( TRUE, "hidden sectors: %L\n", (long)m_nhid );
  #endif	DEBUG
  }
+ char *lsbrk();
  
  main(argc, argv)
  int		argc;
***************
*** 336,348 ****
  	fat_size	= m_bps * m_spf;
  	data_start	= ((	(long)m_ndirs * (long)sizeof(DIRECTORY)
  				+ (long)fat_size * 2L
  			  	+ ((long)cluster_size - 1L)
  			   )	/(long)cluster_size
  			  )	*(long)cluster_size;
  	if( isHardDisk ){
  		data_start += m_bps;	/* some heuristic */
  	}
! 
  	max_cluster	= total_clusters - (data_start/cluster_size) - 2;
  
  	root_entries	= m_ndirs;	
--- 335,351 ----
  	fat_size	= m_bps * m_spf;
  	data_start	= ((	(long)m_ndirs * (long)sizeof(DIRECTORY)
  				+ (long)fat_size * 2L
+ 
+ #ifdef PCMINIX
  			  	+ ((long)cluster_size - 1L)
  			   )	/(long)cluster_size
  			  )	*(long)cluster_size;
  	if( isHardDisk ){
  		data_start += m_bps;	/* some heuristic */
  	}
! #else
! 			+ FAT_START));
! #endif
  	max_cluster	= total_clusters - (data_start/cluster_size) - 2;
  
  	root_entries	= m_ndirs;	
***************
*** 355,371 ****
  		);
  		exit(1);
  	}
! 	if( (fat= (unsigned char*)sbrk( fat_size )) <= (unsigned char*)0 ){
  		print_string(TRUE, "Can't set break!\n" );
  		exit(1);
  	}
! 	disk_read(FAT_START, fat, fat_size);
  
  #ifdef	DEBUG
  	print_string( TRUE, "total_clusters: %L\n", (long)total_clusters );
  	print_string( TRUE, "cluster_size: %L\n", (long)cluster_size );
  	print_string( TRUE, "fat_size: %L\n", (long)fat_size );
! 	print_string( TRUE, "data_start: %L\n", data_start );
  	print_string( TRUE, "root_entries: %L\n", (long)root_entries );
  	print_string( TRUE, "sub_entries: %L\n", (long)sub_entries );
  	print_string( TRUE, "fat type is %d\n", sh88tosh68( &fat[1] ) );
--- 358,375 ----
  		);
  		exit(1);
  	}
! 	if( (fat= (unsigned char*)lsbrk( fat_size )) <= (unsigned char*)0 ){
  		print_string(TRUE, "Can't set break!\n" );
  		exit(1);
  	}
! 	disk_iol(READ,FAT_START, fat, fat_size);
  
  #ifdef	DEBUG
  	print_string( TRUE, "total_clusters: %L\n", (long)total_clusters );
  	print_string( TRUE, "cluster_size: %L\n", (long)cluster_size );
  	print_string( TRUE, "fat_size: %L\n", (long)fat_size );
! 	print_string( TRUE, "data_start: %L bytes (%L blocks)\n",
! 	  data_start, data_start/512 );
  	print_string( TRUE, "root_entries: %L\n", (long)root_entries );
  	print_string( TRUE, "sub_entries: %L\n", (long)sub_entries );
  	print_string( TRUE, "fat type is %d\n", sh88tosh68( &fat[1] ) );
***************
*** 376,381 ****
--- 380,387 ----
  
  	if (fat_check != fat[0]) {
  		print_string(TRUE, "Disk type in FAT copy differs from disk type in FAT original.\n");
+ 		print_string(TRUE, "copy=%x is=%x fat_size=%L FAT_START=%L\n",
+ 			fat_check,fat[0],fat_size,FAT_START);
  		exit(1);
  	}
  
***************
*** 639,646 ****
  			output[index++] = '\r';
  			lf_pending = FALSE;
  		}
! 		if (write(fd, output, index) != index)
! 			bad();
  		index = 0;
  		return;
  	}
--- 645,655 ----
  			output[index++] = '\r';
  			lf_pending = FALSE;
  		}
! 		if (write(fd, output, index) != index) {
! 			print_string(TRUE,"Failed: write(%L,%L,%L)\n",
! 				fd,output,(long)index);
! 			bad();
! 		}
  		index = 0;
  		return;
  	}
***************
*** 889,895 ****
  		 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  		 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  };
! 
  modes(mode)
  register unsigned char mode;
  {
--- 898,919 ----
  		 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  		 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  };
! char *
! lsbrk(l)
! long l;
! {
! 	char *cp,*r;
! 	short sl;
! 
! 	cp = sbrk(0);
! 	while(l) {
! 		sl = l>0x7ff0L?0x7ff0:l;
! 		if((r=sbrk(sl)) <= (char*)0)
! 			return(r);
! 		l -= sl;
! 	}
! 	return(cp);	
! }
  modes(mode)
  register unsigned char mode;
  {
***************
*** 975,980 ****
--- 999,1008 ----
  	if (number == 0)
  		temp[i++] = '0';
  
+ 	if(number < 0L) {
+ 		temp[i++] = '-';
+ 		number = 0 - number;
+ 	}
  	while (number) {
  		temp[i++] = (char) (number % 10L + '0');
  		number /= 10L;
***************
*** 1099,1106 ****
  		}
  	}else{
  		fat_index= &fat[cl_1 * 2];
! 		*(fat_index+1) = (char)cl_2>>8;
! 		*fat_index = (char)cl_2;
  	}
  }
  
--- 1127,1134 ----
  		}
  	}else{
  		fat_index= &fat[cl_1 * 2];
! 		*(fat_index+1) = cl_2>>8;
! 		*fat_index = cl_2;
  	}
  }
  
***************
*** 1169,1174 ****
--- 1197,1217 ----
  		*dest++ = *src++;
  }
  
+ disk_iol(op, seek, address, bytes)
+ register BOOL op;
+ unsigned long seek;
+ unsigned long address;
+ register unsigned long bytes;
+ {
+ 	unsigned short shbytes;
+ 	while(bytes) {
+ 		shbytes = bytes > 0x7ff0L? 0x7ff0: bytes;
+ 		disk_io(op,seek,address,shbytes);
+ 		seek += shbytes;
+ 		address += shbytes;
+ 		bytes -= shbytes;
+ 	}
+ }
  disk_io(op, seek, address, bytes)
  register BOOL op;
  unsigned long seek;
***************
*** 1177,1182 ****
--- 1220,1231 ----
  {
  	unsigned int r;
  
+ #ifdef DEBUG
+ print_string(TRUE,"%s: seek=%L block=%d size=%d\n",
+  (op==READ?"READ":"WRITE"),
+  seek,(int)(seek>>9),(int)(bytes>>9));
+ #endif
+ 
  	if (lseek(disk,(long) seek, 0) < 0L) {
  		flush();
  		print_string(TRUE, "Bad lseek\n");
***************
*** 1189,1194 ****
--- 1238,1245 ----
  		r = write(disk, address, bytes);
  	}
  	if (r != bytes){
+ 		print_string(TRUE,"Failed r/w (%L,%L, %L)\n",
+ 			disk,address,(long)bytes);
  		bad();
  	}
  }