613b972ac065ffcbc60d8f7a363b3b4e6cb2e15d
[debian/amanda] / xfer-src / filter-xor.c
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 2008 Zmanda Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19
20 #include "amxfer.h"
21 #include "amanda.h"
22
23 /*
24  * Class declaration
25  *
26  * This declaration is entirely private; nothing but xfer_filter_xor() references
27  * it directly.
28  */
29
30 GType xfer_filter_xor_get_type(void);
31 #define XFER_FILTER_XOR_TYPE (xfer_filter_xor_get_type())
32 #define XFER_FILTER_XOR(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), xfer_filter_xor_get_type(), XferFilterXor)
33 #define XFER_FILTER_XOR_CONST(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), xfer_filter_xor_get_type(), XferFilterXor const)
34 #define XFER_FILTER_XOR_CLASS(klass) G_TYPE_CHECK_CLASS_CAST((klass), xfer_filter_xor_get_type(), XferFilterXorClass)
35 #define IS_XFER_FILTER_XOR(obj) G_TYPE_CHECK_INSTANCE_TYPE((obj), xfer_filter_xor_get_type ())
36 #define XFER_FILTER_XOR_GET_CLASS(obj) G_TYPE_INSTANCE_GET_CLASS((obj), xfer_filter_xor_get_type(), XferFilterXorClass)
37
38 static GObjectClass *parent_class = NULL;
39
40 /*
41  * Main object structure
42  */
43
44 typedef struct XferFilterXor {
45     XferElement __parent__;
46
47     char xor_key;
48 } XferFilterXor;
49
50 /*
51  * Class definition
52  */
53
54 typedef struct {
55     XferElementClass __parent__;
56 } XferFilterXorClass;
57
58
59 /*
60  * Utilities
61  */
62
63 static void
64 apply_xor(
65     char *buf,
66     size_t len,
67     char xor_key)
68 {
69     size_t i;
70
71     /* Apply XOR.  This is a pretty sophisticated encryption algorithm! */
72     for (i = 0; i < len; i++) {
73         buf[i] ^= xor_key;
74     }
75 }
76
77 /*
78  * Implementation
79  */
80
81 static gpointer
82 pull_buffer_impl(
83     XferElement *elt,
84     size_t *size)
85 {
86     XferFilterXor *self = (XferFilterXor *)elt;
87     char *buf;
88
89     if (elt->cancelled) {
90         /* drain our upstream only if we're expecting an EOF */
91         if (elt->expect_eof) {
92             xfer_element_drain_by_pulling(XFER_ELEMENT(self)->upstream);
93         }
94
95         /* return an EOF */
96         *size = 0;
97         return NULL;
98     }
99
100     /* get a buffer from upstream, xor it, and hand it back */
101     buf = xfer_element_pull_buffer(XFER_ELEMENT(self)->upstream, size);
102     if (buf)
103         apply_xor(buf, *size, self->xor_key);
104     return buf;
105 }
106
107 static void
108 push_buffer_impl(
109     XferElement *elt,
110     gpointer buf,
111     size_t len)
112 {
113     XferFilterXor *self = (XferFilterXor *)elt;
114
115     /* drop the buffer if we've been cancelled */
116     if (elt->cancelled) {
117         amfree(buf);
118         return;
119     }
120
121     /* xor the given buffer and pass it downstream */
122     if (buf)
123         apply_xor(buf, len, self->xor_key);
124
125     xfer_element_push_buffer(XFER_ELEMENT(self)->downstream, buf, len);
126 }
127
128 static void
129 instance_init(
130     XferElement *elt)
131 {
132     elt->can_generate_eof = TRUE;
133 }
134
135 static void
136 class_init(
137     XferFilterXorClass * selfc)
138 {
139     XferElementClass *klass = XFER_ELEMENT_CLASS(selfc);
140     static xfer_element_mech_pair_t mech_pairs[] = {
141         { XFER_MECH_PULL_BUFFER, XFER_MECH_PULL_BUFFER, 1, 0},
142         { XFER_MECH_PUSH_BUFFER, XFER_MECH_PUSH_BUFFER, 1, 0},
143         { XFER_MECH_NONE, XFER_MECH_NONE, 0, 0},
144     };
145
146     klass->push_buffer = push_buffer_impl;
147     klass->pull_buffer = pull_buffer_impl;
148
149     klass->perl_class = "Amanda::Xfer::Filter::Xor";
150     klass->mech_pairs = mech_pairs;
151
152     parent_class = g_type_class_peek_parent(selfc);
153 }
154
155 GType
156 xfer_filter_xor_get_type (void)
157 {
158     static GType type = 0;
159
160     if G_UNLIKELY(type == 0) {
161         static const GTypeInfo info = {
162             sizeof (XferFilterXorClass),
163             (GBaseInitFunc) NULL,
164             (GBaseFinalizeFunc) NULL,
165             (GClassInitFunc) class_init,
166             (GClassFinalizeFunc) NULL,
167             NULL /* class_data */,
168             sizeof (XferFilterXor),
169             0 /* n_preallocs */,
170             (GInstanceInitFunc) instance_init,
171             NULL
172         };
173
174         type = g_type_register_static (XFER_ELEMENT_TYPE, "XferFilterXor", &info, 0);
175     }
176
177     return type;
178 }
179
180 /* create an element of this class; prototype is in xfer-element.h */
181 XferElement *
182 xfer_filter_xor(
183     unsigned char xor_key)
184 {
185     XferFilterXor *xfx = (XferFilterXor *)g_object_new(XFER_FILTER_XOR_TYPE, NULL);
186     XferElement *elt = XFER_ELEMENT(xfx);
187
188     xfx->xor_key = xor_key;
189
190     return elt;
191 }