Exemple #1
0
static int dos33_allocate_sector(int fd) {

	int found_track=0,found_sector=0;
	unsigned char bitmap[4];
	int i,start_track,track_dir,byte;
	int result;

	dos33_read_vtoc(fd);

	/* Originally used to keep things near center of disk for speed */
	/* We can use to avoid fragmentation possibly */
	start_track=sector_buffer[VTOC_LAST_ALLOC_T]%TRACKS_PER_DISK;
	track_dir=sector_buffer[VTOC_ALLOC_DIRECT];

	if (track_dir==255) track_dir=-1;

	if ((track_dir!=1) && (track_dir!=-1)) {
		fprintf(stderr,"ERROR!  Invalid track dir %i\n",track_dir);
	}

	if (((start_track>VTOC_TRACK) && (track_dir!=1)) ||
		((start_track<VTOC_TRACK) && (track_dir!=-1))) {
		fprintf(stderr,"Warning! Non-optimal values for track dir t=%i d=%i!\n",
			start_track,track_dir);
	}

	i=start_track;

	do {
		for(byte=1;byte>-1;byte--) {
			bitmap[byte]=sector_buffer[VTOC_FREE_BITMAPS+(i*4)+byte];
			if (bitmap[byte]!=0x00) {
				found_sector=find_first_one(bitmap[byte]);
				found_track=i;
				/* clear bit indicating in use */
				sector_buffer[VTOC_FREE_BITMAPS+(i*4)+byte]&=~(0x1<<found_sector);
				found_sector+=(8*(1-byte));
				goto found_one;
			}
		}

		/* Move to next track, handling overflows */
		i+=track_dir;
		if (i<0) {
			i=VTOC_TRACK;
			track_dir=1;
		}

		if (i>=TRACKS_PER_DISK) {
			i=VTOC_TRACK;
			track_dir=-1;
		}
	} while (i!=start_track);

	fprintf(stderr,"No room left!\n");
	return -1;

found_one:
	/* store new track/direction info */
	sector_buffer[VTOC_LAST_ALLOC_T]=found_track;

	if (found_track>VTOC_TRACK) sector_buffer[VTOC_ALLOC_DIRECT]=1;
	else sector_buffer[VTOC_ALLOC_DIRECT]=-1;

	/* Seek to VTOC */
	lseek(fd,DISK_OFFSET(VTOC_TRACK,VTOC_SECTOR),SEEK_SET);

	/* Write out VTOC */
	result=write(fd,&sector_buffer,BYTES_PER_SECTOR);

	if (result<0) fprintf(stderr,"Error on I/O\n");

	return ((found_track<<8)+found_sector);
}
Exemple #2
0
	/* returns ?? */
static int dos33_add_file(int fd, char dos_type,
		int file_type, int address, int length,
		char *filename, char *apple_filename) {

	int free_space,file_size,needed_sectors;
	struct stat file_info;
	int size_in_sectors=0;
	int initial_ts_list=0,ts_list=0,i,data_ts,x,bytes_read=0,old_ts_list;
	int catalog_track,catalog_sector,sectors_used=0;
	int input_fd;
	int result;
	int first_write=1;

	if (apple_filename[0]<64) {
		fprintf(stderr,"Error!  First char of filename "
				"must be ASCII 64 or above!\n");
		return ERROR_INVALID_FILENAME;
	}

	/* Check for comma in filename */
	for(i=0;i<strlen(apple_filename);i++) {
		if (apple_filename[i]==',') {
			fprintf(stderr,"Error!  "
				"Cannot have , in a filename!\n");
			return ERROR_INVALID_FILENAME;
		}
	}

	/* FIXME */
	/* check type */
	/* and sanity check a/b filesize is set properly */

	/* Determine size of file to upload */
	if (stat(filename,&file_info)<0) {
		fprintf(stderr,"Error!  %s not found!\n",filename);
		return ERROR_FILE_NOT_FOUND;
	}

	file_size=(int)file_info.st_size;

	if (debug) printf("Filesize: %d\n",file_size);

	if (file_type==ADD_BINARY) {
		if (debug) printf("Adding 4 bytes for size/offset\n");
		if (length==0) length=file_size;
		file_size+=4;
	}

	/* We need to round up to nearest sector size */
	/* Add an extra sector for the T/S list */
	/* Then add extra sector for a T/S list every 122*256 bytes (~31k) */
	needed_sectors=(file_size/BYTES_PER_SECTOR)+ /* round sectors */
			((file_size%BYTES_PER_SECTOR)!=0)+/* tail if needed */
			1+/* first T/S list */
			(file_size/(122*BYTES_PER_SECTOR)); /* extra t/s lists */

	/* Get free space on device */
	free_space=dos33_free_space(fd);

	/* Check for free space */
	if (needed_sectors*BYTES_PER_SECTOR>free_space) {
		fprintf(stderr,"Error!  Not enough free space "
				"on disk image (need %d have %d)\n",
				needed_sectors*BYTES_PER_SECTOR,free_space);
		return ERROR_NO_SPACE;
	}

	/* plus one because we need a sector for the tail */
	size_in_sectors=(file_size/BYTES_PER_SECTOR)+
		((file_size%BYTES_PER_SECTOR)!=0);
	if (debug) printf("Need to allocate %i data sectors\n",size_in_sectors);
	if (debug) printf("Need to allocate %i total sectors\n",needed_sectors);

	/* Open the local file */
	input_fd=open(filename,O_RDONLY);
	if (input_fd<0) {
		fprintf(stderr,"Error! could not open %s\n",filename);
		return ERROR_IMAGE_NOT_FOUND;
	}

	i=0;
	while (i<size_in_sectors) {

		/* Create new T/S list if necessary */
		if (i%TSL_MAX_NUMBER==0) {
			old_ts_list=ts_list;

			/* allocate a sector for the new list */
			ts_list=dos33_allocate_sector(fd);
			sectors_used++;
			if (ts_list<0) return -1;

			/* clear the t/s sector */
			for(x=0;x<BYTES_PER_SECTOR;x++) {
				sector_buffer[x]=0;
			}
			lseek(fd,DISK_OFFSET((ts_list>>8)&0xff,ts_list&0xff),SEEK_SET);
			result=write(fd,sector_buffer,BYTES_PER_SECTOR);

			if (i==0) {
				initial_ts_list=ts_list;
			}
			else {
				/* we aren't the first t/s list so do special stuff */

				/* load in the old t/s list */
				lseek(fd,
					DISK_OFFSET(get_high_byte(old_ts_list),
					get_low_byte(old_ts_list)),
					SEEK_SET);

				result=read(fd,&sector_buffer,BYTES_PER_SECTOR);

				/* point from old ts list to new one we just made */
				sector_buffer[TSL_NEXT_TRACK]=get_high_byte(ts_list);
				sector_buffer[TSL_NEXT_SECTOR]=get_low_byte(ts_list);

				/* set offset into file */
				sector_buffer[TSL_OFFSET_H]=get_high_byte((i-122)*256);
				sector_buffer[TSL_OFFSET_L]=get_low_byte((i-122)*256);

				/* write out the old t/s list with updated info */
				lseek(fd,
					DISK_OFFSET(get_high_byte(old_ts_list),
					get_low_byte(old_ts_list)),
					SEEK_SET);

				result=write(fd,sector_buffer,BYTES_PER_SECTOR);
			}
		}

		/* allocate a sector */
		data_ts=dos33_allocate_sector(fd);
		sectors_used++;

		if (data_ts<0) return -1;

		/* clear sector */
		for(x=0;x<BYTES_PER_SECTOR;x++) sector_buffer[x]=0;

		/* read from input */
		if ((first_write) && (file_type==ADD_BINARY)) {
			first_write=0;
			sector_buffer[0]=address&0xff;
			sector_buffer[1]=(address>>8)&0xff;
			sector_buffer[2]=(length)&0xff;
			sector_buffer[3]=((length)>>8)&0xff;
			bytes_read=read(input_fd,sector_buffer+4,
					BYTES_PER_SECTOR-4);
			bytes_read+=4;
		}
Exemple #3
0
	/* returns entry/track/sector  */
static int dos33_check_file_exists(int fd,
					char *filename,
					int file_deleted) {

	int catalog_track,catalog_sector;
	int i,file_track;
	char file_name[31];
	int result;

	/* read the VTOC into buffer */
	dos33_read_vtoc(fd);

	/* get the catalog track and sector from the VTOC */
	catalog_track=sector_buffer[VTOC_CATALOG_T];
	catalog_sector=sector_buffer[VTOC_CATALOG_S];

repeat_catalog:

	/* Read in Catalog Sector */
	lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET);
	result=read(fd,sector_buffer,BYTES_PER_SECTOR);

	/* scan all file entries in catalog sector */
	for(i=0;i<7;i++) {
		file_track=sector_buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)];
		/* 0xff means file deleted */
		/* 0x0 means empty */
		if (file_track!=0x0) {

			if (file_track==0xff) {
				dos33_filename_to_ascii(file_name,
					sector_buffer+(CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE+FILE_NAME)),29);

				if (file_deleted) {
					/* return if we found the file */
					if (!strncmp(filename,file_name,29)) {
						return ((i<<16)+(catalog_track<<8)+catalog_sector);
					}
				}
			}
			else {
				dos33_filename_to_ascii(file_name,
					sector_buffer+(CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE+FILE_NAME)),30);
				/* return if we found the file */
				if (!strncmp(filename,file_name,30)) {
					return ((i<<16)+(catalog_track<<8)+catalog_sector);
				}
			}
		}
	}

	/* point to next catalog track/sector */
	catalog_track=sector_buffer[CATALOG_NEXT_T];
	catalog_sector=sector_buffer[CATALOG_NEXT_S];

	if (catalog_sector!=0) goto repeat_catalog;

	if (result<0) fprintf(stderr,"Error on I/O\n");

	return -1;
}
Exemple #4
0
static int dos33_dump(int fd) {
   
    int num_tracks,catalog_t,catalog_s,file,ts_t,ts_s,ts_total,track,sector;
    int i,j;
    int deleted=0;
    char temp_string[BUFSIZ];
    unsigned char tslist[BYTES_PER_SECTOR];
    int result;
   
    /* Read Track 1 Sector 9 */
    lseek(fd,DISK_OFFSET(1,9),SEEK_SET);
    result=read(fd,sector_buffer,BYTES_PER_SECTOR);

    printf("Finding name of startup file, Track 1 Sector 9 offset $75\n");
    dump_sector();
    printf("Startup Filename: ");
    for(i=0;i<30;i++) printf("%c",sector_buffer[0x75+i]&0x7f);						
    printf("\n");
   
    dos33_read_vtoc(fd);
    
    printf("\nVTOC Sector:\n");
    dump_sector();
   
    printf("\n\n");
    printf("VTOC INFORMATION:\n");
    catalog_t=sector_buffer[VTOC_CATALOG_T];
    catalog_s=sector_buffer[VTOC_CATALOG_S];
    printf("\tFirst Catalog = %02X/%02X\n",catalog_t,catalog_s);
    printf("\tDOS RELEASE = 3.%i\n",sector_buffer[VTOC_DOS_RELEASE]);
    printf("\tDISK VOLUME = %i\n",sector_buffer[VTOC_DISK_VOLUME]);
    ts_total=sector_buffer[VTOC_MAX_TS_PAIRS];
    printf("\tT/S pairs that will fit in T/S List = %i\n",ts_total);
	                          
    printf("\tLast track where sectors were allocated = $%02X\n",
	                          sector_buffer[VTOC_LAST_ALLOC_T]);
    printf("\tDirection of track allocation = %i\n",
	                          sector_buffer[VTOC_ALLOC_DIRECT]);
   
    num_tracks=sector_buffer[VTOC_NUM_TRACKS];
    printf("\tNumber of tracks per disk = %i\n",num_tracks);
    printf("\tNumber of sectors per track = %i\n",
	                          sector_buffer[VTOC_S_PER_TRACK]);
    printf("\tNumber of bytes per sector = %i\n",
	        (sector_buffer[VTOC_BYTES_PER_SH]<<8)+sector_buffer[VTOC_BYTES_PER_SL]);
    
    printf("\nFree sector bitmap:\n");
    printf("\tTrack  FEDCBA98 76543210\n");
    for(i=0;i<num_tracks;i++) {
       printf("\t $%02X:  ",i);
       for(j=0;j<8;j++) { 
	  if ((sector_buffer[VTOC_FREE_BITMAPS+(i*4)]<<j)&0x80) printf("."); 
          else printf("U");
       }
       printf(" ");
       for(j=0;j<8;j++) { 
	  if ((sector_buffer[VTOC_FREE_BITMAPS+(i*4)+1]<<j)&0x80) printf("."); 
          else printf("U");
       }
       
       printf("\n");
    }

repeat_catalog:
   
    printf("\nCatalog Sector $%02X/$%02x\n",catalog_t,catalog_s);
    lseek(fd,DISK_OFFSET(catalog_t,catalog_s),SEEK_SET);
    result=read(fd,sector_buffer,BYTES_PER_SECTOR);

    dump_sector();
   
    for(file=0;file<7;file++) {
       printf("\n\n");	

       ts_t=sector_buffer[(CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE+FILE_TS_LIST_T))];
       ts_s=sector_buffer[(CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE+FILE_TS_LIST_S))];

       printf("%i+$%02X/$%02X - ",file,catalog_t,catalog_s);
       deleted=0;
       
       if (ts_t==0xff) {
          printf("**DELETED** ");
          deleted=1;
	  ts_t=sector_buffer[(CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE+FILE_NAME+0x1e))];
       }
   
       if (ts_t==0x00) {
          printf("UNUSED!\n");
          goto continue_dump;
       }
   
       strncpy(temp_string,dos33_filename_to_ascii(temp_string,
		sector_buffer+(CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE+FILE_NAME)),30),
	       BUFSIZ);

       for(i=0;i<strlen(temp_string);i++) {
          if (temp_string[i]<0x20) printf("^%c",temp_string[i]+0x40);
          else printf("%c",temp_string[i]);
       }
       printf("\n");
       printf("\tLocked = %s\n",
	    sector_buffer[CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE)+FILE_TYPE]>0x7f?
	   "YES":"NO");
       printf("\tType = %c\n", 
           dos33_file_type(sector_buffer[CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE)+FILE_TYPE]));
       printf("\tSize in sectors = %i\n",
                   sector_buffer[CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE+FILE_SIZE_L)]+
	          (sector_buffer[CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE+FILE_SIZE_H)]<<8));
repeat_tsl:
       printf("\tT/S List $%02X/$%02X:\n",ts_t,ts_s);
       if (deleted) goto continue_dump;
       lseek(fd,DISK_OFFSET(ts_t,ts_s),SEEK_SET);
       result=read(fd,&tslist,BYTES_PER_SECTOR);

       for(i=0;i<ts_total;i++) {
          track=tslist[TSL_LIST+(i*TSL_ENTRY_SIZE)];
          sector=tslist[TSL_LIST+(i*TSL_ENTRY_SIZE)+1];
          if ((track==0) && (sector==0)) printf(".");
          else printf("\n\t\t%02X/%02X",track,sector);
       }
       ts_t=tslist[TSL_NEXT_TRACK];
       ts_s=tslist[TSL_NEXT_SECTOR];
   
       if (!((ts_s==0) && (ts_t==0))) goto repeat_tsl;
continue_dump:;
    }
    
    catalog_t=sector_buffer[CATALOG_NEXT_T];
    catalog_s=sector_buffer[CATALOG_NEXT_S];
   
    if (catalog_s!=0) {
       file=0;
       goto repeat_catalog;
    }
      
    printf("\n");

    if (result<0) fprintf(stderr,"Error on I/O\n");
   
    return 0;
}
Exemple #5
0
static int dos33_delete_file(int fd,int fsl) {
   
    int i;
    int catalog_track,catalog_sector,catalog_entry;
    int ts_track,ts_sector;
    char file_type;
    int result;

       /* unpack file/track/sector info */
    catalog_entry=fsl>>16;
    catalog_track=(fsl>>8)&0xff;
    catalog_sector=(fsl&0xff);

       /* Load in the catalog table for the file */
    lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET);
    result=read(fd,sector_buffer,BYTES_PER_SECTOR);

    file_type=sector_buffer[CATALOG_FILE_LIST+
			    (catalog_entry*CATALOG_ENTRY_SIZE)
                                            +FILE_TYPE];
    if (file_type&0x80) {
       fprintf(stderr,"File is locked!  Unlock before deleting!\n");
       exit(1);
    }
   
   
       /* get pointer to t/s list */
    ts_track=sector_buffer[CATALOG_FILE_LIST+catalog_entry*CATALOG_ENTRY_SIZE+
		    FILE_TS_LIST_T];
    ts_sector=sector_buffer[CATALOG_FILE_LIST+catalog_entry*CATALOG_ENTRY_SIZE+
		     FILE_TS_LIST_S];
   
keep_deleting:
   

   
       /* load in the t/s list info */
    lseek(fd,DISK_OFFSET(ts_track,ts_sector),SEEK_SET);
    result=read(fd,sector_buffer,BYTES_PER_SECTOR);
      
      /* Free each sector listed by t/s list */
    for(i=0;i<TSL_MAX_NUMBER;i++) {
          /* If t/s = 0/0 then no need to clear */
       if ((sector_buffer[TSL_LIST+2*i]==0) && (sector_buffer[TSL_LIST+2*i+1]==0)) {
       }
       else {
          dos33_free_sector(fd,sector_buffer[TSL_LIST+2*i],sector_buffer[TSL_LIST+2*i+1]);
       }
    }

          /* free the t/s list */
    dos33_free_sector(fd,ts_track,ts_sector);
   
       /* Point to next t/s list */
    ts_track=sector_buffer[TSL_NEXT_TRACK];
    ts_sector=sector_buffer[TSL_NEXT_SECTOR];
   
       /* If more tsl lists, keep looping */
    if ((ts_track==0x0) && (ts_sector==0x0)) {
    }
    else {
       goto keep_deleting;        
    }
   
       /* Erase file from catalog entry */
   
       /* First reload proper catalog sector */
   lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET);
   result=read(fd,sector_buffer,BYTES_PER_SECTOR);
      
      /* save track as last char of name, for undelete purposes */
   sector_buffer[CATALOG_FILE_LIST+(catalog_entry*CATALOG_ENTRY_SIZE)+
	  (FILE_NAME+FILE_NAME_SIZE-1)]=
     sector_buffer[CATALOG_FILE_LIST+(catalog_entry*CATALOG_ENTRY_SIZE)];
   
       /* Actually delete the file */
       /* by setting the track value to FF which indicates deleted file */
   sector_buffer[CATALOG_FILE_LIST+(catalog_entry*CATALOG_ENTRY_SIZE)]=0xff;
   
       /* re seek to catalog position and write out changes */
   lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET);
   result=write(fd,sector_buffer,BYTES_PER_SECTOR);

    if (result<0) fprintf(stderr,"Error on I/O\n");
   
   return 0;
}
Exemple #6
0
    /* load a file.  fts=entry/track/sector */
static int dos33_load_file(int fd,int fts,char *filename) {
 
    int output_fd;
    int catalog_file,catalog_track,catalog_sector;
    int file_type,file_size=-1,tsl_track,tsl_sector,data_t,data_s;
    unsigned char data_sector[BYTES_PER_SECTOR];
    int tsl_pointer=0,output_pointer=0;
    int result;
   
    /* Fix me!  Warn if overwriting file! */
    output_fd=open(filename,O_WRONLY|O_CREAT|O_TRUNC,0666);
    if (output_fd<0) {
       fprintf(stderr,"Error! could not open %s for local save\n",filename);
       return -1;
    }

    catalog_file=fts>>16;
    catalog_track=(fts>>8)&0xff;
    catalog_sector=(fts&0xff);


       /* Read in Catalog Sector */
    lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET);
    result=read(fd,sector_buffer,BYTES_PER_SECTOR);
   
    tsl_track=sector_buffer[CATALOG_FILE_LIST+
			    (catalog_file*CATALOG_ENTRY_SIZE)+FILE_TS_LIST_T];
    tsl_sector=sector_buffer[CATALOG_FILE_LIST+
			     (catalog_file*CATALOG_ENTRY_SIZE)+FILE_TS_LIST_S];
    file_type=dos33_file_type(sector_buffer[CATALOG_FILE_LIST+
					    (catalog_file*CATALOG_ENTRY_SIZE)
                                            +FILE_TYPE]);
   
//    printf("file_type: %c\n",file_type);

keep_saving:
       /* Read in TSL Sector */
    lseek(fd,DISK_OFFSET(tsl_track,tsl_sector),SEEK_SET);
    result=read(fd,sector_buffer,BYTES_PER_SECTOR);
    tsl_pointer=0;
   
       /* check each track/sector pair in the list */       
    while(tsl_pointer<TSL_MAX_NUMBER) {
    
       /* get the t/s value */
       data_t=sector_buffer[TSL_LIST+(tsl_pointer*TSL_ENTRY_SIZE)];
       data_s=sector_buffer[TSL_LIST+(tsl_pointer*TSL_ENTRY_SIZE)+1];
       
       if ((data_s==0) && (data_t==0)) {
	  /* empty */
       }
       else {
          lseek(fd,DISK_OFFSET(data_t,data_s),SEEK_SET);
          result=read(fd,&data_sector,BYTES_PER_SECTOR);

	     /* some file formats have the size in the first sector */
	     /* so cheat and get real file size from file itself    */
	  if (output_pointer==0) {
	     switch(file_type) {  
	        case 'A':
	        case 'I':
	           file_size=data_sector[0]+(data_sector[1]<<8)+2;
		   break;
	        case 'B':
		   file_size=data_sector[2]+(data_sector[3]<<8)+4;
		   break;
	        default:
	           file_size=-1;
	     }
	  }

	  /* write the block read in out to the output file */
          lseek(output_fd,output_pointer*BYTES_PER_SECTOR,SEEK_SET);
          result=write(output_fd,&data_sector,BYTES_PER_SECTOR);
       }
       output_pointer++;
       tsl_pointer++;
    }
   
      /* finished with TSL sector, see if we have another */
    tsl_track=sector_buffer[TSL_NEXT_TRACK];
    tsl_sector=sector_buffer[TSL_NEXT_SECTOR];

//    printf("Next track/sector=%d/%d op=%d\n",tsl_track,tsl_sector,
//	   output_pointer*BYTES_PER_SECTOR);
   
    if ((tsl_track==0) && (tsl_sector==0)) {
    }
    else goto keep_saving;
   
       /* Correct the file size */
    if (file_size>=0) {    
//       printf("Truncating file size to %d\n",file_size);
       result=ftruncate(output_fd,file_size);
    }

    if (result<0) fprintf(stderr,"Error on I/O\n");
   
    return 0;
   
}
Exemple #7
0
   /* returns ?? */
static int dos33_add_file(int fd,char type,char *filename,
			  char *apple_filename) {
   
    int free_space,file_size,needed_sectors;
    struct stat file_info;
    int size_in_sectors=0;
    int initial_ts_list=0,ts_list=0,i,data_ts,x,bytes_read=0,old_ts_list;
    int catalog_track,catalog_sector,sectors_used=0;
    int input_fd;
    int result;

    if (apple_filename[0]<64) {
       fprintf(stderr,"Error!  First char of filename must be ASCII 64 or above!\n");
       exit(3);
    }
    {
       int i;
       
       for(i=0;i<strlen(apple_filename);i++) {
	  if (apple_filename[i]==',') {
	     fprintf(stderr,"Error!  Cannot have , in a filename!\n");
	     exit(3);
	  }
       }
    }
   
   /* FIXME */
   /* check type */
   /* and sanity check a/b filesize is set properly */
   
   
       /* Determine size of file to upload */
    if (stat(filename,&file_info)<0) {
       fprintf(stderr,"Error!  %s not found!\n",filename);
       exit(3);
    }
    file_size=(int)file_info.st_size;
   
       /* We need to round up to nearest sector size */
       /* Add an extra sector for the T/S list */
       /* Then add extra sector for a T/S list every 122*256 bytes (~31k) */   
    needed_sectors=(file_size/BYTES_PER_SECTOR)+ /* round sectors */
                   ((file_size%BYTES_PER_SECTOR)!=0)+/* tail if needed */
                   1+/* first T/S list */
                   (file_size/(122*BYTES_PER_SECTOR)); /* extra t/s lists */
   
       /* Get free space on device */
    free_space=dos33_free_space(fd);

       /* Check for free space */
    if (needed_sectors*BYTES_PER_SECTOR>free_space) {
       fprintf(stderr,"Error!  Not enough free space on disk image (need %d have %d)\n",
	      needed_sectors*BYTES_PER_SECTOR,free_space);
       exit(4);
    }

       /* plus one because we need a sector for the tail */
    size_in_sectors=(file_size/BYTES_PER_SECTOR)+
     ((file_size%BYTES_PER_SECTOR)!=0);
//    printf("Need to allocate %i data sectors\n",size_in_sectors);
//    printf("Need to allocate %i total sectors\n",needed_sectors);
   
        /* Open the local file */
    input_fd=open(filename,O_RDONLY);
    if (input_fd<0) {
       fprintf(stderr,"Error! could not open %s\n",filename);
       return -1;
    }

    i=0;
    while (i<size_in_sectors) {
       
          /* Create new T/S list if necessary */
       if (i%TSL_MAX_NUMBER==0) {	  
	  old_ts_list=ts_list;

	     /* allocate a sector for the new list */
	  ts_list=dos33_allocate_sector(fd);
	  sectors_used++;
          if (ts_list<0) return -1;
	  
	     /* clear the t/s sector */
	  for(x=0;x<BYTES_PER_SECTOR;x++) sector_buffer[x]=0;
	  lseek(fd,DISK_OFFSET((ts_list>>8)&0xff,ts_list&0xff),SEEK_SET);
	  result=write(fd,sector_buffer,BYTES_PER_SECTOR);
	  
	  if (i==0) initial_ts_list=ts_list;
	  else {
	        /* we aren't the first t/s list so do special stuff */

	        /* load in the old t/s list */
             lseek(fd,
                   DISK_OFFSET(get_high_byte(old_ts_list),
                               get_low_byte(old_ts_list)),
                   SEEK_SET);

             result=read(fd,&sector_buffer,BYTES_PER_SECTOR);
	     
	        /* point from old ts list to new one we just made */
	     sector_buffer[TSL_NEXT_TRACK]=get_high_byte(ts_list);
	     sector_buffer[TSL_NEXT_SECTOR]=get_low_byte(ts_list);
	     
	        /* set offset into file */
	     sector_buffer[TSL_OFFSET_H]=get_high_byte((i-122)*256);
	     sector_buffer[TSL_OFFSET_L]=get_low_byte((i-122)*256);
	        
	        /* write out the old t/s list with updated info */
	     lseek(fd,
                   DISK_OFFSET(get_high_byte(old_ts_list),
                               get_low_byte(old_ts_list)),
                   SEEK_SET);

	     result=write(fd,sector_buffer,BYTES_PER_SECTOR);
	  }
       }       
       
       
          /* allocate a sector */
       data_ts=dos33_allocate_sector(fd);
       sectors_used++;
       
       if (data_ts<0) return -1;
       
          /* clear sector */
       for(x=0;x<BYTES_PER_SECTOR;x++) sector_buffer[x]=0;

          /* read from input */
       bytes_read=read(input_fd,sector_buffer,BYTES_PER_SECTOR);
       if (bytes_read<0) fprintf(stderr,"Error reading bytes!\n");

          /* write to disk image */
       lseek(fd,DISK_OFFSET((data_ts>>8)&0xff,data_ts&0xff),SEEK_SET);
       result=write(fd,sector_buffer,BYTES_PER_SECTOR);
//       printf("Writing %i bytes to %i/%i\n",bytes_read,(data_ts>>8)&0xff,
//	       data_ts&0xff);
       

       
          /* add to T/s table */
       
          /* read in t/s list */
       lseek(fd,DISK_OFFSET((ts_list>>8)&0xff,ts_list&0xff),SEEK_SET);
       result=read(fd,sector_buffer,BYTES_PER_SECTOR);
       
          /* point to new data sector */
       sector_buffer[((i%TSL_MAX_NUMBER)*2)+TSL_LIST]=(data_ts>>8)&0xff;
       sector_buffer[((i%TSL_MAX_NUMBER)*2)+TSL_LIST+1]=(data_ts&0xff);
       
          /* write t/s list back out */
       lseek(fd,DISK_OFFSET((ts_list>>8)&0xff,ts_list&0xff),SEEK_SET);
       result=write(fd,sector_buffer,BYTES_PER_SECTOR);	  
       
       i++;   
    }