Exemple #1
0
int
checktag(Iobuf *p, int tag, Off qpath)
{
	Tag *t;
	static Off lastaddr;

	t = (Tag*)(p->iobuf+BUFSIZE);
	if(t->tag != tag) {
		if(p->flags & Bmod) {
			print("\ttag = %d/%llu; expected %lld/%d -- not flushed\n",
				t->tag, (Wideoff)t->path, (Wideoff)qpath, tag);
			return 2;
		}
		if(p->dev != nil && p->dev->type == Devcw)
			cwfree(p->dev, p->addr);
		if(p->addr != lastaddr)
			print("\ttag = %G/%llu; expected %G/%lld -- flushed (%lld)\n",
				t->tag, (Wideoff)t->path, tag, (Wideoff)qpath,
				(Wideoff)p->addr);
		lastaddr = p->addr;
		p->dev = devnone;
		p->addr = -1;
		p->flags = 0;
		return 2;
	}
	if(qpath != QPNONE) {
		if((qpath ^ t->path) & ~QPDIR) {
			if(1 || CHAT(0))
				print("\ttag/path = %llu; expected %d/%llux\n",
					(Wideoff)t->path, tag, (Wideoff)qpath);
			return 0;
		}
	}
	return 0;
}
Exemple #2
0
int vhost_load_contents(u_config_t *vhost, const char *origin)
{
    size_t i;
    char wkc[1024] = { '\0' };
    u_config_t *res, *contents;

    dbg_return_if(vhost == NULL, -1);
    dbg_return_if(origin == NULL, -1);

    /* Pick up the "contents" section. */
    dbg_err_ifm(u_config_get_subkey(vhost, "contents", &contents),
            "no contents in virtual host !");

    /* Load hosted resources. */
    for (i = 0;
            (res = u_config_get_child_n(contents, "resource", i)) != NULL;
            ++i)
    {
        dbg_err_ifm(vhost_load_resource(res, origin),
                "error loading resource");
    }

    dbg_err_ifm(i == 0, "no resources in virtual host");

    /* Add the default /.well-known/core interface. */
    dbg_err_if(u_snprintf(wkc, sizeof wkc, "%s/.well-known/core", origin));
    CHAT("adding resource %s (AUTO)", wkc);
    dbg_err_ifm(ec_register_cb(g_ctx.coap, wkc, serve, NULL),
            "registering callback for %s failed", wkc);

    return 0;
err:
    return -1;
}
Exemple #3
0
void
f_nop(Chan *cp, Oldfcall *in, Oldfcall *ou)
{

	USED(in);
	USED(ou);
	if(CHAT(cp))
		print("c_nop %d\n", cp->chan);
}
Exemple #4
0
void
f_clwalk(Chan *cp, Oldfcall *in, Oldfcall *ou)
{
	int er, fid;

	if(CHAT(cp))
		print("c_clwalk macro\n");

	f_clone(cp, in, ou);		/* sets tag, fid */
	if(ou->err)
		return;
	fid = in->fid;
	in->fid = in->newfid;
	f_walk(cp, in, ou);		/* sets tag, fid, qid */
	er = ou->err;
	if(er == Eentry) {
		/*
		 * if error is "no entry"
		 * return non error and fid
		 */
		ou->err = 0;
		f_clunk(cp, in, ou);	/* sets tag, fid */
		ou->err = 0;
		ou->fid = fid;
		if(CHAT(cp))
			print("	error: %s\n", errstring[er]);
		return;
	}
	if(er) {
		/*
		 * if any other error
		 * return an error
		 */
		ou->err = 0;
		f_clunk(cp, in, ou);	/* sets tag, fid */
		ou->err = er;
		return;
	}
	/*
	 * non error
	 * return newfid
	 */
}
Exemple #5
0
/* Payload serving callback. */
const uint8_t *ob_serve(const char *uri, ec_mt_t mt, size_t *p_sz, void *args)
{
    u_unused_args(mt, args);

    CHAT("Producing resource representation for observed URI %s", uri);

    *p_sz = strlen("hello observe");

    return (const uint8_t *) "hello observe";
}
Exemple #6
0
void
f_flush(Chan *cp, Oldfcall *in, Oldfcall *ou)
{

	USED(in);
	USED(ou);
	if(CHAT(cp))
		print("c_flush %d\n", cp->chan);
	runlock(&cp->reflock);
	wlock(&cp->reflock);
	wunlock(&cp->reflock);
	rlock(&cp->reflock);
}
Exemple #7
0
void
f_clone(Chan *cp, Oldfcall *in, Oldfcall *ou)
{
	File *f1, *f2;
	int fid, fid1;

	if(CHAT(cp)) {
		print("c_clone %d\n", cp->chan);
		print("	old fid = %d\n", in->fid);
		print("	new fid = %d\n", in->newfid);
	}

	fid = in->fid;
	fid1 = in->newfid;

	f1 = 0;
	f2 = 0;
	if(fid < fid1) {
		f1 = filep(cp, fid, 0);
		f2 = filep(cp, fid1, 1);
	} else
	if(fid1 < fid) {
		f2 = filep(cp, fid1, 1);
		f1 = filep(cp, fid, 0);
	}
	if(!f1 || !f2) {
		ou->err = Efid;
		goto out;
	}


	f2->fs = f1->fs;
	f2->addr = f1->addr;
	f2->open = f1->open & ~FREMOV;
	f2->uid = f1->uid;
	f2->slot = f1->slot;
	f2->qid = f1->qid;

	freewp(f2->wpath);
	f2->wpath = getwp(f1->wpath);

out:
	ou->fid = fid;
	if(f1)
		qunlock(f1);
	if(f2)
		qunlock(f2);
}
Exemple #8
0
int l_chat_add_colored_text(lua_State *l)
{
  gchar *tag;
  gchar *str;

  luaL_checktype(l, 1, LUA_TSTRING);
  tag = g_strdup(lua_tostring(l, 1));

  luaL_checktype(l, 2, LUA_TSTRING);
  str = g_strdup(lua_tostring(l, 2));

  chat_add_colored_text(CHAT(main_window->chat), tag, str);

  g_free(tag);
  g_free(str);
  return 0;
}
Exemple #9
0
void
f_session(Chan *cp, Oldfcall *in, Oldfcall *ou)
{
	if(CHAT(cp))
		print("c_session %d\n", cp->chan);

	memmove(cp->rchal, in->chal, sizeof(cp->rchal));
	if(wstatallow || cp == cons.srvchan){
		memset(ou->chal, 0, sizeof(ou->chal));
		memset(ou->authid, 0, sizeof(ou->authid));
	}else{
		mkchallenge(cp);
		memmove(ou->chal, cp->chal, sizeof(ou->chal));
		memmove(ou->authid, nvr.authid, sizeof(ou->authid));
	}
	sprint(ou->authdom, "%s.%s", service, nvr.authdom);
	fileinit(cp);
}
Exemple #10
0
void
f_fstat(Chan *cp, Fcall *in, Fcall *ou)
{
	File *f;
	Iobuf *p;
	Dentry *d;
	int i;

	if(CHAT(cp)) {
		fprint(2, "c_fstat %d\n", cp->chan);
		fprint(2, "\tfid = %d\n", in->fid);
	}

	p = 0;
	f = filep(cp, in->fid, 0);
	if(!f) {
		ou->err = Efid;
		goto out;
	}
	p = getbuf(f->fs->dev, f->addr, Brd);
	d = getdir(p, f->slot);
	if(d == 0)
		goto out;

	print("name = %.*s\n", NAMELEN, d->name);
	print("uid = %d; gid = %d; muid = %d\n", d->uid, d->gid, d->muid);
	print("size = %lld; qid = %llux/%lux\n", (Wideoff)d->size,
		(Wideoff)d->qid.path, d->qid.version);
	print("atime = %ld; mtime = %ld\n", d->atime, d->mtime);
	print("dblock =");
	for(i=0; i<NDBLOCK; i++)
		print(" %lld", (Wideoff)d->dblock[i]);
	for (i = 0; i < NIBLOCK; i++)
		print("; iblocks[%d] = %lld", i, (Wideoff)d->iblocks[i]);
	print("\n\n");

out:
	if(p)
		putbuf(p);
	ou->fid = in->fid;
	if(f)
		qunlock(f);
}
Exemple #11
0
void
f_remove(Chan *cp, Oldfcall *in, Oldfcall *ou)
{
	File *f;

	if(CHAT(cp)) {
		print("c_remove %d\n", cp->chan);
		print("	fid = %d\n", in->fid);
	}

	f = filep(cp, in->fid, 0);
	if(!f) {
		ou->err = Efid;
		goto out;
	}
	ou->err = doremove(f, cp==cons.chan);

out:
	ou->fid = in->fid;
	if(f)
		qunlock(f);
}
Exemple #12
0
void
fcall9p1(Chan *cp, Fcall *in, Fcall *ou)
{
	int t;

	rlock(&mainlock);
	t = in->type;
	if(t < 0 || t >= MAXSYSCALL || (t&1) || !call9p1[t]) {
		fprint(2, "bad message type %d\n", t);
		panic("");
	}
	ou->type = t+1;
	ou->err = 0;

	rlock(&cp->reflock);
	(*call9p1[t])(cp, in, ou);
	runlock(&cp->reflock);

	if(ou->err && CHAT(cp))
		fprint(2, "\terror: %s\n", errstr9p[ou->err]);
	runlock(&mainlock);
}
Exemple #13
0
void
f_clri(Chan *cp, Fcall *in, Fcall *ou)
{
	File *f;

	if(CHAT(cp)) {
		fprint(2, "c_clri %d\n", cp->chan);
		fprint(2, "\tfid = %d\n", in->fid);
	}

	f = filep(cp, in->fid, 0);
	if(!f) {
		ou->err = Efid;
		goto out;
	}
	ou->err = doclri(f);

out:
	ou->fid = in->fid;
	if(f)
		qunlock(f);
}
Exemple #14
0
void
f_stat(Chan *cp, Oldfcall *in, Oldfcall *ou)
{
	Iobuf *p;
	Dentry *d;
	File *f;

	if(CHAT(cp)) {
		print("c_stat %d\n", cp->chan);
		print("	fid = %d\n", in->fid);
	}

	p = 0;
	memset(ou->stat, 0, sizeof(ou->stat));
	f = filep(cp, in->fid, 0);
	if(!f) {
		ou->err = Efid;
		goto out;
	}
	p = getbuf(f->fs->dev, f->addr, Bread);
	d = getdir(p, f->slot);
	if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
		ou->err = Ealloc;
		goto out;
	}
	if(ou->err = mkqidcmp(&f->qid, d))
		goto out;
	if(d->qid.path == QPROOT)	/* stat of root gives time */
		d->atime = time(0);
	if(convD2M9p1(d, ou->stat) != DIRREC)
		print("stat convD2M\n");

out:
	if(p)
		putbuf(p);
	if(f)
		qunlock(f);
	ou->fid = in->fid;
}
Exemple #15
0
void
f_clunk(Chan *cp, Oldfcall *in, Oldfcall *ou)
{
	File *f;
	Tlock *t;
	int32_t tim;

	if(CHAT(cp)) {
		print("c_clunk %d\n", cp->chan);
		print("	fid = %d\n", in->fid);
	}

	f = filep(cp, in->fid, 0);
	if(!f) {
		print("%p\n", f);
		ou->err = Efid;
		goto out;
	}
	if(t = f->tlock) {
		tim = time(0);
		if(t->time < tim || t->file != f)
			ou->err = Ebroken;
		t->time = 0;	/* free the lock */
		f->tlock = 0;
	}
	if(f->open & FREMOV)
		ou->err = doremove(f, 0);
	f->open = 0;
	freewp(f->wpath);
	freefp(f);

out:
	if(f)
		qunlock(f);
	ou->fid = in->fid;
}
Exemple #16
0
int vhost_load_resource(u_config_t *resource, const char *origin)
{
    int tmp;
    size_t i, val_sz;
    uint32_t ma;
    const char *path, *max_age, *val, *meth;
    ec_res_t *res = NULL;
    ec_mt_t mt;
    char uri[512];
    ec_method_mask_t methods;
    u_config_t *repr, *attrs;

    dbg_return_if(resource == NULL, -1);

    /* Get resource path. */
    dbg_err_ifm((path = u_config_get_subkey_value(resource, "path")) == NULL,
            "missing mandatory \'path\' in resource");

    /* Get resource max age (default to 60 secs if not specified.) */
    if ((max_age = u_config_get_subkey_value(resource, "max-age")) == NULL)
        ma = 60;
    else
    {
        dbg_err_ifm(u_atoi(max_age, &tmp), "conversion error for %s", max_age);
        ma = (uint32_t) tmp;
    }

    /* Get allowed methods. */
    if ((meth = u_config_get_subkey_value(resource, "allowed-methods")) == NULL)
        methods = EC_GET_MASK; /* Default is read-only. */
    else
    {
        dbg_err_ifm(vhost_load_allowed_methods(meth, &methods),
                "bad allowed-methods in %s%s", origin, path);
    }

    /* Create complete resource name. */
    dbg_err_ifm(u_snprintf(uri, sizeof uri, "%s%s", origin, path),
            "could not create uri for path %s and origin %s", path, origin);

    CHAT("adding resource %s", uri);

    /* Create FS resource. */
    dbg_err_ifm((res = ec_resource_new(uri, methods, ma)) == NULL,
            "resource creation failed");

    /* Load each resource representation. */
    for (i = 0; (repr = u_config_get_child_n(resource,
            "representation", i)) != NULL; ++i)
    {
        /* Retrieve representation type and value. */
        dbg_err_ifm(ec_mt_from_string(u_config_get_subkey_value(repr, "t:"),
                &mt), "media type map error");

        dbg_err_ifm((val = u_config_get_subkey_value(repr, "v:")) == NULL,
                "no value for resource %s", uri);
        val_sz = strlen(val);

        dbg_err_ifm(ec_resource_add_rep(res, (const uint8_t *) val,
                val_sz, mt, NULL),
                "error adding representation for %s", uri);
    }
    dbg_err_ifm(i == 0, "no resources in virtual host");

    /* Add fixed link-format attributes. */
    if (u_config_get_subkey(resource, "link-attrs", &attrs) == 0)
    {
        dbg_err_ifm(vhost_load_resource_attrs(res, attrs),
                "error loading link-attrs for resource %s%s", origin, path);
    }

    /* Put resource into the file system. */
    dbg_err_ifm(ec_filesys_put_resource(g_ctx.fs, res),
            "adding resource failed");
    res = NULL; /* ownership lost */

    /* Register the callback that will serve this URI. */
    dbg_err_ifm(ec_register_cb(g_ctx.coap, uri, serve, NULL),
            "registering callback for %s failed", uri);

    return 0;
err:
    if (res)
        ec_resource_free(res);
    return -1;
}
Exemple #17
0
void
f_wstat(Chan *cp, Oldfcall *in, Oldfcall *ou)
{
	Iobuf *p, *p1;
	Dentry *d, *d1, xd;
	File *f;
	int slot;
	int32_t addr;

	if(CHAT(cp)) {
		print("c_wstat %d\n", cp->chan);
		print("	fid = %d\n", in->fid);
	}

	p = 0;
	p1 = 0;
	d1 = 0;
	f = filep(cp, in->fid, 0);
	if(!f) {
		ou->err = Efid;
		goto out;
	}
	if(isro(f->fs->dev) || (cp != cons.chan && writegroup && !ingroup(f->uid, writegroup))) {
		ou->err = Eronly;
		goto out;
	}

	/*
	 * first get parent
	 */
	if(f->wpath) {
		p1 = getbuf(f->fs->dev, f->wpath->addr, Bread);
		d1 = getdir(p1, f->wpath->slot);
		if(!d1 || checktag(p1, Tdir, QPNONE) || !(d1->mode & DALLOC)) {
			ou->err = Ephase;
			goto out;
		}
	}

	p = getbuf(f->fs->dev, f->addr, Bread);
	d = getdir(p, f->slot);
	if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
		ou->err = Ealloc;
		goto out;
	}
	if(ou->err = mkqidcmp(&f->qid, d))
		goto out;

	convM2D9p1(in->stat, &xd);
	if(CHAT(cp)) {
		print("	d.name = %s\n", xd.name);
		print("	d.uid  = %d\n", xd.uid);
		print("	d.gid  = %d\n", xd.gid);
		print("	d.mode = %.4x\n", xd.mode);
	}

	/*
	 * if chown,
	 * must be god
	 */
	while(xd.uid != d->uid) {
		if(wstatallow)			/* set to allow chown during boot */
			break;
		ou->err = Enotu;
		goto out;
	}

	/*
	 * if chgroup,
	 * must be either
	 *	a) owner and in new group
	 *	b) leader of both groups
	 */
	while(xd.gid != d->gid) {
		if(wstatallow || writeallow)		/* set to allow chgrp during boot */
			break;
		if(d->uid == f->uid && ingroup(f->uid, xd.gid))
			break;
		if(leadgroup(f->uid, xd.gid))
			if(leadgroup(f->uid, d->gid))
				break;
		ou->err = Enotg;
		goto out;
	}

	/*
	 * if rename,
	 * must have write permission in parent
	 */
	if(xd.name[0] == 0)
		strncpy(xd.name, d->name, sizeof(xd.name));
	while(strncmp(d->name, xd.name, sizeof(d->name)) != 0) {
		if(checkname(xd.name)) {
			ou->err = Ename;
			goto out;
		}

		if(strcmp(xd.name, ".") == 0 || strcmp(xd.name, "..") == 0) {
			ou->err = Ename;
			goto out;
		}

		/*
		 * drop entry to prevent lock, then
		 * check that destination name is unique,
		 */
		putbuf(p);
		for(addr=0;; addr++) {
			p = dnodebuf(p1, d1, addr, 0);
			if(!p)
				break;
			if(checktag(p, Tdir, d1->qid.path)) {
				putbuf(p);
				continue;
			}
			for(slot=0; slot<DIRPERBUF; slot++) {
				d = getdir(p, slot);
				if(!(d->mode & DALLOC))
					continue;
				if(!strncmp(xd.name, d->name, sizeof(xd.name))) {
					ou->err = Eexist;
					goto out;
				}
			}
			putbuf(p);
		}

		/*
		 * reacquire entry
		 */
		p = getbuf(f->fs->dev, f->addr, Bread);
		d = getdir(p, f->slot);
		if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
			ou->err = Ephase;
			goto out;
		}

		if(wstatallow || writeallow) /* set to allow rename during boot */
			break;
		if(!d1 || iaccess(f, d1, DWRITE)) {
			ou->err = Eaccess;
			goto out;
		}
		break;
	}

	/*
	 * if mode/time, either
	 *	a) owner
	 *	b) leader of either group
	 */
	while(d->mtime != xd.mtime ||
	     ((d->mode^xd.mode) & (DAPND|DLOCK|0777))) {
		if(wstatallow)			/* set to allow chmod during boot */
			break;
		if(d->uid == f->uid)
			break;
		if(leadgroup(f->uid, xd.gid))
			break;
		if(leadgroup(f->uid, d->gid))
			break;
		ou->err = Enotu;
		goto out;
	}
	d->mtime = xd.mtime;
	d->uid = xd.uid;
	d->gid = xd.gid;
	d->mode = (xd.mode & (DAPND|DLOCK|0777)) | (d->mode & (DALLOC|DDIR));

	strncpy(d->name, xd.name, sizeof(d->name));
	if(wstatallow) {
		p->flags |= Bmod;
		if(xd.atime)
			d->atime = xd.atime;
		if(xd.mtime)
			d->mtime = xd.mtime;
	} else
		accessdir(p, d, FWSTAT);

out:
	if(p)
		putbuf(p);
	if(p1)
		putbuf(p1);
	if(f)
		qunlock(f);
	ou->fid = in->fid;
}
Exemple #18
0
void
serve9p1(Chan *chan, uint8_t *ib, int nib)
{
	int n, t;
	uint8_t inbuf[MAXMSG+MAXDAT], outbuf[MAXMSG+MAXDAT];
	Oldfcall fi, fo;

	for(;;){
		if(nib){
			memmove(inbuf, ib, nib);
			n = nib;
			nib = 0;
		}else
			n = read(chan->chan, inbuf, sizeof inbuf);
		if(chat)
			print("read msg %d\n", n);
		if(n == 0 && (chan == cons.srvchan || chan == cons.chan))
			continue;
		if(n <= 0)
			return;
		if(convM2S9p1(inbuf, &fi, n) != n){
			error9p1(chan, outbuf);
			continue;
		}

		t = fi.type;
		if(t < 0 || t >= MAXSYSCALL || (t&1) || !call9p1[t]) {
			print("9p1: bad message type\n");
			error9p1(chan, outbuf);
			continue;
		}

		if(CHAT(chan))
			print("9p1: fi %O\n", &fi);

		/*
		 * set up reply message
		 */
		fo.err = 0;
		if(t == Tread9p1)
			fo.data = (char*)outbuf + 8;

		/*
		 * call the file system
		 */
		cons.work.count++;
		cons.rate.count += n;

		/*
		 * call the file system
		 */
		rlock(&mainlock);
		rlock(&chan->reflock);

		(*call9p1[t])(chan, &fi, &fo);

		runlock(&chan->reflock);
		runlock(&mainlock);

		fo.type = t+1;
		fo.tag = fi.tag;

		if(chat)
			print("9p1: fo %O\n", &fo);

		if(fo.err) {
			strcpy(fo.ename, errstring[fo.err]);
			if(CHAT(cp))
				print("	error: %s\n", fo.ename);
			fo.type = Terror9p1+1;
		}

		n = convS2M9p1(&fo, outbuf);
		if(n == 0) {
			print("9p1: bad S2M conversion\n");
			error9p1(chan, outbuf);
			continue;
		}

		cons.rate.count += n;
		send(chan, outbuf, n);
	}
}
Exemple #19
0
void
f_walk(Chan *cp, Oldfcall *in, Oldfcall *ou)
{
	Iobuf *p, *p1;
	Dentry *d, *d1;
	File *f;
	Wpath *w, *ow;
	int slot;
	int32_t addr;

	if(CHAT(cp)) {
		print("c_walk %d\n", cp->chan);
		print("	fid = %d\n", in->fid);
		print("	name = %s\n", in->name);
	}

	ou->fid = in->fid;
	ou->qid = QID9P1(0,0);
	p = 0;
	f = filep(cp, in->fid, 0);
	if(!f) {
		ou->err = Efid;
		goto out;
	}
	p = getbuf(f->fs->dev, f->addr, Bread);
	d = getdir(p, f->slot);
	if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
		ou->err = Ealloc;
		goto out;
	}
	if(!(d->mode & DDIR)) {
		ou->err = Edir1;
		goto out;
	}
	if(ou->err = mkqidcmp(&f->qid, d))
		goto out;
	if(cp != cons.chan && iaccess(f, d, DEXEC)) {
		ou->err = Eaccess;
		goto out;
	}
	accessdir(p, d, FREAD);
	if(strcmp(in->name, ".") == 0)
		goto setdot;
	if(strcmp(in->name, "..") == 0) {
		if(f->wpath == 0)
			goto setdot;
		putbuf(p);
		p = 0;
		addr = f->wpath->addr;
		slot = f->wpath->slot;
		p1 = getbuf(f->fs->dev, addr, Bread);
		d1 = getdir(p1, slot);
		if(!d1 || checktag(p1, Tdir, QPNONE) || !(d1->mode & DALLOC)) {
			if(p1)
				putbuf(p1);
			ou->err = Ephase;
			goto out;
		}
		ow = f->wpath;
		f->wpath = ow->up;
		putwp(ow);
		goto found;
	}
	for(addr=0;; addr++) {
		p1 = dnodebuf(p, d, addr, 0);
		if(!p1 || checktag(p1, Tdir, d->qid.path) ) {
			if(p1)
				putbuf(p1);
			ou->err = Eentry;
			goto out;
		}
		for(slot=0; slot<DIRPERBUF; slot++) {
			d1 = getdir(p1, slot);
			if(!(d1->mode & DALLOC))
				continue;
			if(strncmp(in->name, d1->name, sizeof(in->name)))
				continue;
			/*
			 * update walk path
			 */
			w = newwp();
			if(!w) {
				ou->err = Ewalk;
				putbuf(p1);
				goto out;
			}
			w->addr = f->addr;
			w->slot = f->slot;
			w->up = f->wpath;
			f->wpath = w;
			slot += DIRPERBUF*addr;
			goto found;
		}
		putbuf(p1);
	}

found:
	f->addr = p1->addr;
	mkqid(&f->qid, d1, 1);
	putbuf(p1);
	f->slot = slot;

setdot:
	mkqid9p1(&ou->qid, &f->qid);
	f->open = 0;

out:
	if(p)
		putbuf(p);
	if(f)
		qunlock(f);
}
Exemple #20
0
void
f_attach(Chan *cp, Oldfcall *in, Oldfcall *ou)
{
	Iobuf *p;
	Dentry *d;
	File *f;
	int u;
	Filsys *fs;
	int32_t raddr;

	if(CHAT(cp)) {
		print("c_attach %d\n", cp->chan);
		print("	fid = %d\n", in->fid);
		print("	uid = %s\n", in->uname);
		print("	arg = %s\n", in->aname);
	}

	ou->qid = QID9P1(0,0);
	ou->fid = in->fid;
	if(!in->aname[0])	/* default */
		strncpy(in->aname, filesys[0].name, sizeof(in->aname));
	p = 0;
	f = filep(cp, in->fid, 1);
	if(!f) {
		ou->err = Efid;
		goto out;
	}
	u = -1;
	if(cp != cons.chan){
		if(authorize(cp, in, ou) == 0 || strcmp(in->uname, "adm") == 0){
			ou->err = Eauth;
			goto out;
		}
		u = strtouid(in->uname);
		if(u < 0){
			ou->err = Ebadu;
			goto out;
		}
	}

	fs = fsstr(in->aname);
	if(fs == 0) {
		ou->err = Ebadspc;
		goto out;
	}
	raddr = getraddr(fs->dev);
	p = getbuf(fs->dev, raddr, Bread);
	d = getdir(p, 0);
	if(!d || checktag(p, Tdir, QPROOT) || !(d->mode & DALLOC)) {
		ou->err = Ealloc;
		goto out;
	}
	f->uid = u;
	if(iaccess(f, d, DREAD)) {
		ou->err = Eaccess;
		goto out;
	}
	accessdir(p, d, FREAD);
	mkqid(&f->qid, d, 1);
	f->fs = fs;
	f->addr = raddr;
	f->slot = 0;
	f->open = 0;
	freewp(f->wpath);
	f->wpath = 0;

	mkqid9p1(&ou->qid, &f->qid);

out:
	if(p)
		putbuf(p);
	if(f) {
		qunlock(f);
		if(ou->err)
			freefp(f);
	}
}
Exemple #21
0
void
f_write(Chan *cp, Oldfcall *in, Oldfcall *ou)
{
	Iobuf *p, *p1;
	Dentry *d;
	File *f;
	Tlock *t;
	int32_t offset, addr, tim;
	int count, nwrite, o, n;

	if(CHAT(cp)) {
		print("c_write %d\n", cp->chan);
		print("	fid = %d\n", in->fid);
		print("	offset = %ld\n", in->offset);
		print("	count = %ld\n", in->count);
	}

	offset = in->offset;
	count = in->count;
	nwrite = 0;
	p = 0;
	f = filep(cp, in->fid, 0);
	if(!f) {
		ou->err = Efid;
		goto out;
	}
	if(!(f->open & FWRITE)) {
		ou->err = Eopen;
		goto out;
	}
	if(isro(f->fs->dev) || (cp != cons.chan && writegroup && !ingroup(f->uid, writegroup))) {
		ou->err = Eronly;
		goto out;
	}
	if(count < 0 || count > MAXDAT) {
		ou->err = Ecount;
		goto out;
	}
	if(offset < 0) {
		ou->err = Eoffset;
		goto out;
	}
	p = getbuf(f->fs->dev, f->addr, Bread|Bmod);
	d = getdir(p, f->slot);
	if(!d || !(d->mode & DALLOC)) {
		ou->err = Ealloc;
		goto out;
	}
	if(ou->err = mkqidcmp(&f->qid, d))
		goto out;
	if(t = f->tlock) {
		tim = time(0);
		if(t->time < tim || t->file != f) {
			ou->err = Ebroken;
			goto out;
		}
		/* renew the lock */
		t->time = tim + TLOCK;
	}
	accessdir(p, d, FWRITE);
	if(d->mode & DAPND)
		offset = d->size;
	if(offset+count > d->size)
		d->size = offset+count;
	while(count > 0) {
		addr = offset / BUFSIZE;
		o = offset % BUFSIZE;
		n = BUFSIZE - o;
		if(n > count)
			n = count;
		p1 = dnodebuf(p, d, addr, Tfile);
		if(p1 == 0) {
			ou->err = Efull;
			goto out;
		}
		if(checktag(p1, Tfile, d->qid.path)) {
			putbuf(p1);
			ou->err = Ephase;
			goto out;
		}
		memmove(p1->iobuf+o, in->data+nwrite, n);
		p1->flags |= Bmod;
		putbuf(p1);
		count -= n;
		nwrite += n;
		offset += n;
	}
	if(CHAT(cp))
		print("	nwrite = %d\n", nwrite);

out:
	if(p)
		putbuf(p);
	if(f)
		qunlock(f);
	ou->fid = in->fid;
	ou->count = nwrite;
}
Exemple #22
0
ec_cbrc_t serve(ec_server_t *srv, void *u0, struct timeval *tv, bool resched)
{
    ec_mt_t mta[16];
    size_t mta_sz = sizeof mta / sizeof(ec_mt_t);
    ec_rep_t *rep;
    ec_res_t *res;
    char uri[U_URI_STRMAX];
    bool is_proxy;

    u_unused_args(u0);

    /* Get the requested URI and method. */
    dbg_if (ec_request_get_uri(srv, uri, &is_proxy) == NULL);
    ec_method_t method = ec_server_get_method(srv);

    CHAT("%s %s", ec_method_str(method), uri);

    /* Tell'em to use test/proxy to support Proxy-Uri's. */
    if (is_proxy)
    {
        dbg_if (ec_response_set_code(srv, EC_PROXYING_NOT_SUPPORTED));
        return EC_CBRC_READY;
    }

    /* See if configured for separate responses. */
    if (resched == false && g_ctx.sep.tv_sec)
    {
        *tv = g_ctx.sep;
        u_con("reschedule %s() for %s in %llu seconds",
              __func__, uri, (long long) g_ctx.sep.tv_sec);
        return EC_CBRC_WAIT;
    }

    /* See if it is a query for the /.well-known/core URI. */
    if (!strcasecmp(ec_request_get_uri_path(srv), "/.well-known/core"))
    {
        (void) serve_wkc(srv, method);
        return EC_CBRC_READY;
    }

    /* Get Accept'able media types. */
    dbg_err_if(ec_request_get_acceptable_media_types(srv, mta, &mta_sz));

    /* Try to retrieve a representation that fits client request. */
    rep = ec_filesys_get_suitable_rep(g_ctx.fs, ec_server_get_url(srv), mta, 
            mta_sz, NULL);

    /* If found, craft the response. */
    if (rep)
    {
        dbg_err_if((res = ec_rep_get_res(rep)) == NULL);

        /* Make sure resource supports the requested method.
         * Bypass check for Proxy-Uri requests because of Publish admin
         * operations (will be checked in PUT/DELETE handlers.) */
        if (!ec_request_via_proxy(srv)
                && ec_resource_check_method(res, method))
        {
            (void) ec_response_set_code(srv, EC_METHOD_NOT_ALLOWED);
            return EC_CBRC_READY;
        }

        switch (method)
        {
            case EC_COAP_GET:
                (void) serve_get(srv, rep);
                return EC_CBRC_READY;

            case EC_COAP_DELETE:
                (void) serve_delete(srv, uri);
                return EC_CBRC_READY;

            case EC_COAP_PUT:
                (void) serve_put(srv, rep);
                return EC_CBRC_READY;

            case EC_COAP_POST:
                (void) serve_post(srv);
                return EC_CBRC_READY;

            default:
                ec_response_set_code(srv, EC_NOT_IMPLEMENTED);
                return EC_CBRC_READY;
        }
    }
    else
        (void) ec_response_set_code(srv, EC_NOT_FOUND);

    return EC_CBRC_READY;
err:
    return EC_CBRC_ERROR;
}
Exemple #23
0
void
f_open(Chan *cp, Oldfcall *in, Oldfcall *ou)
{
	Iobuf *p;
	Dentry *d;
	File *f;
	Tlock *t;
	Qid qid;
	int ro, fmod;

	if(CHAT(cp)) {
		print("c_open %d\n", cp->chan);
		print("	fid = %d\n", in->fid);
		print("	mode = %o\n", in->mode);
	}

	p = 0;
	f = filep(cp, in->fid, 0);
	if(!f) {
		ou->err = Efid;
		goto out;
	}

	/*
	 * if remove on close, check access here
	 */
	ro = isro(f->fs->dev) || (cp != cons.chan && writegroup && !ingroup(f->uid, writegroup));
	if(in->mode & MRCLOSE) {
		if(ro) {
			ou->err = Eronly;
			goto out;
		}
		/*
		 * check on parent directory of file to be deleted
		 */
		if(f->wpath == 0 || f->wpath->addr == f->addr) {
			ou->err = Ephase;
			goto out;
		}
		p = getbuf(f->fs->dev, f->wpath->addr, Bread);
		d = getdir(p, f->wpath->slot);
		if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
			ou->err = Ephase;
			goto out;
		}
		if(iaccess(f, d, DWRITE)) {
			ou->err = Eaccess;
			goto out;
		}
		putbuf(p);
	}
	p = getbuf(f->fs->dev, f->addr, Bread);
	d = getdir(p, f->slot);
	if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
		ou->err = Ealloc;
		goto out;
	}
	if(ou->err = mkqidcmp(&f->qid, d))
		goto out;
	mkqid(&qid, d, 1);
	switch(in->mode & 7) {

	case MREAD:
		if(iaccess(f, d, DREAD) && !writeallow)
			goto badaccess;
		fmod = FREAD;
		break;

	case MWRITE:
		if((d->mode & DDIR) ||
		   (iaccess(f, d, DWRITE) && !writeallow))
			goto badaccess;
		if(ro) {
			ou->err = Eronly;
			goto out;
		}
		fmod = FWRITE;
		break;

	case MBOTH:
		if((d->mode & DDIR) ||
		   (iaccess(f, d, DREAD) && !writeallow) ||
		   (iaccess(f, d, DWRITE) && !writeallow))
			goto badaccess;
		if(ro) {
			ou->err = Eronly;
			goto out;
		}
		fmod = FREAD+FWRITE;
		break;

	case MEXEC:
		if((d->mode & DDIR) ||
		   iaccess(f, d, DEXEC))
			goto badaccess;
		fmod = FREAD;
		break;

	default:
		ou->err = Emode;
		goto out;
	}
	if(in->mode & MTRUNC) {
		if((d->mode & DDIR) ||
		   (iaccess(f, d, DWRITE) && !writeallow))
			goto badaccess;
		if(ro) {
			ou->err = Eronly;
			goto out;
		}
	}
	t = 0;
	if(d->mode & DLOCK) {
		t = tlocked(p, d);
		if(t == 0) {
			ou->err = Elocked;
			goto out;
		}
		t->file = f;
	}
	if(in->mode & MRCLOSE)
		fmod |= FREMOV;
	f->open = fmod;
	if(in->mode & MTRUNC)
		if(!(d->mode & DAPND))
			dtrunc(p, d);
	f->tlock = t;
	f->lastra = 0;
	mkqid9p1(&ou->qid, &qid);
	goto out;

badaccess:
	ou->err = Eaccess;
	f->open = 0;

out:
	if(p)
		putbuf(p);
	if(f)
		qunlock(f);
	ou->fid = in->fid;
}
Exemple #24
0
/*
   The PUT method requests that the resource identified by the request
   URI be updated or created with the enclosed representation.  The
   representation format is specified by the media type given in the
   Content-Type Option.

   If a resource exists at the request URI the enclosed representation
   SHOULD be considered a modified version of that resource, and a 2.04
   (Changed) response SHOULD be returned.  If no resource exists then
   the server MAY create a new resource with that URI, resulting in a
   2.01 (Created) response.  If the resource could not be created or
   modified, then an appropriate error response code SHOULD be sent.

   Further restrictions to a PUT can be made by including the If-Match
   (see Section 5.10.9) or If-None-Match (see Section 5.10.10) options
   in the request.

   PUT is not safe, but idempotent.
 */
int serve_put(ec_server_t *srv, ec_rep_t *rep)
{
    /* This routine handles the update of a resource using the PUT method.
     * Creation of a resource via PUT is done by the create() routine. */

    ec_mt_t mt;
    size_t pload_sz;
    uint8_t etag[EC_ETAG_SZ] = { 0 }, *pload;
    ec_res_t *res = ec_rep_get_res(rep);
    size_t bsz = g_ctx.bsz ? g_ctx.bsz : EC_COAP_BLOCK_MAX;
    blockopt_t b1 = { .bnum = 0, .more = false, .bsz = 0 };

    /* Check conditionals:
     * 1) If-None-Match
     * "If the target resource does exist, then the server MUST NOT perform
     *  the requested method.  Instead, the server MUST respond with the 4.12
     *  (Precondition Failed) response code." */
    if (res && ec_request_get_if_none_match(srv) == 0)
    {
        (void) ec_response_set_code(srv, EC_PRECONDITION_FAILED);
        return 0;
    }

    /* 2) If-Match (TODO) */

    /* Get payload and media type (if specified.) */
    pload = ec_request_get_payload(srv, &pload_sz);
    if (pload_sz > bsz)
    {
        (void) ec_response_set_code(srv, EC_REQUEST_ENTITY_TOO_LARGE);
        return 0;
    }

    /* Get media type (if not specified default to text/plain. */
    if (ec_request_get_content_type(srv, &mt))
        mt = EC_MT_TEXT_PLAIN;

    /* Handle Block1 Option.
     * Implementation is stateful: we just check that bnum corresponds to
     * expected and add the new representation atomically. */
    if (ec_request_get_block1(srv, &b1.bnum, &b1.more, &b1.bsz) == 0)
    {
        dbg_err_if (b1.bnum != g_ctx.b1.bnum++);

        if (b1.bsz)
           bsz = U_MIN(bsz, b1.bsz);

        dbg_err_if (ec_response_add_block1(srv, b1.bnum, b1.more, bsz));
    }

    /* First block. */
    if (g_ctx.resbuf == NULL)
        dbg_err_if (u_buf_create(&g_ctx.resbuf));

    /* All blocks are appended to resource buffer. */
    if (pload)
        dbg_err_if (u_buf_append(g_ctx.resbuf, pload, pload_sz));

    /* Last block - now we can process it. */
    if (!b1.more)
    {
        /* Add new representation. */
        dbg_err_if (ec_resource_add_rep(res, u_buf_ptr(g_ctx.resbuf),
                    u_buf_len(g_ctx.resbuf), mt, etag));

        /* Delete old in case media-type matches. */
        if (mt == rep->media_type)
            (void) ec_rep_del(res, rep);

        /* Return Etag of the new representation. */
        (void) ec_response_add_etag(srv, etag, sizeof etag);

        /* Reset state. */
        u_buf_free(g_ctx.resbuf);
        g_ctx.resbuf = NULL;
        g_ctx.b1.bnum = 0;
        g_ctx.b1.more = false;
        g_ctx.b1.bsz = 0;
    }

    (void) ec_response_set_code(srv, EC_CHANGED);
    return 0;
err:
    (void) ec_response_set_code(srv, EC_INTERNAL_SERVER_ERROR);

    /* Reset state. */
    if (g_ctx.resbuf)
        u_buf_free(g_ctx.resbuf);
    g_ctx.resbuf = NULL;
    g_ctx.b1.bnum = 0;
    g_ctx.b1.more = false;
    g_ctx.b1.bsz = 0;

    return -1;
}

/*
 * The POST method requests that the representation enclosed in the
 * request be processed.  The actual function performed by the POST
 * method is determined by the origin server and dependent on the target
 * resource.  It usually results in a new resource being created or the
 * target resource being updated.
 *
 * If a resource has been created on the server, a 2.01 (Created)
 * response that includes the URI of the new resource in a sequence of
 * one or more Location-Path and/or Location-Query Options SHOULD be
 * returned.  If the POST succeeds but does not result in a new resource
 * being created on the server, a 2.04 (Changed) response SHOULD be
 * returned.  If the POST succeeds and results in the target resource
 * being deleted, a 2.02 (Deleted) response SHOULD be returned.
 *
 * POST is neither safe nor idempotent.
 */
/* 
 * Creates a new resource at <request_uri>/<num>, where num is an incremental
 * counter.
 */
int serve_post(ec_server_t *srv)
{
    /* Request vars. */
    ec_mt_t mt;
    ec_res_t *res = NULL;
    bool is_proxy = false;
    uint8_t *pload;
    size_t pload_sz;
    ec_method_mask_t mm = EC_METHOD_MASK_ALL;
    char uri[U_URI_STRMAX];
    char ruri[U_URI_STRMAX];

    /* Block handling. */
    size_t bsz = g_ctx.bsz ? g_ctx.bsz : EC_COAP_BLOCK_MAX;
    blockopt_t b1 = { .bnum = 0, .more = false, .bsz = 0 };

    /* Path tokenisation. */
    size_t nelems, i;
    char **tv = NULL;

    pload = ec_request_get_payload(srv, &pload_sz);
    if (pload_sz > bsz)
    {
        (void) ec_response_set_code(srv, EC_REQUEST_ENTITY_TOO_LARGE);
        return 0;
    }

    /* Get media type (if not specified default to text/plain. */
    if (ec_request_get_content_type(srv, &mt))
        mt = EC_MT_TEXT_PLAIN;
    
    /* Handle Block1 Option.
     * Implementation is stateful: we just check that bnum corresponds to
     * expected and add the new representation atomically. */
    if (ec_request_get_block1(srv, &b1.bnum, &b1.more, &b1.bsz) == 0)
    {
        dbg_err_if (b1.bnum != g_ctx.b1.bnum++);

        if (b1.bsz)
           bsz = U_MIN(bsz, b1.bsz);

        dbg_err_if (ec_response_add_block1(srv, b1.bnum, b1.more, bsz));
    }

    /* First block. */
    if (g_ctx.resbuf == NULL)
        dbg_err_if (u_buf_create(&g_ctx.resbuf));

    /* All blocks are appended to resource buffer. */
    if (pload)
        dbg_err_if (u_buf_append(g_ctx.resbuf, pload, pload_sz));

    /* Last block - now we can process it. */
    if (!b1.more)
    {
        (void) ec_request_get_uri(srv, uri, &is_proxy);

        dbg_err_if (u_snprintf(ruri, sizeof ruri, "%s/%u", uri, g_ctx.resnum));

        u_dbg("creating resource on uri: %s", ruri);

        /* Create resource with all methods allowed. */
        dbg_err_ifm ((res = ec_resource_new(ruri, mm, EC_COAP_DEFAULT_MAX_AGE))
                == NULL, "resource creation failed");

        /* Create new resource representation with the requested media type. */
        /* Each resource only has one representation in this implementation.
         * Use automatic ETag. */
        dbg_err_ifm (ec_resource_add_rep(res, u_buf_ptr(g_ctx.resbuf),
                    u_buf_len(g_ctx.resbuf), mt, NULL),
                "error adding representation for %s", ruri);

        /* Attach resource to FS. */
        dbg_err_ifm (ec_filesys_put_resource(g_ctx.fs, res),
                "adding resource failed");
        res = NULL;

        /* Register the callback that will serve this URI.
         * XXX If we get an error here it's really a bad thing because
         * the resource has been already registered and we go into an
         * inconsistent state. */
        dbg_err_ifm (ec_register_cb(g_ctx.coap, ruri, serve, NULL),
                "registering callback for %s failed", ruri);

        dbg_err_if (u_strtok(ruri, "/", &tv, &nelems));
        dbg_err_if (nelems < 3);

        for (i = 2; i < nelems; i++)  /* Get path only */
            dbg_err_if (ec_response_add_location_path(srv, tv[i]));

        u_strtok_cleanup(tv, nelems);

        /* Reset state. */
        u_buf_free(g_ctx.resbuf);
        g_ctx.resbuf = NULL;
        g_ctx.b1.bnum = 0;
        g_ctx.b1.more = false;
        g_ctx.b1.bsz = 0;

        g_ctx.resnum++;
    }

    (void) ec_response_set_code(srv, EC_CREATED);
    return 0;
err:
    (void) ec_response_set_code(srv, EC_INTERNAL_SERVER_ERROR);
    if (res)
        ec_resource_free(res);
    if (tv)
        u_strtok_cleanup(tv, nelems);

    /* Reset state. */
    if (g_ctx.resbuf)
        u_buf_free(g_ctx.resbuf);
    g_ctx.resbuf = NULL;
    g_ctx.b1.bnum = 0;
    g_ctx.b1.more = false;
    g_ctx.b1.bsz = 0;
    return -1;

#if 0
    /* This routine handles the creation of a resource using the POST method. */
    ec_mt_t mt;
    uint8_t *pload;
    size_t pload_sz;
    ec_res_t *res = NULL;
    bool is_proxy = false;
    ec_method_mask_t mm = EC_METHOD_MASK_ALL;
    char uri[U_URI_STRMAX], *first, *uri_tmp, *uri_res;

    /* Get payload (may be empty/NULL).
     * If it is not empty/NULL check/parse the content */
    pload = ec_request_get_payload(srv, &pload_sz);

    first = strtok((char *) pload, ">");
    do
    {
        uri_tmp = strpbrk(first, "<");

        (void) ec_request_get_uri(srv, uri, &is_proxy);

        uri_res = strcat(uri, ++uri_tmp);

        CHAT("adding resource for: %s", uri_res);

        /* Create resource with all methods allowed. */
        dbg_err_ifm ((res = ec_resource_new(uri_res, mm, 3600)) == NULL,
                "resource creation failed");

        /* Get media type (if not specified default to text/plain. */
        if (ec_request_get_content_type(srv, &mt))
            mt = EC_MT_TEXT_PLAIN;

        /* Create new resource representation with the requested media type. */
        /* Each resource only has one representation in this implementation.
         * Use automatic ETag. */
        dbg_err_ifm (ec_resource_add_rep(res, (const uint8_t *) " ", 1, mt, NULL),
                "error adding representation for %s", uri_res);

        /* Attach resource to FS. */
        dbg_err_ifm (ec_filesys_put_resource(g_ctx.fs, res),
                "adding resource failed");
        res = NULL;

        /* Register the callback that will serve this URI.
         * XXX If we get an error here it's really a bad thing because
         * the resource has been already registered and we go into an
         * inconsistent state. */
        dbg_err_ifm (ec_register_cb(g_ctx.coap, uri_res, serve, NULL),
                "registering callback for %s failed", uri_res);

        first = NULL;
        uri[0] = '\0';
        first = strtok(NULL, ">");
    }
    while (first != NULL);

    /* 2.01 Created */
    (void) ec_response_set_code(srv, EC_CREATED);

    return EC_CBRC_READY;
err:
    if (res)
        ec_resource_free(res);
    return EC_CBRC_ERROR;
#endif
}

#if 0
ec_cbrc_t create(ec_server_t *srv, void *u0, struct timeval *u1, bool u2)
{
    uint8_t *pload;
    size_t pload_sz;
    ec_res_t *res = NULL;
    ec_method_t method;
    bool is_proxy = false;
    char uri[U_URI_STRMAX];
    ec_mt_t mt;
    ec_method_mask_t mm = EC_METHOD_MASK_ALL;

    u_unused_args(u0, u1, u2);

    /* Get the requested URI and method. */
    (void) ec_request_get_uri(srv, uri, &is_proxy);

    switch ((method = ec_server_get_method(srv)))
    {
        case EC_COAP_POST:
            (void) serve_post(srv, NULL);
            return EC_CBRC_READY;
        case EC_COAP_PUT:
            break;
        default:
            (void) ec_response_set_code(srv, EC_NOT_FOUND);
            return EC_CBRC_READY;
    }

    CHAT("adding resource for: %s", uri);

    /* Create resource with all methods allowed. */
    dbg_err_ifm((res = ec_resource_new(uri, mm, 3600)) == NULL,
            "resource creation failed");

    /* Get payload (may be empty/NULL). */
    pload = ec_request_get_payload(srv, &pload_sz);

    /* Get media type (if not specified default to text/plain. */
    if (ec_request_get_content_type(srv, &mt))
        mt = EC_MT_TEXT_PLAIN;

    /* Create new resource representation with the requested media type. */
    /* Each resource only has one representation in this implementation.
     * Use automatic ETag. */
    dbg_err_ifm (ec_resource_add_rep(res, pload, pload_sz, mt, NULL),
            "error adding representation for %s", uri);

    /* Attach resource to FS. */
    dbg_err_ifm (ec_filesys_put_resource(g_ctx.fs, res),
            "adding resource failed");
    res = NULL;

    /* Register the callback that will serve this URI.
     * XXX If we get an error here it's really a bad thing because
     * the resource has been already registered and we go into an
     * inconsistent state. */
    dbg_err_ifm (ec_register_cb(g_ctx.coap, uri, serve, NULL),
            "registering callback for %s failed", uri);

    /* 2.01 Created */
    (void) ec_response_set_code(srv, EC_CREATED);

    return EC_CBRC_READY;
err:
    (void) ec_response_set_code(srv, EC_INTERNAL_SERVER_ERROR);
    if (res)
        ec_resource_free(res);
    return EC_CBRC_ERROR;
}
Exemple #25
0
void
f_read(Chan *cp, Oldfcall *in, Oldfcall *ou)
{
	Iobuf *p, *p1;
	File *f;
	Dentry *d, *d1;
	Tlock *t;
	int32_t addr, offset, tim;
	int nread, count, n, o, slot;

	if(CHAT(cp)) {
		print("c_read %d\n", cp->chan);
		print("	fid = %d\n", in->fid);
		print("	offset = %ld\n", in->offset);
		print("	count = %ld\n", in->count);
	}

	p = 0;
	count = in->count;
	offset = in->offset;
	nread = 0;
	f = filep(cp, in->fid, 0);
	if(!f) {
		ou->err = Efid;
		goto out;
	}
	if(!(f->open & FREAD)) {
		ou->err = Eopen;
		goto out;
	}
	if(count < 0 || count > MAXDAT) {
		ou->err = Ecount;
		goto out;
	}
	if(offset < 0) {
		ou->err = Eoffset;
		goto out;
	}
	p = getbuf(f->fs->dev, f->addr, Bread);
	d = getdir(p, f->slot);
	if(!d || !(d->mode & DALLOC)) {
		ou->err = Ealloc;
		goto out;
	}
	if(ou->err = mkqidcmp(&f->qid, d))
		goto out;
	if(t = f->tlock) {
		tim = time(0);
		if(t->time < tim || t->file != f) {
			ou->err = Ebroken;
			goto out;
		}
		/* renew the lock */
		t->time = tim + TLOCK;
	}
	accessdir(p, d, FREAD);
	if(d->mode & DDIR) {
		addr = 0;
		goto dread;
	}
	if(offset+count > d->size)
		count = d->size - offset;
	while(count > 0) {
		addr = offset / BUFSIZE;
		if(addr == f->lastra+1)
			dbufread(p, d, addr+1);
		f->lastra = addr;
		o = offset % BUFSIZE;
		n = BUFSIZE - o;
		if(n > count)
			n = count;
		p1 = dnodebuf(p, d, addr, 0);
		if(p1) {
			if(checktag(p1, Tfile, QPNONE)) {
				ou->err = Ephase;
				putbuf(p1);
				goto out;
			}
			memmove(ou->data+nread, p1->iobuf+o, n);
			putbuf(p1);
		} else
			memset(ou->data+nread, 0, n);
		count -= n;
		nread += n;
		offset += n;
	}
	goto out;

dread:
	p1 = dnodebuf(p, d, addr, 0);
	if(!p1)
		goto out;
	if(checktag(p1, Tdir, QPNONE)) {
		ou->err = Ephase;
		putbuf(p1);
		goto out;
	}
	n = DIRREC;
	for(slot=0; slot<DIRPERBUF; slot++) {
		d1 = getdir(p1, slot);
		if(!(d1->mode & DALLOC))
			continue;
		if(offset >= n) {
			offset -= n;
			continue;
		}
		if(count < n) {
			putbuf(p1);
			goto out;
		}
		if(convD2M9p1(d1, ou->data+nread) != n)
			print("dirread convD2M\n");
		nread += n;
		count -= n;
	}
	putbuf(p1);
	addr++;
	goto dread;

out:
	count = in->count - nread;
	if(count > 0)
		memset(ou->data+nread, 0, count);
	if(p)
		putbuf(p);
	if(f)
		qunlock(f);
	ou->fid = in->fid;
	ou->count = nread;
	if(CHAT(cp))
		print("	nread = %d\n", nread);
}