コード例 #1
0
ファイル: ops.c プロジェクト: carriercomm/diod
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;
}
コード例 #2
0
ファイル: ops.c プロジェクト: lowfatcomputing/diod
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;
}
コード例 #3
0
ファイル: ops.c プロジェクト: carriercomm/diod
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;
}
コード例 #4
0
ファイル: ops.c プロジェクト: eugmes/diod
Npfcall*
diod_lopen (Npfid *fid, u32 flags)
{
    Fid *f = fid->aux;
    Npfcall *res;
    Npqid qid;
    u32 iounit = 0; /* if iounit is 0, v9fs will use msize-P9_IOHDRSZ */
    struct stat sb;

    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 */

    f->fd = open (f->path, flags);
    if (f->fd < 0) {
        np_uerror (errno);
        goto error_quiet;
    }
    f->dir = fdopendir (f->fd);
    if (!f->dir && errno != ENOTDIR) {
        np_uerror (errno);
        goto error_quiet;
    }
    if (fstat (f->fd, &sb) < 0) {
        np_uerror (errno);
        goto error_quiet;
    }
    _ustat2qid (&sb, &qid);
    //iounit = sb.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);
    else if (f->fd != -1)
        (void)close (f->fd); 
    f->dir = NULL;
    f->fd = -1;
    return NULL;
}
コード例 #5
0
ファイル: ops.c プロジェクト: 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;
}
コード例 #6
0
ファイル: ops.c プロジェクト: eugmes/diod
Npfcall*
diod_getattr(Npfid *fid, u64 request_mask)
{
    Fid *f = fid->aux;
    Npfcall *ret;
    Npqid qid;
    struct stat sb;

    if (f->mountpt) {
        if (_statmnt (f->path, &sb) < 0) {
            np_uerror (errno);
            goto error_quiet;
        }
    } else {
        if (lstat (f->path, &sb) < 0) {
            np_uerror (errno);
            goto error_quiet;
        }
    }
    _ustat2qid (&sb, &qid);
    if (!(ret = np_create_rgetattr(request_mask, &qid,
                                    sb.st_mode,
                                    sb.st_uid,
                                    sb.st_gid,
                                    sb.st_nlink,
                                    sb.st_rdev,
                                    sb.st_size,
                                    sb.st_blksize,
                                    sb.st_blocks,
                                    sb.st_atim.tv_sec,
                                    sb.st_atim.tv_nsec,
                                    sb.st_mtim.tv_sec,
                                    sb.st_mtim.tv_nsec,
                                    sb.st_ctim.tv_sec,
                                    sb.st_ctim.tv_nsec,
                                    0, 0, 0, 0))) {
        np_uerror (ENOMEM);
        goto error;
    }
    return ret;
error:
    errn (np_rerror (), "diod_getattr %s@%s:%s",
          fid->user->uname, np_conn_get_client_id (fid->conn), f->path);
error_quiet:
    return NULL;
}
コード例 #7
0
ファイル: ops.c プロジェクト: eugmes/diod
/* Twalk - walk a file path
 * Called from fcall.c::np_walk () on each wname component in succession.
 * On error, call np_uerror () and return 0.
 */
int
diod_walk (Npfid *fid, Npstr* wname, Npqid *wqid)
{
    Fid *f = fid->aux;
    struct stat sb, sb2;
    char *npath = NULL;

    if (f->mountpt) {
        np_uerror (ENOENT);
        goto error_quiet;
    }
    if (!(npath = _mkpath (f->path, wname))) {
        np_uerror (ENOMEM);
        goto error;
    }
    if (lstat (npath, &sb) < 0) {
        np_uerror (errno);
        goto error_quiet;
    }
    if (lstat (f->path, &sb2) < 0) {
        np_uerror (errno);
        goto error;
    }
    if (sb.st_dev != sb2.st_dev) {
        if (_statmnt (npath, &sb) < 0)
            goto error;
        f->mountpt = 1;
    }
    free (f->path);
    f->path = npath;
    _ustat2qid (&sb, wqid);
    return 1;
error:
    errn (np_rerror (), "diod_walk %s@%s:%s/%.*s",
          fid->user->uname, np_conn_get_client_id (fid->conn), f->path,
          wname->len, wname->str);
error_quiet:
    if (npath)
        free (npath);
    return 0;
}
コード例 #8
0
ファイル: ops.c プロジェクト: lowfatcomputing/diod
/* Twalk - walk a file path
 * Called from fcall.c::np_walk () on each wname component in succession.
 * On error, call np_uerror () and return 0.
 */
int
diod_walk (Npfid *fid, Npstr* wname, Npqid *wqid)
{
    Fid *f = fid->aux;
    struct stat st;
    char *npath;

    if (!(npath = _mkpath (f->path, wname))) {
        np_uerror (ENOMEM);
        goto error;
    }
    if (lstat (npath, &st) < 0) {
        np_uerror (errno);
        goto error_quiet;
    }
    /* N.B. inodes would not be unique if we could cross over to another
     * file system.  But with the code below, ls -l returns ??? for mount
     * point dirs, which would otherwise have a "foreign" inode number.
     * How does NFS make them appear as empty directories?  That would be
     * prettier.
     */
    if (_fidstat (f) < 0)
        goto error;
    if (st.st_dev != f->stat.st_dev) { 
        np_uerror (EXDEV);
        goto error;
    }
    free (f->path);
    f->path = npath;
    _ustat2qid (&st, wqid);
    return 1;
error:
    errn (np_rerror (), "diod_walk %s@%s:%s/%.*s",
          fid->user->uname, np_conn_get_client_id (fid->conn), f->path,
          wname->len, wname->str);
error_quiet:
    if (npath)
        free (npath);
    return 0;
}
コード例 #9
0
ファイル: ops.c プロジェクト: eugmes/diod
Npfcall*
diod_mknod(Npfid *fid, Npstr *name, u32 mode, u32 major, u32 minor, u32 gid)
{
    Npfcall *ret;
    Fid *f = fid->aux;
    char *npath = NULL;
    Npqid qid;
    struct stat sb;

    if ((f->xflags & XFLAGS_RO)) {
        np_uerror (EROFS);
        goto error_quiet;
    }
    if (!(npath = _mkpath(f->path, name))) {
        np_uerror (ENOMEM);
        goto error;
    }
    if (mknod (npath, mode, makedev (major, minor)) < 0
                                        || lstat (npath, &sb) < 0) {
        np_uerror (errno);
        goto error_quiet;
    }
    _ustat2qid (&sb, &qid);
    if (!((ret = np_create_rmknod (&qid)))) {
        (void)unlink (npath);
        np_uerror (ENOMEM);
        goto error;
    }
    free (npath);
    return ret;
error:
    errn (np_rerror (), "diod_mknod %s@%s:%s/%.*s",
          fid->user->uname, np_conn_get_client_id (fid->conn), f->path,
          name->len, name->str);
error_quiet:
    if (npath)
        free (npath);
    return NULL;
}
コード例 #10
0
ファイル: ops.c プロジェクト: lowfatcomputing/diod
Npfcall*
diod_getattr(Npfid *fid, u64 request_mask)
{
    Fid *f = fid->aux;
    Npfcall *ret = NULL;
    Npqid qid;

    if (_fidstat (f) < 0)
        goto error_quiet;
    _ustat2qid (&f->stat, &qid);
    if (!(ret = np_create_rgetattr(request_mask, &qid,
                                    f->stat.st_mode,
                                    f->stat.st_uid,
                                    f->stat.st_gid,
                                    f->stat.st_nlink,
                                    f->stat.st_rdev,
                                    f->stat.st_size,
                                    f->stat.st_blksize,
                                    f->stat.st_blocks,
                                    f->stat.st_atim.tv_sec,
                                    f->stat.st_atim.tv_nsec,
                                    f->stat.st_mtim.tv_sec,
                                    f->stat.st_mtim.tv_nsec,
                                    f->stat.st_ctim.tv_sec,
                                    f->stat.st_ctim.tv_nsec,
                                    0, 0, 0, 0))) {
        np_uerror (ENOMEM);
        goto error;
    }
    return ret;
error:
    errn (np_rerror (), "diod_getattr %s@%s:%s",
          fid->user->uname, np_conn_get_client_id (fid->conn), f->path);
error_quiet:
    if (ret)
        free (ret);
    return NULL;
}
コード例 #11
0
ファイル: ops.c プロジェクト: eugmes/diod
static u32
_copy_dirent_linux (Fid *f, u8 *buf, u32 buflen)
{
    Npqid qid;
    u32 ret = 0;

    if (f->dirent->d_type == DT_UNKNOWN) {
        char path[PATH_MAX + 1];
        struct stat sb;
        snprintf (path, sizeof(path), "%s/%s", f->path, f->dirent->d_name);
        if (lstat (path, &sb) < 0) {
            np_uerror (errno);
            goto done;
        }
        _ustat2qid (&sb, &qid);
    } else  {
        _dirent2qid (f->dirent, &qid);
    }
    ret = np_serialize_p9dirent(&qid, f->dirent->d_off, f->dirent->d_type,
                                      f->dirent->d_name, buf, buflen);
done:
    return ret;
}