Add AFS::ukernel libuafs perl bindings

Add the SWIG-generated AFS::ukernel perl module, which provides perl
bindings to libuafs calls.

Change-Id: I5ce480944a8c97cbca72c80e79fc40c0edb0962f
Reviewed-on: http://gerrit.openafs.org/2048
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>
This commit is contained in:
Andrew Deason 2009-08-14 16:32:54 -05:00 committed by Derrick Brashear
parent bbd505a8e1
commit 3505c444f6
4 changed files with 328 additions and 8 deletions

View File

@ -1680,6 +1680,7 @@ AC_SUBST(DOCBOOK_STYLESHEETS)
OPENAFS_OSCONF
OPENAFS_FUSE
OPENAFS_SWIG
TOP_SRCDIR="${srcdir}/src"
dnl

11
src/cf/swig.m4 Normal file
View File

@ -0,0 +1,11 @@
dnl SWIG Autoconf glue. Build with SWIG-derived language bindings if SWIG
dnl is available; if it's not, don't build the extra language bindings.
AC_DEFUN([OPENAFS_SWIG],
[AC_CHECK_PROG([SWIG], [swig], [swig])
LIBUAFS_BUILD_PERL=
if test "x$SWIG" = "xswig" ; then
LIBUAFS_BUILD_PERL=LIBUAFS_BUILD_PERL
fi
AC_SUBST(LIBUAFS_BUILD_PERL)
])

View File

@ -14,11 +14,16 @@ UOBJ =../UAFS
PICOBJ =../UAFS.pic
JUAFS =../JUAFS
WEBOBJ=../AFSWEB
PERLUAFS = PERLUAFS
AFS =../afs
RX =../rx
AFSINT=../afsint
LIB =../lib
NS_INCL =SRC/../afsweb/netscape_includes
SWIG_PERL_CFLAGS = -fPIC $(shell perl -MExtUtils::Embed -e ccopts)
SWIG_PERL_LDFLAGS = -fPIC $(shell perl -MExtUtils::Embed -e ldopts)
SWIG = @SWIG@
LIBUAFS_BUILD_PERL = @LIBUAFS_BUILD_PERL@
TOP_OBJ_AUTH = ${TOP_OBJDIR}/src/auth
TOP_OBJ_FSINT = ${TOP_OBJDIR}/src/fsint
@ -58,7 +63,7 @@ COMMON_INCLUDE = -I. -I.. -I../nfs \
# Build rules - CC and CFLAGS are defined in system specific MakefileProtos.
all: ${TOP_LIBDIR}/$(LIBJUAFS) ${TOP_LIBDIR}/$(LIBUAFS) \
${TOP_LIBDIR}/libuafs_pic.a linktest
${TOP_LIBDIR}/libuafs_pic.a linktest @LIBUAFS_BUILD_PERL@
${TOP_LIBDIR}/$(LIBAFSWEB): AFSWEB/$(LIBAFSWEB)
${INSTALL_DATA} $? $@
@ -75,11 +80,17 @@ ${TOP_LIBDIR}/libuafs_pic.a: UAFS.pic/libuafs_pic.a
${TOP_LIBDIR}/$(LIBJUAFS): JUAFS/$(LIBJUAFS)
${INSTALL_DATA} $? $@
${TOP_LIBDIR}/perl/AFS/ukernel.so: PERLUAFS/ukernel.so
${INSTALL_DATA} $? $@
setup_perllib:
${INSTALL} -d ${TOP_LIBDIR}/perl
${INSTALL} -d ${TOP_LIBDIR}/perl/AFS
${TOP_LIBDIR}/perl/AFS/ukernel.pm: PERLUAFS/ukernel.pm
${INSTALL_DATA} $? $@
${TOP_LIBDIR}/perl/ukernel.so: setup_perllib PERLUAFS/ukernel.so
${INSTALL_DATA} PERLUAFS/ukernel.so $@
${TOP_LIBDIR}/perl/AFS/ukernel.pm: setup_perllib PERLUAFS/ukernel.pm
${INSTALL_DATA} PERLUAFS/ukernel.pm $@
LIBUAFS_BUILD_PERL: ${TOP_LIBDIR}/perl/ukernel.so ${TOP_LIBDIR}/perl/AFS/ukernel.pm
webinstall: all \
${TOP_LIBDIR}/$(LIBAFSWEB) \
@ -2007,23 +2018,50 @@ $(JUAFS)/xdr_mem.o: $(TOP_SRC_RX)/xdr_mem.c
$(JUAFS)/xdr_len.o: $(TOP_SRC_RX)/xdr_len.c
$(CRULE1)
$(PERLUAFS)/ukernel.pm: $(PERLUAFS)/ukernel_swig_perl.c
$(PERLUAFS)/ukernel_swig_perl.c: ${srcdir}/ukernel_swig.i
mkdir -p $(PERLUAFS)
$(SWIG) -perl5 -o $@ ${srcdir}/ukernel_swig.i
$(PERLUAFS)/ukernel_swig_perl.o: $(PERLUAFS)/ukernel_swig_perl.c
${CC} -c ${CPPFLAGS} ${UAFS_CFLAGS} $(SWIG_PERL_CFLAGS) \
$(COMMON_INCLUDE) -DUKERNEL $(SHLIB_CFLAGS) -o $@ \
$(PERLUAFS)/ukernel_swig_perl.c
$(PERLUAFS)/ukernel.so: $(PERLUAFS)/ukernel_swig_perl.o UAFS.pic/libuafs_pic.a
${TOP_OBJDIR}/src/config/shlib-build -d $(srcdir) -p -f $@ -- \
$(SWIG_PERL_LDFLAGS) $(LDFLAGS) \
$(PERLUAFS)/ukernel_swig_perl.o \
UAFS.pic/libuafs_pic.a ${TOP_LIBDIR}/libcmd_pic.a \
${TOP_LIBDIR}/libafsutil_pic.a $(LDFLAGS_roken) \
$(LDFLAGS_hcrypto) $(LIB_hcrypto) $(LIB_roken) $(LIB_crypt) \
$(XLIBS)
clean:
-$(RM) -rf UAFS* JUAFS* AFSWEB* nsapi afsd afs afsint config rx
-$(RM) -rf UAFS* JUAFS* AFSWEB* PERLUAFS nsapi afsd afs afsint config rx
-$(RM) -f h net netinet rpc ufs machine inet nfs sys linktest $(AFS_OS_CLEAN)
install: UAFS/$(LIBUAFS) JUAFS/$(LIBJUAFS) UAFS.pic/libuafs_pic.a
install: UAFS/$(LIBUAFS) JUAFS/$(LIBJUAFS) UAFS.pic/libuafs_pic.a \
@LIBUAFS_BUILD_PERL@
${INSTALL} -d ${DESTDIR}${libdir}
${INSTALL_DATA} UAFS/$(LIBUAFS) ${DESTDIR}${libdir}/$(LIBUAFS)
${INSTALL_DATA} JUAFS/$(LIBJUAFS) ${DESTDIR}${libdir}/$(LIBJUAFS)
${INSTALL_DATA} UAFS.pic/libuafs_pic.a ${DESTDIR}${libdir}/libuafs_pic.a
if [ "x$(LIBUAFS_BUILD_PERL)" != "x" ] ; then \
${INSTALL} -d ${DESTDIR}${libdir}/perl; \
${INSTALL} -d ${DESTDIR}${libdir}/perl/AFS; \
${INSTALL_DATA} PERLUAFS/ukernel.so ${DESTDIR}${libdir}/perl/ukernel.so; \
${INSTALL_DATA} PERLUAFS/ukernel.pm ${DESTDIR}${libdir}/perl/AFS/ukernel.pm; \
fi;
dest: $(TOP_INCDIR)/afs/param.h $(TOP_INCDIR)/afs/stds.h \
$(TOP_INCDIR)/afs/afs_sysnames.h \
$(TOP_INCDIR)/afs/afs_stats.h \
$(TOP_SRCDIR)/afs/sysincludes.h \
$(TOP_SRCDIR)/afs/UKERNEL/afs_usrops.h \
UAFS/$(LIBUAFS) JUAFS/$(LIBJUAFS) UAFS.pic/libuafs_pic.a
UAFS/$(LIBUAFS) JUAFS/$(LIBJUAFS) UAFS.pic/libuafs_pic.a \
@LIBUAFS_BUILD_PERL@
${INSTALL} -d ${DEST}/root.perf/include/afs
${INSTALL} -d ${DEST}/root.perf/lib
${INSTALL_DATA} $(TOP_INCDIR)/afs/param.h \
@ -2041,6 +2079,12 @@ dest: $(TOP_INCDIR)/afs/param.h $(TOP_INCDIR)/afs/stds.h \
${INSTALL_DATA} UAFS/$(LIBUAFS) ${DEST}/root.perf/lib/$(LIBUAFS)
${INSTALL_DATA} JUAFS/$(LIBJUAFS) ${DEST}/root.perf/lib/$(LIBJUAFS)
${INSTALL_DATA} UAFS.pic/libuafs_pic.a ${DEST}/root.perf/lib/libuafs_pic.a
if [ "x$(LIBUAFS_BUILD_PERL)" != "x" ] ; then \
${INSTALL} -d ${DEST}/root.perf/lib/perl; \
${INSTALL} -d ${DEST}/root.perf/lib/perl/AFS; \
${INSTALL_DATA} PERLUAFS/ukernel.so ${DEST}/root.perf/lib/perl/ukernel.so; \
${INSTALL_DATA} PERLUAFS/ukernel.pm ${DEST}/root.perf/lib/perl/AFS/ukernel.pm; \
fi;
#
# Common directory and other build targets

264
src/libuafs/ukernel_swig.i Normal file
View File

@ -0,0 +1,264 @@
/*
* Copyright 2010, Sine Nomine Associates.
* 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
*/
/*
* libuafs SWIG interface file
*
* This file specifies the libuafs interfaces for SWIG, which can then be
* used to easily create libuafs bindings to other languages such as Perl.
*
* For each language you want a binding for, there are two typemaps you
* must define for that language, since SWIG does not handle them natively.
* These are the 'in' typemap for READBUF and LENGTH, and the 'argout'
* typemap for READBUF. Search this file for 'perl5' to see existing ones
* for the Perl 5 bindings.
*/
%module "AFS::ukernel"
%{
#include <afsconfig.h>
#include <afs/param.h>
#include <afs/afsutil.h>
#include <afs/sysincludes.h>
#include <afs_usrops.h>
#include <afs/cmd.h>
#include <afs/afs_args.h>
%}
%include "typemaps.i";
%apply long { off_t };
%rename (uafs_ParseArgs) swig_uafs_ParseArgs;
%inline %{
/* SWIG doesn't handle argv-like string arrays too well, so instead have
* a wrapper to convert a single string of all arguments into an argv-like
* array. Conveniently, libcmd can do this.
*
* We could instead do this with SWIG typemaps, but writing this little
* function instead is much more language-neutral. With typemaps, we'd have
* to write the converting code for each target language.
*/
extern int
swig_uafs_ParseArgs(char *line)
{
char *argv[1024];
int argc;
int code;
code = cmd_ParseLine(line, argv, &argc, sizeof(argv)/sizeof(argv[0]));
if (code) {
afs_com_err("AFS::ukernel", code, "parsing line: '%s'", line);
return code;
}
code = uafs_ParseArgs(argc, argv);
cmd_FreeArgv(argv);
return code;
}
%}
extern int uafs_Setup(const char *mount);
extern int uafs_Run(void);
/*
* Define typemaps for binary read buffers. SWIG natively handles
* NUL-terminated strings, but uafs_read could have NULs in the middle of the
* string, so we need these typemaps to pay attention to the string length.
*
* (Reading in a binary buffer from e.g. uafs_write is already handled natively
* by SWIG. Fancy that.)
*/
%typemap(in, numinputs=1, perl5) (char *READBUF, int LENGTH) {
if (!SvIOK($input)) {
SWIG_croak("expected an integer");
}
$2 = SvIV($input);
Newx($1, $2, char);
}
%typemap(argout, numinputs=1, perl5) char *READBUF {
/* some logic here copied from typemaps.i and/or SWIG itself, since I'm not
* a perl dev */
if (argvi >= items) {
EXTEND(sp, 1);
}
/* 'result' is the return value from the actual C function call; we assume
* it is an int that represents how many bytes of data were actually read into
* the buffer if nonnegative */
if (result < 0) {
$result = &PL_sv_undef;
} else {
$result = sv_2mortal(newSVpvn($1, result));
}
Safefree($1);
argvi++;
}
extern int uafs_mkdir(char *path, int mode);
extern int uafs_chdir(char *path);
extern int uafs_open(char *path, int flags, int mode=0);
extern int uafs_creat(char *path, int mode);
extern int uafs_write(int fd, char *STRING, int LENGTH);
extern int uafs_pwrite(int fd, char *STRING, int LENGTH, off_t offset);
extern int uafs_read(int fd, char *READBUF, int LENGTH);
extern int uafs_pread(int fd, char *READBUF, int LENGTH, off_t offset);
extern int uafs_fsync(int fd);
extern int uafs_close(int fd);
%{
#define STAT_TYPE long
#define STAT_ARGS \
STAT_TYPE *adev, \
STAT_TYPE *aino, \
STAT_TYPE *amode, \
STAT_TYPE *anlink, \
STAT_TYPE *auid, \
STAT_TYPE *agid, \
STAT_TYPE *ardev, \
STAT_TYPE *asize, \
STAT_TYPE *aatime, \
STAT_TYPE *amtime, \
STAT_TYPE *actime, \
STAT_TYPE *ablksize, \
STAT_TYPE *ablocks
#define STAT_COPYFROM(st) do { \
*adev = (st).st_dev; \
*aino = (st).st_ino; \
*amode = (st).st_mode; \
*anlink = (st).st_nlink; \
*auid = (st).st_uid; \
*agid = (st).st_gid; \
*ardev = (st).st_rdev; \
*asize = (st).st_size; \
*aatime = (st).st_atime; \
*amtime = (st).st_mtime; \
*actime = (st).st_ctime; \
*ablksize = (st).st_blksize; \
*ablocks = (st).st_blocks; \
} while (0)
int
swig_uafs_stat(char *path, STAT_ARGS)
{
int code;
struct stat st;
code = uafs_stat(path, &st);
if (code == 0) {
STAT_COPYFROM(st);
}
return code;
}
int
swig_uafs_lstat(char *path, STAT_ARGS)
{
int code;
struct stat st;
code = uafs_lstat(path, &st);
if (code == 0) {
STAT_COPYFROM(st);
}
return code;
}
int
swig_uafs_fstat(int fd, STAT_ARGS)
{
int code;
struct stat st;
code = uafs_fstat(fd, &st);
if (code == 0) {
STAT_COPYFROM(st);
}
return code;
}
#undef STAT_TYPE
#undef STAT_ARGS
#undef STAT_COPYFROM
%}
%define STAT_TYPE
long
%enddef
%define STAT_OUT_ARGS
STAT_TYPE *OUTPUT,
STAT_TYPE *OUTPUT,
STAT_TYPE *OUTPUT,
STAT_TYPE *OUTPUT,
STAT_TYPE *OUTPUT,
STAT_TYPE *OUTPUT,
STAT_TYPE *OUTPUT,
STAT_TYPE *OUTPUT,
STAT_TYPE *OUTPUT,
STAT_TYPE *OUTPUT,
STAT_TYPE *OUTPUT,
STAT_TYPE *OUTPUT,
STAT_TYPE *OUTPUT
%enddef
%rename (uafs_stat) swig_uafs_stat;
%rename (uafs_lstat) swig_uafs_lstat;
%rename (uafs_fstat) swig_uafs_fstat;
extern int swig_uafs_stat(char *path, STAT_OUT_ARGS);
extern int swig_uafs_lstat(char *path, STAT_OUT_ARGS);
extern int swig_uafs_fstat(int fd, STAT_OUT_ARGS);
extern int uafs_truncate(char *path, int len);
extern int uafs_ftruncate(int fd, int len);
extern int uafs_lseek(int fd, int offset, int whence);
extern int uafs_chmod(char *path, int mode);
extern int uafs_fchmod(int fd, int mode);
extern int uafs_symlink(char *target, char *source);
extern int uafs_unlink(char *path);
extern int uafs_rmdir(char *path);
extern int uafs_readlink(char *path, char *READBUF, int LENGTH);
extern int uafs_link(char *existing, char *new);
extern int uafs_rename(char *old, char *new);
extern usr_DIR *uafs_opendir(char *path);
%rename (uafs_readdir) swig_uafs_readdir;
%{
/*
* Language-neutral wrapper for uafs_readdir. Since the language won't know
* what to do with a struct usr_dirent, we could either make a SWIG typemap, or
* define a wrapper with multiple return arguments. Making a typemap is
* language-specific, so we define a wrapper, and let the typemaps.i library
* worry about the language-specific parts of getting multiple return values.
*/
char *
swig_uafs_readdir(usr_DIR *dirp, unsigned long *d_ino, unsigned long *d_off, unsigned short *d_reclen)
{
struct usr_dirent *dentry;
dentry = uafs_readdir(dirp);
if (!dentry) {
*d_ino = *d_off = *d_reclen = 0;
return NULL;
}
*d_ino = dentry->d_ino;
*d_off = dentry->d_off;
*d_reclen = dentry->d_reclen;
return strdup(dentry->d_name);
}
%}
extern char * swig_uafs_readdir(usr_DIR *dirp, unsigned long *OUTPUT, unsigned long *OUTPUT, unsigned short *OUTPUT);
extern int uafs_closedir(usr_DIR * dirp);
extern void uafs_SetRxPort(int);
extern void uafs_Shutdown(void);