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