Imported Upstream version 3.2.0
[debian/amanda] / perl / Amanda / Device.swg
1 /*
2  * Copyright (c) 2007, 2008, 2009, 2010 Zmanda, Inc.  All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 2 as published
6  * by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11  * for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16  *
17  * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
18  * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
19  */
20
21 %module "Amanda::Device"
22 %include "amglue/amglue.swg"
23 %include "exception.i"
24 %import "Amanda/Header.swg";
25
26 %include "Amanda/Device.pod"
27
28 %{
29 #include "device.h"
30 #include "property.h"
31 #include "fileheader.h"
32 #include "glib-util.h"
33 #include "simpleprng.h"
34 %}
35
36 %init %{
37     /* Initialize the Device API on load */
38     device_api_init();
39 %}
40
41 %{
42
43 /* Utility functions for typemaps, below */
44
45 /* return a new, mortal SV corresponding to the given GValue
46  *
47  * @param value: the value to convert
48  * @returns: a new, mortal SV
49  */
50 static SV *
51 set_sv_from_gvalue(GValue *value)
52 {
53     GType fundamental = G_TYPE_FUNDAMENTAL(G_VALUE_TYPE(value));
54     SV *sv = NULL;
55
56     /* complex reference types */
57     switch (fundamental) {
58         case G_TYPE_LONG:
59             return sv_2mortal(amglue_newSVi64(g_value_get_long(value)));
60
61         case G_TYPE_ULONG:
62             return sv_2mortal(amglue_newSVu64(g_value_get_ulong(value)));
63
64         case G_TYPE_INT64:
65             return sv_2mortal(amglue_newSVi64(g_value_get_int64(value)));
66
67         case G_TYPE_UINT64:
68             return sv_2mortal(amglue_newSVu64(g_value_get_uint64(value)));
69     }
70
71     /* simple types that can be constructed with sv_set*v */
72     sv = sv_newmortal();
73     switch (fundamental) {
74         case G_TYPE_CHAR:
75             sv_setiv(sv, g_value_get_char(value));
76             break;
77
78         case G_TYPE_UCHAR:
79             sv_setuv(sv, g_value_get_uchar(value));
80             break;
81
82         case G_TYPE_BOOLEAN:
83             sv_setiv(sv, g_value_get_boolean(value));
84             break;
85
86         case G_TYPE_INT:
87             sv_setiv(sv, g_value_get_int(value));
88             break;
89
90         case G_TYPE_UINT:
91             sv_setuv(sv, g_value_get_uint(value));
92             break;
93
94         case G_TYPE_FLOAT:
95             sv_setnv(sv, g_value_get_float(value));
96             break;
97
98         case G_TYPE_DOUBLE:
99             sv_setnv(sv, g_value_get_double(value));
100             break;
101
102         case G_TYPE_STRING:
103             sv_setpv(sv, g_value_get_string(value));
104             break;
105
106         case G_TYPE_ENUM:
107             sv_setiv(sv, g_value_get_enum(value));
108             break;
109
110         case G_TYPE_FLAGS:
111             sv_setiv(sv, g_value_get_flags(value));
112             break;
113
114         /* Unsupported */
115         default:
116         case G_TYPE_POINTER:
117         case G_TYPE_INTERFACE:
118         case G_TYPE_OBJECT:
119         case G_TYPE_PARAM:
120             warn("Unsupported fundamental property type #%d", (int)fundamental);
121             sv_setsv(sv, &PL_sv_undef);
122             break;
123     }
124
125     return sv;
126 }
127
128 /* Given an SV and an initialized GValue, set the GValue to the value
129  * represented by the SV.  The GValue's type must already be set.
130  *
131  * For basic corresponding types (string -> string, integer -> integer),
132  * the translation is straightforward.  However, if the GValue is not a
133  * string, but the SV has a string value, then g_value_set_from_string will
134  * be used to parse the string.
135  *
136  * @param sv: SV to convert
137  * @param value: (input/output) destination
138  * @returns: TRUE on success
139  */
140 static gboolean
141 set_gvalue_from_sv(SV *sv, GValue *value)
142 {
143     GType fundamental = G_TYPE_FUNDAMENTAL(G_VALUE_TYPE(value));
144
145     /* if we got a string, use g_value_set_from_string to parse any funny
146      * values or suffixes */
147     if (SvPOK(sv)) {
148         if (g_value_set_from_string(value, SvPV_nolen(sv)))
149             return TRUE;
150     }
151
152     /* otherwise, handle numeric types with SvIV, SvNV, or the amglue_* functions */
153     switch (fundamental) {
154         case G_TYPE_BOOLEAN:
155             g_value_set_boolean(value, SvIV(sv));
156             return TRUE;
157
158         case G_TYPE_CHAR:
159             g_value_set_char(value, amglue_SvI8(sv));
160             return TRUE;
161
162         case G_TYPE_UCHAR:
163             g_value_set_uchar(value, amglue_SvU8(sv));
164             return TRUE;
165
166         case G_TYPE_INT:
167             g_value_set_int(value, amglue_SvI32(sv));
168             return TRUE;
169
170         case G_TYPE_UINT:
171             g_value_set_uint(value, amglue_SvU32(sv));
172             return TRUE;
173
174         case G_TYPE_LONG:
175             g_value_set_int64(value, amglue_SvI64(sv));
176             return TRUE;
177
178         case G_TYPE_ULONG:
179             g_value_set_uint64(value, amglue_SvU64(sv));
180             return TRUE;
181
182         case G_TYPE_INT64:
183             g_value_set_int64(value, amglue_SvI64(sv));
184             return TRUE;
185
186         case G_TYPE_UINT64:
187             g_value_set_uint64(value, amglue_SvU64(sv));
188             return TRUE;
189
190         case G_TYPE_FLOAT:
191             g_value_set_float(value, SvNV(sv));
192             return TRUE;
193
194         case G_TYPE_DOUBLE:
195             g_value_set_double(value, SvNV(sv));
196             return TRUE;
197
198         case G_TYPE_ENUM:
199             g_value_set_enum(value, SvIV(sv));
200             return TRUE;
201
202         case G_TYPE_FLAGS:
203             g_value_set_flags(value, SvIV(sv));
204             return TRUE;
205
206         default:
207             /* for anything else, let perl stringify it for us and try parsing it */
208             return g_value_set_from_string(value, SvPV_nolen(sv));
209     }
210 }
211
212 %}
213
214 /*
215  * DirectTCPConnection object
216  */
217
218 typedef struct DirectTCPConnection {
219     %extend {
220         ~DirectTCPConnection() {
221             g_object_unref(self);
222         };
223
224         %newobject close;
225         char *close() {
226             return directtcp_connection_close(self);
227         }
228     };
229 } DirectTCPConnection;
230
231 /*
232  * Device struct, %extend-ed into a Perl class
233  */
234
235 %name(unaliased_name) extern char *device_unaliased_name(char *);
236
237 typedef struct Device {
238
239     /* methods */
240     %extend {
241         /* constructor */
242         Device(char *device_name) {
243             return device_open(device_name);
244         }
245
246         ~Device() {
247             g_object_unref(self);
248         }
249
250         gboolean
251         configure(gboolean use_global_config) {
252             return device_configure(self, use_global_config);
253         }
254
255         char *
256         error() {
257             return device_error(self);
258         }
259
260         char *
261         status_error() {
262             return device_status_error(self);
263         }
264
265         char *
266         error_or_status() {
267             return device_error_or_status(self);
268         }
269
270         DeviceStatusFlags
271         read_label() {
272             return device_read_label(self);
273         }
274
275         gboolean
276         start(DeviceAccessMode mode, char *label, char *timestamp) {
277             return device_start(self, mode, label, timestamp);
278         }
279
280         gboolean
281         finish() {
282             return device_finish(self);
283         }
284
285         gboolean
286         start_file(dumpfile_t *jobInfo) {
287             return device_start_file(self, jobInfo);
288         }
289
290         gboolean
291         write_block(guint size, gpointer data) {
292             return device_write_block(self, size, data);
293         }
294
295         gboolean
296         finish_file() {
297             return device_finish_file(self);
298         }
299
300         dumpfile_t*
301         seek_file(guint file) {
302             return device_seek_file(self, file);
303         }
304
305         gboolean
306         seek_block(guint64 block) {
307             return device_seek_block(self, block);
308         }
309
310         int
311         read_block(gpointer buffer, int *size) {
312             return device_read_block(self, buffer, size);
313         }
314
315         gboolean
316         erase() {
317             return device_erase(self);
318         }
319
320         gboolean
321         eject() {
322             return device_eject(self);
323         }
324
325         gboolean
326         directtcp_supported() {
327             return device_directtcp_supported(self);
328         }
329
330         void
331         listen(gboolean for_writing, DirectTCPAddr **addrs) {
332             /* ensure that the addresses are empty if there was an error */
333             if (!device_listen(self, for_writing, addrs))
334                 *addrs = NULL;
335         }
336
337         %newobject accept; /* connection is already ref'd, so we own it */
338         DirectTCPConnection *
339         accept() {
340             DirectTCPConnection *conn = NULL;
341             gboolean rv;
342
343             rv = device_accept(self, &conn, NULL, NULL);
344             if (!rv && conn) {
345                 /* conn is ref'd for our convenience, but we don't want it */
346                 g_object_unref(conn);
347                 conn = NULL;
348             }
349             return conn;
350         }
351
352         %newobject connect; /* connection is already ref'd, so we own it */
353         DirectTCPConnection *
354         connect(gboolean for_writing, DirectTCPAddr *addrs) {
355             DirectTCPConnection *conn = NULL;
356             gboolean rv;
357
358             rv = device_connect(self, for_writing, addrs, &conn, NULL, NULL);
359             if (!rv && conn) {
360                 /* conn is ref'd for our convenience, but we don't want it */
361                 g_object_unref(conn);
362                 conn = NULL;
363             }
364             return conn;
365         }
366
367         gboolean
368         use_connection(DirectTCPConnection *conn) {
369             return device_use_connection(self, conn);
370         }
371
372         %typemap(in,numinputs=0) guint64 *actual_size (guint64 sz) {
373             sz = 0;
374             $1 = &sz;
375         }
376         %typemap(argout) guint64 *actual_size {
377             SP += argvi; PUTBACK;
378             $result = sv_2mortal(amglue_newSVu64(*$1));
379             SPAGAIN; SP -= argvi; argvi++;
380         }
381         gboolean
382         write_from_connection(guint64 size, guint64 *actual_size) {
383             return device_write_from_connection(self, size, actual_size);
384         }
385
386         gboolean
387         read_to_connection(guint64 size, guint64 *actual_size) {
388             return device_read_to_connection(self, size, actual_size);
389         }
390
391         %typemap(out) const GSList * {
392             GSList *iter;
393
394             /* Count the DeviceProperties */
395             EXTEND(SP, g_slist_length($1)); /* make room for return values */
396
397             /* Note that we set $result several times. the nature of
398              * SWIG's wrapping is such that incrementing argvi points
399              * $result to the next location in perl's argument stack.
400              */
401
402             for (iter = $1; iter; iter = g_slist_next(iter)) {
403                 DeviceProperty *prop = iter->data;
404                 HV *hash = newHV();
405                 SV *rv = newRV_noinc((SV *)hash);
406
407                 hv_store(hash, "name", 4,
408                         newSVpv(prop->base->name, 0), 0);
409                 hv_store(hash, "description", 11,
410                         newSVpv(prop->base->description, 0), 0);
411                 hv_store(hash, "access", 6,
412                         newSViv(prop->access), 0);
413                 $result = sv_2mortal(rv);
414                 argvi++;
415             }
416         }
417         const GSList * property_list(void) {
418             return device_property_get_list(self);
419         }
420
421         %typemap(out) const GSList *; /* remove typemap */
422
423         /* A typemap to convert a property name to a DevicePropertyBase. */
424         %typemap(in) DevicePropertyBase * {
425             char *pname = NULL;
426
427             if (SvPOK($input))
428                 pname = SvPV_nolen($input);
429
430             if (pname)
431                 $1 = (DevicePropertyBase *)device_property_get_by_name(pname);
432             else
433                 $1 = NULL;
434         }
435
436         /* A typemap to convert the GValue in property_get to a return value.  The
437          * (in) typemap sets up storage for the parameters, while the (argout) converts
438          * them to a perl SV. */
439         %typemap(in,numinputs=0) (GValue *out_val, PropertySurety *surety,
440                                   PropertySource *source, gboolean *val_found)
441                             (GValue val,
442                              PropertySurety surety,
443                              PropertySource source,
444                              gboolean found) {
445             memset(&val, 0, sizeof(val));
446             $1 = &val;
447             if (GIMME_V == G_ARRAY) {
448                 $2 = &surety;
449                 $3 = &source;
450             }
451             $4 = &found;
452         }
453         %typemap(argout) (GValue *out_val, PropertySurety *surety,
454                           PropertySource *source, gboolean *val_found) {
455             /* if the result is valid */
456             if (*$4) {
457                 /* move data from $1 to $result, somehow, being careful to
458                  * save the perl stack while doing so */
459                 SP += argvi; PUTBACK;
460                 $result = set_sv_from_gvalue($1);
461                 SPAGAIN; SP -= argvi; argvi++;
462
463                 /* free any memory for the GValue */
464                 g_value_unset($1);
465
466                 if (GIMME_V == G_ARRAY) {
467                     $result = newSViv(*$2);
468                     argvi++;
469                     $result = newSViv(*$3);
470                     argvi++;
471                 }
472             }
473             /* otherwise, return nothing */
474         }
475
476         void
477         property_get(DevicePropertyBase *pbase, GValue *out_val, PropertySurety *surety,
478                      PropertySource *source, gboolean *val_found) {
479             if (pbase) {
480                 *val_found = device_property_get_ex(self, pbase->ID, out_val, surety, source);
481             } else {
482                 *val_found = FALSE;
483             }
484         }
485
486         /* delete typemaps */
487         %typemap(in) (GValue *out_val, gboolean *val_found);
488         %typemap(argout) (GValue *out_val, gboolean *val_found);
489
490         /* We cheat a little bit here and just pass the native Perl type in to
491          * the function.  This is the easiest way to make sure we know the property
492          * information (in particular, its type) before trying to convert the SV.  */
493         %typemap(in) SV *sv "$1 = $input;"
494
495         gboolean
496         property_set(DevicePropertyBase *pbase, SV *sv) {
497             GValue gval;
498             memset(&gval, 0, sizeof(gval));
499             g_value_init(&gval, pbase->type);
500             if (!set_gvalue_from_sv(sv, &gval))
501                 goto fail;
502
503             if (!device_property_set(self, pbase->ID, &gval))
504                 goto fail;
505
506             g_value_unset(&gval);
507             return TRUE;
508         fail:
509             g_value_unset(&gval);
510             return FALSE;
511         }
512
513         gboolean
514         property_set_ex(DevicePropertyBase *pbase, SV *sv,
515                         PropertySurety surety, PropertySource source) {
516             GValue gval;
517             memset(&gval, 0, sizeof(gval));
518             g_value_init(&gval, pbase->type);
519             if (!set_gvalue_from_sv(sv, &gval))
520                 goto fail;
521
522             if (!device_property_set_ex(self, pbase->ID, &gval, surety, source))
523                 goto fail;
524
525             g_value_unset(&gval);
526             return TRUE;
527         fail:
528             g_value_unset(&gval);
529             return FALSE;
530         }
531
532         gboolean recycle_file(guint filenum) {
533             return device_recycle_file(self, filenum);
534         }
535
536         /* accessor functions */
537
538         int file(void) { return self->file; }
539         guint64 block(void) { return self->block; }
540         gboolean in_file(void) { return self->in_file; }
541         char * device_name(void) { return self->device_name; }
542         DeviceAccessMode access_mode(void) { return self->access_mode; }
543         gboolean is_eof(void) { return self->is_eof; }
544         gboolean is_eom(void) { return self->is_eom; }
545         char * volume_label(void) { return self->volume_label; }
546         char * volume_time(void) { return self->volume_time; }
547         DeviceStatusFlags status(void) { return self->status; }
548         gsize min_block_size(void) { return self->min_block_size; }
549         gsize max_block_size(void) { return self->max_block_size; }
550         gsize block_size(void) { return self->block_size; }
551         dumpfile_t *volume_header(void) { return self->volume_header; }
552     };
553
554 } Device;
555
556 /* An alternate constructor for RAIT devices */
557 %typemap(in) GSList *child_devices {
558     AV *av;
559     int i, len;
560
561     if (!SvROK($input) || SvTYPE(SvRV($input)) != SVt_PVAV) {
562         SWIG_exception(SWIG_TypeError, "Expected an arrayref");
563     }
564     av = (AV *)SvRV($input);
565
566     $1 = NULL;
567     len = av_len(av);
568     for (i = 0; i <= len; i++) {
569         SV **elt = av_fetch(av, i, 0);
570         Device *d;
571
572         if (elt && !SvOK(*elt)) {
573             $1 = g_slist_append($1, NULL); /* 'undef' => NULL */
574         } else if (!elt || SWIG_ConvertPtr(*elt, (void **)&d, $descriptor(Device *), 0) == -1) {
575             SWIG_exception(SWIG_TypeError, "array member is not a Device");
576         } else {
577             $1 = g_slist_append($1, d);
578         }
579     }
580 }
581 %typemap(freearg) GSList *child_devices {
582     g_slist_free($1);
583 }
584 %newobject rait_device_open_from_children;
585 Device *rait_device_open_from_children(GSList *child_devices);
586 %perlcode %{
587 sub new_rait_from_children {
588     my $class = shift; # strip the $class from the arguments
589     return rait_device_open_from_children([@_]);
590 }
591 %}
592
593 /*
594  * Utilities for installchecks (not described in POD)
595  */
596
597 %inline %{
598
599 /* write LENGTH bytes of random data to FILENAME, seeded with SEED */
600 gboolean
601 write_random_to_device(guint32 seed, size_t length, Device *device) {
602     simpleprng_state_t prng;
603     char *buf;
604     gsize block_size = device->block_size;
605     g_assert(block_size < G_MAXUINT);
606
607     buf = g_malloc(block_size);
608     simpleprng_seed(&prng, seed);
609
610     while (length) {
611         size_t to_write = min(block_size, length);
612
613         simpleprng_fill_buffer(&prng, buf, to_write);
614         if (!device_write_block(device, (guint)block_size, buf)) {
615             g_free(buf);
616             return FALSE;
617         }
618         length -= to_write;
619     }
620
621     g_free(buf);
622     return TRUE;
623 }
624
625 /* read LENGTH bytes of random data from FILENAME verifying it against
626  * a PRNG seeded with SEED.  Sends any error messages to stderr.
627  */
628 gboolean
629 verify_random_from_device(guint32 seed, size_t length, Device *device) {
630     simpleprng_state_t prng;
631     char *buf = NULL; /* first device_read_block will get the size */
632     int block_size = 0;
633
634     simpleprng_seed(&prng, seed);
635
636     while (length) {
637         int bytes_read;
638         int size = block_size;
639
640         bytes_read = device_read_block(device, buf, &size);
641         if (bytes_read == 0 && size > block_size) {
642             g_free(buf);
643             block_size = size;
644             buf = g_malloc(block_size);
645             continue;
646         }
647         if (bytes_read == -1) {
648             if (device->status == DEVICE_STATUS_SUCCESS) {
649                 g_assert(device->is_eof);
650                 g_debug("verify_random_from_device got unexpected EOF");
651             }
652             goto error;
653         }
654
655         /* strip padding */
656         bytes_read = min(bytes_read, length);
657
658         if (!simpleprng_verify_buffer(&prng, buf, bytes_read))
659             goto error;
660
661         length -= bytes_read;
662     }
663
664     g_free(buf);
665     return TRUE;
666
667 error:
668     g_free(buf);
669     return FALSE;
670 }
671 %}
672
673 /*
674  * Constants
675  */
676
677 amglue_add_flag_tag_fns(DeviceAccessMode);
678 amglue_add_constant_short(ACCESS_NULL, "NULL", DeviceAccessMode);
679 amglue_add_constant_short(ACCESS_READ, "READ", DeviceAccessMode);
680 amglue_add_constant_short(ACCESS_WRITE, "WRITE", DeviceAccessMode);
681 amglue_add_constant_short(ACCESS_APPEND, "APPEND", DeviceAccessMode);
682
683 /* (this is really a macro, but SWIG will Do The Right Thing */
684 gboolean IS_WRITABLE_ACCESS_MODE(DeviceAccessMode mode);
685 amglue_export_tag(DeviceAccessMode, IS_WRITABLE_ACCESS_MODE);
686 amglue_copy_to_tag(DeviceAccessMode, constants);
687
688 amglue_add_flag_tag_fns(DeviceStatusFlags);
689 amglue_add_constant_short(DEVICE_STATUS_SUCCESS, "SUCCESS", DeviceStatusFlags);
690 amglue_add_constant_short(DEVICE_STATUS_DEVICE_ERROR, "DEVICE_ERROR", DeviceStatusFlags);
691 amglue_add_constant_short(DEVICE_STATUS_DEVICE_BUSY, "DEVICE_BUSY", DeviceStatusFlags);
692 amglue_add_constant_short(DEVICE_STATUS_VOLUME_MISSING, "VOLUME_MISSING", DeviceStatusFlags);
693 amglue_add_constant_short(DEVICE_STATUS_VOLUME_UNLABELED, "VOLUME_UNLABELED", DeviceStatusFlags);
694 amglue_add_constant_short(DEVICE_STATUS_VOLUME_ERROR, "VOLUME_ERROR", DeviceStatusFlags);
695 amglue_add_constant_noshort(DEVICE_STATUS_FLAGS_MAX, DeviceStatusFlags);
696 amglue_copy_to_tag(DeviceStatusFlags, constants);
697
698 amglue_add_flag_tag_fns(PropertyPhaseFlags);
699 amglue_add_constant_short(PROPERTY_PHASE_BEFORE_START, "BEFORE_START", PropertyPhaseFlags);
700 amglue_add_constant_short(PROPERTY_PHASE_BETWEEN_FILE_WRITE, "BETWEEN_FILE_WRITE", PropertyPhaseFlags);
701 amglue_add_constant_short(PROPERTY_PHASE_INSIDE_FILE_WRITE, "INSIDE_FILE_WRITE", PropertyPhaseFlags);
702 amglue_add_constant_short(PROPERTY_PHASE_BETWEEN_FILE_READ, "BETWEEN_FILE_READ", PropertyPhaseFlags);
703 amglue_add_constant_short(PROPERTY_PHASE_INSIDE_FILE_READ, "INSIDE_FILE_READ", PropertyPhaseFlags);
704 amglue_add_constant_noshort(PROPERTY_PHASE_MAX, PropertyPhaseFlags);
705 amglue_add_constant_noshort(PROPERTY_PHASE_MASK, PropertyPhaseFlags);
706 amglue_add_constant_noshort(PROPERTY_PHASE_SHIFT, PropertyPhaseFlags);
707 amglue_copy_to_tag(PropertyPhaseFlags, constants);
708
709 amglue_add_flag_tag_fns(PropertyAccessFlags);
710 amglue_add_constant_short(PROPERTY_ACCESS_GET_BEFORE_START,
711                     "GET_BEFORE_START", PropertyAccessFlags);
712 amglue_add_constant_short(PROPERTY_ACCESS_GET_BETWEEN_FILE_WRITE,
713                     "GET_BETWEEN_FILE_WRITE", PropertyAccessFlags);
714 amglue_add_constant_short(PROPERTY_ACCESS_GET_INSIDE_FILE_WRITE,
715                     "GET_INSIDE_FILE_WRITE", PropertyAccessFlags);
716 amglue_add_constant_short(PROPERTY_ACCESS_GET_BETWEEN_FILE_READ,
717                     "GET_BETWEEN_FILE_READ", PropertyAccessFlags);
718 amglue_add_constant_short(PROPERTY_ACCESS_GET_INSIDE_FILE_READ,
719                     "GET_INSIDE_FILE_READ", PropertyAccessFlags);
720 amglue_add_constant_short(PROPERTY_ACCESS_SET_BEFORE_START,
721                     "SET_BEFORE_START", PropertyAccessFlags);
722 amglue_add_constant_short(PROPERTY_ACCESS_SET_BETWEEN_FILE_WRITE,
723                     "SET_BETWEEN_FILE_WRITE", PropertyAccessFlags);
724 amglue_add_constant_short(PROPERTY_ACCESS_SET_INSIDE_FILE_WRITE,
725                     "SET_INSIDE_FILE_WRITE", PropertyAccessFlags);
726 amglue_add_constant_short(PROPERTY_ACCESS_SET_BETWEEN_FILE_READ,
727                     "SET_BETWEEN_FILE_READ", PropertyAccessFlags);
728 amglue_add_constant_short(PROPERTY_ACCESS_SET_INSIDE_FILE_READ,
729                     "SET_INSIDE_FILE_READ", PropertyAccessFlags);
730 amglue_add_constant_noshort(PROPERTY_ACCESS_GET_MASK, PropertyAccessFlags);
731 amglue_add_constant_noshort(PROPERTY_ACCESS_SET_MASK, PropertyAccessFlags);
732 amglue_copy_to_tag(PropertyAccessFlags, constants);
733
734 amglue_add_enum_tag_fns(ConcurrencyParadigm);
735 amglue_add_constant_short(CONCURRENCY_PARADIGM_EXCLUSIVE, "EXCLUSIVE", ConcurrencyParadigm);
736 amglue_add_constant_short(CONCURRENCY_PARADIGM_SHARED_READ, "SHARED_READ", ConcurrencyParadigm);
737 amglue_add_constant_short(CONCURRENCY_PARADIGM_RANDOM_ACCESS, "RANDOM_ACCESS", ConcurrencyParadigm);
738 amglue_copy_to_tag(ConcurrencyParadigm, constants);
739
740 amglue_add_enum_tag_fns(StreamingRequirement);
741 amglue_add_constant_short(STREAMING_REQUIREMENT_NONE, "NONE", StreamingRequirement);
742 amglue_add_constant_short(STREAMING_REQUIREMENT_DESIRED, "DESIRED", StreamingRequirement);
743 amglue_add_constant_short(STREAMING_REQUIREMENT_REQUIRED, "REQUIRED", StreamingRequirement);
744 amglue_copy_to_tag(StreamingRequirement, constants);
745
746 amglue_add_enum_tag_fns(MediaAccessMode);
747 amglue_add_constant_short(MEDIA_ACCESS_MODE_READ_ONLY, "READ_ONLY", MediaAccessMode);
748 amglue_add_constant_short(MEDIA_ACCESS_MODE_WORM, "WORM", MediaAccessMode);
749 amglue_add_constant_short(MEDIA_ACCESS_MODE_READ_WRITE, "READ_WRITE", MediaAccessMode);
750 amglue_add_constant_short(MEDIA_ACCESS_MODE_WRITE_ONLY, "WRITE_ONLY", MediaAccessMode);
751 amglue_copy_to_tag(MediaAccessMode, constants);
752
753 amglue_add_flag_tag_fns(PropertySurety);
754 amglue_add_constant_short(PROPERTY_SURETY_BAD, "SURETY_BAD", PropertySurety);
755 amglue_add_constant_short(PROPERTY_SURETY_GOOD, "SURETY_GOOD", PropertySurety);
756 amglue_copy_to_tag(PropertySurety, constants);
757
758 amglue_add_flag_tag_fns(PropertySource);
759 amglue_add_constant_short(PROPERTY_SOURCE_DEFAULT, "SOURCE_DEFAULT", PropertySource);
760 amglue_add_constant_short(PROPERTY_SOURCE_DETECTED, "SOURCE_DETECTED", PropertySource);
761 amglue_add_constant_short(PROPERTY_SOURCE_USER, "SOURCE_USER", PropertySource);
762 amglue_copy_to_tag(PropertySource, constants);
763
764 %perlcode %{
765
766 # SWIG produces a sub-package for the Device "class", in this case named
767 # Amanda::Device::Device.  For user convenience, we allow Amanda::Device->new(..) to
768 # do the same thing.  This is a wrapper function, and not just a typeglob assignment,
769 # because we want to get the right blessing.
770 sub new {
771     my $pkg = shift;
772     Amanda::Device::Device->new(@_);
773 }
774 %}