nfsm_subs.h revision 1.41
1/* $NetBSD: nfsm_subs.h,v 1.41 2005/05/29 20:58:13 christos Exp $ */ 2 3/* 4 * Copyright (c) 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Rick Macklem at The University of Guelph. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)nfsm_subs.h 8.2 (Berkeley) 3/30/95 35 */ 36 37 38#ifndef _NFS_NFSM_SUBS_H_ 39#define _NFS_NFSM_SUBS_H_ 40 41 42/* 43 * These macros do strange and peculiar things to mbuf chains for 44 * the assistance of the nfs code. To attempt to use them for any 45 * other purpose will be dangerous. (they make weird assumptions) 46 */ 47 48/* 49 * First define what the actual subs. return 50 */ 51 52#define M_HASCL(m) ((m)->m_flags & M_EXT) 53#define NFSMADV(m, s) (m)->m_data += (s) 54#define NFSMSIZ(m) ((M_HASCL(m)) ? (m)->m_ext.ext_size : \ 55 (((m)->m_flags & M_PKTHDR) ? MHLEN : MLEN)) 56 57/* 58 * Now for the macros that do the simple stuff and call the functions 59 * for the hard stuff. 60 * These macros use several vars. declared in nfsm_reqhead and these 61 * vars. must not be used elsewhere unless you are careful not to corrupt 62 * them. The vars. starting with pN and tN (N=1,2,3,..) are temporaries 63 * that may be used so long as the value is not expected to retained 64 * after a macro. 65 * I know, this is kind of dorkey, but it makes the actual op functions 66 * fairly clean and deals with the mess caused by the xdr discriminating 67 * unions. 68 */ 69 70#define nfsm_build(a,c,s) \ 71 { if ((s) > M_TRAILINGSPACE(mb)) { \ 72 struct mbuf *mb2; \ 73 mb2 = m_get(M_WAIT, MT_DATA); \ 74 MCLAIM(mb2, &nfs_mowner); \ 75 if ((s) > MLEN) \ 76 panic("build > MLEN"); \ 77 mb->m_next = mb2; \ 78 mb = mb2; \ 79 mb->m_len = 0; \ 80 bpos = mtod(mb, caddr_t); \ 81 } \ 82 (a) = (c)(bpos); \ 83 mb->m_len += (s); \ 84 bpos += (s); } 85 86#define nfsm_aligned(p) ALIGNED_POINTER(p,u_int32_t) 87 88#define nfsm_dissect(a, c, s) \ 89 { t1 = mtod(md, caddr_t)+md->m_len-dpos; \ 90 if (t1 >= (s) && nfsm_aligned(dpos)) { \ 91 (a) = (c)(dpos); \ 92 dpos += (s); \ 93 } else if ((t1 = nfsm_disct(&md, &dpos, (s), t1, &cp2)) != 0){ \ 94 error = t1; \ 95 m_freem(mrep); \ 96 goto nfsmout; \ 97 } else { \ 98 (a) = (c)cp2; \ 99 } } 100 101#define nfsm_fhtom(n, v3) \ 102 { if (v3) { \ 103 t2 = nfsm_rndup((n)->n_fhsize) + NFSX_UNSIGNED; \ 104 if (t2 <= M_TRAILINGSPACE(mb)) { \ 105 nfsm_build(tl, u_int32_t *, t2); \ 106 *tl++ = txdr_unsigned((n)->n_fhsize); \ 107 *(tl + ((t2>>2) - 2)) = 0; \ 108 memcpy((caddr_t)tl,(caddr_t)(n)->n_fhp, \ 109 (n)->n_fhsize); \ 110 } else if ((t2 = nfsm_strtmbuf(&mb, &bpos, \ 111 (caddr_t)(n)->n_fhp, \ 112 (n)->n_fhsize)) != 0) { \ 113 error = t2; \ 114 m_freem(mreq); \ 115 goto nfsmout; \ 116 } \ 117 } else { \ 118 nfsm_build(cp, caddr_t, NFSX_V2FH); \ 119 memcpy(cp, (caddr_t)(n)->n_fhp, NFSX_V2FH); \ 120 } } 121 122#define nfsm_srvfhtom(f, v3) \ 123 { if (v3) { \ 124 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_V3FH); \ 125 *tl++ = txdr_unsigned(NFSX_V3FH); \ 126 memcpy((caddr_t)tl, (caddr_t)(f), NFSX_V3FH); \ 127 } else { \ 128 nfsm_build(cp, caddr_t, NFSX_V2FH); \ 129 memcpy(cp, (caddr_t)(f), NFSX_V2FH); \ 130 } } 131 132#define nfsm_srvpostop_fh(f) \ 133 { nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED + NFSX_V3FH); \ 134 *tl++ = nfs_true; \ 135 *tl++ = txdr_unsigned(NFSX_V3FH); \ 136 memcpy((caddr_t)tl, (caddr_t)(f), NFSX_V3FH); \ 137 } 138 139/* 140 * nfsm_mtofh: dissect a "resulted obj" part of create-like operations 141 * like mkdir. 142 * 143 * for nfsv3, dissect post_op_fh3 and following post_op_attr. 144 * for nfsv2, dissect fhandle and following fattr. 145 * 146 * d: (IN) the vnode of the parent directry. 147 * v: (OUT) the corresponding vnode (we allocate one if needed) 148 * v3: (IN) true for nfsv3. 149 * f: (OUT) true if we got valid filehandle. always true for nfsv2. 150 */ 151 152#define nfsm_mtofh(d, v, v3, f) \ 153 { struct nfsnode *ttnp; nfsfh_t *ttfhp; int ttfhsize; \ 154 int hasattr = 0; \ 155 if (v3) { \ 156 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 157 (f) = fxdr_unsigned(int, *tl); \ 158 } else { \ 159 (f) = 1; \ 160 hasattr = 1; \ 161 } \ 162 if (f) { \ 163 nfsm_getfh(ttfhp, ttfhsize, (v3)); \ 164 if ((t1 = nfs_nget((d)->v_mount, ttfhp, ttfhsize, \ 165 &ttnp)) != 0) { \ 166 error = t1; \ 167 m_freem(mrep); \ 168 goto nfsmout; \ 169 } \ 170 (v) = NFSTOV(ttnp); \ 171 } \ 172 if (v3) { \ 173 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 174 if (f) \ 175 hasattr = fxdr_unsigned(int, *tl); \ 176 else if (fxdr_unsigned(int, *tl)) \ 177 nfsm_adv(NFSX_V3FATTR); \ 178 } \ 179 if (f && hasattr) \ 180 nfsm_loadattr((v), (struct vattr *)0, 0); \ 181 } 182 183/* 184 * nfsm_getfh: dissect a filehandle. 185 * 186 * f: (OUT) a filehandle. 187 * s: (OUT) size of the filehandle in bytes. 188 * v3: (IN) true if nfsv3. 189 */ 190 191#define nfsm_getfh(f, s, v3) \ 192 { if (v3) { \ 193 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 194 if (((s) = fxdr_unsigned(int, *tl)) <= 0 || \ 195 (s) > NFSX_V3FHMAX) { \ 196 m_freem(mrep); \ 197 error = EBADRPC; \ 198 goto nfsmout; \ 199 } \ 200 } else \ 201 (s) = NFSX_V2FH; \ 202 nfsm_dissect((f), nfsfh_t *, nfsm_rndup(s)); } 203 204#define nfsm_loadattr(v, a, flags) \ 205 { struct vnode *ttvp = (v); \ 206 if ((t1 = nfsm_loadattrcache(&ttvp, &md, &dpos, (a), (flags))) \ 207 != 0) { \ 208 error = t1; \ 209 m_freem(mrep); \ 210 goto nfsmout; \ 211 } \ 212 (v) = ttvp; } 213 214/* 215 * nfsm_postop_attr: process nfsv3 post_op_attr 216 * 217 * dissect post_op_attr. if we got a one, 218 * call nfsm_loadattrcache to update attribute cache. 219 * 220 * v: (IN/OUT) the corresponding vnode 221 * f: (OUT) true if we got valid attribute 222 * flags: (IN) flags for nfsm_loadattrcache 223 */ 224 225#define nfsm_postop_attr(v, f, flags) \ 226 { struct vnode *ttvp = (v); \ 227 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 228 if (((f) = fxdr_unsigned(int, *tl)) != 0) { \ 229 if ((t1 = nfsm_loadattrcache(&ttvp, &md, &dpos, \ 230 (struct vattr *)0, (flags))) != 0) { \ 231 error = t1; \ 232 (f) = 0; \ 233 m_freem(mrep); \ 234 goto nfsmout; \ 235 } \ 236 (v) = ttvp; \ 237 } } 238 239/* 240 * nfsm_wcc_data: process nfsv3 wcc_data 241 * 242 * dissect pre_op_attr and then let nfsm_postop_attr dissect post_op_attr. 243 * 244 * v: (IN/OUT) the corresponding vnode 245 * f: (IN/OUT) 246 * NFSV3_WCCRATTR return true if we got valid post_op_attr. 247 * NFSV3_WCCCHK return true if pre_op_attr's mtime is the same 248 * as our n_mtime. (ie. our cache isn't stale.) 249 * flags: (IN) flags for nfsm_loadattrcache 250 * docheck: (IN) TRUE if timestamp change is expected 251 */ 252 253/* Used as (f) for nfsm_wcc_data() */ 254#define NFSV3_WCCRATTR 0 255#define NFSV3_WCCCHK 1 256 257#define nfsm_wcc_data(v, f, flags, docheck) \ 258 { int ttattrf, ttretf = 0, renewctime = 0, renewnctime = 0; \ 259 struct timespec ctime, mtime; \ 260 struct nfsnode *nfsp = VTONFS(v); \ 261 boolean_t haspreopattr = FALSE; \ 262 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 263 if (*tl == nfs_true) { \ 264 haspreopattr = TRUE; \ 265 nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED); \ 266 fxdr_nfsv3time(tl + 2, &mtime); \ 267 fxdr_nfsv3time(tl + 4, &ctime); \ 268 if (nfsp->n_ctime == ctime.tv_sec) \ 269 renewctime = 1; \ 270 if ((v)->v_type == VDIR) { \ 271 if (timespeccmp(&nfsp->n_nctime, &ctime, ==)) \ 272 renewnctime = 1; \ 273 } \ 274 if (f) { \ 275 ttretf = timespeccmp(&nfsp->n_mtime, &mtime, ==);\ 276 } \ 277 } \ 278 nfsm_postop_attr((v), ttattrf, (flags)); \ 279 nfsp = VTONFS(v); \ 280 if (ttattrf) { \ 281 if (haspreopattr && \ 282 nfs_check_wccdata(nfsp, &ctime, &mtime, (docheck))) \ 283 renewctime = renewnctime = ttretf = 0; \ 284 if (renewctime) \ 285 nfsp->n_ctime = nfsp->n_vattr->va_ctime.tv_sec; \ 286 if (renewnctime) \ 287 nfsp->n_nctime = nfsp->n_vattr->va_ctime; \ 288 } \ 289 if (f) { \ 290 (f) = ttretf; \ 291 } else { \ 292 (f) = ttattrf; \ 293 } } 294 295/* If full is true, set all fields, otherwise just set mode and time fields */ 296#define nfsm_v3attrbuild(a, full) \ 297 { if ((a)->va_mode != (mode_t)VNOVAL) { \ 298 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \ 299 *tl++ = nfs_true; \ 300 *tl = txdr_unsigned((a)->va_mode); \ 301 } else { \ 302 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 303 *tl = nfs_false; \ 304 } \ 305 if ((full) && (a)->va_uid != (uid_t)VNOVAL) { \ 306 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \ 307 *tl++ = nfs_true; \ 308 *tl = txdr_unsigned((a)->va_uid); \ 309 } else { \ 310 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 311 *tl = nfs_false; \ 312 } \ 313 if ((full) && (a)->va_gid != (gid_t)VNOVAL) { \ 314 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \ 315 *tl++ = nfs_true; \ 316 *tl = txdr_unsigned((a)->va_gid); \ 317 } else { \ 318 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 319 *tl = nfs_false; \ 320 } \ 321 if ((full) && (a)->va_size != VNOVAL) { \ 322 nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED); \ 323 *tl++ = nfs_true; \ 324 txdr_hyper((a)->va_size, tl); \ 325 } else { \ 326 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 327 *tl = nfs_false; \ 328 } \ 329 if ((a)->va_atime.tv_sec != VNOVAL) { \ 330 if ((a)->va_atime.tv_sec != time.tv_sec) { \ 331 nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED); \ 332 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); \ 333 txdr_nfsv3time(&(a)->va_atime, tl); \ 334 } else { \ 335 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 336 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); \ 337 } \ 338 } else { \ 339 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 340 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); \ 341 } \ 342 if ((a)->va_mtime.tv_sec != VNOVAL) { \ 343 if ((a)->va_mtime.tv_sec != time.tv_sec) { \ 344 nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED); \ 345 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); \ 346 txdr_nfsv3time(&(a)->va_mtime, tl); \ 347 } else { \ 348 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 349 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); \ 350 } \ 351 } else { \ 352 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \ 353 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); \ 354 } \ 355 } 356 357 358#define nfsm_strsiz(s,m) \ 359 { nfsm_dissect(tl,uint32_t *,NFSX_UNSIGNED); \ 360 if (((s) = fxdr_unsigned(uint32_t,*tl)) > (m)) { \ 361 m_freem(mrep); \ 362 error = EBADRPC; \ 363 goto nfsmout; \ 364 } } 365 366#define nfsm_srvnamesiz(s) \ 367 { nfsm_dissect(tl,uint32_t *,NFSX_UNSIGNED); \ 368 if (((s) = fxdr_unsigned(uint32_t,*tl)) > NFS_MAXNAMLEN) \ 369 error = NFSERR_NAMETOL; \ 370 if (error) \ 371 nfsm_reply(0); \ 372 } 373 374#define nfsm_mtouio(p,s) \ 375 if ((s) > 0 && \ 376 (t1 = nfsm_mbuftouio(&md,(p),(s),&dpos)) != 0) { \ 377 error = t1; \ 378 m_freem(mrep); \ 379 goto nfsmout; \ 380 } 381 382#define nfsm_uiotom(p,s) \ 383 if ((t1 = nfsm_uiotombuf((p),&mb,(s),&bpos)) != 0) { \ 384 error = t1; \ 385 m_freem(mreq); \ 386 goto nfsmout; \ 387 } 388 389#define nfsm_reqhead(n,a,s) \ 390 mb = mreq = nfsm_reqh((n),(a),(s),&bpos) 391 392#define nfsm_reqdone m_freem(mrep); \ 393 nfsmout: 394 395#define nfsm_rndup(a) (((a)+3)&(~0x3)) 396#define nfsm_padlen(a) (nfsm_rndup(a) - (a)) 397 398#define nfsm_request1(v, t, p, c, rexmitp) \ 399 if ((error = nfs_request((v), mreq, (t), (p), \ 400 (c), &mrep, &md, &dpos, (rexmitp))) != 0) { \ 401 if (error & NFSERR_RETERR) \ 402 error &= ~NFSERR_RETERR; \ 403 else \ 404 goto nfsmout; \ 405 } 406 407#define nfsm_request(v, t, p, c) nfsm_request1((v), (t), (p), (c), NULL) 408 409#define nfsm_strtom(a,s,m) \ 410 if ((s) > (m)) { \ 411 m_freem(mreq); \ 412 error = ENAMETOOLONG; \ 413 goto nfsmout; \ 414 } \ 415 t2 = nfsm_rndup(s)+NFSX_UNSIGNED; \ 416 if (t2 <= M_TRAILINGSPACE(mb)) { \ 417 nfsm_build(tl,u_int32_t *,t2); \ 418 *tl++ = txdr_unsigned(s); \ 419 *(tl+((t2>>2)-2)) = 0; \ 420 memcpy((caddr_t)tl, (const char *)(a), (s)); \ 421 } else if ((t2 = nfsm_strtmbuf(&mb, &bpos, (a), (s))) != 0) { \ 422 error = t2; \ 423 m_freem(mreq); \ 424 goto nfsmout; \ 425 } 426 427#define nfsm_srvdone \ 428 nfsmout: \ 429 return(error) 430 431#define nfsm_reply(s) \ 432 { \ 433 nfsd->nd_repstat = error; \ 434 if (error && !(nfsd->nd_flag & ND_NFSV3)) \ 435 (void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \ 436 mrq, &mb, &bpos); \ 437 else \ 438 (void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \ 439 mrq, &mb, &bpos); \ 440 if (mrep != NULL) { \ 441 m_freem(mrep); \ 442 mrep = NULL; \ 443 } \ 444 mreq = *mrq; \ 445 if (error && (!(nfsd->nd_flag & ND_NFSV3) || \ 446 error == EBADRPC)) \ 447 return(0); \ 448 } 449 450#define nfsm_writereply(s, v3) \ 451 { \ 452 nfsd->nd_repstat = error; \ 453 if (error && !(v3)) \ 454 (void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \ 455 &mreq, &mb, &bpos); \ 456 else \ 457 (void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \ 458 &mreq, &mb, &bpos); \ 459 } 460 461#define nfsm_adv(s) \ 462 { t1 = mtod(md, caddr_t)+md->m_len-dpos; \ 463 if (t1 >= (s)) { \ 464 dpos += (s); \ 465 } else if ((t1 = nfs_adv(&md, &dpos, (s), t1)) != 0) { \ 466 error = t1; \ 467 m_freem(mrep); \ 468 goto nfsmout; \ 469 } } 470 471#define nfsm_srvmtofh(f) \ 472 { int fhlen = NFSX_V3FH; \ 473 if (nfsd->nd_flag & ND_NFSV3) { \ 474 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 475 fhlen = fxdr_unsigned(int, *tl); \ 476 if (fhlen == 0) { \ 477 memset((caddr_t)(f), 0, NFSX_V3FH); \ 478 } else if (fhlen != NFSX_V3FH) { \ 479 error = EBADRPC; \ 480 nfsm_reply(0); \ 481 } \ 482 } \ 483 if (fhlen != 0) { \ 484 nfsm_dissect(tl, u_int32_t *, NFSX_V3FH); \ 485 memcpy( (caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \ 486 if ((nfsd->nd_flag & ND_NFSV3) == 0) \ 487 nfsm_adv(NFSX_V2FH - NFSX_V3FH); \ 488 } \ 489 } 490 491#define nfsm_clget \ 492 if (bp >= be) { \ 493 if (mp == mb) \ 494 mp->m_len += bp-bpos; \ 495 mp = m_get(M_WAIT, MT_DATA); \ 496 MCLAIM(mp, &nfs_mowner); \ 497 m_clget(mp, M_WAIT); \ 498 mp->m_len = NFSMSIZ(mp); \ 499 mp2->m_next = mp; \ 500 mp2 = mp; \ 501 bp = mtod(mp, caddr_t); \ 502 be = bp+mp->m_len; \ 503 } \ 504 tl = (u_int32_t *)bp 505 506#define nfsm_srvfillattr(a, f) \ 507 nfsm_srvfattr(nfsd, (a), (f)) 508 509#define nfsm_srvwcc_data(br, b, ar, a) \ 510 nfsm_srvwcc(nfsd, (br), (b), (ar), (a), &mb, &bpos) 511 512#define nfsm_srvpostop_attr(r, a) \ 513 nfsm_srvpostopattr(nfsd, (r), (a), &mb, &bpos) 514 515#define nfsm_srvsattr(a) \ 516 { nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 517 if (*tl == nfs_true) { \ 518 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 519 (a)->va_mode = nfstov_mode(*tl); \ 520 } \ 521 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 522 if (*tl == nfs_true) { \ 523 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 524 (a)->va_uid = fxdr_unsigned(uid_t, *tl); \ 525 } \ 526 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 527 if (*tl == nfs_true) { \ 528 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 529 (a)->va_gid = fxdr_unsigned(gid_t, *tl); \ 530 } \ 531 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 532 if (*tl == nfs_true) { \ 533 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \ 534 (a)->va_size = fxdr_hyper(tl); \ 535 } \ 536 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 537 switch (fxdr_unsigned(int, *tl)) { \ 538 case NFSV3SATTRTIME_TOCLIENT: \ 539 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \ 540 fxdr_nfsv3time(tl, &(a)->va_atime); \ 541 break; \ 542 case NFSV3SATTRTIME_TOSERVER: \ 543 (a)->va_atime.tv_sec = time.tv_sec; \ 544 (a)->va_atime.tv_nsec = time.tv_usec * 1000; \ 545 (a)->va_vaflags |= VA_UTIMES_NULL; \ 546 break; \ 547 }; \ 548 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \ 549 switch (fxdr_unsigned(int, *tl)) { \ 550 case NFSV3SATTRTIME_TOCLIENT: \ 551 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \ 552 fxdr_nfsv3time(tl, &(a)->va_mtime); \ 553 (a)->va_vaflags &= ~VA_UTIMES_NULL; \ 554 break; \ 555 case NFSV3SATTRTIME_TOSERVER: \ 556 (a)->va_mtime.tv_sec = time.tv_sec; \ 557 (a)->va_mtime.tv_nsec = time.tv_usec * 1000; \ 558 (a)->va_vaflags |= VA_UTIMES_NULL; \ 559 break; \ 560 }; } 561 562#endif 563