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