FSINFO3res *nfsproc3_fsinfo_3_svc(FSINFO3args * argp, struct svc_req * rqstp) { static FSINFO3res result; char *path; unsigned int maxdata; if (get_socket_type(rqstp) == SOCK_STREAM) maxdata = NFS_MAXDATA_TCP; else maxdata = NFS_MAXDATA_UDP; PREP(path, argp->fsroot); result.FSINFO3res_u.resok.obj_attributes = get_post_cached(rqstp); result.status = NFS3_OK; result.FSINFO3res_u.resok.rtmax = maxdata; result.FSINFO3res_u.resok.rtpref = maxdata; result.FSINFO3res_u.resok.rtmult = 4096; result.FSINFO3res_u.resok.wtmax = maxdata; result.FSINFO3res_u.resok.wtpref = maxdata; result.FSINFO3res_u.resok.wtmult = 4096; result.FSINFO3res_u.resok.dtpref = 4096; result.FSINFO3res_u.resok.maxfilesize = ~0ULL; result.FSINFO3res_u.resok.time_delta.seconds = backend_time_delta_seconds; result.FSINFO3res_u.resok.time_delta.nseconds = 0; result.FSINFO3res_u.resok.properties = backend_fsinfo_properties; return &result; }
SYMLINK3res *nfsproc3_symlink_3_svc(SYMLINK3args * argp, struct svc_req * rqstp) { static SYMLINK3res result; char *path; pre_op_attr pre; post_op_attr post; char obj[NFS_MAXPATHLEN]; int res; mode_t new_mode; PREP(path, argp->where.dir); pre = get_pre_cached(); result.status = join3(cat_name(path, argp->where.name, obj), atomic_attr(argp->symlink.symlink_attributes), exports_rw()); cluster_create(obj, rqstp, &result.status); if (argp->symlink.symlink_attributes.mode.set_it == TRUE) new_mode = create_mode(argp->symlink.symlink_attributes); else { /* default rwxrwxrwx */ new_mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH; } if (result.status == NFS3_OK) { umask(~new_mode); res = backend_symlink(argp->symlink.symlink_data, obj); umask(0); if (res == -1) result.status = symlink_err(); else { result.SYMLINK3res_u.resok.obj = fh_extend_type(argp->where.dir, obj, S_IFLNK); result.SYMLINK3res_u.resok.obj_attributes = get_post_cached(rqstp); } } post = get_post_attr(path, argp->where.dir, rqstp); /* overlaps with resfail */ result.SYMLINK3res_u.resok.dir_wcc.before = pre; result.SYMLINK3res_u.resok.dir_wcc.after = post; return &result; }
GETATTR3res *nfsproc3_getattr_3_svc(GETATTR3args * argp, struct svc_req * rqstp) { static GETATTR3res result; char *path; post_op_attr post; PREP(path, argp->object); post = get_post_cached(rqstp); result.status = NFS3_OK; result.GETATTR3res_u.resok.obj_attributes = post.post_op_attr_u.attributes; return &result; }
FSSTAT3res *nfsproc3_fsstat_3_svc(FSSTAT3args * argp, struct svc_req * rqstp) { static FSSTAT3res result; char *path; backend_statvfsstruct buf; int res; PREP(path, argp->fsroot); /* overlaps with resfail */ result.FSSTAT3res_u.resok.obj_attributes = get_post_cached(rqstp); res = backend_statvfs(path, &buf); if (res == -1) { /* statvfs fell on its nose */ if ((exports_opts & OPT_REMOVABLE) && export_point(path)) { /* Removable media export point; probably no media inserted. Return dummy values. */ result.status = NFS3_OK; result.FSSTAT3res_u.resok.tbytes = 0; result.FSSTAT3res_u.resok.fbytes = 0; result.FSSTAT3res_u.resok.abytes = 0; result.FSSTAT3res_u.resok.tfiles = 0; result.FSSTAT3res_u.resok.ffiles = 0; result.FSSTAT3res_u.resok.afiles = 0; result.FSSTAT3res_u.resok.invarsec = 0; } else { result.status = NFS3ERR_IO; } } else { result.status = NFS3_OK; result.FSSTAT3res_u.resok.tbytes = (uint64) buf.f_blocks * buf.f_frsize; result.FSSTAT3res_u.resok.fbytes = (uint64) buf.f_bfree * buf.f_frsize; result.FSSTAT3res_u.resok.abytes = (uint64) buf.f_bavail * buf.f_frsize; result.FSSTAT3res_u.resok.tfiles = buf.f_files; result.FSSTAT3res_u.resok.ffiles = buf.f_ffree; result.FSSTAT3res_u.resok.afiles = buf.f_ffree; result.FSSTAT3res_u.resok.invarsec = 0; } return &result; }
MKNOD3res *nfsproc3_mknod_3_svc(MKNOD3args * argp, struct svc_req * rqstp) { static MKNOD3res result; char *path; pre_op_attr pre; post_op_attr post; char obj[NFS_MAXPATHLEN]; int res; mode_t new_mode = 0; dev_t dev = 0; PREP(path, argp->where.dir); pre = get_pre_cached(); result.status = join3(cat_name(path, argp->where.name, obj), mknod_args(argp->what, obj, &new_mode, &dev), exports_rw()); cluster_create(obj, rqstp, &result.status); if (result.status == NFS3_OK) { if (argp->what.type == NF3CHR || argp->what.type == NF3BLK) res = backend_mknod(obj, new_mode, dev); /* device */ else if (argp->what.type == NF3FIFO) res = backend_mkfifo(obj, new_mode); /* FIFO */ else res = backend_mksocket(obj, new_mode); /* socket */ if (res == -1) { result.status = mknod_err(); } else { result.MKNOD3res_u.resok.obj = fh_extend_type(argp->where.dir, obj, type_to_mode(argp->what.type)); result.MKNOD3res_u.resok.obj_attributes = get_post_cached(rqstp); } } post = get_post_attr(path, argp->where.dir, rqstp); /* overlaps with resfail */ result.MKNOD3res_u.resok.dir_wcc.before = pre; result.MKNOD3res_u.resok.dir_wcc.after = post; return &result; }
ACCESS3res *nfsproc3_access_3_svc(ACCESS3args * argp, struct svc_req * rqstp) { static ACCESS3res result; char *path; post_op_attr post; mode_t mode; int newaccess = 0; PREP(path, argp->object); post = get_post_cached(rqstp); mode = post.post_op_attr_u.attributes.mode; if (access(path, R_OK) != -1) newaccess |= ACCESS3_READ; if (access(path, W_OK) != -1) newaccess |= ACCESS3_MODIFY | ACCESS3_EXTEND; if (access(path, X_OK) != -1) { newaccess |= ACCESS3_EXECUTE; if (opt_readable_executables) newaccess |= ACCESS3_READ; } /* root is allowed everything */ if (get_uid(rqstp) == 0) newaccess |= ACCESS3_READ | ACCESS3_MODIFY | ACCESS3_EXTEND; /* adjust if directory */ if (post.post_op_attr_u.attributes.type == NF3DIR) { if (newaccess & (ACCESS3_READ | ACCESS3_EXECUTE)) newaccess |= ACCESS3_LOOKUP; if (newaccess & ACCESS3_MODIFY) newaccess |= ACCESS3_DELETE; newaccess &= ~ACCESS3_EXECUTE; } result.status = NFS3_OK; result.ACCESS3res_u.resok.access = newaccess & argp->access; result.ACCESS3res_u.resok.obj_attributes = post; return &result; }
PATHCONF3res *nfsproc3_pathconf_3_svc(PATHCONF3args * argp, struct svc_req * rqstp) { static PATHCONF3res result; char *path; PREP(path, argp->object); result.PATHCONF3res_u.resok.obj_attributes = get_post_cached(rqstp); result.status = NFS3_OK; result.PATHCONF3res_u.resok.linkmax = 0xFFFFFFFF; result.PATHCONF3res_u.resok.name_max = NFS_MAXPATHLEN; result.PATHCONF3res_u.resok.no_trunc = TRUE; result.PATHCONF3res_u.resok.chown_restricted = FALSE; result.PATHCONF3res_u.resok.case_insensitive = backend_pathconf_case_insensitive; result.PATHCONF3res_u.resok.case_preserving = TRUE; return &result; }
MKDIR3res *nfsproc3_mkdir_3_svc(MKDIR3args * argp, struct svc_req * rqstp) { static MKDIR3res result; char *path; pre_op_attr pre; post_op_attr post; char obj[NFS_MAXPATHLEN]; int res; PREP(path, argp->where.dir); pre = get_pre_cached(); result.status = join3(cat_name(path, argp->where.name, obj), atomic_attr(argp->attributes), exports_rw()); cluster_create(obj, rqstp, &result.status); if (result.status == NFS3_OK) { res = backend_mkdir(obj, create_mode(argp->attributes)); if (res == -1) result.status = mkdir_err(); else { result.MKDIR3res_u.resok.obj = fh_extend_type(argp->where.dir, obj, S_IFDIR); result.MKDIR3res_u.resok.obj_attributes = get_post_cached(rqstp); } } post = get_post_attr(path, argp->where.dir, rqstp); /* overlaps with resfail */ result.MKDIR3res_u.resok.dir_wcc.before = pre; result.MKDIR3res_u.resok.dir_wcc.after = post; return &result; }
ACCESS3res *nfsproc3_access_3_svc(ACCESS3args * argp, struct svc_req * rqstp) { static ACCESS3res result; char *path; post_op_attr post; mode_t mode; int access = 0; PREP(path, argp->object); post = get_post_cached(rqstp); mode = post.post_op_attr_u.attributes.mode; /* owner permissions */ if (is_owner(st_cache.st_uid, rqstp)) { if (mode & S_IRUSR) access |= ACCESS3_READ; if (mode & S_IWUSR) access |= ACCESS3_MODIFY | ACCESS3_EXTEND; if (mode & S_IXUSR) { access |= ACCESS3_EXECUTE; if (opt_readable_executables) access |= ACCESS3_READ; } } else if (has_group(st_cache.st_gid, rqstp)) { /* group permissions */ if (mode & S_IRGRP) access |= ACCESS3_READ; if (mode & S_IWGRP) access |= ACCESS3_MODIFY | ACCESS3_EXTEND; if (mode & S_IXGRP) { access |= ACCESS3_EXECUTE; if (opt_readable_executables) access |= ACCESS3_READ; } } else { /* other permissions */ if (mode & S_IROTH) access |= ACCESS3_READ; if (mode & S_IWOTH) access |= ACCESS3_MODIFY | ACCESS3_EXTEND; if (mode & S_IXOTH) { access |= ACCESS3_EXECUTE; if (opt_readable_executables) access |= ACCESS3_READ; } } /* root is allowed everything */ if (get_uid(rqstp) == 0) access |= ACCESS3_READ | ACCESS3_MODIFY | ACCESS3_EXTEND; /* adjust if directory */ if (post.post_op_attr_u.attributes.type == NF3DIR) { if (access & (ACCESS3_READ | ACCESS3_EXECUTE)) access |= ACCESS3_LOOKUP; if (access & ACCESS3_MODIFY) access |= ACCESS3_DELETE; access &= ~ACCESS3_EXECUTE; } result.status = NFS3_OK; result.ACCESS3res_u.resok.access = access & argp->access; result.ACCESS3res_u.resok.obj_attributes = post; return &result; }