1/*
| 1/*
|
2 * Copyright (c) 1995 - 2000, 2002 Kungliga Tekniska H�gskolan
| 2 * Copyright (c) 1995 - 2000, 2002, 2004 Kungliga Tekniska H�gskolan
|
3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#include "kafs_locl.h" 35
| 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#include "kafs_locl.h" 35
|
36RCSID("$Id: afssys.c,v 1.69 2003/03/18 04:18:45 lha Exp $");
| 36RCSID("$Id: afssys.c,v 1.69.2.2 2004/06/22 14:29:48 lha Exp $");
|
37
| 37
|
| 38struct procdata { 39 unsigned long param4; 40 unsigned long param3; 41 unsigned long param2; 42 unsigned long param1; 43 unsigned long syscall; 44}; 45#define VIOC_SYSCALL _IOW('C', 1, void *) 46 47
|
38int _kafs_debug; /* this should be done in a better way */ 39 40#define NO_ENTRY_POINT 0 41#define SINGLE_ENTRY_POINT 1 42#define MULTIPLE_ENTRY_POINT 2 43#define SINGLE_ENTRY_POINT2 3 44#define SINGLE_ENTRY_POINT3 4
| 48int _kafs_debug; /* this should be done in a better way */ 49 50#define NO_ENTRY_POINT 0 51#define SINGLE_ENTRY_POINT 1 52#define MULTIPLE_ENTRY_POINT 2 53#define SINGLE_ENTRY_POINT2 3 54#define SINGLE_ENTRY_POINT3 4
|
45#define AIX_ENTRY_POINTS 5 46#define UNKNOWN_ENTRY_POINT 6
| 55#define LINUX_PROC_POINT 5 56#define AIX_ENTRY_POINTS 6 57#define UNKNOWN_ENTRY_POINT 7
|
47static int afs_entry_point = UNKNOWN_ENTRY_POINT; 48static int afs_syscalls[2];
| 58static int afs_entry_point = UNKNOWN_ENTRY_POINT; 59static int afs_syscalls[2];
|
| 60static char *afs_procpath;
|
49 50/* Magic to get AIX syscalls to work */ 51#ifdef _AIX 52 53static int (*Pioctl)(char*, int, struct ViceIoctl*, int); 54static int (*Setpag)(void); 55 56#include "dlfcn.h" 57 58/* 59 * 60 */ 61 62static int 63try_aix(void) 64{ 65#ifdef STATIC_AFS_SYSCALLS 66 Pioctl = aix_pioctl; 67 Setpag = aix_setpag; 68#else 69 void *ptr; 70 char path[MaxPathLen], *p; 71 /* 72 * If we are root or running setuid don't trust AFSLIBPATH! 73 */ 74 if (getuid() != 0 && !issuid() && (p = getenv("AFSLIBPATH")) != NULL) 75 strlcpy(path, p, sizeof(path)); 76 else 77 snprintf(path, sizeof(path), "%s/afslib.so", LIBDIR); 78 79 ptr = dlopen(path, RTLD_NOW); 80 if(ptr == NULL) { 81 if(_kafs_debug) { 82 if(errno == ENOEXEC && (p = dlerror()) != NULL) 83 fprintf(stderr, "dlopen(%s): %s\n", path, p); 84 else if (errno != ENOENT) 85 fprintf(stderr, "dlopen(%s): %s\n", path, strerror(errno)); 86 } 87 return 1; 88 } 89 Setpag = (int (*)(void))dlsym(ptr, "aix_setpag"); 90 Pioctl = (int (*)(char*, int, 91 struct ViceIoctl*, int))dlsym(ptr, "aix_pioctl"); 92#endif 93 afs_entry_point = AIX_ENTRY_POINTS; 94 return 0; 95} 96#endif /* _AIX */ 97 98/* 99 * This probably only works under Solaris and could get confused if 100 * there's a /etc/name_to_sysnum file. 101 */ 102 103#define _PATH_ETC_NAME_TO_SYSNUM "/etc/name_to_sysnum" 104 105static int 106map_syscall_name_to_number (const char *str, int *res) 107{ 108 FILE *f; 109 char buf[256]; 110 size_t str_len = strlen (str); 111 112 f = fopen (_PATH_ETC_NAME_TO_SYSNUM, "r"); 113 if (f == NULL) 114 return -1; 115 while (fgets (buf, sizeof(buf), f) != NULL) { 116 if (buf[0] == '#') 117 continue; 118 119 if (strncmp (str, buf, str_len) == 0) { 120 char *begptr = buf + str_len; 121 char *endptr; 122 long val = strtol (begptr, &endptr, 0); 123 124 if (val != 0 && endptr != begptr) { 125 fclose (f); 126 *res = val; 127 return 0; 128 } 129 } 130 } 131 fclose (f); 132 return -1; 133} 134
| 61 62/* Magic to get AIX syscalls to work */ 63#ifdef _AIX 64 65static int (*Pioctl)(char*, int, struct ViceIoctl*, int); 66static int (*Setpag)(void); 67 68#include "dlfcn.h" 69 70/* 71 * 72 */ 73 74static int 75try_aix(void) 76{ 77#ifdef STATIC_AFS_SYSCALLS 78 Pioctl = aix_pioctl; 79 Setpag = aix_setpag; 80#else 81 void *ptr; 82 char path[MaxPathLen], *p; 83 /* 84 * If we are root or running setuid don't trust AFSLIBPATH! 85 */ 86 if (getuid() != 0 && !issuid() && (p = getenv("AFSLIBPATH")) != NULL) 87 strlcpy(path, p, sizeof(path)); 88 else 89 snprintf(path, sizeof(path), "%s/afslib.so", LIBDIR); 90 91 ptr = dlopen(path, RTLD_NOW); 92 if(ptr == NULL) { 93 if(_kafs_debug) { 94 if(errno == ENOEXEC && (p = dlerror()) != NULL) 95 fprintf(stderr, "dlopen(%s): %s\n", path, p); 96 else if (errno != ENOENT) 97 fprintf(stderr, "dlopen(%s): %s\n", path, strerror(errno)); 98 } 99 return 1; 100 } 101 Setpag = (int (*)(void))dlsym(ptr, "aix_setpag"); 102 Pioctl = (int (*)(char*, int, 103 struct ViceIoctl*, int))dlsym(ptr, "aix_pioctl"); 104#endif 105 afs_entry_point = AIX_ENTRY_POINTS; 106 return 0; 107} 108#endif /* _AIX */ 109 110/* 111 * This probably only works under Solaris and could get confused if 112 * there's a /etc/name_to_sysnum file. 113 */ 114 115#define _PATH_ETC_NAME_TO_SYSNUM "/etc/name_to_sysnum" 116 117static int 118map_syscall_name_to_number (const char *str, int *res) 119{ 120 FILE *f; 121 char buf[256]; 122 size_t str_len = strlen (str); 123 124 f = fopen (_PATH_ETC_NAME_TO_SYSNUM, "r"); 125 if (f == NULL) 126 return -1; 127 while (fgets (buf, sizeof(buf), f) != NULL) { 128 if (buf[0] == '#') 129 continue; 130 131 if (strncmp (str, buf, str_len) == 0) { 132 char *begptr = buf + str_len; 133 char *endptr; 134 long val = strtol (begptr, &endptr, 0); 135 136 if (val != 0 && endptr != begptr) { 137 fclose (f); 138 *res = val; 139 return 0; 140 } 141 } 142 } 143 fclose (f); 144 return -1; 145} 146
|
| 147static int 148try_proc(const char *path) 149{ 150 int fd; 151 fd = open(path, O_RDWR); 152 if (fd < 0) 153 return 1; 154 close(fd); 155 afs_procpath = strdup(path); 156 if (afs_procpath == NULL) 157 return 1; 158 afs_entry_point = LINUX_PROC_POINT; 159 return 0; 160} 161 162static int 163do_proc(struct procdata *data) 164{ 165 int fd, ret, saved_errno; 166 fd = open(afs_procpath, O_RDWR); 167 if (fd < 0) { 168 errno = EINVAL; 169 return -1; 170 } 171 ret = ioctl(fd, VIOC_SYSCALL, data); 172 saved_errno = errno; 173 close(fd); 174 errno = saved_errno; 175 return ret; 176} 177
|
135int 136k_pioctl(char *a_path, 137 int o_opcode, 138 struct ViceIoctl *a_paramsP, 139 int a_followSymlinks) 140{ 141#ifndef NO_AFS 142 switch(afs_entry_point){ 143#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3) 144 case SINGLE_ENTRY_POINT: 145 case SINGLE_ENTRY_POINT2: 146 case SINGLE_ENTRY_POINT3: 147 return syscall(afs_syscalls[0], AFSCALL_PIOCTL, 148 a_path, o_opcode, a_paramsP, a_followSymlinks); 149#endif 150#if defined(AFS_PIOCTL) 151 case MULTIPLE_ENTRY_POINT: 152 return syscall(afs_syscalls[0], 153 a_path, o_opcode, a_paramsP, a_followSymlinks); 154#endif
| 178int 179k_pioctl(char *a_path, 180 int o_opcode, 181 struct ViceIoctl *a_paramsP, 182 int a_followSymlinks) 183{ 184#ifndef NO_AFS 185 switch(afs_entry_point){ 186#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3) 187 case SINGLE_ENTRY_POINT: 188 case SINGLE_ENTRY_POINT2: 189 case SINGLE_ENTRY_POINT3: 190 return syscall(afs_syscalls[0], AFSCALL_PIOCTL, 191 a_path, o_opcode, a_paramsP, a_followSymlinks); 192#endif 193#if defined(AFS_PIOCTL) 194 case MULTIPLE_ENTRY_POINT: 195 return syscall(afs_syscalls[0], 196 a_path, o_opcode, a_paramsP, a_followSymlinks); 197#endif
|
| 198 case LINUX_PROC_POINT: { 199 struct procdata data = { 0, 0, 0, 0, AFSCALL_PIOCTL }; 200 data.param1 = (unsigned long)a_path; 201 data.param2 = (unsigned long)o_opcode; 202 data.param3 = (unsigned long)a_paramsP; 203 data.param4 = (unsigned long)a_followSymlinks; 204 return do_proc(&data); 205 }
|
155#ifdef _AIX 156 case AIX_ENTRY_POINTS: 157 return Pioctl(a_path, o_opcode, a_paramsP, a_followSymlinks); 158#endif
| 206#ifdef _AIX 207 case AIX_ENTRY_POINTS: 208 return Pioctl(a_path, o_opcode, a_paramsP, a_followSymlinks); 209#endif
|
159 } 160
| 210 }
|
161 errno = ENOSYS; 162#ifdef SIGSYS 163 kill(getpid(), SIGSYS); /* You lose! */ 164#endif 165#endif /* NO_AFS */ 166 return -1; 167} 168 169int 170k_afs_cell_of_file(const char *path, char *cell, int len) 171{ 172 struct ViceIoctl parms; 173 parms.in = NULL; 174 parms.in_size = 0; 175 parms.out = cell; 176 parms.out_size = len; 177 return k_pioctl((char*)path, VIOC_FILE_CELL_NAME, &parms, 1); 178} 179 180int 181k_unlog(void) 182{ 183 struct ViceIoctl parms; 184 memset(&parms, 0, sizeof(parms)); 185 return k_pioctl(0, VIOCUNLOG, &parms, 0); 186} 187 188int 189k_setpag(void) 190{ 191#ifndef NO_AFS 192 switch(afs_entry_point){ 193#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3) 194 case SINGLE_ENTRY_POINT: 195 case SINGLE_ENTRY_POINT2: 196 case SINGLE_ENTRY_POINT3: 197 return syscall(afs_syscalls[0], AFSCALL_SETPAG); 198#endif 199#if defined(AFS_PIOCTL) 200 case MULTIPLE_ENTRY_POINT: 201 return syscall(afs_syscalls[1]); 202#endif
| 211 errno = ENOSYS; 212#ifdef SIGSYS 213 kill(getpid(), SIGSYS); /* You lose! */ 214#endif 215#endif /* NO_AFS */ 216 return -1; 217} 218 219int 220k_afs_cell_of_file(const char *path, char *cell, int len) 221{ 222 struct ViceIoctl parms; 223 parms.in = NULL; 224 parms.in_size = 0; 225 parms.out = cell; 226 parms.out_size = len; 227 return k_pioctl((char*)path, VIOC_FILE_CELL_NAME, &parms, 1); 228} 229 230int 231k_unlog(void) 232{ 233 struct ViceIoctl parms; 234 memset(&parms, 0, sizeof(parms)); 235 return k_pioctl(0, VIOCUNLOG, &parms, 0); 236} 237 238int 239k_setpag(void) 240{ 241#ifndef NO_AFS 242 switch(afs_entry_point){ 243#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3) 244 case SINGLE_ENTRY_POINT: 245 case SINGLE_ENTRY_POINT2: 246 case SINGLE_ENTRY_POINT3: 247 return syscall(afs_syscalls[0], AFSCALL_SETPAG); 248#endif 249#if defined(AFS_PIOCTL) 250 case MULTIPLE_ENTRY_POINT: 251 return syscall(afs_syscalls[1]); 252#endif
|
| 253 case LINUX_PROC_POINT: { 254 struct procdata data = { 0, 0, 0, 0, AFSCALL_SETPAG }; 255 return do_proc(&data); 256 }
|
203#ifdef _AIX 204 case AIX_ENTRY_POINTS: 205 return Setpag(); 206#endif 207 } 208 209 errno = ENOSYS; 210#ifdef SIGSYS 211 kill(getpid(), SIGSYS); /* You lose! */ 212#endif 213#endif /* NO_AFS */ 214 return -1; 215} 216 217static jmp_buf catch_SIGSYS; 218 219#ifdef SIGSYS 220 221static RETSIGTYPE 222SIGSYS_handler(int sig) 223{ 224 errno = 0; 225 signal(SIGSYS, SIGSYS_handler); /* Need to reinstall handler on SYSV */ 226 longjmp(catch_SIGSYS, 1); 227} 228 229#endif 230 231/* 232 * Try to see if `syscall' is a pioctl. Return 0 iff succesful. 233 */ 234 235#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3) 236static int 237try_one (int syscall_num) 238{ 239 struct ViceIoctl parms; 240 memset(&parms, 0, sizeof(parms)); 241 242 if (setjmp(catch_SIGSYS) == 0) { 243 syscall(syscall_num, AFSCALL_PIOCTL, 244 0, VIOCSETTOK, &parms, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 245 if (errno == EINVAL) { 246 afs_entry_point = SINGLE_ENTRY_POINT; 247 afs_syscalls[0] = syscall_num; 248 return 0; 249 } 250 } 251 return 1; 252} 253#endif 254 255/* 256 * Try to see if `syscall_pioctl' is a pioctl syscall. Return 0 iff 257 * succesful. 258 * 259 */ 260 261#ifdef AFS_PIOCTL 262static int 263try_two (int syscall_pioctl, int syscall_setpag) 264{ 265 struct ViceIoctl parms; 266 memset(&parms, 0, sizeof(parms)); 267 268 if (setjmp(catch_SIGSYS) == 0) { 269 syscall(syscall_pioctl, 270 0, VIOCSETTOK, &parms, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 271 if (errno == EINVAL) { 272 afs_entry_point = MULTIPLE_ENTRY_POINT; 273 afs_syscalls[0] = syscall_pioctl; 274 afs_syscalls[1] = syscall_setpag; 275 return 0; 276 } 277 } 278 return 1; 279} 280#endif 281 282int 283k_hasafs(void) 284{ 285#if !defined(NO_AFS) && defined(SIGSYS) 286 RETSIGTYPE (*saved_func)(int); 287#endif 288 int saved_errno; 289 char *env = getenv ("AFS_SYSCALL"); 290 291 /* 292 * Already checked presence of AFS syscalls? 293 */ 294 if (afs_entry_point != UNKNOWN_ENTRY_POINT) 295 return afs_entry_point != NO_ENTRY_POINT; 296 297 /* 298 * Probe kernel for AFS specific syscalls, 299 * they (currently) come in two flavors. 300 * If the syscall is absent we recive a SIGSYS. 301 */ 302 afs_entry_point = NO_ENTRY_POINT; 303 304 saved_errno = errno; 305#ifndef NO_AFS 306#ifdef SIGSYS 307 saved_func = signal(SIGSYS, SIGSYS_handler); 308#endif 309 310#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3) 311 { 312 int tmp; 313 314 if (env != NULL) { 315 if (sscanf (env, "%d", &tmp) == 1) { 316 if (try_one (tmp) == 0) 317 goto done; 318 } else { 319 char *end = NULL; 320 char *p; 321 char *s = strdup (env); 322 323 if (s != NULL) { 324 for (p = strtok_r (s, ",", &end); 325 p != NULL; 326 p = strtok_r (NULL, ",", &end)) { 327 if (map_syscall_name_to_number (p, &tmp) == 0) 328 if (try_one (tmp) == 0) { 329 free (s); 330 goto done; 331 } 332 } 333 free (s); 334 } 335 } 336 } 337 } 338#endif /* AFS_SYSCALL || AFS_SYSCALL2 || AFS_SYSCALL3 */ 339 340#ifdef AFS_SYSCALL 341 if (try_one (AFS_SYSCALL) == 0) 342 goto done; 343#endif /* AFS_SYSCALL */ 344 345#ifdef AFS_PIOCTL 346 { 347 int tmp[2]; 348 349 if (env != NULL && sscanf (env, "%d%d", &tmp[0], &tmp[1]) == 2) 350 if (try_two (tmp[0], tmp[1]) == 2) 351 goto done; 352 } 353#endif /* AFS_PIOCTL */ 354 355#ifdef AFS_PIOCTL 356 if (try_two (AFS_PIOCTL, AFS_SETPAG) == 0) 357 goto done; 358#endif /* AFS_PIOCTL */ 359 360#ifdef AFS_SYSCALL2 361 if (try_one (AFS_SYSCALL2) == 0) 362 goto done; 363#endif /* AFS_SYSCALL2 */ 364 365#ifdef AFS_SYSCALL3 366 if (try_one (AFS_SYSCALL3) == 0) 367 goto done; 368#endif /* AFS_SYSCALL3 */ 369 370#ifdef _AIX 371#if 0 372 if (env != NULL) { 373 char *pos = NULL; 374 char *pioctl_name; 375 char *setpag_name; 376 377 pioctl_name = strtok_r (env, ", \t", &pos); 378 if (pioctl_name != NULL) { 379 setpag_name = strtok_r (NULL, ", \t", &pos); 380 if (setpag_name != NULL) 381 if (try_aix (pioctl_name, setpag_name) == 0) 382 goto done; 383 } 384 } 385#endif 386 387 if(try_aix() == 0) 388 goto done; 389#endif 390
| 257#ifdef _AIX 258 case AIX_ENTRY_POINTS: 259 return Setpag(); 260#endif 261 } 262 263 errno = ENOSYS; 264#ifdef SIGSYS 265 kill(getpid(), SIGSYS); /* You lose! */ 266#endif 267#endif /* NO_AFS */ 268 return -1; 269} 270 271static jmp_buf catch_SIGSYS; 272 273#ifdef SIGSYS 274 275static RETSIGTYPE 276SIGSYS_handler(int sig) 277{ 278 errno = 0; 279 signal(SIGSYS, SIGSYS_handler); /* Need to reinstall handler on SYSV */ 280 longjmp(catch_SIGSYS, 1); 281} 282 283#endif 284 285/* 286 * Try to see if `syscall' is a pioctl. Return 0 iff succesful. 287 */ 288 289#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3) 290static int 291try_one (int syscall_num) 292{ 293 struct ViceIoctl parms; 294 memset(&parms, 0, sizeof(parms)); 295 296 if (setjmp(catch_SIGSYS) == 0) { 297 syscall(syscall_num, AFSCALL_PIOCTL, 298 0, VIOCSETTOK, &parms, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 299 if (errno == EINVAL) { 300 afs_entry_point = SINGLE_ENTRY_POINT; 301 afs_syscalls[0] = syscall_num; 302 return 0; 303 } 304 } 305 return 1; 306} 307#endif 308 309/* 310 * Try to see if `syscall_pioctl' is a pioctl syscall. Return 0 iff 311 * succesful. 312 * 313 */ 314 315#ifdef AFS_PIOCTL 316static int 317try_two (int syscall_pioctl, int syscall_setpag) 318{ 319 struct ViceIoctl parms; 320 memset(&parms, 0, sizeof(parms)); 321 322 if (setjmp(catch_SIGSYS) == 0) { 323 syscall(syscall_pioctl, 324 0, VIOCSETTOK, &parms, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 325 if (errno == EINVAL) { 326 afs_entry_point = MULTIPLE_ENTRY_POINT; 327 afs_syscalls[0] = syscall_pioctl; 328 afs_syscalls[1] = syscall_setpag; 329 return 0; 330 } 331 } 332 return 1; 333} 334#endif 335 336int 337k_hasafs(void) 338{ 339#if !defined(NO_AFS) && defined(SIGSYS) 340 RETSIGTYPE (*saved_func)(int); 341#endif 342 int saved_errno; 343 char *env = getenv ("AFS_SYSCALL"); 344 345 /* 346 * Already checked presence of AFS syscalls? 347 */ 348 if (afs_entry_point != UNKNOWN_ENTRY_POINT) 349 return afs_entry_point != NO_ENTRY_POINT; 350 351 /* 352 * Probe kernel for AFS specific syscalls, 353 * they (currently) come in two flavors. 354 * If the syscall is absent we recive a SIGSYS. 355 */ 356 afs_entry_point = NO_ENTRY_POINT; 357 358 saved_errno = errno; 359#ifndef NO_AFS 360#ifdef SIGSYS 361 saved_func = signal(SIGSYS, SIGSYS_handler); 362#endif 363 364#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3) 365 { 366 int tmp; 367 368 if (env != NULL) { 369 if (sscanf (env, "%d", &tmp) == 1) { 370 if (try_one (tmp) == 0) 371 goto done; 372 } else { 373 char *end = NULL; 374 char *p; 375 char *s = strdup (env); 376 377 if (s != NULL) { 378 for (p = strtok_r (s, ",", &end); 379 p != NULL; 380 p = strtok_r (NULL, ",", &end)) { 381 if (map_syscall_name_to_number (p, &tmp) == 0) 382 if (try_one (tmp) == 0) { 383 free (s); 384 goto done; 385 } 386 } 387 free (s); 388 } 389 } 390 } 391 } 392#endif /* AFS_SYSCALL || AFS_SYSCALL2 || AFS_SYSCALL3 */ 393 394#ifdef AFS_SYSCALL 395 if (try_one (AFS_SYSCALL) == 0) 396 goto done; 397#endif /* AFS_SYSCALL */ 398 399#ifdef AFS_PIOCTL 400 { 401 int tmp[2]; 402 403 if (env != NULL && sscanf (env, "%d%d", &tmp[0], &tmp[1]) == 2) 404 if (try_two (tmp[0], tmp[1]) == 2) 405 goto done; 406 } 407#endif /* AFS_PIOCTL */ 408 409#ifdef AFS_PIOCTL 410 if (try_two (AFS_PIOCTL, AFS_SETPAG) == 0) 411 goto done; 412#endif /* AFS_PIOCTL */ 413 414#ifdef AFS_SYSCALL2 415 if (try_one (AFS_SYSCALL2) == 0) 416 goto done; 417#endif /* AFS_SYSCALL2 */ 418 419#ifdef AFS_SYSCALL3 420 if (try_one (AFS_SYSCALL3) == 0) 421 goto done; 422#endif /* AFS_SYSCALL3 */ 423 424#ifdef _AIX 425#if 0 426 if (env != NULL) { 427 char *pos = NULL; 428 char *pioctl_name; 429 char *setpag_name; 430 431 pioctl_name = strtok_r (env, ", \t", &pos); 432 if (pioctl_name != NULL) { 433 setpag_name = strtok_r (NULL, ", \t", &pos); 434 if (setpag_name != NULL) 435 if (try_aix (pioctl_name, setpag_name) == 0) 436 goto done; 437 } 438 } 439#endif 440 441 if(try_aix() == 0) 442 goto done; 443#endif 444
|
| 445 if (try_proc("/proc/fs/openafs/afs_ioctl") == 0) 446 goto done; 447 if (try_proc("/proc/fs/nnpfs/afs_ioctl") == 0) 448 goto done; 449 if (env && try_proc(env) == 0) 450 goto done; 451
|
391done: 392#ifdef SIGSYS 393 signal(SIGSYS, saved_func); 394#endif 395#endif /* NO_AFS */ 396 errno = saved_errno; 397 return afs_entry_point != NO_ENTRY_POINT; 398}
| 452done: 453#ifdef SIGSYS 454 signal(SIGSYS, saved_func); 455#endif 456#endif /* NO_AFS */ 457 errno = saved_errno; 458 return afs_entry_point != NO_ENTRY_POINT; 459}
|