Пример #1
0
void
setswapchan(Chan *c)
{
	uchar dirbuf[sizeof(Dir)+100];
	Dir d;
	int n;

	if(swapimage.c) {
		if(swapalloc.free != conf.nswap){
			cclose(c);
			error(Einuse);
		}
		cclose(swapimage.c);
	}

	/*
	 *  if this isn't a file, set the swap space
	 *  to be at most the size of the partition
	 */
	if(devtab[c->type]->dc != L'M'){
		n = devtab[c->type]->stat(c, dirbuf, sizeof dirbuf);
		if(n <= 0){
			cclose(c);
			error("stat failed in setswapchan");
		}
		convM2D(dirbuf, n, &d, nil);
		if(d.length < conf.nswap*BY2PG){
			conf.nswap = d.length/BY2PG;
			swapalloc.top = &swapalloc.swmap[conf.nswap];
			swapalloc.free = conf.nswap;
		}
	}

	swapimage.c = c;
}
Пример #2
0
long
sys_fstat(ulong *arg)
{
	Chan *c;
	char *name;
	uint l;
	uchar buf[128];	/* old DIRLEN plus a little should be plenty */
	char strs[128];
	Dir d;
	char old[] = "old fstat system call - recompile";

	validaddr(arg[1], 116, 1);
	c = fdtochan(arg[0], -1, 0, 1);
	if(waserror()){
		cclose(c);
		nexterror();
	}
	l = devtab[c->type]->stat(c, buf, sizeof buf);
	/* buf contains a new stat buf; convert to old. yuck. */
	if(l <= BIT16SZ)	/* buffer too small; time to face reality */
		error(old);
	name = pathlast(c->path);
	if(name)
		l = dirsetname(name, strlen(name), buf, l, sizeof buf);
	l = convM2D(buf, l, &d, strs);
	if(l == 0)
		error(old);
	packoldstat((uchar*)arg[1], &d);
	
	poperror();
	cclose(c);
	return 0;
}
Пример #3
0
static void
vbecall(Ureg *u)
{
	Proc *up = externup();
	Chan *creg, *cmem;
	uint32_t pa;

	cmem = namec("/dev/realmodemem", Aopen, ORDWR, 0);
	if(waserror()){
		cclose(cmem);
		nexterror();
	}
	creg = namec("/dev/realmode", Aopen, ORDWR, 0);
	if(waserror()){
		cclose(creg);
		nexterror();
	}
	pa = PADDR(RMBUF);
	cmem->dev->write(cmem, modebuf, sizeof modebuf, pa);
	u->trap = 0x10;
	print("vbecall: sizeof u is %d\n", sizeof *u);
	creg->dev->write(creg, u, sizeof *u, 0);

	creg->dev->read(creg, u, sizeof *u, 0);
	if((u->ax&0xFFFF) != 0x004F)
		error("vesa bios error");
	cmem->dev->read(cmem, modebuf, sizeof modebuf, pa);

	poperror();
	cclose(creg);
	poperror();
	cclose(cmem);
}
Пример #4
0
static long
dupread(Chan *c, void *va, long n, vlong offset)
{
	char *a = va;
	char buf[256];
	int fd, twicefd;

	if(c->qid.type == QTDIR)
		return devdirread(c, a, n, nil, 0, dupgen);
	twicefd = c->qid.path - 1;
	fd = twicefd/2;
	if(twicefd & 1){
		c = fdtochan(up->env->fgrp, fd, -1, 0, 1);
		if(waserror()){
			cclose(c);
			nexterror();
		}
		progfdprint(c, fd, 0, buf, sizeof buf);
		poperror();
		cclose(c);
		return readstr((ulong)offset, va, n, buf);
	}
	panic("dupread");
	return 0;
}
Пример #5
0
long
_syspipe(int fd[2])
{
	Chan *c[2];
	Dev *d;
	static char *datastr[] = {"data", "data1"};

	d = devtab[devno('|', 0)];
	c[0] = namec("#|", Atodir, 0, 0);
	c[1] = 0;
	fd[0] = -1;
	fd[1] = -1;

	if(waserror()){
		cclose(c[0]);
		if(c[1])
			cclose(c[1]);
		nexterror();
	}
	c[1] = cclone(c[0]);
	if(walk(&c[0], datastr+0, 1, 1, nil) < 0)
		error(Egreg);
	if(walk(&c[1], datastr+1, 1, 1, nil) < 0)
		error(Egreg);
	c[0] = d->open(c[0], ORDWR);
	c[1] = d->open(c[1], ORDWR);
	if(newfd2(fd, c) < 0)
		error(Enofd);
	poperror();

	return 0;
}
Пример #6
0
long
sysfversion(ulong *arg)
{
	char *vers;
	uint arglen, m, msize;
	Chan *c;

	msize = arg[1];
	vers = (char*)arg[2];
	arglen = arg[3];
	validaddr(arg[2], arglen, 1);
	/* check there's a NUL in the version string */
	if(arglen==0 || memchr(vers, 0, arglen)==0)
		error(Ebadarg);
	c = fdtochan(arg[0], ORDWR, 0, 1);
	if(waserror()){
		cclose(c);
		nexterror();
	}

	m = mntversion(c, vers, msize, arglen);

	cclose(c);
	poperror();
	return m;
}
Пример #7
0
int sysfversion(int fd, unsigned int msize, char *vers, unsigned int arglen)
{
	ERRSTACK(2);
	int m;
	struct chan *c;

	if (waserror()) {
		poperror();
		return -1;
	}

	/* check there's a NUL in the version string */
	if (arglen == 0 || memchr(vers, 0, arglen) == 0)
		error(EINVAL, ERROR_FIXME);

	c = fdtochan(&current->open_files, fd, O_RDWR, 0, 1);
	if (waserror()) {
		cclose(c);
		nexterror();
	}

	m = mntversion(c, vers, msize, arglen);

	poperror();
	cclose(c);

	poperror();
	return m;
}
Пример #8
0
/* must call with d qlocked */
static int
aoeidentify(Ctlr *d, SDunit *u)
{
	Chan *c;

	c = nil;
	if(waserror()){
		if(c)
			cclose(c);
		iprint("aoeidentify: %s\n", up->errstr);
		nexterror();
	}

	uprint("%s/ident", d->path);
	c = namec(up->genbuf, Aopen, OREAD, 0);
	devtab[c->type]->read(c, d->ident, sizeof d->ident, 0);

	poperror();
	cclose(c);

	d->feat = 0;
	d->smart = 0;
	identify(d, (ushort*)d->ident);

	memset(u->inquiry, 0, sizeof u->inquiry);
	u->inquiry[2] = 2;
	u->inquiry[3] = 2;
	u->inquiry[4] = sizeof u->inquiry - 4;
	memmove(u->inquiry+8, d->model, 40);

	return 0;
}
Пример #9
0
struct chan *fdtochan(struct fd_table *fdt, int fd, int mode, int chkmnt,
                      int iref)
{
	struct chan *c;

	c = lookup_fd(fdt, fd, iref, FALSE);
	if (!c) {
		/* We lost the info about why there was a problem (we used to track file
		 * group closed too, can add that in later). */
		error(EBADF, ERROR_FIXME);
	}
	if (chkmnt && (c->flag & CMSG)) {
		if (iref)
			cclose(c);
		error(EBADF, ERROR_FIXME);
	}
	if (mode < 0)
		return c;
	if ((mode & c->mode) != mode) {
		if (iref)
			cclose(c);
		error(EBADF,
		      "FD access mode failure: chan mode 0x%x, wanted 0x%x (opened with 0 instead of O_READ?)",
		      c->mode, mode);
	}
	return c;
}
Пример #10
0
static int32_t
wstat(Chan* c, uint8_t* p, usize n)
{
	Proc *up = externup();
	int32_t l;
	usize namelen;

	if(waserror()){
		cclose(c);
		nexterror();
	}

	/*
	 * Renaming mount points is disallowed to avoid surprises
	 * (which should be renamed? the mount point or the mounted Chan?).
	 */
	if(c->ismtpt){
		dirname(p, &namelen);
		if(namelen)
			nameerror(chanpath(c), Eismtpt);
	}
	l = c->dev->wstat(c, p, n);
	poperror();
	cclose(c);

	return l;
}
Пример #11
0
long
sysremove(ulong *arg)
{
	Chan *c;

	validaddr(arg[0], 1, 0);
	c = namec((char*)arg[0], Aremove, 0, 0);
	/*
	 * Removing mount points is disallowed to avoid surprises
	 * (which should be removed: the mount point or the mounted Chan?).
	 */
	if(c->ismtpt){
		cclose(c);
		error(Eismtpt);
	}
	if(waserror()){
		c->type = 0;	/* see below */
		cclose(c);
		nexterror();
	}
	devtab[c->type]->remove(c);
	/*
	 * Remove clunks the fid, but we need to recover the Chan
	 * so fake it up.  rootclose() is known to be a nop.
	 */
	c->type = 0;
	poperror();
	cclose(c);
	return 0;
}
Пример #12
0
void
sysfversion(Ar0* ar0, va_list list)
{
	Chan *c;
	char *version;
	int fd;
	u32int msize;
	usize nversion;

	/*
	 * int fversion(int fd, int bufsize, char *version, int nversion);
	 * should be
	 * usize fversion(int fd, u32int msize, char *version, usize nversion);
	 */
	fd = va_arg(list, int);
	msize = va_arg(list, u32int);
	version = va_arg(list, char*);
	nversion = va_arg(list, usize);
	version = validaddr(version, nversion, 1);
	/* check there's a NUL in the version string */
	if(nversion == 0 || memchr(version, 0, nversion) == nil)
		error(Ebadarg);

	c = fdtochan(fd, ORDWR, 0, 1);
	if(waserror()){
		cclose(c);
		nexterror();
	}

	ar0->u = mntversion(c, msize, version, nversion);

	cclose(c);
	poperror();
}
Пример #13
0
/* Could pass in the fdt instead of the proc, but we used to need the to_proc
 * for now so we can claim a VFS FD.  Careful, we don't close the old chan. */
int sys_dup_to(struct proc *from_proc, unsigned int from_fd,
               struct proc *to_proc, unsigned int to_fd)
{
	ERRSTACK(1);
	int ret;
	struct chan *c;

	if (waserror()) {
		poperror();
		return -1;
	}
	c = fdtochan(&from_proc->open_files, from_fd, -1, 0, 1);
	if (c->qid.type & QTAUTH) {
		cclose(c);
		error(EPERM, ERROR_FIXME);
	}
	ret = insert_obj_fdt(&to_proc->open_files, c, to_fd, 0, TRUE, FALSE);
	/* drop the ref from fdtochan.  if insert succeeded, there is one other ref
	 * stored in the FDT */
	cclose(c);
	if (ret < 0)
		error(EFAIL, "Can't insert FD %d into FDG", to_fd);
	poperror();
	return 0;
}
Пример #14
0
long
sysunmount(ulong *arg)
{
	Chan *cmount, *cmounted;

	cmounted = 0;

	validaddr(arg[1], 1, 0);
	cmount = namec((char *)arg[1], Amount, 0, 0);
	if(waserror()) {
		cclose(cmount);
		if(cmounted)
			cclose(cmounted);
		nexterror();
	}

	if(arg[0]) {
		/*
		 * This has to be namec(..., Aopen, ...) because
		 * if arg[0] is something like /srv/cs or /fd/0,
		 * opening it is the only way to get at the real
		 * Chan underneath.
		 */
		validaddr(arg[0], 1, 0);
		cmounted = namec((char*)arg[0], Aopen, OREAD, 0);
	}
	cunmount(cmount, cmounted);
	poperror();
	cclose(cmount);
	if(cmounted)
		cclose(cmounted);
	return 0;
}
Пример #15
0
uintptr
sysfversion(va_list list)
{
	uint msize, arglen;
	char *vers;
	Chan *c;
	int fd;

	fd = va_arg(list, int);
	msize = va_arg(list, uint);
	vers = va_arg(list, char*);
	arglen = va_arg(list, uint);
	validaddr((uintptr)vers, arglen, 1);
	/* check there's a NUL in the version string */
	if(arglen==0 || memchr(vers, 0, arglen)==0)
		error(Ebadarg);
	c = fdtochan(fd, ORDWR, 0, 1);
	if(waserror()){
		cclose(c);
		nexterror();
	}
	msize = mntversion(c, vers, msize, arglen);
	cclose(c);
	poperror();
	return msize;
}
Пример #16
0
long
sysstat(uint32 *arg)
{
	char *name;
	Chan *c;
	uint l;
	uchar *p;

	l = arg[2];
	p = uvalidaddr(arg[1], l, 1);
	name = uvalidaddr(arg[0], 1, 0);
	c = namec(name, Aaccess, 0, 0);
	if(waserror()){
		cclose(c);
		nexterror();
	}
	l = devtab[c->type]->stat(c, p, l);
	name = pathlast(c->path);
	if(name)
		l = dirsetname(name, strlen(name), p, l, arg[2]);

	poperror();
	cclose(c);
	return l;
}
Пример #17
0
long
sys_stat(uint32 *arg)
{
	Chan *c;
	uint l;
	uchar buf[128];	/* old DIRLEN plus a little should be plenty */
	char strs[128], *name, *elem;
	Dir d;
	char old[] = "old stat system call - recompile";
	uchar *p;

	p = uvalidaddr(arg[1], 116, 1);
	name = uvalidaddr(arg[0], 1, 0);
	c = namec(name, Aaccess, 0, 0);
	if(waserror()){
		cclose(c);
		nexterror();
	}
	l = devtab[c->type]->stat(c, buf, sizeof buf);
	/* buf contains a new stat buf; convert to old. yuck. */
	if(l <= BIT16SZ)	/* buffer too small; time to face reality */
		error(old);
	elem = pathlast(c->path);
	if(elem)
		l = dirsetname(elem, strlen(elem), buf, l, sizeof buf);
	l = convM2D(buf, l, &d, strs);
	if(l == 0)
		error(old);
	packoldstat(p, &d);
	
	poperror();
	cclose(c);
	return 0;
}
Пример #18
0
static vlong
_sysseek(int fd, vlong off, int whence)
{
	Chan *c;
	uchar buf[sizeof(Dir)+100];
	Dir dir;
	int n;

	c = fdtochan(fd, -1, 1, 1);
	if(waserror()){
		cclose(c);
		nexterror();
	}
	if(devtab[c->type]->dc == '|')
		error(Eisstream);

	switch(whence){
	case 0:
		if((c->qid.type & QTDIR) && off != 0)
			error(Eisdir);
		if(off < 0)
			error(Enegoff);
		c->offset = off;
		break;

	case 1:
		if(c->qid.type & QTDIR)
			error(Eisdir);
		lock(&c->ref.lk);	/* lock for read/write update */
		off = off + c->offset;
		if(off < 0)
			error(Enegoff);
		c->offset = off;
		unlock(&c->ref.lk);
		break;

	case 2:
		if(c->qid.type & QTDIR)
			error(Eisdir);
		n = devtab[c->type]->stat(c, buf, sizeof buf);
		if(convM2D(buf, n, &dir, nil) == 0)
			error("internal error: stat error in seek");
		off = dir.length + off;
		if(off < 0)
			error(Enegoff);
		c->offset = off;
		break;

	default:
		error(Ebadarg);
	}
	c->uri = 0;
	c->dri = 0;
	cclose(c);
	poperror();
	return off;
}
Пример #19
0
static int64_t
sseek(int fd, int64_t offset, int whence)
{
	Proc *up = externup();
	Chan *c;
	uint8_t buf[sizeof(Dir)+100];
	Dir dir;
	int n;

	c = fdtochan(fd, -1, 1, 1);
	if(waserror()){
		cclose(c);
		nexterror();
	}
	if(c->dev->dc == '|')
		error(Eisstream);

	switch(whence){
	case 0:
		if((c->qid.type & QTDIR) && offset != 0LL)
			error(Eisdir);
		c->offset = offset;
		break;

	case 1:
		if(c->qid.type & QTDIR)
			error(Eisdir);
		lock(&c->r.l);	/* lock for read/write update */
		offset += c->offset;
		c->offset = offset;
		unlock(&c->r.l);
		break;

	case 2:
		if(c->qid.type & QTDIR)
			error(Eisdir);
		n = c->dev->stat(c, buf, sizeof buf);
		if(convM2D(buf, n, &dir, nil) == 0)
			error("internal error: stat error in seek");
		offset += dir.length;
		c->offset = offset;
		break;

	default:
		error(Ebadarg);
	}
	c->uri = 0;
	c->dri = 0;
	cclose(c);
	poperror();

	return offset;
}
Пример #20
0
struct chan *fdtochan(struct fgrp *f, int fd, int mode, int chkmnt, int iref)
{
	
	struct chan *c;

	c = 0;

	spin_lock(&f->lock);
	if (f->closed) {
		spin_unlock(&f->lock);
		error("File group closed");
	}
	if (fd < 0 || f->maxfd < fd || (c = f->fd[fd]) == 0) {
		spin_unlock(&f->lock);
		set_errno(EBADF);
		error("Bad FD %d\n", fd);
	}
	if (iref)
		chan_incref(c);
	spin_unlock(&f->lock);

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

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

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

	/* TODO: this is probably wrong.  if you get this from a dev, in the dev's
	 * open, you are probably saving mode directly, without passing it through
	 * openmode. */
	if ((mode & ~OTRUNC) != c->mode) {
		warn("Trunc mode issue: mode %o, mode minus trunc %o, chan mode %o\n",
			 mode, mode & ~OTRUNC, c->mode);
		if (iref)
			cclose(c);
		error(Ebadusefd);
	}

	return c;
}
Пример #21
0
static long
dowrite(uint32 *arg, vlong *offp)
{
	Chan *c;
	long m, n;
	vlong off;
	uchar *p;

	p = uvalidaddr(arg[1], arg[2], 0);
	n = 0;
	c = fdtochan(arg[0], OWRITE, 1, 1);
	if(waserror()) {
		if(offp == nil){
			lock(&c->ref.lk);
			c->offset -= n;
			unlock(&c->ref.lk);
		}
		cclose(c);
		nexterror();
	}

	if(c->qid.type & QTDIR)
		error(Eisdir);

	n = arg[2];

	if(offp == nil){	/* use and maintain channel's offset */
		lock(&c->ref.lk);
		off = c->offset;
		c->offset += n;
		unlock(&c->ref.lk);
	}else
		off = *offp;

	if(off < 0)
		error(Enegoff);

	m = devtab[c->type]->write(c, p, n, off);

	if(offp == nil && m < n){
		lock(&c->ref.lk);
		c->offset -= n - m;
		unlock(&c->ref.lk);
	}

	poperror();
	cclose(c);

	return m;
}
Пример #22
0
void
sysdup(Ar0* ar0, ...)
{
	Proc *up = externup();
	int nfd, ofd;
	Chan *nc, *oc;
	Fgrp *f;
	va_list list;
	va_start(list, ar0);

	/*
	 * int dup(int oldfd, int newfd);
	 *
	 * Close after dup'ing, so date > #d/1 works
	 */
	ofd = va_arg(list, int);
	oc = fdtochan(ofd, -1, 0, 1);
	nfd = va_arg(list, int);
	va_end(list);

	if(nfd != -1){
		f = up->fgrp;
		lock(&f->r.l);
		if(nfd < 0 || growfd(f, nfd) < 0) {
			unlockfgrp(f);
			cclose(oc);
			error(Ebadfd);
		}
		if(nfd > f->maxfd)
			f->maxfd = nfd;

		nc = f->fd[nfd];
		f->fd[nfd] = oc;
		unlockfgrp(f);
		if(nc != nil)
			cclose(nc);
	}else{
		if(waserror()) {
			cclose(oc);
			nexterror();
		}
		nfd = newfd(oc);
		if(nfd < 0)
			error(Enofd);
		poperror();
	}

	ar0->i = nfd;
}
Пример #23
0
void
sysunmount(Ar0* ar0, ...)
{
	Proc *up = externup();
	char *name, *old;
	Chan *cmount, *cmounted;
	va_list list;
	va_start(list, ar0);

	/*
	 * int unmount(char* name, char* old);
	 */
	name = va_arg(list, char*);
	old = va_arg(list, char*);
	cmount = namec(validaddr(old, 1, 0), Amount, 0, 0);
	va_end(list);

	cmounted = nil;
	if(name != nil) {
		if(waserror()) {
			cclose(cmount);
			nexterror();
		}

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

	if(waserror()) {
		cclose(cmount);
		if(cmounted != nil)
			cclose(cmounted);
		nexterror();
	}

	cunmount(cmount, cmounted);
	cclose(cmount);
	if(cmounted != nil)
		cclose(cmounted);
	poperror();

	ar0->i = 0;
}
Пример #24
0
/*
 * read disk partition tables so that readnvram via factotum
 * can see them.
 */
int
readparts(char *disk)
{
	Chan *ctl, *data;

	snprint(buf, sizeof buf, "%s/ctl", disk);
	ctl  = namecopen(buf, ORDWR);
	snprint(buf2, sizeof buf2, "%s/data", disk);
	data = namecopen(buf2, OREAD);
	if (ctl != nil && data != nil)
		setpartitions(buf2, ctl, data);
	cclose(ctl);
	cclose(data);
	return 0;
}
Пример #25
0
static long
kwrite(int fd, void *buf, long nn, vlong *offp)
{
	Chan *c;
	long m, n;
	vlong off;

	n = 0;
	c = fdtochan(fd, OWRITE, 1, 1);
	if(waserror()) {
		if(offp == nil){
			lock(&c->ref.lk);
			c->offset -= n;
			unlock(&c->ref.lk);
		}
		cclose(c);
		nexterror();
	}

	if(c->qid.type & QTDIR)
		error(Eisdir);

	n = nn;

	if(offp == nil){	/* use and maintain channel's offset */
		lock(&c->ref.lk);
		off = c->offset;
		c->offset += n;
		unlock(&c->ref.lk);
	}else
		off = *offp;

	if(off < 0)
		error(Enegoff);

	m = devtab[c->type]->write(c, buf, n, off);

	if(offp == nil && m < n){
		lock(&c->ref.lk);
		c->offset -= n - m;
		unlock(&c->ref.lk);
	}

	poperror();
	cclose(c);

	return m;
}
Пример #26
0
static SDev*
aoeprobe(char *path, SDev *s)
{
    int n, i;
    char *p;
    Chan *c;
    Ctlr *ctlr;

    if((p = strrchr(path, '/')) == 0)
        error(Ebadarg);
    *p = 0;
    uprint("%s/ctl", path);
    *p = '/';

    c = namec(up->genbuf, Aopen, OWRITE, 0);
    if(waserror()) {
        cclose(c);
        nexterror();
    }
    n = uprint("discover %s", p+1);
    devtab[c->type]->write(c, up->genbuf, n, 0);
    poperror();
    cclose(c);

    for(i = 0;; i += Probeintvl) {
        if(i > Probemax || waserror())
            error(Etimedout);
        tsleep(&up->sleep, return0, 0, Probeintvl);
        poperror();

        uprint("%s/ident", path);
        if(waserror())
            continue;
        c = namec(up->genbuf, Aopen, OREAD, 0);
        poperror();
        cclose(c);

        ctlr = newctlr(path);
        break;
    }

    if(s == nil && (s = malloc(sizeof *s)) == nil)
        return nil;
    s->ctlr = ctlr;
    s->ifc = &sdaoeifc;
    s->nunit = 1;
    return s;
}
Пример #27
0
void
closepgrp(Pgrp *p)
{
	Mhead **h, **e, *f, *next;

	if(decref(&p->ref) != 0)
		return;

	qlock(&p->debug);
	wlock(&p->ns);
	p->pgrpid = -1;

	e = &p->mnthash[MNTHASH];
	for(h = p->mnthash; h < e; h++) {
		for(f = *h; f; f = next) {
			wlock(&f->lock);
			cclose(f->from);
			mountfree(f->mount);
			f->mount = nil;
			next = f->hash;
			wunlock(&f->lock);
			putmhead(f);
		}
	}
	wunlock(&p->ns);
	qunlock(&p->debug);
	free(p);
}
Пример #28
0
static Chan*
dupopen(Chan *c, int omode)
{
	Chan *f;
	int fd, twicefd;

	if(c->qid.type & QTDIR){
		if(omode != 0)
			error(Eisdir);
		c->mode = 0;
		c->flag |= COPEN;
		c->offset = 0;
		return c;
	}
	if(c->qid.type & QTAUTH)
		error(Eperm);
	twicefd = c->qid.path - 1;
	fd = twicefd/2;
	if((twicefd & 1)){
		/* ctl file */
		f = c;
		f->mode = openmode(omode);
		f->flag |= COPEN;
		f->offset = 0;
	}else{
		/* fd file */
		f = fdtochan(up->env->fgrp, fd, openmode(omode), 0, 1);
		cclose(c);
	}
	if(omode & OCEXEC)
		f->flag |= CCEXEC;
	return f;
}
Пример #29
0
void
fdclose(int fd, int flag)
{
	Proc *up = externup();
	int i;
	Chan *c;
	Fgrp *f;

	f = up->fgrp;
	lock(&f->r.l);
	c = f->fd[fd];
	if(c == nil){
		/* can happen for users with shared fd tables */
		unlock(&f->r.l);
		return;
	}
	if(flag){
		if(c == nil || !(c->flag&flag)){
			unlock(&f->r.l);
			return;
		}
	}
	f->fd[fd] = nil;
	if(fd == f->maxfd)
		for(i = fd; --i >= 0 && f->fd[i] == 0; )
			f->maxfd = i;

	unlock(&f->r.l);
	cclose(c);
}
Пример #30
0
int syscreate(char *path, int mode, uint32_t perm)
{
	ERRSTACK(2);
	int fd;
	struct chan *c;

	if (waserror()) {
		poperror();
		return -1;
	}

	openmode(mode & ~O_EXCL);	/* error check only; OEXCL okay here */
	c = namec(path, Acreate, mode, perm);
	if (waserror()) {
		cclose(c);
		nexterror();
	}
	fd = newfd(c, mode);	/* 9ns mode is the O_FLAGS and perm is glibc mode */
	if (fd < 0)
		error(-fd, ERROR_FIXME);
	poperror();

	poperror();
	return fd;
}