namecache work stage 1: namespace cleanups. Add a NAMEI_ prefix to
[dragonfly.git] / sys / vfs / hpfs / hpfs_vnops.c
1 /*-
2  * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org)
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD: src/sys/fs/hpfs/hpfs_vnops.c,v 1.2.2.2 2002/01/15 18:35:09 semenu Exp $
27  * $DragonFly: src/sys/vfs/hpfs/hpfs_vnops.c,v 1.10 2003/09/23 05:03:52 dillon Exp $
28  */
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/proc.h>
34 #include <sys/time.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <sys/vnode.h>
38 #include <sys/mount.h>
39 #include <sys/namei.h>
40 #include <sys/malloc.h>
41 #include <sys/buf.h>
42 #include <sys/dirent.h>
43
44 #include <vm/vm.h>
45 #include <vm/vm_param.h>
46 #if !defined(__FreeBSD__)
47 #include <vm/vm_prot.h>
48 #endif
49 #include <vm/vm_page.h>
50 #include <vm/vm_object.h>
51 #include <vm/vm_pager.h>
52 #include <vm/vm_zone.h>
53 #if defined(__FreeBSD__)
54 #include <vm/vnode_pager.h>
55 #endif
56 #include <vm/vm_extern.h>
57 #include <sys/buf2.h>
58
59 #if !defined(__FreeBSD__)
60 #include <miscfs/specfs/specdev.h>
61 #include <miscfs/genfs/genfs.h>
62 #endif
63
64 #include <sys/unistd.h> /* for pathconf(2) constants */
65
66 #include "hpfs.h"
67 #include "hpfsmount.h"
68 #include "hpfs_subr.h"
69 #include "hpfs_ioctl.h"
70
71 static int      hpfs_de_uiomove (struct hpfsmount *, struct hpfsdirent *,
72                                      struct uio *);
73 static int      hpfs_ioctl (struct vop_ioctl_args *ap);
74 static int      hpfs_read (struct vop_read_args *);
75 static int      hpfs_write (struct vop_write_args *ap);
76 static int      hpfs_getattr (struct vop_getattr_args *ap);
77 static int      hpfs_setattr (struct vop_setattr_args *ap);
78 static int      hpfs_inactive (struct vop_inactive_args *ap);
79 static int      hpfs_print (struct vop_print_args *ap);
80 static int      hpfs_reclaim (struct vop_reclaim_args *ap);
81 static int      hpfs_strategy (struct vop_strategy_args *ap);
82 static int      hpfs_access (struct vop_access_args *ap);
83 static int      hpfs_open (struct vop_open_args *ap);
84 static int      hpfs_close (struct vop_close_args *ap);
85 static int      hpfs_readdir (struct vop_readdir_args *ap);
86 static int      hpfs_lookup (struct vop_lookup_args *ap);
87 static int      hpfs_create (struct vop_create_args *);
88 static int      hpfs_remove (struct vop_remove_args *);
89 static int      hpfs_bmap (struct vop_bmap_args *ap);
90 #if defined(__FreeBSD__)
91 static int      hpfs_getpages (struct vop_getpages_args *ap);
92 static int      hpfs_putpages (struct vop_putpages_args *);
93 static int      hpfs_fsync (struct vop_fsync_args *ap);
94 #endif
95 static int      hpfs_pathconf (struct vop_pathconf_args *ap);
96
97 #if defined(__FreeBSD__)
98 int
99 hpfs_getpages(ap)
100         struct vop_getpages_args *ap;
101 {
102         return vnode_pager_generic_getpages(ap->a_vp, ap->a_m, ap->a_count,
103                 ap->a_reqpage);
104 }
105
106 int
107 hpfs_putpages(ap)
108         struct vop_putpages_args *ap;
109 {
110         return vnode_pager_generic_putpages(ap->a_vp, ap->a_m, ap->a_count,
111                 ap->a_sync, ap->a_rtvals);
112 }
113
114 static int
115 hpfs_fsync(ap)
116         struct vop_fsync_args /* {
117                 struct vnode *a_vp;
118                 struct ucred *a_cred;
119                 int a_waitfor;
120                 struct proc *a_td;
121         } */ *ap;
122 {
123         struct vnode *vp = ap->a_vp;
124         int s;
125         struct buf *bp, *nbp;
126
127         /*
128          * Flush all dirty buffers associated with a vnode.
129          */
130 loop:
131         s = splbio();
132         for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
133                 nbp = TAILQ_NEXT(bp, b_vnbufs);
134                 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT))
135                         continue;
136                 if ((bp->b_flags & B_DELWRI) == 0)
137                         panic("hpfs_fsync: not dirty");
138                 bremfree(bp);
139                 splx(s);
140                 (void) bwrite(bp);
141                 goto loop;
142         }
143         while (vp->v_numoutput) {
144                 vp->v_flag |= VBWAIT;
145                 (void) tsleep((caddr_t)&vp->v_numoutput, 0, "hpfsn", 0);
146         }
147 #ifdef DIAGNOSTIC
148         if (!TAILQ_EMPTY(&vp->v_dirtyblkhd)) {
149                 vprint("hpfs_fsync: dirty", vp);
150                 goto loop;
151         }
152 #endif
153         splx(s);
154
155         /*
156          * Write out the on-disc version of the vnode.
157          */
158         return hpfs_update(VTOHP(vp));
159 }
160
161 #endif
162
163 static int
164 hpfs_ioctl (
165         struct vop_ioctl_args /* {
166                 struct vnode *a_vp;
167                 u_long a_command;
168                 caddr_t a_data;
169                 int a_fflag;
170                 struct ucred *a_cred;
171                 struct proc *a_td;
172         } */ *ap)
173 {
174         struct vnode *vp = ap->a_vp;
175         struct hpfsnode *hp = VTOHP(vp);
176         int error;
177
178         printf("hpfs_ioctl(0x%x, 0x%lx, 0x%p, 0x%x): ",
179                 hp->h_no, ap->a_command, ap->a_data, ap->a_fflag);
180
181         switch (ap->a_command) {
182         case HPFSIOCGEANUM: {
183                 u_long eanum;
184                 u_long passed;
185                 struct ea *eap;
186
187                 eanum = 0;
188
189                 if (hp->h_fn.fn_ealen > 0) {
190                         eap = (struct ea *)&(hp->h_fn.fn_int);
191                         passed = 0;
192
193                         while (passed < hp->h_fn.fn_ealen) {
194
195                                 printf("EAname: %s\n", EA_NAME(eap));
196
197                                 eanum++;
198                                 passed += sizeof(struct ea) +
199                                           eap->ea_namelen + 1 + eap->ea_vallen;
200                                 eap = (struct ea *)((caddr_t)hp->h_fn.fn_int +
201                                                 passed);
202                         }
203                         error = 0;
204                 } else {
205                         error = ENOENT;
206                 }
207
208                 printf("%lu eas\n", eanum);
209
210                 *(u_long *)ap->a_data = eanum;
211
212                 break;
213         }
214         case HPFSIOCGEASZ: {
215                 u_long eanum;
216                 u_long passed;
217                 struct ea *eap;
218
219                 printf("EA%ld\n", *(u_long *)ap->a_data);
220
221                 eanum = 0;
222                 if (hp->h_fn.fn_ealen > 0) {
223                         eap = (struct ea *)&(hp->h_fn.fn_int);
224                         passed = 0;
225
226                         error = ENOENT;
227                         while (passed < hp->h_fn.fn_ealen) {
228                                 printf("EAname: %s\n", EA_NAME(eap));
229
230                                 if (eanum == *(u_long *)ap->a_data) {
231                                         *(u_long *)ap->a_data =
232                                                 eap->ea_namelen + 1 +
233                                                 eap->ea_vallen;
234
235                                         error = 0;
236                                         break;
237                                 }
238
239                                 eanum++;
240                                 passed += sizeof(struct ea) +
241                                           eap->ea_namelen + 1 + eap->ea_vallen;
242                                 eap = (struct ea *)((caddr_t)hp->h_fn.fn_int +
243                                                 passed);
244                         }
245                 } else {
246                         error = ENOENT;
247                 }
248
249                 break;
250         }
251         case HPFSIOCRDEA: {
252                 u_long eanum;
253                 u_long passed;
254                 struct hpfs_rdea *rdeap;
255                 struct ea *eap;
256
257                 rdeap = (struct hpfs_rdea *)ap->a_data;
258                 printf("EA%ld\n", rdeap->ea_no);
259
260                 eanum = 0;
261                 if (hp->h_fn.fn_ealen > 0) {
262                         eap = (struct ea *)&(hp->h_fn.fn_int);
263                         passed = 0;
264
265                         error = ENOENT;
266                         while (passed < hp->h_fn.fn_ealen) {
267                                 printf("EAname: %s\n", EA_NAME(eap));
268
269                                 if (eanum == rdeap->ea_no) {
270                                         rdeap->ea_sz = eap->ea_namelen + 1 +
271                                                         eap->ea_vallen;
272                                         copyout(EA_NAME(eap),rdeap->ea_data,
273                                                 rdeap->ea_sz);
274                                         error = 0;
275                                         break;
276                                 }
277
278                                 eanum++;
279                                 passed += sizeof(struct ea) +
280                                           eap->ea_namelen + 1 + eap->ea_vallen;
281                                 eap = (struct ea *)((caddr_t)hp->h_fn.fn_int +
282                                                 passed);
283                         }
284                 } else {
285                         error = ENOENT;
286                 }
287
288                 break;
289         }
290         default:
291                 error = EOPNOTSUPP;
292                 break;
293         }
294         return (error);
295 }
296
297 /*
298  * Map file offset to disk offset.
299  */
300 int
301 hpfs_bmap(ap)
302         struct vop_bmap_args /* {
303                 struct vnode *a_vp;
304                 daddr_t  a_bn;
305                 struct vnode **a_vpp;
306                 daddr_t *a_bnp;
307                 int *a_runp;
308                 int *a_runb;
309         } */ *ap;
310 {
311         struct hpfsnode *hp = VTOHP(ap->a_vp);
312         int error;
313
314         if (ap->a_vpp != NULL) 
315                 *ap->a_vpp = hp->h_devvp;
316 #if defined(__FreeBSD__)
317         if (ap->a_runb != NULL)
318                 *ap->a_runb = 0;
319 #endif
320         if (ap->a_bnp == NULL)
321                 return (0);
322
323         dprintf(("hpfs_bmap(0x%x, 0x%x): ",hp->h_no, ap->a_bn));
324
325         error = hpfs_hpbmap (hp, ap->a_bn, ap->a_bnp, ap->a_runp);
326
327         return (error);
328 }
329
330 static int
331 hpfs_read(ap)
332         struct vop_read_args /* {
333                 struct vnode *a_vp;
334                 struct uio *a_uio;
335                 int a_ioflag;
336                 struct ucred *a_cred;
337         } */ *ap;
338 {
339         struct vnode *vp = ap->a_vp;
340         struct hpfsnode *hp = VTOHP(vp);
341         struct uio *uio = ap->a_uio;
342         struct buf *bp;
343         u_int xfersz, toread;
344         u_int off;
345         daddr_t lbn, bn;
346         int resid;
347         int runl;
348         int error = 0;
349
350         resid = min (uio->uio_resid, hp->h_fn.fn_size - uio->uio_offset);
351
352         dprintf(("hpfs_read(0x%x, off: %d resid: %d, segflg: %d): [resid: 0x%x]\n",hp->h_no,(u_int32_t)uio->uio_offset,uio->uio_resid,uio->uio_segflg, resid));
353
354         while (resid) {
355                 lbn = uio->uio_offset >> DEV_BSHIFT;
356                 off = uio->uio_offset & (DEV_BSIZE - 1);
357                 dprintf(("hpfs_read: resid: 0x%x lbn: 0x%x off: 0x%x\n",
358                         uio->uio_resid, lbn, off));
359                 error = hpfs_hpbmap(hp, lbn, &bn, &runl);
360                 if (error)
361                         return (error);
362
363                 toread = min(off + resid, min(DFLTPHYS, (runl+1)*DEV_BSIZE));
364                 xfersz = (toread + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);
365                 dprintf(("hpfs_read: bn: 0x%x (0x%x) toread: 0x%x (0x%x)\n",
366                         bn, runl, toread, xfersz));
367
368                 if (toread == 0) 
369                         break;
370
371                 error = bread(hp->h_devvp, bn, xfersz, &bp);
372                 if (error) {
373                         brelse(bp);
374                         break;
375                 }
376
377                 error = uiomove(bp->b_data + off, toread - off, uio);
378                 if(error) {
379                         brelse(bp);
380                         break;
381                 }
382                 brelse(bp);
383                 resid -= toread;
384         }
385         dprintf(("hpfs_read: successful\n"));
386         return (error);
387 }
388
389 static int
390 hpfs_write(ap)
391         struct vop_write_args /* {
392                 struct vnode *a_vp;
393                 struct uio *a_uio;
394                 int  a_ioflag;
395                 struct ucred *a_cred;
396         } */ *ap;
397 {
398         struct vnode *vp = ap->a_vp;
399         struct hpfsnode *hp = VTOHP(vp);
400         struct uio *uio = ap->a_uio;
401         struct buf *bp;
402         u_int xfersz, towrite;
403         u_int off;
404         daddr_t lbn, bn;
405         int runl;
406         int error = 0;
407
408         dprintf(("hpfs_write(0x%x, off: %d resid: %d, segflg: %d):\n",hp->h_no,(u_int32_t)uio->uio_offset,uio->uio_resid,uio->uio_segflg));
409
410         if (ap->a_ioflag & IO_APPEND) {
411                 dprintf(("hpfs_write: APPEND mode\n"));
412                 uio->uio_offset = hp->h_fn.fn_size;
413         }
414         if (uio->uio_offset + uio->uio_resid > hp->h_fn.fn_size) {
415                 error = hpfs_extend (hp, uio->uio_offset + uio->uio_resid);
416                 if (error) {
417                         printf("hpfs_write: hpfs_extend FAILED %d\n", error);
418                         return (error);
419                 }
420         }
421
422         while (uio->uio_resid) {
423                 lbn = uio->uio_offset >> DEV_BSHIFT;
424                 off = uio->uio_offset & (DEV_BSIZE - 1);
425                 dprintf(("hpfs_write: resid: 0x%x lbn: 0x%x off: 0x%x\n",
426                         uio->uio_resid, lbn, off));
427                 error = hpfs_hpbmap(hp, lbn, &bn, &runl);
428                 if (error)
429                         return (error);
430
431                 towrite = min(off + uio->uio_resid, min(DFLTPHYS, (runl+1)*DEV_BSIZE));
432                 xfersz = (towrite + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);
433                 dprintf(("hpfs_write: bn: 0x%x (0x%x) towrite: 0x%x (0x%x)\n",
434                         bn, runl, towrite, xfersz));
435
436                 if ((off == 0) && (towrite == xfersz)) {
437                         bp = getblk(hp->h_devvp, bn, xfersz, 0, 0);
438                         clrbuf(bp);
439                 } else {
440                         error = bread(hp->h_devvp, bn, xfersz, &bp);
441                         if (error) {
442                                 brelse(bp);
443                                 return (error);
444                         }
445                 }
446
447                 error = uiomove(bp->b_data + off, towrite - off, uio);
448                 if(error) {
449                         brelse(bp);
450                         return (error);
451                 }
452
453                 if (ap->a_ioflag & IO_SYNC)
454                         bwrite(bp);
455                 else
456                         bawrite(bp);
457         }
458
459         dprintf(("hpfs_write: successful\n"));
460         return (0);
461 }
462
463 /*
464  * XXXXX do we need hpfsnode locking inside?
465  */
466 static int
467 hpfs_getattr(ap)
468         struct vop_getattr_args /* {
469                 struct vnode *a_vp;
470                 struct vattr *a_vap;
471                 struct ucred *a_cred;
472                 struct proc *a_td;
473         } */ *ap;
474 {
475         struct vnode *vp = ap->a_vp;
476         struct hpfsnode *hp = VTOHP(vp);
477         struct vattr *vap = ap->a_vap;
478         int error;
479
480         dprintf(("hpfs_getattr(0x%x):\n", hp->h_no));
481
482 #if defined(__FreeBSD__)
483         vap->va_fsid = dev2udev(hp->h_dev);
484 #else /* defined(__NetBSD__) */
485         vap->va_fsid = ip->i_dev;
486 #endif
487         vap->va_fileid = hp->h_no;
488         vap->va_mode = hp->h_mode;
489         vap->va_nlink = 1;
490         vap->va_uid = hp->h_uid;
491         vap->va_gid = hp->h_gid;
492         vap->va_rdev = 0;                               /* XXX UNODEV ? */
493         vap->va_size = hp->h_fn.fn_size;
494         vap->va_bytes = ((hp->h_fn.fn_size + DEV_BSIZE-1) & ~(DEV_BSIZE-1)) +
495                         DEV_BSIZE;
496
497         if (!(hp->h_flag & H_PARVALID)) {
498                 error = hpfs_validateparent(hp);
499                 if (error) 
500                         return (error);
501         }
502         vap->va_atime = hpfstimetounix(hp->h_atime);
503         vap->va_mtime = hpfstimetounix(hp->h_mtime);
504         vap->va_ctime = hpfstimetounix(hp->h_ctime);
505
506         vap->va_flags = 0;
507         vap->va_gen = 0;
508         vap->va_blocksize = DEV_BSIZE;
509         vap->va_type = vp->v_type;
510         vap->va_filerev = 0;
511
512         return (0);
513 }
514
515 /*
516  * XXXXX do we need hpfsnode locking inside?
517  */
518 static int
519 hpfs_setattr(ap)
520         struct vop_setattr_args /* {
521                 struct vnode *a_vp;
522                 struct vattr *a_vap;
523                 struct ucred *a_cred;
524                 struct thread *a_td;
525         } */ *ap;
526 {
527         struct vnode *vp = ap->a_vp;
528         struct hpfsnode *hp = VTOHP(vp);
529         struct vattr *vap = ap->a_vap;
530         struct ucred *cred = ap->a_cred;
531         struct thread *td = ap->a_td;
532         int error;
533
534         dprintf(("hpfs_setattr(0x%x):\n", hp->h_no));
535
536         /*
537          * Check for unsettable attributes.
538          */
539         if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
540             (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
541             (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
542             (vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
543                 dprintf(("hpfs_setattr: changing nonsettable attr\n"));
544                 return (EINVAL);
545         }
546
547         /* Can't change flags XXX Could be implemented */
548         if (vap->va_flags != VNOVAL) {
549                 printf("hpfs_setattr: FLAGS CANNOT BE SET\n");
550                 return (EINVAL);
551         }
552
553         /* Can't change uid/gid XXX Could be implemented */
554         if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
555                 printf("hpfs_setattr: UID/GID CANNOT BE SET\n");
556                 return (EINVAL);
557         }
558
559         /* Can't change mode XXX Could be implemented */
560         if (vap->va_mode != (mode_t)VNOVAL) {
561                 printf("hpfs_setattr: MODE CANNOT BE SET\n");
562                 return (EINVAL);
563         }
564
565         /* Update times */
566         if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
567                 if (vp->v_mount->mnt_flag & MNT_RDONLY)
568                         return (EROFS);
569                 if (cred->cr_uid != hp->h_uid &&
570                     (error = suser_cred(cred, PRISON_ROOT)) &&
571                     ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
572                     (error = VOP_ACCESS(vp, VWRITE, cred, td))))
573                         return (error);
574                 if (vap->va_atime.tv_sec != VNOVAL)
575                         hp->h_atime = vap->va_atime.tv_sec;
576                 if (vap->va_mtime.tv_sec != VNOVAL)
577                         hp->h_mtime = vap->va_mtime.tv_sec;
578
579                 hp->h_flag |= H_PARCHANGE;
580         }
581
582         if (vap->va_size != VNOVAL) {
583                 switch (vp->v_type) {
584                 case VDIR:
585                         return (EISDIR);
586                 case VREG:
587                         if (vp->v_mount->mnt_flag & MNT_RDONLY)
588                                 return (EROFS);
589                         break;
590                 default:
591                         printf("hpfs_setattr: WRONG v_type\n");
592                         return (EINVAL);
593                 }
594
595                 if (vap->va_size < hp->h_fn.fn_size) {
596 #if defined(__FreeBSD__)
597                         error = vtruncbuf(vp, td, vap->va_size, DEV_BSIZE);
598                         if (error)
599                                 return (error);
600 #else /* defined(__NetBSD__) */
601 #error Need alternation for vtruncbuf()
602 #endif
603                         error = hpfs_truncate(hp, vap->va_size);
604                         if (error)
605                                 return (error);
606
607                 } else if (vap->va_size > hp->h_fn.fn_size) {
608 #if defined(__FreeBSD__)
609                         vnode_pager_setsize(vp, vap->va_size);
610 #endif
611                         error = hpfs_extend(hp, vap->va_size);
612                         if (error)
613                                 return (error);
614                 }
615         }
616
617         return (0);
618 }
619
620 /*
621  * Last reference to an node.  If necessary, write or delete it.
622  */
623 int
624 hpfs_inactive(ap)
625         struct vop_inactive_args /* {
626                 struct vnode *a_vp;
627         } */ *ap;
628 {
629         struct vnode *vp = ap->a_vp;
630         struct hpfsnode *hp = VTOHP(vp);
631         int error;
632
633         dprintf(("hpfs_inactive(0x%x): \n", hp->h_no));
634
635         if (hp->h_flag & H_CHANGE) {
636                 dprintf(("hpfs_inactive: node changed, update\n"));
637                 error = hpfs_update (hp);
638                 if (error)
639                         return (error);
640         }
641
642         if (hp->h_flag & H_PARCHANGE) {
643                 dprintf(("hpfs_inactive: parent node changed, update\n"));
644                 error = hpfs_updateparent (hp);
645                 if (error)
646                         return (error);
647         }
648
649         if (prtactive && vp->v_usecount != 0)
650                 vprint("hpfs_inactive: pushing active", vp);
651
652         if (hp->h_flag & H_INVAL) {
653                 VOP__UNLOCK(vp,0,ap->a_td);
654 #if defined(__FreeBSD__)
655                 vrecycle(vp, NULL, ap->a_td);
656 #else /* defined(__NetBSD__) */
657                 vgone(vp);
658 #endif
659                 return (0);
660         }
661
662         VOP__UNLOCK(vp,0,ap->a_td);
663         return (0);
664 }
665
666 /*
667  * Reclaim an inode so that it can be used for other purposes.
668  */
669 int
670 hpfs_reclaim(ap)
671         struct vop_reclaim_args /* {
672                 struct vnode *a_vp;
673         } */ *ap;
674 {
675         struct vnode *vp = ap->a_vp;
676         struct hpfsnode *hp = VTOHP(vp);
677
678         dprintf(("hpfs_reclaim(0x%x0): \n", hp->h_no));
679
680         hpfs_hphashrem(hp);
681
682         /* Purge old data structures associated with the inode. */
683         cache_purge(vp);
684         if (hp->h_devvp) {
685                 vrele(hp->h_devvp);
686                 hp->h_devvp = NULL;
687         }
688
689         vp->v_data = NULL;
690
691         FREE(hp, M_HPFSNO);
692
693         return (0);
694 }
695
696 static int
697 hpfs_print(ap)
698         struct vop_print_args /* {
699                 struct vnode *a_vp;
700         } */ *ap;
701 {
702         struct vnode *vp = ap->a_vp;
703         struct hpfsnode *hp = VTOHP(vp);
704
705         printf("tag VT_HPFS, ino 0x%x",hp->h_no);
706         lockmgr_printinfo(&hp->h_lock);
707         printf("\n");
708         return (0);
709 }
710
711 /*
712  * Calculate the logical to physical mapping if not done already,
713  * then call the device strategy routine.
714  *
715  * In order to be able to swap to a file, the VOP_BMAP operation may not
716  * deadlock on memory.  See hpfs_bmap() for details. XXXXXXX (not impl)
717  */
718 int
719 hpfs_strategy(ap)
720         struct vop_strategy_args /* {
721                 struct buf *a_bp;
722         } */ *ap;
723 {
724         struct buf *bp = ap->a_bp;
725         struct vnode *vp = ap->a_vp;
726         struct vnode *nvp;
727         int error;
728
729         dprintf(("hpfs_strategy(): \n"));
730
731         if (vp->v_type == VBLK || vp->v_type == VCHR)
732                 panic("hpfs_strategy: spec");
733         if (bp->b_blkno == bp->b_lblkno) {
734                 error = VOP_BMAP(vp, bp->b_lblkno, &nvp, &bp->b_blkno, NULL, NULL);
735                 if (error) {
736                         printf("hpfs_strategy: VOP_BMAP FAILED %d\n", error);
737                         bp->b_error = error;
738                         bp->b_flags |= B_ERROR;
739                         biodone(bp);
740                         return (error);
741                 }
742                 if ((long)bp->b_blkno == -1)
743                         vfs_bio_clrbuf(bp);
744         }
745         if ((long)bp->b_blkno == -1) {
746                 biodone(bp);
747                 return (0);
748         }
749         bp->b_dev = nvp->v_rdev;
750         VOP_STRATEGY(nvp, bp);
751         return (0);
752 }
753
754 /*
755  * XXXXX do we need hpfsnode locking inside?
756  */
757 int
758 hpfs_access(ap)
759         struct vop_access_args /* {
760                 struct vnode *a_vp;
761                 int  a_mode;
762                 struct ucred *a_cred;
763                 struct proc *a_td;
764         } */ *ap;
765 {
766         struct vnode *vp = ap->a_vp;
767         struct hpfsnode *hp = VTOHP(vp);
768         struct ucred *cred = ap->a_cred;
769         mode_t mask, mode = ap->a_mode;
770         gid_t *gp;
771         int i;
772
773         dprintf(("hpfs_access(0x%x):\n", hp->h_no));
774
775         /*
776          * Disallow write attempts on read-only file systems;
777          * unless the file is a socket, fifo, or a block or
778          * character device resident on the file system.
779          */
780         if (mode & VWRITE) {
781                 switch ((int)vp->v_type) {
782                 case VDIR:
783                 case VLNK:
784                 case VREG:
785                         if (vp->v_mount->mnt_flag & MNT_RDONLY)
786                                 return (EROFS);
787                         break;
788                 }
789         }
790
791         /* Otherwise, user id 0 always gets access. */
792         if (cred->cr_uid == 0)
793                 return (0);
794
795         mask = 0;
796
797         /* Otherwise, check the owner. */
798         if (cred->cr_uid == hp->h_uid) {
799                 if (mode & VEXEC)
800                         mask |= S_IXUSR;
801                 if (mode & VREAD)
802                         mask |= S_IRUSR;
803                 if (mode & VWRITE)
804                         mask |= S_IWUSR;
805                 return ((hp->h_mode & mask) == mask ? 0 : EACCES);
806         }
807
808         /* Otherwise, check the groups. */
809         for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
810                 if (hp->h_gid == *gp) {
811                         if (mode & VEXEC)
812                                 mask |= S_IXGRP;
813                         if (mode & VREAD)
814                                 mask |= S_IRGRP;
815                         if (mode & VWRITE)
816                                 mask |= S_IWGRP;
817                         return ((hp->h_mode & mask) == mask ? 0 : EACCES);
818                 }
819
820         /* Otherwise, check everyone else. */
821         if (mode & VEXEC)
822                 mask |= S_IXOTH;
823         if (mode & VREAD)
824                 mask |= S_IROTH;
825         if (mode & VWRITE)
826                 mask |= S_IWOTH;
827         return ((hp->h_mode & mask) == mask ? 0 : EACCES);
828 }
829
830 /*
831  * Open called.
832  *
833  * Nothing to do.
834  */
835 /* ARGSUSED */
836 static int
837 hpfs_open(ap)
838         struct vop_open_args /* {
839                 struct vnode *a_vp;
840                 int  a_mode;
841                 struct ucred *a_cred;
842                 struct proc *a_td;
843         } */ *ap;
844 {
845 #if HPFS_DEBUG
846         struct vnode *vp = ap->a_vp;
847         struct hpfsnode *hp = VTOHP(vp);
848
849         printf("hpfs_open(0x%x):\n",hp->h_no);
850 #endif
851
852         /*
853          * Files marked append-only must be opened for appending.
854          */
855
856         return (0);
857 }
858
859 /*
860  * Close called.
861  *
862  * Update the times on the inode.
863  */
864 /* ARGSUSED */
865 static int
866 hpfs_close(ap)
867         struct vop_close_args /* {
868                 struct vnode *a_vp;
869                 int  a_fflag;
870                 struct ucred *a_cred;
871                 struct proc *a_td;
872         } */ *ap;
873 {
874 #if HPFS_DEBUG
875         struct vnode *vp = ap->a_vp;
876         struct hpfsnode *hp = VTOHP(vp);
877
878         printf("hpfs_close: %d\n",hp->h_no);
879 #endif
880
881         return (0);
882 }
883
884 static int
885 hpfs_de_uiomove (
886         struct hpfsmount *hpmp,
887         struct hpfsdirent *dep,
888         struct uio *uio)
889 {
890         struct dirent cde;
891         int i, error;
892
893         dprintf(("[no: 0x%x, size: %d, name: %2d:%.*s, flag: 0x%x] ",
894                 dep->de_fnode, dep->de_size, dep->de_namelen,
895                 dep->de_namelen, dep->de_name, dep->de_flag));
896
897         /*strncpy(cde.d_name, dep->de_name, dep->de_namelen);*/
898         for (i=0; i<dep->de_namelen; i++) 
899                 cde.d_name[i] = hpfs_d2u(hpmp, dep->de_name[i]);
900
901         cde.d_name[dep->de_namelen] = '\0';
902         cde.d_namlen = dep->de_namelen;
903         cde.d_fileno = dep->de_fnode;
904         cde.d_type = (dep->de_flag & DE_DIR) ? DT_DIR : DT_REG;
905         cde.d_reclen = sizeof(struct dirent);
906
907         error = uiomove((char *)&cde, sizeof(struct dirent), uio);
908         if (error)
909                 return (error);
910         
911         dprintf(("[0x%x] ", uio->uio_resid));
912         return (error);
913 }
914
915
916 static struct dirent hpfs_de_dot =
917         { 0, sizeof(struct dirent), DT_DIR, 1, "." };
918 static struct dirent hpfs_de_dotdot =
919         { 0, sizeof(struct dirent), DT_DIR, 2, ".." };
920 int
921 hpfs_readdir(ap)
922         struct vop_readdir_args /* {
923                 struct vnode *a_vp;
924                 struct uio *a_uio;
925                 struct ucred *a_cred;
926                 int *a_ncookies;
927                 u_int **cookies;
928         } */ *ap;
929 {
930         struct vnode *vp = ap->a_vp;
931         struct hpfsnode *hp = VTOHP(vp);
932         struct hpfsmount *hpmp = hp->h_hpmp;
933         struct uio *uio = ap->a_uio;
934         int ncookies = 0, i, num, cnum;
935         int error = 0;
936         off_t off;
937         struct buf *bp;
938         struct dirblk *dp;
939         struct hpfsdirent *dep;
940         lsn_t olsn;
941         lsn_t lsn;
942         int level;
943
944         dprintf(("hpfs_readdir(0x%x, 0x%x, 0x%x): ",hp->h_no,(u_int32_t)uio->uio_offset,uio->uio_resid));
945
946         off = uio->uio_offset;
947
948         if( uio->uio_offset < sizeof(struct dirent) ) {
949                 dprintf((". faked, "));
950                 hpfs_de_dot.d_fileno = hp->h_no;
951                 error = uiomove((char *)&hpfs_de_dot,sizeof(struct dirent),uio);
952                 if(error) {
953                         return (error);
954                 }
955
956                 ncookies ++;
957         }
958
959         if( uio->uio_offset < 2 * sizeof(struct dirent) ) {
960                 dprintf((".. faked, "));
961                 hpfs_de_dotdot.d_fileno = hp->h_fn.fn_parent;
962
963                 error = uiomove((char *)&hpfs_de_dotdot, sizeof(struct dirent),
964                                 uio);
965                 if(error) {
966                         return (error);
967                 }
968
969                 ncookies ++;
970         }
971
972         num = uio->uio_offset / sizeof(struct dirent) - 2;
973         cnum = 0;
974
975         lsn = ((alleaf_t *)hp->h_fn.fn_abd)->al_lsn;
976
977         olsn = 0;
978         level = 1;
979
980 dive:
981         dprintf(("[dive 0x%x] ", lsn));
982         error = bread(hp->h_devvp, lsn, D_BSIZE, &bp);
983         if (error) {
984                 brelse(bp);
985                 return (error);
986         }
987
988         dp = (struct dirblk *) bp->b_data;
989         if (dp->d_magic != D_MAGIC) {
990                 printf("hpfs_readdir: MAGIC DOESN'T MATCH\n");
991                 brelse(bp);
992                 return (EINVAL);
993         }
994
995         dep = D_DIRENT(dp);
996
997         if (olsn) {
998                 dprintf(("[restore 0x%x] ", olsn));
999
1000                 while(!(dep->de_flag & DE_END) ) {
1001                         if((dep->de_flag & DE_DOWN) &&
1002                            (olsn == DE_DOWNLSN(dep)))
1003                                          break;
1004                         dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
1005                 }
1006
1007                 if((dep->de_flag & DE_DOWN) && (olsn == DE_DOWNLSN(dep))) {
1008                         if (dep->de_flag & DE_END)
1009                                 goto blockdone;
1010
1011                         if (!(dep->de_flag & DE_SPECIAL)) {
1012                                 if (num <= cnum) {
1013                                         if (uio->uio_resid < sizeof(struct dirent)) {
1014                                                 brelse(bp);
1015                                                 dprintf(("[resid] "));
1016                                                 goto readdone;
1017                                         }
1018
1019                                         error = hpfs_de_uiomove(hpmp, dep, uio);
1020                                         if (error) {
1021                                                 brelse (bp);
1022                                                 return (error);
1023                                         }
1024                                         ncookies++;
1025
1026                                         if (uio->uio_resid < sizeof(struct dirent)) {
1027                                                 brelse(bp);
1028                                                 dprintf(("[resid] "));
1029                                                 goto readdone;
1030                                         }
1031                                 }
1032                                 cnum++;
1033                         }
1034
1035                         dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
1036                 } else {
1037                         printf("hpfs_readdir: ERROR! oLSN not found\n");
1038                         brelse(bp);
1039                         return (EINVAL);
1040                 }
1041         }
1042
1043         olsn = 0;
1044
1045         while(!(dep->de_flag & DE_END)) {
1046                 if(dep->de_flag & DE_DOWN) {
1047                         lsn = DE_DOWNLSN(dep);
1048                         brelse(bp);
1049                         level++;
1050                         goto dive;
1051                 }
1052
1053                 if (!(dep->de_flag & DE_SPECIAL)) {
1054                         if (num <= cnum) {
1055                                 if (uio->uio_resid < sizeof(struct dirent)) {
1056                                         brelse(bp);
1057                                         dprintf(("[resid] "));
1058                                         goto readdone;
1059                                 }
1060
1061                                 error = hpfs_de_uiomove(hpmp, dep, uio);
1062                                 if (error) {
1063                                         brelse (bp);
1064                                         return (error);
1065                                 }
1066                                 ncookies++;
1067                                 
1068                                 if (uio->uio_resid < sizeof(struct dirent)) {
1069                                         brelse(bp);
1070                                         dprintf(("[resid] "));
1071                                         goto readdone;
1072                                 }
1073                         }
1074                         cnum++;
1075                 }
1076
1077                 dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
1078         }
1079
1080         if(dep->de_flag & DE_DOWN) {
1081                 dprintf(("[enddive] "));
1082                 lsn = DE_DOWNLSN(dep);
1083                 brelse(bp);
1084                 level++;
1085                 goto dive;
1086         }
1087
1088 blockdone:
1089         dprintf(("[EOB] "));
1090         olsn = lsn;
1091         lsn = dp->d_parent;
1092         brelse(bp);
1093         level--;
1094
1095         dprintf(("[level %d] ", level));
1096
1097         if (level > 0)
1098                 goto dive;      /* undive really */
1099
1100         if (ap->a_eofflag) {
1101             dprintf(("[EOF] "));
1102             *ap->a_eofflag = 1;
1103         }
1104
1105 readdone:
1106         dprintf(("[readdone]\n"));
1107         if (!error && ap->a_ncookies != NULL) {
1108                 struct dirent* dpStart;
1109                 struct dirent* dp;
1110 #if defined(__FreeBSD__)
1111                 u_long *cookies;
1112                 u_long *cookiep;
1113 #else /* defined(__NetBSD__) */
1114                 off_t *cookies;
1115                 off_t *cookiep;
1116 #endif
1117
1118                 dprintf(("%d cookies, ",ncookies));
1119                 if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
1120                         panic("hpfs_readdir: unexpected uio from NFS server");
1121                 dpStart = (struct dirent *)
1122                      ((caddr_t)uio->uio_iov->iov_base -
1123                          (uio->uio_offset - off));
1124 #if defined(__FreeBSD__)
1125                 MALLOC(cookies, u_long *, ncookies * sizeof(u_long),
1126                        M_TEMP, M_WAITOK);
1127 #else /* defined(__NetBSD__) */
1128                 MALLOC(cookies, off_t *, ncookies * sizeof(off_t),
1129                        M_TEMP, M_WAITOK);
1130 #endif
1131                 for (dp = dpStart, cookiep = cookies, i=0;
1132                      i < ncookies;
1133                      dp = (struct dirent *)((caddr_t) dp + dp->d_reclen), i++) {
1134                         off += dp->d_reclen;
1135                         *cookiep++ = (u_int) off;
1136                 }
1137                 *ap->a_ncookies = ncookies;
1138                 *ap->a_cookies = cookies;
1139         }
1140
1141         return (0);
1142 }
1143
1144 int
1145 hpfs_lookup(ap)
1146         struct vop_lookup_args /* {
1147                 struct vnode *a_dvp;
1148                 struct vnode **a_vpp;
1149                 struct componentname *a_cnp;
1150         } */ *ap;
1151 {
1152         struct vnode *dvp = ap->a_dvp;
1153         struct hpfsnode *dhp = VTOHP(dvp);
1154         struct hpfsmount *hpmp = dhp->h_hpmp;
1155         struct componentname *cnp = ap->a_cnp;
1156         struct ucred *cred = cnp->cn_cred;
1157         int error;
1158         int nameiop = cnp->cn_nameiop;
1159         int flags = cnp->cn_flags;
1160         int lockparent = flags & CNP_LOCKPARENT;
1161 #if HPFS_DEBUG
1162         int wantparent = flags & (CNP_LOCKPARENT | CNP_WANTPARENT);
1163 #endif
1164         dprintf(("hpfs_lookup(0x%x, %s, %ld, %d, %d): \n",
1165                 dhp->h_no, cnp->cn_nameptr, cnp->cn_namelen,
1166                 lockparent, wantparent));
1167
1168         if (nameiop != NAMEI_CREATE && nameiop != NAMEI_DELETE && nameiop != NAMEI_LOOKUP) {
1169                 printf("hpfs_lookup: LOOKUP, DELETE and CREATE are only supported\n");
1170                 return (EOPNOTSUPP);
1171         }
1172
1173         error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_td);
1174         if(error)
1175                 return (error);
1176
1177         if( (cnp->cn_namelen == 1) &&
1178             !strncmp(cnp->cn_nameptr,".",1) ) {
1179                 dprintf(("hpfs_lookup(0x%x,...): . faked\n",dhp->h_no));
1180
1181                 VREF(dvp);
1182                 *ap->a_vpp = dvp;
1183
1184                 return (0);
1185         } else if( (cnp->cn_namelen == 2) &&
1186             !strncmp(cnp->cn_nameptr,"..",2) && (flags & CNP_ISDOTDOT) ) {
1187                 dprintf(("hpfs_lookup(0x%x,...): .. faked (0x%x)\n",
1188                         dhp->h_no, dhp->h_fn.fn_parent));
1189
1190                 VOP__UNLOCK(dvp,0,cnp->cn_td);
1191
1192                 error = VFS_VGET(hpmp->hpm_mp,
1193                                  dhp->h_fn.fn_parent, ap->a_vpp); 
1194                 if(error) {
1195                         VOP__LOCK(dvp, 0, cnp->cn_td);
1196                         return(error);
1197                 }
1198
1199                 if( lockparent && (flags & CNP_ISLASTCN) && 
1200                     (error = VOP__LOCK(dvp, 0, cnp->cn_td)) ) {
1201                         vput( *(ap->a_vpp) );
1202                         return (error);
1203                 }
1204                 return (error);
1205         } else {
1206                 struct buf *bp;
1207                 struct hpfsdirent *dep;
1208                 struct hpfsnode *hp;
1209
1210                 error = hpfs_genlookupbyname(dhp,
1211                                 cnp->cn_nameptr, cnp->cn_namelen, &bp, &dep);
1212                 if (error) {
1213                         if ((error == ENOENT) && (flags & CNP_ISLASTCN) &&
1214                             (nameiop == NAMEI_CREATE || nameiop == NAMEI_RENAME)) {
1215                                 if(!lockparent)
1216                                         VOP__UNLOCK(dvp, 0, cnp->cn_td);
1217                                 cnp->cn_flags |= CNP_SAVENAME;
1218                                 return (EJUSTRETURN);
1219                         }
1220
1221                         return (error);
1222                 }
1223
1224                 dprintf(("hpfs_lookup: fnode: 0x%x, CPID: 0x%x\n",
1225                          dep->de_fnode, dep->de_cpid));
1226
1227                 if (nameiop == NAMEI_DELETE && (flags & CNP_ISLASTCN)) {
1228                         error = VOP_ACCESS(dvp, VWRITE, cred, cnp->cn_td);
1229                         if (error) {
1230                                 brelse(bp);
1231                                 return (error);
1232                         }
1233                 }
1234
1235                 if (dhp->h_no == dep->de_fnode) {
1236                         brelse(bp);
1237                         VREF(dvp);
1238                         *ap->a_vpp = dvp;
1239                         return (0);
1240                 }
1241
1242                 error = VFS_VGET(hpmp->hpm_mp, dep->de_fnode, ap->a_vpp);
1243                 if (error) {
1244                         printf("hpfs_lookup: VFS_VGET FAILED %d\n", error);
1245                         brelse(bp);
1246                         return(error);
1247                 }
1248
1249                 hp = VTOHP(*ap->a_vpp);
1250
1251                 hp->h_mtime = dep->de_mtime;
1252                 hp->h_ctime = dep->de_ctime;
1253                 hp->h_atime = dep->de_atime;
1254                 bcopy(dep->de_name, hp->h_name, dep->de_namelen);
1255                 hp->h_name[dep->de_namelen] = '\0';
1256                 hp->h_namelen = dep->de_namelen;
1257                 hp->h_flag |= H_PARVALID;
1258
1259                 brelse(bp);
1260
1261                 if(!lockparent || !(flags & CNP_ISLASTCN))
1262                         VOP__UNLOCK(dvp, 0, cnp->cn_td);
1263                 if ((flags & CNP_MAKEENTRY) &&
1264                     (!(flags & CNP_ISLASTCN) || 
1265                      (nameiop != NAMEI_DELETE && nameiop != NAMEI_CREATE)))
1266                         cache_enter(dvp, *ap->a_vpp, cnp);
1267         }
1268         return (error);
1269 }
1270
1271 int
1272 hpfs_remove(ap)
1273         struct vop_remove_args /* {
1274                 struct vnode *a_dvp;
1275                 struct vnode *a_vp;
1276                 struct componentname *a_cnp;
1277         } */ *ap;
1278 {
1279         int error;
1280
1281         dprintf(("hpfs_remove(0x%x, %s, %ld): \n", VTOHP(ap->a_vp)->h_no,
1282                 ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen));
1283
1284         if (ap->a_vp->v_type == VDIR)
1285                 return (EPERM);
1286
1287         error = hpfs_removefnode (ap->a_dvp, ap->a_vp, ap->a_cnp);
1288         return (error);
1289 }
1290
1291 int
1292 hpfs_create(ap)
1293         struct vop_create_args /* {
1294                 struct vnode *a_dvp;
1295                 struct vnode **a_vpp;
1296                 struct componentname *a_cnp;
1297                 struct vattr *a_vap;
1298         } */ *ap;
1299 {
1300         int error;
1301
1302         dprintf(("hpfs_create(0x%x, %s, %ld): \n", VTOHP(ap->a_dvp)->h_no,
1303                 ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen));
1304
1305         if (!(ap->a_cnp->cn_flags & CNP_HASBUF)) 
1306                 panic ("hpfs_create: no name\n");
1307
1308         error = hpfs_makefnode (ap->a_dvp, ap->a_vpp, ap->a_cnp, ap->a_vap);
1309
1310         return (error);
1311 }
1312
1313 /*
1314  * Return POSIX pathconf information applicable to NTFS filesystem
1315  */
1316 int
1317 hpfs_pathconf(ap)
1318         struct vop_pathconf_args /* {
1319                 struct vnode *a_vp;
1320                 int a_name;
1321                 t *a_retval;
1322         } */ *ap;
1323 {
1324         switch (ap->a_name) {
1325         case _PC_LINK_MAX:
1326                 *ap->a_retval = 1;
1327                 return (0);
1328         case _PC_NAME_MAX:
1329                 *ap->a_retval = HPFS_MAXFILENAME;
1330                 return (0);
1331         case _PC_PATH_MAX:
1332                 *ap->a_retval = PATH_MAX;
1333                 return (0);
1334         case _PC_CHOWN_RESTRICTED:
1335                 *ap->a_retval = 1;
1336                 return (0);
1337         case _PC_NO_TRUNC:
1338                 *ap->a_retval = 0;
1339                 return (0);
1340 #if defined(__NetBSD__)
1341         case _PC_SYNC_IO:
1342                 *ap->a_retval = 1;
1343                 return (0);
1344         case _PC_FILESIZEBITS:
1345                 *ap->a_retval = 32;
1346                 return (0);
1347 #endif
1348         default:
1349                 return (EINVAL);
1350         }
1351         /* NOTREACHED */
1352 }
1353
1354
1355 /*
1356  * Global vfs data structures
1357  */
1358 vop_t **hpfs_vnodeop_p;
1359 #if defined(__FreeBSD__)
1360 struct vnodeopv_entry_desc hpfs_vnodeop_entries[] = {
1361         { &vop_default_desc, (vop_t *)vop_defaultop },
1362
1363         { &vop_getattr_desc, (vop_t *)hpfs_getattr },
1364         { &vop_setattr_desc, (vop_t *)hpfs_setattr },
1365         { &vop_inactive_desc, (vop_t *)hpfs_inactive },
1366         { &vop_reclaim_desc, (vop_t *)hpfs_reclaim },
1367         { &vop_print_desc, (vop_t *)hpfs_print },
1368         { &vop_create_desc, (vop_t *)hpfs_create },
1369         { &vop_remove_desc, (vop_t *)hpfs_remove },
1370         { &vop_islocked_desc, (vop_t *)vop_stdislocked },
1371         { &vop_unlock_desc, (vop_t *)vop_stdunlock },
1372         { &vop_lock_desc, (vop_t *)vop_stdlock },
1373         { &vop_cachedlookup_desc, (vop_t *)hpfs_lookup },
1374         { &vop_lookup_desc, (vop_t *)vfs_cache_lookup },
1375         { &vop_access_desc, (vop_t *)hpfs_access },
1376         { &vop_close_desc, (vop_t *)hpfs_close },
1377         { &vop_open_desc, (vop_t *)hpfs_open },
1378         { &vop_readdir_desc, (vop_t *)hpfs_readdir },
1379         { &vop_fsync_desc, (vop_t *)hpfs_fsync },
1380         { &vop_bmap_desc, (vop_t *)hpfs_bmap },
1381         { &vop_getpages_desc, (vop_t *) hpfs_getpages },
1382         { &vop_putpages_desc, (vop_t *) hpfs_putpages },
1383         { &vop_strategy_desc, (vop_t *)hpfs_strategy },
1384         { &vop_bwrite_desc, (vop_t *)vop_stdbwrite },
1385         { &vop_read_desc, (vop_t *)hpfs_read },
1386         { &vop_write_desc, (vop_t *)hpfs_write },
1387         { &vop_ioctl_desc, (vop_t *)hpfs_ioctl },
1388         { &vop_pathconf_desc, (vop_t *)hpfs_pathconf },
1389         { NULL, NULL }
1390 };
1391
1392 static
1393 struct vnodeopv_desc hpfs_vnodeop_opv_desc =
1394         { &hpfs_vnodeop_p, hpfs_vnodeop_entries };
1395
1396 VNODEOP_SET(hpfs_vnodeop_opv_desc);
1397 #else /* defined(__NetBSD__) */
1398 struct vnodeopv_entry_desc ntfs_vnodeop_entries[] = {
1399         { &vop_default_desc, (vop_t *) genfs_badop },   /* XXX */
1400         { &vop_lookup_desc, (vop_t *) hpfs_lookup },    /* lookup */
1401         { &vop_create_desc, genfs_eopnotsupp },         /* create */
1402         { &vop_mknod_desc, genfs_eopnotsupp },          /* mknod */
1403         { &vop_open_desc, (vop_t *) hpfs_open },        /* open */
1404         { &vop_close_desc,(vop_t *) hpfs_close },       /* close */
1405         { &vop_access_desc, (vop_t *) hpfs_access },    /* access */
1406         { &vop_getattr_desc, (vop_t *) hpfs_getattr },  /* getattr */
1407         { &vop_setattr_desc, genfs_eopnotsupp },        /* setattr */
1408         { &vop_read_desc, (vop_t *) hpfs_read },        /* read */
1409         { &vop_write_desc, (vop_t *) hpfs_write },      /* write */
1410         { &vop_lease_desc, genfs_lease_check },         /* lease */
1411         { &vop_fcntl_desc, genfs_fcntl },               /* fcntl */
1412         { &vop_ioctl_desc, genfs_enoioctl },            /* ioctl */
1413         { &vop_poll_desc, genfs_poll },                 /* poll */
1414         { &vop_revoke_desc, genfs_revoke },             /* revoke */
1415         { &vop_mmap_desc, genfs_eopnotsupp },           /* mmap */
1416         { &vop_fsync_desc, genfs_fsync },               /* fsync */
1417         { &vop_seek_desc, genfs_seek },                 /* seek */
1418         { &vop_remove_desc, genfs_eopnotsupp },         /* remove */
1419         { &vop_link_desc, genfs_eopnotsupp },           /* link */
1420         { &vop_rename_desc, genfs_eopnotsupp },         /* rename */
1421         { &vop_mkdir_desc, genfs_eopnotsupp },          /* mkdir */
1422         { &vop_rmdir_desc, genfs_eopnotsupp },          /* rmdir */
1423         { &vop_symlink_desc, genfs_eopnotsupp },        /* symlink */
1424         { &vop_readdir_desc, (vop_t *) hpfs_readdir },  /* readdir */
1425         { &vop_readlink_desc, genfs_eopnotsupp },       /* readlink */
1426         { &vop_abortop_desc, genfs_abortop },           /* abortop */
1427         { &vop_inactive_desc, (vop_t *) hpfs_inactive },        /* inactive */
1428         { &vop_reclaim_desc, (vop_t *) hpfs_reclaim },  /* reclaim */
1429         { &vop_lock_desc, genfs_lock },                 /* lock */
1430         { &vop_unlock_desc, genfs_unlock },             /* unlock */
1431         { &vop_bmap_desc, (vop_t *) hpfs_bmap },        /* bmap */
1432         { &vop_strategy_desc, (vop_t *) hpfs_strategy },        /* strategy */
1433         { &vop_print_desc, (vop_t *) hpfs_print },      /* print */
1434         { &vop_islocked_desc, genfs_islocked },         /* islocked */
1435         { &vop_pathconf_desc, hpfs_pathconf },          /* pathconf */
1436         { &vop_advlock_desc, genfs_nullop },            /* advlock */
1437         { &vop_blkatoff_desc, genfs_eopnotsupp },       /* blkatoff */
1438         { &vop_valloc_desc, genfs_eopnotsupp },         /* valloc */
1439         { &vop_reallocblks_desc, genfs_eopnotsupp },    /* reallocblks */
1440         { &vop_vfree_desc, genfs_eopnotsupp },          /* vfree */
1441         { &vop_truncate_desc, genfs_eopnotsupp },       /* truncate */
1442         { &vop_update_desc, genfs_eopnotsupp },         /* update */
1443         { &vop_bwrite_desc, vn_bwrite },                /* bwrite */
1444         { (struct vnodeop_desc *)NULL, (int (*) (void *))NULL }
1445 };
1446 struct vnodeopv_desc ntfs_vnodeop_opv_desc =
1447         { &ntfs_vnodeop_p, ntfs_vnodeop_entries };
1448
1449 #endif