This source file includes following definitions.
- ntfs_checkexp
- ntfs_sysctl
- ntfs_mountroot
- ntfs_init
- ntfs_reinit
- ntfs_done
- ntfs_init
- ntfs_mount
- ntfs_mountfs
- ntfs_start
- ntfs_unmount
- ntfs_root
- ntfs_quotactl
- ntfs_calccfree
- ntfs_statfs
- ntfs_sync
- ntfs_fhtovp
- ntfs_vptofh
- ntfs_vgetex
- ntfs_vget
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 #include <sys/cdefs.h>
33 #ifdef __KERNEL_RCSID
34 __KERNEL_RCSID(0, "$NetBSD: ntfs_vfsops.c,v 1.7 2003/04/24 07:50:19 christos Exp $");
35 #endif
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/namei.h>
40 #include <sys/proc.h>
41 #include <sys/kernel.h>
42 #include <sys/vnode.h>
43 #include <sys/mount.h>
44 #include <sys/buf.h>
45 #include <sys/fcntl.h>
46 #include <sys/malloc.h>
47 #include <sys/systm.h>
48 #include <sys/device.h>
49 #include <sys/conf.h>
50
51 #if defined(__NetBSD__) || defined(__OpenBSD__)
52 #include <uvm/uvm_extern.h>
53 #else
54 #include <vm/vm.h>
55 #endif
56
57 #include <miscfs/specfs/specdev.h>
58
59
60 #if defined(__FreeBSD__) || defined(__NetBSD__)
61 #include <fs/ntfs/ntfs.h>
62 #include <fs/ntfs/ntfs_inode.h>
63 #include <fs/ntfs/ntfs_subr.h>
64 #include <fs/ntfs/ntfs_vfsops.h>
65 #include <fs/ntfs/ntfs_ihash.h>
66 #include <fs/ntfs/ntfsmount.h>
67 #else
68 #include <ntfs/ntfs.h>
69 #include <ntfs/ntfs_inode.h>
70 #include <ntfs/ntfs_subr.h>
71 #include <ntfs/ntfs_vfsops.h>
72 #include <ntfs/ntfs_ihash.h>
73 #include <ntfs/ntfsmount.h>
74 #endif
75
76 #ifdef MALLOC_DEFINE
77 MALLOC_DEFINE(M_NTFSMNT, "NTFS mount", "NTFS mount structure");
78 MALLOC_DEFINE(M_NTFSNTNODE,"NTFS ntnode", "NTFS ntnode information");
79 MALLOC_DEFINE(M_NTFSFNODE,"NTFS fnode", "NTFS fnode information");
80 MALLOC_DEFINE(M_NTFSDIR,"NTFS dir", "NTFS dir buffer");
81 #endif
82
83 #if defined(__FreeBSD__)
84 static int ntfs_mount(struct mount *, char *, caddr_t,
85 struct nameidata *, struct proc *);
86 #else
87 static int ntfs_mount(struct mount *, const char *, void *,
88 struct nameidata *, struct proc *);
89 #endif
90 static int ntfs_quotactl(struct mount *, int, uid_t, caddr_t,
91 struct proc *);
92 static int ntfs_root(struct mount *, struct vnode **);
93 static int ntfs_start(struct mount *, int, struct proc *);
94 static int ntfs_statfs(struct mount *, struct statfs *,
95 struct proc *);
96 static int ntfs_sync(struct mount *, int, struct ucred *,
97 struct proc *);
98 static int ntfs_unmount(struct mount *, int, struct proc *);
99 static int ntfs_vget(struct mount *mp, ino_t ino,
100 struct vnode **vpp);
101 static int ntfs_mountfs(struct vnode *, struct mount *,
102 struct ntfs_args *, struct proc *);
103 static int ntfs_vptofh(struct vnode *, struct fid *);
104
105 #if defined(__FreeBSD__)
106 static int ntfs_init(struct vfsconf *);
107 static int ntfs_fhtovp(struct mount *, struct fid *,
108 struct sockaddr *, struct vnode **,
109 int *, struct ucred **);
110 #elif defined(__NetBSD__)
111 static void ntfs_init(void);
112 static void ntfs_reinit(void);
113 static void ntfs_done(void);
114 static int ntfs_fhtovp(struct mount *, struct fid *,
115 struct vnode **);
116 static int ntfs_checkexp(struct mount *, struct mbuf *,
117 int *, struct ucred **);
118 static int ntfs_mountroot(void);
119 static int ntfs_sysctl(int *, u_int, void *, size_t *, void *,
120 size_t, struct proc *);
121 #elif defined(__OpenBSD__)
122 static int ntfs_init(struct vfsconf *);
123 static int ntfs_fhtovp(struct mount *, struct fid *,
124 struct vnode **);
125 static int ntfs_checkexp(struct mount *, struct mbuf *,
126 int *, struct ucred **);
127 static int ntfs_sysctl(int *, u_int, void *, size_t *, void *,
128 size_t, struct proc *);
129 #else
130 static int ntfs_init(void);
131 static int ntfs_fhtovp(struct mount *, struct fid *,
132 struct mbuf *, struct vnode **,
133 int *, struct ucred **);
134 #endif
135
136 #if defined(__FreeBSD__) || defined(__NetBSD__)
137 struct genfs_ops ntfs_genfsops = {
138 NULL,
139 NULL,
140 genfs_compat_gop_write,
141 };
142 #endif
143
144 #if defined(__NetBSD__) || defined(__OpenBSD__)
145
146
147
148
149 static int
150 ntfs_checkexp(mp, nam, exflagsp, credanonp)
151 struct mount *mp;
152 struct mbuf *nam;
153 int *exflagsp;
154 struct ucred **credanonp;
155 {
156 struct netcred *np;
157 struct ntfsmount *ntm = VFSTONTFS(mp);
158
159
160
161
162 np = vfs_export_lookup(mp, &ntm->ntm_export, nam);
163 if (np == NULL)
164 return (EACCES);
165
166 *exflagsp = np->netc_exflags;
167 *credanonp = &np->netc_anon;
168 return (0);
169 }
170
171
172 static int
173 ntfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
174 int *name;
175 u_int namelen;
176 void *oldp;
177 size_t *oldlenp;
178 void *newp;
179 size_t newlen;
180 struct proc *p;
181 {
182 return (EINVAL);
183 }
184
185 #endif
186
187 #ifdef __NetBSD__
188 static int
189 ntfs_mountroot()
190 {
191 struct mount *mp;
192 struct proc *p = curproc;
193 int error;
194 struct ntfs_args args;
195
196 if (root_device->dv_class != DV_DISK)
197 return (ENODEV);
198
199
200
201
202 if (bdevvp(rootdev, &rootvp))
203 panic("ntfs_mountroot: can't setup rootvp");
204
205 if ((error = vfs_rootmountalloc(MOUNT_NTFS, "root_device", &mp))) {
206 vrele(rootvp);
207 return (error);
208 }
209
210 args.flag = 0;
211 args.uid = 0;
212 args.gid = 0;
213 args.mode = 0777;
214
215 if ((error = ntfs_mountfs(rootvp, mp, &args, p)) != 0) {
216 mp->mnt_op->vfs_refcount--;
217 vfs_unbusy(mp);
218 free(mp, M_MOUNT);
219 vrele(rootvp);
220 return (error);
221 }
222
223 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
224 (void)ntfs_statfs(mp, &mp->mnt_stat, p);
225 vfs_unbusy(mp);
226
227 return (0);
228 }
229
230 static void
231 ntfs_init()
232 {
233 #ifdef _LKM
234 malloc_type_attach(M_NTFSMNT);
235 malloc_type_attach(M_NTFSNTNODE);
236 malloc_type_attach(M_NTFSFNODE);
237 malloc_type_attach(M_NTFSDIR);
238 malloc_type_attach(M_NTFSNTHASH);
239 malloc_type_attach(M_NTFSNTVATTR);
240 malloc_type_attach(M_NTFSRDATA);
241 malloc_type_attach(M_NTFSDECOMP);
242 malloc_type_attach(M_NTFSRUN);
243 #endif
244 ntfs_nthashinit();
245 ntfs_toupper_init();
246 }
247
248 static void
249 ntfs_reinit()
250 {
251 ntfs_nthashreinit();
252 }
253
254 static void
255 ntfs_done()
256 {
257 ntfs_nthashdone();
258 #ifdef _LKM
259 malloc_type_detach(M_NTFSMNT);
260 malloc_type_detach(M_NTFSNTNODE);
261 malloc_type_detach(M_NTFSFNODE);
262 malloc_type_detach(M_NTFSDIR);
263 malloc_type_detach(M_NTFSNTHASH);
264 malloc_type_detach(M_NTFSNTVATTR);
265 malloc_type_detach(M_NTFSRDATA);
266 malloc_type_detach(M_NTFSDECOMP);
267 malloc_type_detach(M_NTFSRUN);
268 #endif
269 }
270
271 #elif defined(__FreeBSD__) || defined(__OpenBSD__)
272
273 static int
274 ntfs_init (
275 struct vfsconf *vcp )
276 {
277 ntfs_nthashinit();
278 ntfs_toupper_init();
279 return 0;
280 }
281
282 #endif
283
284 static int
285 ntfs_mount(
286 struct mount *mp,
287 #if defined(__FreeBSD__)
288 char *path,
289 caddr_t data,
290 #else
291 const char *path,
292 void *data,
293 #endif
294 struct nameidata *ndp,
295 struct proc *p )
296 {
297 int err = 0;
298 struct vnode *devvp;
299 struct ntfs_args args;
300 size_t size;
301 mode_t amode;
302
303 #ifdef __FreeBSD__
304
305
306
307 if( path == NULL) {
308
309
310
311
312
313
314
315 if( bdevvp( rootdev, &rootvp))
316 panic("ffs_mountroot: can't setup bdevvp for root");
317
318
319
320
321 mp->mnt_flag |= MNT_RDONLY;
322
323
324
325
326 if( ( err = ntfs_mountfs(rootvp, mp, &args, p)) != 0) {
327
328 goto error_1;
329 }
330
331 goto dostatfs;
332
333 }
334 #endif
335
336 #ifdef __NetBSD__
337 if (mp->mnt_flag & MNT_GETARGS) {
338 struct ntfsmount *ntmp = VFSTONTFS(mp);
339 if (ntmp == NULL)
340 return EIO;
341 args.fspec = NULL;
342 args.uid = ntmp->ntm_uid;
343 args.gid = ntmp->ntm_gid;
344 args.mode = ntmp->ntm_mode;
345 args.flag = ntmp->ntm_flag;
346 vfs_showexport(mp, &args.export, &ntmp->ntm_export);
347 return copyout(&args, data, sizeof(args));
348 }
349 #endif
350
351
352
353
354
355
356
357
358 err = copyin(data, (caddr_t)&args, sizeof (struct ntfs_args));
359 if (err)
360 goto error_1;
361
362
363
364
365
366 if (mp->mnt_flag & MNT_UPDATE) {
367
368 if (args.fspec == 0) {
369
370
371
372
373 struct ntfsmount *ntm = VFSTONTFS(mp);
374 err = vfs_export(mp, &ntm->ntm_export, &args.export_info);
375 goto success;
376 }
377
378 printf("ntfs_mount(): MNT_UPDATE not supported\n");
379 err = EINVAL;
380 goto error_1;
381 }
382
383
384
385
386
387 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
388 err = namei(ndp);
389 if (err) {
390
391 goto error_1;
392 }
393
394 devvp = ndp->ni_vp;
395
396 if (devvp->v_type != VBLK) {
397 err = ENOTBLK;
398 goto error_2;
399 }
400
401 #ifdef __FreeBSD__
402 if (bdevsw(devvp->v_rdev) == NULL) {
403 #elif defined(__NetBSD__)
404 if (bdevsw_lookup(devvp->v_rdev) == NULL) {
405 #else
406 if (major(devvp->v_rdev) >= nblkdev) {
407 #endif
408 err = ENXIO;
409 goto error_2;
410 }
411
412
413
414
415
416 if (p->p_ucred->cr_uid) {
417 amode = (mp->mnt_flag & MNT_RDONLY) ? VREAD : (VREAD | VWRITE);
418 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
419 err = VOP_ACCESS(devvp, amode, p->p_ucred, p);
420 VOP_UNLOCK(devvp, 0, p);
421 if (err)
422 goto error_2;
423 }
424
425 if (mp->mnt_flag & MNT_UPDATE) {
426 #if 0
427
428
429
430
431
432
433 if (devvp != ntmp->um_devvp)
434 err = EINVAL;
435 else
436 vrele(devvp);
437
438
439
440 if( !err) {
441 err = set_statfs_info(NULL, UIO_USERSPACE, args.fspec,
442 UIO_USERSPACE, mp, p);
443 }
444 #endif
445 } else {
446
447
448
449
450
451
452
453
454
455
456
457
458
459 #if defined(__FreeBSD__) || defined(__NetBSD__)
460 err = set_statfs_info(path, UIO_USERSPACE, args.fspec,
461 UIO_USERSPACE, mp, p);
462 #else
463 (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1,
464 &size);
465 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
466 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname,
467 MNAMELEN - 1, &size);
468 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
469 bcopy(&args, &mp->mnt_stat.mount_info.ntfs_args, sizeof(args));
470 #endif
471 if ( !err) {
472 err = ntfs_mountfs(devvp, mp, &args, p);
473 }
474 }
475 if (err) {
476 goto error_2;
477 }
478
479 #ifdef __FreeBSD__
480 dostatfs:
481 #endif
482
483
484
485
486
487
488 (void)VFS_STATFS(mp, &mp->mnt_stat, p);
489
490 goto success;
491
492
493 error_2:
494
495
496 vrele(devvp);
497
498 error_1:
499
500 success:
501 return(err);
502 }
503
504
505
506
507 int
508 ntfs_mountfs(devvp, mp, argsp, p)
509 struct vnode *devvp;
510 struct mount *mp;
511 struct ntfs_args *argsp;
512 struct proc *p;
513 {
514 struct buf *bp;
515 struct ntfsmount *ntmp = NULL;
516 dev_t dev = devvp->v_rdev;
517 int error, ronly, ncount, i;
518 struct vnode *vp;
519
520
521
522
523
524
525
526 error = vfs_mountedon(devvp);
527 if (error)
528 return (error);
529 ncount = vcount(devvp);
530 if (ncount > 1 && devvp != rootvp)
531 return (EBUSY);
532 error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0);
533 if (error)
534 return (error);
535
536 ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
537 error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
538 if (error)
539 return (error);
540
541 bp = NULL;
542
543 error = bread(devvp, BBLOCK, BBSIZE, NOCRED, &bp);
544 if (error)
545 goto out;
546 ntmp = malloc(sizeof *ntmp, M_NTFSMNT, M_WAITOK);
547 bzero(ntmp, sizeof *ntmp);
548 bcopy(bp->b_data, &ntmp->ntm_bootfile, sizeof(struct bootfile));
549 brelse(bp);
550 bp = NULL;
551
552 if (strncmp(ntmp->ntm_bootfile.bf_sysid, NTFS_BBID, NTFS_BBIDLEN)) {
553 error = EINVAL;
554 dprintf(("ntfs_mountfs: invalid boot block\n"));
555 goto out;
556 }
557
558 {
559 int8_t cpr = ntmp->ntm_mftrecsz;
560 if( cpr > 0 )
561 ntmp->ntm_bpmftrec = ntmp->ntm_spc * cpr;
562 else
563 ntmp->ntm_bpmftrec = (1 << (-cpr)) / ntmp->ntm_bps;
564 }
565 dprintf(("ntfs_mountfs(): bps: %d, spc: %d, media: %x, mftrecsz: %d (%d sects)\n",
566 ntmp->ntm_bps,ntmp->ntm_spc,ntmp->ntm_bootfile.bf_media,
567 ntmp->ntm_mftrecsz,ntmp->ntm_bpmftrec));
568 dprintf(("ntfs_mountfs(): mftcn: 0x%x|0x%x\n",
569 (u_int32_t)ntmp->ntm_mftcn,(u_int32_t)ntmp->ntm_mftmirrcn));
570
571 ntmp->ntm_mountp = mp;
572 ntmp->ntm_dev = dev;
573 ntmp->ntm_devvp = devvp;
574 ntmp->ntm_uid = argsp->uid;
575 ntmp->ntm_gid = argsp->gid;
576 ntmp->ntm_mode = argsp->mode;
577 ntmp->ntm_flag = argsp->flag;
578 #ifdef __OpenBSD__
579 mp->mnt_data = (qaddr_t) ntmp;
580 #else
581 mp->mnt_data = ntmp;
582 #endif
583
584
585 ntmp->ntm_wget = ntfs_utf8_wget;
586 ntmp->ntm_wput = ntfs_utf8_wput;
587 ntmp->ntm_wcmp = ntfs_utf8_wcmp;
588
589 dprintf(("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n",
590 (ntmp->ntm_flag & NTFS_MFLAG_CASEINS)?"insens.":"sens.",
591 (ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES)?" allnames,":"",
592 ntmp->ntm_uid, ntmp->ntm_gid, ntmp->ntm_mode));
593
594
595
596
597
598 {
599 int pi[3] = { NTFS_MFTINO, NTFS_ROOTINO, NTFS_BITMAPINO };
600 for (i=0; i<3; i++) {
601 error = VFS_VGET(mp, pi[i], &(ntmp->ntm_sysvn[pi[i]]));
602 if(error)
603 goto out1;
604 ntmp->ntm_sysvn[pi[i]]->v_flag |= VSYSTEM;
605 VREF(ntmp->ntm_sysvn[pi[i]]);
606 vput(ntmp->ntm_sysvn[pi[i]]);
607 }
608 }
609
610
611
612 #ifndef __OpenBSD__
613 if ((error = ntfs_toupper_use(mp, ntmp)))
614 #else
615 if ((error = ntfs_toupper_use(mp, ntmp, p)))
616 #endif
617 goto out1;
618
619
620
621
622 error = ntfs_calccfree(ntmp, &ntmp->ntm_cfree);
623 if(error)
624 goto out1;
625
626
627
628
629
630 {
631 int num,j;
632 struct attrdef ad;
633
634
635 error = VFS_VGET(mp, NTFS_ATTRDEFINO, &vp );
636 if(error)
637 goto out1;
638
639
640 for(num=0;;num++) {
641 error = ntfs_readattr(ntmp, VTONT(vp),
642 NTFS_A_DATA, NULL,
643 num * sizeof(ad), sizeof(ad),
644 &ad, NULL);
645 if (error)
646 goto out1;
647 if (ad.ad_name[0] == 0)
648 break;
649 }
650
651
652 ntmp->ntm_ad = (struct ntvattrdef *) malloc(
653 num * sizeof(struct ntvattrdef),
654 M_NTFSMNT, M_WAITOK);
655
656 ntmp->ntm_adnum = num;
657
658
659 for(i=0;i<num;i++){
660 error = ntfs_readattr(ntmp, VTONT(vp),
661 NTFS_A_DATA, NULL,
662 i * sizeof(ad), sizeof(ad),
663 &ad, NULL);
664 if (error)
665 goto out1;
666 j = 0;
667 do {
668 ntmp->ntm_ad[i].ad_name[j] = ad.ad_name[j];
669 } while(ad.ad_name[j++]);
670 ntmp->ntm_ad[i].ad_namelen = j - 1;
671 ntmp->ntm_ad[i].ad_type = ad.ad_type;
672 }
673
674 vput(vp);
675 }
676
677 #if defined(__FreeBSD__)
678 mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
679 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
680 #else
681 mp->mnt_stat.f_fsid.val[0] = dev;
682 mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_NTFS);
683 #endif
684 mp->mnt_maxsymlinklen = 0;
685 mp->mnt_flag |= MNT_LOCAL;
686 devvp->v_specmountpoint = mp;
687 return (0);
688
689 out1:
690 for (i = 0; i < NTFS_SYSNODESNUM; i++)
691 if (ntmp->ntm_sysvn[i])
692 vrele(ntmp->ntm_sysvn[i]);
693
694 if (vflush(mp,NULLVP,0))
695 dprintf(("ntfs_mountfs: vflush failed\n"));
696
697 out:
698 devvp->v_specmountpoint = NULL;
699 if (bp)
700 brelse(bp);
701
702 if (ntmp != NULL) {
703 if (ntmp->ntm_ad != NULL)
704 free(ntmp->ntm_ad, M_NTFSMNT);
705 free(ntmp, M_NTFSMNT);
706 mp->mnt_data = NULL;
707 }
708
709
710 VN_LOCK(devvp, LK_EXCLUSIVE | LK_RETRY, p);
711 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
712 VOP__UNLOCK(devvp, 0, p);
713
714 return (error);
715 }
716
717 static int
718 ntfs_start (
719 struct mount *mp,
720 int flags,
721 struct proc *p )
722 {
723 return (0);
724 }
725
726 static int
727 ntfs_unmount(
728 struct mount *mp,
729 int mntflags,
730 struct proc *p)
731 {
732 struct ntfsmount *ntmp;
733 int error, ronly = 0, flags, i;
734
735 dprintf(("ntfs_unmount: unmounting...\n"));
736 ntmp = VFSTONTFS(mp);
737
738 flags = 0;
739 if(mntflags & MNT_FORCE)
740 flags |= FORCECLOSE;
741
742 dprintf(("ntfs_unmount: vflushing...\n"));
743 error = vflush(mp,NULLVP,flags | SKIPSYSTEM);
744 if (error) {
745 dprintf(("ntfs_unmount: vflush failed: %d\n",error));
746 return (error);
747 }
748
749
750 for(i=0;i<NTFS_SYSNODESNUM;i++)
751 if((ntmp->ntm_sysvn[i]) &&
752 (ntmp->ntm_sysvn[i]->v_usecount > 1)) return (EBUSY);
753
754
755 for(i=0;i<NTFS_SYSNODESNUM;i++)
756 if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]);
757
758
759 error = vflush(mp,NULLVP,flags);
760 if (error) {
761
762 printf("ntfs_unmount: vflush failed(sysnodes): %d\n",error);
763 }
764
765
766
767
768
769 if (ntmp->ntm_devvp->v_type != VBAD)
770 ntmp->ntm_devvp->v_specmountpoint = NULL;
771
772 vinvalbuf(ntmp->ntm_devvp, V_SAVE, NOCRED, p, 0, 0);
773
774
775 #ifndef __OpenBSD__
776 VOP_LOCK(ntmp->ntm_devvp, LK_EXCLUSIVE | LK_RETRY);
777 #else
778 VOP_LOCK(ntmp->ntm_devvp, LK_EXCLUSIVE | LK_RETRY, p);
779 #endif
780 error = VOP_CLOSE(ntmp->ntm_devvp, ronly ? FREAD : FREAD|FWRITE,
781 NOCRED, p);
782 VOP__UNLOCK(ntmp->ntm_devvp, 0, p);
783
784 vrele(ntmp->ntm_devvp);
785
786
787 #ifndef __OpenBSD__
788 ntfs_toupper_unuse();
789 #else
790 ntfs_toupper_unuse(p);
791 #endif
792
793 dprintf(("ntfs_umount: freeing memory...\n"));
794 mp->mnt_data = NULL;
795 mp->mnt_flag &= ~MNT_LOCAL;
796 free(ntmp->ntm_ad, M_NTFSMNT);
797 free(ntmp, M_NTFSMNT);
798 return (error);
799 }
800
801 static int
802 ntfs_root(
803 struct mount *mp,
804 struct vnode **vpp )
805 {
806 struct vnode *nvp;
807 int error = 0;
808
809 dprintf(("ntfs_root(): sysvn: %p\n",
810 VFSTONTFS(mp)->ntm_sysvn[NTFS_ROOTINO]));
811 error = VFS_VGET(mp, (ino_t)NTFS_ROOTINO, &nvp);
812 if(error) {
813 printf("ntfs_root: VFS_VGET failed: %d\n",error);
814 return (error);
815 }
816
817 *vpp = nvp;
818 return (0);
819 }
820
821
822
823
824
825 static int
826 ntfs_quotactl (
827 struct mount *mp,
828 int cmds,
829 uid_t uid,
830 caddr_t arg,
831 struct proc *p)
832 {
833
834 return EOPNOTSUPP;
835 }
836
837 int
838 ntfs_calccfree(
839 struct ntfsmount *ntmp,
840 cn_t *cfreep)
841 {
842 struct vnode *vp;
843 u_int8_t *tmp;
844 int j, error;
845 cn_t cfree = 0;
846 size_t bmsize, i;
847
848 vp = ntmp->ntm_sysvn[NTFS_BITMAPINO];
849
850 bmsize = VTOF(vp)->f_size;
851
852 tmp = (u_int8_t *) malloc(bmsize, M_TEMP, M_WAITOK);
853
854 error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL,
855 0, bmsize, tmp, NULL);
856 if (error)
857 goto out;
858
859 for(i=0;i<bmsize;i++)
860 for(j=0;j<8;j++)
861 if(~tmp[i] & (1 << j)) cfree++;
862 *cfreep = cfree;
863
864 out:
865 free(tmp, M_TEMP);
866 return(error);
867 }
868
869 static int
870 ntfs_statfs(
871 struct mount *mp,
872 struct statfs *sbp,
873 struct proc *p)
874 {
875 struct ntfsmount *ntmp = VFSTONTFS(mp);
876 u_int64_t mftallocated;
877
878 dprintf(("ntfs_statfs():\n"));
879
880 mftallocated = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_allocated;
881
882 #if defined(__FreeBSD__)
883 sbp->f_type = mp->mnt_vfc->vfc_typenum;
884 #elif defined(__NetBSD__)
885 sbp->f_type = 0;
886 #elif !defined(__OpenBSD__)
887 sbp->f_type = MOUNT_NTFS;
888 #endif
889 sbp->f_bsize = ntmp->ntm_bps;
890 sbp->f_iosize = ntmp->ntm_bps * ntmp->ntm_spc;
891 sbp->f_blocks = ntmp->ntm_bootfile.bf_spv;
892 sbp->f_bfree = sbp->f_bavail = ntfs_cntobn(ntmp->ntm_cfree);
893 sbp->f_ffree = sbp->f_bfree / ntmp->ntm_bpmftrec;
894 sbp->f_files = mftallocated / ntfs_bntob(ntmp->ntm_bpmftrec) +
895 sbp->f_ffree;
896 sbp->f_flags = mp->mnt_flag;
897 #if !defined(__OpenBSD__)
898 copy_statfs_info(sbp, mp);
899 #else
900 if (sbp != &mp->mnt_stat) {
901 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
902 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
903 bcopy(&mp->mnt_stat.mount_info.msdosfs_args,
904 &sbp->mount_info.msdosfs_args, sizeof(struct msdosfs_args));
905 }
906 strncpy(sbp->f_fstypename, mp->mnt_vfc->vfc_name, MFSNAMELEN);
907 #endif
908 return (0);
909 }
910
911 static int
912 ntfs_sync (
913 struct mount *mp,
914 int waitfor,
915 struct ucred *cred,
916 struct proc *p)
917 {
918
919 return (0);
920 }
921
922
923 static int
924 ntfs_fhtovp(
925 #if defined(__FreeBSD__)
926 struct mount *mp,
927 struct fid *fhp,
928 struct sockaddr *nam,
929 struct vnode **vpp,
930 int *exflagsp,
931 struct ucred **credanonp)
932 #elif defined(__NetBSD__) || defined(__OpenBSD__)
933 struct mount *mp,
934 struct fid *fhp,
935 struct vnode **vpp)
936 #else
937 struct mount *mp,
938 struct fid *fhp,
939 struct mbuf *nam,
940 struct vnode **vpp,
941 int *exflagsp,
942 struct ucred **credanonp)
943 #endif
944 {
945 struct ntfid *ntfhp = (struct ntfid *)fhp;
946 int error;
947
948 ddprintf(("ntfs_fhtovp(): %s: %d\n", mp->mnt_stat.f_mntonname,
949 ntfhp->ntfid_ino));
950
951 error = ntfs_vgetex(mp, ntfhp->ntfid_ino, ntfhp->ntfid_attr, NULL,
952 LK_EXCLUSIVE | LK_RETRY, 0, curproc, vpp);
953 if (error != 0) {
954 *vpp = NULLVP;
955 return (error);
956 }
957
958
959
960 return (0);
961 }
962
963 static int
964 ntfs_vptofh(
965 struct vnode *vp,
966 struct fid *fhp)
967 {
968 struct ntnode *ntp;
969 struct ntfid *ntfhp;
970 struct fnode *fn;
971
972 ddprintf(("ntfs_fhtovp(): %s: %p\n", vp->v_mount->mnt_stat.f_mntonname,
973 vp));
974
975 fn = VTOF(vp);
976 ntp = VTONT(vp);
977 ntfhp = (struct ntfid *)fhp;
978 ntfhp->ntfid_len = sizeof(struct ntfid);
979 ntfhp->ntfid_ino = ntp->i_number;
980 ntfhp->ntfid_attr = fn->f_attrtype;
981 #ifdef notyet
982 ntfhp->ntfid_gen = ntp->i_gen;
983 #endif
984 return (0);
985 }
986
987 int
988 ntfs_vgetex(
989 struct mount *mp,
990 ino_t ino,
991 u_int32_t attrtype,
992 char *attrname,
993 u_long lkflags,
994 u_long flags,
995 struct proc *p,
996 struct vnode **vpp)
997 {
998 int error;
999 struct ntfsmount *ntmp;
1000 struct ntnode *ip;
1001 struct fnode *fp;
1002 struct vnode *vp;
1003 enum vtype f_type;
1004
1005 dprintf(("ntfs_vgetex: ino: %d, attr: 0x%x:%s, lkf: 0x%lx, f: 0x%lx\n",
1006 ino, attrtype, attrname?attrname:"", (u_long)lkflags,
1007 (u_long)flags ));
1008
1009 ntmp = VFSTONTFS(mp);
1010 *vpp = NULL;
1011
1012
1013 #ifndef __OpenBSD__
1014 error = ntfs_ntlookup(ntmp, ino, &ip);
1015 #else
1016 error = ntfs_ntlookup(ntmp, ino, &ip, p);
1017 #endif
1018 if (error) {
1019 printf("ntfs_vget: ntfs_ntget failed\n");
1020 return (error);
1021 }
1022
1023
1024 if (!(flags & VG_DONTLOADIN) && !(ip->i_flag & IN_LOADED)) {
1025 error = ntfs_loadntnode(ntmp, ip);
1026 if(error) {
1027 printf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %d\n",
1028 ip->i_number);
1029 #ifndef __OpenBSD__
1030 ntfs_ntput(ip);
1031 #else
1032 ntfs_ntput(ip, p);
1033 #endif
1034 return (error);
1035 }
1036 }
1037
1038 error = ntfs_fget(ntmp, ip, attrtype, attrname, &fp);
1039 if (error) {
1040 printf("ntfs_vget: ntfs_fget failed\n");
1041 #ifndef __OpenBSD__
1042 ntfs_ntput(ip);
1043 #else
1044 ntfs_ntput(ip, p);
1045 #endif
1046 return (error);
1047 }
1048
1049 if (!(flags & VG_DONTVALIDFN) && !(fp->f_flag & FN_VALID)) {
1050 if ((ip->i_frflag & NTFS_FRFLAG_DIR) &&
1051 (fp->f_attrtype == NTFS_A_DATA && fp->f_attrname == NULL)) {
1052 f_type = VDIR;
1053 } else if (flags & VG_EXT) {
1054 f_type = VNON;
1055 fp->f_size = fp->f_allocated = 0;
1056 } else {
1057 f_type = VREG;
1058
1059 error = ntfs_filesize(ntmp, fp,
1060 &fp->f_size, &fp->f_allocated);
1061 if (error) {
1062 #ifndef __OpenBSD__
1063 ntfs_ntput(ip);
1064 #else
1065 ntfs_ntput(ip, p);
1066 #endif
1067 return (error);
1068 }
1069 }
1070
1071 fp->f_flag |= FN_VALID;
1072 }
1073
1074
1075
1076
1077
1078
1079
1080
1081 #ifndef __OpenBSD__
1082 ntfs_ntput(ip);
1083 #else
1084 ntfs_ntput(ip, p);
1085 #endif
1086
1087 if (FTOV(fp)) {
1088
1089 if (VGET(FTOV(fp), lkflags, p) == 0) {
1090 *vpp = FTOV(fp);
1091 return (0);
1092 }
1093 }
1094
1095 error = getnewvnode(VT_NTFS, ntmp->ntm_mountp, ntfs_vnodeop_p, &vp);
1096 if(error) {
1097 ntfs_frele(fp);
1098 #ifndef __OpenBSD__
1099 ntfs_ntput(ip);
1100 #else
1101 ntfs_ntput(ip, p);
1102 #endif
1103 return (error);
1104 }
1105 dprintf(("ntfs_vget: vnode: %p for ntnode: %d\n", vp,ino));
1106
1107 #ifdef __FreeBSD__
1108 lockinit(&fp->f_lock, PINOD, "fnode", 0, 0);
1109 #endif
1110 fp->f_vp = vp;
1111 vp->v_data = fp;
1112 vp->v_type = f_type;
1113
1114 if (ino == NTFS_ROOTINO)
1115 vp->v_flag |= VROOT;
1116
1117 if (lkflags & LK_TYPE_MASK) {
1118 error = VN_LOCK(vp, lkflags, p);
1119 if (error) {
1120 vput(vp);
1121 return (error);
1122 }
1123 }
1124
1125 #if defined(__FreeBSD__) || defined(__NetBSD__)
1126 genfs_node_init(vp, &ntfs_genfsops);
1127 #endif
1128 *vpp = vp;
1129 return (0);
1130 }
1131
1132 static int
1133 ntfs_vget(
1134 struct mount *mp,
1135 ino_t ino,
1136 struct vnode **vpp)
1137 {
1138 return ntfs_vgetex(mp, ino, NTFS_A_DATA, NULL,
1139 LK_EXCLUSIVE | LK_RETRY, 0, curproc, vpp);
1140 }
1141
1142 #if defined(__FreeBSD__)
1143 static struct vfsops ntfs_vfsops = {
1144 ntfs_mount,
1145 ntfs_start,
1146 ntfs_unmount,
1147 ntfs_root,
1148 ntfs_quotactl,
1149 ntfs_statfs,
1150 ntfs_sync,
1151 ntfs_vget,
1152 ntfs_fhtovp,
1153 ntfs_vptofh,
1154 ntfs_init,
1155 NULL
1156 };
1157 VFS_SET(ntfs_vfsops, ntfs, 0);
1158 #elif defined(__NetBSD__)
1159 extern const struct vnodeopv_desc ntfs_vnodeop_opv_desc;
1160
1161 const struct vnodeopv_desc * const ntfs_vnodeopv_descs[] = {
1162 &ntfs_vnodeop_opv_desc,
1163 NULL,
1164 };
1165
1166 struct vfsops ntfs_vfsops = {
1167 MOUNT_NTFS,
1168 ntfs_mount,
1169 ntfs_start,
1170 ntfs_unmount,
1171 ntfs_root,
1172 ntfs_quotactl,
1173 ntfs_statfs,
1174 ntfs_sync,
1175 ntfs_vget,
1176 ntfs_fhtovp,
1177 ntfs_vptofh,
1178 ntfs_init,
1179 ntfs_reinit,
1180 ntfs_done,
1181 ntfs_sysctl,
1182 ntfs_mountroot,
1183 ntfs_checkexp,
1184 ntfs_vnodeopv_descs,
1185 };
1186 #elif defined(__OpenBSD__)
1187 extern const struct vnodeopv_desc ntfs_vnodeop_opv_desc;
1188
1189 const struct vnodeopv_desc * const ntfs_vnodeopv_descs[] = {
1190 &ntfs_vnodeop_opv_desc,
1191 NULL,
1192 };
1193
1194 const struct vfsops ntfs_vfsops = {
1195 ntfs_mount,
1196 ntfs_start,
1197 ntfs_unmount,
1198 ntfs_root,
1199 ntfs_quotactl,
1200 ntfs_statfs,
1201 ntfs_sync,
1202 ntfs_vget,
1203 ntfs_fhtovp,
1204 ntfs_vptofh,
1205 ntfs_init,
1206 ntfs_sysctl,
1207 ntfs_checkexp,
1208 };
1209
1210 #endif