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