Пример #1
0
/* Trename - rename a file, potentially to another directory
 */
Npfcall*
diod_rename (Npfid *fid, Npfid *dfid, Npstr *name)
{
    Npsrv *srv = fid->conn->srv;
    Fid *f = fid->aux;
    Fid *d = dfid->aux;
    Npfcall *ret;
    Path npath = NULL;
    int renamed = 0;

    if ((f->flags & DIOD_FID_FLAGS_ROFS)) {
        np_uerror (EROFS);
        goto error_quiet;
    }
    if (!(npath = path_append (srv, d->path, name))) {
        np_uerror (ENOMEM);
        goto error;
    }
    if (rename (path_s (f->path), path_s (npath)) < 0) {
        np_uerror (errno);
        goto error_quiet;
    }
    renamed = 1;
    if (!(ret = np_create_rrename ())) {
        np_uerror (ENOMEM);
        goto error;
    }
    path_decref (srv, f->path);
    f->path = npath;
    return ret;
error:
    errn (np_rerror (), "diod_rename %s@%s:%s to %s/%.*s",
          fid->user->uname, np_conn_get_client_id (fid->conn), path_s (f->path),
          path_s (d->path), name->len, name->str);
error_quiet:
    if (renamed && npath)
        (void)rename (path_s (npath), path_s (f->path));
    if (npath)
        path_decref (srv, npath);
    return NULL;
}
Пример #2
0
Npfcall*
diod_link (Npfid *dfid, Npfid *fid, Npstr *name)
{
    Fid *f = fid->aux;
    Npfcall *ret = NULL;
    Fid *df = dfid->aux;
    char *npath = NULL;
    int created = 0;

    if ((f->xflags & XFLAGS_RO)) {
        np_uerror (EROFS);
        goto error_quiet;
    }
    if (!(npath = _mkpath(df->path, name))) {
        np_uerror (ENOMEM);
        goto error;
    }
    if (link (f->path, npath) < 0) {
        np_uerror (errno);
        goto error_quiet;
    }
    created = 1;
    if (!((ret = np_create_rlink ()))) {
        np_uerror (ENOMEM);
        goto error;
    }
    free (npath);
    return ret;
error:
    errn (np_rerror (), "diod_link %s@%s:%s %s/%.*s",
          fid->user->uname, np_conn_get_client_id (fid->conn), f->path,
          df->path, name->len, name->str);
error_quiet:
    if (created && npath)
        (void)unlink (npath);
    if (npath)
        free (npath);
    if (ret)
        free (ret);
    return NULL;
}
Пример #3
0
Файл: ops.c Проект: eugmes/diod
/* Twalk - walk a file path
 * Called from fcall.c::np_walk () to clone the fid.
 * On error, call np_uerror () and return 0.
 */
int
diod_clone (Npfid *fid, Npfid *newfid)
{
    Fid *f = fid->aux;
    Fid *nf = NULL;

    if (!(nf = _fidalloc ()) || !(nf->path = strdup (f->path))) {
        np_uerror (ENOMEM);
        goto error;
    }
    nf->xflags = f->xflags;
    nf->mountpt = f->mountpt;
    newfid->aux = nf;
    return 1;
error:
    errn (np_rerror (), "diod_clone %s@%s:%s",
          fid->user->uname, np_conn_get_client_id (fid->conn), f->path);
    if (nf)
        _fidfree (nf);
    return 0;
}
Пример #4
0
/* 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;
}
Пример #5
0
/* 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;

    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 (_fidstat (f) < 0)
        goto error;
    _ustat2qid (&f->stat, &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
Npfcall*
diod_mknod(Npfid *fid, Npstr *name, u32 mode, u32 major, u32 minor, u32 gid)
{
    Npsrv *srv = fid->conn->srv;
    Npfcall *ret;
    Fid *f = fid->aux;
    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 (mknod (path_s (npath), mode, makedev (major, minor)) < 0
                                        || lstat (path_s (npath), &sb) < 0) {
        np_uerror (errno);
        goto error_quiet;
    }
    diod_ustat2qid (&sb, &qid);
    if (!((ret = np_create_rmknod (&qid)))) {
        (void)unlink (path_s (npath));
        np_uerror (ENOMEM);
        goto error;
    }
    path_decref (srv, npath);
    return ret;
error:
    errn (np_rerror (), "diod_mknod %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);
    return NULL;
}
Пример #7
0
Файл: ops.c Проект: eugmes/diod
/* Trename - rename a file, potentially to another directory
 */
Npfcall*
diod_rename (Npfid *fid, Npfid *dfid, Npstr *name)
{
    Fid *f = fid->aux;
    Fid *d = dfid->aux;
    Npfcall *ret;
    char *npath = NULL;
    int renamed = 0;

    if ((f->xflags & XFLAGS_RO)) {
        np_uerror (EROFS);
        goto error_quiet;
    }
    if (!(npath = _mkpath(d->path, name))) {
        np_uerror (ENOMEM);
        goto error;
    }
    if (rename (f->path, npath) < 0) {
        np_uerror (errno);
        goto error_quiet;
    }
    renamed = 1;
    if (!(ret = np_create_rrename ())) {
        np_uerror (ENOMEM);
        goto error;
    }
    free (f->path);
    f->path = npath;
    return ret;
error:
    errn (np_rerror (), "diod_rename %s@%s:%s to %s/%.*s",
          fid->user->uname, np_conn_get_client_id (fid->conn), f->path,
          d->path, name->len, name->str);
error_quiet:
    if (renamed && npath)
        (void)rename (npath, f->path);
    if (npath)
        free (npath);
    return NULL;
}
Пример #8
0
/* Tclunk - close a file.
 */
Npfcall*
diod_clunk (Npfid *fid)
{
    Fid *f = fid->aux;
    Npfcall *ret;

    if (f->ioctx) {
        if (ioctx_close (fid, 1) < 0)
            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),
          path_s (f->path));
error_quiet:
    return NULL;
}
Пример #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
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
Npfcall*
diod_readdir(Npfid *fid, u64 offset, u32 count, Npreq *req)
{
    int n;
    Fid *f = fid->aux;
    Npfcall *ret;

    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);
    return NULL;
}
Пример #12
0
Npfcall*
diod_link (Npfid *dfid, Npfid *fid, Npstr *name)
{
    Npsrv *srv = fid->conn->srv;
    Fid *f = fid->aux;
    Npfcall *ret;
    Fid *df = dfid->aux;
    Path npath = NULL;

    if ((f->flags & DIOD_FID_FLAGS_ROFS)) {
        np_uerror (EROFS);
        goto error_quiet;
    }
    if (!(npath = path_append (srv, df->path, name))) {
        np_uerror (ENOMEM);
        goto error;
    }
    if (link (path_s (f->path), path_s (npath)) < 0) {
        np_uerror (errno);
        goto error_quiet;
    }
    if (!((ret = np_create_rlink ()))) {
        (void)unlink (path_s (npath));
        np_uerror (ENOMEM);
        goto error;
    }
    path_decref (srv, npath);
    return ret;
error:
    errn (np_rerror (), "diod_link %s@%s:%s %s/%.*s",
          fid->user->uname, np_conn_get_client_id (fid->conn), path_s (f->path),
          path_s (df->path), name->len, name->str);
error_quiet:
    if (npath)
        path_decref (srv, npath);
    return NULL;
}
Пример #13
0
Файл: ops.c Проект: eugmes/diod
Npfcall*
diod_readlink(Npfid *fid)
{
    Fid *f = fid->aux;
    Npfcall *ret;
    char target[PATH_MAX + 1];
    int n;

    if ((n = readlink (f->path, target, sizeof(target) - 1)) < 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:
    return NULL;
}
Пример #14
0
int
main (int argc, char *argv[])
{
    Npcfsys *fs;
    Npcfid *afid, *root;
    uid_t uid = geteuid ();
    char *aname, *path, *attr, *value;
    int fd = 0; /* stdin */

    diod_log_init (argv[0]);

    if (argc < 3)
        usage ();
    aname = argv[1];
    path = argv[2];
    attr = argv[3];
    value = argv[4];

    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 (npc_setxattr (root, path, attr, NULL, 0, 0) < 0)
        errn_exit (np_rerror (), "npc_setxattr");

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

    exit (0);
}
Пример #15
0
Файл: ops.c Проект: 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;
}
Пример #16
0
Файл: ops.c Проект: eugmes/diod
/* 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;
    struct stat sb;

    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 (fstat(f->fd, &sb) < 0) {
        np_uerror (errno);
        goto error_quiet;
    }
    switch (type) {
        case P9_LOCK_TYPE_UNLCK:
            if (flock (f->fd, LOCK_UN) >= 0) {
                status = P9_LOCK_SUCCESS;
                f->lock_type = LOCK_UN;
            } else
                status = P9_LOCK_ERROR;
            break;
        case P9_LOCK_TYPE_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 P9_LOCK_TYPE_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:
    return NULL;
}
Пример #17
0
void
usage(char *tail)
{
	char *s, *t, c;
	int count, nflag = 0;
	switch(reason){
	case RESET:
		errs("Flag -");
		errc(badflag);
		errs(": set twice\n");
		break;
	case FEWARGS:
		errs("Flag -");
		errc(badflag);
		errs(": too few arguments\n");
		break;
	case FLAGSYN:
		errs("Bad argument to getflags!\n");
		break;
	case BADFLAG:
		errs("Illegal flag -");
		errc(badflag);
		errc('\n');
		break;
	}
	errs("Usage: ");
	errs(cmdname);
	for(s = flagarg;*s;){
		c=*s;
		if(*s++==' ')
			continue;
		if(*s==':'){
			s++;
			count = 0;
			while('0'<=*s && *s<='9') count = count*10+*s++-'0';
		}
		else count = 0;
		if(count==0){
			if(nflag==0)
				errs(" [-");
			nflag++;
			errc(c);
		}
		if(*s=='['){
			s++;
			while(*s!=']' && *s!='\0') s++;
			if(*s==']')
				s++;
		}
	}
	if(nflag)
		errs("]");
	for(s = flagarg;*s;){
		c=*s;
		if(*s++==' ')
			continue;
		if(*s==':'){
			s++;
			count = 0;
			while('0'<=*s && *s<='9') count = count*10+*s++-'0';
		}
		else count = 0;
		if(count!=0){
			errs(" [-");
			errc(c);
			if(*s=='['){
				s++;
				t = s;
				while(*s!=']' && *s!='\0') s++;
				errs(" ");
				errn(t, s-t);
				if(*s==']')
					s++;
			}
			else
				while(count--) errs(" arg");
			errs("]");
		}
		else if(*s=='['){
			s++;
			while(*s!=']' && *s!='\0') s++;
			if(*s==']')
				s++;
		}
	}
	if(tail){
		errs(" ");
		errs(tail);
	}
	errs("\n");
	Exit("bad flags");
}
Пример #18
0
Файл: ops.c Проект: eugmes/diod
Npfcall*
diod_setattr (Npfid *fid, u32 valid, u32 mode, u32 uid, u32 gid, u64 size,
              u64 atime_sec, u64 atime_nsec, u64 mtime_sec, u64 mtime_nsec)
{
    Npfcall *ret;
    Fid *f = fid->aux;
    int ctime_updated = 0;

    if ((f->xflags & XFLAGS_RO)) {
        np_uerror (EROFS);
        goto error_quiet;
    }
    if ((valid & P9_SETATTR_MODE)) { /* N.B. derefs symlinks */
        if (chmod (f->path, mode) < 0) {
            np_uerror(errno);
            goto error_quiet;
        }
        ctime_updated = 1;
    }
    if ((valid & P9_SETATTR_UID) || (valid & P9_SETATTR_GID)) {
        if (lchown (f->path, (valid & P9_SETATTR_UID) ? uid : -1,
                             (valid & P9_SETATTR_GID) ? gid : -1) < 0) {
            np_uerror(errno);
            goto error_quiet;
        }
        ctime_updated = 1;
    }
    if ((valid & P9_SETATTR_SIZE)) {
        if (truncate (f->path, size) < 0) {
            np_uerror(errno);
            goto error_quiet;
        }
        ctime_updated = 1;
    }
    if ((valid & P9_SETATTR_ATIME) || (valid & P9_SETATTR_MTIME)) {
#if HAVE_UTIMENSAT
        struct timespec ts[2];

        if (!(valid & P9_SETATTR_ATIME)) {
            ts[0].tv_sec = 0;
            ts[0].tv_nsec = UTIME_OMIT;
        } else if (!(valid & P9_SETATTR_ATIME_SET)) {
            ts[0].tv_sec = 0;
            ts[0].tv_nsec = UTIME_NOW;
        } else {
            ts[0].tv_sec = atime_sec;
            ts[0].tv_nsec = atime_nsec;
        }
        if (!(valid & P9_SETATTR_MTIME)) {
            ts[1].tv_sec = 0;
            ts[1].tv_nsec = UTIME_OMIT;
        } else if (!(valid & P9_SETATTR_MTIME_SET)) {
            ts[1].tv_sec = 0;
            ts[1].tv_nsec = UTIME_NOW;
        } else {
            ts[1].tv_sec = mtime_sec;
            ts[1].tv_nsec = mtime_nsec;
        }
        if (utimensat(-1, f->path, ts, AT_SYMLINK_NOFOLLOW) < 0) {
            np_uerror(errno);
            goto error_quiet;
        }
#else /* HAVE_UTIMENSAT */
        struct timeval tv[2], now, *tvp;
        struct stat sb;
        if ((valid & P9_SETATTR_ATIME) && !(valid & P9_SETATTR_ATIME_SET)
         && (valid & P9_SETATTR_MTIME) && !(valid & P9_SETATTR_MTIME_SET)) {
            tvp = NULL; /* set both to now */
        } else {
            if (lstat(f->path, &sb) < 0) {
                np_uerror (errno);
                goto error_quiet;
            }
            if (gettimeofday (&now, NULL) < 0) {
                np_uerror (errno);
                goto error_quiet;
            }
            if (!(valid & P9_SETATTR_ATIME)) {
                tv[0].tv_sec = sb.st_atim.tv_sec;
                tv[0].tv_usec = sb.st_atim.tv_nsec / 1000;
            } else if (!(valid & P9_SETATTR_ATIME_SET)) {
                tv[0].tv_sec = now.tv_sec;
                tv[0].tv_usec = now.tv_usec;
            } else {
                tv[0].tv_sec = atime_sec;
                tv[0].tv_usec = atime_nsec / 1000;
            }

            if (!(valid & P9_SETATTR_MTIME)) {
                tv[1].tv_sec = sb.st_mtim.tv_sec;
                tv[1].tv_usec = sb.st_mtim.tv_nsec / 1000;
            } else if (!(valid & P9_SETATTR_MTIME_SET)) {
                tv[1].tv_sec = now.tv_sec;
                tv[1].tv_usec = now.tv_usec;
            } else {
                tv[1].tv_sec = mtime_sec;
                tv[1].tv_usec = mtime_nsec / 1000;
            }
            tvp = tv;
        }
        if (utimes (f->path, tvp) < 0) {
            np_uerror(errno);
            goto error_quiet;
        }
#endif /* HAVE_UTIMENSAT */
        ctime_updated = 1;
    }
    if ((valid & P9_SETATTR_CTIME) && !ctime_updated) {
        if (lchown (f->path, -1, -1) < 0) {
            np_uerror (errno);
            goto error_quiet;
        }
    }
    if (!(ret = np_create_rsetattr())) {
        np_uerror (ENOMEM);
        goto error;
    }
    return ret;
error:
    errn (np_rerror (), "diod_setattr %s@%s:%s (valid=0x%x)",
          fid->user->uname, np_conn_get_client_id (fid->conn), f->path, valid);
error_quiet:
    return NULL;
}
Пример #19
0
Npfcall*
diod_setattr (Npfid *fid, u32 valid, u32 mode, u32 uid, u32 gid, u64 size,
              u64 atime_sec, u64 atime_nsec, u64 mtime_sec, u64 mtime_nsec)
{
    Npfcall *ret = NULL;
    Fid *f = fid->aux;
    int fidstat_updated = 0;
    int ctime_updated = 0;

    if ((f->xflags & XFLAGS_RO)) {
        np_uerror (EROFS);
        goto error_quiet;
    }

    if ((valid & P9_SETATTR_MODE) || (valid & P9_SETATTR_SIZE)) {
        if (_fidstat(f) < 0)
            goto error_quiet;
        fidstat_updated = 1;
        if (S_ISLNK(f->stat.st_mode)) {
            msg ("diod_setattr: unhandled mode/size update on symlink");
            np_uerror(EINVAL);
            goto error;
        }
    }

    /* chmod (N.B. dereferences symlinks) */
    if ((valid & P9_SETATTR_MODE)) {
        if (chmod (f->path, mode) < 0) {
            np_uerror(errno);
            goto error_quiet;
        }
        ctime_updated = 1;
    }

    /* chown */
    if ((valid & P9_SETATTR_UID) || (valid & P9_SETATTR_GID)) {
        if (lchown (f->path, (valid & P9_SETATTR_UID) ? uid : -1,
                             (valid & P9_SETATTR_GID) ? gid : -1) < 0) {
            np_uerror(errno);
            goto error_quiet;
        }
        ctime_updated = 1;
    }

    /* truncate (N.B. dereferences symlinks) */
    if ((valid & P9_SETATTR_SIZE)) {
        if (truncate (f->path, size) < 0) {
            np_uerror(errno);
            goto error_quiet;
        }
        ctime_updated = 1;
    }

    /* utimes */
    if ((valid & P9_SETATTR_ATIME) || (valid & P9_SETATTR_MTIME)) {
#if HAVE_UTIMENSAT
        struct timespec ts[2];

        if (!(valid & P9_SETATTR_ATIME)) {
            ts[0].tv_sec = 0;
            ts[0].tv_nsec = UTIME_OMIT;
        } else if (!(valid & P9_SETATTR_ATIME_SET)) {
            ts[0].tv_sec = 0;
            ts[0].tv_nsec = UTIME_NOW;
        } else {
            ts[0].tv_sec = atime_sec;
            ts[0].tv_nsec = atime_nsec;
        }

        if (!(valid & P9_SETATTR_MTIME)) {
            ts[1].tv_sec = 0;
            ts[1].tv_nsec = UTIME_OMIT;
        } else if (!(valid & P9_SETATTR_MTIME_SET)) {
            ts[1].tv_sec = 0;
            ts[1].tv_nsec = UTIME_NOW;
        } else {
            ts[1].tv_sec = mtime_sec;
            ts[1].tv_nsec = mtime_nsec;
        }

        if (utimensat(-1, f->path, ts, AT_SYMLINK_NOFOLLOW) < 0) {
            np_uerror(errno);
            goto error_quiet;
        }
        ctime_updated = 1;
#else /* HAVE_UTIMENSAT */
        struct timeval tv[2], now, *tvp;
        /* N.B. this utimes () implementation loses atomicity and precision.
         */
        if ((valid & P9_SETATTR_ATIME) && !(valid & P9_SETATTR_ATIME_SET)
         && (valid & P9_SETATTR_MTIME) && !(valid & P9_SETATTR_MTIME_SET)) {
            tvp = NULL; /* set both to now */
        } else {
            if (!fidstat_updated && _fidstat(f) < 0)
                goto error_quiet;
            fidstat_updated = 1;
            if (gettimeofday (&now, NULL) < 0) {
                np_uerror (errno);
                goto error_quiet;
            }
            if (!(valid & P9_SETATTR_ATIME)) {
                tv[0].tv_sec = f->stat.st_atim.tv_sec;
                tv[0].tv_usec = f->stat.st_atim.tv_nsec / 1000;
            } else if (!(valid & P9_SETATTR_ATIME_SET)) {
                tv[0].tv_sec = now.tv_sec;
                tv[0].tv_usec = now.tv_usec;
            } else {
                tv[0].tv_sec = atime_sec;
                tv[0].tv_usec = atime_nsec / 1000;
            }

            if (!(valid & P9_SETATTR_MTIME)) {
                tv[1].tv_sec = f->stat.st_mtim.tv_sec;
                tv[1].tv_usec = f->stat.st_mtim.tv_nsec / 1000;
            } else if (!(valid & P9_SETATTR_MTIME_SET)) {
                tv[1].tv_sec = now.tv_sec;
                tv[1].tv_usec = now.tv_usec;
            } else {
                tv[1].tv_sec = mtime_sec;
                tv[1].tv_usec = mtime_nsec / 1000;
            }
            tvp = tv;
        }
        if (utimes (f->path, tvp) < 0) {
            np_uerror(errno);
            goto error_quiet;
        }
        ctime_updated = 1;
#endif
    }
    if ((valid & P9_SETATTR_CTIME) && !ctime_updated) {
        if (lchown (f->path, -1, -1) < 0) {
            np_uerror (errno);
            goto error_quiet;
        }
    }
    if (!(ret = np_create_rsetattr())) {
        np_uerror (ENOMEM);
        goto error;
    }
    return ret;
error:
    errn (np_rerror (), "diod_setattr %s@%s:%s (valid=0x%x)",
          fid->user->uname, np_conn_get_client_id (fid->conn), f->path, valid);
error_quiet:
    if (ret)
        free (ret);
    return NULL;
}
Пример #20
0
static void *
loadgen (void *arg)
{
    thd_t *t = (thd_t *)arg;
    uid_t uid = geteuid ();
    void *ret = NULL;
    int n, loops = 0;

    if ((t->fd = diod_sock_connect (t->host, t->port, 0)) < 0)
        goto done;
    if (!(t->fs = npc_start (t->fd, t->fd, t->msize, 0))) {
        errn (np_rerror (), "error negotiating protocol with server");
        goto done;
    }
    if (!(t->afid = npc_auth (t->fs, "ctl", uid, diod_auth))
                                                && np_rerror () != 0) {
        errn (np_rerror (), "error authenticating to server");
        goto done;
    }
    if (!(t->root = npc_attach (t->fs, t->afid, "ctl", uid))) {
        errn (np_rerror (), "error attaching to aname=ctl");
        goto done;
    }
    if (t->loadtype == LOAD_IO) {
        if (!(t->infile = npc_open_bypath (t->root, "zero", O_RDONLY))) {
            errn (np_rerror (), "open zero");
            goto done;
        }
        if (!(t->outfile = npc_open_bypath (t->root, "null", O_WRONLY))) {
            errn (np_rerror (), "open null");
            goto done;
        }
        do {
            if ((n = npc_pread (t->infile, t->buf, t->msize, 0)) <= 0) {
                errn (np_rerror (), "read zero");
                break;
            }
            t->readbytes += n;
            if ((n = npc_pwrite (t->outfile, t->buf, t->msize, 0)) < 0) {
                errn (np_rerror (), "write null");
                break;
            }
            t->writebytes += n;
            t->opcount++;
            loops++;
        } while ((loops % 100 != 0) || time (NULL) < t->stoptime);
    } else if (t->loadtype == LOAD_GETATTR) {
        if (!(t->infile = npc_walk (t->root, "null"))) {
            errn (np_rerror (), "walk null");
            goto done;
        }
        do {
            struct stat sb;

            if (npc_fstat (t->infile, &sb) < 0) {
                errn (np_rerror (), "walk null");
                break;
            }
            t->opcount++;
            loops++;
        } while ((loops % 100 != 0) || time (NULL) < t->stoptime);
    }
done:
    if (t->outfile && npc_clunk (t->outfile) < 0)
        errn (np_rerror (), "error clunking null");
    if (t->infile && npc_clunk (t->infile) < 0)
        errn (np_rerror (), "error clunking zero");
    if (t->root && npc_clunk (t->root) < 0)
        errn (np_rerror (), "error clunking ctl");
    if (t->afid && npc_clunk (t->afid) < 0)
        errn (np_rerror (), "error clunking afid");
    if (t->fs) {
        npc_finish (t->fs); /* closes fd */
        t->fd = -1;
    }
    if (t->fd != -1)
        close (t->fd);
    return ret;
}
Пример #21
0
Файл: dioddate.c Проект: 8l/diod
int
main (int argc, char *argv[])
{
    char *aname = "ctl";
    char *server = NULL;
    int msize = 65536;
    uid_t uid = geteuid ();
    int topt = 0;
    int Sopt = 0;
    int flags = 0;
    int fd, c;
    Npcfsys *fs = NULL;
    Npcfid *afid = NULL, *root = NULL;
    char *buf = NULL;
    struct timeval tv;
    struct timezone tz;

    diod_log_init (argv[0]);

    opterr = 0;
    while ((c = GETOPT (argc, argv, OPTIONS, longopts)) != -1) {
        switch (c) {
            case 's':   /* --server HOST[:PORT] or /path/to/socket */
                server = optarg;
                break;
            case 'm':   /* --msize SIZE */
                msize = strtoul (optarg, NULL, 10);
                break;
            case 'u':   /* --uid UID */
                uid = strtoul (optarg, NULL, 10);
                break;
            case 't':   /* --timeout SECS */
                topt = strtoul (optarg, NULL, 10);
                break;
            case 'S':   /* --set-time */
                Sopt = 1;
                break;
            default:
                usage ();
        }
    }

    if (signal (SIGPIPE, SIG_IGN) == SIG_ERR)
        err_exit ("signal");
    if (signal (SIGALRM, sigalarm) == SIG_ERR)
        err_exit ("signal");

    if (topt > 0)
        alarm (topt);

    if ((fd = diod_sock_connect (server, flags)) < 0)
        exit (1);

    if (!(fs = npc_start (fd, fd, msize, 0))) {
        errn (np_rerror (), "error negotiating protocol with server");
        goto done;
    }
    if (!(afid = npc_auth (fs, aname, uid, diod_auth)) && np_rerror () != 0) {
        errn (np_rerror (), "error authenticating to server");
        goto done;
    }
    if (!(root = npc_attach (fs, afid, aname, uid))) {
        errn (np_rerror (), "error attaching to aname='%s'", aname);
        goto done;
    }
    buf = npc_aget (root, "date");
    if (!buf) {
        errn (np_rerror (), "error reading date");
        goto done;
    }
    if (sscanf (buf, "%lu.%lu %d.%d", &tv.tv_sec, &tv.tv_usec,
                                    &tz.tz_minuteswest, &tz.tz_dsttime) != 4) {
        msg ("error scanning returned date: %s", buf);
        goto done;
    }
    if (Sopt) {
        if (settimeofday (&tv, &tz) < 0)
            err_exit ("settimeofday");
    } else {
        time_t t = tv.tv_sec;
        printf ("%s", ctime (&t));
    }
done:
    if (buf)
        free (buf);
    if (root && npc_clunk (root) < 0)
        errn_exit (np_rerror (), "error clunking %s", aname);
    if (afid && npc_clunk (afid) < 0)
        errn_exit (np_rerror (), "error clunking afid");
    if (fs)
        npc_finish (fs);
    close (fd);

    diod_log_fini ();

    exit (0);
}
Пример #22
0
void test_mt (int argc, char **argv)
{
    thd_t *thd;
    int i, rc;
    flux_t h;
    int errors = 0;

    if (argc != 3) {
        fprintf (stderr, "Usage: mt nthreads changes key\n");
        exit (1);
    }
    nthreads = strtoul (argv[0], NULL, 10);
    changes = strtoul (argv[1], NULL, 10);
    key = argv[2];

    thd = xzmalloc (sizeof (*thd) * nthreads);

    if (!(h = flux_open (NULL, 0)))
        err_exit ("flux_open");

    /* Set initial value of 'key' to -1 */
    if (kvs_put_int (h, key, -1) < 0)
        err_exit ("kvs_put_int %s", key);
    key_stable = xasprintf ("%s-stable", key);
    if (kvs_put_int (h, key_stable, 0) < 0)
        err_exit ("kvs_put_int %s", key);

    if (kvs_commit (h) < 0)
        err_exit ("kvs_commit");

    for (i = 0; i < nthreads; i++) {
        thd[i].n = i;
        thd[i].last_val = -42;
        if ((rc = pthread_attr_init (&thd[i].attr)))
            errn (rc, "pthread_attr_init");
        if ((rc = pthread_create (&thd[i].tid, &thd[i].attr, thread, &thd[i])))
            errn (rc, "pthread_create");
    }
    wait_ready ();

    for (i = 0; i < changes; i++) {
        if (kvs_put_int (h, key, i) < 0)
            err_exit ("kvs_put_int %s", key);
        if (kvs_commit (h) < 0)
            err_exit ("kvs_commit");
    }

    /* Verify that callbacks were called the correct number of times.
     * The nil and stable callbacks will be called exactly once before the
     * reactor is started, then should never be called again.
     * Due to commit merging on the master, the changing callback may
     * miss intervening values but it shouldn't be called extra times.
     */
    for (i = 0; i < nthreads; i++) {
        if ((rc = pthread_join (thd[i].tid, NULL)))
            errn (rc, "pthread_join");
        if (thd[i].nil_count != 1) {
            msg ("%d: nil callback called %d times (expected one)",
                 i, thd[i].nil_count);
            errors++;
        }
        if (thd[i].stable_count != 1) {
            msg ("%d: stable callback called %d times (expected one)",
                 i, thd[i].stable_count);
            errors++;
        }
        if (thd[i].change_count > changes + 1) {
            msg ("%d: changing callback called %d times (expected <= %d)",
                 i, thd[i].change_count, changes + 1);
            errors++;
        }
    }
    if (errors > 0)
        exit (1);

    free (thd);
    free (key_stable);

    flux_close (h);
}