/*============================================================ ** ** SPLITTER ** ** Copyright (c)1994 Stuart Coates & Mark Matts ** **============================================================ ** ** Portable ANSI C version. ** ** ** Successfully compiled without change on: ** ** Atari ST - Lattice C 5.60 ** Atari ST - GNU C 2.4.5 ** MSDOS 6.20 - GNU C (32 Bit) ** OS/2 2.1 - GNU C ** Sequent Dynix/PTX 2.10 ** IBM RS/6000 AIX 3.2.0 ** ** ** Porting issues: ** ** Source code is ANSI therefore K&R compilers ** will require the function definitions to be ** modified to comply with K&R style. ** ** Compiler settings should be modified so that: ** ** short int = 16 bits ** long int = 32 bits ** ** **============================================================ ** ** Version 2.00 ** ** 94/02/19 SINC Initial release. ** ** ** */ #include #include #include #include #include #include #define SPLITTER_VERSION "2.00" #define BUFFER_SIZE 102400 #define EXIT_OK 0 #define EXIT_INVALID_ARGS 1 #define EXIT_INVALID_INFILE 2 #define EXIT_INVALID_INLENGTH 3 #define EXIT_MEMORY_ALLOC_ERR 4 #define EXIT_FILE_CREATE 5 #define EXIT_INVALID_CHECK 6 #define EXIT_FILE_READ 7 #define EXIT_INFO_READ 8 #define EXIT_FILE_WRITE 9 #define EXIT_TOO_MANY_FILES 10 /* ANSI Prototypes */ int main(int argc, char **argv); void logo_show(void); void usage_show(void); int unsplit_files(char *input_file_prefix,short write_flag); int split_files(char *input_file,char *output_files_prefix,long max_filesize); void input_file_error(char *input_file); void input_file_zero_error(char *input_file); void memory_allocation_error(void); void make_filename(char *buffer,char *prefix,short number); long calc_check_value(unsigned long start_value,char *buffer,long length); void file_write_error(char *file); void null_term_line(char *string); void validation_failed(void); void too_many_files(void); char *check_value_padout(unsigned long check_value, char *check_value_string); int main(int argc, char **argv) { logo_show(); if(argc!=4 && argc!=3) { usage_show(); return(EXIT_INVALID_ARGS); } if(argc==3 && strcmp(argv[1],"-u")!=0 && strcmp(argv[1],"-c")!=0) { usage_show(); return(EXIT_INVALID_ARGS); } if(strcmp(argv[1],"-u")==0) return(unsplit_files(argv[2],1)); else if(strcmp(argv[1],"-c")==0) return(unsplit_files(argv[2],0)); else return(split_files(argv[1],argv[2],strtol(argv[3],NULL,10))); } int unsplit_files(char *input_file_prefix,short write_flag) { FILE *fpin; FILE *fpout; FILE *fpinfo; char *buffer; char *info_filename; char *input_filename; short block_number=1; char *output_filename; char *workspace; long expand_filesize; long block_size; unsigned long stored_check_value; unsigned long file_check_value; long bytes_read; long error; char check_value_string[9]; info_filename=malloc(strlen(input_file_prefix)+(5*sizeof(char))); if(info_filename==NULL) { memory_allocation_error(); return(EXIT_MEMORY_ALLOC_ERR); } output_filename=malloc(1024); if(output_filename==NULL) { memory_allocation_error(); return(EXIT_MEMORY_ALLOC_ERR); } workspace=malloc(1024); if(workspace==NULL) { memory_allocation_error(); return(EXIT_MEMORY_ALLOC_ERR); } input_filename=malloc(strlen(input_file_prefix)+(5*sizeof(char))); if(input_filename==NULL) { memory_allocation_error(); return(EXIT_MEMORY_ALLOC_ERR); } buffer=malloc(BUFFER_SIZE); if(buffer==NULL) { memory_allocation_error(); return(EXIT_MEMORY_ALLOC_ERR); } make_filename(info_filename,input_file_prefix,0); fpinfo=fopen(info_filename,"r"); if(fpinfo==NULL) { input_file_error(info_filename); return(EXIT_INFO_READ); } fgets(workspace,1024,fpinfo); null_term_line(workspace); printf("Files created using: %s\n",workspace); fgets(workspace,1024,fpinfo); null_term_line(workspace); strcpy(output_filename,workspace); if(write_flag==1) printf("Recreating file : %s",output_filename); else printf("Original filename : %s",output_filename); fgets(workspace,1024,fpinfo); null_term_line(workspace); expand_filesize=strtol(workspace,NULL,10); printf(" %ld Bytes.\n",expand_filesize); if(write_flag==1) { fpout=fopen(output_filename,"wb"); if(fpout==NULL) { file_write_error(output_filename); return(EXIT_FILE_CREATE); } } for(;;) { fgets(workspace,1024,fpinfo); if(feof(fpinfo)) break; null_term_line(workspace); block_size=strtol(workspace,NULL,10); fgets(workspace,1024,fpinfo); null_term_line(workspace); stored_check_value=strtoul(workspace,NULL,16); make_filename(input_filename,input_file_prefix,block_number); fpin=fopen(input_filename,"rb"); if(fpin==NULL) { input_file_error(input_filename); return(EXIT_INFO_READ); } bytes_read=0; file_check_value=0; printf("\nReading file: %s Check:%s",input_filename,check_value_padout(stored_check_value,check_value_string)); for(;;) { bytes_read=fread(buffer,1,BUFFER_SIZE,fpin); if(write_flag==1) { error=fwrite(buffer,1,bytes_read,fpout); if(error!=bytes_read) { file_write_error(output_filename); return(EXIT_FILE_WRITE); } } file_check_value=calc_check_value(file_check_value,buffer,bytes_read); if(feof(fpin)) break; } fclose(fpin); printf("/%s",check_value_padout(file_check_value,check_value_string)); if(file_check_value != stored_check_value) { validation_failed(); return(EXIT_INVALID_CHECK); } else { printf(" - OK"); } block_number++; } fclose(fpinfo); if(write_flag==1) fclose(fpout); printf("\n\nFinished.\n\n"); free(buffer); free(workspace); free(info_filename); free(input_filename); free(output_filename); return(0); } int split_files(char *input_file,char *output_files_prefix,long max_filesize) { FILE *fpin; FILE *fpout; FILE *fpinfo; struct stat fileinfo; char *output_filename; char *info_filename; char *buffer; long input_bytes_left; long bytes_in_current_block=0; long bytes_read=0; short block_number=1; unsigned long file_check_value; long error; char check_value_string[9]; if(stat(input_file,&fileinfo)!=0) { input_file_error(input_file); return(EXIT_INVALID_INFILE); } if(fileinfo.st_size==0) { input_file_zero_error(input_file); return(EXIT_INVALID_INLENGTH); } input_bytes_left=fileinfo.st_size; if((input_bytes_left / max_filesize) > 999) { too_many_files(); return(EXIT_TOO_MANY_FILES); } output_filename=malloc(strlen(output_files_prefix)+(5*sizeof(char))); if(output_filename==NULL) { memory_allocation_error(); return(EXIT_MEMORY_ALLOC_ERR); } info_filename=malloc(strlen(output_files_prefix)+(5*sizeof(char))); if(info_filename==NULL) { memory_allocation_error(); return(EXIT_MEMORY_ALLOC_ERR); } buffer=malloc(BUFFER_SIZE); if(buffer==NULL) { memory_allocation_error(); return(EXIT_MEMORY_ALLOC_ERR); } make_filename(info_filename,output_files_prefix,0); fpin=fopen(input_file,"rb"); if(fpin==NULL) { input_file_error(input_file); return(EXIT_INVALID_INFILE); } fpinfo=fopen(info_filename,"w"); if(fpinfo==NULL) { file_write_error(info_filename); return(EXIT_FILE_CREATE); } fprintf(fpinfo,"SPLITTER "SPLITTER_VERSION"\n%s\n%ld\n",input_file,fileinfo.st_size); printf("Splitting file: %s into ",input_file); if((max_filesize*(input_bytes_left/max_filesize)) == input_bytes_left) printf("%d",(int)(input_bytes_left/max_filesize)); else printf("%d",(int)((input_bytes_left/max_filesize)+1)); printf(" parts.\n"); for(;;) { make_filename(output_filename,output_files_prefix,block_number); fpout=fopen(output_filename,"wb"); if(fpout==NULL) { file_write_error(output_filename); return(EXIT_FILE_CREATE); } bytes_in_current_block=0; file_check_value=0; printf("\nCreating file: %s",output_filename); for(;;) { if(bytes_in_current_block+BUFFER_SIZE > max_filesize) { bytes_read=fread(buffer,1,max_filesize-bytes_in_current_block,fpin); } else { bytes_read=fread(buffer,1,BUFFER_SIZE,fpin); } file_check_value=calc_check_value(file_check_value,buffer,bytes_read); error=fwrite(buffer,1,bytes_read,fpout); if(error!=bytes_read) { file_write_error(output_filename); return(EXIT_FILE_WRITE); } bytes_in_current_block+=bytes_read; input_bytes_left-=bytes_read; if(bytes_in_current_block==max_filesize || feof(fpin)) break; } fclose(fpout); printf(" Check:%s - %ld Bytes.",check_value_padout(file_check_value,check_value_string),bytes_in_current_block); fprintf(fpinfo,"%ld\n%lX\n",bytes_in_current_block,file_check_value); block_number++; file_check_value=0; if(feof(fpin) || input_bytes_left==0) break; } fclose(fpin); fclose(fpinfo); printf("\n\nFinished.\n\n"); free(buffer); free(info_filename); free(output_filename); } void make_filename(char *buffer,char *prefix,short number) { strcpy(buffer,prefix); if(number<10) sprintf(&buffer[strlen(buffer)],".00%d",number); else if (number<100) sprintf(&buffer[strlen(buffer)],".0%d",number); else sprintf(&buffer[strlen(buffer)],".%d",number); } void memory_allocation_error(void) { printf("\nError allocating memory block.\n"); } void file_write_error(char *file) { printf("\nError writing to file: %s\n",file); } void input_file_error(char *input_file) { printf("\nError opening input file: %s\n",input_file); } void input_file_zero_error(char *input_file) { printf("\nError, input file: %s is of zero length.\n",input_file); } void validation_failed(void) { printf("\nError: File has failed validation check.\n"); } void too_many_files(void) { printf("\nError: You cannot create more than 999 files.\n"); } void logo_show(void) { printf("SPLITTER Version "SPLITTER_VERSION"\n"); printf("This version compiled: "__DATE__" "__TIME__"\n"); printf("Copyright (c)1994 Stuart Coates & Mark Matts\n\n"); } void usage_show(void) { printf("Usage: SPLITTER \n"); printf(" or: SPLITTER -u|c \n"); } long calc_check_value(unsigned long start_value,char *buffer,long length) { register unsigned long value; register long count=0; char *ptr; ptr=buffer; value=start_value; for(count=0;count