예제 #1
0
static int handle_mkdir(struct fuse* fuse, struct fuse_handler* handler,
        const struct fuse_in_header* hdr, const struct fuse_mkdir_in* req, const char* name)
{
    struct node* parent_node;
    char parent_path[PATH_MAX];
    char child_path[PATH_MAX];
    const char* actual_name;

    pthread_mutex_lock(&fuse->lock);
    parent_node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid,
            parent_path, sizeof(parent_path));
    TRACE("[%d] MKDIR %s 0%o @ %llx (%s)\n", handler->token,
            name, req->mode, hdr->nodeid, parent_node ? parent_node->name : "?");
    pthread_mutex_unlock(&fuse->lock);

    if (!parent_node || !(actual_name = find_file_within(parent_path, name,
            child_path, sizeof(child_path), 1))) {
        return -ENOENT;
    }
    __u32 mode = (req->mode & (~0777)) | 0775;
    if (mkdir(child_path, mode) < 0) {
        return -errno;
    }
    return fuse_reply_entry(fuse, hdr->unique, parent_node, name, actual_name, child_path);
}
예제 #2
0
static int zfsfuse_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
{
	if(strlen(name) >= MAXNAMELEN)
		return ENAMETOOLONG;

	vfs_t *vfs = (vfs_t *) fuse_req_userdata(req);
	zfsvfs_t *zfsvfs = vfs->vfs_data;

	ZFS_ENTER(zfsvfs);

	znode_t *znode;

	int error = zfs_zget(zfsvfs, parent, &znode, B_TRUE);
	if(error) {
		ZFS_EXIT(zfsvfs);
		/* If the inode we are trying to get was recently deleted
		   dnode_hold_impl will return EEXIST instead of ENOENT */
		return error == EEXIST ? ENOENT : error;
	}

	ASSERT(znode != NULL);
	vnode_t *dvp = ZTOV(znode);
	ASSERT(dvp != NULL);

	vnode_t *vp = NULL;

	cred_t cred;
	zfsfuse_getcred(req, &cred);

	error = VOP_LOOKUP(dvp, (char *) name, &vp, NULL, 0, NULL, &cred, NULL, NULL, NULL);
	if(error)
		goto out;

	struct fuse_entry_param e = { 0 };

	e.attr_timeout = 0.0;
	e.entry_timeout = 0.0;

	if(vp == NULL)
		goto out;

	e.ino = VTOZ(vp)->z_id;
	if(e.ino == 3)
		e.ino = 1;

	e.generation = VTOZ(vp)->z_phys->zp_gen;

	error = zfsfuse_stat(vp, &e.attr, &cred);

out:
	if(vp != NULL)
		VN_RELE(vp);
	VN_RELE(dvp);
	ZFS_EXIT(zfsvfs);

	if(!error)
		fuse_reply_entry(req, &e);

	return error;
}
예제 #3
0
static void serve_mknod(fuse_req_t req, fuse_ino_t parent,
                        const char * local_name, mode_t mode, dev_t rdev)
{
	Dprintf("%s(parent = %lu, local_name = \"%s\")\n", __FUNCTION__, parent, local_name);
	fdesc_t * fdesc;
	int r;
	struct fuse_entry_param e;

	if (!(mode & S_IFREG))
	{
		r = fuse_reply_err(req, ENOSYS);
		fuse_reply_assert(!r);
		return;
	}

	r = create(req, parent, local_name, mode, &e, &fdesc);
	if (r < 0)
	{
		r = fuse_reply_err(req, -r);
		assert(r);
		return;
	}

	r = CALL(reqcfs(req), close, fdesc);
	assert(r >= 0);

	r = fuse_reply_entry(req, &e);
	fuse_reply_assert(!r);
}
예제 #4
0
static void serve_link(fuse_req_t req, fuse_ino_t fuse_ino,
                       fuse_ino_t new_parent, const char * new_local_name)
{
	Dprintf("%s(ino = %lu, newp = %lu, newln = \"%s\")\n",
	        __FUNCTION__, fuse_ino, new_parent, new_local_name);
	inode_t cfs_ino = fusecfsino(req, fuse_ino);
	inode_t new_cfs_parent = fusecfsino(req, new_parent);
	struct fuse_entry_param e;
	int r;

	r = CALL(reqcfs(req), link, cfs_ino, new_cfs_parent, new_local_name);
	if (r < 0)
	{
		r = fuse_reply_err(req, -r);
		fuse_reply_assert(!r);
		return;
	}

	r = init_fuse_entry(reqmount(req), new_cfs_parent, cfs_ino, fuse_ino, &e);
	if (r < 0)
	{
		(void) CALL(reqmount(req)->cfs, unlink, new_cfs_parent, new_local_name);
		r = fuse_reply_err(req, -r);
		fuse_reply_assert(!r);
		return;
	}

	r = fuse_reply_entry(req, &e);
	fuse_reply_assert(!r);
}
예제 #5
0
static void serve_mkdir(fuse_req_t req, fuse_ino_t parent,
                        const char * local_name, mode_t mode)
{
	Dprintf("%s(parent = %lu, local_name = \"%s\")\n", __FUNCTION__, parent, local_name);
	inode_t cfs_ino;
	inode_t parent_cfs_ino = fusecfsino(req, parent);
	fuse_metadata_t fusemd = { .ctx = fuse_req_ctx(req), .mode = mode, .type = TYPE_DIR };
	metadata_set_t initialmd = { .get = fuse_get_metadata, .arg = &fusemd };
	int r;
	struct fuse_entry_param e;

	r = CALL(reqcfs(req), mkdir, parent_cfs_ino, local_name, &initialmd, &cfs_ino);
	if (r < 0)
	{
		r = fuse_reply_err(req, -r);
		fuse_reply_assert(!r);
		return;
	}

	r = init_fuse_entry(reqmount(req), parent_cfs_ino, cfs_ino, cfsfuseino(req, cfs_ino), &e);
	if (r < 0)
	{
		r = fuse_reply_err(req, -r);
		fuse_reply_assert(!r);
		return;
	}

	r = fuse_reply_entry(req, &e);
	fuse_reply_assert(!r);
}
예제 #6
0
static void serve_lookup(fuse_req_t req, fuse_ino_t parent, const char *local_name)
{
	Dprintf("%s(parent_ino = %lu, local_name = \"%s\")\n", __FUNCTION__, parent, local_name);
	inode_t parent_cfs_ino;
	int r;
	inode_t cfs_ino;
	struct fuse_entry_param e;

	parent_cfs_ino = fusecfsino(req, parent);
	assert(parent_cfs_ino != INODE_NONE);

	r = CALL(reqcfs(req), lookup, parent_cfs_ino, local_name, &cfs_ino);
	if (r < 0)
	{
		r = fuse_reply_err(req, -r);
		fuse_reply_assert(!r);
		return;
	}

	r = init_fuse_entry(reqmount(req), parent_cfs_ino, cfs_ino, cfsfuseino(req, cfs_ino), &e);
	if (r < 0)
	{
		// TODO: is it safe to remove cfs_ino from the parents map if fill_stat() failed?
		fprintf(stderr, "%s(): possible parents entry leak for cfs inode %u\n", __FUNCTION__, cfs_ino);

		r = fuse_reply_err(req, -r);
		fuse_reply_assert(!r);
		return;
	}

	r = fuse_reply_entry(req, &e);
	fuse_reply_assert(!r);
}
예제 #7
0
파일: jediwave.c 프로젝트: trevd/playground
static int handle_lookup(struct fuse* fuse, struct fuse_handler* handler,
        const struct fuse_in_header *hdr, const char* name)
{
    struct node* parent_node;
    char parent_path[PATH_MAX];
    char child_path[PATH_MAX];
    const char* actual_name;
    pthread_mutex_lock(&fuse->lock);
    parent_node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid,
            parent_path, sizeof(parent_path));
            
    TRACE("[%d] LOOKUP %s @ %llx (%s) hdr->uid=%d hdr->pid=%d\n", handler->token, name, hdr->nodeid,
        parent_node ? parent_node->name : "?",hdr->uid,hdr->pid);
    pthread_mutex_unlock(&fuse->lock);
    char prop[PROPERTY_VALUE_MAX];
    property_get("not.the.droid",prop,NULL);
    TRACE("not.the.droid %s\n",prop);
    if(prop != NULL){
        uint propval = atoi(prop);
        if ( hdr->uid == propval ) {
            TRACE("doing the jedi wave - these are not the droids you're looking for!\n %ud",propval);
            // Reject all calls
            return -ENOENT;
        }
    }

    if (!parent_node || !(actual_name = find_file_within(parent_path, name,
            child_path, sizeof(child_path), 1))) {
        return -ENOENT;
    }
    return fuse_reply_entry(fuse, hdr->unique, parent_node, name, actual_name, child_path);
}
예제 #8
0
static void lo_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
{
	struct fuse_entry_param e;
	int err;

	err = lo_do_lookup(req, parent, name, &e);
	if (err)
		fuse_reply_err(req, err);
	else
		fuse_reply_entry(req, &e);
}
예제 #9
0
파일: fuse_lfs.c 프로젝트: Theophilus/ffs
static void lfs_ll_lookup(fuse_req_t req, fuse_ino_t parent, const char *name){
  struct fuse_entry_param e;
  if (parent != 1 || strcmp(name, hello_name) != 0)
    fuse_reply_err(req, ENOENT);
  else {
    memset(&e, 0, sizeof(e));
    e.ino = 2;
    e.attr_timeout = 1.0;
    e.entry_timeout = 1.0;
    lfs_stat(e.ino, &e.attr);
    fuse_reply_entry(req, &e);
  }
}
예제 #10
0
파일: ll.c 프로젝트: ksperling/squashfuse
static void sqfs_ll_op_lookup(fuse_req_t req, fuse_ino_t parent,
		const char *name) {
	sqfs_ll_i lli;
	sqfs_err sqerr;
	sqfs_name namebuf;
	sqfs_dir_entry entry;
	bool found;
	sqfs_inode inode;
	
	if (sqfs_ll_iget(req, &lli, parent))
		return;
	
	if (!S_ISDIR(lli.inode.base.mode)) {
		fuse_reply_err(req, ENOTDIR);
		return;
	}
	
	sqfs_dentry_init(&entry, namebuf);
	sqerr = sqfs_dir_lookup(&lli.ll->fs, &lli.inode, name, strlen(name), &entry,
		&found);
	if (sqerr) {
		fuse_reply_err(req, EIO);
		return;
	}
	if (!found) {
		fuse_reply_err(req, ENOENT);
		return;
	}
	
	if (sqfs_inode_get(&lli.ll->fs, &inode, sqfs_dentry_inode(&entry))) {
		fuse_reply_err(req, ENOENT);
	} else {
		struct fuse_entry_param fentry;
		memset(&fentry, 0, sizeof(fentry));
		if (sqfs_stat(&lli.ll->fs, &inode, &fentry.attr)) {
			fuse_reply_err(req, EIO);
		} else {
			fentry.attr_timeout = fentry.entry_timeout = SQFS_TIMEOUT;
			fentry.ino = lli.ll->ino_register(lli.ll, &entry);
			fentry.attr.st_ino = fentry.ino;
			fuse_reply_entry(req, &fentry);
		}
	}
}
예제 #11
0
static void serve_symlink(fuse_req_t req, const char * link, fuse_ino_t parent,
                          const char * local_name)
{
	Dprintf("%s(parent = %lu, local_name = \"%s\", link = \"%s\")\n", __FUNCTION__, parent, local_name, link);
	CFS_t * cfs = reqcfs(req);
	inode_t cfs_parent = fusecfsino(req, parent);
	int mode = S_IFLNK | (S_IRWXU | S_IRWXG | S_IRWXO);
	fuse_metadata_t fusemd = { .ctx = fuse_req_ctx(req), .mode = mode, .type = TYPE_SYMLINK, .type_info.symlink = { .link = link, .link_len = strlen(link) } };
	metadata_set_t initialmd = { .get = fuse_get_metadata, .arg = &fusemd };
	inode_t cfs_ino;
	fdesc_t * fdesc;
	int r;
	struct fuse_entry_param e;

	if (!feature_supported(cfs, FSTITCH_FEATURE_SYMLINK))
	{
		r = -ENOSYS;
		goto error;
	}

	r = CALL(cfs, create, cfs_parent, local_name, 0, &initialmd, &fdesc, &cfs_ino);
	if (r < 0)
		goto error;
	assert(cfs_ino != INODE_NONE);
	fdesc->common->parent = cfs_parent;
	r = CALL(cfs, close, fdesc);
	assert(r >= 0);
	fdesc = NULL;

	r = init_fuse_entry(reqmount(req), cfs_parent, cfs_ino, cfsfuseino(req, cfs_ino), &e);
	if (r < 0)
	{
		(void) CALL(reqmount(req)->cfs, unlink, parent, local_name);
		goto error;
	}

	r = fuse_reply_entry(req, &e);
	fuse_reply_assert(!r);
	return;

  error:
	r = fuse_reply_err(req, -r);
	fuse_reply_assert(!r);
}
예제 #12
0
void blob_ll_lookup(fuse_req_t req, fuse_ino_t parent, const char *name) {
    struct fuse_entry_param e;

    boost::uint32_t id = ino_id(parent), ver = 0;

    DBG("lookup name = " << name);
    if ((parent == 1 && sscanf(name, "blob-%d", &id) != 1) ||
	(ino_id(parent) != 0 && ino_version(parent) == 0 && 
	 sscanf(name, "version-%d", &ver) != 1) ||
	(ino_id(parent) != 0 && ino_version(parent) != 0))
	fuse_reply_err(req, ENOENT);
    else {
	memset(&e, 0, sizeof(e));
	e.ino = build_ino(id, ver);
	e.attr_timeout = 1.0;
	e.entry_timeout = 1.0;
	blob_stat(e.ino, &e.attr);
	fuse_reply_entry(req, &e);
    }
}
예제 #13
0
static int handle_lookup(struct fuse* fuse, struct fuse_handler* handler,
        const struct fuse_in_header *hdr, const char* name)
{
    struct node* parent_node;
    char parent_path[PATH_MAX];
    char child_path[PATH_MAX];
    const char* actual_name;

    pthread_mutex_lock(&fuse->lock);
    parent_node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid,
            parent_path, sizeof(parent_path));
    TRACE("[%d] LOOKUP %s @ %llx (%s)\n", handler->token, name, hdr->nodeid,
        parent_node ? parent_node->name : "?");
    pthread_mutex_unlock(&fuse->lock);

    if (!parent_node || !(actual_name = find_file_within(parent_path, name,
            child_path, sizeof(child_path), 1))) {
        return -ENOENT;
    }
    return fuse_reply_entry(fuse, hdr->unique, parent_node, name, actual_name, child_path);
}
예제 #14
0
void hsx_fuse_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,
	       	mode_t mode)
{	
	int err = 0;
	struct hsfs_inode *hi_parent = NULL;
	struct hsfs_inode *new = NULL;
	struct fuse_entry_param e;
	struct hsfs_super *sb = NULL;
	const char *dirname = name;
	DEBUG_IN("ino:%lu.\n", parent);

	memset(&e, 0, sizeof(struct fuse_entry_param));

	sb = fuse_req_userdata(req);
	hi_parent = hsx_fuse_iget(sb, parent);
	
	if(NULL == sb) {
		ERR("ERR in fuse_req_userdata");
		goto out;
	}
	if(NULL == hi_parent) {
		ERR("ERR in hsx_fuse_iget");
		goto out;
	}

	
	err = hsi_nfs3_mkdir(hi_parent, &new, dirname, mode);
	if(0 != err ) {
		fuse_reply_err(req, err);
		goto out;
	}else {
		hsx_fuse_fill_reply(new, &e);
		fuse_reply_entry(req, &e);
		goto out;
	}
out:
	DEBUG_OUT(" out errno is: %d\n", err);
	return;
};
예제 #15
0
파일: fuse.c 프로젝트: zmike/compiz
static void
compiz_lookup(fuse_req_t req,
              fuse_ino_t parent,
              const char *name)
{
   CompDisplay *d = (CompDisplay *)fuse_req_userdata(req);
   FuseInode *inode;
   struct fuse_entry_param e;

   inode = fuseFindInode(inodes, parent, DIR_MASK);
   if (!inode)
     {
        fuse_reply_err(req, ENOENT);
        return;
     }

   if (!inode->child || !(inode->type & CONST_DIR_MASK))
     fuseUpdateInode(d, inode);

   inode = fuseLookupChild(inode, name);
   if (!inode)
     {
        fuse_reply_err(req, ENOENT);
        return;
     }

   memset(&e, 0, sizeof (e));

   e.attr_timeout = 1.0;
   e.entry_timeout = 1.0;
   e.ino = inode->ino;

   fuseInodeStat(d, inode, &e.attr);

   fuse_reply_entry(req, &e);
}
예제 #16
0
void mfs_meta_lookup(fuse_req_t req, fuse_ino_t parent, const char *name) {
	struct fuse_entry_param e;
	uint32_t inode;
//	const struct fuse_ctx *ctx;
//	ctx = fuse_req_ctx(req);
	memset(&e, 0, sizeof(e));
	inode = 0;
	switch (parent) {
	case META_ROOT_INODE:
		if (strcmp(name,".")==0 || strcmp(name,"..")==0) {
			inode = META_ROOT_INODE;
		} else if (strcmp(name,META_TRASH_NAME)==0) {
			inode = META_TRASH_INODE;
		} else if (strcmp(name,META_RESERVED_NAME)==0) {
			inode = META_RESERVED_INODE;
//		} else if (strcmp(name,MASTER_NAME)==0) {
//			memset(&e, 0, sizeof(e));
//			e.ino = MASTER_INODE;
//			e.attr_timeout = 3600.0;
//			e.entry_timeout = 3600.0;
//			mfs_attr_to_stat(MASTER_INODE,masterattr,&e.attr);
//			fuse_reply_entry(req, &e);
//			return ;
		} else if (strcmp(name,MASTERINFO_NAME)==0) {
			memset(&e, 0, sizeof(e));
			e.ino = MASTERINFO_INODE;
			e.attr_timeout = 3600.0;
			e.entry_timeout = 3600.0;
			mfs_attr_to_stat(MASTERINFO_INODE,masterinfoattr,&e.attr);
			fuse_reply_entry(req, &e);
			return ;
		}
		break;
	case META_TRASH_INODE:
		if (strcmp(name,".")==0) {
			inode = META_TRASH_INODE;
		} else if (strcmp(name,"..")==0) {
			inode = META_ROOT_INODE;
		} else if (strcmp(name,META_UNDEL_NAME)==0) {
			inode = META_UNDEL_INODE;
		} else {
			inode = mfs_meta_name_to_inode(name);
			if (inode>0) {
				int status;
				uint8_t attr[35];
				status = fs_getdetachedattr(inode,attr);
				status = mfs_errorconv(status);
				if (status!=0) {
					fuse_reply_err(req, status);
				} else {
					e.ino = inode | INODE_TYPE_TRASH;
					e.attr_timeout = attr_cache_timeout;
					e.entry_timeout = entry_cache_timeout;
					mfs_attr_to_stat(inode  | INODE_TYPE_TRASH,attr,&e.attr);
					fuse_reply_entry(req,&e);
				}
				return;
			}
		}
		break;
	case META_UNDEL_INODE:
		if (strcmp(name,".")==0) {
			inode = META_UNDEL_INODE;
		} else if (strcmp(name,"..")==0) {
			inode = META_TRASH_INODE;
		}
		break;
	case META_RESERVED_INODE:
		if (strcmp(name,".")==0) {
			inode = META_RESERVED_INODE;
		} else if (strcmp(name,"..")==0) {
			inode = META_ROOT_INODE;
		} else {
			inode = mfs_meta_name_to_inode(name);
			if (inode>0) {
				int status;
				uint8_t attr[35];
				status = fs_getdetachedattr(inode,attr);
				status = mfs_errorconv(status);
				if (status!=0) {
					fuse_reply_err(req, status);
				} else {
					e.ino = inode | INODE_TYPE_RESERVED;
					e.attr_timeout = attr_cache_timeout;
					e.entry_timeout = entry_cache_timeout;
					mfs_attr_to_stat(inode  | INODE_TYPE_RESERVED,attr,&e.attr);
					fuse_reply_entry(req,&e);
				}
				return;
			}
		}
		break;
	}
	if (inode==0) {
		fuse_reply_err(req,ENOENT);
	} else {
		e.ino = inode;
		e.attr_timeout = attr_cache_timeout;
		e.entry_timeout = entry_cache_timeout;
		mfs_meta_stat(inode,&e.attr);
		fuse_reply_entry(req,&e);
	}
}
예제 #17
0
static void overlay_mknod(fuse_req_t req, struct inode_struct *pinode, struct name_struct *xname, struct call_info_struct *call_info, mode_t mode, dev_t rdev)
{
    struct resource_struct *resource=call_info->object->resource;
    struct localfile_struct *localfile=(struct localfile_struct *) resource->data;
    struct pathinfo_struct *pathinfo=&call_info->pathinfo;
    unsigned int len0=pathinfo->len - call_info->relpath, len1=localfile->pathinfo.len;
    char path[len0 + len1 + 1];
    struct entry_struct *entry=NULL, *parent=pinode->alias;
    struct inode_struct *inode;


    memcpy(path, localfile->pathinfo.path, len1);

    if (len0>0) {

	memcpy(path+len1, pathinfo->path + call_info->relpath, len0);
	len1+=len0;

    }

    path[len1]='\0';

    entry=create_entry(parent, xname);
    inode=create_inode();

    if (entry && inode) {
	struct entry_struct *result=NULL;
	unsigned int error=0;

	entry->inode=inode;
	inode->alias=entry;

	result=insert_entry(entry, &error, _ENTRY_FLAG_TEMP);

	if (result==entry) {
	    uid_t uid_keep=setfsuid(call_info->uid);
	    gid_t gid_keep=setfsgid(call_info->gid);
	    mode_t umask_keep=umask(call_info->umask);

	    mode = (mode & ~call_info->umask);

	    if (mknod(path, mode, rdev)==0) {
    		struct fuse_entry_param e;

		adjust_pathmax(call_info->pathinfo.len);
		add_inode_hashtable(inode, increase_inodes_workspace, (void *) call_info->workspace_mount);

		/* here complete the insert ?? */

		inode->mode=mode;

		inode->nlink=1;
		inode->uid=call_info->uid;
		inode->gid=call_info->gid;
		inode->nlookup=1;

		inode->rdev=rdev;
		inode->size=0;

		get_current_time(&inode->mtim);
		memcpy(&inode->ctim, &inode->mtim, sizeof(struct timespec));

		memset(&e, 0, sizeof(e));

		e.ino = inode->ino;
		e.generation = 1;

		e.attr.st_ino = e.ino;
		e.attr.st_mode = inode->mode;
		e.attr.st_nlink = inode->nlink;
		e.attr.st_dev = 0;
		e.attr.st_uid=inode->uid;
		e.attr.st_gid=inode->gid;
		e.attr.st_size=inode->size;
		e.attr.st_rdev=inode->rdev;

		memcpy(&e.attr.st_mtim, &inode->mtim, sizeof(struct timespec));
		memcpy(&e.attr.st_ctim, &inode->mtim, sizeof(struct timespec));
		memcpy(&e.attr.st_atim, &inode->mtim, sizeof(struct timespec));

		e.attr_timeout = fs_options.attr_timeout;
		e.entry_timeout = fs_options.entry_timeout;

		e.attr.st_blksize=4096;
		e.attr.st_blocks=0;

    		fuse_reply_entry(req, &e);

	    } else {
		unsigned int error_delete=0;

		error=errno;

		remove_entry(entry, &error_delete);

		destroy_entry(entry);
		entry=NULL;

		free(inode);
		inode=NULL;

		fuse_reply_err(req, error);

	    }

	    uid_keep=setfsuid(uid_keep);
	    gid_keep=setfsgid(gid_keep);
	    umask_keep=umask(umask_keep);

	} else {

	    destroy_entry(entry);
	    entry=NULL;

	    free(inode);
	    inode=NULL;

	    if (error==0) error=EEXIST;

	    fuse_reply_err(req, error);

	}

    } else {

	if (entry) {

	    destroy_entry(entry);
	    entry=NULL;

	}

	if (inode) {

	    free(inode);
	    inode=NULL;

	}

	fuse_reply_err(req, ENOMEM);

    }

}
예제 #18
0
static void overlay_lookup_noncached(fuse_req_t req, struct inode_struct *pinode, struct name_struct *xname, struct call_info_struct *call_info)
{
    struct resource_struct *resource=call_info->object->resource;
    struct localfile_struct *localfile=(struct localfile_struct *) resource->data;
    struct pathinfo_struct *pathinfo=&call_info->pathinfo;
    unsigned int len0=pathinfo->len - call_info->relpath, len1=localfile->pathinfo.len;
    char path[len0 + len1 + 1];
    struct stat st;

    memcpy(path, localfile->pathinfo.path, len1);

    if (len0>0) {

	memcpy(path+len1, pathinfo->path + call_info->relpath, len0);
	len1+=len0;

    }

    path[len1]='\0';

    memset(&st, 0, sizeof(struct stat));

    logoutput("overlayfs_lookup_cached, path %s", path);

    if (lstat(path, &st)==-1) {

	fuse_reply_err(req, ENOENT);

    } else {
	struct entry_struct *entry=NULL, *parent=pinode->alias;
	struct inode_struct *inode;

	entry=create_entry(parent, xname);
	inode=create_inode();

	if (entry && inode) {
	    struct fuse_entry_param e;
	    unsigned int error=0;

	    add_inode_hashtable(inode, increase_inodes_workspace, (void *) call_info->workspace_mount);
	    insert_entry(entry, &error, 0);

	    adjust_pathmax(call_info->pathinfo.len);

	    e.ino = inode->ino;
	    e.generation = 1;
	    e.attr_timeout = fs_options.attr_timeout;
	    e.entry_timeout = fs_options.entry_timeout;

	    e.attr.st_ino = e.ino;
	    e.attr.st_mode = st.st_mode;
	    e.attr.st_nlink = st.st_nlink;
	    e.attr.st_uid = st.st_uid;
	    e.attr.st_gid = st.st_gid;
	    e.attr.st_rdev = st.st_rdev;
	    e.attr.st_atim.tv_sec = st.st_atim.tv_sec;
	    e.attr.st_atim.tv_nsec = st.st_atim.tv_nsec;
	    e.attr.st_mtim.tv_sec = st.st_mtim.tv_sec;
	    e.attr.st_mtim.tv_nsec = st.st_mtim.tv_nsec;
	    e.attr.st_ctim.tv_sec = st.st_ctim.tv_sec;
	    e.attr.st_ctim.tv_nsec = st.st_ctim.tv_nsec;

	    e.attr.st_blksize=4096;
	    e.attr.st_blocks=0;

	    inode->mode=st.st_mode;
	    inode->nlink=st.st_nlink;
	    inode->uid=st.st_uid;
	    inode->gid=st.st_gid;

	    inode->rdev=st.st_rdev;

	    if (S_ISDIR(st.st_mode)) {

		e.attr.st_size = 0;

	    } else {

		inode->size=st.st_size;
		e.attr.st_size = st.st_size;

	    }

	    inode->mtim.tv_sec=st.st_mtim.tv_sec;
	    inode->mtim.tv_nsec=st.st_mtim.tv_nsec;

	    inode->ctim.tv_sec=st.st_ctim.tv_sec;
	    inode->ctim.tv_nsec=st.st_ctim.tv_nsec;

	    fuse_reply_entry(req, &e);

	} else {

	    /* not enough memory to allocate entry and/or inode */

	    if (entry) {

		destroy_entry(entry);
		entry=NULL;

	    }

	    if (inode) {

		free(inode);
		inode=NULL;

	    }

	    fuse_reply_err(req, ENOMEM);

	}

    }

    free_path_pathinfo(&call_info->pathinfo);

}
예제 #19
0
static void overlay_lookup_cached(fuse_req_t req, struct entry_struct *entry, struct call_info_struct *call_info)
{
    struct resource_struct *resource=call_info->object->resource;
    struct localfile_struct *localfile=(struct localfile_struct *) resource->data;
    struct pathinfo_struct *pathinfo=&call_info->pathinfo;
    unsigned int len0=pathinfo->len - call_info->relpath, len1=localfile->pathinfo.len;
    char path[len0 + len1 + 1];
    struct stat st;

    memcpy(path, localfile->pathinfo.path, len1);

    if (len0>0) {

	memcpy(path+len1, pathinfo->path + call_info->relpath, len0);
	len1+=len0;

    }

    path[len1]='\0';

    memset(&st, 0, sizeof(struct stat));

    logoutput("overlayfs_lookup_cached, path %s", path);

    if (lstat(path, &st)==-1) {
	struct inode_struct *inode=entry->inode;
	unsigned int error=0;

	inode=entry->inode;
	inode->alias=NULL;

	remove_entry(entry, &error);
	queue_remove(call_info->object, entry, &error);
	entry=NULL;

	fuse_reply_err(req, ENOENT);

    } else {
	struct fuse_entry_param e;
	struct inode_struct *inode=entry->inode;

	e.ino = inode->ino;
	e.generation = 1;
	e.attr_timeout = fs_options.attr_timeout;
	e.entry_timeout = fs_options.entry_timeout;

	e.attr.st_ino = e.ino;
	e.attr.st_mode = st.st_mode;
	e.attr.st_nlink = st.st_nlink;
	e.attr.st_uid = st.st_uid;
	e.attr.st_gid = st.st_gid;
	e.attr.st_rdev = st.st_rdev;
	e.attr.st_atim.tv_sec = st.st_atim.tv_sec;
	e.attr.st_atim.tv_nsec = st.st_atim.tv_nsec;
	e.attr.st_mtim.tv_sec = st.st_mtim.tv_sec;
	e.attr.st_mtim.tv_nsec = st.st_mtim.tv_nsec;
	e.attr.st_ctim.tv_sec = st.st_ctim.tv_sec;
	e.attr.st_ctim.tv_nsec = st.st_ctim.tv_nsec;

	e.attr.st_blksize=4096;
	e.attr.st_blocks=0;

	inode->mode=st.st_mode;
	inode->nlink=st.st_nlink;
	inode->uid=st.st_uid;
	inode->gid=st.st_gid;

	inode->rdev=st.st_rdev;

	if (S_ISDIR(st.st_mode)) {

	    e.attr.st_size = 0;

	} else {

	    inode->size=st.st_size;
	    e.attr.st_size = st.st_size;

	}

	inode->mtim.tv_sec=st.st_mtim.tv_sec;
	inode->mtim.tv_nsec=st.st_mtim.tv_nsec;

	inode->ctim.tv_sec=st.st_ctim.tv_sec;
	inode->ctim.tv_nsec=st.st_ctim.tv_nsec;

	fuse_reply_entry(req, &e);

    }

    free_path_pathinfo(&call_info->pathinfo);

}
예제 #20
0
static void workspace_nfs_lookup_cached(fuse_req_t req, struct entry_struct *entry, struct call_info_struct *call_info)
{
    struct resource_struct *resource=call_info->object->resource;
    struct net_nfs_export_struct *nfs_export=(struct net_nfs_export_struct *) resource->data;
    struct nfs_context *nfs_ctx=(struct nfs_context *) nfs_export->data;
    char *path=call_info->pathinfo.path + call_info->relpath;
    struct stat st;
    int result=0;

    memset(&st, 0, sizeof(struct stat));

    if (strlen(path)==0) path=(char *) rootpath;

    logoutput("workspace_nfs_lookup_cached, path %s", path);

    pthread_mutex_lock(&nfs_export->mutex);

    result=nfs_stat(nfs_ctx, path, &st);

    pthread_mutex_unlock(&nfs_export->mutex);

    if (result<0) {

	result=abs(result);

	if (result==ENOENT) {
	    struct inode_struct *inode=entry->inode;
	    unsigned int error=0;

	    inode=entry->inode;
	    inode->alias=NULL;

	    remove_entry(entry, &error);
	    queue_remove(call_info->object, entry, &error);
	    entry=NULL;

	}

	fuse_reply_err(req, result);

    } else {
	struct fuse_entry_param e;
	struct inode_struct *inode=entry->inode;

	inode->mode=st.st_mode;
	inode->nlink=st.st_nlink;
	inode->uid=st.st_uid;
	inode->gid=st.st_gid;

	inode->rdev=st.st_rdev;

	inode->mtim.tv_sec=st.st_mtim.tv_sec;
	inode->mtim.tv_nsec=st.st_mtim.tv_nsec;

	inode->ctim.tv_sec=st.st_ctim.tv_sec;
	inode->ctim.tv_nsec=st.st_ctim.tv_nsec;

	inode->size=st.st_size;

	e.ino = inode->ino;
	e.generation = 1;
	e.attr_timeout = fs_options.attr_timeout;
	e.entry_timeout = fs_options.entry_timeout;

	get_current_time(&entry->synctime);

	e.attr.st_dev = 0;
	e.attr.st_ino = e.ino;
	e.attr.st_mode = st.st_mode;
	e.attr.st_nlink = st.st_nlink;
	e.attr.st_uid = st.st_uid;
	e.attr.st_gid = st.st_gid;
	e.attr.st_rdev = st.st_rdev;
	e.attr.st_size = st.st_size;
	e.attr.st_atim.tv_sec = st.st_atim.tv_sec;
	e.attr.st_atim.tv_nsec = st.st_atim.tv_nsec;
	e.attr.st_mtim.tv_sec = st.st_mtim.tv_sec;
	e.attr.st_mtim.tv_nsec = st.st_mtim.tv_nsec;
	e.attr.st_ctim.tv_sec = st.st_ctim.tv_sec;
	e.attr.st_ctim.tv_nsec = st.st_ctim.tv_nsec;

	e.attr.st_blksize=_DEFAULT_BLOCKSIZE;

	if (inode->size % e.attr.st_blksize == 0) {

	    e.attr.st_blocks = inode->size / e.attr.st_blksize;

	} else {

	    e.attr.st_blocks = 1 + inode->size / e.attr.st_blksize;

	}

	fuse_reply_entry(req, &e);

    }

    free_path_pathinfo(&call_info->pathinfo);

}
예제 #21
0
static void workspace_nfs_mknod(fuse_req_t req, struct inode_struct *pinode, struct name_struct *xname, struct call_info_struct *call_info, mode_t mode, dev_t rdev)
{
    struct resource_struct *resource=call_info->object->resource;
    struct net_nfs_export_struct *nfs_export=(struct net_nfs_export_struct *) resource->data;
    struct nfs_context *nfs_ctx=(struct nfs_context *) nfs_export->data;
    char *path=call_info->pathinfo.path + call_info->relpath;
    struct entry_struct *entry=NULL, *parent=pinode->alias;
    struct inode_struct *inode;

    logoutput("workspace_nfs_mknod, path %s", path);

    entry=create_entry(parent, xname);
    inode=create_inode();

    if (entry && inode) {
	int result=0;

	inode->alias=entry;
	entry->inode=inode;

        pthread_mutex_lock(&nfs_export->mutex);

	result=nfs_mknod(nfs_ctx, path, mode, rdev);

	pthread_mutex_unlock(&nfs_export->mutex);

	if (result==0) {
	    struct fuse_entry_param e;
	    unsigned int error=0;
	    struct stat st;

	    memset(&st, 0, sizeof(struct stat));

	    add_inode_hashtable(inode, increase_inodes_workspace, (void *) call_info->object->workspace_mount);
	    insert_entry(entry, &error, 0);

	    adjust_pathmax(call_info->pathinfo.len);

	    pthread_mutex_lock(&nfs_export->mutex);

	    nfs_chmod(nfs_ctx, path, mode);
	    nfs_stat(nfs_ctx, path, &st);

	    pthread_mutex_unlock(&nfs_export->mutex);

	    inode->nlookup=1;
	    inode->mode=st.st_mode;
	    inode->nlink=st.st_nlink;
	    inode->uid=st.st_uid;
	    inode->gid=st.st_gid;

	    inode->rdev=st.st_rdev;
	    inode->size=st.st_size;

	    inode->mtim.tv_sec=st.st_mtim.tv_sec;
	    inode->mtim.tv_nsec=st.st_mtim.tv_nsec;

	    inode->ctim.tv_sec=st.st_ctim.tv_sec;
	    inode->ctim.tv_nsec=st.st_ctim.tv_nsec;

	    e.ino = inode->ino;
	    e.generation = 1;
	    e.attr_timeout = fs_options.attr_timeout;
	    e.entry_timeout = fs_options.entry_timeout;

	    e.attr.st_ino = e.ino;
	    e.attr.st_mode = st.st_mode;
	    e.attr.st_nlink = st.st_nlink;
	    e.attr.st_uid = st.st_uid;
	    e.attr.st_gid = st.st_gid;
	    e.attr.st_rdev = st.st_rdev;
	    e.attr.st_atim.tv_sec = st.st_atim.tv_sec;
	    e.attr.st_atim.tv_nsec = st.st_atim.tv_nsec;
	    e.attr.st_mtim.tv_sec = st.st_mtim.tv_sec;
	    e.attr.st_mtim.tv_nsec = st.st_mtim.tv_nsec;
	    e.attr.st_ctim.tv_sec = st.st_ctim.tv_sec;
	    e.attr.st_ctim.tv_nsec = st.st_ctim.tv_nsec;

	    e.attr.st_blksize=_DEFAULT_BLOCKSIZE;

	    if (inode->size % e.attr.st_blksize == 0) {

		e.attr.st_blocks=inode->size / e.attr.st_blksize;

	    } else {

		e.attr.st_blocks=1 + inode->size / e.attr.st_blksize;

	    }

	    fuse_reply_entry(req, &e);

	} else {

	    /* error nfs create */

	    destroy_entry(entry);
	    free(inode);

	    fuse_reply_err(req, abs(result));

	}

    } else {

	/* not enough memory to allocate entry and/or inode */

	if (entry) {

	    destroy_entry(entry);
	    entry=NULL;

	}

	if (inode) {

	    free(inode);
	    inode=NULL;

	}

	fuse_reply_err(req, ENOMEM);

    }

    free_path_pathinfo(&call_info->pathinfo);

}
예제 #22
0
static int zfsfuse_mknod(fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode, dev_t rdev)
{
	if(strlen(name) >= MAXNAMELEN)
		return ENAMETOOLONG;

	vfs_t *vfs = (vfs_t *) fuse_req_userdata(req);
	zfsvfs_t *zfsvfs = vfs->vfs_data;

	ZFS_ENTER(zfsvfs);

	znode_t *znode;

	int error = zfs_zget(zfsvfs, parent, &znode, B_FALSE);
	if(error) {
		ZFS_EXIT(zfsvfs);
		/* If the inode we are trying to get was recently deleted
		   dnode_hold_impl will return EEXIST instead of ENOENT */
		return error == EEXIST ? ENOENT : error;
	}

	ASSERT(znode != NULL);
	vnode_t *dvp = ZTOV(znode);
	ASSERT(dvp != NULL);

	cred_t cred;
	zfsfuse_getcred(req, &cred);

	vattr_t vattr;
	vattr.va_type = IFTOVT(mode);
	vattr.va_mode = mode & PERMMASK;
	vattr.va_mask = AT_TYPE | AT_MODE;

	if(mode & (S_IFCHR | S_IFBLK)) {
		vattr.va_rdev = rdev;
		vattr.va_mask |= AT_RDEV;
	}

	vnode_t *vp = NULL;

	/* FIXME: check filesystem boundaries */
	error = VOP_CREATE(dvp, (char *) name, &vattr, EXCL, 0, &vp, &cred, 0, NULL, NULL);

	VN_RELE(dvp);

	if(error)
		goto out;

	ASSERT(vp != NULL);

	struct fuse_entry_param e = { 0 };

	e.attr_timeout = 0.0;
	e.entry_timeout = 0.0;

	e.ino = VTOZ(vp)->z_id;
	if(e.ino == 3)
		e.ino = 1;

	e.generation = VTOZ(vp)->z_phys->zp_gen;

	error = zfsfuse_stat(vp, &e.attr, &cred);

out:
	if(vp != NULL)
		VN_RELE(vp);
	ZFS_EXIT(zfsvfs);

	if(!error)
		fuse_reply_entry(req, &e);

	return error;
}