home *** CD-ROM | disk | FTP | other *** search
/ ftp.update.uu.se / ftp.update.uu.se.2014.03.zip / ftp.update.uu.se / pub / rainbow / msdos / misc / lsize25.zip / LSIZE.C next >
C/C++ Source or Header  |  1994-01-18  |  26KB  |  717 lines

  1. #include <stdio.h>
  2. #include <conio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <dir.h>
  6. #define BUF_SIZ 2048
  7. #define BSIZE 32760
  8. #define MAX_SUB_FILES 4000
  9. #define demand(fact, remark) {\
  10.     if (!(fact)) {\
  11.         fprintf(stderr, "\nError ->  " #fact "\n");\
  12.         fprintf(stderr, #remark "\n");\
  13.         perror("error");\
  14.         fcloseall();\
  15.         _setcursortype(_NORMALCURSOR);\
  16.         abort();\
  17.         exit(1);\
  18.     }\
  19. }
  20. /************************** Variables *************************************/
  21. char buffer[BUF_SIZ];           /* buffer for reading and writing files */
  22. char outbuf[BSIZE];             /* disk output buffer */
  23. typedef struct{                 /* Structure to hold file info */
  24.     unsigned long int position;  /* location of file in LZH from beginning */
  25.     char filenum;                /* subfile number file will be written to */
  26.     unsigned long int size;      /* file size */
  27.     char *name;                  /* file name - allocated dynamically */
  28.     unsigned long int size2;
  29.     unsigned long int position2;
  30.     } record;
  31. record *file[MAX_SUB_FILES];    /* array of pointers to file records */
  32. unsigned long int fsize;        /* used to hold various file sizes    */
  33. unsigned long int nsize[256];   /* subfile lengths */
  34. unsigned long int i;            /* iteration variable */
  35. unsigned long int skip;         /* used to hold skip file length     */
  36. unsigned long int ovrwrt;       /* overwrite flag(0=dont ovrwrt)     */
  37. unsigned long int tsize;        /* target file size(max for subfiles */
  38. unsigned long int bcount;       /* byte count: used for file buffer  */
  39. unsigned int position;
  40. unsigned int skipper;
  41. unsigned int fsize2;
  42. unsigned int rotaten;
  43. char flag;
  44. unsigned long int startdir=0;
  45. unsigned long int dirsize=0;
  46. char *strptr;
  47. unsigned char subfile;          /* subfile number */
  48. unsigned char max;              /* max = total number of subfiles    */
  49. int count;                      /* count = number of files in archive    */
  50. int count2;
  51. int str_len;
  52. unsigned long int total_size;   /* accumulator -total size of a subfile */
  53. unsigned int hsize;             /* header size */
  54. int j,k;                        /* loop counters */
  55. char temp[MAXPATH];             /* temp string storage */
  56. char prefix[MAXPATH];           /* prefix for target files */
  57. char suffix[4];                 /* holds subfile number suffix 1,2,3,...*/
  58. char ifile[MAXPATH];            /* name of source file */
  59. char tfile[MAXPATH];            /* temp storage for manip file names*/
  60. char ans;                       /* answer for: Overwrite file?          */
  61. char drive[MAXDRIVE];
  62. char dir[MAXDIR];
  63. char comment[85];
  64. char iname[MAXFILE];
  65. char oname[MAXFILE+8];
  66. char ext[MAXEXT];
  67. char saveext[MAXEXT];
  68. int flags;
  69. char trunc_flag=0;
  70. FILE *fp,*sfp;
  71. void sortfs(void);
  72. void help(void);
  73. /********* MAIN PROGRAM **********/
  74. void main(int argc, char *argv[]) /** argc = number of command line args ***/
  75. {                              /**** argv = array containing actual args **/
  76. int lastarg=argc-1;
  77. if(argc<3) help();
  78. if(strtol(argv[lastarg],NULL,10)<0)
  79.     { puts("Error: Invalid file size"); exit(1);}
  80. if(!strcmp(argv[lastarg],"1.44M") || !strcmp(argv[lastarg],"1.44m")\
  81. || !strcmp(argv[lastarg],"1.4M")|| !strcmp(argv[lastarg],"1.4m")) tsize=1457664;
  82. else if(!strcmp(argv[lastarg],"720K") || !strcmp(argv[lastarg],"720k")) tsize=730112;
  83. else if(!strcmp(argv[lastarg],"1.2M") || !strcmp(argv[lastarg],"1.2m")) tsize=1457664;
  84. else if(!strcmp(argv[lastarg],"360K") || !strcmp(argv[lastarg],"360k")) tsize=362496;
  85. else tsize=strtoul(argv[lastarg],NULL,10);
  86. if(tsize<=0) help();
  87.  
  88. strcpy(ifile,argv[1]);
  89. flags=fnsplit(ifile,drive,dir,iname,ext);
  90. if(!(flags & EXTENSION)){        /* If no extension on source file */
  91.     strcpy(tfile,ifile);
  92.     strcat(tfile, ".LZH");                       // try LZH
  93.     fp=fopen(tfile, "rb");
  94.     if(!fp){
  95.         strcpy(tfile,ifile);
  96.         strcat(tfile, ".ARJ");                    // try ARJ
  97.         fp=fopen(tfile, "rb");
  98.         }
  99.     if(!fp){
  100.         strcpy(tfile,ifile);                      // try ZIP
  101.         strcat(tfile, ".ZIP");
  102.         fp=fopen(tfile, "rb");
  103.         }
  104.     strcpy(ifile, tfile);
  105.     fclose(fp);
  106.     }
  107. fp=fopen(ifile, "rb");                                // Open source file
  108. demand(fp!=NULL, Could not open source file);
  109. strupr(ifile);                                  // conv to upper case
  110. flags=fnsplit(ifile,drive,dir,iname,ext);
  111. strcpy(saveext, ext);                          // save file name extension
  112. /********************************* Search LZH file ************************/
  113. /*
  114.     1 byte  - header size
  115.     1 byte  - header checksum
  116.     5 bytes - file header/signature
  117.     4 bytes - compressed size
  118.     4 bytes - original size
  119.     4 bytes - date/time
  120.     2 bytes - file attributes
  121.     n bytes - file path\name (ends with x00)
  122.     n bytes - file data
  123.     .
  124.     .
  125.     .
  126. */
  127. printf("\n...searching file %s\n",ifile);
  128. skip=0;
  129. count=0;
  130. if(!strcmp(ext,".LZH")) {
  131. while(!feof(fp)){
  132.     demand(count<MAX_SUB_FILES, Sorry - Too many files in LZH);
  133.     file[count]=malloc(sizeof(record));
  134.     demand(file[count]!=NULL, Out of memory);
  135.     file[count]->position=skip;
  136.     hsize=fgetc(fp);
  137.     demand(!ferror(fp),Read error);
  138.     if(hsize==0) break;
  139.     if(feof(fp)) break;
  140.     fgetc(fp);
  141.     if(feof(fp)) break;
  142.     fgets(temp,6,fp);
  143.     demand(!strncmp(temp,"-lh",3),LZH file has problems);
  144.     fread(&fsize,sizeof(long),1,fp);
  145.     file[count]->size=fsize+hsize+2;
  146.     file[count]->filenum=0;
  147.     skip+=file[count]->size;
  148.     fseek(fp, (long)10, SEEK_CUR);
  149.     fgets(temp,fgetc(fp)+1,fp);
  150.     file[count]->name = malloc(strlen(temp)+1);
  151.     demand(file[count]->name!=NULL, Out of memory!);
  152.     strcpy(file[count]->name, temp);
  153.     count++;
  154.     fseek(fp, fsize+5, SEEK_CUR);
  155.  }
  156. }
  157. /*********************** SEARCH ARJ FILE **********************************
  158.       ARJ archives contains two types of header blocks:
  159.  
  160.     Archive main header - This is located at the head of the archive
  161.     Local file header   - This is located before each archived file
  162.  
  163.       Structure of main header (low order byte first):
  164.  
  165.       Bytes Description
  166.       ----- -------------------------------------------------------------------
  167.          2   header id (main and local file) = 0x60 0xEA
  168.          2   basic header size (from 'first_hdr_size' thru 'comment' below)
  169.          = first_hdr_size + strlen(filename) + 1 + strlen(comment) + 1
  170.          = 0 if end of archive
  171.          maximum header size is 2600
  172.  
  173.          1   first_hdr_size (size up to and including 'extra data')
  174.          1   archiver version number
  175.          1   minimum archiver version to extract
  176.          1   host OS   (0 = MSDOS, 1 = PRIMOS, 2 = UNIX, 3 = AMIGA, 4 = MAC-OS)
  177.               (5 = OS/2, 6 = APPLE GS, 7 = ATARI ST, 8 = NEXT)
  178.               (9 = VAX VMS)
  179.          1   arj flags
  180.               (0x01 = NOT USED)
  181.               (0x02 = OLD_SECURED_FLAG)
  182.               (0x04 = VOLUME_FLAG)  indicates presence of succeeding
  183.                         volume
  184.               (0x08 = NOT USED)
  185.               (0x10 = PATHSYM_FLAG) indicates archive name translated
  186.                         ("\" changed to "/")
  187.               (0x20 = BACKUP_FLAG) indicates backup type archive
  188.               (0x40 = SECURED_FLAG)
  189.          1   security version (2 = current)
  190.          1   file type        (must equal 2)
  191.          1   reserved
  192.          4   date time when original archive was created
  193.          4   date time when archive was last modified
  194.          4   archive size (currently used only for secured archives)
  195.          4   security envelope file position
  196.          2   filespec position in filename
  197.          2   length in bytes of security envelope data
  198.          2   (currently not used)
  199.          ?   (currently none)
  200.  
  201.          ?   filename of archive when created (null-terminated string)
  202.          ?   archive comment  (null-terminated string)
  203.  
  204.          4   basic header CRC
  205.  
  206.          2   1st extended header size (0 if none)
  207.          ?   1st extended header (currently not used)
  208.          4   1st extended header's CRC (not present when 0 extended header size)
  209.  
  210.  
  211.       Structure of local file header (low order byte first):
  212.  
  213.       Bytes Description
  214.       ----- -------------------------------------------------------------------
  215.          2   header id (main and local file) = 0x60 0xEA
  216.          2   basic header size (from 'first_hdr_size' thru 'comment' below)
  217.          = first_hdr_size + strlen(filename) + 1 + strlen(comment) + 1
  218.          = 0 if end of archive
  219.          maximum header size is 2600
  220.  
  221.          1   first_hdr_size (size up to and including 'extra data')
  222.          1   archiver version number
  223.          1   minimum archiver version to extract
  224.          1   host OS   (0 = MSDOS, 1 = PRIMOS, 2 = UNIX, 3 = AMIGA, 4 = MAC-OS)
  225.               (5 = OS/2, 6 = APPLE GS, 7 = ATARI ST, 8 = NEXT)
  226.               (9 = VAX VMS)
  227.          1   arj flags (0x01 = GARBLED_FLAG) indicates passworded file
  228.               (0x02 = NOT USED)
  229.               (0x04 = VOLUME_FLAG)  indicates continued file to next
  230.                         volume (file is split)
  231.               (0x08 = EXTFILE_FLAG) indicates file starting position
  232.                         field (for split files)
  233.               (0x10 = PATHSYM_FLAG) indicates filename translated
  234.                         ("\" changed to "/")
  235.               (0x20 = BACKUP_FLAG)  indicates file marked as backup
  236.          1   method    (0 = stored, 1 = compressed most ... 4 compressed fastest)
  237.          1   file type (0 = binary,    1 = 7-bit text)
  238.               (3 = directory, 4 = volume label)
  239.          1   reserved
  240.          4   date time modified
  241.          4   compressed size
  242.          4   original size (this will be different for text mode compression)
  243.          4   original file's CRC
  244.          2   filespec position in filename
  245.          2   file access mode
  246.          2   host data (currently not used)
  247.          ?   extra data
  248.         4 bytes for extended file starting position when used
  249.         (these bytes are present when EXTFILE_FLAG is set).
  250.         0 bytes otherwise.
  251.  
  252.          ?   filename (null-terminated string)
  253.          ?   comment  (null-terminated string)
  254.  
  255.          4   basic header CRC
  256.  
  257.          2   1st extended header size (0 if none)
  258.          ?   1st extended header (currently not used)
  259.          4   1st extended header's CRC (not present when 0 extended header size)
  260.  
  261.          ...
  262.  
  263.          ?   compressed file
  264. ****************************************************************************/
  265. if(!strcmp(ext,".ARJ")) {                             /* skip main header */
  266.     file[count]=malloc(sizeof(record));
  267.     file[count]->name = malloc(100);
  268.     demand(file[count]->name!=NULL, Out of memory!);
  269.     demand(file[count]!=NULL, Out of memory);
  270.     file[count]->position=skip;                       /* save file position */
  271.     file[count]->filenum=1;
  272.     strcpy(file[count]->name,"HEADER");
  273.     fread(&hsize,sizeof(int),1,fp);
  274.     demand(hsize==0xEA60, ARJ main header file is corrupt);
  275.     fread(&hsize,sizeof(long),1,fp);
  276.     fseek(fp, (long)hsize+2, SEEK_CUR);
  277.     fread(&position, sizeof(int),1,fp);    /* read file position(skip path) */
  278.     fseek(fp, (long)position, SEEK_CUR);
  279.     skip=hsize+10+position;
  280.     file[count++]->size=skip;
  281. while(!feof(fp)){                                    /*** get files ***/
  282.     demand(count<MAX_SUB_FILES, Sorry - Too many files in ARJ);
  283.     file[count]=malloc(sizeof(record));
  284.     demand(file[count]!=NULL, out of memory);
  285.     file[count]->position=skip;                       /* save file position */
  286.     fread(&hsize,sizeof(int),1,fp);
  287.     demand(hsize==0xEA60, ARJ local hdr file is corrupt);  /* verify header info */
  288.     fread(&skipper,sizeof(int),1,fp);                       /* get header size */
  289.     skip+=skipper+4;
  290.     file[count]->size=skipper+4;
  291.     hsize=(long)fgetc(fp);                       /* get 1st header size */
  292.     demand(!ferror(fp), read error);
  293.     if(hsize==0) break;
  294.     if(feof(fp)) break;
  295.     fseek(fp,(long)11, SEEK_CUR);
  296.     fread(&fsize,sizeof(long),1,fp);         /* read compressed file size */
  297.     file[count]->filenum=0;
  298.     fseek(fp, (long)8, SEEK_CUR);
  299.     fread(&position, sizeof(int),1,fp);    /* read file position(skip path) */
  300.     fseek(fp, (long)hsize-26+position, SEEK_CUR);
  301.     //strptr=(char *)&(file[count]->name);
  302.     strptr = temp;
  303.     do
  304.         *strptr =fgetc(fp);
  305.     while(*strptr++!=0);
  306.     file[count]->name = malloc(strlen(temp)+1);
  307.     demand(file[count]->name!=NULL, out of memory!);
  308.     strcpy(file[count]->name, temp);
  309.     while(fgetc(fp)!=0);
  310.     fseek(fp, (long)4, SEEK_CUR);
  311.     fread(&position,sizeof(int),1,fp);
  312.     file[count]->size+=fsize+6+position;
  313.     skip+=fsize+6+position;
  314.     count++;
  315.     fseek(fp, fsize+position, SEEK_CUR);
  316.  }
  317. total_size=0;
  318. }
  319. /*********************** SEARCH ZIP FILE ***********************************
  320. General Format of a ZIP file
  321. ----------------------------
  322.  
  323.   Files stored in arbitrary order.
  324.  
  325.   Overall zipfile format:
  326.  
  327.      [local file header + file data + data_descriptor] . . .
  328.      [central directory] end of central directory record
  329.  
  330.  
  331.   A.  Local file header:
  332.  
  333.     local file header signature     4 bytes  (0x04034b50)
  334.     version needed to extract       2 bytes
  335.     general purpose bit flag        2 bytes
  336.     compression method              2 bytes
  337.     last mod file time              2 bytes
  338.     last mod file date              2 bytes
  339.     crc-32                          4 bytes
  340.     compressed size                 4 bytes
  341.     uncompressed size               4 bytes
  342.     filename length                 2 bytes
  343.     extra field length              2 bytes
  344.  
  345.     filename (variable size)
  346.     extra field (variable size)
  347.  
  348.  
  349.   B.  Data descriptor:
  350.  
  351.     crc-32                          4 bytes
  352.     compressed size                 4 bytes
  353.     uncompressed size               4 bytes
  354.  
  355.         This descriptor exists only if bit 3 of the general
  356.         purpose bit flag is set (see below).  It is byte aligned
  357.         and immediately follows the last byte of compressed data.
  358.         This descriptor is used only when it was not possible to
  359.         seek in the output zip file, e.g., when the output zip file
  360.         was standard output or a non seekable device.
  361.  
  362.   C.  Central directory structure:
  363.  
  364.         [file header] . . .  end of central dir record
  365.  
  366.         File header:
  367.  
  368.     central file header signature   4 bytes  (0x02014b50)
  369.     version made by                 2 bytes
  370.     version needed to extract       2 bytes
  371.     general purpose bit flag        2 bytes
  372.     compression method              2 bytes
  373.     last mod file time              2 bytes
  374.     last mod file date              2 bytes
  375.     crc-32                          4 bytes
  376.     compressed size                 4 bytes
  377.     uncompressed size               4 bytes
  378.     filename length                 2 bytes
  379.     extra field length              2 bytes
  380.     file comment length             2 bytes
  381.     disk number start               2 bytes
  382.     internal file attributes        2 bytes
  383.     external file attributes        4 bytes
  384.     relative offset of local header 4 bytes
  385.  
  386.     filename (variable size)
  387.     extra field (variable size)
  388.     file comment (variable size)
  389.  
  390.         End of central dir record:
  391.  
  392.     end of central dir signature    4 bytes  (0x06054b50)
  393.     number of this disk             2 bytes
  394.     number of the disk with the
  395.     start of the central directory  2 bytes
  396.     total number of entries in
  397.     the central dir on this disk    2 bytes
  398.     total number of entries in
  399.     the central dir                 2 bytes
  400.     size of the central directory   4 bytes
  401.     offset of start of central
  402.     directory with respect to
  403.     the starting disk number        4 bytes
  404.     zipfile comment length          2 bytes
  405.     zipfile comment (variable size)
  406. ****************************************************************************/
  407.  
  408. if(!strcmp(ext,".ZIP")) {                             /* skip main header */
  409.  
  410. while(!feof(fp)){                                    /*** get files ***/
  411.     fread(&fsize,sizeof(long),1,fp);
  412.     if(fsize==0x04034b50)   /* verify header info LOCAL*/
  413.     {
  414.         demand(count<MAX_SUB_FILES, Sorry - Too many files in ZIP);
  415.         file[count]=malloc(sizeof(record));
  416.         demand(file[count]!=NULL, out of memory);
  417.         file[count]->position=skip;                       /* save file position */
  418.         fseek(fp, (long)14, SEEK_CUR);
  419.         fread(&fsize,sizeof(long),1,fp);                  /* get file size */
  420.         file[count]->size=fsize;
  421.         fseek(fp, (long)4, SEEK_CUR);
  422.         fread(&skipper,sizeof(int),1,fp);            /* get file name len */
  423.         fread(&hsize,sizeof(int),1,fp);             /* get extra len */
  424.         file[count]->size+=hsize;
  425.         if(feof(fp)) break;
  426.         file[count]->name = malloc(skipper+1);
  427.         demand(file[count]->name!=NULL, out of memory!);
  428.         fgets(file[count]->name,skipper+1,fp);       /* get file name len */
  429.         fseek(fp,file[count]->size, SEEK_CUR);
  430.         file[count]->size+=skipper+30;
  431.         skip+=file[count]->size;
  432.         file[count]->filenum=0;
  433.         count++;
  434.         }
  435. else if(fsize==0x02014b50)   /* verify header info CENTRALDIR*/
  436.     {
  437.         file[count2]->position2=skip;              /* save file position */
  438.         fseek(fp, (long)24, SEEK_CUR);
  439.         fread(&fsize2,sizeof(int),1,fp);                  /* get file name size */
  440.         if(feof(fp)) break;
  441.         fread(&skipper,sizeof(int),1,fp);            /* get extra len */
  442.         if(feof(fp)) break;
  443.         fread(&hsize,sizeof(int),1,fp);             /* get comment len */
  444.         if(feof(fp)) break;
  445.         fseek(fp,(long)8, SEEK_CUR);
  446.         fread(&startdir,sizeof(long),1,fp);             /* get position */
  447.         while(file[rotaten]->position!=startdir)
  448.             rotaten = (rotaten+1) % count;
  449.         file[rotaten]->size2=hsize+skipper+fsize2+46;
  450.         file[rotaten]->size+=file[rotaten]->size2;
  451.         fseek(fp, (long)fsize2+skipper+hsize, SEEK_CUR);
  452.  
  453.         if(feof(fp)) break;
  454.         skip+=file[rotaten]->size2;
  455.         count2++;
  456.         }
  457. else if(fsize==0x06054b50)   /* verify header info ENDOFCENTRALDIR*/
  458.     {
  459.         fsize=skip;                                  /* save file position */
  460.         demand(count==count2, ZIP file is damaged);
  461.         fseek(fp, (long)16, SEEK_CUR);
  462.         fread(&fsize2,sizeof(int),1,fp);                  /* get file name size */
  463.         if(feof(fp)) break;
  464.         fseek(fp, (long)fsize2, SEEK_CUR);
  465.         break;
  466.         }
  467. else demand(1==0, ZIP file is damaged);
  468.  }
  469. }
  470. fclose(fp);
  471. if(count<2) {
  472.     printf("%s only contains one file!\n",ifile);
  473.     puts("File cannot be sized!  Use a physical file splitting utility");
  474.     exit(1);
  475.     }
  476. sortfs();   /*** Sort file names by size ***/
  477. printf("...sizing to %lu bytes\n",tsize);
  478.   if(!strcmp(saveext,".LZH") && tsize<=file[0]->size) {
  479.     printf("Error: Impossible to size archive to %lu bytes.\n",tsize);
  480.     printf("%s contains a file, %s, that is %lu bytes compressed.\n",ifile\
  481.     ,file[0]->name,file[0]->size);
  482.     printf("Target file size must be at least %lu bytes to accomodate this file.\n"\
  483.     ,file[0]->size+1);
  484.     printf("If you require a %lu byte file size use a physical file splitting utility\n",tsize);
  485.   exit(1);
  486.   }
  487. if(!strcmp(saveext,".ARJ") && tsize < file[0]->size+4+file[1]->size) {
  488.     printf("Error: Impossible to size archive to %lu bytes.\n",tsize);
  489.     printf("%s contains a file, %s, that is %lu bytes compressed.\n",ifile\
  490.     ,file[1]->name,file[1]->size);
  491.     printf("Target file size must be at least %lu bytes to accomodate this file\n"\
  492.     ,file[0]->size+4+file[1]->size);
  493.     printf("If you require a %lu byte file size use a physical file splitting utility\n",tsize);
  494.   exit(1);
  495.   }
  496. if(!strcmp(saveext,".ZIP") && tsize < file[0]->size+22+fsize2) {
  497.     printf("Error: Impossible to size archive to %lu bytes.\n",tsize);
  498.     printf("%s contains a file, %s, that is %lu bytes compressed.\n",ifile\
  499.     ,file[0]->name,file[0]->size);
  500.     printf("Target file size must be at least %lu bytes to accomodate this file\n"\
  501.     ,file[0]->size+22+fsize2);
  502.   printf("If you require a %lu byte file size use a physical file splitting utility\n",tsize);
  503.   exit(1);
  504.   }
  505. max=0;
  506. /************************* Assign subfiles ****************************/
  507. if(!strcmp(ext,".ARJ"))       for(j=0;j<255;nsize[j++]=file[0]->size+4);
  508. else if(!strcmp(ext,".ZIP"))  for(j=0;j<255;nsize[j++]=22+fsize2);
  509. else if(!strcmp(ext,".LZH"))  for(j=0;j<255;nsize[j++]=1);
  510. for(j=0;j<count;j++) {
  511.     subfile=0;
  512.     while(!file[j]->filenum) {
  513.         if(nsize[subfile]+file[j]->size <= tsize ) {
  514.             nsize[subfile]+=file[j]->size;
  515.             file[j]->filenum = subfile;
  516.             if(subfile>max) max=subfile;
  517.             }
  518.         else {
  519.             subfile++;
  520.             if(subfile>254) puts("Can't create more than 254 subfiles!");
  521.             demand(subfile<=254, Target file size too small - Use a larger target size);
  522.             }
  523.     }
  524. }
  525. /********************* Write Subfiles ***********************************/
  526. if(max<2) {puts("Nothing to do!");exit(0);}
  527. if(argc==4)
  528.     {
  529.     flags=fnsplit(argv[2],drive,dir,oname,ext);
  530.     if(!(flags & FILENAME)) strncpy(oname,iname,8);
  531.     }
  532. else
  533.     {
  534.     trunc_flag=1;
  535.     strncpy(oname,iname,7);  /** assume source name ***/
  536.     }
  537.  
  538. if(max<10)       sprintf(suffix,"%1i",(short)max);
  539. else if(max<100) sprintf(suffix,"%02i",(short)max);
  540. else             sprintf(suffix,"%03i",(short)max);
  541.  
  542. while(strlen(oname)+strlen(suffix)>8)
  543.     {
  544.     if(!trunc_flag)
  545.         {
  546.         puts("  **** Warning: Output filename prefix had to be truncated ****");
  547.         trunc_flag=1;
  548.         }
  549.     oname[strlen(oname)-1]=NULL;
  550.     }
  551. fnmerge(prefix,drive,dir,oname,"");
  552. fp=fopen(ifile,"rb");
  553. demand(fp!=NULL,"Unable to open source file");
  554. for(j=0;j<max;j++) {
  555.     if(max<10)       sprintf(suffix,"%1i",j+1);
  556.     else if(max<100) sprintf(suffix,"%02i",j+1);
  557.     else             sprintf(suffix,"%03i",j+1);
  558.     strcpy(temp,prefix);
  559.     strcat(temp,suffix);
  560.     strcat(temp,saveext);
  561.     sfp=fopen(temp,"rb");
  562.     if(sfp!=NULL) {
  563.         fclose(sfp);
  564.         if(!ovrwrt) {
  565.         do {
  566.           printf("\nFile %s exists, overwrite(Y/N/G)?",temp);
  567.           ans=getche();
  568.             }while(!strchr("YyNnGg", ans));
  569.         puts("\n");
  570.         if(strchr("Gg",ans)) ovrwrt=1;
  571.         if(strchr("Nn",ans)) exit(0);
  572.         }
  573.         demand(!remove(temp), Unable to overwrite file);
  574.         }
  575.     sfp=fopen(temp,"wb");
  576.     demand(sfp!=NULL,Unable to open output file);
  577.     demand(!ferror(sfp),Write error);
  578.     setvbuf(sfp,outbuf,_IOFBF,BSIZE);
  579.     _setcursortype(_NOCURSOR);
  580.     printf("...writing file %s - ",temp);
  581.     for(k=0;k<count;k++) {
  582.         if(file[k]->filenum!=j+1) continue;
  583.         if(k==0 && !strcmp(saveext,".ARJ")) file[0]->filenum++;
  584.         str_len=strlen(file[k]->name);
  585.         clreol();
  586.         printf("%s",file[k]->name);
  587.         while(str_len>0) {
  588.             printf("\b");
  589.             str_len--;
  590.             }
  591.         fseek(fp, file[k]->position, SEEK_SET);
  592.         demand(!ferror(fp), Read error);
  593.         bcount=file[k]->size;
  594.         if(!strcmp(saveext,".ZIP")) {
  595.             bcount-=file[k]->size2;
  596.             file[k]->position=total_size; }
  597.         total_size+=bcount;
  598.         while(bcount) {
  599.         if(bcount>=BUF_SIZ) {
  600.             demand(fread(buffer,1,BUF_SIZ,fp)==BUF_SIZ,Read error);
  601.             demand(fwrite(buffer,1,BUF_SIZ,sfp)==BUF_SIZ,Write error);
  602.             demand(!ferror(sfp),Write error);
  603.             bcount-=BUF_SIZ;
  604.             }
  605.         else {
  606.             demand(fread(buffer,1,bcount,fp)==bcount,Read error);
  607.             demand(fwrite(buffer,1,bcount,sfp)==bcount,Write error);
  608.             demand(!ferror(sfp),Write error)
  609.             bcount=0;
  610.             }
  611.  
  612.             }
  613.         }
  614.         if(!strcmp(saveext,".LZH")) {
  615.             fputc(0,sfp);
  616.             total_size++;
  617.             demand(!ferror(sfp),Write error);
  618.             }
  619.         if(!strcmp(saveext,".ARJ")) {
  620.             fputc(0x60,sfp);
  621.             fputc(0xEA,sfp);
  622.             fputc(0x00,sfp);
  623.             fputc(0x00,sfp);
  624.             total_size+=4;
  625.             demand(!ferror(sfp),Write error);
  626.             }
  627.         if(!strcmp(saveext,".ZIP")) {          /* Write Central ZIP dir */
  628.             count2=0;
  629.             startdir=total_size;
  630.             for(k=0;k<count;k++) {
  631.             if(file[k]->filenum!=j+1) continue;
  632.             fseek(fp, file[k]->position2, SEEK_SET);
  633.             demand(!ferror(fp), Read error);
  634.             demand(fread(buffer,1,42,fp)==42,Read error);
  635.             demand(fwrite(buffer,1,42,sfp)==42,Write error);
  636.             demand(!ferror(sfp),Write error)
  637.             demand(fwrite(&(file[k]->position),sizeof(long),1,sfp)==1,Write error);
  638.             demand(!ferror(sfp),Write error)
  639.             fseek(fp,(long)4,SEEK_CUR);
  640.             demand(fread(buffer,file[k]->size2-46,1,fp)==1,Read error);
  641.             demand(fwrite(buffer,file[k]->size2-46,1,sfp)==1,Write error);
  642.             demand(!ferror(sfp),Write error)
  643.             total_size+=file[k]->size2;
  644.             count2++;
  645.             }
  646.             dirsize=total_size-startdir;
  647.             fseek(fp, fsize, SEEK_SET);                   /* write end of dir */
  648.             demand(!ferror(fp), Read error);
  649.             demand(fread(buffer,1,8,fp)==8,Read error);            /* 8 bytes */
  650.             demand(fwrite(buffer,1,8,sfp)==8,Write error);
  651.             demand(!ferror(sfp),Write error)
  652.             demand(fwrite(&count2,sizeof(int),1,sfp)==1,Write error);
  653.             demand(!ferror(sfp),Write error);
  654.             demand(fwrite(&count2,sizeof(int),1,sfp)==1,Write error);
  655.             demand(!ferror(sfp),Write error);
  656.             demand(fwrite(&dirsize,sizeof(long),1,sfp)==1,Write error);
  657.             demand(!ferror(sfp),Write error);
  658.             demand(fwrite(&startdir,sizeof(long),1,sfp)==1,Write error);
  659.             demand(!ferror(sfp),Write error);
  660.             demand(fwrite(&fsize2,sizeof(int),1,sfp)==1,Write error);
  661.             demand(!ferror(sfp),Write error);
  662.             fseek(fp, (long)14, SEEK_CUR);
  663.             demand(fread(buffer,1,fsize2,fp)==fsize2,Read error);
  664.             demand(fwrite(buffer,1,fsize2,sfp)==fsize2,Write error);
  665.             demand(!ferror(sfp),Write error)
  666.             total_size+=22+fsize2;
  667.         }
  668.         fflush(sfp);
  669.         fclose(sfp);
  670.         demand(!ferror(sfp),Write error);
  671.         clreol();
  672.         printf("%7lu bytes\n",total_size);
  673.         _setcursortype(_NORMALCURSOR);
  674.         total_size=0;
  675.     }
  676. fclose(fp);
  677. }
  678.  
  679. /****************** SORTFS routine to sort files ***************************/
  680. void sortfs(void) {
  681.     int i,j,k=1;
  682.     record *temp;
  683.     if(!strcmp(saveext,".ARJ")) k=2;
  684.     for(i=k;i<count;i++) {
  685.         j=i;
  686.         temp=file[j];
  687.         while(j>k-1 && file[j-1]->size < temp->size) {
  688.           file[j]=file[j-1];
  689.           j--;
  690.           }
  691.         file[j]=temp;
  692.     }
  693. }
  694. /********************** HELP write help screen ****************************/
  695. void help(void) {
  696. /* Print help screen */
  697. puts("\n\
  698. LSIZE 2.5                  Archive File Sizer                       1-18-94\n\
  699. by Lawrence S. Lewis                                        Willingboro, NJ\n\
  700. \n  This utility program will take an archive file (ZIP/LZH/ARJ) and break it\
  701. \nup into smaller volumes.  You may specify the size of these smaller files.\
  702. \nThis is handy for backing up a large archive to a number of floppy\
  703. \ndiskettes.  The original file is left intact.  Each of the smaller files\
  704. \nwill be readable by the original archive program.  This program will work\
  705. \nwith archives created with LHA.EXE v2.13, ARJ.EXE v2.41, and PKZIP v2.04g. \
  706. \n\nSyntax:   LSIZE   SourceFile   [TargetPrefix]   MaxSize\n\
  707. \n         SourceFile  = name of the archive to be broken up.\
  708. \n       TargetPrefix  = the prefix of the files to be created.\
  709. \n                     = default prefix is source name.\
  710. \n             MaxSize = maximum size(in bytes) of each output file.\
  711. \n                     = also accepts size: 1.44M, 720K, 1.2M, or 360K\
  712. \nExamples:  LSIZE month.lzh day 720K  or  LSIZE month c:\\archive 1.44M\
  713. \n       The first command would split up the file MONTH.LZH into smaller\
  714. \n       files called: DAY1.LZH, DAY2.LZH, DAY3.LZH, DAY4.LZH... Each file\
  715. \n       will be small enough to fit on a 720K floppy disk.");
  716. exit(0);
  717. }