Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / afs / DARWIN / osi_misc.c
CommitLineData
805e021f
CE
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#include <afsconfig.h>
11#include "afs/param.h"
12
13
14#include "afs/sysincludes.h"
15#include "afsincludes.h"
16#include <sys/namei.h>
17
18#ifndef PATHBUFLEN
19#define PATHBUFLEN 256
20#endif
21
22#ifdef AFS_DARWIN80_ENV
23static thread_t vfs_context_owner;
24
25/* works like PFlushVolumeData */
26void
27darwin_notify_perms(struct unixuser *auser, int event)
28{
29 int i;
30 struct afs_q *tq, *uq = NULL;
31 struct vcache *tvc, *hnext;
32 int isglock = ISAFS_GLOCK();
33 struct vnode *vp;
34 struct vnode_attr va;
35 int isctxtowner = 0;
36
37 if (!afs_darwin_fsevents)
38 return;
39
40 VATTR_INIT(&va);
41 VATTR_SET(&va, va_mode, 0777);
42 if (event & UTokensObtained)
43 VATTR_SET(&va, va_uid, auser->uid);
44 else
45 VATTR_SET(&va, va_uid, -2); /* nobody */
46
47 if (!isglock)
48 AFS_GLOCK();
49 if (!(vfs_context_owner == current_thread())) {
50 get_vfs_context();
51 isctxtowner = 1;
52 }
53loop:
54 ObtainReadLock(&afs_xvcache);
55 for (i = 0; i < VCSIZE; i++) {
56 for (tq = afs_vhashTV[i].prev; tq != &afs_vhashTV[i]; tq = uq) {
57 uq = QPrev(tq);
58 tvc = QTOVH(tq);
59 if (tvc->f.states & CDeadVnode) {
60 /* we can afford to be best-effort */
61 continue;
62 }
63 /* no per-file acls, so only notify on directories */
64 if (!(vp = AFSTOV(tvc)) || !vnode_isdir(AFSTOV(tvc)))
65 continue;
66 /* dynroot object. no callbacks. anonymous ACL. just no. */
67 if (afs_IsDynrootFid(&tvc->f.fid))
68 continue;
69 /* no fake fsevents on mount point sources. leaks refs */
70 if (tvc->mvstat == AFS_MVSTAT_MTPT)
71 continue;
72 /* if it's being reclaimed, just pass */
73 if (vnode_get(vp))
74 continue;
75 if (vnode_ref(vp)) {
76 AFS_GUNLOCK();
77 vnode_put(vp);
78 AFS_GLOCK();
79 continue;
80 }
81 ReleaseReadLock(&afs_xvcache);
82 /* Avoid potentially re-entering on this lock */
83 if (0 == NBObtainWriteLock(&tvc->lock, 234)) {
84 tvc->f.states |= CEvent;
85 AFS_GUNLOCK();
86 vnode_setattr(vp, &va, afs_osi_ctxtp);
87 tvc->f.states &= ~CEvent;
88 vnode_put(vp);
89 AFS_GLOCK();
90 ReleaseWriteLock(&tvc->lock);
91 } else {
92 AFS_GUNLOCK();
93 vnode_put(vp);
94 AFS_GLOCK();
95 }
96 ObtainReadLock(&afs_xvcache);
97 uq = QPrev(tq);
98 /* our tvc ptr is still good until now */
99 AFS_FAST_RELE(tvc);
100 }
101 }
102 ReleaseReadLock(&afs_xvcache);
103 if (isctxtowner)
104 put_vfs_context();
105 if (!isglock)
106 AFS_GUNLOCK();
107}
108
109int
110osi_lookupname_user(user_addr_t aname, enum uio_seg seg, int followlink,
111 struct vnode **vpp) {
112 char tname[PATHBUFLEN];
113 size_t len;
114 int code;
115
116 if (seg == AFS_UIOUSER) { /* XXX 64bit */
117 AFS_COPYINSTR(aname, tname, sizeof(tname), &len, code);
118 if (code)
119 return code;
120 return osi_lookupname(tname, seg, followlink, vpp);
121 } else
122 return osi_lookupname(CAST_DOWN(char *, aname), seg, followlink, vpp);
123
124}
125
126int
127osi_lookupname(char *aname, enum uio_seg seg, int followlink,
128 struct vnode **vpp) {
129 vfs_context_t ctx;
130 int code, flags;
131
132 flags = 0;
133 if (!followlink)
134 flags |= VNODE_LOOKUP_NOFOLLOW;
135 ctx=vfs_context_create(NULL);
136 code = vnode_lookup(aname, flags, vpp, ctx);
137 if (!code) { /* get a usecount */
138 vnode_ref(*vpp);
139 vnode_put(*vpp);
140 }
141 vfs_context_rele(ctx);
142 return code;
143}
144#else
145int
146osi_lookupname(char *aname, enum uio_seg seg, int followlink,
147 struct vnode **vpp)
148{
149 struct nameidata n;
150 int flags, error;
151 flags = 0;
152 flags = LOCKLEAF;
153 if (followlink)
154 flags |= FOLLOW;
155 else
156 flags |= NOFOLLOW;
157 NDINIT(&n, LOOKUP, flags, seg, aname, current_proc());
158 if (error = namei(&n))
159 return error;
160 *vpp = n.ni_vp;
161 /* should we do this? */
162 VOP_UNLOCK(n.ni_vp, 0, current_proc());
163 return 0;
164}
165#endif
166
167/*
168 * afs_suser() returns true if the caller is superuser, false otherwise.
169 *
170 * Note that it must NOT set errno.
171 */
172int
173afs_suser(void *credp)
174{
175 int error;
176 struct proc *p = current_proc();
177
178#ifdef AFS_DARWIN80_ENV
179 if ((error = proc_suser(p)) == 0) {
180 return (1);
181 }
182 return (0);
183#else
184 if ((error = suser(p->p_ucred, &p->p_acflag)) == 0) {
185 return (1);
186 }
187 return (0);
188#endif
189}
190
191#ifdef AFS_DARWIN80_ENV
192struct uio *
193afsio_partialcopy(struct uio *auio, size_t size)
194{
195 struct uio *res;
196 int i;
197 user_addr_t iovaddr;
198 user_size_t iovsize;
199
200 if (proc_is64bit(current_proc())) {
201 res = uio_create(uio_iovcnt(auio), uio_offset(auio),
202 uio_isuserspace(auio) ? UIO_USERSPACE64 : UIO_SYSSPACE32,
203 uio_rw(auio));
204 } else {
205 res = uio_create(uio_iovcnt(auio), uio_offset(auio),
206 uio_isuserspace(auio) ? UIO_USERSPACE32 : UIO_SYSSPACE32,
207 uio_rw(auio));
208 }
209
210 for (i = 0;i < uio_iovcnt(auio) && size > 0;i++) {
211 if (uio_getiov(auio, i, &iovaddr, &iovsize))
212 break;
213 if (iovsize > size)
214 iovsize = size;
215 if (uio_addiov(res, iovaddr, iovsize))
216 break;
217 size -= iovsize;
218 }
219 return res;
220}
221
222vfs_context_t afs_osi_ctxtp;
223int afs_osi_ctxtp_initialized;
224static proc_t vfs_context_curproc;
225int vfs_context_ref;
226
227void
228get_vfs_context(void)
229{
230 int isglock = ISAFS_GLOCK();
231
232 if (!isglock)
233 AFS_GLOCK();
234 if (afs_osi_ctxtp_initialized) {
235 if (!isglock)
236 AFS_GUNLOCK();
237 return;
238 }
239 osi_Assert(vfs_context_owner != current_thread());
240 if (afs_osi_ctxtp && current_proc() == vfs_context_curproc) {
241 vfs_context_ref++;
242 vfs_context_owner = current_thread();
243 if (!isglock)
244 AFS_GUNLOCK();
245 return;
246 }
247 while (afs_osi_ctxtp && vfs_context_ref) {
248 afs_osi_Sleep(&afs_osi_ctxtp);
249 if (afs_osi_ctxtp_initialized) {
250 if (!isglock)
251 AFS_GUNLOCK();
252 return;
253 }
254 }
255 vfs_context_rele(afs_osi_ctxtp);
256 vfs_context_ref=1;
257 afs_osi_ctxtp = vfs_context_create(NULL);
258 vfs_context_owner = current_thread();
259 vfs_context_curproc = current_proc();
260 if (!isglock)
261 AFS_GUNLOCK();
262}
263
264void
265put_vfs_context(void)
266{
267 int isglock = ISAFS_GLOCK();
268
269 if (!isglock)
270 AFS_GLOCK();
271 if (afs_osi_ctxtp_initialized) {
272 if (!isglock)
273 AFS_GUNLOCK();
274 return;
275 }
276 if (vfs_context_owner == current_thread())
277 vfs_context_owner = (thread_t)0;
278 vfs_context_ref--;
279 afs_osi_Wakeup(&afs_osi_ctxtp);
280 if (!isglock)
281 AFS_GUNLOCK();
282}
283
284int
285afs_cdev_nop_openclose(dev_t dev, int flags, int devtype,struct proc *p)
286{
287 return 0;
288}
289
290int
291afs_cdev_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p) {
292 unsigned int retval=0;
293 int code, is64 = proc_is64bit(p);
294 struct afssysargs *a = (struct afssysargs *)data;
295 struct afssysargs64 *a64 = (struct afssysargs64 *)data;
296
297 if (((unsigned int)cmd != VIOC_SYSCALL) &&
298 ((unsigned int)cmd != VIOC_SYSCALL64))
299 return EINVAL;
300
301 if (((unsigned int)cmd == VIOC_SYSCALL64) && (is64 == 0))
302 return EINVAL;
303
304 if (((unsigned int)cmd == VIOC_SYSCALL) && (is64 != 0))
305 return EINVAL;
306
307 code=afs3_syscall(p, data, &retval);
308 if (code)
309 return code;
310
311 if ((!is64) && retval && a->syscall != AFSCALL_CALL
312 && a->param1 != AFSOP_CACHEINODE)
313 {
314 printf("SSCall(%d,%d) is returning non-error value %d\n", a->syscall, a->param1, retval);
315 }
316 if ((is64) && retval && a64->syscall != AFSCALL_CALL
317 && a64->param1 != AFSOP_CACHEINODE)
318 {
319 printf("SSCall(%d,%llx) is returning non-error value %d\n", a64->syscall, a64->param1, retval);
320 }
321
322 if (!is64)
323 a->retval = retval;
324 else
325 a64->retval = retval;
326 return 0;
327}
328
329#endif