
/*
 *  OPEN.C
 *
 *  (c)Copyright 1990, Matthew Dillon, All Rights Reserved
 */

#include <exec/types.h>
#include <libraries/dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>

_IOFDS *
_MakeFD(pfd)
int *pfd;
{
    int fd;
    _IOFDS *d;

    /*
     *	extend limit if required
     */

    for (fd = 0, d = _IoFD; fd < _IoFDLimit; ++fd) {
	if ((d->fd_Flags & O_ISOPEN) == 0)
	    break;
	++d;
    }
    if (fd == _IoFDLimit) {
	short newLimit = fd + 5;
	_IOFDS *fds = malloc(sizeof(_IOFDS) * newLimit);
	if (fds == NULL) {
	    errno = ENOMEM;
	    return(NULL);
	}
	_slow_bzero(fds, sizeof(_IOFDS) * newLimit);
	_slow_bcopy(_IoFD, fds, sizeof(_IOFDS) * fd);
	if (_IoFD != _IoStaticFD)
	    free(_IoFD);
	_IoFD = fds;
	_IoFDLimit = newLimit;
	d = fds + fd;
    }
    if (d)
	_slow_bzero(d, sizeof(*d));
    *pfd = fd;
    return(d);
}


int
open(name, modes)
const char *name;
int modes;
{
    int fd;
    _IOFDS *d = _MakeFD(&fd);

    if (d == NULL)
	return(-1);

    /*
     *	If we can't lock then be careful to call Open only once.  Don't
     *	bother to open if the IoErr() returns ERROR_DEVICE_NOT_MOUNTED
     */

    {
	long lock = Lock(name, SHARED_LOCK);
	if (lock == NULL) {
	    if (IoErr() == ERROR_DEVICE_NOT_MOUNTED) {
		errno = ENOFILE;
		return(-1);
	    }
	    /*
	     *	file does not exist, open modes 1006 if create request, else
	     *	try to open modes 1005 (could be a non-file device)
	     */

	    if (modes & O_CREAT)
		d->fd_Fh = Open(name, 1006);
	    else
		d->fd_Fh = Open(name, 1005);

	    if (d->fd_Fh == NULL) {
		errno = ENOFILE;
		return(-1);
	    }
	    if (modes & O_APPEND)
		Seek(d->fd_Fh, 0L, 1);
	    d->fd_Flags = modes | O_ISOPEN;
	    return(fd);
	}
	UnLock(lock);
    }

    /*
     *	Assume it is a normal file.. we can open/reopen it any
     *	number of times.  Also, the file exists so...
     */

    if (modes & O_TRUNC)
	d->fd_Fh = Open(name, 1006);
    else
	d->fd_Fh = Open(name, 1005);

    if (d->fd_Fh == NULL && (modes & O_CREAT))  /*  case should never happen? */
	d->fd_Fh = Open(name, 1006);

    if (d->fd_Fh) {
	if (modes & O_APPEND)
	    Seek(d->fd_Fh, 0L, 1);
	d->fd_Flags = modes | O_ISOPEN;
	return(fd);
    }
    return(-1);
}

