diff --git a/lib/kafs/afssys.c b/lib/kafs/afssys.c index 8156a5c30..151d4eabf 100644 --- a/lib/kafs/afssys.c +++ b/lib/kafs/afssys.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995 - 2000, 2002, 2004 Kungliga Tekniska Högskolan + * Copyright (c) 1995 - 2000, 2002, 2004, 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -42,11 +42,24 @@ struct procdata { unsigned long param1; unsigned long syscall; }; -#define VIOC_SYSCALL _IOW('C', 1, void *) +#define VIOC_SYSCALL_PROC _IOW('C', 1, void *) + +struct devdata { + unsigned long syscall; + unsigned long param1; + unsigned long param2; + unsigned long param3; + unsigned long param4; + unsigned long param5; + unsigned long param6; + unsigned long retval; +}; +#define VIOC_SYSCALL_DEV _IOWR('C', 2, struct devdata) int _kafs_debug; /* this should be done in a better way */ +#define UNKNOWN_ENTRY_POINT (-1) #define NO_ENTRY_POINT 0 #define SINGLE_ENTRY_POINT 1 #define MULTIPLE_ENTRY_POINT 2 @@ -54,10 +67,11 @@ int _kafs_debug; /* this should be done in a better way */ #define SINGLE_ENTRY_POINT3 4 #define LINUX_PROC_POINT 5 #define AIX_ENTRY_POINTS 6 -#define UNKNOWN_ENTRY_POINT 7 +#define MACOS_DEV_POINT 7 + static int afs_entry_point = UNKNOWN_ENTRY_POINT; static int afs_syscalls[2]; -static char *afs_procpath; +static char *afs_ioctlpath; /* Magic to get AIX syscalls to work */ #ifdef _AIX @@ -148,30 +162,30 @@ map_syscall_name_to_number (const char *str, int *res) #endif static int -try_proc(const char *path) +try_ioctlpath(const char *path, int entrypoint) { int fd; fd = open(path, O_RDWR); if (fd < 0) return 1; close(fd); - afs_procpath = strdup(path); - if (afs_procpath == NULL) + afs_ioctlpath = strdup(path); + if (afs_ioctlpath == NULL) return 1; - afs_entry_point = LINUX_PROC_POINT; + afs_entry_point = entrypoint; return 0; } static int -do_proc(struct procdata *data) +do_ioctl(void *data, unsigned long cmd) { int fd, ret, saved_errno; - fd = open(afs_procpath, O_RDWR); + fd = open(afs_ioctlpath, O_RDWR); if (fd < 0) { errno = EINVAL; return -1; } - ret = ioctl(fd, VIOC_SYSCALL, data); + ret = ioctl(fd, cmd, data); saved_errno = errno; close(fd); errno = saved_errno; @@ -204,7 +218,22 @@ k_pioctl(char *a_path, data.param2 = (unsigned long)o_opcode; data.param3 = (unsigned long)a_paramsP; data.param4 = (unsigned long)a_followSymlinks; - return do_proc(&data); + return do_ioctl(&data, VIOC_SYSCALL_PROC); + } + case MACOS_DEV_POINT: { + struct devdata data = { AFSCALL_PIOCTL, 0, 0, 0, 0, 0, 0, 0 }; + int ret; + + data.param1 = (unsigned long)a_path; + data.param2 = (unsigned long)o_opcode; + data.param3 = (unsigned long)a_paramsP; + data.param4 = (unsigned long)a_followSymlinks; + + ret = do_ioctl(&data, VIOC_SYSCALL_DEV); + if (ret) + return ret; + + return data.retval; } #ifdef _AIX case AIX_ENTRY_POINTS: @@ -255,8 +284,15 @@ k_setpag(void) #endif case LINUX_PROC_POINT: { struct procdata data = { 0, 0, 0, 0, AFSCALL_SETPAG }; - return do_proc(&data); + return do_ioctl(&data, VIOC_SYSCALL_PROC); } + case MACOS_DEV_POINT: { + struct devdata data = { AFSCALL_SETPAG, 0, 0, 0, 0, 0, 0, 0 }; + int ret = do_ioctl(&data, VIOC_SYSCALL_DEV); + if (ret) + return ret; + return data.retval; + } #ifdef _AIX case AIX_ENTRY_POINTS: return Setpag(); @@ -343,7 +379,10 @@ k_hasafs(void) RETSIGTYPE (*saved_func)(int); #endif int saved_errno; - char *env = getenv ("AFS_SYSCALL"); + char *env = NULL; + + if (!issuid()) + env = getenv ("AFS_SYSCALL"); /* * Already checked presence of AFS syscalls? @@ -364,6 +403,13 @@ k_hasafs(void) saved_func = signal(SIGSYS, SIGSYS_handler); #endif + if (env && (strncmp("/dev/", env, 5) == 0 || strncmp("/proc/", env, 6) == 0)) { + if (try_ioctlpath(env, LINUX_PROC_POINT) == 0) + goto done; + if (try_ioctlpath(env, MACOS_DEV_POINT) == 0) + goto done; + } + #if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3) { int tmp; @@ -445,11 +491,14 @@ k_hasafs(void) goto done; #endif - if (try_proc("/proc/fs/openafs/afs_ioctl") == 0) + if (try_ioctlpath("/proc/fs/openafs/afs_ioctl", LINUX_PROC_POINT) == 0) goto done; - if (try_proc("/proc/fs/nnpfs/afs_ioctl") == 0) + if (try_ioctlpath("/proc/fs/nnpfs/afs_ioctl", LINUX_PROC_POINT) == 0) goto done; - if (env && try_proc(env) == 0) + + if (try_ioctlpath("/dev/openafs_ioctl", MACOS_DEV_POINT) == 0) + goto done; + if (try_ioctlpath("/dev/nnpfs_ioctl", MACOS_DEV_POINT) == 0) goto done; done: