/* * Decode STATFS reply */ static int nfs_xdr_statfsres(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res) { int status; u32 xfer_size; if ((status = ntohl(*p++))) return -nfs_stat_to_errno(status); /* For NFSv2, we more or less have to guess the preferred * read/write/readdir sizes from the single 'transfer size' * value. */ xfer_size = ntohl(*p++); /* tsize */ res->rtmax = 8 * 1024; res->rtpref = xfer_size; res->rtmult = xfer_size; res->wtmax = 8 * 1024; res->wtpref = xfer_size; res->wtmult = xfer_size; res->dtpref = PAGE_CACHE_SIZE; res->maxfilesize = 0x7FFFFFFF; /* just a guess */ res->bsize = ntohl(*p++); res->tbytes = ntohl(*p++) * res->bsize; res->fbytes = ntohl(*p++) * res->bsize; res->abytes = ntohl(*p++) * res->bsize; res->tfiles = 0; res->ffiles = 0; res->afiles = 0; res->namelen = 0; return 0; }
/* * Decode the result of a readdir call. * We're not really decoding anymore, we just leave the buffer untouched * and only check that it is syntactically correct. * The real decoding happens in nfs_decode_entry below, called directly * from nfs_readdir for each entry. */ static int nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy) { struct xdr_buf *rcvbuf = &req->rq_rcv_buf; struct kvec *iov = rcvbuf->head; struct page **page; size_t hdrlen; unsigned int pglen, recvd; int status; if ((status = ntohl(*p++))) return nfs_stat_to_errno(status); hdrlen = (u8 *) p - (u8 *) iov->iov_base; if (iov->iov_len < hdrlen) { dprintk("NFS: READDIR reply header overflowed:" "length %Zu > %Zu\n", hdrlen, iov->iov_len); return -errno_NFSERR_IO; } else if (iov->iov_len != hdrlen) { dprintk("NFS: READDIR header is short. iovec will be shifted.\n"); xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen); } pglen = rcvbuf->page_len; recvd = rcvbuf->len - hdrlen; if (pglen > recvd) pglen = recvd; page = rcvbuf->pages; return pglen; }
/* * Decode READLINK reply */ static int nfs_xdr_readlinkres(struct rpc_rqst *req, u32 *p, void *dummy) { struct xdr_buf *rcvbuf = &req->rq_rcv_buf; struct iovec *iov = rcvbuf->head; unsigned int hdrlen; u32 *strlen, len; char *string; int status; if ((status = ntohl(*p++))) return -nfs_stat_to_errno(status); hdrlen = (u8 *) p - (u8 *) iov->iov_base; if (iov->iov_len > hdrlen) { dprintk("NFS: READLINK header is short. iovec will be shifted.\n"); xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen); } strlen = (u32*)kmap_atomic(rcvbuf->pages[0], KM_USER0); /* Convert length of symlink */ len = ntohl(*strlen); if (len >= rcvbuf->page_len - sizeof(u32) || len > NFS2_MAXPATHLEN) { dprintk("NFS: READLINK server returned giant symlink!\n"); kunmap_atomic(strlen, KM_USER0); return -ENAMETOOLONG; } *strlen = len; /* NULL terminate the string we got */ string = (char *)(strlen + 1); string[len] = 0; kunmap_atomic(strlen, KM_USER0); return 0; }
/* * Decode READ reply */ static int nfs_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res) { struct kvec *iov = req->rq_rcv_buf.head; int status, count, recvd, hdrlen; if ((status = ntohl(*p++))) return -nfs_stat_to_errno(status); p = xdr_decode_fattr(p, res->fattr); count = ntohl(*p++); res->eof = 0; hdrlen = (u8 *) p - (u8 *) iov->iov_base; if (iov->iov_len < hdrlen) { printk(KERN_WARNING "NFS: READ reply header overflowed:" "length %d > %Zu\n", hdrlen, iov->iov_len); return -errno_NFSERR_IO; } else if (iov->iov_len != hdrlen) { dprintk("NFS: READ header is short. iovec will be shifted.\n"); xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen); } recvd = req->rq_rcv_buf.len - hdrlen; if (count > recvd) { printk(KERN_WARNING "NFS: server cheating in read reply: " "count %d > recvd %d\n", count, recvd); count = recvd; } dprintk("RPC: readres OK count %d\n", count); if (count < res->count) res->count = count; return count; }
int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *res) { int *p, *p0; int status; int ruid = 0; PRINTK("NFS call statfs\n"); if (!(p0 = nfs_rpc_alloc(server->rsize))) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_STATFS, ruid); p = xdr_encode_fhandle(p, fhandle); if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) { nfs_rpc_free(p0); return status; } if (!(p = nfs_rpc_verify(p0))) status = -errno_NFSERR_IO; else if ((status = ntohl(*p++)) == NFS_OK) { p = xdr_decode_fsinfo(p, res); PRINTK("NFS reply statfs\n"); /* status = 0; */ } else { if (!ruid && current->fsuid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply statfs failed = %d\n", status); status = -nfs_stat_to_errno(status); } nfs_rpc_free(p0); return status; }
int nfs_proc_rmdir(struct nfs_server *server, struct nfs_fh *dir, const char *name) { int *p, *p0; int status; int ruid = 0; PRINTK("NFS call rmdir %s\n", name); if (!(p0 = nfs_rpc_alloc(server->wsize))) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_RMDIR, ruid); p = xdr_encode_fhandle(p, dir); p = xdr_encode_string(p, name); if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) { nfs_rpc_free(p0); return status; } if (!(p = nfs_rpc_verify(p0))) status = -errno_NFSERR_IO; else if ((status = ntohl(*p++)) == NFS_OK) { PRINTK("NFS reply rmdir\n"); /* status = 0; */ } else { if (!ruid && current->fsuid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply rmdir failed = %d\n", status); status = -nfs_stat_to_errno(status); } nfs_rpc_free(p0); return status; }
int nfs_proc_readlink(struct nfs_server *server, struct nfs_fh *fhandle, int **p0, char **string, unsigned int *len, unsigned int maxlen) { int *p; int status, ruid = 0; PRINTK("NFS call readlink\n"); if (!(*p0 = nfs_rpc_alloc(server->rsize))) return -EIO; retry: p = nfs_rpc_header(*p0, NFSPROC_READLINK, ruid); p = xdr_encode_fhandle(p, fhandle); if ((status = nfs_rpc_call(server, *p0, p, server->rsize)) < 0) return status; if (!(p = nfs_rpc_verify(*p0))) status = -errno_NFSERR_IO; else if ((status = ntohl(*p++)) == NFS_OK) { if (!(p = xdr_decode_string2(p, string, len, maxlen))) { printk("nfs_proc_readlink: giant pathname\n"); status = -errno_NFSERR_IO; } else /* status = 0, */ PRINTK("NFS reply readlink\n"); } else { if (!ruid && current->fsuid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply readlink failed = %d\n", status); status = -nfs_stat_to_errno(status); } return status; }
int nfs_proc_symlink(struct nfs_server *server, struct nfs_fh *dir, const char *name, const char *path, struct nfs_sattr *sattr) { int *p, *p0; int status; int ruid = 0; PRINTK("NFS call symlink %s -> %s\n", name, path); if (!(p0 = nfs_rpc_alloc())) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_SYMLINK, ruid); p = xdr_encode_fhandle(p, dir); p = xdr_encode_string(p, name); p = xdr_encode_string(p, path); p = xdr_encode_sattr(p, sattr); if ((status = nfs_rpc_call(server, p0, p)) < 0) { nfs_rpc_free(p0); return status; } if (!(p = nfs_rpc_verify(p0))) status = NFSERR_IO; else if ((status = ntohl(*p++)) == NFS_OK) { PRINTK("NFS reply symlink\n"); } else { if (!ruid && current->euid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply symlink failed = %d\n", status); } nfs_rpc_free(p0); return -nfs_stat_to_errno(status); }
int nfs_proc_setattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_sattr *sattr, struct nfs_fattr *fattr) { int *p, *p0; int status; int ruid = 0; PRINTK("NFS call setattr\n"); if (!(p0 = nfs_rpc_alloc())) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_SETATTR, ruid); p = xdr_encode_fhandle(p, fhandle); p = xdr_encode_sattr(p, sattr); if ((status = nfs_rpc_call(server, p0, p)) < 0) { nfs_rpc_free(p0); return status; } if (!(p = nfs_rpc_verify(p0))) status = NFSERR_IO; else if ((status = ntohl(*p++)) == NFS_OK) { p = xdr_decode_fattr(p, fattr); PRINTK("NFS reply setattr\n"); } else { if (!ruid && current->euid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply setattr failed = %d\n", status); } nfs_rpc_free(p0); return -nfs_stat_to_errno(status); }
static int nfs3_xdr_dec_lookup3res(struct rpc_rqst *req, struct xdr_stream *xdr, struct nfs3_diropres *result) { enum nfs_stat status; int error; error = decode_nfsstat3(xdr, &status); if (unlikely(error)) goto out; if (status != NFS3_OK) goto out_default; error = decode_nfs_fh3(xdr, result->fh); if (unlikely(error)) goto out; error = decode_post_op_attr(xdr, result->fattr); if (unlikely(error)) goto out; error = decode_post_op_attr(xdr, result->dir_attr); out: return error; out_default: error = decode_post_op_attr(xdr, result->dir_attr); if (unlikely(error)) goto out; return nfs_stat_to_errno(status); }
/* * Decode simple status reply */ static int nfs_xdr_stat(struct rpc_rqst *req, u32 *p, void *dummy) { int status; if ((status = ntohl(*p++)) != 0) status = -nfs_stat_to_errno(status); return status; }
/* * Decode attrstat reply * GETATTR, SETATTR, WRITE */ static int nfs_xdr_attrstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr) { int status; if ((status = ntohl(*p++))) return -nfs_stat_to_errno(status); xdr_decode_fattr(p, fattr); return 0; }
int nfs_proc_readdir(struct nfs_server *server, struct nfs_fh *fhandle, int cookie, int count, struct nfs_entry *entry) { int *p, *p0; int status; int ruid = 0; int i; int size; int eof; PRINTK("NFS call readdir %d @ %d\n", count, cookie); size = server->rsize; if (!(p0 = nfs_rpc_alloc(server->rsize))) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_READDIR, ruid); p = xdr_encode_fhandle(p, fhandle); *p++ = htonl(cookie); *p++ = htonl(size); if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) { nfs_rpc_free(p0); return status; } if (!(p = nfs_rpc_verify(p0))) status = -errno_NFSERR_IO; else if ((status = ntohl(*p++)) == NFS_OK) { for (i = 0; i < count && *p++; i++) { if (!(p = xdr_decode_entry(p, entry++))) break; } if (!p) { printk("nfs_proc_readdir: giant filename\n"); status = -errno_NFSERR_IO; } else { eof = (i == count && !*p++ && *p++) || (i < count && *p++); if (eof && i) entry[-1].eof = 1; PRINTK("NFS reply readdir %d %s\n", i, eof ? "eof" : ""); status = i; } } else { if (!ruid && current->fsuid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply readdir failed = %d\n", status); status = -nfs_stat_to_errno(status); } nfs_rpc_free(p0); return status; }
/* * Decode diropres reply * LOOKUP, CREATE, MKDIR */ static int nfs_xdr_diropres(struct rpc_rqst *req, u32 *p, struct nfs_diropok *res) { int status; if ((status = ntohl(*p++))) return -nfs_stat_to_errno(status); p = xdr_decode_fhandle(p, res->fh); xdr_decode_fattr(p, res->fattr); return 0; }
/* * Decode STATFS reply */ static int nfs_xdr_statfsres(struct rpc_rqst *req, u32 *p, struct nfs2_fsstat *res) { int status; if ((status = ntohl(*p++))) return -nfs_stat_to_errno(status); res->tsize = ntohl(*p++); res->bsize = ntohl(*p++); res->blocks = ntohl(*p++); res->bfree = ntohl(*p++); res->bavail = ntohl(*p++); return 0; }
static int nfs2_xdr_dec_stat(struct rpc_rqst *req, struct xdr_stream *xdr, void *__unused) { enum nfs_stat status; int error; error = decode_stat(xdr, &status); if (unlikely(error)) goto out; if (status != NFS_OK) goto out_default; out: return error; out_default: return nfs_stat_to_errno(status); }
static int decode_diropres(struct xdr_stream *xdr, struct nfs_diropok *result) { enum nfs_stat status; int error; error = decode_stat(xdr, &status); if (unlikely(error)) goto out; if (status != NFS_OK) goto out_default; error = decode_diropok(xdr, result); out: return error; out_default: return nfs_stat_to_errno(status); }
static int nfs2_xdr_dec_statfsres(struct rpc_rqst *req, struct xdr_stream *xdr, struct nfs2_fsstat *result) { enum nfs_stat status; int error; error = decode_stat(xdr, &status); if (unlikely(error)) goto out; if (status != NFS_OK) goto out_default; error = decode_info(xdr, result); out: return error; out_default: return nfs_stat_to_errno(status); }
int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle, int offset, int count, char *data, struct nfs_fattr *fattr, int fs) { int *p, *p0; int status; int ruid = 0; int len; PRINTK("NFS call read %d @ %d\n", count, offset); if (!(p0 = nfs_rpc_alloc(server->rsize))) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_READ, ruid); p = xdr_encode_fhandle(p, fhandle); *p++ = htonl(offset); *p++ = htonl(count); *p++ = htonl(count); /* traditional, could be any value */ if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) { nfs_rpc_free(p0); return status; } if (!(p = nfs_rpc_verify(p0))) status = -errno_NFSERR_IO; else if ((status = ntohl(*p++)) == NFS_OK) { p = xdr_decode_fattr(p, fattr); if (!(p = xdr_decode_data(p, data, &len, count, fs))) { printk("nfs_proc_read: giant data size\n"); status = -errno_NFSERR_IO; } else { status = len; PRINTK("NFS reply read %d\n", len); } } else { if (!ruid && current->fsuid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply read failed = %d\n", status); status = -nfs_stat_to_errno(status); } nfs_rpc_free(p0); return status; }
static int nfs3_xdr_dec_getattr3res(struct rpc_rqst *req, struct xdr_stream *xdr, struct nfs_fattr *result) { enum nfs_stat status; int error; error = decode_nfsstat3(xdr, &status); if (unlikely(error)) goto out; if (status != NFS3_OK) goto out_default; error = decode_fattr3(xdr, result); out: return error; out_default: return nfs_stat_to_errno(status); }
/* * Decode the result of a readdir call. * We're not really decoding anymore, we just leave the buffer untouched * and only check that it is syntactically correct. * The real decoding happens in nfs_decode_entry below, called directly * from nfs_readdir for each entry. */ static int nfs_xdr_readdirres(struct rpc_rqst *req, u32 *p, struct nfs_readdirres *res) { struct iovec *iov = req->rq_rvec; int status, nr; u32 *end, *entry, len; if ((status = ntohl(*p++))) return -nfs_stat_to_errno(status); if ((void *) p != ((u8 *) iov->iov_base+iov->iov_len)) { /* Unexpected reply header size. Punt. */ printk(KERN_WARNING "NFS: Odd RPC header size in readdirres reply\n"); return -errno_NFSERR_IO; } /* Get start and end address of XDR data */ p = (u32 *) iov[1].iov_base; end = (u32 *) ((u8 *) p + iov[1].iov_len); /* Get start and end of dirent buffer */ if (res->buffer != p) { printk(KERN_ERR "NFS: Bad result buffer in readdir\n"); return -errno_NFSERR_IO; } for (nr = 0; *p++; nr++) { entry = p - 1; p++; /* fileid */ len = ntohl(*p++); p += XDR_QUADLEN(len) + 1; /* name plus cookie */ if (len > NFS2_MAXNAMLEN) { printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)!\n", len); return -errno_NFSERR_IO; } if (p + 2 > end) { printk(KERN_NOTICE "NFS: short packet in readdir reply!\n"); entry[0] = entry[1] = 0; break; } } return nr; }
/* not parallel */ int nfs_proc_read_np(struct nfs_fh *fhandle, int offset, int count, char *data, struct nfs_fattr *fattr) { int *p; int len = 0; int status; int ruid = 0; struct generic_server *server = fhandle->server; int *p0; DPRINTF(CLUHELP_LEVEL,("NFS call read %d @ %d\n", count, offset)); if (!(p0 = overhead_rpc_alloc(server->rsize))) return -EIO; p = nfs_rpc_header(p0, NFSPROC_READ, ruid); p = xdr_encode_fhandle(p, fhandle); *p++ = htonl(offset); *p++ = htonl(count); *p++ = htonl(count); /* traditional, could be any value */ DPRINTF(CLUHELP_LEVEL,("ORIGNAL\n")); /* print_rpc2(p0,128); */ if ((status = generic_rpc_call(server, p0, p)) < 0) { overhead_rpc_free(p0); return status; } if (!(p = generic_rpc_verify(p0))) status = NFSERR_IO; else if ((status = ntohl(*p++)) == NFS_OK) { p = xdr_decode_fattr(p, fattr); if (!(p = xdr_decode_data(p, data, &len, count))) { DPRINTF(CLUHELP_LEVEL,("nfs_proc_read: giant data size\n")); status = NFSERR_IO; } else DPRINTF(CLUHELP_LEVEL,("NFS reply read %d\n", len)); } overhead_rpc_free(p0); return (status == NFS_OK) ? len : nfs_stat_to_errno(status); }
static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, struct xdr_stream *xdr, struct nfs_readres *result) { enum nfs_stat status; int error; error = decode_nfsstat3(xdr, &status); if (unlikely(error)) goto out; error = decode_post_op_attr(xdr, result->fattr); if (unlikely(error)) goto out; if (status != NFS3_OK) goto out_status; error = decode_read3resok(xdr, result); out: return error; out_status: return nfs_stat_to_errno(status); }
static int nfs3_xdr_dec_remove3res(struct rpc_rqst *req, struct xdr_stream *xdr, struct nfs_removeres *result) { enum nfs_stat status; int error; error = decode_nfsstat3(xdr, &status); if (unlikely(error)) goto out; error = decode_wcc_data(xdr, result->dir_attr); if (unlikely(error)) goto out; if (status != NFS3_OK) goto out_status; out: return error; out_status: return nfs_stat_to_errno(status); }
/* * 2.2.7. readres * * union readres switch (stat status) { * case NFS_OK: * fattr attributes; * nfsdata data; * default: * void; * }; */ static int nfs2_xdr_dec_readres(struct rpc_rqst *req, struct xdr_stream *xdr, struct nfs_readres *result) { enum nfs_stat status; int error; error = decode_stat(xdr, &status); if (unlikely(error)) goto out; if (status != NFS_OK) goto out_default; error = decode_fattr(xdr, result->fattr); if (unlikely(error)) goto out; error = decode_nfsdata(xdr, result); out: return error; out_default: return nfs_stat_to_errno(status); }
int nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir, const char *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr) { int *p, *p0; int status; int ruid = 0; PRINTK("NFS call lookup %s\n", name); #ifdef NFS_PROC_DEBUG if (!strcmp(name, "xyzzy")) proc_debug = 1 - proc_debug; #endif if (!(p0 = nfs_rpc_alloc(server->rsize))) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_LOOKUP, ruid); p = xdr_encode_fhandle(p, dir); p = xdr_encode_string(p, name); if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) { nfs_rpc_free(p0); return status; } if (!(p = nfs_rpc_verify(p0))) status = -errno_NFSERR_IO; else if ((status = ntohl(*p++)) == NFS_OK) { p = xdr_decode_fhandle(p, fhandle); p = xdr_decode_fattr(p, fattr); PRINTK("NFS reply lookup\n"); /* status = 0; */ } else { if (!ruid && current->fsuid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply lookup failed = %d\n", status); status = -nfs_stat_to_errno(status); } nfs_rpc_free(p0); return status; }
/* * Decode READLINK reply */ static int nfs_xdr_readlinkres(struct rpc_rqst *req, u32 *p, struct nfs_readlinkres *res) { u32 *strlen; char *string; int status; unsigned int len; if ((status = ntohl(*p++))) return -nfs_stat_to_errno(status); strlen = (u32*)res->buffer; /* Convert length of symlink */ len = ntohl(*strlen); if (len > res->bufsiz - 5) len = res->bufsiz - 5; *strlen = len; /* NULL terminate the string we got */ string = (char *)(strlen + 1); string[len] = 0; return 0; }
static int nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy) { struct xdr_buf *rcvbuf = &req->rq_rcv_buf; struct kvec *iov = rcvbuf->head; size_t hdrlen; u32 len, recvd; char *kaddr; int status; if ((status = ntohl(*p++))) return nfs_stat_to_errno(status); /* Convert length of symlink */ len = ntohl(*p++); if (len >= rcvbuf->page_len) { dprintk("nfs: server returned giant symlink!\n"); return -ENAMETOOLONG; } hdrlen = (u8 *) p - (u8 *) iov->iov_base; if (iov->iov_len < hdrlen) { dprintk("NFS: READLINK reply header overflowed:" "length %Zu > %Zu\n", hdrlen, iov->iov_len); return -errno_NFSERR_IO; } else if (iov->iov_len != hdrlen) { dprintk("NFS: READLINK header is short. iovec will be shifted.\n"); xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen); } recvd = req->rq_rcv_buf.len - hdrlen; if (recvd < len) { dprintk("NFS: server cheating in readlink reply: " "count %u > recvd %u\n", len, recvd); return -EIO; } /* NULL terminate the string we got */ kaddr = (char *)kmap_atomic(rcvbuf->pages[0], KM_USER0); kaddr[len+rcvbuf->page_base] = '\0'; kunmap_atomic(kaddr, KM_USER0); return 0; }
int nfs_proc_write(struct nfs_server *server, struct nfs_fh *fhandle, int offset, int count, char *data, struct nfs_fattr *fattr) { int *p, *p0; int status; int ruid = 0; PRINTK("NFS call write %d @ %d\n", count, offset); if (!(p0 = nfs_rpc_alloc(server->wsize))) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_WRITE, ruid); p = xdr_encode_fhandle(p, fhandle); *p++ = htonl(offset); /* traditional, could be any value */ *p++ = htonl(offset); *p++ = htonl(count); /* traditional, could be any value */ p = xdr_encode_data(p, data, count); if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) { nfs_rpc_free(p0); return status; } if (!(p = nfs_rpc_verify(p0))) status = -errno_NFSERR_IO; else if ((status = ntohl(*p++)) == NFS_OK) { p = xdr_decode_fattr(p, fattr); PRINTK("NFS reply write\n"); /* status = 0; */ } else { if (!ruid && current->fsuid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply write failed = %d\n", status); status = -nfs_stat_to_errno(status); } nfs_rpc_free(p0); return status; }
int nfs_proc_readlink(struct nfs_server *server, struct nfs_fh *fhandle, char *res) { int *p, *p0; int status; int ruid = 0; PRINTK("NFS call readlink\n"); if (!(p0 = nfs_rpc_alloc())) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_READLINK, ruid); p = xdr_encode_fhandle(p, fhandle); if ((status = nfs_rpc_call(server, p0, p)) < 0) { nfs_rpc_free(p0); return status; } if (!(p = nfs_rpc_verify(p0))) status = NFSERR_IO; else if ((status = ntohl(*p++)) == NFS_OK) { if (!(p = xdr_decode_string(p, res, NFS_MAXPATHLEN))) { printk("nfs_proc_readlink: giant pathname\n"); status = NFSERR_IO; } else PRINTK("NFS reply readlink %s\n", res); } else { if (!ruid && current->euid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply readlink failed = %d\n", status); } nfs_rpc_free(p0); return -nfs_stat_to_errno(status); }