4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
29 #include <sys/param.h>
30 #include <sys/types.h>
31 #include <sys/systm.h>
33 #include <sys/vnode.h>
35 #include <sys/dirent.h>
37 #include <sys/stream.h>
38 #include <sys/strsubr.h>
39 #include <sys/debug.h>
40 #include <sys/t_lock.h>
43 #include <rpc/types.h>
51 #include <vm/seg_map.h>
52 #include <vm/seg_kmem.h>
54 static bool_t
xdr_fastshorten(XDR
*, uint_t
);
57 * These are the XDR routines used to serialize and deserialize
58 * the various structures passed as parameters accross the network
59 * between NFS clients and servers.
64 * The fhandle struct is treated a opaque data on the wire
67 xdr_fhandle(XDR
*xdrs
, fhandle_t
*fh
)
72 if (xdrs
->x_op
== XDR_FREE
)
75 ptr
= XDR_INLINE(xdrs
, RNDUP(sizeof (fhandle_t
)));
78 if (xdrs
->x_op
== XDR_DECODE
) {
100 return (xdr_opaque(xdrs
, (caddr_t
)fh
, NFS_FHSIZE
));
104 xdr_fastfhandle(XDR
*xdrs
, fhandle_t
**fh
)
108 if (xdrs
->x_op
!= XDR_DECODE
)
111 ptr
= XDR_INLINE(xdrs
, RNDUP(sizeof (fhandle_t
)));
113 *fh
= (fhandle_t
*)ptr
;
121 * Arguments to remote write and writecache
124 xdr_writeargs(XDR
*xdrs
, struct nfswriteargs
*wa
)
129 switch (xdrs
->x_op
) {
131 wa
->wa_args
= &wa
->wa_args_buf
;
132 ptr
= XDR_INLINE(xdrs
, RNDUP(sizeof (fhandle_t
)) +
133 3 * BYTES_PER_XDR_UNIT
);
135 fhp
= (int32_t *)&wa
->wa_fhandle
;
144 wa
->wa_begoff
= IXDR_GET_U_INT32(ptr
);
145 wa
->wa_offset
= IXDR_GET_U_INT32(ptr
);
146 wa
->wa_totcount
= IXDR_GET_U_INT32(ptr
);
151 if (xdrs
->x_ops
== &xdrmblk_ops
) {
152 return (xdrmblk_getmblk(xdrs
, &wa
->wa_mblk
,
155 if (xdrs
->x_ops
== &xdrrdmablk_ops
) {
156 if (xdrrdma_getrdmablk(xdrs
,
160 NFS_MAXDATA
) == TRUE
)
161 return (xdrrdma_read_from_client(
172 * It is just as efficient to xdr_bytes
173 * an array of unknown length as to inline copy it.
175 return (xdr_bytes(xdrs
, &wa
->wa_data
,
176 &wa
->wa_count
, NFS_MAXDATA
));
178 if (xdr_fhandle(xdrs
, &wa
->wa_fhandle
) &&
179 xdr_u_int(xdrs
, &wa
->wa_begoff
) &&
180 xdr_u_int(xdrs
, &wa
->wa_offset
) &&
181 xdr_u_int(xdrs
, &wa
->wa_totcount
)) {
182 /* deal with the variety of data transfer types */
189 if (xdrs
->x_ops
== &xdrmblk_ops
) {
190 if (xdrmblk_getmblk(xdrs
, &wa
->wa_mblk
,
191 &wa
->wa_count
) == TRUE
)
194 if (xdrs
->x_ops
== &xdrrdmablk_ops
) {
195 if (xdrrdma_getrdmablk(xdrs
,
199 NFS_MAXDATA
) == TRUE
)
200 return (xdrrdma_read_from_client(
209 return (xdr_bytes(xdrs
, &wa
->wa_data
,
210 &wa
->wa_count
, NFS_MAXDATA
));
214 ptr
= XDR_INLINE(xdrs
, RNDUP(sizeof (fhandle_t
)) +
215 3 * BYTES_PER_XDR_UNIT
);
217 fhp
= (int32_t *)&wa
->wa_fhandle
;
226 IXDR_PUT_U_INT32(ptr
, wa
->wa_begoff
);
227 IXDR_PUT_U_INT32(ptr
, wa
->wa_offset
);
228 IXDR_PUT_U_INT32(ptr
, wa
->wa_totcount
);
230 if (!(xdr_fhandle(xdrs
, &wa
->wa_fhandle
) &&
231 xdr_u_int(xdrs
, &wa
->wa_begoff
) &&
232 xdr_u_int(xdrs
, &wa
->wa_offset
) &&
233 xdr_u_int(xdrs
, &wa
->wa_totcount
)))
237 return (xdr_bytes(xdrs
, &wa
->wa_data
, &wa
->wa_count
,
241 (void) xdrrdma_free_clist(wa
->wa_conn
, wa
->wa_rlist
);
245 if (wa
->wa_data
!= NULL
) {
246 kmem_free(wa
->wa_data
, wa
->wa_count
);
259 xdr_fattr(XDR
*xdrs
, struct nfsfattr
*na
)
263 if (xdrs
->x_op
== XDR_FREE
)
266 ptr
= XDR_INLINE(xdrs
, 17 * BYTES_PER_XDR_UNIT
);
268 if (xdrs
->x_op
== XDR_DECODE
) {
269 na
->na_type
= IXDR_GET_ENUM(ptr
, enum nfsftype
);
270 na
->na_mode
= IXDR_GET_U_INT32(ptr
);
271 na
->na_nlink
= IXDR_GET_U_INT32(ptr
);
272 na
->na_uid
= IXDR_GET_U_INT32(ptr
);
273 na
->na_gid
= IXDR_GET_U_INT32(ptr
);
274 na
->na_size
= IXDR_GET_U_INT32(ptr
);
275 na
->na_blocksize
= IXDR_GET_U_INT32(ptr
);
276 na
->na_rdev
= IXDR_GET_U_INT32(ptr
);
277 na
->na_blocks
= IXDR_GET_U_INT32(ptr
);
278 na
->na_fsid
= IXDR_GET_U_INT32(ptr
);
279 na
->na_nodeid
= IXDR_GET_U_INT32(ptr
);
280 na
->na_atime
.tv_sec
= IXDR_GET_U_INT32(ptr
);
281 na
->na_atime
.tv_usec
= IXDR_GET_U_INT32(ptr
);
282 na
->na_mtime
.tv_sec
= IXDR_GET_U_INT32(ptr
);
283 na
->na_mtime
.tv_usec
= IXDR_GET_U_INT32(ptr
);
284 na
->na_ctime
.tv_sec
= IXDR_GET_U_INT32(ptr
);
285 na
->na_ctime
.tv_usec
= IXDR_GET_U_INT32(ptr
);
287 IXDR_PUT_ENUM(ptr
, na
->na_type
);
288 IXDR_PUT_U_INT32(ptr
, na
->na_mode
);
289 IXDR_PUT_U_INT32(ptr
, na
->na_nlink
);
290 IXDR_PUT_U_INT32(ptr
, na
->na_uid
);
291 IXDR_PUT_U_INT32(ptr
, na
->na_gid
);
292 IXDR_PUT_U_INT32(ptr
, na
->na_size
);
293 IXDR_PUT_U_INT32(ptr
, na
->na_blocksize
);
294 IXDR_PUT_U_INT32(ptr
, na
->na_rdev
);
295 IXDR_PUT_U_INT32(ptr
, na
->na_blocks
);
296 IXDR_PUT_U_INT32(ptr
, na
->na_fsid
);
297 IXDR_PUT_U_INT32(ptr
, na
->na_nodeid
);
298 IXDR_PUT_U_INT32(ptr
, na
->na_atime
.tv_sec
);
299 IXDR_PUT_U_INT32(ptr
, na
->na_atime
.tv_usec
);
300 IXDR_PUT_U_INT32(ptr
, na
->na_mtime
.tv_sec
);
301 IXDR_PUT_U_INT32(ptr
, na
->na_mtime
.tv_usec
);
302 IXDR_PUT_U_INT32(ptr
, na
->na_ctime
.tv_sec
);
303 IXDR_PUT_U_INT32(ptr
, na
->na_ctime
.tv_usec
);
308 if (xdr_enum(xdrs
, (enum_t
*)&na
->na_type
) &&
309 xdr_u_int(xdrs
, &na
->na_mode
) &&
310 xdr_u_int(xdrs
, &na
->na_nlink
) &&
311 xdr_u_int(xdrs
, &na
->na_uid
) &&
312 xdr_u_int(xdrs
, &na
->na_gid
) &&
313 xdr_u_int(xdrs
, &na
->na_size
) &&
314 xdr_u_int(xdrs
, &na
->na_blocksize
) &&
315 xdr_u_int(xdrs
, &na
->na_rdev
) &&
316 xdr_u_int(xdrs
, &na
->na_blocks
) &&
317 xdr_u_int(xdrs
, &na
->na_fsid
) &&
318 xdr_u_int(xdrs
, &na
->na_nodeid
) &&
319 xdr_nfs2_timeval(xdrs
, &na
->na_atime
) &&
320 xdr_nfs2_timeval(xdrs
, &na
->na_mtime
) &&
321 xdr_nfs2_timeval(xdrs
, &na
->na_ctime
)) {
327 #ifdef _LITTLE_ENDIAN
329 xdr_fastfattr(XDR
*xdrs
, struct nfsfattr
*na
)
331 if (xdrs
->x_op
== XDR_FREE
)
333 if (xdrs
->x_op
== XDR_DECODE
)
336 na
->na_type
= htonl(na
->na_type
);
337 na
->na_mode
= htonl(na
->na_mode
);
338 na
->na_nlink
= htonl(na
->na_nlink
);
339 na
->na_uid
= htonl(na
->na_uid
);
340 na
->na_gid
= htonl(na
->na_gid
);
341 na
->na_size
= htonl(na
->na_size
);
342 na
->na_blocksize
= htonl(na
->na_blocksize
);
343 na
->na_rdev
= htonl(na
->na_rdev
);
344 na
->na_blocks
= htonl(na
->na_blocks
);
345 na
->na_fsid
= htonl(na
->na_fsid
);
346 na
->na_nodeid
= htonl(na
->na_nodeid
);
347 na
->na_atime
.tv_sec
= htonl(na
->na_atime
.tv_sec
);
348 na
->na_atime
.tv_usec
= htonl(na
->na_atime
.tv_usec
);
349 na
->na_mtime
.tv_sec
= htonl(na
->na_mtime
.tv_sec
);
350 na
->na_mtime
.tv_usec
= htonl(na
->na_mtime
.tv_usec
);
351 na
->na_ctime
.tv_sec
= htonl(na
->na_ctime
.tv_sec
);
352 na
->na_ctime
.tv_usec
= htonl(na
->na_ctime
.tv_usec
);
358 xdr_readlink(XDR
*xdrs
, fhandle_t
*fh
)
360 rdma_chunkinfo_t rci
;
361 struct xdr_ops
*xops
= xdrrdma_xops();
363 if (xdr_fhandle(xdrs
, fh
)) {
364 if ((xdrs
->x_ops
== &xdrrdma_ops
|| xdrs
->x_ops
== xops
) &&
365 xdrs
->x_op
== XDR_ENCODE
) {
366 rci
.rci_type
= RCI_REPLY_CHUNK
;
367 rci
.rci_len
= MAXPATHLEN
;
368 XDR_CONTROL(xdrs
, XDR_RDMA_ADD_CHUNK
, &rci
);
377 * Arguments to remote read
380 xdr_readargs(XDR
*xdrs
, struct nfsreadargs
*ra
)
384 rdma_chunkinfo_t rci
;
385 rdma_wlist_conn_info_t rwci
;
386 struct xdr_ops
*xops
= xdrrdma_xops();
388 if (xdrs
->x_op
== XDR_FREE
)
391 ptr
= XDR_INLINE(xdrs
,
392 RNDUP(sizeof (fhandle_t
)) + 3 * BYTES_PER_XDR_UNIT
);
394 if (xdrs
->x_op
== XDR_DECODE
) {
395 fhp
= (int32_t *)&ra
->ra_fhandle
;
404 ra
->ra_offset
= IXDR_GET_INT32(ptr
);
405 ra
->ra_count
= IXDR_GET_INT32(ptr
);
406 ra
->ra_totcount
= IXDR_GET_INT32(ptr
);
408 fhp
= (int32_t *)&ra
->ra_fhandle
;
417 IXDR_PUT_INT32(ptr
, ra
->ra_offset
);
418 IXDR_PUT_INT32(ptr
, ra
->ra_count
);
419 IXDR_PUT_INT32(ptr
, ra
->ra_totcount
);
422 if (!xdr_fhandle(xdrs
, &ra
->ra_fhandle
) ||
423 !xdr_u_int(xdrs
, &ra
->ra_offset
) ||
424 !xdr_u_int(xdrs
, &ra
->ra_count
) ||
425 !xdr_u_int(xdrs
, &ra
->ra_totcount
)) {
430 if (ra
->ra_count
> NFS_MAXDATA
)
436 /* If this is xdrrdma_sizeof, record the expect response size */
437 if (xdrs
->x_ops
== xops
&& xdrs
->x_op
== XDR_ENCODE
) {
438 rci
.rci_type
= RCI_WRITE_ADDR_CHUNK
;
439 rci
.rci_len
= ra
->ra_count
;
440 (void) XDR_CONTROL(xdrs
, XDR_RDMA_ADD_CHUNK
, &rci
);
442 /* Nothing special to do, return */
443 if (xdrs
->x_ops
!= &xdrrdma_ops
|| xdrs
->x_op
== XDR_FREE
)
446 if (xdrs
->x_op
== XDR_ENCODE
) {
447 /* Place the target data location into the RDMA header */
448 rci
.rci_type
= RCI_WRITE_ADDR_CHUNK
;
449 rci
.rci_a
.rci_addr
= ra
->ra_data
;
450 rci
.rci_len
= ra
->ra_count
;
451 rci
.rci_clpp
= &ra
->ra_wlist
;
453 return (XDR_CONTROL(xdrs
, XDR_RDMA_ADD_CHUNK
, &rci
));
456 /* XDR_DECODE case */
457 (void) XDR_CONTROL(xdrs
, XDR_RDMA_GET_WCINFO
, &rwci
);
458 ra
->ra_wlist
= rwci
.rwci_wlist
;
459 ra
->ra_conn
= rwci
.rwci_conn
;
466 * Status OK portion of remote read reply
469 xdr_rrok(XDR
*xdrs
, struct nfsrrok
*rrok
)
473 struct xdr_ops
*xops
= xdrrdma_xops();
475 if (xdr_fattr(xdrs
, &rrok
->rrok_attr
) == FALSE
)
478 /* deal with RDMA separately */
479 if (xdrs
->x_ops
== &xdrrdma_ops
|| xdrs
->x_ops
== xops
) {
480 if (xdrs
->x_op
== XDR_ENCODE
&&
481 rrok
->rrok_mp
!= NULL
) {
482 ret
= xdr_bytes(xdrs
, (char **)&rrok
->rrok_data
,
483 &rrok
->rrok_count
, NFS_MAXDATA
);
487 if (xdrs
->x_op
== XDR_ENCODE
) {
488 if (xdr_u_int(xdrs
, &rrok
->rrok_count
) == FALSE
) {
492 * If read data sent by wlist (RDMA_WRITE), don't do
493 * xdr_bytes() below. RDMA_WRITE transfers the data.
495 if (rrok
->rrok_wlist
) {
496 if (rrok
->rrok_count
!= 0) {
497 return (xdrrdma_send_read_data(
498 xdrs
, rrok
->rrok_count
,
503 if (rrok
->rrok_count
== 0) {
510 XDR_CONTROL(xdrs
, XDR_RDMA_GET_WLIST
, &cl
);
513 if (!xdr_u_int(xdrs
, &count
))
516 rrok
->rrok_wlist_len
= 0;
517 rrok
->rrok_count
= 0;
519 rrok
->rrok_wlist_len
= clist_len(cl
);
520 if (rrok
->rrok_wlist_len
!=
522 BYTES_PER_XDR_UNIT
)) {
523 rrok
->rrok_wlist_len
= 0;
524 rrok
->rrok_count
= 0;
527 rrok
->rrok_count
= count
;
532 ret
= xdr_bytes(xdrs
, (char **)&rrok
->rrok_data
,
533 &rrok
->rrok_count
, NFS_MAXDATA
);
538 if (xdrs
->x_op
== XDR_ENCODE
) {
542 if (mp
!= NULL
&& xdrs
->x_ops
== &xdrmblk_ops
) {
543 mp
->b_wptr
+= rrok
->rrok_count
;
544 rndup
= BYTES_PER_XDR_UNIT
-
545 (rrok
->rrok_count
% BYTES_PER_XDR_UNIT
);
546 if (rndup
!= BYTES_PER_XDR_UNIT
)
547 for (i
= 0; i
< rndup
; i
++)
548 *mp
->b_wptr
++ = '\0';
549 if (xdrmblk_putmblk(xdrs
, mp
,
550 rrok
->rrok_count
) == TRUE
) {
551 rrok
->rrok_mp
= NULL
;
557 * Fall thru for the xdr_bytes()
559 * Note: the mblk mp will be freed in rfs_rdfree
563 ret
= xdr_bytes(xdrs
, (char **)&rrok
->rrok_data
,
564 &rrok
->rrok_count
, NFS_MAXDATA
);
569 static struct xdr_discrim rdres_discrim
[2] = {
570 { NFS_OK
, xdr_rrok
},
571 { __dontcare__
, NULL_xdrproc_t
}
575 * Reply from remote read
578 xdr_rdresult(XDR
*xdrs
, struct nfsrdresult
*rr
)
580 return (xdr_union(xdrs
, (enum_t
*)&(rr
->rr_status
),
581 (caddr_t
)&(rr
->rr_ok
), rdres_discrim
, xdr_void
));
585 * File attributes which can be set
588 xdr_sattr(XDR
*xdrs
, struct nfssattr
*sa
)
590 if (xdr_u_int(xdrs
, &sa
->sa_mode
) &&
591 xdr_u_int(xdrs
, &sa
->sa_uid
) &&
592 xdr_u_int(xdrs
, &sa
->sa_gid
) &&
593 xdr_u_int(xdrs
, &sa
->sa_size
) &&
594 xdr_nfs2_timeval(xdrs
, &sa
->sa_atime
) &&
595 xdr_nfs2_timeval(xdrs
, &sa
->sa_mtime
)) {
601 static struct xdr_discrim attrstat_discrim
[2] = {
602 { (int)NFS_OK
, xdr_fattr
},
603 { __dontcare__
, NULL_xdrproc_t
}
607 * Reply status with file attributes
610 xdr_attrstat(XDR
*xdrs
, struct nfsattrstat
*ns
)
612 return (xdr_union(xdrs
, (enum_t
*)&(ns
->ns_status
),
613 (caddr_t
)&(ns
->ns_attr
), attrstat_discrim
, xdr_void
));
617 * Fast reply status with file attributes
620 xdr_fastattrstat(XDR
*xdrs
, struct nfsattrstat
*ns
)
622 #if defined(_LITTLE_ENDIAN)
624 * we deal with the discriminator; it's an enum
626 if (!xdr_fastenum(xdrs
, (enum_t
*)&ns
->ns_status
))
629 if (ns
->ns_status
== NFS_OK
)
630 return (xdr_fastfattr(xdrs
, &ns
->ns_attr
));
631 #elif defined(_BIG_ENDIAN)
632 if (ns
->ns_status
== NFS_OK
)
635 return (xdr_fastshorten(xdrs
, sizeof (*ns
)));
639 * NFS_OK part of read sym link reply union
642 xdr_srok(XDR
*xdrs
, struct nfssrok
*srok
)
645 * It is just as efficient to xdr_bytes
646 * an array of unknown length as to inline copy it.
648 return (xdr_bytes(xdrs
, &srok
->srok_data
, &srok
->srok_count
,
652 static struct xdr_discrim rdlnres_discrim
[2] = {
653 { (int)NFS_OK
, xdr_srok
},
654 { __dontcare__
, NULL_xdrproc_t
}
658 * Result of reading symbolic link
661 xdr_rdlnres(XDR
*xdrs
, struct nfsrdlnres
*rl
)
663 return (xdr_union(xdrs
, (enum_t
*)&(rl
->rl_status
),
664 (caddr_t
)&(rl
->rl_srok
), rdlnres_discrim
, xdr_void
));
668 * Arguments to readdir
671 xdr_rddirargs(XDR
*xdrs
, struct nfsrddirargs
*rda
)
675 rdma_chunkinfo_t rci
;
676 struct xdr_ops
*xops
= xdrrdma_xops();
678 if (xdrs
->x_op
== XDR_FREE
)
681 ptr
= XDR_INLINE(xdrs
,
682 RNDUP(sizeof (fhandle_t
)) + 2 * BYTES_PER_XDR_UNIT
);
684 if ((xdrs
->x_ops
== &xdrrdma_ops
|| xdrs
->x_ops
== xops
) &&
685 xdrs
->x_op
== XDR_ENCODE
) {
686 rci
.rci_type
= RCI_REPLY_CHUNK
;
687 rci
.rci_len
= rda
->rda_count
;
688 XDR_CONTROL(xdrs
, XDR_RDMA_ADD_CHUNK
, &rci
);
692 if (xdrs
->x_op
== XDR_DECODE
) {
693 fhp
= (int32_t *)&rda
->rda_fh
;
702 rda
->rda_offset
= IXDR_GET_U_INT32(ptr
);
703 rda
->rda_count
= IXDR_GET_U_INT32(ptr
);
705 fhp
= (int32_t *)&rda
->rda_fh
;
714 IXDR_PUT_U_INT32(ptr
, rda
->rda_offset
);
715 IXDR_PUT_U_INT32(ptr
, rda
->rda_count
);
720 if (xdr_fhandle(xdrs
, &rda
->rda_fh
) &&
721 xdr_u_int(xdrs
, &rda
->rda_offset
) &&
722 xdr_u_int(xdrs
, &rda
->rda_count
)) {
730 * Directory read reply:
731 * union (enum status) {
739 * off_t d_off; * offset of next entry *
740 * u_int d_fileno; * inode number of entry *
741 * u_short d_reclen; * length of this record *
742 * u_short d_namlen; * length of string in d_name *
743 * char d_name[MAXNAMLEN + 1]; * name no longer than this *
745 * are on the wire as:
746 * union entlist (boolean valid) {
747 * TRUE: struct otw_dirent;
752 * where otw_dirent is:
755 * string de_name<NFS_MAXNAMELEN>;
762 #define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
766 #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
772 xdr_putrddirres(XDR
*xdrs
, struct nfsrddirres
*rd
)
785 if (xdrs
->x_op
!= XDR_ENCODE
)
787 if (!xdr_enum(xdrs
, (enum_t
*)&rd
->rd_status
))
789 if (rd
->rd_status
!= NFS_OK
)
792 bufsize
= 1 * BYTES_PER_XDR_UNIT
;
793 for (size
= rd
->rd_size
, dp
= rd
->rd_entries
;
795 size
-= dp
->d_reclen
, dp
= nextdp(dp
)) {
796 if (dp
->d_reclen
== 0 /* || DIRSIZ(dp) > dp->d_reclen */)
800 ino
= (uint32_t)dp
->d_ino
; /* for LP64 we clip the bits */
801 if (dp
->d_ino
!= (ino64_t
)ino
) /* and they better be zeros */
803 off
= (uint32_t)dp
->d_off
;
805 namlen
= (uint_t
)strlen(name
);
806 entrysz
= (1 + 1 + 1 + 1) * BYTES_PER_XDR_UNIT
+
807 roundup(namlen
, BYTES_PER_XDR_UNIT
);
808 tofit
= entrysz
+ 2 * BYTES_PER_XDR_UNIT
;
809 if (bufsize
+ tofit
> rd
->rd_bufsize
) {
813 if (!xdr_bool(xdrs
, &t
) ||
814 !xdr_u_int(xdrs
, &ino
) ||
815 !xdr_bytes(xdrs
, &name
, &namlen
, NFS_MAXNAMLEN
) ||
816 !xdr_u_int(xdrs
, &off
)) {
821 if (!xdr_bool(xdrs
, &f
))
823 if (!xdr_bool(xdrs
, &rd
->rd_eof
))
832 xdr_getrddirres(XDR
*xdrs
, struct nfsrddirres
*rd
)
839 uint_t fileid
, this_reclen
;
841 if (xdrs
->x_op
!= XDR_DECODE
)
844 if (!xdr_enum(xdrs
, (enum_t
*)&rd
->rd_status
))
846 if (rd
->rd_status
!= NFS_OK
)
851 offset
= rd
->rd_offset
;
853 if (!xdr_bool(xdrs
, &valid
))
857 if (!xdr_u_int(xdrs
, &fileid
) ||
858 !xdr_u_int(xdrs
, &namlen
))
860 this_reclen
= DIRENT64_RECLEN(namlen
);
861 if (this_reclen
> size
) {
865 if (!xdr_opaque(xdrs
, dp
->d_name
, namlen
)||
866 !xdr_u_int(xdrs
, &offset
)) {
869 bzero(&dp
->d_name
[namlen
],
870 DIRENT64_NAMELEN(this_reclen
) - namlen
);
871 dp
->d_ino
= (ino64_t
)fileid
;
872 dp
->d_reclen
= this_reclen
;
873 dp
->d_off
= (off64_t
)offset
;
874 size
-= dp
->d_reclen
;
877 if (!xdr_bool(xdrs
, &rd
->rd_eof
))
880 rd
->rd_size
= (uint32_t)((char *)dp
- (char *)(rd
->rd_entries
));
881 rd
->rd_offset
= offset
;
886 * Arguments for directory operations
889 xdr_diropargs(XDR
*xdrs
, struct nfsdiropargs
*da
)
899 if (xdrs
->x_op
== XDR_DECODE
) {
900 da
->da_fhandle
= &da
->da_fhandle_buf
;
901 ptr
= XDR_INLINE(xdrs
, RNDUP(sizeof (fhandle_t
)) +
902 1 * BYTES_PER_XDR_UNIT
);
904 fhp
= (int32_t *)da
->da_fhandle
;
913 size
= IXDR_GET_U_INT32(ptr
);
914 if (size
> NFS_MAXNAMLEN
)
919 if (da
->da_name
== NULL
) {
920 da
->da_name
= kmem_alloc(nodesize
, KM_NOSLEEP
);
921 if (da
->da_name
== NULL
)
923 da
->da_flags
|= DA_FREENAME
;
925 ptr
= XDR_INLINE(xdrs
, RNDUP(size
));
927 if (!xdr_opaque(xdrs
, da
->da_name
, size
)) {
928 if (da
->da_flags
& DA_FREENAME
) {
929 kmem_free(da
->da_name
,
935 da
->da_name
[size
] = '\0';
936 if (strlen(da
->da_name
) != size
) {
937 if (da
->da_flags
& DA_FREENAME
) {
938 kmem_free(da
->da_name
,
946 bcopy(ptr
, da
->da_name
, size
);
947 da
->da_name
[size
] = '\0';
948 if (strlen(da
->da_name
) != size
) {
949 if (da
->da_flags
& DA_FREENAME
) {
950 kmem_free(da
->da_name
, nodesize
);
957 if (da
->da_name
== NULL
)
958 da
->da_flags
|= DA_FREENAME
;
961 if (xdrs
->x_op
== XDR_ENCODE
) {
962 size
= (uint32_t)strlen(da
->da_name
);
963 if (size
> NFS_MAXNAMLEN
)
965 ptr
= XDR_INLINE(xdrs
, (int)(RNDUP(sizeof (fhandle_t
)) +
966 1 * BYTES_PER_XDR_UNIT
+ RNDUP(size
)));
968 fhp
= (int32_t *)da
->da_fhandle
;
977 IXDR_PUT_U_INT32(ptr
, (uint32_t)size
);
978 bcopy(da
->da_name
, ptr
, size
);
979 rndup
= BYTES_PER_XDR_UNIT
-
980 (size
% BYTES_PER_XDR_UNIT
);
981 if (rndup
!= BYTES_PER_XDR_UNIT
) {
982 cptr
= (char *)ptr
+ size
;
983 for (i
= 0; i
< rndup
; i
++)
990 if (xdrs
->x_op
== XDR_FREE
) {
991 if (da
->da_name
== NULL
)
993 size
= (uint32_t)strlen(da
->da_name
);
994 if (size
> NFS_MAXNAMLEN
)
996 if (da
->da_flags
& DA_FREENAME
)
997 kmem_free(da
->da_name
, size
+ 1);
1002 if (xdr_fhandle(xdrs
, da
->da_fhandle
) &&
1003 xdr_string(xdrs
, &da
->da_name
, NFS_MAXNAMLEN
)) {
1010 * NFS_OK part of directory operation result
1013 xdr_drok(XDR
*xdrs
, struct nfsdrok
*drok
)
1017 struct nfsfattr
*na
;
1019 if (xdrs
->x_op
== XDR_FREE
)
1022 ptr
= XDR_INLINE(xdrs
,
1023 RNDUP(sizeof (fhandle_t
)) + 17 * BYTES_PER_XDR_UNIT
);
1025 if (xdrs
->x_op
== XDR_DECODE
) {
1026 fhp
= (int32_t *)&drok
->drok_fhandle
;
1035 na
= &drok
->drok_attr
;
1036 na
->na_type
= IXDR_GET_ENUM(ptr
, enum nfsftype
);
1037 na
->na_mode
= IXDR_GET_U_INT32(ptr
);
1038 na
->na_nlink
= IXDR_GET_U_INT32(ptr
);
1039 na
->na_uid
= IXDR_GET_U_INT32(ptr
);
1040 na
->na_gid
= IXDR_GET_U_INT32(ptr
);
1041 na
->na_size
= IXDR_GET_U_INT32(ptr
);
1042 na
->na_blocksize
= IXDR_GET_U_INT32(ptr
);
1043 na
->na_rdev
= IXDR_GET_U_INT32(ptr
);
1044 na
->na_blocks
= IXDR_GET_U_INT32(ptr
);
1045 na
->na_fsid
= IXDR_GET_U_INT32(ptr
);
1046 na
->na_nodeid
= IXDR_GET_U_INT32(ptr
);
1047 na
->na_atime
.tv_sec
= IXDR_GET_U_INT32(ptr
);
1048 na
->na_atime
.tv_usec
= IXDR_GET_U_INT32(ptr
);
1049 na
->na_mtime
.tv_sec
= IXDR_GET_U_INT32(ptr
);
1050 na
->na_mtime
.tv_usec
= IXDR_GET_U_INT32(ptr
);
1051 na
->na_ctime
.tv_sec
= IXDR_GET_U_INT32(ptr
);
1052 na
->na_ctime
.tv_usec
= IXDR_GET_U_INT32(ptr
);
1054 fhp
= (int32_t *)&drok
->drok_fhandle
;
1063 na
= &drok
->drok_attr
;
1064 IXDR_PUT_ENUM(ptr
, na
->na_type
);
1065 IXDR_PUT_U_INT32(ptr
, na
->na_mode
);
1066 IXDR_PUT_U_INT32(ptr
, na
->na_nlink
);
1067 IXDR_PUT_U_INT32(ptr
, na
->na_uid
);
1068 IXDR_PUT_U_INT32(ptr
, na
->na_gid
);
1069 IXDR_PUT_U_INT32(ptr
, na
->na_size
);
1070 IXDR_PUT_U_INT32(ptr
, na
->na_blocksize
);
1071 IXDR_PUT_U_INT32(ptr
, na
->na_rdev
);
1072 IXDR_PUT_U_INT32(ptr
, na
->na_blocks
);
1073 IXDR_PUT_U_INT32(ptr
, na
->na_fsid
);
1074 IXDR_PUT_U_INT32(ptr
, na
->na_nodeid
);
1075 IXDR_PUT_U_INT32(ptr
, na
->na_atime
.tv_sec
);
1076 IXDR_PUT_U_INT32(ptr
, na
->na_atime
.tv_usec
);
1077 IXDR_PUT_U_INT32(ptr
, na
->na_mtime
.tv_sec
);
1078 IXDR_PUT_U_INT32(ptr
, na
->na_mtime
.tv_usec
);
1079 IXDR_PUT_U_INT32(ptr
, na
->na_ctime
.tv_sec
);
1080 IXDR_PUT_U_INT32(ptr
, na
->na_ctime
.tv_usec
);
1085 if (xdr_fhandle(xdrs
, &drok
->drok_fhandle
) &&
1086 xdr_fattr(xdrs
, &drok
->drok_attr
)) {
1092 #ifdef _LITTLE_ENDIAN
1094 xdr_fastdrok(XDR
*xdrs
, struct nfsdrok
*drok
)
1096 struct nfsfattr
*na
;
1098 if (xdrs
->x_op
== XDR_FREE
)
1100 if (xdrs
->x_op
== XDR_DECODE
)
1103 na
= &drok
->drok_attr
;
1104 na
->na_type
= (enum nfsftype
)htonl(na
->na_type
);
1105 na
->na_mode
= (uint32_t)htonl(na
->na_mode
);
1106 na
->na_nlink
= (uint32_t)htonl(na
->na_nlink
);
1107 na
->na_uid
= (uint32_t)htonl(na
->na_uid
);
1108 na
->na_gid
= (uint32_t)htonl(na
->na_gid
);
1109 na
->na_size
= (uint32_t)htonl(na
->na_size
);
1110 na
->na_blocksize
= (uint32_t)htonl(na
->na_blocksize
);
1111 na
->na_rdev
= (uint32_t)htonl(na
->na_rdev
);
1112 na
->na_blocks
= (uint32_t)htonl(na
->na_blocks
);
1113 na
->na_fsid
= (uint32_t)htonl(na
->na_fsid
);
1114 na
->na_nodeid
= (uint32_t)htonl(na
->na_nodeid
);
1115 na
->na_atime
.tv_sec
= htonl(na
->na_atime
.tv_sec
);
1116 na
->na_atime
.tv_usec
= htonl(na
->na_atime
.tv_usec
);
1117 na
->na_mtime
.tv_sec
= htonl(na
->na_mtime
.tv_sec
);
1118 na
->na_mtime
.tv_usec
= htonl(na
->na_mtime
.tv_usec
);
1119 na
->na_ctime
.tv_sec
= htonl(na
->na_ctime
.tv_sec
);
1120 na
->na_ctime
.tv_usec
= htonl(na
->na_ctime
.tv_usec
);
1125 static struct xdr_discrim diropres_discrim
[2] = {
1126 { NFS_OK
, xdr_drok
},
1127 { __dontcare__
, NULL_xdrproc_t
}
1131 * Results from directory operation
1134 xdr_diropres(XDR
*xdrs
, struct nfsdiropres
*dr
)
1136 return (xdr_union(xdrs
, (enum_t
*)&(dr
->dr_status
),
1137 (caddr_t
)&(dr
->dr_drok
), diropres_discrim
, xdr_void
));
1141 * Results from directory operation
1144 xdr_fastdiropres(XDR
*xdrs
, struct nfsdiropres
*dr
)
1146 #if defined(_LITTLE_ENDIAN)
1148 * we deal with the discriminator; it's an enum
1150 if (!xdr_fastenum(xdrs
, (enum_t
*)&dr
->dr_status
))
1153 if (dr
->dr_status
== NFS_OK
)
1154 return (xdr_fastdrok(xdrs
, &dr
->dr_drok
));
1155 #elif defined(_BIG_ENDIAN)
1156 if (dr
->dr_status
== NFS_OK
)
1159 return (xdr_fastshorten(xdrs
, sizeof (*dr
)));
1163 * Time Structure, unsigned
1166 xdr_nfs2_timeval(XDR
*xdrs
, struct nfs2_timeval
*tv
)
1168 if (xdr_u_int(xdrs
, &tv
->tv_sec
) &&
1169 xdr_u_int(xdrs
, &tv
->tv_usec
))
1175 * arguments to setattr
1178 xdr_saargs(XDR
*xdrs
, struct nfssaargs
*argp
)
1182 struct nfssattr
*sa
;
1184 if (xdrs
->x_op
== XDR_FREE
)
1187 ptr
= XDR_INLINE(xdrs
,
1188 RNDUP(sizeof (fhandle_t
)) + 8 * BYTES_PER_XDR_UNIT
);
1190 if (xdrs
->x_op
== XDR_DECODE
) {
1191 arg
= (int32_t *)&argp
->saa_fh
;
1201 sa
->sa_mode
= IXDR_GET_U_INT32(ptr
);
1202 sa
->sa_uid
= IXDR_GET_U_INT32(ptr
);
1203 sa
->sa_gid
= IXDR_GET_U_INT32(ptr
);
1204 sa
->sa_size
= IXDR_GET_U_INT32(ptr
);
1205 sa
->sa_atime
.tv_sec
= IXDR_GET_U_INT32(ptr
);
1206 sa
->sa_atime
.tv_usec
= IXDR_GET_U_INT32(ptr
);
1207 sa
->sa_mtime
.tv_sec
= IXDR_GET_U_INT32(ptr
);
1208 sa
->sa_mtime
.tv_usec
= IXDR_GET_U_INT32(ptr
);
1210 arg
= (int32_t *)&argp
->saa_fh
;
1220 IXDR_PUT_U_INT32(ptr
, sa
->sa_mode
);
1221 IXDR_PUT_U_INT32(ptr
, sa
->sa_uid
);
1222 IXDR_PUT_U_INT32(ptr
, sa
->sa_gid
);
1223 IXDR_PUT_U_INT32(ptr
, sa
->sa_size
);
1224 IXDR_PUT_U_INT32(ptr
, sa
->sa_atime
.tv_sec
);
1225 IXDR_PUT_U_INT32(ptr
, sa
->sa_atime
.tv_usec
);
1226 IXDR_PUT_U_INT32(ptr
, sa
->sa_mtime
.tv_sec
);
1227 IXDR_PUT_U_INT32(ptr
, sa
->sa_mtime
.tv_usec
);
1232 if (xdr_fhandle(xdrs
, &argp
->saa_fh
) &&
1233 xdr_sattr(xdrs
, &argp
->saa_sa
)) {
1241 * arguments to create and mkdir
1244 xdr_creatargs(XDR
*xdrs
, struct nfscreatargs
*argp
)
1246 argp
->ca_sa
= &argp
->ca_sa_buf
;
1248 if (xdrs
->x_op
== XDR_DECODE
)
1249 argp
->ca_sa
= &argp
->ca_sa_buf
;
1250 if (xdr_diropargs(xdrs
, &argp
->ca_da
) &&
1251 xdr_sattr(xdrs
, argp
->ca_sa
)) {
1261 xdr_linkargs(XDR
*xdrs
, struct nfslinkargs
*argp
)
1263 if (xdrs
->x_op
== XDR_DECODE
)
1264 argp
->la_from
= &argp
->la_from_buf
;
1265 if (xdr_fhandle(xdrs
, argp
->la_from
) &&
1266 xdr_diropargs(xdrs
, &argp
->la_to
)) {
1273 * arguments to rename
1276 xdr_rnmargs(XDR
*xdrs
, struct nfsrnmargs
*argp
)
1278 if (xdr_diropargs(xdrs
, &argp
->rna_from
) &&
1279 xdr_diropargs(xdrs
, &argp
->rna_to
))
1286 * arguments to symlink
1289 xdr_slargs(XDR
*xdrs
, struct nfsslargs
*argp
)
1291 if (xdrs
->x_op
== XDR_FREE
) {
1292 if (!xdr_diropargs(xdrs
, &argp
->sla_from
))
1294 if ((argp
->sla_tnm_flags
& SLA_FREETNM
) &&
1295 !xdr_string(xdrs
, &argp
->sla_tnm
, (uint_t
)NFS_MAXPATHLEN
))
1300 if (xdrs
->x_op
== XDR_DECODE
) {
1301 argp
->sla_sa
= &argp
->sla_sa_buf
;
1302 if (argp
->sla_tnm
== NULL
)
1303 argp
->sla_tnm_flags
|= SLA_FREETNM
;
1306 if (xdr_diropargs(xdrs
, &argp
->sla_from
) &&
1307 xdr_string(xdrs
, &argp
->sla_tnm
, (uint_t
)NFS_MAXPATHLEN
) &&
1308 xdr_sattr(xdrs
, argp
->sla_sa
)) {
1316 * NFS_OK part of statfs operation
1319 xdr_fsok(XDR
*xdrs
, struct nfsstatfsok
*fsok
)
1323 if (xdrs
->x_op
== XDR_FREE
)
1326 ptr
= XDR_INLINE(xdrs
, 5 * BYTES_PER_XDR_UNIT
);
1328 if (xdrs
->x_op
== XDR_DECODE
) {
1329 fsok
->fsok_tsize
= IXDR_GET_INT32(ptr
);
1330 fsok
->fsok_bsize
= IXDR_GET_INT32(ptr
);
1331 fsok
->fsok_blocks
= IXDR_GET_INT32(ptr
);
1332 fsok
->fsok_bfree
= IXDR_GET_INT32(ptr
);
1333 fsok
->fsok_bavail
= IXDR_GET_INT32(ptr
);
1335 IXDR_PUT_INT32(ptr
, fsok
->fsok_tsize
);
1336 IXDR_PUT_INT32(ptr
, fsok
->fsok_bsize
);
1337 IXDR_PUT_INT32(ptr
, fsok
->fsok_blocks
);
1338 IXDR_PUT_INT32(ptr
, fsok
->fsok_bfree
);
1339 IXDR_PUT_INT32(ptr
, fsok
->fsok_bavail
);
1344 if (xdr_u_int(xdrs
, &fsok
->fsok_tsize
) &&
1345 xdr_u_int(xdrs
, &fsok
->fsok_bsize
) &&
1346 xdr_u_int(xdrs
, &fsok
->fsok_blocks
) &&
1347 xdr_u_int(xdrs
, &fsok
->fsok_bfree
) &&
1348 xdr_u_int(xdrs
, &fsok
->fsok_bavail
)) {
1354 #ifdef _LITTLE_ENDIAN
1356 xdr_fastfsok(XDR
*xdrs
, struct nfsstatfsok
*fsok
)
1359 if (xdrs
->x_op
== XDR_FREE
)
1361 if (xdrs
->x_op
== XDR_DECODE
)
1364 fsok
->fsok_tsize
= htonl(fsok
->fsok_tsize
);
1365 fsok
->fsok_bsize
= htonl(fsok
->fsok_bsize
);
1366 fsok
->fsok_blocks
= htonl(fsok
->fsok_blocks
);
1367 fsok
->fsok_bfree
= htonl(fsok
->fsok_bfree
);
1368 fsok
->fsok_bavail
= htonl(fsok
->fsok_bavail
);
1373 static struct xdr_discrim statfs_discrim
[2] = {
1374 { NFS_OK
, xdr_fsok
},
1375 { __dontcare__
, NULL_xdrproc_t
}
1379 * Results of statfs operation
1382 xdr_statfs(XDR
*xdrs
, struct nfsstatfs
*fs
)
1384 return (xdr_union(xdrs
, (enum_t
*)&(fs
->fs_status
),
1385 (caddr_t
)&(fs
->fs_fsok
), statfs_discrim
, xdr_void
));
1389 * Results of statfs operation
1392 xdr_faststatfs(XDR
*xdrs
, struct nfsstatfs
*fs
)
1394 #if defined(_LITTLE_ENDIAN)
1396 * we deal with the discriminator; it's an enum
1398 if (!xdr_fastenum(xdrs
, (enum_t
*)&fs
->fs_status
))
1401 if (fs
->fs_status
== NFS_OK
)
1402 return (xdr_fastfsok(xdrs
, &fs
->fs_fsok
));
1403 #elif defined(_BIG_ENDIAN)
1404 if (fs
->fs_status
== NFS_OK
)
1407 return (xdr_fastshorten(xdrs
, sizeof (*fs
)));
1410 #ifdef _LITTLE_ENDIAN
1414 static enum sizecheck
{ SIZEVAL
} sizecheckvar
; /* used to find the size of */
1417 xdr_fastenum(XDR
*xdrs
, enum_t
*ep
)
1419 if (xdrs
->x_op
== XDR_FREE
)
1421 if (xdrs
->x_op
== XDR_DECODE
)
1425 * enums are treated as ints
1427 if (sizeof (sizecheckvar
) == sizeof (int32_t)) {
1428 *ep
= (enum_t
)htonl((int32_t)(*ep
));
1429 } else if (sizeof (sizecheckvar
) == sizeof (short)) {
1430 *ep
= (enum_t
)htons((short)(*ep
));
1439 xdr_fastshorten(XDR
*xdrs
, uint_t ressize
)
1443 curpos
= XDR_GETPOS(xdrs
);
1444 ressize
-= BYTES_PER_XDR_UNIT
;
1446 return (XDR_SETPOS(xdrs
, curpos
));