/*
; OSDATE - return file's creation-date (called from Lattice), or -1
;         if can't find the file.
; Synopsis:
;              int osdate(filename, time1, time2)
;                      char *filename;
;                      int *time1, *time2;
;
*/

#include "lar.h"
#define FILERR (-1)
#include "make.h"

static void getftime ();
extern char *printdate ();

DATE osdate (filename, success)
char *filename;
int *success;
{
    extern DATE adate ();
    auto DATE newdate;
#ifndef MCH_AMIGA
    register int handle;
#endif

    DBUG_ENTER ("osdate");
#ifdef MCH_AMIGA
    newdate = adate ();
    getftime (filename, newdate, success);
#else
    if ((handle = _open (filename, O_RDONLY)) == FILERR) {
       *success = FAILURE;
       newdate = (DATE) NULL;
    } else {
       newdate = adate ();
       getftime (handle, newdate);
       _close (handle);
       *success = SUCCEED;
    }
#endif
    DBUG_RETURN (newdate);
}

struct ludir ldir[MAXFILES];
int nslots;
extern char *getname ();

DATE getarchdate (archname, filename)
char *archname;
char *filename;
{
    register fildesc lfd;
    register int i;
    register struct ludir *lptr;
    union timing {
       DATE ftimeptr;
       long *longptr;
    } unionptr;
    extern DATE adate ();
    auto DATE newdate;
    register char *realname;
    extern void cant ();

    DBUG_ENTER ("getarchdate");
    DBUG_4 ("ard", "looking for %s inside %s", filename, archname);
    if ((lfd = _open (archname, O_RDONLY)) == FILERR) {
       cant (archname);
    }
    getdir (lfd);
    for (i = 1, lptr = ldir + 1; i < nslots; i++, lptr++) {
       if (lptr -> l_stat != ACTIVE) {
           continue;
       }
       realname = getname ((char *) lptr -> l_name, (char *) lptr -> l_ext);
       if (strcmp (realname, filename) != 0) {
           continue;
       }
       DBUG_3 ("ard", "found name %s", realname);
       DBUG_3 ("ard", "time %lx", lwtol (lptr -> l_datetime));
       newdate = adate ();
       unionptr.ftimeptr = newdate;
       *(unionptr.longptr) = lwtol (lptr -> l_datetime);
       break;
    }
    (void) _close (lfd);
    DBUG_3 ("ard", "date is %s", printdate (newdate));
    DBUG_RETURN (newdate);
}

#ifdef LAR
copyfile (archname, filename)
char *archname;
char *filename;
{
    register int i;
    register struct ludir *lptr;
    register fildesc lfd;
    register fildesc ofd;
    union timer timeunion;
    extern int errno;
    register char *realname;
    auto char outname[64];
    register char *tmpptr;
    extern char *strrchr ();
    extern void cant ();

    DBUG_ENTER ("copyfile");
    DBUG_4 ("cpf", "looking for %s inside %s", filename, archname);
    if ((lfd = _open (archname, O_RDWR)) == FILERR) {
       cant (archname);
    }
    getdir (lfd);
    for (i = 1, lptr = &ldir[1]; i < nslots; i++, lptr++) {
       if (lptr -> l_stat != ACTIVE) {
           continue;
       }
       realname = getname (lptr -> l_name, lptr -> l_ext);
       if (strcmp (realname, filename) != 0) {
           continue;
       }
       /* generate real filename */
       tmpptr = strrchr (archname, '/');       /* should be path chr */
       if (tmpptr != NULL) {
           i = (int) (tmpptr - archname);
           i++;
           DBUG_3 ("tmpptr", "tmpptr was not NULL; i is %d", i);
           strncpy (outname, archname, i);
       } else {
           DBUG_2 ("tmpptr", "tmpptr was NULL");
           i = 0;
           *outname = '\0';
       }
       strcat (outname, realname);
       DBUG_3 ("outn", "got it; about to extract %s", outname);
       ofd = _creat (outname, 0);
       if (ofd == FILERR) {
           fputs (outname, stderr);
           fputs ("  - can't create\n", stderr);
           DBUG_VOID_RETURN;
       } else {
           (void) lseek (lfd, (long) lwtol (lptr -> l_off), 0);
           acopy (lfd, ofd, lwtol (lptr -> l_len));
           timeunion.realtime = lwtol (lptr -> l_dATETIME);
           if (ofd != fileno (stdout)) {
               (void) setftime (ofd, &(timeunion.ftimep));
               (void) _close (ofd);
           }
           break;              /* exit after copy */
       }
    }
    (void) _close (lfd);
    DBUG_VOID_RETURN;
}

static void acopy (fdi, fdo, nbytes)   /* copy nbytes from fdi to fdo */
fildesc fdi;
fildesc fdo;
long nbytes;
{
    register int btr;
    register int retval;
    char blockbuf[BLOCK];

    for (btr = (nbytes > BLOCK) ? BLOCK : (int) nbytes; btr > 0;
           nbytes -= BLOCK, btr = (nbytes > BLOCK) ? BLOCK : (int) nbytes) {
       if ((retval = _read (fdi, blockbuf, btr)) != btr) {
           if (retval == 0) {
               error ("Premature EOF\n");
           }
           if (retval == FILERR) {
               error ("Can't read");
           }
       }
       if ((retval = _write (fdo, blockbuf, btr)) != btr) {
           if (retval == FILERR) {
               error ("Write Error");
           }
       }
    }
}
#endif                         /* LAR */

#ifdef unix
#include <sys/types.h>
#include <sys/stat.h>

static void getftime (handle, date)
int handle;
DATE date;
{
    struct stat statb;

    DBUG_ENTER ("getftime");
    fstat (handle, &statb);
    *date = statb.st_mtime;
    DBUG_3 ("date", "got date %lu", *date);
    DBUG_VOID_RETURN;
}
#endif

#ifdef MCH_AMIGA
#include <libraries/dosextens.h>
#include <libraries/dos.h>
#include <functions.h>

static void getftime (filename, date, success)
char *filename;
DATE date;
int *success;
{
    struct FileInfoBlock *fib;
    struct Lock *lockp;    
    int status = FAILURE;

    DBUG_ENTER ("getftime");
    lockp = Lock (filename, ACCESS_READ);
    if (lockp != NULL) {
       fib = (struct FileInfoBlock *) Calloc (1, sizeof (struct FileInfoBlock));
       DBUG_3 ("fib", "fib = %x", fib);
       if (fib == NULL) {
           allerr ();
       } else {
           if (Examine (lockp, fib)) {
               DBUG_3 ("date", "file '%s'", filename);
               DBUG_3 ("date", "date is %s", printdate (&(fib -> fib_Date)));
               date -> ds_Days = fib -> fib_Date.ds_Days;
               date -> ds_Minute = fib -> fib_Date.ds_Minute;
               date -> ds_Tick = fib -> fib_Date.ds_Tick;
               status = SUCCEED;
           } else {
               fprintf (stderr, "Examine() failed!\n");
           }
           free (fib);
           UnLock (lockp);
       }
    }
    *success = status;
    DBUG_VOID_RETURN;
}
#endif
