/*
 *  This file is part of ixemul.library for the Amiga.
 *  Copyright (C) 1991, 1992  Markus M. Wild
 *  Portions Copyright (C) 1994 Rafael W. Luebbert
 *  Portions Copyright (C) 1995 Jeff Shepherd
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public
 *  License along with this library; if not, write to the Free
 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *  $Id$
 *
 *  $Log$
 */
#define KERNEL
#include <library/ixemul.h>
#include <sys/file.h>
#include <sys/syslog.h>
#include <errno.h>
#include <proto/exec.h>
#undef errno;
extern int errno;

extern int gcc_fstat (unsigned fdes, struct stat *sb);
extern int ix_panic (const char *msg);

static void ix_lock_base () {
    u.u_oldmask = u.p_sigmask;
    u.p_sigmask = ~0;
    ObtainSemaphore (& ix.ix_semaph);
}

static void ix_unlock_base () {
    ReleaseSemaphore (& ix.ix_semaph);
    u.p_sigmask = u.u_oldmask;
}

/*
 * Allocate a user file descriptor.
 */
static int ufalloc(int want, int *result) {
    for (; want < NOFILE; want++) {
	if (u.u_ofile[want] == NULL) {
	    u.u_pofile[want] = 0;
	    if (want > u.u_lastfile)
		u.u_lastfile = want;
	    *result = want;
	    return 0;
	}
    }
    return EMFILE;
}



/*
 * Allocate a user file descriptor
 * and a file structure.
 * Initialize the descriptor
 * to point at the file structure.
 */
int falloc(struct file **resultfp, int *resultfd) {
    register struct file *fp;
    int error, i;

    if ((error = ufalloc(0, &i)))  /* Change *resultfd used to be 0 */
	return (error);

    ix_lock_base ();

    if (ix.ix_lastf == 0)
	ix.ix_lastf = ix.ix_file_tab;

    for (fp = ix.ix_lastf; fp < ix.ix_fileNFILE; fp++)
	if (fp->f_count == 0)
	    goto slot;

    for (fp = ix.ix_file_tab; fp < ix.ix_lastf; fp++)
	if (fp->f_count == 0)
	    goto slot;

    /* YES I know.. it's not optimal, we should resize the table...
     * unfortunately all code accessing file structures will then have
     * to be changed as well, and this is a job for later improvement,
     * first goal is to get this baby working... */
    ix_panic ("falloc: ixemul.library file table full!");
    error = ENFILE;
    goto do_ret;

slot:
    u.u_ofile[i] = fp;
    fp->f_name = 0;
    fp->f_count = 1;
    fp->f_type = 0;		  /* inexistant type ;-) */
    fp->f_async_buf = 0;
    fp->f_async_len = 0;
    ix.ix_lastf = fp + 1;

    if (resultfp)
	*resultfp = fp;

    if (resultfd)
	*resultfd = i;

    error = 0;

do_ret:
    ix_unlock_base();
    return error;
}

