#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <dir.h>
#define BUF_SIZ 2048
#define BSIZE 32760
#define MAX_SUB_FILES 4000
#define demand(fact, remark) {\
	if (!(fact)) {\
		fprintf(stderr, "\nError ->  " #fact "\n");\
		fprintf(stderr, #remark "\n");\
		perror("error");\
		fcloseall();\
		_setcursortype(_NORMALCURSOR);\
		abort();\
		exit(1);\
	}\
}
/************************** Variables *************************************/
char buffer[BUF_SIZ];           /* buffer for reading and writing files */
char outbuf[BSIZE];             /* disk output buffer */
typedef struct{                 /* Structure to hold file info */
	unsigned long int position;  /* location of file in LZH from beginning */
	char filenum;                /* subfile number file will be written to */
	unsigned long int size;      /* file size */
	char *name;                  /* file name - allocated dynamically */
	unsigned long int size2;
	unsigned long int position2;
	} record;
record *file[MAX_SUB_FILES];    /* array of pointers to file records */
unsigned long int fsize;        /* used to hold various file sizes    */
unsigned long int nsize[256];   /* subfile lengths */
unsigned long int i;            /* iteration variable */
unsigned long int skip;         /* used to hold skip file length     */
unsigned long int ovrwrt;       /* overwrite flag(0=dont ovrwrt)     */
unsigned long int tsize;        /* target file size(max for subfiles */
unsigned long int bcount;       /* byte count: used for file buffer  */
unsigned int position;
unsigned int skipper;
unsigned int fsize2;
unsigned int rotaten;
char flag;
unsigned long int startdir=0;
unsigned long int dirsize=0;
char *strptr;
unsigned char subfile;          /* subfile number */
unsigned char max;              /* max = total number of subfiles    */
int count;                      /* count = number of files in archive    */
int count2;
int str_len;
unsigned long int total_size;   /* accumulator -total size of a subfile */
unsigned int hsize;             /* header size */
int j,k;                        /* loop counters */
char temp[MAXPATH];             /* temp string storage */
char prefix[MAXPATH];           /* prefix for target files */
char suffix[4];                 /* holds subfile number suffix 1,2,3,...*/
char ifile[MAXPATH];            /* name of source file */
char tfile[MAXPATH];            /* temp storage for manip file names*/
char ans;                       /* answer for: Overwrite file?          */
char drive[MAXDRIVE];
char dir[MAXDIR];
char comment[85];
char iname[MAXFILE];
char oname[MAXFILE+8];
char ext[MAXEXT];
char saveext[MAXEXT];
int flags;
char trunc_flag=0;
FILE *fp,*sfp;
void sortfs(void);
void help(void);
/********* MAIN PROGRAM **********/
void main(int argc, char *argv[]) /** argc = number of command line args ***/
{                              /**** argv = array containing actual args **/
	int	namesize,c;
int lastarg=argc-1;
if(argc<3) help();
if(strtol(argv[lastarg],NULL,10)<0)
	{ puts("Error: Invalid file size"); exit(1);}
if(!strcmp(argv[lastarg],"1.44M") || !strcmp(argv[lastarg],"1.44m")\
|| !strcmp(argv[lastarg],"1.4M")|| !strcmp(argv[lastarg],"1.4m")) tsize=1457664;
else if(!strcmp(argv[lastarg],"720K") || !strcmp(argv[lastarg],"720k")) tsize=730112;
else if(!strcmp(argv[lastarg],"1.2M") || !strcmp(argv[lastarg],"1.2m")) tsize=1213952;
else if(!strcmp(argv[lastarg],"360K") || !strcmp(argv[lastarg],"360k")) tsize=362496;
else tsize=strtoul(argv[lastarg],NULL,10);
if(tsize<=0) help();

strcpy(ifile,argv[1]);
flags=fnsplit(ifile,drive,dir,iname,ext);
if(!(flags & EXTENSION)){        /* If no extension on source file */
	strcpy(tfile,ifile);
	strcat(tfile, ".LZH");                       // try LZH
	fp=fopen(tfile, "rb");
	if(!fp){
		strcpy(tfile,ifile);
		strcat(tfile, ".ARJ");                    // try ARJ
		fp=fopen(tfile, "rb");
		}
	if(!fp){
		strcpy(tfile,ifile);                      // try ZIP
		strcat(tfile, ".ZIP");
		fp=fopen(tfile, "rb");
		}
	if(!fp){
		strcpy(tfile,ifile);                      // try RAR
		strcat(tfile, ".RAR");
		fp=fopen(tfile, "rb");
		}
	strcpy(ifile, tfile);
	fclose(fp);
	}
fp=fopen(ifile, "rb");             				   // Open source file
demand(fp!=NULL, Could not open source file);
strupr(ifile);                                  // conv to upper case
flags=fnsplit(ifile,drive,dir,iname,ext);
strcpy(saveext, ext);                          // save file name extension
/********************************* Search RAR file ************************/
/***********BEGINNING OF ADDED CODES BY YYZ************************************/
/***DETAILS OF .RAR FILE FORMAT, PLEASE REFER TO TECHNOTE.DOC IN RAR1_52.EXE***/
printf("\n...searching file %s\n",ifile);
skip=0;
count=0;
if(!strcmp(ext,".RAR")) {
fscanf(fp, "%7c", temp);
demand(!strcmp(temp, "\x52\x61\x72\x21\x1a\x07"),Not a .RAR file! Processing terminated!);
fscanf(fp, "%2c", temp);
demand(fgetc(fp)==0x73, Invalid archive header! Processing terminated);
fseek(fp, (long) 12, SEEK_CUR);
for(skip=20; !feof(fp);count++){
	demand(count<MAX_SUB_FILES, Sorry - Too many files in RAR);
	file[count]=(record *) malloc(sizeof(record));
	demand(file[count]!=NULL, Out of memory);
	file[count]->position=skip;
	c=fgetc(fp);
	if (feof(fp)) break;
	demand(c==0x74, Unknown block encountered! Processing terminated);
	fseek(fp, (long) 2, SEEK_CUR);
	fread(&hsize, sizeof(int),1,fp);
	demand(!ferror(fp),Read error);
	if(hsize==0) break;
	if(feof(fp)) break;
	fread(&fsize,sizeof(long),1,fp);
	file[count]->size=fsize+hsize;
	file[count]->filenum=0;
	skip+=file[count]->size;
	fseek(fp, (long)15, SEEK_CUR);
	fread(&namesize,sizeof(int),1,fp);
	fseek(fp, (long)4, SEEK_CUR);
	fgets(temp, namesize+1, fp);
	file[count]->name = (char *) malloc(strlen(temp)+1);
	demand(file[count]->name!=NULL, Out of memory!);
	strcpy(file[count]->name, temp);
	fseek(fp, fsize+2, SEEK_CUR);
 }
}
/***********END OF ADDED CODES BY YYZ******************************************/
/********************************* Search LZH file ************************/
/*
	1 byte  - header size
	1 byte  - header checksum
	5 bytes - file header/signature
	4 bytes - compressed size
	4 bytes - original size
	4 bytes - date/time
	2 bytes - file attributes
	n bytes - file path\name (ends with x00)
	n bytes - file data
	.
	.
	.
*/
if(!strcmp(ext,".LZH")) {
while(!feof(fp)){
	demand(count<MAX_SUB_FILES, Sorry - Too many files in LZH);
	file[count]=(record *) malloc(sizeof(record));
	demand(file[count]!=NULL, Out of memory);
	file[count]->position=skip;
	hsize=fgetc(fp);
	demand(!ferror(fp),Read error);
	if(hsize==0) break;
	if(feof(fp)) break;
	fgetc(fp);
	if(feof(fp)) break;
	fgets(temp,6,fp);
	demand(!strncmp(temp,"-lh",3),LZH file has problems);
	fread(&fsize,sizeof(long),1,fp);
	file[count]->size=fsize+hsize+2;
	file[count]->filenum=0;
	skip+=file[count]->size;
	fseek(fp, (long)10, SEEK_CUR);
	fgets(temp,fgetc(fp)+1,fp);
	file[count]->name = (char *) malloc(strlen(temp)+1);
	demand(file[count]->name!=NULL, Out of memory!);
	strcpy(file[count]->name, temp);
	count++;
	fseek(fp, fsize+5, SEEK_CUR);
 }
}
/*********************** SEARCH ARJ FILE **********************************
	  ARJ archives contains two types of header blocks:

	Archive main header - This is located at the head of the archive
	Local file header   - This is located before each archived file

	  Structure of main header (low order byte first):

	  Bytes Description
	  ----- -------------------------------------------------------------------
		 2   header id (main and local file) = 0x60 0xEA
		 2   basic header size (from 'first_hdr_size' thru 'comment' below)
		 = first_hdr_size + strlen(filename) + 1 + strlen(comment) + 1
		 = 0 if end of archive
		 maximum header size is 2600

		 1   first_hdr_size (size up to and including 'extra data')
		 1   archiver version number
		 1   minimum archiver version to extract
		 1   host OS   (0 = MSDOS, 1 = PRIMOS, 2 = UNIX, 3 = AMIGA, 4 = MAC-OS)
			  (5 = OS/2, 6 = APPLE GS, 7 = ATARI ST, 8 = NEXT)
			  (9 = VAX VMS)
		 1   arj flags
			  (0x01 = NOT USED)
			  (0x02 = OLD_SECURED_FLAG)
			  (0x04 = VOLUME_FLAG)  indicates presence of succeeding
						volume
			  (0x08 = NOT USED)
			  (0x10 = PATHSYM_FLAG) indicates archive name translated
						("\" changed to "/")
			  (0x20 = BACKUP_FLAG) indicates backup type archive
			  (0x40 = SECURED_FLAG)
		 1   security version (2 = current)
		 1   file type	    (must equal 2)
		 1   reserved
		 4   date time when original archive was created
		 4   date time when archive was last modified
		 4   archive size (currently used only for secured archives)
		 4   security envelope file position
		 2   filespec position in filename
		 2   length in bytes of security envelope data
		 2   (currently not used)
		 ?   (currently none)

		 ?   filename of archive when created (null-terminated string)
		 ?   archive comment  (null-terminated string)

		 4   basic header CRC

		 2   1st extended header size (0 if none)
		 ?   1st extended header (currently not used)
		 4   1st extended header's CRC (not present when 0 extended header size)


	  Structure of local file header (low order byte first):

	  Bytes Description
	  ----- -------------------------------------------------------------------
		 2   header id (main and local file) = 0x60 0xEA
		 2   basic header size (from 'first_hdr_size' thru 'comment' below)
		 = first_hdr_size + strlen(filename) + 1 + strlen(comment) + 1
		 = 0 if end of archive
		 maximum header size is 2600

		 1   first_hdr_size (size up to and including 'extra data')
		 1   archiver version number
		 1   minimum archiver version to extract
		 1   host OS   (0 = MSDOS, 1 = PRIMOS, 2 = UNIX, 3 = AMIGA, 4 = MAC-OS)
			  (5 = OS/2, 6 = APPLE GS, 7 = ATARI ST, 8 = NEXT)
			  (9 = VAX VMS)
		 1   arj flags (0x01 = GARBLED_FLAG) indicates passworded file
			  (0x02 = NOT USED)
			  (0x04 = VOLUME_FLAG)  indicates continued file to next
						volume (file is split)
			  (0x08 = EXTFILE_FLAG) indicates file starting position
						field (for split files)
			  (0x10 = PATHSYM_FLAG) indicates filename translated
						("\" changed to "/")
			  (0x20 = BACKUP_FLAG)  indicates file marked as backup
		 1   method    (0 = stored, 1 = compressed most ... 4 compressed fastest)
		 1   file type (0 = binary,    1 = 7-bit text)
			  (3 = directory, 4 = volume label)
		 1   reserved
		 4   date time modified
		 4   compressed size
		 4   original size (this will be different for text mode compression)
		 4   original file's CRC
		 2   filespec position in filename
		 2   file access mode
		 2   host data (currently not used)
		 ?   extra data
		4 bytes for extended file starting position when used
		(these bytes are present when EXTFILE_FLAG is set).
		0 bytes otherwise.

		 ?   filename (null-terminated string)
		 ?   comment  (null-terminated string)

		 4   basic header CRC

		 2   1st extended header size (0 if none)
		 ?   1st extended header (currently not used)
		 4   1st extended header's CRC (not present when 0 extended header size)

		 ...

		 ?   compressed file
****************************************************************************/
if(!strcmp(ext,".ARJ")) {                             /* skip main header */
	file[count]=(record *) malloc(sizeof(record));
	file[count]->name = (char *) malloc(100);
	demand(file[count]->name!=NULL, Out of memory!);
	demand(file[count]!=NULL, Out of memory);
	file[count]->position=skip;                       /* save file position */
	file[count]->filenum=1;
	strcpy(file[count]->name,"HEADER");
	fread(&hsize,sizeof(int),1,fp);
	demand(hsize==0xEA60, ARJ main header file is corrupt);
	fread(&hsize,sizeof(long),1,fp);
	fseek(fp, (long)hsize+2, SEEK_CUR);
	fread(&position, sizeof(int),1,fp);    /* read file position(skip path) */
	fseek(fp, (long)position, SEEK_CUR);
	skip=hsize+10+position;
	file[count++]->size=skip;
while(!feof(fp)){                                    /*** get files ***/
	demand(count<MAX_SUB_FILES, Sorry - Too many files in ARJ);
	file[count]=(record *) malloc(sizeof(record));
	demand(file[count]!=NULL, out of memory);
	file[count]->position=skip;                       /* save file position */
	fread(&hsize,sizeof(int),1,fp);
	demand(hsize==0xEA60, ARJ local hdr file is corrupt);  /* verify header info */
	fread(&skipper,sizeof(int),1,fp);             		  /* get header size */
	skip+=skipper+4;
	file[count]->size=skipper+4;
	hsize=(long)fgetc(fp);                       /* get 1st header size */
	demand(!ferror(fp), read error);
	if(hsize==0) break;
	if(feof(fp)) break;
	fseek(fp,(long)11, SEEK_CUR);
	fread(&fsize,sizeof(long),1,fp);         /* read compressed file size */
	file[count]->filenum=0;
	fseek(fp, (long)8, SEEK_CUR);
	fread(&position, sizeof(int),1,fp);    /* read file position(skip path) */
	fseek(fp, (long)hsize-26+position, SEEK_CUR);
	//strptr=(char *)&(file[count]->name);
	strptr = temp;
	do
		*strptr =fgetc(fp);
	while(*strptr++!=0);
	file[count]->name = (char *) malloc(strlen(temp)+1);
	demand(file[count]->name!=NULL, out of memory!);
	strcpy(file[count]->name, temp);
	while(fgetc(fp)!=0);
	fseek(fp, (long)4, SEEK_CUR);
	fread(&position,sizeof(int),1,fp);
	file[count]->size+=fsize+6+position;
	skip+=fsize+6+position;
	count++;
	fseek(fp, fsize+position, SEEK_CUR);
 }
total_size=0;
}
/*********************** SEARCH ZIP FILE ***********************************
General Format of a ZIP file
----------------------------

  Files stored in arbitrary order.

  Overall zipfile format:

	 [local file header + file data + data_descriptor] . . .
	 [central directory] end of central directory record


  A.  Local file header:

	local file header signature     4 bytes  (0x04034b50)
	version needed to extract       2 bytes
	general purpose bit flag        2 bytes
	compression method              2 bytes
	last mod file time              2 bytes
	last mod file date              2 bytes
	crc-32                          4 bytes
	compressed size                 4 bytes
	uncompressed size               4 bytes
	filename length                 2 bytes
	extra field length              2 bytes

	filename (variable size)
	extra field (variable size)


  B.  Data descriptor:

	crc-32                          4 bytes
	compressed size                 4 bytes
	uncompressed size               4 bytes

		This descriptor exists only if bit 3 of the general
		purpose bit flag is set (see below).  It is byte aligned
		and immediately follows the last byte of compressed data.
		This descriptor is used only when it was not possible to
		seek in the output zip file, e.g., when the output zip file
		was standard output or a non seekable device.

  C.  Central directory structure:

		[file header] . . .  end of central dir record

		File header:

	central file header signature   4 bytes  (0x02014b50)
	version made by                 2 bytes
	version needed to extract       2 bytes
	general purpose bit flag        2 bytes
	compression method              2 bytes
	last mod file time              2 bytes
	last mod file date              2 bytes
	crc-32                          4 bytes
	compressed size                 4 bytes
	uncompressed size               4 bytes
	filename length                 2 bytes
	extra field length              2 bytes
	file comment length             2 bytes
	disk number start               2 bytes
	internal file attributes        2 bytes
	external file attributes        4 bytes
	relative offset of local header 4 bytes

	filename (variable size)
	extra field (variable size)
	file comment (variable size)

		End of central dir record:

	end of central dir signature    4 bytes  (0x06054b50)
	number of this disk             2 bytes
	number of the disk with the
	start of the central directory  2 bytes
	total number of entries in
	the central dir on this disk    2 bytes
	total number of entries in
	the central dir                 2 bytes
	size of the central directory   4 bytes
	offset of start of central
	directory with respect to
	the starting disk number        4 bytes
	zipfile comment length          2 bytes
	zipfile comment (variable size)
****************************************************************************/

if(!strcmp(ext,".ZIP")) {                             /* skip main header */

while(!feof(fp)){                                    /*** get files ***/
	fread(&fsize,sizeof(long),1,fp);
	if(fsize==0x04034b50)   /* verify header info LOCAL*/
	{
		demand(count<MAX_SUB_FILES, Sorry - Too many files in ZIP);
		file[count]=(record *) malloc(sizeof(record));
		demand(file[count]!=NULL, out of memory);
		file[count]->position=skip;                       /* save file position */
		fseek(fp, (long)14, SEEK_CUR);
		fread(&fsize,sizeof(long),1,fp);             	 /* get file size */
		file[count]->size=fsize;
		fseek(fp, (long)4, SEEK_CUR);
		fread(&skipper,sizeof(int),1,fp);            /* get file name len */
		fread(&hsize,sizeof(int),1,fp);             /* get extra len */
		file[count]->size+=hsize;
		if(feof(fp)) break;
		file[count]->name = (char *) malloc(skipper+1);
		demand(file[count]->name!=NULL, out of memory!);
		fgets(file[count]->name,skipper+1,fp);       /* get file name len */
		fseek(fp,file[count]->size, SEEK_CUR);
		file[count]->size+=skipper+30;
		skip+=file[count]->size;
		file[count]->filenum=0;
		count++;
		}
else if(fsize==0x02014b50)   /* verify header info CENTRALDIR*/
	{
		file[count2]->position2=skip;              /* save file position */
		fseek(fp, (long)24, SEEK_CUR);
		fread(&fsize2,sizeof(int),1,fp);             	 /* get file name size */
		if(feof(fp)) break;
		fread(&skipper,sizeof(int),1,fp);            /* get extra len */
		if(feof(fp)) break;
		fread(&hsize,sizeof(int),1,fp);             /* get comment len */
		if(feof(fp)) break;
		fseek(fp,(long)8, SEEK_CUR);
		fread(&startdir,sizeof(long),1,fp);             /* get position */
		while(file[rotaten]->position!=startdir)
			rotaten = (rotaten+1) % count;
		file[rotaten]->size2=hsize+skipper+fsize2+46;
		file[rotaten]->size+=file[rotaten]->size2;
		fseek(fp, (long)fsize2+skipper+hsize, SEEK_CUR);

		if(feof(fp)) break;
		skip+=file[rotaten]->size2;
		count2++;
		}
else if(fsize==0x06054b50)   /* verify header info ENDOFCENTRALDIR*/
	{
		fsize=skip;                                  /* save file position */
		demand(count==count2, ZIP file is damaged);
		fseek(fp, (long)16, SEEK_CUR);
		fread(&fsize2,sizeof(int),1,fp);             	 /* get file name size */
		if(feof(fp)) break;
		fseek(fp, (long)fsize2, SEEK_CUR);
		break;
		}
else demand(1==0, ZIP file is damaged);
 }
}
fclose(fp);
if(count<2) {
	printf("%s only contains one file!\n",ifile);
	puts("File cannot be sized!  Use a physical file splitting utility");
	exit(1);
	}
sortfs();   /*** Sort file names by size ***/
printf("...sizing to %lu bytes\n",tsize);
/***********BEGINNING OF ADDED CODES BY YYZ************************************/
  if(!strcmp(saveext,".RAR") && tsize<file[0]->size+20) {
	printf("Error: Impossible to size archive to %lu bytes.\n",tsize);
	printf("%s contains a file, %s, that is %lu bytes compressed.\n",ifile\
	,file[0]->name,file[0]->size+20);
	printf("Target file size must be at least %lu bytes to accomodate this file.\n"\
	,file[0]->size+21);
	printf("If you require a %lu byte file size use a physical file splitting utility\n",tsize);
  exit(1);
  }
/***********END OF ADDED CODES BY YYZ******************************************/
  if(!strcmp(saveext,".LZH") && tsize<=file[0]->size) {
	printf("Error: Impossible to size archive to %lu bytes.\n",tsize);
	printf("%s contains a file, %s, that is %lu bytes compressed.\n",ifile\
	,file[0]->name,file[0]->size);
	printf("Target file size must be at least %lu bytes to accomodate this file.\n"\
	,file[0]->size+1);
	printf("If you require a %lu byte file size use a physical file splitting utility\n",tsize);
  exit(1);
  }
if(!strcmp(saveext,".ARJ") && tsize < file[0]->size+4+file[1]->size) {
	printf("Error: Impossible to size archive to %lu bytes.\n",tsize);
	printf("%s contains a file, %s, that is %lu bytes compressed.\n",ifile\
	,file[1]->name,file[1]->size);
	printf("Target file size must be at least %lu bytes to accomodate this file\n"\
	,file[0]->size+4+file[1]->size);
	printf("If you require a %lu byte file size use a physical file splitting utility\n",tsize);
  exit(1);
  }
if(!strcmp(saveext,".ZIP") && tsize < file[0]->size+22+fsize2) {
	printf("Error: Impossible to size archive to %lu bytes.\n",tsize);
	printf("%s contains a file, %s, that is %lu bytes compressed.\n",ifile\
	,file[0]->name,file[0]->size);
	printf("Target file size must be at least %lu bytes to accomodate this file\n"\
	,file[0]->size+22+fsize2);
  printf("If you require a %lu byte file size use a physical file splitting utility\n",tsize);
  exit(1);
  }
max=0;
/************************* Assign subfiles ****************************/
if(!strcmp(ext,".ARJ"))       for(j=0;j<255;nsize[j++]=file[0]->size+4);
else if(!strcmp(ext,".ZIP"))  for(j=0;j<255;nsize[j++]=22+fsize2);
else if(!strcmp(ext,".LZH"))  for(j=0;j<255;nsize[j++]=1);
/***********BEGINNING OF ADDED CODES BY YYZ************************************/
else if(!strcmp(ext,".RAR")) for(j=0;j<255;nsize[j++]=20);
/***********END OF ADDED CODES BY YYZ******************************************/
for(j=0;j<count;j++) {
	subfile=0;
	while(!file[j]->filenum) {
		if(nsize[subfile]+file[j]->size <= tsize ) {
			nsize[subfile]+=file[j]->size;
			file[j]->filenum = subfile;
			if(subfile>max) max=subfile;
			}
		else {
			subfile++;
			if(subfile>254) puts("Can't create more than 254 subfiles!");
			demand(subfile<=254, Target file size too small - Use a larger target size);
			}
	}
}
/********************* Write Subfiles ***********************************/
if(max<2) {puts("Nothing to do!");exit(0);}
if(argc==4)
	{
	flags=fnsplit(argv[2],drive,dir,oname,ext);
	if(!(flags & FILENAME)) strncpy(oname,iname,8);
	}
else
	{
	trunc_flag=1;
	strncpy(oname,iname,7);  /** assume source name ***/
	}

if(max<10)       sprintf(suffix,"%1i",(short)max);
else if(max<100) sprintf(suffix,"%02i",(short)max);
else             sprintf(suffix,"%03i",(short)max);

while(strlen(oname)+strlen(suffix)>8)
	{
	if(!trunc_flag)
		{
		puts("  **** Warning: Output filename prefix had to be truncated ****");
		trunc_flag=1;
		}
	oname[strlen(oname)-1]=NULL;
	}
fnmerge(prefix,drive,dir,oname,"");
fp=fopen(ifile,"rb");
demand(fp!=NULL,"Unable to open source file");
for(j=0;j<max;j++) {
	if(max<10)       sprintf(suffix,"%1i",j+1);
	else if(max<100) sprintf(suffix,"%02i",j+1);
	else             sprintf(suffix,"%03i",j+1);
	strcpy(temp,prefix);
	strcat(temp,suffix);
	strcat(temp,saveext);
	sfp=fopen(temp,"rb");
	if(sfp!=NULL) {
		fclose(sfp);
		if(!ovrwrt) {
		do {
		  printf("\nFile %s exists, overwrite(Y/N/G)?",temp);
		  ans=getche();
			}while(!strchr("YyNnGg", ans));
		puts("\n");
		if(strchr("Gg",ans)) ovrwrt=1;
		if(strchr("Nn",ans)) exit(0);
		}
		demand(!remove(temp), Unable to overwrite file);
		}
	sfp=fopen(temp,"wb");
	demand(sfp!=NULL,Unable to open output file);
	demand(!ferror(sfp),Write error);
	setvbuf(sfp,outbuf,_IOFBF,BSIZE);
	_setcursortype(_NOCURSOR);
	printf("...writing file %s - ",temp);
/***********BEGINNING OF ADDED CODES BY YYZ************************************/
	if(!strcmp(saveext,".RAR")) {
		fseek(fp, 0, SEEK_SET);
		fread(buffer,1,20,fp);
		fwrite(buffer,1,20,sfp);
		demand(!ferror(sfp),Write error);
		total_size=20;
	}
/***********END OF ADDED CODES BY YYZ******************************************/
	for(k=0;k<count;k++) {
		if(file[k]->filenum!=j+1) continue;
		if(k==0 && !strcmp(saveext,".ARJ")) file[0]->filenum++;
		str_len=strlen(file[k]->name);
		clreol();
		printf("%s",file[k]->name);
		while(str_len>0) {
			printf("\b");
			str_len--;
			}
		fseek(fp, file[k]->position, SEEK_SET);
		demand(!ferror(fp), Read error);
		bcount=file[k]->size;
		if(!strcmp(saveext,".ZIP")) {
			bcount-=file[k]->size2;
			file[k]->position=total_size; }
		total_size+=bcount;
		while(bcount) {
		if(bcount>=BUF_SIZ) {
			demand(fread(buffer,1,BUF_SIZ,fp)==BUF_SIZ,Read error);
			demand(fwrite(buffer,1,BUF_SIZ,sfp)==BUF_SIZ,Write error);
			demand(!ferror(sfp),Write error);
			bcount-=BUF_SIZ;
			}
		else {
			demand(fread(buffer,1,bcount,fp)==bcount,Read error);
			demand(fwrite(buffer,1,bcount,sfp)==bcount,Write error);
			demand(!ferror(sfp),Write error)
			bcount=0;
			}

			}
		}
		if(!strcmp(saveext,".LZH")) {
			fputc(0,sfp);
			total_size++;
			demand(!ferror(sfp),Write error);
			}
		if(!strcmp(saveext,".ARJ")) {
			fputc(0x60,sfp);
			fputc(0xEA,sfp);
			fputc(0x00,sfp);
			fputc(0x00,sfp);
			total_size+=4;
			demand(!ferror(sfp),Write error);
			}
		if(!strcmp(saveext,".ZIP")) {          /* Write Central ZIP dir */
			count2=0;
			startdir=total_size;
			for(k=0;k<count;k++) {
			if(file[k]->filenum!=j+1) continue;
			fseek(fp, file[k]->position2, SEEK_SET);
			demand(!ferror(fp), Read error);
			demand(fread(buffer,1,42,fp)==42,Read error);
			demand(fwrite(buffer,1,42,sfp)==42,Write error);
			demand(!ferror(sfp),Write error)
			demand(fwrite(&(file[k]->position),sizeof(long),1,sfp)==1,Write error);
			demand(!ferror(sfp),Write error)
			fseek(fp,(long)4,SEEK_CUR);
			demand(fread(buffer,file[k]->size2-46,1,fp)==1,Read error);
			demand(fwrite(buffer,file[k]->size2-46,1,sfp)==1,Write error);
			demand(!ferror(sfp),Write error)
			total_size+=file[k]->size2;
			count2++;
			}
			dirsize=total_size-startdir;
			fseek(fp, fsize, SEEK_SET);                   /* write end of dir */
			demand(!ferror(fp), Read error);
			demand(fread(buffer,1,8,fp)==8,Read error);            /* 8 bytes */
			demand(fwrite(buffer,1,8,sfp)==8,Write error);
			demand(!ferror(sfp),Write error)
			demand(fwrite(&count2,sizeof(int),1,sfp)==1,Write error);
			demand(!ferror(sfp),Write error);
			demand(fwrite(&count2,sizeof(int),1,sfp)==1,Write error);
			demand(!ferror(sfp),Write error);
			demand(fwrite(&dirsize,sizeof(long),1,sfp)==1,Write error);
			demand(!ferror(sfp),Write error);
			demand(fwrite(&startdir,sizeof(long),1,sfp)==1,Write error);
			demand(!ferror(sfp),Write error);
			demand(fwrite(&fsize2,sizeof(int),1,sfp)==1,Write error);
			demand(!ferror(sfp),Write error);
			fseek(fp, (long)14, SEEK_CUR);
			demand(fread(buffer,1,fsize2,fp)==fsize2,Read error);
			demand(fwrite(buffer,1,fsize2,sfp)==fsize2,Write error);
			demand(!ferror(sfp),Write error)
			total_size+=22+fsize2;
		}
		fflush(sfp);
		fclose(sfp);
		demand(!ferror(sfp),Write error);
		clreol();
		printf("%7lu bytes\n",total_size);
		_setcursortype(_NORMALCURSOR);
		total_size=0;
	}
fclose(fp);
}

/****************** SORTFS routine to sort files ***************************/
void sortfs(void) {
	int i,j,k=1;
	record *temp;
	if(!strcmp(saveext,".ARJ")) k=2;
	for(i=k;i<count;i++) {
		j=i;
		temp=file[j];
		while(j>k-1 && file[j-1]->size < temp->size) {
		  file[j]=file[j-1];
		  j--;
		  }
		file[j]=temp;
	}
}
/********************** HELP write help screen ****************************/
void help(void) {
/* Print help screen */
puts("\n\
LSIZE 2.52                 Archive File Sizer                         9-28-94\n\
by Lawrence S. Lewis                                          Willingboro, NJ\n\
Enhanced by Yang Yuanzhi		     Inst. of CS at NTHU, Taiwan, ROC\n\
\n   This utility program will take an archive file (ZIP/LZH/ARJ/RAR) and break\
\nit up into smaller volumes.  You may specify the size of these smaller files.\
\nThis is handy for backing up a large archive to a number of floppy diskettes.\
\nThe original file is left intact.  Each of the smaller files will be readable\
\nby the original archive program. This program will work with archives created\
\nwith RAR.EXE v1.502, LHA.EXE v2.13, ARJ.EXE v2.41, and PKZIP v2.04g.\
\nSyntax:   LSIZE   SourceFile   [TargetPrefix]   MaxSize\n\
\n         SourceFile  = name of the archive to be broken up.\
\n       TargetPrefix  = the prefix of the files to be created.\
\n                     = default prefix is source name.\
\n             MaxSize = maximum size(in bytes) of each output file.\
\n                     = also accepts size: 1.44M, 720K, 1.2M, or 360K\
\nExamples:  LSIZE month.lzh day 720K  or  LSIZE month c:\\archive 1.44M\
\n       The first command would split up the file MONTH.LZH into smaller\
\n       files called: DAY1.LZH, DAY2.LZH, DAY3.LZH, DAY4.LZH... Each file\
\n       will be small enough to fit on a 720K floppy disk.\
\nNote:	.RAR files must have no AV inside.");
exit(0);
}