Esempio n. 1
0
/* Retrieve export flags for the given aname.
 * Don't set np_uerror() here, just return 1 on match, 0 otherwise.
 */
int diod_fetch_xflags (Npstr *aname, int *xfp)
{
    List exports = diod_conf_get_exports ();
    ListIterator itr = NULL;
    Export *x;
    char *path = NULL;
    int res = 0;

    if (!(path = np_strdup (aname)))
        goto done;
    NP_ASSERT (exports != NULL);
    if (strstr (path, "/..") != NULL)
        goto done;
    if (!(itr = list_iterator_create (exports)))
        goto done;
    while ((x = list_next (itr))) {
        if (_match_export_path (x, path)) {
            if (xfp)
                *xfp = x->oflags;
            res = 1;
            break;
        }
    }
done:
    if (itr)
        list_iterator_destroy (itr);
    if (path)
        free (path);
    return res;
}
Esempio n. 2
0
static Xattr _xattr_create (Npstr *name, size_t size, int flags, u32 setflags)
{
    Xattr x;

    x = malloc (sizeof (struct xattr_struct));
    if (!x)
        goto nomem;
    memset (x, 0, sizeof (struct xattr_struct));
    x->flags = flags;
    x->setflags = setflags;
    if (name && name->len > 0) {
        x->name = np_strdup (name);
        if (!x->name)
            goto nomem;
    }
    if (size > 0) {
        x->buf = malloc (size);
        if (!x->buf)
            goto nomem;
        x->len = size;
    }
    return x;
nomem:
    _xattr_destroy (&x);
    np_uerror (ENOMEM);
    return NULL;
}
Esempio n. 3
0
Npfcall*
diod_symlink(Npfid *fid, Npstr *name, Npstr *symtgt, u32 gid)
{
    Fid *f = fid->aux;
    Npfcall *ret = NULL;
    char *target = NULL, *npath = NULL;
    Npqid qid;
    struct stat sb;
    mode_t saved_umask;
    int created = 0;

    if ((f->xflags & XFLAGS_RO)) {
        np_uerror (EROFS);
        goto error_quiet;
    }
    if (!(npath = _mkpath(f->path, name))) {
        np_uerror (ENOMEM);
        goto error;
    }
    if (!(target = np_strdup (symtgt))) {
        np_uerror (ENOMEM);
        goto error;
    }
    saved_umask = umask(0);
    if (symlink (target, npath) < 0) {
        np_uerror (errno);
        goto error_quiet;
    }
    created = 1;
    umask(saved_umask);
    if (lstat (npath, &sb) < 0) {
        np_uerror (errno);
        goto error; /* shouldn't happen? */
    }
    _ustat2qid (&sb, &qid);
    if (!((ret = np_create_rsymlink (&qid)))) {
        np_uerror (ENOMEM);
        goto error;
    }
    free (npath);
    free (target);
    return ret;
error:
    errn (np_rerror (), "diod_symlink %s@%s:%s/%.*s",
          fid->user->uname, np_conn_get_client_id (fid->conn), f->path,
          name->len, name->str);
error_quiet:
    if (created && npath)
        (void)unlink (npath);
    if (npath)
        free (npath);
    if (target)
        free (target);
    if (ret)
        free (ret);
    return NULL;
}
Esempio n. 4
0
File: ioctx.c Progetto: chaos/diod
Path
path_create (Npsrv *srv, Npstr *ns)
{
    char *s;

    if (!(s = np_strdup (ns)))
        return NULL;
    return _path_alloc (srv, s, ns->len);
}
Esempio n. 5
0
Npfcall*
diod_symlink(Npfid *fid, Npstr *name, Npstr *symtgt, u32 gid)
{
    Npsrv *srv = fid->conn->srv;
    Fid *f = fid->aux;
    Npfcall *ret;
    char *target = NULL;
    Path npath = NULL;
    Npqid qid;
    struct stat sb;

    if ((f->flags & DIOD_FID_FLAGS_ROFS)) {
        np_uerror (EROFS);
        goto error_quiet;
    }
    if (!(npath = path_append (srv, f->path, name))) {
        np_uerror (ENOMEM);
        goto error;
    }
    if (!(target = np_strdup (symtgt))) {
        np_uerror (ENOMEM);
        goto error;
    }
    if (symlink (target, path_s (npath)) < 0 || lstat (path_s (npath),
                                                       &sb) < 0) {
        np_uerror (errno);
        goto error_quiet;
    }
    diod_ustat2qid (&sb, &qid);
    if (!((ret = np_create_rsymlink (&qid)))) {
        (void)unlink (path_s (npath));
        np_uerror (ENOMEM);
        goto error;
    }
    path_decref (srv, npath);
    free (target);
    return ret;
error:
    errn (np_rerror (), "diod_symlink %s@%s:%s/%.*s",
          fid->user->uname, np_conn_get_client_id (fid->conn),
          path_s (f->path), name->len, name->str);
error_quiet:
    if (npath)
        path_decref (srv, npath);
    if (target)
        free (target);
    return NULL;
}
Esempio n. 6
0
File: ops.c Progetto: eugmes/diod
/* Tattach - attach a new user (fid->user) to aname.
 *   diod_auth.c::diod_checkauth first authenticates/authorizes user
 */
Npfcall*
diod_attach (Npfid *fid, Npfid *afid, Npstr *aname)
{
    Npfcall* ret = NULL;
    Fid *f = NULL;
    Npqid qid;
    struct stat sb;

    if (aname->len == 0 || *aname->str != '/') {
        np_uerror (EPERM);
        goto error;
    }
    if (!(f = _fidalloc ()) || !(f->path = np_strdup (aname))) {
        np_uerror (ENOMEM);
        goto error;
    }
    if (diod_conf_opt_runasuid ()) {
        if (fid->user->uid != diod_conf_get_runasuid ()) {
            np_uerror (EPERM);
            goto error;
        }
    }
    if (!diod_match_exports (f->path, fid->conn, fid->user, &f->xflags))
        goto error;
    if (stat (f->path, &sb) < 0) { /* OK to follow symbolic links */
        np_uerror (errno);
        goto error;
    }
    if (!S_ISDIR (sb.st_mode)) {
        np_uerror (ENOTDIR);
        goto error;
    }
    _ustat2qid (&sb, &qid);
    if ((ret = np_create_rattach (&qid)) == NULL) {
        np_uerror (ENOMEM);
        goto error;
    }
    fid->aux = f;
    np_fid_incref (fid);
    return ret;
error:
    errn (np_rerror (), "diod_attach %s@%s:%.*s", fid->user->uname,
          np_conn_get_client_id (fid->conn), aname->len, aname->str);
    if (f)
        _fidfree (f);
    return NULL;
}
Esempio n. 7
0
Npfcall*
diod_getlock (Npfid *fid, u8 type, u64 start, u64 length, u32 proc_id,
             Npstr *client_id)
{
    Fid *f = fid->aux;
    Npfcall *ret;
    char *cid = NULL;
    int ftype;

    if ((f->flags & DIOD_FID_FLAGS_ROFS)) {
        np_uerror (EROFS);
        goto error_quiet;
    }
    if (!f->ioctx) {
        msg ("diod_getlock: fid is not open");
        np_uerror (EBADF);
        goto error;
    }
    if (!(cid = np_strdup (client_id))) {
        np_uerror (ENOMEM);
        goto error;
    }
    if (type != P9_LOCK_TYPE_RDLCK && type != P9_LOCK_TYPE_WRLCK) {
        np_uerror (EINVAL);
        goto error;
    }
    ftype = (type == P9_LOCK_TYPE_RDLCK) ? LOCK_SH : LOCK_EX;
    ftype = ioctx_testlock (f->ioctx, ftype);    
    type = (ftype == LOCK_EX) ? P9_LOCK_TYPE_WRLCK : P9_LOCK_TYPE_UNLCK;
    if (!((ret = np_create_rgetlock(type, start, length, proc_id, cid)))) {
        np_uerror (ENOMEM);
        goto error;
    }
    free (cid);
    return ret;
error:
    errn (np_rerror (), "diod_getlock %s@%s:%s",
          fid->user->uname, np_conn_get_client_id (fid->conn),
          path_s (f->path));
error_quiet:
    if (cid)
        free (cid);
    return NULL;
}
Esempio n. 8
0
Npuser *
np_attach2user (Npsrv *srv, Npstr *uname, u32 n_uname)
{
    Npuser *u = NULL;
    char *s;

    if (n_uname != P9_NONUNAME) {
        u = np_uid2user (srv, n_uname);
    } else {
        if (uname->len == 0) {
            np_uerror (EIO);
            goto done;
        }
        s = np_strdup (uname);
        if (!s) {
            np_uerror (ENOMEM);
            goto done;
        }
        u = np_uname2user (srv, s);
        free (s);
    }
done:
    return u;
}
Esempio n. 9
0
File: ops.c Progetto: eugmes/diod
Npfcall*
diod_getlock (Npfid *fid, u8 type, u64 start, u64 length, u32 proc_id,
             Npstr *client_id)
{
    Fid *f = fid->aux;
    Npfcall *ret;
    char *cid = NULL;
    struct stat sb;

    if ((f->xflags & XFLAGS_RO)) {
        np_uerror (EROFS);
        goto error_quiet;
    }
    if (!(cid = np_strdup (client_id))) {
        np_uerror (ENOMEM);
        goto error;
    }
    if (fstat(f->fd, &sb) < 0) {
        np_uerror (errno);
        goto error_quiet;
    }
    switch (type) {
        case P9_LOCK_TYPE_RDLCK:
            switch (f->lock_type) {
                case LOCK_EX:
                case LOCK_SH:
                    type = P9_LOCK_TYPE_UNLCK;
                    break;
                case LOCK_UN:
                    if (flock (f->fd, LOCK_SH | LOCK_NB) >= 0) {
                        (void)flock (f->fd, LOCK_UN);
                        type = P9_LOCK_TYPE_UNLCK;
                    } else
                        type = P9_LOCK_TYPE_WRLCK;
                    break;
            }
            break;
        case P9_LOCK_TYPE_WRLCK:
            switch (f->lock_type) {
                case LOCK_EX:
                    type = P9_LOCK_TYPE_UNLCK;
                    break;
                case LOCK_SH:
                    /* Rather than upgrade the lock to LOCK_EX and risk
                     * not reacquiring the LOCK_SH afterwards, lie about
                     * the lock being available.  Getlock is racy anyway.
                     */
                    type = P9_LOCK_TYPE_UNLCK;
                    break;
                case LOCK_UN:
                    if (flock (f->fd, LOCK_EX | LOCK_NB) >= 0) {
                        (void)flock (f->fd, LOCK_UN);
                        type = P9_LOCK_TYPE_UNLCK;
                    } else
                        type = P9_LOCK_TYPE_WRLCK; /* could also be LOCK_SH actually */
            }
            break;
        default:
            np_uerror (EINVAL);
            goto error;
    }
    if (type != P9_LOCK_TYPE_UNLCK && type != F_UNLCK) {
        /* FIXME: need to fake up start, length, proc_id, cid? */
    }
    if (!((ret = np_create_rgetlock(type, start, length, proc_id, cid)))) {
        np_uerror (ENOMEM);
        goto error;
    }
    free (cid);
    return ret;
error:
    errn (np_rerror (), "diod_getlock %s@%s:%s",
          fid->user->uname, np_conn_get_client_id (fid->conn), f->path);
error_quiet:
    if (cid)
        free (cid);
    return NULL;
}
Esempio n. 10
0
/* Look up operation's fid and assign it to req->fid.
 * This is done before the request is handed off to a worker, with
 * the plan of using fid data in scheduling work.
 * The fid refcount is incremented here, then decremented in
 * np_process_request ().
 */
static void
np_preprocess_request(Npreq *req)
{
	Npfcall *tc = req->tcall;
	Npconn *conn = req->conn;

	switch (tc->type) {
		case P9_TSTATFS:
			req->fid = np_fid_find (conn, tc->u.tstatfs.fid);
			break;
		case P9_TLOPEN:
			req->fid = np_fid_find (conn, tc->u.tlopen.fid);
			break;
		case P9_TLCREATE:
			req->fid = np_fid_find (conn, tc->u.tlcreate.fid);
			break;
		case P9_TSYMLINK:
			req->fid = np_fid_find (conn, tc->u.tsymlink.fid);
			break;
		case P9_TMKNOD:
			req->fid = np_fid_find (conn, tc->u.tmknod.fid);
			break;
		case P9_TRENAME:
			req->fid = np_fid_find (conn, tc->u.trename.fid);
			break;
		case P9_TREADLINK:
			req->fid = np_fid_find (conn, tc->u.treadlink.fid);
			break;
		case P9_TGETATTR:
			req->fid = np_fid_find (conn, tc->u.tgetattr.fid);
			break;
		case P9_TSETATTR:
			req->fid = np_fid_find (conn, tc->u.tsetattr.fid);
			break;
		case P9_TXATTRWALK:
			req->fid = np_fid_find (conn, tc->u.txattrwalk.fid);
			break;
		case P9_TXATTRCREATE:
			req->fid = np_fid_find (conn, tc->u.txattrcreate.fid);
			break;
		case P9_TREADDIR:
			req->fid = np_fid_find (conn, tc->u.treaddir.fid);
			break;
		case P9_TFSYNC:
			req->fid = np_fid_find (conn, tc->u.tfsync.fid);
			break;
		case P9_TLOCK:
			req->fid = np_fid_find (conn, tc->u.tlock.fid);
			break;
		case P9_TGETLOCK:
			req->fid = np_fid_find (conn, tc->u.tgetlock.fid);
			break;
		case P9_TLINK:
			req->fid = np_fid_find (conn, tc->u.tlink.dfid);
			break;
		case P9_TMKDIR:
			req->fid = np_fid_find (conn, tc->u.tmkdir.fid);
			break;
		case P9_TVERSION:
			break;
		case P9_TAUTH:
			req->fid = np_fid_create (conn, tc->u.tauth.afid);
			if (!req->fid)
				break;
			req->fid->aname = np_strdup (&tc->u.tauth.aname);
			if (!req->fid->aname)
				np_fid_decref (&req->fid);
			/* XXX leave fid->tpool NULL for now as auth
			 * can be handled in the default thread pool
			 * without risk of deadlock.
			 */
			break;
		case P9_TATTACH:
			req->fid = np_fid_create (conn, tc->u.tattach.fid);
			if (!req->fid)
				break;
			req->fid->aname = np_strdup (&tc->u.tattach.aname);
			if (!req->fid->aname)
				np_fid_decref (&req->fid);
			/* Here we select the tpool that will handle this
			 * request and requests on fids walked from this fid.
			 */
			np_tpool_select (req);
			break;
		case P9_TFLUSH:
			break;
		case P9_TWALK:
			req->fid = np_fid_find (conn, tc->u.twalk.fid);
			break;
		case P9_TREAD:
			req->fid = np_fid_find (conn, tc->u.tread.fid);
			break;
		case P9_TWRITE:
			req->fid = np_fid_find (conn, tc->u.twrite.fid);
			break;
		case P9_TCLUNK:
			req->fid = np_fid_find (conn, tc->u.tclunk.fid);
			break;
		case P9_TREMOVE:
			req->fid = np_fid_find (conn, tc->u.tremove.fid);
			break;
		case P9_TRENAMEAT:
			req->fid = np_fid_find (conn,
						tc->u.trenameat.olddirfid);
			break;
		case P9_TUNLINKAT:
			req->fid = np_fid_find (conn, tc->u.tunlinkat.dirfid);
			break;
		default:
			break;
	}
}