home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / util / arc / lino / src / lino.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-13  |  36.3 KB  |  1,447 lines

  1.  
  2.  
  3. /* lino.c (main) */
  4. /* AZTEC_C 5.x: cc -md -sa lino / ln lino xpklib checksum -lc */
  5. /* SAS_C 6.x: sc OPTTIME OPTIMIZE link lino checksum.asm */
  6.  
  7.  
  8.  
  9. #include <exec/types.h>
  10. #include <exec/memory.h>
  11. #include <libraries/dos.h>
  12. #include <stdio.h>
  13.  
  14. #ifndef AZTEC_C
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <proto/exec.h>
  18. #include <proto/dos.h>
  19. #else
  20. #include <functions.h>
  21. #endif
  22.  
  23. #include <inc/lin.h>  /* 'inc' is your subdirectory of include */
  24.  
  25.  
  26.  
  27. #define UB UBYTE
  28. #define US USHORT
  29. #define UL ULONG
  30.  
  31. /* keys */
  32. #define K_LSHFT   61
  33. #define K_RSHFT   63
  34. #define K_DELAY    8
  35.  
  36. /* file type */
  37. #define EXPAND       0
  38. #define COMPRESS   1
  39. #define DATAFILE   1
  40. #define EXECUTABLE 2
  41.  
  42.  
  43. /* error codes */
  44.  
  45. #define UPPER_ERR       6
  46.  
  47. #define ERR_LOCK       5
  48. #define ERR_OPEN       4
  49. #define ERR_WRITE       3
  50. #define ERR_READ       2
  51. #define X_INFO           1
  52. /* XPK-ERROR-CODES from 0 to -32 */
  53. #define ERR_EXECUTABLE     -33
  54. #define ERR_DATAFILE     -34
  55. #define ERR_TOO_SMALL     -35
  56. #define ERR_PATTERN     -36
  57. #define ERR_PATTERN_2     -37
  58. #define ERR_NO_PRINTER     -38
  59. #define ERR_WRONG_PACKER -39
  60. #define ERR_PROT     -40
  61. #define ERR_DELETE     -41
  62.  
  63. #define LOWER_ERR     -42
  64.  
  65. #define MAX_ERRS (UPPER_ERR-LOWER_ERR)
  66. #define BLEVEL          -17  /* ERR > BLEVEL will cause a break */
  67.  
  68. #define NO_PATTERN     0
  69. #define PATTERN        1
  70. #define NO_MATCH       0
  71. #define MATCH           1
  72. #define NO_CUT       (UB)0
  73. #define CUT       (UB)1
  74. #define PACKED           1
  75.  
  76. #define MIN_SIZE     250L    /* minimal size of file */
  77. #define MAX_SIZE  0x7fffffff /* maximal size of file */
  78. #define EPU_MIN      130L    /* f. EPU    */
  79. #define MARGIN         256L
  80.  
  81.  
  82. /* f. F_HEADER->flags (XPK-Format) */
  83. /* flag1 */
  84. #define LONGHDR   0x01000000
  85. #define PASSWORD  0x02000000
  86.  
  87.  
  88. #define MAX_DIRS       10
  89. #define MAX_FILES      40
  90. #define MAX_FLEN       32   /* max.len of filename */
  91. #define MIN_CHUNK    1   /* 1 KB */
  92. #define MAX_CHUNK 2097152   /* MAX_CHUNK*KB = 2^31 */
  93. #define CHUNK_DEF      32L
  94. #define CHUNK_SUBDEF    0   /* will get default chunksize of sublib */
  95. #define MODE_SUBDEF    -1   /* - || - default mode - || - */
  96. #define SMARG        5   /* OutBuffer += (OutBuffer >> smarg) */
  97.  
  98. #define FORMAT 0x4c494e4f   /* 'LINO' */
  99.  
  100.  
  101. #define XRead(to,len) if(Read((BPTR)lock,(char *)(to),\
  102.    (long)(len))!=(long)(len)){ Close((BPTR)lock); return(ERR_READ); }
  103.  
  104. #define Low(x) (((x)>0x40 && (x)<0x5b) ? (x) | 0x20 : x)
  105. #define Cap(x) (((x)>0x60 && (x)<0x7b) ? (x) & 0xdf : x)
  106.  
  107. #define act_ticks clo.ds_Minute*3000+clo.ds_Tick
  108. struct DateStamp clo;
  109. int timer=0,i_time=0,stime;
  110.  
  111.  
  112. #define XPK_COMPAT 4L
  113.  
  114. typedef struct C_Header {
  115.    long clen;
  116.    long dlen;
  117. } CH_HEAD;
  118. CH_HEAD cheadv,*chead;
  119. #define CHUNK_HEAD (long)sizeof(CH_HEAD)
  120. #define SHORT_HEAD  4L
  121.  
  122. typedef struct F_Header {
  123.    long head;  // XPKF/LINO
  124.    long clen;
  125.    long pack;  // LIN1,ZENO,...
  126.    long dlen;
  127.    char first16[16];  // first 16 bytes of original file
  128.    long flags;     // differs from XPK file format
  129.    long chksum;  //        -  ||  -
  130.    long cchunk;
  131.    long dchunk;
  132. } FHEAD;
  133. FHEAD fheadv,*fhead;
  134. #define XHEAD (long)sizeof(FHEAD)
  135. #define HEAD (XHEAD-CHUNK_HEAD)
  136.  
  137.  
  138.  
  139. struct xfile{
  140.    char fname[MAX_FLEN];
  141.    long prot;
  142.    long len;
  143. };
  144. struct dfile{
  145.    char dname[MAX_FLEN];
  146. };
  147.  
  148.  
  149. FILE *Out = stdout;
  150.  
  151.  
  152. XPARAMS xpav,*xpar;
  153.  
  154. struct Library *XpkSubBase;
  155. char xpklib[40];
  156.  
  157. long dlen,clen,csum,dsum,chunk,cmin,cover,pack,passw,format,smarg,
  158.      longhdr,packed,minsize,maxchunk;
  159. US count,fcon;
  160. char readfile[256],writefile[256],owfile[256],sfile[40],wpath[256],
  161.      suff[32],pstr[32],crst[5],
  162.      pat,pflag,pcom,prio,info,mode,blevel,fc16[16],
  163.      fh16[16]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 },
  164.      patt[MAX_FLEN],ca[MAX_FLEN],na[MAX_FLEN],fa[MAX_FLEN],ta[MAX_FLEN];
  165. UB hid,type,out,ex,exe,pri,all,wf,ident,pre,epu,time,kilo,oflow,
  166.    *adr=0L, *xkey=(UB*)0xbfec01,*xmouse=(UB*)0xbfe001;
  167. UB errstr[MAX_ERRS-1][30] = {
  168.    "Can't delete tempfile",
  169.    "File is protected",
  170.    "Wrong packer",
  171.    "Can't open printer",
  172.    "File/Path missing",    // Pattern_err_2
  173.    "Wrong pattern",        // Pattern_err_1
  174.    "File is too small",
  175.    "No Exe file",
  176.    "No Data file",
  177.    "Sorry, wrong password",  // WRONGPW (XPK -32)
  178.    "",
  179.    "",
  180.    "",
  181.    "Can't find info",  // NOINFO
  182.    "",
  183.    "",
  184.    "",
  185.    "",
  186.    "File is not packed",  // NOTPACKED
  187.    "File already packed", // PACKED
  188.    "",
  189.    "",
  190.    "User-break",  // ABORTED
  191.    "",
  192.    "Can't pack file",  // EXPANSION
  193.    "",
  194.    "Can't find packing-library",  // MISSINGLIB
  195.    "packed file is corrupt",  // CORRUPTPKD
  196.    "Password required",  // NEEDPASSWD
  197.    "",
  198.    "",
  199.    "",
  200.    "",
  201.    "",
  202.    "No memory",  // NOMEM
  203.    "",
  204.    "Wrong checksum",  // CHECKSUM
  205.    "",
  206.    "IO-Error", // IOERRIN
  207.    "",
  208.    "",
  209.    "",  // OK     (XPK 0)
  210.    "",  // f.e. INFO
  211.    "Read-Error",
  212.    "Write-Error",
  213.    "Open-Error",
  214.    "Lock-Error",
  215. };
  216.  
  217.  
  218.  
  219.  
  220.  
  221. long GetDir(char *path);
  222. UB parent(char *path,UB cut);
  223. char getwc(char *name);
  224. char pmatch(char text[]);
  225. long work(char *sfile,char *readfile);
  226. long file_check(char *filename);
  227. long xload(char *readfile,char *writefile,long len);
  228. long eload(char *readfile,char *writefile);
  229. long xsave(char *readfile,char *writefile,long len,
  230.    long chunk,char mode,long pack,UB out);
  231. long xcopy(char *readfile,char *writefile,long len,long chunk);
  232. long esave(char *readfile,char *writefile,long *clen,long len,
  233.       long chunk,char mode);
  234. long change_name(char *readfile, char *writefile);
  235. void write_err(long xerr);
  236. long breaktest(void);
  237.  
  238.  
  239. void START (void);
  240. void STOP (void);
  241. void I_START (void);
  242. void I_STOP (void);
  243. void PRINT_TIME(long len);
  244.  
  245. long checksum(long *adr,long len);  // see checksum.asm
  246.  
  247.  
  248. #ifdef AZTEC_C
  249. void _wb_parse(){}
  250. void _abort(){}
  251. #endif
  252.  
  253.  
  254. void main(int argc,char *argv[])
  255. {
  256.    char c,d,par,path[256];
  257.    UB len;
  258.    US i,j;
  259.    long xerr;
  260.  
  261.    if(argc == 1 || (argc == 2 &&  *(argv[1]) == '?')){
  262.       fprintf(Out,"%s <readfile> [options]!!\n",argv[0]);
  263.       fprintf(Out,"  -w Write-file/path\n");
  264.       fprintf(Out,"  -s Suffix\n");
  265.       fprintf(Out,"  -m Method (4 letters)\n");
  266.       fprintf(Out,"  -e Efficiency/mode (0-100)\n");
  267.       fprintf(Out,"  -c Chunksize (KB def: 32)\n");
  268.       fprintf(Out,"  -p Password\n");
  269.       fprintf(Out,"  -z Minimal filesize (def: 250 bytes)\n");
  270.       fprintf(Out,"  -y Taskpriority (def: -5)\n");
  271.       fprintf(Out,"  -l Errorlevel (-42 to +5, def:-17)\n");
  272.       fprintf(Out,"  -b overflow buffer (3-5 def:5)\n");
  273.  
  274.       fprintf(Out,"  -u  Expansion                  ");
  275.       fprintf(Out,"  -h  Hidden password entry\n");
  276.       fprintf(Out,"  -x  Executable files only      ");
  277.       fprintf(Out,"  -d  Data files only\n");
  278.       fprintf(Out,"  -n  No output                  ");
  279.       fprintf(Out,"  -o  Output to printer\n");
  280.       fprintf(Out,"  -a  All subdirectories         ");
  281.       fprintf(Out,"  -k  Speed in kb/sec\n");
  282.       fprintf(Out,"  -i  Info about packer          ");
  283.       fprintf(Out,"  -t  Output of time\n");
  284.       fprintf(Out,"  -f  Packed file is allowed to be larger than original\n");
  285.  
  286.       fprintf(Out,"\nPattern matching: ?, #, #?(*), !(not)\n");
  287.       fprintf(Out,"Press left mousebutton and -Shft- to abort program!!!\n");
  288.  
  289.       fprintf(Out,"\nExamples\n");
  290.       fprintf(Out,"%s file -s .xp -m ZENO -c 64 -e 100\n",argv[0]);
  291.       fprintf(Out,"%s df0:back/!f#? -u -w dh0:tools/\n",argv[0]);
  292.       fprintf(Out,"%s -m LIN1.100 -p Aladdin file\n",argv[0]);
  293.  
  294.       exit(0L);
  295.    }
  296.  
  297.  
  298.    strcpy(crst,"LINO");   par = 0;
  299.    xpar = &xpav;  fhead = &fheadv;  chead = &cheadv;
  300.    suff[0] = 0;  pstr[0] = 0;  path[0] = 0;
  301.    clen = 0L;  dlen = 0L;  cmin = 0L;
  302.    pre = 0;  info = 0;     epu = 0;
  303.    XpkSubBase = 0L;  chunk = CHUNK_SUBDEF;
  304.    passw = 0L;     minsize = MIN_SIZE;
  305.    prio = -5;    pcom = 0;
  306.    pri = 0;  mode = MODE_SUBDEF;
  307.    hid = 0;  wf = 0;
  308.    type = COMPRESS;  ex = 0;  out = 1;
  309.    all = 0;  count = 0;
  310.    pat = NO_PATTERN;  pflag = MATCH;
  311.    time = 0;  kilo = 0;  oflow = 0;  blevel=BLEVEL;
  312.  
  313.  
  314.    i = 1;
  315.    while(i<argc){
  316.       d = Low(*argv[i]);  c = *(argv[i]+1);
  317.       if(d == '-'){
  318.      i++;    d = Low(*argv[i]);
  319.      if(c == 'w'){ strcpy(owfile,argv[i]);  wf=1; }
  320.      else if(c == 's') strcpy(suff,argv[i]);
  321.      else if(c == 'm'){
  322.         crst[0]=Cap(*(argv[i]));  pack = crst[0]<<24;
  323.         crst[1]=Cap(*(argv[i]+1));  pack += crst[1]<<16;
  324.         crst[2]=Cap(*(argv[i]+2));  pack += crst[2]<<8;
  325.         crst[3]=Cap(*(argv[i]+3));  pack += crst[3];
  326.         crst[4]='\0';
  327.         if(*(argv[i]+4) == '.'){
  328.            mode = 0;  j = 5;
  329.            while((c = *(argv[i]+j)) >= '0'){
  330.           mode = mode*10+c-48;    j++;
  331.            }
  332.            if(mode<0 || mode>100) mode=-1;
  333.         }
  334.      }
  335.      else if(c == 'e' && d >= '0' && d <= '9'){
  336.         mode = (char)atoi(argv[i]);
  337.         if(mode<0 || mode>100) mode=MODE_SUBDEF;
  338.      }
  339.      else if(c == 'c' && d >= '0' && d <= '9'){
  340.         chunk = (long)atoi(argv[i]);
  341.         if(chunk < MIN_CHUNK) chunk = MIN_CHUNK;
  342.         if(chunk > MAX_CHUNK) chunk = MAX_CHUNK;
  343.      }
  344.      else if(c == 'p'){
  345.         if(strlen(argv[i])>=32) strncpy(pstr,argv[i],31);
  346.         else strcpy(pstr,argv[i]);
  347.         passw = (long)PASSWORD;
  348.      }
  349.      else if(c == 'z' && d >= '0' && d <= '9'){
  350.         minsize = (long)atoi(argv[i]);
  351.         if(minsize<MIN_SIZE || minsize>MAX_SIZE) minsize=MIN_SIZE;
  352.      }
  353.      else if(c == 'y'){
  354.         prio = atoi(argv[i]);
  355.         if(prio<-50 || prio>50) prio=-5;
  356.      }
  357.      else if(c == 'l'){
  358.         blevel = atoi(argv[i]);
  359.         if(blevel<-42 || blevel>5) blevel=BLEVEL;
  360.      }
  361.      else if(c == 'b'){
  362.         smarg = atoi(argv[i]);
  363.         if(smarg<3 || smarg>5) smarg=SMARG;
  364.      }
  365.      else{
  366.         i--;
  367.         if(c == 'u') type = EXPAND;
  368.         else if(c == 'd') ex = DATAFILE;
  369.         else if(c == 'x') ex = EXECUTABLE;
  370.         else if(c == 'h') hid = 1;
  371.         else if(c == 'n') out = 0;
  372.         else if(c == 'o') pri = 1;
  373.         else if(c == 'a') all = 1;
  374.         else if(c == 'k') kilo = 1;
  375.         else if(c == 'i') info = 1;
  376.         else if(c == 't') time = 1;
  377.         else if(c == 'f') oflow = 1;
  378.         else i++;
  379.      }
  380.       }
  381.       else{
  382.      if(!par){ strcpy(path,argv[i]);  par = i; }
  383.       }
  384.       i++;
  385.    }
  386.  
  387.  
  388.    if(pri){
  389.      if(!(Out = fopen("PRT:","w+"))){
  390.     write_err(ERR_NO_PRINTER);
  391.     exit(0L);
  392.      }
  393.    }
  394.  
  395.  
  396.    if(info){
  397.       work((char*)"",(char*)"");
  398.       if(pri) fclose(Out);
  399.       exit(0L);
  400.    }
  401.  
  402.    if(!wf && suff[0]==0) ident=1;
  403.  
  404.    if(chunk) chunk = (chunk<<10)-4L;
  405.  
  406.  
  407.    if(path[0] == 0){ write_err(ERR_PATTERN_2);  exit(0L); }
  408.  
  409.    len = parent(path,NO_CUT);
  410.    strncpy(patt,argv[par]+strlen(argv[par])-len,len);
  411.  
  412.    pat = getwc(patt);
  413.  
  414.    if(pat == MATCH) parent(path,CUT);
  415.  
  416.    if(path[0] == 0){ write_err(ERR_PATTERN_2); exit(0L); }
  417.  
  418.    if(pat > PATTERN){
  419.       write_err(ERR_PATTERN);
  420.       exit(0L);
  421.    }
  422.  
  423.    if(hid){                   // hidden entry
  424.       printf("\033[30m\033[40m");
  425.       scanf("%s",pstr);
  426.       printf("\033[31m\n");
  427.       passw = (long)PASSWORD;
  428.    }
  429.  
  430.    xpar->Password = (APTR)pstr;
  431.  
  432.  
  433.    if(time) START();
  434.  
  435.  
  436.    prio = SetTaskPri(FindTask(0L),prio);
  437.  
  438.    xerr = GetDir(path);
  439.  
  440.    prio = SetTaskPri(FindTask(0L),prio);
  441.  
  442.    if(xerr != XPKERR_OK) write_err(xerr);
  443.  
  444.    if(out && count>1){
  445.       if(type==COMPRESS){
  446.      cmin = ((dsum-csum)*1000)/dsum;
  447.      fprintf(Out,"%d files compressed:  %ld -> %ld bytes (%ld.%ld%%)\n",count,dsum,csum,cmin/10,cmin-(cmin/10)*10);
  448.       }
  449.       else fprintf(Out,"%d files expanded:  %ld -> %ld bytes\n",count,csum,dsum);
  450.    }
  451.  
  452.    if(pri) fclose(Out);
  453.  
  454.    if(time){
  455.       STOP();
  456.       PRINT_TIME(dsum);
  457.    }
  458.  
  459. }
  460.  
  461.  
  462.  
  463. long GetDir(char *path)
  464. {
  465.    struct xfile *Fcopy,*FList;
  466.    struct dfile *Dcopy,*DList;
  467.    struct FileInfoBlock *fib = 0L;
  468.    BPTR lock = 0L;
  469.    long xerr;
  470.    US dnum=0,fnum=0,maxfiles=MAX_FILES,maxdirs=MAX_DIRS;
  471.    UB len;
  472.  
  473.  
  474.    if(!(FList = (struct xfile*)calloc((long)
  475.     sizeof(struct xfile),MAX_FILES)))
  476.       return(XPKERR_NOMEM);
  477.    if(!(DList = (struct dfile*)calloc((long)
  478.     sizeof(struct dfile),MAX_DIRS))){
  479.       xerr = XPKERR_NOMEM;  goto exidus; }
  480.    if(!(fib = AllocMem((long)sizeof(struct FileInfoBlock),0L))){
  481.       xerr = XPKERR_NOMEM;  goto exidus; }
  482.    if(!(lock = Lock(path,ACCESS_READ))){
  483.       xerr = ERR_LOCK;    goto exidus; }
  484.    if(!(Examine((BPTR)lock,(struct FileInfoBlock*)fib))){
  485.       xerr = XPKERR_IOERRIN;  goto exidus; }
  486.  
  487.    do{
  488.       if(fib->fib_DirEntryType > 0){  //directory
  489.      if(all){
  490.         if(!dnum){
  491.            len = path[strlen(path)-1];
  492.            if(len != '/' && len != ':'){
  493.           strcat(path,"/");
  494.           if(wf) strcat(wpath,"/");
  495.            }
  496.         }
  497.         else strcpy(DList[dnum].dname,fib->fib_FileName);
  498.      }//all
  499.      if(++dnum % maxdirs == maxdirs-1){
  500.         if(!(Dcopy = (struct dfile*)calloc((long)
  501.            sizeof(struct dfile),dnum+MAX_DIRS+1))){
  502.         xerr = XPKERR_NOMEM;
  503.         goto exidus;
  504.         }
  505.         movmem(DList,Dcopy,(long)(dnum+1)*sizeof(struct dfile));
  506.         free(DList);  DList = Dcopy;
  507.         maxdirs += MAX_DIRS;
  508.      }
  509.       }
  510.       else{   // file
  511.      if(pat == PATTERN) pflag = pmatch(fib->fib_FileName);
  512.      if(pflag){
  513.         if(fib->fib_Size>=minsize || type==EXPAND || wf){
  514.            strcpy(FList[fnum].fname,fib->fib_FileName);
  515.            FList[fnum].len = fib->fib_Size;
  516.            FList[fnum].prot = fib->fib_Protection;
  517.            fnum++;
  518.            if(!dnum){
  519.           parent(path,CUT);
  520.           if(all && wf) parent(wpath,CUT);
  521.           goto next;
  522.            }
  523.         }
  524.      }
  525.      if(fnum % maxfiles == maxfiles-1){
  526.         if(!(Fcopy = (struct xfile*)calloc((long)
  527.           sizeof(struct xfile),fnum+MAX_FILES+1))){
  528.         xerr = XPKERR_NOMEM;
  529.         goto exidus;
  530.         }
  531.         movmem(FList,Fcopy,(long)(fnum+1)*sizeof(struct xfile));
  532.         free(FList);  FList = Fcopy;
  533.         maxfiles += MAX_FILES;
  534.      }
  535.       }//else
  536.       if((xerr = breaktest()) != XPKERR_OK) goto exidus;
  537.  
  538.    }while(ExNext((BPTR)lock,(struct FileInfoBlock *)fib));
  539.  
  540. next:
  541.    UnLock((BPTR)lock);  lock = 0L;
  542.    FreeMem(fib,(long)sizeof(struct FileInfoBlock));  fib = 0L;
  543.    while(fnum>0){
  544.       fnum--;
  545.       strcpy(sfile,FList[fnum].fname);
  546.       strcpy(readfile,path);
  547.       strcat(readfile,FList[fnum].fname);
  548.       clen = dlen = FList[fnum].len;
  549.       if(!(FList[fnum].prot & 1) || !ident){
  550.      xerr = work(sfile,readfile);
  551.      if(ident) SetProtection(readfile,FList[fnum].prot);
  552.       }
  553.       else xerr = ERR_PROT;
  554.       if(xerr != XPKERR_OK){
  555.      if(all == 0 && xerr != XPKERR_OK && xerr>blevel) goto exidus2;
  556.      if(dnum == 0 || (xerr != XPKERR_PACKED && \
  557.       xerr != XPKERR_NOTPACKED)){
  558.          fprintf(Out,"%s  -  ",readfile);
  559.          write_err(xerr);
  560.       }
  561.       }
  562.       if((xerr=breaktest()) != XPKERR_OK) goto exidus2;
  563.    }
  564.    free(FList); FList = 0L;
  565.    if(all){
  566.       while(dnum>1){
  567.      dnum--;
  568.      strcat(path,DList[dnum].dname);
  569.      if(wf) strcat(wpath,DList[dnum].dname);
  570.      xerr = GetDir(path);
  571.      if(xerr != XPKERR_OK){
  572.         if(xerr>blevel) goto exidus2;
  573.         else write_err(xerr);
  574.      }
  575.      parent(path,CUT);
  576.      if(wf) parent(wpath,CUT);
  577.       }
  578.    }
  579.  
  580.    xerr = XPKERR_OK;
  581.  
  582. exidus:
  583.    if(fib)   FreeMem(fib,(long)sizeof(struct FileInfoBlock));
  584.    if(lock)  UnLock((BPTR)lock);
  585. exidus2:
  586.    if(FList) free(FList);
  587.    if(DList) free(DList);
  588.  
  589.    return(xerr);
  590. }
  591.  
  592.  
  593.  
  594. UB parent(char *path,UB cut)
  595. {
  596.    UB len = 0;
  597.  
  598.    char *ptr = path;
  599.    path += strlen(path) - 1;
  600.    do{
  601.       path--; len++;
  602.    }while(!((*path == '/')||(*path == ':')||(path<ptr)));
  603.    if(cut == CUT) *(path + 1) = '\0';
  604.  
  605.    return(len);
  606. }
  607.  
  608.  
  609. char getwc(char *name)
  610. {
  611.    short pp,pl,cn,last;
  612.    char c1,c2,flag=0,pattern[MAX_FLEN];
  613.  
  614.  
  615.    pp = 0;  pl = 1;
  616.  
  617.    if(name[0] == '!'){ pcom = 1; pp++; }
  618.    else pcom = 0;
  619.    while(name[pp] != '\0'){
  620.       if(name[pp] == '*'){
  621.      pattern[pl] = '#';  pl++;
  622.      pattern[pl] = '?';  flag = 1;
  623.       }
  624.       else if(name[pp]=='#' && name[pp+1]>='0' && name[pp+1]<='9'){
  625.      flag = 1;  cn = name[pp+1]-48;  last = pp+2;
  626.      if(name[pp+2]>='0' && name[pp+2]<='9'){
  627.         cn = cn*10+name[pp+2]-48;  last++;
  628.      }
  629.      if(cn+pp<=last){
  630.         if(cn) name[pp] = name[last];
  631.         c1 = pp+1;    c2 = cn+pp;
  632.         while(c1<c2){ name[c1] = name[c1-1];  c1++; }
  633.         c1 = last+1;  c2 = pp+cn;  cn = c1-c2;
  634.         while(name[c1]){ name[c1-cn] = name[c1]; c1++; }
  635.         name[c1-cn] = '\0';
  636.      }
  637.      else{
  638.         c1 = cn-last+pp-1;
  639.         if(c1+pp >= MAX_FLEN) c1 = MAX_FLEN-pp-1;
  640.         cn = MAX_FLEN-1; name[cn--] = '\0';  c2 = last+c1;
  641.         while(cn>c2){ name[cn] = name[cn-c1];  cn--; }
  642.         name[cn] = name[last];  c1 = cn--;
  643.         while(cn>=pp){ name[cn] = name[c1];  cn--; }
  644.      }
  645.      pattern[pl] = Low(name[pp]);
  646.       }
  647.       else{
  648.      pattern[pl] = Low(name[pp]);
  649.      if(!flag)
  650.         if(pattern[pl] == '#' || pattern[pl] == '?') flag=1;
  651.       }
  652.       pp++;  pl++;
  653.    }
  654.    if(!flag) return(NO_PATTERN);
  655.  
  656.    cn = pp = 1;  last = -1;  na[0] = 0;  pl--;
  657.    while(pp <= pl){
  658.       c1 = pattern[pp];
  659.       c2 = pattern[pp+1];
  660.       if(c1 == '#' && c2 == '\0') return(ERR_PATTERN);
  661.       if(c1 == '#' && c2 == '?'){
  662.      last = cn;  ta[cn] = 1;  pp++;
  663.       }
  664.       else{
  665.      if(c1 == '#'){
  666.         na[cn] = cn;  fa[cn] = cn+1;  ca[cn] = c2;
  667.         na[0] = 1;    pp++;
  668.      }
  669.      else if(c1 == '?'){
  670.         na[cn] = cn+1;  ca[cn] = c1;  fa[cn] = cn+1;
  671.      }
  672.      else{
  673.         na[cn] = cn+1;  ca[cn] = c1;  fa[cn] = last;
  674.      }
  675.      ta[cn] = (cn > fa[cn]) ? 0 : 1;
  676.      cn++;
  677.       }
  678.       pp++;
  679.    }
  680.    na[cn] = -2;  fa[cn] = last;
  681.    return(PATTERN);
  682. }
  683.  
  684.  
  685. char pmatch(char text[])
  686. {
  687.    short pp,pl,next;
  688.    char true=0;
  689.  
  690.    pp = 0;  next = 1;
  691.    pl = strlen(text);
  692.    while (pp < pl && next>0){
  693.       if(Low(text[pp]) == ca[next]) { pp++;  next = na[next]; }
  694.       else { pp += ta[next];  next = fa[next]; }
  695.    }
  696.    if(next>0) next = na[next+na[0]];
  697.    if(next == -2) true = 1;
  698.    if(next > 0)
  699.       if(fa[next] != -1 && pp<pl) true = 1;
  700.    if(pcom) true = 1-true;
  701.  
  702.    return(true);
  703. }
  704.  
  705.  
  706.  
  707. long work(char *sfile,char *readfile)
  708. {
  709.    char wdir,i,j;
  710.    long xerr;
  711.    XINFO *xinfo;
  712.    XMINFO *xminfo;
  713.  
  714.    if(!info){
  715.       if(dlen < XHEAD){
  716.      if(type == EXPAND) clen=1;
  717.       }
  718.       else{
  719.      xerr = file_check(readfile);
  720.      if(xerr == XPKERR_PACKED || xerr == XPKERR_NOTPACKED){
  721.         clen=1L;
  722.      }
  723.      else{
  724.         if(xerr != XPKERR_OK) return(xerr);
  725.      }
  726.       }
  727.  
  728.       if(wf){
  729.      strcpy(writefile,owfile);
  730.      if(all) strcat(writefile,wpath);
  731.      wdir = writefile[strlen(writefile)-1];
  732.      if(wdir == ':' || wdir == '/') strcat(writefile,sfile);
  733.       }
  734.       else strcpy(writefile,readfile);
  735.  
  736.       if(suff[0]){
  737.      if(type == COMPRESS) strcat(writefile,suff);
  738.      else{
  739.         i=strlen(writefile)-1;  j=strlen(suff)-1;
  740.         while(writefile[i]==suff[j] && i>1 && j>=0){ i--; j--; }
  741.         writefile[i+1] = '\0';
  742.      }
  743.       }
  744.       else if(ident) strcat(writefile,".lin_tempfile");
  745.  
  746.       if(clen == 1L)
  747.      return(xload(readfile,writefile,dlen)); //copy unpacked file
  748.       if(type == COMPRESS && dlen < minsize)
  749.      return(xsave(readfile,writefile,dlen,20000L,mode,pack,out));
  750.    }
  751.  
  752.    strcpy(xpklib,"xpk");
  753.    strcat(xpklib,crst);  strcat(xpklib,".library");
  754.    if(!(XpkSubBase=(struct Library*)OpenLibrary(xpklib,0L))){
  755.       strcpy(xpklib,"compressors/xpk");
  756.       strcat(xpklib,crst);  strcat(xpklib,".library");
  757.       if(!(XpkSubBase=(struct Library*)OpenLibrary(xpklib,0L)))
  758.      return(XPKERR_MISSINGLIB);
  759.    }
  760.    xinfo = (XINFO*)XpksPackerInfo();
  761.    if(xinfo == 0L){ xerr=XPKERR_NOINFO; goto werr; }
  762.  
  763.    if(info){
  764.       fprintf(Out,"\nXpkInfoVersion: %d\n",xinfo->XpkInfoVersion);
  765.       fprintf(Out,"LibVersion:     %d\n",xinfo->LibVersion);
  766.       fprintf(Out,"MasterVersion:  %d\n",xinfo->MasterVersion);
  767.       fprintf(Out,"ModesVersion:   %d\n",xinfo->ModesVersion);
  768.       fprintf(Out,"Name:           %s\n",xinfo->Name);
  769.       fprintf(Out,"LongName:       %s\n",xinfo->LongName);
  770.       fprintf(Out,"Description:    %s\n",xinfo->Description);
  771.       fprintf(Out,"ID:             %s\n",crst);  // (xinfo->ID);
  772.       fprintf(Out,"Flags:          ");
  773.       if(xinfo->Flags & 0x1) fprintf(Out,"PK_CHUNK  ");
  774.       if(xinfo->Flags & 0x2) fprintf(Out,"PK_STREAM  ");
  775.       if(xinfo->Flags & 0x4) fprintf(Out,"PK_ARCHIVE  ");
  776.       if(xinfo->Flags & 0x8) fprintf(Out,"UP_CHUNK  ");
  777.       if(xinfo->Flags & 0x10) fprintf(Out,"UP_STREAM  ");
  778.       if(xinfo->Flags & 0x20) fprintf(Out,"UP_ARCHIVE  ");
  779.       fprintf(Out,"\n                ");
  780.       if(xinfo->Flags & 0x80) fprintf(Out,"HOOKIO  ");
  781.       if(xinfo->Flags & 0x400) fprintf(Out,"CHECKING  ");
  782.       if(xinfo->Flags & 0x800) fprintf(Out,"PREREADHDR  ");
  783.       if(xinfo->Flags & 0x2000) fprintf(Out,"ENCRYPTION  ");
  784.       if(xinfo->Flags & 0x4000) fprintf(Out,"NEEDPASSWD  ");
  785.       if(xinfo->Flags & 0x8000) fprintf(Out,"MODES  ");
  786.       if(xinfo->Flags & 0x10000) fprintf(Out,"LOSSY");
  787.       fprintf(Out,"\nMaxPkInChunk:   %ld\n",xinfo->MaxPkInChunk);
  788.       fprintf(Out,"MinPkInChunk:   %ld\n",xinfo->MinPkInChunk);
  789.       fprintf(Out,"DefPkInChunk:   %ld\n",xinfo->DefPkInChunk);
  790.       fprintf(Out,"PackMsg:        %s\n",xinfo->PackMsg);
  791.       fprintf(Out,"UnpackMsg:      %s\n",xinfo->UnpackMsg);
  792.       fprintf(Out,"PackedMsg:      %s\n",xinfo->PackedMsg);
  793.       fprintf(Out,"UnpackedMsg:    %s\n",xinfo->UnpackedMsg);
  794.       fprintf(Out,"DefMode:        %d\n\n\n",xinfo->DefMode);
  795.       //fprintf(Out,"Pad:            %d\n\n\n",xinfo->Pad);
  796.  
  797.       xminfo = xinfo->ModeDesc;
  798.       do{
  799.      if(xerr = breaktest()) goto werr;
  800.      fprintf(Out,"Upto:          %ld\n",xminfo->Upto);
  801.      fprintf(Out,"Flags:         ");
  802.      if(xminfo->Flags & 1) fprintf(Out,"A3000SPEED  ");
  803.      if(xminfo->Flags & 2) fprintf(Out,"PK_NOCPU  ");
  804.      if(xminfo->Flags & 4) fprintf(Out,"UP_NOCPU");
  805.      fprintf(Out,"\nPackMemory:    %ld\n",xminfo->PackMemory);
  806.      fprintf(Out,"UnpackMemory:  %ld\n",xminfo->UnpackMemory);
  807.      fprintf(Out,"PackSpeed:     %ld\n",xminfo->PackSpeed);
  808.      fprintf(Out,"UnpackSpeed:   %ld\n",xminfo->UnpackSpeed);
  809.      fprintf(Out,"Ratio:         %d\n",xminfo->Ratio);
  810.      fprintf(Out,"ChunkSize:     %d\n",xminfo->ChunkSize);
  811.      fprintf(Out,"Description:   %s\n\n",xminfo->Description);
  812.  
  813.      xminfo = xminfo->Next;
  814.       }while(xminfo);
  815.  
  816.       xerr = X_INFO;  goto werr;
  817.    }
  818.  
  819.    if(!(xinfo->Flags & XPKIF_PK_CHUNK))
  820.       { xerr=ERR_WRONG_PACKER; goto werr; }
  821.    if(!passw && (xinfo->Flags & XPKIF_NEEDPASSWD))
  822.       { xerr=XPKERR_NEEDPASSWD; goto werr; }
  823.    cmin = xinfo->MinPkInChunk;
  824.  
  825.    if(type == COMPRESS){  // save
  826.       if(xinfo->Flags & XPKIF_PREREADHDR) pre=1;
  827.       if(mode==MODE_SUBDEF) mode = (char)xinfo->DefMode;
  828.       if(chunk==CHUNK_SUBDEF) chunk = xinfo->DefPkInChunk;
  829.       if(chunk==0L) chunk = CHUNK_DEF;
  830.       if(chunk>xinfo->MaxPkInChunk) chunk = xinfo->MaxPkInChunk;
  831.  
  832.       xerr = xsave(readfile,writefile,dlen,chunk,mode,pack,out);
  833.       if(xerr != XPKERR_OK) goto werr;
  834.    }
  835.    else{  // load
  836.       xerr = xload(readfile,writefile,clen);
  837.    }
  838.  
  839.  
  840. werr:
  841.    if(XpkSubBase) CloseLibrary(XpkSubBase);
  842.    return(xerr);
  843. }
  844.  
  845.  
  846.  
  847.  
  848.  
  849. long file_check(char *name)
  850. {
  851.    struct FileLock *lock;
  852.    long *lptr;        //    EPU
  853.    char *ptr;        //    EPU
  854.  
  855.  
  856.  
  857.    epu = 0;  longhdr = 0;
  858.    if(!(lock = (struct FileLock *)Open(name,MODE_OLDFILE))){
  859.       return(ERR_OPEN);
  860.    }
  861.    XRead(fhead,XHEAD);
  862.    Close((BPTR)lock);
  863.  
  864.    format = fhead->head;
  865.  
  866.    /* check if packed */
  867.  
  868.    if(format == 0x58504b46 || format == FORMAT){ // ('XPKF' || 'LINO')
  869.       if(type == COMPRESS) return(XPKERR_PACKED);
  870.       if(!passw && (fhead->flags & PASSWORD)) return(XPKERR_NEEDPASSWD);
  871.       lptr = (long*)fhead+4;
  872.       if(*lptr == 0x03f3 && ex == DATAFILE) return(ERR_EXECUTABLE);
  873.       if(*lptr != 0x03f3 && ex == EXECUTABLE) return(ERR_DATAFILE);
  874.       pack = fhead->pack;
  875.       clen = fhead->clen;
  876.       dlen = fhead->dlen;
  877.       mode = (char)fhead->flags;
  878.       longhdr = (long)(fhead->flags & LONGHDR);
  879.       if(longhdr){
  880.      maxchunk = fhead->dchunk;
  881.      if(fhead->cchunk>maxchunk) maxchunk=fhead->cchunk;
  882.       }
  883.       else{
  884.      maxchunk = (fhead->cchunk) & 0xffff;
  885.      if((fhead->cchunk>>16)>maxchunk) maxchunk=fhead->cchunk>>16;
  886.       }
  887.       crst[0] = (pack & 0xff000000) >> 24;
  888.       crst[1] = (pack & 0xff0000) >> 16;
  889.       crst[2] = (pack & 0xff00) >> 8;
  890.       crst[3] = pack;  crst[4] = '\0';
  891.       packed = PACKED;
  892.    }
  893.  
  894.    else if(format == 0x01806368){              // EPU
  895.       if(type == COMPRESS) return(XPKERR_PACKED);
  896.       ptr = (char*)fhead+19;
  897.       strncpy(crst,ptr,4);
  898.       maxchunk = (long)((fhead->clen)&0xff)*1000;
  899.       dlen = fhead->pack;   clen = fhead->dlen+8L;
  900.       lptr = (long*)fhead+4;
  901.       pack = ((*lptr++)<<24) | ((*lptr)>>8);
  902.       longhdr = 0L;
  903.       packed = PACKED;
  904.       epu = 1;
  905.    }                           // -EPU
  906.    else{   // not packed
  907.       dlen = clen;
  908.       if(type == EXPAND) return(XPKERR_NOTPACKED);
  909.       if(format == 0x03f3 && ex == DATAFILE) return(ERR_EXECUTABLE);
  910.       if(format != 0x03f3 && ex == EXECUTABLE) return(ERR_DATAFILE);
  911.    }
  912.    return(XPKERR_OK);
  913. }
  914.  
  915.  
  916.  
  917.  
  918. long xload(char *readfile,char *writefile,long len)
  919. {
  920.    long xerr;
  921.  
  922.  
  923.    if(out) fprintf(Out,"%s  -  cr: %s\n",readfile,crst);
  924.  
  925.    if(clen == 1L) xerr = xcopy(readfile,writefile,dlen,20000L);
  926.    else xerr = eload(readfile,writefile);
  927.  
  928.    if(!xerr && ident) xerr = change_name(readfile,writefile);
  929.    else if(xerr){
  930.       if(DeleteFile(writefile) != -1) xerr = ERR_DELETE;
  931.    }
  932.  
  933.    if(xerr) return(xerr);
  934.  
  935.    count++;  dsum += dlen;  csum += len;
  936.  
  937.    if(out){
  938.       fprintf(Out,"%ld -> %ld bytes",len,dlen);
  939.       if(!time){ fprintf(Out,"  - "); PRINT_TIME(dlen); }
  940.       else fprintf(Out,"\n");
  941.    }
  942.    return(XPKERR_OK);
  943. }
  944.  
  945.  
  946. long eload(char *readfile,char *writefile)
  947. {
  948.    char ln,newdir[256];
  949.    struct FileLock *rlock,*wlock,*dlock;
  950.    long xerr,ch_size;
  951.    register long xlen,iblen,oblen,ilen,olen,chksum;
  952.  
  953.    xerr = 0L;  chksum = 0L;  ln = 2;
  954.  
  955.    if(!(rlock = (struct FileLock *)Open(readfile,MODE_OLDFILE)))
  956.       return(ERR_OPEN);
  957.  
  958.    rw_open:
  959.    if(!(wlock = (struct FileLock *)Open(writefile,MODE_NEWFILE))){
  960.       if(all && wf && ln>1){
  961.      strcpy(newdir,writefile);  ln = strlen(newdir)-1;
  962.      rw_sub:
  963.      while(newdir[ln] != '/' && ln>1) ln--;
  964.      newdir[ln]=0;
  965.      if(ln>1){  // new subdirectory
  966.        if((dlock=(struct FileLock*)CreateDir(newdir))){
  967.           UnLock((BPTR)dlock);
  968.           if(out) fprintf(Out,"(dir) %s  [created]\n",newdir);
  969.           goto rw_open;
  970.        }
  971.        else goto rw_sub;
  972.      }
  973.       }
  974.       xerr = ERR_OPEN; goto felo;
  975.    }
  976.  
  977.    if(Read((BPTR)rlock,(char*)fhead,HEAD)!=HEAD){
  978.        xerr = ERR_READ; goto felo;
  979.    }
  980.  
  981.    if(epu){       // EPU
  982.       fhead->dlen = dlen;  // glob
  983.       cmin = EPU_MIN;
  984.       if(Seek((BPTR)rlock,-16L,OFFSET_CURRENT)==-1L){
  985.      xerr = XPKERR_IOERRIN;  goto felo;
  986.       }
  987.    }          // -EPU
  988.  
  989.    iblen = maxchunk+16L;  // ilen maybe larger
  990.    iblen = iblen+(iblen>>smarg)+MARGIN+MARGIN;
  991.    xpar->OutBufLen = iblen;
  992.    oblen = iblen+MARGIN;
  993.  
  994.    xpar->InBuf = 0L;  xpar->OutBuf = 0L;
  995.    xpar->Sub[0] = 0L;
  996.  
  997.    if(!(xpar->InBuf = (APTR)AllocMem((long)iblen,
  998.      (long)(MEMF_PUBLIC+MEMF_CLEAR)))){ xerr = XPKERR_NOMEM; goto felo; }
  999.    if(!(xpar->OutBuf = (APTR)AllocMem((long)oblen,
  1000.     (long)(MEMF_PUBLIC+MEMF_CLEAR)))){ xerr = XPKERR_NOMEM; goto felo; }
  1001.  
  1002.    if(longhdr) ch_size = CHUNK_HEAD;
  1003.    else if(epu) ch_size = 2;          // EPU
  1004.    else ch_size = SHORT_HEAD;
  1005.    xlen = 0L;  xpar->Number = 0L;
  1006.  
  1007.    if(!time){ START(); I_STOP(); }
  1008.    while(xlen<fhead->dlen){
  1009.       if(Read((BPTR)rlock,(char*)chead,ch_size)!=ch_size){
  1010.       xerr = ERR_READ; goto felo;
  1011.       }
  1012.       if(longhdr){
  1013.      ilen = (UL)chead->clen;
  1014.      olen = (UL)chead->dlen;
  1015.       }
  1016.       else{
  1017.      ilen = (UL)(chead->clen)>>16;
  1018.      olen = (UL)(chead->clen)&0xffff;
  1019.       }
  1020.       if(ilen != olen) packed=1; else packed=0;
  1021.       if(epu){                // EPU
  1022.      if(ilen==0L) break;
  1023.      else{
  1024.         if(fhead->dlen-xlen<maxchunk) olen = fhead->dlen-xlen;
  1025.         else olen = maxchunk;
  1026.         if(olen<=cmin) ilen = olen;
  1027.      }
  1028.       }               // -EPU
  1029.  
  1030.       xpar->InLen = ilen;
  1031.       xpar->OutLen = olen;
  1032.       if(epu) ilen = ((ilen+1L)&0xfffffffe);  // EPU
  1033.       else ilen = ((ilen+3L)&0xfffffffc);
  1034.       if(format == 0x58504b46) ilen += XPK_COMPAT;   // ('XPKF')
  1035.       if(Read((BPTR)rlock,(char*)xpar->InBuf,ilen)!=ilen){
  1036.       xerr = ERR_READ; goto felo;
  1037.       }
  1038.       // if(pre){  // if lib prereads chunkheader
  1039.       //    if(Seek((BPTR)rlock,-4L,OFFSET_CURRENT)==-1L){
  1040.       //       xerr = XPKERR_IOERRIN;  goto felo;
  1041.       // }
  1042.  
  1043.       xpar->Number = xpar->Number+1;
  1044.  
  1045.       if(packed && xpar->OutLen>cmin){
  1046.      if(!time) I_START();
  1047.      xerr = XpksUnpackChunk(xpar);
  1048.      if(!time) I_STOP();
  1049.      if(format == FORMAT)
  1050.         chksum += checksum((long*)xpar->OutBuf,xpar->OutLen);
  1051.       }
  1052.       else{
  1053.      CopyMem((char*)xpar->InBuf,(char*)xpar->OutBuf,xpar->InLen);
  1054.      xpar->OutLen = xpar->InLen;
  1055.       }
  1056.  
  1057.  
  1058.       if(xerr != XPKERR_OK) goto felo;
  1059.       if(xpar->OutLen > xpar->OutBufLen || xpar->OutLen != olen)
  1060.      { xerr=XPKERR_CORRUPTPKD; goto felo; }
  1061.  
  1062.       if(!xlen) strncpy(fc16,(char*)xpar->OutBuf,16);
  1063.  
  1064.       xlen += xpar->OutLen;
  1065.  
  1066.       if(Write((BPTR)wlock,(char*)xpar->OutBuf,
  1067.        xpar->OutLen)!=xpar->OutLen){
  1068.      xerr = ERR_WRITE;  goto felo;
  1069.       }
  1070.       if(epu){ XpksUnpackFree(xpar);  xpar->Sub[0]=0L; }  // EPU
  1071.    }
  1072.  
  1073.    if(!epu){  // EPU
  1074.     if(!passw && strncmp(fhead->first16,fc16,16))
  1075.       xerr = XPKERR_CORRUPTPKD;
  1076.    }          // EPU
  1077.  
  1078.    if(format == FORMAT){
  1079.       if(chksum != fhead->chksum)
  1080.      xerr=XPKERR_CHECKSUM; goto felo;
  1081.    }
  1082.  
  1083.  
  1084.    felo:
  1085.    if(!time) STOP();
  1086.    if(!epu) XpksUnpackFree(xpar);      // epu
  1087.    if(xpar->InBuf){ FreeMem(xpar->InBuf,iblen); xpar->InBuf=0L; }
  1088.    if(xpar->OutBuf){ FreeMem(xpar->OutBuf,oblen); xpar->OutBuf=0L; }
  1089.    if(rlock) Close((BPTR)rlock);
  1090.    if(wlock) Close((BPTR)wlock);
  1091.  
  1092.    return(xerr);
  1093. }
  1094.  
  1095.  
  1096.  
  1097.  
  1098. long xsave(char *readfile,char *writefile,long len,long chunk,char mode,
  1099.      long pack,UB out)
  1100. {
  1101.    long clen,pro,xerr;
  1102.  
  1103.  
  1104.    if(out){
  1105.      if(ident) fprintf(Out,"%s  -  cr: %s  mode %d\n",readfile,crst,mode);
  1106.      else fprintf(Out,"%s  -  cr: %s  mode %d\n",writefile,crst,mode);
  1107.    }
  1108.    clen = len;
  1109.  
  1110.    if(dlen >= minsize)
  1111.       xerr = esave(readfile,writefile,&clen,len,chunk,mode);
  1112.    if(dlen < minsize || xerr != XPKERR_OK)
  1113.       xerr = xcopy(readfile,writefile,len,chunk);
  1114.  
  1115.    if(dlen>=minsize){
  1116.       if(!xerr && ident) xerr = change_name(readfile,writefile);
  1117.       else if(xerr){
  1118.      if(DeleteFile(writefile) != -1) xerr = ERR_DELETE;
  1119.       }
  1120.    }
  1121.  
  1122.    if(xerr != XPKERR_OK) return(xerr);
  1123.  
  1124.    count++;  dsum += len;  csum += clen;
  1125.    if(out){
  1126.       fprintf(Out,"%ld -> %ld bytes",len,clen);
  1127.       pro = ((len-clen)*1000)/len;
  1128.       fprintf(Out,"  %ld.%ld%%  - ",pro/10,pro-(pro/10)*10);
  1129.       if(!time) PRINT_TIME(len);
  1130.       else fprintf(Out,"\n");
  1131.    }
  1132.  
  1133.    return(xerr);
  1134. }
  1135.  
  1136.  
  1137.  
  1138. long xcopy(char *readfile,char *writefile,long len,long chunk)
  1139. {
  1140.    char ln,newdir[256];
  1141.    struct FileLock *rlock,*wlock,*dlock;
  1142.    long *buf,blen,slen,xerr;
  1143.  
  1144.  
  1145.    buf = 0L;  xerr = 0L;  ln = 2;
  1146.    if(!(rlock = (struct FileLock *)Open(readfile,MODE_OLDFILE)))
  1147.       return(ERR_OPEN);
  1148.  
  1149.    xw_open:
  1150.    if(!(wlock = (struct FileLock *)Open(writefile,MODE_NEWFILE))){
  1151.       if(all && wf && ln>1){
  1152.      strcpy(newdir,writefile);  ln = strlen(newdir)-1;
  1153.      xw_sub:
  1154.      while(newdir[ln] != '/' && ln>1) ln--;
  1155.      newdir[ln]=0;
  1156.      if(ln>1){  // new subdirectory
  1157.        if((dlock=(struct FileLock*)CreateDir(newdir))){
  1158.           UnLock((BPTR)dlock);
  1159.           if(out) fprintf(Out,"(dir) %s  [created]\n",newdir);
  1160.           goto xw_open;
  1161.        }
  1162.        else goto xw_sub;
  1163.      }
  1164.       }
  1165.       xerr = ERR_OPEN;    goto fxw;
  1166.    }
  1167.  
  1168.    blen = chunk;
  1169.    if(!(buf = (long*)AllocMem((long)blen,
  1170.       (long)(MEMF_PUBLIC+MEMF_CLEAR)))){ xerr=XPKERR_NOMEM; goto fxw; }
  1171.    slen = 0L;
  1172.    while(slen<len){
  1173.       if(len-slen<chunk) chunk=len-slen;
  1174.       if(Read((BPTR)rlock,(char*)buf,(long)chunk)!=(long)chunk){
  1175.      { xerr=ERR_READ;  goto fx1; }
  1176.       }
  1177.       if(Write((BPTR)wlock,(char*)buf,(long)chunk)!=(long)chunk){
  1178.      { xerr=ERR_WRITE;  goto fx1; }
  1179.       }
  1180.       slen += chunk;
  1181.    }
  1182.    goto fxw;
  1183.  
  1184.    fx1:
  1185.    Close((BPTR)wlock);  wlock=0L;
  1186.    if(DeleteFile(writefile) != -1) xerr = ERR_DELETE;
  1187.  
  1188.    fxw:
  1189.    if(buf) FreeMem(buf,blen);
  1190.    Close((BPTR)rlock);
  1191.    if(wlock) Close((BPTR)wlock);
  1192.    return(xerr);
  1193. }
  1194.  
  1195.  
  1196.  
  1197.  
  1198. long esave(char *readfile,char *writefile,long *clen,long len,long chunk,
  1199.      char mode)
  1200. {
  1201.    char ln,newdir[256];
  1202.    struct FileLock *rlock,*wlock,*dlock;
  1203.    long *lptr,*sptr,iblen,oblen,ch_size,w_over,xerr=0L;
  1204.    register long xclen,xdlen,chksum,echunk,olen;
  1205.    UB *dst;
  1206.  
  1207.    xpar->InBuf = 0L;  xpar->Sub[0] = 0L;  dst = 0L;  ln=2;
  1208.    chksum = 0L;  echunk = chunk;
  1209.    if(!(rlock = (struct FileLock *)Open(readfile,MODE_OLDFILE)))
  1210.       return(ERR_OPEN);
  1211.  
  1212.    sw_open:
  1213.    if(!(wlock = (struct FileLock *)Open(writefile,MODE_NEWFILE))){
  1214.       if(all && wf && ln>1){
  1215.      strcpy(newdir,writefile);  ln = strlen(newdir)-1;
  1216.      sw_sub:
  1217.      while(newdir[ln] != '/' && ln>1) ln--;
  1218.      newdir[ln]=0;
  1219.      if(ln>1){  // new subdirectory
  1220.        if((dlock=(struct FileLock*)CreateDir(newdir))){
  1221.           UnLock((BPTR)dlock);
  1222.           if(out) fprintf(Out,"(dir) %s  [created]\n",newdir);
  1223.           goto sw_open;
  1224.        }
  1225.        else goto sw_sub;
  1226.      }
  1227.       }
  1228.       xerr = ERR_OPEN;    goto fepo;
  1229.    }
  1230.  
  1231.    if(echunk>len) echunk = ((len+3L)&0xfffffffc);
  1232.    iblen = echunk;
  1233.    w_over = (iblen>>smarg)+MARGIN;
  1234.    xpar->OutBufLen = echunk+w_over+MARGIN;
  1235.    oblen = xpar->OutBufLen+MARGIN;
  1236.  
  1237.    if(echunk>0xffff){
  1238.       longhdr = LONGHDR;
  1239.       ch_size = CHUNK_HEAD;
  1240.    }
  1241.    else{
  1242.       longhdr = 0L;
  1243.       ch_size = SHORT_HEAD;
  1244.    }
  1245.  
  1246.    if(!(xpar->InBuf = (APTR)AllocMem((long)iblen,
  1247.     (long)(MEMF_PUBLIC+MEMF_CLEAR)))){ xerr=XPKERR_NOMEM; goto fepo; }
  1248.    if(!(dst = (UB*)AllocMem((long)oblen,
  1249.     (long)(MEMF_PUBLIC+MEMF_CLEAR)))){ xerr=XPKERR_NOMEM; goto fepo; }
  1250.    xpar->OutBuf = (APTR)((long)dst+ch_size);
  1251.  
  1252.    xpar->Mode = (long)mode;
  1253.  
  1254.    // Header
  1255.    sptr = (long*)fhead->first16;
  1256.    if(passw) lptr = (long*)fh16;
  1257.    else lptr = (long*)fhead;
  1258.    *sptr++ = *lptr++;  *sptr++ = *lptr++;
  1259.    *sptr++ = *lptr++;  *sptr = *lptr;
  1260.  
  1261.    fhead->head = (long)FORMAT;
  1262.    fhead->pack = pack;
  1263.    fhead->dlen = len;
  1264.    fhead->flags = mode|passw|longhdr;
  1265.  
  1266.  
  1267.    if(Write((BPTR)wlock,(char*)fhead,HEAD)!=HEAD){
  1268.       xerr = ERR_WRITE;  goto fepo;
  1269.    }
  1270.  
  1271.    xclen = 0L;    xdlen = 0L;
  1272.    xpar->Number = 0L;
  1273.    lptr = (long*)dst;
  1274.  
  1275.    if(!time){ START(); I_STOP(); }
  1276.  
  1277.    while((long)xdlen<len){
  1278.       if(len-xdlen<echunk){
  1279.      echunk=len-xdlen;
  1280.      xpar->OutBufLen = echunk+w_over+MARGIN;
  1281.       }
  1282.  
  1283.       if(Read((BPTR)rlock,(char*)xpar->InBuf,echunk)!=echunk){
  1284.      xerr=ERR_READ;
  1285.      goto fepo;
  1286.       }
  1287.  
  1288.       xpar->InLen = (long)echunk;
  1289.       xpar->Number = xpar->Number+1;
  1290.  
  1291.  
  1292.       if(echunk>cmin){
  1293.      if(!time) I_START();
  1294.      xerr = XpksPackChunk(xpar);
  1295.      if(!time) I_STOP();
  1296.      if(xerr == XPKERR_EXPANSION || (xpar->OutLen > xpar->InLen && !oflow)){
  1297.         CopyMem((char*)xpar->InBuf,(char*)xpar->OutBuf,echunk);
  1298.         xpar->OutLen = echunk;
  1299.         xerr = XPKERR_OK;
  1300.      }
  1301.      else chksum += checksum((long*)xpar->InBuf,xpar->InLen);
  1302.       }
  1303.       else{
  1304.      CopyMem((char*)xpar->InBuf,(char*)xpar->OutBuf,echunk);
  1305.      xpar->OutLen = echunk;
  1306.       }
  1307.  
  1308.  
  1309.       if(xerr != XPKERR_OK) goto fepo;
  1310.  
  1311.       olen = xpar->OutLen+ch_size;
  1312.       olen = ((olen+3L)&0xfffffffc);  //+XPK_COMPAT;
  1313.       if(longhdr){
  1314.      *lptr = xpar->OutLen;
  1315.      *(lptr+1) = echunk;
  1316.       }
  1317.       else *lptr = ((xpar->OutLen)<<16)|(echunk&0xffff);
  1318.  
  1319.       if(Write((BPTR)wlock,(char*)dst,olen)!=olen){
  1320.      xerr = ERR_WRITE;
  1321.      goto fepo;
  1322.       }
  1323.  
  1324.       xdlen += echunk;
  1325.       xclen += olen;
  1326.       if(!oflow){
  1327.      if(xclen>xdlen+w_over && !passw)
  1328.         { xerr=XPKERR_EXPANSION; goto fepo; }
  1329.       }
  1330.    }
  1331.    xclen += HEAD;
  1332.    if(!oflow){
  1333.       if(xclen >= len && !passw)
  1334.      { xerr = XPKERR_EXPANSION; goto fepo; }
  1335.    }
  1336.    if(Seek((BPTR)wlock,4L,OFFSET_BEGINNING)==-1L){
  1337.       xerr = XPKERR_IOERRIN;  goto fepo;
  1338.    }
  1339.    w_over = xclen;  // bec. of reg.
  1340.    if(Write((BPTR)wlock,(char*)&w_over,4L)!=4L){ // packed length
  1341.       xerr = ERR_WRITE;  goto fepo;
  1342.    }
  1343.    *clen = xclen;
  1344.  
  1345.    if(Seek((BPTR)wlock,36L,OFFSET_BEGINNING)==-1L){
  1346.       xerr = XPKERR_IOERRIN;  goto fepo;
  1347.    }
  1348.    w_over = chksum;  // bec. of reg.
  1349.    if(Write((BPTR)wlock,(char*)&w_over,4L)!=4L){ // checksum
  1350.       xerr = ERR_WRITE;  goto fepo;
  1351.    }
  1352.  
  1353.  
  1354.    fepo:
  1355.    if(!time) STOP();
  1356.    XpksPackFree(xpar);
  1357.    if(xpar->InBuf){ FreeMem(xpar->InBuf,iblen); xpar->InBuf=0L; }
  1358.    if(dst) FreeMem(dst,oblen);
  1359.    if(rlock) Close((BPTR)rlock);
  1360.    if(wlock) Close((BPTR)wlock);
  1361.  
  1362.    return(xerr);
  1363. }
  1364.  
  1365.  
  1366. long change_name(char *readfile, char *writefile)
  1367. {
  1368.    if(DeleteFile(readfile) != -1) return(ERR_LOCK);
  1369.    if(Rename(writefile,readfile) != -1) return(ERR_LOCK);
  1370.  
  1371.    return(XPKERR_OK);
  1372. }
  1373.  
  1374.  
  1375. void write_err(long xerr)
  1376. {
  1377.    if(out && xerr != XPKERR_OK)
  1378.       fprintf(Out,"%s !!!\n",errstr[xerr-LOWER_ERR-1]);
  1379. }
  1380.  
  1381.  
  1382. long breaktest(void)
  1383. {
  1384.    if (*xkey == K_LSHFT || *xkey == K_RSHFT){ // Keys -SHFT-
  1385.       *xkey = 0;
  1386.       Delay (K_DELAY);
  1387.       if(!(*xmouse & (1<<6)))  // left mouse-button
  1388.      return(XPKERR_ABORTED);
  1389.    }
  1390.    return(XPKERR_OK);
  1391. }
  1392.  
  1393.  
  1394.  
  1395.  
  1396.  
  1397.  
  1398.  
  1399. void START (void)
  1400. {
  1401.    DateStamp(&clo); timer=act_ticks;
  1402. }
  1403. void STOP (void)
  1404. {
  1405.    DateStamp(&clo);  timer=act_ticks-timer;
  1406. }
  1407. void PRINT_TIME(long len)
  1408. {
  1409.    i_time = timer/50; stime = (timer-i_time*50)*2;
  1410.    if(timer==0) timer=1;  // to prevent from division by zero
  1411.    if(kilo){
  1412.      if(stime<10) fprintf(Out," %d.0%d sec (%ld kb/s)\n",i_time,stime,(len*50/timer+512)>>10);
  1413.      else fprintf(Out," %d.%d sec (%ld kb/s)\n",i_time,stime,(len*50/timer+512)>>10);
  1414.    }
  1415.    else{
  1416.      if(stime<10) fprintf(Out," %d.0%d sec (%ld bps)\n",i_time,stime,len*50/timer);
  1417.      else fprintf(Out," %d.%d sec (%ld bps)\n",i_time,stime,len*50/timer);
  1418.    }
  1419. }
  1420. void I_START (void)      /* continues after I_STOP */
  1421. {
  1422.    DateStamp(&clo);
  1423.    i_time = act_ticks-i_time;
  1424.    timer = timer+i_time;
  1425. }
  1426.  
  1427. void I_STOP (void)
  1428. {
  1429.    DateStamp(&clo);
  1430.    i_time = act_ticks;
  1431. }
  1432.  
  1433.  
  1434.  
  1435.  
  1436. /************************************************
  1437.  
  1438. Some ideas, what future versions could support:
  1439.  
  1440. + Reading files, that are packed with powerpacker
  1441. + Writing other fileformats
  1442. + Recrunchmode
  1443. + Workbench version
  1444.  
  1445. *************************************************/
  1446.  
  1447.