Commit | Line | Data |
---|---|---|
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 | |
23 | static thread_t vfs_context_owner; | |
24 | ||
25 | /* works like PFlushVolumeData */ | |
26 | void | |
27 | darwin_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 | } | |
53 | loop: | |
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 | ||
109 | int | |
110 | osi_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 | ||
126 | int | |
127 | osi_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 | |
145 | int | |
146 | osi_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 | */ | |
172 | int | |
173 | afs_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 | |
192 | struct uio * | |
193 | afsio_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 | ||
222 | vfs_context_t afs_osi_ctxtp; | |
223 | int afs_osi_ctxtp_initialized; | |
224 | static proc_t vfs_context_curproc; | |
225 | int vfs_context_ref; | |
226 | ||
227 | void | |
228 | get_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 | ||
264 | void | |
265 | put_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 | ||
284 | int | |
285 | afs_cdev_nop_openclose(dev_t dev, int flags, int devtype,struct proc *p) | |
286 | { | |
287 | return 0; | |
288 | } | |
289 | ||
290 | int | |
291 | afs_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 |