Exemple #1
0
Npfcall*
diod_readdir(Npfid *fid, u64 offset, u32 count, Npreq *req)
{
    int n;
    Fid *f = fid->aux;
    Npfcall *ret = NULL;

    if (!(ret = np_create_rreaddir (count))) {
        np_uerror (ENOMEM);
        goto error;
    }
    n = _read_dir_linux (f, ret->u.rreaddir.data, offset, count);
    if (np_rerror ()) {
        free (ret);
        ret = NULL;
    } else
        np_finalize_rreaddir (ret, n);
    return ret;
error:
    errn (np_rerror (), "diod_readdir %s@%s:%s",
          fid->user->uname, np_conn_get_client_id (fid->conn), f->path);
    if (ret)
        free (ret);
    return NULL;
}
Exemple #2
0
Npfcall*
diod_lcreate(Npfid *fid, Npstr *name, u32 flags, u32 mode, u32 gid)
{
    Npsrv *srv = fid->conn->srv;
    Fid *f = fid->aux;
    Npfcall *ret;
    Path opath = NULL;

    if ((f->flags & DIOD_FID_FLAGS_ROFS)) {
        np_uerror (EROFS);
        goto error_quiet;
    }

    flags = _remap_oflags (flags);

    if (flags & O_DIRECT) {
        np_uerror (EINVAL); /* O_DIRECT not allowed - see issue 110 */
        goto error_quiet;
    }
    if (!(flags & O_CREAT)) /* can't happen? */
        flags |= O_CREAT;

    if (f->ioctx != NULL) {
        msg ("diod_lcreate: fid is already open");
        np_uerror (EINVAL);
        goto error; 
    }
    opath = f->path;
    if (!(f->path = path_append (srv, opath, name))) {
        np_uerror (ENOMEM);
        goto error;
    }
    if (ioctx_open (fid, flags, mode) < 0) {
        if (np_rerror () == ENOMEM)
            goto error;
        goto error_quiet;
    }
    if (!((ret = np_create_rlcreate (ioctx_qid (f->ioctx),
                                     ioctx_iounit (f->ioctx))))) {
        (void)ioctx_close (fid, 0);
        (void)unlink (path_s (f->path));
        np_uerror (ENOMEM);
        goto error;
    }
    path_decref (srv, opath);
    return ret;
error:
    errn (np_rerror (), "diod_lcreate %s@%s:%s/%.*s",
          fid->user->uname, np_conn_get_client_id (fid->conn),
          opath ? path_s (opath) : path_s (f->path), name->len, name->str);
error_quiet:
    if (opath) {
        if (f->path)
            path_decref (srv, f->path);
        f->path = opath;
    }
    return NULL;
}
Exemple #3
0
/* Twrite - write to a file.
 */
Npfcall*
diod_write (Npfid *fid, u64 offset, u32 count, u8 *data, Npreq *req)
{
    Fid *f = fid->aux;
    Npfcall *ret;
    ssize_t n;

    if (!f->ioctx) {
        msg ("diod_write: fid is not open");
        np_uerror (EBADF);
        goto error;
    }
    if ((f->flags & DIOD_FID_FLAGS_ROFS)) {
        np_uerror (EROFS);
        goto error_quiet;
    }
    if ((n = ioctx_pwrite (f->ioctx, data, count, offset)) < 0) {
        np_uerror (errno);
        goto error_quiet;
    }
    if (!(ret = np_create_rwrite (n))) {
        np_uerror (ENOMEM);
        goto error;
    }
    return ret;
error:
    errn (np_rerror (), "diod_write %s@%s:%s",
          fid->user->uname, np_conn_get_client_id (fid->conn),
          path_s (f->path));
error_quiet:
    return NULL;
}
Exemple #4
0
/* Tread - read from a file or directory.
 */
Npfcall*
diod_read (Npfid *fid, u64 offset, u32 count, Npreq *req)
{
    Fid *f = fid->aux;
    Npfcall *ret = NULL;
    ssize_t n;

    if (!f->ioctx) {
        msg ("diod_read: fid is not open");
        np_uerror (EBADF);
        goto error;
    }
    if (!(ret = np_alloc_rread (count))) {
        np_uerror (ENOMEM);
        goto error;
    }
    n = ioctx_pread (f->ioctx, ret->u.rread.data, count, offset);
    if (n < 0) {
        np_uerror (errno);
        goto error_quiet;
    }
    np_set_rread_count (ret, n);
    return ret;
error:
    errn (np_rerror (), "diod_read %s@%s:%s",
          fid->user->uname, np_conn_get_client_id (fid->conn),
          path_s (f->path));
error_quiet:
    if (ret)
        free (ret);
    return NULL; 
}
Exemple #5
0
Npcfid*
npc_auth (Npcfsys *fs, char *aname, u32 uid, AuthFun auth)
{
        Npcfid *afid = NULL;
        Npfcall *tc = NULL, *rc = NULL;

        if (!(afid = npc_fid_alloc (fs)))
                goto done;
        if (!(tc = np_create_tauth (afid->fid, NULL, aname, uid))) {
		np_uerror (ENOMEM);
		npc_fid_free (afid);
		afid = NULL;
                goto done;
	}
        if (afid->fsys->rpc (afid->fsys, tc, &rc) < 0) {
		npc_fid_free (afid);
		afid = NULL;
		goto done;
	}
	if (auth && auth (afid, uid) < 0) {
		int saved_err = np_rerror ();
		(void)npc_clunk (afid);
		afid = NULL;
		np_uerror (saved_err);
		goto done;
	}
done:
        if (tc)
                free(tc);
        if (rc)
                free(rc);
        return afid;
}
Exemple #6
0
Npfcall*
diod_fsync (Npfid *fid)
{
    Fid *f = fid->aux;
    Npfcall *ret;

    if ((f->flags & DIOD_FID_FLAGS_ROFS)) {
        np_uerror (EROFS);
        goto error_quiet;
    }
    if (!f->ioctx) {
        msg ("diod_fsync: fid is not open");
        np_uerror (EBADF);
        goto error;
    }
    if (ioctx_fsync (f->ioctx) < 0) {
        np_uerror (errno);
        goto error_quiet;
    }
    if (!((ret = np_create_rfsync ()))) {
        np_uerror (ENOMEM);
        goto error;
    }
    return ret;
error:
    errn (np_rerror (), "diod_fsync %s@%s:%s",
          fid->user->uname, np_conn_get_client_id (fid->conn),
          path_s (f->path));
error_quiet:
    return NULL;
}
Exemple #7
0
Npcfsys*
npc_start (int rfd, int wfd, int msize, int flags)
{
	Npcfsys *fs;
	Npfcall *tc = NULL, *rc = NULL;

	if ((flags & NPC_MULTI_RPC))
		fs = npc_create_mtfsys (rfd, wfd, msize, flags);
	else 
		fs = npc_create_fsys (rfd, wfd, msize, flags);
	if (!fs)
		goto done;
	if (!(tc = np_create_tversion (msize, "9P2000.L"))) {
		np_uerror (ENOMEM);
		goto done;
	}
	if (fs->rpc (fs, tc, &rc) < 0)
		goto done;
	if (rc->u.rversion.msize < msize)
		fs->msize = rc->u.rversion.msize;
	if (np_strcmp (&rc->u.rversion.version, "9P2000.L") != 0) {
		np_uerror(EIO);
		goto done;
	}
done:
	if (tc)
		free (tc);
	if (rc)
		free (rc);
	if (np_rerror () && fs) {
		npc_finish (fs);
		fs = NULL;
	}			
	return fs;
}
Exemple #8
0
/* Locking note:
 * Implement POSIX locks in terms of BSD flock locks.
 * This at least gets distributed whole-file locking to work.
 * Strategies for distributed record locking will deadlock.
 */
Npfcall*
diod_lock (Npfid *fid, u8 type, u32 flags, u64 start, u64 length, u32 proc_id,
           Npstr *client_id)
{
    Fid *f = fid->aux;
    Npfcall *ret = NULL;
    u8 status = P9_LOCK_ERROR;

    if ((f->xflags & XFLAGS_RO)) {
        np_uerror (EROFS);
        goto error_quiet;
    }
    if (flags & ~P9_LOCK_FLAGS_BLOCK) { /* only one valid flag for now */
        np_uerror (EINVAL);             /*  (which we ignore) */
        goto error;
    }
    if (_fidstat(f) < 0)
        goto error_quiet;
    switch (type) {
        case F_UNLCK:
            if (flock (f->fd, LOCK_UN) >= 0) {
                status = P9_LOCK_SUCCESS;
                f->lock_type = LOCK_UN;
            } else
                status = P9_LOCK_ERROR;
            break;
        case F_RDLCK:
            if (flock (f->fd, LOCK_SH | LOCK_NB) >= 0) {
                status = P9_LOCK_SUCCESS;
                f->lock_type = LOCK_SH;
            } else if (errno == EWOULDBLOCK) {
                status = P9_LOCK_BLOCKED;
            } else
                status = P9_LOCK_ERROR;
            break;
        case F_WRLCK:
            if (flock (f->fd, LOCK_EX | LOCK_NB) >= 0) {
                status = P9_LOCK_SUCCESS;
                f->lock_type = LOCK_EX;
            } else if (errno == EWOULDBLOCK) {
                status  = P9_LOCK_BLOCKED;
            }
            break;
        default:
            np_uerror (EINVAL);
            goto error;
    }
    if (!((ret = np_create_rlock (status)))) {
        np_uerror (ENOMEM);
        goto error;
    }
    return ret;
error:
    errn (np_rerror (), "diod_lock %s@%s:%s",
          fid->user->uname, np_conn_get_client_id (fid->conn), f->path);
error_quiet:
    if (ret)
        free (ret);
    return NULL;
}
Exemple #9
0
/* Twrite - write to a file.
 */
Npfcall*
diod_write (Npfid *fid, u64 offset, u32 count, u8 *data, Npreq *req)
{
    Fid *f = fid->aux;
    Npfcall *ret;
    ssize_t n;

    if ((f->xflags & XFLAGS_RO)) {
        np_uerror (EROFS);
        goto error_quiet;
    }
    if ((n = pwrite (f->fd, data, count, offset)) < 0) {
        np_uerror (errno);
        goto error_quiet;
    }
    if (!(ret = np_create_rwrite (n))) {
        np_uerror (ENOMEM);
        goto error;
    }
    return ret;
error:
    errn (np_rerror (), "diod_write %s@%s:%s",
          fid->user->uname, np_conn_get_client_id (fid->conn), f->path);
error_quiet:
    return NULL;
}
Exemple #10
0
/* Tread - read from a file or directory.
 */
Npfcall*
diod_read (Npfid *fid, u64 offset, u32 count, Npreq *req)
{
    Fid *f = fid->aux;
    Npfcall *ret = NULL;
    ssize_t n;

    if (!(ret = np_alloc_rread (count))) {
        np_uerror (ENOMEM);
        goto error;
    }
    if ((n = pread (f->fd, ret->u.rread.data, count, offset)) < 0) {
        np_uerror (errno);
        goto error_quiet;
    }
    np_set_rread_count (ret, n);
    return ret;
error:
    errn (np_rerror (), "diod_read %s@%s:%s",
          fid->user->uname, np_conn_get_client_id (fid->conn), f->path);
error_quiet:
    if (ret)
        free (ret);
    return NULL; 
}
Exemple #11
0
/* This needs to be called with the usercache lock held.
 * I don't think it's thread safe. -jg
 */
static int
_getgrouplist (Npsrv *srv, Npuser *u)
{
    int i, ret = -1;
    gid_t *sgcpy;

    u->nsg = sysconf(_SC_NGROUPS_MAX);
    if (u->nsg < 65536)
        u->nsg = 65536;
    if (!(u->sg = malloc (u->nsg * sizeof (gid_t)))) {
        np_uerror (ENOMEM);
        np_logerr (srv, "_alloc_user: %s", u->uname);
        goto done;
    }
    if (getgrouplist(u->uname, u->gid, u->sg, &u->nsg) == -1) {
        np_logerr (srv, "_alloc_user: %s: getgrouplist", u->uname);
        if (np_rerror () == 0)
            np_uerror (EPERM);
        goto done;
    }
    if ((sgcpy = malloc (u->nsg * sizeof (gid_t)))) {
        for (i = 0; i < u->nsg; i++)
            sgcpy[i] = u->sg[i];
        free (u->sg);
        u->sg = sgcpy;
    }
    ret = 0;
done:
    return ret;
}
Exemple #12
0
/* Tstatfs - read file system information.
 */
Npfcall*
diod_statfs (Npfid *fid)
{
    Fid *f = fid->aux;
    struct statfs sb;
    Npfcall *ret;
    u64 fsid;

    if (statfs (f->path, &sb) < 0) {
        np_uerror (errno);
        goto error;
    }
    fsid = (u64)sb.f_fsid.__val[0] | ((u64)sb.f_fsid.__val[1] << 32);
    if (!(ret = np_create_rstatfs(sb.f_type, sb.f_bsize, sb.f_blocks,
                                  sb.f_bfree, sb.f_bavail, sb.f_files,
                                  sb.f_ffree, fsid,
                                  sb.f_namelen))) {
        np_uerror (ENOMEM);
        goto error;
    }
    return ret;
error:
    errn (np_rerror (), "diod_statfs %s@%s:%s",
          fid->user->uname, np_conn_get_client_id (fid->conn), f->path);
    return NULL;
}
Exemple #13
0
/* Tremove - remove a file or directory.
 */
Npfcall*
diod_remove (Npfid *fid)
{
    Fid *f = fid->aux;
    Npfcall *ret;

    if ((f->xflags & XFLAGS_RO)) {
        np_uerror (EROFS);
        goto error_quiet;
    }
    if (remove (f->path) < 0) {
        np_uerror (errno);
        goto error_quiet;
    }
    if (!(ret = np_create_rremove ())) {
        np_uerror (ENOMEM);
        goto error;
    }
    return ret;
error:
    errn (np_rerror (), "diod_remove %s@%s:%s",
          fid->user->uname, np_conn_get_client_id (fid->conn), f->path);
error_quiet:
    return NULL;
}
Exemple #14
0
/* Returns error code > 0 on error.
 * Returns 0 on success: result set to NULL at EOF, o/w set to entry
 */
int
npc_readdir_r (Npcfid *fid, struct dirent *entry, struct dirent **result)
{
	Npqid qid;
	int dname_size = PATH_MAX + 1;
	u64 offset;
	u8 type;
	int res;

	if (fid->dbuf_used >= fid->dbuf_len) {
		fid->dbuf_len = npc_readdir (fid, fid->offset, fid->dbuf,
					      fid->dbuf_size);
		if (fid->dbuf_len < 0)
			return np_rerror ();
		if (fid->dbuf_len == 0) {	/* EOF */
			*result = NULL;
			return 0;
		}
		fid->dbuf_used = 0;
	}
	res = np_deserialize_p9dirent (&qid, &offset, &type,
				       entry->d_name, dname_size,
				       (u8 *)fid->dbuf + fid->dbuf_used,
				       fid->dbuf_len   - fid->dbuf_used);
	if (res == 0)
		return EIO;
	entry->d_off = offset;
	entry->d_type = type;
	entry->d_ino = qid.path;
	//entry->d_reclen
	fid->offset = offset;
	fid->dbuf_used += res;
	*result = entry;
	return 0;
}
Exemple #15
0
Npcfid *
npc_attach (Npcfsys *fs, Npcfid *afid, char *aname, uid_t uid)
{
	Npfcall *tc = NULL, *rc = NULL;
	Npcfid *fid = NULL;

	if (!(fid = npc_fid_alloc (fs)))
		goto done;
	if (!(tc = np_create_tattach (fid->fid, afid ? afid->fid : P9_NOFID,
				      NULL, aname, uid))) {
		np_uerror (ENOMEM);
		goto done;
	}
	if (fs->rpc (fs, tc, &rc) < 0)
		goto done;
done:
	if (tc)
		free (tc);
	if (rc)
		free (rc);
	if (np_rerror () && fid) {
		npc_fid_free (fid);
		fid = NULL;
	}
	return fid;	
}
Exemple #16
0
Npfcall*
diod_lcreate(Npfid *fid, Npstr *name, u32 flags, u32 mode, u32 gid)
{
    Fid *f = fid->aux;
    Npfcall *ret = NULL;
    char *npath = NULL;
    Npqid qid;
    int fd = -1;
    struct stat sb;
    mode_t saved_umask;
    int created = 0;
    u32 iounit = 0; /* client will use msize-P9_IOHDRSZ */

    if ((f->xflags & XFLAGS_RO)) {
        np_uerror (EROFS);
        goto error_quiet;
    }
    if (!(flags & O_CREAT)) /* can't happen? */
        flags |= O_CREAT;
    if (!(npath = _mkpath(f->path, name))) {
        np_uerror (ENOMEM);
        goto error;
    }
    saved_umask = umask(0);
    if ((fd = open (npath, flags, mode)) < 0) {
        np_uerror (errno);
        goto error_quiet;
    }
    created = 1;
    umask(saved_umask);
    if (fstat (fd, &sb) < 0) {
        np_uerror (errno);
        goto error; /* shouldn't happen? */
    }
    _ustat2qid (&sb, &qid);
    //iounit = sb.st_blksize;
    if (!((ret = np_create_rlcreate (&qid, iounit)))) {
        np_uerror (ENOMEM);
        goto error;
    }
    free (f->path);
    f->path = npath;
    f->fd = fd;
    return ret;
error:
    errn (np_rerror (), "diod_lcreate %s@%s:%s/%.*s",
          fid->user->uname, np_conn_get_client_id (fid->conn), f->path,
          name->len, name->str);
error_quiet:
    if (fd >= 0) {
        (void)close (fd);
    }
    if (created && npath)
        (void)unlink (npath);
    if (npath)
        free (npath);
    if (ret)
        free (ret);
    return NULL;
}
Exemple #17
0
Npfcall*
diod_readlink(Npfid *fid)
{
    Fid *f = fid->aux;
    Npfcall *ret = NULL;
    char target[PATH_MAX + 1];
    int n;

    if ((n = readlink (f->path, target, sizeof(target))) < 0) {
        np_uerror (errno);
        goto error_quiet;
    }
    target[n] = '\0';
    if (!(ret = np_create_rreadlink(target))) {
        np_uerror (ENOMEM);
        goto error;
    }
    return ret;
error:
    errn (np_rerror (), "diod_readlink %s@%s:%s",
          fid->user->uname, np_conn_get_client_id (fid->conn), f->path);
error_quiet:
    if (ret)
        free (ret);
    return NULL;
}
Exemple #18
0
/* Tclunk - close a file.
 */
Npfcall*
diod_clunk (Npfid *fid)
{
    Fid *f = fid->aux;
    Npfcall *ret;

    if (f->dir) {
        if (closedir(f->dir) < 0) {
            np_uerror (errno);
            goto error_quiet;
        }
    } else if (f->fd != -1) {
        if (close (f->fd) < 0) {
            np_uerror (errno);
            goto error_quiet;
        }
    }
    if (!(ret = np_create_rclunk ())) {
        np_uerror (ENOMEM);
        goto error;
    }
    return ret;
error:
    errn (np_rerror (), "diod_clunk %s@%s:%s",
          fid->user->uname, np_conn_get_client_id (fid->conn), f->path);
error_quiet:
    return NULL;
}
Exemple #19
0
Npfcall*
diod_fsync (Npfid *fid)
{
    Fid *f = fid->aux;
    Npfcall *ret = NULL;

    if ((f->xflags & XFLAGS_RO)) {
        np_uerror (EROFS);
        goto error_quiet;
    }
    if (fsync(f->dir ? dirfd (f->dir) : f->fd) < 0) {
        np_uerror (errno);
        goto error_quiet;
    }
    if (!((ret = np_create_rfsync ()))) {
        np_uerror (ENOMEM);
        goto error;
    }
    return ret;
error:
    errn (np_rerror (), "diod_fsync %s@%s:%s",
          fid->user->uname, np_conn_get_client_id (fid->conn), f->path);
error_quiet:
    if (ret)
        free (ret);
    return NULL;
}
Exemple #20
0
Fichier : tmkdir.c Projet : 8l/diod
int
main (int argc, char *argv[])
{
    Npcfsys *fs;
    Npcfid *afid, *root;
    uid_t uid = geteuid ();
    char *aname, *path;
    int fd = 0; /* stdin */

    diod_log_init (argv[0]);

    if (argc != 3)
        usage ();
    aname = argv[1];
    path = argv[2];

    if (!(fs = npc_start (fd, fd, 65536+24, 0)))
        errn_exit (np_rerror (), "npc_start");
    if (!(afid = npc_auth (fs, aname, uid, diod_auth)) && np_rerror () != 0)
        errn_exit (np_rerror (), "npc_auth");
    if (!(root = npc_attach (fs, afid, aname, uid)))
        errn_exit (np_rerror (), "npc_attach");
    if (afid && npc_clunk (afid) < 0)
        errn (np_rerror (), "npc_clunk afid");

    if (_mkdir_p (root, path, 0755) < 0)
        errn_exit (np_rerror (), "mkdir");

    if (npc_clunk (root) < 0)
        errn_exit (np_rerror (), "npc_clunk root");
    npc_finish (fs);

    exit (0);
}
Exemple #21
0
Npfcall*
diod_lopen (Npfid *fid, u32 flags)
{
    Fid *f = fid->aux;
    Npfcall *res;

    if ((f->flags & DIOD_FID_FLAGS_ROFS) && ((flags & O_WRONLY)
                                          || (flags & O_RDWR))) {
        np_uerror (EROFS);
        goto error_quiet;
    }

    flags = _remap_oflags (flags);

    if (flags & O_DIRECT) {
        np_uerror (EINVAL); /* O_DIRECT not allowed - see issue 110 */
        goto error_quiet;
    }
    if ((flags & O_CREAT)) /* can't happen? */
        flags &= ~O_CREAT; /* clear and allow to fail with ENOENT */

    if (f->ioctx != NULL) {
        msg ("diod_lopen: fid is already open");
        np_uerror (EINVAL);
        goto error; 
    }
    if (ioctx_open (fid, flags, 0) < 0) {
        if (np_rerror () == ENOMEM)
            goto error;
        goto error_quiet;
    }
    if (!(res = np_create_rlopen (ioctx_qid (f->ioctx),
                                  ioctx_iounit (f->ioctx)))) {
        (void)ioctx_close (fid, 0);
        np_uerror (ENOMEM);
        goto error;
    }
    return res;
error:
    errn (np_rerror (), "diod_lopen %s@%s:%s",
          fid->user->uname, np_conn_get_client_id (fid->conn),
          path_s (f->path));
error_quiet:
    return NULL;
}
Exemple #22
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;
}
Exemple #23
0
Npfcall*
diod_lopen (Npfid *fid, u32 flags)
{
    Fid *f = fid->aux;
    Npfcall *res = NULL;
    Npqid qid;
    u32 iounit = 0; /* client will use msize-P9_IOHDRSZ */

    if ((f->xflags & XFLAGS_RO) && ((flags & O_WRONLY) || (flags & O_RDWR))) {
        np_uerror (EROFS);
        goto error_quiet;
    }
    if ((flags & O_CREAT)) /* can't happen? */
        flags &= ~O_CREAT; /* clear and allow to fail with ENOENT */

    if (_fidstat (f) < 0)
        goto error_quiet;

    if (S_ISDIR (f->stat.st_mode)) {
        f->dir = opendir (f->path);
        if (!f->dir) {
            np_uerror (errno);
            goto error_quiet;
        }
    } else {
        f->fd = open (f->path, flags);
        if (f->fd < 0) {
            np_uerror (errno);
            goto error_quiet;
        }
    }
    if (_fidstat (f) < 0)
        goto error; /* can't happen? */
    _ustat2qid (&f->stat, &qid);
    //iounit = f->stat.st_blksize;
    if (!(res = np_create_rlopen (&qid, iounit))) {
        np_uerror (ENOMEM);
        goto error;
    }
    return res;
error:
    errn (np_rerror (), "diod_lopen %s@%s:%s",
          fid->user->uname, np_conn_get_client_id (fid->conn), f->path);
error_quiet:
    if (f->dir) {
        (void)closedir (f->dir);
        f->dir = NULL;
    }
    if (f->fd != -1) {
        (void)close (f->fd); 
        f->fd = -1;
    }
    if (res)
        free (res);
    return NULL;
}
Exemple #24
0
int
main (int argc, char *argv[])
{
    Npcfsys *fs;
    Npcfid *afid, *root, *fid;
    char *aname;
    const int fd = 0; /* stdin */
    uid_t uid;
    gid_t gid, ngid;

    diod_log_init (argv[0]);

    if (argc != 2)
        usage ();
    aname = argv[1];

    if (geteuid () != 0) /* the server actually must be running as root */
        msg_exit ("must run as root");

    pick_user (&uid, &gid, &ngid);

    if (!(fs = npc_start (fd, 8192+24, 0)))
        errn_exit (np_rerror (), "npc_start");
    if (!(afid = npc_auth (fs, aname, uid, diod_auth)) && np_rerror () != 0)
        errn_exit (np_rerror (), "npc_auth");
    if (!(root = npc_attach (fs, afid, aname, uid)))
        errn_exit (np_rerror (), "npc_attach");
    if (afid && npc_clunk (afid) < 0)
        errn_exit (np_rerror (), "npc_clunk afid");

    /* should succeed */
    if (!(fid = npc_create_bypath (root, "foo", 0644, O_RDONLY, gid)))
        errn_exit (np_rerror (), "npc_create_bypath as %d:%d with gid %d",
                   uid, gid, gid);
    if (npc_clunk (fid) < 0)
        errn_exit (np_rerror (), "npc_clunk");
    msg ("create foo with good gid succeeded");

    /* should fail */
    if ((fid = npc_create_bypath (root, "foo2", 0644, O_RDONLY, ngid)))
        msg_exit ("npc_create_bypath as %d:%d with gid %d succeeded: FAIL",
                  uid, gid, ngid);
    msg ("create foo2 with bad gid failed");

    if (npc_clunk (root) < 0)
        errn_exit (np_rerror (), "npc_clunk root");

    npc_finish (fs);

    diod_log_fini ();

    exit (0);
}
Exemple #25
0
static int
lsdir (int i, int count, Npcfid *root, int lopt, char *path)
{
    Npcfid *dir = NULL;
    struct dirent d, *dp;

    if (!(dir = npc_opendir (root, path))) {
        if (np_rerror () == ENOTDIR) {
            if (lopt)
                lsfile_l (root, path);
            else
                printf ("%s\n", path);
            return 0;
        }
        errn (np_rerror (), "%s", path);
        goto error;
    }
    if (count > 1)
        printf ("%s:\n", path);
    do { 
        if ((npc_readdir_r (dir, &d, &dp)) > 0) {
            errn (np_rerror (), "npc_readdir: %s", path);
            goto error;
        }
        if (dp) {
            if (lopt)
                lsfile_l (dir, dp->d_name);
            else
                printf ("%s\n", dp->d_name);
        }
    } while (dp != NULL);
    if (npc_clunk (dir) < 0) {
        errn (np_rerror (), "npc_clunk: %s", path);
        goto error;
    }
    if (count > 1 && i < count - 1)
        printf ("\n");
    return 0;
error:
    if (dir)
        (void)npc_clunk (dir);
    return -1;
}
Exemple #26
0
/* Locking note:
 * Implement POSIX locks in terms of BSD flock locks.
 * This at least gets distributed whole-file locking to work.
 * Strategies for distributed record locking will deadlock.
 */
Npfcall*
diod_lock (Npfid *fid, u8 type, u32 flags, u64 start, u64 length, u32 proc_id,
           Npstr *client_id)
{
    Fid *f = fid->aux;
    Npfcall *ret;
    u8 status = P9_LOCK_ERROR;

    if ((f->flags & DIOD_FID_FLAGS_ROFS)) {
        np_uerror (EROFS);
        goto error_quiet;
    }
    if (flags & ~P9_LOCK_FLAGS_BLOCK) { /* only one valid flag for now */
        np_uerror (EINVAL);             /*  (which we ignore) */
        goto error;
    }
    if (!f->ioctx) {
        msg ("diod_lock: fid is not open");
        np_uerror (EBADF);
        goto error;
    }
    switch (type) {
        case P9_LOCK_TYPE_UNLCK:
            if (ioctx_flock (f->ioctx, LOCK_UN) == 0)
                status = P9_LOCK_SUCCESS;
            break;
        case P9_LOCK_TYPE_RDLCK:
            if (ioctx_flock (f->ioctx, LOCK_SH | LOCK_NB) == 0)
                status = P9_LOCK_SUCCESS;
            else if (errno == EWOULDBLOCK)
                status = P9_LOCK_BLOCKED;
            break;
        case P9_LOCK_TYPE_WRLCK:
            if (ioctx_flock (f->ioctx, LOCK_EX | LOCK_NB) == 0) 
                status = P9_LOCK_SUCCESS;
            else if (errno == EWOULDBLOCK)
                status  = P9_LOCK_BLOCKED;
            break;
        default:
            np_uerror (EINVAL);
            goto error;
    }
    if (!((ret = np_create_rlock (status)))) {
        np_uerror (ENOMEM);
        goto error;
    }
    return ret;
error:
    errn (np_rerror (), "diod_lock %s@%s:%s",
          fid->user->uname, np_conn_get_client_id (fid->conn),
          path_s (f->path));
error_quiet:
    return NULL;
}
Exemple #27
0
int
main (int argc, char *argv[])
{
    Npcfsys *fs;
    Npcfid *afid, *root;
    char *aname;
    int fd = 0; /* stdin */
    uid_t uid = geteuid ();

    diod_log_init (argv[0]);

    if (argc != 2)
        usage ();
    aname = argv[1];

    if (!(fs = npc_start (fd, 8192+24, 0)))
        errn_exit (np_rerror (), "npc_start");
    if (!(afid = npc_auth (fs, aname, uid, diod_auth)) && np_rerror () != 0)
        errn_exit (np_rerror (), "npc_auth");
    if (!(root = npc_attach (fs, afid, aname, uid)))
        errn_exit (np_rerror (), "npc_attach");
    if (afid && npc_clunk (afid) < 0)
        errn_exit (np_rerror (), "npc_clunk afid");

    _flush_series (fs, root);

    if (npc_clunk (root) < 0)
        errn_exit (np_rerror (), "npc_clunk root");
    npc_finish (fs);

    diod_log_fini ();

    exit (0);
}
Exemple #28
0
static void
lsfile_l (Npcfid *dir, char *name)
{
    Npcfid *fid = NULL;
    struct stat sb;
    struct passwd *pw;
    struct group *gr;
    char uid[16], gid[16];
    char *mtime;

    if (!(fid = npc_walk (dir, name))) {
        errn (np_rerror (), "npc_walk %s\n", name);
        goto error;
    }
    if (npc_fstat (fid, &sb) < 0) {
        errn (np_rerror (), "npc_fstat %s\n", name);
        goto error;
    }
    if (npc_clunk (fid) < 0) {
        errn (np_rerror (), "npc_clunk %s\n", name);
        goto error;
    }
    if (!(pw = getpwuid (sb.st_uid)))
        snprintf (uid, sizeof (uid), "%d", sb.st_uid);
    if (!(gr = getgrgid (sb.st_gid)))
        snprintf (gid, sizeof (gid), "%d", sb.st_gid);
    mtime = ctime( &sb.st_mtime);
    printf ("%10s %4lu %s %s %12lu %.*s %s\n",
            mode2str (sb.st_mode),
            sb.st_nlink,
            pw ? pw->pw_name : uid,
            gr ? gr->gr_name : gid,
            sb.st_size,
            (int)strlen (mtime) - 13, mtime + 4,
            name);
    return;
error:
    if (fid)
        (void)npc_clunk (fid);
}
Exemple #29
0
void
diod_sock_startfd (Npsrv *srv, int fdin, int fdout, char *client_id)
{
    Npconn *conn;
    Nptrans *trans;

    trans = np_fdtrans_create (fdin, fdout);
    if (!trans) {
        errn (np_rerror (), "error creating transport for %s", client_id);
        (void)close (fdin);
        if (fdin != fdout)
            (void)close (fdout);
        return;
    }
                 
    conn = np_conn_create (srv, trans, client_id);
    if (!conn) {
        errn (np_rerror (), "error creating connection for %s", client_id);
	/* trans is destroyed in np_conn_create on failure */
        return;
    }
}
Exemple #30
0
static void
_diod_mount (Opt o, int rfd, int wfd, char *spec, char *dir, int vopt,
             int fopt, int nopt)
{
    char *options, *options9p, *aname, *uname;
    uid_t uid;
    int msize;
    Npcfsys *fs;
    Npcfid *afid, *root;
    unsigned long mountflags = 0;

    options = opt_csv (o);
    _getflags (o, &mountflags);
    options9p = opt_csv (o); /* after mountflags removed from opt list */

    if (!(uname = opt_find (o, "uname")))
        msg_exit ("uname is not set"); /* can't happen */
    uid = _uname2uid (uname);
    aname = opt_find (o, "aname"); /* can be null */
    if (!opt_scanf (o, "msize=%d", &msize) || msize < P9_IOHDRSZ)
        msg_exit ("msize must be set to integer >= %d", P9_IOHDRSZ);

    if (vopt)
        msg ("pre-authenticating connection to server");
    if (!(fs = npc_start (rfd, wfd, msize, 0)))
        errn_exit (np_rerror (), "version");
    if (!(afid = npc_auth (fs, aname, uid, diod_auth)) && np_rerror () != 0)
        errn_exit (np_rerror (), "auth");
    if (!(root = npc_attach (fs, afid, aname, uid))) {
        errn (np_rerror (), "attach");
        if (afid)
            (void)npc_clunk (afid);
        exit (1);
    }
    if (afid && npc_clunk (afid) < 0)
        errn_exit (np_rerror (), "clunk afid");
    if (npc_clunk (root) < 0)
        errn_exit (np_rerror (), "clunk root");
    if (vopt)
        msg ("mount -t 9p %s %s -o%s", spec, dir, options);
    if (!fopt) {
        /* kernel wants non-blocking */
        if (fcntl (rfd, F_SETFL, O_NONBLOCK) < 0)
            err_exit ("setting O_NONBLOCK flag on rfd=%d", rfd);
        if (fcntl (wfd, F_SETFL, O_NONBLOCK) < 0)
            err_exit ("setting O_NONBLOCK flag on wfd=%d", wfd);
        _mount (spec, dir, mountflags, options9p);
    }
    npc_finish (fs); /* closes fd */

    if (!nopt) {
        if (!_update_mtab (options, spec, dir))
            msg_exit ("failed to update /etc/mtab");
    }
    free (options);
    free (options9p);
}