LINUX 5.3.0: Check for 'recurse' arg in keyring_search
[openafs.git] / src / afs / LINUX / osi_misc.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  * Linux support routines.
12  *
13  */
14 #include <afsconfig.h>
15 #include "afs/param.h"
16
17
18 #include <linux/module.h> /* early to avoid printf->printk mapping */
19 #include <linux/dcache.h>
20 #include <linux/namei.h>
21 #include <linux/kthread.h>
22 #include "afs/sysincludes.h"
23 #include "afsincludes.h"
24 #include "afs/afs_stats.h"
25
26 #include "osi_compat.h"
27
28 int afs_osicred_initialized = 0;
29 afs_ucred_t afs_osi_cred;
30
31 void
32 osi_linux_mask(void)
33 {
34     SIG_LOCK(current);
35     sigfillset(&current->blocked);
36     RECALC_SIGPENDING(current);
37     SIG_UNLOCK(current);
38 }
39
40 /* LOOKUP_POSITIVE is becoming the default */
41 #ifndef LOOKUP_POSITIVE
42 #define LOOKUP_POSITIVE 0
43 #endif
44 /* Lookup name and return vnode for same. */
45 int
46 osi_lookupname_internal(char *aname, int followlink, struct vfsmount **mnt,
47                         struct dentry **dpp)
48 {
49     int code;
50 #if defined(HAVE_LINUX_PATH_LOOKUP)
51     struct nameidata path_data;
52 #else
53     afs_linux_path_t path_data;
54 #endif
55     int flags = LOOKUP_POSITIVE;
56
57     if (followlink)
58        flags |= LOOKUP_FOLLOW;
59     code = afs_kern_path(aname, flags, &path_data);
60
61     if (!code)
62         afs_get_dentry_ref(&path_data, mnt, dpp);
63
64     return code;
65 }
66
67 static char *
68 afs_getname(char *aname)
69 {
70     int len;
71     char *name = kmem_cache_alloc(names_cachep, GFP_KERNEL);
72
73     if (!name)
74         return ERR_PTR(-ENOMEM);
75
76     len = strncpy_from_user(name, aname, PATH_MAX);
77     if (len < 0)
78         goto error;
79     if (len >= PATH_MAX) {
80         len = -ENAMETOOLONG;
81         goto error;
82     }
83     return name;
84
85 error:
86     kmem_cache_free(names_cachep, name);
87     return ERR_PTR(len);
88 }
89
90 static void
91 afs_putname(char *name)
92 {
93     kmem_cache_free(names_cachep, name);
94 }
95
96 int
97 osi_lookupname(char *aname, uio_seg_t seg, int followlink,
98                struct dentry **dpp)
99 {
100     int code;
101     char *name;
102
103     if (seg == AFS_UIOUSER) {
104         name = afs_getname(aname);
105         if (IS_ERR(name))
106             return -PTR_ERR(name);
107     } else {
108         name = aname;
109     }
110     code = osi_lookupname_internal(name, followlink, NULL, dpp);
111     if (seg == AFS_UIOUSER) {
112         afs_putname(name);
113     }
114     return code;
115 }
116
117 int osi_abspath(char *aname, char *buf, int buflen,
118                 int followlink, char **pathp)
119 {
120     struct dentry *dp = NULL;
121     struct vfsmount *mnt = NULL;
122     char *name, *path;
123     int code;
124
125     name = afs_getname(aname);
126     if (IS_ERR(name))
127         return -PTR_ERR(name);
128     code = osi_lookupname_internal(name, followlink, &mnt, &dp);
129     if (!code) {
130 #if defined(D_PATH_TAKES_STRUCT_PATH)
131         afs_linux_path_t p = { .mnt = mnt, .dentry = dp };
132         path = d_path(&p, buf, buflen);
133 #else
134         path = d_path(dp, mnt, buf, buflen);
135 #endif
136
137         if (IS_ERR(path)) {
138             code = -PTR_ERR(path);
139         } else {
140             *pathp = path;
141         }
142
143         dput(dp);
144         mntput(mnt);
145     }
146
147     afs_putname(name);
148     return code;
149 }
150
151
152 /* This could use some work, and support on more platforms. */
153 int afs_thread_wrapper(void *rock)
154 {
155     void (*proc)(void) = rock;
156     __module_get(THIS_MODULE);
157     AFS_GLOCK();
158     (*proc)();
159     AFS_GUNLOCK();
160     module_put(THIS_MODULE);
161     return 0;
162 }
163
164 void afs_start_thread(void (*proc)(void), char *name)
165 {
166     kthread_run(afs_thread_wrapper, proc, "%s", name);
167 }