1/* 2 * Copyright (c) 2009-2013 Zmanda, Inc. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * for more details. 13 * 14 * You should have received a copy of the GNU General Public License along 15 * with this program; if not, write to the Free Software Foundation, Inc., 16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 * 18 * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300 19 * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com 20 */ 21 22%module "Amanda::NDMP" 23%include "amglue/amglue.swg" 24%include "exception.i" 25 26%include "Amanda/NDMP.pod" 27 28%{ 29#include "ndmpconnobj.h" 30#include "glib-util.h" 31%} 32 33/* initialize glib, and in particular GType */ 34%init %{ 35 glib_init(); 36%} 37 38/* supporting typemaps */ 39 40/* treat all enums in this file as regular UV's - no need for BigInt */ 41%{ 42typedef guint ndmp_enum; 43%} 44 45/* Any enumeration, input */ 46%typemap(in) ndmp_enum "$1 = SvIV($input);"; 47 48/* Any enumeration, output argument */ 49%typemap(in,numinputs=0) ndmp_enum * (int temp) "$1 = &temp; temp = 0;"; 50%typemap(argout) ndmp_enum * { 51 if (argvi >= items) { 52 EXTEND(sp,1); 53 } 54 55 $result = sv_newmortal(); 56 sv_setuv($result, (UV)(*$1)); 57 argvi++; 58} 59 60/* gsize, output argument */ 61%typemap(in,numinputs=0) gsize * (gsize temp) "$1 = &temp; temp = 0;" 62%typemap(argout) gsize * { 63 if (argvi >= items) { 64 EXTEND(sp,1); 65 } 66 67 SP += argvi; PUTBACK; 68 $result = sv_2mortal(amglue_newSVu64(*$1)); 69 SP -= argvi; argvi++; 70} 71 72/* guint64, output argument */ 73%typemap(in,numinputs=0) guint64 * (guint64 temp) "$1 = &temp; temp = 0;" 74%typemap(argout) guint64 * { 75 if (argvi >= items) { 76 EXTEND(sp,1); 77 } 78 79 SP += argvi; PUTBACK; 80 $result = sv_2mortal(amglue_newSVu64(*$1)); 81 SP -= argvi; argvi++; 82} 83 84/* guint, output argument */ 85%typemap(in,numinputs=0) guint * (guint temp) "$1 = &temp; temp = 0;" 86%typemap(argout) guint * { 87 if (argvi >= items) { 88 EXTEND(sp,1); 89 } 90 91 SP += argvi; PUTBACK; 92 $result = sv_2mortal(amglue_newSVu64(*$1)); 93 SP -= argvi; argvi++; 94} 95 96typedef struct { 97 /* methods */ 98 %extend { 99 /* constructor */ 100 NDMPConnection( 101 gchar *hostname, 102 gint port, 103 gchar *username, 104 gchar *password, 105 gchar *auth) { 106 return ndmp_connection_new( 107 hostname, port, username, password, auth); 108 } 109 110 ~NDMPConnection() { 111 g_object_unref(self); 112 } 113 114 /* error handling */ 115 116 int 117 err_code() { 118 return ndmp_connection_err_code(self); 119 } 120 121 %newobject err_msg; 122 gchar * 123 err_msg() { 124 return ndmp_connection_err_msg(self); 125 } 126 127 void 128 set_verbose(gboolean verbose) { 129 ndmp_connection_set_verbose(self, verbose); 130 } 131 132 /* operations */ 133 134 gboolean 135 scsi_open(gchar *device) { 136 return ndmp_connection_scsi_open( 137 self, 138 device); 139 } 140 141 gboolean 142 scsi_close() { 143 return ndmp_connection_scsi_close(self); 144 } 145 146 /* NOTE: this method is wrapped with a more perlish interface; see below */ 147 148 /* handle cdb */ 149 %typemap(in) (gpointer cdb, gsize cdb_len) { 150 /* cdb */ 151 int alloc = SWIG_OLDOBJ; 152 SWIG_AsCharPtrAndSize($input, (char **)&$1, &$2, &alloc); 153 if ($2) $2--; /* strip trailing NUL byte */ 154 } 155 156 /* handle dataout and its response */ 157 %typemap(in,numinputs=1) 158 (gpointer dataout, gsize dataout_len, gsize *actual_dataout_len) 159 (gsize dataout_len) { 160 /* dataout */ 161 162 /* handle the actual input here */ 163 int alloc = SWIG_OLDOBJ; 164 SWIG_AsCharPtrAndSize($input, (char **)&$1, &$2, &alloc); 165 if ($2) $2--; /* strip trailing NUL byte */ 166 /* set up for argout typemap, below */ 167 dataout_len = 0; 168 $3 = &dataout_len; 169 } 170 %typemap(argout) 171 (gpointer dataout, gsize dataout_len, gsize *actual_dataout_len) { 172 if (argvi >= items) { 173 EXTEND(sp,1); 174 } 175 176 SP += argvi; PUTBACK; 177 $result = sv_2mortal(amglue_newSVu64(*$3)); 178 SP -= argvi; argvi++; 179 } 180 181 /* handle datain and its response */ 182 %typemap(in,numinputs=1) 183 (gpointer datain, gsize datain_max_len, gsize *actual_datain_len) 184 (gpointer datain_buf, gsize actual_datain_len) { 185 /* datain */ 186 gsize max_size = amglue_SvU64($input); 187 $2 = max_size; 188 if (max_size) { 189 $1 = g_malloc(max_size); 190 } else { 191 $1 = NULL; 192 } 193 actual_datain_len = 0; 194 $3 = &actual_datain_len; 195 } 196 %typemap(argout) 197 (gpointer datain, gsize datain_max_len, gsize *actual_datain_len) { 198 if (argvi >= items) { 199 EXTEND(sp,1); 200 } 201 202 /* convert the value, even if it's NULL */ 203 $result = SWIG_FromCharPtrAndSize($1, *$3); 204 argvi++; 205 if ($1) g_free($1); 206 } 207 208 /* handle status */ 209 %typemap(in,numinputs=0) (guint8 *status) (guint8 temp) "$1 = &temp;"; 210 %typemap(argout) (guint8 *status) { 211 if (argvi >= items) { 212 EXTEND(sp,1); 213 } 214 215 $result = sv_newmortal(); 216 sv_setuv($result, (UV)(*$1)); 217 argvi++; 218 } 219 220 /* handle ext_status */ 221 %typemap(in,numinputs=0) 222 (gpointer ext_sense, gsize ext_sense_max_len, gsize *actual_ext_sense_len) 223 (guint8 ext_sense_buf[128], gsize actual_ext_sense_len) { 224 $1 = ext_sense_buf; 225 $2 = sizeof(ext_sense_buf); /* always allocate 128 bytes for sense */ 226 actual_ext_sense_len = 0; 227 $3 = &actual_ext_sense_len; 228 } 229 %typemap(argout) 230 (gpointer ext_sense, gsize ext_sense_max_len, gsize *actual_ext_sense_len) { 231 if (argvi >= items) { 232 EXTEND(sp,1); 233 } 234 235 $result = SWIG_FromCharPtrAndSize($1, *$3); 236 argvi++; 237 } 238 239 gboolean 240 scsi_execute_cdb_C( 241 ndmp_enum flags, 242 guint32 timeout, 243 gpointer cdb, 244 gsize cdb_len, 245 gpointer dataout, 246 gsize dataout_len, 247 gsize *actual_dataout_len, 248 gpointer datain, 249 gsize datain_max_len, 250 gsize *actual_datain_len, 251 guint8 *status, 252 gpointer ext_sense, 253 gsize ext_sense_max_len, 254 gsize *actual_ext_sense_len 255 ) { 256 return ndmp_connection_scsi_execute_cdb( 257 self, 258 flags, 259 timeout, 260 cdb, 261 cdb_len, 262 dataout, 263 dataout_len, 264 actual_dataout_len, 265 datain, 266 datain_max_len, 267 actual_datain_len, 268 status, 269 ext_sense, 270 ext_sense_max_len, 271 actual_ext_sense_len 272 ); 273 } 274 275 gboolean 276 tape_open( 277 gchar *device, 278 ndmp_enum mode) { 279 return ndmp_connection_tape_open( 280 self, 281 device, 282 mode); 283 } 284 285 gboolean 286 tape_close() { 287 return ndmp_connection_tape_close(self); 288 } 289 290 gboolean 291 tape_mtio( 292 ndmp_enum tape_op, 293 gint count, 294 guint *resid) { 295 return ndmp_connection_tape_mtio( 296 self, 297 tape_op, 298 count, 299 resid); 300 } 301 302 %typemap(in) (gpointer buf, guint64 len) { 303 int alloc = SWIG_OLDOBJ; 304 size_t len_tmp; /* use a temporary with the right type */ 305 SWIG_AsCharPtrAndSize($input, (char **)&$1, &len_tmp, &alloc); 306 if (len_tmp) len_tmp--; /* strip trailing NUL byte */ 307 $2 = len_tmp; 308 } 309 gboolean 310 tape_write( 311 gpointer buf, 312 guint64 len, 313 guint64 *count) { 314 return ndmp_connection_tape_write( 315 self, 316 buf, 317 len, 318 count); 319 } 320 321 %typemap(in,numinputs=1) 322 (gpointer buf, guint64 count, guint64 *out_count) 323 (guint64 out_count) { 324 $2 = amglue_SvU64($input); 325 $1 = $2?g_malloc($2):NULL; 326 out_count = 0; 327 $3 = &out_count; 328 } 329 %typemap(argout) 330 (gpointer buf, guint64 count, guint64 *out_count) { 331 if (argvi >= items) { 332 EXTEND(sp,1); 333 } 334 335 /* convert the value, even if it's NULL */ 336 $result = SWIG_FromCharPtrAndSize($1, *$3); 337 argvi++; 338 if ($1) g_free($1); 339 } 340 gboolean 341 tape_read( 342 gpointer buf, 343 guint64 count, 344 guint64 *out_count) { 345 return ndmp_connection_tape_read( 346 self, 347 buf, 348 count, 349 out_count); 350 } 351 352 gboolean 353 tape_get_state( 354 guint64 *blocksize, 355 guint64 *file_num, 356 guint64 *blockno) { 357 return ndmp_connection_tape_get_state( 358 self, 359 blocksize, 360 file_num, 361 blockno); 362 } 363 364 /* mover interface is not yet SWIGged */ 365 }; 366} NDMPConnection; 367 368/* perlish wrappers */ 369%perlcode %{ 370package Amanda::NDMP::NDMPConnection; 371 372sub scsi_execute_cdb { 373 my $self = shift; 374 my %params = @_; 375 376 die "no 'flags' parameter'" unless defined $params{'flags'}; 377 die "no 'timeout' parameter'" unless defined $params{'timeout'}; 378 die "no 'cdb' parameter'" unless defined $params{'cdb'}; 379 if ($params{'flags'} & $Amanda::NDMP::NDMP9_SCSI_DATA_DIR_IN) { 380 die "no 'datain_len' parameter'" unless defined $params{'datain_len'}; 381 } else { 382 $params{'datain_len'} = 0; 383 } 384 if ($params{'flags'} & $Amanda::NDMP::NDMP9_SCSI_DATA_DIR_OUT) { 385 die "no 'dataout' parameter'" unless defined $params{'dataout'}; 386 } else { 387 $params{'dataout'} = undef; 388 } 389 390 my ($ok, $dataout_len, $datain, $status, $ext_sense) = 391 $self->scsi_execute_cdb_C( 392 $params{'flags'}, $params{'timeout'}, 393 $params{'cdb'}, $params{'dataout'}, 394 $params{'datain_len'}); 395 396 return 0 unless ($ok); 397 398 my %result = ( 399 status => $status, 400 ext_sense => $ext_sense); 401 if ($params{'flags'} & $Amanda::NDMP::NDMP9_SCSI_DATA_DIR_IN) { 402 $result{'datain'} = $datain; 403 } 404 if ($params{'flags'} & $Amanda::NDMP::NDMP9_SCSI_DATA_DIR_OUT) { 405 $result{'dataout_len'} = $dataout_len; 406 } 407 return \%result; 408} 409 410package Amanda::NDMP; 411%} 412 413/* selected NDMP constants; note that the "NDMP9_" prfix is required */ 414 415amglue_add_flag_tag_fns(scsi_data_dir); 416amglue_add_constant_short(NDMP9_SCSI_DATA_DIR_NONE, "NDMP9_SCSI_DATA_DIR_NONE", scsi_data_dir); 417amglue_add_constant_short(NDMP9_SCSI_DATA_DIR_IN, "NDMP9_SCSI_DATA_DIR_IN", scsi_data_dir); 418amglue_add_constant_short(NDMP9_SCSI_DATA_DIR_OUT, "NDMP9_SCSI_DATA_DIR_OUT", scsi_data_dir); 419amglue_copy_to_tag(scsi_data_dir, constants); 420 421amglue_add_flag_tag_fns(tape_open_mode); 422amglue_add_constant_short(NDMP9_TAPE_READ_MODE, "NDMP9_TAPE_READ_MODE", tape_open_mode); 423amglue_add_constant_short(NDMP9_TAPE_RDWR_MODE, "NDMP9_TAPE_RDRW_MODE", tape_open_mode); 424amglue_add_constant_short(NDMP9_TAPE_RAW_MODE, "NDMP9_TAPE_RAW_MODE", tape_open_mode); 425amglue_copy_to_tag(tape_open_mode, constants); 426 427amglue_add_flag_tag_fns(tape_mtio_op); 428amglue_add_constant_short(NDMP9_MTIO_FSF, "NDMP9_MTIO_FSF", tape_mtio_op); 429amglue_add_constant_short(NDMP9_MTIO_BSF, "NDMP9_MTIO_BSF", tape_mtio_op); 430amglue_add_constant_short(NDMP9_MTIO_FSR, "NDMP9_MTIO_FSR", tape_mtio_op); 431amglue_add_constant_short(NDMP9_MTIO_BSR, "NDMP9_MTIO_BSR", tape_mtio_op); 432amglue_add_constant_short(NDMP9_MTIO_REW, "NDMP9_MTIO_REW", tape_mtio_op); 433amglue_add_constant_short(NDMP9_MTIO_EOF, "NDMP9_MTIO_EOF", tape_mtio_op); 434amglue_add_constant_short(NDMP9_MTIO_OFF, "NDMP9_MTIO_OFF", tape_mtio_op); 435amglue_copy_to_tag(tape_mtio_op, constants); 436 437amglue_add_flag_tag_fns(mover_mode); 438amglue_add_constant_short(NDMP9_MOVER_MODE_READ, "NDMP9_MOVER_MODE_READ", mover_mode); 439amglue_add_constant_short(NDMP9_MOVER_MODE_WRITE, "NDMP9_MOVER_MODE_WRITE", mover_mode); 440amglue_copy_to_tag(mover_mode, constants); 441 442amglue_add_flag_tag_fns(addr_type); 443amglue_add_constant_short(NDMP9_ADDR_LOCAL, "NDMP9_ADDR_LOCAL", addr_type); 444amglue_add_constant_short(NDMP9_ADDR_TCP, "NDMP9_ADDR_TCP", addr_type); 445amglue_add_constant_short(NDMP9_ADDR_AS_CONNECTED, "NDMP9_ADDR_AS_CONNECTED", addr_type); 446amglue_copy_to_tag(addr_type, constants); 447 448amglue_add_flag_tag_fns(mover_state); 449amglue_add_constant_short(NDMP9_MOVER_STATE_IDLE, "NDMP9_MOVER_STATE_IDLE", mover_state); 450amglue_add_constant_short(NDMP9_MOVER_STATE_LISTEN, "NDMP9_MOVER_STATE_LISTEN", mover_state); 451amglue_add_constant_short(NDMP9_MOVER_STATE_ACTIVE, "NDMP9_MOVER_STATE_ACTIVE", mover_state); 452amglue_add_constant_short(NDMP9_MOVER_STATE_PAUSED, "NDMP9_MOVER_STATE_PAUSED", mover_state); 453amglue_add_constant_short(NDMP9_MOVER_STATE_HALTED, "NDMP9_MOVER_STATE_HALTED", mover_state); 454amglue_add_constant_short(NDMP9_MOVER_STATE_STANDBY, "NDMP9_MOVER_STATE_STANDBY", mover_state); 455amglue_copy_to_tag(mover_state, constants); 456 457amglue_add_flag_tag_fns(data_halt_reason); 458amglue_add_constant_short(NDMP9_DATA_HALT_NA, "NDMP9_DATA_HALT_NA", data_halt_reason); 459amglue_add_constant_short(NDMP9_DATA_HALT_SUCCESSFUL, "NDMP9_DATA_HALT_SUCCESSFUL", data_halt_reason); 460amglue_add_constant_short(NDMP9_DATA_HALT_ABORTED, "NDMP9_DATA_HALT_ABORTED", data_halt_reason); 461amglue_add_constant_short(NDMP9_DATA_HALT_INTERNAL_ERROR, "NDMP9_DATA_HALT_INTERNAL_ERROR", data_halt_reason); 462amglue_add_constant_short(NDMP9_DATA_HALT_CONNECT_ERROR, "NDMP9_DATA_HALT_CONNECT_ERROR", data_halt_reason); 463amglue_copy_to_tag(data_halt_reason, constants); 464 465amglue_add_flag_tag_fns(mover_halt_reason); 466amglue_add_constant_short(NDMP9_MOVER_HALT_NA, "NDMP9_MOVER_HALT_NA", mover_halt_reason); 467amglue_add_constant_short(NDMP9_MOVER_HALT_CONNECT_CLOSED, "NDMP9_MOVER_HALT_CONNECT_CLOSED", mover_halt_reason); 468amglue_add_constant_short(NDMP9_MOVER_HALT_ABORTED, "NDMP9_MOVER_HALT_ABORTED", mover_halt_reason); 469amglue_add_constant_short(NDMP9_MOVER_HALT_INTERNAL_ERROR, "NDMP9_MOVER_HALT_INTERNAL_ERROR", mover_halt_reason); 470amglue_add_constant_short(NDMP9_MOVER_HALT_CONNECT_ERROR, "NDMP9_MOVER_HALT_CONNECT_ERROR", mover_halt_reason); 471amglue_copy_to_tag(mover_halt_reason, constants); 472 473amglue_add_flag_tag_fns(mover_pause_reason); 474amglue_add_constant_short(NDMP9_MOVER_PAUSE_NA, "NDMP9_MOVER_PAUSE_NA", mover_pause_reason); 475amglue_add_constant_short(NDMP9_MOVER_PAUSE_EOM, "NDMP9_MOVER_PAUSE_EOM", mover_pause_reason); 476amglue_add_constant_short(NDMP9_MOVER_PAUSE_EOF, "NDMP9_MOVER_PAUSE_EOF", mover_pause_reason); 477amglue_add_constant_short(NDMP9_MOVER_PAUSE_SEEK, "NDMP9_MOVER_PAUSE_SEEK", mover_pause_reason); 478amglue_add_constant_short(NDMP9_MOVER_PAUSE_MEDIA_ERROR, "NDMP9_MOVER_PAUSE_MEDIA_ERROR", mover_pause_reason); 479amglue_add_constant_short(NDMP9_MOVER_PAUSE_EOW, "NDMP9_MOVER_PAUSE_EOW", mover_pause_reason); 480amglue_copy_to_tag(mover_pause_reason, constants); 481