/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program 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.

**********************************************************************/

#define U_FILE_LIB

#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include	"machine/include.h"
#include	"u_file.h"


typedef struct u_fd_debug {
	char *		file;
	int		line;
} U_FD_DEBUG;

int _get_tid();
UFR_TBL * ufr_dispatch;
int open_err_sub_code;
int open_err_main_code;
int u_open_point;

U_FD_DEBUG *	fdd_list;

#define RW_MODE	(O_RDONLY|O_WRONLY|O_RDWR)


int
u_geteuid()
{
static int uid;
static int flag;
	if ( flag == 0 ) {
		uid = geteuid();
		flag = 1;
	}
	return uid;
}

#define _u_open(fname,flags,...)	\
	xx_u_open(fname,flags,__FILE__,__LINE__,__VA_ARGS__)


int
u_open(char * filename,int flags,int mode)
{
UFR_TBL * tbl;
UFR_REQ rq;
UFR_ARGS argv[3];
UFR_ERR e;
int uid;
	tbl = ufr_dispatch;

	if ( tbl && ( (flags&RW_MODE) != O_RDONLY ) ) {
		if ( (*tbl->fns.check_own)(&uid,filename) < 0 ) {
			u_open_point = 1;
			goto dm;
		}
		if ( u_geteuid() == uid ) {
			u_open_point = 2;
			goto dm;
		}
		rq.uid = uid;
		rq.argc = 3;
		rq.argv = &argv[0];
		argv[0].type = UFR_T_CHAR_PTR;
		argv[0].d_char_ptr.d = filename;
		argv[0].d_char_ptr.len = strlen(filename)+1;
		argv[1].type = UFR_T_INT;
		argv[1].d_int.d = flags;
		argv[2].type = UFR_T_INT;
		argv[2].d_int.d = mode;
		rq.ufr_code = UFR_CODE(u_open);
		rq.transaction = 1;
		e = (*tbl->fns.__ufr_call)(&rq);
		if ( e.ufr_code >= 0 ) {
			u_open_point = 3;
			return e.r.sys_code;
		}
		else {
			open_err_sub_code = e.ufr_code;
			open_err_main_code = e.r.sys_code;
			errno = e.r.sys_code;
			u_open_point = 4;
			return -1;
		}
	}
	u_open_point = 5;
dm:

	return open(filename,flags,mode);
}


int
u_close(int fd)
{
UFR_TBL * tbl;
UFR_REQ rq;
UFR_ARGS argv[1];
UFR_ERR e;

	tbl = ufr_dispatch;
	if ( tbl && (fd >= 0x10000) ) {
		rq.argc = 1;
		rq.argv = &argv[0];
		argv[0].type = UFR_T_INT;
		argv[0].d_int.d = fd;
		rq.ufr_code = UFR_CODE(u_close);
		rq.transaction = -1;
		e = (*tbl->fns.__ufr_call)(&rq);
		if ( e.ufr_code >= 0 )
			return e.r.sys_code;
		else {
			errno = e.r.sys_code;
			return -1;
		}
	}

	return close(fd);
}

int
u_write(int fd,void * data,int len)
{
UFR_TBL * tbl;
UFR_REQ rq;
UFR_ARGS argv[2];
UFR_ERR e;
	tbl = ufr_dispatch;


	if ( tbl && (fd >= 0x10000)  ) {
		rq.argc = 2;
		rq.argv = &argv[0];
		argv[0].type = UFR_T_INT;
		argv[0].d_int.d = fd;
		argv[1].type = UFR_T_CHAR_PTR;
		argv[1].d_char_ptr.d = data;
		argv[1].d_char_ptr.len = len;
		rq.ufr_code = UFR_CODE(u_write);
		rq.transaction = 0;
		e = (*tbl->fns.__ufr_call)(&rq);
		if ( e.ufr_code >= 0 )
			return e.r.sys_code;
		else {
			errno = e.r.sys_code;
			return -1;
		}
	}

	return write(fd,data,len);
}

int
u_read(int fd,void * data,int len)
{
UFR_TBL * tbl;
UFR_REQ rq;
UFR_ARGS argv[2];
UFR_ERR e;
	tbl = ufr_dispatch;
	if ( tbl && (fd >= 0x10000)  ) {
		rq.argc = 2;
		rq.argv = &argv[0];
		argv[0].type = UFR_T_INT;
		argv[0].d_int.d = fd;
		argv[1].type = UFR_T_REP_CHAR_PTR;
		argv[1].d_rep_char_ptr.d = data;
		argv[1].d_rep_char_ptr.len = len;
		rq.ufr_code = UFR_CODE(u_read);
		rq.transaction = 0;
		e = (*tbl->fns.__ufr_call)(&rq);
		if ( e.ufr_code >= 0 )
			return e.r.sys_code;
		else {
			errno = e.r.sys_code;
			return -1;
		}
	}

	return read(fd,data,len);
}

int
u_lseek(int fd,int ofs,int where)
{
UFR_TBL * tbl;
UFR_REQ rq;
UFR_ARGS argv[3];
UFR_ERR e;
	tbl = ufr_dispatch;
	if ( tbl && (fd >= 0x10000)  ) {
		rq.argc = 3;
		rq.argv = &argv[0];
		argv[0].type = UFR_T_INT;
		argv[0].d_int.d = fd;
		argv[1].type = UFR_T_INT;
		argv[1].d_int.d = ofs;
		argv[2].type = UFR_T_INT;
		argv[2].d_int.d = where;
		rq.ufr_code = UFR_CODE(u_lseek);
		rq.transaction = 0;
		e = (*tbl->fns.__ufr_call)(&rq);
		if ( e.ufr_code >= 0 )
			return e.r.sys_code;
		else {
			errno = e.r.sys_code;
			return -1;
		}
	}

	return lseek(fd,ofs,where);
}

int
u_open64(char * filename,int flags,int mode)
{
UFR_TBL * tbl;
UFR_REQ rq;
UFR_ARGS argv[3];
UFR_ERR e;
int uid;
	tbl = ufr_dispatch;
	if ( tbl && ( (flags&RW_MODE) != O_RDONLY )  ) {
		if ( (*tbl->fns.check_own)(&uid,filename) < 0 )
			goto dm;
		if ( u_geteuid() == uid )
			goto dm;
		rq.uid = uid;
		rq.argc = 3;
		rq.argv = &argv[0];
		argv[0].type = UFR_T_CHAR_PTR;
		argv[0].d_char_ptr.d = filename;
		argv[0].d_char_ptr.len = strlen(filename)+1;
		argv[1].type = UFR_T_INT;
		argv[1].d_int.d = flags;
		argv[2].type = UFR_T_INT;
		argv[2].d_int.d = mode;
		rq.ufr_code = UFR_CODE(u_open64);
		rq.transaction = 1;
		e = (*tbl->fns.__ufr_call)(&rq);
		if ( e.ufr_code >= 0 )
			return e.r.sys_code;
		else {
			errno = e.r.sys_code;
			return -1;
		}
	}
dm:

	return _open64(filename,flags,mode);
}

INTEGER64
u_lseek64(int fd,INTEGER64 ofs,int where)
{
UFR_TBL * tbl;
UFR_REQ rq;
UFR_ARGS argv[3];
UFR_ERR e;
	tbl = ufr_dispatch;
	if ( tbl && (fd >= 0x10000)  ) {
		rq.argc = 3;
		rq.argv = &argv[0];
		argv[0].type = UFR_T_INT;
		argv[0].d_int.d = fd;
		argv[1].type = UFR_T_INT64;
		argv[1].d_int64.d = ofs;
		argv[2].type = UFR_T_INT;
		argv[2].d_int.d = where;
		rq.ufr_code = UFR_CODE(u_lseek64);
		rq.transaction = 0;
		e = (*tbl->fns.__ufr_call)(&rq);
		if ( e.ufr_code >= 0 )
			return e.r.d_int64;
		else {
			errno = e.r.sys_code;
			return -1;
		}
	}

	return _lseek64(fd,ofs,where);
}

int
u_unlink(char * path)
{
UFR_TBL * tbl;
UFR_REQ rq;
UFR_ARGS argv[1];
UFR_ERR e;
int uid;
	tbl = ufr_dispatch;
	if ( tbl ) {
		if ( (*tbl->fns.check_own)(&uid,path) < 0 )
			goto dm;
		if ( u_geteuid() == uid )
			goto dm;
		rq.uid = uid;
		rq.argc = 1;
		rq.argv = &argv[0];
		argv[0].type = UFR_T_CHAR_PTR;
		argv[0].d_char_ptr.d = path;
		argv[0].d_char_ptr.len = strlen(path)+1;
		rq.ufr_code = UFR_CODE(u_unlink);
		rq.transaction = 0;
		e = (*tbl->fns.__ufr_call)(&rq);
		if ( e.ufr_code >= 0 )
			return e.r.sys_code;
		else {
			errno = e.r.sys_code;
			return -1;
		}
	}
dm:

	return unlink(path);
}

int
u_rmdir(char * path)
{
UFR_TBL * tbl;
UFR_REQ rq;
UFR_ARGS argv[1];
UFR_ERR e;
int uid;
	tbl = ufr_dispatch;
	if ( tbl ) {
		if ( (*tbl->fns.check_own)(&uid,path) < 0 )
			goto dm;
		if ( u_geteuid() == uid )
			goto dm;
		rq.uid = uid;
		rq.argc = 1;
		rq.argv = &argv[0];
		argv[0].type = UFR_T_CHAR_PTR;
		argv[0].d_char_ptr.d = path;
		argv[0].d_char_ptr.len = strlen(path)+1;
		rq.ufr_code = UFR_CODE(u_rmdir);
		rq.transaction = 0;
		e = (*tbl->fns.__ufr_call)(&rq);
		if ( e.ufr_code >= 0 )
			return e.r.sys_code;
		else {
			errno = e.r.sys_code;
			return -1;
		}
	}
dm:

	return rmdir(path);
}

int
m_mkdir(char * path,int mode)
{
UFR_TBL * tbl;
UFR_REQ rq;
UFR_ARGS argv[2];
UFR_ERR e;
int uid;
int ret;
	tbl = ufr_dispatch;
	if ( tbl ) {
		if ( (*tbl->fns.check_own)(&uid,path) < 0 )
			goto dm;
		if ( u_geteuid() == uid )
			goto dm;
		rq.uid = uid;
		rq.argc = 2;
		rq.argv = &argv[0];
		argv[0].type = UFR_T_CHAR_PTR;
		argv[0].d_char_ptr.d = path;
		argv[0].d_char_ptr.len = strlen(path)+1;

		argv[1].type = UFR_T_INT;
		argv[1].d_int.d = mode;
		rq.ufr_code = UFR_CODE(u_mkdir);
		rq.transaction = 0;
		e = (*tbl->fns.__ufr_call)(&rq);
		if ( e.ufr_code >= 0 )
			return e.r.sys_code;
		else {
			errno = e.r.sys_code;
			return -1;
		}
	}
dm:

	ret = mkdir(path,mode);
	if ( ret < 0 )
		return ret;
	return chmod(path,mode);
}



char *
u_getenv(char * name)
{
	return getenv(name);
}


