This source file includes following definitions.
- nfsrv3_access
- nfsrv_getattr
- nfsrv_setattr
- nfsrv_lookup
- nfsrv_readlink
- nfsrv_read
- nfsrv_write
- nfsrv_writegather
- nfsrvw_coalesce
- nfsrv_create
- nfsrv_mknod
- nfsrv_remove
- nfsrv_rename
- nfsrv_link
- nfsrv_symlink
- nfsrv_mkdir
- nfsrv_rmdir
- nfsrv_readdir
- nfsrv_readdirplus
- nfsrv_commit
- nfsrv_statfs
- nfsrv_fsinfo
- nfsrv_pathconf
- nfsrv_null
- nfsrv_noop
- nfsrv_access
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58 #include <sys/param.h>
59 #include <sys/systm.h>
60 #include <sys/proc.h>
61 #include <sys/file.h>
62 #include <sys/namei.h>
63 #include <sys/vnode.h>
64 #include <sys/mount.h>
65 #include <sys/socket.h>
66 #include <sys/socketvar.h>
67 #include <sys/mbuf.h>
68 #include <sys/dirent.h>
69 #include <sys/stat.h>
70 #include <sys/kernel.h>
71 #include <sys/pool.h>
72 #include <ufs/ufs/dir.h>
73
74 #include <uvm/uvm_extern.h>
75
76 #include <nfs/nfsproto.h>
77 #include <nfs/rpcv2.h>
78 #include <nfs/nfs.h>
79 #include <nfs/xdr_subs.h>
80 #include <nfs/nfsm_subs.h>
81 #include <nfs/nfs_var.h>
82
83
84 extern u_int32_t nfs_xdrneg1;
85 extern u_int32_t nfs_false, nfs_true;
86 extern enum vtype nv3tov_type[8];
87 extern struct nfsstats nfsstats;
88 extern nfstype nfsv2_type[9];
89 extern nfstype nfsv3_type[9];
90 int nfsrvw_procrastinate = NFS_GATHERDELAY * 1000;
91
92
93
94
95 int
96 nfsrv3_access(nfsd, slp, procp, mrq)
97 struct nfsrv_descript *nfsd;
98 struct nfssvc_sock *slp;
99 struct proc *procp;
100 struct mbuf **mrq;
101 {
102 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
103 struct mbuf *nam = nfsd->nd_nam;
104 caddr_t dpos = nfsd->nd_dpos;
105 struct ucred *cred = &nfsd->nd_cr;
106 struct vnode *vp;
107 nfsfh_t nfh;
108 fhandle_t *fhp;
109 u_int32_t *tl;
110 int32_t t1;
111 caddr_t bpos;
112 int error = 0, rdonly, getret;
113 char *cp2;
114 struct mbuf *mb, *mreq, *mb2;
115 struct vattr va;
116 u_long testmode, nfsmode;
117 u_quad_t frev;
118
119 fhp = &nfh.fh_generic;
120 nfsm_srvmtofh(fhp);
121 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
122 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
123 (nfsd->nd_flag & ND_KERBAUTH));
124 if (error) {
125 nfsm_reply(NFSX_UNSIGNED);
126 nfsm_srvpostop_attr(1, (struct vattr *)0);
127 return (0);
128 }
129 nfsmode = fxdr_unsigned(u_int32_t, *tl);
130 if ((nfsmode & NFSV3ACCESS_READ) &&
131 nfsrv_access(vp, VREAD, cred, rdonly, procp, 0))
132 nfsmode &= ~NFSV3ACCESS_READ;
133 if (vp->v_type == VDIR)
134 testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
135 NFSV3ACCESS_DELETE);
136 else
137 testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
138 if ((nfsmode & testmode) &&
139 nfsrv_access(vp, VWRITE, cred, rdonly, procp, 0))
140 nfsmode &= ~testmode;
141 if (vp->v_type == VDIR)
142 testmode = NFSV3ACCESS_LOOKUP;
143 else
144 testmode = NFSV3ACCESS_EXECUTE;
145 if ((nfsmode & testmode) &&
146 nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0))
147 nfsmode &= ~testmode;
148 getret = VOP_GETATTR(vp, &va, cred, procp);
149 vput(vp);
150 nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED);
151 nfsm_srvpostop_attr(getret, &va);
152 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
153 *tl = txdr_unsigned(nfsmode);
154 nfsm_srvdone;
155 }
156
157
158
159
160 int
161 nfsrv_getattr(nfsd, slp, procp, mrq)
162 struct nfsrv_descript *nfsd;
163 struct nfssvc_sock *slp;
164 struct proc *procp;
165 struct mbuf **mrq;
166 {
167 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
168 struct mbuf *nam = nfsd->nd_nam;
169 caddr_t dpos = nfsd->nd_dpos;
170 struct ucred *cred = &nfsd->nd_cr;
171 struct nfs_fattr *fp;
172 struct vattr va;
173 struct vnode *vp;
174 nfsfh_t nfh;
175 fhandle_t *fhp;
176 u_int32_t *tl;
177 int32_t t1;
178 caddr_t bpos;
179 int error = 0, rdonly;
180 char *cp2;
181 struct mbuf *mb, *mb2, *mreq;
182 u_quad_t frev;
183
184 fhp = &nfh.fh_generic;
185 nfsm_srvmtofh(fhp);
186 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
187 (nfsd->nd_flag & ND_KERBAUTH));
188 if (error) {
189 nfsm_reply(0);
190 return (0);
191 }
192 error = VOP_GETATTR(vp, &va, cred, procp);
193 vput(vp);
194 nfsm_reply(NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
195 if (error)
196 return (0);
197 nfsm_build(fp, struct nfs_fattr *, NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
198 nfsm_srvfillattr(&va, fp);
199 nfsm_srvdone;
200 }
201
202
203
204
205 int
206 nfsrv_setattr(nfsd, slp, procp, mrq)
207 struct nfsrv_descript *nfsd;
208 struct nfssvc_sock *slp;
209 struct proc *procp;
210 struct mbuf **mrq;
211 {
212 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
213 struct mbuf *nam = nfsd->nd_nam;
214 caddr_t dpos = nfsd->nd_dpos;
215 struct ucred *cred = &nfsd->nd_cr;
216 struct vattr va, preat;
217 struct nfsv2_sattr *sp;
218 struct nfs_fattr *fp;
219 struct vnode *vp;
220 nfsfh_t nfh;
221 fhandle_t *fhp;
222 u_int32_t *tl;
223 int32_t t1;
224 caddr_t bpos;
225 int error = 0, rdonly, preat_ret = 1, postat_ret = 1;
226 int v3 = (nfsd->nd_flag & ND_NFSV3), gcheck = 0;
227 char *cp2;
228 struct mbuf *mb, *mb2, *mreq;
229 u_quad_t frev;
230 struct timespec guard;
231
232 fhp = &nfh.fh_generic;
233 nfsm_srvmtofh(fhp);
234 VATTR_NULL(&va);
235 if (v3) {
236 va.va_vaflags |= VA_UTIMES_NULL;
237 nfsm_srvsattr(&va);
238 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
239 gcheck = fxdr_unsigned(int, *tl);
240 if (gcheck) {
241 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
242 fxdr_nfsv3time(tl, &guard);
243 }
244 } else {
245 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
246
247
248
249
250
251
252
253 if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
254 va.va_mode = nfstov_mode(sp->sa_mode);
255 if (sp->sa_uid != nfs_xdrneg1)
256 va.va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
257 if (sp->sa_gid != nfs_xdrneg1)
258 va.va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
259 if (sp->sa_size != nfs_xdrneg1)
260 va.va_size = fxdr_unsigned(u_quad_t, sp->sa_size);
261 if (sp->sa_atime.nfsv2_sec != nfs_xdrneg1) {
262 #ifdef notyet
263 fxdr_nfsv2time(&sp->sa_atime, &va.va_atime);
264 #else
265 va.va_atime.tv_sec =
266 fxdr_unsigned(u_int32_t,sp->sa_atime.nfsv2_sec);
267 va.va_atime.tv_nsec = 0;
268 #endif
269 }
270 if (sp->sa_mtime.nfsv2_sec != nfs_xdrneg1)
271 fxdr_nfsv2time(&sp->sa_mtime, &va.va_mtime);
272
273 }
274
275
276
277
278 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
279 (nfsd->nd_flag & ND_KERBAUTH));
280 if (error) {
281 nfsm_reply(2 * NFSX_UNSIGNED);
282 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, &va);
283 return (0);
284 }
285 if (v3) {
286 error = preat_ret = VOP_GETATTR(vp, &preat, cred, procp);
287 if (!error && gcheck &&
288 (preat.va_ctime.tv_sec != guard.tv_sec ||
289 preat.va_ctime.tv_nsec != guard.tv_nsec))
290 error = NFSERR_NOT_SYNC;
291 if (error) {
292 vput(vp);
293 nfsm_reply(NFSX_WCCDATA(v3));
294 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, &va);
295 return (0);
296 }
297 }
298
299
300
301
302
303 if (va.va_size == ((u_quad_t)((quad_t) -1))) {
304 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
305 error = EROFS;
306 goto out;
307 }
308 } else {
309 if (vp->v_type == VDIR) {
310 error = EISDIR;
311 goto out;
312 } else if ((error = nfsrv_access(vp, VWRITE, cred, rdonly,
313 procp, 0)) != 0)
314 goto out;
315 }
316 error = VOP_SETATTR(vp, &va, cred, procp);
317 postat_ret = VOP_GETATTR(vp, &va, cred, procp);
318 if (!error)
319 error = postat_ret;
320 out:
321 vput(vp);
322 nfsm_reply(NFSX_WCCORFATTR(v3));
323 if (v3) {
324 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, &va);
325 return (0);
326 } else {
327 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
328 nfsm_srvfillattr(&va, fp);
329 }
330 nfsm_srvdone;
331 }
332
333
334
335
336 int
337 nfsrv_lookup(nfsd, slp, procp, mrq)
338 struct nfsrv_descript *nfsd;
339 struct nfssvc_sock *slp;
340 struct proc *procp;
341 struct mbuf **mrq;
342 {
343 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
344 struct mbuf *nam = nfsd->nd_nam;
345 caddr_t dpos = nfsd->nd_dpos;
346 struct ucred *cred = &nfsd->nd_cr;
347 struct nfs_fattr *fp;
348 struct nameidata nd;
349 struct vnode *vp, *dirp;
350 nfsfh_t nfh;
351 fhandle_t *fhp;
352 caddr_t cp;
353 u_int32_t *tl;
354 int32_t t1;
355 caddr_t bpos;
356 int error = 0, len, dirattr_ret = 1;
357 int v3 = (nfsd->nd_flag & ND_NFSV3);
358 char *cp2;
359 struct mbuf *mb, *mb2, *mreq;
360 struct vattr va, dirattr;
361 u_quad_t frev;
362
363 fhp = &nfh.fh_generic;
364 nfsm_srvmtofh(fhp);
365 nfsm_srvnamesiz(len);
366 nd.ni_cnd.cn_cred = cred;
367 nd.ni_cnd.cn_nameiop = LOOKUP;
368 nd.ni_cnd.cn_flags = LOCKLEAF | SAVESTART;
369 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
370 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
371 if (dirp) {
372 if (v3)
373 dirattr_ret = VOP_GETATTR(dirp, &dirattr, cred,
374 procp);
375 vrele(dirp);
376 }
377 if (error) {
378 nfsm_reply(NFSX_POSTOPATTR(v3));
379 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
380 return (0);
381 }
382 vrele(nd.ni_startdir);
383 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
384 vp = nd.ni_vp;
385 bzero((caddr_t)fhp, sizeof(nfh));
386 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
387 error = VFS_VPTOFH(vp, &fhp->fh_fid);
388 if (!error)
389 error = VOP_GETATTR(vp, &va, cred, procp);
390 vput(vp);
391 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPORFATTR(v3) + NFSX_POSTOPATTR(v3));
392 if (error) {
393 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
394 return (0);
395 }
396 nfsm_srvfhtom(fhp, v3);
397 if (v3) {
398 nfsm_srvpostop_attr(0, &va);
399 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
400 } else {
401 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
402 nfsm_srvfillattr(&va, fp);
403 }
404 nfsm_srvdone;
405 }
406
407
408
409
410 int
411 nfsrv_readlink(nfsd, slp, procp, mrq)
412 struct nfsrv_descript *nfsd;
413 struct nfssvc_sock *slp;
414 struct proc *procp;
415 struct mbuf **mrq;
416 {
417 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
418 struct mbuf *nam = nfsd->nd_nam;
419 caddr_t dpos = nfsd->nd_dpos;
420 struct ucred *cred = &nfsd->nd_cr;
421 struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
422 struct iovec *ivp = iv;
423 struct mbuf *mp;
424 u_int32_t *tl;
425 int32_t t1;
426 caddr_t bpos;
427 int error = 0, rdonly, i, tlen, len, getret;
428 int v3 = (nfsd->nd_flag & ND_NFSV3);
429 char *cp2;
430 struct mbuf *mb, *mb2, *mp2 = NULL, *mp3 = NULL, *mreq;
431 struct vnode *vp;
432 struct vattr attr;
433 nfsfh_t nfh;
434 fhandle_t *fhp;
435 struct uio io, *uiop = &io;
436 u_quad_t frev;
437
438 fhp = &nfh.fh_generic;
439 nfsm_srvmtofh(fhp);
440 len = 0;
441 i = 0;
442 while (len < NFS_MAXPATHLEN) {
443 MGET(mp, M_WAIT, MT_DATA);
444 MCLGET(mp, M_WAIT);
445 mp->m_len = NFSMSIZ(mp);
446 if (len == 0)
447 mp3 = mp2 = mp;
448 else {
449 mp2->m_next = mp;
450 mp2 = mp;
451 }
452 if ((len+mp->m_len) > NFS_MAXPATHLEN) {
453 mp->m_len = NFS_MAXPATHLEN-len;
454 len = NFS_MAXPATHLEN;
455 } else
456 len += mp->m_len;
457 ivp->iov_base = mtod(mp, caddr_t);
458 ivp->iov_len = mp->m_len;
459 i++;
460 ivp++;
461 }
462 uiop->uio_iov = iv;
463 uiop->uio_iovcnt = i;
464 uiop->uio_offset = 0;
465 uiop->uio_resid = len;
466 uiop->uio_rw = UIO_READ;
467 uiop->uio_segflg = UIO_SYSSPACE;
468 uiop->uio_procp = (struct proc *)0;
469 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
470 &rdonly, (nfsd->nd_flag & ND_KERBAUTH));
471 if (error) {
472 m_freem(mp3);
473 nfsm_reply(2 * NFSX_UNSIGNED);
474 nfsm_srvpostop_attr(1, (struct vattr *)0);
475 return (0);
476 }
477 if (vp->v_type != VLNK) {
478 if (v3)
479 error = EINVAL;
480 else
481 error = ENXIO;
482 goto out;
483 }
484 error = VOP_READLINK(vp, uiop, cred);
485 out:
486 getret = VOP_GETATTR(vp, &attr, cred, procp);
487 vput(vp);
488 if (error)
489 m_freem(mp3);
490 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_UNSIGNED);
491 if (v3) {
492 nfsm_srvpostop_attr(getret, &attr);
493 if (error)
494 return (0);
495 }
496 if (uiop->uio_resid > 0) {
497 len -= uiop->uio_resid;
498 tlen = nfsm_rndup(len);
499 nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len);
500 }
501 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
502 *tl = txdr_unsigned(len);
503 mb->m_next = mp3;
504 nfsm_srvdone;
505 }
506
507
508
509
510 int
511 nfsrv_read(nfsd, slp, procp, mrq)
512 struct nfsrv_descript *nfsd;
513 struct nfssvc_sock *slp;
514 struct proc *procp;
515 struct mbuf **mrq;
516 {
517 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
518 struct mbuf *nam = nfsd->nd_nam;
519 caddr_t dpos = nfsd->nd_dpos;
520 struct ucred *cred = &nfsd->nd_cr;
521 struct iovec *iv;
522 struct iovec *iv2;
523 struct mbuf *m;
524 struct nfs_fattr *fp;
525 u_int32_t *tl;
526 int32_t t1;
527 int i;
528 caddr_t bpos;
529 int error = 0, rdonly, cnt, len, left, siz, tlen, getret;
530 int v3 = (nfsd->nd_flag & ND_NFSV3), reqlen;
531 char *cp2;
532 struct mbuf *mb, *mb2, *mreq;
533 struct mbuf *m2;
534 struct vnode *vp;
535 nfsfh_t nfh;
536 fhandle_t *fhp;
537 struct uio io, *uiop = &io;
538 struct vattr va;
539 off_t off;
540 u_quad_t frev;
541
542 fhp = &nfh.fh_generic;
543 nfsm_srvmtofh(fhp);
544 if (v3) {
545 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
546 off = fxdr_hyper(tl);
547 } else {
548 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
549 off = (off_t)fxdr_unsigned(u_int32_t, *tl);
550 }
551 nfsm_srvstrsiz(reqlen, NFS_SRVMAXDATA(nfsd));
552 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
553 &rdonly, (nfsd->nd_flag & ND_KERBAUTH));
554 if (error) {
555 nfsm_reply(2 * NFSX_UNSIGNED);
556 nfsm_srvpostop_attr(1, (struct vattr *)0);
557 return (0);
558 }
559 if (vp->v_type != VREG) {
560 if (v3)
561 error = EINVAL;
562 else
563 error = (vp->v_type == VDIR) ? EISDIR : EACCES;
564 }
565 if (!error) {
566 if ((error = nfsrv_access(vp, VREAD, cred, rdonly, procp, 1)) != 0)
567 error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 1);
568 }
569 getret = VOP_GETATTR(vp, &va, cred, procp);
570 if (!error)
571 error = getret;
572 if (error) {
573 vput(vp);
574 nfsm_reply(NFSX_POSTOPATTR(v3));
575 nfsm_srvpostop_attr(getret, &va);
576 return (0);
577 }
578 if (off >= va.va_size)
579 cnt = 0;
580 else if ((off + reqlen) > va.va_size)
581 cnt = va.va_size - off;
582 else
583 cnt = reqlen;
584 nfsm_reply(NFSX_POSTOPORFATTR(v3) + 3 * NFSX_UNSIGNED+nfsm_rndup(cnt));
585 if (v3) {
586 nfsm_build(tl, u_int32_t *, NFSX_V3FATTR + 4 * NFSX_UNSIGNED);
587 *tl++ = nfs_true;
588 fp = (struct nfs_fattr *)tl;
589 tl += (NFSX_V3FATTR / sizeof (u_int32_t));
590 } else {
591 nfsm_build(tl, u_int32_t *, NFSX_V2FATTR + NFSX_UNSIGNED);
592 fp = (struct nfs_fattr *)tl;
593 tl += (NFSX_V2FATTR / sizeof (u_int32_t));
594 }
595 len = left = nfsm_rndup (cnt);
596 if (cnt > 0) {
597
598
599
600 i = 0;
601 m = m2 = mb;
602 while (left > 0) {
603 siz = min(M_TRAILINGSPACE(m), left);
604 if (siz > 0) {
605 left -= siz;
606 i++;
607 }
608 if (left > 0) {
609 MGET(m, M_WAIT, MT_DATA);
610 MCLGET(m, M_WAIT);
611 m->m_len = 0;
612 m2->m_next = m;
613 m2 = m;
614 }
615 }
616 MALLOC(iv, struct iovec *, i * sizeof (struct iovec),
617 M_TEMP, M_WAITOK);
618 uiop->uio_iov = iv2 = iv;
619 m = mb;
620 left = len;
621 i = 0;
622 while (left > 0) {
623 if (m == NULL)
624 panic("nfsrv_read iov");
625 siz = min(M_TRAILINGSPACE(m), left);
626 if (siz > 0) {
627 iv->iov_base = mtod(m, caddr_t) + m->m_len;
628 iv->iov_len = siz;
629 m->m_len += siz;
630 left -= siz;
631 iv++;
632 i++;
633 }
634 m = m->m_next;
635 }
636 uiop->uio_iovcnt = i;
637 uiop->uio_offset = off;
638 uiop->uio_resid = len;
639 uiop->uio_rw = UIO_READ;
640 uiop->uio_segflg = UIO_SYSSPACE;
641 error = VOP_READ(vp, uiop, IO_NODELOCKED, cred);
642 off = uiop->uio_offset;
643 FREE((caddr_t)iv2, M_TEMP);
644 if (error || (getret = VOP_GETATTR(vp, &va, cred, procp)) != 0){
645 if (!error)
646 error = getret;
647 m_freem(mreq);
648 vput(vp);
649 nfsm_reply(NFSX_POSTOPATTR(v3));
650 nfsm_srvpostop_attr(getret, &va);
651 return (0);
652 }
653 } else
654 uiop->uio_resid = 0;
655 vput(vp);
656 nfsm_srvfillattr(&va, fp);
657 tlen = len - uiop->uio_resid;
658 cnt = cnt < tlen ? cnt : tlen;
659 tlen = nfsm_rndup (cnt);
660 if (len != tlen || tlen != cnt)
661 nfsm_adj(mb, len - tlen, tlen - cnt);
662 if (v3) {
663 *tl++ = txdr_unsigned(cnt);
664 if (len < reqlen)
665 *tl++ = nfs_true;
666 else
667 *tl++ = nfs_false;
668 }
669 *tl = txdr_unsigned(cnt);
670 nfsm_srvdone;
671 }
672
673
674
675
676 int
677 nfsrv_write(nfsd, slp, procp, mrq)
678 struct nfsrv_descript *nfsd;
679 struct nfssvc_sock *slp;
680 struct proc *procp;
681 struct mbuf **mrq;
682 {
683 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
684 struct mbuf *nam = nfsd->nd_nam;
685 caddr_t dpos = nfsd->nd_dpos;
686 struct ucred *cred = &nfsd->nd_cr;
687 struct iovec *ivp;
688 int i, cnt;
689 struct mbuf *mp;
690 struct nfs_fattr *fp;
691 struct iovec *iv;
692 struct vattr va, forat;
693 u_int32_t *tl;
694 int32_t t1;
695 caddr_t bpos;
696 int error = 0, rdonly, len, forat_ret = 1;
697 int ioflags, aftat_ret = 1, retlen, zeroing, adjust;
698 int stable = NFSV3WRITE_FILESYNC;
699 int v3 = (nfsd->nd_flag & ND_NFSV3);
700 char *cp2;
701 struct mbuf *mb, *mb2, *mreq;
702 struct vnode *vp;
703 nfsfh_t nfh;
704 fhandle_t *fhp;
705 struct uio io, *uiop = &io;
706 off_t off;
707 u_quad_t frev;
708
709 if (mrep == NULL) {
710 *mrq = NULL;
711 return (0);
712 }
713 fhp = &nfh.fh_generic;
714 nfsm_srvmtofh(fhp);
715 if (v3) {
716 nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
717 off = fxdr_hyper(tl);
718 tl += 3;
719 stable = fxdr_unsigned(int, *tl++);
720 } else {
721 nfsm_dissect(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
722 off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
723 tl += 2;
724 }
725 retlen = len = fxdr_unsigned(int32_t, *tl);
726 cnt = i = 0;
727
728
729
730
731
732
733 if (len > 0) {
734 zeroing = 1;
735 mp = mrep;
736 while (mp) {
737 if (mp == md) {
738 zeroing = 0;
739 adjust = dpos - mtod(mp, caddr_t);
740 mp->m_len -= adjust;
741 if (mp->m_len > 0 && adjust > 0)
742 NFSMADV(mp, adjust);
743 }
744 if (zeroing)
745 mp->m_len = 0;
746 else if (mp->m_len > 0) {
747 i += mp->m_len;
748 if (i > len) {
749 mp->m_len -= (i - len);
750 zeroing = 1;
751 }
752 if (mp->m_len > 0)
753 cnt++;
754 }
755 mp = mp->m_next;
756 }
757 }
758 if (len > NFS_MAXDATA || len < 0 || i < len) {
759 error = EIO;
760 nfsm_reply(2 * NFSX_UNSIGNED);
761 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
762 return (0);
763 }
764 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
765 &rdonly, (nfsd->nd_flag & ND_KERBAUTH));
766 if (error) {
767 nfsm_reply(2 * NFSX_UNSIGNED);
768 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
769 return (0);
770 }
771 if (v3)
772 forat_ret = VOP_GETATTR(vp, &forat, cred, procp);
773 if (vp->v_type != VREG) {
774 if (v3)
775 error = EINVAL;
776 else
777 error = (vp->v_type == VDIR) ? EISDIR : EACCES;
778 }
779 if (!error) {
780 error = nfsrv_access(vp, VWRITE, cred, rdonly, procp, 1);
781 }
782 if (error) {
783 vput(vp);
784 nfsm_reply(NFSX_WCCDATA(v3));
785 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
786 return (0);
787 }
788
789 if (len > 0) {
790 MALLOC(ivp, struct iovec *, cnt * sizeof (struct iovec), M_TEMP,
791 M_WAITOK);
792 uiop->uio_iov = iv = ivp;
793 uiop->uio_iovcnt = cnt;
794 mp = mrep;
795 while (mp) {
796 if (mp->m_len > 0) {
797 ivp->iov_base = mtod(mp, caddr_t);
798 ivp->iov_len = mp->m_len;
799 ivp++;
800 }
801 mp = mp->m_next;
802 }
803
804
805
806
807
808
809
810
811 if (stable == NFSV3WRITE_UNSTABLE)
812 ioflags = IO_NODELOCKED;
813 else if (stable == NFSV3WRITE_DATASYNC)
814 ioflags = (IO_SYNC | IO_NODELOCKED);
815 else
816 ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
817 uiop->uio_resid = len;
818 uiop->uio_rw = UIO_WRITE;
819 uiop->uio_segflg = UIO_SYSSPACE;
820 uiop->uio_procp = (struct proc *)0;
821 uiop->uio_offset = off;
822 error = VOP_WRITE(vp, uiop, ioflags, cred);
823 nfsstats.srvvop_writes++;
824 FREE((caddr_t)iv, M_TEMP);
825 }
826 aftat_ret = VOP_GETATTR(vp, &va, cred, procp);
827 vput(vp);
828 if (!error)
829 error = aftat_ret;
830 nfsm_reply(NFSX_PREOPATTR(v3) + NFSX_POSTOPORFATTR(v3) +
831 2 * NFSX_UNSIGNED + NFSX_WRITEVERF(v3));
832 if (v3) {
833 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
834 if (error)
835 return (0);
836 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
837 *tl++ = txdr_unsigned(retlen);
838 if (stable == NFSV3WRITE_UNSTABLE)
839 *tl++ = txdr_unsigned(stable);
840 else
841 *tl++ = txdr_unsigned(NFSV3WRITE_FILESYNC);
842
843
844
845
846
847 *tl++ = txdr_unsigned(boottime.tv_sec);
848 *tl = txdr_unsigned(boottime.tv_usec);
849 } else {
850 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
851 nfsm_srvfillattr(&va, fp);
852 }
853 nfsm_srvdone;
854 }
855
856
857
858
859
860
861
862
863 int
864 nfsrv_writegather(ndp, slp, procp, mrq)
865 struct nfsrv_descript **ndp;
866 struct nfssvc_sock *slp;
867 struct proc *procp;
868 struct mbuf **mrq;
869 {
870 struct iovec *ivp;
871 struct mbuf *mp;
872 struct nfsrv_descript *wp, *nfsd, *owp, *swp;
873 struct nfs_fattr *fp;
874 int i = 0;
875 struct iovec *iov;
876 struct nfsrvw_delayhash *wpp;
877 struct ucred *cred;
878 struct vattr va, forat;
879 u_int32_t *tl;
880 int32_t t1;
881 caddr_t bpos, dpos;
882 int error = 0, rdonly, len = 0, forat_ret = 1;
883 int ioflags, aftat_ret = 1, s, adjust, v3, zeroing;
884 char *cp2;
885 struct mbuf *mb, *mb2, *mreq, *mrep, *md;
886 struct vnode *vp;
887 struct uio io, *uiop = &io;
888 u_quad_t frev, cur_usec;
889 struct timeval tv;
890
891 *mrq = NULL;
892 if (*ndp) {
893 nfsd = *ndp;
894 *ndp = NULL;
895 mrep = nfsd->nd_mrep;
896 md = nfsd->nd_md;
897 dpos = nfsd->nd_dpos;
898 cred = &nfsd->nd_cr;
899 v3 = (nfsd->nd_flag & ND_NFSV3);
900 LIST_INIT(&nfsd->nd_coalesce);
901 nfsd->nd_mreq = NULL;
902 nfsd->nd_stable = NFSV3WRITE_FILESYNC;
903 getmicrotime(&tv);
904 cur_usec = (u_quad_t)tv.tv_sec * 1000000 + (u_quad_t)tv.tv_usec;
905 nfsd->nd_time = cur_usec + nfsrvw_procrastinate;
906
907
908
909
910 nfsm_srvmtofh(&nfsd->nd_fh);
911 if (v3) {
912 nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
913 nfsd->nd_off = fxdr_hyper(tl);
914 tl += 3;
915 nfsd->nd_stable = fxdr_unsigned(int, *tl++);
916 } else {
917 nfsm_dissect(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
918 nfsd->nd_off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
919 tl += 2;
920 }
921 len = fxdr_unsigned(int32_t, *tl);
922 nfsd->nd_len = len;
923 nfsd->nd_eoff = nfsd->nd_off + len;
924
925
926
927
928
929 zeroing = 1;
930 i = 0;
931 mp = mrep;
932 while (mp) {
933 if (mp == md) {
934 zeroing = 0;
935 adjust = dpos - mtod(mp, caddr_t);
936 mp->m_len -= adjust;
937 if (mp->m_len > 0 && adjust > 0)
938 NFSMADV(mp, adjust);
939 }
940 if (zeroing)
941 mp->m_len = 0;
942 else {
943 i += mp->m_len;
944 if (i > len) {
945 mp->m_len -= (i - len);
946 zeroing = 1;
947 }
948 }
949 mp = mp->m_next;
950 }
951 if (len > NFS_MAXDATA || len < 0 || i < len) {
952 m_freem(mrep);
953 nfsmout:
954 error = EIO;
955 nfsm_writereply(2 * NFSX_UNSIGNED, v3);
956 if (v3)
957 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
958 nfsd->nd_mreq = mreq;
959 nfsd->nd_mrep = NULL;
960 nfsd->nd_time = 0;
961 }
962
963
964
965
966 s = splsoftclock();
967 owp = NULL;
968 wp = LIST_FIRST(&slp->ns_tq);
969 while (wp && wp->nd_time < nfsd->nd_time) {
970 owp = wp;
971 wp = LIST_NEXT(wp, nd_tq);
972 }
973 if (owp) {
974 LIST_INSERT_AFTER(owp, nfsd, nd_tq);
975 } else {
976 LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
977 }
978 if (nfsd->nd_mrep) {
979 wpp = NWDELAYHASH(slp, nfsd->nd_fh.fh_fid.fid_data);
980 owp = NULL;
981 wp = LIST_FIRST(wpp);
982 while (wp &&
983 bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh,NFSX_V3FH)) {
984 owp = wp;
985 wp = LIST_NEXT(wp, nd_hash);
986 }
987 while (wp && wp->nd_off < nfsd->nd_off &&
988 !bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh,NFSX_V3FH)) {
989 owp = wp;
990 wp = LIST_NEXT(wp, nd_hash);
991 }
992 if (owp) {
993 LIST_INSERT_AFTER(owp, nfsd, nd_hash);
994
995
996
997
998
999 for(; nfsd && NFSW_CONTIG(owp, nfsd); nfsd = wp) {
1000 wp = LIST_NEXT(nfsd, nd_hash);
1001 if (NFSW_SAMECRED(owp, nfsd))
1002 nfsrvw_coalesce(owp, nfsd);
1003 }
1004 } else {
1005 LIST_INSERT_HEAD(wpp, nfsd, nd_hash);
1006 }
1007 }
1008 splx(s);
1009 }
1010
1011
1012
1013
1014
1015 loop1:
1016 getmicrotime(&tv);
1017 cur_usec = (u_quad_t)tv.tv_sec * 1000000 + (u_quad_t)tv.tv_usec;
1018 s = splsoftclock();
1019 for (nfsd = LIST_FIRST(&slp->ns_tq); nfsd != NULL; nfsd = owp) {
1020 owp = LIST_NEXT(nfsd, nd_tq);
1021 if (nfsd->nd_time > cur_usec)
1022 break;
1023 if (nfsd->nd_mreq)
1024 continue;
1025 LIST_REMOVE(nfsd, nd_tq);
1026 LIST_REMOVE(nfsd, nd_hash);
1027 splx(s);
1028 mrep = nfsd->nd_mrep;
1029 nfsd->nd_mrep = NULL;
1030 cred = &nfsd->nd_cr;
1031 v3 = (nfsd->nd_flag & ND_NFSV3);
1032 forat_ret = aftat_ret = 1;
1033 error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &vp, cred, slp,
1034 nfsd->nd_nam, &rdonly, (nfsd->nd_flag & ND_KERBAUTH));
1035 if (!error) {
1036 if (v3)
1037 forat_ret = VOP_GETATTR(vp, &forat, cred, procp);
1038 if (vp->v_type != VREG) {
1039 if (v3)
1040 error = EINVAL;
1041 else
1042 error = (vp->v_type == VDIR) ? EISDIR : EACCES;
1043 }
1044 } else
1045 vp = NULL;
1046 if (!error) {
1047 error = nfsrv_access(vp, VWRITE, cred, rdonly, procp, 1);
1048 }
1049
1050 if (nfsd->nd_stable == NFSV3WRITE_UNSTABLE)
1051 ioflags = IO_NODELOCKED;
1052 else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC)
1053 ioflags = (IO_SYNC | IO_NODELOCKED);
1054 else
1055 ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
1056 uiop->uio_rw = UIO_WRITE;
1057 uiop->uio_segflg = UIO_SYSSPACE;
1058 uiop->uio_procp = (struct proc *)0;
1059 uiop->uio_offset = nfsd->nd_off;
1060 uiop->uio_resid = nfsd->nd_eoff - nfsd->nd_off;
1061 if (uiop->uio_resid > 0) {
1062 mp = mrep;
1063 i = 0;
1064 while (mp) {
1065 if (mp->m_len > 0)
1066 i++;
1067 mp = mp->m_next;
1068 }
1069 uiop->uio_iovcnt = i;
1070 MALLOC(iov, struct iovec *, i * sizeof (struct iovec),
1071 M_TEMP, M_WAITOK);
1072 uiop->uio_iov = ivp = iov;
1073 mp = mrep;
1074 while (mp) {
1075 if (mp->m_len > 0) {
1076 ivp->iov_base = mtod(mp, caddr_t);
1077 ivp->iov_len = mp->m_len;
1078 ivp++;
1079 }
1080 mp = mp->m_next;
1081 }
1082 if (!error) {
1083 error = VOP_WRITE(vp, uiop, ioflags, cred);
1084 nfsstats.srvvop_writes++;
1085 }
1086 FREE((caddr_t)iov, M_TEMP);
1087 }
1088 m_freem(mrep);
1089 if (vp) {
1090 aftat_ret = VOP_GETATTR(vp, &va, cred, procp);
1091 vput(vp);
1092 }
1093
1094
1095
1096
1097
1098 swp = nfsd;
1099 do {
1100 if (error) {
1101 nfsm_writereply(NFSX_WCCDATA(v3), v3);
1102 if (v3) {
1103 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
1104 }
1105 } else {
1106 nfsm_writereply(NFSX_PREOPATTR(v3) +
1107 NFSX_POSTOPORFATTR(v3) + 2 * NFSX_UNSIGNED +
1108 NFSX_WRITEVERF(v3), v3);
1109 if (v3) {
1110 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
1111 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1112 *tl++ = txdr_unsigned(nfsd->nd_len);
1113 *tl++ = txdr_unsigned(swp->nd_stable);
1114
1115
1116
1117
1118
1119 *tl++ = txdr_unsigned(boottime.tv_sec);
1120 *tl = txdr_unsigned(boottime.tv_usec);
1121 } else {
1122 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
1123 nfsm_srvfillattr(&va, fp);
1124 }
1125 }
1126 nfsd->nd_mreq = mreq;
1127 if (nfsd->nd_mrep)
1128 panic("nfsrv_write: nd_mrep not free");
1129
1130
1131
1132
1133
1134 s = splsoftclock();
1135 if (nfsd != swp) {
1136 nfsd->nd_time = 0;
1137 LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
1138 }
1139 nfsd = LIST_FIRST(&swp->nd_coalesce);
1140 if (nfsd) {
1141 LIST_REMOVE(nfsd, nd_tq);
1142 }
1143 splx(s);
1144 } while (nfsd);
1145 s = splsoftclock();
1146 swp->nd_time = 0;
1147 LIST_INSERT_HEAD(&slp->ns_tq, swp, nd_tq);
1148 splx(s);
1149 goto loop1;
1150 }
1151 splx(s);
1152
1153
1154
1155
1156 s = splsoftclock();
1157 for (nfsd = LIST_FIRST(&slp->ns_tq); nfsd != NULL;
1158 nfsd = LIST_NEXT(nfsd, nd_tq)) {
1159 if (nfsd->nd_mreq) {
1160 LIST_REMOVE(nfsd, nd_tq);
1161 *mrq = nfsd->nd_mreq;
1162 *ndp = nfsd;
1163 break;
1164 }
1165 }
1166 splx(s);
1167 return (0);
1168 }
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178 void
1179 nfsrvw_coalesce(struct nfsrv_descript *owp, struct nfsrv_descript *nfsd)
1180 {
1181 int overlap;
1182 struct mbuf *mp;
1183
1184 splassert(IPL_SOFTCLOCK);
1185
1186 LIST_REMOVE(nfsd, nd_hash);
1187 LIST_REMOVE(nfsd, nd_tq);
1188 if (owp->nd_eoff < nfsd->nd_eoff) {
1189 overlap = owp->nd_eoff - nfsd->nd_off;
1190 if (overlap < 0)
1191 panic("nfsrv_coalesce: bad off");
1192 if (overlap > 0)
1193 m_adj(nfsd->nd_mrep, overlap);
1194 mp = owp->nd_mrep;
1195 while (mp->m_next)
1196 mp = mp->m_next;
1197 mp->m_next = nfsd->nd_mrep;
1198 owp->nd_eoff = nfsd->nd_eoff;
1199 } else
1200 m_freem(nfsd->nd_mrep);
1201 nfsd->nd_mrep = NULL;
1202 if (nfsd->nd_stable == NFSV3WRITE_FILESYNC)
1203 owp->nd_stable = NFSV3WRITE_FILESYNC;
1204 else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC &&
1205 owp->nd_stable == NFSV3WRITE_UNSTABLE)
1206 owp->nd_stable = NFSV3WRITE_DATASYNC;
1207 LIST_INSERT_HEAD(&owp->nd_coalesce, nfsd, nd_tq);
1208
1209
1210
1211
1212
1213 if (LIST_FIRST(&nfsd->nd_coalesce) != NULL) {
1214 struct nfsrv_descript *m;
1215
1216 while ((m = LIST_FIRST(&nfsd->nd_coalesce)) != NULL) {
1217 LIST_REMOVE(m, nd_tq);
1218 LIST_INSERT_HEAD(&owp->nd_coalesce, m, nd_tq);
1219 }
1220 }
1221 }
1222
1223
1224
1225
1226
1227 int
1228 nfsrv_create(nfsd, slp, procp, mrq)
1229 struct nfsrv_descript *nfsd;
1230 struct nfssvc_sock *slp;
1231 struct proc *procp;
1232 struct mbuf **mrq;
1233 {
1234 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1235 struct mbuf *nam = nfsd->nd_nam;
1236 caddr_t dpos = nfsd->nd_dpos;
1237 struct ucred *cred = &nfsd->nd_cr;
1238 struct nfs_fattr *fp;
1239 struct vattr va, dirfor, diraft;
1240 struct nfsv2_sattr *sp;
1241 u_int32_t *tl;
1242 struct nameidata nd;
1243 caddr_t cp;
1244 int32_t t1;
1245 caddr_t bpos;
1246 int error = 0, len, tsize, dirfor_ret = 1, diraft_ret = 1;
1247 dev_t rdev = 0;
1248 int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0;
1249 char *cp2;
1250 struct mbuf *mb, *mb2, *mreq;
1251 struct vnode *vp = NULL, *dirp = NULL;
1252 nfsfh_t nfh;
1253 fhandle_t *fhp;
1254 u_quad_t frev, tempsize;
1255 u_char cverf[NFSX_V3CREATEVERF];
1256
1257 nd.ni_cnd.cn_nameiop = 0;
1258 fhp = &nfh.fh_generic;
1259 nfsm_srvmtofh(fhp);
1260 nfsm_srvnamesiz(len);
1261 nd.ni_cnd.cn_cred = cred;
1262 nd.ni_cnd.cn_nameiop = CREATE;
1263 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
1264 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1265 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
1266 if (dirp) {
1267 if (v3)
1268 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
1269 procp);
1270 else {
1271 vrele(dirp);
1272 dirp = (struct vnode *)0;
1273 }
1274 }
1275 if (error) {
1276 nfsm_reply(NFSX_WCCDATA(v3));
1277 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1278 if (dirp)
1279 vrele(dirp);
1280 return (0);
1281 }
1282 VATTR_NULL(&va);
1283 if (v3) {
1284 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
1285 how = fxdr_unsigned(int, *tl);
1286 switch (how) {
1287 case NFSV3CREATE_GUARDED:
1288 if (nd.ni_vp) {
1289 error = EEXIST;
1290 break;
1291 }
1292 case NFSV3CREATE_UNCHECKED:
1293 nfsm_srvsattr(&va);
1294 break;
1295 case NFSV3CREATE_EXCLUSIVE:
1296 nfsm_dissect(cp, caddr_t, NFSX_V3CREATEVERF);
1297 bcopy(cp, cverf, NFSX_V3CREATEVERF);
1298 exclusive_flag = 1;
1299 if (nd.ni_vp == NULL)
1300 va.va_mode = 0;
1301 break;
1302 };
1303 va.va_type = VREG;
1304 } else {
1305 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1306 va.va_type = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode));
1307 if (va.va_type == VNON)
1308 va.va_type = VREG;
1309 va.va_mode = nfstov_mode(sp->sa_mode);
1310 switch (va.va_type) {
1311 case VREG:
1312 tsize = fxdr_unsigned(int32_t, sp->sa_size);
1313 if (tsize != -1)
1314 va.va_size = (u_quad_t)tsize;
1315 break;
1316 case VCHR:
1317 case VBLK:
1318 case VFIFO:
1319 rdev = (dev_t)fxdr_unsigned(int32_t, sp->sa_size);
1320 break;
1321 default:
1322 break;
1323 };
1324 }
1325
1326
1327
1328
1329
1330
1331 if (nd.ni_vp == NULL) {
1332 if (va.va_type == VREG || va.va_type == VSOCK) {
1333 vrele(nd.ni_startdir);
1334 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
1335 if (!error) {
1336 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
1337 if (exclusive_flag) {
1338 exclusive_flag = 0;
1339 VATTR_NULL(&va);
1340 bcopy(cverf, (caddr_t)&va.va_atime,
1341 NFSX_V3CREATEVERF);
1342 error = VOP_SETATTR(nd.ni_vp, &va, cred,
1343 procp);
1344 }
1345 }
1346 } else if (va.va_type == VCHR || va.va_type == VBLK ||
1347 va.va_type == VFIFO) {
1348 if (va.va_type == VCHR && rdev == 0xffffffff)
1349 va.va_type = VFIFO;
1350 if (va.va_type != VFIFO &&
1351 (error = suser_ucred(cred))) {
1352 vrele(nd.ni_startdir);
1353 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
1354 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1355 vput(nd.ni_dvp);
1356 nfsm_reply(0);
1357 return (0);
1358 } else
1359 va.va_rdev = (dev_t)rdev;
1360 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd,
1361 &va);
1362 if (error) {
1363 vrele(nd.ni_startdir);
1364 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
1365 nfsm_reply(0);
1366 return (0);
1367 }
1368 nd.ni_cnd.cn_nameiop = LOOKUP;
1369 nd.ni_cnd.cn_flags &= ~(LOCKPARENT | SAVESTART);
1370 nd.ni_cnd.cn_proc = procp;
1371 nd.ni_cnd.cn_cred = cred;
1372 if ((error = lookup(&nd)) != 0) {
1373 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
1374 nfsm_reply(0);
1375 return (0);
1376 }
1377
1378 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
1379 if (nd.ni_cnd.cn_flags & ISSYMLINK) {
1380 vrele(nd.ni_dvp);
1381 vput(nd.ni_vp);
1382 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1383 error = EINVAL;
1384 nfsm_reply(0);
1385 return (0);
1386 }
1387 } else {
1388 vrele(nd.ni_startdir);
1389 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
1390 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1391 vput(nd.ni_dvp);
1392 error = ENXIO;
1393 }
1394 vp = nd.ni_vp;
1395 } else {
1396 vrele(nd.ni_startdir);
1397 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
1398 vp = nd.ni_vp;
1399 if (nd.ni_dvp == vp)
1400 vrele(nd.ni_dvp);
1401 else
1402 vput(nd.ni_dvp);
1403 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1404 if (va.va_size != -1) {
1405 error = nfsrv_access(vp, VWRITE, cred,
1406 (nd.ni_cnd.cn_flags & RDONLY), procp, 0);
1407 if (!error) {
1408 tempsize = va.va_size;
1409 VATTR_NULL(&va);
1410 va.va_size = tempsize;
1411 error = VOP_SETATTR(vp, &va, cred,
1412 procp);
1413 }
1414 if (error)
1415 vput(vp);
1416 }
1417 }
1418 if (!error) {
1419 bzero((caddr_t)fhp, sizeof(nfh));
1420 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
1421 error = VFS_VPTOFH(vp, &fhp->fh_fid);
1422 if (!error)
1423 error = VOP_GETATTR(vp, &va, cred, procp);
1424 vput(vp);
1425 }
1426 if (v3) {
1427 if (exclusive_flag && !error &&
1428 bcmp(cverf, (caddr_t)&va.va_atime, NFSX_V3CREATEVERF))
1429 error = EEXIST;
1430 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
1431 vrele(dirp);
1432 }
1433 nfsm_reply(NFSX_SRVFH(v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3));
1434 if (v3) {
1435 if (!error) {
1436 nfsm_srvpostop_fh(fhp);
1437 nfsm_srvpostop_attr(0, &va);
1438 }
1439 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1440 } else {
1441 nfsm_srvfhtom(fhp, v3);
1442 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
1443 nfsm_srvfillattr(&va, fp);
1444 }
1445 return (0);
1446 nfsmout:
1447 if (dirp)
1448 vrele(dirp);
1449 if (nd.ni_cnd.cn_nameiop) {
1450 vrele(nd.ni_startdir);
1451 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
1452 }
1453 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1454 if (nd.ni_dvp == nd.ni_vp)
1455 vrele(nd.ni_dvp);
1456 else
1457 vput(nd.ni_dvp);
1458 if (nd.ni_vp)
1459 vput(nd.ni_vp);
1460 return (error);
1461 }
1462
1463
1464
1465
1466 int
1467 nfsrv_mknod(nfsd, slp, procp, mrq)
1468 struct nfsrv_descript *nfsd;
1469 struct nfssvc_sock *slp;
1470 struct proc *procp;
1471 struct mbuf **mrq;
1472 {
1473 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1474 struct mbuf *nam = nfsd->nd_nam;
1475 caddr_t dpos = nfsd->nd_dpos;
1476 struct ucred *cred = &nfsd->nd_cr;
1477 struct vattr va, dirfor, diraft;
1478 u_int32_t *tl;
1479 struct nameidata nd;
1480 int32_t t1;
1481 caddr_t bpos;
1482 int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
1483 u_int32_t major, minor;
1484 enum vtype vtyp;
1485 char *cp2;
1486 struct mbuf *mb, *mb2, *mreq;
1487 struct vnode *vp, *dirp = (struct vnode *)0;
1488 nfsfh_t nfh;
1489 fhandle_t *fhp;
1490 u_quad_t frev;
1491
1492 nd.ni_cnd.cn_nameiop = 0;
1493 fhp = &nfh.fh_generic;
1494 nfsm_srvmtofh(fhp);
1495 nfsm_srvnamesiz(len);
1496 nd.ni_cnd.cn_cred = cred;
1497 nd.ni_cnd.cn_nameiop = CREATE;
1498 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
1499 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1500 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
1501 if (dirp)
1502 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, procp);
1503 if (error) {
1504 nfsm_reply(NFSX_WCCDATA(1));
1505 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1506 if (dirp)
1507 vrele(dirp);
1508 return (0);
1509 }
1510 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
1511 vtyp = nfsv3tov_type(*tl);
1512 if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
1513 vrele(nd.ni_startdir);
1514 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
1515 error = NFSERR_BADTYPE;
1516 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1517 vput(nd.ni_dvp);
1518 goto out;
1519 }
1520 VATTR_NULL(&va);
1521 nfsm_srvsattr(&va);
1522 if (vtyp == VCHR || vtyp == VBLK) {
1523 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1524 major = fxdr_unsigned(u_int32_t, *tl++);
1525 minor = fxdr_unsigned(u_int32_t, *tl);
1526 va.va_rdev = makedev(major, minor);
1527 }
1528
1529
1530
1531
1532 if (nd.ni_vp) {
1533 vrele(nd.ni_startdir);
1534 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
1535 error = EEXIST;
1536 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1537 vput(nd.ni_dvp);
1538 goto out;
1539 }
1540 va.va_type = vtyp;
1541 if (vtyp == VSOCK) {
1542 vrele(nd.ni_startdir);
1543 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
1544 if (!error)
1545 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
1546 } else {
1547 if (va.va_type != VFIFO &&
1548 (error = suser_ucred(cred))) {
1549 vrele(nd.ni_startdir);
1550 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
1551 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1552 vput(nd.ni_dvp);
1553 goto out;
1554 }
1555 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
1556 if (error) {
1557 vrele(nd.ni_startdir);
1558 goto out;
1559 }
1560 nd.ni_cnd.cn_nameiop = LOOKUP;
1561 nd.ni_cnd.cn_flags &= ~(LOCKPARENT | SAVESTART);
1562 nd.ni_cnd.cn_proc = procp;
1563 nd.ni_cnd.cn_cred = procp->p_ucred;
1564 error = lookup(&nd);
1565 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
1566 if (error)
1567 goto out;
1568 if (nd.ni_cnd.cn_flags & ISSYMLINK) {
1569 vrele(nd.ni_dvp);
1570 vput(nd.ni_vp);
1571 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1572 error = EINVAL;
1573 }
1574 }
1575 out:
1576 vp = nd.ni_vp;
1577 if (!error) {
1578 bzero((caddr_t)fhp, sizeof(nfh));
1579 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
1580 error = VFS_VPTOFH(vp, &fhp->fh_fid);
1581 if (!error)
1582 error = VOP_GETATTR(vp, &va, cred, procp);
1583 vput(vp);
1584 }
1585 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
1586 vrele(dirp);
1587 nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
1588 if (!error) {
1589 nfsm_srvpostop_fh(fhp);
1590 nfsm_srvpostop_attr(0, &va);
1591 }
1592 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1593 return (0);
1594 nfsmout:
1595 if (dirp)
1596 vrele(dirp);
1597 if (nd.ni_cnd.cn_nameiop) {
1598 vrele(nd.ni_startdir);
1599 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
1600 }
1601 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1602 if (nd.ni_dvp == nd.ni_vp)
1603 vrele(nd.ni_dvp);
1604 else
1605 vput(nd.ni_dvp);
1606 if (nd.ni_vp)
1607 vput(nd.ni_vp);
1608 return (error);
1609 }
1610
1611
1612
1613
1614 int
1615 nfsrv_remove(nfsd, slp, procp, mrq)
1616 struct nfsrv_descript *nfsd;
1617 struct nfssvc_sock *slp;
1618 struct proc *procp;
1619 struct mbuf **mrq;
1620 {
1621 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1622 struct mbuf *nam = nfsd->nd_nam;
1623 caddr_t dpos = nfsd->nd_dpos;
1624 struct ucred *cred = &nfsd->nd_cr;
1625 struct nameidata nd;
1626 u_int32_t *tl;
1627 int32_t t1;
1628 caddr_t bpos;
1629 int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
1630 int v3 = (nfsd->nd_flag & ND_NFSV3);
1631 char *cp2;
1632 struct mbuf *mb, *mreq;
1633 struct vnode *vp, *dirp;
1634 struct vattr dirfor, diraft;
1635 nfsfh_t nfh;
1636 fhandle_t *fhp;
1637 u_quad_t frev;
1638
1639 #ifndef nolint
1640 vp = (struct vnode *)0;
1641 #endif
1642 fhp = &nfh.fh_generic;
1643 nfsm_srvmtofh(fhp);
1644 nfsm_srvnamesiz(len);
1645 nd.ni_cnd.cn_cred = cred;
1646 nd.ni_cnd.cn_nameiop = DELETE;
1647 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
1648 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1649 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
1650 if (dirp) {
1651 if (v3)
1652 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
1653 procp);
1654 else
1655 vrele(dirp);
1656 }
1657 if (!error) {
1658 vp = nd.ni_vp;
1659 if (vp->v_type == VDIR &&
1660 (error = suser_ucred(cred)) != 0)
1661 goto out;
1662
1663
1664
1665 if (vp->v_flag & VROOT) {
1666 error = EBUSY;
1667 goto out;
1668 }
1669 if (vp->v_flag & VTEXT)
1670 uvm_vnp_uncache(vp);
1671 out:
1672 if (!error) {
1673 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1674 } else {
1675 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1676 if (nd.ni_dvp == vp)
1677 vrele(nd.ni_dvp);
1678 else
1679 vput(nd.ni_dvp);
1680 vput(vp);
1681 }
1682 }
1683 if (dirp && v3) {
1684 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
1685 vrele(dirp);
1686 }
1687 nfsm_reply(NFSX_WCCDATA(v3));
1688 if (v3) {
1689 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1690 return (0);
1691 }
1692 nfsm_srvdone;
1693 }
1694
1695
1696
1697
1698 int
1699 nfsrv_rename(nfsd, slp, procp, mrq)
1700 struct nfsrv_descript *nfsd;
1701 struct nfssvc_sock *slp;
1702 struct proc *procp;
1703 struct mbuf **mrq;
1704 {
1705 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1706 struct mbuf *nam = nfsd->nd_nam;
1707 caddr_t dpos = nfsd->nd_dpos;
1708 struct ucred *cred = &nfsd->nd_cr;
1709 u_int32_t *tl;
1710 int32_t t1;
1711 caddr_t bpos;
1712 int error = 0, len, len2, fdirfor_ret = 1, fdiraft_ret = 1;
1713 int tdirfor_ret = 1, tdiraft_ret = 1;
1714 int v3 = (nfsd->nd_flag & ND_NFSV3);
1715 char *cp2;
1716 struct mbuf *mb, *mreq;
1717 struct nameidata fromnd, tond;
1718 struct vnode *fvp = NULL, *tvp, *tdvp, *fdirp = NULL;
1719 struct vnode *tdirp = NULL;
1720 struct vattr fdirfor, fdiraft, tdirfor, tdiraft;
1721 nfsfh_t fnfh, tnfh;
1722 fhandle_t *ffhp, *tfhp;
1723 u_quad_t frev;
1724 uid_t saved_uid;
1725
1726 ffhp = &fnfh.fh_generic;
1727 tfhp = &tnfh.fh_generic;
1728 fromnd.ni_cnd.cn_nameiop = 0;
1729 tond.ni_cnd.cn_nameiop = 0;
1730 nfsm_srvmtofh(ffhp);
1731 nfsm_srvnamesiz(len);
1732
1733
1734
1735
1736 saved_uid = cred->cr_uid;
1737 fromnd.ni_cnd.cn_cred = cred;
1738 fromnd.ni_cnd.cn_nameiop = DELETE;
1739 fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART;
1740 error = nfs_namei(&fromnd, ffhp, len, slp, nam, &md,
1741 &dpos, &fdirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
1742 if (fdirp) {
1743 if (v3)
1744 fdirfor_ret = VOP_GETATTR(fdirp, &fdirfor, cred,
1745 procp);
1746 else {
1747 vrele(fdirp);
1748 fdirp = (struct vnode *)0;
1749 }
1750 }
1751 if (error) {
1752 nfsm_reply(2 * NFSX_WCCDATA(v3));
1753 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
1754 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
1755 if (fdirp)
1756 vrele(fdirp);
1757 return (0);
1758 }
1759 fvp = fromnd.ni_vp;
1760 nfsm_srvmtofh(tfhp);
1761 nfsm_strsiz(len2, NFS_MAXNAMLEN);
1762 cred->cr_uid = saved_uid;
1763 tond.ni_cnd.cn_cred = cred;
1764 tond.ni_cnd.cn_nameiop = RENAME;
1765 tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
1766 error = nfs_namei(&tond, tfhp, len2, slp, nam, &md,
1767 &dpos, &tdirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
1768 if (tdirp) {
1769 if (v3)
1770 tdirfor_ret = VOP_GETATTR(tdirp, &tdirfor, cred,
1771 procp);
1772 else {
1773 vrele(tdirp);
1774 tdirp = (struct vnode *)0;
1775 }
1776 }
1777 if (error) {
1778 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1779 vrele(fromnd.ni_dvp);
1780 vrele(fvp);
1781 goto out1;
1782 }
1783 tdvp = tond.ni_dvp;
1784 tvp = tond.ni_vp;
1785 if (tvp != NULL) {
1786 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1787 error = v3 ? EEXIST : EISDIR;
1788 goto out;
1789 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1790 error = v3 ? EEXIST : ENOTDIR;
1791 goto out;
1792 }
1793 if (tvp->v_type == VDIR && tvp->v_mountedhere) {
1794 error = v3 ? EXDEV : ENOTEMPTY;
1795 goto out;
1796 }
1797 }
1798 if (fvp->v_type == VDIR && fvp->v_mountedhere) {
1799 error = v3 ? EXDEV : ENOTEMPTY;
1800 goto out;
1801 }
1802 if (fvp->v_mount != tdvp->v_mount) {
1803 error = v3 ? EXDEV : ENOTEMPTY;
1804 goto out;
1805 }
1806 if (fvp == tdvp)
1807 error = v3 ? EINVAL : ENOTEMPTY;
1808
1809
1810
1811
1812
1813 if (fvp == tvp && fromnd.ni_dvp == tdvp &&
1814 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
1815 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
1816 fromnd.ni_cnd.cn_namelen))
1817 error = -1;
1818 out:
1819 if (!error) {
1820 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
1821 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
1822 } else {
1823 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
1824 if (tdvp == tvp)
1825 vrele(tdvp);
1826 else
1827 vput(tdvp);
1828 if (tvp)
1829 vput(tvp);
1830 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1831 vrele(fromnd.ni_dvp);
1832 vrele(fvp);
1833 if (error == -1)
1834 error = 0;
1835 }
1836 vrele(tond.ni_startdir);
1837 pool_put(&namei_pool, tond.ni_cnd.cn_pnbuf);
1838 out1:
1839 if (fdirp) {
1840 fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, cred, procp);
1841 vrele(fdirp);
1842 }
1843 if (tdirp) {
1844 tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, cred, procp);
1845 vrele(tdirp);
1846 }
1847 vrele(fromnd.ni_startdir);
1848 pool_put(&namei_pool, fromnd.ni_cnd.cn_pnbuf);
1849 nfsm_reply(2 * NFSX_WCCDATA(v3));
1850 if (v3) {
1851 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
1852 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
1853 }
1854 return (0);
1855
1856 nfsmout:
1857 if (fdirp)
1858 vrele(fdirp);
1859 if (tdirp)
1860 vrele(tdirp);
1861 if (tond.ni_cnd.cn_nameiop) {
1862 vrele(tond.ni_startdir);
1863 pool_put(&namei_pool, tond.ni_cnd.cn_pnbuf);
1864 }
1865 if (fromnd.ni_cnd.cn_nameiop) {
1866 vrele(fromnd.ni_startdir);
1867 pool_put(&namei_pool, fromnd.ni_cnd.cn_pnbuf);
1868 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1869 vrele(fromnd.ni_dvp);
1870 vrele(fvp);
1871 }
1872 return (error);
1873 }
1874
1875
1876
1877
1878 int
1879 nfsrv_link(nfsd, slp, procp, mrq)
1880 struct nfsrv_descript *nfsd;
1881 struct nfssvc_sock *slp;
1882 struct proc *procp;
1883 struct mbuf **mrq;
1884 {
1885 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1886 struct mbuf *nam = nfsd->nd_nam;
1887 caddr_t dpos = nfsd->nd_dpos;
1888 struct ucred *cred = &nfsd->nd_cr;
1889 struct nameidata nd;
1890 u_int32_t *tl;
1891 int32_t t1;
1892 caddr_t bpos;
1893 int error = 0, rdonly, len, dirfor_ret = 1, diraft_ret = 1;
1894 int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3);
1895 char *cp2;
1896 struct mbuf *mb, *mreq;
1897 struct vnode *vp, *xp, *dirp = (struct vnode *)0;
1898 struct vattr dirfor, diraft, at;
1899 nfsfh_t nfh, dnfh;
1900 fhandle_t *fhp, *dfhp;
1901 u_quad_t frev;
1902
1903 fhp = &nfh.fh_generic;
1904 dfhp = &dnfh.fh_generic;
1905 nfsm_srvmtofh(fhp);
1906 nfsm_srvmtofh(dfhp);
1907 nfsm_srvnamesiz(len);
1908 error = nfsrv_fhtovp(fhp, FALSE, &vp, cred, slp, nam,
1909 &rdonly, (nfsd->nd_flag & ND_KERBAUTH));
1910 if (error) {
1911 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
1912 nfsm_srvpostop_attr(getret, &at);
1913 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1914 return (0);
1915 }
1916 if (vp->v_type == VDIR && (error = suser_ucred(cred)) != 0)
1917 goto out1;
1918 nd.ni_cnd.cn_cred = cred;
1919 nd.ni_cnd.cn_nameiop = CREATE;
1920 nd.ni_cnd.cn_flags = LOCKPARENT;
1921 error = nfs_namei(&nd, dfhp, len, slp, nam, &md, &dpos,
1922 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
1923 if (dirp) {
1924 if (v3)
1925 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
1926 procp);
1927 else {
1928 vrele(dirp);
1929 dirp = (struct vnode *)0;
1930 }
1931 }
1932 if (error)
1933 goto out1;
1934 xp = nd.ni_vp;
1935 if (xp != NULL) {
1936 error = EEXIST;
1937 goto out;
1938 }
1939 xp = nd.ni_dvp;
1940 if (vp->v_mount != xp->v_mount)
1941 error = EXDEV;
1942 out:
1943 if (!error) {
1944 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1945 } else {
1946 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1947 if (nd.ni_dvp == nd.ni_vp)
1948 vrele(nd.ni_dvp);
1949 else
1950 vput(nd.ni_dvp);
1951 if (nd.ni_vp)
1952 vrele(nd.ni_vp);
1953 }
1954 out1:
1955 if (v3)
1956 getret = VOP_GETATTR(vp, &at, cred, procp);
1957 if (dirp) {
1958 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
1959 vrele(dirp);
1960 }
1961 vrele(vp);
1962 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
1963 if (v3) {
1964 nfsm_srvpostop_attr(getret, &at);
1965 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1966 return (0);
1967 }
1968 nfsm_srvdone;
1969 }
1970
1971
1972
1973
1974 int
1975 nfsrv_symlink(nfsd, slp, procp, mrq)
1976 struct nfsrv_descript *nfsd;
1977 struct nfssvc_sock *slp;
1978 struct proc *procp;
1979 struct mbuf **mrq;
1980 {
1981 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1982 struct mbuf *nam = nfsd->nd_nam;
1983 caddr_t dpos = nfsd->nd_dpos;
1984 struct ucred *cred = &nfsd->nd_cr;
1985 struct vattr va, dirfor, diraft;
1986 struct nameidata nd;
1987 u_int32_t *tl;
1988 int32_t t1;
1989 struct nfsv2_sattr *sp;
1990 char *bpos, *pathcp = NULL, *cp2;
1991 struct uio io;
1992 struct iovec iv;
1993 int error = 0, len, len2, dirfor_ret = 1, diraft_ret = 1;
1994 int v3 = (nfsd->nd_flag & ND_NFSV3);
1995 struct mbuf *mb, *mreq, *mb2;
1996 struct vnode *dirp = (struct vnode *)0;
1997 nfsfh_t nfh;
1998 fhandle_t *fhp;
1999 u_quad_t frev;
2000
2001 nd.ni_cnd.cn_nameiop = 0;
2002 fhp = &nfh.fh_generic;
2003 nfsm_srvmtofh(fhp);
2004 nfsm_srvnamesiz(len);
2005 nd.ni_cnd.cn_cred = cred;
2006 nd.ni_cnd.cn_nameiop = CREATE;
2007 nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART;
2008 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
2009 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
2010 if (dirp) {
2011 if (v3)
2012 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
2013 procp);
2014 else {
2015 vrele(dirp);
2016 dirp = (struct vnode *)0;
2017 }
2018 }
2019 if (error)
2020 goto out;
2021 VATTR_NULL(&va);
2022 if (v3)
2023 nfsm_srvsattr(&va);
2024 nfsm_strsiz(len2, NFS_MAXPATHLEN);
2025 MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK);
2026 iv.iov_base = pathcp;
2027 iv.iov_len = len2;
2028 io.uio_resid = len2;
2029 io.uio_offset = 0;
2030 io.uio_iov = &iv;
2031 io.uio_iovcnt = 1;
2032 io.uio_segflg = UIO_SYSSPACE;
2033 io.uio_rw = UIO_READ;
2034 io.uio_procp = (struct proc *)0;
2035 nfsm_mtouio(&io, len2);
2036 if (!v3) {
2037 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
2038 va.va_mode = fxdr_unsigned(u_int16_t, sp->sa_mode);
2039 }
2040 *(pathcp + len2) = '\0';
2041 if (nd.ni_vp) {
2042 vrele(nd.ni_startdir);
2043 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
2044 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2045 if (nd.ni_dvp == nd.ni_vp)
2046 vrele(nd.ni_dvp);
2047 else
2048 vput(nd.ni_dvp);
2049 vrele(nd.ni_vp);
2050 error = EEXIST;
2051 goto out;
2052 }
2053 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va, pathcp);
2054 if (error)
2055 vrele(nd.ni_startdir);
2056 else {
2057 if (v3) {
2058 nd.ni_cnd.cn_nameiop = LOOKUP;
2059 nd.ni_cnd.cn_flags &= ~(LOCKPARENT | SAVESTART | FOLLOW);
2060 nd.ni_cnd.cn_flags |= (NOFOLLOW | LOCKLEAF);
2061 nd.ni_cnd.cn_proc = procp;
2062 nd.ni_cnd.cn_cred = cred;
2063 error = lookup(&nd);
2064 if (!error) {
2065 bzero((caddr_t)fhp, sizeof(nfh));
2066 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
2067 error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
2068 if (!error)
2069 error = VOP_GETATTR(nd.ni_vp, &va, cred,
2070 procp);
2071 vput(nd.ni_vp);
2072 }
2073 } else
2074 vrele(nd.ni_startdir);
2075 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
2076 }
2077 out:
2078 if (pathcp)
2079 FREE(pathcp, M_TEMP);
2080 if (dirp) {
2081 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
2082 vrele(dirp);
2083 }
2084 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2085 if (v3) {
2086 if (!error) {
2087 nfsm_srvpostop_fh(fhp);
2088 nfsm_srvpostop_attr(0, &va);
2089 }
2090 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2091 }
2092 return (0);
2093 nfsmout:
2094 if (nd.ni_cnd.cn_nameiop) {
2095 vrele(nd.ni_startdir);
2096 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
2097 }
2098 if (dirp)
2099 vrele(dirp);
2100 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2101 if (nd.ni_dvp == nd.ni_vp)
2102 vrele(nd.ni_dvp);
2103 else
2104 vput(nd.ni_dvp);
2105 if (nd.ni_vp)
2106 vrele(nd.ni_vp);
2107 if (pathcp)
2108 FREE(pathcp, M_TEMP);
2109 return (error);
2110 }
2111
2112
2113
2114
2115 int
2116 nfsrv_mkdir(nfsd, slp, procp, mrq)
2117 struct nfsrv_descript *nfsd;
2118 struct nfssvc_sock *slp;
2119 struct proc *procp;
2120 struct mbuf **mrq;
2121 {
2122 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2123 struct mbuf *nam = nfsd->nd_nam;
2124 caddr_t dpos = nfsd->nd_dpos;
2125 struct ucred *cred = &nfsd->nd_cr;
2126 struct vattr va, dirfor, diraft;
2127 struct nfs_fattr *fp;
2128 struct nameidata nd;
2129 caddr_t cp;
2130 u_int32_t *tl;
2131 int32_t t1;
2132 caddr_t bpos;
2133 int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
2134 int v3 = (nfsd->nd_flag & ND_NFSV3);
2135 char *cp2;
2136 struct mbuf *mb, *mb2, *mreq;
2137 struct vnode *vp, *dirp = (struct vnode *)0;
2138 nfsfh_t nfh;
2139 fhandle_t *fhp;
2140 u_quad_t frev;
2141
2142 fhp = &nfh.fh_generic;
2143 nfsm_srvmtofh(fhp);
2144 nfsm_srvnamesiz(len);
2145 nd.ni_cnd.cn_cred = cred;
2146 nd.ni_cnd.cn_nameiop = CREATE;
2147 nd.ni_cnd.cn_flags = LOCKPARENT;
2148 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
2149 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
2150 if (dirp) {
2151 if (v3)
2152 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
2153 procp);
2154 else {
2155 vrele(dirp);
2156 dirp = (struct vnode *)0;
2157 }
2158 }
2159 if (error) {
2160 nfsm_reply(NFSX_WCCDATA(v3));
2161 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2162 if (dirp)
2163 vrele(dirp);
2164 return (0);
2165 }
2166 VATTR_NULL(&va);
2167 if (v3) {
2168 nfsm_srvsattr(&va);
2169 } else {
2170 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2171 va.va_mode = nfstov_mode(*tl++);
2172 }
2173 va.va_type = VDIR;
2174 vp = nd.ni_vp;
2175 if (vp != NULL) {
2176 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2177 if (nd.ni_dvp == vp)
2178 vrele(nd.ni_dvp);
2179 else
2180 vput(nd.ni_dvp);
2181 vrele(vp);
2182 error = EEXIST;
2183 goto out;
2184 }
2185 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
2186 if (!error) {
2187 vp = nd.ni_vp;
2188 bzero((caddr_t)fhp, sizeof(nfh));
2189 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
2190 error = VFS_VPTOFH(vp, &fhp->fh_fid);
2191 if (!error)
2192 error = VOP_GETATTR(vp, &va, cred, procp);
2193 vput(vp);
2194 }
2195 out:
2196 if (dirp) {
2197 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
2198 vrele(dirp);
2199 }
2200 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2201 if (v3) {
2202 if (!error) {
2203 nfsm_srvpostop_fh(fhp);
2204 nfsm_srvpostop_attr(0, &va);
2205 }
2206 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2207 } else {
2208 nfsm_srvfhtom(fhp, v3);
2209 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
2210 nfsm_srvfillattr(&va, fp);
2211 }
2212 return (0);
2213 nfsmout:
2214 if (dirp)
2215 vrele(dirp);
2216 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2217 if (nd.ni_dvp == nd.ni_vp)
2218 vrele(nd.ni_dvp);
2219 else
2220 vput(nd.ni_dvp);
2221 if (nd.ni_vp)
2222 vrele(nd.ni_vp);
2223 return (error);
2224 }
2225
2226
2227
2228
2229 int
2230 nfsrv_rmdir(nfsd, slp, procp, mrq)
2231 struct nfsrv_descript *nfsd;
2232 struct nfssvc_sock *slp;
2233 struct proc *procp;
2234 struct mbuf **mrq;
2235 {
2236 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2237 struct mbuf *nam = nfsd->nd_nam;
2238 caddr_t dpos = nfsd->nd_dpos;
2239 struct ucred *cred = &nfsd->nd_cr;
2240 u_int32_t *tl;
2241 int32_t t1;
2242 caddr_t bpos;
2243 int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
2244 int v3 = (nfsd->nd_flag & ND_NFSV3);
2245 char *cp2;
2246 struct mbuf *mb, *mreq;
2247 struct vnode *vp, *dirp = (struct vnode *)0;
2248 struct vattr dirfor, diraft;
2249 nfsfh_t nfh;
2250 fhandle_t *fhp;
2251 struct nameidata nd;
2252 u_quad_t frev;
2253
2254 fhp = &nfh.fh_generic;
2255 nfsm_srvmtofh(fhp);
2256 nfsm_srvnamesiz(len);
2257 nd.ni_cnd.cn_cred = cred;
2258 nd.ni_cnd.cn_nameiop = DELETE;
2259 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
2260 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
2261 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
2262 if (dirp) {
2263 if (v3)
2264 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
2265 procp);
2266 else {
2267 vrele(dirp);
2268 dirp = (struct vnode *)0;
2269 }
2270 }
2271 if (error) {
2272 nfsm_reply(NFSX_WCCDATA(v3));
2273 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2274 if (dirp)
2275 vrele(dirp);
2276 return (0);
2277 }
2278 vp = nd.ni_vp;
2279 if (vp->v_type != VDIR) {
2280 error = ENOTDIR;
2281 goto out;
2282 }
2283
2284
2285
2286 if (nd.ni_dvp == vp) {
2287 error = EINVAL;
2288 goto out;
2289 }
2290
2291
2292
2293 if (vp->v_flag & VROOT)
2294 error = EBUSY;
2295 out:
2296 if (!error) {
2297 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
2298 } else {
2299 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2300 if (nd.ni_dvp == nd.ni_vp)
2301 vrele(nd.ni_dvp);
2302 else
2303 vput(nd.ni_dvp);
2304 vput(vp);
2305 }
2306 if (dirp) {
2307 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
2308 vrele(dirp);
2309 }
2310 nfsm_reply(NFSX_WCCDATA(v3));
2311 if (v3) {
2312 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2313 return (0);
2314 }
2315 nfsm_srvdone;
2316 }
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347 struct flrep {
2348 nfsuint64 fl_off;
2349 u_int32_t fl_postopok;
2350 u_int32_t fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)];
2351 u_int32_t fl_fhok;
2352 u_int32_t fl_fhsize;
2353 u_int32_t fl_nfh[NFSX_V3FH / sizeof (u_int32_t)];
2354 };
2355
2356 int
2357 nfsrv_readdir(nfsd, slp, procp, mrq)
2358 struct nfsrv_descript *nfsd;
2359 struct nfssvc_sock *slp;
2360 struct proc *procp;
2361 struct mbuf **mrq;
2362 {
2363 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2364 struct mbuf *nam = nfsd->nd_nam;
2365 caddr_t dpos = nfsd->nd_dpos;
2366 struct ucred *cred = &nfsd->nd_cr;
2367 char *bp, *be;
2368 struct mbuf *mp;
2369 struct dirent *dp;
2370 caddr_t cp;
2371 u_int32_t *tl;
2372 int32_t t1;
2373 caddr_t bpos;
2374 struct mbuf *mb, *mb2, *mreq, *mp2;
2375 char *cpos, *cend, *cp2, *rbuf;
2376 struct vnode *vp;
2377 struct vattr at;
2378 nfsfh_t nfh;
2379 fhandle_t *fhp;
2380 struct uio io;
2381 struct iovec iv;
2382 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
2383 int siz, cnt, fullsiz, eofflag, rdonly, ncookies;
2384 int v3 = (nfsd->nd_flag & ND_NFSV3);
2385 u_quad_t frev, off, toff, verf;
2386 u_long *cookies = NULL, *cookiep;
2387
2388 fhp = &nfh.fh_generic;
2389 nfsm_srvmtofh(fhp);
2390 if (v3) {
2391 nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
2392 toff = fxdr_hyper(tl);
2393 tl += 2;
2394 verf = fxdr_hyper(tl);
2395 tl += 2;
2396 } else {
2397 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2398 toff = fxdr_unsigned(u_quad_t, *tl++);
2399 }
2400 off = toff;
2401 cnt = fxdr_unsigned(int, *tl);
2402 siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
2403 xfer = NFS_SRVMAXDATA(nfsd);
2404 if (siz > xfer)
2405 siz = xfer;
2406 if (cnt > xfer)
2407 cnt = xfer;
2408 fullsiz = siz;
2409 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
2410 &rdonly, (nfsd->nd_flag & ND_KERBAUTH));
2411 if (error) {
2412 nfsm_reply(NFSX_UNSIGNED);
2413 nfsm_srvpostop_attr(getret, &at);
2414 return (0);
2415 }
2416 if (v3) {
2417 error = getret = VOP_GETATTR(vp, &at, cred, procp);
2418 #ifdef NFS3_STRICTVERF
2419
2420
2421
2422 if (!error && toff && verf != at.va_filerev)
2423 error = NFSERR_BAD_COOKIE;
2424 #endif
2425 }
2426 if (!error)
2427 error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0);
2428 if (error) {
2429 vput(vp);
2430 nfsm_reply(NFSX_POSTOPATTR(v3));
2431 nfsm_srvpostop_attr(getret, &at);
2432 return (0);
2433 }
2434 VOP_UNLOCK(vp, 0, procp);
2435 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
2436 again:
2437 iv.iov_base = rbuf;
2438 iv.iov_len = fullsiz;
2439 io.uio_iov = &iv;
2440 io.uio_iovcnt = 1;
2441 io.uio_offset = (off_t)off;
2442 io.uio_resid = fullsiz;
2443 io.uio_segflg = UIO_SYSSPACE;
2444 io.uio_rw = UIO_READ;
2445 io.uio_procp = (struct proc *)0;
2446 eofflag = 0;
2447
2448 if (cookies) {
2449 free((caddr_t)cookies, M_TEMP);
2450 cookies = NULL;
2451 }
2452
2453 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, procp);
2454 error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
2455
2456 off = (off_t)io.uio_offset;
2457 if (!cookies && !error)
2458 error = NFSERR_PERM;
2459 if (v3) {
2460 getret = VOP_GETATTR(vp, &at, cred, procp);
2461 if (!error)
2462 error = getret;
2463 }
2464
2465 VOP_UNLOCK(vp, 0, procp);
2466 if (error) {
2467 vrele(vp);
2468 free((caddr_t)rbuf, M_TEMP);
2469 if (cookies)
2470 free((caddr_t)cookies, M_TEMP);
2471 nfsm_reply(NFSX_POSTOPATTR(v3));
2472 nfsm_srvpostop_attr(getret, &at);
2473 return (0);
2474 }
2475 if (io.uio_resid) {
2476 siz -= io.uio_resid;
2477
2478
2479
2480
2481
2482 if (siz == 0) {
2483 vrele(vp);
2484 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) +
2485 2 * NFSX_UNSIGNED);
2486 if (v3) {
2487 nfsm_srvpostop_attr(getret, &at);
2488 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
2489 txdr_hyper(at.va_filerev, tl);
2490 tl += 2;
2491 } else
2492 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2493 *tl++ = nfs_false;
2494 *tl = nfs_true;
2495 FREE((caddr_t)rbuf, M_TEMP);
2496 FREE((caddr_t)cookies, M_TEMP);
2497 return (0);
2498 }
2499 }
2500
2501
2502
2503
2504
2505 cpos = rbuf;
2506 cend = rbuf + siz;
2507 dp = (struct dirent *)cpos;
2508 cookiep = cookies;
2509
2510 while (cpos < cend && ncookies > 0 && dp->d_fileno == 0) {
2511 cpos += dp->d_reclen;
2512 dp = (struct dirent *)cpos;
2513 cookiep++;
2514 ncookies--;
2515 }
2516 if (cpos >= cend || ncookies == 0) {
2517 toff = off;
2518 siz = fullsiz;
2519 goto again;
2520 }
2521
2522 len = 3 * NFSX_UNSIGNED;
2523 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz);
2524 if (v3) {
2525 nfsm_srvpostop_attr(getret, &at);
2526 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2527 txdr_hyper(at.va_filerev, tl);
2528 }
2529 mp = mp2 = mb;
2530 bp = bpos;
2531 be = bp + M_TRAILINGSPACE(mp);
2532
2533
2534 while (cpos < cend && ncookies > 0) {
2535 if (dp->d_fileno != 0) {
2536 nlen = dp->d_namlen;
2537 rem = nfsm_rndup(nlen)-nlen;
2538 len += (4 * NFSX_UNSIGNED + nlen + rem);
2539 if (v3)
2540 len += 2 * NFSX_UNSIGNED;
2541 if (len > cnt) {
2542 eofflag = 0;
2543 break;
2544 }
2545
2546
2547
2548
2549 nfsm_clget;
2550 *tl = nfs_true;
2551 bp += NFSX_UNSIGNED;
2552 if (v3) {
2553 nfsm_clget;
2554 *tl = 0;
2555 bp += NFSX_UNSIGNED;
2556 }
2557 nfsm_clget;
2558 *tl = txdr_unsigned(dp->d_fileno);
2559 bp += NFSX_UNSIGNED;
2560 nfsm_clget;
2561 *tl = txdr_unsigned(nlen);
2562 bp += NFSX_UNSIGNED;
2563
2564
2565 xfer = nlen;
2566 cp = dp->d_name;
2567 while (xfer > 0) {
2568 nfsm_clget;
2569 if ((bp+xfer) > be)
2570 tsiz = be-bp;
2571 else
2572 tsiz = xfer;
2573 bcopy(cp, bp, tsiz);
2574 bp += tsiz;
2575 xfer -= tsiz;
2576 if (xfer > 0)
2577 cp += tsiz;
2578 }
2579
2580 for (i = 0; i < rem; i++)
2581 *bp++ = '\0';
2582 nfsm_clget;
2583
2584
2585 if (v3) {
2586 *tl = 0;
2587 bp += NFSX_UNSIGNED;
2588 nfsm_clget;
2589 }
2590 *tl = txdr_unsigned(*cookiep);
2591 bp += NFSX_UNSIGNED;
2592 }
2593 cpos += dp->d_reclen;
2594 dp = (struct dirent *)cpos;
2595 cookiep++;
2596 ncookies--;
2597 }
2598 vrele(vp);
2599 nfsm_clget;
2600 *tl = nfs_false;
2601 bp += NFSX_UNSIGNED;
2602 nfsm_clget;
2603 if (eofflag)
2604 *tl = nfs_true;
2605 else
2606 *tl = nfs_false;
2607 bp += NFSX_UNSIGNED;
2608 if (mp != mb) {
2609 if (bp < be)
2610 mp->m_len = bp - mtod(mp, caddr_t);
2611 } else
2612 mp->m_len += bp - bpos;
2613 FREE((caddr_t)rbuf, M_TEMP);
2614 FREE((caddr_t)cookies, M_TEMP);
2615 nfsm_srvdone;
2616 }
2617
2618 int
2619 nfsrv_readdirplus(nfsd, slp, procp, mrq)
2620 struct nfsrv_descript *nfsd;
2621 struct nfssvc_sock *slp;
2622 struct proc *procp;
2623 struct mbuf **mrq;
2624 {
2625 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2626 struct mbuf *nam = nfsd->nd_nam;
2627 caddr_t dpos = nfsd->nd_dpos;
2628 struct ucred *cred = &nfsd->nd_cr;
2629 char *bp, *be;
2630 struct mbuf *mp;
2631 struct dirent *dp;
2632 caddr_t cp;
2633 u_int32_t *tl;
2634 int32_t t1;
2635 caddr_t bpos;
2636 struct mbuf *mb, *mb2, *mreq, *mp2;
2637 char *cpos, *cend, *cp2, *rbuf;
2638 struct vnode *vp, *nvp;
2639 struct flrep fl;
2640 nfsfh_t nfh;
2641 fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh;
2642 struct uio io;
2643 struct iovec iv;
2644 struct vattr va, at, *vap = &va;
2645 struct nfs_fattr *fp;
2646 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
2647 int siz, cnt, fullsiz, eofflag, rdonly, dirlen, ncookies;
2648 u_quad_t frev, off, toff, verf;
2649 u_long *cookies = NULL, *cookiep;
2650
2651 fhp = &nfh.fh_generic;
2652 nfsm_srvmtofh(fhp);
2653 nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
2654 toff = fxdr_hyper(tl);
2655 tl += 2;
2656 verf = fxdr_hyper(tl);
2657 tl += 2;
2658 siz = fxdr_unsigned(int, *tl++);
2659 cnt = fxdr_unsigned(int, *tl);
2660 off = toff;
2661 siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
2662 xfer = NFS_SRVMAXDATA(nfsd);
2663 if (siz > xfer)
2664 siz = xfer;
2665 if (cnt > xfer)
2666 cnt = xfer;
2667 fullsiz = siz;
2668 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
2669 &rdonly, (nfsd->nd_flag & ND_KERBAUTH));
2670 if (error) {
2671 nfsm_reply(NFSX_UNSIGNED);
2672 nfsm_srvpostop_attr(getret, &at);
2673 return (0);
2674 }
2675 error = getret = VOP_GETATTR(vp, &at, cred, procp);
2676 #ifdef NFS3_STRICTVERF
2677
2678
2679
2680 if (!error && toff && verf != at.va_filerev)
2681 error = NFSERR_BAD_COOKIE;
2682 #endif
2683 if (!error) {
2684 error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0);
2685 }
2686 if (error) {
2687 vput(vp);
2688 nfsm_reply(NFSX_V3POSTOPATTR);
2689 nfsm_srvpostop_attr(getret, &at);
2690 return (0);
2691 }
2692 VOP_UNLOCK(vp, 0, procp);
2693
2694 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
2695 again:
2696 iv.iov_base = rbuf;
2697 iv.iov_len = fullsiz;
2698 io.uio_iov = &iv;
2699 io.uio_iovcnt = 1;
2700 io.uio_offset = (off_t)off;
2701 io.uio_resid = fullsiz;
2702 io.uio_segflg = UIO_SYSSPACE;
2703 io.uio_rw = UIO_READ;
2704 io.uio_procp = (struct proc *)0;
2705 eofflag = 0;
2706
2707 if (cookies) {
2708 free((caddr_t)cookies, M_TEMP);
2709 cookies = NULL;
2710 }
2711
2712 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, procp);
2713 error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
2714
2715 off = (u_quad_t)io.uio_offset;
2716 getret = VOP_GETATTR(vp, &at, cred, procp);
2717
2718 VOP_UNLOCK(vp, 0, procp);
2719
2720 if (!cookies && !error)
2721 error = NFSERR_PERM;
2722 if (!error)
2723 error = getret;
2724 if (error) {
2725 vrele(vp);
2726 if (cookies)
2727 free((caddr_t)cookies, M_TEMP);
2728 free((caddr_t)rbuf, M_TEMP);
2729 nfsm_reply(NFSX_V3POSTOPATTR);
2730 nfsm_srvpostop_attr(getret, &at);
2731 return (0);
2732 }
2733 if (io.uio_resid) {
2734 siz -= io.uio_resid;
2735
2736
2737
2738
2739
2740 if (siz == 0) {
2741 vrele(vp);
2742 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
2743 2 * NFSX_UNSIGNED);
2744 nfsm_srvpostop_attr(getret, &at);
2745 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
2746 txdr_hyper(at.va_filerev, tl);
2747 tl += 2;
2748 *tl++ = nfs_false;
2749 *tl = nfs_true;
2750 FREE((caddr_t)cookies, M_TEMP);
2751 FREE((caddr_t)rbuf, M_TEMP);
2752 return (0);
2753 }
2754 }
2755
2756
2757
2758
2759
2760 cpos = rbuf;
2761 cend = rbuf + siz;
2762 dp = (struct dirent *)cpos;
2763 cookiep = cookies;
2764
2765 while (cpos < cend && ncookies > 0 && dp->d_fileno == 0) {
2766 cpos += dp->d_reclen;
2767 dp = (struct dirent *)cpos;
2768 cookiep++;
2769 ncookies--;
2770 }
2771 if (cpos >= cend || ncookies == 0) {
2772 toff = off;
2773 siz = fullsiz;
2774 goto again;
2775 }
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789 dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 2 * NFSX_UNSIGNED;
2790 nfsm_reply(cnt);
2791 nfsm_srvpostop_attr(getret, &at);
2792 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2793 txdr_hyper(at.va_filerev, tl);
2794 mp = mp2 = mb;
2795 bp = bpos;
2796 be = bp + M_TRAILINGSPACE(mp);
2797
2798
2799 while (cpos < cend && ncookies > 0) {
2800 if (dp->d_fileno != 0) {
2801 nlen = dp->d_namlen;
2802 rem = nfsm_rndup(nlen)-nlen;
2803
2804
2805
2806
2807
2808 if (VFS_VGET(vp->v_mount, dp->d_fileno, &nvp))
2809 goto invalid;
2810 bzero((caddr_t)nfhp, NFSX_V3FH);
2811 nfhp->fh_fsid =
2812 nvp->v_mount->mnt_stat.f_fsid;
2813 if (VFS_VPTOFH(nvp, &nfhp->fh_fid)) {
2814 vput(nvp);
2815 goto invalid;
2816 }
2817 if (VOP_GETATTR(nvp, vap, cred, procp)) {
2818 vput(nvp);
2819 goto invalid;
2820 }
2821 vput(nvp);
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840 len += (8 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH +
2841 NFSX_V3POSTOPATTR);
2842 dirlen += (6 * NFSX_UNSIGNED + nlen + rem);
2843 if (len > cnt || dirlen > fullsiz) {
2844 eofflag = 0;
2845 break;
2846 }
2847
2848
2849
2850
2851
2852 fp = (struct nfs_fattr *)&fl.fl_fattr;
2853 nfsm_srvfillattr(vap, fp);
2854 fl.fl_fhsize = txdr_unsigned(NFSX_V3FH);
2855 fl.fl_fhok = nfs_true;
2856 fl.fl_postopok = nfs_true;
2857 fl.fl_off.nfsuquad[0] = 0;
2858 fl.fl_off.nfsuquad[1] = txdr_unsigned(*cookiep);
2859
2860 nfsm_clget;
2861 *tl = nfs_true;
2862 bp += NFSX_UNSIGNED;
2863 nfsm_clget;
2864 *tl = 0;
2865 bp += NFSX_UNSIGNED;
2866 nfsm_clget;
2867 *tl = txdr_unsigned(dp->d_fileno);
2868 bp += NFSX_UNSIGNED;
2869 nfsm_clget;
2870 *tl = txdr_unsigned(nlen);
2871 bp += NFSX_UNSIGNED;
2872
2873
2874 xfer = nlen;
2875 cp = dp->d_name;
2876 while (xfer > 0) {
2877 nfsm_clget;
2878 if ((bp + xfer) > be)
2879 tsiz = be - bp;
2880 else
2881 tsiz = xfer;
2882 bcopy(cp, bp, tsiz);
2883 bp += tsiz;
2884 xfer -= tsiz;
2885 if (xfer > 0)
2886 cp += tsiz;
2887 }
2888
2889 for (i = 0; i < rem; i++)
2890 *bp++ = '\0';
2891
2892
2893
2894
2895 xfer = sizeof (struct flrep);
2896 cp = (caddr_t)&fl;
2897 while (xfer > 0) {
2898 nfsm_clget;
2899 if ((bp + xfer) > be)
2900 tsiz = be - bp;
2901 else
2902 tsiz = xfer;
2903 bcopy(cp, bp, tsiz);
2904 bp += tsiz;
2905 xfer -= tsiz;
2906 if (xfer > 0)
2907 cp += tsiz;
2908 }
2909 }
2910 invalid:
2911 cpos += dp->d_reclen;
2912 dp = (struct dirent *)cpos;
2913 cookiep++;
2914 ncookies--;
2915 }
2916 vrele(vp);
2917 nfsm_clget;
2918 *tl = nfs_false;
2919 bp += NFSX_UNSIGNED;
2920 nfsm_clget;
2921 if (eofflag)
2922 *tl = nfs_true;
2923 else
2924 *tl = nfs_false;
2925 bp += NFSX_UNSIGNED;
2926 if (mp != mb) {
2927 if (bp < be)
2928 mp->m_len = bp - mtod(mp, caddr_t);
2929 } else
2930 mp->m_len += bp - bpos;
2931 FREE((caddr_t)cookies, M_TEMP);
2932 FREE((caddr_t)rbuf, M_TEMP);
2933 nfsm_srvdone;
2934 }
2935
2936
2937
2938
2939 int
2940 nfsrv_commit(nfsd, slp, procp, mrq)
2941 struct nfsrv_descript *nfsd;
2942 struct nfssvc_sock *slp;
2943 struct proc *procp;
2944 struct mbuf **mrq;
2945 {
2946 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2947 struct mbuf *nam = nfsd->nd_nam;
2948 caddr_t dpos = nfsd->nd_dpos;
2949 struct ucred *cred = &nfsd->nd_cr;
2950 struct vattr bfor, aft;
2951 struct vnode *vp;
2952 nfsfh_t nfh;
2953 fhandle_t *fhp;
2954 u_int32_t *tl;
2955 int32_t t1;
2956 caddr_t bpos;
2957 int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt;
2958 char *cp2;
2959 struct mbuf *mb, *mb2, *mreq;
2960 u_quad_t frev, off;
2961
2962 fhp = &nfh.fh_generic;
2963 nfsm_srvmtofh(fhp);
2964 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2965
2966
2967
2968
2969
2970 off = fxdr_hyper(tl);
2971 tl += 2;
2972 cnt = fxdr_unsigned(int, *tl);
2973 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
2974 &rdonly, (nfsd->nd_flag & ND_KERBAUTH));
2975 if (error) {
2976 nfsm_reply(2 * NFSX_UNSIGNED);
2977 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
2978 return (0);
2979 }
2980 for_ret = VOP_GETATTR(vp, &bfor, cred, procp);
2981 error = VOP_FSYNC(vp, cred, MNT_WAIT, procp);
2982 aft_ret = VOP_GETATTR(vp, &aft, cred, procp);
2983 vput(vp);
2984 nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF);
2985 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
2986 if (!error) {
2987 nfsm_build(tl, u_int32_t *, NFSX_V3WRITEVERF);
2988 *tl++ = txdr_unsigned(boottime.tv_sec);
2989 *tl = txdr_unsigned(boottime.tv_usec);
2990 } else
2991 return (0);
2992 nfsm_srvdone;
2993 }
2994
2995
2996
2997
2998 int
2999 nfsrv_statfs(nfsd, slp, procp, mrq)
3000 struct nfsrv_descript *nfsd;
3001 struct nfssvc_sock *slp;
3002 struct proc *procp;
3003 struct mbuf **mrq;
3004 {
3005 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3006 struct mbuf *nam = nfsd->nd_nam;
3007 caddr_t dpos = nfsd->nd_dpos;
3008 struct ucred *cred = &nfsd->nd_cr;
3009 struct statfs *sf;
3010 struct nfs_statfs *sfp;
3011 u_int32_t *tl;
3012 int32_t t1;
3013 caddr_t bpos;
3014 int error = 0, rdonly, getret = 1;
3015 int v3 = (nfsd->nd_flag & ND_NFSV3);
3016 char *cp2;
3017 struct mbuf *mb, *mb2, *mreq;
3018 struct vnode *vp;
3019 struct vattr at;
3020 nfsfh_t nfh;
3021 fhandle_t *fhp;
3022 struct statfs statfs;
3023 u_quad_t frev, tval;
3024
3025 fhp = &nfh.fh_generic;
3026 nfsm_srvmtofh(fhp);
3027 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
3028 &rdonly, (nfsd->nd_flag & ND_KERBAUTH));
3029 if (error) {
3030 nfsm_reply(NFSX_UNSIGNED);
3031 nfsm_srvpostop_attr(getret, &at);
3032 return (0);
3033 }
3034 sf = &statfs;
3035 error = VFS_STATFS(vp->v_mount, sf, procp);
3036 getret = VOP_GETATTR(vp, &at, cred, procp);
3037 vput(vp);
3038 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3));
3039 if (v3)
3040 nfsm_srvpostop_attr(getret, &at);
3041 if (error)
3042 return (0);
3043 nfsm_build(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
3044 if (v3) {
3045 tval = (u_quad_t)sf->f_blocks;
3046 tval *= (u_quad_t)sf->f_bsize;
3047 txdr_hyper(tval, &sfp->sf_tbytes);
3048 tval = (u_quad_t)sf->f_bfree;
3049 tval *= (u_quad_t)sf->f_bsize;
3050 txdr_hyper(tval, &sfp->sf_fbytes);
3051 tval = (u_quad_t)sf->f_bavail;
3052 tval *= (u_quad_t)sf->f_bsize;
3053 txdr_hyper(tval, &sfp->sf_abytes);
3054 sfp->sf_tfiles.nfsuquad[0] = 0;
3055 sfp->sf_tfiles.nfsuquad[1] = txdr_unsigned(sf->f_files);
3056 sfp->sf_ffiles.nfsuquad[0] = 0;
3057 sfp->sf_ffiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
3058 sfp->sf_afiles.nfsuquad[0] = 0;
3059 sfp->sf_afiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
3060 sfp->sf_invarsec = 0;
3061 } else {
3062 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
3063 sfp->sf_bsize = txdr_unsigned(sf->f_bsize);
3064 sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
3065 sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
3066 sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
3067 }
3068 nfsm_srvdone;
3069 }
3070
3071
3072
3073
3074 int
3075 nfsrv_fsinfo(nfsd, slp, procp, mrq)
3076 struct nfsrv_descript *nfsd;
3077 struct nfssvc_sock *slp;
3078 struct proc *procp;
3079 struct mbuf **mrq;
3080 {
3081 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3082 struct mbuf *nam = nfsd->nd_nam;
3083 caddr_t dpos = nfsd->nd_dpos;
3084 struct ucred *cred = &nfsd->nd_cr;
3085 u_int32_t *tl;
3086 struct nfsv3_fsinfo *sip;
3087 int32_t t1;
3088 caddr_t bpos;
3089 int error = 0, rdonly, getret = 1, pref;
3090 char *cp2;
3091 struct mbuf *mb, *mb2, *mreq;
3092 struct vnode *vp;
3093 struct vattr at;
3094 nfsfh_t nfh;
3095 fhandle_t *fhp;
3096 u_quad_t frev;
3097
3098 fhp = &nfh.fh_generic;
3099 nfsm_srvmtofh(fhp);
3100 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
3101 &rdonly, (nfsd->nd_flag & ND_KERBAUTH));
3102 if (error) {
3103 nfsm_reply(NFSX_UNSIGNED);
3104 nfsm_srvpostop_attr(getret, &at);
3105 return (0);
3106 }
3107 getret = VOP_GETATTR(vp, &at, cred, procp);
3108 vput(vp);
3109 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO);
3110 nfsm_srvpostop_attr(getret, &at);
3111 nfsm_build(sip, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
3112
3113
3114
3115
3116
3117
3118 if (slp->ns_so->so_type == SOCK_DGRAM)
3119 pref = NFS_MAXDGRAMDATA;
3120 else
3121 pref = NFS_MAXDATA;
3122 sip->fs_rtmax = txdr_unsigned(NFS_MAXDATA);
3123 sip->fs_rtpref = txdr_unsigned(pref);
3124 sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE);
3125 sip->fs_wtmax = txdr_unsigned(NFS_MAXDATA);
3126 sip->fs_wtpref = txdr_unsigned(pref);
3127 sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE);
3128 sip->fs_dtpref = txdr_unsigned(pref);
3129 sip->fs_maxfilesize.nfsuquad[0] = 0xffffffff;
3130 sip->fs_maxfilesize.nfsuquad[1] = 0xffffffff;
3131 sip->fs_timedelta.nfsv3_sec = 0;
3132 sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1);
3133 sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK |
3134 NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS |
3135 NFSV3FSINFO_CANSETTIME);
3136 nfsm_srvdone;
3137 }
3138
3139
3140
3141
3142 int
3143 nfsrv_pathconf(nfsd, slp, procp, mrq)
3144 struct nfsrv_descript *nfsd;
3145 struct nfssvc_sock *slp;
3146 struct proc *procp;
3147 struct mbuf **mrq;
3148 {
3149 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3150 struct mbuf *nam = nfsd->nd_nam;
3151 caddr_t dpos = nfsd->nd_dpos;
3152 struct ucred *cred = &nfsd->nd_cr;
3153 u_int32_t *tl;
3154 struct nfsv3_pathconf *pc;
3155 int32_t t1;
3156 caddr_t bpos;
3157 int error = 0, rdonly, getret = 1;
3158 register_t linkmax, namemax, chownres, notrunc;
3159 char *cp2;
3160 struct mbuf *mb, *mb2, *mreq;
3161 struct vnode *vp;
3162 struct vattr at;
3163 nfsfh_t nfh;
3164 fhandle_t *fhp;
3165 u_quad_t frev;
3166
3167 fhp = &nfh.fh_generic;
3168 nfsm_srvmtofh(fhp);
3169 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
3170 &rdonly, (nfsd->nd_flag & ND_KERBAUTH));
3171 if (error) {
3172 nfsm_reply(NFSX_UNSIGNED);
3173 nfsm_srvpostop_attr(getret, &at);
3174 return (0);
3175 }
3176 error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax);
3177 if (!error)
3178 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax);
3179 if (!error)
3180 error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres);
3181 if (!error)
3182 error = VOP_PATHCONF(vp, _PC_NO_TRUNC, ¬runc);
3183 getret = VOP_GETATTR(vp, &at, cred, procp);
3184 vput(vp);
3185 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF);
3186 nfsm_srvpostop_attr(getret, &at);
3187 if (error)
3188 return (0);
3189 nfsm_build(pc, struct nfsv3_pathconf *, NFSX_V3PATHCONF);
3190
3191 pc->pc_linkmax = txdr_unsigned(linkmax);
3192 pc->pc_namemax = txdr_unsigned(namemax);
3193 pc->pc_notrunc = txdr_unsigned(notrunc);
3194 pc->pc_chownrestricted = txdr_unsigned(chownres);
3195
3196
3197
3198
3199
3200
3201 pc->pc_caseinsensitive = nfs_false;
3202 pc->pc_casepreserving = nfs_true;
3203 nfsm_srvdone;
3204 }
3205
3206
3207
3208
3209
3210 int
3211 nfsrv_null(nfsd, slp, procp, mrq)
3212 struct nfsrv_descript *nfsd;
3213 struct nfssvc_sock *slp;
3214 struct proc *procp;
3215 struct mbuf **mrq;
3216 {
3217 struct mbuf *mrep = nfsd->nd_mrep;
3218 caddr_t bpos;
3219 int error = NFSERR_RETVOID;
3220 struct mbuf *mb, *mreq;
3221 u_quad_t frev;
3222
3223 nfsm_reply(0);
3224 return (0);
3225 }
3226
3227
3228
3229
3230
3231 int
3232 nfsrv_noop(nfsd, slp, procp, mrq)
3233 struct nfsrv_descript *nfsd;
3234 struct nfssvc_sock *slp;
3235 struct proc *procp;
3236 struct mbuf **mrq;
3237 {
3238 struct mbuf *mrep = nfsd->nd_mrep;
3239 caddr_t bpos;
3240 int error;
3241 struct mbuf *mb, *mreq;
3242 u_quad_t frev;
3243
3244 if (nfsd->nd_repstat)
3245 error = nfsd->nd_repstat;
3246 else
3247 error = EPROCUNAVAIL;
3248 nfsm_reply(0);
3249 return (0);
3250 }
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263 int
3264 nfsrv_access(vp, flags, cred, rdonly, p, override)
3265 struct vnode *vp;
3266 int flags;
3267 struct ucred *cred;
3268 int rdonly;
3269 struct proc *p;
3270 int override;
3271 {
3272 struct vattr vattr;
3273 int error;
3274
3275 if (flags & VWRITE) {
3276
3277
3278
3279
3280
3281
3282 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
3283 switch (vp->v_type) {
3284 case VREG:
3285 case VDIR:
3286 case VLNK:
3287 return (EROFS);
3288 default:
3289 break;
3290 }
3291 }
3292
3293
3294
3295
3296
3297 if ((vp->v_flag & VTEXT) && !uvm_vnp_uncache(vp))
3298 return (ETXTBSY);
3299 }
3300 error = VOP_ACCESS(vp, flags, cred, p);
3301
3302
3303
3304
3305 if (override && (error == EPERM || error == EACCES) &&
3306 VOP_GETATTR(vp, &vattr, cred, p) == 0 &&
3307 cred->cr_uid == vattr.va_uid)
3308 error = 0;
3309 return error;
3310 }