/*
   Miscellaneous routines which are needed by FOLDER but are not in the TC
   library or cannot be used for some reasons)
*/
/*{{{  includes*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stat.h>    /* needed for struct stat */
#include <errno.h>
#include <tos.h>
#include "..\fold\fold_os.h"
/*}}}  */

/*{{{  stat*/
/*
   This is a very simple stat() implementation. It does just enough to satisfy
   folder, that is, it can tell if the given name is a file or a directory, and
   it returns access codes so FOLDER thinks that the files can be accessed.
   1991 by M. Schwingen. This is PD.
*/
int stat(char *path, struct stat *statbuf)
{
  DTA mydta, *olddta;
  int result;

  olddta=Fgetdta();
  Fsetdta(&mydta);

  result = 0;
  if (Fsfirst(path,0x31) == 0)
  {
    statbuf->st_mode = mydta.d_attrib | 256;
  }
  else
    statbuf->st_mode = 16|256;
  statbuf->st_uid = 1;
  statbuf->st_gid = 1;

  Fsetdta(olddta);
  return result;
}
/*}}}  */

/*{{{  directory routines*/
/* POSIX compatible directory access routines for TOS */
/* written by Eric R. Smith and placed in the public domain */
/* modified for TurboC/ORIGAMI by M. Schwingen */

static ino_t  inode = 0;
#define FA_HIDDEN 0x02
#define FA_SYSTEM 0x04
#define FA_DIR    0x10

/*{{{  DIR *opendir(const char *_dirname)*/
DIR *opendir(const char *_dirname)
{
  char dirname[FILENAME_MAX];
  char tmp[FILENAME_MAX];
  char *t;
  DIR  *dd;
  struct dirent *d, *x;
  long r;
  short i = 0;
  DTA mydta, *olddta;

  if (!(dd = malloc((size_t)sizeof(DIR)))) {
    errno = ENOMEM;
    return NULL;
  }
  olddta = (DTA *)Fgetdta();
  Fsetdta(&mydta);
  strcpy(tmp,_dirname);
  for (t = tmp; *t; t++) ;

/* make sure it's terminated by a slash */
  if (t > tmp && *(t-1) == '\\')
    *--t = 0;
  strcpy(t,"\\*.*");
  strcpy(dirname,tmp);

  if ((r = Fsfirst(dirname, FA_SYSTEM|FA_HIDDEN|FA_DIR)) < 0) {
    if ((r = -r) != ENOENT) {
      errno = r;
      free(dd);
      dd = NULL;
      goto _done;
    }
    d = NULL;
    goto _done;
  }
  d = x = malloc((size_t)(DIRENTSIZ(strlen(mydta.d_fname))));
  for (;;) {
    if (!x) {
      errno = ENOMEM;
      free(dd); dd = NULL;
      break;
    }
    strcpy(x->d_name,mydta.d_fname);
    x->d_ino = ++inode; /* make sure no two are equal */
    x->d_off = i++;

/* I don't know what d_reclen means on Unix, but for TOS we might as well
  stuff the string length in here (so sys/dir.h can be more like BSD) */
    x->d_reclen = strlen(x->d_name);
    if (Fsnext() == 0) {
           x->d_next = malloc((size_t)(DIRENTSIZ(strlen(mydta.d_fname))));
           x = x->d_next;
    }
    else {
           x->d_next = 0;
           break;
    }
  }
_done:
  Fsetdta(olddta);
  if (dd) {
    dd->D_list = dd->D_curpos = d;
  }
  return dd;
}
/*}}}  */
/*{{{  struct dirent *readdir(DIR *dirp)*/
struct dirent *readdir(DIR *dirp)
{
  struct dirent *x;

  if (!dirp) return NULL;

  x = dirp->D_curpos;
  if (x) dirp->D_curpos = x->d_next;
  return x;
}
/*}}}  */
/*{{{  int closedir(DIR *dirp)*/
int closedir(DIR *dirp)
{
  struct dirent *x, *oldx;

  if (!dirp) return -1;

  for (x = dirp->D_list; x; ) {
    oldx = x;
    x = x->d_next;
    free(oldx);
  }
  free(dirp);
  return 0;
}
/*}}}  */
/*
  Functions which are not needed in FOLDER are not included here. Get the original
  version by Eric R. Smith if you wich to use these routines.
*/
/*}}}  */
