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); }
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 }
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); }
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); }
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)); }
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); }
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); }
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); }