static int fuse_nfs_mkdir(const char *path, mode_t mode) { int ret = 0; ret = nfs_mkdir(nfs, path); if (ret < 0) { return ret; } ret = nfs_chmod(nfs, path, mode); if (ret < 0) { return ret; } return ret; }
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 void workspace_nfs_setattr(fuse_req_t req, struct entry_struct *entry, struct call_info_struct *call_info, struct stat *st, int fuse_set) { 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; int result=0; struct inode_struct *inode=entry->inode; if (strlen(path)==0) path=(char *) rootpath; logoutput("workspace_nfs_setattr, path %s", path); if (fuse_set & FUSE_SET_ATTR_MODE) { pthread_mutex_lock(&nfs_export->mutex); result=nfs_chmod(nfs_ctx, path, st->st_mode); pthread_mutex_unlock(&nfs_export->mutex); if (result<0) { fuse_reply_err(req, -result); free_path_pathinfo(&call_info->pathinfo); return; } else { inode->mode=st->st_mode; } } if (fuse_set & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID)) { uid_t uid=inode->uid; gid_t gid=inode->gid; if (fuse_set & FUSE_SET_ATTR_UID) uid=st->st_uid; if (fuse_set & FUSE_SET_ATTR_GID) gid=st->st_gid; result=nfs_chown(nfs_ctx, path, uid, gid); if (result<0) { fuse_reply_err(req, -result); free_path_pathinfo(&call_info->pathinfo); return; } else { if (fuse_set & FUSE_SET_ATTR_UID) { inode->uid=st->st_uid; } else { st->st_uid=inode->uid; } if (fuse_set & FUSE_SET_ATTR_GID) { inode->gid=st->st_gid; } else { st->st_gid=inode->gid; } } } if (fuse_set & FUSE_SET_ATTR_SIZE) { pthread_mutex_lock(&nfs_export->mutex); result=nfs_truncate(nfs_ctx, path, st->st_size); pthread_mutex_unlock(&nfs_export->mutex); if (result<0) { fuse_reply_err(req, -result); free_path_pathinfo(&call_info->pathinfo); return; } else { inode->size=st->st_size; } } if (fuse_set & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) { struct timespec rightnow; struct timeval newtimes[2]; newtimes[0].tv_sec=0; newtimes[0].tv_usec=0; newtimes[1].tv_sec=inode->mtim.tv_sec; newtimes[1].tv_usec=inode->mtim.tv_nsec / 1000; if (fuse_set & (FUSE_SET_ATTR_ATIME_NOW | FUSE_SET_ATTR_MTIME_NOW)) get_current_time(&rightnow); if (fuse_set & FUSE_SET_ATTR_ATIME) { if (fuse_set & FUSE_SET_ATTR_ATIME_NOW) { st->st_atim.tv_sec = rightnow.tv_sec; st->st_atim.tv_nsec = rightnow.tv_nsec; } newtimes[0].tv_sec=st->st_atim.tv_sec; newtimes[0].tv_usec = st->st_atim.tv_nsec / 1000; } if (fuse_set & FUSE_SET_ATTR_MTIME) { if (fuse_set & FUSE_SET_ATTR_MTIME_NOW) { st->st_mtim.tv_sec = rightnow.tv_sec; st->st_mtim.tv_nsec = rightnow.tv_nsec; } newtimes[1].tv_sec = st->st_mtim.tv_sec; newtimes[1].tv_usec = st->st_mtim.tv_nsec / 1000; } pthread_mutex_lock(&nfs_export->mutex); result=nfs_utimes(nfs_ctx, path, newtimes); pthread_mutex_unlock(&nfs_export->mutex); if (result<0) { fuse_reply_err(req, -result); free_path_pathinfo(&call_info->pathinfo); return; } else { if (fuse_set & FUSE_SET_ATTR_MTIME) { inode->mtim.tv_sec=newtimes[1].tv_sec; inode->mtim.tv_nsec=newtimes[1].tv_usec * 1000; } } } out: st->st_dev=0; st->st_ino=inode->ino; st->st_mode=inode->mode; st->st_nlink=inode->nlink; st->st_uid=inode->uid; st->st_gid=inode->gid; st->st_rdev=inode->rdev; st->st_size=inode->size; st->st_blksize=_DEFAULT_BLOCKSIZE; if (inode->size % st->st_blksize == 0) { st->st_blocks = inode->size / st->st_blksize; } else { st->st_blocks = 1 + inode->size / st->st_blksize; } memcpy(&st->st_mtim, &inode->mtim, sizeof(struct timespec)); memcpy(&st->st_ctim, &inode->ctim, sizeof(struct timespec)); st->st_atim.tv_sec=0; st->st_atim.tv_nsec=0; fuse_reply_attr(req, st, fs_options.attr_timeout); free_path_pathinfo(&call_info->pathinfo); }