This source file includes following definitions.
- vn_open
- vn_writechk
- vn_marktext
- vn_close
- vn_rdwr
- vn_read
- vn_write
- vn_statfile
- vn_stat
- vn_ioctl
- vn_poll
- vn_lock
- vn_closefile
- vn_kqfilter
- vn_isunder
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 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/malloc.h>
44 #include <sys/file.h>
45 #include <sys/stat.h>
46 #include <sys/buf.h>
47 #include <sys/proc.h>
48 #include <sys/mount.h>
49 #include <sys/namei.h>
50 #include <sys/vnode.h>
51 #include <sys/ioctl.h>
52 #include <sys/tty.h>
53 #include <sys/cdio.h>
54 #include <sys/poll.h>
55
56 #include <uvm/uvm_extern.h>
57 #include <miscfs/specfs/specdev.h>
58
59 int vn_read(struct file *, off_t *, struct uio *, struct ucred *);
60 int vn_write(struct file *, off_t *, struct uio *, struct ucred *);
61 int vn_poll(struct file *, int, struct proc *);
62 int vn_kqfilter(struct file *, struct knote *);
63 int vn_closefile(struct file *, struct proc *);
64
65 struct fileops vnops =
66 { vn_read, vn_write, vn_ioctl, vn_poll, vn_kqfilter, vn_statfile,
67 vn_closefile };
68
69
70
71
72
73 int
74 vn_open(struct nameidata *ndp, int fmode, int cmode)
75 {
76 struct vnode *vp;
77 struct proc *p = ndp->ni_cnd.cn_proc;
78 struct ucred *cred = p->p_ucred;
79 struct vattr va;
80 int error;
81
82 if ((fmode & (FREAD|FWRITE)) == 0)
83 return (EINVAL);
84 if ((fmode & (O_TRUNC | FWRITE)) == O_TRUNC)
85 return (EINVAL);
86 if (fmode & O_CREAT) {
87 ndp->ni_cnd.cn_nameiop = CREATE;
88 ndp->ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
89 if ((fmode & O_EXCL) == 0 && (fmode & O_NOFOLLOW) == 0)
90 ndp->ni_cnd.cn_flags |= FOLLOW;
91 if ((error = namei(ndp)) != 0)
92 return (error);
93
94 if (ndp->ni_vp == NULL) {
95 VATTR_NULL(&va);
96 va.va_type = VREG;
97 va.va_mode = cmode;
98 error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp,
99 &ndp->ni_cnd, &va);
100 if (error)
101 return (error);
102 fmode &= ~O_TRUNC;
103 vp = ndp->ni_vp;
104 } else {
105 VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd);
106 if (ndp->ni_dvp == ndp->ni_vp)
107 vrele(ndp->ni_dvp);
108 else
109 vput(ndp->ni_dvp);
110 ndp->ni_dvp = NULL;
111 vp = ndp->ni_vp;
112 if (fmode & O_EXCL) {
113 error = EEXIST;
114 goto bad;
115 }
116 fmode &= ~O_CREAT;
117 }
118 } else {
119 ndp->ni_cnd.cn_nameiop = LOOKUP;
120 ndp->ni_cnd.cn_flags =
121 ((fmode & O_NOFOLLOW) ? NOFOLLOW : FOLLOW) | LOCKLEAF;
122 if ((error = namei(ndp)) != 0)
123 return (error);
124 vp = ndp->ni_vp;
125 }
126 if (vp->v_type == VSOCK) {
127 error = EOPNOTSUPP;
128 goto bad;
129 }
130 if (vp->v_type == VLNK) {
131 error = EMLINK;
132 goto bad;
133 }
134 if ((fmode & O_CREAT) == 0) {
135 if (fmode & FREAD) {
136 if ((error = VOP_ACCESS(vp, VREAD, cred, p)) != 0)
137 goto bad;
138 }
139 if (fmode & FWRITE) {
140 if (vp->v_type == VDIR) {
141 error = EISDIR;
142 goto bad;
143 }
144 if ((error = vn_writechk(vp)) != 0 ||
145 (error = VOP_ACCESS(vp, VWRITE, cred, p)) != 0)
146 goto bad;
147 }
148 }
149 if ((fmode & O_TRUNC) && vp->v_type == VREG) {
150 VATTR_NULL(&va);
151 va.va_size = 0;
152 if ((error = VOP_SETATTR(vp, &va, cred, p)) != 0)
153 goto bad;
154 }
155 if ((error = VOP_OPEN(vp, fmode, cred, p)) != 0)
156 goto bad;
157
158 if (vp->v_flag & VCLONED) {
159 struct cloneinfo *cip = (struct cloneinfo *) vp->v_data;
160
161 vp->v_flag &= ~VCLONED;
162 ndp->ni_vp = cip->ci_vp;
163 vp->v_data = cip->ci_data;
164 VOP_UNLOCK(vp, 0, p);
165 vp = ndp->ni_vp;
166
167 free(cip, M_TEMP);
168 }
169
170 if (fmode & FWRITE)
171 vp->v_writecount++;
172 return (0);
173 bad:
174 vput(vp);
175 return (error);
176 }
177
178
179
180
181
182 int
183 vn_writechk(struct vnode *vp)
184 {
185
186
187
188
189
190 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
191 switch (vp->v_type) {
192 case VREG:
193 case VDIR:
194 case VLNK:
195 return (EROFS);
196 case VNON:
197 case VCHR:
198 case VSOCK:
199 case VFIFO:
200 case VBAD:
201 case VBLK:
202 break;
203 }
204 }
205
206
207
208
209
210 if ((vp->v_flag & VTEXT) && !uvm_vnp_uncache(vp))
211 return (ETXTBSY);
212
213 return (0);
214 }
215
216
217
218
219 void
220 vn_marktext(struct vnode *vp)
221 {
222 vp->v_flag |= VTEXT;
223 }
224
225
226
227
228 int
229 vn_close(struct vnode *vp, int flags, struct ucred *cred, struct proc *p)
230 {
231 int error;
232
233 if (flags & FWRITE)
234 vp->v_writecount--;
235 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
236 error = VOP_CLOSE(vp, flags, cred, p);
237 vput(vp);
238 return (error);
239 }
240
241
242
243
244 int
245 vn_rdwr(enum uio_rw rw, struct vnode *vp, caddr_t base, int len, off_t offset,
246 enum uio_seg segflg, int ioflg, struct ucred *cred, size_t *aresid,
247 struct proc *p)
248 {
249 struct uio auio;
250 struct iovec aiov;
251 int error;
252
253 if ((ioflg & IO_NODELOCKED) == 0)
254 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
255 auio.uio_iov = &aiov;
256 auio.uio_iovcnt = 1;
257 aiov.iov_base = base;
258 aiov.iov_len = len;
259 auio.uio_resid = len;
260 auio.uio_offset = offset;
261 auio.uio_segflg = segflg;
262 auio.uio_rw = rw;
263 auio.uio_procp = p;
264 if (rw == UIO_READ) {
265 error = VOP_READ(vp, &auio, ioflg, cred);
266 } else {
267 error = VOP_WRITE(vp, &auio, ioflg, cred);
268 }
269 if (aresid)
270 *aresid = auio.uio_resid;
271 else
272 if (auio.uio_resid && error == 0)
273 error = EIO;
274 if ((ioflg & IO_NODELOCKED) == 0)
275 VOP_UNLOCK(vp, 0, p);
276 return (error);
277 }
278
279
280
281
282 int
283 vn_read(struct file *fp, off_t *poff, struct uio *uio, struct ucred *cred)
284 {
285 struct vnode *vp = (struct vnode *)fp->f_data;
286 int error = 0;
287 size_t count;
288 struct proc *p = uio->uio_procp;
289
290 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
291 uio->uio_offset = *poff;
292 count = uio->uio_resid;
293 if (vp->v_type != VDIR)
294 error = VOP_READ(vp, uio,
295 (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0, cred);
296 *poff += count - uio->uio_resid;
297 VOP_UNLOCK(vp, 0, p);
298 return (error);
299 }
300
301
302
303
304 int
305 vn_write(struct file *fp, off_t *poff, struct uio *uio, struct ucred *cred)
306 {
307 struct vnode *vp = (struct vnode *)fp->f_data;
308 struct proc *p = uio->uio_procp;
309 int error, ioflag = IO_UNIT;
310 size_t count;
311
312 if (vp->v_type == VREG && (fp->f_flag & O_APPEND))
313 ioflag |= IO_APPEND;
314 if (fp->f_flag & FNONBLOCK)
315 ioflag |= IO_NDELAY;
316 if ((fp->f_flag & FFSYNC) ||
317 (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS)))
318 ioflag |= IO_SYNC;
319 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
320 uio->uio_offset = *poff;
321 count = uio->uio_resid;
322 error = VOP_WRITE(vp, uio, ioflag, cred);
323 if (ioflag & IO_APPEND)
324 *poff = uio->uio_offset;
325 else
326 *poff += count - uio->uio_resid;
327 VOP_UNLOCK(vp, 0, p);
328 return (error);
329 }
330
331
332
333
334 int
335 vn_statfile(struct file *fp, struct stat *sb, struct proc *p)
336 {
337 struct vnode *vp = (struct vnode *)fp->f_data;
338 return vn_stat(vp, sb, p);
339 }
340
341
342
343
344 int
345 vn_stat(struct vnode *vp, struct stat *sb, struct proc *p)
346 {
347 struct vattr va;
348 int error;
349 mode_t mode;
350
351 error = VOP_GETATTR(vp, &va, p->p_ucred, p);
352 if (error)
353 return (error);
354
355
356
357 sb->st_dev = va.va_fsid;
358 sb->st_ino = va.va_fileid;
359 mode = va.va_mode;
360 switch (vp->v_type) {
361 case VREG:
362 mode |= S_IFREG;
363 break;
364 case VDIR:
365 mode |= S_IFDIR;
366 break;
367 case VBLK:
368 mode |= S_IFBLK;
369 break;
370 case VCHR:
371 mode |= S_IFCHR;
372 break;
373 case VLNK:
374 mode |= S_IFLNK;
375 break;
376 case VSOCK:
377 mode |= S_IFSOCK;
378 break;
379 case VFIFO:
380 mode |= S_IFIFO;
381 break;
382 default:
383 return (EBADF);
384 }
385 sb->st_mode = mode;
386 sb->st_nlink = va.va_nlink;
387 sb->st_uid = va.va_uid;
388 sb->st_gid = va.va_gid;
389 sb->st_rdev = va.va_rdev;
390 sb->st_size = va.va_size;
391 sb->st_atimespec = va.va_atime;
392 sb->st_mtimespec = va.va_mtime;
393 sb->st_ctimespec = va.va_ctime;
394 sb->st_blksize = va.va_blocksize;
395 sb->st_flags = va.va_flags;
396 sb->st_gen = va.va_gen;
397 sb->st_blocks = va.va_bytes / S_BLKSIZE;
398 return (0);
399 }
400
401
402
403
404 int
405 vn_ioctl(struct file *fp, u_long com, caddr_t data, struct proc *p)
406 {
407 struct vnode *vp = ((struct vnode *)fp->f_data);
408 struct vattr vattr;
409 int error;
410
411 switch (vp->v_type) {
412
413 case VREG:
414 case VDIR:
415 if (com == FIONREAD) {
416 error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
417 if (error)
418 return (error);
419 *(int *)data = vattr.va_size - fp->f_offset;
420 return (0);
421 }
422 if (com == FIONBIO || com == FIOASYNC)
423 return (0);
424
425 default:
426 return (ENOTTY);
427
428 case VFIFO:
429 case VCHR:
430 case VBLK:
431 error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p);
432 if (error == 0 && com == TIOCSCTTY) {
433 if (p->p_session->s_ttyvp)
434 vrele(p->p_session->s_ttyvp);
435 p->p_session->s_ttyvp = vp;
436 VREF(vp);
437 }
438 return (error);
439 }
440 }
441
442
443
444
445 int
446 vn_poll(struct file *fp, int events, struct proc *p)
447 {
448 return (VOP_POLL(((struct vnode *)fp->f_data), events, p));
449 }
450
451
452
453
454
455 int
456 vn_lock(struct vnode *vp, int flags, struct proc *p)
457 {
458 int error;
459
460 if ((flags & LK_RECURSEFAIL) == 0)
461 flags |= LK_CANRECURSE;
462
463 do {
464 if (vp->v_flag & VXLOCK) {
465 vp->v_flag |= VXWANT;
466 tsleep(vp, PINOD, "vn_lock", 0);
467 error = ENOENT;
468 } else {
469 error = VOP_LOCK(vp, flags, p);
470 if (error == 0)
471 return (error);
472 }
473 } while (flags & LK_RETRY);
474 return (error);
475 }
476
477
478
479
480 int
481 vn_closefile(struct file *fp, struct proc *p)
482 {
483 return (vn_close(((struct vnode *)fp->f_data), fp->f_flag,
484 fp->f_cred, p));
485 }
486
487 int
488 vn_kqfilter(struct file *fp, struct knote *kn)
489 {
490 return (VOP_KQFILTER(((struct vnode *)fp->f_data), kn));
491 }
492
493
494
495
496
497
498 int
499 vn_isunder(struct vnode *lvp, struct vnode *rvp, struct proc *p)
500 {
501 int error;
502
503 error = vfs_getcwd_common(lvp, rvp, NULL, NULL, MAXPATHLEN/2, 0, p);
504
505 if (!error)
506 return (1);
507
508 return (0);
509 }