/*
; 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 AMIGA
    register int handle;
#endif

    DBUG_ENTER ("osdate");
#ifdef 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 AMIGA
#include <libraries/dosextens.h>
#include <libraries/dos.h>

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

    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
