GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / fs / nfsd / nfsxdr.c
blobff6482b2a69f9fd7bfacce0798b05779ebc98c04
1 /*
2 * XDR support for nfsd
4 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
5 */
7 #include "xdr.h"
8 #include "auth.h"
10 #define NFSDDBG_FACILITY NFSDDBG_XDR
13 * Mapping of S_IF* types to NFS file types
15 static u32 nfs_ftypes[] = {
16 NFNON, NFCHR, NFCHR, NFBAD,
17 NFDIR, NFBAD, NFBLK, NFBAD,
18 NFREG, NFBAD, NFLNK, NFBAD,
19 NFSOCK, NFBAD, NFLNK, NFBAD,
24 * XDR functions for basic NFS types
26 static __be32 *
27 decode_fh(__be32 *p, struct svc_fh *fhp)
29 fh_init(fhp, NFS_FHSIZE);
30 memcpy(&fhp->fh_handle.fh_base, p, NFS_FHSIZE);
31 fhp->fh_handle.fh_size = NFS_FHSIZE;
33 return p + (NFS_FHSIZE >> 2);
36 /* Helper function for NFSv2 ACL code */
37 __be32 *nfs2svc_decode_fh(__be32 *p, struct svc_fh *fhp)
39 return decode_fh(p, fhp);
42 static __be32 *
43 encode_fh(__be32 *p, struct svc_fh *fhp)
45 memcpy(p, &fhp->fh_handle.fh_base, NFS_FHSIZE);
46 return p + (NFS_FHSIZE>> 2);
50 * Decode a file name and make sure that the path contains
51 * no slashes or null bytes.
53 static __be32 *
54 decode_filename(__be32 *p, char **namp, unsigned int *lenp)
56 char *name;
57 unsigned int i;
59 if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS_MAXNAMLEN)) != NULL) {
60 for (i = 0, name = *namp; i < *lenp; i++, name++) {
61 if (*name == '\0' || *name == '/')
62 return NULL;
66 return p;
69 static __be32 *
70 decode_pathname(__be32 *p, char **namp, unsigned int *lenp)
72 char *name;
73 unsigned int i;
75 if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS_MAXPATHLEN)) != NULL) {
76 for (i = 0, name = *namp; i < *lenp; i++, name++) {
77 if (*name == '\0')
78 return NULL;
82 return p;
85 static __be32 *
86 decode_sattr(__be32 *p, struct iattr *iap)
88 u32 tmp, tmp1;
90 iap->ia_valid = 0;
92 /* Sun client bug compatibility check: some sun clients seem to
93 * put 0xffff in the mode field when they mean 0xffffffff.
94 * Quoting the 4.4BSD nfs server code: Nah nah nah nah na nah.
96 if ((tmp = ntohl(*p++)) != (u32)-1 && tmp != 0xffff) {
97 iap->ia_valid |= ATTR_MODE;
98 iap->ia_mode = tmp;
100 if ((tmp = ntohl(*p++)) != (u32)-1) {
101 iap->ia_valid |= ATTR_UID;
102 iap->ia_uid = tmp;
104 if ((tmp = ntohl(*p++)) != (u32)-1) {
105 iap->ia_valid |= ATTR_GID;
106 iap->ia_gid = tmp;
108 if ((tmp = ntohl(*p++)) != (u32)-1) {
109 iap->ia_valid |= ATTR_SIZE;
110 iap->ia_size = tmp;
112 tmp = ntohl(*p++); tmp1 = ntohl(*p++);
113 if (tmp != (u32)-1 && tmp1 != (u32)-1) {
114 iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
115 iap->ia_atime.tv_sec = tmp;
116 iap->ia_atime.tv_nsec = tmp1 * 1000;
118 tmp = ntohl(*p++); tmp1 = ntohl(*p++);
119 if (tmp != (u32)-1 && tmp1 != (u32)-1) {
120 iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
121 iap->ia_mtime.tv_sec = tmp;
122 iap->ia_mtime.tv_nsec = tmp1 * 1000;
124 * Passing the invalid value useconds=1000000 for mtime
125 * is a Sun convention for "set both mtime and atime to
126 * current server time". It's needed to make permissions
127 * checks for the "touch" program across v2 mounts to
128 * Solaris and Irix boxes work correctly. See description of
129 * sattr in section 6.1 of "NFS Illustrated" by
130 * Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5
132 if (tmp1 == 1000000)
133 iap->ia_valid &= ~(ATTR_ATIME_SET|ATTR_MTIME_SET);
135 return p;
138 static __be32 *
139 encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
140 struct kstat *stat)
142 struct dentry *dentry = fhp->fh_dentry;
143 int type;
144 struct timespec time;
145 u32 f;
147 type = (stat->mode & S_IFMT);
149 *p++ = htonl(nfs_ftypes[type >> 12]);
150 *p++ = htonl((u32) stat->mode);
151 *p++ = htonl((u32) stat->nlink);
152 *p++ = htonl((u32) nfsd_ruid(rqstp, stat->uid));
153 *p++ = htonl((u32) nfsd_rgid(rqstp, stat->gid));
155 if (S_ISLNK(type) && stat->size > NFS_MAXPATHLEN) {
156 *p++ = htonl(NFS_MAXPATHLEN);
157 } else {
158 *p++ = htonl((u32) stat->size);
160 *p++ = htonl((u32) stat->blksize);
161 if (S_ISCHR(type) || S_ISBLK(type))
162 *p++ = htonl(new_encode_dev(stat->rdev));
163 else
164 *p++ = htonl(0xffffffff);
165 *p++ = htonl((u32) stat->blocks);
166 switch (fsid_source(fhp)) {
167 default:
168 case FSIDSOURCE_DEV:
169 *p++ = htonl(new_encode_dev(stat->dev));
170 break;
171 case FSIDSOURCE_FSID:
172 *p++ = htonl((u32) fhp->fh_export->ex_fsid);
173 break;
174 case FSIDSOURCE_UUID:
175 f = ((u32*)fhp->fh_export->ex_uuid)[0];
176 f ^= ((u32*)fhp->fh_export->ex_uuid)[1];
177 f ^= ((u32*)fhp->fh_export->ex_uuid)[2];
178 f ^= ((u32*)fhp->fh_export->ex_uuid)[3];
179 *p++ = htonl(f);
180 break;
182 *p++ = htonl((u32) stat->ino);
183 *p++ = htonl((u32) stat->atime.tv_sec);
184 *p++ = htonl(stat->atime.tv_nsec ? stat->atime.tv_nsec / 1000 : 0);
185 lease_get_mtime(dentry->d_inode, &time);
186 *p++ = htonl((u32) time.tv_sec);
187 *p++ = htonl(time.tv_nsec ? time.tv_nsec / 1000 : 0);
188 *p++ = htonl((u32) stat->ctime.tv_sec);
189 *p++ = htonl(stat->ctime.tv_nsec ? stat->ctime.tv_nsec / 1000 : 0);
191 return p;
194 /* Helper function for NFSv2 ACL code */
195 __be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
197 struct kstat stat;
198 vfs_getattr(fhp->fh_export->ex_path.mnt, fhp->fh_dentry, &stat);
199 return encode_fattr(rqstp, p, fhp, &stat);
203 * XDR decode functions
206 nfssvc_decode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy)
208 return xdr_argsize_check(rqstp, p);
212 nfssvc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p, struct nfsd_fhandle *args)
214 if (!(p = decode_fh(p, &args->fh)))
215 return 0;
216 return xdr_argsize_check(rqstp, p);
220 nfssvc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p,
221 struct nfsd_sattrargs *args)
223 p = decode_fh(p, &args->fh);
224 if (!p)
225 return 0;
226 p = decode_sattr(p, &args->attrs);
228 return xdr_argsize_check(rqstp, p);
232 nfssvc_decode_diropargs(struct svc_rqst *rqstp, __be32 *p,
233 struct nfsd_diropargs *args)
235 if (!(p = decode_fh(p, &args->fh))
236 || !(p = decode_filename(p, &args->name, &args->len)))
237 return 0;
239 return xdr_argsize_check(rqstp, p);
243 nfssvc_decode_readargs(struct svc_rqst *rqstp, __be32 *p,
244 struct nfsd_readargs *args)
246 unsigned int len;
247 int v,pn;
248 if (!(p = decode_fh(p, &args->fh)))
249 return 0;
251 args->offset = ntohl(*p++);
252 len = args->count = ntohl(*p++);
253 p++; /* totalcount - unused */
255 if (len > NFSSVC_MAXBLKSIZE_V2)
256 len = NFSSVC_MAXBLKSIZE_V2;
258 /* set up somewhere to store response.
259 * We take pages, put them on reslist and include in iovec
261 v=0;
262 while (len > 0) {
263 pn = rqstp->rq_resused++;
264 rqstp->rq_vec[v].iov_base = page_address(rqstp->rq_respages[pn]);
265 rqstp->rq_vec[v].iov_len = len < PAGE_SIZE?len:PAGE_SIZE;
266 len -= rqstp->rq_vec[v].iov_len;
267 v++;
269 args->vlen = v;
270 return xdr_argsize_check(rqstp, p);
274 nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
275 struct nfsd_writeargs *args)
277 unsigned int len, hdr, dlen;
278 int v;
280 if (!(p = decode_fh(p, &args->fh)))
281 return 0;
283 p++; /* beginoffset */
284 args->offset = ntohl(*p++); /* offset */
285 p++; /* totalcount */
286 len = args->len = ntohl(*p++);
288 * The protocol specifies a maximum of 8192 bytes.
290 if (len > NFSSVC_MAXBLKSIZE_V2)
291 return 0;
294 * Check to make sure that we got the right number of
295 * bytes.
297 hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
298 dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len
299 - hdr;
302 * Round the length of the data which was specified up to
303 * the next multiple of XDR units and then compare that
304 * against the length which was actually received.
305 * Note that when RPCSEC/GSS (for example) is used, the
306 * data buffer can be padded so dlen might be larger
307 * than required. It must never be smaller.
309 if (dlen < XDR_QUADLEN(len)*4)
310 return 0;
312 rqstp->rq_vec[0].iov_base = (void*)p;
313 rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr;
314 v = 0;
315 while (len > rqstp->rq_vec[v].iov_len) {
316 len -= rqstp->rq_vec[v].iov_len;
317 v++;
318 rqstp->rq_vec[v].iov_base = page_address(rqstp->rq_pages[v]);
319 rqstp->rq_vec[v].iov_len = PAGE_SIZE;
321 rqstp->rq_vec[v].iov_len = len;
322 args->vlen = v + 1;
323 return 1;
327 nfssvc_decode_createargs(struct svc_rqst *rqstp, __be32 *p,
328 struct nfsd_createargs *args)
330 if ( !(p = decode_fh(p, &args->fh))
331 || !(p = decode_filename(p, &args->name, &args->len)))
332 return 0;
333 p = decode_sattr(p, &args->attrs);
335 return xdr_argsize_check(rqstp, p);
339 nfssvc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p,
340 struct nfsd_renameargs *args)
342 if (!(p = decode_fh(p, &args->ffh))
343 || !(p = decode_filename(p, &args->fname, &args->flen))
344 || !(p = decode_fh(p, &args->tfh))
345 || !(p = decode_filename(p, &args->tname, &args->tlen)))
346 return 0;
348 return xdr_argsize_check(rqstp, p);
352 nfssvc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd_readlinkargs *args)
354 if (!(p = decode_fh(p, &args->fh)))
355 return 0;
356 args->buffer = page_address(rqstp->rq_respages[rqstp->rq_resused++]);
358 return xdr_argsize_check(rqstp, p);
362 nfssvc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p,
363 struct nfsd_linkargs *args)
365 if (!(p = decode_fh(p, &args->ffh))
366 || !(p = decode_fh(p, &args->tfh))
367 || !(p = decode_filename(p, &args->tname, &args->tlen)))
368 return 0;
370 return xdr_argsize_check(rqstp, p);
374 nfssvc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p,
375 struct nfsd_symlinkargs *args)
377 if ( !(p = decode_fh(p, &args->ffh))
378 || !(p = decode_filename(p, &args->fname, &args->flen))
379 || !(p = decode_pathname(p, &args->tname, &args->tlen)))
380 return 0;
381 p = decode_sattr(p, &args->attrs);
383 return xdr_argsize_check(rqstp, p);
387 nfssvc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p,
388 struct nfsd_readdirargs *args)
390 if (!(p = decode_fh(p, &args->fh)))
391 return 0;
392 args->cookie = ntohl(*p++);
393 args->count = ntohl(*p++);
394 if (args->count > PAGE_SIZE)
395 args->count = PAGE_SIZE;
397 args->buffer = page_address(rqstp->rq_respages[rqstp->rq_resused++]);
399 return xdr_argsize_check(rqstp, p);
403 * XDR encode functions
406 nfssvc_encode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy)
408 return xdr_ressize_check(rqstp, p);
412 nfssvc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p,
413 struct nfsd_attrstat *resp)
415 p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
416 return xdr_ressize_check(rqstp, p);
420 nfssvc_encode_diropres(struct svc_rqst *rqstp, __be32 *p,
421 struct nfsd_diropres *resp)
423 p = encode_fh(p, &resp->fh);
424 p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
425 return xdr_ressize_check(rqstp, p);
429 nfssvc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p,
430 struct nfsd_readlinkres *resp)
432 *p++ = htonl(resp->len);
433 xdr_ressize_check(rqstp, p);
434 rqstp->rq_res.page_len = resp->len;
435 if (resp->len & 3) {
436 /* need to pad the tail */
437 rqstp->rq_res.tail[0].iov_base = p;
438 *p = 0;
439 rqstp->rq_res.tail[0].iov_len = 4 - (resp->len&3);
441 return 1;
445 nfssvc_encode_readres(struct svc_rqst *rqstp, __be32 *p,
446 struct nfsd_readres *resp)
448 p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
449 *p++ = htonl(resp->count);
450 xdr_ressize_check(rqstp, p);
452 /* now update rqstp->rq_res to reflect data aswell */
453 rqstp->rq_res.page_len = resp->count;
454 if (resp->count & 3) {
455 /* need to pad the tail */
456 rqstp->rq_res.tail[0].iov_base = p;
457 *p = 0;
458 rqstp->rq_res.tail[0].iov_len = 4 - (resp->count&3);
460 return 1;
464 nfssvc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p,
465 struct nfsd_readdirres *resp)
467 xdr_ressize_check(rqstp, p);
468 p = resp->buffer;
469 *p++ = 0; /* no more entries */
470 *p++ = htonl((resp->common.err == nfserr_eof));
471 rqstp->rq_res.page_len = (((unsigned long)p-1) & ~PAGE_MASK)+1;
473 return 1;
477 nfssvc_encode_statfsres(struct svc_rqst *rqstp, __be32 *p,
478 struct nfsd_statfsres *resp)
480 struct kstatfs *stat = &resp->stats;
482 *p++ = htonl(NFSSVC_MAXBLKSIZE_V2); /* max transfer size */
483 *p++ = htonl(stat->f_bsize);
484 *p++ = htonl(stat->f_blocks);
485 *p++ = htonl(stat->f_bfree);
486 *p++ = htonl(stat->f_bavail);
487 return xdr_ressize_check(rqstp, p);
491 nfssvc_encode_entry(void *ccdv, const char *name,
492 int namlen, loff_t offset, u64 ino, unsigned int d_type)
494 struct readdir_cd *ccd = ccdv;
495 struct nfsd_readdirres *cd = container_of(ccd, struct nfsd_readdirres, common);
496 __be32 *p = cd->buffer;
497 int buflen, slen;
500 dprintk("nfsd: entry(%.*s off %ld ino %ld)\n",
501 namlen, name, offset, ino);
504 if (offset > ~((u32) 0)) {
505 cd->common.err = nfserr_fbig;
506 return -EINVAL;
508 if (cd->offset)
509 *cd->offset = htonl(offset);
510 if (namlen > NFS2_MAXNAMLEN)
511 namlen = NFS2_MAXNAMLEN;/* truncate filename */
513 slen = XDR_QUADLEN(namlen);
514 if ((buflen = cd->buflen - slen - 4) < 0) {
515 cd->common.err = nfserr_toosmall;
516 return -EINVAL;
518 if (ino > ~((u32) 0)) {
519 cd->common.err = nfserr_fbig;
520 return -EINVAL;
522 *p++ = xdr_one; /* mark entry present */
523 *p++ = htonl((u32) ino); /* file id */
524 p = xdr_encode_array(p, name, namlen);/* name length & name */
525 cd->offset = p; /* remember pointer */
526 *p++ = htonl(~0U); /* offset of next entry */
528 cd->buflen = buflen;
529 cd->buffer = p;
530 cd->common.err = nfs_ok;
531 return 0;
535 * XDR release functions
538 nfssvc_release_fhandle(struct svc_rqst *rqstp, __be32 *p,
539 struct nfsd_fhandle *resp)
541 fh_put(&resp->fh);
542 return 1;