a6bbeda95ca172903073d22503c4d3073ab058d1
[openafs.git] / src / afs / DARWIN / 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  * MACOS inode operations
11  *
12  * Implements:
13  *
14  */
15 #include <afsconfig.h>
16 #include "afs/param.h"
17
18 RCSID
19     ("$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 <ufs/ufs/ufsmount.h>
26 extern struct ucred afs_osi_cred;
27
28 getinode(fs, dev, inode, vpp, perror)
29      struct mount *fs;
30      struct vnode **vpp;
31      dev_t dev;
32      ino_t inode;
33      int *perror;
34 {
35     struct vnode *vp;
36     int code;
37
38     *vpp = 0;
39     *perror = 0;
40     if (!fs) {
41         register struct ufsmount *ump;
42 #ifdef VFSTOHFS
43         register struct hfsmount *hmp;
44 #endif
45         register struct vnode *vp;
46         register struct mount *mp;
47         extern struct mount *rootfs;
48         if (mp = rootfs)
49             do {
50                 /*
51                  * XXX Also do the test for MFS 
52                  */
53                 if (!strcmp(mp->mnt_vfc->vfc_name, "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 #ifdef VFSTOHFS
62                 if (!strcmp(mp->mnt_vfc->vfc_name, "hfs")) {
63                     hmp = VFSTOHFS(mp);
64 #if 0
65                     if (hmp->hfs_mp == NULL)
66                         break;
67 #endif
68                     if (hmp->hfs_raw_dev == dev) {
69                         fs = hmp->hfs_mp;
70                     }
71                 }
72 #endif
73
74                 mp = CIRCLEQ_NEXT(mp, mnt_list);
75             } while (mp != rootfs);
76         if (!fs)
77             return (ENXIO);
78     }
79     code = VFS_VGET(fs, (void *)inode, &vp);
80     if (code) {
81         *perror = BAD_IGET;
82         return code;
83     } else {
84         *vpp = vp;
85         return (0);
86     }
87 }
88 extern int afs_CacheFSType;
89 igetinode(vfsp, dev, inode, vpp, va, perror)
90      struct vnode **vpp;
91      struct mount *vfsp;
92      dev_t dev;
93      ino_t inode;
94      struct vattr *va;
95      int *perror;
96 {
97     struct vnode *pvp, *vp;
98     extern struct osi_dev cacheDev;
99     register int code = 0;
100
101     *perror = 0;
102
103     AFS_STATCNT(igetinode);
104     if ((code = getinode(vfsp, dev, inode, &vp, perror)) != 0) {
105         return (code);
106     }
107     if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) {
108         printf("igetinode: bad type %d\n", vp->v_type);
109         iforget(vp);
110         return (ENOENT);
111     }
112     VOP_GETATTR(vp, va, &afs_osi_cred, current_proc());
113     if (va->va_mode == 0) {
114         /* Not an allocated inode */
115         iforget(vp);
116         return (ENOENT);
117     }
118     if (vfsp && afs_CacheFSType == AFS_APPL_HFS_CACHE && va->va_nlink == 0) {
119         printf("igetinode: hfs nlink 0\n");
120     }
121     if (va->va_nlink == 0) {
122         vput(vp);
123         return (ENOENT);
124     }
125
126     VOP_UNLOCK(vp, 0, current_proc());
127     *vpp = vp;
128     return (0);
129 }
130
131 iforget(vp)
132      struct vnode *vp;
133 {
134
135     AFS_STATCNT(iforget);
136     /* XXX could sleep */
137     vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, current_proc());
138     /* this whole thing is too wierd.  Why??? XXX */
139     if (vp->v_usecount == 1) {
140         vp->v_usecount = 0;
141         VOP_UNLOCK(vp, 0, current_proc());
142 #if 0
143         simple_lock(&vnode_free_list_slock);
144         TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
145         freevnodes++;
146         simple_unlock(&vnode_free_list_slock);
147 #else
148         printf("iforget: leaking vnode\n");
149 #endif
150     } else {
151         vput(vp);
152     }
153 }
154
155 #if 0
156 /*
157  * icreate system call -- create an inode
158  */
159 afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, retval)
160      long *retval;
161      long dev, near_inode, param1, param2, param3, param4;
162 {
163     int dummy, err = 0;
164     struct inode *ip, *newip;
165     register int code;
166     struct vnode *vp;
167
168     AFS_STATCNT(afs_syscall_icreate);
169
170     if (!afs_suser())
171         return (EPERM);
172
173     code = getinode(0, (dev_t) dev, 2, &ip, &dummy);
174     if (code) {
175         return (ENOENT);
176     }
177     code = ialloc(ip, (ino_t) near_inode, 0, &newip);
178     iput(ip);
179     if (code) {
180         return (code);
181     }
182     IN_LOCK(newip);
183     newip->i_flag |= IACC | IUPD | ICHG;
184
185     newip->i_nlink = 1;
186
187     newip->i_mode = IFREG;
188
189     IN_UNLOCK(newip);
190     vp = ITOV(newip);
191     VN_LOCK(vp);
192     vp->v_type = VREG;
193     VN_UNLOCK(vp);
194
195     if (!vp->v_object) {
196         extern struct vfs_ubcops ufs_ubcops;
197         extern struct vm_ubc_object *ubc_object_allocate();
198         struct vm_ubc_object *vop;
199         vop = ubc_object_allocate(&vp, &ufs_ubcops, vp->v_mount->m_funnel);
200         VN_LOCK(vp);
201         vp->v_object = vop;
202         VN_UNLOCK(vp);
203     }
204
205
206     IN_LOCK(newip);
207     newip->i_flags |= IC_XUID | IC_XGID;
208     newip->i_flags &= ~IC_PROPLIST;
209     newip->i_vicep1 = param1;
210     if (param2 == 0x1fffffff /*INODESPECIAL*/) {
211         newip->i_vicep2 = ((0x1fffffff << 3) + (param4 & 0x3));
212         newip->i_vicep3a = (u_short) (param3 >> 16);
213         newip->i_vicep3b = (u_short) param3;
214     } else {
215         newip->i_vicep2 =
216             (((param2 >> 16) & 0x1f) << 27) +
217             (((param4 >> 16) & 0x1f) << 22) + (param3 & 0x3fffff);
218         newip->i_vicep3a = (u_short) param4;
219         newip->i_vicep3b = (u_short) param2;
220     }
221     newip->i_vicemagic = VICEMAGIC;
222
223     *retval = newip->i_number;
224     IN_UNLOCK(newip);
225     iput(newip);
226     return (code);
227 }
228
229
230 afs_syscall_iopen(dev, inode, usrmod, retval)
231      long *retval;
232      int dev, inode, usrmod;
233 {
234     struct file *fp;
235     struct inode *ip;
236     struct vnode *vp = NULL;
237     int dummy;
238     int fd;
239     extern struct fileops vnops;
240     register int code;
241
242     AFS_STATCNT(afs_syscall_iopen);
243
244     if (!afs_suser())
245         return (EPERM);
246
247     code = igetinode(0, (dev_t) dev, (ino_t) inode, &ip, &dummy);
248     if (code) {
249         return (code);
250     }
251     if ((code = falloc(&fp, &fd)) != 0) {
252         iput(ip);
253         return (code);
254     }
255     IN_UNLOCK(ip);
256
257     FP_LOCK(fp);
258     fp->f_flag = (usrmod - FOPEN) & FMASK;
259     fp->f_type = DTYPE_VNODE;
260     fp->f_ops = &vnops;
261     fp->f_data = (caddr_t) ITOV(ip);
262
263     FP_UNLOCK(fp);
264     U_FD_SET(fd, fp, &u.u_file_state);
265     *retval = fd;
266     return (0);
267 }
268
269
270 /*
271  * Support for iinc() and idec() system calls--increment or decrement
272  * count on inode.
273  * Restricted to super user.
274  * Only VICEMAGIC type inodes.
275  */
276 afs_syscall_iincdec(dev, inode, inode_p1, amount)
277      int dev, inode, inode_p1, amount;
278 {
279     int dummy;
280     struct inode *ip;
281     register int code;
282
283     if (!afs_suser())
284         return (EPERM);
285
286     code = igetinode(0, (dev_t) dev, (ino_t) inode, &ip, &dummy);
287     if (code) {
288         return (code);
289     }
290     if (!IS_VICEMAGIC(ip)) {
291         return (EPERM);
292     } else if (ip->i_vicep1 != inode_p1) {
293         return (ENXIO);
294     }
295     ip->i_nlink += amount;
296     if (ip->i_nlink == 0) {
297         CLEAR_VICEMAGIC(ip);
298     }
299     ip->i_flag |= ICHG;
300     iput(ip);
301     return (0);
302 }
303 #else
304 afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, retval)
305      long *retval;
306      long dev, near_inode, param1, param2, param3, param4;
307 {
308     return EOPNOTSUPP;
309 }
310
311 afs_syscall_iopen(dev, inode, usrmod, retval)
312      long *retval;
313      int dev, inode, usrmod;
314 {
315     return EOPNOTSUPP;
316 }
317
318 afs_syscall_iincdec(dev, inode, inode_p1, amount)
319      int dev, inode, inode_p1, amount;
320 {
321     return EOPNOTSUPP;
322 }
323 #endif