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