
#include <exec/types.h>
#include <libraries/dos.h>
#include <functions.h>

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <error.h>
#include <time.h>
#include <fcntl.h>


int
_get_status(fl, st)
    BPTR fl;
    struct stat *st;
{
  struct FileInfoBlock *fib;

  /* Allocate space on stack for fib. */

  BYTE fib_Block[sizeof(struct FileInfoBlock) + 2];

  /* Make sure fib is longword aligned. */

  fib = (struct FileInfoBlock *)fib_Block;
  if (((ULONG)fib & 0x02) != 0)
    fib = (struct FileInfoBlock *)((ULONG)fib + 2);

  /* Get info on the file. */

  if (Examine(fl, fib) == DOSFALSE) {
    errno = EIO;
    return -1;
  }
  else {
    u_short mode = 0;
    LONG prot;

    prot = fib->fib_Protection;

    if ((prot & FIBB_READ)    == 0) mode |= S_IREAD;
    if ((prot & FIBB_WRITE)   == 0) mode |= S_IWRITE;
    if ((prot & FIBB_EXECUTE) == 0) mode |= S_IEXEC;

    mode |= (mode >> 3) | (mode >> 6);

    if (fib->fib_DirEntryType >= 0)
      mode |= S_IFDIR;
    else
      mode |= S_IFREG;

    st->st_mode = mode;

    st->st_size = (off_t)fib->fib_Size;
    st->st_blocks = fib->fib_NumBlocks;

    st->st_dev = (dev_t)0;  /* ...for now */
    st->st_blksize  = 512;  /* ...for now */

    st->st_ino = (ino_t)fib->fib_DiskKey;

    st->st_nlink = 0;
    st->st_uid = 0;
    st->st_gid = 0;
    st->st_rdev = 0;

    st->st_atime =
    st->st_mtime =
    st->st_ctime = (time_t)((fib->fib_Date.ds_Minute +
                             fib->fib_Date.ds_Days * 60 * 24) * 60 +
                            fib->fib_Date.ds_Tick / CLK_TCK);

    return 0;
  }
}


int
stat (path, st)
    const char *path;
    struct stat *st;
{
  BPTR fl;
  int ReturnValue;

  fl = Lock((char *)path, ACCESS_READ);
  if (fl == 0) {
    errno = ENOENT;
    return -1;
  }

  ReturnValue = _get_status(fl, st);

  UnLock (fl);

  return ReturnValue;
}


int
fstat(fd, st)
    int fd;
    struct stat *st;
{
  long filepos;
  BPTR fh;
  extern struct _device *_devtab;

  /* fprintf(stderr, "Warning: Bogus fstat() called.\n"); */

  if (fd < 0 || fd >= _numdev) {
    errno = EBADF;
    return -1;
  }

  fh = _devtab[fd]._fileHandle;

  filepos = Seek(fh, 0L, OFFSET_END);

  if (filepos >= 0)
    filepos = Seek(fh, filepos, OFFSET_BEGINNING);

  if (filepos < 0) {
    errno = IoErr();
    return -1;
  }

  st->st_size = filepos;

  st->st_atime = 0;
  st->st_mtime = 0;
  st->st_ctime = 0;

  st->st_mode = S_IFREG | S_IREAD | S_IWRITE | S_IEXEC;

  st->st_ino = 0;

  st->st_dev = 0;
  st->st_rdev = 0;

  st->st_nlink = 0;

  st->st_uid = 0;
  st->st_gid = 0;

  st->st_blocks = 0;
  st->st_blksize = 0;

  return 0;
}

