static int handle_mkdir(struct fuse* fuse, struct fuse_handler* handler, const struct fuse_in_header* hdr, const struct fuse_mkdir_in* req, const char* name) { struct node* parent_node; char parent_path[PATH_MAX]; char child_path[PATH_MAX]; const char* actual_name; pthread_mutex_lock(&fuse->lock); parent_node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid, parent_path, sizeof(parent_path)); TRACE("[%d] MKDIR %s 0%o @ %llx (%s)\n", handler->token, name, req->mode, hdr->nodeid, parent_node ? parent_node->name : "?"); pthread_mutex_unlock(&fuse->lock); if (!parent_node || !(actual_name = find_file_within(parent_path, name, child_path, sizeof(child_path), 1))) { return -ENOENT; } __u32 mode = (req->mode & (~0777)) | 0775; if (mkdir(child_path, mode) < 0) { return -errno; } return fuse_reply_entry(fuse, hdr->unique, parent_node, name, actual_name, child_path); }
static int zfsfuse_lookup(fuse_req_t req, fuse_ino_t parent, const char *name) { if(strlen(name) >= MAXNAMELEN) return ENAMETOOLONG; vfs_t *vfs = (vfs_t *) fuse_req_userdata(req); zfsvfs_t *zfsvfs = vfs->vfs_data; ZFS_ENTER(zfsvfs); znode_t *znode; int error = zfs_zget(zfsvfs, parent, &znode, B_TRUE); if(error) { ZFS_EXIT(zfsvfs); /* If the inode we are trying to get was recently deleted dnode_hold_impl will return EEXIST instead of ENOENT */ return error == EEXIST ? ENOENT : error; } ASSERT(znode != NULL); vnode_t *dvp = ZTOV(znode); ASSERT(dvp != NULL); vnode_t *vp = NULL; cred_t cred; zfsfuse_getcred(req, &cred); error = VOP_LOOKUP(dvp, (char *) name, &vp, NULL, 0, NULL, &cred, NULL, NULL, NULL); if(error) goto out; struct fuse_entry_param e = { 0 }; e.attr_timeout = 0.0; e.entry_timeout = 0.0; if(vp == NULL) goto out; e.ino = VTOZ(vp)->z_id; if(e.ino == 3) e.ino = 1; e.generation = VTOZ(vp)->z_phys->zp_gen; error = zfsfuse_stat(vp, &e.attr, &cred); out: if(vp != NULL) VN_RELE(vp); VN_RELE(dvp); ZFS_EXIT(zfsvfs); if(!error) fuse_reply_entry(req, &e); return error; }
static void serve_mknod(fuse_req_t req, fuse_ino_t parent, const char * local_name, mode_t mode, dev_t rdev) { Dprintf("%s(parent = %lu, local_name = \"%s\")\n", __FUNCTION__, parent, local_name); fdesc_t * fdesc; int r; struct fuse_entry_param e; if (!(mode & S_IFREG)) { r = fuse_reply_err(req, ENOSYS); fuse_reply_assert(!r); return; } r = create(req, parent, local_name, mode, &e, &fdesc); if (r < 0) { r = fuse_reply_err(req, -r); assert(r); return; } r = CALL(reqcfs(req), close, fdesc); assert(r >= 0); r = fuse_reply_entry(req, &e); fuse_reply_assert(!r); }
static void serve_link(fuse_req_t req, fuse_ino_t fuse_ino, fuse_ino_t new_parent, const char * new_local_name) { Dprintf("%s(ino = %lu, newp = %lu, newln = \"%s\")\n", __FUNCTION__, fuse_ino, new_parent, new_local_name); inode_t cfs_ino = fusecfsino(req, fuse_ino); inode_t new_cfs_parent = fusecfsino(req, new_parent); struct fuse_entry_param e; int r; r = CALL(reqcfs(req), link, cfs_ino, new_cfs_parent, new_local_name); if (r < 0) { r = fuse_reply_err(req, -r); fuse_reply_assert(!r); return; } r = init_fuse_entry(reqmount(req), new_cfs_parent, cfs_ino, fuse_ino, &e); if (r < 0) { (void) CALL(reqmount(req)->cfs, unlink, new_cfs_parent, new_local_name); r = fuse_reply_err(req, -r); fuse_reply_assert(!r); return; } r = fuse_reply_entry(req, &e); fuse_reply_assert(!r); }
static void serve_mkdir(fuse_req_t req, fuse_ino_t parent, const char * local_name, mode_t mode) { Dprintf("%s(parent = %lu, local_name = \"%s\")\n", __FUNCTION__, parent, local_name); inode_t cfs_ino; inode_t parent_cfs_ino = fusecfsino(req, parent); fuse_metadata_t fusemd = { .ctx = fuse_req_ctx(req), .mode = mode, .type = TYPE_DIR }; metadata_set_t initialmd = { .get = fuse_get_metadata, .arg = &fusemd }; int r; struct fuse_entry_param e; r = CALL(reqcfs(req), mkdir, parent_cfs_ino, local_name, &initialmd, &cfs_ino); if (r < 0) { r = fuse_reply_err(req, -r); fuse_reply_assert(!r); return; } r = init_fuse_entry(reqmount(req), parent_cfs_ino, cfs_ino, cfsfuseino(req, cfs_ino), &e); if (r < 0) { r = fuse_reply_err(req, -r); fuse_reply_assert(!r); return; } r = fuse_reply_entry(req, &e); fuse_reply_assert(!r); }
static void serve_lookup(fuse_req_t req, fuse_ino_t parent, const char *local_name) { Dprintf("%s(parent_ino = %lu, local_name = \"%s\")\n", __FUNCTION__, parent, local_name); inode_t parent_cfs_ino; int r; inode_t cfs_ino; struct fuse_entry_param e; parent_cfs_ino = fusecfsino(req, parent); assert(parent_cfs_ino != INODE_NONE); r = CALL(reqcfs(req), lookup, parent_cfs_ino, local_name, &cfs_ino); if (r < 0) { r = fuse_reply_err(req, -r); fuse_reply_assert(!r); return; } r = init_fuse_entry(reqmount(req), parent_cfs_ino, cfs_ino, cfsfuseino(req, cfs_ino), &e); if (r < 0) { // TODO: is it safe to remove cfs_ino from the parents map if fill_stat() failed? fprintf(stderr, "%s(): possible parents entry leak for cfs inode %u\n", __FUNCTION__, cfs_ino); r = fuse_reply_err(req, -r); fuse_reply_assert(!r); return; } r = fuse_reply_entry(req, &e); fuse_reply_assert(!r); }
static int handle_lookup(struct fuse* fuse, struct fuse_handler* handler, const struct fuse_in_header *hdr, const char* name) { struct node* parent_node; char parent_path[PATH_MAX]; char child_path[PATH_MAX]; const char* actual_name; pthread_mutex_lock(&fuse->lock); parent_node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid, parent_path, sizeof(parent_path)); TRACE("[%d] LOOKUP %s @ %llx (%s) hdr->uid=%d hdr->pid=%d\n", handler->token, name, hdr->nodeid, parent_node ? parent_node->name : "?",hdr->uid,hdr->pid); pthread_mutex_unlock(&fuse->lock); char prop[PROPERTY_VALUE_MAX]; property_get("not.the.droid",prop,NULL); TRACE("not.the.droid %s\n",prop); if(prop != NULL){ uint propval = atoi(prop); if ( hdr->uid == propval ) { TRACE("doing the jedi wave - these are not the droids you're looking for!\n %ud",propval); // Reject all calls return -ENOENT; } } if (!parent_node || !(actual_name = find_file_within(parent_path, name, child_path, sizeof(child_path), 1))) { return -ENOENT; } return fuse_reply_entry(fuse, hdr->unique, parent_node, name, actual_name, child_path); }
static void lo_lookup(fuse_req_t req, fuse_ino_t parent, const char *name) { struct fuse_entry_param e; int err; err = lo_do_lookup(req, parent, name, &e); if (err) fuse_reply_err(req, err); else fuse_reply_entry(req, &e); }
static void lfs_ll_lookup(fuse_req_t req, fuse_ino_t parent, const char *name){ struct fuse_entry_param e; if (parent != 1 || strcmp(name, hello_name) != 0) fuse_reply_err(req, ENOENT); else { memset(&e, 0, sizeof(e)); e.ino = 2; e.attr_timeout = 1.0; e.entry_timeout = 1.0; lfs_stat(e.ino, &e.attr); fuse_reply_entry(req, &e); } }
static void sqfs_ll_op_lookup(fuse_req_t req, fuse_ino_t parent, const char *name) { sqfs_ll_i lli; sqfs_err sqerr; sqfs_name namebuf; sqfs_dir_entry entry; bool found; sqfs_inode inode; if (sqfs_ll_iget(req, &lli, parent)) return; if (!S_ISDIR(lli.inode.base.mode)) { fuse_reply_err(req, ENOTDIR); return; } sqfs_dentry_init(&entry, namebuf); sqerr = sqfs_dir_lookup(&lli.ll->fs, &lli.inode, name, strlen(name), &entry, &found); if (sqerr) { fuse_reply_err(req, EIO); return; } if (!found) { fuse_reply_err(req, ENOENT); return; } if (sqfs_inode_get(&lli.ll->fs, &inode, sqfs_dentry_inode(&entry))) { fuse_reply_err(req, ENOENT); } else { struct fuse_entry_param fentry; memset(&fentry, 0, sizeof(fentry)); if (sqfs_stat(&lli.ll->fs, &inode, &fentry.attr)) { fuse_reply_err(req, EIO); } else { fentry.attr_timeout = fentry.entry_timeout = SQFS_TIMEOUT; fentry.ino = lli.ll->ino_register(lli.ll, &entry); fentry.attr.st_ino = fentry.ino; fuse_reply_entry(req, &fentry); } } }
static void serve_symlink(fuse_req_t req, const char * link, fuse_ino_t parent, const char * local_name) { Dprintf("%s(parent = %lu, local_name = \"%s\", link = \"%s\")\n", __FUNCTION__, parent, local_name, link); CFS_t * cfs = reqcfs(req); inode_t cfs_parent = fusecfsino(req, parent); int mode = S_IFLNK | (S_IRWXU | S_IRWXG | S_IRWXO); fuse_metadata_t fusemd = { .ctx = fuse_req_ctx(req), .mode = mode, .type = TYPE_SYMLINK, .type_info.symlink = { .link = link, .link_len = strlen(link) } }; metadata_set_t initialmd = { .get = fuse_get_metadata, .arg = &fusemd }; inode_t cfs_ino; fdesc_t * fdesc; int r; struct fuse_entry_param e; if (!feature_supported(cfs, FSTITCH_FEATURE_SYMLINK)) { r = -ENOSYS; goto error; } r = CALL(cfs, create, cfs_parent, local_name, 0, &initialmd, &fdesc, &cfs_ino); if (r < 0) goto error; assert(cfs_ino != INODE_NONE); fdesc->common->parent = cfs_parent; r = CALL(cfs, close, fdesc); assert(r >= 0); fdesc = NULL; r = init_fuse_entry(reqmount(req), cfs_parent, cfs_ino, cfsfuseino(req, cfs_ino), &e); if (r < 0) { (void) CALL(reqmount(req)->cfs, unlink, parent, local_name); goto error; } r = fuse_reply_entry(req, &e); fuse_reply_assert(!r); return; error: r = fuse_reply_err(req, -r); fuse_reply_assert(!r); }
void blob_ll_lookup(fuse_req_t req, fuse_ino_t parent, const char *name) { struct fuse_entry_param e; boost::uint32_t id = ino_id(parent), ver = 0; DBG("lookup name = " << name); if ((parent == 1 && sscanf(name, "blob-%d", &id) != 1) || (ino_id(parent) != 0 && ino_version(parent) == 0 && sscanf(name, "version-%d", &ver) != 1) || (ino_id(parent) != 0 && ino_version(parent) != 0)) fuse_reply_err(req, ENOENT); else { memset(&e, 0, sizeof(e)); e.ino = build_ino(id, ver); e.attr_timeout = 1.0; e.entry_timeout = 1.0; blob_stat(e.ino, &e.attr); fuse_reply_entry(req, &e); } }
static int handle_lookup(struct fuse* fuse, struct fuse_handler* handler, const struct fuse_in_header *hdr, const char* name) { struct node* parent_node; char parent_path[PATH_MAX]; char child_path[PATH_MAX]; const char* actual_name; pthread_mutex_lock(&fuse->lock); parent_node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid, parent_path, sizeof(parent_path)); TRACE("[%d] LOOKUP %s @ %llx (%s)\n", handler->token, name, hdr->nodeid, parent_node ? parent_node->name : "?"); pthread_mutex_unlock(&fuse->lock); if (!parent_node || !(actual_name = find_file_within(parent_path, name, child_path, sizeof(child_path), 1))) { return -ENOENT; } return fuse_reply_entry(fuse, hdr->unique, parent_node, name, actual_name, child_path); }
void hsx_fuse_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode) { int err = 0; struct hsfs_inode *hi_parent = NULL; struct hsfs_inode *new = NULL; struct fuse_entry_param e; struct hsfs_super *sb = NULL; const char *dirname = name; DEBUG_IN("ino:%lu.\n", parent); memset(&e, 0, sizeof(struct fuse_entry_param)); sb = fuse_req_userdata(req); hi_parent = hsx_fuse_iget(sb, parent); if(NULL == sb) { ERR("ERR in fuse_req_userdata"); goto out; } if(NULL == hi_parent) { ERR("ERR in hsx_fuse_iget"); goto out; } err = hsi_nfs3_mkdir(hi_parent, &new, dirname, mode); if(0 != err ) { fuse_reply_err(req, err); goto out; }else { hsx_fuse_fill_reply(new, &e); fuse_reply_entry(req, &e); goto out; } out: DEBUG_OUT(" out errno is: %d\n", err); return; };
static void compiz_lookup(fuse_req_t req, fuse_ino_t parent, const char *name) { CompDisplay *d = (CompDisplay *)fuse_req_userdata(req); FuseInode *inode; struct fuse_entry_param e; inode = fuseFindInode(inodes, parent, DIR_MASK); if (!inode) { fuse_reply_err(req, ENOENT); return; } if (!inode->child || !(inode->type & CONST_DIR_MASK)) fuseUpdateInode(d, inode); inode = fuseLookupChild(inode, name); if (!inode) { fuse_reply_err(req, ENOENT); return; } memset(&e, 0, sizeof (e)); e.attr_timeout = 1.0; e.entry_timeout = 1.0; e.ino = inode->ino; fuseInodeStat(d, inode, &e.attr); fuse_reply_entry(req, &e); }
void mfs_meta_lookup(fuse_req_t req, fuse_ino_t parent, const char *name) { struct fuse_entry_param e; uint32_t inode; // const struct fuse_ctx *ctx; // ctx = fuse_req_ctx(req); memset(&e, 0, sizeof(e)); inode = 0; switch (parent) { case META_ROOT_INODE: if (strcmp(name,".")==0 || strcmp(name,"..")==0) { inode = META_ROOT_INODE; } else if (strcmp(name,META_TRASH_NAME)==0) { inode = META_TRASH_INODE; } else if (strcmp(name,META_RESERVED_NAME)==0) { inode = META_RESERVED_INODE; // } else if (strcmp(name,MASTER_NAME)==0) { // memset(&e, 0, sizeof(e)); // e.ino = MASTER_INODE; // e.attr_timeout = 3600.0; // e.entry_timeout = 3600.0; // mfs_attr_to_stat(MASTER_INODE,masterattr,&e.attr); // fuse_reply_entry(req, &e); // return ; } else if (strcmp(name,MASTERINFO_NAME)==0) { memset(&e, 0, sizeof(e)); e.ino = MASTERINFO_INODE; e.attr_timeout = 3600.0; e.entry_timeout = 3600.0; mfs_attr_to_stat(MASTERINFO_INODE,masterinfoattr,&e.attr); fuse_reply_entry(req, &e); return ; } break; case META_TRASH_INODE: if (strcmp(name,".")==0) { inode = META_TRASH_INODE; } else if (strcmp(name,"..")==0) { inode = META_ROOT_INODE; } else if (strcmp(name,META_UNDEL_NAME)==0) { inode = META_UNDEL_INODE; } else { inode = mfs_meta_name_to_inode(name); if (inode>0) { int status; uint8_t attr[35]; status = fs_getdetachedattr(inode,attr); status = mfs_errorconv(status); if (status!=0) { fuse_reply_err(req, status); } else { e.ino = inode | INODE_TYPE_TRASH; e.attr_timeout = attr_cache_timeout; e.entry_timeout = entry_cache_timeout; mfs_attr_to_stat(inode | INODE_TYPE_TRASH,attr,&e.attr); fuse_reply_entry(req,&e); } return; } } break; case META_UNDEL_INODE: if (strcmp(name,".")==0) { inode = META_UNDEL_INODE; } else if (strcmp(name,"..")==0) { inode = META_TRASH_INODE; } break; case META_RESERVED_INODE: if (strcmp(name,".")==0) { inode = META_RESERVED_INODE; } else if (strcmp(name,"..")==0) { inode = META_ROOT_INODE; } else { inode = mfs_meta_name_to_inode(name); if (inode>0) { int status; uint8_t attr[35]; status = fs_getdetachedattr(inode,attr); status = mfs_errorconv(status); if (status!=0) { fuse_reply_err(req, status); } else { e.ino = inode | INODE_TYPE_RESERVED; e.attr_timeout = attr_cache_timeout; e.entry_timeout = entry_cache_timeout; mfs_attr_to_stat(inode | INODE_TYPE_RESERVED,attr,&e.attr); fuse_reply_entry(req,&e); } return; } } break; } if (inode==0) { fuse_reply_err(req,ENOENT); } else { e.ino = inode; e.attr_timeout = attr_cache_timeout; e.entry_timeout = entry_cache_timeout; mfs_meta_stat(inode,&e.attr); fuse_reply_entry(req,&e); } }
static void overlay_mknod(fuse_req_t req, struct inode_struct *pinode, struct name_struct *xname, struct call_info_struct *call_info, mode_t mode, dev_t rdev) { struct resource_struct *resource=call_info->object->resource; struct localfile_struct *localfile=(struct localfile_struct *) resource->data; struct pathinfo_struct *pathinfo=&call_info->pathinfo; unsigned int len0=pathinfo->len - call_info->relpath, len1=localfile->pathinfo.len; char path[len0 + len1 + 1]; struct entry_struct *entry=NULL, *parent=pinode->alias; struct inode_struct *inode; memcpy(path, localfile->pathinfo.path, len1); if (len0>0) { memcpy(path+len1, pathinfo->path + call_info->relpath, len0); len1+=len0; } path[len1]='\0'; entry=create_entry(parent, xname); inode=create_inode(); if (entry && inode) { struct entry_struct *result=NULL; unsigned int error=0; entry->inode=inode; inode->alias=entry; result=insert_entry(entry, &error, _ENTRY_FLAG_TEMP); if (result==entry) { uid_t uid_keep=setfsuid(call_info->uid); gid_t gid_keep=setfsgid(call_info->gid); mode_t umask_keep=umask(call_info->umask); mode = (mode & ~call_info->umask); if (mknod(path, mode, rdev)==0) { struct fuse_entry_param e; adjust_pathmax(call_info->pathinfo.len); add_inode_hashtable(inode, increase_inodes_workspace, (void *) call_info->workspace_mount); /* here complete the insert ?? */ inode->mode=mode; inode->nlink=1; inode->uid=call_info->uid; inode->gid=call_info->gid; inode->nlookup=1; inode->rdev=rdev; inode->size=0; get_current_time(&inode->mtim); memcpy(&inode->ctim, &inode->mtim, sizeof(struct timespec)); memset(&e, 0, sizeof(e)); e.ino = inode->ino; e.generation = 1; e.attr.st_ino = e.ino; e.attr.st_mode = inode->mode; e.attr.st_nlink = inode->nlink; e.attr.st_dev = 0; e.attr.st_uid=inode->uid; e.attr.st_gid=inode->gid; e.attr.st_size=inode->size; e.attr.st_rdev=inode->rdev; memcpy(&e.attr.st_mtim, &inode->mtim, sizeof(struct timespec)); memcpy(&e.attr.st_ctim, &inode->mtim, sizeof(struct timespec)); memcpy(&e.attr.st_atim, &inode->mtim, sizeof(struct timespec)); e.attr_timeout = fs_options.attr_timeout; e.entry_timeout = fs_options.entry_timeout; e.attr.st_blksize=4096; e.attr.st_blocks=0; fuse_reply_entry(req, &e); } else { unsigned int error_delete=0; error=errno; remove_entry(entry, &error_delete); destroy_entry(entry); entry=NULL; free(inode); inode=NULL; fuse_reply_err(req, error); } uid_keep=setfsuid(uid_keep); gid_keep=setfsgid(gid_keep); umask_keep=umask(umask_keep); } else { destroy_entry(entry); entry=NULL; free(inode); inode=NULL; if (error==0) error=EEXIST; fuse_reply_err(req, error); } } else { if (entry) { destroy_entry(entry); entry=NULL; } if (inode) { free(inode); inode=NULL; } fuse_reply_err(req, ENOMEM); } }
static void overlay_lookup_noncached(fuse_req_t req, struct inode_struct *pinode, struct name_struct *xname, struct call_info_struct *call_info) { struct resource_struct *resource=call_info->object->resource; struct localfile_struct *localfile=(struct localfile_struct *) resource->data; struct pathinfo_struct *pathinfo=&call_info->pathinfo; unsigned int len0=pathinfo->len - call_info->relpath, len1=localfile->pathinfo.len; char path[len0 + len1 + 1]; struct stat st; memcpy(path, localfile->pathinfo.path, len1); if (len0>0) { memcpy(path+len1, pathinfo->path + call_info->relpath, len0); len1+=len0; } path[len1]='\0'; memset(&st, 0, sizeof(struct stat)); logoutput("overlayfs_lookup_cached, path %s", path); if (lstat(path, &st)==-1) { fuse_reply_err(req, ENOENT); } else { struct entry_struct *entry=NULL, *parent=pinode->alias; struct inode_struct *inode; entry=create_entry(parent, xname); inode=create_inode(); if (entry && inode) { struct fuse_entry_param e; unsigned int error=0; add_inode_hashtable(inode, increase_inodes_workspace, (void *) call_info->workspace_mount); insert_entry(entry, &error, 0); adjust_pathmax(call_info->pathinfo.len); e.ino = inode->ino; e.generation = 1; e.attr_timeout = fs_options.attr_timeout; e.entry_timeout = fs_options.entry_timeout; e.attr.st_ino = e.ino; e.attr.st_mode = st.st_mode; e.attr.st_nlink = st.st_nlink; e.attr.st_uid = st.st_uid; e.attr.st_gid = st.st_gid; e.attr.st_rdev = st.st_rdev; e.attr.st_atim.tv_sec = st.st_atim.tv_sec; e.attr.st_atim.tv_nsec = st.st_atim.tv_nsec; e.attr.st_mtim.tv_sec = st.st_mtim.tv_sec; e.attr.st_mtim.tv_nsec = st.st_mtim.tv_nsec; e.attr.st_ctim.tv_sec = st.st_ctim.tv_sec; e.attr.st_ctim.tv_nsec = st.st_ctim.tv_nsec; e.attr.st_blksize=4096; e.attr.st_blocks=0; inode->mode=st.st_mode; inode->nlink=st.st_nlink; inode->uid=st.st_uid; inode->gid=st.st_gid; inode->rdev=st.st_rdev; if (S_ISDIR(st.st_mode)) { e.attr.st_size = 0; } else { inode->size=st.st_size; e.attr.st_size = st.st_size; } inode->mtim.tv_sec=st.st_mtim.tv_sec; inode->mtim.tv_nsec=st.st_mtim.tv_nsec; inode->ctim.tv_sec=st.st_ctim.tv_sec; inode->ctim.tv_nsec=st.st_ctim.tv_nsec; fuse_reply_entry(req, &e); } else { /* not enough memory to allocate entry and/or inode */ if (entry) { destroy_entry(entry); entry=NULL; } if (inode) { free(inode); inode=NULL; } fuse_reply_err(req, ENOMEM); } } free_path_pathinfo(&call_info->pathinfo); }
static void overlay_lookup_cached(fuse_req_t req, struct entry_struct *entry, struct call_info_struct *call_info) { struct resource_struct *resource=call_info->object->resource; struct localfile_struct *localfile=(struct localfile_struct *) resource->data; struct pathinfo_struct *pathinfo=&call_info->pathinfo; unsigned int len0=pathinfo->len - call_info->relpath, len1=localfile->pathinfo.len; char path[len0 + len1 + 1]; struct stat st; memcpy(path, localfile->pathinfo.path, len1); if (len0>0) { memcpy(path+len1, pathinfo->path + call_info->relpath, len0); len1+=len0; } path[len1]='\0'; memset(&st, 0, sizeof(struct stat)); logoutput("overlayfs_lookup_cached, path %s", path); if (lstat(path, &st)==-1) { struct inode_struct *inode=entry->inode; unsigned int error=0; inode=entry->inode; inode->alias=NULL; remove_entry(entry, &error); queue_remove(call_info->object, entry, &error); entry=NULL; fuse_reply_err(req, ENOENT); } else { struct fuse_entry_param e; struct inode_struct *inode=entry->inode; e.ino = inode->ino; e.generation = 1; e.attr_timeout = fs_options.attr_timeout; e.entry_timeout = fs_options.entry_timeout; e.attr.st_ino = e.ino; e.attr.st_mode = st.st_mode; e.attr.st_nlink = st.st_nlink; e.attr.st_uid = st.st_uid; e.attr.st_gid = st.st_gid; e.attr.st_rdev = st.st_rdev; e.attr.st_atim.tv_sec = st.st_atim.tv_sec; e.attr.st_atim.tv_nsec = st.st_atim.tv_nsec; e.attr.st_mtim.tv_sec = st.st_mtim.tv_sec; e.attr.st_mtim.tv_nsec = st.st_mtim.tv_nsec; e.attr.st_ctim.tv_sec = st.st_ctim.tv_sec; e.attr.st_ctim.tv_nsec = st.st_ctim.tv_nsec; e.attr.st_blksize=4096; e.attr.st_blocks=0; inode->mode=st.st_mode; inode->nlink=st.st_nlink; inode->uid=st.st_uid; inode->gid=st.st_gid; inode->rdev=st.st_rdev; if (S_ISDIR(st.st_mode)) { e.attr.st_size = 0; } else { inode->size=st.st_size; e.attr.st_size = st.st_size; } inode->mtim.tv_sec=st.st_mtim.tv_sec; inode->mtim.tv_nsec=st.st_mtim.tv_nsec; inode->ctim.tv_sec=st.st_ctim.tv_sec; inode->ctim.tv_nsec=st.st_ctim.tv_nsec; fuse_reply_entry(req, &e); } free_path_pathinfo(&call_info->pathinfo); }
static void workspace_nfs_lookup_cached(fuse_req_t req, struct entry_struct *entry, struct call_info_struct *call_info) { struct resource_struct *resource=call_info->object->resource; struct net_nfs_export_struct *nfs_export=(struct net_nfs_export_struct *) resource->data; struct nfs_context *nfs_ctx=(struct nfs_context *) nfs_export->data; char *path=call_info->pathinfo.path + call_info->relpath; struct stat st; int result=0; memset(&st, 0, sizeof(struct stat)); if (strlen(path)==0) path=(char *) rootpath; logoutput("workspace_nfs_lookup_cached, path %s", path); pthread_mutex_lock(&nfs_export->mutex); result=nfs_stat(nfs_ctx, path, &st); pthread_mutex_unlock(&nfs_export->mutex); if (result<0) { result=abs(result); if (result==ENOENT) { struct inode_struct *inode=entry->inode; unsigned int error=0; inode=entry->inode; inode->alias=NULL; remove_entry(entry, &error); queue_remove(call_info->object, entry, &error); entry=NULL; } fuse_reply_err(req, result); } else { struct fuse_entry_param e; struct inode_struct *inode=entry->inode; inode->mode=st.st_mode; inode->nlink=st.st_nlink; inode->uid=st.st_uid; inode->gid=st.st_gid; inode->rdev=st.st_rdev; inode->mtim.tv_sec=st.st_mtim.tv_sec; inode->mtim.tv_nsec=st.st_mtim.tv_nsec; inode->ctim.tv_sec=st.st_ctim.tv_sec; inode->ctim.tv_nsec=st.st_ctim.tv_nsec; inode->size=st.st_size; e.ino = inode->ino; e.generation = 1; e.attr_timeout = fs_options.attr_timeout; e.entry_timeout = fs_options.entry_timeout; get_current_time(&entry->synctime); e.attr.st_dev = 0; e.attr.st_ino = e.ino; e.attr.st_mode = st.st_mode; e.attr.st_nlink = st.st_nlink; e.attr.st_uid = st.st_uid; e.attr.st_gid = st.st_gid; e.attr.st_rdev = st.st_rdev; e.attr.st_size = st.st_size; e.attr.st_atim.tv_sec = st.st_atim.tv_sec; e.attr.st_atim.tv_nsec = st.st_atim.tv_nsec; e.attr.st_mtim.tv_sec = st.st_mtim.tv_sec; e.attr.st_mtim.tv_nsec = st.st_mtim.tv_nsec; e.attr.st_ctim.tv_sec = st.st_ctim.tv_sec; e.attr.st_ctim.tv_nsec = st.st_ctim.tv_nsec; e.attr.st_blksize=_DEFAULT_BLOCKSIZE; if (inode->size % e.attr.st_blksize == 0) { e.attr.st_blocks = inode->size / e.attr.st_blksize; } else { e.attr.st_blocks = 1 + inode->size / e.attr.st_blksize; } fuse_reply_entry(req, &e); } free_path_pathinfo(&call_info->pathinfo); }
static void workspace_nfs_mknod(fuse_req_t req, struct inode_struct *pinode, struct name_struct *xname, struct call_info_struct *call_info, mode_t mode, dev_t rdev) { struct resource_struct *resource=call_info->object->resource; struct net_nfs_export_struct *nfs_export=(struct net_nfs_export_struct *) resource->data; struct nfs_context *nfs_ctx=(struct nfs_context *) nfs_export->data; char *path=call_info->pathinfo.path + call_info->relpath; struct entry_struct *entry=NULL, *parent=pinode->alias; struct inode_struct *inode; logoutput("workspace_nfs_mknod, path %s", path); entry=create_entry(parent, xname); inode=create_inode(); if (entry && inode) { int result=0; inode->alias=entry; entry->inode=inode; pthread_mutex_lock(&nfs_export->mutex); result=nfs_mknod(nfs_ctx, path, mode, rdev); pthread_mutex_unlock(&nfs_export->mutex); if (result==0) { struct fuse_entry_param e; unsigned int error=0; struct stat st; memset(&st, 0, sizeof(struct stat)); add_inode_hashtable(inode, increase_inodes_workspace, (void *) call_info->object->workspace_mount); insert_entry(entry, &error, 0); adjust_pathmax(call_info->pathinfo.len); pthread_mutex_lock(&nfs_export->mutex); nfs_chmod(nfs_ctx, path, mode); nfs_stat(nfs_ctx, path, &st); pthread_mutex_unlock(&nfs_export->mutex); inode->nlookup=1; inode->mode=st.st_mode; inode->nlink=st.st_nlink; inode->uid=st.st_uid; inode->gid=st.st_gid; inode->rdev=st.st_rdev; inode->size=st.st_size; inode->mtim.tv_sec=st.st_mtim.tv_sec; inode->mtim.tv_nsec=st.st_mtim.tv_nsec; inode->ctim.tv_sec=st.st_ctim.tv_sec; inode->ctim.tv_nsec=st.st_ctim.tv_nsec; e.ino = inode->ino; e.generation = 1; e.attr_timeout = fs_options.attr_timeout; e.entry_timeout = fs_options.entry_timeout; e.attr.st_ino = e.ino; e.attr.st_mode = st.st_mode; e.attr.st_nlink = st.st_nlink; e.attr.st_uid = st.st_uid; e.attr.st_gid = st.st_gid; e.attr.st_rdev = st.st_rdev; e.attr.st_atim.tv_sec = st.st_atim.tv_sec; e.attr.st_atim.tv_nsec = st.st_atim.tv_nsec; e.attr.st_mtim.tv_sec = st.st_mtim.tv_sec; e.attr.st_mtim.tv_nsec = st.st_mtim.tv_nsec; e.attr.st_ctim.tv_sec = st.st_ctim.tv_sec; e.attr.st_ctim.tv_nsec = st.st_ctim.tv_nsec; e.attr.st_blksize=_DEFAULT_BLOCKSIZE; if (inode->size % e.attr.st_blksize == 0) { e.attr.st_blocks=inode->size / e.attr.st_blksize; } else { e.attr.st_blocks=1 + inode->size / e.attr.st_blksize; } fuse_reply_entry(req, &e); } else { /* error nfs create */ destroy_entry(entry); free(inode); fuse_reply_err(req, abs(result)); } } else { /* not enough memory to allocate entry and/or inode */ if (entry) { destroy_entry(entry); entry=NULL; } if (inode) { free(inode); inode=NULL; } fuse_reply_err(req, ENOMEM); } free_path_pathinfo(&call_info->pathinfo); }
static int zfsfuse_mknod(fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode, dev_t rdev) { if(strlen(name) >= MAXNAMELEN) return ENAMETOOLONG; vfs_t *vfs = (vfs_t *) fuse_req_userdata(req); zfsvfs_t *zfsvfs = vfs->vfs_data; ZFS_ENTER(zfsvfs); znode_t *znode; int error = zfs_zget(zfsvfs, parent, &znode, B_FALSE); if(error) { ZFS_EXIT(zfsvfs); /* If the inode we are trying to get was recently deleted dnode_hold_impl will return EEXIST instead of ENOENT */ return error == EEXIST ? ENOENT : error; } ASSERT(znode != NULL); vnode_t *dvp = ZTOV(znode); ASSERT(dvp != NULL); cred_t cred; zfsfuse_getcred(req, &cred); vattr_t vattr; vattr.va_type = IFTOVT(mode); vattr.va_mode = mode & PERMMASK; vattr.va_mask = AT_TYPE | AT_MODE; if(mode & (S_IFCHR | S_IFBLK)) { vattr.va_rdev = rdev; vattr.va_mask |= AT_RDEV; } vnode_t *vp = NULL; /* FIXME: check filesystem boundaries */ error = VOP_CREATE(dvp, (char *) name, &vattr, EXCL, 0, &vp, &cred, 0, NULL, NULL); VN_RELE(dvp); if(error) goto out; ASSERT(vp != NULL); struct fuse_entry_param e = { 0 }; e.attr_timeout = 0.0; e.entry_timeout = 0.0; e.ino = VTOZ(vp)->z_id; if(e.ino == 3) e.ino = 1; e.generation = VTOZ(vp)->z_phys->zp_gen; error = zfsfuse_stat(vp, &e.attr, &cred); out: if(vp != NULL) VN_RELE(vp); ZFS_EXIT(zfsvfs); if(!error) fuse_reply_entry(req, &e); return error; }