/* * Copyright 2000, International Business Machines Corporation and others. * All Rights Reserved. * * This software has been released under the terms of the IBM Public * License. For details, see the LICENSE file in the top-level source * directory or online at http://www.openafs.org/dl/license10.html */ /* * Glue code for the kopenafs API. Mostly just wrappers around the functions * included in the libsys code. */ #include #include #include #ifdef AFS_AIX51_ENV # include # ifdef HAVE_SYS_PAG_H # include # endif #endif #include #include static volatile sig_atomic_t syscall_okay = 1; /* Signal handler to catch failed system calls and change the okay flag. */ #ifdef SIGSYS static void sigsys_handler(int s) { syscall_okay = 0; signal(SIGSYS, sigsys_handler); } #endif /* SIGSYS */ int k_hasafs(void) { struct ViceIoctl iob; int okay, saved_errno; void (*saved_func)(int); saved_errno = errno; #ifdef SIGSYS saved_func = signal(SIGSYS, sigsys_handler); #endif iob.in = NULL; iob.in_size = 0; iob.out = NULL; iob.out_size = 0; lpioctl(NULL, VIOCSETTOK, &iob, 0); #ifdef SIGSYS signal(SIGSYS, saved_func); #endif okay = 1; if (!syscall_okay || errno != EINVAL) okay = 0; errno = saved_errno; return okay; } int k_setpag(void) { return lsetpag(); } int k_pioctl(char *path, int cmd, struct ViceIoctl *cmarg, int follow) { return lpioctl(path, cmd, cmarg, follow); } int k_unlog(void) { struct ViceIoctl iob; iob.in = NULL; iob.in_size = 0; iob.out = NULL; iob.out_size = 0; return lpioctl(NULL, VIOCUNLOG, &iob, 0); } /* * If we don't have the VIOC_GETPAG pioctl, we try to determine whether we're * in a PAG by using either a special OS call (AIX 5.2 and later) or by * walking the group list, which works differently for current versions of * Linux. * * These OS differences are encapsulated in the following OS-specific haspag * helper functions. * * This is largely copied from auth/ktc.c and should be merged with that * version, but that version calls through the pioctl() interface right now * and therefore pulls in Rx for NFS translator support. This avoids an Rx * dependency in the standalone libkopenafs interface. */ #if defined(AFS_AIX52_ENV) static int os_haspag(void) { return (getpagvalue("afs") < 0) ? 0 : 1; } #elif defined(AFS_AIX51_ENV) static int os_haspag(void) { return 0; } #else static int os_haspag(void) { int ngroups; gid_t *groups; afs_uint32 g0, g1; afs_uint32 h, l, pag; # ifdef AFS_PAG_ONEGROUP_ENV int i; # endif ngroups = getgroups(0, NULL); groups = malloc(sizeof(*groups) * ngroups); if (groups == NULL) return 0; ngroups = getgroups(ngroups, groups); /* Check for one-group PAGs. */ # ifdef AFS_PAG_ONEGROUP_ENV for (i = 0; i < ngroups; i++) if (((groups[i] >> 24) & 0xff) == 'A') { free(groups); return 1; } # endif /* Check for the PAG group pair. */ if (ngroups < 2) { free(groups); return 0; } g0 = groups[0] & 0xffff; g1 = groups[1] & 0xffff; free(groups); g0 -= 0x3f00; g1 -= 0x3f00; if (g0 < 0xc000 && g1 < 0xc000) { l = ((g0 & 0x3fff) << 14) | (g1 & 0x3fff); h = (g0 >> 14); h = (g1 >> 14) + h + h + h; pag = ((h << 28) | l); if (((pag >> 24) & 0xff) == 'A') return 1; else return 0; } return 0; } #endif /* !AFS_AIX51_ENV */ int k_haspag(void) { int code; struct ViceIoctl iob; afs_uint32 pag; iob.in = NULL; iob.in_size = 0; iob.out = (caddr_t) &pag; iob.out_size = sizeof(afs_uint32); code = lpioctl(NULL, VIOC_GETPAG, &iob, 0); if (code == 0) return pag != (afs_uint32) -1; else return os_haspag(); }