Add k_haspag to libkopenafs

Add the k_haspag function to libkopenafs, which returns true if the
current process is in a PAG and false otherwise.

The implementation currently duplicates code from the ktc_curpag
function since the latter calls the regular pioctl() interface and
hence introduces an Rx dependency that we're avoiding for libkopenafs.
This should be refactored to avoid the code duplication at some point,
but that will require building a utility library that can be reasonably
linked into libkopenafs and is therefore deferred for future work.

Change-Id: Ib97322ef24dc3a4e48cb45090c516c95b71e9fc7
Reviewed-on: http://gerrit.openafs.org/2041
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>
This commit is contained in:
Russ Allbery 2010-05-26 23:23:10 -05:00 committed by Derrick Brashear
parent e29bd1f8d1
commit 5f2c6bd341
5 changed files with 123 additions and 4 deletions

View File

@ -17,7 +17,7 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
# API version. When something changes, increment as appropriate.
# Ignore at your own risk.
MAJOR = 1
MINOR = 0
MINOR = 1
CC = ${MT_CC}
INCLUDES = -I. -I${srcdir} -I../sys

View File

@ -12,14 +12,23 @@
* included in the libsys code.
*/
#include <sys/param.h>
#include <netinet/in.h>
#include <errno.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdlib.h>
#ifdef AFS_AIX51_ENV
# include <sys/cred.h>
# ifdef HAVE_SYS_PAG_H
# include <sys/pag.h>
# endif
#endif
#include <sys/param.h>
#include <sys/types.h>
#include <unistd.h>
#include <afsconfig.h>
#include <afs/afssyscalls.h>
#include <afs/param.h>
#include <kopenafs.h>
static volatile sig_atomic_t syscall_okay = 1;
@ -87,3 +96,99 @@ k_unlog(void)
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_LINUX26_ENV
int i;
# endif
ngroups = getgroups(0, NULL);
groups = malloc(sizeof(*groups) * ngroups);
if (groups == NULL)
return 0;
ngroups = getgroups(ngroups, groups);
/* Check for AFS_LINUX26_ONEGROUP_ENV PAGs. */
# ifdef AFS_LINUX26_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();
}

View File

@ -37,6 +37,12 @@ int k_hasafs(void);
*/
int k_setpag(void);
/*
* Returns true if the current process is in a PAG and false if it is not or
* if an error was encountered in determining whether it is in a PAG.
*/
int k_haspag(void);
/*
* Remove the tokens in the current PAG. Returns 0 on success, non-zero on
* system call failure.

View File

@ -6,6 +6,7 @@ KOPENAFS_1.0 {
global:
k_hasafs;
k_setpag;
k_haspag;
k_unlog;
k_pioctl;
local:

View File

@ -13,6 +13,9 @@
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <kopenafs.h>
int
main(int argc, char *argv[])
@ -20,9 +23,12 @@ main(int argc, char *argv[])
int status;
if (k_hasafs()) {
printf("%s in a PAG\n", k_haspag() ? "Currently" : "Not currently");
printf("Running k_setpag\n");
status = k_setpag();
printf("Status: %d, errno: %d\n", status, errno);
if (!k_haspag())
printf("Error: not in a PAG after k_setpag()\n");
if (argc > 1) {
argv++;
execvp(argv[0], argv);
@ -30,4 +36,5 @@ main(int argc, char *argv[])
} else {
printf("AFS apparently not running\n");
}
return 0;
}