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 2005 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 "%Z%%M% %I% %E% 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 45 #include <rpc/types.h> 46 #include <rpc/xdr.h> 47 48 #include <nfs/nfs.h> 49 50 #include <vm/hat.h> 51 #include <vm/as.h> 52 #include <vm/seg.h> 53 #include <vm/seg_map.h> 54 #include <vm/seg_kmem.h> 55 56 static bool_t xdr_fastshorten(XDR *, uint_t); 57 58 /* 59 * These are the XDR routines used to serialize and deserialize 60 * the various structures passed as parameters accross the network 61 * between NFS clients and servers. 62 */ 63 64 /* 65 * File access handle 66 * The fhandle struct is treated a opaque data on the wire 67 */ 68 bool_t 69 xdr_fhandle(XDR *xdrs, fhandle_t *fh) 70 { 71 int32_t *ptr; 72 int32_t *fhp; 73 74 if (xdrs->x_op == XDR_FREE) 75 return (TRUE); 76 77 ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t))); 78 if (ptr != NULL) { 79 fhp = (int32_t *)fh; 80 if (xdrs->x_op == XDR_DECODE) { 81 *fhp++ = *ptr++; 82 *fhp++ = *ptr++; 83 *fhp++ = *ptr++; 84 *fhp++ = *ptr++; 85 *fhp++ = *ptr++; 86 *fhp++ = *ptr++; 87 *fhp++ = *ptr++; 88 *fhp = *ptr; 89 } else { 90 *ptr++ = *fhp++; 91 *ptr++ = *fhp++; 92 *ptr++ = *fhp++; 93 *ptr++ = *fhp++; 94 *ptr++ = *fhp++; 95 *ptr++ = *fhp++; 96 *ptr++ = *fhp++; 97 *ptr = *fhp; 98 } 99 return (TRUE); 100 } 101 102 return (xdr_opaque(xdrs, (caddr_t)fh, NFS_FHSIZE)); 103 } 104 105 bool_t 106 xdr_fastfhandle(XDR *xdrs, fhandle_t **fh) 107 { 108 int32_t *ptr; 109 110 if (xdrs->x_op != XDR_DECODE) 111 return (FALSE); 112 113 ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t))); 114 if (ptr != NULL) { 115 *fh = (fhandle_t *)ptr; 116 return (TRUE); 117 } 118 119 return (FALSE); 120 } 121 122 /* 123 * Arguments to remote write and writecache 124 */ 125 bool_t 126 xdr_writeargs(XDR *xdrs, struct nfswriteargs *wa) 127 { 128 int32_t *ptr; 129 int32_t *fhp; 130 131 if (xdrs->x_op == XDR_DECODE) { 132 wa->wa_args = &wa->wa_args_buf; 133 ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)) + 134 3 * BYTES_PER_XDR_UNIT); 135 if (ptr != NULL) { 136 fhp = (int32_t *)&wa->wa_fhandle; 137 *fhp++ = *ptr++; 138 *fhp++ = *ptr++; 139 *fhp++ = *ptr++; 140 *fhp++ = *ptr++; 141 *fhp++ = *ptr++; 142 *fhp++ = *ptr++; 143 *fhp++ = *ptr++; 144 *fhp = *ptr++; 145 wa->wa_begoff = IXDR_GET_U_INT32(ptr); 146 wa->wa_offset = IXDR_GET_U_INT32(ptr); 147 wa->wa_totcount = IXDR_GET_U_INT32(ptr); 148 if (xdrs->x_ops == &xdrmblk_ops) 149 return (xdrmblk_getmblk(xdrs, &wa->wa_mblk, 150 &wa->wa_count)); 151 /* 152 * It is just as efficient to xdr_bytes 153 * an array of unknown length as to inline copy it. 154 */ 155 return (xdr_bytes(xdrs, &wa->wa_data, 156 &wa->wa_count, NFS_MAXDATA)); 157 } 158 } 159 160 if (xdrs->x_op == XDR_ENCODE) { 161 ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)) + 162 3 * BYTES_PER_XDR_UNIT); 163 if (ptr != NULL) { 164 fhp = (int32_t *)&wa->wa_fhandle; 165 *ptr++ = *fhp++; 166 *ptr++ = *fhp++; 167 *ptr++ = *fhp++; 168 *ptr++ = *fhp++; 169 *ptr++ = *fhp++; 170 *ptr++ = *fhp++; 171 *ptr++ = *fhp++; 172 *ptr++ = *fhp; 173 IXDR_PUT_U_INT32(ptr, wa->wa_begoff); 174 IXDR_PUT_U_INT32(ptr, wa->wa_offset); 175 IXDR_PUT_U_INT32(ptr, wa->wa_totcount); 176 } else { 177 if (!(xdr_fhandle(xdrs, &wa->wa_fhandle) && 178 xdr_u_int(xdrs, &wa->wa_begoff) && 179 xdr_u_int(xdrs, &wa->wa_offset) && 180 xdr_u_int(xdrs, &wa->wa_totcount))) 181 return (FALSE); 182 } 183 #if 0 /* notdef */ 184 if (wa->wa_mblk != NULL && xdrs->x_ops == &xdrmblk_ops) { 185 mblk_t *mp; 186 187 mp = dupb(wa->wa_mblk); 188 if (mp != NULL) { 189 mp->b_wptr += wa->wa_count; 190 if (xdrmblk_putmblk(xdrs, mp, 191 wa->wa_count) == TRUE) { 192 return (TRUE); 193 } else 194 freeb(mp); 195 } 196 /* else Fall thru for the xdr_bytes() */ 197 } 198 /* wa_mblk == NULL || xdrs->x_ops != &xdrmblk_ops Fall thru */ 199 #endif /* notdef */ 200 return (xdr_bytes(xdrs, &wa->wa_data, &wa->wa_count, 201 NFS_MAXDATA)); 202 } 203 204 if (xdrs->x_op == XDR_FREE) { 205 if (wa->wa_data != NULL) { 206 kmem_free(wa->wa_data, wa->wa_count); 207 wa->wa_data = NULL; 208 } 209 return (TRUE); 210 } 211 212 if (xdr_fhandle(xdrs, &wa->wa_fhandle) && 213 xdr_u_int(xdrs, &wa->wa_begoff) && 214 xdr_u_int(xdrs, &wa->wa_offset) && 215 xdr_u_int(xdrs, &wa->wa_totcount) && 216 (xdrs->x_op == XDR_DECODE && xdrs->x_ops == &xdrmblk_ops) ? 217 xdrmblk_getmblk(xdrs, &wa->wa_mblk, &wa->wa_count) : 218 xdr_bytes(xdrs, &wa->wa_data, &wa->wa_count, NFS_MAXDATA)) { 219 return (TRUE); 220 } 221 return (FALSE); 222 } 223 224 225 /* 226 * File attributes 227 */ 228 bool_t 229 xdr_fattr(XDR *xdrs, struct nfsfattr *na) 230 { 231 int32_t *ptr; 232 233 if (xdrs->x_op == XDR_FREE) 234 return (TRUE); 235 236 ptr = XDR_INLINE(xdrs, 17 * BYTES_PER_XDR_UNIT); 237 if (ptr != NULL) { 238 if (xdrs->x_op == XDR_DECODE) { 239 na->na_type = IXDR_GET_ENUM(ptr, enum nfsftype); 240 na->na_mode = IXDR_GET_U_INT32(ptr); 241 na->na_nlink = IXDR_GET_U_INT32(ptr); 242 na->na_uid = IXDR_GET_U_INT32(ptr); 243 na->na_gid = IXDR_GET_U_INT32(ptr); 244 na->na_size = IXDR_GET_U_INT32(ptr); 245 na->na_blocksize = IXDR_GET_U_INT32(ptr); 246 na->na_rdev = IXDR_GET_U_INT32(ptr); 247 na->na_blocks = IXDR_GET_U_INT32(ptr); 248 na->na_fsid = IXDR_GET_U_INT32(ptr); 249 na->na_nodeid = IXDR_GET_U_INT32(ptr); 250 na->na_atime.tv_sec = IXDR_GET_U_INT32(ptr); 251 na->na_atime.tv_usec = IXDR_GET_U_INT32(ptr); 252 na->na_mtime.tv_sec = IXDR_GET_U_INT32(ptr); 253 na->na_mtime.tv_usec = IXDR_GET_U_INT32(ptr); 254 na->na_ctime.tv_sec = IXDR_GET_U_INT32(ptr); 255 na->na_ctime.tv_usec = IXDR_GET_U_INT32(ptr); 256 } else { 257 IXDR_PUT_ENUM(ptr, na->na_type); 258 IXDR_PUT_U_INT32(ptr, na->na_mode); 259 IXDR_PUT_U_INT32(ptr, na->na_nlink); 260 IXDR_PUT_U_INT32(ptr, na->na_uid); 261 IXDR_PUT_U_INT32(ptr, na->na_gid); 262 IXDR_PUT_U_INT32(ptr, na->na_size); 263 IXDR_PUT_U_INT32(ptr, na->na_blocksize); 264 IXDR_PUT_U_INT32(ptr, na->na_rdev); 265 IXDR_PUT_U_INT32(ptr, na->na_blocks); 266 IXDR_PUT_U_INT32(ptr, na->na_fsid); 267 IXDR_PUT_U_INT32(ptr, na->na_nodeid); 268 IXDR_PUT_U_INT32(ptr, na->na_atime.tv_sec); 269 IXDR_PUT_U_INT32(ptr, na->na_atime.tv_usec); 270 IXDR_PUT_U_INT32(ptr, na->na_mtime.tv_sec); 271 IXDR_PUT_U_INT32(ptr, na->na_mtime.tv_usec); 272 IXDR_PUT_U_INT32(ptr, na->na_ctime.tv_sec); 273 IXDR_PUT_U_INT32(ptr, na->na_ctime.tv_usec); 274 } 275 return (TRUE); 276 } 277 278 if (xdr_enum(xdrs, (enum_t *)&na->na_type) && 279 xdr_u_int(xdrs, &na->na_mode) && 280 xdr_u_int(xdrs, &na->na_nlink) && 281 xdr_u_int(xdrs, &na->na_uid) && 282 xdr_u_int(xdrs, &na->na_gid) && 283 xdr_u_int(xdrs, &na->na_size) && 284 xdr_u_int(xdrs, &na->na_blocksize) && 285 xdr_u_int(xdrs, &na->na_rdev) && 286 xdr_u_int(xdrs, &na->na_blocks) && 287 xdr_u_int(xdrs, &na->na_fsid) && 288 xdr_u_int(xdrs, &na->na_nodeid) && 289 xdr_nfs2_timeval(xdrs, &na->na_atime) && 290 xdr_nfs2_timeval(xdrs, &na->na_mtime) && 291 xdr_nfs2_timeval(xdrs, &na->na_ctime)) { 292 return (TRUE); 293 } 294 return (FALSE); 295 } 296 297 #ifdef _LITTLE_ENDIAN 298 bool_t 299 xdr_fastfattr(XDR *xdrs, struct nfsfattr *na) 300 { 301 if (xdrs->x_op == XDR_FREE) 302 return (TRUE); 303 if (xdrs->x_op == XDR_DECODE) 304 return (FALSE); 305 306 na->na_type = htonl(na->na_type); 307 na->na_mode = htonl(na->na_mode); 308 na->na_nlink = htonl(na->na_nlink); 309 na->na_uid = htonl(na->na_uid); 310 na->na_gid = htonl(na->na_gid); 311 na->na_size = htonl(na->na_size); 312 na->na_blocksize = htonl(na->na_blocksize); 313 na->na_rdev = htonl(na->na_rdev); 314 na->na_blocks = htonl(na->na_blocks); 315 na->na_fsid = htonl(na->na_fsid); 316 na->na_nodeid = htonl(na->na_nodeid); 317 na->na_atime.tv_sec = htonl(na->na_atime.tv_sec); 318 na->na_atime.tv_usec = htonl(na->na_atime.tv_usec); 319 na->na_mtime.tv_sec = htonl(na->na_mtime.tv_sec); 320 na->na_mtime.tv_usec = htonl(na->na_mtime.tv_usec); 321 na->na_ctime.tv_sec = htonl(na->na_ctime.tv_sec); 322 na->na_ctime.tv_usec = htonl(na->na_ctime.tv_usec); 323 return (TRUE); 324 } 325 #endif 326 327 /* 328 * Arguments to remote read 329 */ 330 bool_t 331 xdr_readargs(XDR *xdrs, struct nfsreadargs *ra) 332 { 333 int32_t *ptr; 334 int32_t *fhp; 335 336 if (xdrs->x_op == XDR_FREE) 337 return (TRUE); 338 339 ptr = XDR_INLINE(xdrs, 340 RNDUP(sizeof (fhandle_t)) + 3 * BYTES_PER_XDR_UNIT); 341 if (ptr != NULL) { 342 if (xdrs->x_op == XDR_DECODE) { 343 fhp = (int32_t *)&ra->ra_fhandle; 344 *fhp++ = *ptr++; 345 *fhp++ = *ptr++; 346 *fhp++ = *ptr++; 347 *fhp++ = *ptr++; 348 *fhp++ = *ptr++; 349 *fhp++ = *ptr++; 350 *fhp++ = *ptr++; 351 *fhp = *ptr++; 352 ra->ra_offset = IXDR_GET_INT32(ptr); 353 ra->ra_count = IXDR_GET_INT32(ptr); 354 ra->ra_totcount = IXDR_GET_INT32(ptr); 355 } else { 356 fhp = (int32_t *)&ra->ra_fhandle; 357 *ptr++ = *fhp++; 358 *ptr++ = *fhp++; 359 *ptr++ = *fhp++; 360 *ptr++ = *fhp++; 361 *ptr++ = *fhp++; 362 *ptr++ = *fhp++; 363 *ptr++ = *fhp++; 364 *ptr++ = *fhp; 365 IXDR_PUT_INT32(ptr, ra->ra_offset); 366 IXDR_PUT_INT32(ptr, ra->ra_count); 367 IXDR_PUT_INT32(ptr, ra->ra_totcount); 368 } 369 if (ra->ra_count > NFS_MAXDATA) 370 return (FALSE); 371 return (TRUE); 372 } 373 374 if (xdr_fhandle(xdrs, &ra->ra_fhandle) && 375 xdr_u_int(xdrs, &ra->ra_offset) && 376 xdr_u_int(xdrs, &ra->ra_count) && 377 xdr_u_int(xdrs, &ra->ra_totcount)) { 378 if (ra->ra_count > NFS_MAXDATA) 379 return (FALSE); 380 return (TRUE); 381 } 382 return (FALSE); 383 } 384 385 386 /* 387 * Status OK portion of remote read reply 388 */ 389 bool_t 390 xdr_rrok(XDR *xdrs, struct nfsrrok *rrok) 391 { 392 bool_t ret; 393 mblk_t *mp; 394 395 if (xdr_fattr(xdrs, &rrok->rrok_attr) == FALSE) 396 return (FALSE); 397 398 if (xdrs->x_op == XDR_ENCODE) { 399 int i, rndup; 400 401 mp = rrok->rrok_mp; 402 if (mp != NULL && xdrs->x_ops == &xdrmblk_ops) { 403 mp->b_wptr += rrok->rrok_count; 404 rndup = BYTES_PER_XDR_UNIT - 405 (rrok->rrok_count % BYTES_PER_XDR_UNIT); 406 if (rndup != BYTES_PER_XDR_UNIT) 407 for (i = 0; i < rndup; i++) 408 *mp->b_wptr++ = '\0'; 409 if (xdrmblk_putmblk(xdrs, mp, 410 rrok->rrok_count) == TRUE) { 411 rrok->rrok_mp = NULL; 412 return (TRUE); 413 } 414 } 415 /* 416 * Fall thru for the xdr_bytes() 417 * 418 * Note: the mblk mp will be freed in rfs_rdfree 419 */ 420 } 421 422 ret = xdr_bytes(xdrs, (char **)&rrok->rrok_data, 423 &rrok->rrok_count, NFS_MAXDATA); 424 425 return (ret); 426 } 427 428 static struct xdr_discrim rdres_discrim[2] = { 429 { NFS_OK, xdr_rrok }, 430 { __dontcare__, NULL_xdrproc_t } 431 }; 432 433 /* 434 * Reply from remote read 435 */ 436 bool_t 437 xdr_rdresult(XDR *xdrs, struct nfsrdresult *rr) 438 { 439 return (xdr_union(xdrs, (enum_t *)&(rr->rr_status), 440 (caddr_t)&(rr->rr_ok), rdres_discrim, xdr_void)); 441 } 442 443 /* 444 * File attributes which can be set 445 */ 446 bool_t 447 xdr_sattr(XDR *xdrs, struct nfssattr *sa) 448 { 449 if (xdr_u_int(xdrs, &sa->sa_mode) && 450 xdr_u_int(xdrs, &sa->sa_uid) && 451 xdr_u_int(xdrs, &sa->sa_gid) && 452 xdr_u_int(xdrs, &sa->sa_size) && 453 xdr_nfs2_timeval(xdrs, &sa->sa_atime) && 454 xdr_nfs2_timeval(xdrs, &sa->sa_mtime)) { 455 return (TRUE); 456 } 457 return (FALSE); 458 } 459 460 static struct xdr_discrim attrstat_discrim[2] = { 461 { (int)NFS_OK, xdr_fattr }, 462 { __dontcare__, NULL_xdrproc_t } 463 }; 464 465 /* 466 * Reply status with file attributes 467 */ 468 bool_t 469 xdr_attrstat(XDR *xdrs, struct nfsattrstat *ns) 470 { 471 return (xdr_union(xdrs, (enum_t *)&(ns->ns_status), 472 (caddr_t)&(ns->ns_attr), attrstat_discrim, xdr_void)); 473 } 474 475 /* 476 * Fast reply status with file attributes 477 */ 478 bool_t 479 xdr_fastattrstat(XDR *xdrs, struct nfsattrstat *ns) 480 { 481 #if defined(_LITTLE_ENDIAN) 482 /* 483 * we deal with the discriminator; it's an enum 484 */ 485 if (!xdr_fastenum(xdrs, (enum_t *)&ns->ns_status)) 486 return (FALSE); 487 488 if (ns->ns_status == NFS_OK) 489 return (xdr_fastfattr(xdrs, &ns->ns_attr)); 490 #elif defined(_BIG_ENDIAN) 491 if (ns->ns_status == NFS_OK) 492 return (TRUE); 493 #endif 494 return (xdr_fastshorten(xdrs, sizeof (*ns))); 495 } 496 497 /* 498 * NFS_OK part of read sym link reply union 499 */ 500 bool_t 501 xdr_srok(XDR *xdrs, struct nfssrok *srok) 502 { 503 /* 504 * It is just as efficient to xdr_bytes 505 * an array of unknown length as to inline copy it. 506 */ 507 return (xdr_bytes(xdrs, &srok->srok_data, &srok->srok_count, 508 NFS_MAXPATHLEN)); 509 } 510 511 static struct xdr_discrim rdlnres_discrim[2] = { 512 { (int)NFS_OK, xdr_srok }, 513 { __dontcare__, NULL_xdrproc_t } 514 }; 515 516 /* 517 * Result of reading symbolic link 518 */ 519 bool_t 520 xdr_rdlnres(XDR *xdrs, struct nfsrdlnres *rl) 521 { 522 return (xdr_union(xdrs, (enum_t *)&(rl->rl_status), 523 (caddr_t)&(rl->rl_srok), rdlnres_discrim, xdr_void)); 524 } 525 526 /* 527 * Arguments to readdir 528 */ 529 bool_t 530 xdr_rddirargs(XDR *xdrs, struct nfsrddirargs *rda) 531 { 532 int32_t *ptr; 533 int32_t *fhp; 534 535 if (xdrs->x_op == XDR_FREE) 536 return (TRUE); 537 538 ptr = XDR_INLINE(xdrs, 539 RNDUP(sizeof (fhandle_t)) + 2 * BYTES_PER_XDR_UNIT); 540 if (ptr != NULL) { 541 if (xdrs->x_op == XDR_DECODE) { 542 fhp = (int32_t *)&rda->rda_fh; 543 *fhp++ = *ptr++; 544 *fhp++ = *ptr++; 545 *fhp++ = *ptr++; 546 *fhp++ = *ptr++; 547 *fhp++ = *ptr++; 548 *fhp++ = *ptr++; 549 *fhp++ = *ptr++; 550 *fhp = *ptr++; 551 rda->rda_offset = IXDR_GET_U_INT32(ptr); 552 rda->rda_count = IXDR_GET_U_INT32(ptr); 553 } else { 554 fhp = (int32_t *)&rda->rda_fh; 555 *ptr++ = *fhp++; 556 *ptr++ = *fhp++; 557 *ptr++ = *fhp++; 558 *ptr++ = *fhp++; 559 *ptr++ = *fhp++; 560 *ptr++ = *fhp++; 561 *ptr++ = *fhp++; 562 *ptr++ = *fhp; 563 IXDR_PUT_U_INT32(ptr, rda->rda_offset); 564 IXDR_PUT_U_INT32(ptr, rda->rda_count); 565 } 566 return (TRUE); 567 } 568 569 if (xdr_fhandle(xdrs, &rda->rda_fh) && 570 xdr_u_int(xdrs, &rda->rda_offset) && 571 xdr_u_int(xdrs, &rda->rda_count)) { 572 return (TRUE); 573 } 574 return (FALSE); 575 } 576 577 578 /* 579 * Directory read reply: 580 * union (enum status) { 581 * NFS_OK: entlist; 582 * boolean eof; 583 * default: 584 * } 585 * 586 * Directory entries 587 * struct direct { 588 * off_t d_off; * offset of next entry * 589 * u_int d_fileno; * inode number of entry * 590 * u_short d_reclen; * length of this record * 591 * u_short d_namlen; * length of string in d_name * 592 * char d_name[MAXNAMLEN + 1]; * name no longer than this * 593 * }; 594 * are on the wire as: 595 * union entlist (boolean valid) { 596 * TRUE: struct otw_dirent; 597 * u_int nxtoffset; 598 * union entlist; 599 * FALSE: 600 * } 601 * where otw_dirent is: 602 * struct dirent { 603 * u_int de_fid; 604 * string de_name<NFS_MAXNAMELEN>; 605 * } 606 */ 607 608 #ifdef nextdp 609 #undef nextdp 610 #endif 611 #define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen)) 612 #ifdef roundup 613 #undef roundup 614 #endif 615 #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) 616 617 /* 618 * ENCODE ONLY 619 */ 620 bool_t 621 xdr_putrddirres(XDR *xdrs, struct nfsrddirres *rd) 622 { 623 struct dirent64 *dp; 624 char *name; 625 int size; 626 uint_t namlen; 627 bool_t true = TRUE; 628 bool_t false = FALSE; 629 int entrysz; 630 int tofit; 631 int bufsize; 632 uint32_t ino, off; 633 634 if (xdrs->x_op != XDR_ENCODE) 635 return (FALSE); 636 if (!xdr_enum(xdrs, (enum_t *)&rd->rd_status)) 637 return (FALSE); 638 if (rd->rd_status != NFS_OK) 639 return (TRUE); 640 641 bufsize = 1 * BYTES_PER_XDR_UNIT; 642 for (size = rd->rd_size, dp = rd->rd_entries; 643 size > 0; 644 size -= dp->d_reclen, dp = nextdp(dp)) { 645 if (dp->d_reclen == 0 /* || DIRSIZ(dp) > dp->d_reclen */) 646 return (FALSE); 647 if (dp->d_ino == 0) 648 continue; 649 ino = (uint32_t)dp->d_ino; /* for LP64 we clip the bits */ 650 if (dp->d_ino != (ino64_t)ino) /* and they better be zeros */ 651 return (FALSE); 652 off = (uint32_t)dp->d_off; 653 name = dp->d_name; 654 namlen = (uint_t)strlen(name); 655 entrysz = (1 + 1 + 1 + 1) * BYTES_PER_XDR_UNIT + 656 roundup(namlen, BYTES_PER_XDR_UNIT); 657 tofit = entrysz + 2 * BYTES_PER_XDR_UNIT; 658 if (bufsize + tofit > rd->rd_bufsize) { 659 rd->rd_eof = FALSE; 660 break; 661 } 662 if (!xdr_bool(xdrs, &true) || 663 !xdr_u_int(xdrs, &ino) || 664 !xdr_bytes(xdrs, &name, &namlen, NFS_MAXNAMLEN) || 665 !xdr_u_int(xdrs, &off)) { 666 return (FALSE); 667 } 668 bufsize += entrysz; 669 } 670 if (!xdr_bool(xdrs, &false)) 671 return (FALSE); 672 if (!xdr_bool(xdrs, &rd->rd_eof)) 673 return (FALSE); 674 return (TRUE); 675 } 676 677 /* 678 * DECODE ONLY 679 */ 680 bool_t 681 xdr_getrddirres(XDR *xdrs, struct nfsrddirres *rd) 682 { 683 struct dirent64 *dp; 684 uint_t namlen; 685 int size; 686 bool_t valid; 687 uint32_t offset; 688 uint_t fileid, this_reclen; 689 690 if (xdrs->x_op != XDR_DECODE) 691 return (FALSE); 692 693 if (!xdr_enum(xdrs, (enum_t *)&rd->rd_status)) 694 return (FALSE); 695 if (rd->rd_status != NFS_OK) 696 return (TRUE); 697 698 size = rd->rd_size; 699 dp = rd->rd_entries; 700 offset = rd->rd_offset; 701 for (;;) { 702 if (!xdr_bool(xdrs, &valid)) 703 return (FALSE); 704 if (!valid) 705 break; 706 if (!xdr_u_int(xdrs, &fileid) || 707 !xdr_u_int(xdrs, &namlen)) 708 return (FALSE); 709 this_reclen = DIRENT64_RECLEN(namlen); 710 if (this_reclen > size) { 711 rd->rd_eof = FALSE; 712 goto bufovflw; 713 } 714 if (!xdr_opaque(xdrs, dp->d_name, namlen)|| 715 !xdr_u_int(xdrs, &offset)) { 716 return (FALSE); 717 } 718 bzero(&dp->d_name[namlen], 719 DIRENT64_NAMELEN(this_reclen) - namlen); 720 dp->d_ino = (ino64_t)fileid; 721 dp->d_reclen = this_reclen; 722 dp->d_off = (off64_t)offset; 723 size -= dp->d_reclen; 724 dp = nextdp(dp); 725 } 726 if (!xdr_bool(xdrs, &rd->rd_eof)) 727 return (FALSE); 728 bufovflw: 729 rd->rd_size = (uint32_t)((char *)dp - (char *)(rd->rd_entries)); 730 rd->rd_offset = offset; 731 return (TRUE); 732 } 733 734 /* 735 * Arguments for directory operations 736 */ 737 bool_t 738 xdr_diropargs(XDR *xdrs, struct nfsdiropargs *da) 739 { 740 int32_t *ptr; 741 int32_t *fhp; 742 uint32_t size; 743 uint32_t nodesize; 744 int i; 745 int rndup; 746 char *cptr; 747 748 if (xdrs->x_op == XDR_DECODE) { 749 da->da_fhandle = &da->da_fhandle_buf; 750 ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)) + 751 1 * BYTES_PER_XDR_UNIT); 752 if (ptr != NULL) { 753 fhp = (int32_t *)da->da_fhandle; 754 *fhp++ = *ptr++; 755 *fhp++ = *ptr++; 756 *fhp++ = *ptr++; 757 *fhp++ = *ptr++; 758 *fhp++ = *ptr++; 759 *fhp++ = *ptr++; 760 *fhp++ = *ptr++; 761 *fhp = *ptr++; 762 size = IXDR_GET_U_INT32(ptr); 763 if (size > NFS_MAXNAMLEN) 764 return (FALSE); 765 nodesize = size + 1; 766 if (nodesize == 0) 767 return (TRUE); 768 if (da->da_name == NULL) { 769 da->da_name = kmem_alloc(nodesize, KM_NOSLEEP); 770 if (da->da_name == NULL) 771 return (FALSE); 772 da->da_flags |= DA_FREENAME; 773 } 774 ptr = XDR_INLINE(xdrs, RNDUP(size)); 775 if (ptr == NULL) { 776 if (!xdr_opaque(xdrs, da->da_name, size)) { 777 if (da->da_flags & DA_FREENAME) { 778 kmem_free(da->da_name, 779 nodesize); 780 da->da_name = NULL; 781 } 782 return (FALSE); 783 } 784 da->da_name[size] = '\0'; 785 if (strlen(da->da_name) != size) { 786 if (da->da_flags & DA_FREENAME) { 787 kmem_free(da->da_name, 788 nodesize); 789 da->da_name = NULL; 790 } 791 return (FALSE); 792 } 793 return (TRUE); 794 } 795 bcopy(ptr, da->da_name, size); 796 da->da_name[size] = '\0'; 797 if (strlen(da->da_name) != size) { 798 if (da->da_flags & DA_FREENAME) { 799 kmem_free(da->da_name, nodesize); 800 da->da_name = NULL; 801 } 802 return (FALSE); 803 } 804 return (TRUE); 805 } 806 if (da->da_name == NULL) 807 da->da_flags |= DA_FREENAME; 808 } 809 810 if (xdrs->x_op == XDR_ENCODE) { 811 size = (uint32_t)strlen(da->da_name); 812 if (size > NFS_MAXNAMLEN) 813 return (FALSE); 814 ptr = XDR_INLINE(xdrs, (int)(RNDUP(sizeof (fhandle_t)) + 815 1 * BYTES_PER_XDR_UNIT + RNDUP(size))); 816 if (ptr != NULL) { 817 fhp = (int32_t *)da->da_fhandle; 818 *ptr++ = *fhp++; 819 *ptr++ = *fhp++; 820 *ptr++ = *fhp++; 821 *ptr++ = *fhp++; 822 *ptr++ = *fhp++; 823 *ptr++ = *fhp++; 824 *ptr++ = *fhp++; 825 *ptr++ = *fhp; 826 IXDR_PUT_U_INT32(ptr, (uint32_t)size); 827 bcopy(da->da_name, ptr, size); 828 rndup = BYTES_PER_XDR_UNIT - 829 (size % BYTES_PER_XDR_UNIT); 830 if (rndup != BYTES_PER_XDR_UNIT) { 831 cptr = (char *)ptr + size; 832 for (i = 0; i < rndup; i++) 833 *cptr++ = '\0'; 834 } 835 return (TRUE); 836 } 837 } 838 839 if (xdrs->x_op == XDR_FREE) { 840 if (da->da_name == NULL) 841 return (TRUE); 842 size = (uint32_t)strlen(da->da_name); 843 if (size > NFS_MAXNAMLEN) 844 return (FALSE); 845 if (da->da_flags & DA_FREENAME) 846 kmem_free(da->da_name, size + 1); 847 da->da_name = NULL; 848 return (TRUE); 849 } 850 851 if (xdr_fhandle(xdrs, da->da_fhandle) && 852 xdr_string(xdrs, &da->da_name, NFS_MAXNAMLEN)) { 853 return (TRUE); 854 } 855 return (FALSE); 856 } 857 858 /* 859 * NFS_OK part of directory operation result 860 */ 861 bool_t 862 xdr_drok(XDR *xdrs, struct nfsdrok *drok) 863 { 864 int32_t *ptr; 865 int32_t *fhp; 866 struct nfsfattr *na; 867 868 if (xdrs->x_op == XDR_FREE) 869 return (TRUE); 870 871 ptr = XDR_INLINE(xdrs, 872 RNDUP(sizeof (fhandle_t)) + 17 * BYTES_PER_XDR_UNIT); 873 if (ptr != NULL) { 874 if (xdrs->x_op == XDR_DECODE) { 875 fhp = (int32_t *)&drok->drok_fhandle; 876 *fhp++ = *ptr++; 877 *fhp++ = *ptr++; 878 *fhp++ = *ptr++; 879 *fhp++ = *ptr++; 880 *fhp++ = *ptr++; 881 *fhp++ = *ptr++; 882 *fhp++ = *ptr++; 883 *fhp = *ptr++; 884 na = &drok->drok_attr; 885 na->na_type = IXDR_GET_ENUM(ptr, enum nfsftype); 886 na->na_mode = IXDR_GET_U_INT32(ptr); 887 na->na_nlink = IXDR_GET_U_INT32(ptr); 888 na->na_uid = IXDR_GET_U_INT32(ptr); 889 na->na_gid = IXDR_GET_U_INT32(ptr); 890 na->na_size = IXDR_GET_U_INT32(ptr); 891 na->na_blocksize = IXDR_GET_U_INT32(ptr); 892 na->na_rdev = IXDR_GET_U_INT32(ptr); 893 na->na_blocks = IXDR_GET_U_INT32(ptr); 894 na->na_fsid = IXDR_GET_U_INT32(ptr); 895 na->na_nodeid = IXDR_GET_U_INT32(ptr); 896 na->na_atime.tv_sec = IXDR_GET_U_INT32(ptr); 897 na->na_atime.tv_usec = IXDR_GET_U_INT32(ptr); 898 na->na_mtime.tv_sec = IXDR_GET_U_INT32(ptr); 899 na->na_mtime.tv_usec = IXDR_GET_U_INT32(ptr); 900 na->na_ctime.tv_sec = IXDR_GET_U_INT32(ptr); 901 na->na_ctime.tv_usec = IXDR_GET_U_INT32(ptr); 902 } else { 903 fhp = (int32_t *)&drok->drok_fhandle; 904 *ptr++ = *fhp++; 905 *ptr++ = *fhp++; 906 *ptr++ = *fhp++; 907 *ptr++ = *fhp++; 908 *ptr++ = *fhp++; 909 *ptr++ = *fhp++; 910 *ptr++ = *fhp++; 911 *ptr++ = *fhp; 912 na = &drok->drok_attr; 913 IXDR_PUT_ENUM(ptr, na->na_type); 914 IXDR_PUT_U_INT32(ptr, na->na_mode); 915 IXDR_PUT_U_INT32(ptr, na->na_nlink); 916 IXDR_PUT_U_INT32(ptr, na->na_uid); 917 IXDR_PUT_U_INT32(ptr, na->na_gid); 918 IXDR_PUT_U_INT32(ptr, na->na_size); 919 IXDR_PUT_U_INT32(ptr, na->na_blocksize); 920 IXDR_PUT_U_INT32(ptr, na->na_rdev); 921 IXDR_PUT_U_INT32(ptr, na->na_blocks); 922 IXDR_PUT_U_INT32(ptr, na->na_fsid); 923 IXDR_PUT_U_INT32(ptr, na->na_nodeid); 924 IXDR_PUT_U_INT32(ptr, na->na_atime.tv_sec); 925 IXDR_PUT_U_INT32(ptr, na->na_atime.tv_usec); 926 IXDR_PUT_U_INT32(ptr, na->na_mtime.tv_sec); 927 IXDR_PUT_U_INT32(ptr, na->na_mtime.tv_usec); 928 IXDR_PUT_U_INT32(ptr, na->na_ctime.tv_sec); 929 IXDR_PUT_U_INT32(ptr, na->na_ctime.tv_usec); 930 } 931 return (TRUE); 932 } 933 934 if (xdr_fhandle(xdrs, &drok->drok_fhandle) && 935 xdr_fattr(xdrs, &drok->drok_attr)) { 936 return (TRUE); 937 } 938 return (FALSE); 939 } 940 941 #ifdef _LITTLE_ENDIAN 942 bool_t 943 xdr_fastdrok(XDR *xdrs, struct nfsdrok *drok) 944 { 945 struct nfsfattr *na; 946 947 if (xdrs->x_op == XDR_FREE) 948 return (TRUE); 949 if (xdrs->x_op == XDR_DECODE) 950 return (FALSE); 951 952 na = &drok->drok_attr; 953 na->na_type = (enum nfsftype)htonl(na->na_type); 954 na->na_mode = (uint32_t)htonl(na->na_mode); 955 na->na_nlink = (uint32_t)htonl(na->na_nlink); 956 na->na_uid = (uint32_t)htonl(na->na_uid); 957 na->na_gid = (uint32_t)htonl(na->na_gid); 958 na->na_size = (uint32_t)htonl(na->na_size); 959 na->na_blocksize = (uint32_t)htonl(na->na_blocksize); 960 na->na_rdev = (uint32_t)htonl(na->na_rdev); 961 na->na_blocks = (uint32_t)htonl(na->na_blocks); 962 na->na_fsid = (uint32_t)htonl(na->na_fsid); 963 na->na_nodeid = (uint32_t)htonl(na->na_nodeid); 964 na->na_atime.tv_sec = htonl(na->na_atime.tv_sec); 965 na->na_atime.tv_usec = htonl(na->na_atime.tv_usec); 966 na->na_mtime.tv_sec = htonl(na->na_mtime.tv_sec); 967 na->na_mtime.tv_usec = htonl(na->na_mtime.tv_usec); 968 na->na_ctime.tv_sec = htonl(na->na_ctime.tv_sec); 969 na->na_ctime.tv_usec = htonl(na->na_ctime.tv_usec); 970 return (TRUE); 971 } 972 #endif 973 974 static struct xdr_discrim diropres_discrim[2] = { 975 { NFS_OK, xdr_drok }, 976 { __dontcare__, NULL_xdrproc_t } 977 }; 978 979 /* 980 * Results from directory operation 981 */ 982 bool_t 983 xdr_diropres(XDR *xdrs, struct nfsdiropres *dr) 984 { 985 return (xdr_union(xdrs, (enum_t *)&(dr->dr_status), 986 (caddr_t)&(dr->dr_drok), diropres_discrim, xdr_void)); 987 } 988 989 /* 990 * Results from directory operation 991 */ 992 bool_t 993 xdr_fastdiropres(XDR *xdrs, struct nfsdiropres *dr) 994 { 995 #if defined(_LITTLE_ENDIAN) 996 /* 997 * we deal with the discriminator; it's an enum 998 */ 999 if (!xdr_fastenum(xdrs, (enum_t *)&dr->dr_status)) 1000 return (FALSE); 1001 1002 if (dr->dr_status == NFS_OK) 1003 return (xdr_fastdrok(xdrs, &dr->dr_drok)); 1004 #elif defined(_BIG_ENDIAN) 1005 if (dr->dr_status == NFS_OK) 1006 return (TRUE); 1007 #endif 1008 return (xdr_fastshorten(xdrs, sizeof (*dr))); 1009 } 1010 1011 /* 1012 * Time Structure, unsigned 1013 */ 1014 bool_t 1015 xdr_nfs2_timeval(XDR *xdrs, struct nfs2_timeval *tv) 1016 { 1017 if (xdr_u_int(xdrs, &tv->tv_sec) && 1018 xdr_u_int(xdrs, &tv->tv_usec)) 1019 return (TRUE); 1020 return (FALSE); 1021 } 1022 1023 /* 1024 * arguments to setattr 1025 */ 1026 bool_t 1027 xdr_saargs(XDR *xdrs, struct nfssaargs *argp) 1028 { 1029 int32_t *ptr; 1030 int32_t *arg; 1031 struct nfssattr *sa; 1032 1033 if (xdrs->x_op == XDR_FREE) 1034 return (TRUE); 1035 1036 ptr = XDR_INLINE(xdrs, 1037 RNDUP(sizeof (fhandle_t)) + 8 * BYTES_PER_XDR_UNIT); 1038 if (ptr != NULL) { 1039 if (xdrs->x_op == XDR_DECODE) { 1040 arg = (int32_t *)&argp->saa_fh; 1041 *arg++ = *ptr++; 1042 *arg++ = *ptr++; 1043 *arg++ = *ptr++; 1044 *arg++ = *ptr++; 1045 *arg++ = *ptr++; 1046 *arg++ = *ptr++; 1047 *arg++ = *ptr++; 1048 *arg = *ptr++; 1049 sa = &argp->saa_sa; 1050 sa->sa_mode = IXDR_GET_U_INT32(ptr); 1051 sa->sa_uid = IXDR_GET_U_INT32(ptr); 1052 sa->sa_gid = IXDR_GET_U_INT32(ptr); 1053 sa->sa_size = IXDR_GET_U_INT32(ptr); 1054 sa->sa_atime.tv_sec = IXDR_GET_U_INT32(ptr); 1055 sa->sa_atime.tv_usec = IXDR_GET_U_INT32(ptr); 1056 sa->sa_mtime.tv_sec = IXDR_GET_U_INT32(ptr); 1057 sa->sa_mtime.tv_usec = IXDR_GET_U_INT32(ptr); 1058 } else { 1059 arg = (int32_t *)&argp->saa_fh; 1060 *ptr++ = *arg++; 1061 *ptr++ = *arg++; 1062 *ptr++ = *arg++; 1063 *ptr++ = *arg++; 1064 *ptr++ = *arg++; 1065 *ptr++ = *arg++; 1066 *ptr++ = *arg++; 1067 *ptr++ = *arg; 1068 sa = &argp->saa_sa; 1069 IXDR_PUT_U_INT32(ptr, sa->sa_mode); 1070 IXDR_PUT_U_INT32(ptr, sa->sa_uid); 1071 IXDR_PUT_U_INT32(ptr, sa->sa_gid); 1072 IXDR_PUT_U_INT32(ptr, sa->sa_size); 1073 IXDR_PUT_U_INT32(ptr, sa->sa_atime.tv_sec); 1074 IXDR_PUT_U_INT32(ptr, sa->sa_atime.tv_usec); 1075 IXDR_PUT_U_INT32(ptr, sa->sa_mtime.tv_sec); 1076 IXDR_PUT_U_INT32(ptr, sa->sa_mtime.tv_usec); 1077 } 1078 return (TRUE); 1079 } 1080 1081 if (xdr_fhandle(xdrs, &argp->saa_fh) && 1082 xdr_sattr(xdrs, &argp->saa_sa)) { 1083 return (TRUE); 1084 } 1085 return (FALSE); 1086 } 1087 1088 1089 /* 1090 * arguments to create and mkdir 1091 */ 1092 bool_t 1093 xdr_creatargs(XDR *xdrs, struct nfscreatargs *argp) 1094 { 1095 argp->ca_sa = &argp->ca_sa_buf; 1096 1097 if (xdrs->x_op == XDR_DECODE) 1098 argp->ca_sa = &argp->ca_sa_buf; 1099 if (xdr_diropargs(xdrs, &argp->ca_da) && 1100 xdr_sattr(xdrs, argp->ca_sa)) { 1101 return (TRUE); 1102 } 1103 return (FALSE); 1104 } 1105 1106 /* 1107 * arguments to link 1108 */ 1109 bool_t 1110 xdr_linkargs(XDR *xdrs, struct nfslinkargs *argp) 1111 { 1112 if (xdrs->x_op == XDR_DECODE) 1113 argp->la_from = &argp->la_from_buf; 1114 if (xdr_fhandle(xdrs, argp->la_from) && 1115 xdr_diropargs(xdrs, &argp->la_to)) { 1116 return (TRUE); 1117 } 1118 return (FALSE); 1119 } 1120 1121 /* 1122 * arguments to rename 1123 */ 1124 bool_t 1125 xdr_rnmargs(XDR *xdrs, struct nfsrnmargs *argp) 1126 { 1127 if (xdr_diropargs(xdrs, &argp->rna_from) && 1128 xdr_diropargs(xdrs, &argp->rna_to)) 1129 return (TRUE); 1130 return (FALSE); 1131 } 1132 1133 1134 /* 1135 * arguments to symlink 1136 */ 1137 bool_t 1138 xdr_slargs(XDR *xdrs, struct nfsslargs *argp) 1139 { 1140 if (xdrs->x_op == XDR_FREE) { 1141 if (!xdr_diropargs(xdrs, &argp->sla_from)) 1142 return (FALSE); 1143 if ((argp->sla_tnm_flags & SLA_FREETNM) && 1144 !xdr_string(xdrs, &argp->sla_tnm, (uint_t)NFS_MAXPATHLEN)) 1145 return (FALSE); 1146 return (TRUE); 1147 } 1148 1149 if (xdrs->x_op == XDR_DECODE) { 1150 argp->sla_sa = &argp->sla_sa_buf; 1151 if (argp->sla_tnm == NULL) 1152 argp->sla_tnm_flags |= SLA_FREETNM; 1153 } 1154 1155 if (xdr_diropargs(xdrs, &argp->sla_from) && 1156 xdr_string(xdrs, &argp->sla_tnm, (uint_t)NFS_MAXPATHLEN) && 1157 xdr_sattr(xdrs, argp->sla_sa)) { 1158 return (TRUE); 1159 } 1160 return (FALSE); 1161 } 1162 1163 1164 /* 1165 * NFS_OK part of statfs operation 1166 */ 1167 bool_t 1168 xdr_fsok(XDR *xdrs, struct nfsstatfsok *fsok) 1169 { 1170 int32_t *ptr; 1171 1172 if (xdrs->x_op == XDR_FREE) 1173 return (TRUE); 1174 1175 ptr = XDR_INLINE(xdrs, 5 * BYTES_PER_XDR_UNIT); 1176 if (ptr != NULL) { 1177 if (xdrs->x_op == XDR_DECODE) { 1178 fsok->fsok_tsize = IXDR_GET_INT32(ptr); 1179 fsok->fsok_bsize = IXDR_GET_INT32(ptr); 1180 fsok->fsok_blocks = IXDR_GET_INT32(ptr); 1181 fsok->fsok_bfree = IXDR_GET_INT32(ptr); 1182 fsok->fsok_bavail = IXDR_GET_INT32(ptr); 1183 } else { 1184 IXDR_PUT_INT32(ptr, fsok->fsok_tsize); 1185 IXDR_PUT_INT32(ptr, fsok->fsok_bsize); 1186 IXDR_PUT_INT32(ptr, fsok->fsok_blocks); 1187 IXDR_PUT_INT32(ptr, fsok->fsok_bfree); 1188 IXDR_PUT_INT32(ptr, fsok->fsok_bavail); 1189 } 1190 return (TRUE); 1191 } 1192 1193 if (xdr_u_int(xdrs, &fsok->fsok_tsize) && 1194 xdr_u_int(xdrs, &fsok->fsok_bsize) && 1195 xdr_u_int(xdrs, &fsok->fsok_blocks) && 1196 xdr_u_int(xdrs, &fsok->fsok_bfree) && 1197 xdr_u_int(xdrs, &fsok->fsok_bavail)) { 1198 return (TRUE); 1199 } 1200 return (FALSE); 1201 } 1202 1203 #ifdef _LITTLE_ENDIAN 1204 bool_t 1205 xdr_fastfsok(XDR *xdrs, struct nfsstatfsok *fsok) 1206 { 1207 1208 if (xdrs->x_op == XDR_FREE) 1209 return (TRUE); 1210 if (xdrs->x_op == XDR_DECODE) 1211 return (FALSE); 1212 1213 fsok->fsok_tsize = htonl(fsok->fsok_tsize); 1214 fsok->fsok_bsize = htonl(fsok->fsok_bsize); 1215 fsok->fsok_blocks = htonl(fsok->fsok_blocks); 1216 fsok->fsok_bfree = htonl(fsok->fsok_bfree); 1217 fsok->fsok_bavail = htonl(fsok->fsok_bavail); 1218 return (TRUE); 1219 } 1220 #endif 1221 1222 static struct xdr_discrim statfs_discrim[2] = { 1223 { NFS_OK, xdr_fsok }, 1224 { __dontcare__, NULL_xdrproc_t } 1225 }; 1226 1227 /* 1228 * Results of statfs operation 1229 */ 1230 bool_t 1231 xdr_statfs(XDR *xdrs, struct nfsstatfs *fs) 1232 { 1233 return (xdr_union(xdrs, (enum_t *)&(fs->fs_status), 1234 (caddr_t)&(fs->fs_fsok), statfs_discrim, xdr_void)); 1235 } 1236 1237 /* 1238 * Results of statfs operation 1239 */ 1240 bool_t 1241 xdr_faststatfs(XDR *xdrs, struct nfsstatfs *fs) 1242 { 1243 #if defined(_LITTLE_ENDIAN) 1244 /* 1245 * we deal with the discriminator; it's an enum 1246 */ 1247 if (!xdr_fastenum(xdrs, (enum_t *)&fs->fs_status)) 1248 return (FALSE); 1249 1250 if (fs->fs_status == NFS_OK) 1251 return (xdr_fastfsok(xdrs, &fs->fs_fsok)); 1252 #elif defined(_BIG_ENDIAN) 1253 if (fs->fs_status == NFS_OK) 1254 return (TRUE); 1255 #endif 1256 return (xdr_fastshorten(xdrs, sizeof (*fs))); 1257 } 1258 1259 #ifdef _LITTLE_ENDIAN 1260 /* 1261 * XDR enumerations 1262 */ 1263 #ifndef lint 1264 static enum sizecheck { SIZEVAL } sizecheckvar; /* used to find the size of */ 1265 /* an enum */ 1266 #endif 1267 bool_t 1268 xdr_fastenum(XDR *xdrs, enum_t *ep) 1269 { 1270 if (xdrs->x_op == XDR_FREE) 1271 return (TRUE); 1272 if (xdrs->x_op == XDR_DECODE) 1273 return (FALSE); 1274 1275 #ifndef lint 1276 /* 1277 * enums are treated as ints 1278 */ 1279 if (sizeof (sizecheckvar) == sizeof (int32_t)) { 1280 *ep = (enum_t)htonl((int32_t)(*ep)); 1281 } else if (sizeof (sizecheckvar) == sizeof (short)) { 1282 *ep = (enum_t)htons((short)(*ep)); 1283 } else { 1284 return (FALSE); 1285 } 1286 return (TRUE); 1287 #else 1288 (void) (xdr_short(xdrs, (short *)ep)); 1289 return (xdr_int(xdrs, (int *)ep)); 1290 #endif 1291 } 1292 #endif 1293 1294 static bool_t 1295 xdr_fastshorten(XDR *xdrs, uint_t ressize) 1296 { 1297 uint_t curpos; 1298 1299 curpos = XDR_GETPOS(xdrs); 1300 ressize -= BYTES_PER_XDR_UNIT; 1301 curpos -= ressize; 1302 return (XDR_SETPOS(xdrs, curpos)); 1303 } 1304