/* sys/fstat.c (emx+gcc) -- Copyright (c) 1992-1993 by Eberhard Mattes */

#include <sys/emx.h>
#include <os2emx.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "syscalls.h"

int __fstat (int handle, struct stat *buf)
{
  ULONG rc;
  ULONG htype, hflags;
  FILESTATUS3 info;

  memset (buf, 0, sizeof (*buf));
  rc = DosQueryHType (handle, &htype, &hflags);
  if (rc != 0)
    {
      _sys_set_errno (rc);
      return (-1);
    }
  switch (htype & 0xff)
    {
    case 1:
      buf->st_mode = S_IFCHR;
      break;
    case 2:
      buf->st_mode = S_IFSOCK;
      break;
    default:
      buf->st_mode = S_IFREG;
      break;
    }
  if (buf->st_mode == S_IFREG)
    {
      rc = DosQueryFileInfo (handle, FIL_STANDARD, &info, sizeof (info));
      if (rc != 0)
        {
          _sys_set_errno (rc);
          return (-1);
        }
      buf->st_attr = info.attrFile;
      buf->st_size = info.cbFile;
      buf->st_reserved = 0;
      buf->st_mtime = _sys_p2t (info.ftimeLastWrite, info.fdateLastWrite);
      if (FTIMEZEROP (info.ftimeCreation) &&
          FDATEZEROP (info.fdateCreation))
        buf->st_ctime = buf->st_mtime;
      else
        buf->st_ctime = _sys_p2t (info.ftimeCreation, info.fdateCreation);
      if (FTIMEZEROP (info.ftimeLastAccess) &&
          FDATEZEROP (info.fdateLastAccess))
        buf->st_atime = buf->st_mtime;
      else
        buf->st_atime = _sys_p2t (info.ftimeLastAccess, info.fdateLastAccess);
      if (info.attrFile & 1)
        buf->st_mode |= (S_IREAD >> 6) * 0111;
      else
        buf->st_mode |= ((S_IREAD|S_IWRITE) >> 6) * 0111;
    }
  else
    {
      buf->st_size = 0;
      rc = DosQueryFHState (handle, &hflags);
      if (rc != 0)
        {
          _sys_set_errno (rc);
          return (-1);
        }
      if ((hflags & 7) == 0)
        buf->st_mode |= (S_IREAD >> 6) * 0111;
      else
        buf->st_mode |= ((S_IREAD|S_IWRITE) >> 6) * 0111;
    }
  buf->st_uid = 0;
  buf->st_gid = 0;
  buf->st_ino = _sys_ino++;
  if (_sys_ino == 0)
    _sys_ino = 1;
  buf->st_dev = 0;
  buf->st_rdev = 0;
  buf->st_nlink = 1;
  return (0);
}
