a6b1a0256af0e1d8884e0479bc4eeba890bf858b
[debian/amanda] / device-src / null-device.c
1 /*
2  * Copyright (c) 2005 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 as 
6  * 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 #include "amanda.h"
22 #include "device.h"
23 #include "null-device.h"
24
25 #define NULL_DEVICE_MIN_BLOCK_SIZE (1)
26 #define NULL_DEVICE_MAX_BLOCK_SIZE SHRT_MAX
27
28 /* here are local prototypes */
29 static void null_device_init (NullDevice * o);
30 static void null_device_class_init (NullDeviceClass * c);
31 static gboolean null_device_start (Device * self, DeviceAccessMode mode,
32                                    char * label, char * timestamp);
33 static gboolean null_device_write_block (Device * self, guint size,
34                                          gpointer data, gboolean last);
35 static Device* null_device_factory(char * device_type,
36                                    char * device_name);
37
38 /* pointer to the class of our parent */
39 static DeviceClass *parent_class = NULL;
40
41 void null_device_register(void) {
42     static const char * device_prefix_list[] = { "null", NULL };
43     register_device(null_device_factory, device_prefix_list);
44 }
45
46 GType
47 null_device_get_type (void)
48 {
49     static GType type = 0;
50     
51     if G_UNLIKELY(type == 0) {
52         static const GTypeInfo info = {
53             sizeof (NullDeviceClass),
54             (GBaseInitFunc) NULL,
55             (GBaseFinalizeFunc) NULL,
56             (GClassInitFunc) null_device_class_init,
57             (GClassFinalizeFunc) NULL,
58             NULL /* class_data */,
59             sizeof (NullDevice),
60             0 /* n_preallocs */,
61             (GInstanceInitFunc) null_device_init,
62             NULL
63         };
64         
65         type = g_type_register_static (TYPE_DEVICE, "NullDevice", &info,
66                                        (GTypeFlags)0);
67     }
68
69     return type;
70 }
71
72 static void 
73 null_device_init (NullDevice * self)
74 {
75     Device * o;
76     DeviceProperty prop;
77     GValue response;
78
79     o = (Device*)(self);
80     bzero(&response, sizeof(response));
81
82     /* Register properties */
83     prop.base = &device_property_concurrency;
84     prop.access = PROPERTY_ACCESS_GET_MASK;
85     g_value_init(&response, CONCURRENCY_PARADIGM_TYPE);
86     g_value_set_enum(&response, CONCURRENCY_PARADIGM_RANDOM_ACCESS);
87     device_add_property(o, &prop, &response);
88     g_value_unset(&response);
89     
90
91     prop.base = &device_property_streaming;
92     g_value_init(&response, STREAMING_REQUIREMENT_TYPE);
93     g_value_set_enum(&response, STREAMING_REQUIREMENT_NONE);
94     device_add_property(o, &prop, &response);
95     g_value_unset(&response);
96     
97     prop.base = &device_property_block_size;
98     g_value_init(&response, G_TYPE_INT);
99     g_value_set_int(&response, -1);
100     device_add_property(o, &prop, &response);
101     g_value_unset(&response);
102     
103     prop.base = &device_property_min_block_size;
104     g_value_init(&response, G_TYPE_UINT);
105     g_value_set_uint(&response, NULL_DEVICE_MIN_BLOCK_SIZE);
106     device_add_property(o, &prop, &response);
107
108     prop.base = &device_property_max_block_size;
109     g_value_set_uint(&response, NULL_DEVICE_MAX_BLOCK_SIZE);
110     device_add_property(o, &prop, &response);
111     g_value_unset(&response);
112
113     prop.base = &device_property_appendable;
114     g_value_init(&response, G_TYPE_BOOLEAN);
115     g_value_set_boolean(&response, FALSE);
116     device_add_property(o, &prop, &response);
117
118     prop.base = &device_property_partial_deletion;
119     device_add_property(o, &prop, &response);
120     g_value_unset(&response);
121
122     prop.base = &device_property_canonical_name;
123     g_value_init(&response, G_TYPE_STRING);
124     g_value_set_static_string(&response, "null:");
125     device_add_property(o, &prop, &response);
126     g_value_unset(&response);
127
128     prop.base = &device_property_medium_access_type;
129     g_value_init(&response, MEDIA_ACCESS_MODE_TYPE);
130     g_value_set_enum(&response, MEDIA_ACCESS_MODE_WRITE_ONLY);
131     device_add_property(o, &prop, &response);
132     g_value_unset(&response);
133 }
134
135 static void 
136 null_device_class_init (NullDeviceClass * c G_GNUC_UNUSED)
137 {
138     DeviceClass *device_class = (DeviceClass *)c;
139
140     parent_class = g_type_class_ref (TYPE_DEVICE);
141
142     device_class->start = null_device_start;
143     device_class->write_block = null_device_write_block;
144 }
145
146
147 static Device* null_device_factory(char * device_type,
148                                    char * device_name G_GNUC_UNUSED) {
149     g_assert(0 == strcmp(device_type, "null"));
150     return DEVICE(g_object_new(TYPE_NULL_DEVICE, NULL));
151     
152 }
153
154 /* Begin virtual function overrides */
155
156 static gboolean 
157 null_device_start (Device * pself, DeviceAccessMode mode,
158                    char * label, char * timestamp) {
159     NullDevice * self;
160     self = NULL_DEVICE(pself);
161     g_return_val_if_fail (self != NULL, FALSE);
162
163     if (mode == ACCESS_WRITE) {
164         if (parent_class->start) {
165             return parent_class->start((Device*)self, mode, label, timestamp);
166         } else {
167             return TRUE;
168         }
169     } else {
170         g_fprintf(stderr, "Can't open NULL device for reading or appending.\n");
171         return FALSE;
172     }
173 }
174
175 static gboolean
176 null_device_write_block (Device * pself, guint size, gpointer data,
177                          gboolean last_block) {
178     NullDevice * self;
179     self = NULL_DEVICE(pself);
180     g_return_val_if_fail (self != NULL, FALSE);
181     g_return_val_if_fail (data != NULL, FALSE);
182     
183     if ((size < NULL_DEVICE_MIN_BLOCK_SIZE && !last_block) ||
184         size > NULL_DEVICE_MAX_BLOCK_SIZE) {
185         return FALSE;
186     } else {
187         if (parent_class->write_block) {
188             /* Calls device_finish_file(). */
189             parent_class->write_block((Device*)self, size, data, last_block);
190         }
191         return TRUE;
192     }
193
194     g_assert_not_reached();
195 }