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