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