示例#1
1
文件: read.c 项目: mt-inside/fsfuse
/* This, and hence fuse_reply, are called on a different thread to the one the
 * request came in on. This doesn't seem to matter. */
static void chunk_done (void *read_ctxt, int rc, size_t size)
{
    read_context_t *ctxt = (read_context_t *)read_ctxt;


    if (size != ctxt->size)
    {
        read_trace("bytes read != request size => EOF / error\n");
    }

    /* As a result of this read() operation we can say certain things
     * about the direntry. These professions can be made with confidence
     * because we've just performed an actual network transaction, so
     * our information is "live":
     * - If we actually read data from the file then it definitely still
     *   exists, now.
     * - If we tried to read from it and found it didn't exist, then it
     *   definitely doesn't exist any more.
     * - Any other error doesn't give enough info.
     */
    if (!rc)
    {
        direntry_still_exists(ctxt->de);
    }
    else if (rc == ENOENT)
    {
        direntry_no_longer_exists(ctxt->de);
    }


    if (!rc)
    {
        assert(!fuse_reply_buf(ctxt->req, ctxt->buf, size));
    }
    else
    {
        assert(!fuse_reply_err(ctxt->req, rc));
    }

    direntry_delete(CALLER_INFO ctxt->de);
    free(ctxt->buf);
    free(read_ctxt);
}
示例#2
0
static void serve_read(fuse_req_t req, fuse_ino_t fuse_ino, size_t size,
                       off_t off, struct fuse_file_info * fi)
{
	fdesc_t * fdesc = fi_get_fdesc(fi);
	uint32_t offset = off;
	char * buf;
	int r;
	Dprintf("%s(ino = %lu, fdesc = %p, size = %u, off = %lld)\n", __FUNCTION__, fuse_ino, fdesc, size, off);

	if (offset != off)
	{
		fprintf(stderr, "%s:%d: fstitchd offset not able to satisfy request for %lld\n", __FILE__, __LINE__, off);
		r = fuse_reply_err(req, EINVAL);
		fuse_reply_assert(!r);
		return;
	}

	buf = malloc(size);
	assert(buf);

	r = CALL(reqcfs(req), read, fdesc, NULL, buf, off, size);
	if (r <= 0)
	{
		// TODO: handle EOF?
		r = fuse_reply_buf(req, NULL, 0);
		fuse_reply_assert(!r);
		return;
	}

	r = fuse_reply_buf(req, buf, r);
	free(buf);
	assert(r >= 0);
	return;
}
示例#3
0
static int reply_buf_limited(fuse_req_t req, const char *buf, size_t bufsize,
                             off_t off, size_t maxsize)
{
    if (off < bufsize)
        return fuse_reply_buf(req, buf + off, min(bufsize - off, maxsize));
    else
        return fuse_reply_buf(req, NULL, 0);
}
示例#4
0
文件: ll.c 项目: ksperling/squashfuse
static void sqfs_ll_op_getxattr(fuse_req_t req, fuse_ino_t ino,
		const char *name, size_t size
#ifdef FUSE_XATTR_POSITION
		, uint32_t position
#endif
		) {
	sqfs_ll_i lli;
	char *buf = NULL;
	size_t real = size;

#ifdef FUSE_XATTR_POSITION
	if (position != 0) { /* We don't support resource forks */
		fuse_reply_err(req, EINVAL);
		return;
	}
#endif
	
	if (sqfs_ll_iget(req, &lli, ino))
		return;
	
	if (!(buf = malloc(size)))
		fuse_reply_err(req, ENOMEM);
	else if (sqfs_xattr_lookup(&lli.ll->fs, &lli.inode, name, buf, &real))
		fuse_reply_err(req, EIO);
	else if (real == 0)
		fuse_reply_err(req, sqfs_enoattr());
	else if (size == 0)
		fuse_reply_xattr(req, real);
	else if (size < real)
		fuse_reply_err(req, ERANGE);
	else
		fuse_reply_buf(req, buf, real);
	free(buf);
}
示例#5
0
static void overlay_readdirplus(fuse_req_t req, size_t size, off_t offset, struct workspace_dh_struct *dh)
{
    if (dh->mode & _WORKSPACE_READDIR_MODE_FINISH) {

	fuse_reply_buf(req, NULL, 0);

    } else {
	struct overlay_readdir_struct *overlay_readdir=(struct overlay_readdir_struct *)dh->handle.data;

	if (overlay_readdir->mode & _FW_READDIR_MODE_VIRTUAL) {

	    overlay_readdirplus_virtual(req, size, offset, dh);

	} else if (overlay_readdir->mode & _FW_READDIR_MODE_SIMPLE) {

	    overlay_readdirplus_simple(req, size, offset, dh);

	} else if (overlay_readdir->mode & _FW_READDIR_MODE_FULL) {

	    overlay_readdirplus_full(req, size, offset, dh);

	}

    }

}
示例#6
0
void hsx_fuse_readdir_plus(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
			   struct fuse_file_info *fi)
{
	struct hsfs_readdir_ctx *saved_ctx, *ctx = NULL;
	struct hsfs_inode *parent;
	struct hsfs_super *sb;
	size_t res, len = 0;
	char * buf;
	int err, count = 0;

	DEBUG_IN("P_I(%lu), Size(%lld), Off(0x%llx)", ino, size, off);

	(void)fi;
	sb = fuse_req_userdata(req);
	FUSE_ASSERT(sb != NULL);

	parent = hsfs_ilookup(sb, ino);
	FUSE_ASSERT(parent != NULL);

	err = hsi_nfs3_readdir_plus(parent, size, off, &ctx, size);
	if(err)
		goto out1;
	saved_ctx = ctx;

	buf = (char *) malloc(size);
	if( NULL == buf){
		err = ENOMEM;
		goto out2;
	}
	while(ctx != NULL){
		struct fuse_entry_param e;

		hsx_fuse_fill_reply(ctx->inode, &e);
		res = fuse_add_direntry_plus(req, buf + len, size - len, ctx->name,
					     &e, ctx->off);
	  	if(res > size - len)
			break;
		else if (res == size - len){
			ctx = ctx->next;
			break;
		}
		count++;
	       	hsx_fuse_ref_inc(ctx->inode, 1);
		len += res;
		ctx = ctx->next;
	}

	if (!err)
		fuse_reply_buf(req, buf, len);
	
	free(buf);
out2:
	__free_ctx(saved_ctx, 0);
out1:
	if(err)
		fuse_reply_err(req, err);

	DEBUG_OUT("with %d, %d entries returned", err, count);
	return;
}
示例#7
0
void blob_ll_read(fuse_req_t req, fuse_ino_t ino, size_t size,
		    off_t off, struct fuse_file_info *fi) {
    blob_mirror_t *lm = (blob_mirror_t *)fi->fh;
    char *buf;

    boost::uint64_t read_size = lm->read(size, off, buf);
    fuse_reply_buf(req, buf, read_size);
}
示例#8
0
static void serve_readdir(fuse_req_t req, fuse_ino_t fuse_ino, size_t size,
                          off_t foff, struct fuse_file_info * fi)
{
	fdesc_t * fdesc = fi_get_fdesc(fi);
	uint32_t off = foff;
	uint32_t total_size = 0;
	char * buf = NULL;
	int r;
	Dprintf("%s(ino = %lu, size = %u, off = %lld)\n", __FUNCTION__, fuse_ino, size, foff);

	while (1)
	{
		dirent_t dirent;
		int nbytes;
		struct stat stbuf;
		inode_t entry_cfs_ino;
		size_t oldsize = total_size;

		nbytes = CALL(reqcfs(req), get_dirent, fdesc, &dirent, sizeof(dirent), &off);
		if (nbytes == -1)
			break;
		else if (nbytes < 0)
		{
			fprintf(stderr, "%s:%s(): CALL(cfs, get_dirent, fdesc = %p, off = %d) = %d (%s)\n", __FILE__, __FUNCTION__, fdesc, off, nbytes, strerror(nbytes));
			assert(nbytes >= 0);
		}

		if (total_size + fuse_dirent_size(dirent.d_namelen) > size)
			break;
		Dprintf("%s: \"%s\"\n", __FUNCTION__, dirent.d_name);

		total_size += fuse_dirent_size(dirent.d_namelen);
		buf = (char *) realloc(buf, total_size);
		if (!buf)
			kpanic("realloc() failed");

		memset(&stbuf, 0, sizeof(stbuf));
		// Generate "." and ".." here rather than in the base file system
		// because they are not able to find ".."'s inode from just
		// "."'s inode
		if (!strcmp(dirent.d_name, "."))
			entry_cfs_ino = fusecfsino(req, fuse_ino);
		else if (!strcmp(dirent.d_name, ".."))
			entry_cfs_ino = fdesc->common->parent;
		else
		{
			r = CALL(reqcfs(req), lookup, fusecfsino(req, fuse_ino), dirent.d_name, &entry_cfs_ino);
			assert(r >= 0);
		}
		stbuf.st_ino = cfsfuseino(req, entry_cfs_ino);
		fuse_add_dirent(buf + oldsize, dirent.d_name, &stbuf, off);
	}

	r = fuse_reply_buf(req, buf, total_size);
	fuse_reply_assert(!r);
	free(buf);
}
示例#9
0
static void cusexmp_read(fuse_req_t req, size_t size, off_t off,
                         struct fuse_file_info *fi)
{
        (void)fi;
        if (off >= cusexmp_size)
                off = cusexmp_size;
        if (size > cusexmp_size - off)
                size = cusexmp_size - off;
        fuse_reply_buf(req, cusexmp_buf + off, size);
}
示例#10
0
void hsx_fuse_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
		      struct fuse_file_info *fi)
{
	struct hsfs_readdir_ctx *saved_ctx, *ctx = NULL;
	struct hsfs_inode *parent;
	struct hsfs_super *sb;
	size_t res, len = 0;
	char * buf;
	int err, count = 0;

	DEBUG_IN("P_I(%lu), Size(%lld), Off(0x%llx)", ino, size, off);

	(void)fi;
	sb = fuse_req_userdata(req);
	FUSE_ASSERT(sb != NULL);

	parent = hsfs_ilookup(sb, ino);
	FUSE_ASSERT(parent != NULL);

	err = hsi_nfs3_readdir(parent, size, off, &ctx);
	if(err)
		goto out1;
	saved_ctx = ctx;

	buf = (char *) malloc(size);
	if( NULL == buf){
		err = ENOMEM;
		goto out2;
	}
	while(ctx != NULL){
		res = fuse_add_direntry(req, buf + len, size - len, ctx->name,
					&ctx->stbuf, ctx->off);
		/* From fuse doc, buf is not copied if res larger than
		 * requested */
	  	if(res >= size - len)
			break;
		len += res;
		ctx = ctx->next;
		count++;
	}
	/* If EOF, we will return an empty buffer here. */
	if (!err)
		fuse_reply_buf(req, buf, len);
	
	free(buf);
out2:
	__free_ctx(saved_ctx, 0);
out1:
	if(err)
		fuse_reply_err(req, err);

	DEBUG_OUT("with %d, %d entries returned.", err, count);
}
示例#11
0
文件: ll.c 项目: ksperling/squashfuse
static void sqfs_ll_op_read(fuse_req_t req, fuse_ino_t ino,
		size_t size, off_t off, struct fuse_file_info *fi) {
	sqfs_ll *ll = fuse_req_userdata(req);
	sqfs_inode *inode = (sqfs_inode*)(intptr_t)fi->fh;
	sqfs_err err = SQFS_OK;
	
	off_t osize;
	char *buf = malloc(size);
	if (!buf) {
		fuse_reply_err(req, ENOMEM);
		return;
	}
	
	osize = size;
	err = sqfs_read_range(&ll->fs, inode, off, &osize, buf);
	if (err) {
		fuse_reply_err(req, EIO);
	} else if (osize == 0) { /* EOF */
		fuse_reply_buf(req, NULL, 0);
	} else {
		fuse_reply_buf(req, buf, osize);
	}
	free(buf);
}
示例#12
0
static int zfsfuse_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi)
{
	file_info_t *info = (file_info_t *)(uintptr_t) fi->fh;

	vnode_t *vp = info->vp;
	ASSERT(vp != NULL);
	ASSERT(VTOZ(vp) != NULL);
	ASSERT(VTOZ(vp)->z_id == ino);

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

	char *outbuf = kmem_alloc(size, KM_NOSLEEP);
	if(outbuf == NULL)
		return ENOMEM;

	ZFS_ENTER(zfsvfs);

	iovec_t iovec;
	uio_t uio;
	uio.uio_iov = &iovec;
	uio.uio_iovcnt = 1;
	uio.uio_segflg = UIO_SYSSPACE;
	uio.uio_fmode = 0;
	uio.uio_llimit = RLIM64_INFINITY;

	iovec.iov_base = outbuf;
	iovec.iov_len = size;
	uio.uio_resid = iovec.iov_len;
	uio.uio_loffset = off;

	cred_t cred;
	zfsfuse_getcred(req, &cred);

	int error = VOP_READ(vp, &uio, info->flags, &cred, NULL);

	ZFS_EXIT(zfsvfs);

	if(!error)
		fuse_reply_buf(req, outbuf, uio.uio_loffset - off);

	kmem_free(outbuf, size);

	return error;
}
示例#13
0
文件: ll.c 项目: ksperling/squashfuse
static void sqfs_ll_op_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
		off_t off, struct fuse_file_info *fi) {
	sqfs_err sqerr;
	sqfs_dir dir;
	sqfs_name namebuf;
	sqfs_dir_entry entry;
	size_t esize;
	struct stat st;
	
	char *buf = NULL, *bufpos = NULL;
	sqfs_ll_i *lli = (sqfs_ll_i*)(intptr_t)fi->fh;
	int err = 0;
	
	if (sqfs_dir_open(&lli->ll->fs, &lli->inode, &dir, off))
		err = EINVAL;
	if (!err && !(bufpos = buf = malloc(size)))
		err = ENOMEM;
	
	if (!err) {
		memset(&st, 0, sizeof(st));
		sqfs_dentry_init(&entry, namebuf);
		while (sqfs_dir_next(&lli->ll->fs, &dir, &entry, &sqerr)) {
			st.st_ino = lli->ll->ino_fuse_num(lli->ll, &entry);
			st.st_mode = sqfs_dentry_mode(&entry);
		
			esize = sqfs_ll_add_direntry(req, bufpos, size, sqfs_dentry_name(&entry),
				&st, sqfs_dentry_next_offset(&entry));
			if (esize > size)
				break;
		
			bufpos += esize;
			size -= esize;
		}
		if (sqerr)
			err = EIO;
	}
	
	if (err)
		fuse_reply_err(req, err);
	else
		fuse_reply_buf(req, buf, bufpos - buf);
	free(buf);
}
示例#14
0
/**
*  Read data from a file

  @param thread_ctx_p: pointer to the thread context
  @param msg         : address of the message received
  
  @retval: none
*/
static inline void rozofs_fuse_th_fuse_reply_buf(rozofs_fuse_thread_ctx_t *thread_ctx_p,rozofs_fuse_thread_msg_t * msg) {
  struct timeval     timeDay;
  unsigned long long timeBefore, timeAfter;
  char *buf_sharem = (char *)msg->payload;
      
  gettimeofday(&timeDay,(struct timezone *)0);  
  timeBefore = MICROLONG(timeDay);	          
  /*
  ** update statistics
  */
  thread_ctx_p->stat.write_count++;     
  thread_ctx_p->stat.write_Byte_count+=msg->size;     
  fuse_reply_buf(msg->req, (char *) buf_sharem, msg->size);

  rozofs_fuse_th_send_response(thread_ctx_p,msg,0);

  /*
  ** Update statistics
  */
  gettimeofday(&timeDay,(struct timezone *)0);  
  timeAfter = MICROLONG(timeDay);
  thread_ctx_p->stat.write_time +=(timeAfter-timeBefore);  
}
示例#15
0
static void workspace_nfs_read(fuse_req_t req, size_t size, off_t offset, struct workspace_fh_struct *fh)
{
    struct resource_struct *resource=fh->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;
    struct nfsfh *nfsfh=(struct nfsfh *) fh->handle.data;
    int result=0;
    char *buff;

    buff=malloc(size);

    if (! buff) {

	fuse_reply_err(req, ENOMEM);
	return;

    }

    logoutput("workspace_nfs_read");

    pthread_mutex_lock(&nfs_export->mutex);

    result=nfs_pread(nfs_ctx, nfsfh, offset, size, buff);

    pthread_mutex_unlock(&nfs_export->mutex);

    if (result>=0) {

	fuse_reply_buf(req, buff, result);

    } else {

	fuse_reply_err(req, abs(result));

    }

}
示例#16
0
文件: ll.c 项目: ksperling/squashfuse
static void sqfs_ll_op_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) {
	sqfs_ll_i lli;
	char *buf;
	int ferr;
	
	if (sqfs_ll_iget(req, &lli, ino))
		return;

	buf = NULL;
	if (size && !(buf = malloc(size))) {
		fuse_reply_err(req, ENOMEM);
		return;
	}
	
	ferr = sqfs_listxattr(&lli.ll->fs, &lli.inode, buf, &size);
	if (ferr) {
		fuse_reply_err(req, ferr);
	} else if (buf) {
		fuse_reply_buf(req, buf, size);
	} else {
		fuse_reply_xattr(req, size);
	}
	free(buf);
}
示例#17
0
void mfs_meta_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi) {
	pathbuf *pathinfo = (pathbuf *)((unsigned long)(fi->fh));
	if (ino==MASTERINFO_INODE) {
		uint8_t masterinfo[14];
		fs_getmasterlocation(masterinfo);
		masterproxy_getlocation(masterinfo);
#ifdef MASTERINFO_WITH_VERSION
		if (off>=14) {
			fuse_reply_buf(req,NULL,0);
		} else if (off+size>14) {
			fuse_reply_buf(req,(char*)(masterinfo+off),14-off);
#else
		if (off>=10) {
			fuse_reply_buf(req,NULL,0);
		} else if (off+size>10) {
			fuse_reply_buf(req,(char*)(masterinfo+off),10-off);
#endif
		} else {
			fuse_reply_buf(req,(char*)(masterinfo+off),size);
		}
		return;
	}
	if (pathinfo==NULL) {
		fuse_reply_err(req,EBADF);
		return;
	}
//	if (ino==MASTER_INODE) {
//		minfo *masterinfo = (minfo*)(unsigned long)(fi->fh);
//		if (masterinfo->sent) {
//			int rsize;
//			uint8_t *buff;
//			buff = malloc(size);
//			rsize = fs_direct_read(masterinfo->sd,buff,size);
//			fuse_reply_buf(req,(char*)buff,rsize);
			//syslog(LOG_WARNING,"master received: %d/%u",rsize,size);
//			free(buff);
//		} else {
//			syslog(LOG_WARNING,"master: read before write");
//			fuse_reply_buf(req,NULL,0);
//		}
//		return;
//	}
	pthread_mutex_lock(&(pathinfo->lock));
	if (off<0) {
		pthread_mutex_unlock(&(pathinfo->lock));
		fuse_reply_err(req,EINVAL);
		return;
	}
	if ((size_t)off>pathinfo->size) {
		fuse_reply_buf(req, NULL, 0);
	} else if (off + size > pathinfo->size) {
		fuse_reply_buf(req, (pathinfo->p)+off,(pathinfo->size)-off);
	} else {
		fuse_reply_buf(req, (pathinfo->p)+off,size);
	}
	pthread_mutex_unlock(&(pathinfo->lock));
}

void mfs_meta_write(fuse_req_t req, fuse_ino_t ino, const char *buf, size_t size, off_t off, struct fuse_file_info *fi) {
	pathbuf *pathinfo = (pathbuf *)((unsigned long)(fi->fh));
	if (ino==MASTERINFO_INODE) {
		fuse_reply_err(req,EACCES);
		return;
	}
	if (pathinfo==NULL) {
		fuse_reply_err(req,EBADF);
		return;
	}
//	if (ino==MASTER_INODE) {
//		minfo *masterinfo = (minfo*)(unsigned long)(fi->fh);
//		int wsize;
//		masterinfo->sent=1;
//		wsize = fs_direct_write(masterinfo->sd,(const uint8_t*)buf,size);
		//syslog(LOG_WARNING,"master sent: %d/%u",wsize,size);
//		fuse_reply_write(req,wsize);
//		return;
//	}
	if (off + size > PATH_SIZE_LIMIT) {
		fuse_reply_err(req,EINVAL);
		return;
	}
	pthread_mutex_lock(&(pathinfo->lock));
	if (pathinfo->changed==0) {
		pathinfo->size = 0;
	}
	if (off+size > pathinfo->size) {
		size_t s = pathinfo->size;
		pathinfo->p = realloc(pathinfo->p,off+size);
		pathinfo->size = off+size;
		memset(pathinfo->p+s,0,off+size-s);
	}
	memcpy((pathinfo->p)+off,buf,size);
	pathinfo->changed = 1;
	pthread_mutex_unlock(&(pathinfo->lock));
	fuse_reply_write(req,size);
}
示例#18
0
void mfs_meta_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi) {
        dirbuf *dirinfo = (dirbuf *)((unsigned long)(fi->fh));
	char buffer[READDIR_BUFFSIZE];
	char *name,c;
	const uint8_t *ptr,*eptr;
	uint8_t end;
	size_t opos,oleng;
	uint8_t nleng;
	uint32_t inode;
	uint8_t type;
	struct stat stbuf;

	if (off<0) {
		fuse_reply_err(req,EINVAL);
		return;
	}
	pthread_mutex_lock(&(dirinfo->lock));
	if (dirinfo->wasread==0 || (dirinfo->wasread==1 && off==0)) {
		if (dirinfo->p!=NULL) {
			free(dirinfo->p);
		}
		dirbuf_meta_fill(dirinfo,ino);
//		syslog(LOG_WARNING,"inode: %lu , dirinfo->p: %p , dirinfo->size: %lu",(unsigned long)ino,dirinfo->p,(unsigned long)dirinfo->size);
	}
	dirinfo->wasread=1;

	if (off>=(off_t)(dirinfo->size)) {
		fuse_reply_buf(req, NULL, 0);
	} else {
		if (size>READDIR_BUFFSIZE) {
			size=READDIR_BUFFSIZE;
		}
		ptr = (const uint8_t*)(dirinfo->p)+off;
		eptr = (const uint8_t*)(dirinfo->p)+dirinfo->size;
		opos = 0;
		end = 0;

		while (ptr<eptr && end==0) {
			nleng = ptr[0];
			ptr++;
			name = (char*)ptr;
			ptr+=nleng;
			off+=nleng+6;
			if (ptr+5<=eptr) {
				inode = get32bit(&ptr);
				type = get8bit(&ptr);
				mfs_meta_type_to_stat(inode,type,&stbuf);
				c = name[nleng];
				name[nleng]=0;
				oleng = fuse_add_direntry(req, buffer + opos, size - opos, name, &stbuf, off);
				name[nleng] = c;
				if (opos+oleng>size) {
					end=1;
				} else {
					opos+=oleng;
				}
			}
		}
		fuse_reply_buf(req,buffer,opos);
	}
	pthread_mutex_unlock(&(dirinfo->lock));
}
示例#19
0
static void overlay_readdirplus_full(fuse_req_t req, size_t size, off_t offset, struct workspace_dh_struct *dh)
{
    unsigned int error=0;
    char *buff=NULL;
    size_t pos=0;
    size_t dirent_size;
    struct fuse_entry_param e;
    char *name=NULL;
    struct directory_struct *directory=dh->directory;
    struct overlay_readdir_struct *overlay_readdir=(struct overlay_readdir_struct *)dh->handle.data;
    struct entry_struct *entry, *result;
    struct inode_struct *inode;
    unsigned char dtype;
    struct name_struct xname={NULL, 0, 0};
    int res=0;

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

    e.generation = 1;
    e.attr_timeout = fs_options.attr_timeout;
    e.entry_timeout = fs_options.entry_timeout;

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

    buff=malloc(size);

    if (! buff) {

	error=ENOMEM;
	goto error;

    }

    if (lock_directory(directory, _DIRECTORY_LOCK_EXCL)==-1) {

	free(buff);
	buff=NULL;
	error=EAGAIN;
	goto error;

    }

    while (pos<size) {

    	if (offset==0) {

	    inode=dh->parent->inode;

    	    /* the . entry */

	    e.ino = inode->ino;

	    e.attr.st_ino = e.ino;
	    e.attr.st_mode = inode->mode;
	    e.attr.st_nlink = inode->nlink;
	    e.attr.st_uid = inode->uid;
	    e.attr.st_gid = inode->gid;
	    e.attr.st_rdev = inode->rdev;
	    e.attr.st_size = 0;
	    e.attr.st_atim.tv_sec = 0;
	    e.attr.st_atim.tv_nsec = 0;
	    e.attr.st_mtim.tv_sec = inode->mtim.tv_sec;
	    e.attr.st_mtim.tv_nsec = inode->mtim.tv_nsec;
	    e.attr.st_ctim.tv_sec = inode->ctim.tv_sec;
	    e.attr.st_ctim.tv_nsec = inode->ctim.tv_nsec;

	    name = (char *) dotname;

	    inode->nlookup++;

    	} else if (offset==1) {

    	    /* the .. entry */

	    if ( ! dh->parent->parent ) {

		inode=dh->parent->inode;

	    } else {

		inode=dh->parent->parent->inode;

	    }

	    e.ino = inode->ino;

	    e.attr.st_ino = e.ino;
	    e.attr.st_mode = inode->mode;
	    e.attr.st_nlink = inode->nlink;
	    e.attr.st_uid = inode->uid;
	    e.attr.st_gid = inode->gid;
	    e.attr.st_rdev = inode->rdev;
	    e.attr.st_size = 0;
	    e.attr.st_atim.tv_sec = 0;
	    e.attr.st_atim.tv_nsec = 0;
	    e.attr.st_mtim.tv_sec = inode->mtim.tv_sec;
	    e.attr.st_mtim.tv_nsec = inode->mtim.tv_nsec;
	    e.attr.st_ctim.tv_sec = inode->ctim.tv_sec;
	    e.attr.st_ctim.tv_nsec = inode->ctim.tv_nsec;

	    name = (char *) dotdotname;

	    inode->nlookup++;

    	} else {

	    if (! dh->entry) {

		readdir:

		res=get_direntry(overlay_readdir, &xname, &dtype, &error);

		if (res<=0) {

		    if (res==-1) {

			free(buff);
			unlock_directory(directory, _DIRECTORY_LOCK_EXCL);
			goto error;

		    }

		    dh->mode |= _WORKSPACE_READDIR_MODE_FINISH;
		    break;

		}

		if (fstatat(overlay_readdir->fd, xname.name, &e.attr, AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT)==-1) {

		    goto readdir;

		}

		logoutput("overlayfs_readdirplus_real_full: read %s", xname.name);

		xname.len=strlen(xname.name);
		calculate_nameindex(&xname);

		error=0;

		entry=create_entry(dh->parent, &xname);
		inode=create_inode();

		if (entry && inode) {

		    result=insert_entry_batch(directory, entry, &error, 0);

		    if (result==entry) {

			memcpy(&entry->synctime, &dh->synctime, sizeof(struct timespec));
			inode->mode=DTTOIF(dtype);

			add_inode_hashtable(inode, increase_inodes_workspace, (void *) dh->object->workspace_mount);

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

			adjust_pathmax(dh->pathinfo.len + 1 + xname.len);

		    } else {

			if (error==EEXIST) {

			    destroy_entry(entry);
			    entry=result;

			    memcpy(&entry->synctime, &dh->synctime, sizeof(struct timespec));

			    free(inode);
			    inode=entry->inode;

			} else {

			    free(buff);
			    destroy_entry(entry);
			    free(inode);

			    goto error;

			}

		    }

		    e.attr.st_ino=inode->ino;
		    e.ino=inode->ino;
		    e.attr.st_rdev = inode->rdev;
		    e.attr.st_dev = 0;
		    name=entry->name.name;

		} else {

		    if (entry) {

			destroy_entry(entry);
			entry=NULL;

		    }

		    if (inode) {

			free(inode);
			inode=NULL;

		    }

		    error=ENOMEM;
		    free(buff);

		    goto error;

		}

		name=entry->name.name;
		dh->entry=entry;

		inode->mode = e.attr.st_mode;
		inode->nlink = e.attr.st_nlink;
		inode->uid = e.attr.st_uid;
		inode->gid = e.attr.st_gid;
		inode->rdev = e.attr.st_rdev;

		inode->mtim.tv_sec = e.attr.st_mtim.tv_sec;
		inode->mtim.tv_nsec = e.attr.st_mtim.tv_nsec;
		inode->ctim.tv_sec = e.attr.st_ctim.tv_sec;
		inode->ctim.tv_nsec = e.attr.st_ctim.tv_nsec;

		if (S_ISDIR(e.attr.st_mode)) {

		    e.attr.st_size=0;

		} else {

		    inode->size=e.attr.st_size;

		}

	    } else {

		entry=dh->entry;
		inode=entry->inode;
		name=entry->name.name;

		e.attr.st_mode = inode->mode;
		e.attr.st_nlink = inode->nlink;
		e.attr.st_uid = inode->uid;
		e.attr.st_gid = inode->gid;
		e.attr.st_rdev = inode->rdev;

		if (S_ISDIR(inode->mode)) {

		    e.attr.st_size = 0;

		} else {

		    e.attr.st_size = inode->size;

		}

		e.attr.st_atim.tv_sec = 0;
		e.attr.st_atim.tv_nsec = 0;
		e.attr.st_mtim.tv_sec = inode->mtim.tv_sec;
		e.attr.st_mtim.tv_nsec = inode->mtim.tv_nsec;
		e.attr.st_ctim.tv_sec = inode->ctim.tv_sec;
		e.attr.st_ctim.tv_nsec = inode->ctim.tv_nsec;

		inode->nlookup++;

	    }

	    e.ino = inode->ino;
	    e.attr.st_ino = e.ino;

	}

    	dirent_size=fuse_add_direntry_plus(req, buff+pos, size-pos, name, &e, offset+1);

	if (pos + dirent_size > size) {

	    dh->offset=offset+1;
	    break;

	}

	/* increase counter and clear the various fields */

	dh->entry=NULL; /* forget current entry to force readdir */
	offset++;
	pos += dirent_size;

    }

    unlock_directory(directory, _DIRECTORY_LOCK_EXCL);

    fuse_reply_buf(req, buff, pos);

    free(buff);
    buff=NULL;

    return;

    error:

    fuse_reply_err(req, error);

}
示例#20
0
static void overlay_readdirplus_virtual(fuse_req_t req, size_t size, off_t offset, struct workspace_dh_struct *dh)
{
    unsigned int error=0;
    char *buff=NULL;
    size_t pos=0;
    size_t dirent_size;
    struct fuse_entry_param e;
    char *name=NULL;
    struct name_struct xname={NULL, 0, 0};
    unsigned char dtype=0;
    struct directory_struct *directory=dh->directory;
    struct overlay_readdir_struct *overlay_readdir=(struct overlay_readdir_struct *)dh->handle.data;
    struct entry_struct *entry=NULL;
    struct inode_struct *inode=NULL;

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

    e.generation = 1;
    e.attr_timeout = fs_options.attr_timeout;
    e.entry_timeout = fs_options.entry_timeout;

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

    buff=malloc(size);

    if (! buff) {

	error=ENOMEM;
	goto error;

    }

    if (lock_directory(directory, _DIRECTORY_LOCK_READ)==-1) {

	free(buff);
	buff=NULL;
	error=EAGAIN;
	goto error;

    }

    while (pos<size) {

    	if (offset==0) {

	    inode=dh->parent->inode;

    	    /* the . entry */

	    e.ino = inode->ino;

	    e.attr.st_ino = e.ino;
	    e.attr.st_mode = inode->mode;
	    e.attr.st_nlink = inode->nlink;
	    e.attr.st_uid = inode->uid;
	    e.attr.st_gid = inode->gid;
	    e.attr.st_rdev = inode->rdev;
	    e.attr.st_size = 0;
	    e.attr.st_atim.tv_sec = 0;
	    e.attr.st_atim.tv_nsec = 0;
	    e.attr.st_mtim.tv_sec = inode->mtim.tv_sec;
	    e.attr.st_mtim.tv_nsec = inode->mtim.tv_nsec;
	    e.attr.st_ctim.tv_sec = inode->ctim.tv_sec;
	    e.attr.st_ctim.tv_nsec = inode->ctim.tv_nsec;

	    name = (char *) dotname;

	    inode->nlookup++;

    	} else if (offset==1) {

    	    /* the .. entry */

	    if ( ! dh->parent->parent) {

		inode=dh->parent->inode;

	    } else {

		inode=dh->parent->parent->inode;

	    }

	    e.ino = inode->ino;

	    e.attr.st_ino = e.ino;
	    e.attr.st_mode = inode->mode;
	    e.attr.st_nlink = inode->nlink;
	    e.attr.st_uid = inode->uid;
	    e.attr.st_gid = inode->gid;
	    e.attr.st_rdev = inode->rdev;
	    e.attr.st_size = 0;
	    e.attr.st_atim.tv_sec = 0;
	    e.attr.st_atim.tv_nsec = 0;
	    e.attr.st_mtim.tv_sec = inode->mtim.tv_sec;
	    e.attr.st_mtim.tv_nsec = inode->mtim.tv_nsec;
	    e.attr.st_ctim.tv_sec = inode->ctim.tv_sec;
	    e.attr.st_ctim.tv_nsec = inode->ctim.tv_nsec;

	    name = (char *) dotdotname;

	    inode->nlookup++;

    	} else {

	    if (! dh->entry) {

		readdir:

		entry=(struct entry_struct *) overlay_readdir->data;

		if (entry) {

		    overlay_readdir->data=(void *) entry->name_next;

		} else {

		    dh->mode |= _WORKSPACE_READDIR_MODE_FINISH;
		    break;

		}

		dh->entry=entry;

	    } else {

		entry=dh->entry;

	    }

	    inode=entry->inode;

	    e.ino = inode->ino;

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

	    if (S_ISDIR(inode->mode)) {

		e.attr.st_size = 0;

	    } else {

		e.attr.st_size = inode->size;

	    }

	    e.attr.st_atim.tv_sec = 0;
	    e.attr.st_atim.tv_nsec = 0;
	    e.attr.st_mtim.tv_sec = inode->mtim.tv_sec;
	    e.attr.st_mtim.tv_nsec = inode->mtim.tv_nsec;
	    e.attr.st_ctim.tv_sec = inode->ctim.tv_sec;
	    e.attr.st_ctim.tv_nsec = inode->ctim.tv_nsec;

	    name=entry->name.name;
	    inode->nlookup++;

	}

    	dirent_size=fuse_add_direntry_plus(req, buff+pos, size-pos, name, &e, offset+1);

	if (pos + dirent_size > size) {

	    dh->offset=offset+1;
	    break;

	}

	/* increase counter and clear the various fields */

	dh->entry=NULL; /* forget current entry to force readdir */
	offset++;
	pos += dirent_size;

    }

    unlock_directory(directory, _DIRECTORY_LOCK_READ);

    fuse_reply_buf(req, buff, pos);

    free(buff);
    buff=NULL;

    return;

    error:

    fuse_reply_err(req, error);

}
示例#21
0
static int zfsfuse_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi)
{
	vnode_t *vp = ((file_info_t *)(uintptr_t) fi->fh)->vp;
	ASSERT(vp != NULL);
	ASSERT(VTOZ(vp) != NULL);
	ASSERT(VTOZ(vp)->z_id == ino);

	if(vp->v_type != VDIR)
		return ENOTDIR;

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

	char *outbuf = kmem_alloc(size, KM_NOSLEEP);
	if(outbuf == NULL)
		return ENOMEM;

	ZFS_ENTER(zfsvfs);

	cred_t cred;
	zfsfuse_getcred(req, &cred);

	union {
		char buf[DIRENT64_RECLEN(MAXNAMELEN)];
		struct dirent64 dirent;
	} entry;

	struct stat fstat = { 0 };

	iovec_t iovec;
	uio_t uio;
	uio.uio_iov = &iovec;
	uio.uio_iovcnt = 1;
	uio.uio_segflg = UIO_SYSSPACE;
	uio.uio_fmode = 0;
	uio.uio_llimit = RLIM64_INFINITY;

	int eofp = 0;

	int outbuf_off = 0;
	int outbuf_resid = size;

	off_t next = off;

	int error;

	for(;;) {
		iovec.iov_base = entry.buf;
		iovec.iov_len = sizeof(entry.buf);
		uio.uio_resid = iovec.iov_len;
		uio.uio_loffset = next;

		error = VOP_READDIR(vp, &uio, &cred, &eofp, NULL, 0);
		if(error)
			goto out;

		/* No more directory entries */
		if(iovec.iov_base == entry.buf)
			break;

		fstat.st_ino = entry.dirent.d_ino;
		fstat.st_mode = 0;

		int dsize = fuse_dirent_size(strlen(entry.dirent.d_name));
		if(dsize > outbuf_resid)
			break;

		fuse_add_dirent(outbuf + outbuf_off, entry.dirent.d_name, &fstat, entry.dirent.d_off);

		outbuf_off += dsize;
		outbuf_resid -= dsize;
		next = entry.dirent.d_off;
	}

out:
	ZFS_EXIT(zfsvfs);

	if(!error)
		fuse_reply_buf(req, outbuf, outbuf_off);

	kmem_free(outbuf, size);

	return error;
}
示例#22
0
static void workspace_nfs_readdirplus_simple(fuse_req_t req, size_t size, off_t offset, struct workspace_dh_struct *dh)
{
    struct resource_struct *resource=dh->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;
    unsigned int error=0;
    char *buff=NULL;
    size_t pos=0;
    size_t dirent_size;
    struct fuse_entry_param e;
    char *name=NULL;
    struct directory_struct *directory=dh->directory;
    struct nfsdir *dir=(struct nfsdir *) dh->handle.data;
    struct entry_struct *entry, *result;
    struct inode_struct *inode;
    struct name_struct xname={NULL, 0, 0};

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

    e.generation = 1;
    e.attr_timeout = fs_options.attr_timeout;
    e.entry_timeout = fs_options.entry_timeout;

    e.attr.st_blksize=_DEFAULT_BLOCKSIZE;

    buff=malloc(size);

    if (! buff) {

	error=ENOMEM;
	goto error;

    }

    if (lock_directory(directory, _DIRECTORY_LOCK_EXCL)==-1) {

	free(buff);
	buff=NULL;
	error=EAGAIN;
	goto error;

    }

    while (pos<size) {

    	if (offset==0) {

	    inode=dh->parent->inode;

    	    /* the . entry */

	    e.ino = inode->ino;

	    e.attr.st_ino = e.ino;
	    e.attr.st_mode = inode->mode;
	    e.attr.st_nlink = inode->nlink;
	    e.attr.st_uid = inode->uid;
	    e.attr.st_gid = inode->gid;
	    e.attr.st_rdev = inode->rdev;
	    e.attr.st_size = inode->size;
	    e.attr.st_atim.tv_sec = 0;
	    e.attr.st_atim.tv_nsec = 0;
	    e.attr.st_mtim.tv_sec = inode->mtim.tv_sec;
	    e.attr.st_mtim.tv_nsec = inode->mtim.tv_nsec;
	    e.attr.st_ctim.tv_sec = inode->ctim.tv_sec;
	    e.attr.st_ctim.tv_nsec = inode->ctim.tv_nsec;

	    name = (char *) dotname;

	    inode->nlookup++;

    	} else if (offset==1) {

    	    /* the .. entry */

	    if ( ! dh->parent->parent ) {

		inode=dh->parent->inode;

	    } else {

		inode=dh->parent->parent->inode;

	    }

	    e.ino = inode->ino;

	    e.attr.st_ino = e.ino;
	    e.attr.st_mode = inode->mode;
	    e.attr.st_nlink = inode->nlink;
	    e.attr.st_uid = inode->uid;
	    e.attr.st_gid = inode->gid;
	    e.attr.st_rdev = inode->rdev;
	    e.attr.st_size = inode->size;
	    e.attr.st_atim.tv_sec = 0;
	    e.attr.st_atim.tv_nsec = 0;
	    e.attr.st_mtim.tv_sec = inode->mtim.tv_sec;
	    e.attr.st_mtim.tv_nsec = inode->mtim.tv_nsec;
	    e.attr.st_ctim.tv_sec = inode->ctim.tv_sec;
	    e.attr.st_ctim.tv_nsec = inode->ctim.tv_nsec;

	    name = (char *) dotdotname;

	    inode->nlookup++;

    	} else {

	    if (! dh->entry) {
		struct nfsdirent *de;

		readdir:

	        pthread_mutex_lock(&nfs_export->mutex);

		de=nfs_readdir(nfs_ctx, dir);

	        pthread_mutex_unlock(&nfs_export->mutex);

		if (de) {

		    if (strcmp(de->name, ".")==0 || strcmp(de->name, "..")==0) continue;

		    xname.name=de->name;
		    xname.len=strlen(xname.name);
		    calculate_nameindex(&xname);

		} else {

		    dh->mode |= _WORKSPACE_READDIR_MODE_FINISH;
		    break;

		}

		error=0;

		entry=create_entry(dh->parent, &xname);
		inode=create_inode();

		if (entry && inode) {

		    result=insert_entry_batch(directory, entry, &error, 0);

		    if (result==entry) {
			struct workspace_object_struct *export_object=NULL;

			inode->mode = translate_libnfs_type(de->type);
			inode->mode |= de->mode;

			add_inode_hashtable(inode, increase_inodes_workspace, (void *) dh->object->workspace_mount);

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

			memcpy(&entry->synctime, &dh->synctime, sizeof(struct timespec));

			inode->nlookup++;
			inode->nlink=2;
			inode->uid=0; /* ?? */
			inode->gid=0; /* ?? */
			inode->size=de->size;

			/* struct timeval convert to timespec */

			inode->mtim.tv_sec=de->mtime.tv_sec;
			inode->mtim.tv_nsec=1000 * de->mtime.tv_usec;

			inode->ctim.tv_sec=de->ctime.tv_sec;
			inode->ctim.tv_nsec=1000 * de->ctime.tv_usec;

			adjust_pathmax(dh->pathinfo.len + 1 + xname.len);

		    } else {

			if (error==EEXIST) {

			    destroy_entry(entry);
			    entry=result;

			    memcpy(&entry->synctime, &dh->synctime, sizeof(struct timespec));

			    free(inode);
			    inode=entry->inode;

			} else {

			    free(buff);
			    destroy_entry(entry);
			    free(inode);

			    goto error;

			}

		    }

		} else {

		    if (entry) {

			destroy_entry(entry);
			entry=NULL;

		    }

		    if (inode) {

			free(inode);
			inode=NULL;

		    }

		    error=ENOMEM;
		    free(buff);

		    goto error;

		}

		name=entry->name.name;
		dh->entry=entry;


	    } else {

		entry=dh->entry;

		inode=entry->inode;
		name=entry->name.name;

	    }

	    e.ino = inode->ino;

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

	    e.attr.st_atim.tv_sec = 0;
	    e.attr.st_atim.tv_nsec = 0;
	    e.attr.st_mtim.tv_sec = inode->mtim.tv_sec;
	    e.attr.st_mtim.tv_nsec = inode->mtim.tv_nsec;
	    e.attr.st_ctim.tv_sec = inode->ctim.tv_sec;
	    e.attr.st_ctim.tv_nsec = inode->ctim.tv_nsec;

	    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;

	    }

	}

    	dirent_size=fuse_add_direntry_plus(req, buff+pos, size-pos, name, &e, offset+1);

	if (pos + dirent_size > size) {

	    dh->offset=offset;
	    break;

	}

	/* increase counter and clear the various fields */

	dh->entry=NULL; /* forget current entry to force readdir */
	offset++;
	pos += dirent_size;

    }

    unlock_directory(directory, _DIRECTORY_LOCK_EXCL);

    fuse_reply_buf(req, buff, pos);

    free(buff);
    buff=NULL;

    return;

    error:

    fuse_reply_err(req, error);

}
示例#23
0
static void workspace_nfs_readdir_simple(fuse_req_t req, size_t size, off_t offset, struct workspace_dh_struct *dh)
{
    struct resource_struct *resource=dh->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;
    unsigned int error=0;
    char *buff=NULL;
    size_t pos=0;
    size_t dirent_size;
    char *name=NULL;
    struct directory_struct *directory=dh->directory;
    struct nfsdir *dir=(struct nfsdir *) dh->handle.data;
    struct entry_struct *entry, *result;
    struct inode_struct *inode;
    struct name_struct xname={NULL, 0, 0};
    struct stat st;

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

    buff=malloc(size);

    if (! buff) {

	error=ENOMEM;
	goto error;

    }

    if (lock_directory(directory, _DIRECTORY_LOCK_EXCL)==-1) {

	free(buff);
	buff=NULL;
	error=EAGAIN;
	goto error;

    }

    while (pos<size) {

	if (offset==0) {

	    inode=dh->parent->inode;

    	    /* the . entry */

    	    st.st_ino = inode->ino;
	    st.st_mode = S_IFDIR;
	    name = (char *) dotname;

    	} else if (offset==1) {

    	    /* the .. entry */

	    if (! dh->parent->parent ) {

		inode=dh->parent->inode;
	    	st.st_ino = inode->ino;

	    } else {
		struct entry_struct *parent=dh->parent->parent;

		inode=parent->inode;
	    	st.st_ino=inode->ino;

	    }

	    st.st_mode = S_IFDIR;
	    name = (char *) dotdotname;

    	} else {

	    if (! dh->entry) {
		struct nfsdirent *de;

		readdir:

		pthread_mutex_lock(&nfs_export->mutex);

		de=nfs_readdir(nfs_ctx, dir);

	        pthread_mutex_unlock(&nfs_export->mutex);

		if (de) {

		    if (strcmp(de->name, ".")==0 || strcmp(de->name, "..")==0) continue;

		    xname.name=de->name;
		    xname.len=strlen(xname.name);
		    calculate_nameindex(&xname);

		} else {

		    dh->mode |= _WORKSPACE_READDIR_MODE_FINISH;
		    break;

		}

		error=0;

		entry=create_entry(dh->parent, &xname);
		inode=create_inode();

		if (entry && inode) {

		    result=insert_entry_batch(directory, entry, &error, 0);

		    if (result==entry) {
			struct workspace_object_struct *export_object=NULL;

			inode->mode = translate_libnfs_type(de->type);
			inode->mode |= de->mode;

			add_inode_hashtable(inode, increase_inodes_workspace, (void *) dh->object->workspace_mount);

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

			adjust_pathmax(dh->pathinfo.len + 1 + xname.len);

		    } else {

			if (error==EEXIST) {

			    destroy_entry(entry);
			    entry=result;

			    free(inode);
			    inode=entry->inode;

			} else {

			    free(buff);
			    destroy_entry(entry);
			    free(inode);

			    goto error;

			}

		    }

		    st.st_mode=entry->inode->mode;
		    st.st_ino=entry->inode->ino;
		    name=entry->name.name;

		} else {

		    if (entry) {

			destroy_entry(entry);
			entry=NULL;

		    }

		    if (inode) {

			free(inode);
			inode=NULL;

		    }

		    error=ENOMEM;
		    free(buff);

		    goto error;

		}

		dh->entry=entry;

	    } else {

		st.st_ino=dh->entry->inode->ino;
		st.st_mode=dh->entry->inode->mode;
		name=dh->entry->name.name;

	    }

	}

    	dirent_size=fuse_add_direntry(req, buff+pos, size-pos, name, &st, offset+1);

	if (pos + dirent_size > size) {

	    dh->offset = offset + 1;
	    break;

	}

	/* increase counter and clear the various fields */

	dh->entry=NULL; /* forget current entry to force readdir */
	offset++;
	pos += dirent_size;

    }

    unlock_directory(directory, _DIRECTORY_LOCK_EXCL);

    fuse_reply_buf(req, buff, pos);

    free(buff);
    buff=NULL;

    return;

    error:

    fuse_reply_err(req, error);

}
示例#24
0
static void lo_do_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
			  off_t offset, struct fuse_file_info *fi, int plus)
{
	struct lo_dirp *d = lo_dirp(fi);
	char *buf;
	char *p;
	size_t rem;
	int err;

	(void) ino;

	buf = calloc(size, 1);
	if (!buf)
		return (void) fuse_reply_err(req, ENOMEM);

	if (offset != d->offset) {
		seekdir(d->dp, offset);
		d->entry = NULL;
		d->offset = offset;
	}
	p = buf;
	rem = size;
	while (1) {
		size_t entsize;
		off_t nextoff;

		if (!d->entry) {
			errno = 0;
			d->entry = readdir(d->dp);
			if (!d->entry) {
				if (errno && rem == size) {
					err = errno;
					goto error;
				}
				break;
			}
		}
		nextoff = telldir(d->dp);
		if (plus) {
			struct fuse_entry_param e;

			err = lo_do_lookup(req, ino, d->entry->d_name, &e);
			if (err)
				goto error;

			entsize = fuse_add_direntry_plus(req, p, rem,
							 d->entry->d_name,
							 &e, nextoff);
		} else {
			struct stat st = {
				.st_ino = d->entry->d_ino,
				.st_mode = d->entry->d_type << 12,
			};
			entsize = fuse_add_direntry(req, p, rem,
						    d->entry->d_name,
						    &st, nextoff);
		}
		if (entsize > rem)
			break;

		p += entsize;
		rem -= entsize;

		d->entry = NULL;
		d->offset = nextoff;
	}

	fuse_reply_buf(req, buf, size - rem);
	free(buf);
	return;

error:
	free(buf);
	fuse_reply_err(req, err);
}

static void lo_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
		       off_t offset, struct fuse_file_info *fi)
{
	lo_do_readdir(req, ino, size, offset, fi, 0);
}
示例#25
0
static void overlay_readdir_virtual(fuse_req_t req, size_t size, off_t offset, struct workspace_dh_struct *dh)
{
    unsigned int error=0;
    char *buff=NULL;
    size_t pos=0;
    size_t dirent_size;
    struct stat st;
    char *name=NULL;
    struct name_struct xname={NULL, 0, 0};
    struct entry_struct *entry=NULL;
    struct inode_struct *inode=NULL;
    struct directory_struct *directory=dh->directory;
    struct overlay_readdir_struct *overlay_readdir=(struct overlay_readdir_struct *)dh->handle.data;
    unsigned char dtype=0;

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

    buff=malloc(size);

    if (! buff) {

	error=ENOMEM;
	goto error;

    }

    if (lock_directory(directory, _DIRECTORY_LOCK_READ)==-1) {

	free(buff);
	buff=NULL;
	error=EAGAIN;
	goto error;

    }

    while (pos<size) {

    	if (offset==0) {

	    inode=dh->parent->inode;

    	    /* the . entry */

    	    st.st_ino = inode->ino;
	    st.st_mode = S_IFDIR;
	    name = (char *) dotname;

    	} else if (offset==1) {

    	    /* the .. entry */

	    if (! dh->parent->parent ) {

		inode=dh->parent->inode;
	    	st.st_ino = inode->ino;

	    } else {
		struct entry_struct *parent=dh->parent->parent;

		inode=parent->inode;
	    	st.st_ino=inode->ino;

	    }

	    st.st_mode = S_IFDIR;
	    name = (char *) dotdotname;

    	} else {

	    if (! dh->entry) {

		readdir:

		entry=(struct entry_struct *) overlay_readdir->data;

		if (entry) {

		    overlay_readdir->data=(void *) entry->name_next;

		} else {

		    dh->mode |= _WORKSPACE_READDIR_MODE_FINISH;
		    break;

		}

		dh->entry=entry;

	    } else {

		entry=dh->entry;

	    }

	    name=entry->name.name;
	    st.st_mode=entry->inode->mode;
	    st.st_ino=entry->inode->ino;

	}

    	dirent_size=fuse_add_direntry(req, buff+pos, size-pos, name, &st, offset+1);

	if (pos + dirent_size > size) {

	    dh->offset=offset + 1;
	    break;

	}

	/* increase counter and clear the various fields */

	offset++;
	pos += dirent_size;
	dh->entry=NULL;

    }

    fuse_reply_buf(req, buff, pos);

    unlock_directory(directory, _DIRECTORY_LOCK_READ);

    free(buff);
    buff=NULL;

    return;

    error:

    fuse_reply_err(req, error);

}
示例#26
0
static void overlay_readdir_full(fuse_req_t req, size_t size, off_t offset, struct workspace_dh_struct *dh)
{
    unsigned int error=0;
    char *buff=NULL;
    size_t pos=0;
    size_t dirent_size;
    struct stat st;
    char *name=NULL;
    struct directory_struct *directory=dh->directory;
    struct overlay_readdir_struct *overlay_readdir=(struct overlay_readdir_struct *)dh->handle.data;
    struct entry_struct *entry, *result;
    struct inode_struct *inode;
    struct name_struct xname={NULL, 0, 0};
    unsigned char dtype=0;
    int res;

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

    buff=malloc(size);

    if (! buff) {

	error=ENOMEM;
	goto error;

    }

    if (lock_directory(directory, _DIRECTORY_LOCK_EXCL)==-1) {

	free(buff);
	buff=NULL;
	error=EAGAIN;
	goto error;

    }

    while (pos<size) {

    	if (offset==0) {

	    inode=dh->parent->inode;

    	    /* the . entry */

    	    st.st_ino = inode->ino;
	    st.st_mode = S_IFDIR;
	    name = (char *) dotname;

    	} else if (offset==1) {

    	    /* the .. entry */

	    if ( ! dh->parent->parent ) {

		inode=dh->parent->inode;
	    	st.st_ino = inode->ino;

	    } else {
		struct entry_struct *parent=dh->parent->parent;

		inode=parent->inode;
	    	st.st_ino=inode->ino;

	    }

	    st.st_mode = S_IFDIR;
	    name = (char *) dotdotname;

    	} else {

	    if (! dh->entry) {

		readdir:

		res=get_direntry(overlay_readdir, &xname, &dtype, &error);

		if (res<=0) {

		    if (res==-1) {

			free(buff);
			unlock_directory(directory, _DIRECTORY_LOCK_EXCL);
			goto error;

		    }

		    dh->mode |= _WORKSPACE_READDIR_MODE_FINISH;
		    break;

		}

		xname.len=strlen(xname.name);
		calculate_nameindex(&xname);

		error=0;

		entry=create_entry(dh->parent, &xname);
		inode=create_inode();

		if (entry && inode) {

		    result=insert_entry_batch(directory, entry, &error, 0);

		    if (result==entry) {

			entry->inode->mode=DTTOIF(dtype);

			add_inode_hashtable(inode, increase_inodes_workspace, (void *) dh->object->workspace_mount);

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

			adjust_pathmax(dh->pathinfo.len + 1 + xname.len);

		    } else {

			if (error==EEXIST) {

			    destroy_entry(entry);
			    entry=result;

			    free(inode);
			    inode=entry->inode;

			} else {

			    free(buff);
			    destroy_entry(entry);
			    free(inode);

			    goto error;

			}

		    }

		    st.st_mode=entry->inode->mode;
		    st.st_ino=entry->inode->ino;
		    name=entry->name.name;

		} else {

		    if (entry) {

			destroy_entry(entry);
			entry=NULL;

		    }

		    if (inode) {

			free(inode);
			inode=NULL;

		    }

		    error=ENOMEM;
		    free(buff);

		    goto error;

		}

		dh->entry=entry;

	    } else {

		entry=dh->entry;

		st.st_ino=entry->inode->ino;
		st.st_mode=entry->inode->mode;
		name=entry->name.name;

	    }

	}

    	dirent_size=fuse_add_direntry(req, buff+pos, size-pos, name, &st, offset+1);

	if (pos + dirent_size > size) {

	    dh->offset = offset + 1;
	    break;

	}

	/* increase counter and clear the various fields */

	dh->entry=NULL; /* forget current entry to force readdir */
	offset++;
	pos += dirent_size;

    }

    unlock_directory(directory, _DIRECTORY_LOCK_EXCL);

    fuse_reply_buf(req, buff, pos);

    free(buff);
    buff=NULL;

    return;

    error:

    fuse_reply_err(req, error);

}
示例#27
0
文件: read.c 项目: daos-stack/daos
static bool
read_bulk_cb(struct dfuse_request *request)
{
	struct dfuse_rb *rb = container_of(request, struct dfuse_rb, rb_req);
	struct dfuse_readx_out *out = request->out;
	int rc = 0;
	size_t bytes_read = 0;
	void *buff = NULL;

	if (out->err) {
		DFUSE_TRA_ERROR(rb, "Error from target %d", out->err);
		rb->failure = true;
		D_GOTO(out, request->rc = EIO);
	}

	DFUSE_REQUEST_RESOLVE(request, out);
	if (request->rc)
		D_GOTO(out, 0);

	if (out->iov_len > 0) {
		if (out->data.iov_len != out->iov_len)
			D_GOTO(out, request->rc = EIO);
		buff = out->data.iov_buf;
		bytes_read = out->data.iov_len;
	} else if (out->bulk_len > 0) {
		bytes_read = out->bulk_len;
	}

out:
	if (request->rc) {
		DFUSE_REPLY_ERR(request, request->rc);
	} else {

		/* It's not clear without benchmarking which approach is better
		 * here, fuse_reply_buf() is a small wrapper around writev()
		 * which is a much shorter code-path however fuse_reply_data()
		 * attempts to use splice which may well be faster.
		 *
		 * For now it's easy to pick between them, and both of them are
		 * passing valgrind tests.
		 */
		if (request->fsh->flags & DFUSE_FUSE_READ_BUF) {
			rc = fuse_reply_buf(request->req, buff, bytes_read);
			if (rc != 0)
				DFUSE_TRA_ERROR(rb,
						"fuse_reply_buf returned %d:%s",
						rc, strerror(-rc));

		} else {
			rb->fbuf.buf[0].size = bytes_read;
			rb->fbuf.buf[0].mem = buff;
			rc = fuse_reply_data(request->req, &rb->fbuf, 0);
			if (rc != 0)
				DFUSE_TRA_ERROR(rb,
						"fuse_reply_data returned %d:%s",
						rc, strerror(-rc));
		}
	}
	dfuse_da_release(rb->pt, rb);
	return false;
}