From 87f7fc15f5c498d34e2410e08ff627d9a45f5fdc Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Thu, 9 Jun 2022 16:46:17 -0400 Subject: [PATCH] dos33: fix some issues when copying files off disk image ran across this when trying to debug a different issue by default we can only get total sector size from the T/S lists (which is only a multiple of 256 bytes) but in addition A (basic) and B (binary) files also tell you the exact length. So we used that to truncate to the exact length Only it turns out some programs (I'm looking at you, cracked version of WAVY NAVY) intentionally set the file size to be wrong and so we were truncating things improperly I think this updated code is a bit more clear. Hopefully it doesn't break anything, I need a better test suite. --- utils/dos33fs-utils/dos33.c | 53 +++++++++++++++++++++++++------- utils/dos33fs-utils/dos33.h | 1 + utils/dos33fs-utils/dos33_dump.c | 50 +++++++++++++++++++++++++----- 3 files changed, 86 insertions(+), 18 deletions(-) diff --git a/utils/dos33fs-utils/dos33.c b/utils/dos33fs-utils/dos33.c index e9c00dbc..6e1fe5d5 100644 --- a/utils/dos33fs-utils/dos33.c +++ b/utils/dos33fs-utils/dos33.c @@ -455,13 +455,14 @@ static int dos33_load_file(int fd,int fts,char *filename) { unsigned char sector_buffer[BYTES_PER_SECTOR]; int tsl_pointer=0,output_pointer=0; int result; + int total_sectors=0,last_output_pointer=0; /* FIXME! 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; + return -ERROR_CANNOT_OPEN; } catalog_file=fts>>16; @@ -480,7 +481,8 @@ static int dos33_load_file(int fd,int fts,char *filename) { file_type=dos33_file_type(sector_buffer[CATALOG_FILE_LIST+ (catalog_file*CATALOG_ENTRY_SIZE)+FILE_TYPE]); -// printf("file_type: %c\n",file_type); + if (debug) printf("Using TSL at %02X:%02X\n",tsl_track,tsl_sector); + if (debug) printf("file_type: %c\n",file_type); keep_saving: /* Read in TSL Sector */ @@ -497,6 +499,8 @@ keep_saving: if ((data_s==0) && (data_t==0)) { /* empty */ + /* this is complicated, can be a "hole" if in middle */ + /* or else ignored if at the end */ } else { lseek(fd,DISK_OFFSET(data_t,data_s),SEEK_SET); @@ -508,39 +512,65 @@ keep_saving: switch(file_type) { case 'A': case 'I': - file_size=data_sector[0]+(data_sector[1]<<8)+2; + file_size=data_sector[0]+ + (data_sector[1]<<8)+2; break; case 'B': - file_size=data_sector[2]+(data_sector[3]<<8)+4; + file_size=data_sector[2]+ + (data_sector[3]<<8)+4; break; default: file_size=-1; } + if (debug) printf("File size = %d\n",file_size); } /* 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); + last_output_pointer=output_pointer+1; } output_pointer++; tsl_pointer++; } + total_sectors=last_output_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; + else { + if (debug) printf("Next track/sector=%02X:%02X op=%d\n", + tsl_track,tsl_sector, + output_pointer*BYTES_PER_SECTOR); + goto keep_saving; + } /* Correct the file size */ + /* Note: this can cause issues if the original disk image */ + /* was doing something extra-clever and intentionally */ + /* had a mis-matched file size */ if (file_size>=0) { -// printf("Truncating file size to %d\n",file_size); - result=ftruncate(output_fd,file_size); + + if (debug) printf("Total size %d sectors (%d bytes)\n", + total_sectors,total_sectors*BYTES_PER_SECTOR); + + /* Tricky, 0...255 will give sectors of 0 */ + /* 256...511 will give sectors of 1 */ + if (((file_size-1)/256)!=total_sectors-1) { + printf("Warning! Total size %d not within " + "256 bytes of sector total (%d %d)!\n", + file_size,file_size/256,total_sectors); + printf("This could mean your program is trying " + "to be clever. Not truncating.\n"); + } + else { + printf("Auto-truncating file size to %d\n",file_size); + result=ftruncate(output_fd,file_size); + } } if (result<0) fprintf(stderr,"Error on I/O\n"); @@ -828,8 +858,9 @@ static void display_help(char *name, int version_only) { if (version_only) return; - printf("Usage: %s [-h] [-y] [-x] disk_image COMMAND [options]\n",name); + printf("Usage: %s [-h] [-d] [-y] [-x] disk_image COMMAND [options]\n",name); printf("\t-h : this help message\n"); + printf("\t-d : enable debugging\n"); printf("\t-y : always answer yes for anying warning questions\n"); printf("\t-x : ignore errors (useful for making invalid filenames)\n"); printf("\n"); diff --git a/utils/dos33fs-utils/dos33.h b/utils/dos33fs-utils/dos33.h index 9594ceff..317b3953 100644 --- a/utils/dos33fs-utils/dos33.h +++ b/utils/dos33fs-utils/dos33.h @@ -63,6 +63,7 @@ #define ERROR_NO_SPACE 3 #define ERROR_IMAGE_NOT_FOUND 4 #define ERROR_CATALOG_FULL 5 +#define ERROR_CANNOT_OPEN 6 /* dos33_vtoc_bitmap.c */ int dos33_vtoc_free_space(unsigned char *vtoc); diff --git a/utils/dos33fs-utils/dos33_dump.c b/utils/dos33fs-utils/dos33_dump.c index 084182ed..da03f454 100644 --- a/utils/dos33fs-utils/dos33_dump.c +++ b/utils/dos33fs-utils/dos33_dump.c @@ -59,7 +59,7 @@ static void dump_vtoc(unsigned char *vtoc) { int dos33_dump(unsigned char *vtoc, int fd) { int num_tracks,catalog_t,catalog_s,file,ts_t,ts_s,ts_total; - int track,sector; + int track,sector,type; int i; int deleted=0; char temp_string[BUFSIZ]; @@ -67,6 +67,7 @@ int dos33_dump(unsigned char *vtoc, int fd) { unsigned char catalog_buffer[BYTES_PER_SECTOR]; unsigned char data[BYTES_PER_SECTOR]; int result; + int size_already=0; /* Read Track 1 Sector 9 */ lseek(fd,DISK_OFFSET(1,9),SEEK_SET); @@ -104,6 +105,7 @@ repeat_catalog: dump_sector(catalog_buffer); for(file=0;file<7;file++) { + size_already=0; printf("\n\n"); ts_t=catalog_buffer[(CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE+FILE_TS_LIST_T))]; @@ -138,28 +140,62 @@ repeat_catalog: printf("\tLocked = %s\n", catalog_buffer[CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE)+FILE_TYPE]>0x7f? "YES":"NO"); - printf("\tType = %c\n", - dos33_file_type(catalog_buffer[CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE)+FILE_TYPE])); + type=dos33_file_type(catalog_buffer[CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE)+FILE_TYPE]); + printf("\tType = %c\n",type); printf("\tSize in sectors = %i\n", catalog_buffer[CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE+FILE_SIZE_L)]+ (catalog_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); + /* read first sector to try to get size */ + if (type=='B') { + + } + if (deleted) goto continue_dump; + +repeat_tsl: + + /* read T/S list */ lseek(fd,DISK_OFFSET(ts_t,ts_s),SEEK_SET); result=read(fd,&tslist,BYTES_PER_SECTOR); + /* read data */ for(i=0;i