/* ftw.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */

#include <stdlib.h>
#include <string.h>
#include <io.h>
#include <ftw.h>
#include <errno.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <emx/io.h>

static int ftw_recurse (int (*fn)(const char *name,
                                  const struct stat *stat_ptr,
                                  int flag),
                        char *name_buf, int index)
{
  int rc, flag, len;
  struct stat st;
  DIR *dir;
  struct dirent *ent;

  dir = _opendir (name_buf);
  if (dir == NULL)
    return -1;
  if (index < 1 || !_trslash (name_buf, index, 0))
    name_buf[index++] = '/';
  rc = 0;
  for (;;)
    {
      ent = _readdir (dir);     /* emx version never fails */
      if (ent == NULL)
        break;
      len = strlen (ent->d_name);
      if (index + len >= MAXPATHLEN)
        {
          errno = ENAMETOOLONG;
          rc = -1;
          break;
        }
      strcpy (name_buf + index, ent->d_name);
      if (_stat (name_buf, &st) != 0)
        flag = FTW_NS;
      else if ((st.st_mode & S_IFMT) == S_IFDIR)
        flag = FTW_D;
      else
        flag = FTW_F;
      if (flag != FTW_D || (strcmp (ent->d_name, ".") != 0 &&
                            strcmp (ent->d_name, "..") != 0))
        {
          rc = fn (name_buf, &st, flag);
          if (rc != 0)
            break;
          if (flag == FTW_D)
            {
              rc = ftw_recurse (fn, name_buf, index + len);
              if (rc != 0)
                break;
            }
        }
    }
  _closedir (dir);
  return rc;
}


int _ftw (const char *path,
          int (*fn)(const char *name, const struct stat *stat_ptr, int flag),
          int depth)
{
  struct stat st;
  char name_buf[MAXPATHLEN+1];
  int rc, len;

  len = strlen (path);
  if (len >= MAXPATHLEN)
    {
      errno = ENAMETOOLONG;
      return -1;
    }
  if (_stat (path, &st) != 0)
    return -1;
  if ((st.st_mode & S_IFMT) != S_IFDIR)
    {
      errno = ENOTDIR;
      return -1;
    }
  strcpy (name_buf, path);
  rc = fn (name_buf, &st, FTW_D);
  if (rc != 0)
    return rc;
  return ftw_recurse (fn, name_buf, len);
}
