Imported Upstream version 2.6.0p2
[debian/amanda] / perl / Amanda / Device.swg
1 /*
2  * Copyright (c) Zmanda, Inc.  All Rights Reserved.
3  *
4  * This library is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License version 2.1
6  * as published by the Free Software Foundation.
7  *
8  * This library 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 Lesser General Public
11  * License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this library; if not, write to the Free Software Foundation,
15  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
16  *
17  * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120
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
25 %{
26 #include "device.h"
27 #include "property.h"
28 #include "fileheader.h"
29 %}
30
31 /* import dumptype_t, among others */
32 %import "Amanda/Types.swg";
33
34 %perlcode %{
35 =head1 NAME
36
37 Amanda::Device - interact with Amanda data-storage devices
38
39 =head1 SYNOPSIS
40
41   use Amanda::Device qw( :constants );
42
43   my $dev = Amanda::Device->new($device_name);
44   $dev->set_startup_properties_from_config();
45   if ($dev->read_label() == $READ_LABEL_STATUS_SUCCESS) {
46       print "Label on $device_name is '$dev->volume_label'\n";
47   }
48   
49 See http://wiki.zmanda.com/index.php/Device_API for details on how Devices are used.
50
51 =head1 API STATUS
52
53 Stable
54
55 =head1 Amanda::Device Objects
56
57 =head2 Instance Variables
58
59 =over
60
61 =item C<$file>
62
63 =item C<$block>
64
65 =item C<$in_file>
66
67 =item C<$device_name>
68
69 =item C<$access_mode>
70
71 =item C<$is_eof>
72
73 =item C<$volume_label>
74
75 =item C<$volume_time>
76
77 =back
78
79 =head2 Methods
80
81 See the wiki for descriptions of these functions
82
83 =over
84
85 =item C<read_label()>
86
87 =item C<start($mode, $label, $timestamp)>
88
89 =item C<finish()>
90
91 =item C<start_file($jobinfo)>
92
93 where C<$jobinfo> is a C<dumpfile_t> (see L<Amanda::Datatypes>)
94
95 =item C<write_min_size()>
96
97 =item C<write_max_size()>
98
99 =item C<read_max_size()>
100
101 =item C<write_block($size, $data, $short_block)>
102
103 Note that Perl code is not expected to handle on-device data, so there
104 is currently no way to provide data to this function from Perl.  This may
105 change in future revisions.
106
107 =item C<write_from_fd($fd)>
108
109 where C<$fd> is an integer file descriptor, not a filehandle
110
111 =item C<finish_file()>
112
113 =item C<seek_file($file)>
114
115 =item C<seek_block($block)>
116
117 =item C<read_block($size)>
118
119 =item C<read_to_fd($fd)>
120
121 where C<$fd> is an integer file descriptor, not a filehandle
122
123 Note that Perl code is not expected to handle on-device data, so there
124 is currently no way to access the data this function returns.  This may
125 change in future revisions.
126
127 =item C<property_list()>
128
129 returns a list of property names.
130
131 =item C<property_get($property_name)>
132
133 returns the property as the appropriate Perl type.
134
135 =item C<property_set($property_name, $value)>
136
137 where $value is of an appropriate type for the given property
138
139 =item C<recycle_file($filenum)>
140
141 =item C<set_startup_properties_from_config()>
142
143 =back
144
145 =head1 CONSTANTS
146
147 This module defines a large number of constants.  Again, consult the
148 wiki or C<device.h> for the details on their meaning.  These constants
149 are available from the package namespace (e.g.,
150 C<Amanda::Device::ACCESS_WRITE>), of imported with the C<:constant>
151 import tag.
152
153 =cut
154 %}
155
156 %init %{
157     /* Initialize the Device API on load */
158     device_api_init();
159 %}
160
161 %{
162
163 /* Utility functions for typemaps, below */
164
165 static SV *
166 set_sv_from_gvalue(GValue *value)
167 {
168     GType fundamental = G_TYPE_FUNDAMENTAL(G_VALUE_TYPE(value));
169     SV *sv = NULL;
170
171     /* complex reference types */
172     switch (fundamental) {
173         case G_TYPE_LONG:
174             sv = sv_2mortal(amglue_newSVi64(g_value_get_long(value)));
175             break;
176
177         case G_TYPE_ULONG:
178             sv = sv_2mortal(amglue_newSVu64(g_value_get_ulong(value)));
179             break;
180
181         case G_TYPE_INT64:
182             sv = sv_2mortal(amglue_newSVi64(g_value_get_int64(value)));
183             break;
184
185         case G_TYPE_UINT64:
186             sv = sv_2mortal(amglue_newSVu64(g_value_get_uint64(value)));
187             break;
188
189         case G_TYPE_BOXED: {
190             GType boxed_type = G_VALUE_TYPE(value);
191             QualifiedSize qs;
192             HV *hv;
193
194             if (boxed_type == QUALIFIED_SIZE_TYPE) {
195                 qs = *(QualifiedSize*)(g_value_get_boxed(value));
196                 
197                 /* build a hash */
198                 hv = (HV *)sv_2mortal((SV *)newHV());
199                 hv_store(hv, "accuracy", 8, newSViv(qs.accuracy), 0);
200                 hv_store(hv, "bytes", 5, amglue_newSVi64(qs.bytes), 0);
201
202                 sv = newRV((SV *)hv);
203                 return newRV((SV *)hv);
204             } else {
205                 warn("Unsupported boxed property type #%d", boxed_type);
206
207                 sv = sv_newmortal();
208                 sv_setsv(sv, &PL_sv_undef);
209                 return sv;
210             }
211         }
212     }
213
214     /* simple types that can be constructed with sv_set*v */
215     sv = sv_newmortal();
216     switch (fundamental) {
217         case G_TYPE_CHAR:
218             sv_setiv(sv, g_value_get_char(value));
219             break;
220
221         case G_TYPE_UCHAR:
222             sv_setuv(sv, g_value_get_uchar(value));
223             break;
224
225         case G_TYPE_BOOLEAN:
226             sv_setiv(sv, g_value_get_boolean(value));
227             break;
228
229         case G_TYPE_INT:
230             sv_setiv(sv, g_value_get_int(value));
231             break;
232
233         case G_TYPE_UINT:
234             sv_setuv(sv, g_value_get_uint(value));
235             break;
236
237         case G_TYPE_FLOAT:
238             sv_setnv(sv, g_value_get_float(value));
239             break;
240
241         case G_TYPE_DOUBLE:
242             sv_setnv(sv, g_value_get_double(value));
243             break;
244
245         case G_TYPE_STRING:
246             sv_setpv(sv, g_value_get_string(value));
247             break;
248
249         case G_TYPE_ENUM:
250             sv_setiv(sv, g_value_get_enum(value));
251             break;
252
253         case G_TYPE_FLAGS:
254             sv_setiv(sv, g_value_get_flags(value));
255             break;
256
257         /* Unsupported */
258         default:
259         case G_TYPE_POINTER:
260         case G_TYPE_INTERFACE:
261         case G_TYPE_OBJECT:
262         case G_TYPE_PARAM:
263             warn("Unsupported fundamental property type #%d", fundamental);
264             sv_setsv(sv, &PL_sv_undef);
265             break;
266     }
267
268     return sv;
269 }
270
271 static gboolean
272 set_gvalue_from_sv(SV *sv, GValue *value)
273 {
274     GType fundamental = G_TYPE_FUNDAMENTAL(G_VALUE_TYPE(value));
275     switch (fundamental) {
276         case G_TYPE_CHAR:
277             if (!SvIOK(sv)) return FALSE;
278             g_value_set_char(value, SvIV(sv));
279             break;
280
281         case G_TYPE_UCHAR:
282             if (!SvIOK(sv)) return FALSE;
283             g_value_set_uchar(value, SvUV(sv));
284             break;
285
286         case G_TYPE_BOOLEAN:
287             if (!SvIOK(sv)) return FALSE;
288             g_value_set_boolean(value, SvIV(sv));
289             break;
290
291         case G_TYPE_INT:
292             g_value_set_int(value, amglue_SvI32(sv));
293             break;
294
295         case G_TYPE_UINT:
296             g_value_set_uint(value, amglue_SvU32(sv));
297             break;
298
299         case G_TYPE_LONG:
300             g_value_set_int64(value, amglue_SvI64(sv));
301             break;
302
303         case G_TYPE_ULONG:
304             g_value_set_uint64(value, amglue_SvU64(sv));
305             break;
306
307         case G_TYPE_INT64:
308             g_value_set_int64(value, amglue_SvI64(sv));
309             break;
310
311         case G_TYPE_UINT64:
312             g_value_set_uint64(value, amglue_SvU64(sv));
313             break;
314
315         case G_TYPE_FLOAT:
316             if (!SvNOK(sv)) return FALSE;
317             g_value_set_float(value, SvNV(sv));
318             break;
319
320         case G_TYPE_DOUBLE:
321             if (!SvNOK(sv)) return FALSE;
322             g_value_set_double(value, SvNV(sv));
323             break;
324
325         case G_TYPE_STRING:
326             if (!SvPOK(sv)) return FALSE;
327             g_value_set_string(value, SvPV_nolen(sv));
328             break;
329
330         case G_TYPE_ENUM: 
331             if (!SvIOK(sv)) return FALSE;
332             g_value_set_enum(value, SvIV(sv));
333             break;
334
335         case G_TYPE_FLAGS:
336             if (!SvIOK(sv)) return FALSE;
337             g_value_set_flags(value, SvIV(sv));
338             break;
339
340         /* Unsupported */
341         default:
342         case G_TYPE_POINTER:
343         case G_TYPE_INTERFACE:
344         case G_TYPE_BOXED: /* note: *getting* boxed values is supported */
345         case G_TYPE_OBJECT:
346         case G_TYPE_PARAM:
347             return FALSE;
348     }
349
350     return TRUE;
351 }
352
353 %}
354
355 /*
356  * Device struct, %extend-ed into a Perl class
357  */
358
359 typedef struct Device {
360     /* Instance variables -- all readonly */
361     %immutable;
362     int file;
363     guint64 block;
364     gboolean in_file;
365     char * device_name;
366     DeviceAccessMode access_mode;
367     gboolean is_eof;
368     char * volume_label;
369     char * volume_time;
370     %mutable;
371
372     /* methods */
373     %extend {
374         /* constructor */
375         Device(char *device_name) {
376             return device_open(device_name);
377         }
378
379         ~Device() {
380             g_object_unref(self);
381         }
382
383         ReadLabelStatusFlags
384         read_label() {
385             return device_read_label(self);
386         }
387
388         gboolean
389         start(DeviceAccessMode mode, char *label, char *timestamp) {
390             return device_start(self, mode, label, timestamp);
391         }
392
393         gboolean
394         finish() {
395             return device_finish(self);
396         }
397
398         gboolean
399         start_file(const dumpfile_t *jobInfo) {
400             return device_start_file(self, jobInfo);
401         }
402
403         guint
404         write_min_size() {
405             return device_write_min_size(self);
406         }
407
408         guint
409         write_max_size() {
410             return device_write_max_size(self);
411         }
412
413         guint
414         read_max_size() {
415             return device_read_max_size(self);
416         }
417
418         gboolean
419         write_block(guint size, gpointer data, gboolean short_block) {
420             return device_write_block(self, size, data, short_block);
421         }
422
423         gboolean
424         write_from_fd(int fd) {
425             return device_write_from_fd(self, fd);
426         }
427
428         gboolean
429         finish_file() {
430             return device_finish_file(self);
431         }
432
433         dumpfile_t*
434         seek_file(guint file) {
435             return device_seek_file(self, file);
436         }
437
438         gboolean
439         seek_block(guint64 block) {
440             return device_seek_block(self, block);
441         }
442
443         int
444         read_block(gpointer buffer, int *size) {
445             return device_read_block(self, buffer, size);
446         }
447
448         gboolean read_to_fd(int fd) {
449             return device_read_to_fd(self, fd);
450         }
451
452         %typemap(out) const DeviceProperty * {
453             int i = 0;
454             int len = 0;
455
456             /* Count the DeviceProperties */
457             while ($1[len].base) len++;
458             EXTEND(SP, len); /* make room for return values */
459
460             /* Note that we set $result several times. the nature of
461              * SWIG's wrapping is such that incrementing argvi points
462              * $result to the next location in perl's argument stack.
463              */
464
465             for (i = 0; i < len ; i++) { 
466                 $result = sv_newmortal(); 
467                 sv_setpv($result, $1[i].base->name); 
468                 argvi++;
469             }; 
470         }
471         const DeviceProperty * property_list(void) {
472             return device_property_get_list(self);
473         }
474
475         %typemap(out) const DeviceProperty *; /* remove typemap */
476
477         /* A typemap to convert a property name to a DevicePropertyBase. */
478         %typemap(in) DevicePropertyBase * {
479             char *pname = NULL;
480
481             if (SvPOK($input))
482                 pname = SvPV_nolen($input);
483
484             if (pname) $1 = (DevicePropertyBase *)device_property_get_by_name(pname);
485             if (!pname || !$1) {
486                 SWIG_exception_fail(SWIG_ValueError, "Invalid property name");
487             }
488         }
489
490         /* A typemap to convert the GValue in property_get to a return value.  The
491          * (in) typemap sets up storage for the parameters, while the (argout) converts
492          * them to a perl SV. */
493         %typemap(in,numinputs=0) (GValue *out_val, gboolean *val_found)
494                             (GValue val, gboolean found) {
495             memset(&val, 0, sizeof(val));
496             $1 = &val;
497             $2 = &found;
498         }
499         %typemap(argout) (GValue *out_val, gboolean *val_found) {
500             /* if the result is valid */
501             if (*$2) {
502                 /* move data from $1 to $result, somehow */
503                 $result = set_sv_from_gvalue($1);
504
505                 /* free any memory for the GValue */
506                 g_value_unset($1);
507             } else {
508                 /* silently return 'undef', the sentinel for "undefined" */
509                 $result = sv_newmortal();
510                 sv_setsv($result, &PL_sv_undef);
511             }
512             argvi++;
513         }
514
515         void
516         property_get(DevicePropertyBase *pbase, GValue *out_val, gboolean *val_found) {
517             *val_found = device_property_get(self, pbase->ID, out_val);
518         }
519
520         /* delete typemaps */
521         %typemap(in) (GValue *out_val, gboolean *val_found);
522         %typemap(argout) (GValue *out_val, gboolean *val_found);
523
524         /* We cheat a little bit here and just pass the native Perl type in to
525          * the function.  This is the easiest way to make sure we know the property
526          * information (in particular, its type) before trying to convert the SV.  */
527         %typemap(in) SV *sv "$1 = $input;"
528
529         gboolean
530         property_set(DevicePropertyBase *pbase, SV *sv) {
531             GValue gval;
532             memset(&gval, 0, sizeof(gval));
533             g_value_init(&gval, pbase->type);
534             if (!set_gvalue_from_sv(sv, &gval))
535                 goto fail;
536
537             if (!device_property_set(self, pbase->ID, &gval))
538                 goto fail;
539
540             g_value_unset(&gval);
541             return TRUE;
542         fail:
543             g_value_unset(&gval);
544             return FALSE;
545         }
546
547         gboolean recycle_file(guint filenum) {
548             return device_recycle_file(self, filenum);
549         }
550         
551         void set_startup_properties_from_config(void) {
552             device_set_startup_properties_from_config(self);
553         }
554     };
555 } Device;
556
557 /*
558  * Constants
559  */
560
561 amglue_add_flag_tag_fns(DeviceAccessMode);
562 amglue_add_constant_short(ACCESS_NULL, "NULL", DeviceAccessMode);
563 amglue_add_constant_short(ACCESS_READ, "READ", DeviceAccessMode);
564 amglue_add_constant_short(ACCESS_WRITE, "WRITE", DeviceAccessMode);
565 amglue_add_constant_short(ACCESS_APPEND, "APPEND", DeviceAccessMode);
566
567 /* (this is really a macro, but SWIG will Do The Right Thing */
568 gboolean IS_WRITABLE_ACCESS_MODE(DeviceAccessMode mode);
569 amglue_export_tag(DeviceAccessMode, IS_WRITABLE_ACCESS_MODE);
570 amglue_copy_to_tag(DeviceAccessMode, constants);
571
572 amglue_add_flag_tag_fns(ReadLabelStatusFlags);
573 amglue_add_constant_short(READ_LABEL_STATUS_SUCCESS, "SUCCESS", ReadLabelStatusFlags);
574 amglue_add_constant_short(READ_LABEL_STATUS_DEVICE_MISSING, "DEVICE_MISSING", ReadLabelStatusFlags);
575 amglue_add_constant_short(READ_LABEL_STATUS_DEVICE_ERROR, "DEVICE_ERROR", ReadLabelStatusFlags);
576 amglue_add_constant_short(READ_LABEL_STATUS_VOLUME_MISSING, "VOLUME_MISSING", ReadLabelStatusFlags);
577 amglue_add_constant_short(READ_LABEL_STATUS_VOLUME_UNLABELED, "VOLUME_UNLABELED", ReadLabelStatusFlags);
578 amglue_add_constant_short(READ_LABEL_STATUS_VOLUME_ERROR, "VOLUME_ERROR", ReadLabelStatusFlags);
579 amglue_add_constant_noshort(READ_LABEL_STATUS_FLAGS_MAX, ReadLabelStatusFlags);
580 amglue_copy_to_tag(ReadLabelStatusFlags, constants);
581
582 amglue_add_flag_tag_fns(PropertyPhaseFlags);
583 amglue_add_constant_short(PROPERTY_PHASE_BEFORE_START, "BEFORE_START", PropertyPhaseFlags);
584 amglue_add_constant_short(PROPERTY_PHASE_BETWEEN_FILE_WRITE, "BETWEEN_FILE_WRITE", PropertyPhaseFlags);
585 amglue_add_constant_short(PROPERTY_PHASE_INSIDE_FILE_WRITE, "INSIDE_FILE_WRITE", PropertyPhaseFlags);
586 amglue_add_constant_short(PROPERTY_PHASE_BETWEEN_FILE_READ, "BETWEEN_FILE_READ", PropertyPhaseFlags);
587 amglue_add_constant_short(PROPERTY_PHASE_INSIDE_FILE_READ, "INSIDE_FILE_READ", PropertyPhaseFlags);
588 amglue_add_constant_noshort(PROPERTY_PHASE_MAX, PropertyPhaseFlags);
589 amglue_add_constant_noshort(PROPERTY_PHASE_MASK, PropertyPhaseFlags);
590 amglue_add_constant_noshort(PROPERTY_PHASE_SHIFT, PropertyPhaseFlags);
591 amglue_copy_to_tag(PropertyPhaseFlags, constants);
592
593 amglue_add_flag_tag_fns(PropertyAccessFlags);
594 amglue_add_constant_short(PROPERTY_ACCESS_GET_BEFORE_START, 
595                     "GET_BEFORE_START", PropertyAccessFlags);
596 amglue_add_constant_short(PROPERTY_ACCESS_GET_BETWEEN_FILE_WRITE, 
597                     "GET_BETWEEN_FILE_WRITE", PropertyAccessFlags);
598 amglue_add_constant_short(PROPERTY_ACCESS_GET_INSIDE_FILE_WRITE, 
599                     "GET_INSIDE_FILE_WRITE", PropertyAccessFlags);
600 amglue_add_constant_short(PROPERTY_ACCESS_GET_BETWEEN_FILE_READ, 
601                     "GET_BETWEEN_FILE_READ", PropertyAccessFlags);
602 amglue_add_constant_short(PROPERTY_ACCESS_GET_INSIDE_FILE_READ, 
603                     "GET_INSIDE_FILE_READ", PropertyAccessFlags);
604 amglue_add_constant_short(PROPERTY_ACCESS_SET_BEFORE_START, 
605                     "SET_BEFORE_START", PropertyAccessFlags);
606 amglue_add_constant_short(PROPERTY_ACCESS_SET_BETWEEN_FILE_WRITE, 
607                     "SET_BETWEEN_FILE_WRITE", PropertyAccessFlags);
608 amglue_add_constant_short(PROPERTY_ACCESS_SET_INSIDE_FILE_WRITE, 
609                     "SET_INSIDE_FILE_WRITE", PropertyAccessFlags);
610 amglue_add_constant_short(PROPERTY_ACCESS_SET_BETWEEN_FILE_READ, 
611                     "SET_BETWEEN_FILE_READ", PropertyAccessFlags);
612 amglue_add_constant_short(PROPERTY_ACCESS_SET_INSIDE_FILE_READ, 
613                     "SET_INSIDE_FILE_READ", PropertyAccessFlags);
614 amglue_add_constant_noshort(PROPERTY_ACCESS_GET_MASK, PropertyAccessFlags);
615 amglue_add_constant_noshort(PROPERTY_ACCESS_SET_MASK, PropertyAccessFlags);
616 amglue_copy_to_tag(PropertyAccessFlags, constants);
617
618 amglue_add_enum_tag_fns(ConcurrencyParadigm);
619 amglue_add_constant_short(CONCURRENCY_PARADIGM_EXCLUSIVE, "EXCLUSIVE", ConcurrencyParadigm);
620 amglue_add_constant_short(CONCURRENCY_PARADIGM_SHARED_READ, "SHARED_READ", ConcurrencyParadigm);
621 amglue_add_constant_short(CONCURRENCY_PARADIGM_RANDOM_ACCESS, "RANDOM_ACCESS", ConcurrencyParadigm);
622 amglue_copy_to_tag(ConcurrencyParadigm, constants);
623
624 amglue_add_enum_tag_fns(StreamingRequirement);
625 amglue_add_constant_short(STREAMING_REQUIREMENT_NONE, "NONE", StreamingRequirement);
626 amglue_add_constant_short(STREAMING_REQUIREMENT_DESIRED, "DESIRED", StreamingRequirement);
627 amglue_add_constant_short(STREAMING_REQUIREMENT_REQUIRED, "REQUIRED", StreamingRequirement);
628 amglue_copy_to_tag(StreamingRequirement, constants);
629
630 amglue_add_enum_tag_fns(MediaAccessMode);
631 amglue_add_constant_short(MEDIA_ACCESS_MODE_READ_ONLY, "READ_ONLY", MediaAccessMode);
632 amglue_add_constant_short(MEDIA_ACCESS_MODE_WORM, "WORM", MediaAccessMode);
633 amglue_add_constant_short(MEDIA_ACCESS_MODE_READ_WRITE, "READ_WRITE", MediaAccessMode);
634 amglue_add_constant_short(MEDIA_ACCESS_MODE_WRITE_ONLY, "WRITE_ONLY", MediaAccessMode);
635 amglue_copy_to_tag(MediaAccessMode, constants);
636
637 amglue_add_enum_tag_fns(SizeAccuracy);
638 amglue_add_constant_short(SIZE_ACCURACY_UNKNOWN, "UNKNOWN", SizeAccuracy);
639 amglue_add_constant_short(SIZE_ACCURACY_ESTIMATE, "ESTIMATE", SizeAccuracy);
640 amglue_add_constant_short(SIZE_ACCURACY_REAL, "REAL", SizeAccuracy);
641 amglue_copy_to_tag(SizeAccuracy, constants);
642
643 amglue_add_flag_tag_fns(FeatureSupportFlags);
644 amglue_add_constant_short(FEATURE_STATUS_ENABLED, "STATUS_ENABLED", FeatureSupportFlags);
645 amglue_add_constant_short(FEATURE_STATUS_DISABLED, "STATUS_DISABLED", FeatureSupportFlags);
646 amglue_add_constant_short(FEATURE_SURETY_BAD, "SURETY_BAD", FeatureSupportFlags);
647 amglue_add_constant_short(FEATURE_SURETY_GOOD, "SURETY_GOOD", FeatureSupportFlags);
648 amglue_add_constant_short(FEATURE_SOURCE_DEFAULT, "SOURCE_DEFAULT", FeatureSupportFlags);
649 amglue_add_constant_short(FEATURE_SOURCE_DETECTED, "SOURCE_DETECTED", FeatureSupportFlags);
650 amglue_add_constant_short(FEATURE_SOURCE_USER, "SOURCE_USER", FeatureSupportFlags);
651 amglue_add_constant_noshort(FEATURE_SUPPORT_FLAGS_MAX, FeatureSupportFlags);
652 amglue_add_constant_noshort(FEATURE_SUPPORT_FLAGS_MASK, FeatureSupportFlags);
653 amglue_add_constant_noshort(FEATURE_SUPPORT_FLAGS_STATUS_MASK, FeatureSupportFlags);
654 amglue_add_constant_noshort(FEATURE_SUPPORT_FLAGS_SURETY_MASK, FeatureSupportFlags);
655 amglue_add_constant_noshort(FEATURE_SUPPORT_FLAGS_SOURCE_MASK, FeatureSupportFlags);
656
657 gboolean feature_support_flags_is_valid(FeatureSupportFlags);
658 amglue_export_tag(FeatureSupportFlags, feature_support_flags_is_valid);
659 amglue_copy_to_tag(FeatureSupportFlags, constants);
660
661 %perlcode %{
662
663 # SWIG produces a sub-package for the Device "class", in this case named 
664 # Amanda::Device::Device.  For user convenience, we allow Amanda::Device->new(..) to
665 # do the same thing.  This is a wrapper function, and not just a typeglob assignment,
666 # because we want to get the right blessing.
667 sub new {
668     my $pkg = shift;
669     Amanda::Device::Device->new(@_);
670 }
671 %}