eefa4acd1c84f9c6cf379b5c6758acf51c2cf240
[debian/amanda] / device-src / null-device.c
1 /*
2  * Copyright (c) 2005-2008 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., 465 S Mathlida Ave, Suite 300
18  * Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
19  */
20
21 #include "amanda.h"
22 #include "device.h"
23
24 #define NULL_DEVICE_MIN_BLOCK_SIZE (1)
25 #define NULL_DEVICE_MAX_BLOCK_SIZE (INT_MAX)
26 #define NULL_DEVICE_DEFAULT_BLOCK_SIZE DISK_BLOCK_BYTES
27
28 /*
29  * Type checking and casting macros
30  */
31 #define TYPE_NULL_DEVICE        (null_device_get_type())
32 #define NULL_DEVICE(obj)        G_TYPE_CHECK_INSTANCE_CAST((obj), null_device_get_type(), NullDevice)
33 #define NULL_DEVICE_CONST(obj)  G_TYPE_CHECK_INSTANCE_CAST((obj), null_device_get_type(), NullDevice const)
34 #define NULL_DEVICE_CLASS(klass)        G_TYPE_CHECK_CLASS_CAST((klass), null_device_get_type(), NullDeviceClass)
35 #define IS_NULL_DEVICE(obj)     G_TYPE_CHECK_INSTANCE_TYPE((obj), null_device_get_type ())
36 #define NULL_DEVICE_GET_CLASS(obj)      G_TYPE_INSTANCE_GET_CLASS((obj), null_device_get_type(), NullDeviceClass)
37 static GType null_device_get_type (void);
38
39 /*
40  * Main object structure
41  */
42 typedef struct _NullDevice NullDevice;
43 struct _NullDevice {
44         Device __parent__;
45 };
46
47 /*
48  * Class definition
49  */
50 typedef struct _NullDeviceClass NullDeviceClass;
51 struct _NullDeviceClass {
52     DeviceClass __parent__;
53     gboolean in_file;
54 };
55
56 void null_device_register(void);
57
58 /* here are local prototypes */
59 static void null_device_init (NullDevice * o);
60 static void null_device_class_init (NullDeviceClass * c);
61 static void null_device_base_init (NullDeviceClass * c);
62 static DeviceStatusFlags null_device_read_label(Device * dself);
63 static void null_device_open_device(Device * self, char *device_name,
64                                     char * device_type, char * device_node);
65 static gboolean null_device_start (Device * self, DeviceAccessMode mode,
66                                    char * label, char * timestamp);
67 static gboolean null_device_finish (Device * pself);
68 static gboolean null_device_start_file(Device * self, dumpfile_t * jobInfo);
69 static gboolean null_device_write_block (Device * self, guint size, gpointer data);
70 static gboolean null_device_finish_file(Device * self);
71 static Device* null_device_factory(char * device_name, char * device_type, char * device_node);
72
73 /* pointer to the class of our parent */
74 static DeviceClass *parent_class = NULL;
75
76 void null_device_register(void) {
77     static const char * device_prefix_list[] = { "null", NULL };
78     register_device(null_device_factory, device_prefix_list);
79 }
80
81 static GType
82 null_device_get_type (void)
83 {
84     static GType type = 0;
85     
86     if G_UNLIKELY(type == 0) {
87         static const GTypeInfo info = {
88             sizeof (NullDeviceClass),
89             (GBaseInitFunc) null_device_base_init,
90             (GBaseFinalizeFunc) NULL,
91             (GClassInitFunc) null_device_class_init,
92             (GClassFinalizeFunc) NULL,
93             NULL /* class_data */,
94             sizeof (NullDevice),
95             0 /* n_preallocs */,
96             (GInstanceInitFunc) null_device_init,
97             NULL
98         };
99         
100         type = g_type_register_static (TYPE_DEVICE, "NullDevice", &info,
101                                        (GTypeFlags)0);
102     }
103
104     return type;
105 }
106
107 static void 
108 null_device_init (NullDevice * self)
109 {
110     Device * dself;
111     GValue response;
112
113     dself = (Device*)(self);
114     bzero(&response, sizeof(response));
115
116     /* Register properties */
117     g_value_init(&response, CONCURRENCY_PARADIGM_TYPE);
118     g_value_set_enum(&response, CONCURRENCY_PARADIGM_RANDOM_ACCESS);
119     device_set_simple_property(dself, PROPERTY_CONCURRENCY,
120             &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
121     g_value_unset(&response);
122
123     g_value_init(&response, STREAMING_REQUIREMENT_TYPE);
124     g_value_set_enum(&response, STREAMING_REQUIREMENT_NONE);
125     device_set_simple_property(dself, PROPERTY_STREAMING,
126             &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
127     g_value_unset(&response);
128
129     g_value_init(&response, G_TYPE_BOOLEAN);
130     g_value_set_boolean(&response, FALSE);
131     device_set_simple_property(dself, PROPERTY_APPENDABLE,
132             &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
133     g_value_unset(&response);
134
135     g_value_init(&response, G_TYPE_BOOLEAN);
136     g_value_set_boolean(&response, FALSE);
137     device_set_simple_property(dself, PROPERTY_PARTIAL_DELETION,
138             &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
139     g_value_unset(&response);
140
141     /* this device's canonical name is always "null:", regardless of
142      * the name the user supplies; note that we install the simple
143      * getter in null_device_class_init. */
144     g_value_init(&response, G_TYPE_STRING);
145     g_value_set_static_string(&response, "null:");
146     device_set_simple_property(dself, PROPERTY_CANONICAL_NAME,
147             &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DEFAULT);
148     g_value_unset(&response);
149
150     g_value_init(&response, MEDIA_ACCESS_MODE_TYPE);
151     g_value_set_enum(&response, MEDIA_ACCESS_MODE_WRITE_ONLY);
152     device_set_simple_property(dself, PROPERTY_MEDIUM_ACCESS_TYPE,
153             &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
154     g_value_unset(&response);
155 }
156
157 static void 
158 null_device_class_init (NullDeviceClass * c)
159 {
160     DeviceClass *device_class = (DeviceClass *)c;
161
162     parent_class = g_type_class_ref (TYPE_DEVICE);
163
164     device_class->read_label = null_device_read_label;
165     device_class->open_device = null_device_open_device;
166     device_class->start = null_device_start;
167     device_class->finish = null_device_finish;
168     device_class->start_file = null_device_start_file;
169     device_class->write_block = null_device_write_block;
170     device_class->finish_file = null_device_finish_file;
171 }
172
173 static void
174 null_device_base_init (NullDeviceClass * c)
175 {
176     DeviceClass *device_class = (DeviceClass *)c;
177
178     /* Our canonical name is simpler than most devices' */
179     device_class_register_property(device_class, PROPERTY_CANONICAL_NAME,
180             PROPERTY_ACCESS_GET_MASK,
181             device_simple_property_get_fn,
182             device_simple_property_set_fn);
183 }
184
185
186 static Device* null_device_factory(char * device_name, char * device_type, char * device_node) {
187     Device * device;
188     g_assert(0 == strcmp(device_type, "null"));
189     device = DEVICE(g_object_new(TYPE_NULL_DEVICE, NULL));
190     device_open_device(device, device_name, device_type, device_node);
191     return device;
192 }
193
194 /* Begin virtual function overrides */
195
196 static DeviceStatusFlags
197 null_device_read_label(Device * dself) {
198     if (device_in_error(dself)) return FALSE;
199
200     device_set_error(dself,
201         stralloc(_("Can't open NULL device for reading or appending.")),
202         DEVICE_STATUS_DEVICE_ERROR);
203     return FALSE;
204 }
205
206 static void
207 null_device_open_device(Device * pself, char *device_name,
208                         char * device_type, char * device_node)
209 {
210     pself->min_block_size = NULL_DEVICE_MIN_BLOCK_SIZE;
211     pself->max_block_size = NULL_DEVICE_MAX_BLOCK_SIZE;
212     pself->block_size = NULL_DEVICE_DEFAULT_BLOCK_SIZE;
213
214     if (parent_class->open_device) {
215         parent_class->open_device(pself, device_name, device_type, device_node);
216     }
217 }
218
219 static gboolean
220 null_device_start (Device * pself, DeviceAccessMode mode,
221                    char * label, char * timestamp) {
222     NullDevice * self;
223     self = NULL_DEVICE(pself);
224
225     if (device_in_error(self)) return FALSE;
226
227     pself->access_mode = mode;
228     pself->in_file = FALSE;
229
230     if (mode == ACCESS_WRITE) {
231         pself->volume_label = newstralloc(pself->volume_label, label);
232         pself->volume_time = newstralloc(pself->volume_time, timestamp);
233         return TRUE;
234     } else {
235         device_set_error(pself,
236             stralloc(_("Can't open NULL device for reading or appending.")),
237             DEVICE_STATUS_DEVICE_ERROR);
238         return FALSE;
239     }
240 }
241
242 /* This default implementation does very little. */
243 static gboolean
244 null_device_finish (Device * pself) {
245     if (device_in_error(pself)) return FALSE;
246
247     pself->access_mode = ACCESS_NULL;
248     return TRUE;
249 }
250
251 static gboolean
252 null_device_start_file(Device * d_self,
253                     dumpfile_t * jobInfo G_GNUC_UNUSED)
254 {
255     d_self->in_file = TRUE;
256     d_self->block = 0;
257     if (d_self->file <= 0)
258         d_self->file = 1;
259     else
260         d_self->file ++;
261
262     return TRUE;
263 }
264
265 static gboolean
266 null_device_write_block (Device * pself, guint size G_GNUC_UNUSED,
267             gpointer data G_GNUC_UNUSED) {
268     NullDevice * self;
269     self = NULL_DEVICE(pself);
270
271     if (device_in_error(self)) return FALSE;
272
273     pself->block++;
274
275     return TRUE;
276 }
277
278 static gboolean
279 null_device_finish_file(Device * pself) {
280     if (device_in_error(pself)) return FALSE;
281
282     pself->in_file = FALSE;
283     return TRUE;
284 }