~ed.so/duplicity/reuse-passphrase-for-signing-fix

« back to all changes in this revision

Viewing changes to duplicity/_librsyncmodule.c

  • Committer: bescoto
  • Date: 2002-10-29 01:49:46 UTC
  • Revision ID: vcs-imports@canonical.com-20021029014946-3m4rmm5plom7pl6q
Initial checkin

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ----------------------------------------------------------------------- *
 
2
 *   
 
3
 *   Copyright 2002 Ben Escoto
 
4
 *
 
5
 *   This file is part of rdiff-backup.
 
6
 *
 
7
 *   rdiff-backup is free software; you can redistribute it and/or
 
8
 *   modify it under the terms of the GNU General Public License as
 
9
 *   published by the Free Software Foundation, Inc., 675 Mass Ave,
 
10
 *   Cambridge MA 02139, USA; either version 2 of the License, or (at
 
11
 *   your option) any later version; incorporated herein by reference.
 
12
 *
 
13
 * ----------------------------------------------------------------------- */
 
14
 
 
15
#include <Python.h>
 
16
#include <rsync.h>
 
17
#define RS_JOB_BLOCKSIZE 65536
 
18
 
 
19
static PyObject *librsyncError;
 
20
 
 
21
/* Sets python error string from result */
 
22
static void
 
23
_librsync_seterror(rs_result result, char *location)
 
24
{
 
25
  char error_string[200];
 
26
  sprintf(error_string, "librsync error %d while in %s", result, location);
 
27
  PyErr_SetString(librsyncError, error_string);
 
28
}
 
29
 
 
30
 
 
31
/* --------------- SigMaker Object for incremental signatures */
 
32
staticforward PyTypeObject _librsync_SigMakerType;
 
33
 
 
34
typedef struct {
 
35
  PyObject_HEAD
 
36
  PyObject *x_attr;
 
37
  rs_job_t *sig_job;
 
38
} _librsync_SigMakerObject;
 
39
 
 
40
static PyObject*
 
41
_librsync_new_sigmaker(PyObject* self, PyObject* args)
 
42
{
 
43
  _librsync_SigMakerObject* sm;
 
44
  
 
45
  if (!PyArg_ParseTuple(args,":new_sigmaker"))
 
46
        return NULL;
 
47
 
 
48
  sm = PyObject_New(_librsync_SigMakerObject, &_librsync_SigMakerType);
 
49
  if (sm == NULL) return NULL;
 
50
  sm->x_attr = NULL;
 
51
 
 
52
  sm->sig_job = rs_sig_begin((size_t)RS_DEFAULT_BLOCK_LEN,
 
53
                                                         (size_t)RS_DEFAULT_STRONG_LEN);
 
54
  return (PyObject*)sm;
 
55
}
 
56
 
 
57
static void
 
58
_librsync_sigmaker_dealloc(PyObject* self)
 
59
{
 
60
  rs_job_free(((_librsync_SigMakerObject *)self)->sig_job);
 
61
  PyObject_Del(self);
 
62
}
 
63
 
 
64
/* Take an input string, and generate a signature from it.  The output
 
65
   will be a triple (done, bytes_used, signature_string), where done
 
66
   is true iff there is no more data coming and bytes_used is the
 
67
   number of bytes of the input string processed.
 
68
*/
 
69
static PyObject *
 
70
_librsync_sigmaker_cycle(_librsync_SigMakerObject *self, PyObject *args)
 
71
{
 
72
  char *inbuf, outbuf[RS_JOB_BLOCKSIZE];
 
73
  long inbuf_length;
 
74
  rs_buffers_t buf;
 
75
  rs_result result;
 
76
 
 
77
  if (!PyArg_ParseTuple(args, "s#:cycle", &inbuf, &inbuf_length))
 
78
        return NULL;
 
79
 
 
80
  buf.next_in = inbuf;
 
81
  buf.avail_in = (size_t)inbuf_length;
 
82
  buf.next_out = outbuf;
 
83
  buf.avail_out = (size_t)RS_JOB_BLOCKSIZE;
 
84
  buf.eof_in = (inbuf_length == 0);
 
85
 
 
86
  result = rs_job_iter(self->sig_job, &buf);
 
87
 
 
88
  if (result != RS_DONE && result != RS_BLOCKED) {
 
89
        _librsync_seterror(result, "signature cycle");
 
90
        return NULL;
 
91
  }
 
92
 
 
93
  return Py_BuildValue("(ils#)", (result == RS_DONE),
 
94
                                           inbuf_length - (long)buf.avail_in,
 
95
                                           outbuf, RS_JOB_BLOCKSIZE - (long)buf.avail_out);
 
96
}
 
97
 
 
98
static PyMethodDef _librsync_sigmaker_methods[] = {
 
99
  {"cycle", (PyCFunction)_librsync_sigmaker_cycle, METH_VARARGS},
 
100
  {NULL, NULL, 0, NULL}  /* sentinel */
 
101
};
 
102
 
 
103
static PyObject *
 
104
_librsync_sigmaker_getattr(_librsync_SigMakerObject *sm,
 
105
                                                                                         char *name)
 
106
{
 
107
  if (sm->x_attr != NULL) {
 
108
        PyObject *v = PyDict_GetItemString(sm->x_attr, name);
 
109
        if (v != NULL) {
 
110
          Py_INCREF(v);
 
111
          return v;
 
112
        }
 
113
  }
 
114
  return Py_FindMethod(_librsync_sigmaker_methods, (PyObject *)sm, name);
 
115
}
 
116
 
 
117
static int
 
118
_librsync_sigmaker_setattr(_librsync_SigMakerObject *sm,
 
119
                                                                           char *name, PyObject *v)
 
120
{
 
121
  if (sm->x_attr == NULL) {
 
122
        sm->x_attr = PyDict_New();
 
123
        if (sm->x_attr == NULL) return -1;
 
124
  }
 
125
  if (v == NULL) {
 
126
        int rv = PyDict_DelItemString(sm->x_attr, name);
 
127
        if (rv < 0)
 
128
          PyErr_SetString(PyExc_AttributeError,
 
129
                                          "delete non-existing sigmaker attribute");
 
130
        return rv;
 
131
  }
 
132
  else return PyDict_SetItemString(sm->x_attr, name, v);
 
133
}
 
134
 
 
135
static PyTypeObject _librsync_SigMakerType = {
 
136
  PyObject_HEAD_INIT(NULL)
 
137
  0,
 
138
  "sigmaker",
 
139
  sizeof(_librsync_SigMakerObject),
 
140
  0,
 
141
  _librsync_sigmaker_dealloc, /*tp_dealloc*/
 
142
  0,          /*tp_print*/
 
143
  (getattrfunc)_librsync_sigmaker_getattr, /*tp_getattr*/
 
144
  (setattrfunc)_librsync_sigmaker_setattr, /*tp_setattr*/
 
145
  0,          /*tp_compare*/
 
146
  0,          /*tp_repr*/
 
147
  0,          /*tp_as_number*/
 
148
  0,          /*tp_as_sequence*/
 
149
  0,          /*tp_as_mapping*/
 
150
  0,          /*tp_hash */
 
151
};
 
152
 
 
153
 
 
154
/* --------------- DeltaMaker Object for incremental deltas */
 
155
 
 
156
staticforward PyTypeObject _librsync_DeltaMakerType;
 
157
 
 
158
typedef struct {
 
159
  PyObject_HEAD
 
160
  PyObject *x_attr;
 
161
  rs_job_t *delta_job;
 
162
  rs_signature_t *sig_ptr;
 
163
} _librsync_DeltaMakerObject;
 
164
 
 
165
/* Call with the entire signature loaded into one big string */
 
166
static PyObject*
 
167
_librsync_new_deltamaker(PyObject* self, PyObject* args)
 
168
{
 
169
  _librsync_DeltaMakerObject* dm;
 
170
  char *sig_string, outbuf[RS_JOB_BLOCKSIZE];
 
171
  long sig_length;
 
172
  rs_job_t *sig_loader;
 
173
  rs_signature_t *sig_ptr;
 
174
  rs_buffers_t buf;
 
175
  rs_result result;
 
176
 
 
177
  if (!PyArg_ParseTuple(args,"s#:new_deltamaker", &sig_string, &sig_length))
 
178
        return NULL;
 
179
 
 
180
  dm = PyObject_New(_librsync_DeltaMakerObject, &_librsync_DeltaMakerType);
 
181
  if (dm == NULL) return NULL;
 
182
  dm->x_attr = NULL;
 
183
 
 
184
  /* Put signature at sig_ptr and build hash */
 
185
  sig_loader = rs_loadsig_begin(&sig_ptr);
 
186
  buf.next_in = sig_string;
 
187
  buf.avail_in = (size_t)sig_length;
 
188
  buf.next_out = outbuf;
 
189
  buf.avail_out = (size_t)RS_JOB_BLOCKSIZE;
 
190
  buf.eof_in = 1;
 
191
  result = rs_job_iter(sig_loader, &buf);
 
192
  rs_job_free(sig_loader);
 
193
  if (result != RS_DONE) {
 
194
        _librsync_seterror(result, "delta rs_signature_t builder");
 
195
        return NULL;
 
196
  }
 
197
  if ((result = rs_build_hash_table(sig_ptr)) != RS_DONE) {
 
198
        _librsync_seterror(result, "delta rs_build_hash_table");
 
199
        return NULL;
 
200
  }
 
201
 
 
202
  dm->sig_ptr = sig_ptr;
 
203
  dm->delta_job = rs_delta_begin(sig_ptr);
 
204
  return (PyObject*)dm;
 
205
}
 
206
 
 
207
static void
 
208
_librsync_deltamaker_dealloc(PyObject* self)
 
209
{
 
210
  _librsync_DeltaMakerObject *dm = (_librsync_DeltaMakerObject *)self;
 
211
  rs_signature_t *sig_ptr = dm->sig_ptr;
 
212
 
 
213
  rs_free_sumset(sig_ptr);
 
214
  rs_job_free(dm->delta_job);
 
215
  PyObject_Del(self);
 
216
}
 
217
 
 
218
/* Take a chunk of the new file in an input string, and return a
 
219
   triple (done bytes_used, delta_string), where done is true iff no
 
220
   more data is coming and bytes_used is the number of bytes of the
 
221
   input string processed.
 
222
*/
 
223
static PyObject *
 
224
_librsync_deltamaker_cycle(_librsync_DeltaMakerObject *self, PyObject *args)
 
225
{
 
226
  char *inbuf, outbuf[RS_JOB_BLOCKSIZE];
 
227
  long inbuf_length;
 
228
  rs_buffers_t buf;
 
229
  rs_result result;
 
230
 
 
231
  if (!PyArg_ParseTuple(args, "s#:cycle", &inbuf, &inbuf_length))
 
232
        return NULL;
 
233
 
 
234
  buf.next_in = inbuf;
 
235
  buf.avail_in = (size_t)inbuf_length;
 
236
  buf.next_out = outbuf;
 
237
  buf.avail_out = (size_t)RS_JOB_BLOCKSIZE;
 
238
  buf.eof_in = (inbuf_length == 0);
 
239
 
 
240
  result = rs_job_iter(self->delta_job, &buf);
 
241
  if (result != RS_DONE && result != RS_BLOCKED) {
 
242
        _librsync_seterror(result, "delta cycle");
 
243
        return NULL;
 
244
  }
 
245
 
 
246
  return Py_BuildValue("(ils#)", (result == RS_DONE),
 
247
                                           inbuf_length - (long)buf.avail_in,
 
248
                                           outbuf, RS_JOB_BLOCKSIZE - (long)buf.avail_out);
 
249
}
 
250
 
 
251
static PyMethodDef _librsync_deltamaker_methods[] = {
 
252
  {"cycle", (PyCFunction)_librsync_deltamaker_cycle, METH_VARARGS},
 
253
  {NULL, NULL, 0, NULL}  /* sentinel */
 
254
};
 
255
 
 
256
static PyObject *
 
257
_librsync_deltamaker_getattr(_librsync_DeltaMakerObject *dm, char *name)
 
258
{
 
259
  if (dm->x_attr != NULL) {
 
260
        PyObject *v = PyDict_GetItemString(dm->x_attr, name);
 
261
        if (v != NULL) {
 
262
          Py_INCREF(v);
 
263
          return v;
 
264
        }
 
265
  }
 
266
  return Py_FindMethod(_librsync_deltamaker_methods, (PyObject *)dm, name);
 
267
}
 
268
 
 
269
static int
 
270
_librsync_deltamaker_setattr(_librsync_DeltaMakerObject *dm,
 
271
                                                         char *name, PyObject *v)
 
272
{
 
273
  if (dm->x_attr == NULL) {
 
274
        dm->x_attr = PyDict_New();
 
275
        if (dm->x_attr == NULL) return -1;
 
276
  }
 
277
  if (v == NULL) {
 
278
        int rv = PyDict_DelItemString(dm->x_attr, name);
 
279
        if (rv < 0)
 
280
          PyErr_SetString(PyExc_AttributeError,
 
281
                                          "delete non-existing deltamaker attribute");
 
282
        return rv;
 
283
  }
 
284
  else return PyDict_SetItemString(dm->x_attr, name, v);
 
285
}
 
286
 
 
287
static PyTypeObject _librsync_DeltaMakerType = {
 
288
  PyObject_HEAD_INIT(NULL)
 
289
  0,
 
290
  "deltamaker",
 
291
  sizeof(_librsync_DeltaMakerObject),
 
292
  0,
 
293
  _librsync_deltamaker_dealloc, /*tp_dealloc*/
 
294
  0,          /*tp_print*/
 
295
  (getattrfunc)_librsync_deltamaker_getattr, /*tp_getattr*/
 
296
  (setattrfunc)_librsync_deltamaker_setattr, /*tp_setattr*/
 
297
  0,          /*tp_compare*/
 
298
  0,          /*tp_repr*/
 
299
  0,          /*tp_as_number*/
 
300
  0,          /*tp_as_sequence*/
 
301
  0,          /*tp_as_mapping*/
 
302
  0,          /*tp_hash */
 
303
};
 
304
 
 
305
 
 
306
/* --------------- PatchMaker Object for incremental patching */
 
307
 
 
308
 
 
309
staticforward PyTypeObject _librsync_PatchMakerType;
 
310
 
 
311
typedef struct {
 
312
  PyObject_HEAD
 
313
  PyObject *x_attr;
 
314
  rs_job_t *patch_job;
 
315
  PyObject *basis_file;
 
316
} _librsync_PatchMakerObject;
 
317
 
 
318
/* Call with the basis file */
 
319
static PyObject*
 
320
_librsync_new_patchmaker(PyObject* self, PyObject* args)
 
321
{
 
322
  _librsync_PatchMakerObject* pm;
 
323
  PyObject *python_file;
 
324
  FILE *cfile;
 
325
 
 
326
  if (!PyArg_ParseTuple(args, "O:new_patchmaker", &python_file))
 
327
        return NULL;
 
328
  if (!PyFile_Check(python_file)) {
 
329
        PyErr_SetString(PyExc_TypeError, "Need true file object");
 
330
        return NULL;
 
331
  }
 
332
  Py_INCREF(python_file);
 
333
  
 
334
  pm = PyObject_New(_librsync_PatchMakerObject, &_librsync_PatchMakerType);
 
335
  if (pm == NULL) return NULL;
 
336
  pm->x_attr = NULL;
 
337
 
 
338
  pm->basis_file = python_file;
 
339
  cfile = PyFile_AsFile(python_file);
 
340
  pm->patch_job = rs_patch_begin(rs_file_copy_cb, cfile);
 
341
 
 
342
  return (PyObject*)pm;
 
343
}
 
344
 
 
345
static void
 
346
_librsync_patchmaker_dealloc(PyObject* self)
 
347
{
 
348
  _librsync_PatchMakerObject *pm = (_librsync_PatchMakerObject *)self;
 
349
  Py_DECREF(pm->basis_file);
 
350
  rs_job_free(pm->patch_job);
 
351
  PyObject_Del(self);
 
352
}
 
353
 
 
354
/* Take a chunk of the delta file in an input string, and return a
 
355
   triple (done, bytes_used, patched_string), where done is true iff
 
356
   there is no more data coming out and bytes_used is the number of
 
357
   bytes of the input string processed.
 
358
*/
 
359
static PyObject *
 
360
_librsync_patchmaker_cycle(_librsync_PatchMakerObject *self, PyObject *args)
 
361
{
 
362
  char *inbuf, outbuf[RS_JOB_BLOCKSIZE];
 
363
  long inbuf_length;
 
364
  rs_buffers_t buf;
 
365
  rs_result result;
 
366
 
 
367
  if (!PyArg_ParseTuple(args, "s#:cycle", &inbuf, &inbuf_length))
 
368
        return NULL;
 
369
 
 
370
  buf.next_in = inbuf;
 
371
  buf.avail_in = (size_t)inbuf_length;
 
372
  buf.next_out = outbuf;
 
373
  buf.avail_out = (size_t)RS_JOB_BLOCKSIZE;
 
374
  buf.eof_in = (inbuf_length == 0);
 
375
 
 
376
  result = rs_job_iter(self->patch_job, &buf);
 
377
  if (result != RS_DONE && result != RS_BLOCKED) {
 
378
        _librsync_seterror(result, "patch cycle");
 
379
        return NULL;
 
380
  }
 
381
 
 
382
  return Py_BuildValue("(ils#)", (result == RS_DONE),
 
383
                                           inbuf_length - (long)buf.avail_in,
 
384
                                           outbuf, RS_JOB_BLOCKSIZE - (long)buf.avail_out);
 
385
}
 
386
 
 
387
static PyMethodDef _librsync_patchmaker_methods[] = {
 
388
  {"cycle", (PyCFunction)_librsync_patchmaker_cycle, METH_VARARGS},
 
389
  {NULL, NULL, 0, NULL}  /* sentinel */
 
390
};
 
391
 
 
392
static PyObject *
 
393
_librsync_patchmaker_getattr(_librsync_PatchMakerObject *pm, char *name)
 
394
{
 
395
  if (pm->x_attr != NULL) {
 
396
        PyObject *v = PyDict_GetItemString(pm->x_attr, name);
 
397
        if (v != NULL) {
 
398
          Py_INCREF(v);
 
399
          return v;
 
400
        }
 
401
  }
 
402
  return Py_FindMethod(_librsync_patchmaker_methods, (PyObject *)pm, name);
 
403
}
 
404
 
 
405
static int
 
406
_librsync_patchmaker_setattr(_librsync_PatchMakerObject *pm,
 
407
                                                         char *name, PyObject *v)
 
408
{
 
409
  if (pm->x_attr == NULL) {
 
410
        pm->x_attr = PyDict_New();
 
411
        if (pm->x_attr == NULL) return -1;
 
412
  }
 
413
  if (v == NULL) {
 
414
        int rv = PyDict_DelItemString(pm->x_attr, name);
 
415
        if (rv < 0)
 
416
          PyErr_SetString(PyExc_AttributeError,
 
417
                                          "delete non-existing patchmaker attribute");
 
418
        return rv;
 
419
  }
 
420
  else return PyDict_SetItemString(pm->x_attr, name, v);
 
421
}
 
422
 
 
423
static PyTypeObject _librsync_PatchMakerType = {
 
424
  PyObject_HEAD_INIT(NULL)
 
425
  0,
 
426
  "patchmaker",
 
427
  sizeof(_librsync_PatchMakerObject),
 
428
  0,
 
429
  _librsync_patchmaker_dealloc, /*tp_dealloc*/
 
430
  0,          /*tp_print*/
 
431
  (getattrfunc)_librsync_patchmaker_getattr, /*tp_getattr*/
 
432
  (setattrfunc)_librsync_patchmaker_setattr, /*tp_setattr*/
 
433
  0,          /*tp_compare*/
 
434
  0,          /*tp_repr*/
 
435
  0,          /*tp_as_number*/
 
436
  0,          /*tp_as_sequence*/
 
437
  0,          /*tp_as_mapping*/
 
438
  0,          /*tp_hash */
 
439
};
 
440
 
 
441
 
 
442
/* --------------- _librsync module definition */
 
443
 
 
444
static PyMethodDef _librsyncMethods[] = {
 
445
  {"new_sigmaker", _librsync_new_sigmaker, METH_VARARGS,
 
446
   "Return a sigmaker object, for finding the signature of an object"},
 
447
  {"new_deltamaker", _librsync_new_deltamaker, METH_VARARGS,
 
448
   "Return a deltamaker object, for computing deltas"},
 
449
  {"new_patchmaker", _librsync_new_patchmaker, METH_VARARGS,
 
450
   "Return a patchmaker object, for patching basis files"},
 
451
  {NULL, NULL, 0, NULL}
 
452
};
 
453
 
 
454
void init_librsync(void)
 
455
{
 
456
  PyObject *m, *d;
 
457
 
 
458
  _librsync_SigMakerType.ob_type = &PyType_Type;
 
459
  _librsync_DeltaMakerType.ob_type = &PyType_Type;
 
460
  m = Py_InitModule("_librsync", _librsyncMethods);
 
461
  d = PyModule_GetDict(m);
 
462
  librsyncError = PyErr_NewException("_librsync.librsyncError", NULL, NULL);
 
463
  PyDict_SetItemString(d, "librsyncError", librsyncError);
 
464
  PyDict_SetItemString(d, "RS_JOB_BLOCKSIZE",
 
465
                                           Py_BuildValue("l", (long)RS_JOB_BLOCKSIZE));
 
466
  PyDict_SetItemString(d, "RS_DEFAULT_BLOCK_LEN",
 
467
                                           Py_BuildValue("l", (long)RS_DEFAULT_BLOCK_LEN));
 
468
}