diff options
author | Martin Pool <mbp@samba.org> | 2002-11-04 22:22:12 +0000 |
---|---|---|
committer | Martin Pool <mbp@samba.org> | 2002-11-04 22:22:12 +0000 |
commit | 859850faf7bed5464f644df3aeedd40b9663be6a (patch) | |
tree | 59062ac5c86682bb80b6b14bbd69ebb0b3b59e03 /source3/python | |
parent | 70cdcfb5b331b90b5dd8b02d07227c968c3f94fc (diff) | |
download | samba-859850faf7bed5464f644df3aeedd40b9663be6a.tar.gz samba-859850faf7bed5464f644df3aeedd40b9663be6a.tar.bz2 samba-859850faf7bed5464f644df3aeedd40b9663be6a.zip |
Change to representing buffers ('B') as (LEN, STRING) in Python,
rather than as just a string. Makes the code more messy, but needed
for compatibility with existing PSA Python code which seems to be too
knotty to separate out.
(This used to be commit 20d88a7d1e2a6d2daca29c5ffff3781197a97b57)
Diffstat (limited to 'source3/python')
-rw-r--r-- | source3/python/py_tdbpack.c | 242 |
1 files changed, 112 insertions, 130 deletions
diff --git a/source3/python/py_tdbpack.c b/source3/python/py_tdbpack.c index 6c697533a0..001b082f16 100644 --- a/source3/python/py_tdbpack.c +++ b/source3/python/py_tdbpack.c @@ -31,18 +31,20 @@ static int pytdbpack_calc_reqd_len(char *format_str, PyObject *val_seq); static PyObject *pytdbpack_unpack_item(char, - char **pbuf, - int *plen); -static int -pytdbpack_calc_item_len(char format_ch, - PyObject *val_obj); + char **pbuf, + int *plen); static PyObject *pytdbpack_pack_data(const char *format_str, PyObject *val_seq, unsigned char *buf); - + + +static PyObject *pytdbpack_bad_type(char ch, + const char *expected, + PyObject *val_obj); + static const char * pytdbpack_docstring = "Convert between Python values and Samba binary encodings. @@ -76,7 +78,8 @@ tdbpack format strings: value of the Python object is used. 'B': 4-byte LE length, followed by that many bytes of binary data. - Corresponds to a Python byte string of the appropriate length. + Corresponds to a Python integer giving the length, followed by a byte + string of the appropriate length. '$': Special flag indicating that the preceding format code should be repeated while data remains. This is only supported for unpacking. @@ -253,7 +256,7 @@ pytdbpack_unpack(PyObject *self, last_format = format; } - /* put leftovers in box for lunch tomorrow */ + /* save leftovers for next time */ rest_string = PyString_FromStringAndSize(ppacked, packed_len); if (!rest_string) goto failed; @@ -302,8 +305,6 @@ pytdbpack_calc_reqd_len(char *format_str, for (p = format_str, val_i = 0; *p; p++, val_i++) { char ch = *p; - PyObject *val_obj; - int item_len; if (val_i >= val_len) { PyErr_Format(PyExc_IndexError, @@ -313,15 +314,57 @@ pytdbpack_calc_reqd_len(char *format_str, } /* borrow a reference to the item */ - val_obj = PySequence_GetItem(val_seq, val_i); - if (!val_obj) - return -1; + if (ch == 'd' || ch == 'p') + len += 4; + else if (ch == 'w') + len += 2; + else if (ch == 'f' || ch == 'P') { + /* nul-terminated 8-bit string */ + int item_len; + PyObject *str_obj; + + str_obj = PySequence_GetItem(val_seq, val_i); + if (!str_obj) + return -1; + + item_len = PyString_Size(str_obj); + if (item_len == -1) { + pytdbpack_bad_type(ch, "String", str_obj); + return -1; + } + + len += item_len; + } + else if (ch == 'B') { + /* length-preceded byte buffer: n bytes, plus a preceding + * word */ + PyObject *len_obj; + long len_val; + + len_obj = PySequence_GetItem(val_seq, val_i); + val_i++; /* skip over buffer */ + + if (!PyNumber_Check(len_obj)) { + pytdbpack_bad_type(ch, "Number", len_obj); + return -1; + } - item_len = pytdbpack_calc_item_len(ch, val_obj); - if (item_len == -1) + len_val = PyInt_AsLong(len_obj); + if (len_val < 0) { + PyErr_Format(PyExc_ValueError, + "%s: format 'B' requires positive integer", __FUNCTION__); + return -1; + } + + len += 4 + len_val; + } + else { + PyErr_Format(PyExc_ValueError, + "%s: format character '%c' is not supported", + __FUNCTION__, ch); + return -1; - else - len += item_len; + } } return len; @@ -344,56 +387,6 @@ static PyObject *pytdbpack_bad_type(char ch, /* - * Calculate the number of bytes required to pack a single value. While doing - * this, also conduct some initial checks that the argument types are - * reasonable. - * - * Returns -1 on exception. - */ -static int -pytdbpack_calc_item_len(char ch, - PyObject *val_obj) -{ - if (ch == 'd' || ch == 'w') { - if (!PyInt_Check(val_obj)) { - pytdbpack_bad_type(ch, "Int", val_obj); - return -1; - } - if (ch == 'w') - return 2; - else - return 4; - } else if (ch == 'p') { - return 4; - } - else if (ch == 'f' || ch == 'P' || ch == 'B') { - /* nul-terminated 8-bit string */ - if (!PyString_Check(val_obj)) { - pytdbpack_bad_type(ch, "String", val_obj); - return -1; - } - - if (ch == 'B') { - /* byte buffer; just use Python string's length, plus - a preceding word */ - return 4 + PyString_GET_SIZE(val_obj); - } - else { - /* one nul character */ - return 1 + PyString_GET_SIZE(val_obj); - } - } - else { - PyErr_Format(PyExc_ValueError, - "tdbpack: format character '%c' is not supported", - ch); - - return -1; - } -} - - -/* XXX: glib and Samba have quicker macro for doing the endianness conversions, but I don't know of one in plain libc, and it's probably not a big deal. I realize this is kind of dumb because we'll almost always be on x86, but @@ -566,63 +559,6 @@ static PyObject *pytdbpack_unpack_item(char ch, -/* - Pack a single item VAL_OBJ, encoded using format CH, into a buffer at *PBUF, - and advance the pointer. Buffer length has been pre-calculated so we are - sure that there is enough space. - -*/ -static PyObject * -pytdbpack_pack_item(char ch, - PyObject *val_obj, - unsigned char **pbuf) -{ - if (ch == 'w') { - unsigned long val_long = PyInt_AsLong(val_obj); - (*pbuf)[0] = val_long & 0xff; - (*pbuf)[1] = (val_long >> 8) & 0xff; - (*pbuf) += 2; - } - else if (ch == 'd') { - /* 4-byte LE number */ - pack_int32(PyInt_AsLong(val_obj), pbuf); - } - else if (ch == 'p') { - /* "Pointer" value -- in the subset of DCERPC used by Samba, - this is really just an "exists" or "does not exist" - flag. */ - pack_int32(PyObject_IsTrue(val_obj), pbuf); - } - else if (ch == 'f' || ch == 'P') { - int size; - char *sval; - - size = PyString_GET_SIZE(val_obj); - sval = PyString_AS_STRING(val_obj); - pack_bytes(size+1, sval, pbuf); /* include nul */ - } - else if (ch == 'B') { - int size; - char *sval; - - size = PyString_GET_SIZE(val_obj); - pack_int32(size, pbuf); - sval = PyString_AS_STRING(val_obj); - pack_bytes(size, sval, pbuf); /* do not include nul */ - } - else { - /* this ought to be caught while calculating the length, but - just in case. */ - PyErr_Format(PyExc_ValueError, - "%s: format character '%c' is not supported", - __FUNCTION__, ch); - - return NULL; - } - - return Py_None; -} - /* Pack data according to FORMAT_STR from the elements of VAL_SEQ into @@ -639,7 +575,7 @@ pytdbpack_pack_item(char ch, PyObject * pytdbpack_pack_data(const char *format_str, PyObject *val_seq, - unsigned char *packed_buf) + unsigned char *packed) { int i; @@ -648,21 +584,67 @@ pytdbpack_pack_data(const char *format_str, PyObject *val_obj; /* borrow a reference to the item */ - val_obj = PySequence_Fast_GET_ITEM(val_seq, i); + val_obj = PySequence_GetItem(val_seq, i); if (!val_obj) return NULL; - if (!pytdbpack_pack_item(ch, val_obj, &packed_buf)) + if (ch == 'w') { + unsigned long val_long = PyInt_AsLong(val_obj); + (packed)[0] = val_long & 0xff; + (packed)[1] = (val_long >> 8) & 0xff; + (packed) += 2; + } + else if (ch == 'd') { + /* 4-byte LE number */ + pack_int32(PyInt_AsLong(val_obj), &packed); + } + else if (ch == 'p') { + /* "Pointer" value -- in the subset of DCERPC used by Samba, + this is really just an "exists" or "does not exist" + flag. */ + pack_int32(PyObject_IsTrue(val_obj), &packed); + } + else if (ch == 'f' || ch == 'P') { + int size; + char *sval; + + size = PyString_GET_SIZE(val_obj); + sval = PyString_AS_STRING(val_obj); + pack_bytes(size+1, sval, &packed); /* include nul */ + } + else if (ch == 'B') { + long size; + char *sval; + + size = PyInt_AsLong(val_obj); + pack_int32(size, &packed); + + val_obj = PySequence_GetItem(val_seq, ++i); + if (!val_obj) + return NULL; + + sval = PyString_AsString(val_obj); + if (!sval) + return NULL; + + pack_bytes(size, sval, &packed); /* do not include nul */ + } + else { + /* this ought to be caught while calculating the length, but + just in case. */ + PyErr_Format(PyExc_ValueError, + "%s: format character '%c' is not supported", + __FUNCTION__, ch); + return NULL; + } } - + return Py_None; } - - static PyMethodDef pytdbpack_methods[] = { { "pack", pytdbpack_pack, METH_VARARGS, (char *) pytdbpack_pack_doc }, { "unpack", pytdbpack_unpack, METH_VARARGS, (char *) pytdbpack_unpack_doc }, |