Пример #1
0
static void dirbuf_add(fuse_req_t req, struct dirbuf *b, const char *name, fuse_ino_t ino)
{
  struct stat stbuf;
  size_t oldsize = b->size;
  b->size += fuse_add_direntry(req, NULL, 0, name, NULL, 0);
  b->p = (char *)realloc(b->p, b->size);
  memset(&stbuf, 0, sizeof(stbuf));
  stbuf.st_ino = ino;
  fuse_add_direntry(req, b->p + oldsize, b->size - oldsize, name, &stbuf, b->size);
}
Пример #2
0
static size_t sqfs_ll_add_direntry(fuse_req_t req, char *buf, size_t bufsize,
		const char *name, const struct stat *st, off_t off) {
	#if HAVE_DECL_FUSE_ADD_DIRENTRY
		return fuse_add_direntry(req, buf, bufsize, name, st, off);
	#else
		size_t esize = fuse_dirent_size(strlen(name));
		if (bufsize >= esize)
			fuse_add_dirent(buf, name, st, off);
		return esize;
	#endif
}
Пример #3
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);
}
Пример #4
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);
}
Пример #5
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));
}
Пример #6
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);

}
Пример #7
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);

}
Пример #8
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);

}