2 * Copyright (c) 2007-2012 Zmanda, Inc. All Rights Reserved.
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.
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
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
17 * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
18 * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
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
29 * Type checking and casting macros
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);
40 * Main object structure
42 typedef struct _NullDevice NullDevice;
50 typedef struct _NullDeviceClass NullDeviceClass;
51 struct _NullDeviceClass {
52 DeviceClass __parent__;
55 void null_device_register(void);
57 /* here are local prototypes */
58 static void null_device_init (NullDevice * o);
59 static void null_device_class_init (NullDeviceClass * c);
60 static void null_device_base_init (NullDeviceClass * c);
61 static DeviceStatusFlags null_device_read_label(Device * dself);
62 static void null_device_open_device(Device * self, char *device_name,
63 char * device_type, char * device_node);
64 static gboolean null_device_start (Device * self, DeviceAccessMode mode,
65 char * label, char * timestamp);
66 static gboolean null_device_finish (Device * pself);
67 static gboolean null_device_start_file(Device * self, dumpfile_t * jobInfo);
68 static gboolean null_device_write_block (Device * self, guint size, gpointer data);
69 static gboolean null_device_finish_file(Device * self);
70 static Device* null_device_factory(char * device_name, char * device_type, char * device_node);
72 /* pointer to the class of our parent */
73 static DeviceClass *parent_class = NULL;
75 void null_device_register(void) {
76 static const char * device_prefix_list[] = { "null", NULL };
77 register_device(null_device_factory, device_prefix_list);
81 null_device_get_type (void)
83 static GType type = 0;
85 if G_UNLIKELY(type == 0) {
86 static const GTypeInfo info = {
87 sizeof (NullDeviceClass),
88 (GBaseInitFunc) null_device_base_init,
89 (GBaseFinalizeFunc) NULL,
90 (GClassInitFunc) null_device_class_init,
91 (GClassFinalizeFunc) NULL,
92 NULL /* class_data */,
95 (GInstanceInitFunc) null_device_init,
99 type = g_type_register_static (TYPE_DEVICE, "NullDevice", &info,
107 null_device_init (NullDevice * self)
112 dself = (Device*)(self);
113 bzero(&response, sizeof(response));
115 /* Register properties */
116 g_value_init(&response, CONCURRENCY_PARADIGM_TYPE);
117 g_value_set_enum(&response, CONCURRENCY_PARADIGM_RANDOM_ACCESS);
118 device_set_simple_property(dself, PROPERTY_CONCURRENCY,
119 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
120 g_value_unset(&response);
122 g_value_init(&response, STREAMING_REQUIREMENT_TYPE);
123 g_value_set_enum(&response, STREAMING_REQUIREMENT_NONE);
124 device_set_simple_property(dself, PROPERTY_STREAMING,
125 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
126 g_value_unset(&response);
128 g_value_init(&response, G_TYPE_BOOLEAN);
129 g_value_set_boolean(&response, FALSE);
130 device_set_simple_property(dself, PROPERTY_APPENDABLE,
131 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
132 g_value_unset(&response);
134 g_value_init(&response, G_TYPE_BOOLEAN);
135 g_value_set_boolean(&response, FALSE);
136 device_set_simple_property(dself, PROPERTY_PARTIAL_DELETION,
137 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
138 g_value_unset(&response);
140 g_value_init(&response, G_TYPE_BOOLEAN);
141 g_value_set_boolean(&response, FALSE);
142 device_set_simple_property(dself, PROPERTY_FULL_DELETION,
143 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
144 g_value_unset(&response);
146 g_value_init(&response, G_TYPE_BOOLEAN);
147 g_value_set_boolean(&response, FALSE);
148 device_set_simple_property(dself, PROPERTY_LEOM,
149 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
150 g_value_unset(&response);
152 /* this device's canonical name is always "null:", regardless of
153 * the name the user supplies; note that we install the simple
154 * getter in null_device_class_init. */
155 g_value_init(&response, G_TYPE_STRING);
156 g_value_set_static_string(&response, "null:");
157 device_set_simple_property(dself, PROPERTY_CANONICAL_NAME,
158 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DEFAULT);
159 g_value_unset(&response);
161 g_value_init(&response, MEDIA_ACCESS_MODE_TYPE);
162 g_value_set_enum(&response, MEDIA_ACCESS_MODE_WRITE_ONLY);
163 device_set_simple_property(dself, PROPERTY_MEDIUM_ACCESS_TYPE,
164 &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
165 g_value_unset(&response);
169 null_device_class_init (NullDeviceClass * c)
171 DeviceClass *device_class = (DeviceClass *)c;
173 parent_class = g_type_class_ref (TYPE_DEVICE);
175 device_class->read_label = null_device_read_label;
176 device_class->open_device = null_device_open_device;
177 device_class->start = null_device_start;
178 device_class->finish = null_device_finish;
179 device_class->start_file = null_device_start_file;
180 device_class->write_block = null_device_write_block;
181 device_class->finish_file = null_device_finish_file;
185 null_device_base_init (NullDeviceClass * c)
187 DeviceClass *device_class = (DeviceClass *)c;
189 /* Our canonical name is simpler than most devices' */
190 device_class_register_property(device_class, PROPERTY_CANONICAL_NAME,
191 PROPERTY_ACCESS_GET_MASK,
192 device_simple_property_get_fn,
193 device_simple_property_set_fn);
197 static Device* null_device_factory(char * device_name, char * device_type, char * device_node) {
199 g_assert(0 == strcmp(device_type, "null"));
200 device = DEVICE(g_object_new(TYPE_NULL_DEVICE, NULL));
201 device_open_device(device, device_name, device_type, device_node);
205 /* Begin virtual function overrides */
207 static DeviceStatusFlags
208 null_device_read_label(Device * dself) {
209 if (device_in_error(dself)) return FALSE;
211 device_set_error(dself,
212 stralloc(_("Can't open NULL device for reading or appending.")),
213 DEVICE_STATUS_DEVICE_ERROR);
218 null_device_open_device(Device * pself, char *device_name,
219 char * device_type, char * device_node)
221 pself->min_block_size = NULL_DEVICE_MIN_BLOCK_SIZE;
222 pself->max_block_size = NULL_DEVICE_MAX_BLOCK_SIZE;
223 pself->block_size = NULL_DEVICE_DEFAULT_BLOCK_SIZE;
225 if (parent_class->open_device) {
226 parent_class->open_device(pself, device_name, device_type, device_node);
231 null_device_start (Device * pself, DeviceAccessMode mode,
232 char * label, char * timestamp) {
234 self = NULL_DEVICE(pself);
236 if (device_in_error(self)) return FALSE;
238 pself->access_mode = mode;
239 g_mutex_lock(pself->device_mutex);
240 pself->in_file = FALSE;
241 g_mutex_unlock(pself->device_mutex);
243 if (mode == ACCESS_WRITE) {
244 pself->volume_label = newstralloc(pself->volume_label, label);
245 pself->volume_time = newstralloc(pself->volume_time, timestamp);
246 pself->header_block_size = 32768;
249 device_set_error(pself,
250 stralloc(_("Can't open NULL device for reading or appending.")),
251 DEVICE_STATUS_DEVICE_ERROR);
256 /* This default implementation does very little. */
258 null_device_finish (Device * pself) {
259 pself->access_mode = ACCESS_NULL;
261 if (device_in_error(pself)) return FALSE;
267 null_device_start_file(Device * d_self,
268 dumpfile_t * jobInfo G_GNUC_UNUSED)
270 g_mutex_lock(d_self->device_mutex);
271 d_self->in_file = TRUE;
272 g_mutex_unlock(d_self->device_mutex);
273 d_self->is_eom = FALSE;
275 if (d_self->file <= 0)
284 null_device_write_block (Device * pself, guint size G_GNUC_UNUSED,
285 gpointer data G_GNUC_UNUSED) {
287 self = NULL_DEVICE(pself);
289 if (device_in_error(self)) return FALSE;
297 null_device_finish_file(Device * pself) {
298 if (device_in_error(pself)) return FALSE;
300 g_mutex_lock(pself->device_mutex);
301 pself->in_file = FALSE;
302 g_mutex_unlock(pself->device_mutex);