/*
* Copyright (c) 2009-2012 Zmanda, Inc. All Rights Reserved.
* Copyright (c) 2013-2016 Carbonite, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact information: Carbonite Inc., 756 N Pastoria Ave
* Sunnyvale, CA 94085, or: http://www.zmanda.com
*/
%module "Amanda::NDMP"
%include "amglue/amglue.swg"
%include "exception.i"
%include "Amanda/NDMP.pod"
%{
#include "ndmpconnobj.h"
#include "glib-util.h"
%}
/* initialize glib, and in particular GType */
%init %{
glib_init();
%}
/* supporting typemaps */
/* treat all enums in this file as regular UV's - no need for BigInt */
%{
typedef guint ndmp_enum;
%}
/* Any enumeration, input */
%typemap(in) ndmp_enum "$1 = SvIV($input);";
/* Any enumeration, output argument */
%typemap(in,numinputs=0) ndmp_enum * (int temp) "$1 = &temp; temp = 0;";
%typemap(argout) ndmp_enum * {
if (argvi >= items) {
EXTEND(sp,1);
}
$result = sv_newmortal();
sv_setuv($result, (UV)(*$1));
argvi++;
}
/* gsize, output argument */
%typemap(in,numinputs=0) gsize * (gsize temp) "$1 = &temp; temp = 0;"
%typemap(argout) gsize * {
if (argvi >= items) {
EXTEND(sp,1);
}
SP += argvi; PUTBACK;
$result = sv_2mortal(amglue_newSVu64(*$1));
SP -= argvi; argvi++;
}
/* guint64, output argument */
%typemap(in,numinputs=0) guint64 * (guint64 temp) "$1 = &temp; temp = 0;"
%typemap(argout) guint64 * {
if (argvi >= items) {
EXTEND(sp,1);
}
SP += argvi; PUTBACK;
$result = sv_2mortal(amglue_newSVu64(*$1));
SP -= argvi; argvi++;
}
/* guint, output argument */
%typemap(in,numinputs=0) guint * (guint temp) "$1 = &temp; temp = 0;"
%typemap(argout) guint * {
if (argvi >= items) {
EXTEND(sp,1);
}
SP += argvi; PUTBACK;
$result = sv_2mortal(amglue_newSVu64(*$1));
SP -= argvi; argvi++;
}
typedef struct {
/* methods */
%extend {
/* constructor */
NDMPConnection(
gchar *hostname,
gint port,
gchar *username,
gchar *password,
gchar *auth) {
return ndmp_connection_new(
hostname, port, username, password, auth);
}
~NDMPConnection() {
g_object_unref(self);
}
/* error handling */
int
err_code() {
return ndmp_connection_err_code(self);
}
%newobject err_msg;
gchar *
err_msg() {
return ndmp_connection_err_msg(self);
}
void
set_verbose(gboolean verbose) {
ndmp_connection_set_verbose(self, verbose);
}
/* operations */
gboolean
scsi_open(gchar *device) {
return ndmp_connection_scsi_open(
self,
device);
}
gboolean
scsi_close() {
return ndmp_connection_scsi_close(self);
}
/* NOTE: this method is wrapped with a more perlish interface; see below */
/* handle cdb */
%typemap(in) (gpointer cdb, gsize cdb_len) {
/* cdb */
int g_malloc = SWIG_OLDOBJ;
SWIG_AsCharPtrAndSize($input, (char **)&$1, &$2, &g_malloc);
if ($2) $2--; /* strip trailing NUL byte */
}
/* handle dataout and its response */
%typemap(in,numinputs=1)
(gpointer dataout, gsize dataout_len, gsize *actual_dataout_len)
(gsize dataout_len) {
/* dataout */
/* handle the actual input here */
int g_malloc = SWIG_OLDOBJ;
SWIG_AsCharPtrAndSize($input, (char **)&$1, &$2, &g_malloc);
if ($2) $2--; /* strip trailing NUL byte */
/* set up for argout typemap, below */
dataout_len = 0;
$3 = &dataout_len;
}
%typemap(argout)
(gpointer dataout, gsize dataout_len, gsize *actual_dataout_len) {
if (argvi >= items) {
EXTEND(sp,1);
}
SP += argvi; PUTBACK;
$result = sv_2mortal(amglue_newSVu64(*$3));
SP -= argvi; argvi++;
}
/* handle datain and its response */
%typemap(in,numinputs=1)
(gpointer datain, gsize datain_max_len, gsize *actual_datain_len)
(gpointer datain_buf, gsize actual_datain_len) {
/* datain */
gchar *err = NULL;
gsize max_size = amglue_SvU64($input, &err);
$2 = max_size;
if (max_size) {
$1 = g_malloc(max_size);
} else {
$1 = NULL;
}
actual_datain_len = 0;
$3 = &actual_datain_len;
}
%typemap(argout)
(gpointer datain, gsize datain_max_len, gsize *actual_datain_len) {
if (argvi >= items) {
EXTEND(sp,1);
}
/* convert the value, even if it's NULL */
$result = SWIG_FromCharPtrAndSize($1, *$3);
argvi++;
if ($1) g_free($1);
}
/* handle status */
%typemap(in,numinputs=0) (guint8 *status) (guint8 temp) "$1 = &temp;";
%typemap(argout) (guint8 *status) {
if (argvi >= items) {
EXTEND(sp,1);
}
$result = sv_newmortal();
sv_setuv($result, (UV)(*$1));
argvi++;
}
/* handle ext_status */
%typemap(in,numinputs=0)
(gpointer ext_sense, gsize ext_sense_max_len, gsize *actual_ext_sense_len)
(guint8 ext_sense_buf[128], gsize actual_ext_sense_len) {
$1 = ext_sense_buf;
$2 = sizeof(ext_sense_buf); /* always allocate 128 bytes for sense */
actual_ext_sense_len = 0;
$3 = &actual_ext_sense_len;
}
%typemap(argout)
(gpointer ext_sense, gsize ext_sense_max_len, gsize *actual_ext_sense_len) {
if (argvi >= items) {
EXTEND(sp,1);
}
$result = SWIG_FromCharPtrAndSize($1, *$3);
argvi++;
}
gboolean
scsi_execute_cdb_C(
ndmp_enum flags,
guint32 timeout,
gpointer cdb,
gsize cdb_len,
gpointer dataout,
gsize dataout_len,
gsize *actual_dataout_len,
gpointer datain,
gsize datain_max_len,
gsize *actual_datain_len,
guint8 *status,
gpointer ext_sense,
gsize ext_sense_max_len,
gsize *actual_ext_sense_len
) {
return ndmp_connection_scsi_execute_cdb(
self,
flags,
timeout,
cdb,
cdb_len,
dataout,
dataout_len,
actual_dataout_len,
datain,
datain_max_len,
actual_datain_len,
status,
ext_sense,
ext_sense_max_len,
actual_ext_sense_len
);
}
gboolean
tape_open(
gchar *device,
ndmp_enum mode) {
return ndmp_connection_tape_open(
self,
device,
mode);
}
gboolean
tape_close() {
return ndmp_connection_tape_close(self);
}
gboolean
tape_mtio(
ndmp_enum tape_op,
gint count,
guint *resid) {
return ndmp_connection_tape_mtio(
self,
tape_op,
count,
resid);
}
%typemap(in) (gpointer buf, guint64 len) {
int g_malloc = SWIG_OLDOBJ;
size_t len_tmp; /* use a temporary with the right type */
SWIG_AsCharPtrAndSize($input, (char **)&$1, &len_tmp, &g_malloc);
if (len_tmp) len_tmp--; /* strip trailing NUL byte */
$2 = len_tmp;
}
gboolean
tape_write(
gpointer buf,
guint64 len,
guint64 *count) {
return ndmp_connection_tape_write(
self,
buf,
len,
count);
}
%typemap(in,numinputs=1)
(gpointer buf, guint64 count, guint64 *out_count)
(guint64 out_count) {
gchar *err = NULL;
$2 = amglue_SvU64($input, &err);
$1 = $2?g_malloc($2):NULL;
out_count = 0;
$3 = &out_count;
}
%typemap(argout)
(gpointer buf, guint64 count, guint64 *out_count) {
if (argvi >= items) {
EXTEND(sp,1);
}
/* convert the value, even if it's NULL */
$result = SWIG_FromCharPtrAndSize($1, *$3);
argvi++;
if ($1) g_free($1);
}
gboolean
tape_read(
gpointer buf,
guint64 count,
guint64 *out_count) {
return ndmp_connection_tape_read(
self,
buf,
count,
out_count);
}
gboolean
tape_get_state(
guint64 *blocksize,
guint64 *file_num,
guint64 *blockno) {
return ndmp_connection_tape_get_state(
self,
blocksize,
file_num,
blockno);
}
/* mover interface is not yet SWIGged */
};
} NDMPConnection;
/* perlish wrappers */
%perlcode %{
package Amanda::NDMP::NDMPConnection;
sub scsi_execute_cdb {
my $self = shift;
my %params = @_;
die "no 'flags' parameter'" unless defined $params{'flags'};
die "no 'timeout' parameter'" unless defined $params{'timeout'};
die "no 'cdb' parameter'" unless defined $params{'cdb'};
if ($params{'flags'} & $Amanda::NDMP::NDMP9_SCSI_DATA_DIR_IN) {
die "no 'datain_len' parameter'" unless defined $params{'datain_len'};
} else {
$params{'datain_len'} = 0;
}
if ($params{'flags'} & $Amanda::NDMP::NDMP9_SCSI_DATA_DIR_OUT) {
die "no 'dataout' parameter'" unless defined $params{'dataout'};
} else {
$params{'dataout'} = undef;
}
my ($ok, $dataout_len, $datain, $status, $ext_sense) =
$self->scsi_execute_cdb_C(
$params{'flags'}, $params{'timeout'},
$params{'cdb'}, $params{'dataout'},
$params{'datain_len'});
return 0 unless ($ok);
my %result = (
status => $status,
ext_sense => $ext_sense);
if ($params{'flags'} & $Amanda::NDMP::NDMP9_SCSI_DATA_DIR_IN) {
$result{'datain'} = $datain;
}
if ($params{'flags'} & $Amanda::NDMP::NDMP9_SCSI_DATA_DIR_OUT) {
$result{'dataout_len'} = $dataout_len;
}
return \%result;
}
package Amanda::NDMP;
%}
/* selected NDMP constants; note that the "NDMP9_" prfix is required */
amglue_add_flag_tag_fns(scsi_data_dir);
amglue_add_constant_short(NDMP9_SCSI_DATA_DIR_NONE, "NDMP9_SCSI_DATA_DIR_NONE", scsi_data_dir);
amglue_add_constant_short(NDMP9_SCSI_DATA_DIR_IN, "NDMP9_SCSI_DATA_DIR_IN", scsi_data_dir);
amglue_add_constant_short(NDMP9_SCSI_DATA_DIR_OUT, "NDMP9_SCSI_DATA_DIR_OUT", scsi_data_dir);
amglue_copy_to_tag(scsi_data_dir, constants);
amglue_add_flag_tag_fns(tape_open_mode);
amglue_add_constant_short(NDMP9_TAPE_READ_MODE, "NDMP9_TAPE_READ_MODE", tape_open_mode);
amglue_add_constant_short(NDMP9_TAPE_RDWR_MODE, "NDMP9_TAPE_RDRW_MODE", tape_open_mode);
amglue_add_constant_short(NDMP9_TAPE_RAW_MODE, "NDMP9_TAPE_RAW_MODE", tape_open_mode);
amglue_copy_to_tag(tape_open_mode, constants);
amglue_add_flag_tag_fns(tape_mtio_op);
amglue_add_constant_short(NDMP9_MTIO_FSF, "NDMP9_MTIO_FSF", tape_mtio_op);
amglue_add_constant_short(NDMP9_MTIO_BSF, "NDMP9_MTIO_BSF", tape_mtio_op);
amglue_add_constant_short(NDMP9_MTIO_FSR, "NDMP9_MTIO_FSR", tape_mtio_op);
amglue_add_constant_short(NDMP9_MTIO_BSR, "NDMP9_MTIO_BSR", tape_mtio_op);
amglue_add_constant_short(NDMP9_MTIO_REW, "NDMP9_MTIO_REW", tape_mtio_op);
amglue_add_constant_short(NDMP9_MTIO_EOF, "NDMP9_MTIO_EOF", tape_mtio_op);
amglue_add_constant_short(NDMP9_MTIO_OFF, "NDMP9_MTIO_OFF", tape_mtio_op);
amglue_copy_to_tag(tape_mtio_op, constants);
amglue_add_flag_tag_fns(mover_mode);
amglue_add_constant_short(NDMP9_MOVER_MODE_READ, "NDMP9_MOVER_MODE_READ", mover_mode);
amglue_add_constant_short(NDMP9_MOVER_MODE_WRITE, "NDMP9_MOVER_MODE_WRITE", mover_mode);
amglue_copy_to_tag(mover_mode, constants);
amglue_add_flag_tag_fns(addr_type);
amglue_add_constant_short(NDMP9_ADDR_LOCAL, "NDMP9_ADDR_LOCAL", addr_type);
amglue_add_constant_short(NDMP9_ADDR_TCP, "NDMP9_ADDR_TCP", addr_type);
amglue_add_constant_short(NDMP9_ADDR_AS_CONNECTED, "NDMP9_ADDR_AS_CONNECTED", addr_type);
amglue_copy_to_tag(addr_type, constants);
amglue_add_flag_tag_fns(mover_state);
amglue_add_constant_short(NDMP9_MOVER_STATE_IDLE, "NDMP9_MOVER_STATE_IDLE", mover_state);
amglue_add_constant_short(NDMP9_MOVER_STATE_LISTEN, "NDMP9_MOVER_STATE_LISTEN", mover_state);
amglue_add_constant_short(NDMP9_MOVER_STATE_ACTIVE, "NDMP9_MOVER_STATE_ACTIVE", mover_state);
amglue_add_constant_short(NDMP9_MOVER_STATE_PAUSED, "NDMP9_MOVER_STATE_PAUSED", mover_state);
amglue_add_constant_short(NDMP9_MOVER_STATE_HALTED, "NDMP9_MOVER_STATE_HALTED", mover_state);
amglue_add_constant_short(NDMP9_MOVER_STATE_STANDBY, "NDMP9_MOVER_STATE_STANDBY", mover_state);
amglue_copy_to_tag(mover_state, constants);
amglue_add_flag_tag_fns(data_halt_reason);
amglue_add_constant_short(NDMP9_DATA_HALT_NA, "NDMP9_DATA_HALT_NA", data_halt_reason);
amglue_add_constant_short(NDMP9_DATA_HALT_SUCCESSFUL, "NDMP9_DATA_HALT_SUCCESSFUL", data_halt_reason);
amglue_add_constant_short(NDMP9_DATA_HALT_ABORTED, "NDMP9_DATA_HALT_ABORTED", data_halt_reason);
amglue_add_constant_short(NDMP9_DATA_HALT_INTERNAL_ERROR, "NDMP9_DATA_HALT_INTERNAL_ERROR", data_halt_reason);
amglue_add_constant_short(NDMP9_DATA_HALT_CONNECT_ERROR, "NDMP9_DATA_HALT_CONNECT_ERROR", data_halt_reason);
amglue_copy_to_tag(data_halt_reason, constants);
amglue_add_flag_tag_fns(mover_halt_reason);
amglue_add_constant_short(NDMP9_MOVER_HALT_NA, "NDMP9_MOVER_HALT_NA", mover_halt_reason);
amglue_add_constant_short(NDMP9_MOVER_HALT_CONNECT_CLOSED, "NDMP9_MOVER_HALT_CONNECT_CLOSED", mover_halt_reason);
amglue_add_constant_short(NDMP9_MOVER_HALT_ABORTED, "NDMP9_MOVER_HALT_ABORTED", mover_halt_reason);
amglue_add_constant_short(NDMP9_MOVER_HALT_INTERNAL_ERROR, "NDMP9_MOVER_HALT_INTERNAL_ERROR", mover_halt_reason);
amglue_add_constant_short(NDMP9_MOVER_HALT_CONNECT_ERROR, "NDMP9_MOVER_HALT_CONNECT_ERROR", mover_halt_reason);
amglue_copy_to_tag(mover_halt_reason, constants);
amglue_add_flag_tag_fns(mover_pause_reason);
amglue_add_constant_short(NDMP9_MOVER_PAUSE_NA, "NDMP9_MOVER_PAUSE_NA", mover_pause_reason);
amglue_add_constant_short(NDMP9_MOVER_PAUSE_EOM, "NDMP9_MOVER_PAUSE_EOM", mover_pause_reason);
amglue_add_constant_short(NDMP9_MOVER_PAUSE_EOF, "NDMP9_MOVER_PAUSE_EOF", mover_pause_reason);
amglue_add_constant_short(NDMP9_MOVER_PAUSE_SEEK, "NDMP9_MOVER_PAUSE_SEEK", mover_pause_reason);
amglue_add_constant_short(NDMP9_MOVER_PAUSE_MEDIA_ERROR, "NDMP9_MOVER_PAUSE_MEDIA_ERROR", mover_pause_reason);
amglue_add_constant_short(NDMP9_MOVER_PAUSE_EOW, "NDMP9_MOVER_PAUSE_EOW", mover_pause_reason);
amglue_copy_to_tag(mover_pause_reason, constants);