/*
 * stubs to make bootstrap kernels link, copies of a few functions
 * to avoid including system calls yet have access to i/o functions,
 * and some convenience routines.
 */
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"../port/error.h"

void (*proctrace)(Proc*, int, vlong);

/* devmnt.c */

void
muxclose(Mnt *)
{
}

Chan*
mntauth(Chan *, char *)
{
	return nil;
}

long
mntversion(Chan *, char *, int, int)
{
	return 0;
}

/* swap.c */

Image swapimage;

void
putswap(Page *)
{
}

void
dupswap(Page *)
{
}

void
kickpager(void)
{
}

int
swapcount(ulong)
{
	return 0;
}

void
pagersummary(void)
{
}

void
setswapchan(Chan *)
{
}

/* devenv.c */

void
closeegrp(Egrp *)
{
}

void
ksetenv(char *, char *, int)
{
}

/* devproc.c */

Segment*
data2txt(Segment *s)
{
	Segment *ps;

	ps = newseg(SG_TEXT, s->base, s->size);
	ps->image = s->image;
	incref(ps->image);
	ps->fstart = s->fstart;
	ps->flen = s->flen;
	ps->flushme = 1;
	return ps;
}

/* sysproc.c */

int
return0(void*)
{
	return 0;
}

/* syscallfmt.c */
void
syscallfmt(int, ulong, va_list)
{
}

void
sysretfmt(int, va_list, long, uvlong, uvlong)
{
}

/* sysfile.c */

int
newfd(Chan *)
{
	return -1;
}

void
validstat(uchar *s, int n)
{
	int m;
	char buf[64];

	if(statcheck(s, n) < 0)
		error(Ebadstat);
	/* verify that name entry is acceptable */
	s += STATFIXLEN - 4*BIT16SZ;	/* location of first string */
	/*
	 * s now points at count for first string.
	 * if it's too long, let the server decide; this is
	 * only for his protection anyway. otherwise
	 * we'd have to allocate and waserror.
	 */
	m = GBIT16(s);
	s += BIT16SZ;
	if(m+1 > sizeof buf)
		return;
	memmove(buf, s, m);
	buf[m] = '\0';
	/* name could be '/' */
	if(strcmp(buf, "/") != 0)
		validname(buf, 0);
}

Chan*
fdtochan(int fd, int mode, int chkmnt, int iref)
{
	Chan *c;
	Fgrp *f;

	c = 0;
	f = up->fgrp;

	lock(f);
	if(fd<0 || f->nfd<=fd || (c = f->fd[fd])==0) {
		unlock(f);
		error(Ebadfd);
	}
	if(iref)
		incref(c);
	unlock(f);

	if(chkmnt && (c->flag&CMSG)) {
		if(iref)
			cclose(c);
		error(Ebadusefd);
	}

	if(mode<0 || c->mode==ORDWR)
		return c;

	if((mode&OTRUNC) && c->mode==OREAD) {
		if(iref)
			cclose(c);
		error(Ebadusefd);
	}

	if((mode&~OTRUNC) != c->mode) {
		if(iref)
			cclose(c);
		error(Ebadusefd);
	}

	return c;
}

int
openmode(ulong o)
{
	o &= ~(OTRUNC|OCEXEC|ORCLOSE);
	if(o > OEXEC)
		error(Ebadarg);
	if(o == OEXEC)
		return OREAD;
	return o;
}

int
bind(char *old, char *new, int flag)
{
	int ret;
	Chan *c0, *c1;

	if((flag&~MMASK) || (flag&MORDER)==(MBEFORE|MAFTER))
		error(Ebadarg);

	c0 = namec(old, Abind, 0, 0);
	if(waserror()){
		cclose(c0);
		return -1;
	}

	c1 = namec(new, Amount, 0, 0);
	if(waserror()){
		cclose(c1);
		nexterror();
	}

	ret = cmount(&c0, c1, flag, nil);

	poperror();
	cclose(c1);
	poperror();
	cclose(c0);
	return ret;
}

long
unmount(char *name, char *old)
{
	Chan *cmount, *cmounted;

	cmounted = 0;
	cmount = namec(old, Amount, 0, 0);
	if(waserror()) {
		cclose(cmount);
		if(cmounted)
			cclose(cmounted);
		return -1;
	}

	if(name)
		/*
		 * This has to be namec(..., Aopen, ...) because
		 * if name is something like /srv/cs or /fd/0,
		 * opening it is the only way to get at the real
		 * Chan underneath.
		 */
		cmounted = namec(name, Aopen, OREAD, 0);
	cunmount(cmount, cmounted);
	poperror();
	cclose(cmount);
	if(cmounted)
		cclose(cmounted);
	return 0;
}

long
chdir(char *dir)
{
	Chan *c;

	if (waserror())
		return -1;
	c = namec(dir, Atodir, 0, 0);
	if (up->dot)
		cclose(up->dot);
	up->dot = c;
	poperror();
	return 0;
}

Chan *
namecopen(char *name, int mode)
{
	Chan *c;

	if (waserror())
		return nil;
	c = namec(name, Aopen, mode, 0);
	poperror();
	return c;
}

Chan *
enamecopen(char *name, int mode)
{
	Chan *c;

	c = namecopen(name, mode);
	if (c == nil)
		panic("can't open %s", name);
	return c;
}

Chan *
nameccreate(char *name, int mode)
{
	Chan *c;

	if (waserror())
		return nil;
	c = namec(name, Acreate, mode, 0);
	poperror();
	return c;
}

Chan *
enameccreate(char *name, int mode)
{
	Chan *c;

	c = nameccreate(name, mode);
	if (c == nil)
		panic("can't create %s", name);
	return c;
}

int
myreadn(Chan *c, void *vp, long n)
{
	char *p = vp;
	long nn;

	while(n > 0) {
		nn = devtab[c->type]->read(c, p, n, c->offset);
		if(nn == 0)
			break;
		c->offset += nn;
		p += nn;
		n -= nn;
	}
	return p - (char *)vp;
}

int
readfile(char *file, void *buf, int len)
{
	int n;
	Chan *cc;

	cc = nil;
	if (waserror()) {
		if (cc)
			cclose(cc);
		return -1;
	}
	cc = namecopen(file, OREAD);
	if (cc == nil)
		error("no such file");
	n = myreadn(cc, buf, len);
	poperror();
	cclose(cc);
	return n;
}

static int
dumpfile(char *file)
{
	int n;
	char *buf;

	buf = smalloc(Maxfile + 1);
	n = readfile(file, buf, Maxfile);
	if (n < 0)
		return -1;
	buf[n] = 0;
	print("%s (%d bytes):\n", file, n);
	print("%s\n", buf);
	free(buf);
	return 0;
}

/* main.c */

void
fpx87restore(FPsave*)
{
}

void
fpx87save(FPsave*)
{
}

void
fpssesave(FPsave *)
{
}

void
fpsserestore(FPsave *)
{
}

ulong
l2be(long l)
{
	uchar *cp;

	cp = (uchar*)&l;
	return (cp[0]<<24) | (cp[1]<<16) | (cp[2]<<8) | cp[3];
}
