Old nfs3_xdr.c
1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 #pragma ident "@(#)nfs3_xdr.c 1.62 05/06/08 SMI"
31
32 #include <sys/param.h>
33 #include <sys/types.h>
34 #include <sys/systm.h>
35 #include <sys/user.h>
36 #include <sys/vnode.h>
37 #include <sys/file.h>
38 #include <sys/dirent.h>
39 #include <sys/vfs.h>
40 #include <sys/stream.h>
41 #include <sys/strsubr.h>
42 #include <sys/debug.h>
43 #include <sys/t_lock.h>
44 #include <sys/cmn_err.h>
45 #include <sys/dnlc.h>
46 #include <sys/cred.h>
47 #include <sys/time.h>
48
49 #include <rpc/types.h>
50 #include <rpc/xdr.h>
51
52 #include <nfs/nfs.h>
53 #include <nfs/rnode.h>
54
55 /* Checks if the fh is 32 bytes and returns TRUE if it is, otherwise FALSE */
56 #define XDR_CHECKFHSIZE(x, len, sz) \
57 (((int32_t)ntohl(len) == NFS3_CURFHSIZE) ? TRUE : \
58 (xdr_rewind(x, sz), FALSE))
59
60 /*
61 * These are the XDR routines used to serialize and deserialize
62 * the various structures passed as parameters across the network
63 * between NFS clients and servers.
64 */
65
66 /*
67 * XDR null terminated ASCII strings
68 * xdr_string3 deals with "C strings" - arrays of bytes that are
69 * terminated by a NULL character. The parameter cpp references a
70 * pointer to storage; If the pointer is null, then the necessary
71 * storage is allocated. The last parameter is the max allowed length
72 * of the string as allowed by the system. The NFS Version 3 protocol
73 * does not place limits on strings, but the implementation needs to
74 * place a reasonable limit to avoid problems.
75 */
76 bool_t
77 xdr_string3(XDR *xdrs, char **cpp, uint_t maxsize)
78 {
79 char *sp;
80 uint_t size;
81 uint_t nodesize;
82 bool_t mem_alloced = FALSE;
83
84 /*
85 * first deal with the length since xdr strings are counted-strings
86 */
87 sp = *cpp;
88 switch (xdrs->x_op) {
89 case XDR_FREE:
90 if (sp == NULL || sp == nfs3nametoolong)
91 return (TRUE); /* already free */
92 /* FALLTHROUGH */
93
94 case XDR_ENCODE:
95 size = (uint_t)strlen(sp);
96 break;
97
98 case XDR_DECODE:
99 break;
100 }
101
102 if (!xdr_u_int(xdrs, &size))
103 return (FALSE);
104
105 /*
106 * now deal with the actual bytes
107 */
108 switch (xdrs->x_op) {
109 case XDR_DECODE:
110 if (size >= maxsize) {
111 *cpp = nfs3nametoolong;
112 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &size))
113 return (FALSE);
114 return (TRUE);
115 }
116 nodesize = size + 1;
117 if (nodesize == 0)
118 return (TRUE);
119 if (sp == NULL) {
120 sp = kmem_alloc(nodesize, KM_NOSLEEP);
121 *cpp = sp;
122 if (sp == NULL)
123 return (FALSE);
124 mem_alloced = TRUE;
125 }
126 sp[size] = 0;
127
128 if (xdr_opaque(xdrs, sp, size)) {
129 if (strlen(sp) != size) {
130 if (mem_alloced)
131 kmem_free(sp, nodesize);
132 *cpp = NULL;
133 return (FALSE);
134 }
135 } else {
136 if (mem_alloced)
137 kmem_free(sp, nodesize);
138 *cpp = NULL;
139 return (FALSE);
140 }
141 return (TRUE);
142
143 case XDR_ENCODE:
144 return (xdr_opaque(xdrs, sp, size));
145
146 case XDR_FREE:
147 nodesize = size + 1;
148 kmem_free(sp, nodesize);
149 *cpp = NULL;
150 return (TRUE);
151 }
152
153 return (FALSE);
154 }
155
156 /*
157 * If the filehandle is not equal to NFS3_CURFHSIZE then
158 * rewind/set the pointer back to it's previous location prior to
159 * the call.
160 * Inlining is only being done for 32 byte fhandles since
161 * predominantly the size of the fh is 32 and thus
162 * optimizing only this case would be the best.
163 */
164 static void
165 xdr_rewind(register XDR *xdrs, uint_t inl_sz)
166 {
167 uint_t curpos;
168
169 curpos = XDR_GETPOS(xdrs);
170 (void) XDR_SETPOS(xdrs, curpos - inl_sz);
171 }
172
173 bool_t
174 xdr_nfs_fh3(XDR *xdrs, nfs_fh3 *objp)
175 {
176 int32_t *ptr;
177 int32_t *fhp;
178 uint_t len;
179 uint_t in_size;
180
181 if (xdrs->x_op == XDR_FREE)
182 return (TRUE);
183
184 in_size = RNDUP(sizeof (fhandle_t)) + 1 * BYTES_PER_XDR_UNIT;
185
186 ptr = XDR_INLINE(xdrs, in_size);
187 if (ptr != NULL) {
188 len = ((xdrs->x_op == XDR_DECODE) ? *ptr : objp->fh3_length);
189
190 if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
191 fhp = (int32_t *)&(objp->fh3_u.data);
192 if (xdrs->x_op == XDR_DECODE) {
193 objp->fh3_length = IXDR_GET_U_INT32(ptr);
194 *fhp++ = *ptr++;
195 *fhp++ = *ptr++;
196 *fhp++ = *ptr++;
197 *fhp++ = *ptr++;
198 *fhp++ = *ptr++;
199 *fhp++ = *ptr++;
200 *fhp++ = *ptr++;
201 *fhp = *ptr;
202 } else {
203 IXDR_PUT_U_INT32(ptr, objp->fh3_length);
204 *ptr++ = *fhp++;
205 *ptr++ = *fhp++;
206 *ptr++ = *fhp++;
207 *ptr++ = *fhp++;
208 *ptr++ = *fhp++;
209 *ptr++ = *fhp++;
210 *ptr++ = *fhp++;
211 *ptr = *fhp;
212 }
213 return (TRUE);
214 }
215 }
216
217 if (!xdr_u_int(xdrs, &objp->fh3_length))
218 return (FALSE);
219
220 if (objp->fh3_length > NFS3_FHSIZE)
221 return (FALSE);
222
223 return (xdr_opaque(xdrs, objp->fh3_u.data, objp->fh3_length));
224 }
225
226 /*
227 * Will only consider the DECODE case for the fast way
228 * since it does not require any additional allocation of
229 * memory and thus can just assign the objp to point to
230 * the data returned from XDR_INLINE
231 */
232 bool_t
233 xdr_fastnfs_fh3(register XDR *xdrs, nfs_fh3 **objp)
234 {
235 int32_t *ptr;
236 uint_t in_size;
237
238 if (xdrs->x_op != XDR_DECODE)
239 return (FALSE);
240
241 in_size = RNDUP(sizeof (fhandle_t)) + 1 * BYTES_PER_XDR_UNIT;
242
243 ptr = XDR_INLINE(xdrs, in_size);
244
245 if ((ptr != NULL) && (XDR_CHECKFHSIZE(xdrs, *ptr, in_size))) {
246 #ifdef _LITTLE_ENDIAN
247 /* Decode the length */
248 *ptr = (int32_t)ntohl(*(uint32_t *)ptr);
249 #endif
250 *objp = (nfs_fh3 *) ptr;
251 return (TRUE);
252 }
253 return (FALSE);
254 }
255
256 bool_t
257 xdr_diropargs3(XDR *xdrs, diropargs3 *objp)
258 {
259 uint32_t size;
260 int32_t *ptr;
261 int32_t *fhp;
262 uint32_t nodesize;
263 uint32_t in_size;
264 int rndup, i;
265 char *cptr;
266
267 if (xdrs->x_op == XDR_DECODE) {
268 objp->dirp = &objp->dir;
269 /* includes: fh, length of fh, and length of name */
270 in_size = RNDUP(sizeof (fhandle_t)) + 2 * BYTES_PER_XDR_UNIT;
271
272 ptr = XDR_INLINE(xdrs, in_size);
273
274 if (ptr != NULL) {
275 if (XDR_CHECKFHSIZE(xdrs, *ptr, in_size)) {
276 fhp = (int32_t *)(objp->dir.fh3_u.data);
277 /* Get length of fhandle and then fh. */
278 objp->dir.fh3_length = IXDR_GET_U_INT32(ptr);
279 *fhp++ = *ptr++;
280 *fhp++ = *ptr++;
281 *fhp++ = *ptr++;
282 *fhp++ = *ptr++;
283 *fhp++ = *ptr++;
284 *fhp++ = *ptr++;
285 *fhp++ = *ptr++;
286 *fhp = *ptr++;
287
288 size = IXDR_GET_U_INT32(ptr);
289
290 if (size >= MAXNAMELEN) {
291 objp->name = nfs3nametoolong;
292 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES,
293 &size))
294 return (FALSE);
295 return (TRUE);
296 }
297 nodesize = size+1;
298 if (nodesize == 0)
299 return (TRUE);
300 if (objp->name == NULL) {
301 objp->name = (char *)kmem_alloc(nodesize,
302 KM_NOSLEEP);
303 if (objp->name == NULL)
304 return (FALSE);
305 objp->flags |= DA_FREENAME;
306 }
307 ptr = XDR_INLINE(xdrs, RNDUP(size));
308 if (ptr == NULL) {
309 if (! xdr_opaque(xdrs, objp->name, size)) {
310 if (objp->flags & DA_FREENAME) {
311 kmem_free(objp->name,
312 nodesize);
313 objp->name = NULL;
314 }
315 return (FALSE);
316 }
317 objp->name[size] = '\0';
318 if (strlen(objp->name) != size) {
319 if (objp->flags & DA_FREENAME) {
320 kmem_free(objp->name,
321 nodesize);
322 objp->name = NULL;
323 }
324 return (FALSE);
325 }
326 return (TRUE);
327 }
328 bcopy((char *)ptr, objp->name, size);
329 objp->name[size] = '\0';
330 if (strlen(objp->name) != size) {
331 if (objp->flags & DA_FREENAME) {
332 kmem_free(objp->name,
333 nodesize);
334 objp->name = NULL;
335 }
336 return (FALSE);
337 }
338 return (TRUE);
339 }
340 }
341 if (objp->name == NULL)
342 objp->flags |= DA_FREENAME;
343 }
344
345 if ((xdrs->x_op == XDR_ENCODE) &&
346 (objp->dirp->fh3_length == NFS3_CURFHSIZE)) {
347 fhp = (int32_t *)(objp->dirp->fh3_u.data);
348 size = strlen(objp->name);
349 in_size = RNDUP(sizeof (fhandle_t)) +
350 (2 * BYTES_PER_XDR_UNIT) + RNDUP(size);
351
352 ptr = XDR_INLINE(xdrs, in_size);
353 if (ptr != NULL) {
354 IXDR_PUT_U_INT32(ptr, objp->dirp->fh3_length);
355 *ptr++ = *fhp++;
356 *ptr++ = *fhp++;
357 *ptr++ = *fhp++;
358 *ptr++ = *fhp++;
359 *ptr++ = *fhp++;
360 *ptr++ = *fhp++;
361 *ptr++ = *fhp++;
362 *ptr++ = *fhp;
363
364 IXDR_PUT_U_INT32(ptr, (uint32_t)size);
365
366 bcopy(objp->name, (char *)ptr, size);
367 rndup = BYTES_PER_XDR_UNIT -
368 (size % BYTES_PER_XDR_UNIT);
369 if (rndup != BYTES_PER_XDR_UNIT) {
370 cptr = (char *)ptr + size;
371 for (i = 0; i < rndup; i++)
372 *cptr++ = '\0';
373 }
374 return (TRUE);
375 }
376 }
377 if (xdrs->x_op == XDR_FREE) {
378 if ((objp->name == NULL) || (objp->name == nfs3nametoolong))
379 return (TRUE);
380 size = strlen(objp->name);
381 if (objp->flags & DA_FREENAME)
382 kmem_free(objp->name, size + 1);
383 objp->name = NULL;
384 return (TRUE);
385 }
386 /* Normal case */
387 if (!xdr_nfs_fh3(xdrs, objp->dirp))
388 return (FALSE);
389 return (xdr_string3(xdrs, &objp->name, MAXNAMELEN));
390 }
391
392 bool_t
393 xdr_fastdiropargs3(XDR *xdrs, diropargs3 **objp)
394 {
395 int32_t *ptr;
396 uint_t size;
397 uint_t nodesize;
398 struct diropargs3 *da;
399 uint_t in_size;
400 uint_t skipsize;
401
402 if (xdrs->x_op != XDR_DECODE)
403 return (FALSE);
404
405 in_size = RNDUP(sizeof (fhandle_t)) + 1 * BYTES_PER_XDR_UNIT;
406
407 /* includes the fh and fh length */
408 ptr = XDR_INLINE(xdrs, in_size);
409
410 if ((ptr != NULL) && (XDR_CHECKFHSIZE(xdrs, *ptr, in_size))) {
411 da = *objp;
412 #ifdef _LITTLE_ENDIAN
413 *ptr = (int32_t)ntohl(*(uint32_t *)ptr);
414 #endif
415 da->dirp = (nfs_fh3 *)ptr;
416 da->name = NULL;
417 da->flags = 0;
418 if (!XDR_CONTROL(xdrs, XDR_PEEK, (void *)&size)) {
419 da->flags |= DA_FREENAME;
420 return (xdr_string3(xdrs, &da->name, MAXNAMELEN));
421 }
422 if (size >= MAXNAMELEN) {
423 da->name = nfs3nametoolong;
424 skipsize = RNDUP(size) + (1 * BYTES_PER_XDR_UNIT);
425 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &skipsize))
426 return (FALSE);
427 return (TRUE);
428 }
429 nodesize = size + 1;
430 if (nodesize == 0)
431 return (TRUE);
432 ptr = XDR_INLINE(xdrs, 1 * BYTES_PER_XDR_UNIT + RNDUP(size));
433 if (ptr != NULL) {
434 if ((size % BYTES_PER_XDR_UNIT) != 0)
435 /* Plus 1 skips the size */
436 da->name = (char *)(ptr + 1);
437 else {
438 da->name = (char *)ptr;
439 bcopy((char *)(ptr + 1), da->name, size);
440 }
441 da->name[size] = '\0';
442 return (TRUE);
443 }
444 da->flags |= DA_FREENAME;
445 return (xdr_string3(xdrs, &da->name, MAXNAMELEN));
446 }
447 return (FALSE);
448 }
449
450 static bool_t
451 xdr_fattr3(XDR *xdrs, fattr3 *na)
452 {
453 int32_t *ptr;
454
455 if (xdrs->x_op == XDR_FREE)
456 return (TRUE);
457
458 ptr = XDR_INLINE(xdrs, NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT);
459 if (ptr != NULL) {
460 if (xdrs->x_op == XDR_DECODE) {
461 na->type = IXDR_GET_ENUM(ptr, enum ftype3);
462 na->mode = IXDR_GET_U_INT32(ptr);
463 na->nlink = IXDR_GET_U_INT32(ptr);
464 na->uid = IXDR_GET_U_INT32(ptr);
465 na->gid = IXDR_GET_U_INT32(ptr);
466 IXDR_GET_U_HYPER(ptr, na->size);
467 IXDR_GET_U_HYPER(ptr, na->used);
468 na->rdev.specdata1 = IXDR_GET_U_INT32(ptr);
469 na->rdev.specdata2 = IXDR_GET_U_INT32(ptr);
470 IXDR_GET_U_HYPER(ptr, na->fsid);
471 IXDR_GET_U_HYPER(ptr, na->fileid);
472 na->atime.seconds = IXDR_GET_U_INT32(ptr);
473 na->atime.nseconds = IXDR_GET_U_INT32(ptr);
474 na->mtime.seconds = IXDR_GET_U_INT32(ptr);
475 na->mtime.nseconds = IXDR_GET_U_INT32(ptr);
476 na->ctime.seconds = IXDR_GET_U_INT32(ptr);
477 na->ctime.nseconds = IXDR_GET_U_INT32(ptr);
478 } else {
479 IXDR_PUT_ENUM(ptr, na->type);
480 IXDR_PUT_U_INT32(ptr, na->mode);
481 IXDR_PUT_U_INT32(ptr, na->nlink);
482 IXDR_PUT_U_INT32(ptr, na->uid);
483 IXDR_PUT_U_INT32(ptr, na->gid);
484 IXDR_PUT_U_HYPER(ptr, na->size);
485 IXDR_PUT_U_HYPER(ptr, na->used);
486 IXDR_PUT_U_INT32(ptr, na->rdev.specdata1);
487 IXDR_PUT_U_INT32(ptr, na->rdev.specdata2);
488 IXDR_PUT_U_HYPER(ptr, na->fsid);
489 IXDR_PUT_U_HYPER(ptr, na->fileid);
490 IXDR_PUT_U_INT32(ptr, na->atime.seconds);
491 IXDR_PUT_U_INT32(ptr, na->atime.nseconds);
492 IXDR_PUT_U_INT32(ptr, na->mtime.seconds);
493 IXDR_PUT_U_INT32(ptr, na->mtime.nseconds);
494 IXDR_PUT_U_INT32(ptr, na->ctime.seconds);
495 IXDR_PUT_U_INT32(ptr, na->ctime.nseconds);
496 }
497 return (TRUE);
498 }
499 if (!(xdr_enum(xdrs, (enum_t *)&na->type) &&
500 xdr_u_int(xdrs, &na->mode) &&
501 xdr_u_int(xdrs, &na->nlink) &&
502 xdr_u_int(xdrs, &na->uid) &&
503 xdr_u_int(xdrs, &na->gid) &&
504 xdr_u_longlong_t(xdrs, &na->size) &&
505 xdr_u_longlong_t(xdrs, &na->used) &&
506 xdr_u_int(xdrs, &na->rdev.specdata1) &&
507 xdr_u_int(xdrs, &na->rdev.specdata2) &&
508 xdr_u_longlong_t(xdrs, &na->fsid) &&
509 xdr_u_longlong_t(xdrs, &na->fileid) &&
510 xdr_u_int(xdrs, &na->atime.seconds) &&
511 xdr_u_int(xdrs, &na->atime.nseconds) &&
512 xdr_u_int(xdrs, &na->mtime.seconds) &&
513 xdr_u_int(xdrs, &na->mtime.nseconds) &&
514 xdr_u_int(xdrs, &na->ctime.seconds) &&
515 xdr_u_int(xdrs, &na->ctime.nseconds)))
516 return (FALSE);
517 return (TRUE);
518 }
519
520 /*
521 * Fast decode of an fattr3 to a vattr
522 * Only return FALSE on decode error, all other fattr to vattr translation
523 * failures set status.
524 *
525 * Callers must catch the following errors:
526 * EFBIG - file size will not fit in va_size
527 * EOVERFLOW - time will not fit in va_*time
528 */
529 static bool_t
530 xdr_fattr3_to_vattr(XDR *xdrs, fattr3_res *objp)
531 {
532 int32_t *ptr;
533 size3 used;
534 specdata3 rdev;
535 uint32_t ntime;
536 vattr_t *vap = objp->vap;
537
538 /*
539 * DECODE only
540 */
541 ASSERT(xdrs->x_op == XDR_DECODE);
542
543 objp->status = 0;
544 ptr = XDR_INLINE(xdrs, NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT);
545 if (ptr != NULL) {
546 /*
547 * Common case
548 */
549 vap->va_type = IXDR_GET_ENUM(ptr, enum vtype);
550 if (vap->va_type < NF3REG || vap->va_type > NF3FIFO)
551 vap->va_type = VBAD;
552 else
553 vap->va_type = nf3_to_vt[vap->va_type];
554 vap->va_mode = IXDR_GET_U_INT32(ptr);
555 vap->va_nlink = IXDR_GET_U_INT32(ptr);
556 vap->va_uid = (uid_t)IXDR_GET_U_INT32(ptr);
557 if (vap->va_uid == NFS_UID_NOBODY)
558 vap->va_uid = UID_NOBODY;
559 vap->va_gid = (gid_t)IXDR_GET_U_INT32(ptr);
560 if (vap->va_gid == NFS_GID_NOBODY)
561 vap->va_gid = GID_NOBODY;
562 IXDR_GET_U_HYPER(ptr, vap->va_size);
563 /*
564 * If invalid size, stop decode, set status, and
565 * return TRUE, x_handy will be correct, caller must ignore vap.
566 */
567 if (!NFS3_SIZE_OK(vap->va_size)) {
568 objp->status = EFBIG;
569 return (TRUE);
570 }
571 IXDR_GET_U_HYPER(ptr, used);
572 rdev.specdata1 = IXDR_GET_U_INT32(ptr);
573 rdev.specdata2 = IXDR_GET_U_INT32(ptr);
574 /* fsid is ignored */
575 ptr += 2;
576 IXDR_GET_U_HYPER(ptr, vap->va_nodeid);
577
578 /*
579 * nfs protocol defines times as unsigned so don't
580 * extend sign, unless sysadmin set nfs_allow_preepoch_time.
581 * The inline macros do the equivilant of NFS_TIME_T_CONVERT
582 */
583 if (nfs_allow_preepoch_time) {
584 vap->va_atime.tv_sec = IXDR_GET_INT32(ptr);
585 vap->va_atime.tv_nsec = IXDR_GET_U_INT32(ptr);
586 vap->va_mtime.tv_sec = IXDR_GET_INT32(ptr);
587 vap->va_mtime.tv_nsec = IXDR_GET_U_INT32(ptr);
588 vap->va_ctime.tv_sec = IXDR_GET_INT32(ptr);
589 vap->va_ctime.tv_nsec = IXDR_GET_U_INT32(ptr);
590 } else {
591 /*
592 * Check if the time would overflow on 32-bit
593 */
594 ntime = IXDR_GET_U_INT32(ptr);
595 /*CONSTCOND*/
596 if (NFS3_TIME_OVERFLOW(ntime)) {
597 objp->status = EOVERFLOW;
598 return (TRUE);
599 }
600 vap->va_atime.tv_sec = ntime;
601 vap->va_atime.tv_nsec = IXDR_GET_U_INT32(ptr);
602
603 ntime = IXDR_GET_U_INT32(ptr);
604 /*CONSTCOND*/
605 if (NFS3_TIME_OVERFLOW(ntime)) {
606 objp->status = EOVERFLOW;
607 return (TRUE);
608 }
609 vap->va_mtime.tv_sec = ntime;
610 vap->va_mtime.tv_nsec = IXDR_GET_U_INT32(ptr);
611
612 ntime = IXDR_GET_U_INT32(ptr);
613 /*CONSTCOND*/
614 if (NFS3_TIME_OVERFLOW(ntime)) {
615 objp->status = EOVERFLOW;
616 return (TRUE);
617 }
618 vap->va_ctime.tv_sec = ntime;
619 vap->va_ctime.tv_nsec = IXDR_GET_U_INT32(ptr);
620 }
621
622 } else {
623 uint64 fsid;
624
625 /*
626 * Slow path
627 */
628 if (!(xdr_enum(xdrs, (enum_t *)&vap->va_type) &&
629 xdr_u_int(xdrs, &vap->va_mode) &&
630 xdr_u_int(xdrs, &vap->va_nlink) &&
631 xdr_u_int(xdrs, (uint_t *)&vap->va_uid) &&
632 xdr_u_int(xdrs, (uint_t *)&vap->va_gid) &&
633 xdr_u_longlong_t(xdrs, &vap->va_size) &&
634 xdr_u_longlong_t(xdrs, &used) &&
635 xdr_u_int(xdrs, &rdev.specdata1) &&
636 xdr_u_int(xdrs, &rdev.specdata2) &&
637 xdr_u_longlong_t(xdrs, &fsid) && /* ignored */
638 xdr_u_longlong_t(xdrs, &vap->va_nodeid)))
639 return (FALSE);
640
641 if (nfs_allow_preepoch_time) {
642 if (!xdr_u_int(xdrs, &ntime))
643 return (FALSE);
644 vap->va_atime.tv_sec = (int32_t)ntime;
645 if (!xdr_u_int(xdrs, &ntime))
646 return (FALSE);
647 vap->va_atime.tv_nsec = ntime;
648
649 if (!xdr_u_int(xdrs, &ntime))
650 return (FALSE);
651 vap->va_mtime.tv_sec = (int32_t)ntime;
652 if (!xdr_u_int(xdrs, &ntime))
653 return (FALSE);
654 vap->va_mtime.tv_nsec = ntime;
655
656 if (!xdr_u_int(xdrs, &ntime))
657 return (FALSE);
658 vap->va_ctime.tv_sec = (int32_t)ntime;
659 if (!xdr_u_int(xdrs, &ntime))
660 return (FALSE);
661 vap->va_ctime.tv_nsec = ntime;
662 } else {
663 /*
664 * Check if the time would overflow on 32-bit
665 * Set status and keep decoding stream.
666 */
667 if (!xdr_u_int(xdrs, &ntime))
668 return (FALSE);
669 /*CONSTCOND*/
670 if (NFS3_TIME_OVERFLOW(ntime)) {
671 objp->status = EOVERFLOW;
672 }
673 vap->va_atime.tv_sec = ntime;
674 if (!xdr_u_int(xdrs, &ntime))
675 return (FALSE);
676 vap->va_atime.tv_nsec = ntime;
677
678 if (!xdr_u_int(xdrs, &ntime))
679 return (FALSE);
680 /*CONSTCOND*/
681 if (NFS3_TIME_OVERFLOW(ntime)) {
682 objp->status = EOVERFLOW;
683 }
684 vap->va_mtime.tv_sec = ntime;
685 if (!xdr_u_int(xdrs, &ntime))
686 return (FALSE);
687 vap->va_mtime.tv_nsec = ntime;
688
689 if (!xdr_u_int(xdrs, &ntime))
690 return (FALSE);
691 /*CONSTCOND*/
692 if (NFS3_TIME_OVERFLOW(ntime)) {
693 objp->status = EOVERFLOW;
694 }
695 vap->va_ctime.tv_sec = ntime;
696 if (!xdr_u_int(xdrs, &ntime))
697 return (FALSE);
698 vap->va_ctime.tv_nsec = ntime;
699 }
700
701 /*
702 * Fixup as needed
703 */
704 if (vap->va_type < NF3REG || vap->va_type > NF3FIFO)
705 vap->va_type = VBAD;
706 else
707 vap->va_type = nf3_to_vt[vap->va_type];
708 if (vap->va_uid == NFS_UID_NOBODY)
709 vap->va_uid = UID_NOBODY;
710 if (vap->va_gid == NFS_GID_NOBODY)
711 vap->va_gid = GID_NOBODY;
712 /*
713 * If invalid size, set status, and
714 * return TRUE, caller must ignore vap.
715 */
716 if (!NFS3_SIZE_OK(vap->va_size)) {
717 objp->status = EFBIG;
718 return (TRUE);
719 }
720 }
721
722 /*
723 * Fill in derived fields
724 */
725 vap->va_fsid = objp->vp->v_vfsp->vfs_dev;
726 vap->va_seq = 0;
727
728 /*
729 * Common case values
730 */
731 vap->va_rdev = 0;
732 vap->va_blksize = MAXBSIZE;
733 vap->va_nblocks = 0;
734
735 switch (vap->va_type) {
736 case VREG:
737 case VDIR:
738 case VLNK:
739 vap->va_nblocks = (u_longlong_t)
740 ((used + (size3)DEV_BSIZE - (size3)1) /
741 (size3)DEV_BSIZE);
742 break;
743 case VBLK:
744 vap->va_blksize = DEV_BSIZE;
745 /* FALLTHRU */
746 case VCHR:
747 vap->va_rdev = makedevice(rdev.specdata1, rdev.specdata2);
748 break;
749 case VSOCK:
750 case VFIFO:
751 default:
752 break;
753 }
754
755 return (TRUE);
756 }
757
758 static bool_t
759 xdr_post_op_vattr(XDR *xdrs, post_op_vattr *objp)
760 {
761 /*
762 * DECODE only
763 */
764 ASSERT(xdrs->x_op == XDR_DECODE);
765
766 if (!xdr_bool(xdrs, &objp->attributes))
767 return (FALSE);
768
769 if (objp->attributes == FALSE)
770 return (TRUE);
771
772 if (objp->attributes != TRUE)
773 return (FALSE);
774
775 if (!xdr_fattr3_to_vattr(xdrs, &objp->fres))
776 return (FALSE);
777
778 /*
779 * The file size may cause an EFBIG or the time values
780 * may cause EOVERFLOW, if so simply drop the attributes.
781 */
782 if (objp->fres.status != NFS3_OK)
783 objp->attributes = FALSE;
784
785 return (TRUE);
786 }
787
788 bool_t
789 xdr_post_op_attr(XDR *xdrs, post_op_attr *objp)
790 {
791 if (!xdr_bool(xdrs, &objp->attributes))
792 return (FALSE);
793
794 if (objp->attributes == FALSE)
795 return (TRUE);
796
797 if (objp->attributes != TRUE)
798 return (FALSE);
799
800 if (!xdr_fattr3(xdrs, &objp->attr))
801 return (FALSE);
802
803 /*
804 * Check that we don't get a file we can't handle through
805 * existing interfaces (especially stat64()).
806 * Decode only check since on encode the data has
807 * been dealt with in the above call to xdr_fattr3().
808 */
809 if (xdrs->x_op == XDR_DECODE) {
810 /* Set attrs to false if invalid size or time */
811 if (!NFS3_SIZE_OK(objp->attr.size)) {
812 objp->attributes = FALSE;
813 return (TRUE);
814 }
815 #ifndef _LP64
816 if (!NFS3_FATTR_TIME_OK(&objp->attr))
817 objp->attributes = FALSE;
818 #endif
819 }
820 return (TRUE);
821 }
822
823 static bool_t
824 xdr_wcc_data(XDR *xdrs, wcc_data *objp)
825 {
826 int32_t *ptr;
827 wcc_attr *attrp;
828
829 if (xdrs->x_op == XDR_FREE)
830 return (TRUE);
831
832 if (xdrs->x_op == XDR_DECODE) {
833 /* pre_op_attr */
834 if (!xdr_bool(xdrs, &objp->before.attributes))
835 return (FALSE);
836
837 switch (objp->before.attributes) {
838 case TRUE:
839 attrp = &objp->before.attr;
840 ptr = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
841 if (ptr != NULL) {
842 IXDR_GET_U_HYPER(ptr, attrp->size);
843 attrp->mtime.seconds = IXDR_GET_U_INT32(ptr);
844 attrp->mtime.nseconds = IXDR_GET_U_INT32(ptr);
845 attrp->ctime.seconds = IXDR_GET_U_INT32(ptr);
846 attrp->ctime.nseconds = IXDR_GET_U_INT32(ptr);
847 } else {
848 if (!xdr_u_longlong_t(xdrs, &attrp->size))
849 return (FALSE);
850 if (!xdr_u_int(xdrs, &attrp->mtime.seconds))
851 return (FALSE);
852 if (!xdr_u_int(xdrs, &attrp->mtime.nseconds))
853 return (FALSE);
854 if (!xdr_u_int(xdrs, &attrp->ctime.seconds))
855 return (FALSE);
856 if (!xdr_u_int(xdrs, &attrp->ctime.nseconds))
857 return (FALSE);
858 }
859
860 #ifndef _LP64
861 /*
862 * check time overflow.
863 */
864 if (!NFS3_TIME_OK(attrp->mtime.seconds) ||
865 !NFS3_TIME_OK(attrp->ctime.seconds))
866 objp->before.attributes = FALSE;
867 #endif
868 break;
869 case FALSE:
870 break;
871 default:
872 return (FALSE);
873 }
874 }
875
876 if (xdrs->x_op == XDR_ENCODE) {
877 /* pre_op_attr */
878 if (!xdr_bool(xdrs, &objp->before.attributes))
879 return (FALSE);
880
881 switch (objp->before.attributes) {
882 case TRUE:
883 attrp = &objp->before.attr;
884
885 ptr = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
886 if (ptr != NULL) {
887 IXDR_PUT_U_HYPER(ptr, attrp->size);
888 IXDR_PUT_U_INT32(ptr, attrp->mtime.seconds);
889 IXDR_PUT_U_INT32(ptr, attrp->mtime.nseconds);
890 IXDR_PUT_U_INT32(ptr, attrp->ctime.seconds);
891 IXDR_PUT_U_INT32(ptr, attrp->ctime.nseconds);
892 } else {
893 if (!xdr_u_longlong_t(xdrs, &attrp->size))
894 return (FALSE);
895 if (!xdr_u_int(xdrs, &attrp->mtime.seconds))
896 return (FALSE);
897 if (!xdr_u_int(xdrs, &attrp->mtime.nseconds))
898 return (FALSE);
899 if (!xdr_u_int(xdrs, &attrp->ctime.seconds))
900 return (FALSE);
901 if (!xdr_u_int(xdrs, &attrp->ctime.nseconds))
902 return (FALSE);
903 }
904 break;
905 case FALSE:
906 break;
907 default:
908 return (FALSE);
909 }
910 }
911 return (xdr_post_op_attr(xdrs, &objp->after));
912 }
913
914 bool_t
915 xdr_post_op_fh3(XDR *xdrs, post_op_fh3 *objp)
916 {
917 if (!xdr_bool(xdrs, &objp->handle_follows))
918 return (FALSE);
919 switch (objp->handle_follows) {
920 case TRUE:
921 return (xdr_nfs_fh3(xdrs, &objp->handle));
922 case FALSE:
923 return (TRUE);
924 default:
925 return (FALSE);
926 }
927 }
928
929 static bool_t
930 xdr_sattr3(XDR *xdrs, sattr3 *objp)
931 {
932 /* set_mode3 */
933 if (!xdr_bool(xdrs, &objp->mode.set_it))
934 return (FALSE);
935 if (objp->mode.set_it)
936 if (!xdr_u_int(xdrs, &objp->mode.mode))
937 return (FALSE);
938 /* set_uid3 */
939 if (!xdr_bool(xdrs, &objp->uid.set_it))
940 return (FALSE);
941 if (objp->uid.set_it)
942 if (!xdr_u_int(xdrs, &objp->uid.uid))
943 return (FALSE);
944 /* set_gid3 */
945 if (!xdr_bool(xdrs, &objp->gid.set_it))
946 return (FALSE);
947 if (objp->gid.set_it)
948 if (!xdr_u_int(xdrs, &objp->gid.gid))
949 return (FALSE);
950
951 /* set_size3 */
952 if (!xdr_bool(xdrs, &objp->size.set_it))
953 return (FALSE);
954 if (objp->size.set_it)
955 if (!xdr_u_longlong_t(xdrs, &objp->size.size))
956 return (FALSE);
957
958 /* set_atime */
959 if (!xdr_enum(xdrs, (enum_t *)&objp->atime.set_it))
960 return (FALSE);
961 if (objp->atime.set_it == SET_TO_CLIENT_TIME) {
962 if (!xdr_u_int(xdrs, &objp->atime.atime.seconds))
963 return (FALSE);
964 if (!xdr_u_int(xdrs, &objp->atime.atime.nseconds))
965 return (FALSE);
966 }
967
968 /* set_mtime */
969 if (!xdr_enum(xdrs, (enum_t *)&objp->mtime.set_it))
970 return (FALSE);
971 if (objp->mtime.set_it == SET_TO_CLIENT_TIME) {
972 if (!xdr_u_int(xdrs, &objp->mtime.mtime.seconds))
973 return (FALSE);
974 if (!xdr_u_int(xdrs, &objp->mtime.mtime.nseconds))
975 return (FALSE);
976 }
977
978 return (TRUE);
979 }
980
981 bool_t
982 xdr_GETATTR3res(XDR *xdrs, GETATTR3res *objp)
983 {
984 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
985 return (FALSE);
986 if (objp->status != NFS3_OK)
987 return (TRUE);
988 /* xdr_GETATTR3resok */
989 return (xdr_fattr3(xdrs, &objp->resok.obj_attributes));
990 }
991
992 bool_t
993 xdr_GETATTR3vres(XDR *xdrs, GETATTR3vres *objp)
994 {
995 /*
996 * DECODE or FREE only
997 */
998 if (xdrs->x_op == XDR_FREE)
999 return (TRUE);
1000
1001 if (xdrs->x_op != XDR_DECODE)
1002 return (FALSE);
1003
1004 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1005 return (FALSE);
1006
1007 if (objp->status != NFS3_OK)
1008 return (TRUE);
1009
1010 return (xdr_fattr3_to_vattr(xdrs, &objp->fres));
1011 }
1012
1013
1014 bool_t
1015 xdr_SETATTR3args(XDR *xdrs, SETATTR3args *objp)
1016 {
1017 if (!xdr_nfs_fh3(xdrs, &objp->object))
1018 return (FALSE);
1019 if (!xdr_sattr3(xdrs, &objp->new_attributes))
1020 return (FALSE);
1021
1022 /* sattrguard3 */
1023 if (!xdr_bool(xdrs, &objp->guard.check))
1024 return (FALSE);
1025 switch (objp->guard.check) {
1026 case TRUE:
1027 if (!xdr_u_int(xdrs, &objp->guard.obj_ctime.seconds))
1028 return (FALSE);
1029 return (xdr_u_int(xdrs, &objp->guard.obj_ctime.nseconds));
1030 case FALSE:
1031 return (TRUE);
1032 default:
1033 return (FALSE);
1034 }
1035 }
1036
1037 bool_t
1038 xdr_SETATTR3res(XDR *xdrs, SETATTR3res *objp)
1039 {
1040 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1041 return (FALSE);
1042 switch (objp->status) {
1043 case NFS3_OK:
1044 return (xdr_wcc_data(xdrs, &objp->resok.obj_wcc));
1045 default:
1046 return (xdr_wcc_data(xdrs, &objp->resfail.obj_wcc));
1047 }
1048 }
1049
1050 bool_t
1051 xdr_LOOKUP3res(XDR *xdrs, LOOKUP3res *objp)
1052 {
1053 LOOKUP3resok *resokp;
1054
1055 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1056 return (FALSE);
1057
1058 if (objp->status != NFS3_OK)
1059 return (xdr_post_op_attr(xdrs, &objp->resfail.dir_attributes));
1060
1061 /* xdr_LOOKUP3resok */
1062 resokp = &objp->resok;
1063 if (!xdr_nfs_fh3(xdrs, &resokp->object))
1064 return (FALSE);
1065 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
1066 return (FALSE);
1067 return (xdr_post_op_attr(xdrs, &resokp->dir_attributes));
1068 }
1069
1070 bool_t
1071 xdr_LOOKUP3vres(XDR *xdrs, LOOKUP3vres *objp)
1072 {
1073 /*
1074 * DECODE or FREE only
1075 */
1076 if (xdrs->x_op == XDR_FREE)
1077 return (TRUE);
1078
1079 if (xdrs->x_op != XDR_DECODE)
1080 return (FALSE);
1081
1082 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1083 return (FALSE);
1084
1085 if (objp->status != NFS3_OK)
1086 return (xdr_post_op_vattr(xdrs, &objp->dir_attributes));
1087
1088 if (!xdr_nfs_fh3(xdrs, &objp->object))
1089 return (FALSE);
1090 if (!xdr_post_op_vattr(xdrs, &objp->obj_attributes))
1091 return (FALSE);
1092 return (xdr_post_op_vattr(xdrs, &objp->dir_attributes));
1093 }
1094
1095 bool_t
1096 xdr_ACCESS3args(XDR *xdrs, ACCESS3args *objp)
1097 {
1098 int32_t *ptr;
1099 int32_t *fhp;
1100 int len;
1101 uint_t in_size;
1102
1103 if (xdrs->x_op == XDR_FREE)
1104 return (TRUE);
1105
1106 in_size = RNDUP(sizeof (fhandle_t)) + 2 * BYTES_PER_XDR_UNIT;
1107 ptr = XDR_INLINE(xdrs, in_size);
1108
1109 if (ptr != NULL) {
1110 len = (xdrs->x_op == XDR_DECODE) ?
1111 *ptr : objp->object.fh3_length;
1112
1113 if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
1114 fhp = (int32_t *)&(objp->object.fh3_u.data);
1115 if (xdrs->x_op == XDR_DECODE) {
1116 objp->object.fh3_length = IXDR_GET_U_INT32(ptr);
1117 *fhp++ = *ptr++;
1118 *fhp++ = *ptr++;
1119 *fhp++ = *ptr++;
1120 *fhp++ = *ptr++;
1121 *fhp++ = *ptr++;
1122 *fhp++ = *ptr++;
1123 *fhp++ = *ptr++;
1124 *fhp = *ptr++;
1125 objp->access = IXDR_GET_U_INT32(ptr);
1126 } else {
1127 IXDR_PUT_U_INT32(ptr, objp->object.fh3_length);
1128 *ptr++ = *fhp++;
1129 *ptr++ = *fhp++;
1130 *ptr++ = *fhp++;
1131 *ptr++ = *fhp++;
1132 *ptr++ = *fhp++;
1133 *ptr++ = *fhp++;
1134 *ptr++ = *fhp++;
1135 *ptr++ = *fhp;
1136 IXDR_PUT_U_INT32(ptr, objp->access);
1137 }
1138 return (TRUE);
1139 }
1140 }
1141
1142 if (!xdr_nfs_fh3(xdrs, &objp->object))
1143 return (FALSE);
1144 return (xdr_u_int(xdrs, &objp->access));
1145 }
1146
1147
1148 bool_t
1149 xdr_ACCESS3res(XDR *xdrs, ACCESS3res *objp)
1150 {
1151 ACCESS3resok *resokp;
1152
1153 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1154 return (FALSE);
1155 if (objp->status != NFS3_OK)
1156 return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes));
1157
1158 /* xdr_ACCESS3resok */
1159 resokp = &objp->resok;
1160 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
1161 return (FALSE);
1162 return (xdr_u_int(xdrs, &resokp->access));
1163 }
1164
1165 bool_t
1166 xdr_READLINK3res(XDR *xdrs, READLINK3res *objp)
1167 {
1168
1169 READLINK3resok *resokp;
1170
1171 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1172 return (FALSE);
1173 if (objp->status != NFS3_OK)
1174 return (xdr_post_op_attr(xdrs,
1175 &objp->resfail.symlink_attributes));
1176
1177 /* xdr_READLINK3resok */
1178 resokp = &objp->resok;
1179 if (!xdr_post_op_attr(xdrs, &resokp->symlink_attributes))
1180 return (FALSE);
1181 return (xdr_string3(xdrs, &resokp->data, MAXPATHLEN));
1182 }
1183
1184 bool_t
1185 xdr_READ3args(XDR *xdrs, READ3args *objp)
1186 {
1187 int32_t *ptr;
1188 int32_t *fhp;
1189 uint_t in_size;
1190 int len;
1191
1192 if (xdrs->x_op == XDR_FREE)
1193 return (TRUE);
1194
1195 in_size = RNDUP(sizeof (fhandle_t)) + 4 * BYTES_PER_XDR_UNIT;
1196 ptr = XDR_INLINE(xdrs, in_size);
1197 if (ptr != NULL) {
1198 len = (xdrs->x_op == XDR_DECODE) ?
1199 *ptr : objp->file.fh3_length;
1200
1201 if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
1202 fhp = (int32_t *)& objp->file.fh3_u.data;
1203 if (xdrs->x_op == XDR_DECODE) {
1204 objp->file.fh3_length = IXDR_GET_U_INT32(ptr);
1205 *fhp++ = *ptr++;
1206 *fhp++ = *ptr++;
1207 *fhp++ = *ptr++;
1208 *fhp++ = *ptr++;
1209 *fhp++ = *ptr++;
1210 *fhp++ = *ptr++;
1211 *fhp++ = *ptr++;
1212 *fhp = *ptr++;
1213 IXDR_GET_U_HYPER(ptr, objp->offset);
1214 objp->count = IXDR_GET_U_INT32(ptr);
1215 } else {
1216 IXDR_PUT_U_INT32(ptr, objp->file.fh3_length);
1217 *ptr++ = *fhp++;
1218 *ptr++ = *fhp++;
1219 *ptr++ = *fhp++;
1220 *ptr++ = *fhp++;
1221 *ptr++ = *fhp++;
1222 *ptr++ = *fhp++;
1223 *ptr++ = *fhp++;
1224 *ptr++ = *fhp;
1225 IXDR_PUT_U_HYPER(ptr, objp->offset);
1226 IXDR_PUT_U_INT32(ptr, objp->count);
1227 }
1228 return (TRUE);
1229 }
1230 }
1231
1232 if (!xdr_nfs_fh3(xdrs, &objp->file))
1233 return (FALSE);
1234 if (!xdr_u_longlong_t(xdrs, &objp->offset))
1235 return (FALSE);
1236 return (xdr_u_int(xdrs, &objp->count));
1237 }
1238
1239 bool_t
1240 xdr_READ3res(XDR *xdrs, READ3res *objp)
1241 {
1242 READ3resok *resokp;
1243 bool_t ret;
1244 mblk_t *mp;
1245
1246 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1247 return (FALSE);
1248
1249 if (objp->status != NFS3_OK)
1250 return (xdr_post_op_attr(xdrs, &objp->resfail.file_attributes));
1251
1252 resokp = &objp->resok;
1253
1254 if (xdr_post_op_attr(xdrs, &resokp->file_attributes) == FALSE ||
1255 xdr_u_int(xdrs, &resokp->count) == FALSE ||
1256 xdr_bool(xdrs, &resokp->eof) == FALSE) {
1257 return (FALSE);
1258 }
1259
1260 if (xdrs->x_op == XDR_ENCODE) {
1261 int i, rndup;
1262
1263 mp = resokp->data.mp;
1264 if (mp != NULL && xdrs->x_ops == &xdrmblk_ops) {
1265 mp->b_wptr += resokp->count;
1266 rndup = BYTES_PER_XDR_UNIT -
1267 (resokp->data.data_len % BYTES_PER_XDR_UNIT);
1268 if (rndup != BYTES_PER_XDR_UNIT)
1269 for (i = 0; i < rndup; i++)
1270 *mp->b_wptr++ = '\0';
1271 if (xdrmblk_putmblk(xdrs, mp, resokp->count) == TRUE) {
1272 resokp->data.mp = NULL;
1273 return (TRUE);
1274 }
1275 }
1276 /*
1277 * Fall thru for the xdr_bytes()
1278 *
1279 * note: the mblk will be freed in
1280 * rfs3_read_free.
1281 */
1282 }
1283
1284 ret = xdr_bytes(xdrs, (char **)&resokp->data.data_val,
1285 &resokp->data.data_len, nfs3tsize());
1286
1287 return (ret);
1288 }
1289
1290 bool_t
1291 xdr_READ3vres(XDR *xdrs, READ3vres *objp)
1292 {
1293 /*
1294 * DECODE or FREE only
1295 */
1296 if (xdrs->x_op == XDR_FREE)
1297 return (TRUE);
1298
1299 if (xdrs->x_op != XDR_DECODE)
1300 return (FALSE);
1301
1302 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1303 return (FALSE);
1304
1305 if (!xdr_post_op_vattr(xdrs, &objp->pov))
1306 return (FALSE);
1307
1308 if (objp->status != NFS3_OK)
1309 return (TRUE);
1310
1311 if (!xdr_u_int(xdrs, &objp->count))
1312 return (FALSE);
1313
1314 if (!xdr_bool(xdrs, &objp->eof))
1315 return (FALSE);
1316
1317 return (xdr_bytes(xdrs, (char **)&objp->data.data_val,
1318 &objp->data.data_len, nfs3tsize()));
1319 }
1320
1321 bool_t
1322 xdr_READ3uiores(XDR *xdrs, READ3uiores *objp)
1323 {
1324 bool_t attributes;
1325 mblk_t *mp;
1326 size_t n;
1327 int error;
1328 int size = (int)objp->size;
1329 struct uio *uiop = objp->uiop;
1330 int32_t fattr3_len = NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT;
1331 int32_t *ptr;
1332
1333 /*
1334 * DECODE or FREE only
1335 */
1336 if (xdrs->x_op == XDR_FREE)
1337 return (TRUE);
1338
1339 if (xdrs->x_op != XDR_DECODE)
1340 return (FALSE);
1341
1342 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status))
1343 return (FALSE);
1344
1345 if (!XDR_GETINT32(xdrs, (int32_t *)&attributes))
1346 return (FALSE);
1347
1348 /*
1349 * For directio we just skip over attributes if present
1350 */
1351 switch (attributes) {
1352 case TRUE:
1353 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &fattr3_len))
1354 return (FALSE);
1355 break;
1356 case FALSE:
1357 break;
1358 default:
1359 return (FALSE);
1360 }
1361
1362 if (objp->status != NFS3_OK)
1363 return (TRUE);
1364
1365 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->count))
1366 return (FALSE);
1367
1368 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->eof))
1369 return (FALSE);
1370
1371 if (xdrs->x_ops == &xdrmblk_ops) {
1372 if (!xdrmblk_getmblk(xdrs, &mp, &objp->size))
1373 return (FALSE);
1374
1375 if (objp->size == 0)
1376 return (TRUE);
1377
1378 if (objp->size > size)
1379 return (FALSE);
1380
1381 size = (int)objp->size;
1382 do {
1383 n = MIN(size, mp->b_wptr - mp->b_rptr);
1384 if ((n = MIN(uiop->uio_resid, n)) != 0) {
1385
1386 error = uiomove((char *)mp->b_rptr, n, UIO_READ,
1387 uiop);
1388 if (error)
1389 return (FALSE);
1390 mp->b_rptr += n;
1391 size -= n;
1392 }
1393
1394 while (mp && (mp->b_rptr >= mp->b_wptr))
1395 mp = mp->b_cont;
1396 } while (mp && size > 0 && uiop->uio_resid > 0);
1397
1398 return (TRUE);
1399 }
1400
1401 /*
1402 * This isn't an xdrmblk stream. Handle the likely
1403 * case that it can be inlined (ex. xdrmem).
1404 */
1405 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->size))
1406 return (FALSE);
1407
1408 if (objp->size == 0)
1409 return (TRUE);
1410
1411 if (objp->size > size)
1412 return (FALSE);
1413
1414 size = (int)objp->size;
1415 if ((ptr = XDR_INLINE(xdrs, size)) != NULL)
1416 return (uiomove(ptr, size, UIO_READ, uiop) ? FALSE : TRUE);
1417
1418 /*
1419 * Handle some other (unlikely) stream type that will need a copy.
1420 */
1421 if ((ptr = kmem_alloc(size, KM_NOSLEEP)) == NULL)
1422 return (FALSE);
1423
1424 if (!XDR_GETBYTES(xdrs, (caddr_t)ptr, size)) {
1425 kmem_free(ptr, size);
1426 return (FALSE);
1427 }
1428 error = uiomove(ptr, size, UIO_READ, uiop);
1429 kmem_free(ptr, size);
1430
1431 return (error ? FALSE : TRUE);
1432 }
1433
1434 bool_t
1435 xdr_WRITE3args(XDR *xdrs, WRITE3args *objp)
1436 {
1437 int32_t *ptr;
1438 int32_t *fhp;
1439 uint_t in_size;
1440 int len;
1441
1442 in_size = RNDUP(sizeof (fhandle_t)) + 5 * BYTES_PER_XDR_UNIT;
1443 ptr = XDR_INLINE(xdrs, in_size);
1444
1445 if (ptr != NULL) {
1446 len = (xdrs->x_op == XDR_DECODE) ? *ptr : objp->file.fh3_length;
1447
1448 if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
1449 fhp = (int32_t *)&(objp->file.fh3_u.data);
1450 if (xdrs->x_op == XDR_DECODE) {
1451 objp->file.fh3_length = IXDR_GET_U_INT32(ptr);
1452 *fhp++ = *ptr++;
1453 *fhp++ = *ptr++;
1454 *fhp++ = *ptr++;
1455 *fhp++ = *ptr++;
1456 *fhp++ = *ptr++;
1457 *fhp++ = *ptr++;
1458 *fhp++ = *ptr++;
1459 *fhp = *ptr++;
1460 IXDR_GET_U_HYPER(ptr, objp->offset);
1461 objp->count = IXDR_GET_U_INT32(ptr);
1462 objp->stable = IXDR_GET_ENUM(ptr,
1463 enum stable_how);
1464 if (xdrs->x_ops == &xdrmblk_ops)
1465 return (xdrmblk_getmblk(xdrs,
1466 &objp->mblk,
1467 (uint_t *)&objp->data.data_len));
1468 /*
1469 * It is just as efficient to xdr_bytes
1470 * an array of unknown length as to inline
1471 * copy it.
1472 */
1473 return (xdr_bytes(xdrs, &objp->data.data_val,
1474 (uint_t *)&objp->data.data_len,
1475 nfs3tsize()));
1476 }
1477
1478 if (xdrs->x_op == XDR_ENCODE) {
1479 IXDR_PUT_U_INT32(ptr, objp->file.fh3_length);
1480 *ptr++ = *fhp++;
1481 *ptr++ = *fhp++;
1482 *ptr++ = *fhp++;
1483 *ptr++ = *fhp++;
1484 *ptr++ = *fhp++;
1485 *ptr++ = *fhp++;
1486 *ptr++ = *fhp++;
1487 *ptr++ = *fhp;
1488 IXDR_PUT_U_HYPER(ptr, objp->offset);
1489 IXDR_PUT_U_INT32(ptr, objp->count);
1490 IXDR_PUT_ENUM(ptr, objp->stable);
1491 return (xdr_bytes(xdrs,
1492 (char **)&objp->data.data_val,
1493 (uint_t *)&objp->data.data_len,
1494 nfs3tsize()));
1495 }
1496
1497 ASSERT(xdrs->x_op == XDR_FREE);
1498 if (objp->data.data_val != NULL) {
1499 kmem_free(objp->data.data_val,
1500 (uint_t)objp->data.data_len);
1501 objp->data.data_val = NULL;
1502 }
1503 return (TRUE);
1504 }
1505 }
1506
1507 if (!xdr_nfs_fh3(xdrs, &objp->file))
1508 return (FALSE);
1509 if (!xdr_u_longlong_t(xdrs, &objp->offset))
1510 return (FALSE);
1511 if (!xdr_u_int(xdrs, &objp->count))
1512 return (FALSE);
1513 if (!xdr_enum(xdrs, (enum_t *)&objp->stable))
1514 return (FALSE);
1515
1516 if (xdrs->x_op == XDR_DECODE) {
1517 if (xdrs->x_ops == &xdrmblk_ops) {
1518 if (xdrmblk_getmblk(xdrs, &objp->mblk,
1519 &objp->data.data_len) == TRUE) {
1520 objp->data.data_val = NULL;
1521 return (TRUE);
1522 }
1523 }
1524 objp->mblk = NULL;
1525 /* Else fall thru for the xdr_bytes(). */
1526 }
1527
1528 return (xdr_bytes(xdrs, (char **)&objp->data.data_val,
1529 &objp->data.data_len, nfs3tsize()));
1530 }
1531
1532 bool_t
1533 xdr_WRITE3res(XDR *xdrs, WRITE3res *objp)
1534 {
1535 WRITE3resok *resokp;
1536
1537 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1538 return (FALSE);
1539 if (objp->status != NFS3_OK) /* xdr_WRITE3resfail */
1540 return (xdr_wcc_data(xdrs, &objp->resfail.file_wcc));
1541
1542 /* xdr_WRITE3resok */
1543 resokp = &objp->resok;
1544 if (!xdr_wcc_data(xdrs, &resokp->file_wcc))
1545 return (FALSE);
1546 if (!xdr_u_int(xdrs, &resokp->count))
1547 return (FALSE);
1548 if (!xdr_enum(xdrs, (enum_t *)&resokp->committed))
1549 return (FALSE);
1550 /*
1551 * writeverf3 is really an opaque 8 byte
1552 * quantity, but we will treat it as a
1553 * hyper for efficiency, the cost of
1554 * a byteswap here saves bcopys elsewhere
1555 */
1556 return (xdr_u_longlong_t(xdrs, &resokp->verf));
1557 }
1558
1559 bool_t
1560 xdr_CREATE3args(XDR *xdrs, CREATE3args *objp)
1561 {
1562 createhow3 *howp;
1563
1564 if (!xdr_diropargs3(xdrs, &objp->where))
1565 return (FALSE);
1566
1567 /* xdr_createhow3 */
1568 howp = &objp->how;
1569
1570 if (!xdr_enum(xdrs, (enum_t *)&howp->mode))
1571 return (FALSE);
1572 switch (howp->mode) {
1573 case UNCHECKED:
1574 case GUARDED:
1575 return (xdr_sattr3(xdrs, &howp->createhow3_u.obj_attributes));
1576 case EXCLUSIVE:
1577 /*
1578 * createverf3 is really an opaque 8 byte
1579 * quantity, but we will treat it as a
1580 * hyper for efficiency, the cost of
1581 * a byteswap here saves bcopys elsewhere
1582 */
1583 return (xdr_u_longlong_t(xdrs, &howp->createhow3_u.verf));
1584 default:
1585 return (FALSE);
1586 }
1587 }
1588
1589 bool_t
1590 xdr_CREATE3res(XDR *xdrs, CREATE3res *objp)
1591 {
1592 CREATE3resok *resokp;
1593
1594 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1595 return (FALSE);
1596 switch (objp->status) {
1597 case NFS3_OK:
1598 /* xdr_CREATE3resok */
1599 resokp = &objp->resok;
1600
1601 if (!xdr_post_op_fh3(xdrs, &resokp->obj))
1602 return (FALSE);
1603 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
1604 return (FALSE);
1605 return (xdr_wcc_data(xdrs, &resokp->dir_wcc));
1606 default:
1607 /* xdr_CREATE3resfail */
1608 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
1609 }
1610 }
1611
1612 bool_t
1613 xdr_MKDIR3args(XDR *xdrs, MKDIR3args *objp)
1614 {
1615 if (!xdr_diropargs3(xdrs, &objp->where))
1616 return (FALSE);
1617 return (xdr_sattr3(xdrs, &objp->attributes));
1618 }
1619
1620 bool_t
1621 xdr_MKDIR3res(XDR *xdrs, MKDIR3res *objp)
1622 {
1623 MKDIR3resok *resokp;
1624
1625 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1626 return (FALSE);
1627 switch (objp->status) {
1628 case NFS3_OK:
1629 /* xdr_MKDIR3resok */
1630 resokp = &objp->resok;
1631
1632 if (!xdr_post_op_fh3(xdrs, &resokp->obj))
1633 return (FALSE);
1634 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
1635 return (FALSE);
1636 return (xdr_wcc_data(xdrs, &resokp->dir_wcc));
1637 default:
1638 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
1639 }
1640 }
1641
1642 bool_t
1643 xdr_SYMLINK3args(XDR *xdrs, SYMLINK3args *objp)
1644 {
1645 if (!xdr_diropargs3(xdrs, &objp->where))
1646 return (FALSE);
1647 if (!xdr_sattr3(xdrs, &objp->symlink.symlink_attributes))
1648 return (FALSE);
1649 return (xdr_string3(xdrs, &objp->symlink.symlink_data, MAXPATHLEN));
1650 }
1651
1652 bool_t
1653 xdr_SYMLINK3res(XDR *xdrs, SYMLINK3res *objp)
1654 {
1655 SYMLINK3resok *resokp;
1656
1657 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1658 return (FALSE);
1659 switch (objp->status) {
1660 case NFS3_OK:
1661 resokp = &objp->resok;
1662 /* xdr_SYMLINK3resok */
1663 if (!xdr_post_op_fh3(xdrs, &resokp->obj))
1664 return (FALSE);
1665 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
1666 return (FALSE);
1667 return (xdr_wcc_data(xdrs, &resokp->dir_wcc));
1668 default:
1669 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
1670 }
1671 }
1672
1673 bool_t
1674 xdr_MKNOD3args(XDR *xdrs, MKNOD3args *objp)
1675 {
1676 mknoddata3 *whatp;
1677 devicedata3 *nod_objp;
1678
1679 if (!xdr_diropargs3(xdrs, &objp->where))
1680 return (FALSE);
1681
1682 whatp = &objp->what;
1683 if (!xdr_enum(xdrs, (enum_t *)&whatp->type))
1684 return (FALSE);
1685 switch (whatp->type) {
1686 case NF3CHR:
1687 case NF3BLK:
1688 /* xdr_devicedata3 */
1689 nod_objp = &whatp->mknoddata3_u.device;
1690 if (!xdr_sattr3(xdrs, &nod_objp->dev_attributes))
1691 return (FALSE);
1692 if (!xdr_u_int(xdrs, &nod_objp->spec.specdata1))
1693 return (FALSE);
1694 return (xdr_u_int(xdrs, &nod_objp->spec.specdata2));
1695 case NF3SOCK:
1696 case NF3FIFO:
1697 return (xdr_sattr3(xdrs, &whatp->mknoddata3_u.pipe_attributes));
1698 default:
1699 break;
1700 }
1701 return (TRUE);
1702 }
1703
1704 bool_t
1705 xdr_MKNOD3res(XDR *xdrs, MKNOD3res *objp)
1706 {
1707 MKNOD3resok *resokp;
1708
1709 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1710 return (FALSE);
1711 switch (objp->status) {
1712 case NFS3_OK:
1713 /* xdr_MKNOD3resok */
1714 resokp = &objp->resok;
1715 if (!xdr_post_op_fh3(xdrs, &resokp->obj))
1716 return (FALSE);
1717 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
1718 return (FALSE);
1719 return (xdr_wcc_data(xdrs, &resokp->dir_wcc));
1720 default:
1721 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
1722 }
1723 }
1724
1725 bool_t
1726 xdr_REMOVE3res(XDR *xdrs, REMOVE3res *objp)
1727 {
1728 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1729 return (FALSE);
1730 switch (objp->status) {
1731 case NFS3_OK:
1732 return (xdr_wcc_data(xdrs, &objp->resok.dir_wcc));
1733 default:
1734 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
1735 }
1736 }
1737
1738 bool_t
1739 xdr_RMDIR3res(XDR *xdrs, RMDIR3res *objp)
1740 {
1741 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1742 return (FALSE);
1743 switch (objp->status) {
1744 case NFS3_OK:
1745 return (xdr_wcc_data(xdrs, &objp->resok.dir_wcc));
1746 default:
1747 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
1748 }
1749 }
1750
1751 bool_t
1752 xdr_RENAME3args(XDR *xdrs, RENAME3args *objp)
1753 {
1754 if (!xdr_diropargs3(xdrs, &objp->from))
1755 return (FALSE);
1756 return (xdr_diropargs3(xdrs, &objp->to));
1757 }
1758
1759 bool_t
1760 xdr_RENAME3res(XDR *xdrs, RENAME3res *objp)
1761 {
1762 RENAME3resok *resokp;
1763 RENAME3resfail *resfailp;
1764
1765 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1766 return (FALSE);
1767 switch (objp->status) {
1768 case NFS3_OK:
1769 /* xdr_RENAME3resok */
1770 resokp = &objp->resok;
1771
1772 if (!xdr_wcc_data(xdrs, &resokp->fromdir_wcc))
1773 return (FALSE);
1774 return (xdr_wcc_data(xdrs, &resokp->todir_wcc));
1775 default:
1776 /* xdr_RENAME3resfail */
1777 resfailp = &objp->resfail;
1778 if (!xdr_wcc_data(xdrs, &resfailp->fromdir_wcc))
1779 return (FALSE);
1780 return (xdr_wcc_data(xdrs, &resfailp->todir_wcc));
1781 }
1782 }
1783
1784 bool_t
1785 xdr_LINK3args(XDR *xdrs, LINK3args *objp)
1786 {
1787 if (!xdr_nfs_fh3(xdrs, &objp->file))
1788 return (FALSE);
1789 return (xdr_diropargs3(xdrs, &objp->link));
1790 }
1791
1792 bool_t
1793 xdr_LINK3res(XDR *xdrs, LINK3res *objp)
1794 {
1795 LINK3resok *resokp;
1796 LINK3resfail *resfailp;
1797
1798 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1799 return (FALSE);
1800 switch (objp->status) {
1801 case NFS3_OK:
1802 /* xdr_LINK3resok */
1803 resokp = &objp->resok;
1804 if (!xdr_post_op_attr(xdrs, &resokp->file_attributes))
1805 return (FALSE);
1806 return (xdr_wcc_data(xdrs, &resokp->linkdir_wcc));
1807 default:
1808 /* xdr_LINK3resfail */
1809 resfailp = &objp->resfail;
1810 if (!xdr_post_op_attr(xdrs, &resfailp->file_attributes))
1811 return (FALSE);
1812 return (xdr_wcc_data(xdrs, &resfailp->linkdir_wcc));
1813 }
1814 }
1815
1816 bool_t
1817 xdr_READDIR3args(XDR *xdrs, READDIR3args *objp)
1818 {
1819 int32_t *ptr;
1820 int32_t *fhp;
1821 uint_t in_size;
1822 int len;
1823
1824 if (xdrs->x_op == XDR_FREE)
1825 return (TRUE);
1826
1827 in_size = RNDUP(sizeof (fhandle_t)) + NFS3_COOKIEVERFSIZE +
1828 4 * BYTES_PER_XDR_UNIT;
1829 ptr = XDR_INLINE(xdrs, in_size);
1830
1831 if (ptr != NULL) {
1832 len = (xdrs->x_op == XDR_DECODE) ? *ptr : objp->dir.fh3_length;
1833
1834 if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
1835
1836 fhp = (int32_t *)&(objp->dir.fh3_u.data);
1837
1838 if (xdrs->x_op == XDR_DECODE) {
1839 objp->dir.fh3_length = IXDR_GET_U_INT32(ptr);
1840 *fhp++ = *ptr++;
1841 *fhp++ = *ptr++;
1842 *fhp++ = *ptr++;
1843 *fhp++ = *ptr++;
1844 *fhp++ = *ptr++;
1845 *fhp++ = *ptr++;
1846 *fhp++ = *ptr++;
1847 *fhp = *ptr++;
1848 IXDR_GET_U_HYPER(ptr, objp->cookie);
1849 /*
1850 * cookieverf is really an opaque 8 byte
1851 * quantity, but we will treat it as a
1852 * hyper for efficiency, the cost of
1853 * a byteswap here saves bcopys elsewhere
1854 */
1855 IXDR_GET_U_HYPER(ptr, objp->cookieverf);
1856 objp->count = IXDR_GET_U_INT32(ptr);
1857 } else {
1858 IXDR_PUT_U_INT32(ptr, objp->dir.fh3_length);
1859 *ptr++ = *fhp++;
1860 *ptr++ = *fhp++;
1861 *ptr++ = *fhp++;
1862 *ptr++ = *fhp++;
1863 *ptr++ = *fhp++;
1864 *ptr++ = *fhp++;
1865 *ptr++ = *fhp++;
1866 *ptr++ = *fhp;
1867 IXDR_PUT_U_HYPER(ptr, objp->cookie);
1868 /*
1869 * cookieverf is really an opaque 8 byte
1870 * quantity, but we will treat it as a
1871 * hyper for efficiency, the cost of
1872 * a byteswap here saves bcopys elsewhere
1873 */
1874 IXDR_PUT_U_HYPER(ptr, objp->cookieverf);
1875 IXDR_PUT_U_INT32(ptr, objp->count);
1876 }
1877 return (TRUE);
1878 }
1879 }
1880
1881 if (!xdr_nfs_fh3(xdrs, &objp->dir))
1882 return (FALSE);
1883 if (!xdr_u_longlong_t(xdrs, &objp->cookie))
1884 return (FALSE);
1885 /*
1886 * cookieverf is really an opaque 8 byte
1887 * quantity, but we will treat it as a
1888 * hyper for efficiency, the cost of
1889 * a byteswap here saves bcopys elsewhere
1890 */
1891 if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
1892 return (FALSE);
1893 return (xdr_u_int(xdrs, &objp->count));
1894 }
1895
1896 #ifdef nextdp
1897 #undef nextdp
1898 #endif
1899 #define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
1900 #ifdef roundup
1901 #undef roundup
1902 #endif
1903 #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
1904
1905 /*
1906 * ENCODE ONLY
1907 */
1908 static bool_t
1909 xdr_putdirlist(XDR *xdrs, READDIR3resok *objp)
1910 {
1911 struct dirent64 *dp;
1912 char *name;
1913 int size;
1914 int bufsize;
1915 uint_t namlen;
1916 bool_t true = TRUE;
1917 bool_t false = FALSE;
1918 int entrysz;
1919 int tofit;
1920 fileid3 fileid;
1921 cookie3 cookie;
1922
1923 if (xdrs->x_op != XDR_ENCODE)
1924 return (FALSE);
1925
1926 /*
1927 * bufsize is used to keep track of the size of the response.
1928 * It is primed with:
1929 * 1 for the status +
1930 * 1 for the dir_attributes.attributes boolean +
1931 * 2 for the cookie verifier
1932 * all times BYTES_PER_XDR_UNIT to convert from XDR units
1933 * to bytes. If there are directory attributes to be
1934 * returned, then:
1935 * NFS3_SIZEOF_FATTR3 for the dir_attributes.attr fattr3
1936 * time BYTES_PER_XDR_UNIT is added to account for them.
1937 */
1938 bufsize = (1 + 1 + 2) * BYTES_PER_XDR_UNIT;
1939 if (objp->dir_attributes.attributes)
1940 bufsize += NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT;
1941 for (size = objp->size, dp = (struct dirent64 *)objp->reply.entries;
1942 size > 0;
1943 size -= dp->d_reclen, dp = nextdp(dp)) {
1944 if (dp->d_reclen == 0)
1945 return (FALSE);
1946 if (dp->d_ino == 0)
1947 continue;
1948 name = dp->d_name;
1949 namlen = (uint_t)strlen(dp->d_name);
1950 /*
1951 * An entry is composed of:
1952 * 1 for the true/false list indicator +
1953 * 2 for the fileid +
1954 * 1 for the length of the name +
1955 * 2 for the cookie +
1956 * all times BYTES_PER_XDR_UNIT to convert from
1957 * XDR units to bytes, plus the length of the name
1958 * rounded up to the nearest BYTES_PER_XDR_UNIT.
1959 */
1960 entrysz = (1 + 2 + 1 + 2) * BYTES_PER_XDR_UNIT +
1961 roundup(namlen, BYTES_PER_XDR_UNIT);
1962 /*
1963 * We need to check to see if the number of bytes left
1964 * to go into the buffer will actually fit into the
1965 * buffer. This is calculated as the size of this
1966 * entry plus:
1967 * 1 for the true/false list indicator +
1968 * 1 for the eof indicator
1969 * times BYTES_PER_XDR_UNIT to convert from from
1970 * XDR units to bytes.
1971 */
1972 tofit = entrysz + (1 + 1) * BYTES_PER_XDR_UNIT;
1973 if (bufsize + tofit > objp->count) {
1974 objp->reply.eof = FALSE;
1975 break;
1976 }
1977 fileid = (fileid3)(dp->d_ino);
1978 cookie = (cookie3)(dp->d_off);
1979 if (!xdr_bool(xdrs, &true) ||
1980 !xdr_u_longlong_t(xdrs, &fileid) ||
1981 !xdr_bytes(xdrs, &name, &namlen, ~0) ||
1982 !xdr_u_longlong_t(xdrs, &cookie)) {
1983 return (FALSE);
1984 }
1985 bufsize += entrysz;
1986 }
1987 if (!xdr_bool(xdrs, &false))
1988 return (FALSE);
1989 if (!xdr_bool(xdrs, &objp->reply.eof))
1990 return (FALSE);
1991 return (TRUE);
1992 }
1993
1994 bool_t
1995 xdr_READDIR3res(XDR *xdrs, READDIR3res *objp)
1996 {
1997 READDIR3resok *resokp;
1998
1999 /*
2000 * ENCODE or FREE only
2001 */
2002 if (xdrs->x_op == XDR_DECODE)
2003 return (FALSE);
2004
2005 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2006 return (FALSE);
2007 if (objp->status != NFS3_OK)
2008 return (xdr_post_op_attr(xdrs, &objp->resfail.dir_attributes));
2009
2010 /* xdr_READDIR3resok */
2011 resokp = &objp->resok;
2012 if (!xdr_post_op_attr(xdrs, &resokp->dir_attributes))
2013 return (FALSE);
2014 if (xdrs->x_op != XDR_ENCODE)
2015 return (TRUE);
2016 /*
2017 * cookieverf is really an opaque 8 byte
2018 * quantity, but we will treat it as a
2019 * hyper for efficiency, the cost of
2020 * a byteswap here saves bcopys elsewhere
2021 */
2022 if (!xdr_u_longlong_t(xdrs, &resokp->cookieverf))
2023 return (FALSE);
2024 return (xdr_putdirlist(xdrs, resokp));
2025 }
2026
2027 bool_t
2028 xdr_READDIR3vres(XDR *xdrs, READDIR3vres *objp)
2029 {
2030 dirent64_t *dp;
2031 uint_t entries_size;
2032 int outcount = 0;
2033
2034 /*
2035 * DECODE or FREE only
2036 */
2037 if (xdrs->x_op == XDR_FREE)
2038 return (TRUE);
2039
2040 if (xdrs->x_op != XDR_DECODE)
2041 return (FALSE);
2042
2043 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2044 return (FALSE);
2045
2046 if (!xdr_post_op_vattr(xdrs, &objp->dir_attributes))
2047 return (FALSE);
2048
2049 if (objp->status != NFS3_OK)
2050 return (TRUE);
2051
2052 /*
2053 * cookieverf is really an opaque 8 byte
2054 * quantity, but we will treat it as a
2055 * hyper for efficiency, the cost of
2056 * a byteswap here saves bcopys elsewhere
2057 */
2058 if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
2059 return (FALSE);
2060
2061 entries_size = objp->entries_size;
2062 dp = objp->entries;
2063
2064 for (;;) {
2065 uint_t this_reclen;
2066 bool_t valid;
2067 uint_t namlen;
2068 ino64_t fileid;
2069
2070 if (!XDR_GETINT32(xdrs, (int32_t *)&valid))
2071 return (FALSE);
2072 if (!valid) {
2073 /*
2074 * We have run out of entries, decode eof.
2075 */
2076 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->eof))
2077 return (FALSE);
2078
2079 break;
2080 }
2081
2082 /*
2083 * fileid3 fileid
2084 */
2085 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&fileid))
2086 return (FALSE);
2087
2088 /*
2089 * filename3 name
2090 */
2091 if (!XDR_GETINT32(xdrs, (int32_t *)&namlen))
2092 return (FALSE);
2093 this_reclen = DIRENT64_RECLEN(namlen);
2094
2095 /*
2096 * If this will overflow buffer, stop decoding
2097 */
2098 if ((outcount + this_reclen) > entries_size) {
2099 objp->eof = FALSE;
2100 break;
2101 }
2102 dp->d_reclen = this_reclen;
2103 dp->d_ino = fileid;
2104
2105 if (!xdr_opaque(xdrs, dp->d_name, namlen))
2106 return (FALSE);
2107 bzero(&dp->d_name[namlen],
2108 DIRENT64_NAMELEN(this_reclen) - namlen);
2109
2110 /*
2111 * cookie3 cookie
2112 */
2113 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&dp->d_off))
2114 return (FALSE);
2115 objp->loff = dp->d_off;
2116
2117 outcount += this_reclen;
2118 dp = (dirent64_t *)((intptr_t)dp + this_reclen);
2119 }
2120
2121 objp->size = outcount;
2122 return (TRUE);
2123 }
2124
2125 bool_t
2126 xdr_READDIRPLUS3args(XDR *xdrs, READDIRPLUS3args *objp)
2127 {
2128 int32_t *ptr;
2129 int32_t *fhp;
2130 uint_t in_size;
2131 int len;
2132
2133 if (xdrs->x_op == XDR_FREE)
2134 return (TRUE);
2135
2136 in_size = RNDUP(sizeof (fhandle_t)) + NFS3_COOKIEVERFSIZE +
2137 5 * BYTES_PER_XDR_UNIT;
2138
2139 ptr = XDR_INLINE(xdrs, in_size);
2140 if (ptr != NULL) {
2141 len = (xdrs->x_op == XDR_DECODE) ? *ptr : objp->dir.fh3_length;
2142
2143 if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
2144
2145 fhp = (int32_t *)&(objp->dir.fh3_u.data);
2146
2147 if (xdrs->x_op == XDR_DECODE) {
2148 objp->dir.fh3_length = IXDR_GET_U_INT32(ptr);
2149 *fhp++ = *ptr++;
2150 *fhp++ = *ptr++;
2151 *fhp++ = *ptr++;
2152 *fhp++ = *ptr++;
2153 *fhp++ = *ptr++;
2154 *fhp++ = *ptr++;
2155 *fhp++ = *ptr++;
2156 *fhp = *ptr++;
2157 IXDR_GET_U_HYPER(ptr, objp->cookie);
2158 /*
2159 * cookieverf is really an opaque 8 byte
2160 * quantity, but we will treat it as a
2161 * hyper for efficiency, the cost of
2162 * a byteswap here saves bcopys elsewhere
2163 */
2164 IXDR_GET_U_HYPER(ptr, objp->cookieverf);
2165 objp->dircount = IXDR_GET_U_INT32(ptr);
2166 objp->maxcount = IXDR_GET_U_INT32(ptr);
2167 } else {
2168 IXDR_PUT_U_INT32(ptr, objp->dir.fh3_length);
2169 *ptr++ = *fhp++;
2170 *ptr++ = *fhp++;
2171 *ptr++ = *fhp++;
2172 *ptr++ = *fhp++;
2173 *ptr++ = *fhp++;
2174 *ptr++ = *fhp++;
2175 *ptr++ = *fhp++;
2176 *ptr++ = *fhp;
2177 IXDR_PUT_U_HYPER(ptr, objp->cookie);
2178 /*
2179 * cookieverf is really an opaque 8 byte
2180 * quantity, but we will treat it as a
2181 * hyper for efficiency, the cost of
2182 * a byteswap here saves bcopys elsewhere
2183 */
2184 IXDR_PUT_U_HYPER(ptr, objp->cookieverf);
2185 IXDR_PUT_U_INT32(ptr, objp->dircount);
2186 IXDR_PUT_U_INT32(ptr, objp->maxcount);
2187 }
2188 return (TRUE);
2189 }
2190 }
2191
2192 if (!xdr_nfs_fh3(xdrs, &objp->dir))
2193 return (FALSE);
2194 if (!xdr_u_longlong_t(xdrs, &objp->cookie))
2195 return (FALSE);
2196 /*
2197 * cookieverf is really an opaque 8 byte
2198 * quantity, but we will treat it as a
2199 * hyper for efficiency, the cost of
2200 * a byteswap here saves bcopys elsewhere
2201 */
2202 if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
2203 return (FALSE);
2204 if (!xdr_u_int(xdrs, &objp->dircount))
2205 return (FALSE);
2206 return (xdr_u_int(xdrs, &objp->maxcount));
2207
2208 }
2209
2210 /*
2211 * ENCODE ONLY
2212 */
2213 static bool_t
2214 xdr_putdirpluslist(XDR *xdrs, READDIRPLUS3resok *objp)
2215 {
2216 struct dirent64 *dp;
2217 char *name;
2218 int nents;
2219 bool_t true = TRUE;
2220 bool_t false = FALSE;
2221 fileid3 fileid;
2222 cookie3 cookie;
2223 entryplus3_info *infop;
2224
2225 if (xdrs->x_op != XDR_ENCODE)
2226 return (FALSE);
2227
2228 dp = (struct dirent64 *)objp->reply.entries;
2229 nents = objp->size;
2230 infop = objp->infop;
2231
2232 while (nents > 0) {
2233 if (dp->d_reclen == 0)
2234 return (FALSE);
2235 if (dp->d_ino != 0) {
2236 name = dp->d_name;
2237 fileid = (fileid3)(dp->d_ino);
2238 cookie = (cookie3)(dp->d_off);
2239 if (!xdr_bool(xdrs, &true) ||
2240 !xdr_u_longlong_t(xdrs, &fileid) ||
2241 !xdr_bytes(xdrs, &name, &infop->namelen, ~0) ||
2242 !xdr_u_longlong_t(xdrs, &cookie) ||
2243 !xdr_post_op_attr(xdrs, &infop->attr) ||
2244 !xdr_post_op_fh3(xdrs, &infop->fh)) {
2245 return (FALSE);
2246 }
2247 }
2248 dp = nextdp(dp);
2249 infop++;
2250 nents--;
2251 }
2252
2253 if (!xdr_bool(xdrs, &false))
2254 return (FALSE);
2255 if (!xdr_bool(xdrs, &objp->reply.eof))
2256 return (FALSE);
2257 return (TRUE);
2258 }
2259
2260 bool_t
2261 xdr_READDIRPLUS3res(XDR *xdrs, READDIRPLUS3res *objp)
2262 {
2263 READDIRPLUS3resok *resokp;
2264
2265 /*
2266 * ENCODE or FREE only
2267 */
2268 if (xdrs->x_op == XDR_DECODE)
2269 return (FALSE);
2270
2271 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2272 return (FALSE);
2273 switch (objp->status) {
2274 case NFS3_OK:
2275 /* xdr_READDIRPLUS3resok */
2276 resokp = &objp->resok;
2277 if (!xdr_post_op_attr(xdrs, &resokp->dir_attributes))
2278 return (FALSE);
2279 /*
2280 * cookieverf is really an opaque 8 byte
2281 * quantity, but we will treat it as a
2282 * hyper for efficiency, the cost of
2283 * a byteswap here saves bcopys elsewhere
2284 */
2285 if (!xdr_u_longlong_t(xdrs, &resokp->cookieverf))
2286 return (FALSE);
2287 if (xdrs->x_op == XDR_ENCODE) {
2288 if (!xdr_putdirpluslist(xdrs, resokp))
2289 return (FALSE);
2290 }
2291 break;
2292 default:
2293 return (xdr_post_op_attr(xdrs, &objp->resfail.dir_attributes));
2294 }
2295 return (TRUE);
2296 }
2297
2298 /*
2299 * Decode readdirplus directly into a dirent64_t and do the DNLC caching.
2300 */
2301 bool_t
2302 xdr_READDIRPLUS3vres(XDR *xdrs, READDIRPLUS3vres *objp)
2303 {
2304 dirent64_t *dp;
2305 vnode_t *dvp;
2306 uint_t entries_size;
2307 int outcount = 0;
2308 vnode_t *nvp;
2309 rnode_t *rp;
2310 post_op_vattr pov;
2311 vattr_t va;
2312
2313 /*
2314 * DECODE or FREE only
2315 */
2316 if (xdrs->x_op == XDR_FREE)
2317 return (TRUE);
2318
2319 if (xdrs->x_op != XDR_DECODE)
2320 return (FALSE);
2321
2322 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status))
2323 return (FALSE);
2324
2325 if (!xdr_post_op_vattr(xdrs, &objp->dir_attributes))
2326 return (FALSE);
2327
2328 if (objp->status != NFS3_OK)
2329 return (TRUE);
2330
2331 /*
2332 * cookieverf is really an opaque 8 byte
2333 * quantity, but we will treat it as a
2334 * hyper for efficiency, the cost of
2335 * a byteswap here saves bcopys elsewhere
2336 */
2337 if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
2338 return (FALSE);
2339
2340 dvp = objp->dir_attributes.fres.vp;
2341 rp = VTOR(dvp);
2342
2343 pov.fres.vap = &va;
2344 pov.fres.vp = dvp;
2345
2346 entries_size = objp->entries_size;
2347 dp = objp->entries;
2348
2349 for (;;) {
2350 uint_t this_reclen;
2351 bool_t valid;
2352 uint_t namlen;
2353 nfs_fh3 fh;
2354 int va_valid;
2355 int fh_valid;
2356 ino64_t fileid;
2357
2358 if (!XDR_GETINT32(xdrs, (int32_t *)&valid))
2359 return (FALSE);
2360 if (!valid) {
2361 /*
2362 * We have run out of entries, decode eof.
2363 */
2364 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->eof))
2365 return (FALSE);
2366
2367 break;
2368 }
2369
2370 /*
2371 * fileid3 fileid
2372 */
2373 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&fileid))
2374 return (FALSE);
2375
2376 /*
2377 * filename3 name
2378 */
2379 if (!XDR_GETINT32(xdrs, (int32_t *)&namlen))
2380 return (FALSE);
2381 this_reclen = DIRENT64_RECLEN(namlen);
2382
2383 /*
2384 * If this will overflow buffer, stop decoding
2385 */
2386 if ((outcount + this_reclen) > entries_size) {
2387 objp->eof = FALSE;
2388 break;
2389 }
2390 dp->d_reclen = this_reclen;
2391 dp->d_ino = fileid;
2392
2393 if (!xdr_opaque(xdrs, dp->d_name, namlen))
2394 return (FALSE);
2395 bzero(&dp->d_name[namlen],
2396 DIRENT64_NAMELEN(this_reclen) - namlen);
2397
2398 /*
2399 * cookie3 cookie
2400 */
2401 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&dp->d_off))
2402 return (FALSE);
2403 objp->loff = dp->d_off;
2404
2405 /*
2406 * post_op_attr name_attributes
2407 */
2408 if (!xdr_post_op_vattr(xdrs, &pov))
2409 return (FALSE);
2410
2411 if (pov.attributes == TRUE &&
2412 pov.fres.status == NFS3_OK)
2413 va_valid = TRUE;
2414 else
2415 va_valid = FALSE;
2416
2417 /*
2418 * post_op_fh3 name_handle
2419 */
2420 if (!XDR_GETINT32(xdrs, (int32_t *)&fh_valid))
2421 return (FALSE);
2422
2423 /*
2424 * By definition of the standard fh_valid can be 0 (FALSE) or
2425 * 1 (TRUE), but we have to account for it being anything else
2426 * in case some other system didn't follow the standard. Note
2427 * that this is why the else checks if the fh_valid variable
2428 * is != FALSE.
2429 */
2430 if (fh_valid == TRUE) {
2431 if (!xdr_nfs_fh3(xdrs, &fh))
2432 return (FALSE);
2433 } else {
2434 if (fh_valid != FALSE)
2435 return (FALSE);
2436 }
2437
2438 /*
2439 * If the name is "." or there are no attributes,
2440 * don't polute the DNLC with "." entries or files
2441 * we cannot determine the type for.
2442 */
2443 if (!(namlen == 1 && dp->d_name[0] == '.') &&
2444 va_valid && fh_valid) {
2445
2446 /*
2447 * Do the DNLC caching
2448 */
2449 nvp = makenfs3node_va(&fh, &va, dvp->v_vfsp,
2450 objp->time, objp->credentials,
2451 rp->r_path, dp->d_name);
2452 dnlc_update(dvp, dp->d_name, nvp);
2453 VN_RELE(nvp);
2454 }
2455
2456 outcount += this_reclen;
2457 dp = (dirent64_t *)((intptr_t)dp + this_reclen);
2458 }
2459
2460 objp->size = outcount;
2461 return (TRUE);
2462 }
2463
2464 bool_t
2465 xdr_FSSTAT3res(XDR *xdrs, FSSTAT3res *objp)
2466 {
2467 FSSTAT3resok *resokp;
2468
2469 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2470 return (FALSE);
2471 if (objp->status != NFS3_OK)
2472 return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes));
2473
2474 /* xdr_FSSTAT3resok */
2475 resokp = &objp->resok;
2476 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
2477 return (FALSE);
2478 if (!xdr_u_longlong_t(xdrs, &resokp->tbytes))
2479 return (FALSE);
2480 if (!xdr_u_longlong_t(xdrs, &resokp->fbytes))
2481 return (FALSE);
2482 if (!xdr_u_longlong_t(xdrs, &resokp->abytes))
2483 return (FALSE);
2484 if (!xdr_u_longlong_t(xdrs, &resokp->tfiles))
2485 return (FALSE);
2486 if (!xdr_u_longlong_t(xdrs, &resokp->ffiles))
2487 return (FALSE);
2488 if (!xdr_u_longlong_t(xdrs, &resokp->afiles))
2489 return (FALSE);
2490 return (xdr_u_int(xdrs, &resokp->invarsec));
2491 }
2492
2493 bool_t
2494 xdr_FSINFO3res(XDR *xdrs, FSINFO3res *objp)
2495 {
2496 FSINFO3resok *resokp;
2497
2498 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2499 return (FALSE);
2500 if (objp->status != NFS3_OK) /* xdr_FSSTAT3resfail */
2501 return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes));
2502
2503 /* xdr_FSINFO3resok */
2504 resokp = &objp->resok;
2505 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
2506 return (FALSE);
2507 if (!xdr_u_int(xdrs, &resokp->rtmax))
2508 return (FALSE);
2509 if (!xdr_u_int(xdrs, &resokp->rtpref))
2510 return (FALSE);
2511 if (!xdr_u_int(xdrs, &resokp->rtmult))
2512 return (FALSE);
2513 if (!xdr_u_int(xdrs, &resokp->wtmax))
2514 return (FALSE);
2515 if (!xdr_u_int(xdrs, &resokp->wtpref))
2516 return (FALSE);
2517 if (!xdr_u_int(xdrs, &resokp->wtmult))
2518 return (FALSE);
2519 if (!xdr_u_int(xdrs, &resokp->dtpref))
2520 return (FALSE);
2521 if (!xdr_u_longlong_t(xdrs, &resokp->maxfilesize))
2522 return (FALSE);
2523 if (!xdr_u_int(xdrs, &resokp->time_delta.seconds))
2524 return (FALSE);
2525 if (!xdr_u_int(xdrs, &resokp->time_delta.nseconds))
2526 return (FALSE);
2527 return (xdr_u_int(xdrs, &resokp->properties));
2528 }
2529
2530 bool_t
2531 xdr_PATHCONF3res(XDR *xdrs, PATHCONF3res *objp)
2532 {
2533 PATHCONF3resok *resokp;
2534
2535 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2536 return (FALSE);
2537 if (objp->status != NFS3_OK)
2538 return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes));
2539
2540 /* xdr_PATHCONF3resok */
2541 resokp = &objp->resok;
2542 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
2543 return (FALSE);
2544 if (!xdr_u_int(xdrs, &resokp->info.link_max))
2545 return (FALSE);
2546 if (!xdr_u_int(xdrs, &resokp->info.name_max))
2547 return (FALSE);
2548 if (!xdr_bool(xdrs, &resokp->info.no_trunc))
2549 return (FALSE);
2550 if (!xdr_bool(xdrs, &resokp->info.chown_restricted))
2551 return (FALSE);
2552 if (!xdr_bool(xdrs, &resokp->info.case_insensitive))
2553 return (FALSE);
2554 return (xdr_bool(xdrs, &resokp->info.case_preserving));
2555 }
2556
2557 bool_t
2558 xdr_COMMIT3args(XDR *xdrs, COMMIT3args *objp)
2559 {
2560 int32_t *ptr;
2561 int32_t *fhp;
2562 int len;
2563 uint_t in_size;
2564
2565 if (xdrs->x_op == XDR_FREE)
2566 return (TRUE);
2567
2568 in_size = RNDUP(sizeof (fhandle_t)) + 4 * BYTES_PER_XDR_UNIT;
2569 ptr = XDR_INLINE(xdrs, in_size);
2570
2571 if (ptr != NULL) {
2572 len = (xdrs->x_op == XDR_DECODE) ? *ptr : objp->file.fh3_length;
2573
2574 if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
2575 fhp = (int32_t *)&(objp->file.fh3_u.data);
2576 if (xdrs->x_op == XDR_DECODE) {
2577 objp->file.fh3_length = IXDR_GET_U_INT32(ptr);
2578 *fhp++ = *ptr++;
2579 *fhp++ = *ptr++;
2580 *fhp++ = *ptr++;
2581 *fhp++ = *ptr++;
2582 *fhp++ = *ptr++;
2583 *fhp++ = *ptr++;
2584 *fhp++ = *ptr++;
2585 *fhp = *ptr++;
2586 IXDR_GET_U_HYPER(ptr, objp->offset);
2587 objp->count = IXDR_GET_U_INT32(ptr);
2588 } else {
2589 IXDR_PUT_U_INT32(ptr, objp->file.fh3_length);
2590 *ptr++ = *fhp++;
2591 *ptr++ = *fhp++;
2592 *ptr++ = *fhp++;
2593 *ptr++ = *fhp++;
2594 *ptr++ = *fhp++;
2595 *ptr++ = *fhp++;
2596 *ptr++ = *fhp++;
2597 *ptr++ = *fhp;
2598 IXDR_PUT_U_HYPER(ptr, objp->offset);
2599 IXDR_PUT_U_INT32(ptr, objp->count);
2600 }
2601 return (TRUE);
2602 }
2603 }
2604
2605 if (!xdr_nfs_fh3(xdrs, &objp->file))
2606 return (FALSE);
2607 if (!xdr_u_longlong_t(xdrs, &objp->offset))
2608 return (FALSE);
2609 return (xdr_u_int(xdrs, &objp->count));
2610 }
2611
2612 bool_t
2613 xdr_COMMIT3res(XDR *xdrs, COMMIT3res *objp)
2614 {
2615 COMMIT3resok *resokp;
2616
2617 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2618 return (FALSE);
2619 if (objp->status != NFS3_OK)
2620 return (xdr_wcc_data(xdrs, &objp->resfail.file_wcc));
2621
2622 /* xdr_COMMIT3resok */
2623 resokp = &objp->resok;
2624 if (!xdr_wcc_data(xdrs, &resokp->file_wcc))
2625 return (FALSE);
2626 /*
2627 * writeverf3 is really an opaque 8 byte
2628 * quantity, but we will treat it as a
2629 * hyper for efficiency, the cost of
2630 * a byteswap here saves bcopys elsewhere
2631 */
2632 return (xdr_u_longlong_t(xdrs, &resokp->verf));
2633 }