#define INCL_DOS
#define INCL_DOSERRORS
#define INCL_WIN

#include <os2.h>
#include <io.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
#include <time.h>
#include "fm3dll.h"

#ifndef WinMoveObject
  HOBJECT APIENTRY WinMoveObject(HOBJECT hObjectofObject,
                                 HOBJECT hObjectofDest,
                                 ULONG   ulReserved);
#endif
#ifndef WinCopyObject
  HOBJECT APIENTRY WinCopyObject(HOBJECT hObjectofObject,
                                 HOBJECT hObjectofDest,
                                 ULONG   ulReserved);
#endif

#pragma alloc_text(LONGNAMES,TruncName,GetLongName,WriteLongName)
#pragma alloc_text(LONGNAMES,ZapLongName,AdjustWildcardName)
#pragma alloc_text(COPYF,default_disk,docopyf)
#pragma alloc_text(UNLINKF,unlinkf,unlink_allf,make_deleteable,wipeallf)


char *MakeTempName (char *buffer) {

  FILESTATUS3 fs3;
  APIRET      rc;
  char       *p,*o;

  p = o = buffer + strlen(buffer);
  sprintf(p,"%08lx.%03lx",clock(),mypid);
  p = buffer + (strlen(buffer) - 1);
  for(;;) {
    DosError(FERR_DISABLEHARDERR);
    rc = DosQueryPathInfo(buffer,FIL_STANDARD,&fs3,
                        (ULONG)sizeof(fs3));
    if(rc == ERROR_DISK_CHANGE) {
      DosError(FERR_ENABLEHARDERR);
      rc = DosQueryPathInfo(buffer,FIL_STANDARD,&fs3,
                          (ULONG)sizeof(fs3));
    }
    if(rc)
      break;
Loop:
    if(p < o) {
      *buffer = 0;
      return NULL;
    }
    if((*p) + 1 < 'Z' + 1) {
      (*p)++;
      while(strchr("*?<>\":/\\|+=;,[]. ",*p))
        (*p)++;
      *p = toupper(*p);
    }
    else {
      p--;
      if(p >= o && *p == '.')
        p--;
      goto Loop;
    }
  }
  return buffer;
}


CHAR *TruncName (CHAR *oldname,CHAR *buffer) {

  CHAR       *p,*f,*s,*o;
  FILESTATUS3 fs3;
  APIRET      rc;

  if(!buffer || !oldname || !*oldname) {
    if(buffer)
      *buffer = 0;
    return NULL;
  }
  strcpy(buffer,oldname);
  f = strrchr(buffer,'\\');
  if(!f)
    f = strrchr(buffer,'/');
  if(!f)
    f = buffer;
  else
    f++;
  p = f;
  o = p;
  f = oldname + (f - buffer);
  strupr(buffer);
  while(*f == '.')  /* skip leading '.'s */
    f++;
  s = f;
  while(*f && *f != '.' && f < s + 8) { /* skip past rootname */
    *p = toupper(*f);
    p++;
    f++;
  }
  while(*f == '.')
    f++;
  s = f;
  f = strrchr(f,'.');
  if(f) {
    while(*f == '.')
      f++;
  }
  if(f && *(f + 1))
    s = f;
  else
    f = s;
  if(*f) {
    *p = '.';
    p++;
    while(*f && *f != '.' && f < s + 3) {
      *p = toupper(*f);
      p++;
      f++;
    }
  }
  *p = 0;

  p = o;
  while(*p) {
    if(strchr("*?<>\":/\\|+=;,[] ",*p) || *p < 0x20)
      *p = '_';
    if(*p == '.' && *(p + 1) == '.')
      *(p + 1) = '_';
    p++;
  }

  p = o + (strlen(o) - 1);
  for(;;) {
    DosError(FERR_DISABLEHARDERR);
    rc = DosQueryPathInfo(buffer,FIL_STANDARD,&fs3,
                        (ULONG)sizeof(fs3));
    if(rc == ERROR_DISK_CHANGE) {
      DosError(FERR_ENABLEHARDERR);
      rc = DosQueryPathInfo(buffer,FIL_STANDARD,&fs3,
                          (ULONG)sizeof(fs3));
    }
    if(rc)
      break;
Loop:
    if(p < o) {
      *buffer = 0;
      return NULL;
    }
    if((*p) + 1 < 'Z' + 1) {
      (*p)++;
      while(strchr("*?<>\":/\\|+=;,[]. ",*p))
        (*p)++;
      *p = toupper(*p);
    }
    else {
      p--;
      if(p >= o && *p == '.')
        p--;
      goto Loop;
    }
  }
  return buffer;
}


CHAR *GetLongName (CHAR *oldname,CHAR *longname) {

  if(!longname)
    return NULL;
  *longname = 0;
  if(!oldname ||
     !*oldname)
    return NULL;
  if(IsFullName(oldname)) {

    APIRET    rc;
    EAOP2     eaop;
    PGEA2LIST pgealist;
    PFEA2LIST pfealist;
    PGEA2     pgea;
    PFEA2     pfea;
    CHAR      *value;

    strcpy(longname,
           oldname);
    value = longname;
    while(*value) {
      if(*value == '/')
        *value = '\\';
      value++;
    }
    value = strrchr(longname,'\\');
    if(value) {
      value++;
      *value = 0;
    }
    pgealist = malloc(sizeof(GEA2LIST) + 32);
    if(pgealist) {
      memset(pgealist,0,sizeof(GEA2LIST) + 32);
      pgea = &pgealist->list[0];
      strcpy(pgea->szName,LONGNAME);
      pgea->cbName = strlen(pgea->szName);
      pgea->oNextEntryOffset = 0L;
      pgealist->cbList = (sizeof(GEA2LIST) + pgea->cbName);
      pfealist = malloc(1536);
      if(pfealist) {
        memset(pfealist,0,1024);
        pfealist->cbList = 1024;
        eaop.fpGEA2List = pgealist;
        eaop.fpFEA2List = pfealist;
        eaop.oError = 0L;
        DosError(FERR_DISABLEHARDERR);
        rc = DosQueryPathInfo(oldname,
                              FIL_QUERYEASFROMLIST,
                              (PVOID)&eaop,
                              (ULONG)sizeof(EAOP2));
        if(!rc) {
          pfea = &eaop.fpFEA2List->list[0];
          value = pfea->szName + pfea->cbName + 1;
          value[pfea->cbValue] = 0;
          if(*(USHORT *)value == EAT_ASCII)
            strncat(longname,
                    value + (sizeof(USHORT) * 2),
                    CCHMAXPATH - strlen(longname));
          longname[CCHMAXPATH - 1] = 0;
        }
        free(pfealist);
      }
      free(pgealist);
    }
  }
  return longname;
}


BOOL ZapLongName (char *filename) {

saymsg(MB_ENTER,HWND_DESKTOP,DEBUG_STRING,"Zapped longname.");
  return WriteLongName(filename,
                       "");
}


BOOL WriteLongName (CHAR *filename,CHAR *longname) {

  APIRET    rc;
  EAOP2     eaop;
  PFEA2LIST pfealist = NULL;
  ULONG     ealen;
  USHORT    len;
  CHAR     *eaval,*p;

  if(!filename ||
     !*filename ||
     !longname)
    return FALSE;
  p = strrchr(longname,'\\');
  if(p)
    memmove(longname,
            p + 1,
            strlen(p + 1) + 1);
  p = strrchr(longname,'/');
  if(p)
    memmove(longname,
            p + 1,
            strlen(p + 1) + 1);
  lstrip(rstrip(longname));
  len = strlen(longname);
  if(len)
    ealen = sizeof(FEA2LIST) + 10 + len + 4;
  else
    ealen = sizeof(FEALIST) + 10;
  if(!DosAllocMem((PPVOID)&pfealist,
                  ealen + 32L,
                  OBJ_TILE | PAG_COMMIT | PAG_READ | PAG_WRITE)) {
    memset(pfealist,
           0,
           ealen + 1);
    pfealist->cbList = ealen;
    pfealist->list[0].oNextEntryOffset = 0L;
    pfealist->list[0].fEA = 0;
    pfealist->list[0].cbName = 9;
    strcpy(pfealist->list[0].szName,
           LONGNAME);
    if(len) {
      eaval = pfealist->list[0].szName + 10;
      *(USHORT *)eaval = (USHORT)EAT_ASCII;
      eaval += sizeof(USHORT);
      *(USHORT *)eaval = (USHORT)len;
      eaval += sizeof(USHORT);
      memcpy(eaval,
             longname,
             len);
      pfealist->list[0].cbValue = len + (sizeof(USHORT) * 2);
    }
    else
      pfealist->list[0].cbValue = 0;
    eaop.fpGEA2List = (PGEA2LIST)0;
    eaop.fpFEA2List = pfealist;
    eaop.oError = 0L;
    DosError(FERR_DISABLEHARDERR);
    rc = DosSetPathInfo(filename,
                        FIL_QUERYEASIZE,
                        (PVOID)&eaop,
                        (ULONG)sizeof(EAOP2),
                        DSPI_WRTTHRU);
    DosFreeMem(pfealist);
    if(rc)
      return FALSE;
  }
  return TRUE;
}


BOOL AdjustWildcardName (CHAR *oldname,CHAR *newname) {

  BOOL ret = FALSE;

  /* NOTE:  newname should be CCHMAXPATH chars long! */

  if(strchr(newname,'*') || strchr(newname,'?')) {

    CHAR srce[CCHMAXPATHCOMP],dest[CCHMAXPATHCOMP],result[CCHMAXPATHCOMP],*p;

    p = strrchr(newname,'\\');
    if(p && *(p + 1)) {
      strcpy(dest,p + 1);
      p = strrchr(oldname,'\\');
      if(p && *(p + 1)) {
        strcpy(srce,p + 1);
        DosError(FERR_DISABLEHARDERR);
        if(!DosEditName(1L,srce,dest,result,(ULONG)sizeof(result))) {
          p = strrchr(newname,'\\');
          p++;
          strcpy(p,result);
          ret = TRUE;
        }
      }
    }
  }
  return ret;
}


CHAR default_disk (VOID) {

  ULONG ulDriveNum,ulDriveMap;

  DosError(FERR_DISABLEHARDERR);
  DosQCurDisk(&ulDriveNum,&ulDriveMap);
  return (CHAR)toupper((INT)ulDriveNum) + '@';
}


#ifdef NEVER

APIRET docopyallf (INT type,CHAR *oldname,CHAR *newname,...) {

  FILEFINDBUF3 fb;
  ULONG        nm;
  HDIR         hdir;
  APIRET       rc = 0;
  CHAR        *enddir,fullname[CCHMAXPATH];

  va_start(ap,newname);
  vsprintf(fullname,newname,ap);
  va_end(ap);

  DosError(FERR_DISABLEHARDERR);
  if(!DosFindFirst(oldname)) {
    do {

      /* build target name */

      if(fb.attrFile & FILE_DIRECTORY) {
        DosError(FERR_ENABLEHARDERR);
        rc = DosCreateDir();
        if(rc == ERROR_INVALID_NAME || rc == ERROR_FILENAME_EXCED_RANGE) {

          /* truncate directory name */
          /* create that directory   */
          /* update containers for name used */

        }
        rc = docopyallf(type,,"%s",);  /* recurse */
      }
      else
        rc = docopyf(type,,"%s",);     /* copy file */
      DosError(FERR_DISABLEHARDERR);
    } while(!rc && !DosFindNext());
    DosFindClose(hdir);
  }
  else
    rc = ERROR_FILE_NOT_FOUND;
  return rc;
}

#endif


APIRET docopyf (INT type,CHAR *oldname,CHAR *newname,...) {

  /*
   * returns:
   *   0:  success
   *  -1:  bad string parameter(s)
   *  -2:  source didn't exist
   *  -3:  bad type
   *   anything else:  API return
   */

  CHAR        fullnewname[CCHMAXPATH + 1],longname[CCHMAXPATH],
              shortname[CCHMAXPATH];
  CHAR        olddisk,newdisk,dir[CCHMAXPATH],*p,*pp;
  APIRET      ret = -1,rc;
  FILESTATUS3 st,st2,dummy;
  BOOL        diskchange = FALSE,zaplong = FALSE;
  va_list     ap;

  *fullnewname = *longname = *shortname = *dir = 0;

  va_start(ap,
           newname);
  vsprintf(fullnewname,
           newname,
           ap);
  va_end(ap);

  if(!oldname ||
     !*oldname ||
     !*fullnewname)  /* bad string args */
    return (APIRET)-1;
  DosError(FERR_DISABLEHARDERR);
  if(DosQueryPathInfo(oldname,
                      FIL_STANDARD,
                      &st,
                      sizeof(FILESTATUS3)))
    /* no source */
    return (APIRET)-2;
  AdjustWildcardName(oldname,
                     fullnewname);
  MakeFullName(oldname);
  MakeFullName(fullnewname);
  olddisk = toupper(*oldname);        /* source drive */
  newdisk = toupper(*fullnewname);    /* destination drive */
  GetLongName(oldname,
              longname);
  if(*longname) {
    if(!(driveflags[toupper(*oldname) - 'A'] & DRIVE_NOLONGNAMES))
      *longname = 0;
    else {
      p = RootName(longname);
      if(p != longname)
        memmove(longname,
                p,
                strlen(p));
    }
    /* did root name change? */
    p = RootName(oldname);
    pp = RootName(fullnewname);
    saymsg(MB_ENTER,HWND_DESKTOP,DEBUG_STRING,"oldname: %s\rnewname: %s",oldname,fullnewname);
    if(stricmp(p,
               pp))
      zaplong = TRUE;
  }

  DosError(FERR_DISABLEHARDERR);
  switch(type) {
    case WPSMOVE:
      {
        HOBJECT hobjsrc;
        HOBJECT hobjdest;

        ret = ERROR_FILE_NOT_FOUND;
        hobjsrc = WinQueryObject(oldname);
        if(hobjsrc) {
          strcpy(dir,
                 fullnewname);
          p = strrchr(dir,'\\');
          if(p < dir + 3)
            p++;
          *p = 0;
          ret = ERROR_PATH_NOT_FOUND;
          hobjdest = WinQueryObject(dir);
          if(hobjdest) {
            ret = ERROR_GEN_FAILURE;
            hobjsrc = WinMoveObject(hobjsrc,
                                    hobjdest,
                                    0);
            if(hobjsrc)
              ret = 0;
          }
        }
      }
      return ret;

    case WPSCOPY:
      {
        HOBJECT hobjsrc;
        HOBJECT hobjdest;

        ret = ERROR_FILE_NOT_FOUND;
        hobjsrc = WinQueryObject(oldname);
        if(hobjsrc) {
          strcpy(dir,
                 fullnewname);
          p = strrchr(dir,'\\');
          if(p < dir + 3)
            p++;
          *p = 0;
          ret = ERROR_PATH_NOT_FOUND;
          hobjdest = WinQueryObject(dir);
          if(hobjdest) {
            ret = ERROR_GEN_FAILURE;
            hobjsrc = WinCopyObject(hobjsrc,
                                    hobjdest,
                                    0);
            if(hobjsrc)
              ret = 0;
          }
        }
      }
      return ret;

    case MOVE:
      *dir = 0;
      if(olddisk == newdisk) {      /* same drive */
        /* make temporary copy in case move fails */
        if(IsFile(fullnewname) != -1 &&
           stricmp(oldname,
                   fullnewname)) {
          strcpy(dir,
                 fullnewname);
          p = strrchr(dir,'\\');
          if(p)
            *p = 0;
          strcat(dir,"\\");
          MakeTempName(dir);
          if(DosMove(fullnewname,
                     dir))
            *dir = 0;
        }
        DosError(FERR_DISABLEHARDERR);
        ret = DosMove(oldname,
                      fullnewname);   /* move it */
        if(ret &&
           *dir) { /* failed -- clean up */
          DosError(FERR_DISABLEHARDERR);
          if(!DosMove(dir,
                      fullnewname))
            Broadcast((HAB)0,
                      hwndMain,
                      UM_UPDATERECORD,
                      MPFROMP(dir),
                      MPVOID);
        }
        else if(!ret &&
                *dir) {
          if(!IsFile(dir)) {
            if(!strchr(dir,'?') &&
               !strchr(dir,'*'))
              wipeallf("%s\\*",dir);
            DosError(FERR_DISABLEHARDERR);
            if(DosDeleteDir(dir)) {
              make_deleteable(dir);
              DosDeleteDir(dir);
            }
          }
          else if(IsFile(dir) > 0) {
            DosError(FERR_DISABLEHARDERR);
            if(DosForceDelete(dir)) {
              make_deleteable(dir);
              DosForceDelete(dir);
            }
            if(zaplong)
              ZapLongName(dir);
            Broadcast((HAB)0,
                      hwndMain,
                      UM_UPDATERECORD,
                      MPFROMP(dir),
                      MPVOID);
          }
        }
      }
      else {                          /* different drives */
        DosError(FERR_DISABLEHARDERR);
        ret = DosCopy(oldname,
                      fullnewname,
                      DCPY_EXISTING);   /* <=-NOTE! */
        if(ret == ERROR_DISK_CHANGE) {
          DosError(FERR_ENABLEHARDERR);
          ret = DosCopy(oldname,
                        fullnewname,
                        DCPY_EXISTING);
          diskchange = TRUE;
        }
        if(ret == ERROR_INVALID_NAME ||
           ret == ERROR_FILENAME_EXCED_RANGE) {
          if(TruncName(fullnewname,
                       shortname)) {  /* make 8.3 filename */
            DosError(FERR_DISABLEHARDERR);
            ret = DosCopy(oldname,
                          shortname,
                          DCPY_EXISTING);
            if(!ret) {  /* success -- write longname ea */
              WriteLongName(shortname,
                            fullnewname);
              strcpy(fullnewname,
                     shortname);
              /* broadcast fixup msg to windows */
              Broadcast((HAB)0,
                        hwndMain,
                        UM_UPDATERECORD,
                        MPFROMP(shortname),
                        MPVOID);
            }
          }
        }
        else if(!ret &&
                *longname) {

          CHAR fixname[CCHMAXPATH];

          strcpy(fixname,
                 fullnewname);
          p = strrchr(fixname,'\\');
          if(p) {
            p++;
            *p = 0;
          }
          strcat(fixname,
                 longname);
          DosError(FERR_DISABLEHARDERR);
          DosMove(fullnewname,
                  fixname);
          strcpy(fullnewname,
                 fixname);
          if(zaplong)
            ZapLongName(fixname);
          Broadcast((HAB)0,
                    hwndMain,
                    UM_UPDATERECORD,
                    MPFROMP(fixname),
                    MPVOID);
        }
        if(!ret) {                        /* double-check success */
          DosError(FERR_DISABLEHARDERR);
          rc = DosQueryPathInfo(fullnewname,
                                FIL_STANDARD,
                                &st2,
                                sizeof(FILESTATUS3));
          if(rc == ERROR_DISK_CHANGE) {
            DosError(FERR_ENABLEHARDERR);
            rc = DosQueryPathInfo(fullnewname,
                                  FIL_STANDARD,
                                  &st2,
                                  sizeof(FILESTATUS3));
          }
          if(!rc && st2.cbFile == st.cbFile) {   /* seems to have worked... */
            DosError(FERR_DISABLEHARDERR);
            if(diskchange) {
              DosError(FERR_ENABLEHARDERR);
              DosQueryPathInfo(oldname,
                               FIL_STANDARD,
                               &dummy,
                               sizeof(FILESTATUS3)); /* force disk change */
            }
            if(!(st2.attrFile & FILE_DIRECTORY))   /* erase file */
              unlinkf("%s",oldname);
            else {                                /* remove directory */
              wipeallf("%s\\*",oldname);
              DosError(FERR_DISABLEHARDERR);
              if(DosDeleteDir(oldname)) {
                make_deleteable(oldname);
                DosDeleteDir(oldname);
              }
            }
          }
        }
      }
      return ret;

    case COPY:
      DosError(FERR_DISABLEHARDERR);
      ret = DosCopy(oldname,
                    fullnewname,
                    DCPY_EXISTING);  /* <=-NOTE! */
      if(ret == ERROR_DISK_CHANGE) {
        DosError(FERR_ENABLEHARDERR);
        ret = DosCopy(oldname,
                      fullnewname,
                      DCPY_EXISTING);
        diskchange = TRUE;
      }
      if(ret == ERROR_INVALID_NAME ||
         ret == ERROR_FILENAME_EXCED_RANGE) {
        if(TruncName(fullnewname,
                     shortname)) {
          DosError((diskchange) ?
           FERR_ENABLEHARDERR :
           FERR_DISABLEHARDERR);
          ret = DosCopy(oldname,
                        shortname,
                        DCPY_EXISTING);
          if(!ret) {
            WriteLongName(shortname,
                          fullnewname);
            strcpy(fullnewname,
                   shortname);
            Broadcast((HAB)0,
                      hwndMain,
                      UM_UPDATERECORD,
                      MPFROMP(shortname),
                      MPVOID);
          }
        }
      }
      else if(!ret &&
              *longname) {

        CHAR fixname[CCHMAXPATH];

        strcpy(fixname,
               fullnewname);
        p = strrchr(fixname,'\\');
        if(p) {
          p++;
          *p = 0;
        }
        strcat(fixname,
               longname);
        DosError(FERR_DISABLEHARDERR);
        DosMove(fullnewname,
                fixname);
        if(zaplong)
          ZapLongName(fixname);
        Broadcast((HAB)0,
                  hwndMain,
                  UM_UPDATERECORD,
                  MPFROMP(fixname),
                  MPVOID);
      }
      return ret;

    default:  /* shouldn't happen */
      DosBeep(50,100);
      break;
  }
  return (APIRET)-3;  /* bad type */
}


INT make_deleteable (CHAR *filename) {

  INT ret = -1;
  FILESTATUS3 fsi;

  DosError(FERR_DISABLEHARDERR);
  if(!DosQueryPathInfo(filename,
                       FIL_STANDARD,
                       &fsi,
                       sizeof(FILESTATUS3))) {
    fsi.attrFile = 0;
    DosError(FERR_DISABLEHARDERR);
    if(!DosSetPathInfo(filename,
                       FIL_STANDARD,
                       &fsi,
                       sizeof(FILESTATUS3),
                       0L))
      ret = 0;
  }
  return ret;
}


INT wipeallf (CHAR *string,...) {

  /* unlink everything from directory on down... */

  FILEFINDBUF3  *f;
  HDIR          search_handle;
  ULONG         num_matches;
  CHAR          *p,*ss,*str;
  CHAR          s[CCHMAXPATH],mask[257];
  va_list       ap;
  INT           rc;

  va_start(ap,string);
  vsprintf(s,string,ap);
  va_end(ap);

  if(!*s)
    return -1;
  p = s;
  while((p = strchr(p,'/')) != NULL) {
    *p = '\\';
    p++;
  }

  str = strdup(s);
  if(!str)
    return -1;

  { /* safety net -- disallow deleting a root dir or partial name */
    CHAR temp;

    p = strrchr(str,'\\');
    if(p) {
      p++;
      temp = *p;
      *p = 0;
      if(IsRoot(str) || !IsFullName(str)) {   /* under no circumstances! */
        free(str);
        DosBeep(100,250);
        return -1;
      }
      *p = temp;
    }
  }

  p = s;
  p = strrchr(s,'\\');           /* strip s to just path */
  if(!p)
    p = strrchr(s,':');
  if(p) {
    p++;
    strncpy(mask,p,256);
    mask[256] = 0;
    *p = 0;
  }
  else {
    *mask = 0;
    *s = 0;
  }

  ss = (CHAR *)malloc(CCHMAXPATH);
  f = (FILEFINDBUF3 *)malloc(sizeof(FILEFINDBUF3));
  if(!ss || !f) {
    if(ss)
      free(ss);
    if(f)
      free(f);
    free(str);
    return -1;
  }

  search_handle = HDIR_CREATE;
  num_matches = 1L;

  DosError(FERR_DISABLEHARDERR);
  if(!DosFindFirst(str,&search_handle,FILE_NORMAL | FILE_DIRECTORY |
     FILE_SYSTEM | FILE_READONLY | FILE_HIDDEN | FILE_ARCHIVED,f,
     sizeof(FILEFINDBUF3),&num_matches,FIL_STANDARD)) {

    strcpy(ss,s);
    p = &ss[strlen(ss)];

    do {
      strcpy(p,f->achName);
      if(f->attrFile & FILE_DIRECTORY) {
        if(strcmp(f->achName,".") && strcmp(f->achName,"..")) {
          wipeallf("%s/%s",ss,mask);    /* recurse to wipe files */
          DosError(FERR_DISABLEHARDERR);
          if(DosDeleteDir(ss)) {               /* remove directory */
            make_deleteable(ss);
            DosError(FERR_DISABLEHARDERR);
            DosDeleteDir(ss);
          }
        }
      }
      else {
        DosError(FERR_DISABLEHARDERR);
        if(DosForceDelete(ss)) {
          make_deleteable(ss);
          DosError(FERR_DISABLEHARDERR);
          rc = (INT)DosForceDelete(ss);
          if(rc)
            return rc;
        }
      }
      num_matches = 1L;
      DosError(FERR_DISABLEHARDERR);
    } while(!DosFindNext(search_handle,f,sizeof(FILEFINDBUF3),
                         &num_matches));
    DosFindClose(search_handle);
  }

  free(f);
  free(ss);
  free(str);
  return 0;
}


INT unlink_allf (CHAR *string,...) {

  /* wildcard delete */

  FILEFINDBUF3 *f;
  HDIR  search_handle;
  ULONG num_matches;
  CHAR  *p,*ss,*str;
  CHAR  s[CCHMAXPATH];
  va_list ap;

  va_start(ap,string);
  vsprintf(s,string,ap);
  va_end(ap);

  if(!*s)
    return -1;
  p = s;
  while((p = strchr(p,'/')) != NULL) {
    *p = '\\';
    p++;
  }

  str = strdup(s);
  if(!str)
    return -1;

  p = s;
  p = strrchr(s,'\\');           /* strip s to just path */
  if(!p)
    p = strrchr(s,':');
  if(p) {
    p++;
    *p = 0;
  }
  else
    *s = 0;

  ss = (CHAR *)malloc(CCHMAXPATH);
  f = (FILEFINDBUF3 *)malloc(sizeof(FILEFINDBUF3));
  if(!ss || !f) {
    if(ss)
      free(ss);
    if(f)
      free(f);
    free(str);
    return -1;
  }

  search_handle = HDIR_CREATE;
  num_matches = 1L;

  DosError(FERR_DISABLEHARDERR);
  if(!DosFindFirst(str,&search_handle,FILE_NORMAL,f,
     sizeof(FILEFINDBUF3),&num_matches,FIL_STANDARD)) {

    strcpy(ss,s);
    p = &ss[strlen(ss)];

    do {
      strcpy(p,f->achName);
      unlinkf("%s",ss);
      num_matches = 1L;
      DosError(FERR_DISABLEHARDERR);
    } while(!DosFindNext(search_handle,f,sizeof(FILEFINDBUF3),
                         &num_matches));
    DosFindClose(search_handle);
  }

  free(f);
  free(ss);
  free(str);
  return 0;
}


INT unlinkf (CHAR *string,...) {

  CHAR buffer[CCHMAXPATH];
  va_list ap;

  va_start(ap,string);
  vsprintf(buffer,string,ap);
  va_end(ap);

  if(!strstr(buffer,ArcTempRoot)) {
    DosError(FERR_DISABLEHARDERR);
    if(DosDelete(buffer)) {
      make_deleteable(buffer);
      DosError(FERR_DISABLEHARDERR);
      return DosDelete(buffer);
    }
  }
  else {
    DosError(FERR_DISABLEHARDERR);
    if(DosForceDelete(buffer)) {
      make_deleteable(buffer);
      DosError(FERR_DISABLEHARDERR);
      return DosForceDelete(buffer);
    }
  }
  return 0;
}

