#include <stdio.h>
#include <libraries/dosextens.h>

#define CPY_BUFF_LEN 30000

char CpyBuff[CPY_BUFF_LEN];
WORD all=0;

void RecompFile();
void RecompDir();
char *GetFullName();

void main(int argc, char *argv[])
{
  BPTR lock;
  struct FileInfoBlock fib;

  if( argc<2 || argc>3 ) {fprintf(stderr,"Bad args\n");exit(10);}
  if( argc==3 )
    if( stricmp(argv[2],"all")==0 )
      all=1;
    else
      {fprintf(stderr,"Bad args\n");exit(10);}
  if( lock=Lock(argv[1],SHARED_LOCK) )
  {
    if( Examine(lock,&fib) )
    {
      if(fib.fib_DirEntryType<0)
      {
        RecompFile(lock,&fib);
      }
      else
      {
        RecompDir(lock);
        UnLock(lock);
      }
    }
  }
}

void RecompFile(BPTR lock, struct FileInfoBlock *fib)
{
  long in=0,out,c,d;
  BPTR Parent; 
  struct Process *p=(struct Process *)FindTask(0);
  BPTR PrevLock=p->pr_CurrentDir; 
  char Name[100];

  printf("(re)compressing %s",GetFullName(lock) );
  if(Parent=ParentDir(lock))
  {
    p->pr_CurrentDir=lock;
    if(in=Open("",MODE_OLDFILE))
    {
      p->pr_CurrentDir=Parent;
      strcpy(Name,fib->fib_FileName);
      strcat(Name,".EpuTmp");
      if(out=Open(Name,MODE_NEWFILE));
      {
        do
        {
          c=Read(in,CpyBuff,CPY_BUFF_LEN);
          d=Write(out,CpyBuff,c);
        }while(c==d && c!=0);
        Close(out);
        Close(in);in=0;
        UnLock(lock);lock=0;
        if(c==d)
        {
          DeleteFile(fib->fib_FileName);
          if( Rename(Name,fib->fib_FileName) )printf(" Done");
        }
      }
      if(in)Close(in);
    }
    UnLock(Parent);
  }
  if(lock) UnLock(lock);
  p->pr_CurrentDir=PrevLock;
  printf("\n");  
}

#define MAX_FILES_IN_DIR 40

void RecompDir(BPTR lock)
{
  struct FileInfoBlock fib,
         fibs[MAX_FILES_IN_DIR];
  long c=0;  

  Examine(lock,&fib);
  while( ExNext(lock,&fib) )
  {         
     if(c>=MAX_FILES_IN_DIR) break;
     fibs[c]=fib;
     c++;
  }
  c--;
  for(;c>=0;c--)
  {
    struct Process *p=(struct Process *)FindTask(0);
    BPTR l2, PrevLock=p->pr_CurrentDir;
           
    p->pr_CurrentDir=lock;
    l2=Lock(fibs[c].fib_FileName,SHARED_LOCK);
    p->pr_CurrentDir=PrevLock;
           
    if(l2)
    {
      if(fibs[c].fib_DirEntryType<0) RecompFile(l2,&fibs[c]);
      else { if(all) RecompDir(l2);    UnLock(l2);}      
    }
  }
}

#define BS 500

static char Buff[BS];

char  *GetFullName(BPTR lock)
{
  char *p=Buff+BS-5 , *lp;
  struct FileInfoBlock fib;
  long c, h=0;
  BPTR lock2;

  *p--=0;
  do
  {
    *p--='/';lp=p+1;
    if(!Examine(lock,&fib)){ if(h) UnLock(lock); return(p+1); }
    for(c=strlen(fib.fib_FileName)-1;c>=0;c--) 
      *p--=fib.fib_FileName[c];
    lock2=ParentDir(lock);
    if(h) UnLock(lock);
    h=1;
    lock=lock2;
  }while(lock);
  *lp=':';
  return(p+1);
}


