freebsd-50-20030416
[openafs.git] / src / afs / FBSD / osi_inode.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * FreeBSD inode operations
12  *
13  * Implements:
14  *
15  */
16 #include <afsconfig.h>
17 #include "afs/param.h"
18
19 RCSID("$Header$");
20
21 #include "afs/sysincludes.h"    /* Standard vendor system headers */
22 #include "afsincludes.h"        /* Afs-based standard headers */
23 #include "afs/osi_inode.h"
24 #include "afs/afs_stats.h" /* statistics stuff */
25 #include <sys/queue.h>
26 #include <sys/lock.h>
27 #include <ufs/ufs/dinode.h>
28 #if defined(AFS_FBSD50_ENV)
29 #include <ufs/ufs/extattr.h>
30 #endif
31 #include <ufs/ufsmount.h>
32
33 int
34 getinode(fs, dev, inode, ipp, perror)
35      struct mount *fs;
36      struct inode **ipp;
37      dev_t dev;
38      ino_t inode;
39      int *perror;
40 {
41     struct vnode *vp;
42     int code;
43
44     *ipp = 0;
45     *perror = 0;
46     if (!fs) {
47         register struct ufsmount *ump;
48         register struct mount *mp;
49
50 #if defined(AFS_FBSD50_ENV)
51         mtx_lock(&mountlist_mtx);
52 #else
53         simple_lock(&mountlist_slock);
54 #endif
55         if (mp = TAILQ_FIRST(&mountlist)) do {
56             /*
57              * XXX Also do the test for MFS
58              */
59 #undef m_data
60 #undef m_next
61             if (mp->mnt_stat.f_type == MOUNT_UFS) {
62                 ump = VFSTOUFS(mp);
63                 if (ump->um_fs == NULL)
64                     break;
65                 if (ump->um_dev == dev) {
66                     fs = ump->um_mountp;
67                 }
68             }
69             mp = TAILQ_NEXT(mp, mnt_list);
70         } while (mp != TAILQ_FIRST(&mountlist));
71 #if defined(AFS_FBSD50_ENV)
72         mtx_unlock(&mountlist_mtx);
73 #else
74         simple_unlock(&mountlist_slock);
75 #endif
76         if (!fs)
77             return(ENXIO);
78     }
79 #if defined(AFS_FBSD50_ENV)
80     code = VFS_VGET(fs, inode, 0, &vp);
81 #else
82     code = VFS_VGET(fs, inode, &vp);
83 #endif
84     if (code != 0) {
85         *perror = BAD_IGET;
86         return code;
87     } else {
88         *ipp = VTOI(vp);
89         return(0);
90     }
91 }
92
93 int
94 igetinode(vfsp, dev, inode, ipp, perror)
95      struct inode **ipp;
96      struct mount *vfsp;
97      dev_t dev;
98      ino_t inode;
99      int *perror;
100 {
101     struct inode *ip;
102     register int code = 0;
103
104     *perror = 0;
105
106     AFS_STATCNT(igetinode);
107
108     if ((code = getinode(vfsp, dev, inode, &ip, perror)) != 0) {
109         return(code);
110     }
111
112     if (ip->i_mode == 0) {
113         /* Not an allocated inode */
114         vput(ITOV(ip));
115         return(ENOENT);
116     }
117
118     if (ip->i_nlink == 0 || (ip->i_mode&IFMT) != IFREG) {
119         vput(ITOV(ip));
120         return(ENOENT);
121     }
122
123     *ipp = ip;
124     return(0);
125 }
126
127 #if 0
128 /*
129  * icreate system call -- create an inode
130  */
131 afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, retval)
132      long *retval;
133      long dev, near_inode, param1, param2, param3, param4;
134 {
135     int dummy, err=0;
136     struct inode *ip, *newip;
137     register int code;
138     struct vnode *vp;
139     
140     AFS_STATCNT(afs_syscall_icreate);
141     
142     if (!afs_suser())
143         return(EPERM);
144
145     code = getinode(0, (dev_t)dev, 2, &ip, &dummy);
146     if (code) {
147         return(ENOENT);
148     }
149     code = ialloc(ip, (ino_t)near_inode, 0, &newip);
150     iput(ip);
151     if (code) {
152         return(code);
153     }
154     IN_LOCK(newip);
155     newip->i_flag |= IACC|IUPD|ICHG;
156     
157     newip->i_nlink = 1;
158
159     newip->i_mode = IFREG;
160     
161     IN_UNLOCK(newip);
162     vp = ITOV(newip);
163     VN_LOCK(vp);
164     vp->v_type = VREG;
165     VN_UNLOCK(vp);
166     
167     /*
168     if ( !vp->v_object)
169         {
170             extern struct vfs_ubcops ufs_ubcops;
171             extern struct vm_ubc_object* ubc_object_allocate();
172             struct vm_ubc_object* vop;
173             vop = ubc_object_allocate(&vp, &ufs_ubcops,
174                                       vp->v_mount->m_funnel);
175             VN_LOCK(vp);
176             vp->v_object = vop;
177             VN_UNLOCK(vp);
178         }
179     */
180     
181     IN_LOCK(newip);
182     /*    newip->i_flags |= IC_XUID|IC_XGID; */
183     /*    newip->i_flags &= ~IC_PROPLIST; */
184     newip->i_vicep1 = param1;
185     if (param2 == 0x1fffffff/*INODESPECIAL*/)   {
186         newip->i_vicep2 = ((0x1fffffff << 3) + (param4 & 0x3));
187         newip->i_vicep3a = (u_short)(param3 >> 16);
188         newip->i_vicep3b = (u_short)param3;
189     } else {
190         newip->i_vicep2 = (((param2 >> 16) & 0x1f) << 27) +
191             (((param4 >> 16) & 0x1f) << 22) + 
192                 (param3 & 0x3fffff);        
193         newip->i_vicep3a = (u_short)param4;
194         newip->i_vicep3b = (u_short)param2;
195     }
196     newip->i_vicemagic = VICEMAGIC;
197     
198     *retval = newip->i_number;
199     IN_UNLOCK(newip);
200     iput(newip);
201     return(code);
202 }
203
204
205 int
206 afs_syscall_iopen(dev, inode, usrmod, retval)
207      long *retval;
208      int dev, inode, usrmod;
209 {
210     struct file *fp;
211     struct inode *ip;
212     struct vnode *vp = NULL;
213     int dummy;
214     int fd;
215     extern struct fileops vnops;
216     register int code;
217     
218     AFS_STATCNT(afs_syscall_iopen);
219     
220     if (!afs_suser())
221         return(EPERM);
222
223     code = igetinode(0, (dev_t)dev, (ino_t)inode, &ip, &dummy);
224     if (code) {
225         return(code);
226     }
227     if ((code = falloc(curproc, &fp, &fd)) != 0) {
228         iput(ip);
229         return(code);
230     }
231     IN_UNLOCK(ip);
232     
233     /* FreeBSD doesn't do much mp stuff yet :( */
234     /* FP_LOCK(fp); */
235     fp->f_flag = (usrmod) & FMASK;
236     fp->f_type = DTYPE_VNODE;
237     fp->f_ops = &vnops;
238     fp->f_data = (caddr_t)ITOV(ip);
239     
240     /* FP_UNLOCK(fp); */
241     return(0);
242 }
243
244
245 /*
246  * Support for iinc() and idec() system calls--increment or decrement
247  * count on inode.
248  * Restricted to super user.
249  * Only VICEMAGIC type inodes.
250  */
251 int
252 afs_syscall_iincdec(dev, inode, inode_p1, amount)
253      int dev, inode, inode_p1, amount;
254 {
255     int dummy;
256     struct inode *ip;
257     register int code;
258     
259     if (!afs_suser())
260         return(EPERM);
261
262     code = igetinode(0, (dev_t)dev, (ino_t)inode, &ip, &dummy);
263     if (code) {
264         return(code);
265     }
266     if (!IS_VICEMAGIC(ip)) {
267         return(EPERM);
268     } else if (ip->i_vicep1 != inode_p1) {
269         return(ENXIO);
270     }
271     ip->i_nlink += amount;
272     if (ip->i_nlink == 0) {
273         CLEAR_VICEMAGIC(ip);
274     }
275     ip->i_flag |= ICHG;
276     iput(ip);
277     return(0);
278 }
279 #else
280 int
281 afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, retval)
282      long *retval;
283      long dev, near_inode, param1, param2, param3, param4;
284 {
285      return EOPNOTSUPP;
286 }
287
288 int
289 afs_syscall_iopen(dev, inode, usrmod, retval)
290      long *retval;
291      int dev, inode, usrmod;
292 {
293      return EOPNOTSUPP;
294 }
295
296 int
297 afs_syscall_iincdec(dev, inode, inode_p1, amount)
298      int dev, inode, inode_p1, amount;
299 {
300      return EOPNOTSUPP;
301 }
302 #endif
303