changes to make lfs_vget retrieve the IFILE inode like any other
[unix-history] / usr / src / sys / nfs / nfs_serv.c
CommitLineData
971b93e3
KM
1/*
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
7 *
dbf0c423 8 * %sccs.include.redist.c%
971b93e3 9 *
2c5b44a2 10 * @(#)nfs_serv.c 7.43 (Berkeley) %G%
971b93e3
KM
11 */
12
13/*
14 * nfs version 2 server calls to vnode ops
15 * - these routines generally have 3 phases
16 * 1 - break down and validate rpc request in mbuf list
17 * 2 - do the vnode ops for the request
36c3043b 18 * (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c)
971b93e3
KM
19 * 3 - build the rpc reply in an mbuf list
20 * nb:
21 * - do not mix the phases, since the nfsm_?? macros can return failures
f0f1cbaa 22 * on a bad rpc or similar and do not do any vrele() or vput()'s
971b93e3 23 *
36c3043b 24 * - the nfsm_reply() macro generates an nfs rpc reply with the nfs
971b93e3 25 * error number iff error != 0 whereas
f0f1cbaa
KM
26 * returning an error from the server function implies a fatal error
27 * such as a badly constructed rpc request that should be dropped without
28 * a reply.
971b93e3
KM
29 */
30
971b93e3 31#include "param.h"
74c40d5a 32#include "proc.h"
e587d97d 33#include "file.h"
236c2c19 34#include "namei.h"
971b93e3 35#include "vnode.h"
e587d97d
KM
36#include "mount.h"
37#include "mbuf.h"
058dee65 38
982c504e
KB
39#include "ufs/ufs/quota.h"
40#include "ufs/ufs/inode.h"
41#include "ufs/ufs/dir.h"
058dee65 42
971b93e3 43#include "nfsv2.h"
2c5b44a2 44#include "rpcv2.h"
971b93e3
KM
45#include "nfs.h"
46#include "xdr_subs.h"
47#include "nfsm_subs.h"
2c5b44a2 48#include "nqnfs.h"
971b93e3
KM
49
50/* Defs */
36c3043b
KM
51#define TRUE 1
52#define FALSE 0
971b93e3
KM
53
54/* Global vars */
55extern u_long nfs_procids[NFS_NPROCS];
56extern u_long nfs_xdrneg1;
57extern u_long nfs_false, nfs_true;
2c5b44a2 58nfstype nfs_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON,
d4e5799e 59 NFCHR, NFNON };
971b93e3
KM
60
61/*
62 * nfs getattr service
63 */
2c5b44a2
KM
64nfsrv_getattr(nfsd, mrep, md, dpos, cred, nam, mrq)
65 struct nfsd *nfsd;
971b93e3
KM
66 struct mbuf *mrep, *md;
67 caddr_t dpos;
68 struct ucred *cred;
2c5b44a2 69 struct mbuf *nam, **mrq;
971b93e3 70{
9238aa59 71 register struct nfsv2_fattr *fp;
971b93e3
KM
72 struct vattr va;
73 register struct vattr *vap = &va;
74 struct vnode *vp;
75 nfsv2fh_t nfh;
76 fhandle_t *fhp;
236c2c19 77 register u_long *tl;
0bd503ad
KM
78 register long t1;
79 caddr_t bpos;
2c5b44a2 80 int error = 0, rdonly, cache;
0bd503ad 81 char *cp2;
e8540f59 82 struct mbuf *mb, *mb2, *mreq;
2c5b44a2 83 u_quad_t frev;
971b93e3
KM
84
85 fhp = &nfh.fh_generic;
86 nfsm_srvmtofh(fhp);
2c5b44a2 87 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))
971b93e3 88 nfsm_reply(0);
2c5b44a2
KM
89 nqsrv_getl(vp, NQL_READ);
90 error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
971b93e3
KM
91 vput(vp);
92 nfsm_reply(NFSX_FATTR);
9238aa59 93 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
e8540f59 94 nfsm_srvfillattr;
971b93e3
KM
95 nfsm_srvdone;
96}
97
98/*
99 * nfs setattr service
100 */
2c5b44a2
KM
101nfsrv_setattr(nfsd, mrep, md, dpos, cred, nam, mrq)
102 struct nfsd *nfsd;
971b93e3
KM
103 struct mbuf *mrep, *md;
104 caddr_t dpos;
105 struct ucred *cred;
2c5b44a2 106 struct mbuf *nam, **mrq;
971b93e3
KM
107{
108 struct vattr va;
109 register struct vattr *vap = &va;
9238aa59
RM
110 register struct nfsv2_sattr *sp;
111 register struct nfsv2_fattr *fp;
971b93e3
KM
112 struct vnode *vp;
113 nfsv2fh_t nfh;
114 fhandle_t *fhp;
236c2c19 115 register u_long *tl;
0bd503ad
KM
116 register long t1;
117 caddr_t bpos;
2c5b44a2 118 int error = 0, rdonly, cache, duration2, cache2;
0bd503ad 119 char *cp2;
e8540f59 120 struct mbuf *mb, *mb2, *mreq;
2c5b44a2 121 u_quad_t frev, frev2;
971b93e3
KM
122
123 fhp = &nfh.fh_generic;
124 nfsm_srvmtofh(fhp);
2c5b44a2
KM
125 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_SATTR);
126 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))
971b93e3 127 nfsm_reply(0);
2c5b44a2
KM
128 nqsrv_getl(vp, NQL_WRITE);
129 if (error = nfsrv_access(vp, VWRITE, cred, rdonly, nfsd->nd_procp))
971b93e3 130 goto out;
3ee1461b 131 VATTR_NULL(vap);
971b93e3
KM
132 /*
133 * Nah nah nah nah na nah
134 * There is a bug in the Sun client that puts 0xffff in the mode
135 * field of sattr when it should put in 0xffffffff. The u_short
136 * doesn't sign extend.
137 * --> check the low order 2 bytes for 0xffff
138 */
9238aa59
RM
139 if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
140 vap->va_mode = nfstov_mode(sp->sa_mode);
141 if (sp->sa_uid != nfs_xdrneg1)
142 vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
143 if (sp->sa_gid != nfs_xdrneg1)
144 vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
e8540f59 145 if (sp->sa_size != nfs_xdrneg1)
9238aa59 146 vap->va_size = fxdr_unsigned(u_long, sp->sa_size);
e8540f59
KM
147 /*
148 * The usec field of sa_atime is overloaded with the va_flags field
149 * for 4.4BSD clients. Hopefully other clients always set both the
150 * sec and usec fields to -1 when not setting the atime.
151 */
152 if (sp->sa_atime.tv_sec != nfs_xdrneg1) {
153 vap->va_atime.tv_sec = fxdr_unsigned(long, sp->sa_atime.tv_sec);
154 vap->va_atime.tv_usec = 0;
36c3043b 155 }
e8540f59
KM
156 if (sp->sa_atime.tv_usec != nfs_xdrneg1)
157 vap->va_flags = fxdr_unsigned(u_long, sp->sa_atime.tv_usec);
9238aa59
RM
158 if (sp->sa_mtime.tv_sec != nfs_xdrneg1)
159 fxdr_time(&sp->sa_mtime, &vap->va_mtime);
2c5b44a2 160 if (error = VOP_SETATTR(vp, vap, cred, nfsd->nd_procp)) {
971b93e3
KM
161 vput(vp);
162 nfsm_reply(0);
163 }
2c5b44a2 164 error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
971b93e3
KM
165out:
166 vput(vp);
2c5b44a2 167 nfsm_reply(NFSX_FATTR + 2*NFSX_UNSIGNED);
9238aa59 168 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
e8540f59 169 nfsm_srvfillattr;
2c5b44a2
KM
170 if (nfsd->nd_nqlflag != NQL_NOVAL) {
171 nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
172 txdr_hyper(&frev2, tl);
173 }
971b93e3
KM
174 nfsm_srvdone;
175}
176
177/*
178 * nfs lookup rpc
179 */
2c5b44a2
KM
180nfsrv_lookup(nfsd, mrep, md, dpos, cred, nam, mrq)
181 struct nfsd *nfsd;
971b93e3
KM
182 struct mbuf *mrep, *md;
183 caddr_t dpos;
184 struct ucred *cred;
2c5b44a2 185 struct mbuf *nam, **mrq;
971b93e3 186{
9238aa59 187 register struct nfsv2_fattr *fp;
74c40d5a 188 struct nameidata nd;
971b93e3
KM
189 struct vnode *vp;
190 nfsv2fh_t nfh;
191 fhandle_t *fhp;
0bd503ad 192 register caddr_t cp;
236c2c19 193 register u_long *tl;
0bd503ad
KM
194 register long t1;
195 caddr_t bpos;
2c5b44a2 196 int error = 0, lflag = 0, rdonly, cache, duration2, cache2, len;
0bd503ad 197 char *cp2;
e8540f59 198 struct mbuf *mb, *mb2, *mreq;
971b93e3 199 struct vattr va, *vap = &va;
2c5b44a2 200 u_quad_t frev, frev2;
971b93e3
KM
201
202 fhp = &nfh.fh_generic;
2c5b44a2
KM
203 if (nfsd->nd_nqlflag != NQL_NOVAL) {
204 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
205 if (*tl) {
206 lflag = fxdr_unsigned(int, *tl);
207 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
208 duration2 = fxdr_unsigned(int, *tl);
209 }
210 }
971b93e3
KM
211 nfsm_srvmtofh(fhp);
212 nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
74c40d5a 213 nd.ni_cred = cred;
2c5b44a2
KM
214 nd.ni_nameiop = LOOKUP | LOCKLEAF | SAVESTART;
215 if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos, nfsd->nd_procp))
971b93e3 216 nfsm_reply(0);
2c5b44a2
KM
217 nqsrv_getl(nd.ni_startdir, NQL_READ);
218 vrele(nd.ni_startdir);
74c40d5a 219 vp = nd.ni_vp;
971b93e3 220 bzero((caddr_t)fhp, sizeof(nfh));
54fb9dc2 221 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
971b93e3
KM
222 if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) {
223 vput(vp);
224 nfsm_reply(0);
225 }
2c5b44a2
KM
226 if (lflag)
227 (void) nqsrv_getlease(vp, &duration2, lflag, nfsd,
228 nam, &cache2, &frev2, cred);
229 error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
971b93e3 230 vput(vp);
2c5b44a2
KM
231 nfsm_reply(NFSX_FH + NFSX_FATTR + 5*NFSX_UNSIGNED);
232 if (nfsd->nd_nqlflag != NQL_NOVAL) {
233 if (lflag) {
234 nfsm_build(tl, u_long *, 5*NFSX_UNSIGNED);
235 *tl++ = txdr_unsigned(lflag);
236 *tl++ = txdr_unsigned(cache2);
237 *tl++ = txdr_unsigned(duration2);
238 txdr_hyper(&frev2, tl);
239 } else {
240 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
241 *tl = 0;
242 }
243 }
971b93e3 244 nfsm_srvfhtom(fhp);
9238aa59 245 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
e8540f59 246 nfsm_srvfillattr;
971b93e3
KM
247 nfsm_srvdone;
248}
249
250/*
251 * nfs readlink service
252 */
2c5b44a2
KM
253nfsrv_readlink(nfsd, mrep, md, dpos, cred, nam, mrq)
254 struct nfsd *nfsd;
971b93e3
KM
255 struct mbuf *mrep, *md;
256 caddr_t dpos;
257 struct ucred *cred;
2c5b44a2 258 struct mbuf *nam, **mrq;
971b93e3 259{
f0f1cbaa 260 struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
971b93e3
KM
261 register struct iovec *ivp = iv;
262 register struct mbuf *mp;
236c2c19 263 register u_long *tl;
0bd503ad
KM
264 register long t1;
265 caddr_t bpos;
2c5b44a2 266 int error = 0, rdonly, cache, i, tlen, len;
0bd503ad 267 char *cp2;
e8540f59 268 struct mbuf *mb, *mb2, *mp2, *mp3, *mreq;
971b93e3
KM
269 struct vnode *vp;
270 nfsv2fh_t nfh;
271 fhandle_t *fhp;
272 struct uio io, *uiop = &io;
2c5b44a2 273 u_quad_t frev;
971b93e3
KM
274
275 fhp = &nfh.fh_generic;
276 nfsm_srvmtofh(fhp);
277 len = 0;
278 i = 0;
279 while (len < NFS_MAXPATHLEN) {
280 MGET(mp, M_WAIT, MT_DATA);
f0f1cbaa 281 MCLGET(mp, M_WAIT);
971b93e3
KM
282 mp->m_len = NFSMSIZ(mp);
283 if (len == 0)
284 mp3 = mp2 = mp;
f0f1cbaa 285 else {
971b93e3 286 mp2->m_next = mp;
f0f1cbaa
KM
287 mp2 = mp;
288 }
971b93e3
KM
289 if ((len+mp->m_len) > NFS_MAXPATHLEN) {
290 mp->m_len = NFS_MAXPATHLEN-len;
291 len = NFS_MAXPATHLEN;
292 } else
293 len += mp->m_len;
294 ivp->iov_base = mtod(mp, caddr_t);
295 ivp->iov_len = mp->m_len;
296 i++;
297 ivp++;
298 }
299 uiop->uio_iov = iv;
300 uiop->uio_iovcnt = i;
301 uiop->uio_offset = 0;
302 uiop->uio_resid = len;
303 uiop->uio_rw = UIO_READ;
304 uiop->uio_segflg = UIO_SYSSPACE;
236c2c19 305 uiop->uio_procp = (struct proc *)0;
2c5b44a2 306 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly)) {
971b93e3
KM
307 m_freem(mp3);
308 nfsm_reply(0);
309 }
310 if (vp->v_type != VLNK) {
311 error = EINVAL;
312 goto out;
313 }
2c5b44a2 314 nqsrv_getl(vp, NQL_READ);
971b93e3
KM
315 error = VOP_READLINK(vp, uiop, cred);
316out:
317 vput(vp);
318 if (error)
319 m_freem(mp3);
320 nfsm_reply(NFSX_UNSIGNED);
321 if (uiop->uio_resid > 0) {
322 len -= uiop->uio_resid;
323 tlen = nfsm_rndup(len);
324 nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len);
325 }
236c2c19
KM
326 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
327 *tl = txdr_unsigned(len);
971b93e3
KM
328 mb->m_next = mp3;
329 nfsm_srvdone;
330}
331
332/*
333 * nfs read service
334 */
2c5b44a2
KM
335nfsrv_read(nfsd, mrep, md, dpos, cred, nam, mrq)
336 struct nfsd *nfsd;
971b93e3
KM
337 struct mbuf *mrep, *md;
338 caddr_t dpos;
339 struct ucred *cred;
2c5b44a2 340 struct mbuf *nam, **mrq;
971b93e3 341{
170bfd05
KM
342 register struct iovec *iv;
343 struct iovec *iv2;
f0f1cbaa 344 register struct mbuf *m;
9238aa59 345 register struct nfsv2_fattr *fp;
236c2c19 346 register u_long *tl;
0bd503ad
KM
347 register long t1;
348 caddr_t bpos;
2c5b44a2 349 int error = 0, rdonly, cache, i, cnt, len, left, siz, tlen;
0bd503ad 350 char *cp2;
e8540f59 351 struct mbuf *mb, *mb2, *mreq;
2c5b44a2 352 struct mbuf *m2;
971b93e3
KM
353 struct vnode *vp;
354 nfsv2fh_t nfh;
355 fhandle_t *fhp;
356 struct uio io, *uiop = &io;
357 struct vattr va, *vap = &va;
971b93e3 358 off_t off;
2c5b44a2 359 u_quad_t frev;
971b93e3
KM
360
361 fhp = &nfh.fh_generic;
362 nfsm_srvmtofh(fhp);
2c5b44a2 363 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
236c2c19 364 off = fxdr_unsigned(off_t, *tl);
971b93e3 365 nfsm_srvstrsiz(cnt, NFS_MAXDATA);
2c5b44a2 366 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))
971b93e3 367 nfsm_reply(0);
2c5b44a2
KM
368 nqsrv_getl(vp, NQL_READ);
369 if (error = nfsrv_access(vp, VREAD | VEXEC, cred, rdonly, nfsd->nd_procp)) {
971b93e3
KM
370 vput(vp);
371 nfsm_reply(0);
372 }
2c5b44a2 373 if (error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp)) {
971b93e3
KM
374 vput(vp);
375 nfsm_reply(0);
376 }
2c5b44a2
KM
377 if (off >= vap->va_size)
378 cnt = 0;
379 else if ((off + cnt) > vap->va_size)
380 cnt = nfsm_rndup(vap->va_size - off);
381 nfsm_reply(NFSX_FATTR+NFSX_UNSIGNED+nfsm_rndup(cnt));
9238aa59 382 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
2c5b44a2
KM
383 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
384 len = left = cnt;
385 if (cnt > 0) {
386 /*
387 * Generate the mbuf list with the uio_iov ref. to it.
388 */
389 i = 0;
390 m = m2 = mb;
391 MALLOC(iv, struct iovec *,
392 ((NFS_MAXDATA+MLEN-1)/MLEN) * sizeof (struct iovec),
393 M_TEMP, M_WAITOK);
394 iv2 = iv;
395 while (left > 0) {
396 siz = MIN(M_TRAILINGSPACE(m), left);
397 if (siz > 0) {
398 m->m_len += siz;
399 iv->iov_base = bpos;
400 iv->iov_len = siz;
401 iv++;
402 i++;
403 left -= siz;
404 }
405 if (left > 0) {
406 MGET(m, M_WAIT, MT_DATA);
407 MCLGET(m, M_WAIT);
408 m->m_len = 0;
409 m2->m_next = m;
410 m2 = m;
411 bpos = mtod(m, caddr_t);
412 }
413 }
414 uiop->uio_iov = iv2;
415 uiop->uio_iovcnt = i;
416 uiop->uio_offset = off;
417 uiop->uio_resid = cnt;
418 uiop->uio_rw = UIO_READ;
419 uiop->uio_segflg = UIO_SYSSPACE;
420 error = VOP_READ(vp, uiop, IO_NODELOCKED, cred);
421 off = uiop->uio_offset;
422 FREE((caddr_t)iv2, M_TEMP);
423 if (error || (error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp))) {
424 m_freem(mreq);
425 vput(vp);
426 nfsm_reply(0);
427 }
428 } else
429 uiop->uio_resid = 0;
430 vput(vp);
e8540f59 431 nfsm_srvfillattr;
25951042 432 len -= uiop->uio_resid;
2c5b44a2
KM
433 tlen = nfsm_rndup(len);
434 if (cnt != tlen || tlen != len)
435 nfsm_adj(mb, cnt-tlen, tlen-len);
236c2c19 436 *tl = txdr_unsigned(len);
971b93e3
KM
437 nfsm_srvdone;
438}
439
440/*
441 * nfs write service
442 */
2c5b44a2
KM
443nfsrv_write(nfsd, mrep, md, dpos, cred, nam, mrq)
444 struct nfsd *nfsd;
445 struct mbuf *mrep, *md;
971b93e3
KM
446 caddr_t dpos;
447 struct ucred *cred;
2c5b44a2 448 struct mbuf *nam, **mrq;
971b93e3
KM
449{
450 register struct iovec *ivp;
451 register struct mbuf *mp;
9238aa59 452 register struct nfsv2_fattr *fp;
f0f1cbaa 453 struct iovec iv[NFS_MAXIOVEC];
971b93e3
KM
454 struct vattr va;
455 register struct vattr *vap = &va;
236c2c19 456 register u_long *tl;
0bd503ad
KM
457 register long t1;
458 caddr_t bpos;
2c5b44a2 459 int error = 0, rdonly, cache, siz, len, xfer;
0bd503ad 460 char *cp2;
e8540f59 461 struct mbuf *mb, *mb2, *mreq;
971b93e3
KM
462 struct vnode *vp;
463 nfsv2fh_t nfh;
464 fhandle_t *fhp;
465 struct uio io, *uiop = &io;
466 off_t off;
2c5b44a2 467 u_quad_t frev;
971b93e3
KM
468
469 fhp = &nfh.fh_generic;
470 nfsm_srvmtofh(fhp);
2c5b44a2 471 nfsm_dissect(tl, u_long *, 4*NFSX_UNSIGNED);
236c2c19
KM
472 off = fxdr_unsigned(off_t, *++tl);
473 tl += 2;
474 len = fxdr_unsigned(long, *tl);
971b93e3
KM
475 if (len > NFS_MAXDATA || len <= 0) {
476 error = EBADRPC;
477 nfsm_reply(0);
478 }
479 if (dpos == (mtod(md, caddr_t)+md->m_len)) {
480 mp = md->m_next;
481 if (mp == NULL) {
482 error = EBADRPC;
483 nfsm_reply(0);
484 }
485 } else {
486 mp = md;
487 siz = dpos-mtod(mp, caddr_t);
488 mp->m_len -= siz;
489 NFSMADV(mp, siz);
490 }
2c5b44a2 491 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))
971b93e3 492 nfsm_reply(0);
2c5b44a2
KM
493 nqsrv_getl(vp, NQL_WRITE);
494 if (error = nfsrv_access(vp, VWRITE, cred, rdonly, nfsd->nd_procp)) {
971b93e3
KM
495 vput(vp);
496 nfsm_reply(0);
497 }
498 uiop->uio_resid = 0;
499 uiop->uio_rw = UIO_WRITE;
500 uiop->uio_segflg = UIO_SYSSPACE;
236c2c19 501 uiop->uio_procp = (struct proc *)0;
971b93e3 502 /*
f0f1cbaa 503 * Do up to NFS_MAXIOVEC mbufs of write each iteration of the
971b93e3
KM
504 * loop until done.
505 */
506 while (len > 0 && uiop->uio_resid == 0) {
507 ivp = iv;
508 siz = 0;
509 uiop->uio_iov = ivp;
510 uiop->uio_iovcnt = 0;
511 uiop->uio_offset = off;
f0f1cbaa 512 while (len > 0 && uiop->uio_iovcnt < NFS_MAXIOVEC && mp != NULL) {
971b93e3
KM
513 ivp->iov_base = mtod(mp, caddr_t);
514 if (len < mp->m_len)
515 ivp->iov_len = xfer = len;
516 else
517 ivp->iov_len = xfer = mp->m_len;
518#ifdef notdef
519 /* Not Yet .. */
520 if (M_HASCL(mp) && (((u_long)ivp->iov_base) & CLOFSET) == 0)
521 ivp->iov_op = NULL; /* what should it be ?? */
522 else
523 ivp->iov_op = NULL;
524#endif
525 uiop->uio_iovcnt++;
526 ivp++;
527 len -= xfer;
528 siz += xfer;
529 mp = mp->m_next;
530 }
531 if (len > 0 && mp == NULL) {
532 error = EBADRPC;
533 vput(vp);
534 nfsm_reply(0);
535 }
536 uiop->uio_resid = siz;
e9843ca3 537 if (error = VOP_WRITE(vp, uiop, IO_SYNC | IO_NODELOCKED,
971b93e3
KM
538 cred)) {
539 vput(vp);
540 nfsm_reply(0);
541 }
e9843ca3 542 off = uiop->uio_offset;
971b93e3 543 }
2c5b44a2 544 error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
971b93e3
KM
545 vput(vp);
546 nfsm_reply(NFSX_FATTR);
9238aa59 547 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
e8540f59 548 nfsm_srvfillattr;
971b93e3
KM
549 nfsm_srvdone;
550}
551
552/*
553 * nfs create service
554 * now does a truncate to 0 length via. setattr if it already exists
555 */
2c5b44a2
KM
556nfsrv_create(nfsd, mrep, md, dpos, cred, nam, mrq)
557 struct nfsd *nfsd;
558 struct mbuf *mrep, *md;
971b93e3
KM
559 caddr_t dpos;
560 struct ucred *cred;
2c5b44a2 561 struct mbuf *nam, **mrq;
971b93e3 562{
9238aa59 563 register struct nfsv2_fattr *fp;
971b93e3
KM
564 struct vattr va;
565 register struct vattr *vap = &va;
74c40d5a 566 struct nameidata nd;
0bd503ad 567 register caddr_t cp;
236c2c19 568 register u_long *tl;
0bd503ad
KM
569 register long t1;
570 caddr_t bpos;
2c5b44a2 571 int error = 0, rdev, cache, len;
0bd503ad 572 char *cp2;
e8540f59 573 struct mbuf *mb, *mb2, *mreq;
971b93e3
KM
574 struct vnode *vp;
575 nfsv2fh_t nfh;
576 fhandle_t *fhp;
2c5b44a2 577 u_quad_t frev;
971b93e3 578
74c40d5a 579 nd.ni_nameiop = 0;
971b93e3
KM
580 fhp = &nfh.fh_generic;
581 nfsm_srvmtofh(fhp);
582 nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
74c40d5a
KM
583 nd.ni_cred = cred;
584 nd.ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF | SAVESTART;
2c5b44a2 585 if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos, nfsd->nd_procp))
971b93e3 586 nfsm_reply(0);
3ee1461b 587 VATTR_NULL(vap);
2c5b44a2 588 nfsm_dissect(tl, u_long *, NFSX_SATTR);
971b93e3
KM
589 /*
590 * Iff doesn't exist, create it
591 * otherwise just truncate to 0 length
592 * should I set the mode too ??
593 */
74c40d5a 594 if (nd.ni_vp == NULL) {
236c2c19 595 vap->va_type = IFTOVT(fxdr_unsigned(u_long, *tl));
4249699a
KM
596 if (vap->va_type == VNON)
597 vap->va_type = VREG;
236c2c19
KM
598 vap->va_mode = nfstov_mode(*tl);
599 rdev = fxdr_unsigned(long, *(tl+3));
1c89915d 600 if (vap->va_type == VREG || vap->va_type == VSOCK) {
5e03b55d 601 p->p_spare[1]--;
74c40d5a 602 vrele(nd.ni_startdir);
2c5b44a2
KM
603 nqsrv_getl(nd.ni_dvp, NQL_WRITE);
604 if (error = VOP_CREATE(&nd, vap, nfsd->nd_procp))
d4e5799e 605 nfsm_reply(0);
74c40d5a 606 FREE(nd.ni_pnbuf, M_NAMEI);
d4e5799e
KM
607 } else if (vap->va_type == VCHR || vap->va_type == VBLK ||
608 vap->va_type == VFIFO) {
609 if (vap->va_type == VCHR && rdev == 0xffffffff)
610 vap->va_type = VFIFO;
611 if (vap->va_type == VFIFO) {
612#ifndef FIFO
74c40d5a
KM
613 VOP_ABORTOP(&nd);
614 vput(nd.ni_dvp);
d4e5799e 615 error = ENXIO;
74c40d5a 616 goto out;
d4e5799e 617#endif /* FIFO */
2c5b44a2 618 } else if (error = suser(cred, (u_short *)0)) {
74c40d5a
KM
619 VOP_ABORTOP(&nd);
620 vput(nd.ni_dvp);
621 goto out;
d4e5799e
KM
622 } else
623 vap->va_rdev = (dev_t)rdev;
2c5b44a2
KM
624 nqsrv_getl(nd.ni_dvp, NQL_WRITE);
625 if (error = VOP_MKNOD(&nd, vap, cred, nfsd->nd_procp)) {
5e03b55d 626 p->p_spare[1]--;
74c40d5a 627 vrele(nd.ni_startdir);
d4e5799e 628 nfsm_reply(0);
74c40d5a
KM
629 }
630 nd.ni_nameiop &= ~(OPMASK | LOCKPARENT | SAVESTART);
631 nd.ni_nameiop |= LOOKUP;
5e03b55d 632 p->p_spare[1]--;
2c5b44a2 633 if (error = lookup(&nd, nfsd->nd_procp)) {
74c40d5a 634 free(nd.ni_pnbuf, M_NAMEI);
d4e5799e 635 nfsm_reply(0);
74c40d5a
KM
636 }
637 FREE(nd.ni_pnbuf, M_NAMEI);
638 if (nd.ni_more) {
639 vrele(nd.ni_dvp);
640 vput(nd.ni_vp);
641 VOP_ABORTOP(&nd);
642 error = EINVAL;
643 nfsm_reply(0);
644 }
d4e5799e 645 } else {
74c40d5a
KM
646 VOP_ABORTOP(&nd);
647 vput(nd.ni_dvp);
d4e5799e 648 error = ENXIO;
74c40d5a 649 goto out;
d4e5799e 650 }
74c40d5a 651 vp = nd.ni_vp;
971b93e3 652 } else {
5e03b55d 653 p->p_spare[1]--;
74c40d5a
KM
654 vrele(nd.ni_startdir);
655 free(nd.ni_pnbuf, M_NAMEI);
656 vp = nd.ni_vp;
657 if (nd.ni_dvp == vp)
658 vrele(nd.ni_dvp);
639383fa 659 else
74c40d5a
KM
660 vput(nd.ni_dvp);
661 VOP_ABORTOP(&nd);
971b93e3 662 vap->va_size = 0;
2c5b44a2
KM
663 nqsrv_getl(vp, NQL_WRITE);
664 if (error = VOP_SETATTR(vp, vap, cred, nfsd->nd_procp)) {
383e7b4c 665 vput(vp);
971b93e3 666 nfsm_reply(0);
383e7b4c 667 }
971b93e3 668 }
971b93e3 669 bzero((caddr_t)fhp, sizeof(nfh));
54fb9dc2 670 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
971b93e3
KM
671 if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) {
672 vput(vp);
673 nfsm_reply(0);
674 }
2c5b44a2 675 error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
971b93e3
KM
676 vput(vp);
677 nfsm_reply(NFSX_FH+NFSX_FATTR);
678 nfsm_srvfhtom(fhp);
9238aa59 679 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
e8540f59 680 nfsm_srvfillattr;
971b93e3
KM
681 return (error);
682nfsmout:
74c40d5a 683 if (nd.ni_nameiop)
5e03b55d 684 p->p_spare[1]--, vrele(nd.ni_startdir);
74c40d5a
KM
685 VOP_ABORTOP(&nd);
686 if (nd.ni_dvp == nd.ni_vp)
687 vrele(nd.ni_dvp);
639383fa 688 else
74c40d5a
KM
689 vput(nd.ni_dvp);
690 if (nd.ni_vp)
691 vput(nd.ni_vp);
971b93e3 692 return (error);
74c40d5a
KM
693
694out:
5e03b55d 695 p->p_spare[1]--;
74c40d5a
KM
696 vrele(nd.ni_startdir);
697 free(nd.ni_pnbuf, M_NAMEI);
698 nfsm_reply(0);
971b93e3
KM
699}
700
701/*
702 * nfs remove service
703 */
2c5b44a2
KM
704nfsrv_remove(nfsd, mrep, md, dpos, cred, nam, mrq)
705 struct nfsd *nfsd;
706 struct mbuf *mrep, *md;
971b93e3
KM
707 caddr_t dpos;
708 struct ucred *cred;
2c5b44a2 709 struct mbuf *nam, **mrq;
971b93e3 710{
74c40d5a 711 struct nameidata nd;
236c2c19 712 register u_long *tl;
0bd503ad
KM
713 register long t1;
714 caddr_t bpos;
2c5b44a2 715 int error = 0, cache, len;
0bd503ad 716 char *cp2;
e8540f59 717 struct mbuf *mb, *mreq;
971b93e3
KM
718 struct vnode *vp;
719 nfsv2fh_t nfh;
720 fhandle_t *fhp;
2c5b44a2 721 u_quad_t frev;
971b93e3
KM
722
723 fhp = &nfh.fh_generic;
724 nfsm_srvmtofh(fhp);
725 nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
74c40d5a
KM
726 nd.ni_cred = cred;
727 nd.ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
2c5b44a2 728 if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos, nfsd->nd_procp))
971b93e3 729 nfsm_reply(0);
74c40d5a 730 vp = nd.ni_vp;
971b93e3 731 if (vp->v_type == VDIR &&
2c5b44a2 732 (error = suser(cred, (u_short *)0)))
971b93e3
KM
733 goto out;
734 /*
4b0bcec3 735 * The root of a mounted filesystem cannot be deleted.
971b93e3
KM
736 */
737 if (vp->v_flag & VROOT) {
738 error = EBUSY;
739 goto out;
740 }
741 if (vp->v_flag & VTEXT)
8986c97c 742 (void) vnode_pager_uncache(vp);
971b93e3 743out:
66955caf 744 if (!error) {
2c5b44a2
KM
745 nqsrv_getl(nd.ni_dvp, NQL_WRITE);
746 nqsrv_getl(vp, NQL_WRITE);
747 error = VOP_REMOVE(&nd, nfsd->nd_procp);
66955caf 748 } else {
74c40d5a
KM
749 VOP_ABORTOP(&nd);
750 if (nd.ni_dvp == vp)
751 vrele(nd.ni_dvp);
639383fa 752 else
74c40d5a 753 vput(nd.ni_dvp);
66955caf
KM
754 vput(vp);
755 }
971b93e3
KM
756 nfsm_reply(0);
757 nfsm_srvdone;
758}
759
760/*
761 * nfs rename service
971b93e3 762 */
2c5b44a2
KM
763nfsrv_rename(nfsd, mrep, md, dpos, cred, nam, mrq)
764 struct nfsd *nfsd;
765 struct mbuf *mrep, *md;
971b93e3
KM
766 caddr_t dpos;
767 struct ucred *cred;
2c5b44a2 768 struct mbuf *nam, **mrq;
971b93e3 769{
236c2c19 770 register u_long *tl;
0bd503ad
KM
771 register long t1;
772 caddr_t bpos;
2c5b44a2 773 int error = 0, rdonly, cache, len, len2;
0bd503ad 774 char *cp2;
e8540f59 775 struct mbuf *mb, *mreq;
74c40d5a 776 struct nameidata fromnd, tond;
971b93e3
KM
777 struct vnode *fvp, *tvp, *tdvp;
778 nfsv2fh_t fnfh, tnfh;
779 fhandle_t *ffhp, *tfhp;
2c5b44a2
KM
780 u_quad_t frev;
781 uid_t saved_uid;
971b93e3 782
971b93e3
KM
783 ffhp = &fnfh.fh_generic;
784 tfhp = &tnfh.fh_generic;
74c40d5a
KM
785 fromnd.ni_nameiop = 0;
786 tond.ni_nameiop = 0;
971b93e3
KM
787 nfsm_srvmtofh(ffhp);
788 nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
789 /*
2c5b44a2
KM
790 * Remember our original uid so that we can reset cr_uid before
791 * the second nfs_namei() call, in case it is remapped.
971b93e3 792 */
2c5b44a2 793 saved_uid = cred->cr_uid;
74c40d5a
KM
794 fromnd.ni_cred = cred;
795 fromnd.ni_nameiop = DELETE | WANTPARENT | SAVESTART;
2c5b44a2 796 if (error = nfs_namei(&fromnd, ffhp, len, nfsd->nd_slp, nam, &md, &dpos, nfsd->nd_procp))
971b93e3 797 nfsm_reply(0);
74c40d5a 798 fvp = fromnd.ni_vp;
971b93e3 799 nfsm_srvmtofh(tfhp);
f0f1cbaa 800 nfsm_strsiz(len2, NFS_MAXNAMLEN);
2c5b44a2 801 cred->cr_uid = saved_uid;
ffe6f482 802 tond.ni_cred = cred;
10bae9ee 803 tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE
74c40d5a 804 | SAVESTART;
2c5b44a2 805 if (error = nfs_namei(&tond, tfhp, len2, nfsd->nd_slp, nam, &md, &dpos, nfsd->nd_procp)) {
74c40d5a
KM
806 VOP_ABORTOP(&fromnd);
807 vrele(fromnd.ni_dvp);
66955caf
KM
808 vrele(fvp);
809 goto out1;
810 }
36c3043b
KM
811 tdvp = tond.ni_dvp;
812 tvp = tond.ni_vp;
971b93e3
KM
813 if (tvp != NULL) {
814 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
815 error = EISDIR;
816 goto out;
817 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
818 error = ENOTDIR;
819 goto out;
820 }
2c5b44a2
KM
821 if (tvp->v_type == VDIR && tvp->v_mountedhere) {
822 error = EXDEV;
823 goto out;
824 }
825 }
826 if (fvp->v_type == VDIR && fvp->v_mountedhere) {
827 error = EBUSY;
828 goto out;
971b93e3 829 }
971b93e3
KM
830 if (fvp->v_mount != tdvp->v_mount) {
831 error = EXDEV;
832 goto out;
833 }
74c40d5a 834 if (fvp == tdvp)
971b93e3 835 error = EINVAL;
74c40d5a
KM
836 /*
837 * If source is the same as the destination (that is the
838 * same vnode with the same name in the same directory),
839 * then there is nothing to do.
840 */
841 if (fvp == tvp && fromnd.ni_dvp == tdvp &&
842 fromnd.ni_namelen == tond.ni_namelen &&
843 !bcmp(fromnd.ni_ptr, tond.ni_ptr, fromnd.ni_namelen))
844 error = -1;
971b93e3 845out:
66955caf 846 if (!error) {
2c5b44a2
KM
847 nqsrv_getl(fromnd.ni_dvp, NQL_WRITE);
848 nqsrv_getl(tdvp, NQL_WRITE);
849 if (tvp)
850 nqsrv_getl(tvp, NQL_WRITE);
851 error = VOP_RENAME(&fromnd, &tond, nfsd->nd_procp);
66955caf
KM
852 } else {
853 VOP_ABORTOP(&tond);
639383fa
KM
854 if (tdvp == tvp)
855 vrele(tdvp);
856 else
857 vput(tdvp);
66955caf
KM
858 if (tvp)
859 vput(tvp);
74c40d5a
KM
860 VOP_ABORTOP(&fromnd);
861 vrele(fromnd.ni_dvp);
66955caf 862 vrele(fvp);
971b93e3 863 }
5e03b55d 864 p->p_spare[1]--;
10bae9ee 865 vrele(tond.ni_startdir);
74c40d5a 866 FREE(tond.ni_pnbuf, M_NAMEI);
971b93e3 867out1:
5e03b55d 868 p->p_spare[1]--;
74c40d5a
KM
869 vrele(fromnd.ni_startdir);
870 FREE(fromnd.ni_pnbuf, M_NAMEI);
971b93e3
KM
871 nfsm_reply(0);
872 return (error);
74c40d5a 873
971b93e3 874nfsmout:
74c40d5a 875 if (tond.ni_nameiop) {
5e03b55d 876 p->p_spare[1]--;
74c40d5a
KM
877 vrele(tond.ni_startdir);
878 FREE(tond.ni_pnbuf, M_NAMEI);
879 }
880 if (fromnd.ni_nameiop) {
5e03b55d 881 p->p_spare[1]--;
74c40d5a
KM
882 vrele(fromnd.ni_startdir);
883 FREE(fromnd.ni_pnbuf, M_NAMEI);
884 VOP_ABORTOP(&fromnd);
885 vrele(fromnd.ni_dvp);
886 vrele(fvp);
887 }
971b93e3
KM
888 return (error);
889}
890
891/*
892 * nfs link service
893 */
2c5b44a2
KM
894nfsrv_link(nfsd, mrep, md, dpos, cred, nam, mrq)
895 struct nfsd *nfsd;
896 struct mbuf *mrep, *md;
971b93e3
KM
897 caddr_t dpos;
898 struct ucred *cred;
2c5b44a2 899 struct mbuf *nam, **mrq;
971b93e3 900{
74c40d5a 901 struct nameidata nd;
236c2c19 902 register u_long *tl;
0bd503ad
KM
903 register long t1;
904 caddr_t bpos;
2c5b44a2 905 int error = 0, rdonly, cache, len;
0bd503ad 906 char *cp2;
e8540f59 907 struct mbuf *mb, *mreq;
971b93e3
KM
908 struct vnode *vp, *xp;
909 nfsv2fh_t nfh, dnfh;
910 fhandle_t *fhp, *dfhp;
2c5b44a2 911 u_quad_t frev;
971b93e3
KM
912
913 fhp = &nfh.fh_generic;
914 dfhp = &dnfh.fh_generic;
915 nfsm_srvmtofh(fhp);
916 nfsm_srvmtofh(dfhp);
917 nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
2c5b44a2 918 if (error = nfsrv_fhtovp(fhp, FALSE, &vp, cred, nfsd->nd_slp, nam, &rdonly))
971b93e3 919 nfsm_reply(0);
2c5b44a2 920 if (vp->v_type == VDIR && (error = suser(cred, (u_short *)0)))
971b93e3 921 goto out1;
74c40d5a
KM
922 nd.ni_cred = cred;
923 nd.ni_nameiop = CREATE | LOCKPARENT;
2c5b44a2 924 if (error = nfs_namei(&nd, dfhp, len, nfsd->nd_slp, nam, &md, &dpos, nfsd->nd_procp))
971b93e3 925 goto out1;
74c40d5a 926 xp = nd.ni_vp;
971b93e3
KM
927 if (xp != NULL) {
928 error = EEXIST;
929 goto out;
930 }
74c40d5a 931 xp = nd.ni_dvp;
971b93e3
KM
932 if (vp->v_mount != xp->v_mount)
933 error = EXDEV;
934out:
66955caf 935 if (!error) {
2c5b44a2
KM
936 nqsrv_getl(vp, NQL_WRITE);
937 nqsrv_getl(xp, NQL_WRITE);
938 error = VOP_LINK(vp, &nd, nfsd->nd_procp);
66955caf 939 } else {
74c40d5a
KM
940 VOP_ABORTOP(&nd);
941 if (nd.ni_dvp == nd.ni_vp)
942 vrele(nd.ni_dvp);
639383fa 943 else
74c40d5a
KM
944 vput(nd.ni_dvp);
945 if (nd.ni_vp)
946 vrele(nd.ni_vp);
66955caf 947 }
971b93e3
KM
948out1:
949 vrele(vp);
950 nfsm_reply(0);
951 nfsm_srvdone;
952}
953
954/*
955 * nfs symbolic link service
956 */
2c5b44a2
KM
957nfsrv_symlink(nfsd, mrep, md, dpos, cred, nam, mrq)
958 struct nfsd *nfsd;
959 struct mbuf *mrep, *md;
971b93e3
KM
960 caddr_t dpos;
961 struct ucred *cred;
2c5b44a2 962 struct mbuf *nam, **mrq;
971b93e3
KM
963{
964 struct vattr va;
74c40d5a 965 struct nameidata nd;
971b93e3 966 register struct vattr *vap = &va;
236c2c19 967 register u_long *tl;
0bd503ad 968 register long t1;
09e56da6 969 struct nfsv2_sattr *sp;
0bd503ad 970 caddr_t bpos;
f0f1cbaa
KM
971 struct uio io;
972 struct iovec iv;
2c5b44a2 973 int error = 0, rdonly, cache, len, len2;
f0f1cbaa 974 char *pathcp, *cp2;
e8540f59 975 struct mbuf *mb, *mreq;
971b93e3
KM
976 nfsv2fh_t nfh;
977 fhandle_t *fhp;
2c5b44a2 978 u_quad_t frev;
971b93e3 979
f0f1cbaa 980 pathcp = (char *)0;
971b93e3
KM
981 fhp = &nfh.fh_generic;
982 nfsm_srvmtofh(fhp);
983 nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
74c40d5a
KM
984 nd.ni_cred = cred;
985 nd.ni_nameiop = CREATE | LOCKPARENT;
2c5b44a2 986 if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos, nfsd->nd_procp))
66955caf 987 goto out;
f0f1cbaa
KM
988 nfsm_strsiz(len2, NFS_MAXPATHLEN);
989 MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK);
990 iv.iov_base = pathcp;
991 iv.iov_len = len2;
992 io.uio_resid = len2;
993 io.uio_offset = 0;
994 io.uio_iov = &iv;
995 io.uio_iovcnt = 1;
996 io.uio_segflg = UIO_SYSSPACE;
997 io.uio_rw = UIO_READ;
236c2c19 998 io.uio_procp = (struct proc *)0;
f0f1cbaa 999 nfsm_mtouio(&io, len2);
2c5b44a2 1000 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_SATTR);
f0f1cbaa 1001 *(pathcp + len2) = '\0';
74c40d5a
KM
1002 if (nd.ni_vp) {
1003 VOP_ABORTOP(&nd);
1004 if (nd.ni_dvp == nd.ni_vp)
1005 vrele(nd.ni_dvp);
639383fa 1006 else
74c40d5a
KM
1007 vput(nd.ni_dvp);
1008 vrele(nd.ni_vp);
971b93e3
KM
1009 error = EEXIST;
1010 goto out;
1011 }
3ee1461b 1012 VATTR_NULL(vap);
09e56da6 1013 vap->va_mode = fxdr_unsigned(u_short, sp->sa_mode);
2c5b44a2
KM
1014 nqsrv_getl(nd.ni_dvp, NQL_WRITE);
1015 error = VOP_SYMLINK(&nd, vap, pathcp, nfsd->nd_procp);
971b93e3 1016out:
f0f1cbaa
KM
1017 if (pathcp)
1018 FREE(pathcp, M_TEMP);
971b93e3
KM
1019 nfsm_reply(0);
1020 return (error);
1021nfsmout:
74c40d5a
KM
1022 VOP_ABORTOP(&nd);
1023 if (nd.ni_dvp == nd.ni_vp)
1024 vrele(nd.ni_dvp);
639383fa 1025 else
74c40d5a
KM
1026 vput(nd.ni_dvp);
1027 if (nd.ni_vp)
1028 vrele(nd.ni_vp);
f0f1cbaa
KM
1029 if (pathcp)
1030 FREE(pathcp, M_TEMP);
971b93e3
KM
1031 return (error);
1032}
1033
1034/*
1035 * nfs mkdir service
1036 */
2c5b44a2
KM
1037nfsrv_mkdir(nfsd, mrep, md, dpos, cred, nam, mrq)
1038 struct nfsd *nfsd;
1039 struct mbuf *mrep, *md;
971b93e3
KM
1040 caddr_t dpos;
1041 struct ucred *cred;
2c5b44a2 1042 struct mbuf *nam, **mrq;
971b93e3
KM
1043{
1044 struct vattr va;
1045 register struct vattr *vap = &va;
9238aa59 1046 register struct nfsv2_fattr *fp;
74c40d5a 1047 struct nameidata nd;
0bd503ad 1048 register caddr_t cp;
236c2c19 1049 register u_long *tl;
0bd503ad
KM
1050 register long t1;
1051 caddr_t bpos;
2c5b44a2 1052 int error = 0, rdonly, cache, len;
0bd503ad 1053 char *cp2;
e8540f59 1054 struct mbuf *mb, *mb2, *mreq;
971b93e3
KM
1055 struct vnode *vp;
1056 nfsv2fh_t nfh;
1057 fhandle_t *fhp;
2c5b44a2 1058 u_quad_t frev;
971b93e3 1059
971b93e3
KM
1060 fhp = &nfh.fh_generic;
1061 nfsm_srvmtofh(fhp);
1062 nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
74c40d5a
KM
1063 nd.ni_cred = cred;
1064 nd.ni_nameiop = CREATE | LOCKPARENT;
2c5b44a2 1065 if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos, nfsd->nd_procp))
971b93e3 1066 nfsm_reply(0);
2c5b44a2 1067 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
3ee1461b 1068 VATTR_NULL(vap);
971b93e3 1069 vap->va_type = VDIR;
236c2c19 1070 vap->va_mode = nfstov_mode(*tl++);
74c40d5a 1071 vp = nd.ni_vp;
971b93e3 1072 if (vp != NULL) {
74c40d5a
KM
1073 VOP_ABORTOP(&nd);
1074 if (nd.ni_dvp == vp)
1075 vrele(nd.ni_dvp);
639383fa 1076 else
74c40d5a 1077 vput(nd.ni_dvp);
66955caf 1078 vrele(vp);
971b93e3
KM
1079 error = EEXIST;
1080 nfsm_reply(0);
1081 }
2c5b44a2
KM
1082 nqsrv_getl(nd.ni_dvp, NQL_WRITE);
1083 if (error = VOP_MKDIR(&nd, vap, nfsd->nd_procp))
971b93e3 1084 nfsm_reply(0);
74c40d5a 1085 vp = nd.ni_vp;
971b93e3 1086 bzero((caddr_t)fhp, sizeof(nfh));
54fb9dc2 1087 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
971b93e3
KM
1088 if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) {
1089 vput(vp);
1090 nfsm_reply(0);
1091 }
2c5b44a2 1092 error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
971b93e3
KM
1093 vput(vp);
1094 nfsm_reply(NFSX_FH+NFSX_FATTR);
1095 nfsm_srvfhtom(fhp);
9238aa59 1096 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
e8540f59 1097 nfsm_srvfillattr;
971b93e3
KM
1098 return (error);
1099nfsmout:
74c40d5a
KM
1100 VOP_ABORTOP(&nd);
1101 if (nd.ni_dvp == nd.ni_vp)
1102 vrele(nd.ni_dvp);
639383fa 1103 else
74c40d5a
KM
1104 vput(nd.ni_dvp);
1105 if (nd.ni_vp)
1106 vrele(nd.ni_vp);
971b93e3
KM
1107 return (error);
1108}
1109
1110/*
1111 * nfs rmdir service
1112 */
2c5b44a2
KM
1113nfsrv_rmdir(nfsd, mrep, md, dpos, cred, nam, mrq)
1114 struct nfsd *nfsd;
1115 struct mbuf *mrep, *md;
971b93e3
KM
1116 caddr_t dpos;
1117 struct ucred *cred;
2c5b44a2 1118 struct mbuf *nam, **mrq;
971b93e3 1119{
236c2c19 1120 register u_long *tl;
0bd503ad
KM
1121 register long t1;
1122 caddr_t bpos;
2c5b44a2 1123 int error = 0, rdonly, cache, len;
0bd503ad 1124 char *cp2;
e8540f59 1125 struct mbuf *mb, *mreq;
971b93e3
KM
1126 struct vnode *vp;
1127 nfsv2fh_t nfh;
1128 fhandle_t *fhp;
74c40d5a 1129 struct nameidata nd;
2c5b44a2 1130 u_quad_t frev;
971b93e3
KM
1131
1132 fhp = &nfh.fh_generic;
1133 nfsm_srvmtofh(fhp);
1134 nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
74c40d5a
KM
1135 nd.ni_cred = cred;
1136 nd.ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
2c5b44a2 1137 if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos, nfsd->nd_procp))
971b93e3 1138 nfsm_reply(0);
74c40d5a 1139 vp = nd.ni_vp;
971b93e3
KM
1140 if (vp->v_type != VDIR) {
1141 error = ENOTDIR;
1142 goto out;
1143 }
1144 /*
1145 * No rmdir "." please.
1146 */
74c40d5a 1147 if (nd.ni_dvp == vp) {
971b93e3
KM
1148 error = EINVAL;
1149 goto out;
1150 }
1151 /*
4b0bcec3 1152 * The root of a mounted filesystem cannot be deleted.
971b93e3
KM
1153 */
1154 if (vp->v_flag & VROOT)
1155 error = EBUSY;
1156out:
66955caf 1157 if (!error) {
2c5b44a2
KM
1158 nqsrv_getl(nd.ni_dvp, NQL_WRITE);
1159 nqsrv_getl(vp, NQL_WRITE);
1160 error = VOP_RMDIR(&nd, nfsd->nd_procp);
66955caf 1161 } else {
74c40d5a
KM
1162 VOP_ABORTOP(&nd);
1163 if (nd.ni_dvp == nd.ni_vp)
1164 vrele(nd.ni_dvp);
639383fa 1165 else
74c40d5a 1166 vput(nd.ni_dvp);
66955caf
KM
1167 vput(vp);
1168 }
971b93e3
KM
1169 nfsm_reply(0);
1170 nfsm_srvdone;
1171}
1172
1173/*
1174 * nfs readdir service
1175 * - mallocs what it thinks is enough to read
236c2c19 1176 * count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
971b93e3 1177 * - calls VOP_READDIR()
732aefe9 1178 * - loops around building the reply
36c3043b
KM
1179 * if the output generated exceeds count break out of loop
1180 * The nfsm_clget macro is used here so that the reply will be packed
1181 * tightly in mbuf clusters.
971b93e3 1182 * - it only knows that it has encountered eof when the VOP_READDIR()
36c3043b 1183 * reads nothing
971b93e3 1184 * - as such one readdir rpc will return eof false although you are there
36c3043b 1185 * and then the next will return eof
971b93e3 1186 * - it trims out records with d_ino == 0
36c3043b
KM
1187 * this doesn't matter for Unix clients, but they might confuse clients
1188 * for other os'.
971b93e3 1189 * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
36c3043b
KM
1190 * than requested, but this may not apply to all filesystems. For
1191 * example, client NFS does not { although it is never remote mounted
1192 * anyhow }
2c5b44a2 1193 * The alternate call nqnfsrv_readdirlook() does lookups as well.
971b93e3 1194 * PS: The NFS protocol spec. does not clarify what the "count" byte
36c3043b
KM
1195 * argument is a count of.. just name strings and file id's or the
1196 * entire reply rpc or ...
1197 * I tried just file name and id sizes and it confused the Sun client,
1198 * so I am using the full rpc size now. The "paranoia.." comment refers
1199 * to including the status longwords that are not a part of the dir.
1200 * "entry" structures, but are in the rpc.
971b93e3 1201 */
2c5b44a2
KM
1202struct flrep {
1203 u_long fl_cachable;
1204 u_long fl_duration;
1205 u_quad_t fl_frev;
1206 nfsv2fh_t fl_nfh;
1207 struct nfsv2_fattr fl_fattr;
1208};
1209
1210nfsrv_readdir(nfsd, mrep, md, dpos, cred, nam, mrq)
1211 struct nfsd *nfsd;
971b93e3
KM
1212 struct mbuf *mrep, *md;
1213 caddr_t dpos;
1214 struct ucred *cred;
2c5b44a2 1215 struct mbuf *nam, **mrq;
971b93e3
KM
1216{
1217 register char *bp, *be;
1218 register struct mbuf *mp;
1219 register struct direct *dp;
0bd503ad 1220 register caddr_t cp;
236c2c19 1221 register u_long *tl;
0bd503ad
KM
1222 register long t1;
1223 caddr_t bpos;
2c5b44a2
KM
1224 struct mbuf *mb, *mb2, *mreq, *mp2;
1225 char *cpos, *cend, *cp2, *rbuf;
971b93e3 1226 struct vnode *vp;
971b93e3
KM
1227 nfsv2fh_t nfh;
1228 fhandle_t *fhp;
1229 struct uio io;
1230 struct iovec iv;
2c5b44a2
KM
1231 struct vattr va;
1232 int len, nlen, rem, xfer, tsiz, i, error = 0;
1233 int siz, cnt, fullsiz, eofflag, rdonly, cache;
1234 u_quad_t frev;
971b93e3 1235 u_long on;
971b93e3
KM
1236 off_t off, toff;
1237
1238 fhp = &nfh.fh_generic;
1239 nfsm_srvmtofh(fhp);
2c5b44a2 1240 nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED);
236c2c19
KM
1241 toff = fxdr_unsigned(off_t, *tl++);
1242 off = (toff & ~(NFS_DIRBLKSIZ-1));
1243 on = (toff & (NFS_DIRBLKSIZ-1));
1244 cnt = fxdr_unsigned(int, *tl);
1245 siz = ((cnt+NFS_DIRBLKSIZ-1) & ~(NFS_DIRBLKSIZ-1));
f0f1cbaa
KM
1246 if (cnt > NFS_MAXREADDIR)
1247 siz = NFS_MAXREADDIR;
971b93e3 1248 fullsiz = siz;
2c5b44a2 1249 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))
971b93e3 1250 nfsm_reply(0);
2c5b44a2
KM
1251 nqsrv_getl(vp, NQL_READ);
1252 if (error = nfsrv_access(vp, VEXEC, cred, rdonly, nfsd->nd_procp)) {
971b93e3
KM
1253 vput(vp);
1254 nfsm_reply(0);
1255 }
1256 VOP_UNLOCK(vp);
1257 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
1258again:
1259 iv.iov_base = rbuf;
1260 iv.iov_len = fullsiz;
1261 io.uio_iov = &iv;
1262 io.uio_iovcnt = 1;
1263 io.uio_offset = off;
1264 io.uio_resid = fullsiz;
1265 io.uio_segflg = UIO_SYSSPACE;
1266 io.uio_rw = UIO_READ;
236c2c19 1267 io.uio_procp = (struct proc *)0;
e49b1a6c 1268 error = VOP_READDIR(vp, &io, cred, &eofflag);
e9843ca3 1269 off = io.uio_offset;
971b93e3
KM
1270 if (error) {
1271 vrele(vp);
1272 free((caddr_t)rbuf, M_TEMP);
1273 nfsm_reply(0);
1274 }
1275 if (io.uio_resid) {
1276 siz -= io.uio_resid;
1277
1278 /*
1279 * If nothing read, return eof
1280 * rpc reply
1281 */
1282 if (siz == 0) {
1283 vrele(vp);
1284 nfsm_reply(2*NFSX_UNSIGNED);
236c2c19
KM
1285 nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
1286 *tl++ = nfs_false;
1287 *tl = nfs_true;
971b93e3
KM
1288 FREE((caddr_t)rbuf, M_TEMP);
1289 return (0);
1290 }
1291 }
732aefe9 1292
971b93e3
KM
1293 /*
1294 * Check for degenerate cases of nothing useful read.
732aefe9 1295 * If so go try again
971b93e3 1296 */
732aefe9
KM
1297 cpos = rbuf + on;
1298 cend = rbuf + siz;
1299 dp = (struct direct *)cpos;
1300 while (cpos < cend && dp->d_ino == 0) {
1301 cpos += dp->d_reclen;
1302 dp = (struct direct *)cpos;
1303 }
1304 if (cpos >= cend) {
971b93e3
KM
1305 toff = off;
1306 siz = fullsiz;
1307 on = 0;
1308 goto again;
1309 }
732aefe9
KM
1310
1311 cpos = rbuf + on;
1312 cend = rbuf + siz;
1313 dp = (struct direct *)cpos;
2c5b44a2
KM
1314 len = 3*NFSX_UNSIGNED; /* paranoia, probably can be 0 */
1315 nfsm_reply(siz);
1316 mp = mp2 = mb;
1317 bp = bpos;
1318 be = bp + M_TRAILINGSPACE(mp);
1319
1320 /* Loop through the records and build reply */
1321 while (cpos < cend) {
1322 if (dp->d_ino != 0) {
1323 nlen = dp->d_namlen;
1324 rem = nfsm_rndup(nlen)-nlen;
1325 len += (4*NFSX_UNSIGNED + nlen + rem);
1326 if (len > cnt) {
1327 eofflag = 0;
1328 break;
1329 }
1330
1331 /* Build the directory record xdr from the direct entry */
1332 nfsm_clget;
1333 *tl = nfs_true;
1334 bp += NFSX_UNSIGNED;
1335 nfsm_clget;
1336 *tl = txdr_unsigned(dp->d_ino);
1337 bp += NFSX_UNSIGNED;
1338 nfsm_clget;
1339 *tl = txdr_unsigned(nlen);
1340 bp += NFSX_UNSIGNED;
1341
1342 /* And loop around copying the name */
1343 xfer = nlen;
1344 cp = dp->d_name;
1345 while (xfer > 0) {
1346 nfsm_clget;
1347 if ((bp+xfer) > be)
1348 tsiz = be-bp;
1349 else
1350 tsiz = xfer;
1351 bcopy(cp, bp, tsiz);
1352 bp += tsiz;
1353 xfer -= tsiz;
1354 if (xfer > 0)
1355 cp += tsiz;
1356 }
1357 /* And null pad to a long boundary */
1358 for (i = 0; i < rem; i++)
1359 *bp++ = '\0';
1360 nfsm_clget;
1361
1362 /* Finish off the record */
1363 toff += dp->d_reclen;
1364 *tl = txdr_unsigned(toff);
1365 bp += NFSX_UNSIGNED;
1366 } else
1367 toff += dp->d_reclen;
1368 cpos += dp->d_reclen;
1369 dp = (struct direct *)cpos;
1370 }
971b93e3 1371 vrele(vp);
2c5b44a2
KM
1372 nfsm_clget;
1373 *tl = nfs_false;
1374 bp += NFSX_UNSIGNED;
1375 nfsm_clget;
1376 if (eofflag)
1377 *tl = nfs_true;
1378 else
1379 *tl = nfs_false;
1380 bp += NFSX_UNSIGNED;
1381 if (mp != mb) {
1382 if (bp < be)
1383 mp->m_len = bp - mtod(mp, caddr_t);
1384 } else
1385 mp->m_len += bp - bpos;
1386 FREE(rbuf, M_TEMP);
1387 nfsm_srvdone;
1388}
1389
1390nqnfsrv_readdirlook(nfsd, mrep, md, dpos, cred, nam, mrq)
1391 struct nfsd *nfsd;
1392 struct mbuf *mrep, *md;
1393 caddr_t dpos;
1394 struct ucred *cred;
1395 struct mbuf *nam, **mrq;
1396{
1397 register char *bp, *be;
1398 register struct mbuf *mp;
1399 register struct direct *dp;
1400 register caddr_t cp;
1401 register u_long *tl;
1402 register long t1;
1403 caddr_t bpos;
1404 struct mbuf *mb, *mb2, *mreq, *mp2;
1405 char *cpos, *cend, *cp2, *rbuf;
1406 struct vnode *vp, *nvp;
1407 struct flrep fl;
1408 struct ufid *ufp = (struct ufid *)&fl.fl_nfh.fh_generic.fh_fid;
1409 struct mount *mntp;
1410 nfsv2fh_t nfh;
1411 fhandle_t *fhp;
1412 struct uio io;
1413 struct iovec iv;
1414 struct vattr va, *vap = &va;
1415 struct nfsv2_fattr *fp;
1416 int len, nlen, rem, xfer, tsiz, i, error = 0, duration2, cache2;
1417 int siz, cnt, fullsiz, eofflag, rdonly, cache;
1418 u_quad_t frev, frev2;
1419 u_long on;
1420 off_t off, toff;
1421
1422 fhp = &nfh.fh_generic;
1423 nfsm_srvmtofh(fhp);
1424 nfsm_dissect(tl, u_long *, 3*NFSX_UNSIGNED);
1425 toff = fxdr_unsigned(off_t, *tl++);
1426 off = (toff & ~(NFS_DIRBLKSIZ-1));
1427 on = (toff & (NFS_DIRBLKSIZ-1));
1428 cnt = fxdr_unsigned(int, *tl++);
1429 duration2 = fxdr_unsigned(int, *tl);
1430 siz = ((cnt+NFS_DIRBLKSIZ-1) & ~(NFS_DIRBLKSIZ-1));
1431 if (cnt > NFS_MAXREADDIR)
1432 siz = NFS_MAXREADDIR;
1433 fullsiz = siz;
1434 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))
1435 nfsm_reply(0);
1436 nqsrv_getl(vp, NQL_READ);
1437 if (error = nfsrv_access(vp, VEXEC, cred, rdonly, nfsd->nd_procp)) {
1438 vput(vp);
1439 nfsm_reply(0);
1440 }
1441 VOP_UNLOCK(vp);
1442 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
1443again:
1444 iv.iov_base = rbuf;
1445 iv.iov_len = fullsiz;
1446 io.uio_iov = &iv;
1447 io.uio_iovcnt = 1;
1448 io.uio_offset = off;
1449 io.uio_resid = fullsiz;
1450 io.uio_segflg = UIO_SYSSPACE;
1451 io.uio_rw = UIO_READ;
1452 io.uio_procp = (struct proc *)0;
1453 error = VOP_READDIR(vp, &io, cred, &eofflag);
1454 off = io.uio_offset;
1455 if (error) {
1456 vrele(vp);
1457 free((caddr_t)rbuf, M_TEMP);
1458 nfsm_reply(0);
1459 }
1460 if (io.uio_resid) {
1461 siz -= io.uio_resid;
1462
1463 /*
1464 * If nothing read, return eof
1465 * rpc reply
1466 */
1467 if (siz == 0) {
1468 vrele(vp);
1469 nfsm_reply(2*NFSX_UNSIGNED);
1470 nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
1471 *tl++ = nfs_false;
1472 *tl = nfs_true;
1473 FREE((caddr_t)rbuf, M_TEMP);
1474 return (0);
1475 }
1476 }
1477
1478 /*
1479 * Check for degenerate cases of nothing useful read.
1480 * If so go try again
1481 */
1482 cpos = rbuf + on;
1483 cend = rbuf + siz;
1484 dp = (struct direct *)cpos;
1485 while (cpos < cend && dp->d_ino == 0) {
1486 cpos += dp->d_reclen;
1487 dp = (struct direct *)cpos;
1488 }
1489 if (cpos >= cend) {
1490 toff = off;
1491 siz = fullsiz;
1492 on = 0;
1493 goto again;
1494 }
1495
1496 cpos = rbuf + on;
1497 cend = rbuf + siz;
1498 dp = (struct direct *)cpos;
36c3043b 1499 len = 3*NFSX_UNSIGNED; /* paranoia, probably can be 0 */
971b93e3 1500 nfsm_reply(siz);
2c5b44a2
KM
1501 mp = mp2 = mb;
1502 bp = bpos;
1503 be = bp + M_TRAILINGSPACE(mp);
1504 mntp = vp->v_mount;
971b93e3
KM
1505
1506 /* Loop through the records and build reply */
1507 while (cpos < cend) {
1508 if (dp->d_ino != 0) {
1509 nlen = dp->d_namlen;
1510 rem = nfsm_rndup(nlen)-nlen;
36c3043b 1511
971b93e3 1512 /*
2c5b44a2
KM
1513 * For readdir_and_lookup get the vnode using
1514 * the file number.
971b93e3 1515 */
2c5b44a2
KM
1516 bzero((caddr_t)&fl.fl_nfh, sizeof (nfsv2fh_t));
1517 ufp->ufid_len = sizeof (struct ufid);
1518 ufp->ufid_ino = dp->d_ino;
1519 fl.fl_nfh.fh_generic.fh_fsid = mntp->mnt_stat.f_fsid;
1520 if (VFS_FHTOVP(mntp, (struct fid *)ufp, 1, &nvp))
1521 goto invalid;
1522 (void) nqsrv_getlease(nvp, &duration2, NQL_READ, nfsd,
1523 nam, &cache2, &frev2, cred);
1524 fl.fl_duration = txdr_unsigned(duration2);
1525 fl.fl_cachable = txdr_unsigned(cache2);
1526 txdr_hyper(&frev2, &fl.fl_frev);
1527 if (VOP_GETATTR(nvp, vap, cred, nfsd->nd_procp)) {
1528 vput(nvp);
1529 goto invalid;
1530 }
1531 vput(nvp);
1532 fp = &fl.fl_fattr;
1533 nfsm_srvfillattr;
1534 len += (4*NFSX_UNSIGNED + nlen + rem + NFSX_FH
1535 + NFSX_FATTR);
f0f1cbaa
KM
1536 if (len > cnt) {
1537 eofflag = 0;
971b93e3 1538 break;
f0f1cbaa 1539 }
36c3043b 1540
971b93e3
KM
1541 /* Build the directory record xdr from the direct entry */
1542 nfsm_clget;
236c2c19 1543 *tl = nfs_true;
971b93e3 1544 bp += NFSX_UNSIGNED;
2c5b44a2
KM
1545
1546 /*
1547 * For readdir_and_lookup copy the stuff out.
1548 */
1549 xfer = sizeof (struct flrep);
1550 cp = (caddr_t)&fl;
1551 while (xfer > 0) {
1552 nfsm_clget;
1553 if ((bp+xfer) > be)
1554 tsiz = be-bp;
1555 else
1556 tsiz = xfer;
1557 bcopy(cp, bp, tsiz);
1558 bp += tsiz;
1559 xfer -= tsiz;
1560 if (xfer > 0)
1561 cp += tsiz;
1562 }
971b93e3 1563 nfsm_clget;
236c2c19 1564 *tl = txdr_unsigned(dp->d_ino);
971b93e3
KM
1565 bp += NFSX_UNSIGNED;
1566 nfsm_clget;
236c2c19 1567 *tl = txdr_unsigned(nlen);
971b93e3 1568 bp += NFSX_UNSIGNED;
36c3043b 1569
2c5b44a2 1570 /* And loop around copying the name */
971b93e3
KM
1571 xfer = nlen;
1572 cp = dp->d_name;
1573 while (xfer > 0) {
1574 nfsm_clget;
1575 if ((bp+xfer) > be)
1576 tsiz = be-bp;
1577 else
1578 tsiz = xfer;
1579 bcopy(cp, bp, tsiz);
1580 bp += tsiz;
1581 xfer -= tsiz;
1582 if (xfer > 0)
1583 cp += tsiz;
1584 }
1585 /* And null pad to a long boundary */
1586 for (i = 0; i < rem; i++)
1587 *bp++ = '\0';
1588 nfsm_clget;
36c3043b 1589
971b93e3
KM
1590 /* Finish off the record */
1591 toff += dp->d_reclen;
236c2c19 1592 *tl = txdr_unsigned(toff);
971b93e3
KM
1593 bp += NFSX_UNSIGNED;
1594 } else
2c5b44a2 1595invalid:
971b93e3
KM
1596 toff += dp->d_reclen;
1597 cpos += dp->d_reclen;
1598 dp = (struct direct *)cpos;
1599 }
2c5b44a2 1600 vrele(vp);
971b93e3 1601 nfsm_clget;
236c2c19 1602 *tl = nfs_false;
971b93e3
KM
1603 bp += NFSX_UNSIGNED;
1604 nfsm_clget;
e49b1a6c 1605 if (eofflag)
236c2c19 1606 *tl = nfs_true;
e49b1a6c 1607 else
236c2c19 1608 *tl = nfs_false;
971b93e3 1609 bp += NFSX_UNSIGNED;
2c5b44a2
KM
1610 if (mp != mb) {
1611 if (bp < be)
1612 mp->m_len = bp - mtod(mp, caddr_t);
1613 } else
1614 mp->m_len += bp - bpos;
971b93e3
KM
1615 FREE(rbuf, M_TEMP);
1616 nfsm_srvdone;
1617}
1618
1619/*
1620 * nfs statfs service
1621 */
2c5b44a2
KM
1622nfsrv_statfs(nfsd, mrep, md, dpos, cred, nam, mrq)
1623 struct nfsd *nfsd;
971b93e3
KM
1624 struct mbuf *mrep, *md;
1625 caddr_t dpos;
1626 struct ucred *cred;
2c5b44a2 1627 struct mbuf *nam, **mrq;
971b93e3
KM
1628{
1629 register struct statfs *sf;
9238aa59 1630 register struct nfsv2_statfs *sfp;
236c2c19 1631 register u_long *tl;
0bd503ad
KM
1632 register long t1;
1633 caddr_t bpos;
2c5b44a2 1634 int error = 0, rdonly, cache;
0bd503ad 1635 char *cp2;
e8540f59 1636 struct mbuf *mb, *mb2, *mreq;
971b93e3
KM
1637 struct vnode *vp;
1638 nfsv2fh_t nfh;
1639 fhandle_t *fhp;
1640 struct statfs statfs;
2c5b44a2 1641 u_quad_t frev;
971b93e3
KM
1642
1643 fhp = &nfh.fh_generic;
1644 nfsm_srvmtofh(fhp);
2c5b44a2 1645 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))
971b93e3
KM
1646 nfsm_reply(0);
1647 sf = &statfs;
2c5b44a2 1648 error = VFS_STATFS(vp->v_mount, sf, nfsd->nd_procp);
971b93e3
KM
1649 vput(vp);
1650 nfsm_reply(NFSX_STATFS);
9238aa59 1651 nfsm_build(sfp, struct nfsv2_statfs *, NFSX_STATFS);
b28c3bcc 1652 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
a22e809c 1653 sfp->sf_bsize = txdr_unsigned(sf->f_bsize);
9238aa59
RM
1654 sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
1655 sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
1656 sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
971b93e3
KM
1657 nfsm_srvdone;
1658}
1659
1660/*
1661 * Null operation, used by clients to ping server
1662 */
0bd503ad 1663/* ARGSUSED */
2c5b44a2
KM
1664nfsrv_null(nfsd, mrep, md, dpos, cred, nam, mrq)
1665 struct nfsd *nfsd;
971b93e3
KM
1666 struct mbuf *mrep, *md;
1667 caddr_t dpos;
1668 struct ucred *cred;
2c5b44a2 1669 struct mbuf *nam, **mrq;
971b93e3 1670{
0bd503ad 1671 caddr_t bpos;
2c5b44a2 1672 int error = VNOVAL, cache;
e8540f59 1673 struct mbuf *mb, *mreq;
2c5b44a2 1674 u_quad_t frev;
971b93e3 1675
971b93e3 1676 nfsm_reply(0);
0bd503ad 1677 return (error);
971b93e3
KM
1678}
1679
1680/*
1681 * No operation, used for obsolete procedures
1682 */
0bd503ad 1683/* ARGSUSED */
2c5b44a2
KM
1684nfsrv_noop(nfsd, mrep, md, dpos, cred, nam, mrq)
1685 struct nfsd *nfsd;
971b93e3
KM
1686 struct mbuf *mrep, *md;
1687 caddr_t dpos;
1688 struct ucred *cred;
2c5b44a2 1689 struct mbuf *nam, **mrq;
971b93e3 1690{
0bd503ad 1691 caddr_t bpos;
2c5b44a2 1692 int error, cache;
e8540f59 1693 struct mbuf *mb, *mreq;
2c5b44a2 1694 u_quad_t frev;
971b93e3 1695
2c5b44a2
KM
1696 if (nfsd->nd_repstat)
1697 error = nfsd->nd_repstat;
1698 else
1699 error = EPROCUNAVAIL;
971b93e3 1700 nfsm_reply(0);
0bd503ad 1701 return (error);
971b93e3 1702}
36c3043b 1703
24ed1a73
KM
1704/*
1705 * Perform access checking for vnodes obtained from file handles that would
1706 * refer to files already opened by a Unix client. You cannot just use
1707 * vn_writechk() and VOP_ACCESS() for two reasons.
2c5b44a2 1708 * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case
24ed1a73
KM
1709 * 2 - The owner is to be given access irrespective of mode bits so that
1710 * processes that chmod after opening a file don't break. I don't like
1711 * this because it opens a security hole, but since the nfs server opens
1712 * a security hole the size of a barn door anyhow, what the heck.
1713 */
2c5b44a2 1714nfsrv_access(vp, flags, cred, rdonly, p)
24ed1a73
KM
1715 register struct vnode *vp;
1716 int flags;
1717 register struct ucred *cred;
2c5b44a2 1718 int rdonly;
236c2c19 1719 struct proc *p;
24ed1a73
KM
1720{
1721 struct vattr vattr;
1722 int error;
1723 if (flags & VWRITE) {
2c5b44a2 1724 /* Just vn_writechk() changed to check rdonly */
24ed1a73
KM
1725 /*
1726 * Disallow write attempts on read-only file systems;
1727 * unless the file is a socket or a block or character
1728 * device resident on the file system.
1729 */
2c5b44a2 1730 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
fef23149
KM
1731 switch (vp->v_type) {
1732 case VREG: case VDIR: case VLNK:
24ed1a73 1733 return (EROFS);
fef23149
KM
1734 }
1735 }
24ed1a73
KM
1736 /*
1737 * If there's shared text associated with
1738 * the inode, try to free it up once. If
1739 * we fail, we can't allow writing.
1740 */
8986c97c 1741 if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp))
24ed1a73 1742 return (ETXTBSY);
24ed1a73 1743 }
236c2c19 1744 if (error = VOP_GETATTR(vp, &vattr, cred, p))
fef23149 1745 return (error);
236c2c19 1746 if ((error = VOP_ACCESS(vp, flags, cred, p)) &&
fef23149
KM
1747 cred->cr_uid != vattr.va_uid)
1748 return (error);
1749 return (0);
24ed1a73 1750}