/* stat.c: */

#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <exec/memory.h>
#include <errno.h>
#include "unixlib.h"

#ifdef LATTICE
#include <proto/dos.h>
#include <proto/exec.h>
#endif

static time_t cvt_date (struct DateStamp *p_date)
{
  unsigned long t = p_date->ds_Tick / TICKS_PER_SECOND +
  	            p_date->ds_Minute * 60 +
	            p_date->ds_Days * 60 * 60 * 24;

  t += (8 * 365 + 2) * 24 * 60 * 60;
  return (time_t) t;
}

int stat (const char *p_name, struct stat *p_stat)
{
  BPTR lock;
  struct FileInfoBlock *fib;
  
  lock = Lock ((UBYTE *) p_name, ACCESS_READ);
  if (!lock) {
    errno = ENOENT;
    return -1;
  }

  fib = AllocMem ((ULONG) sizeof (*fib), 0);
  if (!fib) {
    UnLock (lock);
    return -1;
  }

  if (!Examine (lock, fib)) {
    UnLock (lock);
    FreeMem (fib, sizeof (*fib));
    return -1;  
  }

  p_stat->st_dev = 0;
  p_stat->st_ino = 0;
  p_stat->st_mode = 0;
  if (!(fib->fib_Protection & FIBF_READ))
    p_stat->st_mode |= S_IRUSR | S_IRGRP | S_IROTH;
  if (!(fib->fib_Protection & FIBF_WRITE))
    p_stat->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
  if (!(fib->fib_Protection & FIBF_EXECUTE))
    p_stat->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH;

  if (fib->fib_DirEntryType < 0)
    p_stat->st_mode |= S_IFREG;
  else {
    p_stat->st_mode |= S_IFDIR;
    p_stat->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH;
  }
  p_stat->st_nlink = 0;
  p_stat->st_uid = 1;
  p_stat->st_gid = 1;
  p_stat->st_rdev = 0;
  p_stat->st_size = fib->fib_Size;
  p_stat->st_atime = cvt_date (&(fib->fib_Date));
  p_stat->st_mtime = cvt_date (&(fib->fib_Date));
  p_stat->st_ctime = cvt_date (&(fib->fib_Date));


  FreeMem (fib, sizeof (*fib));
  
  UnLock (lock);
  
  return 0;
}

int lstat (const char *p_name, struct stat *p_stat)
{
  return stat (p_name, p_stat);
}

#ifdef LATTICE
int access (const char *p_path, int p_modus)
#else
int access (char *p_path, int p_modus)
#endif
{
  struct stat sbuf;

  if (stat (p_path, &sbuf) < 0)
    return -1;

  if ((p_modus & R_OK) && !(sbuf.st_mode & S_IRUSR))
    return -1;

  if ((p_modus & W_OK) && !(sbuf.st_mode & S_IWUSR))
    return -1;

  if ((p_modus & X_OK) && !(sbuf.st_mode & S_IXUSR))
    return -1;

  return 0;
}
