int main(int argc, char *argv[]) { struct nfs_context *nfs; struct nfs_url *url; uint64_t length; struct nfs_stat_64 st; if (argc != 5) { usage(); } length = strtol(argv[4], NULL, 10); nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); exit(1); } url = nfs_parse_url_full(nfs, argv[1]); if (url == NULL) { fprintf(stderr, "%s\n", nfs_get_error(nfs)); exit(1); } if (nfs_mount(nfs, url->server, url->path) != 0) { fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); exit(1); } if (nfs_chdir(nfs, argv[2]) != 0) { fprintf(stderr, "Failed to chdir to \"%s\" : %s\n", argv[2], nfs_get_error(nfs)); exit(1); } if (nfs_truncate(nfs, argv[3], length)) { fprintf(stderr, "Failed to truncate file : %s\n", nfs_get_error(nfs)); exit(1); } if (nfs_stat64(nfs, argv[3], &st)) { fprintf(stderr, "Failed to stat file : %s\n", nfs_get_error(nfs)); exit(1); } if (st.nfs_size != length) { fprintf(stderr, "Unexpected file size. Expected %d got %d\n", (int)length, (int)st.nfs_size); exit(1); } nfs_destroy_url(url); nfs_destroy_context(nfs); return 0; }
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); }