Add AFS::ukernel libuafs perl bindings
[openafs.git] / src / libuafs / ukernel_swig.i
1 /*
2  * Copyright 2010, Sine Nomine Associates.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * libuafs SWIG interface file
12  *
13  * This file specifies the libuafs interfaces for SWIG, which can then be
14  * used to easily create libuafs bindings to other languages such as Perl.
15  *
16  * For each language you want a binding for, there are two typemaps you
17  * must define for that language, since SWIG does not handle them natively.
18  * These are the 'in' typemap for READBUF and LENGTH, and the 'argout'
19  * typemap for READBUF. Search this file for 'perl5' to see existing ones
20  * for the Perl 5 bindings.
21  */
22
23 %module "AFS::ukernel"
24
25 %{
26 #include <afsconfig.h>
27 #include <afs/param.h>
28
29 #include <afs/afsutil.h>
30 #include <afs/sysincludes.h>
31 #include <afs_usrops.h>
32 #include <afs/cmd.h>
33 #include <afs/afs_args.h>
34 %}
35
36 %include "typemaps.i";
37
38 %apply long { off_t };
39
40 %rename (uafs_ParseArgs) swig_uafs_ParseArgs;
41 %inline %{
42 /* SWIG doesn't handle argv-like string arrays too well, so instead have
43  * a wrapper to convert a single string of all arguments into an argv-like
44  * array. Conveniently, libcmd can do this.
45  *
46  * We could instead do this with SWIG typemaps, but writing this little
47  * function instead is much more language-neutral. With typemaps, we'd have
48  * to write the converting code for each target language.
49  */
50 extern int
51 swig_uafs_ParseArgs(char *line)
52 {
53     char *argv[1024];
54     int argc;
55     int code;
56
57     code = cmd_ParseLine(line, argv, &argc, sizeof(argv)/sizeof(argv[0]));
58     if (code) {
59         afs_com_err("AFS::ukernel", code, "parsing line: '%s'", line);
60         return code;
61     }
62
63     code = uafs_ParseArgs(argc, argv);
64
65     cmd_FreeArgv(argv);
66
67     return code;
68 }
69 %}
70 extern int uafs_Setup(const char *mount);
71 extern int uafs_Run(void);
72
73 /*
74  * Define typemaps for binary read buffers. SWIG natively handles
75  * NUL-terminated strings, but uafs_read could have NULs in the middle of the
76  * string, so we need these typemaps to pay attention to the string length.
77  *
78  * (Reading in a binary buffer from e.g. uafs_write is already handled natively
79  * by SWIG. Fancy that.)
80  */
81 %typemap(in, numinputs=1, perl5) (char *READBUF, int LENGTH) {
82     if (!SvIOK($input)) {
83         SWIG_croak("expected an integer");
84     }
85     $2 = SvIV($input);
86     Newx($1, $2, char);
87 }
88 %typemap(argout, numinputs=1, perl5) char *READBUF {
89     /* some logic here copied from typemaps.i and/or SWIG itself, since I'm not
90      * a perl dev */
91
92     if (argvi >= items) {
93         EXTEND(sp, 1);
94     }
95
96     /* 'result' is the return value from the actual C function call; we assume
97      * it is an int that represents how many bytes of data were actually read into
98      * the buffer if nonnegative */
99     if (result < 0) {
100         $result = &PL_sv_undef;
101     } else {
102         $result = sv_2mortal(newSVpvn($1, result));
103     }
104
105     Safefree($1);
106     argvi++;
107 }
108
109 extern int uafs_mkdir(char *path, int mode);
110 extern int uafs_chdir(char *path);
111 extern int uafs_open(char *path, int flags, int mode=0);
112 extern int uafs_creat(char *path, int mode);
113 extern int uafs_write(int fd, char *STRING, int LENGTH);
114 extern int uafs_pwrite(int fd, char *STRING, int LENGTH, off_t offset);
115 extern int uafs_read(int fd, char *READBUF, int LENGTH);
116 extern int uafs_pread(int fd, char *READBUF, int LENGTH, off_t offset);
117 extern int uafs_fsync(int fd);
118 extern int uafs_close(int fd);
119
120 %{
121 #define STAT_TYPE long
122 #define STAT_ARGS        \
123     STAT_TYPE *adev,     \
124     STAT_TYPE *aino,     \
125     STAT_TYPE *amode,    \
126     STAT_TYPE *anlink,   \
127     STAT_TYPE *auid,     \
128     STAT_TYPE *agid,     \
129     STAT_TYPE *ardev,    \
130     STAT_TYPE *asize,    \
131     STAT_TYPE *aatime,   \
132     STAT_TYPE *amtime,   \
133     STAT_TYPE *actime,   \
134     STAT_TYPE *ablksize, \
135     STAT_TYPE *ablocks
136
137 #define STAT_COPYFROM(st) do {   \
138     *adev     = (st).st_dev;     \
139     *aino     = (st).st_ino;     \
140     *amode    = (st).st_mode;    \
141     *anlink   = (st).st_nlink;   \
142     *auid     = (st).st_uid;     \
143     *agid     = (st).st_gid;     \
144     *ardev    = (st).st_rdev;    \
145     *asize    = (st).st_size;    \
146     *aatime   = (st).st_atime;   \
147     *amtime   = (st).st_mtime;   \
148     *actime   = (st).st_ctime;   \
149     *ablksize = (st).st_blksize; \
150     *ablocks  = (st).st_blocks;  \
151 } while (0)
152
153 int
154 swig_uafs_stat(char *path, STAT_ARGS)
155 {
156     int code;
157     struct stat st;
158     code = uafs_stat(path, &st);
159     if (code == 0) {
160         STAT_COPYFROM(st);
161     }
162     return code;
163 }
164 int
165 swig_uafs_lstat(char *path, STAT_ARGS)
166 {
167     int code;
168     struct stat st;
169     code = uafs_lstat(path, &st);
170     if (code == 0) {
171         STAT_COPYFROM(st);
172     }
173     return code;
174 }
175 int
176 swig_uafs_fstat(int fd, STAT_ARGS)
177 {
178     int code;
179     struct stat st;
180     code = uafs_fstat(fd, &st);
181     if (code == 0) {
182         STAT_COPYFROM(st);
183     }
184     return code;
185 }
186
187 #undef STAT_TYPE
188 #undef STAT_ARGS
189 #undef STAT_COPYFROM
190 %}
191
192 %define STAT_TYPE
193 long
194 %enddef
195 %define STAT_OUT_ARGS
196 STAT_TYPE *OUTPUT,
197 STAT_TYPE *OUTPUT,
198 STAT_TYPE *OUTPUT,
199 STAT_TYPE *OUTPUT,
200 STAT_TYPE *OUTPUT,
201 STAT_TYPE *OUTPUT,
202 STAT_TYPE *OUTPUT,
203 STAT_TYPE *OUTPUT,
204 STAT_TYPE *OUTPUT,
205 STAT_TYPE *OUTPUT,
206 STAT_TYPE *OUTPUT,
207 STAT_TYPE *OUTPUT,
208 STAT_TYPE *OUTPUT
209 %enddef
210
211 %rename (uafs_stat) swig_uafs_stat;
212 %rename (uafs_lstat) swig_uafs_lstat;
213 %rename (uafs_fstat) swig_uafs_fstat;
214
215 extern int swig_uafs_stat(char *path, STAT_OUT_ARGS);
216 extern int swig_uafs_lstat(char *path, STAT_OUT_ARGS);
217 extern int swig_uafs_fstat(int fd, STAT_OUT_ARGS);
218
219 extern int uafs_truncate(char *path, int len);
220 extern int uafs_ftruncate(int fd, int len);
221 extern int uafs_lseek(int fd, int offset, int whence);
222 extern int uafs_chmod(char *path, int mode);
223 extern int uafs_fchmod(int fd, int mode);
224 extern int uafs_symlink(char *target, char *source);
225 extern int uafs_unlink(char *path);
226 extern int uafs_rmdir(char *path);
227 extern int uafs_readlink(char *path, char *READBUF, int LENGTH);
228 extern int uafs_link(char *existing, char *new);
229 extern int uafs_rename(char *old, char *new);
230
231 extern usr_DIR *uafs_opendir(char *path);
232
233 %rename (uafs_readdir) swig_uafs_readdir;
234 %{
235 /*
236  * Language-neutral wrapper for uafs_readdir. Since the language won't know
237  * what to do with a struct usr_dirent, we could either make a SWIG typemap, or
238  * define a wrapper with multiple return arguments. Making a typemap is
239  * language-specific, so we define a wrapper, and let the typemaps.i library
240  * worry about the language-specific parts of getting multiple return values.
241  */
242 char *
243 swig_uafs_readdir(usr_DIR *dirp, unsigned long *d_ino, unsigned long *d_off, unsigned short *d_reclen)
244 {
245     struct usr_dirent *dentry;
246
247     dentry = uafs_readdir(dirp);
248     if (!dentry) {
249         *d_ino = *d_off = *d_reclen = 0;
250         return NULL;
251     }
252
253     *d_ino = dentry->d_ino;
254     *d_off = dentry->d_off;
255     *d_reclen = dentry->d_reclen;
256
257     return strdup(dentry->d_name);
258 }
259 %}
260
261 extern char * swig_uafs_readdir(usr_DIR *dirp, unsigned long *OUTPUT, unsigned long *OUTPUT, unsigned short *OUTPUT);
262 extern int uafs_closedir(usr_DIR * dirp);
263 extern void uafs_SetRxPort(int);
264 extern void uafs_Shutdown(void);