This source file includes following definitions.
- ntfs_getpages
- ntfs_putpages
- ntfs_bmap
- ntfs_read
- ntfs_bypass
- ntfs_getattr
- ntfs_inactive
- ntfs_reclaim
- ntfs_print
- ntfs_strategy
- ntfs_write
- ntfs_access
- ntfs_open
- ntfs_close
- ntfs_readdir
- ntfs_lookup
- ntfs_fsync
- ntfs_pathconf
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 #include <sys/cdefs.h>
40 #ifdef __KERNEL_RCSID
41 __KERNEL_RCSID(0, "$NetBSD: ntfs_vnops.c,v 1.6 2003/04/10 21:57:26 jdolecek Exp $");
42 #endif
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/kernel.h>
47 #include <sys/time.h>
48 #include <sys/stat.h>
49 #include <sys/vnode.h>
50 #include <sys/mount.h>
51 #include <sys/namei.h>
52 #include <sys/malloc.h>
53 #include <sys/buf.h>
54 #include <sys/dirent.h>
55
56 #if !defined(__NetBSD__) && !defined(__OpenBSD__)
57 #include <vm/vm.h>
58 #endif
59
60 #if defined(__FreeBSD__)
61 #include <vm/vnode_pager.h>
62 #endif
63
64 #include <sys/sysctl.h>
65
66
67
68 #if defined(__FreeBSD__) || defined(__NetBSD__)
69 #include <fs/ntfs/ntfs.h>
70 #include <fs/ntfs/ntfs_inode.h>
71 #include <fs/ntfs/ntfs_subr.h>
72 #include <miscfs/genfs/genfs.h>
73 #else
74 #include <ntfs/ntfs.h>
75 #include <ntfs/ntfs_inode.h>
76 #include <ntfs/ntfs_subr.h>
77 #endif
78
79 #include <miscfs/specfs/specdev.h>
80
81 #include <sys/unistd.h>
82
83 static int ntfs_bypass(struct vop_generic_args *ap);
84 static int ntfs_read(struct vop_read_args *);
85 static int ntfs_write(struct vop_write_args *ap);
86 static int ntfs_getattr(struct vop_getattr_args *ap);
87 static int ntfs_inactive(struct vop_inactive_args *ap);
88 static int ntfs_print(struct vop_print_args *ap);
89 static int ntfs_reclaim(struct vop_reclaim_args *ap);
90 static int ntfs_strategy(struct vop_strategy_args *ap);
91 static int ntfs_access(struct vop_access_args *ap);
92 static int ntfs_open(struct vop_open_args *ap);
93 static int ntfs_close(struct vop_close_args *ap);
94 static int ntfs_readdir(struct vop_readdir_args *ap);
95 static int ntfs_lookup(struct vop_lookup_args *ap);
96 static int ntfs_bmap(struct vop_bmap_args *ap);
97 #if defined(__FreeBSD__)
98 static int ntfs_getpages(struct vop_getpages_args *ap);
99 static int ntfs_putpages(struct vop_putpages_args *);
100 #endif
101 #if defined(__FreeBSD__) || defined(__OpenBSD__)
102 static int ntfs_fsync(struct vop_fsync_args *ap);
103 #endif
104 static int ntfs_pathconf(void *);
105
106 int ntfs_prtactive = 1;
107
108 #if defined(__FreeBSD__)
109 int
110 ntfs_getpages(ap)
111 struct vop_getpages_args *ap;
112 {
113 return vnode_pager_generic_getpages(ap->a_vp, ap->a_m, ap->a_count,
114 ap->a_reqpage);
115 }
116
117 int
118 ntfs_putpages(ap)
119 struct vop_putpages_args *ap;
120 {
121 return vnode_pager_generic_putpages(ap->a_vp, ap->a_m, ap->a_count,
122 ap->a_sync, ap->a_rtvals);
123 }
124 #endif
125
126
127
128
129 int
130 ntfs_bmap(ap)
131 struct vop_bmap_args *ap;
132 {
133 dprintf(("ntfs_bmap: vn: %p, blk: %d\n", ap->a_vp,(u_int32_t)ap->a_bn));
134 if (ap->a_vpp != NULL)
135 *ap->a_vpp = ap->a_vp;
136 if (ap->a_bnp != NULL)
137 *ap->a_bnp = ap->a_bn;
138 if (ap->a_runp != NULL)
139 *ap->a_runp = 0;
140 #if !defined(__NetBSD__) && !defined(__OpenBSD__)
141 if (ap->a_runb != NULL)
142 *ap->a_runb = 0;
143 #endif
144 return (0);
145 }
146
147 static int
148 ntfs_read(ap)
149 struct vop_read_args *ap;
150 {
151 struct vnode *vp = ap->a_vp;
152 struct fnode *fp = VTOF(vp);
153 struct ntnode *ip = FTONT(fp);
154 struct uio *uio = ap->a_uio;
155 struct ntfsmount *ntmp = ip->i_mp;
156 u_int64_t toread;
157 int error;
158
159 dprintf(("ntfs_read: ino: %d, off: %d resid: %d, segflg: %d\n",ip->i_number,(u_int32_t)uio->uio_offset,uio->uio_resid,uio->uio_segflg));
160
161 dprintf(("ntfs_read: filesize: %d",(u_int32_t)fp->f_size));
162
163
164 if (uio->uio_offset > fp->f_size)
165 toread = 0;
166 else
167 toread = MIN(uio->uio_resid, fp->f_size - uio->uio_offset );
168
169 dprintf((", toread: %d\n",(u_int32_t)toread));
170
171 if (toread == 0)
172 return (0);
173
174 error = ntfs_readattr(ntmp, ip, fp->f_attrtype,
175 fp->f_attrname, uio->uio_offset, toread, NULL, uio);
176 if (error) {
177 printf("ntfs_read: ntfs_readattr failed: %d\n",error);
178 return (error);
179 }
180
181 return (0);
182 }
183
184 static int
185 ntfs_bypass(ap)
186 struct vop_generic_args *ap;
187 {
188 int error = ENOTTY;
189 dprintf(("ntfs_bypass: %s\n", ap->a_desc->vdesc_name));
190 return (error);
191 }
192
193
194 static int
195 ntfs_getattr(ap)
196 struct vop_getattr_args *ap;
197 {
198 struct vnode *vp = ap->a_vp;
199 struct fnode *fp = VTOF(vp);
200 struct ntnode *ip = FTONT(fp);
201 struct vattr *vap = ap->a_vap;
202
203 dprintf(("ntfs_getattr: %d, flags: %d\n",ip->i_number,ip->i_flag));
204
205 #if defined(__FreeBSD__)
206 vap->va_fsid = dev2udev(ip->i_dev);
207 #else
208 vap->va_fsid = ip->i_dev;
209 #endif
210 vap->va_fileid = ip->i_number;
211 vap->va_mode = ip->i_mp->ntm_mode;
212 vap->va_nlink = ip->i_nlink;
213 vap->va_uid = ip->i_mp->ntm_uid;
214 vap->va_gid = ip->i_mp->ntm_gid;
215 vap->va_rdev = 0;
216 vap->va_size = fp->f_size;
217 vap->va_bytes = fp->f_allocated;
218 vap->va_atime = ntfs_nttimetounix(fp->f_times.t_access);
219 vap->va_mtime = ntfs_nttimetounix(fp->f_times.t_write);
220 vap->va_ctime = ntfs_nttimetounix(fp->f_times.t_create);
221 vap->va_flags = ip->i_flag;
222 vap->va_gen = 0;
223 vap->va_blocksize = ip->i_mp->ntm_spc * ip->i_mp->ntm_bps;
224 vap->va_type = vp->v_type;
225 vap->va_filerev = 0;
226 return (0);
227 }
228
229
230
231
232
233 int
234 ntfs_inactive(ap)
235 struct vop_inactive_args *ap;
236 {
237 struct vnode *vp = ap->a_vp;
238 #ifdef __OpenBSD__
239 struct proc *p = ap->a_p;
240 #endif
241 #ifdef NTFS_DEBUG
242 struct ntnode *ip = VTONT(vp);
243 #endif
244
245 dprintf(("ntfs_inactive: vnode: %p, ntnode: %d\n", vp, ip->i_number));
246
247 #ifdef DIAGNOSTIC
248 if (ntfs_prtactive && vp->v_usecount != 0)
249 vprint("ntfs_inactive: pushing active", vp);
250 #endif
251
252 VOP__UNLOCK(vp, 0, p);
253
254
255
256
257 return (0);
258 }
259
260
261
262
263 int
264 ntfs_reclaim(ap)
265 struct vop_reclaim_args *ap;
266 {
267 struct vnode *vp = ap->a_vp;
268 struct fnode *fp = VTOF(vp);
269 struct ntnode *ip = FTONT(fp);
270 #ifdef __OpenBSD__
271 struct proc *p = ap->a_p;
272 #endif
273 int error;
274
275 dprintf(("ntfs_reclaim: vnode: %p, ntnode: %d\n", vp, ip->i_number));
276
277 #ifdef DIAGNOSTIC
278 if (ntfs_prtactive && vp->v_usecount != 0)
279 vprint("ntfs_reclaim: pushing active", vp);
280 #endif
281
282 #ifndef __OpenBSD__
283 if ((error = ntfs_ntget(ip)) != 0)
284 #else
285 if ((error = ntfs_ntget(ip, p)) != 0)
286 #endif
287 return (error);
288
289
290 cache_purge(vp);
291
292 ntfs_frele(fp);
293 #ifndef __OpenBSD__
294 ntfs_ntput(ip);
295 #else
296 ntfs_ntput(ip, p);
297 #endif
298 vp->v_data = NULL;
299
300 return (0);
301 }
302
303 static int
304 ntfs_print(ap)
305 struct vop_print_args *ap;
306 {
307 struct ntnode *ip = VTONT(ap->a_vp);
308
309 printf("tag VT_NTFS, ino %u, flag %#x, usecount %d, nlink %ld\n",
310 ip->i_number, ip->i_flag, ip->i_usecount, ip->i_nlink);
311
312 return (0);
313 }
314
315
316
317
318
319 int
320 ntfs_strategy(ap)
321 struct vop_strategy_args *ap;
322 {
323 struct buf *bp = ap->a_bp;
324 struct vnode *vp = bp->b_vp;
325 struct fnode *fp = VTOF(vp);
326 struct ntnode *ip = FTONT(fp);
327 struct ntfsmount *ntmp = ip->i_mp;
328 int error;
329
330 #ifdef __FreeBSD__
331 dprintf(("ntfs_strategy: offset: %d, blkno: %d, lblkno: %d\n",
332 (u_int32_t)bp->b_offset,(u_int32_t)bp->b_blkno,
333 (u_int32_t)bp->b_lblkno));
334 #else
335 dprintf(("ntfs_strategy: blkno: %d, lblkno: %d\n",
336 (u_int32_t)bp->b_blkno,
337 (u_int32_t)bp->b_lblkno));
338 #endif
339
340 dprintf(("strategy: bcount: %u flags: 0x%x\n",
341 (u_int32_t)bp->b_bcount,bp->b_flags));
342
343 if (bp->b_flags & B_READ) {
344 u_int32_t toread;
345
346 if (ntfs_cntob(bp->b_blkno) >= fp->f_size) {
347 clrbuf(bp);
348 error = 0;
349 } else {
350 toread = MIN(bp->b_bcount,
351 fp->f_size - ntfs_cntob(bp->b_blkno));
352 dprintf(("ntfs_strategy: toread: %d, fsize: %d\n",
353 toread,(u_int32_t)fp->f_size));
354
355 error = ntfs_readattr(ntmp, ip, fp->f_attrtype,
356 fp->f_attrname, ntfs_cntob(bp->b_blkno),
357 toread, bp->b_data, NULL);
358
359 if (error) {
360 printf("ntfs_strategy: ntfs_readattr failed\n");
361 bp->b_error = error;
362 bp->b_flags |= B_ERROR;
363 }
364
365 bzero(bp->b_data + toread, bp->b_bcount - toread);
366 }
367 } else {
368 size_t tmp;
369 u_int32_t towrite;
370
371 if (ntfs_cntob(bp->b_blkno) + bp->b_bcount >= fp->f_size) {
372 printf("ntfs_strategy: CAN'T EXTEND FILE\n");
373 bp->b_error = error = EFBIG;
374 bp->b_flags |= B_ERROR;
375 } else {
376 towrite = MIN(bp->b_bcount,
377 fp->f_size - ntfs_cntob(bp->b_blkno));
378 dprintf(("ntfs_strategy: towrite: %d, fsize: %d\n",
379 towrite,(u_int32_t)fp->f_size));
380
381 error = ntfs_writeattr_plain(ntmp, ip, fp->f_attrtype,
382 fp->f_attrname, ntfs_cntob(bp->b_blkno),towrite,
383 bp->b_data, &tmp, NULL);
384
385 if (error) {
386 printf("ntfs_strategy: ntfs_writeattr fail\n");
387 bp->b_error = error;
388 bp->b_flags |= B_ERROR;
389 }
390 }
391 }
392 biodone(bp);
393 return (error);
394 }
395
396 static int
397 ntfs_write(ap)
398 struct vop_write_args *ap;
399 {
400 struct vnode *vp = ap->a_vp;
401 struct fnode *fp = VTOF(vp);
402 struct ntnode *ip = FTONT(fp);
403 struct uio *uio = ap->a_uio;
404 struct ntfsmount *ntmp = ip->i_mp;
405 u_int64_t towrite;
406 size_t written;
407 int error;
408
409 dprintf(("ntfs_write: ino: %d, off: %d resid: %d, segflg: %d\n",ip->i_number,(u_int32_t)uio->uio_offset,uio->uio_resid,uio->uio_segflg));
410 dprintf(("ntfs_write: filesize: %d",(u_int32_t)fp->f_size));
411
412 if (uio->uio_resid + uio->uio_offset > fp->f_size) {
413 printf("ntfs_write: CAN'T WRITE BEYOND END OF FILE\n");
414 return (EFBIG);
415 }
416
417 towrite = MIN(uio->uio_resid, fp->f_size - uio->uio_offset);
418
419 dprintf((", towrite: %d\n",(u_int32_t)towrite));
420
421 error = ntfs_writeattr_plain(ntmp, ip, fp->f_attrtype,
422 fp->f_attrname, uio->uio_offset, towrite, NULL, &written, uio);
423 #ifdef NTFS_DEBUG
424 if (error)
425 printf("ntfs_write: ntfs_writeattr failed: %d\n", error);
426 #endif
427
428 return (error);
429 }
430
431 int
432 ntfs_access(ap)
433 struct vop_access_args *ap;
434 {
435 struct vnode *vp = ap->a_vp;
436 struct ntnode *ip = VTONT(vp);
437 struct ucred *cred = ap->a_cred;
438 mode_t mask, mode = ap->a_mode;
439 gid_t *gp;
440 int i;
441
442 dprintf(("ntfs_access: %d\n",ip->i_number));
443
444
445
446
447
448
449 if (mode & VWRITE) {
450 switch ((int)vp->v_type) {
451 case VDIR:
452 case VLNK:
453 case VREG:
454 if (vp->v_mount->mnt_flag & MNT_RDONLY)
455 return (EROFS);
456 break;
457 }
458 }
459
460
461 if (cred->cr_uid == 0)
462 return (0);
463
464 mask = 0;
465
466
467 if (cred->cr_uid == ip->i_mp->ntm_uid) {
468 if (mode & VEXEC)
469 mask |= S_IXUSR;
470 if (mode & VREAD)
471 mask |= S_IRUSR;
472 if (mode & VWRITE)
473 mask |= S_IWUSR;
474 return ((ip->i_mp->ntm_mode & mask) == mask ? 0 : EACCES);
475 }
476
477
478 for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
479 if (ip->i_mp->ntm_gid == *gp) {
480 if (mode & VEXEC)
481 mask |= S_IXGRP;
482 if (mode & VREAD)
483 mask |= S_IRGRP;
484 if (mode & VWRITE)
485 mask |= S_IWGRP;
486 return ((ip->i_mp->ntm_mode&mask) == mask ? 0 : EACCES);
487 }
488
489
490 if (mode & VEXEC)
491 mask |= S_IXOTH;
492 if (mode & VREAD)
493 mask |= S_IROTH;
494 if (mode & VWRITE)
495 mask |= S_IWOTH;
496 return ((ip->i_mp->ntm_mode & mask) == mask ? 0 : EACCES);
497 }
498
499
500
501
502
503
504
505 static int
506 ntfs_open(ap)
507 struct vop_open_args *ap;
508 {
509 #if NTFS_DEBUG
510 struct vnode *vp = ap->a_vp;
511 struct ntnode *ip = VTONT(vp);
512
513 printf("ntfs_open: %d\n",ip->i_number);
514 #endif
515
516
517
518
519
520 return (0);
521 }
522
523
524
525
526
527
528
529 static int
530 ntfs_close(ap)
531 struct vop_close_args *ap;
532 {
533 #if NTFS_DEBUG
534 struct vnode *vp = ap->a_vp;
535 struct ntnode *ip = VTONT(vp);
536
537 printf("ntfs_close: %d\n",ip->i_number);
538 #endif
539
540 return (0);
541 }
542
543 int
544 ntfs_readdir(ap)
545 struct vop_readdir_args *ap;
546 {
547 struct vnode *vp = ap->a_vp;
548 struct fnode *fp = VTOF(vp);
549 struct ntnode *ip = FTONT(fp);
550 struct uio *uio = ap->a_uio;
551 struct ntfsmount *ntmp = ip->i_mp;
552 int i, error = 0;
553 u_int32_t faked = 0, num;
554 int ncookies = 0;
555 struct dirent *cde;
556 off_t off;
557
558 dprintf(("ntfs_readdir %d off: %d resid: %d\n",ip->i_number,(u_int32_t)uio->uio_offset,uio->uio_resid));
559
560 off = uio->uio_offset;
561
562 MALLOC(cde, struct dirent *, sizeof(struct dirent), M_TEMP, M_WAITOK);
563
564
565 if (ip->i_number != NTFS_ROOTINO
566 && uio->uio_offset < sizeof(struct dirent)) {
567 cde->d_fileno = ip->i_number;
568 cde->d_reclen = sizeof(struct dirent);
569 cde->d_type = DT_DIR;
570 cde->d_namlen = 1;
571 strncpy(cde->d_name, ".", 2);
572 error = uiomove((void *)cde, sizeof(struct dirent), uio);
573 if (error)
574 goto out;
575
576 ncookies++;
577 }
578
579
580 if (uio->uio_offset < 2 * sizeof(struct dirent)) {
581 cde->d_fileno = NTFS_ROOTINO;
582 cde->d_reclen = sizeof(struct dirent);
583 cde->d_type = DT_DIR;
584 cde->d_namlen = 2;
585 strncpy(cde->d_name, "..", 3);
586
587 error = uiomove((void *) cde, sizeof(struct dirent), uio);
588 if (error)
589 goto out;
590
591 ncookies++;
592 }
593
594 faked = (ip->i_number == NTFS_ROOTINO) ? 1 : 2;
595 num = uio->uio_offset / sizeof(struct dirent) - faked;
596
597 while (uio->uio_resid >= sizeof(struct dirent)) {
598 struct attr_indexentry *iep;
599 char *fname;
600 size_t remains;
601 int sz;
602
603 #ifndef __OpenBSD__
604 error = ntfs_ntreaddir(ntmp, fp, num, &iep);
605 #else
606 error = ntfs_ntreaddir(ntmp, fp, num, &iep, uio->uio_procp);
607 #endif
608 if (error)
609 goto out;
610
611 if (NULL == iep)
612 break;
613
614 for(; !(iep->ie_flag & NTFS_IEFLAG_LAST) && (uio->uio_resid >= sizeof(struct dirent));
615 iep = NTFS_NEXTREC(iep, struct attr_indexentry *))
616 {
617 if(!ntfs_isnamepermitted(ntmp,iep))
618 continue;
619
620 remains = sizeof(cde->d_name) - 1;
621 fname = cde->d_name;
622 for(i=0; i<iep->ie_fnamelen; i++) {
623 sz = (*ntmp->ntm_wput)(fname, remains,
624 iep->ie_fname[i]);
625 fname += sz;
626 remains -= sz;
627 }
628 *fname = '\0';
629 dprintf(("ntfs_readdir: elem: %d, fname:[%s] type: %d, flag: %d, ",
630 num, cde->d_name, iep->ie_fnametype,
631 iep->ie_flag));
632 cde->d_namlen = fname - (char *) cde->d_name;
633 cde->d_fileno = iep->ie_number;
634 cde->d_type = (iep->ie_fflag & NTFS_FFLAG_DIR) ? DT_DIR : DT_REG;
635 cde->d_reclen = sizeof(struct dirent);
636 dprintf(("%s\n", (cde->d_type == DT_DIR) ? "dir":"reg"));
637
638 error = uiomove((void *)cde, sizeof(struct dirent), uio);
639 if (error)
640 goto out;
641
642 ncookies++;
643 num++;
644 }
645 }
646
647 dprintf(("ntfs_readdir: %d entries (%d bytes) read\n",
648 ncookies,(u_int)(uio->uio_offset - off)));
649 dprintf(("ntfs_readdir: off: %d resid: %d\n",
650 (u_int32_t)uio->uio_offset,uio->uio_resid));
651
652 if (!error && ap->a_ncookies != NULL) {
653 struct dirent* dpStart;
654 struct dirent* dp;
655 #if defined(__FreeBSD__) || defined(__OpenBSD__)
656 u_long *cookies;
657 u_long *cookiep;
658 #else
659 off_t *cookies;
660 off_t *cookiep;
661 #endif
662
663 dprintf(("ntfs_readdir: %d cookies\n",ncookies));
664 if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
665 panic("ntfs_readdir: unexpected uio from NFS server");
666 dpStart = (struct dirent *)
667 ((caddr_t)uio->uio_iov->iov_base -
668 (uio->uio_offset - off));
669 #if defined(__FreeBSD__)
670 MALLOC(cookies, u_long *, ncookies * sizeof(u_long),
671 M_TEMP, M_WAITOK);
672 #else
673 cookies = malloc(ncookies * sizeof(off_t), M_TEMP, M_WAITOK);
674 #endif
675 for (dp = dpStart, cookiep = cookies, i=0;
676 i < ncookies;
677 dp = (struct dirent *)((caddr_t) dp + dp->d_reclen), i++) {
678 off += dp->d_reclen;
679 *cookiep++ = (u_int) off;
680 }
681 *ap->a_ncookies = ncookies;
682 *ap->a_cookies = cookies;
683 }
684
685
686
687
688 out:
689 FREE(cde, M_TEMP);
690 return (error);
691 }
692
693 int
694 ntfs_lookup(ap)
695 struct vop_lookup_args *ap;
696 {
697 struct vnode *dvp = ap->a_dvp;
698 struct ntnode *dip = VTONT(dvp);
699 struct ntfsmount *ntmp = dip->i_mp;
700 struct componentname *cnp = ap->a_cnp;
701 struct ucred *cred = cnp->cn_cred;
702 int error;
703 int lockparent = cnp->cn_flags & LOCKPARENT;
704 #ifdef __OpenBSD__
705 struct proc *p = cnp->cn_proc;
706 #endif
707 #if NTFS_DEBUG
708 int wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT);
709 #endif
710 dprintf(("ntfs_lookup: \"%.*s\" (%ld bytes) in %d, lp: %d, wp: %d \n",
711 (int)cnp->cn_namelen, cnp->cn_nameptr, cnp->cn_namelen,
712 dip->i_number, lockparent, wantparent));
713
714 error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_proc);
715 if(error)
716 return (error);
717
718 if ((cnp->cn_flags & ISLASTCN) &&
719 (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
720 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
721 return (EROFS);
722
723 #if defined(__NetBSD__) || defined(__OpenBSD__)
724
725
726
727
728
729
730
731
732 if ((error = cache_lookup(ap->a_dvp, ap->a_vpp, cnp)) >= 0)
733 return (error);
734 #endif
735
736 if(cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
737 dprintf(("ntfs_lookup: faking . directory in %d\n",
738 dip->i_number));
739
740 VREF(dvp);
741 *ap->a_vpp = dvp;
742 error = 0;
743 } else if (cnp->cn_flags & ISDOTDOT) {
744 struct ntvattr *vap;
745
746 dprintf(("ntfs_lookup: faking .. directory in %d\n",
747 dip->i_number));
748
749 VOP__UNLOCK(dvp, 0, p);
750 cnp->cn_flags |= PDIRUNLOCK;
751
752 error = ntfs_ntvattrget(ntmp, dip, NTFS_A_NAME, NULL, 0, &vap);
753 if(error)
754 return (error);
755
756 dprintf(("ntfs_lookup: parentdir: %d\n",
757 vap->va_a_name->n_pnumber));
758 error = VFS_VGET(ntmp->ntm_mountp,
759 vap->va_a_name->n_pnumber,ap->a_vpp);
760 ntfs_ntvattrrele(vap);
761 if (error) {
762 if (VN_LOCK(dvp, LK_EXCLUSIVE | LK_RETRY, p) == 0)
763 cnp->cn_flags &= ~PDIRUNLOCK;
764 return (error);
765 }
766
767 if (lockparent && (cnp->cn_flags & ISLASTCN)) {
768 error = VN_LOCK(dvp, LK_EXCLUSIVE, p);
769 if (error) {
770 vput( *(ap->a_vpp) );
771 return (error);
772 }
773 cnp->cn_flags &= ~PDIRUNLOCK;
774 }
775 } else {
776 #ifndef __OpenBSD__
777 error = ntfs_ntlookupfile(ntmp, dvp, cnp, ap->a_vpp);
778 #else
779 error = ntfs_ntlookupfile(ntmp, dvp, cnp, ap->a_vpp, p);
780 #endif
781 if (error) {
782 dprintf(("ntfs_ntlookupfile: returned %d\n", error));
783 return (error);
784 }
785
786 dprintf(("ntfs_lookup: found ino: %d\n",
787 VTONT(*ap->a_vpp)->i_number));
788
789 if(!lockparent || (cnp->cn_flags & ISLASTCN) == 0) {
790 VOP__UNLOCK(dvp, 0, p);
791 cnp->cn_flags |= PDIRUNLOCK;
792 }
793 }
794
795 if (cnp->cn_flags & MAKEENTRY)
796 cache_enter(dvp, *ap->a_vpp, cnp);
797
798 return (error);
799 }
800
801 #if defined(__FreeBSD__) || defined(__OpenBSD__)
802
803
804
805
806
807
808 static int
809 ntfs_fsync(ap)
810 struct vop_fsync_args *ap;
811 {
812 return (0);
813 }
814 #endif
815
816
817
818
819 static int
820 ntfs_pathconf(v)
821 void *v;
822 {
823 struct vop_pathconf_args *ap = v;
824
825 switch (ap->a_name) {
826 case _PC_LINK_MAX:
827 *ap->a_retval = 1;
828 return (0);
829 case _PC_NAME_MAX:
830 *ap->a_retval = NTFS_MAXFILENAME;
831 return (0);
832 case _PC_PATH_MAX:
833 *ap->a_retval = PATH_MAX;
834 return (0);
835 case _PC_CHOWN_RESTRICTED:
836 *ap->a_retval = 1;
837 return (0);
838 case _PC_NO_TRUNC:
839 *ap->a_retval = 0;
840 return (0);
841 #ifdef __NetBSD__
842 case _PC_SYNC_IO:
843 *ap->a_retval = 1;
844 return (0);
845 case _PC_FILESIZEBITS:
846 *ap->a_retval = 64;
847 return (0);
848 #endif
849 default:
850 return (EINVAL);
851 }
852
853 }
854
855
856
857
858 vop_t **ntfs_vnodeop_p;
859 #if defined(__FreeBSD__)
860 static
861 struct vnodeopv_entry_desc ntfs_vnodeop_entries[] = {
862 { &vop_default_desc, (vop_t *)ntfs_bypass },
863
864 { &vop_getattr_desc, (vop_t *)ntfs_getattr },
865 { &vop_inactive_desc, (vop_t *)ntfs_inactive },
866 { &vop_reclaim_desc, (vop_t *)ntfs_reclaim },
867 { &vop_print_desc, (vop_t *)ntfs_print },
868 { &vop_pathconf_desc, ntfs_pathconf },
869
870 { &vop_islocked_desc, (vop_t *)vop_stdislocked },
871 { &vop_unlock_desc, (vop_t *)vop_stdunlock },
872 { &vop_lock_desc, (vop_t *)vop_stdlock },
873 { &vop_cachedlookup_desc, (vop_t *)ntfs_lookup },
874 { &vop_lookup_desc, (vop_t *)vfs_cache_lookup },
875
876 { &vop_access_desc, (vop_t *)ntfs_access },
877 { &vop_close_desc, (vop_t *)ntfs_close },
878 { &vop_open_desc, (vop_t *)ntfs_open },
879 { &vop_readdir_desc, (vop_t *)ntfs_readdir },
880 { &vop_fsync_desc, (vop_t *)ntfs_fsync },
881
882 { &vop_bmap_desc, (vop_t *)ntfs_bmap },
883 { &vop_getpages_desc, (vop_t *) ntfs_getpages },
884 { &vop_putpages_desc, (vop_t *) ntfs_putpages },
885 { &vop_strategy_desc, (vop_t *)ntfs_strategy },
886 { &vop_bwrite_desc, (vop_t *)vop_stdbwrite },
887 { &vop_read_desc, (vop_t *)ntfs_read },
888 { &vop_write_desc, (vop_t *)ntfs_write },
889
890 { NULL, NULL }
891 };
892
893 static
894 struct vnodeopv_desc ntfs_vnodeop_opv_desc =
895 { &ntfs_vnodeop_p, ntfs_vnodeop_entries };
896
897 VNODEOP_SET(ntfs_vnodeop_opv_desc);
898
899 #elif defined(__OpenBSD__)
900 static
901 struct vnodeopv_entry_desc ntfs_vnodeop_entries[] = {
902 { &vop_default_desc, (vop_t *)ntfs_bypass },
903
904 { &vop_getattr_desc, (vop_t *)ntfs_getattr },
905 { &vop_inactive_desc, (vop_t *)ntfs_inactive },
906 { &vop_reclaim_desc, (vop_t *)ntfs_reclaim },
907 { &vop_print_desc, (vop_t *)ntfs_print },
908 { &vop_pathconf_desc, ntfs_pathconf },
909
910 { &vop_islocked_desc, (vop_t *)vop_generic_islocked },
911 { &vop_unlock_desc, (vop_t *)vop_generic_unlock },
912 { &vop_lock_desc, (vop_t *)vop_generic_lock },
913 { &vop_lookup_desc, (vop_t *)ntfs_lookup },
914
915 { &vop_access_desc, (vop_t *)ntfs_access },
916 { &vop_close_desc, (vop_t *)ntfs_close },
917 { &vop_open_desc, (vop_t *)ntfs_open },
918 { &vop_readdir_desc, (vop_t *)ntfs_readdir },
919 { &vop_fsync_desc, (vop_t *)ntfs_fsync },
920
921 { &vop_bmap_desc, (vop_t *)ntfs_bmap },
922 { &vop_strategy_desc, (vop_t *)ntfs_strategy },
923 { &vop_bwrite_desc, (vop_t *)vop_generic_bwrite },
924 { &vop_read_desc, (vop_t *)ntfs_read },
925 { &vop_write_desc, (vop_t *)ntfs_write },
926
927 { NULL, NULL }
928 };
929
930 const struct vnodeopv_desc ntfs_vnodeop_opv_desc =
931 { &ntfs_vnodeop_p, ntfs_vnodeop_entries };
932
933 #else
934
935 const struct vnodeopv_entry_desc ntfs_vnodeop_entries[] = {
936 { &vop_default_desc, (vop_t *) ntfs_bypass },
937 { &vop_lookup_desc, (vop_t *) ntfs_lookup },
938 { &vop_create_desc, genfs_eopnotsupp },
939 { &vop_mknod_desc, genfs_eopnotsupp },
940 { &vop_open_desc, (vop_t *) ntfs_open },
941 { &vop_close_desc,(vop_t *) ntfs_close },
942 { &vop_access_desc, (vop_t *) ntfs_access },
943 { &vop_getattr_desc, (vop_t *) ntfs_getattr },
944 { &vop_setattr_desc, genfs_eopnotsupp },
945 { &vop_read_desc, (vop_t *) ntfs_read },
946 { &vop_write_desc, (vop_t *) ntfs_write },
947 { &vop_lease_desc, genfs_lease_check },
948 { &vop_fcntl_desc, genfs_fcntl },
949 { &vop_ioctl_desc, genfs_enoioctl },
950 { &vop_poll_desc, genfs_poll },
951 { &vop_kqfilter_desc, genfs_kqfilter },
952 { &vop_revoke_desc, genfs_revoke },
953 { &vop_mmap_desc, genfs_mmap },
954 { &vop_fsync_desc, genfs_fsync },
955 { &vop_seek_desc, genfs_seek },
956 { &vop_remove_desc, genfs_eopnotsupp },
957 { &vop_link_desc, genfs_eopnotsupp },
958 { &vop_rename_desc, genfs_eopnotsupp },
959 { &vop_mkdir_desc, genfs_eopnotsupp },
960 { &vop_rmdir_desc, genfs_eopnotsupp },
961 { &vop_symlink_desc, genfs_eopnotsupp },
962 { &vop_readdir_desc, (vop_t *) ntfs_readdir },
963 { &vop_readlink_desc, genfs_eopnotsupp },
964 { &vop_abortop_desc, genfs_abortop },
965 { &vop_inactive_desc, (vop_t *) ntfs_inactive },
966 { &vop_reclaim_desc, (vop_t *) ntfs_reclaim },
967 { &vop_lock_desc, genfs_lock },
968 { &vop_unlock_desc, genfs_unlock },
969 { &vop_bmap_desc, (vop_t *) ntfs_bmap },
970 { &vop_strategy_desc, (vop_t *) ntfs_strategy },
971 { &vop_print_desc, (vop_t *) ntfs_print },
972 { &vop_islocked_desc, genfs_islocked },
973 { &vop_pathconf_desc, ntfs_pathconf },
974 { &vop_advlock_desc, genfs_nullop },
975 { &vop_blkatoff_desc, genfs_eopnotsupp },
976 { &vop_valloc_desc, genfs_eopnotsupp },
977 { &vop_reallocblks_desc, genfs_eopnotsupp },
978 { &vop_vfree_desc, genfs_eopnotsupp },
979 { &vop_truncate_desc, genfs_eopnotsupp },
980 { &vop_update_desc, genfs_eopnotsupp },
981 { &vop_bwrite_desc, vn_bwrite },
982 { &vop_getpages_desc, genfs_compat_getpages },
983 { &vop_putpages_desc, genfs_putpages },
984 { NULL, NULL }
985 };
986 const struct vnodeopv_desc ntfs_vnodeop_opv_desc =
987 { &ntfs_vnodeop_p, ntfs_vnodeop_entries };
988
989 #endif