7180c3e12cf8804b4e196d65176da443e35be09d
[kai/samba.git] / source3 / python / py_tdbpack.c
1 /* -*- c-file-style: "python"; indent-tabs-mode: nil; -*-
2          
3    Python wrapper for Samba tdb pack/unpack functions
4    Copyright (C) Martin Pool 2002
5
6
7    NOTE PYTHON STYLE GUIDE
8    http://www.python.org/peps/pep-0007.html
9    
10    
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 2 of the License, or
14    (at your option) any later version.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26
27
28 #include "Python.h"
29
30 static PyObject * pytdbpack_number(char ch, PyObject *val_iter, PyObject *packed_list);
31 static PyObject * pytdbpack_str_850(PyObject *val_iter, PyObject *packed_list);
32 static PyObject * pytdbpack_buffer(PyObject *val_iter, PyObject *packed_list);
33
34 static PyObject *pytdbpack_unpack_item(char, char **pbuf, int *plen, PyObject *);
35
36 static PyObject *pytdbpack_data(const char *format_str,
37                                      PyObject *val_seq,
38                                      PyObject *val_list);
39
40 static void pack_le_uint32(unsigned long val_long, unsigned char *pbuf);
41
42
43 static PyObject *pytdbpack_bad_type(char ch,
44                                     const char *expected,
45                                     PyObject *val_obj);
46
47 static const char * pytdbpack_docstring =
48 "Convert between Python values and Samba binary encodings.
49
50 This module is conceptually similar to the standard 'struct' module, but it
51 uses both a different binary format and a different description string.
52
53 Samba's encoding is based on that used inside DCE-RPC and SMB: a
54 little-endian, unpadded, non-self-describing binary format.  It is intended
55 that these functions be as similar as possible to the routines in Samba's
56 tdb/tdbutil module, with appropriate adjustments for Python datatypes.
57
58 Python strings are used to specify the format of data to be packed or
59 unpacked.
60
61 Strings are always stored in codepage 850.  Unicode objects are translated
62 to cp850; plain strings are assumed to be in latin-1 and are also
63 translated.
64
65 This may be a problem in the future if it is different to the Samba codepage.
66 It might be better to have the caller do the conversion, but that would conflict
67 with existing CMI code.
68
69 tdbpack format strings:
70
71     'f':  NULL-terminated string in codepage 850
72
73     'P':  same as 'f'
74
75     'd':  4 byte little-endian unsigned number
76
77     'w':  2 byte little-endian unsigned number
78
79     'P': \"Pointer\" value -- in the subset of DCERPC used by Samba, this is
80           really just an \"exists\" or \"does not exist\" flag.  The boolean
81           value of the Python object is used.
82     
83     'B': 4-byte LE length, followed by that many bytes of binary data.
84          Corresponds to a Python integer giving the length, followed by a byte
85          string of the appropriate length.
86
87     '$': Special flag indicating that the preceding format code should be
88          repeated while data remains.  This is only supported for unpacking.
89
90     Every code corresponds to a single Python object, except 'B' which
91     corresponds to two values (length and contents), and '$', which produces
92     however many make sense.
93 ";
94
95
96 static char const pytdbpack_doc[] = 
97 "pack(format, values) -> buffer
98 Pack Python objects into Samba binary format according to format string.
99
100 arguments:
101     format -- string of tdbpack format characters
102     values -- sequence of value objects corresponding 1:1 to format characters
103
104 returns:
105     buffer -- string containing packed data
106
107 raises:
108     IndexError -- if there are too few values for the format
109     ValueError -- if any of the format characters is illegal
110     TypeError  -- if the format is not a string, or values is not a sequence,
111         or any of the values is of the wrong type for the corresponding
112         format character
113
114 notes:
115     For historical reasons, it is not an error to pass more values than are consumed
116     by the format.
117 ";
118
119
120 static char const pytdbpack_unpack_doc[] =
121 "unpack(format, buffer) -> (values, rest)
122 Unpack Samba binary data according to format string.
123
124 arguments:
125     format -- string of tdbpack characters
126     buffer -- string of packed binary data
127
128 returns:
129     2-tuple of:
130         values -- sequence of values corresponding 1:1 to format characters
131         rest -- string containing data that was not decoded, or '' if the
132             whole string was consumed
133
134 raises:
135     IndexError -- if there is insufficient data in the buffer for the
136         format (or if the data is corrupt and contains a variable-length
137         field extending past the end)
138     ValueError -- if any of the format characters is illegal
139
140 notes:
141     Because unconsumed data is returned, you can feed it back in to the
142     unpacker to extract further fields.  Alternatively, if you wish to modify
143     some fields near the start of the data, you may be able to save time by
144     only unpacking and repacking the necessary part.
145 ";
146
147
148
149
150 /*
151   * Pack objects to bytes.
152   *
153   * All objects are first individually encoded onto a list, and then the list
154   * of strings is concatenated.  This is faster than concatenating strings,
155   * and reasonably simple to code.
156   */
157 static PyObject *
158 pytdbpack(PyObject *self,
159                PyObject *args)
160 {
161         char *format_str;
162         PyObject *val_seq, *val_iter = NULL,
163                 *packed_list = NULL, *packed_str = NULL,
164                 *empty_str = NULL;
165
166         /* TODO: Test passing wrong types or too many arguments */
167         if (!PyArg_ParseTuple(args, "sO", &format_str, &val_seq))
168                 return NULL;
169
170         if (!(val_iter = PyObject_GetIter(val_seq)))
171                 goto out;
172
173         /* Create list to hold strings until we're done, then join them all. */
174         if (!(packed_list = PyList_New(0)))
175                 goto out;
176
177         if (!pytdbpack_data(format_str, val_iter, packed_list))
178                 goto out;
179
180         /* this function is not officially documented but it works */
181         if (!(empty_str = PyString_InternFromString("")))
182                 goto out;
183         
184         packed_str = _PyString_Join(empty_str, packed_list);
185
186   out:
187         Py_XDECREF(empty_str);
188         Py_XDECREF(val_iter);
189         Py_XDECREF(packed_list);
190
191         return packed_str;
192 }
193
194
195 /*
196   Pack data according to FORMAT_STR from the elements of VAL_SEQ into
197   PACKED_BUF.
198
199   The string has already been checked out, so we know that VAL_SEQ is large
200   enough to hold the packed data, and that there are enough value items.
201   (However, their types may not have been thoroughly checked yet.)
202
203   In addition, val_seq is a Python Fast sequence.
204
205   Returns NULL for error (with exception set), or None.
206 */
207 PyObject *
208 pytdbpack_data(const char *format_str,
209                     PyObject *val_iter,
210                     PyObject *packed_list)
211 {
212         int format_i, val_i = 0;
213
214         for (format_i = 0, val_i = 0; format_str[format_i]; format_i++) {
215                 char ch = format_str[format_i];
216
217                 switch (ch) {
218                         /* dispatch to the appropriate packer for this type,
219                            which should pull things off the iterator, and
220                            append them to the packed_list */
221                 case 'w':
222                 case 'd':
223                 case 'p':
224                         if (!(packed_list = pytdbpack_number(ch, val_iter, packed_list)))
225                                 return NULL;
226                         break;
227
228                 case 'f':
229                 case 'P':
230                         if (!(packed_list = pytdbpack_str_850(val_iter, packed_list)))
231                                 return NULL;
232                         break;
233
234                 case 'B':
235                         if (!(packed_list = pytdbpack_buffer(val_iter, packed_list)))
236                                 return NULL;
237                         break;
238
239                 default:
240                         PyErr_Format(PyExc_ValueError,
241                                      "%s: format character '%c' is not supported",
242                                      __FUNCTION__, ch);
243                         return NULL;
244                 }
245         }
246
247         return packed_list;
248 }
249
250
251 static PyObject *
252 pytdbpack_number(char ch, PyObject *val_iter, PyObject *packed_list)
253 {
254         unsigned long val_long;
255         PyObject *val_obj = NULL, *long_obj = NULL, *result_obj = NULL;
256         PyObject *new_list = NULL;
257         unsigned char pack_buf[4];
258
259         if (!(val_obj = PyIter_Next(val_iter)))
260                 goto out;
261
262         if (!(long_obj = PyNumber_Long(val_obj))) {
263                 pytdbpack_bad_type(ch, "Number", val_obj);
264                 goto out;
265         }
266
267         val_long = PyLong_AsUnsignedLong(long_obj);
268         pack_le_uint32(val_long, pack_buf);
269
270         /* pack as 32-bit; if just packing a 'w' 16-bit word then only take
271            the first two bytes. */
272         
273         if (!(result_obj = PyString_FromStringAndSize(pack_buf, ch == 'w' ? 2 : 4)))
274                 goto out;
275
276         if (PyList_Append(packed_list, result_obj) != -1)
277                 new_list = packed_list;
278
279   out:
280         Py_XDECREF(val_obj);
281         Py_XDECREF(long_obj);
282         Py_XDECREF(result_obj);
283
284         return new_list;
285 }
286
287
288 /*
289  * Take one string from the iterator val_iter, convert it to 8-bit CP850, and
290  * return it.
291  *
292  * If the input is neither a string nor Unicode, an exception is raised.
293  *
294  * If the input is Unicode, then it is converted to CP850.
295  *
296  * If the input is a String, then it is converted to Unicode using the default
297  * decoding method, and then converted to CP850.  This in effect gives
298  * conversion from latin-1 (currently the PSA's default) to CP850, without
299  * needing a custom translation table.
300  *
301  * I hope this approach avoids being too fragile w.r.t. being passed either
302  * Unicode or String objects.
303  */
304 static PyObject *
305 pytdbpack_str_850(PyObject *val_iter, PyObject *packed_list)
306 {
307         PyObject *val_obj = NULL;
308         PyObject *unicode_obj = NULL;
309         PyObject *cp850_str = NULL;
310         PyObject *nul_str = NULL;
311         PyObject *new_list = NULL;
312
313         if (!(val_obj = PyIter_Next(val_iter)))
314                 goto out;
315
316         if (PyUnicode_Check(val_obj)) {
317                 unicode_obj = val_obj;
318         }
319         else {
320                 /* string */
321                 if (!(unicode_obj = PyString_AsDecodedObject(val_obj, NULL, NULL)))
322                         goto out;
323                 Py_XDECREF(val_obj);
324                 val_obj = NULL;
325         }
326
327         if (!(cp850_str = PyUnicode_AsEncodedString(unicode_obj, "cp850", NULL)))
328                 goto out;
329
330         if (!nul_str)
331                 /* this is constant and often-used; hold it forever */
332                 if (!(nul_str = PyString_FromStringAndSize("", 1)))
333                         goto out;
334
335         if ((PyList_Append(packed_list, cp850_str) != -1)
336             && (PyList_Append(packed_list, nul_str) != -1))
337                 new_list = packed_list;
338
339   out:
340         Py_XDECREF(unicode_obj);
341         Py_XDECREF(cp850_str);
342
343         return new_list;
344 }
345
346
347 /*
348  * Pack (LENGTH, BUFFER) pair onto the list.
349  *
350  * The buffer must already be a String, not Unicode, because it contains 8-bit
351  * untranslated data.  In some cases it will actually be UTF_16_LE data.
352  */
353 static PyObject *
354 pytdbpack_buffer(PyObject *val_iter, PyObject *packed_list)
355 {
356         PyObject *val_obj;
357         PyObject *new_list = NULL;
358         
359         /* pull off integer and stick onto list */
360         if (!(packed_list = pytdbpack_number('d', val_iter, packed_list)))
361                 return NULL;
362
363         /* this assumes that the string is the right length; the old code did the same. */
364         if (!(val_obj = PyIter_Next(val_iter)))
365                 return NULL;
366
367         if (!PyString_Check(val_obj)) {
368                 pytdbpack_bad_type('B', "String", val_obj);
369                 goto out;
370         }
371         
372         if (PyList_Append(packed_list, val_obj) != -1)
373                 new_list = packed_list;
374
375   out:
376         Py_XDECREF(val_obj);
377         return new_list;
378 }
379
380
381 #if 0
382 else if (ch == 'B') {
383                         long size;
384                         char *sval;
385
386                         if (!PyNumber_Check(val_obj)) {
387                                 pytdbpack_bad_type(ch, "Number", val_obj);
388                                 return NULL;
389                         }
390
391                         if (!(val_obj = PyNumber_Long(val_obj)))
392                                 return NULL;
393
394                         size = PyLong_AsLong(val_obj);
395                         pack_le_uint32(size, &packed);
396
397                         /* Release the new reference created by the cast */
398                         Py_DECREF(val_obj);
399
400                         val_obj = PySequence_GetItem(val_seq, val_i++);
401                         if (!val_obj)
402                                 return NULL;
403                         
404                         sval = PyString_AsString(val_obj);
405                         if (!sval)
406                                 return NULL;
407                         
408                         pack_bytes(size, sval, &packed); /* do not include nul */
409                 }
410                 else {
411                 
412         }
413                 
414         return Py_None;
415 }
416 #endif
417
418 static PyObject *
419 pytdbpack_unpack(PyObject *self,
420                  PyObject *args)
421 {
422         char *format_str, *packed_str, *ppacked;
423         PyObject *val_list = NULL, *ret_tuple = NULL;
424         PyObject *rest_string = NULL;
425         int format_len, packed_len;
426         char last_format = '#'; /* invalid */
427         int i;
428         
429         /* get arguments */
430         if (!PyArg_ParseTuple(args, "ss#", &format_str, &packed_str, &packed_len))
431                 return NULL;
432
433         format_len = strlen(format_str);
434         
435         /* Allocate list to hold results.  Initially empty, and we append
436            results as we go along. */
437         val_list = PyList_New(0);
438         if (!val_list)
439                 goto failed;
440         ret_tuple = PyTuple_New(2);
441         if (!ret_tuple)
442                 goto failed;
443         
444         /* For every object, unpack.  */
445         for (ppacked = packed_str, i = 0; i < format_len && format_str[i] != '$'; i++) {
446                 last_format = format_str[i];
447                 /* packed_len is reduced in place */
448                 if (!pytdbpack_unpack_item(format_str[i], &ppacked, &packed_len, val_list))
449                         goto failed;
450         }
451
452         /* If the last character was '$', keep going until out of space */
453         if (format_str[i] == '$') {
454                 if (i == 0) {
455                         PyErr_Format(PyExc_ValueError,
456                                      "%s: '$' may not be first character in format",
457                                      __FUNCTION__);
458                         return NULL;
459                 } 
460                 while (packed_len > 0)
461                         if (!pytdbpack_unpack_item(last_format, &ppacked, &packed_len, val_list))
462                                 goto failed;
463         }
464         
465         /* save leftovers for next time */
466         rest_string = PyString_FromStringAndSize(ppacked, packed_len);
467         if (!rest_string)
468                 goto failed;
469
470         /* return (values, rest) tuple; give up references to them */
471         PyTuple_SET_ITEM(ret_tuple, 0, val_list);
472         val_list = NULL;
473         PyTuple_SET_ITEM(ret_tuple, 1, rest_string);
474         val_list = NULL;
475         return ret_tuple;
476
477   failed:
478         /* handle failure: deallocate anything.  XDECREF forms handle NULL
479            pointers for objects that haven't been allocated yet. */
480         Py_XDECREF(val_list);
481         Py_XDECREF(ret_tuple);
482         Py_XDECREF(rest_string);
483         return NULL;
484 }
485
486
487
488 #if 0
489 /*
490   Internal routine that calculates how many bytes will be required to
491   encode the values in the format.
492
493   Also checks that the value list is the right size for the format list.
494
495   Returns number of bytes (may be 0), or -1 if there's something wrong, in
496   which case a Python exception has been raised.
497
498   Arguments:
499
500     val_seq: a Fast Sequence (list or tuple), being all the values
501 */
502 static int
503 pytdbpack_calc_reqd_len(char *format_str,
504                         PyObject *val_seq)
505 {
506         int len = 0;
507         char *p;
508         int val_i;
509         int val_len;
510
511         val_len = PySequence_Length(val_seq);
512         if (val_len == -1)
513                 return -1;
514
515         for (p = format_str, val_i = 0; *p; p++, val_i++) {
516                 char ch = *p;
517
518                 if (val_i >= val_len) {
519                         PyErr_Format(PyExc_IndexError,
520                                      "%s: value list is too short for format string",
521                                      __FUNCTION__);
522                         return -1;
523                 }
524
525                 /* borrow a reference to the item */
526                 if (ch == 'd' || ch == 'p') 
527                         len += 4;
528                 else if (ch == 'w')
529                         len += 2;
530                 else if (ch == 'f' || ch == 'P') {
531                         /* nul-terminated 8-bit string */
532                         int item_len;
533                         PyObject *str_obj;
534
535                         str_obj = PySequence_GetItem(val_seq, val_i);
536                         if (!str_obj)
537                                 return -1;
538
539                         if (!PyString_Check(str_obj) || ((item_len = PyString_Size(str_obj)) == -1)) {
540                                 pytdbpack_bad_type(ch, "String", str_obj);
541                                 return -1;
542                         }
543                         
544                         len += 1 + item_len;
545                 }
546                 else if (ch == 'B') {
547                         /* length-preceded byte buffer: n bytes, plus a preceding
548                          * word */
549                         PyObject *len_obj;
550                         long len_val;
551
552                         len_obj = PySequence_GetItem(val_seq, val_i);
553                         val_i++; /* skip over buffer */
554
555                         if (!PyNumber_Check(len_obj)) {
556                                 pytdbpack_bad_type(ch, "Number", len_obj);
557                                 return -1;
558                         }
559
560                         len_val = PyInt_AsLong(len_obj);
561                         if (len_val < 0) {
562                                 PyErr_Format(PyExc_ValueError,
563                                              "%s: format 'B' requires positive integer", __FUNCTION__);
564                                 return -1;
565                         }
566
567                         len += 4 + len_val;
568                 }
569                 else {  
570                         PyErr_Format(PyExc_ValueError,
571                                      "%s: format character '%c' is not supported",
572                                      __FUNCTION__, ch);
573                 
574                         return -1;
575                 }
576         }
577
578         return len;
579 }
580 #endif
581
582
583 static PyObject *pytdbpack_bad_type(char ch,
584                                     const char *expected,
585                                     PyObject *val_obj)
586 {
587         PyObject *r = PyObject_Repr(val_obj);
588         if (!r)
589                 return NULL;
590         PyErr_Format(PyExc_TypeError,
591                      "tdbpack: format '%c' requires %s, not %s",
592                      ch, expected, PyString_AS_STRING(r));
593         Py_DECREF(r);
594         return val_obj;
595 }
596
597
598 /*
599   XXX: glib and Samba have quicker macro for doing the endianness conversions,
600   but I don't know of one in plain libc, and it's probably not a big deal.  I
601   realize this is kind of dumb because we'll almost always be on x86, but
602   being safe is important.
603 */
604 static void pack_le_uint32(unsigned long val_long, unsigned char *pbuf)
605 {
606         pbuf[0] =         val_long & 0xff;
607         pbuf[1] = (val_long >> 8)  & 0xff;
608         pbuf[2] = (val_long >> 16) & 0xff;
609         pbuf[3] = (val_long >> 24) & 0xff;
610 }
611
612
613 static void pack_bytes(long len, const char *from,
614                        unsigned char **pbuf)
615 {
616         memcpy(*pbuf, from, len);
617         (*pbuf) += len;
618 }
619
620
621 static void
622 unpack_err_too_short(void)
623 {
624         PyErr_Format(PyExc_IndexError,
625                      __FUNCTION__ ": data too short for unpack format");
626 }
627
628
629 static PyObject *
630 unpack_uint32(char **pbuf, int *plen)
631 {
632         unsigned long v;
633         unsigned char *b;
634         
635         if (*plen < 4) {
636                 unpack_err_too_short();
637                 return NULL;
638         }
639
640         b = *pbuf;
641         v = b[0] | b[1]<<8 | b[2]<<16 | b[3]<<24;
642         
643         (*pbuf) += 4;
644         (*plen) -= 4;
645
646         return PyLong_FromUnsignedLong(v);
647 }
648
649
650 static PyObject *unpack_int16(char **pbuf, int *plen)
651 {
652         long v;
653         unsigned char *b;
654         
655         if (*plen < 2) {
656                 unpack_err_too_short();
657                 return NULL;
658         }
659
660         b = *pbuf;
661         v = b[0] | b[1]<<8;
662         
663         (*pbuf) += 2;
664         (*plen) -= 2;
665
666         return PyInt_FromLong(v);
667 }
668
669
670 static PyObject *
671 unpack_string(char **pbuf, int *plen)
672 {
673         int len;
674         char *nul_ptr, *start;
675
676         start = *pbuf;
677         
678         nul_ptr = memchr(start, '\0', *plen);
679         if (!nul_ptr) {
680                 unpack_err_too_short();
681                 return NULL;
682         }
683
684         len = nul_ptr - start;
685
686         *pbuf += len + 1;       /* skip \0 */
687         *plen -= len + 1;
688
689         return PyString_FromStringAndSize(start, len);
690 }
691
692
693 static PyObject *
694 unpack_buffer(char **pbuf, int *plen, PyObject *val_list)
695 {
696         /* first get 32-bit len */
697         long slen;
698         unsigned char *b;
699         unsigned char *start;
700         PyObject *str_obj = NULL, *len_obj = NULL;
701         
702         if (*plen < 4) {
703                 unpack_err_too_short();
704                 return NULL;
705         }
706         
707         b = *pbuf;
708         slen = b[0] | b[1]<<8 | b[2]<<16 | b[3]<<24;
709
710         if (slen < 0) { /* surely you jest */
711                 PyErr_Format(PyExc_ValueError,
712                              __FUNCTION__ ": buffer seems to have negative length");
713                 return NULL;
714         }
715
716         (*pbuf) += 4;
717         (*plen) -= 4;
718         start = *pbuf;
719
720         if (*plen < slen) {
721                 PyErr_Format(PyExc_IndexError,
722                              __FUNCTION__ ": not enough data to unpack buffer: "
723                              "need %d bytes, have %d",
724                              (int) slen, *plen);
725                 return NULL;
726         }
727
728         (*pbuf) += slen;
729         (*plen) -= slen;
730
731         if (!(len_obj = PyInt_FromLong(slen)))
732                 goto failed;
733
734         if (PyList_Append(val_list, len_obj) == -1)
735                 goto failed;
736         
737         if (!(str_obj = PyString_FromStringAndSize(start, slen)))
738                 goto failed;
739         
740         if (PyList_Append(val_list, str_obj) == -1)
741                 goto failed;
742         
743         return val_list;
744
745   failed:
746         Py_XDECREF(len_obj);    /* handles NULL */
747         Py_XDECREF(str_obj);
748         return NULL;
749 }
750
751
752 /* Unpack a single field from packed data, according to format character CH.
753    Remaining data is at *PBUF, of *PLEN.
754
755    *PBUF is advanced, and *PLEN reduced to reflect the amount of data that has
756    been consumed.
757
758    Returns a reference to None, or NULL for failure.
759 */
760 static PyObject *pytdbpack_unpack_item(char ch,
761                                        char **pbuf,
762                                        int *plen,
763                                        PyObject *val_list)
764 {
765         PyObject *result;
766         
767         if (ch == 'w') {        /* 16-bit int */
768                 result = unpack_int16(pbuf, plen);
769         }
770         else if (ch == 'd' || ch == 'p') { /* 32-bit int */
771                 /* pointers can just come through as integers */
772                 result = unpack_uint32(pbuf, plen);
773         }
774         else if (ch == 'f' || ch == 'P') { /* nul-term string  */
775                 result = unpack_string(pbuf, plen);
776         }
777         else if (ch == 'B') { /* length, buffer */
778                 return unpack_buffer(pbuf, plen, val_list);
779         }
780         else {
781                 PyErr_Format(PyExc_ValueError,
782                              __FUNCTION__ ": format character '%c' is not supported",
783                              ch);
784                 
785                 return NULL;
786         }
787
788         /* otherwise OK */
789         if (!result)
790                 return NULL;
791         if (PyList_Append(val_list, result) == -1)
792                 return NULL;
793         
794         return val_list;
795 }
796
797
798
799
800
801
802 static PyMethodDef pytdbpack_methods[] = {
803         { "pack", pytdbpack, METH_VARARGS, (char *) pytdbpack_doc },
804         { "unpack", pytdbpack_unpack, METH_VARARGS, (char *) pytdbpack_unpack_doc },
805 };
806
807 DL_EXPORT(void)
808 inittdbpack(void)
809 {
810         Py_InitModule3("tdbpack", pytdbpack_methods,
811                        (char *) pytdbpack_docstring);
812 }