afs-suser-consistent-20040728
[openafs.git] / src / afs / NBSD / 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
20     ("$Header$");
21
22 #include "afs/sysincludes.h"    /* Standard vendor system headers */
23 #include "afsincludes.h"        /* Afs-based standard headers */
24 #include "afs/osi_inode.h"
25 #include "afs/afs_stats.h"      /* statistics stuff */
26 #include <sys/queue.h>
27 #include <sys/lock.h>
28 #include <ufs/ufsmount.h>
29 #include <ufs/ufs/dinode.h>
30
31 getinode(fs, dev, inode, ipp, perror)
32      struct mount *fs;
33      struct inode **ipp;
34      dev_t dev;
35      ino_t inode;
36      int *perror;
37 {
38     register struct vnode *vp;
39     char fake_vnode[FAKE_INODE_SIZE];
40     struct inode *ip;
41     int code;
42
43     *ipp = 0;
44     *perror = 0;
45     if (!fs) {
46         register struct ufsmount *ump;
47         register struct vnode *vp;
48         register struct mount *mp;
49
50         MOUNTLIST_LOCK();
51         if (mp = TAILQ_FIRST(&mountlist))
52             do {
53                 /*
54                  * XXX Also do the test for MFS 
55                  */
56 #undef m_data
57 #undef m_next
58                 if (mp->mnt_stat.f_type == MOUNT_UFS) {
59                     MOUNTLIST_UNLOCK();
60                     ump = VFSTOUFS(mp);
61                     if (ump->um_fs == NULL)
62                         break;
63                     if (ump->um_dev == dev) {
64                         fs = ump->um_mountp;
65                     }
66                     MOUNTLIST_LOCK();
67                 }
68                 mp = TAILQ_NEXT(mp, mnt_list);
69             } while (mp != TAILQ_FIRST(&mountlist));
70         MOUNTLIST_UNLOCK();
71         if (!fs)
72             return (ENXIO);
73     }
74     vp = (struct vnode *)fake_vnode;
75     fake_inode_init(vp, fs);
76     code = iget(VTOI(vp), inode, &ip, 0);
77     if (code != 0) {
78         *perror = BAD_IGET;
79         return code;
80     } else {
81         *ipp = ip;
82         return (0);
83     }
84 }
85
86 igetinode(vfsp, dev, inode, ipp, perror)
87      struct inode **ipp;
88      struct mount *vfsp;
89      dev_t dev;
90      ino_t inode;
91      int *perror;
92 {
93     struct inode *pip, *ip;
94     extern struct osi_dev cacheDev;
95     register int code = 0;
96
97     *perror = 0;
98
99     AFS_STATCNT(igetinode);
100
101     if ((code = getinode(vfsp, dev, inode, &ip, perror)) != 0) {
102         return (code);
103     }
104
105     if (ip->i_mode == 0) {
106         /* Not an allocated inode */
107         iforget(ip);
108         return (ENOENT);
109     }
110
111     if (ip->i_nlink == 0 || (ip->i_mode & IFMT) != IFREG) {
112         iput(ip);
113         return (ENOENT);
114     }
115
116     *ipp = ip;
117     return (0);
118 }
119
120 iforget(ip)
121      struct inode *ip;
122 {
123     struct vnode *vp = ITOV(ip);
124
125     AFS_STATCNT(iforget);
126
127     VN_LOCK(vp);
128     /* this whole thing is too wierd.  Why??? XXX */
129     if (vp->v_usecount == 1) {
130         VN_UNLOCK(vp);
131         idrop(ip);
132     } else {
133         VN_UNLOCK(vp);
134     }
135 }
136
137 /*
138  * icreate system call -- create an inode
139  */
140 afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, retval)
141      long *retval;
142      long dev, near_inode, param1, param2, param3, param4;
143 {
144     int dummy, err = 0;
145     struct inode *ip, *newip;
146     register int code;
147     struct vnode *vp;
148
149     AFS_STATCNT(afs_syscall_icreate);
150
151     if (!afs_suser(NULL))
152         return (EPERM);
153
154     code = getinode(0, (dev_t) dev, 2, &ip, &dummy);
155     if (code) {
156         return (ENOENT);
157     }
158     code = ialloc(ip, (ino_t) near_inode, 0, &newip);
159     iput(ip);
160     if (code) {
161         return (code);
162     }
163     IN_LOCK(newip);
164     newip->i_flag |= IACC | IUPD | ICHG;
165
166     newip->i_nlink = 1;
167
168     newip->i_mode = IFREG;
169
170     IN_UNLOCK(newip);
171     vp = ITOV(newip);
172     VN_LOCK(vp);
173     vp->v_type = VREG;
174     VN_UNLOCK(vp);
175
176     /*
177      * if ( !vp->v_object)
178      * {
179      * extern struct vfs_ubcops ufs_ubcops;
180      * extern struct vm_ubc_object* ubc_object_allocate();
181      * struct vm_ubc_object* vop;
182      * vop = ubc_object_allocate(&vp, &ufs_ubcops,
183      * vp->v_mount->m_funnel);
184      * VN_LOCK(vp);
185      * vp->v_object = vop;
186      * VN_UNLOCK(vp);
187      * }
188      */
189
190     IN_LOCK(newip);
191     /*    newip->i_flags |= IC_XUID|IC_XGID; */
192     /*    newip->i_flags &= ~IC_PROPLIST; */
193     newip->i_vicep1 = param1;
194     if (param2 == 0x1fffffff /*INODESPECIAL*/) {
195         newip->i_vicep2 = ((0x1fffffff << 3) + (param4 & 0x3));
196         newip->i_vicep3a = (u_short) (param3 >> 16);
197         newip->i_vicep3b = (u_short) param3;
198     } else {
199         newip->i_vicep2 =
200             (((param2 >> 16) & 0x1f) << 27) +
201             (((param4 >> 16) & 0x1f) << 22) + (param3 & 0x3fffff);
202         newip->i_vicep3a = (u_short) param4;
203         newip->i_vicep3b = (u_short) param2;
204     }
205     newip->i_vicemagic = VICEMAGIC;
206
207     *retval = newip->i_number;
208     IN_UNLOCK(newip);
209     iput(newip);
210     return (code);
211 }
212
213
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 afs_syscall_iincdec(dev, inode, inode_p1, amount)
260      int dev, inode, inode_p1, amount;
261 {
262     int dummy;
263     struct inode *ip;
264     register int code;
265
266     if (!afs_suser(NULL))
267         return (EPERM);
268
269     code = igetinode(0, (dev_t) dev, (ino_t) inode, &ip, &dummy);
270     if (code) {
271         return (code);
272     }
273     if (!IS_VICEMAGIC(ip)) {
274         return (EPERM);
275     } else if (ip->i_vicep1 != inode_p1) {
276         return (ENXIO);
277     }
278     ip->i_nlink += amount;
279     if (ip->i_nlink == 0) {
280         CLEAR_VICEMAGIC(ip);
281     }
282     ip->i_flag |= ICHG;
283     iput(ip);
284     return (0);
285 }