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
# 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} $? $@
${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) \
$(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 \
${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
--- /dev/null
+/*
+ * 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);